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 "SparcMCTargetDesc.h"
17 #include "MCTargetDesc/SparcFixupKinds.h"
18 #include "llvm/MC/MCCodeEmitter.h"
19 #include "llvm/MC/MCContext.h"
20 #include "llvm/MC/MCExpr.h"
21 #include "llvm/MC/MCInst.h"
22 #include "llvm/MC/MCRegisterInfo.h"
23 #include "llvm/ADT/Statistic.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) const;
44 // getBinaryCodeForInstr - TableGen'erated function for getting the
45 // binary encoding for an instruction.
46 uint64_t getBinaryCodeForInstr(const MCInst &MI,
47 SmallVectorImpl<MCFixup> &Fixups) const;
49 /// getMachineOpValue - Return binary encoding of operand. If the machine
50 /// operand requires relocation, record the relocation and return zero.
51 unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO,
52 SmallVectorImpl<MCFixup> &Fixups) const;
54 unsigned getCallTargetOpValue(const MCInst &MI, unsigned OpNo,
55 SmallVectorImpl<MCFixup> &Fixups) const;
56 unsigned getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
57 SmallVectorImpl<MCFixup> &Fixups) const;
60 } // end anonymous namespace
62 MCCodeEmitter *llvm::createSparcMCCodeEmitter(const MCInstrInfo &MCII,
63 const MCRegisterInfo &MRI,
64 const MCSubtargetInfo &STI,
66 return new SparcMCCodeEmitter(Ctx);
69 void SparcMCCodeEmitter::
70 EncodeInstruction(const MCInst &MI, raw_ostream &OS,
71 SmallVectorImpl<MCFixup> &Fixups) const {
72 unsigned Bits = getBinaryCodeForInstr(MI, Fixups);
74 // Output the constant in big endian byte order.
75 for (unsigned i = 0; i != 4; ++i) {
76 OS << (char)(Bits >> 24);
80 ++MCNumEmitted; // Keep track of the # of mi's emitted.
84 unsigned SparcMCCodeEmitter::
85 getMachineOpValue(const MCInst &MI, const MCOperand &MO,
86 SmallVectorImpl<MCFixup> &Fixups) const {
89 return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());
95 const MCExpr *Expr = MO.getExpr();
96 if (const SparcMCExpr *SExpr = dyn_cast<SparcMCExpr>(Expr)) {
97 switch(SExpr->getKind()) {
98 default: assert(0 && "Unhandled sparc expression!"); break;
99 case SparcMCExpr::VK_Sparc_LO:
100 Fixups.push_back(MCFixup::Create(0, Expr,
101 (MCFixupKind)Sparc::fixup_sparc_lo10));
103 case SparcMCExpr::VK_Sparc_HI:
104 Fixups.push_back(MCFixup::Create(0, Expr,
105 (MCFixupKind)Sparc::fixup_sparc_hi22));
107 case SparcMCExpr::VK_Sparc_H44:
108 Fixups.push_back(MCFixup::Create(0, Expr,
109 (MCFixupKind)Sparc::fixup_sparc_h44));
111 case SparcMCExpr::VK_Sparc_M44:
112 Fixups.push_back(MCFixup::Create(0, Expr,
113 (MCFixupKind)Sparc::fixup_sparc_m44));
115 case SparcMCExpr::VK_Sparc_L44:
116 Fixups.push_back(MCFixup::Create(0, Expr,
117 (MCFixupKind)Sparc::fixup_sparc_l44));
119 case SparcMCExpr::VK_Sparc_HH:
120 Fixups.push_back(MCFixup::Create(0, Expr,
121 (MCFixupKind)Sparc::fixup_sparc_hh));
123 case SparcMCExpr::VK_Sparc_HM:
124 Fixups.push_back(MCFixup::Create(0, Expr,
125 (MCFixupKind)Sparc::fixup_sparc_hm));
132 if (Expr->EvaluateAsAbsolute(Res))
135 assert(0 && "Unhandled expression!");
139 unsigned SparcMCCodeEmitter::
140 getCallTargetOpValue(const MCInst &MI, unsigned OpNo,
141 SmallVectorImpl<MCFixup> &Fixups) const {
142 const MCOperand &MO = MI.getOperand(OpNo);
143 if (MO.isReg() || MO.isImm())
144 return getMachineOpValue(MI, MO, Fixups);
146 Fixups.push_back(MCFixup::Create(0, MO.getExpr(),
147 (MCFixupKind)Sparc::fixup_sparc_call30));
151 unsigned SparcMCCodeEmitter::
152 getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
153 SmallVectorImpl<MCFixup> &Fixups) const {
154 const MCOperand &MO = MI.getOperand(OpNo);
155 if (MO.isReg() || MO.isImm())
156 return getMachineOpValue(MI, MO, Fixups);
158 Sparc::Fixups fixup = Sparc::fixup_sparc_br22;
159 if (MI.getOpcode() == SP::BPXCC)
160 fixup = Sparc::fixup_sparc_br19;
162 Fixups.push_back(MCFixup::Create(0, MO.getExpr(),
163 (MCFixupKind)fixup));
167 #include "SparcGenMCCodeEmitter.inc"