MipsMCCodeEmitter.cpp revision f530aff9de2738db0e3471b259ff0b577a6603e6
1//===-- MipsMCCodeEmitter.cpp - Convert Mips 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 MipsMCCodeEmitter class. 11// 12//===----------------------------------------------------------------------===// 13// 14#define DEBUG_TYPE "mccodeemitter" 15#include "MCTargetDesc/MipsBaseInfo.h" 16#include "MCTargetDesc/MipsDirectObjLower.h" 17#include "MCTargetDesc/MipsFixupKinds.h" 18#include "MCTargetDesc/MipsMCTargetDesc.h" 19#include "llvm/ADT/APFloat.h" 20#include "llvm/ADT/Statistic.h" 21#include "llvm/MC/MCCodeEmitter.h" 22#include "llvm/MC/MCContext.h" 23#include "llvm/MC/MCExpr.h" 24#include "llvm/MC/MCInst.h" 25#include "llvm/MC/MCInstrInfo.h" 26#include "llvm/MC/MCRegisterInfo.h" 27#include "llvm/MC/MCSubtargetInfo.h" 28#include "llvm/Support/raw_ostream.h" 29 30#define GET_INSTRMAP_INFO 31#include "MipsGenInstrInfo.inc" 32 33using namespace llvm; 34 35namespace { 36class MipsMCCodeEmitter : public MCCodeEmitter { 37 MipsMCCodeEmitter(const MipsMCCodeEmitter &) LLVM_DELETED_FUNCTION; 38 void operator=(const MipsMCCodeEmitter &) LLVM_DELETED_FUNCTION; 39 const MCInstrInfo &MCII; 40 MCContext &Ctx; 41 const MCSubtargetInfo &STI; 42 bool IsLittleEndian; 43 44public: 45 MipsMCCodeEmitter(const MCInstrInfo &mcii, MCContext &Ctx_, 46 const MCSubtargetInfo &sti, bool IsLittle) : 47 MCII(mcii), Ctx(Ctx_), STI (sti), IsLittleEndian(IsLittle) {} 48 49 ~MipsMCCodeEmitter() {} 50 51 void EmitByte(unsigned char C, raw_ostream &OS) const { 52 OS << (char)C; 53 } 54 55 void EmitInstruction(uint64_t Val, unsigned Size, raw_ostream &OS) const { 56 // Output the instruction encoding in little endian byte order. 57 for (unsigned i = 0; i < Size; ++i) { 58 unsigned Shift = IsLittleEndian ? i * 8 : (Size - 1 - i) * 8; 59 EmitByte((Val >> Shift) & 0xff, OS); 60 } 61 } 62 63 void EncodeInstruction(const MCInst &MI, raw_ostream &OS, 64 SmallVectorImpl<MCFixup> &Fixups) const; 65 66 // getBinaryCodeForInstr - TableGen'erated function for getting the 67 // binary encoding for an instruction. 68 uint64_t getBinaryCodeForInstr(const MCInst &MI, 69 SmallVectorImpl<MCFixup> &Fixups) const; 70 71 // getBranchJumpOpValue - Return binary encoding of the jump 72 // target operand. If the machine operand requires relocation, 73 // record the relocation and return zero. 74 unsigned getJumpTargetOpValue(const MCInst &MI, unsigned OpNo, 75 SmallVectorImpl<MCFixup> &Fixups) const; 76 77 // getBranchTargetOpValue - Return binary encoding of the branch 78 // target operand. If the machine operand requires relocation, 79 // record the relocation and return zero. 80 unsigned getBranchTargetOpValue(const MCInst &MI, unsigned OpNo, 81 SmallVectorImpl<MCFixup> &Fixups) const; 82 83 // getMachineOpValue - Return binary encoding of operand. If the machin 84 // operand requires relocation, record the relocation and return zero. 85 unsigned getMachineOpValue(const MCInst &MI,const MCOperand &MO, 86 SmallVectorImpl<MCFixup> &Fixups) const; 87 88 unsigned getMemEncoding(const MCInst &MI, unsigned OpNo, 89 SmallVectorImpl<MCFixup> &Fixups) const; 90 unsigned getSizeExtEncoding(const MCInst &MI, unsigned OpNo, 91 SmallVectorImpl<MCFixup> &Fixups) const; 92 unsigned getSizeInsEncoding(const MCInst &MI, unsigned OpNo, 93 SmallVectorImpl<MCFixup> &Fixups) const; 94 95 unsigned 96 getExprOpValue(const MCExpr *Expr,SmallVectorImpl<MCFixup> &Fixups) const; 97 98}; // class MipsMCCodeEmitter 99} // namespace 100 101MCCodeEmitter *llvm::createMipsMCCodeEmitterEB(const MCInstrInfo &MCII, 102 const MCRegisterInfo &MRI, 103 const MCSubtargetInfo &STI, 104 MCContext &Ctx) 105{ 106 return new MipsMCCodeEmitter(MCII, Ctx, STI, false); 107} 108 109MCCodeEmitter *llvm::createMipsMCCodeEmitterEL(const MCInstrInfo &MCII, 110 const MCRegisterInfo &MRI, 111 const MCSubtargetInfo &STI, 112 MCContext &Ctx) 113{ 114 return new MipsMCCodeEmitter(MCII, Ctx, STI, true); 115} 116 117/// EncodeInstruction - Emit the instruction. 118/// Size the instruction (currently only 4 bytes 119void MipsMCCodeEmitter:: 120EncodeInstruction(const MCInst &MI, raw_ostream &OS, 121 SmallVectorImpl<MCFixup> &Fixups) const 122{ 123 124 // Non-pseudo instructions that get changed for direct object 125 // only based on operand values. 126 // If this list of instructions get much longer we will move 127 // the check to a function call. Until then, this is more efficient. 128 MCInst TmpInst = MI; 129 switch (MI.getOpcode()) { 130 // If shift amount is >= 32 it the inst needs to be lowered further 131 case Mips::DSLL: 132 case Mips::DSRL: 133 case Mips::DSRA: 134 Mips::LowerLargeShift(TmpInst); 135 break; 136 // Double extract instruction is chosen by pos and size operands 137 case Mips::DEXT: 138 case Mips::DINS: 139 Mips::LowerDextDins(TmpInst); 140 } 141 142 uint32_t Binary = getBinaryCodeForInstr(TmpInst, Fixups); 143 144 // Check for unimplemented opcodes. 145 // Unfortunately in MIPS both NOP and SLL will come in with Binary == 0 146 // so we have to special check for them. 147 unsigned Opcode = TmpInst.getOpcode(); 148 if ((Opcode != Mips::NOP) && (Opcode != Mips::SLL) && !Binary) 149 llvm_unreachable("unimplemented opcode in EncodeInstruction()"); 150 151 if (STI.getFeatureBits() & Mips::FeatureMicroMips) { 152 int NewOpcode = Mips::Std2MicroMips (Opcode, Mips::Arch_micromips); 153 if (NewOpcode != -1) { 154 Opcode = NewOpcode; 155 TmpInst.setOpcode (NewOpcode); 156 Binary = getBinaryCodeForInstr(TmpInst, Fixups); 157 } 158 } 159 160 const MCInstrDesc &Desc = MCII.get(TmpInst.getOpcode()); 161 162 // Get byte count of instruction 163 unsigned Size = Desc.getSize(); 164 if (!Size) 165 llvm_unreachable("Desc.getSize() returns 0"); 166 167 EmitInstruction(Binary, Size, OS); 168} 169 170/// getBranchTargetOpValue - Return binary encoding of the branch 171/// target operand. If the machine operand requires relocation, 172/// record the relocation and return zero. 173unsigned MipsMCCodeEmitter:: 174getBranchTargetOpValue(const MCInst &MI, unsigned OpNo, 175 SmallVectorImpl<MCFixup> &Fixups) const { 176 177 const MCOperand &MO = MI.getOperand(OpNo); 178 179 // If the destination is an immediate, divide by 4. 180 if (MO.isImm()) return MO.getImm() >> 2; 181 182 assert(MO.isExpr() && 183 "getBranchTargetOpValue expects only expressions or immediates"); 184 185 const MCExpr *Expr = MO.getExpr(); 186 Fixups.push_back(MCFixup::Create(0, Expr, 187 MCFixupKind(Mips::fixup_Mips_PC16))); 188 return 0; 189} 190 191/// getJumpTargetOpValue - Return binary encoding of the jump 192/// target operand. If the machine operand requires relocation, 193/// record the relocation and return zero. 194unsigned MipsMCCodeEmitter:: 195getJumpTargetOpValue(const MCInst &MI, unsigned OpNo, 196 SmallVectorImpl<MCFixup> &Fixups) const { 197 198 const MCOperand &MO = MI.getOperand(OpNo); 199 // If the destination is an immediate, divide by 4. 200 if (MO.isImm()) return MO.getImm()>>2; 201 202 assert(MO.isExpr() && 203 "getJumpTargetOpValue expects only expressions or an immediate"); 204 205 const MCExpr *Expr = MO.getExpr(); 206 Fixups.push_back(MCFixup::Create(0, Expr, 207 MCFixupKind(Mips::fixup_Mips_26))); 208 return 0; 209} 210 211unsigned MipsMCCodeEmitter:: 212getExprOpValue(const MCExpr *Expr,SmallVectorImpl<MCFixup> &Fixups) const { 213 int64_t Res; 214 215 if (Expr->EvaluateAsAbsolute(Res)) 216 return Res; 217 218 MCExpr::ExprKind Kind = Expr->getKind(); 219 if (Kind == MCExpr::Constant) { 220 return cast<MCConstantExpr>(Expr)->getValue(); 221 } 222 223 if (Kind == MCExpr::Binary) { 224 unsigned Res = getExprOpValue(cast<MCBinaryExpr>(Expr)->getLHS(), Fixups); 225 Res += getExprOpValue(cast<MCBinaryExpr>(Expr)->getRHS(), Fixups); 226 return Res; 227 } 228 if (Kind == MCExpr::SymbolRef) { 229 Mips::Fixups FixupKind = Mips::Fixups(0); 230 231 switch(cast<MCSymbolRefExpr>(Expr)->getKind()) { 232 default: llvm_unreachable("Unknown fixup kind!"); 233 break; 234 case MCSymbolRefExpr::VK_Mips_GPOFF_HI : 235 FixupKind = Mips::fixup_Mips_GPOFF_HI; 236 break; 237 case MCSymbolRefExpr::VK_Mips_GPOFF_LO : 238 FixupKind = Mips::fixup_Mips_GPOFF_LO; 239 break; 240 case MCSymbolRefExpr::VK_Mips_GOT_PAGE : 241 FixupKind = Mips::fixup_Mips_GOT_PAGE; 242 break; 243 case MCSymbolRefExpr::VK_Mips_GOT_OFST : 244 FixupKind = Mips::fixup_Mips_GOT_OFST; 245 break; 246 case MCSymbolRefExpr::VK_Mips_GOT_DISP : 247 FixupKind = Mips::fixup_Mips_GOT_DISP; 248 break; 249 case MCSymbolRefExpr::VK_Mips_GPREL: 250 FixupKind = Mips::fixup_Mips_GPREL16; 251 break; 252 case MCSymbolRefExpr::VK_Mips_GOT_CALL: 253 FixupKind = Mips::fixup_Mips_CALL16; 254 break; 255 case MCSymbolRefExpr::VK_Mips_GOT16: 256 FixupKind = Mips::fixup_Mips_GOT_Global; 257 break; 258 case MCSymbolRefExpr::VK_Mips_GOT: 259 FixupKind = Mips::fixup_Mips_GOT_Local; 260 break; 261 case MCSymbolRefExpr::VK_Mips_ABS_HI: 262 FixupKind = Mips::fixup_Mips_HI16; 263 break; 264 case MCSymbolRefExpr::VK_Mips_ABS_LO: 265 FixupKind = Mips::fixup_Mips_LO16; 266 break; 267 case MCSymbolRefExpr::VK_Mips_TLSGD: 268 FixupKind = Mips::fixup_Mips_TLSGD; 269 break; 270 case MCSymbolRefExpr::VK_Mips_TLSLDM: 271 FixupKind = Mips::fixup_Mips_TLSLDM; 272 break; 273 case MCSymbolRefExpr::VK_Mips_DTPREL_HI: 274 FixupKind = Mips::fixup_Mips_DTPREL_HI; 275 break; 276 case MCSymbolRefExpr::VK_Mips_DTPREL_LO: 277 FixupKind = Mips::fixup_Mips_DTPREL_LO; 278 break; 279 case MCSymbolRefExpr::VK_Mips_GOTTPREL: 280 FixupKind = Mips::fixup_Mips_GOTTPREL; 281 break; 282 case MCSymbolRefExpr::VK_Mips_TPREL_HI: 283 FixupKind = Mips::fixup_Mips_TPREL_HI; 284 break; 285 case MCSymbolRefExpr::VK_Mips_TPREL_LO: 286 FixupKind = Mips::fixup_Mips_TPREL_LO; 287 break; 288 case MCSymbolRefExpr::VK_Mips_HIGHER: 289 FixupKind = Mips::fixup_Mips_HIGHER; 290 break; 291 case MCSymbolRefExpr::VK_Mips_HIGHEST: 292 FixupKind = Mips::fixup_Mips_HIGHEST; 293 break; 294 case MCSymbolRefExpr::VK_Mips_GOT_HI16: 295 FixupKind = Mips::fixup_Mips_GOT_HI16; 296 break; 297 case MCSymbolRefExpr::VK_Mips_GOT_LO16: 298 FixupKind = Mips::fixup_Mips_GOT_LO16; 299 break; 300 case MCSymbolRefExpr::VK_Mips_CALL_HI16: 301 FixupKind = Mips::fixup_Mips_CALL_HI16; 302 break; 303 case MCSymbolRefExpr::VK_Mips_CALL_LO16: 304 FixupKind = Mips::fixup_Mips_CALL_LO16; 305 break; 306 } // switch 307 308 Fixups.push_back(MCFixup::Create(0, Expr, MCFixupKind(FixupKind))); 309 return 0; 310 } 311 return 0; 312} 313 314/// getMachineOpValue - Return binary encoding of operand. If the machine 315/// operand requires relocation, record the relocation and return zero. 316unsigned MipsMCCodeEmitter:: 317getMachineOpValue(const MCInst &MI, const MCOperand &MO, 318 SmallVectorImpl<MCFixup> &Fixups) const { 319 if (MO.isReg()) { 320 unsigned Reg = MO.getReg(); 321 unsigned RegNo = Ctx.getRegisterInfo().getEncodingValue(Reg); 322 return RegNo; 323 } else if (MO.isImm()) { 324 return static_cast<unsigned>(MO.getImm()); 325 } else if (MO.isFPImm()) { 326 return static_cast<unsigned>(APFloat(MO.getFPImm()) 327 .bitcastToAPInt().getHiBits(32).getLimitedValue()); 328 } 329 // MO must be an Expr. 330 assert(MO.isExpr()); 331 return getExprOpValue(MO.getExpr(),Fixups); 332} 333 334/// getMemEncoding - Return binary encoding of memory related operand. 335/// If the offset operand requires relocation, record the relocation. 336unsigned 337MipsMCCodeEmitter::getMemEncoding(const MCInst &MI, unsigned OpNo, 338 SmallVectorImpl<MCFixup> &Fixups) const { 339 // Base register is encoded in bits 20-16, offset is encoded in bits 15-0. 340 assert(MI.getOperand(OpNo).isReg()); 341 unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo),Fixups) << 16; 342 unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups); 343 344 return (OffBits & 0xFFFF) | RegBits; 345} 346 347unsigned 348MipsMCCodeEmitter::getSizeExtEncoding(const MCInst &MI, unsigned OpNo, 349 SmallVectorImpl<MCFixup> &Fixups) const { 350 assert(MI.getOperand(OpNo).isImm()); 351 unsigned SizeEncoding = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups); 352 return SizeEncoding - 1; 353} 354 355// FIXME: should be called getMSBEncoding 356// 357unsigned 358MipsMCCodeEmitter::getSizeInsEncoding(const MCInst &MI, unsigned OpNo, 359 SmallVectorImpl<MCFixup> &Fixups) const { 360 assert(MI.getOperand(OpNo-1).isImm()); 361 assert(MI.getOperand(OpNo).isImm()); 362 unsigned Position = getMachineOpValue(MI, MI.getOperand(OpNo-1), Fixups); 363 unsigned Size = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups); 364 365 return Position + Size - 1; 366} 367 368#include "MipsGenMCCodeEmitter.inc" 369 370