SparcMCCodeEmitter.cpp revision 263763
1//===-- SparcMCCodeEmitter.cpp - Convert Sparc code to machine code -------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This file implements the SparcMCCodeEmitter class. 11// 12//===----------------------------------------------------------------------===// 13 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/MC/MCSymbol.h" 24#include "llvm/ADT/Statistic.h" 25#include "llvm/Support/raw_ostream.h" 26 27using namespace llvm; 28 29STATISTIC(MCNumEmitted, "Number of MC instructions emitted"); 30 31namespace { 32class SparcMCCodeEmitter : public MCCodeEmitter { 33 SparcMCCodeEmitter(const SparcMCCodeEmitter &) LLVM_DELETED_FUNCTION; 34 void operator=(const SparcMCCodeEmitter &) LLVM_DELETED_FUNCTION; 35 MCContext &Ctx; 36 37public: 38 SparcMCCodeEmitter(MCContext &ctx): Ctx(ctx) {} 39 40 ~SparcMCCodeEmitter() {} 41 42 void EncodeInstruction(const MCInst &MI, raw_ostream &OS, 43 SmallVectorImpl<MCFixup> &Fixups) const; 44 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) const; 49 50 /// getMachineOpValue - Return binary encoding of operand. If the machine 51 /// operand requires relocation, record the relocation and return zero. 52 unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO, 53 SmallVectorImpl<MCFixup> &Fixups) const; 54 55 unsigned getCallTargetOpValue(const MCInst &MI, unsigned OpNo, 56 SmallVectorImpl<MCFixup> &Fixups) const; 57 unsigned getBranchTargetOpValue(const MCInst &MI, unsigned OpNo, 58 SmallVectorImpl<MCFixup> &Fixups) const; 59 60}; 61} // end anonymous namespace 62 63MCCodeEmitter *llvm::createSparcMCCodeEmitter(const MCInstrInfo &MCII, 64 const MCRegisterInfo &MRI, 65 const MCSubtargetInfo &STI, 66 MCContext &Ctx) { 67 return new SparcMCCodeEmitter(Ctx); 68} 69 70void SparcMCCodeEmitter:: 71EncodeInstruction(const MCInst &MI, raw_ostream &OS, 72 SmallVectorImpl<MCFixup> &Fixups) const { 73 unsigned Bits = getBinaryCodeForInstr(MI, Fixups); 74 75 // Output the constant in big endian byte order. 76 for (unsigned i = 0; i != 4; ++i) { 77 OS << (char)(Bits >> 24); 78 Bits <<= 8; 79 } 80 unsigned tlsOpNo = 0; 81 switch (MI.getOpcode()) { 82 default: break; 83 case SP::TLS_CALL: tlsOpNo = 1; break; 84 case SP::TLS_ADDrr: 85 case SP::TLS_ADDXrr: 86 case SP::TLS_LDrr: 87 case SP::TLS_LDXrr: tlsOpNo = 3; break; 88 } 89 if (tlsOpNo != 0) { 90 const MCOperand &MO = MI.getOperand(tlsOpNo); 91 uint64_t op = getMachineOpValue(MI, MO, Fixups); 92 assert(op == 0 && "Unexpected operand value!"); 93 (void)op; // suppress warning. 94 } 95 96 ++MCNumEmitted; // Keep track of the # of mi's emitted. 97} 98 99 100unsigned SparcMCCodeEmitter:: 101getMachineOpValue(const MCInst &MI, const MCOperand &MO, 102 SmallVectorImpl<MCFixup> &Fixups) const { 103 104 if (MO.isReg()) 105 return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg()); 106 107 if (MO.isImm()) 108 return MO.getImm(); 109 110 assert(MO.isExpr()); 111 const MCExpr *Expr = MO.getExpr(); 112 if (const SparcMCExpr *SExpr = dyn_cast<SparcMCExpr>(Expr)) { 113 MCFixupKind Kind = (MCFixupKind)SExpr->getFixupKind(); 114 Fixups.push_back(MCFixup::Create(0, Expr, Kind)); 115 return 0; 116 } 117 118 int64_t Res; 119 if (Expr->EvaluateAsAbsolute(Res)) 120 return Res; 121 122 assert(0 && "Unhandled expression!"); 123 return 0; 124} 125 126unsigned SparcMCCodeEmitter:: 127getCallTargetOpValue(const MCInst &MI, unsigned OpNo, 128 SmallVectorImpl<MCFixup> &Fixups) const { 129 const MCOperand &MO = MI.getOperand(OpNo); 130 if (MO.isReg() || MO.isImm()) 131 return getMachineOpValue(MI, MO, Fixups); 132 133 if (MI.getOpcode() == SP::TLS_CALL) { 134 // No fixups for __tls_get_addr. Will emit for fixups for tls_symbol in 135 // EncodeInstruction. 136#ifndef NDEBUG 137 // Verify that the callee is actually __tls_get_addr. 138 const SparcMCExpr *SExpr = dyn_cast<SparcMCExpr>(MO.getExpr()); 139 assert(SExpr && SExpr->getSubExpr()->getKind() == MCExpr::SymbolRef && 140 "Unexpected expression in TLS_CALL"); 141 const MCSymbolRefExpr *SymExpr = cast<MCSymbolRefExpr>(SExpr->getSubExpr()); 142 assert(SymExpr->getSymbol().getName() == "__tls_get_addr" && 143 "Unexpected function for TLS_CALL"); 144#endif 145 return 0; 146 } 147 148 MCFixupKind fixupKind = (MCFixupKind)Sparc::fixup_sparc_call30; 149 150 if (const SparcMCExpr *SExpr = dyn_cast<SparcMCExpr>(MO.getExpr())) { 151 if (SExpr->getKind() == SparcMCExpr::VK_Sparc_WPLT30) 152 fixupKind = (MCFixupKind)Sparc::fixup_sparc_wplt30; 153 } 154 155 Fixups.push_back(MCFixup::Create(0, MO.getExpr(), fixupKind)); 156 157 return 0; 158} 159 160unsigned SparcMCCodeEmitter:: 161getBranchTargetOpValue(const MCInst &MI, unsigned OpNo, 162 SmallVectorImpl<MCFixup> &Fixups) const { 163 const MCOperand &MO = MI.getOperand(OpNo); 164 if (MO.isReg() || MO.isImm()) 165 return getMachineOpValue(MI, MO, Fixups); 166 167 Sparc::Fixups fixup = Sparc::fixup_sparc_br22; 168 if (MI.getOpcode() == SP::BPXCC) 169 fixup = Sparc::fixup_sparc_br19; 170 171 Fixups.push_back(MCFixup::Create(0, MO.getExpr(), 172 (MCFixupKind)fixup)); 173 return 0; 174} 175 176#include "SparcGenMCCodeEmitter.inc" 177