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