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