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