19f610119SJia Liu //===-- MipsMCCodeEmitter.cpp - Convert Mips Code to Machine Code ---------===// 2750ecec7SAkira Hatanaka // 3750ecec7SAkira Hatanaka // The LLVM Compiler Infrastructure 4750ecec7SAkira Hatanaka // 5750ecec7SAkira Hatanaka // This file is distributed under the University of Illinois Open Source 6750ecec7SAkira Hatanaka // License. See LICENSE.TXT for details. 7750ecec7SAkira Hatanaka // 8750ecec7SAkira Hatanaka //===----------------------------------------------------------------------===// 9750ecec7SAkira Hatanaka // 10750ecec7SAkira Hatanaka // This file implements the MipsMCCodeEmitter class. 11750ecec7SAkira Hatanaka // 12750ecec7SAkira Hatanaka //===----------------------------------------------------------------------===// 13750ecec7SAkira Hatanaka // 149e1450bcSMatheus Almeida 159e1450bcSMatheus Almeida #include "MipsMCCodeEmitter.h" 16c85e3ff3SBruno Cardoso Lopes #include "MCTargetDesc/MipsFixupKinds.h" 17a5da588bSPetar Jovanovic #include "MCTargetDesc/MipsMCExpr.h" 18c85e3ff3SBruno Cardoso Lopes #include "MCTargetDesc/MipsMCTargetDesc.h" 19c85e3ff3SBruno Cardoso Lopes #include "llvm/ADT/APFloat.h" 209e1450bcSMatheus Almeida #include "llvm/ADT/SmallVector.h" 215d6faed1SAkira Hatanaka #include "llvm/MC/MCContext.h" 22750ecec7SAkira Hatanaka #include "llvm/MC/MCExpr.h" 23750ecec7SAkira Hatanaka #include "llvm/MC/MCInst.h" 24750ecec7SAkira Hatanaka #include "llvm/MC/MCInstrInfo.h" 259e1450bcSMatheus Almeida #include "llvm/MC/MCFixup.h" 26750ecec7SAkira Hatanaka #include "llvm/MC/MCSubtargetInfo.h" 27750ecec7SAkira Hatanaka #include "llvm/Support/raw_ostream.h" 28750ecec7SAkira Hatanaka 2984e68b29SChandler Carruth #define DEBUG_TYPE "mccodeemitter" 3084e68b29SChandler Carruth 31be6a818fSAkira Hatanaka #define GET_INSTRMAP_INFO 32be6a818fSAkira Hatanaka #include "MipsGenInstrInfo.inc" 339e1450bcSMatheus Almeida #undef GET_INSTRMAP_INFO 34be6a818fSAkira Hatanaka 359e1450bcSMatheus Almeida namespace llvm { 369e1450bcSMatheus Almeida MCCodeEmitter *createMipsMCCodeEmitterEB(const MCInstrInfo &MCII, 37c3b04279SJim Grosbach const MCRegisterInfo &MRI, 38750ecec7SAkira Hatanaka const MCSubtargetInfo &STI, 399e1450bcSMatheus Almeida MCContext &Ctx) { 40d2cca113SDavid Woodhouse return new MipsMCCodeEmitter(MCII, Ctx, false); 411ee768dbSAkira Hatanaka } 421ee768dbSAkira Hatanaka 439e1450bcSMatheus Almeida MCCodeEmitter *createMipsMCCodeEmitterEL(const MCInstrInfo &MCII, 44c3b04279SJim Grosbach const MCRegisterInfo &MRI, 451ee768dbSAkira Hatanaka const MCSubtargetInfo &STI, 469e1450bcSMatheus Almeida MCContext &Ctx) { 47d2cca113SDavid Woodhouse return new MipsMCCodeEmitter(MCII, Ctx, true); 48750ecec7SAkira Hatanaka } 499e1450bcSMatheus Almeida } // End of namespace llvm. 50f30f2cceSRafael Espindola 51f30f2cceSRafael Espindola // If the D<shift> instruction has a shift amount that is greater 52f30f2cceSRafael Espindola // than 31 (checked in calling routine), lower it to a D<shift>32 instruction 53f30f2cceSRafael Espindola static void LowerLargeShift(MCInst& Inst) { 54f30f2cceSRafael Espindola 55f30f2cceSRafael Espindola assert(Inst.getNumOperands() == 3 && "Invalid no. of operands for shift!"); 56f30f2cceSRafael Espindola assert(Inst.getOperand(2).isImm()); 57f30f2cceSRafael Espindola 58f30f2cceSRafael Espindola int64_t Shift = Inst.getOperand(2).getImm(); 59f30f2cceSRafael Espindola if (Shift <= 31) 60f30f2cceSRafael Espindola return; // Do nothing 61f30f2cceSRafael Espindola Shift -= 32; 62f30f2cceSRafael Espindola 63f30f2cceSRafael Espindola // saminus32 64f30f2cceSRafael Espindola Inst.getOperand(2).setImm(Shift); 65f30f2cceSRafael Espindola 66f30f2cceSRafael Espindola switch (Inst.getOpcode()) { 67f30f2cceSRafael Espindola default: 68f30f2cceSRafael Espindola // Calling function is not synchronized 69f30f2cceSRafael Espindola llvm_unreachable("Unexpected shift instruction"); 70f30f2cceSRafael Espindola case Mips::DSLL: 71f30f2cceSRafael Espindola Inst.setOpcode(Mips::DSLL32); 72f30f2cceSRafael Espindola return; 73f30f2cceSRafael Espindola case Mips::DSRL: 74f30f2cceSRafael Espindola Inst.setOpcode(Mips::DSRL32); 75f30f2cceSRafael Espindola return; 76f30f2cceSRafael Espindola case Mips::DSRA: 77f30f2cceSRafael Espindola Inst.setOpcode(Mips::DSRA32); 78f30f2cceSRafael Espindola return; 796a3fe574SAkira Hatanaka case Mips::DROTR: 806a3fe574SAkira Hatanaka Inst.setOpcode(Mips::DROTR32); 816a3fe574SAkira Hatanaka return; 82f30f2cceSRafael Espindola } 83f30f2cceSRafael Espindola } 84f30f2cceSRafael Espindola 85f30f2cceSRafael Espindola // Pick a DEXT or DINS instruction variant based on the pos and size operands 86f30f2cceSRafael Espindola static void LowerDextDins(MCInst& InstIn) { 87f30f2cceSRafael Espindola int Opcode = InstIn.getOpcode(); 88f30f2cceSRafael Espindola 89f30f2cceSRafael Espindola if (Opcode == Mips::DEXT) 90f30f2cceSRafael Espindola assert(InstIn.getNumOperands() == 4 && 91f30f2cceSRafael Espindola "Invalid no. of machine operands for DEXT!"); 92f30f2cceSRafael Espindola else // Only DEXT and DINS are possible 93f30f2cceSRafael Espindola assert(InstIn.getNumOperands() == 5 && 94f30f2cceSRafael Espindola "Invalid no. of machine operands for DINS!"); 95f30f2cceSRafael Espindola 96f30f2cceSRafael Espindola assert(InstIn.getOperand(2).isImm()); 97f30f2cceSRafael Espindola int64_t pos = InstIn.getOperand(2).getImm(); 98f30f2cceSRafael Espindola assert(InstIn.getOperand(3).isImm()); 99f30f2cceSRafael Espindola int64_t size = InstIn.getOperand(3).getImm(); 100f30f2cceSRafael Espindola 101f30f2cceSRafael Espindola if (size <= 32) { 102f30f2cceSRafael Espindola if (pos < 32) // DEXT/DINS, do nothing 103f30f2cceSRafael Espindola return; 104f30f2cceSRafael Espindola // DEXTU/DINSU 105f30f2cceSRafael Espindola InstIn.getOperand(2).setImm(pos - 32); 106f30f2cceSRafael Espindola InstIn.setOpcode((Opcode == Mips::DEXT) ? Mips::DEXTU : Mips::DINSU); 107f30f2cceSRafael Espindola return; 108f30f2cceSRafael Espindola } 109f30f2cceSRafael Espindola // DEXTM/DINSM 110f30f2cceSRafael Espindola assert(pos < 32 && "DEXT/DINS cannot have both size and pos > 32"); 111f30f2cceSRafael Espindola InstIn.getOperand(3).setImm(size - 32); 112f30f2cceSRafael Espindola InstIn.setOpcode((Opcode == Mips::DEXT) ? Mips::DEXTM : Mips::DINSM); 113f30f2cceSRafael Espindola return; 114f30f2cceSRafael Espindola } 115f30f2cceSRafael Espindola 1169e1450bcSMatheus Almeida bool MipsMCCodeEmitter::isMicroMips(const MCSubtargetInfo &STI) const { 1179e1450bcSMatheus Almeida return STI.getFeatureBits() & Mips::FeatureMicroMips; 1189e1450bcSMatheus Almeida } 1199e1450bcSMatheus Almeida 1209e1450bcSMatheus Almeida void MipsMCCodeEmitter::EmitByte(unsigned char C, raw_ostream &OS) const { 1219e1450bcSMatheus Almeida OS << (char)C; 1229e1450bcSMatheus Almeida } 1239e1450bcSMatheus Almeida 1249e1450bcSMatheus Almeida void MipsMCCodeEmitter::EmitInstruction(uint64_t Val, unsigned Size, 1259e1450bcSMatheus Almeida const MCSubtargetInfo &STI, 1269e1450bcSMatheus Almeida raw_ostream &OS) const { 1279e1450bcSMatheus Almeida // Output the instruction encoding in little endian byte order. 1289e1450bcSMatheus Almeida // Little-endian byte ordering: 1299e1450bcSMatheus Almeida // mips32r2: 4 | 3 | 2 | 1 1309e1450bcSMatheus Almeida // microMIPS: 2 | 1 | 4 | 3 1319e1450bcSMatheus Almeida if (IsLittleEndian && Size == 4 && isMicroMips(STI)) { 1329e1450bcSMatheus Almeida EmitInstruction(Val >> 16, 2, STI, OS); 1339e1450bcSMatheus Almeida EmitInstruction(Val, 2, STI, OS); 1349e1450bcSMatheus Almeida } else { 1359e1450bcSMatheus Almeida for (unsigned i = 0; i < Size; ++i) { 1369e1450bcSMatheus Almeida unsigned Shift = IsLittleEndian ? i * 8 : (Size - 1 - i) * 8; 1379e1450bcSMatheus Almeida EmitByte((Val >> Shift) & 0xff, OS); 1389e1450bcSMatheus Almeida } 1399e1450bcSMatheus Almeida } 1409e1450bcSMatheus Almeida } 1419e1450bcSMatheus Almeida 142c85e3ff3SBruno Cardoso Lopes /// EncodeInstruction - Emit the instruction. 1434e07b95dSJack Carter /// Size the instruction with Desc.getSize(). 144c85e3ff3SBruno Cardoso Lopes void MipsMCCodeEmitter:: 145c85e3ff3SBruno Cardoso Lopes EncodeInstruction(const MCInst &MI, raw_ostream &OS, 1469784cef3SDavid Woodhouse SmallVectorImpl<MCFixup> &Fixups, 1479784cef3SDavid Woodhouse const MCSubtargetInfo &STI) const 148c85e3ff3SBruno Cardoso Lopes { 149aa7aeaa0SJack Carter 150aa7aeaa0SJack Carter // Non-pseudo instructions that get changed for direct object 151aa7aeaa0SJack Carter // only based on operand values. 152aa7aeaa0SJack Carter // If this list of instructions get much longer we will move 153aa7aeaa0SJack Carter // the check to a function call. Until then, this is more efficient. 154aa7aeaa0SJack Carter MCInst TmpInst = MI; 155aa7aeaa0SJack Carter switch (MI.getOpcode()) { 156aa7aeaa0SJack Carter // If shift amount is >= 32 it the inst needs to be lowered further 157aa7aeaa0SJack Carter case Mips::DSLL: 158aa7aeaa0SJack Carter case Mips::DSRL: 159aa7aeaa0SJack Carter case Mips::DSRA: 1606a3fe574SAkira Hatanaka case Mips::DROTR: 161f30f2cceSRafael Espindola LowerLargeShift(TmpInst); 162aa7aeaa0SJack Carter break; 163aa7aeaa0SJack Carter // Double extract instruction is chosen by pos and size operands 164aa7aeaa0SJack Carter case Mips::DEXT: 165aa7aeaa0SJack Carter case Mips::DINS: 166f30f2cceSRafael Espindola LowerDextDins(TmpInst); 167aa7aeaa0SJack Carter } 168aa7aeaa0SJack Carter 16997700977SJack Carter unsigned long N = Fixups.size(); 1703fa98a65SDavid Woodhouse uint32_t Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI); 171c85e3ff3SBruno Cardoso Lopes 172c85e3ff3SBruno Cardoso Lopes // Check for unimplemented opcodes. 173aa7aeaa0SJack Carter // Unfortunately in MIPS both NOP and SLL will come in with Binary == 0 174c85e3ff3SBruno Cardoso Lopes // so we have to special check for them. 175aa7aeaa0SJack Carter unsigned Opcode = TmpInst.getOpcode(); 176c85e3ff3SBruno Cardoso Lopes if ((Opcode != Mips::NOP) && (Opcode != Mips::SLL) && !Binary) 177c85e3ff3SBruno Cardoso Lopes llvm_unreachable("unimplemented opcode in EncodeInstruction()"); 178c85e3ff3SBruno Cardoso Lopes 179be6a818fSAkira Hatanaka if (STI.getFeatureBits() & Mips::FeatureMicroMips) { 180be6a818fSAkira Hatanaka int NewOpcode = Mips::Std2MicroMips (Opcode, Mips::Arch_micromips); 181be6a818fSAkira Hatanaka if (NewOpcode != -1) { 18297700977SJack Carter if (Fixups.size() > N) 18397700977SJack Carter Fixups.pop_back(); 184be6a818fSAkira Hatanaka Opcode = NewOpcode; 185be6a818fSAkira Hatanaka TmpInst.setOpcode (NewOpcode); 1863fa98a65SDavid Woodhouse Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI); 187be6a818fSAkira Hatanaka } 188be6a818fSAkira Hatanaka } 189be6a818fSAkira Hatanaka 190aa7aeaa0SJack Carter const MCInstrDesc &Desc = MCII.get(TmpInst.getOpcode()); 191c85e3ff3SBruno Cardoso Lopes 1925b5559d3SJack Carter // Get byte count of instruction 1935b5559d3SJack Carter unsigned Size = Desc.getSize(); 1945b5559d3SJack Carter if (!Size) 1955b5559d3SJack Carter llvm_unreachable("Desc.getSize() returns 0"); 196c85e3ff3SBruno Cardoso Lopes 197d2cca113SDavid Woodhouse EmitInstruction(Binary, Size, STI, OS); 198c85e3ff3SBruno Cardoso Lopes } 199c85e3ff3SBruno Cardoso Lopes 200c85e3ff3SBruno Cardoso Lopes /// getBranchTargetOpValue - Return binary encoding of the branch 201c85e3ff3SBruno Cardoso Lopes /// target operand. If the machine operand requires relocation, 202c85e3ff3SBruno Cardoso Lopes /// record the relocation and return zero. 203c85e3ff3SBruno Cardoso Lopes unsigned MipsMCCodeEmitter:: 204c85e3ff3SBruno Cardoso Lopes getBranchTargetOpValue(const MCInst &MI, unsigned OpNo, 2053fa98a65SDavid Woodhouse SmallVectorImpl<MCFixup> &Fixups, 2063fa98a65SDavid Woodhouse const MCSubtargetInfo &STI) const { 207c85e3ff3SBruno Cardoso Lopes 208c85e3ff3SBruno Cardoso Lopes const MCOperand &MO = MI.getOperand(OpNo); 20971e6a749SJack Carter 2104f69a0f2SJack Carter // If the destination is an immediate, divide by 4. 2114f69a0f2SJack Carter if (MO.isImm()) return MO.getImm() >> 2; 2124f69a0f2SJack Carter 21371e6a749SJack Carter assert(MO.isExpr() && 21471e6a749SJack Carter "getBranchTargetOpValue expects only expressions or immediates"); 215c85e3ff3SBruno Cardoso Lopes 216c85e3ff3SBruno Cardoso Lopes const MCExpr *Expr = MO.getExpr(); 217c85e3ff3SBruno Cardoso Lopes Fixups.push_back(MCFixup::Create(0, Expr, 218c85e3ff3SBruno Cardoso Lopes MCFixupKind(Mips::fixup_Mips_PC16))); 219c85e3ff3SBruno Cardoso Lopes return 0; 220c85e3ff3SBruno Cardoso Lopes } 221c85e3ff3SBruno Cardoso Lopes 2228a80aa76SZoran Jovanovic /// getBranchTargetOpValue - Return binary encoding of the microMIPS branch 2238a80aa76SZoran Jovanovic /// target operand. If the machine operand requires relocation, 2248a80aa76SZoran Jovanovic /// record the relocation and return zero. 2258a80aa76SZoran Jovanovic unsigned MipsMCCodeEmitter:: 2268a80aa76SZoran Jovanovic getBranchTargetOpValueMM(const MCInst &MI, unsigned OpNo, 2273fa98a65SDavid Woodhouse SmallVectorImpl<MCFixup> &Fixups, 2283fa98a65SDavid Woodhouse const MCSubtargetInfo &STI) const { 2298a80aa76SZoran Jovanovic 2308a80aa76SZoran Jovanovic const MCOperand &MO = MI.getOperand(OpNo); 2318a80aa76SZoran Jovanovic 2328a80aa76SZoran Jovanovic // If the destination is an immediate, divide by 2. 2338a80aa76SZoran Jovanovic if (MO.isImm()) return MO.getImm() >> 1; 2348a80aa76SZoran Jovanovic 2358a80aa76SZoran Jovanovic assert(MO.isExpr() && 2368a80aa76SZoran Jovanovic "getBranchTargetOpValueMM expects only expressions or immediates"); 2378a80aa76SZoran Jovanovic 2388a80aa76SZoran Jovanovic const MCExpr *Expr = MO.getExpr(); 2398a80aa76SZoran Jovanovic Fixups.push_back(MCFixup::Create(0, Expr, 2408a80aa76SZoran Jovanovic MCFixupKind(Mips:: 2418a80aa76SZoran Jovanovic fixup_MICROMIPS_PC16_S1))); 2428a80aa76SZoran Jovanovic return 0; 2438a80aa76SZoran Jovanovic } 2448a80aa76SZoran Jovanovic 2453c8869dcSZoran Jovanovic /// getBranchTarget21OpValue - Return binary encoding of the branch 2463c8869dcSZoran Jovanovic /// target operand. If the machine operand requires relocation, 2473c8869dcSZoran Jovanovic /// record the relocation and return zero. 2483c8869dcSZoran Jovanovic unsigned MipsMCCodeEmitter:: 2493c8869dcSZoran Jovanovic getBranchTarget21OpValue(const MCInst &MI, unsigned OpNo, 2503c8869dcSZoran Jovanovic SmallVectorImpl<MCFixup> &Fixups, 2513c8869dcSZoran Jovanovic const MCSubtargetInfo &STI) const { 2523c8869dcSZoran Jovanovic 2533c8869dcSZoran Jovanovic const MCOperand &MO = MI.getOperand(OpNo); 2543c8869dcSZoran Jovanovic 2553c8869dcSZoran Jovanovic // If the destination is an immediate, divide by 4. 2563c8869dcSZoran Jovanovic if (MO.isImm()) return MO.getImm() >> 2; 2573c8869dcSZoran Jovanovic 2583c8869dcSZoran Jovanovic assert(MO.isExpr() && 2593c8869dcSZoran Jovanovic "getBranchTarget21OpValue expects only expressions or immediates"); 2603c8869dcSZoran Jovanovic 2613c8869dcSZoran Jovanovic // TODO: Push 21 PC fixup. 2623c8869dcSZoran Jovanovic return 0; 2633c8869dcSZoran Jovanovic } 2643c8869dcSZoran Jovanovic 2653c8869dcSZoran Jovanovic /// getBranchTarget26OpValue - Return binary encoding of the branch 2663c8869dcSZoran Jovanovic /// target operand. If the machine operand requires relocation, 2673c8869dcSZoran Jovanovic /// record the relocation and return zero. 2683c8869dcSZoran Jovanovic unsigned MipsMCCodeEmitter:: 2693c8869dcSZoran Jovanovic getBranchTarget26OpValue(const MCInst &MI, unsigned OpNo, 2703c8869dcSZoran Jovanovic SmallVectorImpl<MCFixup> &Fixups, 2713c8869dcSZoran Jovanovic const MCSubtargetInfo &STI) const { 2723c8869dcSZoran Jovanovic 2733c8869dcSZoran Jovanovic const MCOperand &MO = MI.getOperand(OpNo); 2743c8869dcSZoran Jovanovic 2753c8869dcSZoran Jovanovic // If the destination is an immediate, divide by 4. 2763c8869dcSZoran Jovanovic if (MO.isImm()) return MO.getImm() >> 2; 2773c8869dcSZoran Jovanovic 2783c8869dcSZoran Jovanovic assert(MO.isExpr() && 2793c8869dcSZoran Jovanovic "getBranchTarget26OpValue expects only expressions or immediates"); 2803c8869dcSZoran Jovanovic 2813c8869dcSZoran Jovanovic // TODO: Push 26 PC fixup. 2823c8869dcSZoran Jovanovic return 0; 2833c8869dcSZoran Jovanovic } 2843c8869dcSZoran Jovanovic 285*52c56b93SZoran Jovanovic /// getJumpOffset16OpValue - Return binary encoding of the jump 286*52c56b93SZoran Jovanovic /// target operand. If the machine operand requires relocation, 287*52c56b93SZoran Jovanovic /// record the relocation and return zero. 288*52c56b93SZoran Jovanovic unsigned MipsMCCodeEmitter:: 289*52c56b93SZoran Jovanovic getJumpOffset16OpValue(const MCInst &MI, unsigned OpNo, 290*52c56b93SZoran Jovanovic SmallVectorImpl<MCFixup> &Fixups, 291*52c56b93SZoran Jovanovic const MCSubtargetInfo &STI) const { 292*52c56b93SZoran Jovanovic 293*52c56b93SZoran Jovanovic const MCOperand &MO = MI.getOperand(OpNo); 294*52c56b93SZoran Jovanovic 295*52c56b93SZoran Jovanovic if (MO.isImm()) return MO.getImm(); 296*52c56b93SZoran Jovanovic 297*52c56b93SZoran Jovanovic assert(MO.isExpr() && 298*52c56b93SZoran Jovanovic "getJumpOffset16OpValue expects only expressions or an immediate"); 299*52c56b93SZoran Jovanovic 300*52c56b93SZoran Jovanovic // TODO: Push fixup. 301*52c56b93SZoran Jovanovic return 0; 302*52c56b93SZoran Jovanovic } 303*52c56b93SZoran Jovanovic 304c85e3ff3SBruno Cardoso Lopes /// getJumpTargetOpValue - Return binary encoding of the jump 305c85e3ff3SBruno Cardoso Lopes /// target operand. If the machine operand requires relocation, 306c85e3ff3SBruno Cardoso Lopes /// record the relocation and return zero. 307c85e3ff3SBruno Cardoso Lopes unsigned MipsMCCodeEmitter:: 308c85e3ff3SBruno Cardoso Lopes getJumpTargetOpValue(const MCInst &MI, unsigned OpNo, 3093fa98a65SDavid Woodhouse SmallVectorImpl<MCFixup> &Fixups, 3103fa98a65SDavid Woodhouse const MCSubtargetInfo &STI) const { 311c85e3ff3SBruno Cardoso Lopes 312c85e3ff3SBruno Cardoso Lopes const MCOperand &MO = MI.getOperand(OpNo); 3134f69a0f2SJack Carter // If the destination is an immediate, divide by 4. 3144f69a0f2SJack Carter if (MO.isImm()) return MO.getImm()>>2; 3154f69a0f2SJack Carter 31671e6a749SJack Carter assert(MO.isExpr() && 31771e6a749SJack Carter "getJumpTargetOpValue expects only expressions or an immediate"); 318c85e3ff3SBruno Cardoso Lopes 319c85e3ff3SBruno Cardoso Lopes const MCExpr *Expr = MO.getExpr(); 320c85e3ff3SBruno Cardoso Lopes Fixups.push_back(MCFixup::Create(0, Expr, 321c85e3ff3SBruno Cardoso Lopes MCFixupKind(Mips::fixup_Mips_26))); 322c85e3ff3SBruno Cardoso Lopes return 0; 323c85e3ff3SBruno Cardoso Lopes } 324c85e3ff3SBruno Cardoso Lopes 325c85e3ff3SBruno Cardoso Lopes unsigned MipsMCCodeEmitter:: 326507e084aSZoran Jovanovic getJumpTargetOpValueMM(const MCInst &MI, unsigned OpNo, 3273fa98a65SDavid Woodhouse SmallVectorImpl<MCFixup> &Fixups, 3283fa98a65SDavid Woodhouse const MCSubtargetInfo &STI) const { 329507e084aSZoran Jovanovic 330507e084aSZoran Jovanovic const MCOperand &MO = MI.getOperand(OpNo); 331507e084aSZoran Jovanovic // If the destination is an immediate, divide by 2. 332507e084aSZoran Jovanovic if (MO.isImm()) return MO.getImm() >> 1; 333507e084aSZoran Jovanovic 334507e084aSZoran Jovanovic assert(MO.isExpr() && 335507e084aSZoran Jovanovic "getJumpTargetOpValueMM expects only expressions or an immediate"); 336507e084aSZoran Jovanovic 337507e084aSZoran Jovanovic const MCExpr *Expr = MO.getExpr(); 338507e084aSZoran Jovanovic Fixups.push_back(MCFixup::Create(0, Expr, 339507e084aSZoran Jovanovic MCFixupKind(Mips::fixup_MICROMIPS_26_S1))); 340507e084aSZoran Jovanovic return 0; 341507e084aSZoran Jovanovic } 342507e084aSZoran Jovanovic 343507e084aSZoran Jovanovic unsigned MipsMCCodeEmitter:: 3443fa98a65SDavid Woodhouse getExprOpValue(const MCExpr *Expr,SmallVectorImpl<MCFixup> &Fixups, 3453fa98a65SDavid Woodhouse const MCSubtargetInfo &STI) const { 346b5cf5909SJack Carter int64_t Res; 347049e9e4dSAkira Hatanaka 348b5cf5909SJack Carter if (Expr->EvaluateAsAbsolute(Res)) 349b5cf5909SJack Carter return Res; 350fe384a2cSAkira Hatanaka 351fe384a2cSAkira Hatanaka MCExpr::ExprKind Kind = Expr->getKind(); 352b5cf5909SJack Carter if (Kind == MCExpr::Constant) { 353b5cf5909SJack Carter return cast<MCConstantExpr>(Expr)->getValue(); 354b5cf5909SJack Carter } 355fe384a2cSAkira Hatanaka 356fe384a2cSAkira Hatanaka if (Kind == MCExpr::Binary) { 3573fa98a65SDavid Woodhouse unsigned Res = getExprOpValue(cast<MCBinaryExpr>(Expr)->getLHS(), Fixups, STI); 3583fa98a65SDavid Woodhouse Res += getExprOpValue(cast<MCBinaryExpr>(Expr)->getRHS(), Fixups, STI); 359b5cf5909SJack Carter return Res; 360fe384a2cSAkira Hatanaka } 361a5da588bSPetar Jovanovic 362a5da588bSPetar Jovanovic if (Kind == MCExpr::Target) { 363a5da588bSPetar Jovanovic const MipsMCExpr *MipsExpr = cast<MipsMCExpr>(Expr); 364a5da588bSPetar Jovanovic 365a5da588bSPetar Jovanovic Mips::Fixups FixupKind = Mips::Fixups(0); 366a5da588bSPetar Jovanovic switch (MipsExpr->getKind()) { 367a5da588bSPetar Jovanovic default: llvm_unreachable("Unsupported fixup kind for target expression!"); 36806c47803SSasa Stankovic case MipsMCExpr::VK_Mips_HIGHEST: 36906c47803SSasa Stankovic FixupKind = Mips::fixup_Mips_HIGHEST; 37006c47803SSasa Stankovic break; 37106c47803SSasa Stankovic case MipsMCExpr::VK_Mips_HIGHER: 37206c47803SSasa Stankovic FixupKind = Mips::fixup_Mips_HIGHER; 37306c47803SSasa Stankovic break; 37406c47803SSasa Stankovic case MipsMCExpr::VK_Mips_HI: 375a5da588bSPetar Jovanovic FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_HI16 376a5da588bSPetar Jovanovic : Mips::fixup_Mips_HI16; 377a5da588bSPetar Jovanovic break; 37806c47803SSasa Stankovic case MipsMCExpr::VK_Mips_LO: 379a5da588bSPetar Jovanovic FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_LO16 380a5da588bSPetar Jovanovic : Mips::fixup_Mips_LO16; 381a5da588bSPetar Jovanovic break; 382a5da588bSPetar Jovanovic } 383a5da588bSPetar Jovanovic Fixups.push_back(MCFixup::Create(0, MipsExpr, MCFixupKind(FixupKind))); 384a5da588bSPetar Jovanovic return 0; 385a5da588bSPetar Jovanovic } 386a5da588bSPetar Jovanovic 387b5cf5909SJack Carter if (Kind == MCExpr::SymbolRef) { 388f9774c32SBill Wendling Mips::Fixups FixupKind = Mips::Fixups(0); 389e2eed964SAkira Hatanaka 390049e9e4dSAkira Hatanaka switch(cast<MCSymbolRefExpr>(Expr)->getKind()) { 391b9f9de93SJack Carter default: llvm_unreachable("Unknown fixup kind!"); 392b9f9de93SJack Carter break; 393b9f9de93SJack Carter case MCSymbolRefExpr::VK_Mips_GPOFF_HI : 394b9f9de93SJack Carter FixupKind = Mips::fixup_Mips_GPOFF_HI; 395b9f9de93SJack Carter break; 396b9f9de93SJack Carter case MCSymbolRefExpr::VK_Mips_GPOFF_LO : 397b9f9de93SJack Carter FixupKind = Mips::fixup_Mips_GPOFF_LO; 398b9f9de93SJack Carter break; 399b9f9de93SJack Carter case MCSymbolRefExpr::VK_Mips_GOT_PAGE : 400d2cca113SDavid Woodhouse FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOT_PAGE 401e7ae8af8SZoran Jovanovic : Mips::fixup_Mips_GOT_PAGE; 402b9f9de93SJack Carter break; 403b9f9de93SJack Carter case MCSymbolRefExpr::VK_Mips_GOT_OFST : 404d2cca113SDavid Woodhouse FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOT_OFST 405e7ae8af8SZoran Jovanovic : Mips::fixup_Mips_GOT_OFST; 406b9f9de93SJack Carter break; 4075ddcfda8SJack Carter case MCSymbolRefExpr::VK_Mips_GOT_DISP : 408d2cca113SDavid Woodhouse FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOT_DISP 409e7ae8af8SZoran Jovanovic : Mips::fixup_Mips_GOT_DISP; 4105ddcfda8SJack Carter break; 411c85e3ff3SBruno Cardoso Lopes case MCSymbolRefExpr::VK_Mips_GPREL: 412c85e3ff3SBruno Cardoso Lopes FixupKind = Mips::fixup_Mips_GPREL16; 413c85e3ff3SBruno Cardoso Lopes break; 414c85e3ff3SBruno Cardoso Lopes case MCSymbolRefExpr::VK_Mips_GOT_CALL: 415d2cca113SDavid Woodhouse FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_CALL16 416e7ae8af8SZoran Jovanovic : Mips::fixup_Mips_CALL16; 417c85e3ff3SBruno Cardoso Lopes break; 41861e6d987SBruno Cardoso Lopes case MCSymbolRefExpr::VK_Mips_GOT16: 419d2cca113SDavid Woodhouse FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOT16 420e7ae8af8SZoran Jovanovic : Mips::fixup_Mips_GOT_Global; 42161e6d987SBruno Cardoso Lopes break; 422c85e3ff3SBruno Cardoso Lopes case MCSymbolRefExpr::VK_Mips_GOT: 423d2cca113SDavid Woodhouse FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOT16 424e7ae8af8SZoran Jovanovic : Mips::fixup_Mips_GOT_Local; 425c85e3ff3SBruno Cardoso Lopes break; 426c85e3ff3SBruno Cardoso Lopes case MCSymbolRefExpr::VK_Mips_ABS_HI: 427d2cca113SDavid Woodhouse FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_HI16 428e7ae8af8SZoran Jovanovic : Mips::fixup_Mips_HI16; 429c85e3ff3SBruno Cardoso Lopes break; 430c85e3ff3SBruno Cardoso Lopes case MCSymbolRefExpr::VK_Mips_ABS_LO: 431d2cca113SDavid Woodhouse FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_LO16 432e7ae8af8SZoran Jovanovic : Mips::fixup_Mips_LO16; 433c85e3ff3SBruno Cardoso Lopes break; 434c85e3ff3SBruno Cardoso Lopes case MCSymbolRefExpr::VK_Mips_TLSGD: 435d2cca113SDavid Woodhouse FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_GD 43669be811aSZoran Jovanovic : Mips::fixup_Mips_TLSGD; 437c85e3ff3SBruno Cardoso Lopes break; 438e2eed964SAkira Hatanaka case MCSymbolRefExpr::VK_Mips_TLSLDM: 439d2cca113SDavid Woodhouse FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_LDM 44069be811aSZoran Jovanovic : Mips::fixup_Mips_TLSLDM; 441e2eed964SAkira Hatanaka break; 442e2eed964SAkira Hatanaka case MCSymbolRefExpr::VK_Mips_DTPREL_HI: 443d2cca113SDavid Woodhouse FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_DTPREL_HI16 444e7ae8af8SZoran Jovanovic : Mips::fixup_Mips_DTPREL_HI; 445e2eed964SAkira Hatanaka break; 446e2eed964SAkira Hatanaka case MCSymbolRefExpr::VK_Mips_DTPREL_LO: 447d2cca113SDavid Woodhouse FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_DTPREL_LO16 448e7ae8af8SZoran Jovanovic : Mips::fixup_Mips_DTPREL_LO; 449e2eed964SAkira Hatanaka break; 450c85e3ff3SBruno Cardoso Lopes case MCSymbolRefExpr::VK_Mips_GOTTPREL: 451c85e3ff3SBruno Cardoso Lopes FixupKind = Mips::fixup_Mips_GOTTPREL; 452c85e3ff3SBruno Cardoso Lopes break; 453c85e3ff3SBruno Cardoso Lopes case MCSymbolRefExpr::VK_Mips_TPREL_HI: 454d2cca113SDavid Woodhouse FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_TPREL_HI16 455e7ae8af8SZoran Jovanovic : Mips::fixup_Mips_TPREL_HI; 456c85e3ff3SBruno Cardoso Lopes break; 457c85e3ff3SBruno Cardoso Lopes case MCSymbolRefExpr::VK_Mips_TPREL_LO: 458d2cca113SDavid Woodhouse FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_TPREL_LO16 459e7ae8af8SZoran Jovanovic : Mips::fixup_Mips_TPREL_LO; 460c85e3ff3SBruno Cardoso Lopes break; 46184491abbSJack Carter case MCSymbolRefExpr::VK_Mips_HIGHER: 46284491abbSJack Carter FixupKind = Mips::fixup_Mips_HIGHER; 46384491abbSJack Carter break; 46484491abbSJack Carter case MCSymbolRefExpr::VK_Mips_HIGHEST: 46584491abbSJack Carter FixupKind = Mips::fixup_Mips_HIGHEST; 46684491abbSJack Carter break; 467b05cb67bSJack Carter case MCSymbolRefExpr::VK_Mips_GOT_HI16: 468b05cb67bSJack Carter FixupKind = Mips::fixup_Mips_GOT_HI16; 469b05cb67bSJack Carter break; 470b05cb67bSJack Carter case MCSymbolRefExpr::VK_Mips_GOT_LO16: 471b05cb67bSJack Carter FixupKind = Mips::fixup_Mips_GOT_LO16; 472b05cb67bSJack Carter break; 473b05cb67bSJack Carter case MCSymbolRefExpr::VK_Mips_CALL_HI16: 474b05cb67bSJack Carter FixupKind = Mips::fixup_Mips_CALL_HI16; 475b05cb67bSJack Carter break; 476b05cb67bSJack Carter case MCSymbolRefExpr::VK_Mips_CALL_LO16: 477b05cb67bSJack Carter FixupKind = Mips::fixup_Mips_CALL_LO16; 478b05cb67bSJack Carter break; 479c85e3ff3SBruno Cardoso Lopes } // switch 480fe384a2cSAkira Hatanaka 481b5cf5909SJack Carter Fixups.push_back(MCFixup::Create(0, Expr, MCFixupKind(FixupKind))); 482fe384a2cSAkira Hatanaka return 0; 483c85e3ff3SBruno Cardoso Lopes } 484b5cf5909SJack Carter return 0; 485b5cf5909SJack Carter } 486b5cf5909SJack Carter 487b5cf5909SJack Carter /// getMachineOpValue - Return binary encoding of operand. If the machine 488b5cf5909SJack Carter /// operand requires relocation, record the relocation and return zero. 489b5cf5909SJack Carter unsigned MipsMCCodeEmitter:: 490b5cf5909SJack Carter getMachineOpValue(const MCInst &MI, const MCOperand &MO, 4913fa98a65SDavid Woodhouse SmallVectorImpl<MCFixup> &Fixups, 4923fa98a65SDavid Woodhouse const MCSubtargetInfo &STI) const { 493b5cf5909SJack Carter if (MO.isReg()) { 494b5cf5909SJack Carter unsigned Reg = MO.getReg(); 495bc07a890SBill Wendling unsigned RegNo = Ctx.getRegisterInfo()->getEncodingValue(Reg); 496b5cf5909SJack Carter return RegNo; 497b5cf5909SJack Carter } else if (MO.isImm()) { 498b5cf5909SJack Carter return static_cast<unsigned>(MO.getImm()); 499b5cf5909SJack Carter } else if (MO.isFPImm()) { 500b5cf5909SJack Carter return static_cast<unsigned>(APFloat(MO.getFPImm()) 501b5cf5909SJack Carter .bitcastToAPInt().getHiBits(32).getLimitedValue()); 502b5cf5909SJack Carter } 503b5cf5909SJack Carter // MO must be an Expr. 504b5cf5909SJack Carter assert(MO.isExpr()); 5053fa98a65SDavid Woodhouse return getExprOpValue(MO.getExpr(),Fixups, STI); 506b5cf5909SJack Carter } 507c85e3ff3SBruno Cardoso Lopes 5086b59c449SMatheus Almeida /// getMSAMemEncoding - Return binary encoding of memory operand for LD/ST 5096b59c449SMatheus Almeida /// instructions. 5106b59c449SMatheus Almeida unsigned 5116b59c449SMatheus Almeida MipsMCCodeEmitter::getMSAMemEncoding(const MCInst &MI, unsigned OpNo, 5123fa98a65SDavid Woodhouse SmallVectorImpl<MCFixup> &Fixups, 5133fa98a65SDavid Woodhouse const MCSubtargetInfo &STI) const { 5146b59c449SMatheus Almeida // Base register is encoded in bits 20-16, offset is encoded in bits 15-0. 5156b59c449SMatheus Almeida assert(MI.getOperand(OpNo).isReg()); 5163fa98a65SDavid Woodhouse unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo),Fixups, STI) << 16; 5173fa98a65SDavid Woodhouse unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI); 5186b59c449SMatheus Almeida 5196b59c449SMatheus Almeida // The immediate field of an LD/ST instruction is scaled which means it must 5206b59c449SMatheus Almeida // be divided (when encoding) by the size (in bytes) of the instructions' 5216b59c449SMatheus Almeida // data format. 5226b59c449SMatheus Almeida // .b - 1 byte 5236b59c449SMatheus Almeida // .h - 2 bytes 5246b59c449SMatheus Almeida // .w - 4 bytes 5256b59c449SMatheus Almeida // .d - 8 bytes 5266b59c449SMatheus Almeida switch(MI.getOpcode()) 5276b59c449SMatheus Almeida { 5286b59c449SMatheus Almeida default: 5296b59c449SMatheus Almeida assert (0 && "Unexpected instruction"); 5306b59c449SMatheus Almeida break; 5316b59c449SMatheus Almeida case Mips::LD_B: 5326b59c449SMatheus Almeida case Mips::ST_B: 5336b59c449SMatheus Almeida // We don't need to scale the offset in this case 5346b59c449SMatheus Almeida break; 5356b59c449SMatheus Almeida case Mips::LD_H: 5366b59c449SMatheus Almeida case Mips::ST_H: 5376b59c449SMatheus Almeida OffBits >>= 1; 5386b59c449SMatheus Almeida break; 5396b59c449SMatheus Almeida case Mips::LD_W: 5406b59c449SMatheus Almeida case Mips::ST_W: 5416b59c449SMatheus Almeida OffBits >>= 2; 5426b59c449SMatheus Almeida break; 5436b59c449SMatheus Almeida case Mips::LD_D: 5446b59c449SMatheus Almeida case Mips::ST_D: 5456b59c449SMatheus Almeida OffBits >>= 3; 5466b59c449SMatheus Almeida break; 5476b59c449SMatheus Almeida } 5486b59c449SMatheus Almeida 5496b59c449SMatheus Almeida return (OffBits & 0xFFFF) | RegBits; 5506b59c449SMatheus Almeida } 5516b59c449SMatheus Almeida 552c85e3ff3SBruno Cardoso Lopes /// getMemEncoding - Return binary encoding of memory related operand. 553c85e3ff3SBruno Cardoso Lopes /// If the offset operand requires relocation, record the relocation. 554c85e3ff3SBruno Cardoso Lopes unsigned 555c85e3ff3SBruno Cardoso Lopes MipsMCCodeEmitter::getMemEncoding(const MCInst &MI, unsigned OpNo, 5563fa98a65SDavid Woodhouse SmallVectorImpl<MCFixup> &Fixups, 5573fa98a65SDavid Woodhouse const MCSubtargetInfo &STI) const { 558c85e3ff3SBruno Cardoso Lopes // Base register is encoded in bits 20-16, offset is encoded in bits 15-0. 559c85e3ff3SBruno Cardoso Lopes assert(MI.getOperand(OpNo).isReg()); 5603fa98a65SDavid Woodhouse unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo),Fixups, STI) << 16; 5613fa98a65SDavid Woodhouse unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI); 562c85e3ff3SBruno Cardoso Lopes 563c85e3ff3SBruno Cardoso Lopes return (OffBits & 0xFFFF) | RegBits; 564c85e3ff3SBruno Cardoso Lopes } 565c85e3ff3SBruno Cardoso Lopes 56697700977SJack Carter unsigned MipsMCCodeEmitter:: 56797700977SJack Carter getMemEncodingMMImm12(const MCInst &MI, unsigned OpNo, 5683fa98a65SDavid Woodhouse SmallVectorImpl<MCFixup> &Fixups, 5693fa98a65SDavid Woodhouse const MCSubtargetInfo &STI) const { 57097700977SJack Carter // Base register is encoded in bits 20-16, offset is encoded in bits 11-0. 57197700977SJack Carter assert(MI.getOperand(OpNo).isReg()); 5723fa98a65SDavid Woodhouse unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI) << 16; 5733fa98a65SDavid Woodhouse unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI); 57497700977SJack Carter 57597700977SJack Carter return (OffBits & 0x0FFF) | RegBits; 57697700977SJack Carter } 57797700977SJack Carter 578c85e3ff3SBruno Cardoso Lopes unsigned 579c85e3ff3SBruno Cardoso Lopes MipsMCCodeEmitter::getSizeExtEncoding(const MCInst &MI, unsigned OpNo, 5803fa98a65SDavid Woodhouse SmallVectorImpl<MCFixup> &Fixups, 5813fa98a65SDavid Woodhouse const MCSubtargetInfo &STI) const { 582049e9e4dSAkira Hatanaka assert(MI.getOperand(OpNo).isImm()); 5833fa98a65SDavid Woodhouse unsigned SizeEncoding = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI); 58456b70de0SBruno Cardoso Lopes return SizeEncoding - 1; 585c85e3ff3SBruno Cardoso Lopes } 586c85e3ff3SBruno Cardoso Lopes 587049e9e4dSAkira Hatanaka // FIXME: should be called getMSBEncoding 588049e9e4dSAkira Hatanaka // 589c85e3ff3SBruno Cardoso Lopes unsigned 590c85e3ff3SBruno Cardoso Lopes MipsMCCodeEmitter::getSizeInsEncoding(const MCInst &MI, unsigned OpNo, 5913fa98a65SDavid Woodhouse SmallVectorImpl<MCFixup> &Fixups, 5923fa98a65SDavid Woodhouse const MCSubtargetInfo &STI) const { 593049e9e4dSAkira Hatanaka assert(MI.getOperand(OpNo-1).isImm()); 594049e9e4dSAkira Hatanaka assert(MI.getOperand(OpNo).isImm()); 5953fa98a65SDavid Woodhouse unsigned Position = getMachineOpValue(MI, MI.getOperand(OpNo-1), Fixups, STI); 5963fa98a65SDavid Woodhouse unsigned Size = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI); 597049e9e4dSAkira Hatanaka 59856b70de0SBruno Cardoso Lopes return Position + Size - 1; 599c85e3ff3SBruno Cardoso Lopes } 600c85e3ff3SBruno Cardoso Lopes 601779c5937SMatheus Almeida unsigned 602779c5937SMatheus Almeida MipsMCCodeEmitter::getLSAImmEncoding(const MCInst &MI, unsigned OpNo, 6033fa98a65SDavid Woodhouse SmallVectorImpl<MCFixup> &Fixups, 6043fa98a65SDavid Woodhouse const MCSubtargetInfo &STI) const { 605779c5937SMatheus Almeida assert(MI.getOperand(OpNo).isImm()); 606779c5937SMatheus Almeida // The immediate is encoded as 'immediate - 1'. 6073fa98a65SDavid Woodhouse return getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI) - 1; 608779c5937SMatheus Almeida } 609779c5937SMatheus Almeida 610b59e1a41SDaniel Sanders unsigned 611b59e1a41SDaniel Sanders MipsMCCodeEmitter::getSimm19Lsl2Encoding(const MCInst &MI, unsigned OpNo, 612b59e1a41SDaniel Sanders SmallVectorImpl<MCFixup> &Fixups, 613b59e1a41SDaniel Sanders const MCSubtargetInfo &STI) const { 614b59e1a41SDaniel Sanders assert(MI.getOperand(OpNo).isImm()); 615b59e1a41SDaniel Sanders // The immediate is encoded as 'immediate << 2'. 616b59e1a41SDaniel Sanders unsigned Res = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI); 617b59e1a41SDaniel Sanders assert((Res & 3) == 0); 618b59e1a41SDaniel Sanders return Res >> 2; 619b59e1a41SDaniel Sanders } 620c85e3ff3SBruno Cardoso Lopes 621b59e1a41SDaniel Sanders #include "MipsGenMCCodeEmitter.inc" 622