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