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