SparcMCCodeEmitter.cpp revision 4c5e43da7792f75567b693105cc53e3f1992ad98
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#include "SparcMCExpr.h" 15#include "MCTargetDesc/SparcFixupKinds.h" 16#include "SparcMCTargetDesc.h" 17#include "llvm/ADT/Statistic.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/Support/raw_ostream.h" 25 26using namespace llvm; 27 28#define DEBUG_TYPE "mccodeemitter" 29 30STATISTIC(MCNumEmitted, "Number of MC instructions emitted"); 31 32namespace { 33class SparcMCCodeEmitter : public MCCodeEmitter { 34 SparcMCCodeEmitter(const SparcMCCodeEmitter &) = delete; 35 void operator=(const SparcMCCodeEmitter &) = delete; 36 MCContext &Ctx; 37 38public: 39 SparcMCCodeEmitter(MCContext &ctx): Ctx(ctx) {} 40 41 ~SparcMCCodeEmitter() {} 42 43 void EncodeInstruction(const MCInst &MI, raw_ostream &OS, 44 SmallVectorImpl<MCFixup> &Fixups, 45 const MCSubtargetInfo &STI) const override; 46 47 // getBinaryCodeForInstr - TableGen'erated function for getting the 48 // binary encoding for an instruction. 49 uint64_t getBinaryCodeForInstr(const MCInst &MI, 50 SmallVectorImpl<MCFixup> &Fixups, 51 const MCSubtargetInfo &STI) const; 52 53 /// getMachineOpValue - Return binary encoding of operand. If the machine 54 /// operand requires relocation, record the relocation and return zero. 55 unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO, 56 SmallVectorImpl<MCFixup> &Fixups, 57 const MCSubtargetInfo &STI) const; 58 59 unsigned getCallTargetOpValue(const MCInst &MI, unsigned OpNo, 60 SmallVectorImpl<MCFixup> &Fixups, 61 const MCSubtargetInfo &STI) const; 62 unsigned getBranchTargetOpValue(const MCInst &MI, unsigned OpNo, 63 SmallVectorImpl<MCFixup> &Fixups, 64 const MCSubtargetInfo &STI) const; 65 unsigned getBranchPredTargetOpValue(const MCInst &MI, unsigned OpNo, 66 SmallVectorImpl<MCFixup> &Fixups, 67 const MCSubtargetInfo &STI) const; 68 unsigned getBranchOnRegTargetOpValue(const MCInst &MI, unsigned OpNo, 69 SmallVectorImpl<MCFixup> &Fixups, 70 const MCSubtargetInfo &STI) const; 71 72}; 73} // end anonymous namespace 74 75MCCodeEmitter *llvm::createSparcMCCodeEmitter(const MCInstrInfo &MCII, 76 const MCRegisterInfo &MRI, 77 MCContext &Ctx) { 78 return new SparcMCCodeEmitter(Ctx); 79} 80 81void SparcMCCodeEmitter:: 82EncodeInstruction(const MCInst &MI, raw_ostream &OS, 83 SmallVectorImpl<MCFixup> &Fixups, 84 const MCSubtargetInfo &STI) const { 85 unsigned Bits = getBinaryCodeForInstr(MI, Fixups, STI); 86 87 // Output the constant in big endian byte order. 88 for (unsigned i = 0; i != 4; ++i) { 89 OS << (char)(Bits >> 24); 90 Bits <<= 8; 91 } 92 unsigned tlsOpNo = 0; 93 switch (MI.getOpcode()) { 94 default: break; 95 case SP::TLS_CALL: tlsOpNo = 1; break; 96 case SP::TLS_ADDrr: 97 case SP::TLS_ADDXrr: 98 case SP::TLS_LDrr: 99 case SP::TLS_LDXrr: tlsOpNo = 3; break; 100 } 101 if (tlsOpNo != 0) { 102 const MCOperand &MO = MI.getOperand(tlsOpNo); 103 uint64_t op = getMachineOpValue(MI, MO, Fixups, STI); 104 assert(op == 0 && "Unexpected operand value!"); 105 (void)op; // suppress warning. 106 } 107 108 ++MCNumEmitted; // Keep track of the # of mi's emitted. 109} 110 111 112unsigned SparcMCCodeEmitter:: 113getMachineOpValue(const MCInst &MI, const MCOperand &MO, 114 SmallVectorImpl<MCFixup> &Fixups, 115 const MCSubtargetInfo &STI) const { 116 117 if (MO.isReg()) 118 return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg()); 119 120 if (MO.isImm()) 121 return MO.getImm(); 122 123 assert(MO.isExpr()); 124 const MCExpr *Expr = MO.getExpr(); 125 if (const SparcMCExpr *SExpr = dyn_cast<SparcMCExpr>(Expr)) { 126 MCFixupKind Kind = (MCFixupKind)SExpr->getFixupKind(); 127 Fixups.push_back(MCFixup::Create(0, Expr, Kind)); 128 return 0; 129 } 130 131 int64_t Res; 132 if (Expr->EvaluateAsAbsolute(Res)) 133 return Res; 134 135 llvm_unreachable("Unhandled expression!"); 136 return 0; 137} 138 139unsigned SparcMCCodeEmitter:: 140getCallTargetOpValue(const MCInst &MI, unsigned OpNo, 141 SmallVectorImpl<MCFixup> &Fixups, 142 const MCSubtargetInfo &STI) const { 143 const MCOperand &MO = MI.getOperand(OpNo); 144 if (MO.isReg() || MO.isImm()) 145 return getMachineOpValue(MI, MO, Fixups, STI); 146 147 if (MI.getOpcode() == SP::TLS_CALL) { 148 // No fixups for __tls_get_addr. Will emit for fixups for tls_symbol in 149 // EncodeInstruction. 150#ifndef NDEBUG 151 // Verify that the callee is actually __tls_get_addr. 152 const SparcMCExpr *SExpr = dyn_cast<SparcMCExpr>(MO.getExpr()); 153 assert(SExpr && SExpr->getSubExpr()->getKind() == MCExpr::SymbolRef && 154 "Unexpected expression in TLS_CALL"); 155 const MCSymbolRefExpr *SymExpr = cast<MCSymbolRefExpr>(SExpr->getSubExpr()); 156 assert(SymExpr->getSymbol().getName() == "__tls_get_addr" && 157 "Unexpected function for TLS_CALL"); 158#endif 159 return 0; 160 } 161 162 MCFixupKind fixupKind = (MCFixupKind)Sparc::fixup_sparc_call30; 163 164 if (const SparcMCExpr *SExpr = dyn_cast<SparcMCExpr>(MO.getExpr())) { 165 if (SExpr->getKind() == SparcMCExpr::VK_Sparc_WPLT30) 166 fixupKind = (MCFixupKind)Sparc::fixup_sparc_wplt30; 167 } 168 169 Fixups.push_back(MCFixup::Create(0, MO.getExpr(), fixupKind)); 170 171 return 0; 172} 173 174unsigned SparcMCCodeEmitter:: 175getBranchTargetOpValue(const MCInst &MI, unsigned OpNo, 176 SmallVectorImpl<MCFixup> &Fixups, 177 const MCSubtargetInfo &STI) const { 178 const MCOperand &MO = MI.getOperand(OpNo); 179 if (MO.isReg() || MO.isImm()) 180 return getMachineOpValue(MI, MO, Fixups, STI); 181 182 Fixups.push_back(MCFixup::Create(0, MO.getExpr(), 183 (MCFixupKind)Sparc::fixup_sparc_br22)); 184 return 0; 185} 186 187unsigned SparcMCCodeEmitter:: 188getBranchPredTargetOpValue(const MCInst &MI, unsigned OpNo, 189 SmallVectorImpl<MCFixup> &Fixups, 190 const MCSubtargetInfo &STI) const { 191 const MCOperand &MO = MI.getOperand(OpNo); 192 if (MO.isReg() || MO.isImm()) 193 return getMachineOpValue(MI, MO, Fixups, STI); 194 195 Fixups.push_back(MCFixup::Create(0, MO.getExpr(), 196 (MCFixupKind)Sparc::fixup_sparc_br19)); 197 return 0; 198} 199unsigned SparcMCCodeEmitter:: 200getBranchOnRegTargetOpValue(const MCInst &MI, unsigned OpNo, 201 SmallVectorImpl<MCFixup> &Fixups, 202 const MCSubtargetInfo &STI) const { 203 const MCOperand &MO = MI.getOperand(OpNo); 204 if (MO.isReg() || MO.isImm()) 205 return getMachineOpValue(MI, MO, Fixups, STI); 206 207 Fixups.push_back(MCFixup::Create(0, MO.getExpr(), 208 (MCFixupKind)Sparc::fixup_sparc_br16_2)); 209 Fixups.push_back(MCFixup::Create(0, MO.getExpr(), 210 (MCFixupKind)Sparc::fixup_sparc_br16_14)); 211 212 return 0; 213} 214 215 216 217#include "SparcGenMCCodeEmitter.inc" 218