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