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