1 //===-- SparcMCCodeEmitter.cpp - Convert Sparc code to machine code -------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file implements the SparcMCCodeEmitter class.
12 //===----------------------------------------------------------------------===//
14 #define DEBUG_TYPE "mccodeemitter"
15 #include "SparcMCExpr.h"
16 #include "MCTargetDesc/SparcFixupKinds.h"
17 #include "SparcMCTargetDesc.h"
18 #include "llvm/ADT/Statistic.h"
19 #include "llvm/MC/MCCodeEmitter.h"
20 #include "llvm/MC/MCContext.h"
21 #include "llvm/MC/MCExpr.h"
22 #include "llvm/MC/MCInst.h"
23 #include "llvm/MC/MCRegisterInfo.h"
24 #include "llvm/Support/raw_ostream.h"
28 STATISTIC(MCNumEmitted, "Number of MC instructions emitted");
31 class SparcMCCodeEmitter : public MCCodeEmitter {
32 SparcMCCodeEmitter(const SparcMCCodeEmitter &) LLVM_DELETED_FUNCTION;
33 void operator=(const SparcMCCodeEmitter &) LLVM_DELETED_FUNCTION;
37 SparcMCCodeEmitter(MCContext &ctx): Ctx(ctx) {}
39 ~SparcMCCodeEmitter() {}
41 void EncodeInstruction(const MCInst &MI, raw_ostream &OS,
42 SmallVectorImpl<MCFixup> &Fixups,
43 const MCSubtargetInfo &STI) const;
45 // getBinaryCodeForInstr - TableGen'erated function for getting the
46 // binary encoding for an instruction.
47 uint64_t getBinaryCodeForInstr(const MCInst &MI,
48 SmallVectorImpl<MCFixup> &Fixups,
49 const MCSubtargetInfo &STI) const;
51 /// getMachineOpValue - Return binary encoding of operand. If the machine
52 /// operand requires relocation, record the relocation and return zero.
53 unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO,
54 SmallVectorImpl<MCFixup> &Fixups,
55 const MCSubtargetInfo &STI) const;
57 unsigned getCallTargetOpValue(const MCInst &MI, unsigned OpNo,
58 SmallVectorImpl<MCFixup> &Fixups,
59 const MCSubtargetInfo &STI) const;
60 unsigned getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
61 SmallVectorImpl<MCFixup> &Fixups,
62 const MCSubtargetInfo &STI) const;
65 } // end anonymous namespace
67 MCCodeEmitter *llvm::createSparcMCCodeEmitter(const MCInstrInfo &MCII,
68 const MCRegisterInfo &MRI,
69 const MCSubtargetInfo &STI,
71 return new SparcMCCodeEmitter(Ctx);
74 void SparcMCCodeEmitter::
75 EncodeInstruction(const MCInst &MI, raw_ostream &OS,
76 SmallVectorImpl<MCFixup> &Fixups,
77 const MCSubtargetInfo &STI) const {
78 unsigned Bits = getBinaryCodeForInstr(MI, Fixups, STI);
80 // Output the constant in big endian byte order.
81 for (unsigned i = 0; i != 4; ++i) {
82 OS << (char)(Bits >> 24);
86 ++MCNumEmitted; // Keep track of the # of mi's emitted.
90 unsigned SparcMCCodeEmitter::
91 getMachineOpValue(const MCInst &MI, const MCOperand &MO,
92 SmallVectorImpl<MCFixup> &Fixups,
93 const MCSubtargetInfo &STI) const {
96 return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());
102 const MCExpr *Expr = MO.getExpr();
103 if (const SparcMCExpr *SExpr = dyn_cast<SparcMCExpr>(Expr)) {
104 MCFixupKind Kind = (MCFixupKind)SExpr->getFixupKind();
105 Fixups.push_back(MCFixup::Create(0, Expr, Kind));
110 if (Expr->EvaluateAsAbsolute(Res))
113 assert(0 && "Unhandled expression!");
117 unsigned SparcMCCodeEmitter::
118 getCallTargetOpValue(const MCInst &MI, unsigned OpNo,
119 SmallVectorImpl<MCFixup> &Fixups,
120 const MCSubtargetInfo &STI) const {
121 const MCOperand &MO = MI.getOperand(OpNo);
122 if (MO.isReg() || MO.isImm())
123 return getMachineOpValue(MI, MO, Fixups, STI);
125 MCFixupKind fixupKind = (MCFixupKind)Sparc::fixup_sparc_call30;
127 if (const SparcMCExpr *SExpr = dyn_cast<SparcMCExpr>(MO.getExpr())) {
128 if (SExpr->getKind() == SparcMCExpr::VK_Sparc_WPLT30)
129 fixupKind = (MCFixupKind)Sparc::fixup_sparc_wplt30;
132 Fixups.push_back(MCFixup::Create(0, MO.getExpr(), fixupKind));
137 unsigned SparcMCCodeEmitter::
138 getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
139 SmallVectorImpl<MCFixup> &Fixups,
140 const MCSubtargetInfo &STI) const {
141 const MCOperand &MO = MI.getOperand(OpNo);
142 if (MO.isReg() || MO.isImm())
143 return getMachineOpValue(MI, MO, Fixups, STI);
145 Sparc::Fixups fixup = Sparc::fixup_sparc_br22;
146 if (MI.getOpcode() == SP::BPXCC)
147 fixup = Sparc::fixup_sparc_br19;
149 Fixups.push_back(MCFixup::Create(0, MO.getExpr(),
150 (MCFixupKind)fixup));
154 #include "SparcGenMCCodeEmitter.inc"