1234353Sdim//===-- MipsMCCodeEmitter.cpp - Convert Mips Code to Machine Code ---------===// 2226584Sdim// 3226584Sdim// The LLVM Compiler Infrastructure 4226584Sdim// 5226584Sdim// This file is distributed under the University of Illinois Open Source 6226584Sdim// License. See LICENSE.TXT for details. 7226584Sdim// 8226584Sdim//===----------------------------------------------------------------------===// 9226584Sdim// 10226584Sdim// This file implements the MipsMCCodeEmitter class. 11226584Sdim// 12226584Sdim//===----------------------------------------------------------------------===// 13226584Sdim// 14276479Sdim 15276479Sdim#include "MipsMCCodeEmitter.h" 16234353Sdim#include "MCTargetDesc/MipsFixupKinds.h" 17276479Sdim#include "MCTargetDesc/MipsMCExpr.h" 18234353Sdim#include "MCTargetDesc/MipsMCTargetDesc.h" 19234353Sdim#include "llvm/ADT/APFloat.h" 20276479Sdim#include "llvm/ADT/SmallVector.h" 21249423Sdim#include "llvm/MC/MCContext.h" 22226584Sdim#include "llvm/MC/MCExpr.h" 23280031Sdim#include "llvm/MC/MCFixup.h" 24226584Sdim#include "llvm/MC/MCInst.h" 25226584Sdim#include "llvm/MC/MCInstrInfo.h" 26288943Sdim#include "llvm/MC/MCRegisterInfo.h" 27226584Sdim#include "llvm/MC/MCSubtargetInfo.h" 28226584Sdim#include "llvm/Support/raw_ostream.h" 29226584Sdim 30276479Sdim#define DEBUG_TYPE "mccodeemitter" 31276479Sdim 32251662Sdim#define GET_INSTRMAP_INFO 33251662Sdim#include "MipsGenInstrInfo.inc" 34276479Sdim#undef GET_INSTRMAP_INFO 35251662Sdim 36276479Sdimnamespace llvm { 37276479SdimMCCodeEmitter *createMipsMCCodeEmitterEB(const MCInstrInfo &MCII, 38276479Sdim const MCRegisterInfo &MRI, 39276479Sdim MCContext &Ctx) { 40276479Sdim return new MipsMCCodeEmitter(MCII, Ctx, false); 41226584Sdim} 42234353Sdim 43276479SdimMCCodeEmitter *createMipsMCCodeEmitterEL(const MCInstrInfo &MCII, 44276479Sdim const MCRegisterInfo &MRI, 45276479Sdim MCContext &Ctx) { 46276479Sdim return new MipsMCCodeEmitter(MCII, Ctx, true); 47234353Sdim} 48276479Sdim} // End of namespace llvm. 49234353Sdim 50261991Sdim// If the D<shift> instruction has a shift amount that is greater 51261991Sdim// than 31 (checked in calling routine), lower it to a D<shift>32 instruction 52261991Sdimstatic void LowerLargeShift(MCInst& Inst) { 53261991Sdim 54261991Sdim assert(Inst.getNumOperands() == 3 && "Invalid no. of operands for shift!"); 55261991Sdim assert(Inst.getOperand(2).isImm()); 56261991Sdim 57261991Sdim int64_t Shift = Inst.getOperand(2).getImm(); 58261991Sdim if (Shift <= 31) 59261991Sdim return; // Do nothing 60261991Sdim Shift -= 32; 61261991Sdim 62261991Sdim // saminus32 63261991Sdim Inst.getOperand(2).setImm(Shift); 64261991Sdim 65261991Sdim switch (Inst.getOpcode()) { 66261991Sdim default: 67261991Sdim // Calling function is not synchronized 68261991Sdim llvm_unreachable("Unexpected shift instruction"); 69261991Sdim case Mips::DSLL: 70261991Sdim Inst.setOpcode(Mips::DSLL32); 71261991Sdim return; 72261991Sdim case Mips::DSRL: 73261991Sdim Inst.setOpcode(Mips::DSRL32); 74261991Sdim return; 75261991Sdim case Mips::DSRA: 76261991Sdim Inst.setOpcode(Mips::DSRA32); 77261991Sdim return; 78261991Sdim case Mips::DROTR: 79261991Sdim Inst.setOpcode(Mips::DROTR32); 80261991Sdim return; 81261991Sdim } 82261991Sdim} 83261991Sdim 84261991Sdim// Pick a DEXT or DINS instruction variant based on the pos and size operands 85261991Sdimstatic void LowerDextDins(MCInst& InstIn) { 86261991Sdim int Opcode = InstIn.getOpcode(); 87261991Sdim 88261991Sdim if (Opcode == Mips::DEXT) 89261991Sdim assert(InstIn.getNumOperands() == 4 && 90261991Sdim "Invalid no. of machine operands for DEXT!"); 91261991Sdim else // Only DEXT and DINS are possible 92261991Sdim assert(InstIn.getNumOperands() == 5 && 93261991Sdim "Invalid no. of machine operands for DINS!"); 94261991Sdim 95261991Sdim assert(InstIn.getOperand(2).isImm()); 96261991Sdim int64_t pos = InstIn.getOperand(2).getImm(); 97261991Sdim assert(InstIn.getOperand(3).isImm()); 98261991Sdim int64_t size = InstIn.getOperand(3).getImm(); 99261991Sdim 100261991Sdim if (size <= 32) { 101261991Sdim if (pos < 32) // DEXT/DINS, do nothing 102261991Sdim return; 103261991Sdim // DEXTU/DINSU 104261991Sdim InstIn.getOperand(2).setImm(pos - 32); 105261991Sdim InstIn.setOpcode((Opcode == Mips::DEXT) ? Mips::DEXTU : Mips::DINSU); 106261991Sdim return; 107261991Sdim } 108261991Sdim // DEXTM/DINSM 109261991Sdim assert(pos < 32 && "DEXT/DINS cannot have both size and pos > 32"); 110261991Sdim InstIn.getOperand(3).setImm(size - 32); 111261991Sdim InstIn.setOpcode((Opcode == Mips::DEXT) ? Mips::DEXTM : Mips::DINSM); 112261991Sdim return; 113261991Sdim} 114261991Sdim 115276479Sdimbool MipsMCCodeEmitter::isMicroMips(const MCSubtargetInfo &STI) const { 116288943Sdim return STI.getFeatureBits()[Mips::FeatureMicroMips]; 117276479Sdim} 118276479Sdim 119288943Sdimbool MipsMCCodeEmitter::isMips32r6(const MCSubtargetInfo &STI) const { 120288943Sdim return STI.getFeatureBits()[Mips::FeatureMips32r6]; 121288943Sdim} 122288943Sdim 123276479Sdimvoid MipsMCCodeEmitter::EmitByte(unsigned char C, raw_ostream &OS) const { 124276479Sdim OS << (char)C; 125276479Sdim} 126276479Sdim 127276479Sdimvoid MipsMCCodeEmitter::EmitInstruction(uint64_t Val, unsigned Size, 128276479Sdim const MCSubtargetInfo &STI, 129276479Sdim raw_ostream &OS) const { 130276479Sdim // Output the instruction encoding in little endian byte order. 131276479Sdim // Little-endian byte ordering: 132276479Sdim // mips32r2: 4 | 3 | 2 | 1 133276479Sdim // microMIPS: 2 | 1 | 4 | 3 134276479Sdim if (IsLittleEndian && Size == 4 && isMicroMips(STI)) { 135276479Sdim EmitInstruction(Val >> 16, 2, STI, OS); 136276479Sdim EmitInstruction(Val, 2, STI, OS); 137276479Sdim } else { 138276479Sdim for (unsigned i = 0; i < Size; ++i) { 139276479Sdim unsigned Shift = IsLittleEndian ? i * 8 : (Size - 1 - i) * 8; 140276479Sdim EmitByte((Val >> Shift) & 0xff, OS); 141276479Sdim } 142276479Sdim } 143276479Sdim} 144276479Sdim 145288943Sdim/// encodeInstruction - Emit the instruction. 146261991Sdim/// Size the instruction with Desc.getSize(). 147234353Sdimvoid MipsMCCodeEmitter:: 148288943SdimencodeInstruction(const MCInst &MI, raw_ostream &OS, 149276479Sdim SmallVectorImpl<MCFixup> &Fixups, 150276479Sdim const MCSubtargetInfo &STI) const 151234353Sdim{ 152234353Sdim 153243830Sdim // Non-pseudo instructions that get changed for direct object 154243830Sdim // only based on operand values. 155243830Sdim // If this list of instructions get much longer we will move 156243830Sdim // the check to a function call. Until then, this is more efficient. 157243830Sdim MCInst TmpInst = MI; 158243830Sdim switch (MI.getOpcode()) { 159243830Sdim // If shift amount is >= 32 it the inst needs to be lowered further 160243830Sdim case Mips::DSLL: 161243830Sdim case Mips::DSRL: 162243830Sdim case Mips::DSRA: 163261991Sdim case Mips::DROTR: 164261991Sdim LowerLargeShift(TmpInst); 165243830Sdim break; 166243830Sdim // Double extract instruction is chosen by pos and size operands 167243830Sdim case Mips::DEXT: 168243830Sdim case Mips::DINS: 169261991Sdim LowerDextDins(TmpInst); 170243830Sdim } 171243830Sdim 172261991Sdim unsigned long N = Fixups.size(); 173276479Sdim uint32_t Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI); 174243830Sdim 175234353Sdim // Check for unimplemented opcodes. 176243830Sdim // Unfortunately in MIPS both NOP and SLL will come in with Binary == 0 177234353Sdim // so we have to special check for them. 178243830Sdim unsigned Opcode = TmpInst.getOpcode(); 179280031Sdim if ((Opcode != Mips::NOP) && (Opcode != Mips::SLL) && 180280031Sdim (Opcode != Mips::SLL_MM) && !Binary) 181288943Sdim llvm_unreachable("unimplemented opcode in encodeInstruction()"); 182234353Sdim 183288943Sdim int NewOpcode = -1; 184288943Sdim if (isMicroMips(STI)) { 185288943Sdim if (isMips32r6(STI)) { 186288943Sdim NewOpcode = Mips::MipsR62MicroMipsR6(Opcode, Mips::Arch_micromipsr6); 187288943Sdim if (NewOpcode == -1) 188288943Sdim NewOpcode = Mips::Std2MicroMipsR6(Opcode, Mips::Arch_micromipsr6); 189288943Sdim } 190288943Sdim else 191288943Sdim NewOpcode = Mips::Std2MicroMips(Opcode, Mips::Arch_micromips); 192288943Sdim 193296417Sdim // Check whether it is Dsp instruction. 194296417Sdim if (NewOpcode == -1) 195296417Sdim NewOpcode = Mips::Dsp2MicroMips(Opcode, Mips::Arch_mmdsp); 196296417Sdim 197251662Sdim if (NewOpcode != -1) { 198261991Sdim if (Fixups.size() > N) 199261991Sdim Fixups.pop_back(); 200288943Sdim 201251662Sdim Opcode = NewOpcode; 202251662Sdim TmpInst.setOpcode (NewOpcode); 203276479Sdim Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI); 204251662Sdim } 205251662Sdim } 206251662Sdim 207243830Sdim const MCInstrDesc &Desc = MCII.get(TmpInst.getOpcode()); 208234353Sdim 209243830Sdim // Get byte count of instruction 210243830Sdim unsigned Size = Desc.getSize(); 211243830Sdim if (!Size) 212243830Sdim llvm_unreachable("Desc.getSize() returns 0"); 213234353Sdim 214276479Sdim EmitInstruction(Binary, Size, STI, OS); 215234353Sdim} 216234353Sdim 217234353Sdim/// getBranchTargetOpValue - Return binary encoding of the branch 218234353Sdim/// target operand. If the machine operand requires relocation, 219234353Sdim/// record the relocation and return zero. 220234353Sdimunsigned MipsMCCodeEmitter:: 221234353SdimgetBranchTargetOpValue(const MCInst &MI, unsigned OpNo, 222276479Sdim SmallVectorImpl<MCFixup> &Fixups, 223276479Sdim const MCSubtargetInfo &STI) const { 224234353Sdim 225234353Sdim const MCOperand &MO = MI.getOperand(OpNo); 226234353Sdim 227249423Sdim // If the destination is an immediate, divide by 4. 228249423Sdim if (MO.isImm()) return MO.getImm() >> 2; 229249423Sdim 230243830Sdim assert(MO.isExpr() && 231243830Sdim "getBranchTargetOpValue expects only expressions or immediates"); 232243830Sdim 233288943Sdim const MCExpr *FixupExpression = MCBinaryExpr::createAdd( 234288943Sdim MO.getExpr(), MCConstantExpr::create(-4, Ctx), Ctx); 235288943Sdim Fixups.push_back(MCFixup::create(0, FixupExpression, 236234353Sdim MCFixupKind(Mips::fixup_Mips_PC16))); 237234353Sdim return 0; 238234353Sdim} 239234353Sdim 240280031Sdim/// getBranchTarget7OpValueMM - Return binary encoding of the microMIPS branch 241280031Sdim/// target operand. If the machine operand requires relocation, 242280031Sdim/// record the relocation and return zero. 243280031Sdimunsigned MipsMCCodeEmitter:: 244280031SdimgetBranchTarget7OpValueMM(const MCInst &MI, unsigned OpNo, 245280031Sdim SmallVectorImpl<MCFixup> &Fixups, 246280031Sdim const MCSubtargetInfo &STI) const { 247280031Sdim 248280031Sdim const MCOperand &MO = MI.getOperand(OpNo); 249280031Sdim 250280031Sdim // If the destination is an immediate, divide by 2. 251280031Sdim if (MO.isImm()) return MO.getImm() >> 1; 252280031Sdim 253280031Sdim assert(MO.isExpr() && 254280031Sdim "getBranchTargetOpValueMM expects only expressions or immediates"); 255280031Sdim 256280031Sdim const MCExpr *Expr = MO.getExpr(); 257288943Sdim Fixups.push_back(MCFixup::create(0, Expr, 258280031Sdim MCFixupKind(Mips::fixup_MICROMIPS_PC7_S1))); 259280031Sdim return 0; 260280031Sdim} 261280031Sdim 262288943Sdim/// getBranchTargetOpValueMMPC10 - Return binary encoding of the microMIPS 263288943Sdim/// 10-bit branch target operand. If the machine operand requires relocation, 264288943Sdim/// record the relocation and return zero. 265288943Sdimunsigned MipsMCCodeEmitter:: 266288943SdimgetBranchTargetOpValueMMPC10(const MCInst &MI, unsigned OpNo, 267288943Sdim SmallVectorImpl<MCFixup> &Fixups, 268288943Sdim const MCSubtargetInfo &STI) const { 269288943Sdim 270288943Sdim const MCOperand &MO = MI.getOperand(OpNo); 271288943Sdim 272288943Sdim // If the destination is an immediate, divide by 2. 273288943Sdim if (MO.isImm()) return MO.getImm() >> 1; 274288943Sdim 275288943Sdim assert(MO.isExpr() && 276288943Sdim "getBranchTargetOpValuePC10 expects only expressions or immediates"); 277288943Sdim 278288943Sdim const MCExpr *Expr = MO.getExpr(); 279288943Sdim Fixups.push_back(MCFixup::create(0, Expr, 280288943Sdim MCFixupKind(Mips::fixup_MICROMIPS_PC10_S1))); 281288943Sdim return 0; 282288943Sdim} 283288943Sdim 284261991Sdim/// getBranchTargetOpValue - Return binary encoding of the microMIPS branch 285261991Sdim/// target operand. If the machine operand requires relocation, 286261991Sdim/// record the relocation and return zero. 287261991Sdimunsigned MipsMCCodeEmitter:: 288261991SdimgetBranchTargetOpValueMM(const MCInst &MI, unsigned OpNo, 289276479Sdim SmallVectorImpl<MCFixup> &Fixups, 290276479Sdim const MCSubtargetInfo &STI) const { 291261991Sdim 292261991Sdim const MCOperand &MO = MI.getOperand(OpNo); 293261991Sdim 294261991Sdim // If the destination is an immediate, divide by 2. 295261991Sdim if (MO.isImm()) return MO.getImm() >> 1; 296261991Sdim 297261991Sdim assert(MO.isExpr() && 298261991Sdim "getBranchTargetOpValueMM expects only expressions or immediates"); 299261991Sdim 300261991Sdim const MCExpr *Expr = MO.getExpr(); 301288943Sdim Fixups.push_back(MCFixup::create(0, Expr, 302261991Sdim MCFixupKind(Mips:: 303261991Sdim fixup_MICROMIPS_PC16_S1))); 304261991Sdim return 0; 305261991Sdim} 306261991Sdim 307276479Sdim/// getBranchTarget21OpValue - Return binary encoding of the branch 308276479Sdim/// target operand. If the machine operand requires relocation, 309276479Sdim/// record the relocation and return zero. 310276479Sdimunsigned MipsMCCodeEmitter:: 311276479SdimgetBranchTarget21OpValue(const MCInst &MI, unsigned OpNo, 312276479Sdim SmallVectorImpl<MCFixup> &Fixups, 313276479Sdim const MCSubtargetInfo &STI) const { 314276479Sdim 315276479Sdim const MCOperand &MO = MI.getOperand(OpNo); 316276479Sdim 317276479Sdim // If the destination is an immediate, divide by 4. 318276479Sdim if (MO.isImm()) return MO.getImm() >> 2; 319276479Sdim 320276479Sdim assert(MO.isExpr() && 321276479Sdim "getBranchTarget21OpValue expects only expressions or immediates"); 322276479Sdim 323288943Sdim const MCExpr *FixupExpression = MCBinaryExpr::createAdd( 324288943Sdim MO.getExpr(), MCConstantExpr::create(-4, Ctx), Ctx); 325288943Sdim Fixups.push_back(MCFixup::create(0, FixupExpression, 326276479Sdim MCFixupKind(Mips::fixup_MIPS_PC21_S2))); 327276479Sdim return 0; 328276479Sdim} 329276479Sdim 330276479Sdim/// getBranchTarget26OpValue - Return binary encoding of the branch 331276479Sdim/// target operand. If the machine operand requires relocation, 332276479Sdim/// record the relocation and return zero. 333276479Sdimunsigned MipsMCCodeEmitter:: 334276479SdimgetBranchTarget26OpValue(const MCInst &MI, unsigned OpNo, 335276479Sdim SmallVectorImpl<MCFixup> &Fixups, 336276479Sdim const MCSubtargetInfo &STI) const { 337276479Sdim 338276479Sdim const MCOperand &MO = MI.getOperand(OpNo); 339276479Sdim 340276479Sdim // If the destination is an immediate, divide by 4. 341276479Sdim if (MO.isImm()) return MO.getImm() >> 2; 342276479Sdim 343276479Sdim assert(MO.isExpr() && 344276479Sdim "getBranchTarget26OpValue expects only expressions or immediates"); 345276479Sdim 346288943Sdim const MCExpr *FixupExpression = MCBinaryExpr::createAdd( 347288943Sdim MO.getExpr(), MCConstantExpr::create(-4, Ctx), Ctx); 348288943Sdim Fixups.push_back(MCFixup::create(0, FixupExpression, 349276479Sdim MCFixupKind(Mips::fixup_MIPS_PC26_S2))); 350276479Sdim return 0; 351276479Sdim} 352276479Sdim 353296417Sdim/// getBranchTarget26OpValueMM - Return binary encoding of the branch 354296417Sdim/// target operand. If the machine operand requires relocation, 355296417Sdim/// record the relocation and return zero. 356296417Sdimunsigned MipsMCCodeEmitter::getBranchTarget26OpValueMM( 357296417Sdim const MCInst &MI, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups, 358296417Sdim const MCSubtargetInfo &STI) const { 359296417Sdim 360296417Sdim const MCOperand &MO = MI.getOperand(OpNo); 361296417Sdim 362296417Sdim // If the destination is an immediate, divide by 2. 363296417Sdim if (MO.isImm()) 364296417Sdim return MO.getImm() >> 1; 365296417Sdim 366296417Sdim // TODO: Push 26 PC fixup. 367296417Sdim return 0; 368296417Sdim} 369296417Sdim 370276479Sdim/// getJumpOffset16OpValue - Return binary encoding of the jump 371276479Sdim/// target operand. If the machine operand requires relocation, 372276479Sdim/// record the relocation and return zero. 373276479Sdimunsigned MipsMCCodeEmitter:: 374276479SdimgetJumpOffset16OpValue(const MCInst &MI, unsigned OpNo, 375276479Sdim SmallVectorImpl<MCFixup> &Fixups, 376276479Sdim const MCSubtargetInfo &STI) const { 377276479Sdim 378276479Sdim const MCOperand &MO = MI.getOperand(OpNo); 379276479Sdim 380276479Sdim if (MO.isImm()) return MO.getImm(); 381276479Sdim 382276479Sdim assert(MO.isExpr() && 383276479Sdim "getJumpOffset16OpValue expects only expressions or an immediate"); 384276479Sdim 385276479Sdim // TODO: Push fixup. 386276479Sdim return 0; 387276479Sdim} 388276479Sdim 389234353Sdim/// getJumpTargetOpValue - Return binary encoding of the jump 390234353Sdim/// target operand. If the machine operand requires relocation, 391234353Sdim/// record the relocation and return zero. 392234353Sdimunsigned MipsMCCodeEmitter:: 393234353SdimgetJumpTargetOpValue(const MCInst &MI, unsigned OpNo, 394276479Sdim SmallVectorImpl<MCFixup> &Fixups, 395276479Sdim const MCSubtargetInfo &STI) const { 396234353Sdim 397234353Sdim const MCOperand &MO = MI.getOperand(OpNo); 398249423Sdim // If the destination is an immediate, divide by 4. 399249423Sdim if (MO.isImm()) return MO.getImm()>>2; 400249423Sdim 401243830Sdim assert(MO.isExpr() && 402243830Sdim "getJumpTargetOpValue expects only expressions or an immediate"); 403234353Sdim 404234353Sdim const MCExpr *Expr = MO.getExpr(); 405288943Sdim Fixups.push_back(MCFixup::create(0, Expr, 406234353Sdim MCFixupKind(Mips::fixup_Mips_26))); 407234353Sdim return 0; 408234353Sdim} 409234353Sdim 410234353Sdimunsigned MipsMCCodeEmitter:: 411261991SdimgetJumpTargetOpValueMM(const MCInst &MI, unsigned OpNo, 412276479Sdim SmallVectorImpl<MCFixup> &Fixups, 413276479Sdim const MCSubtargetInfo &STI) const { 414261991Sdim 415261991Sdim const MCOperand &MO = MI.getOperand(OpNo); 416261991Sdim // If the destination is an immediate, divide by 2. 417261991Sdim if (MO.isImm()) return MO.getImm() >> 1; 418261991Sdim 419261991Sdim assert(MO.isExpr() && 420261991Sdim "getJumpTargetOpValueMM expects only expressions or an immediate"); 421261991Sdim 422261991Sdim const MCExpr *Expr = MO.getExpr(); 423288943Sdim Fixups.push_back(MCFixup::create(0, Expr, 424261991Sdim MCFixupKind(Mips::fixup_MICROMIPS_26_S1))); 425261991Sdim return 0; 426261991Sdim} 427261991Sdim 428261991Sdimunsigned MipsMCCodeEmitter:: 429280031SdimgetUImm5Lsl2Encoding(const MCInst &MI, unsigned OpNo, 430280031Sdim SmallVectorImpl<MCFixup> &Fixups, 431280031Sdim const MCSubtargetInfo &STI) const { 432280031Sdim 433280031Sdim const MCOperand &MO = MI.getOperand(OpNo); 434280031Sdim if (MO.isImm()) { 435280031Sdim // The immediate is encoded as 'immediate << 2'. 436280031Sdim unsigned Res = getMachineOpValue(MI, MO, Fixups, STI); 437280031Sdim assert((Res & 3) == 0); 438280031Sdim return Res >> 2; 439280031Sdim } 440280031Sdim 441280031Sdim assert(MO.isExpr() && 442280031Sdim "getUImm5Lsl2Encoding expects only expressions or an immediate"); 443280031Sdim 444280031Sdim return 0; 445280031Sdim} 446280031Sdim 447280031Sdimunsigned MipsMCCodeEmitter:: 448280031SdimgetSImm3Lsa2Value(const MCInst &MI, unsigned OpNo, 449280031Sdim SmallVectorImpl<MCFixup> &Fixups, 450280031Sdim const MCSubtargetInfo &STI) const { 451280031Sdim 452280031Sdim const MCOperand &MO = MI.getOperand(OpNo); 453280031Sdim if (MO.isImm()) { 454280031Sdim int Value = MO.getImm(); 455280031Sdim return Value >> 2; 456280031Sdim } 457280031Sdim 458280031Sdim return 0; 459280031Sdim} 460280031Sdim 461280031Sdimunsigned MipsMCCodeEmitter:: 462280031SdimgetUImm6Lsl2Encoding(const MCInst &MI, unsigned OpNo, 463280031Sdim SmallVectorImpl<MCFixup> &Fixups, 464280031Sdim const MCSubtargetInfo &STI) const { 465280031Sdim 466280031Sdim const MCOperand &MO = MI.getOperand(OpNo); 467280031Sdim if (MO.isImm()) { 468280031Sdim unsigned Value = MO.getImm(); 469280031Sdim return Value >> 2; 470280031Sdim } 471280031Sdim 472280031Sdim return 0; 473280031Sdim} 474280031Sdim 475280031Sdimunsigned MipsMCCodeEmitter:: 476280031SdimgetSImm9AddiuspValue(const MCInst &MI, unsigned OpNo, 477280031Sdim SmallVectorImpl<MCFixup> &Fixups, 478280031Sdim const MCSubtargetInfo &STI) const { 479280031Sdim 480280031Sdim const MCOperand &MO = MI.getOperand(OpNo); 481280031Sdim if (MO.isImm()) { 482280031Sdim unsigned Binary = (MO.getImm() >> 2) & 0x0000ffff; 483280031Sdim return (((Binary & 0x8000) >> 7) | (Binary & 0x00ff)); 484280031Sdim } 485280031Sdim 486280031Sdim return 0; 487280031Sdim} 488280031Sdim 489280031Sdimunsigned MipsMCCodeEmitter:: 490288943SdimgetExprOpValue(const MCExpr *Expr, SmallVectorImpl<MCFixup> &Fixups, 491276479Sdim const MCSubtargetInfo &STI) const { 492251662Sdim int64_t Res; 493234353Sdim 494288943Sdim if (Expr->evaluateAsAbsolute(Res)) 495251662Sdim return Res; 496234353Sdim 497234353Sdim MCExpr::ExprKind Kind = Expr->getKind(); 498251662Sdim if (Kind == MCExpr::Constant) { 499251662Sdim return cast<MCConstantExpr>(Expr)->getValue(); 500251662Sdim } 501234353Sdim 502234353Sdim if (Kind == MCExpr::Binary) { 503276479Sdim unsigned Res = getExprOpValue(cast<MCBinaryExpr>(Expr)->getLHS(), Fixups, STI); 504276479Sdim Res += getExprOpValue(cast<MCBinaryExpr>(Expr)->getRHS(), Fixups, STI); 505251662Sdim return Res; 506234353Sdim } 507276479Sdim 508276479Sdim if (Kind == MCExpr::Target) { 509276479Sdim const MipsMCExpr *MipsExpr = cast<MipsMCExpr>(Expr); 510276479Sdim 511276479Sdim Mips::Fixups FixupKind = Mips::Fixups(0); 512276479Sdim switch (MipsExpr->getKind()) { 513276479Sdim default: llvm_unreachable("Unsupported fixup kind for target expression!"); 514276479Sdim case MipsMCExpr::VK_Mips_HIGHEST: 515276479Sdim FixupKind = Mips::fixup_Mips_HIGHEST; 516276479Sdim break; 517276479Sdim case MipsMCExpr::VK_Mips_HIGHER: 518276479Sdim FixupKind = Mips::fixup_Mips_HIGHER; 519276479Sdim break; 520276479Sdim case MipsMCExpr::VK_Mips_HI: 521276479Sdim FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_HI16 522276479Sdim : Mips::fixup_Mips_HI16; 523276479Sdim break; 524276479Sdim case MipsMCExpr::VK_Mips_LO: 525276479Sdim FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_LO16 526276479Sdim : Mips::fixup_Mips_LO16; 527276479Sdim break; 528276479Sdim } 529288943Sdim Fixups.push_back(MCFixup::create(0, MipsExpr, MCFixupKind(FixupKind))); 530276479Sdim return 0; 531276479Sdim } 532276479Sdim 533251662Sdim if (Kind == MCExpr::SymbolRef) { 534276479Sdim Mips::Fixups FixupKind = Mips::Fixups(0); 535234353Sdim 536276479Sdim switch(cast<MCSymbolRefExpr>(Expr)->getKind()) { 537276479Sdim default: llvm_unreachable("Unknown fixup kind!"); 538276479Sdim break; 539288943Sdim case MCSymbolRefExpr::VK_None: 540288943Sdim FixupKind = Mips::fixup_Mips_32; // FIXME: This is ok for O32/N32 but not N64. 541288943Sdim break; 542276479Sdim case MCSymbolRefExpr::VK_Mips_GPOFF_HI : 543276479Sdim FixupKind = Mips::fixup_Mips_GPOFF_HI; 544276479Sdim break; 545276479Sdim case MCSymbolRefExpr::VK_Mips_GPOFF_LO : 546276479Sdim FixupKind = Mips::fixup_Mips_GPOFF_LO; 547276479Sdim break; 548276479Sdim case MCSymbolRefExpr::VK_Mips_GOT_PAGE : 549276479Sdim FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOT_PAGE 550276479Sdim : Mips::fixup_Mips_GOT_PAGE; 551276479Sdim break; 552276479Sdim case MCSymbolRefExpr::VK_Mips_GOT_OFST : 553276479Sdim FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOT_OFST 554276479Sdim : Mips::fixup_Mips_GOT_OFST; 555276479Sdim break; 556276479Sdim case MCSymbolRefExpr::VK_Mips_GOT_DISP : 557276479Sdim FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOT_DISP 558276479Sdim : Mips::fixup_Mips_GOT_DISP; 559276479Sdim break; 560276479Sdim case MCSymbolRefExpr::VK_Mips_GPREL: 561276479Sdim FixupKind = Mips::fixup_Mips_GPREL16; 562276479Sdim break; 563276479Sdim case MCSymbolRefExpr::VK_Mips_GOT_CALL: 564276479Sdim FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_CALL16 565276479Sdim : Mips::fixup_Mips_CALL16; 566276479Sdim break; 567276479Sdim case MCSymbolRefExpr::VK_Mips_GOT16: 568276479Sdim FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOT16 569276479Sdim : Mips::fixup_Mips_GOT_Global; 570276479Sdim break; 571276479Sdim case MCSymbolRefExpr::VK_Mips_GOT: 572276479Sdim FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOT16 573276479Sdim : Mips::fixup_Mips_GOT_Local; 574276479Sdim break; 575276479Sdim case MCSymbolRefExpr::VK_Mips_ABS_HI: 576276479Sdim FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_HI16 577276479Sdim : Mips::fixup_Mips_HI16; 578276479Sdim break; 579276479Sdim case MCSymbolRefExpr::VK_Mips_ABS_LO: 580276479Sdim FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_LO16 581276479Sdim : Mips::fixup_Mips_LO16; 582276479Sdim break; 583276479Sdim case MCSymbolRefExpr::VK_Mips_TLSGD: 584276479Sdim FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_GD 585276479Sdim : Mips::fixup_Mips_TLSGD; 586276479Sdim break; 587276479Sdim case MCSymbolRefExpr::VK_Mips_TLSLDM: 588276479Sdim FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_LDM 589276479Sdim : Mips::fixup_Mips_TLSLDM; 590276479Sdim break; 591276479Sdim case MCSymbolRefExpr::VK_Mips_DTPREL_HI: 592276479Sdim FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_DTPREL_HI16 593276479Sdim : Mips::fixup_Mips_DTPREL_HI; 594276479Sdim break; 595276479Sdim case MCSymbolRefExpr::VK_Mips_DTPREL_LO: 596276479Sdim FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_DTPREL_LO16 597276479Sdim : Mips::fixup_Mips_DTPREL_LO; 598276479Sdim break; 599276479Sdim case MCSymbolRefExpr::VK_Mips_GOTTPREL: 600276479Sdim FixupKind = Mips::fixup_Mips_GOTTPREL; 601276479Sdim break; 602276479Sdim case MCSymbolRefExpr::VK_Mips_TPREL_HI: 603276479Sdim FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_TPREL_HI16 604276479Sdim : Mips::fixup_Mips_TPREL_HI; 605276479Sdim break; 606276479Sdim case MCSymbolRefExpr::VK_Mips_TPREL_LO: 607276479Sdim FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_TPREL_LO16 608276479Sdim : Mips::fixup_Mips_TPREL_LO; 609276479Sdim break; 610276479Sdim case MCSymbolRefExpr::VK_Mips_HIGHER: 611276479Sdim FixupKind = Mips::fixup_Mips_HIGHER; 612276479Sdim break; 613276479Sdim case MCSymbolRefExpr::VK_Mips_HIGHEST: 614276479Sdim FixupKind = Mips::fixup_Mips_HIGHEST; 615276479Sdim break; 616276479Sdim case MCSymbolRefExpr::VK_Mips_GOT_HI16: 617276479Sdim FixupKind = Mips::fixup_Mips_GOT_HI16; 618276479Sdim break; 619276479Sdim case MCSymbolRefExpr::VK_Mips_GOT_LO16: 620276479Sdim FixupKind = Mips::fixup_Mips_GOT_LO16; 621276479Sdim break; 622276479Sdim case MCSymbolRefExpr::VK_Mips_CALL_HI16: 623276479Sdim FixupKind = Mips::fixup_Mips_CALL_HI16; 624276479Sdim break; 625276479Sdim case MCSymbolRefExpr::VK_Mips_CALL_LO16: 626276479Sdim FixupKind = Mips::fixup_Mips_CALL_LO16; 627276479Sdim break; 628276479Sdim case MCSymbolRefExpr::VK_Mips_PCREL_HI16: 629276479Sdim FixupKind = Mips::fixup_MIPS_PCHI16; 630276479Sdim break; 631276479Sdim case MCSymbolRefExpr::VK_Mips_PCREL_LO16: 632276479Sdim FixupKind = Mips::fixup_MIPS_PCLO16; 633276479Sdim break; 634276479Sdim } // switch 635234353Sdim 636288943Sdim Fixups.push_back(MCFixup::create(0, Expr, MCFixupKind(FixupKind))); 637251662Sdim return 0; 638251662Sdim } 639234353Sdim return 0; 640234353Sdim} 641234353Sdim 642251662Sdim/// getMachineOpValue - Return binary encoding of operand. If the machine 643251662Sdim/// operand requires relocation, record the relocation and return zero. 644251662Sdimunsigned MipsMCCodeEmitter:: 645251662SdimgetMachineOpValue(const MCInst &MI, const MCOperand &MO, 646276479Sdim SmallVectorImpl<MCFixup> &Fixups, 647276479Sdim const MCSubtargetInfo &STI) const { 648251662Sdim if (MO.isReg()) { 649251662Sdim unsigned Reg = MO.getReg(); 650261991Sdim unsigned RegNo = Ctx.getRegisterInfo()->getEncodingValue(Reg); 651251662Sdim return RegNo; 652251662Sdim } else if (MO.isImm()) { 653251662Sdim return static_cast<unsigned>(MO.getImm()); 654251662Sdim } else if (MO.isFPImm()) { 655251662Sdim return static_cast<unsigned>(APFloat(MO.getFPImm()) 656251662Sdim .bitcastToAPInt().getHiBits(32).getLimitedValue()); 657251662Sdim } 658251662Sdim // MO must be an Expr. 659251662Sdim assert(MO.isExpr()); 660276479Sdim return getExprOpValue(MO.getExpr(),Fixups, STI); 661251662Sdim} 662251662Sdim 663276479Sdim/// getMSAMemEncoding - Return binary encoding of memory operand for LD/ST 664276479Sdim/// instructions. 665276479Sdimunsigned 666276479SdimMipsMCCodeEmitter::getMSAMemEncoding(const MCInst &MI, unsigned OpNo, 667276479Sdim SmallVectorImpl<MCFixup> &Fixups, 668276479Sdim const MCSubtargetInfo &STI) const { 669276479Sdim // Base register is encoded in bits 20-16, offset is encoded in bits 15-0. 670276479Sdim assert(MI.getOperand(OpNo).isReg()); 671276479Sdim unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo),Fixups, STI) << 16; 672276479Sdim unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI); 673276479Sdim 674276479Sdim // The immediate field of an LD/ST instruction is scaled which means it must 675276479Sdim // be divided (when encoding) by the size (in bytes) of the instructions' 676276479Sdim // data format. 677276479Sdim // .b - 1 byte 678276479Sdim // .h - 2 bytes 679276479Sdim // .w - 4 bytes 680276479Sdim // .d - 8 bytes 681276479Sdim switch(MI.getOpcode()) 682276479Sdim { 683276479Sdim default: 684276479Sdim assert (0 && "Unexpected instruction"); 685276479Sdim break; 686276479Sdim case Mips::LD_B: 687276479Sdim case Mips::ST_B: 688276479Sdim // We don't need to scale the offset in this case 689276479Sdim break; 690276479Sdim case Mips::LD_H: 691276479Sdim case Mips::ST_H: 692276479Sdim OffBits >>= 1; 693276479Sdim break; 694276479Sdim case Mips::LD_W: 695276479Sdim case Mips::ST_W: 696276479Sdim OffBits >>= 2; 697276479Sdim break; 698276479Sdim case Mips::LD_D: 699276479Sdim case Mips::ST_D: 700276479Sdim OffBits >>= 3; 701276479Sdim break; 702276479Sdim } 703276479Sdim 704276479Sdim return (OffBits & 0xFFFF) | RegBits; 705276479Sdim} 706276479Sdim 707234353Sdim/// getMemEncoding - Return binary encoding of memory related operand. 708234353Sdim/// If the offset operand requires relocation, record the relocation. 709234353Sdimunsigned 710234353SdimMipsMCCodeEmitter::getMemEncoding(const MCInst &MI, unsigned OpNo, 711276479Sdim SmallVectorImpl<MCFixup> &Fixups, 712276479Sdim const MCSubtargetInfo &STI) const { 713234353Sdim // Base register is encoded in bits 20-16, offset is encoded in bits 15-0. 714234353Sdim assert(MI.getOperand(OpNo).isReg()); 715276479Sdim unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo),Fixups, STI) << 16; 716276479Sdim unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI); 717234353Sdim 718234353Sdim return (OffBits & 0xFFFF) | RegBits; 719234353Sdim} 720234353Sdim 721261991Sdimunsigned MipsMCCodeEmitter:: 722280031SdimgetMemEncodingMMImm4(const MCInst &MI, unsigned OpNo, 723280031Sdim SmallVectorImpl<MCFixup> &Fixups, 724280031Sdim const MCSubtargetInfo &STI) const { 725280031Sdim // Base register is encoded in bits 6-4, offset is encoded in bits 3-0. 726280031Sdim assert(MI.getOperand(OpNo).isReg()); 727280031Sdim unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), 728280031Sdim Fixups, STI) << 4; 729280031Sdim unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), 730280031Sdim Fixups, STI); 731280031Sdim 732280031Sdim return (OffBits & 0xF) | RegBits; 733280031Sdim} 734280031Sdim 735280031Sdimunsigned MipsMCCodeEmitter:: 736280031SdimgetMemEncodingMMImm4Lsl1(const MCInst &MI, unsigned OpNo, 737280031Sdim SmallVectorImpl<MCFixup> &Fixups, 738280031Sdim const MCSubtargetInfo &STI) const { 739280031Sdim // Base register is encoded in bits 6-4, offset is encoded in bits 3-0. 740280031Sdim assert(MI.getOperand(OpNo).isReg()); 741280031Sdim unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), 742280031Sdim Fixups, STI) << 4; 743280031Sdim unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), 744280031Sdim Fixups, STI) >> 1; 745280031Sdim 746280031Sdim return (OffBits & 0xF) | RegBits; 747280031Sdim} 748280031Sdim 749280031Sdimunsigned MipsMCCodeEmitter:: 750280031SdimgetMemEncodingMMImm4Lsl2(const MCInst &MI, unsigned OpNo, 751280031Sdim SmallVectorImpl<MCFixup> &Fixups, 752280031Sdim const MCSubtargetInfo &STI) const { 753280031Sdim // Base register is encoded in bits 6-4, offset is encoded in bits 3-0. 754280031Sdim assert(MI.getOperand(OpNo).isReg()); 755280031Sdim unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), 756280031Sdim Fixups, STI) << 4; 757280031Sdim unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), 758280031Sdim Fixups, STI) >> 2; 759280031Sdim 760280031Sdim return (OffBits & 0xF) | RegBits; 761280031Sdim} 762280031Sdim 763280031Sdimunsigned MipsMCCodeEmitter:: 764280031SdimgetMemEncodingMMSPImm5Lsl2(const MCInst &MI, unsigned OpNo, 765280031Sdim SmallVectorImpl<MCFixup> &Fixups, 766280031Sdim const MCSubtargetInfo &STI) const { 767280031Sdim // Register is encoded in bits 9-5, offset is encoded in bits 4-0. 768280031Sdim assert(MI.getOperand(OpNo).isReg() && 769296417Sdim (MI.getOperand(OpNo).getReg() == Mips::SP || 770296417Sdim MI.getOperand(OpNo).getReg() == Mips::SP_64) && 771280031Sdim "Unexpected base register!"); 772280031Sdim unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), 773280031Sdim Fixups, STI) >> 2; 774280031Sdim 775280031Sdim return OffBits & 0x1F; 776280031Sdim} 777280031Sdim 778280031Sdimunsigned MipsMCCodeEmitter:: 779288943SdimgetMemEncodingMMGPImm7Lsl2(const MCInst &MI, unsigned OpNo, 780288943Sdim SmallVectorImpl<MCFixup> &Fixups, 781288943Sdim const MCSubtargetInfo &STI) const { 782288943Sdim // Register is encoded in bits 9-7, offset is encoded in bits 6-0. 783288943Sdim assert(MI.getOperand(OpNo).isReg() && 784288943Sdim MI.getOperand(OpNo).getReg() == Mips::GP && 785288943Sdim "Unexpected base register!"); 786288943Sdim 787288943Sdim unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), 788288943Sdim Fixups, STI) >> 2; 789288943Sdim 790288943Sdim return OffBits & 0x7F; 791288943Sdim} 792288943Sdim 793288943Sdimunsigned MipsMCCodeEmitter:: 794296417SdimgetMemEncodingMMImm9(const MCInst &MI, unsigned OpNo, 795296417Sdim SmallVectorImpl<MCFixup> &Fixups, 796296417Sdim const MCSubtargetInfo &STI) const { 797296417Sdim // Base register is encoded in bits 20-16, offset is encoded in bits 8-0. 798296417Sdim assert(MI.getOperand(OpNo).isReg()); 799296417Sdim unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, 800296417Sdim STI) << 16; 801296417Sdim unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo + 1), Fixups, STI); 802296417Sdim 803296417Sdim return (OffBits & 0x1FF) | RegBits; 804296417Sdim} 805296417Sdim 806296417Sdimunsigned MipsMCCodeEmitter:: 807261991SdimgetMemEncodingMMImm12(const MCInst &MI, unsigned OpNo, 808276479Sdim SmallVectorImpl<MCFixup> &Fixups, 809276479Sdim const MCSubtargetInfo &STI) const { 810280031Sdim // opNum can be invalid if instruction had reglist as operand. 811280031Sdim // MemOperand is always last operand of instruction (base + offset). 812280031Sdim switch (MI.getOpcode()) { 813280031Sdim default: 814280031Sdim break; 815280031Sdim case Mips::SWM32_MM: 816280031Sdim case Mips::LWM32_MM: 817280031Sdim OpNo = MI.getNumOperands() - 2; 818280031Sdim break; 819280031Sdim } 820280031Sdim 821261991Sdim // Base register is encoded in bits 20-16, offset is encoded in bits 11-0. 822261991Sdim assert(MI.getOperand(OpNo).isReg()); 823276479Sdim unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI) << 16; 824276479Sdim unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI); 825261991Sdim 826261991Sdim return (OffBits & 0x0FFF) | RegBits; 827261991Sdim} 828261991Sdim 829280031Sdimunsigned MipsMCCodeEmitter:: 830296417SdimgetMemEncodingMMImm16(const MCInst &MI, unsigned OpNo, 831296417Sdim SmallVectorImpl<MCFixup> &Fixups, 832296417Sdim const MCSubtargetInfo &STI) const { 833296417Sdim // Base register is encoded in bits 20-16, offset is encoded in bits 15-0. 834296417Sdim assert(MI.getOperand(OpNo).isReg()); 835296417Sdim unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, 836296417Sdim STI) << 16; 837296417Sdim unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI); 838296417Sdim 839296417Sdim return (OffBits & 0xFFFF) | RegBits; 840296417Sdim} 841296417Sdim 842296417Sdimunsigned MipsMCCodeEmitter:: 843280031SdimgetMemEncodingMMImm4sp(const MCInst &MI, unsigned OpNo, 844280031Sdim SmallVectorImpl<MCFixup> &Fixups, 845280031Sdim const MCSubtargetInfo &STI) const { 846280031Sdim // opNum can be invalid if instruction had reglist as operand 847280031Sdim // MemOperand is always last operand of instruction (base + offset) 848280031Sdim switch (MI.getOpcode()) { 849280031Sdim default: 850280031Sdim break; 851280031Sdim case Mips::SWM16_MM: 852296417Sdim case Mips::SWM16_MMR6: 853280031Sdim case Mips::LWM16_MM: 854296417Sdim case Mips::LWM16_MMR6: 855280031Sdim OpNo = MI.getNumOperands() - 2; 856280031Sdim break; 857280031Sdim } 858280031Sdim 859280031Sdim // Offset is encoded in bits 4-0. 860280031Sdim assert(MI.getOperand(OpNo).isReg()); 861280031Sdim // Base register is always SP - thus it is not encoded. 862280031Sdim assert(MI.getOperand(OpNo+1).isImm()); 863280031Sdim unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI); 864280031Sdim 865280031Sdim return ((OffBits >> 2) & 0x0F); 866280031Sdim} 867280031Sdim 868234353Sdim// FIXME: should be called getMSBEncoding 869234353Sdim// 870234353Sdimunsigned 871234353SdimMipsMCCodeEmitter::getSizeInsEncoding(const MCInst &MI, unsigned OpNo, 872276479Sdim SmallVectorImpl<MCFixup> &Fixups, 873276479Sdim const MCSubtargetInfo &STI) const { 874234353Sdim assert(MI.getOperand(OpNo-1).isImm()); 875234353Sdim assert(MI.getOperand(OpNo).isImm()); 876276479Sdim unsigned Position = getMachineOpValue(MI, MI.getOperand(OpNo-1), Fixups, STI); 877276479Sdim unsigned Size = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI); 878234353Sdim 879234353Sdim return Position + Size - 1; 880234353Sdim} 881234353Sdim 882296417Sdimtemplate <unsigned Bits, int Offset> 883261991Sdimunsigned 884296417SdimMipsMCCodeEmitter::getUImmWithOffsetEncoding(const MCInst &MI, unsigned OpNo, 885296417Sdim SmallVectorImpl<MCFixup> &Fixups, 886296417Sdim const MCSubtargetInfo &STI) const { 887261991Sdim assert(MI.getOperand(OpNo).isImm()); 888296417Sdim unsigned Value = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI); 889296417Sdim Value -= Offset; 890296417Sdim return Value; 891261991Sdim} 892261991Sdim 893276479Sdimunsigned 894276479SdimMipsMCCodeEmitter::getSimm19Lsl2Encoding(const MCInst &MI, unsigned OpNo, 895276479Sdim SmallVectorImpl<MCFixup> &Fixups, 896276479Sdim const MCSubtargetInfo &STI) const { 897276479Sdim const MCOperand &MO = MI.getOperand(OpNo); 898276479Sdim if (MO.isImm()) { 899276479Sdim // The immediate is encoded as 'immediate << 2'. 900276479Sdim unsigned Res = getMachineOpValue(MI, MO, Fixups, STI); 901276479Sdim assert((Res & 3) == 0); 902276479Sdim return Res >> 2; 903276479Sdim } 904276479Sdim 905276479Sdim assert(MO.isExpr() && 906276479Sdim "getSimm19Lsl2Encoding expects only expressions or an immediate"); 907276479Sdim 908276479Sdim const MCExpr *Expr = MO.getExpr(); 909288943Sdim Fixups.push_back(MCFixup::create(0, Expr, 910276479Sdim MCFixupKind(Mips::fixup_MIPS_PC19_S2))); 911276479Sdim return 0; 912276479Sdim} 913276479Sdim 914276479Sdimunsigned 915276479SdimMipsMCCodeEmitter::getSimm18Lsl3Encoding(const MCInst &MI, unsigned OpNo, 916276479Sdim SmallVectorImpl<MCFixup> &Fixups, 917276479Sdim const MCSubtargetInfo &STI) const { 918276479Sdim const MCOperand &MO = MI.getOperand(OpNo); 919276479Sdim if (MO.isImm()) { 920276479Sdim // The immediate is encoded as 'immediate << 3'. 921276479Sdim unsigned Res = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI); 922276479Sdim assert((Res & 7) == 0); 923276479Sdim return Res >> 3; 924276479Sdim } 925276479Sdim 926276479Sdim assert(MO.isExpr() && 927276479Sdim "getSimm18Lsl2Encoding expects only expressions or an immediate"); 928276479Sdim 929276479Sdim const MCExpr *Expr = MO.getExpr(); 930288943Sdim Fixups.push_back(MCFixup::create(0, Expr, 931276479Sdim MCFixupKind(Mips::fixup_MIPS_PC18_S3))); 932276479Sdim return 0; 933276479Sdim} 934276479Sdim 935280031Sdimunsigned 936280031SdimMipsMCCodeEmitter::getUImm3Mod8Encoding(const MCInst &MI, unsigned OpNo, 937280031Sdim SmallVectorImpl<MCFixup> &Fixups, 938280031Sdim const MCSubtargetInfo &STI) const { 939280031Sdim assert(MI.getOperand(OpNo).isImm()); 940280031Sdim const MCOperand &MO = MI.getOperand(OpNo); 941280031Sdim return MO.getImm() % 8; 942280031Sdim} 943280031Sdim 944280031Sdimunsigned 945280031SdimMipsMCCodeEmitter::getUImm4AndValue(const MCInst &MI, unsigned OpNo, 946280031Sdim SmallVectorImpl<MCFixup> &Fixups, 947280031Sdim const MCSubtargetInfo &STI) const { 948280031Sdim assert(MI.getOperand(OpNo).isImm()); 949280031Sdim const MCOperand &MO = MI.getOperand(OpNo); 950280031Sdim unsigned Value = MO.getImm(); 951280031Sdim switch (Value) { 952280031Sdim case 128: return 0x0; 953280031Sdim case 1: return 0x1; 954280031Sdim case 2: return 0x2; 955280031Sdim case 3: return 0x3; 956280031Sdim case 4: return 0x4; 957280031Sdim case 7: return 0x5; 958280031Sdim case 8: return 0x6; 959280031Sdim case 15: return 0x7; 960280031Sdim case 16: return 0x8; 961280031Sdim case 31: return 0x9; 962280031Sdim case 32: return 0xa; 963280031Sdim case 63: return 0xb; 964280031Sdim case 64: return 0xc; 965280031Sdim case 255: return 0xd; 966280031Sdim case 32768: return 0xe; 967280031Sdim case 65535: return 0xf; 968280031Sdim } 969280031Sdim llvm_unreachable("Unexpected value"); 970280031Sdim} 971280031Sdim 972280031Sdimunsigned 973280031SdimMipsMCCodeEmitter::getRegisterListOpValue(const MCInst &MI, unsigned OpNo, 974280031Sdim SmallVectorImpl<MCFixup> &Fixups, 975280031Sdim const MCSubtargetInfo &STI) const { 976280031Sdim unsigned res = 0; 977280031Sdim 978280031Sdim // Register list operand is always first operand of instruction and it is 979280031Sdim // placed before memory operand (register + imm). 980280031Sdim 981280031Sdim for (unsigned I = OpNo, E = MI.getNumOperands() - 2; I < E; ++I) { 982280031Sdim unsigned Reg = MI.getOperand(I).getReg(); 983280031Sdim unsigned RegNo = Ctx.getRegisterInfo()->getEncodingValue(Reg); 984280031Sdim if (RegNo != 31) 985280031Sdim res++; 986280031Sdim else 987280031Sdim res |= 0x10; 988280031Sdim } 989280031Sdim return res; 990280031Sdim} 991280031Sdim 992280031Sdimunsigned 993280031SdimMipsMCCodeEmitter::getRegisterListOpValue16(const MCInst &MI, unsigned OpNo, 994280031Sdim SmallVectorImpl<MCFixup> &Fixups, 995280031Sdim const MCSubtargetInfo &STI) const { 996280031Sdim return (MI.getNumOperands() - 4); 997280031Sdim} 998280031Sdim 999280031Sdimunsigned 1000280031SdimMipsMCCodeEmitter::getRegisterPairOpValue(const MCInst &MI, unsigned OpNo, 1001280031Sdim SmallVectorImpl<MCFixup> &Fixups, 1002280031Sdim const MCSubtargetInfo &STI) const { 1003280031Sdim return getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI); 1004280031Sdim} 1005280031Sdim 1006288943Sdimunsigned 1007288943SdimMipsMCCodeEmitter::getMovePRegPairOpValue(const MCInst &MI, unsigned OpNo, 1008288943Sdim SmallVectorImpl<MCFixup> &Fixups, 1009288943Sdim const MCSubtargetInfo &STI) const { 1010288943Sdim unsigned res = 0; 1011288943Sdim 1012288943Sdim if (MI.getOperand(0).getReg() == Mips::A1 && 1013288943Sdim MI.getOperand(1).getReg() == Mips::A2) 1014288943Sdim res = 0; 1015288943Sdim else if (MI.getOperand(0).getReg() == Mips::A1 && 1016288943Sdim MI.getOperand(1).getReg() == Mips::A3) 1017288943Sdim res = 1; 1018288943Sdim else if (MI.getOperand(0).getReg() == Mips::A2 && 1019288943Sdim MI.getOperand(1).getReg() == Mips::A3) 1020288943Sdim res = 2; 1021288943Sdim else if (MI.getOperand(0).getReg() == Mips::A0 && 1022288943Sdim MI.getOperand(1).getReg() == Mips::S5) 1023288943Sdim res = 3; 1024288943Sdim else if (MI.getOperand(0).getReg() == Mips::A0 && 1025288943Sdim MI.getOperand(1).getReg() == Mips::S6) 1026288943Sdim res = 4; 1027288943Sdim else if (MI.getOperand(0).getReg() == Mips::A0 && 1028288943Sdim MI.getOperand(1).getReg() == Mips::A1) 1029288943Sdim res = 5; 1030288943Sdim else if (MI.getOperand(0).getReg() == Mips::A0 && 1031288943Sdim MI.getOperand(1).getReg() == Mips::A2) 1032288943Sdim res = 6; 1033288943Sdim else if (MI.getOperand(0).getReg() == Mips::A0 && 1034288943Sdim MI.getOperand(1).getReg() == Mips::A3) 1035288943Sdim res = 7; 1036288943Sdim 1037288943Sdim return res; 1038288943Sdim} 1039288943Sdim 1040288943Sdimunsigned 1041288943SdimMipsMCCodeEmitter::getSimm23Lsl2Encoding(const MCInst &MI, unsigned OpNo, 1042288943Sdim SmallVectorImpl<MCFixup> &Fixups, 1043288943Sdim const MCSubtargetInfo &STI) const { 1044288943Sdim const MCOperand &MO = MI.getOperand(OpNo); 1045288943Sdim assert(MO.isImm() && "getSimm23Lsl2Encoding expects only an immediate"); 1046288943Sdim // The immediate is encoded as 'immediate >> 2'. 1047288943Sdim unsigned Res = static_cast<unsigned>(MO.getImm()); 1048288943Sdim assert((Res & 3) == 0); 1049288943Sdim return Res >> 2; 1050288943Sdim} 1051288943Sdim 1052234353Sdim#include "MipsGenMCCodeEmitter.inc" 1053