10b57cec5SDimitry Andric //===-- MipsMCCodeEmitter.cpp - Convert Mips Code to Machine Code ---------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file implements the MipsMCCodeEmitter class. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #include "MipsMCCodeEmitter.h" 140b57cec5SDimitry Andric #include "MCTargetDesc/MipsFixupKinds.h" 150b57cec5SDimitry Andric #include "MCTargetDesc/MipsMCExpr.h" 160b57cec5SDimitry Andric #include "MCTargetDesc/MipsMCTargetDesc.h" 170b57cec5SDimitry Andric #include "llvm/ADT/APFloat.h" 180b57cec5SDimitry Andric #include "llvm/ADT/APInt.h" 190b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h" 200b57cec5SDimitry Andric #include "llvm/MC/MCContext.h" 210b57cec5SDimitry Andric #include "llvm/MC/MCExpr.h" 220b57cec5SDimitry Andric #include "llvm/MC/MCFixup.h" 230b57cec5SDimitry Andric #include "llvm/MC/MCInst.h" 240b57cec5SDimitry Andric #include "llvm/MC/MCInstrDesc.h" 250b57cec5SDimitry Andric #include "llvm/MC/MCInstrInfo.h" 260b57cec5SDimitry Andric #include "llvm/MC/MCRegisterInfo.h" 270b57cec5SDimitry Andric #include "llvm/MC/MCSubtargetInfo.h" 280b57cec5SDimitry Andric #include "llvm/Support/Casting.h" 29*5f757f3fSDimitry Andric #include "llvm/Support/EndianStream.h" 300b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 310b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 320b57cec5SDimitry Andric #include <cassert> 330b57cec5SDimitry Andric #include <cstdint> 340b57cec5SDimitry Andric 350b57cec5SDimitry Andric using namespace llvm; 360b57cec5SDimitry Andric 370b57cec5SDimitry Andric #define DEBUG_TYPE "mccodeemitter" 380b57cec5SDimitry Andric 390b57cec5SDimitry Andric #define GET_INSTRMAP_INFO 400b57cec5SDimitry Andric #include "MipsGenInstrInfo.inc" 410b57cec5SDimitry Andric #undef GET_INSTRMAP_INFO 420b57cec5SDimitry Andric 430b57cec5SDimitry Andric namespace llvm { 440b57cec5SDimitry Andric 450b57cec5SDimitry Andric MCCodeEmitter *createMipsMCCodeEmitterEB(const MCInstrInfo &MCII, 460b57cec5SDimitry Andric MCContext &Ctx) { 470b57cec5SDimitry Andric return new MipsMCCodeEmitter(MCII, Ctx, false); 480b57cec5SDimitry Andric } 490b57cec5SDimitry Andric 500b57cec5SDimitry Andric MCCodeEmitter *createMipsMCCodeEmitterEL(const MCInstrInfo &MCII, 510b57cec5SDimitry Andric MCContext &Ctx) { 520b57cec5SDimitry Andric return new MipsMCCodeEmitter(MCII, Ctx, true); 530b57cec5SDimitry Andric } 540b57cec5SDimitry Andric 550b57cec5SDimitry Andric } // end namespace llvm 560b57cec5SDimitry Andric 570b57cec5SDimitry Andric // If the D<shift> instruction has a shift amount that is greater 580b57cec5SDimitry Andric // than 31 (checked in calling routine), lower it to a D<shift>32 instruction 590b57cec5SDimitry Andric static void LowerLargeShift(MCInst& Inst) { 600b57cec5SDimitry Andric assert(Inst.getNumOperands() == 3 && "Invalid no. of operands for shift!"); 610b57cec5SDimitry Andric assert(Inst.getOperand(2).isImm()); 620b57cec5SDimitry Andric 630b57cec5SDimitry Andric int64_t Shift = Inst.getOperand(2).getImm(); 640b57cec5SDimitry Andric if (Shift <= 31) 650b57cec5SDimitry Andric return; // Do nothing 660b57cec5SDimitry Andric Shift -= 32; 670b57cec5SDimitry Andric 680b57cec5SDimitry Andric // saminus32 690b57cec5SDimitry Andric Inst.getOperand(2).setImm(Shift); 700b57cec5SDimitry Andric 710b57cec5SDimitry Andric switch (Inst.getOpcode()) { 720b57cec5SDimitry Andric default: 730b57cec5SDimitry Andric // Calling function is not synchronized 740b57cec5SDimitry Andric llvm_unreachable("Unexpected shift instruction"); 750b57cec5SDimitry Andric case Mips::DSLL: 760b57cec5SDimitry Andric Inst.setOpcode(Mips::DSLL32); 770b57cec5SDimitry Andric return; 780b57cec5SDimitry Andric case Mips::DSRL: 790b57cec5SDimitry Andric Inst.setOpcode(Mips::DSRL32); 800b57cec5SDimitry Andric return; 810b57cec5SDimitry Andric case Mips::DSRA: 820b57cec5SDimitry Andric Inst.setOpcode(Mips::DSRA32); 830b57cec5SDimitry Andric return; 840b57cec5SDimitry Andric case Mips::DROTR: 850b57cec5SDimitry Andric Inst.setOpcode(Mips::DROTR32); 860b57cec5SDimitry Andric return; 870b57cec5SDimitry Andric } 880b57cec5SDimitry Andric } 890b57cec5SDimitry Andric 900b57cec5SDimitry Andric // Fix a bad compact branch encoding for beqc/bnec. 910b57cec5SDimitry Andric void MipsMCCodeEmitter::LowerCompactBranch(MCInst& Inst) const { 920b57cec5SDimitry Andric // Encoding may be illegal !(rs < rt), but this situation is 930b57cec5SDimitry Andric // easily fixed. 940b57cec5SDimitry Andric unsigned RegOp0 = Inst.getOperand(0).getReg(); 950b57cec5SDimitry Andric unsigned RegOp1 = Inst.getOperand(1).getReg(); 960b57cec5SDimitry Andric 970b57cec5SDimitry Andric unsigned Reg0 = Ctx.getRegisterInfo()->getEncodingValue(RegOp0); 980b57cec5SDimitry Andric unsigned Reg1 = Ctx.getRegisterInfo()->getEncodingValue(RegOp1); 990b57cec5SDimitry Andric 1000b57cec5SDimitry Andric if (Inst.getOpcode() == Mips::BNEC || Inst.getOpcode() == Mips::BEQC || 1010b57cec5SDimitry Andric Inst.getOpcode() == Mips::BNEC64 || Inst.getOpcode() == Mips::BEQC64) { 1020b57cec5SDimitry Andric assert(Reg0 != Reg1 && "Instruction has bad operands ($rs == $rt)!"); 1030b57cec5SDimitry Andric if (Reg0 < Reg1) 1040b57cec5SDimitry Andric return; 1050b57cec5SDimitry Andric } else if (Inst.getOpcode() == Mips::BNVC || Inst.getOpcode() == Mips::BOVC) { 1060b57cec5SDimitry Andric if (Reg0 >= Reg1) 1070b57cec5SDimitry Andric return; 1080b57cec5SDimitry Andric } else if (Inst.getOpcode() == Mips::BNVC_MMR6 || 1090b57cec5SDimitry Andric Inst.getOpcode() == Mips::BOVC_MMR6) { 1100b57cec5SDimitry Andric if (Reg1 >= Reg0) 1110b57cec5SDimitry Andric return; 1120b57cec5SDimitry Andric } else 1130b57cec5SDimitry Andric llvm_unreachable("Cannot rewrite unknown branch!"); 1140b57cec5SDimitry Andric 1150b57cec5SDimitry Andric Inst.getOperand(0).setReg(RegOp1); 1160b57cec5SDimitry Andric Inst.getOperand(1).setReg(RegOp0); 1170b57cec5SDimitry Andric } 1180b57cec5SDimitry Andric 1190b57cec5SDimitry Andric bool MipsMCCodeEmitter::isMicroMips(const MCSubtargetInfo &STI) const { 12006c3fb27SDimitry Andric return STI.hasFeature(Mips::FeatureMicroMips); 1210b57cec5SDimitry Andric } 1220b57cec5SDimitry Andric 1230b57cec5SDimitry Andric bool MipsMCCodeEmitter::isMips32r6(const MCSubtargetInfo &STI) const { 12406c3fb27SDimitry Andric return STI.hasFeature(Mips::FeatureMips32r6); 1250b57cec5SDimitry Andric } 1260b57cec5SDimitry Andric 1270b57cec5SDimitry Andric void MipsMCCodeEmitter::EmitByte(unsigned char C, raw_ostream &OS) const { 1280b57cec5SDimitry Andric OS << (char)C; 1290b57cec5SDimitry Andric } 1300b57cec5SDimitry Andric 1310b57cec5SDimitry Andric /// encodeInstruction - Emit the instruction. 1320b57cec5SDimitry Andric /// Size the instruction with Desc.getSize(). 133*5f757f3fSDimitry Andric void MipsMCCodeEmitter::encodeInstruction(const MCInst &MI, 134*5f757f3fSDimitry Andric SmallVectorImpl<char> &CB, 1350b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 136*5f757f3fSDimitry Andric const MCSubtargetInfo &STI) const { 1370b57cec5SDimitry Andric // Non-pseudo instructions that get changed for direct object 1380b57cec5SDimitry Andric // only based on operand values. 1390b57cec5SDimitry Andric // If this list of instructions get much longer we will move 1400b57cec5SDimitry Andric // the check to a function call. Until then, this is more efficient. 1410b57cec5SDimitry Andric MCInst TmpInst = MI; 1420b57cec5SDimitry Andric switch (MI.getOpcode()) { 1430b57cec5SDimitry Andric // If shift amount is >= 32 it the inst needs to be lowered further 1440b57cec5SDimitry Andric case Mips::DSLL: 1450b57cec5SDimitry Andric case Mips::DSRL: 1460b57cec5SDimitry Andric case Mips::DSRA: 1470b57cec5SDimitry Andric case Mips::DROTR: 1480b57cec5SDimitry Andric LowerLargeShift(TmpInst); 1490b57cec5SDimitry Andric break; 1500b57cec5SDimitry Andric // Compact branches, enforce encoding restrictions. 1510b57cec5SDimitry Andric case Mips::BEQC: 1520b57cec5SDimitry Andric case Mips::BNEC: 1530b57cec5SDimitry Andric case Mips::BEQC64: 1540b57cec5SDimitry Andric case Mips::BNEC64: 1550b57cec5SDimitry Andric case Mips::BOVC: 1560b57cec5SDimitry Andric case Mips::BOVC_MMR6: 1570b57cec5SDimitry Andric case Mips::BNVC: 1580b57cec5SDimitry Andric case Mips::BNVC_MMR6: 1590b57cec5SDimitry Andric LowerCompactBranch(TmpInst); 1600b57cec5SDimitry Andric } 1610b57cec5SDimitry Andric 162bdd1243dSDimitry Andric size_t N = Fixups.size(); 1630b57cec5SDimitry Andric uint32_t Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI); 1640b57cec5SDimitry Andric 1650b57cec5SDimitry Andric // Check for unimplemented opcodes. 1660b57cec5SDimitry Andric // Unfortunately in MIPS both NOP and SLL will come in with Binary == 0 1670b57cec5SDimitry Andric // so we have to special check for them. 1680b57cec5SDimitry Andric const unsigned Opcode = TmpInst.getOpcode(); 1690b57cec5SDimitry Andric if ((Opcode != Mips::NOP) && (Opcode != Mips::SLL) && 1700b57cec5SDimitry Andric (Opcode != Mips::SLL_MM) && (Opcode != Mips::SLL_MMR6) && !Binary) 1710b57cec5SDimitry Andric llvm_unreachable("unimplemented opcode in encodeInstruction()"); 1720b57cec5SDimitry Andric 1730b57cec5SDimitry Andric int NewOpcode = -1; 1740b57cec5SDimitry Andric if (isMicroMips(STI)) { 1750b57cec5SDimitry Andric if (isMips32r6(STI)) { 1760b57cec5SDimitry Andric NewOpcode = Mips::MipsR62MicroMipsR6(Opcode, Mips::Arch_micromipsr6); 1770b57cec5SDimitry Andric if (NewOpcode == -1) 1780b57cec5SDimitry Andric NewOpcode = Mips::Std2MicroMipsR6(Opcode, Mips::Arch_micromipsr6); 1790b57cec5SDimitry Andric } 1800b57cec5SDimitry Andric else 1810b57cec5SDimitry Andric NewOpcode = Mips::Std2MicroMips(Opcode, Mips::Arch_micromips); 1820b57cec5SDimitry Andric 1830b57cec5SDimitry Andric // Check whether it is Dsp instruction. 1840b57cec5SDimitry Andric if (NewOpcode == -1) 1850b57cec5SDimitry Andric NewOpcode = Mips::Dsp2MicroMips(Opcode, Mips::Arch_mmdsp); 1860b57cec5SDimitry Andric 1870b57cec5SDimitry Andric if (NewOpcode != -1) { 1880b57cec5SDimitry Andric if (Fixups.size() > N) 1890b57cec5SDimitry Andric Fixups.pop_back(); 1900b57cec5SDimitry Andric 1910b57cec5SDimitry Andric TmpInst.setOpcode (NewOpcode); 1920b57cec5SDimitry Andric Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI); 1930b57cec5SDimitry Andric } 1940b57cec5SDimitry Andric 1950b57cec5SDimitry Andric if (((MI.getOpcode() == Mips::MOVEP_MM) || 1960b57cec5SDimitry Andric (MI.getOpcode() == Mips::MOVEP_MMR6))) { 1970b57cec5SDimitry Andric unsigned RegPair = getMovePRegPairOpValue(MI, 0, Fixups, STI); 1980b57cec5SDimitry Andric Binary = (Binary & 0xFFFFFC7F) | (RegPair << 7); 1990b57cec5SDimitry Andric } 2000b57cec5SDimitry Andric } 2010b57cec5SDimitry Andric 2020b57cec5SDimitry Andric const MCInstrDesc &Desc = MCII.get(TmpInst.getOpcode()); 2030b57cec5SDimitry Andric 2040b57cec5SDimitry Andric // Get byte count of instruction 2050b57cec5SDimitry Andric unsigned Size = Desc.getSize(); 2060b57cec5SDimitry Andric if (!Size) 2070b57cec5SDimitry Andric llvm_unreachable("Desc.getSize() returns 0"); 2080b57cec5SDimitry Andric 209*5f757f3fSDimitry Andric auto Endian = 210*5f757f3fSDimitry Andric IsLittleEndian ? llvm::endianness::little : llvm::endianness::big; 211*5f757f3fSDimitry Andric if (Size == 2) { 212*5f757f3fSDimitry Andric support::endian::write<uint16_t>(CB, Binary, Endian); 213*5f757f3fSDimitry Andric } else if (IsLittleEndian && isMicroMips(STI)) { 214*5f757f3fSDimitry Andric support::endian::write<uint16_t>(CB, Binary >> 16, Endian); 215*5f757f3fSDimitry Andric support::endian::write<uint16_t>(CB, Binary & 0xffff, Endian); 216*5f757f3fSDimitry Andric } else { 217*5f757f3fSDimitry Andric support::endian::write<uint32_t>(CB, Binary, Endian); 218*5f757f3fSDimitry Andric } 2190b57cec5SDimitry Andric } 2200b57cec5SDimitry Andric 2210b57cec5SDimitry Andric /// getBranchTargetOpValue - Return binary encoding of the branch 2220b57cec5SDimitry Andric /// target operand. If the machine operand requires relocation, 2230b57cec5SDimitry Andric /// record the relocation and return zero. 2240b57cec5SDimitry Andric unsigned MipsMCCodeEmitter:: 2250b57cec5SDimitry Andric getBranchTargetOpValue(const MCInst &MI, unsigned OpNo, 2260b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 2270b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 2280b57cec5SDimitry Andric const MCOperand &MO = MI.getOperand(OpNo); 2290b57cec5SDimitry Andric 2300b57cec5SDimitry Andric // If the destination is an immediate, divide by 4. 2310b57cec5SDimitry Andric if (MO.isImm()) return MO.getImm() >> 2; 2320b57cec5SDimitry Andric 2330b57cec5SDimitry Andric assert(MO.isExpr() && 2340b57cec5SDimitry Andric "getBranchTargetOpValue expects only expressions or immediates"); 2350b57cec5SDimitry Andric 2360b57cec5SDimitry Andric const MCExpr *FixupExpression = MCBinaryExpr::createAdd( 2370b57cec5SDimitry Andric MO.getExpr(), MCConstantExpr::create(-4, Ctx), Ctx); 2380b57cec5SDimitry Andric Fixups.push_back(MCFixup::create(0, FixupExpression, 2390b57cec5SDimitry Andric MCFixupKind(Mips::fixup_Mips_PC16))); 2400b57cec5SDimitry Andric return 0; 2410b57cec5SDimitry Andric } 2420b57cec5SDimitry Andric 2430b57cec5SDimitry Andric /// getBranchTargetOpValue1SImm16 - Return binary encoding of the branch 2440b57cec5SDimitry Andric /// target operand. If the machine operand requires relocation, 2450b57cec5SDimitry Andric /// record the relocation and return zero. 2460b57cec5SDimitry Andric unsigned MipsMCCodeEmitter:: 2470b57cec5SDimitry Andric getBranchTargetOpValue1SImm16(const MCInst &MI, unsigned OpNo, 2480b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 2490b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 2500b57cec5SDimitry Andric const MCOperand &MO = MI.getOperand(OpNo); 2510b57cec5SDimitry Andric 2520b57cec5SDimitry Andric // If the destination is an immediate, divide by 2. 2530b57cec5SDimitry Andric if (MO.isImm()) return MO.getImm() >> 1; 2540b57cec5SDimitry Andric 2550b57cec5SDimitry Andric assert(MO.isExpr() && 2560b57cec5SDimitry Andric "getBranchTargetOpValue expects only expressions or immediates"); 2570b57cec5SDimitry Andric 2580b57cec5SDimitry Andric const MCExpr *FixupExpression = MCBinaryExpr::createAdd( 2590b57cec5SDimitry Andric MO.getExpr(), MCConstantExpr::create(-4, Ctx), Ctx); 2600b57cec5SDimitry Andric Fixups.push_back(MCFixup::create(0, FixupExpression, 2610b57cec5SDimitry Andric MCFixupKind(Mips::fixup_Mips_PC16))); 2620b57cec5SDimitry Andric return 0; 2630b57cec5SDimitry Andric } 2640b57cec5SDimitry Andric 2650b57cec5SDimitry Andric /// getBranchTargetOpValueMMR6 - Return binary encoding of the branch 2660b57cec5SDimitry Andric /// target operand. If the machine operand requires relocation, 2670b57cec5SDimitry Andric /// record the relocation and return zero. 2680b57cec5SDimitry Andric unsigned MipsMCCodeEmitter:: 2690b57cec5SDimitry Andric getBranchTargetOpValueMMR6(const MCInst &MI, unsigned OpNo, 2700b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 2710b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 2720b57cec5SDimitry Andric const MCOperand &MO = MI.getOperand(OpNo); 2730b57cec5SDimitry Andric 2740b57cec5SDimitry Andric // If the destination is an immediate, divide by 2. 2750b57cec5SDimitry Andric if (MO.isImm()) 2760b57cec5SDimitry Andric return MO.getImm() >> 1; 2770b57cec5SDimitry Andric 2780b57cec5SDimitry Andric assert(MO.isExpr() && 2790b57cec5SDimitry Andric "getBranchTargetOpValueMMR6 expects only expressions or immediates"); 2800b57cec5SDimitry Andric 2810b57cec5SDimitry Andric const MCExpr *FixupExpression = MCBinaryExpr::createAdd( 2820b57cec5SDimitry Andric MO.getExpr(), MCConstantExpr::create(-2, Ctx), Ctx); 2830b57cec5SDimitry Andric Fixups.push_back(MCFixup::create(0, FixupExpression, 2840b57cec5SDimitry Andric MCFixupKind(Mips::fixup_Mips_PC16))); 2850b57cec5SDimitry Andric return 0; 2860b57cec5SDimitry Andric } 2870b57cec5SDimitry Andric 2880b57cec5SDimitry Andric /// getBranchTargetOpValueLsl2MMR6 - Return binary encoding of the branch 2890b57cec5SDimitry Andric /// target operand. If the machine operand requires relocation, 2900b57cec5SDimitry Andric /// record the relocation and return zero. 2910b57cec5SDimitry Andric unsigned MipsMCCodeEmitter:: 2920b57cec5SDimitry Andric getBranchTargetOpValueLsl2MMR6(const MCInst &MI, unsigned OpNo, 2930b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 2940b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 2950b57cec5SDimitry Andric const MCOperand &MO = MI.getOperand(OpNo); 2960b57cec5SDimitry Andric 2970b57cec5SDimitry Andric // If the destination is an immediate, divide by 4. 2980b57cec5SDimitry Andric if (MO.isImm()) 2990b57cec5SDimitry Andric return MO.getImm() >> 2; 3000b57cec5SDimitry Andric 3010b57cec5SDimitry Andric assert(MO.isExpr() && 3020b57cec5SDimitry Andric "getBranchTargetOpValueLsl2MMR6 expects only expressions or immediates"); 3030b57cec5SDimitry Andric 3040b57cec5SDimitry Andric const MCExpr *FixupExpression = MCBinaryExpr::createAdd( 3050b57cec5SDimitry Andric MO.getExpr(), MCConstantExpr::create(-4, Ctx), Ctx); 3060b57cec5SDimitry Andric Fixups.push_back(MCFixup::create(0, FixupExpression, 3070b57cec5SDimitry Andric MCFixupKind(Mips::fixup_Mips_PC16))); 3080b57cec5SDimitry Andric return 0; 3090b57cec5SDimitry Andric } 3100b57cec5SDimitry Andric 3110b57cec5SDimitry Andric /// getBranchTarget7OpValueMM - Return binary encoding of the microMIPS branch 3120b57cec5SDimitry Andric /// target operand. If the machine operand requires relocation, 3130b57cec5SDimitry Andric /// record the relocation and return zero. 3140b57cec5SDimitry Andric unsigned MipsMCCodeEmitter:: 3150b57cec5SDimitry Andric getBranchTarget7OpValueMM(const MCInst &MI, unsigned OpNo, 3160b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 3170b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 3180b57cec5SDimitry Andric const MCOperand &MO = MI.getOperand(OpNo); 3190b57cec5SDimitry Andric 3200b57cec5SDimitry Andric // If the destination is an immediate, divide by 2. 3210b57cec5SDimitry Andric if (MO.isImm()) return MO.getImm() >> 1; 3220b57cec5SDimitry Andric 3230b57cec5SDimitry Andric assert(MO.isExpr() && 3240b57cec5SDimitry Andric "getBranchTargetOpValueMM expects only expressions or immediates"); 3250b57cec5SDimitry Andric 3260b57cec5SDimitry Andric const MCExpr *Expr = MO.getExpr(); 3270b57cec5SDimitry Andric Fixups.push_back(MCFixup::create(0, Expr, 3280b57cec5SDimitry Andric MCFixupKind(Mips::fixup_MICROMIPS_PC7_S1))); 3290b57cec5SDimitry Andric return 0; 3300b57cec5SDimitry Andric } 3310b57cec5SDimitry Andric 3320b57cec5SDimitry Andric /// getBranchTargetOpValueMMPC10 - Return binary encoding of the microMIPS 3330b57cec5SDimitry Andric /// 10-bit branch target operand. If the machine operand requires relocation, 3340b57cec5SDimitry Andric /// record the relocation and return zero. 3350b57cec5SDimitry Andric unsigned MipsMCCodeEmitter:: 3360b57cec5SDimitry Andric getBranchTargetOpValueMMPC10(const MCInst &MI, unsigned OpNo, 3370b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 3380b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 3390b57cec5SDimitry Andric const MCOperand &MO = MI.getOperand(OpNo); 3400b57cec5SDimitry Andric 3410b57cec5SDimitry Andric // If the destination is an immediate, divide by 2. 3420b57cec5SDimitry Andric if (MO.isImm()) return MO.getImm() >> 1; 3430b57cec5SDimitry Andric 3440b57cec5SDimitry Andric assert(MO.isExpr() && 3450b57cec5SDimitry Andric "getBranchTargetOpValuePC10 expects only expressions or immediates"); 3460b57cec5SDimitry Andric 3470b57cec5SDimitry Andric const MCExpr *Expr = MO.getExpr(); 3480b57cec5SDimitry Andric Fixups.push_back(MCFixup::create(0, Expr, 3490b57cec5SDimitry Andric MCFixupKind(Mips::fixup_MICROMIPS_PC10_S1))); 3500b57cec5SDimitry Andric return 0; 3510b57cec5SDimitry Andric } 3520b57cec5SDimitry Andric 3530b57cec5SDimitry Andric /// getBranchTargetOpValue - Return binary encoding of the microMIPS branch 3540b57cec5SDimitry Andric /// target operand. If the machine operand requires relocation, 3550b57cec5SDimitry Andric /// record the relocation and return zero. 3560b57cec5SDimitry Andric unsigned MipsMCCodeEmitter:: 3570b57cec5SDimitry Andric getBranchTargetOpValueMM(const MCInst &MI, unsigned OpNo, 3580b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 3590b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 3600b57cec5SDimitry Andric const MCOperand &MO = MI.getOperand(OpNo); 3610b57cec5SDimitry Andric 3620b57cec5SDimitry Andric // If the destination is an immediate, divide by 2. 3630b57cec5SDimitry Andric if (MO.isImm()) return MO.getImm() >> 1; 3640b57cec5SDimitry Andric 3650b57cec5SDimitry Andric assert(MO.isExpr() && 3660b57cec5SDimitry Andric "getBranchTargetOpValueMM expects only expressions or immediates"); 3670b57cec5SDimitry Andric 3680b57cec5SDimitry Andric const MCExpr *Expr = MO.getExpr(); 3690b57cec5SDimitry Andric Fixups.push_back(MCFixup::create(0, Expr, 3700b57cec5SDimitry Andric MCFixupKind(Mips:: 3710b57cec5SDimitry Andric fixup_MICROMIPS_PC16_S1))); 3720b57cec5SDimitry Andric return 0; 3730b57cec5SDimitry Andric } 3740b57cec5SDimitry Andric 3750b57cec5SDimitry Andric /// getBranchTarget21OpValue - Return binary encoding of the branch 3760b57cec5SDimitry Andric /// target operand. If the machine operand requires relocation, 3770b57cec5SDimitry Andric /// record the relocation and return zero. 3780b57cec5SDimitry Andric unsigned MipsMCCodeEmitter:: 3790b57cec5SDimitry Andric getBranchTarget21OpValue(const MCInst &MI, unsigned OpNo, 3800b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 3810b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 3820b57cec5SDimitry Andric const MCOperand &MO = MI.getOperand(OpNo); 3830b57cec5SDimitry Andric 3840b57cec5SDimitry Andric // If the destination is an immediate, divide by 4. 3850b57cec5SDimitry Andric if (MO.isImm()) return MO.getImm() >> 2; 3860b57cec5SDimitry Andric 3870b57cec5SDimitry Andric assert(MO.isExpr() && 3880b57cec5SDimitry Andric "getBranchTarget21OpValue expects only expressions or immediates"); 3890b57cec5SDimitry Andric 3900b57cec5SDimitry Andric const MCExpr *FixupExpression = MCBinaryExpr::createAdd( 3910b57cec5SDimitry Andric MO.getExpr(), MCConstantExpr::create(-4, Ctx), Ctx); 3920b57cec5SDimitry Andric Fixups.push_back(MCFixup::create(0, FixupExpression, 3930b57cec5SDimitry Andric MCFixupKind(Mips::fixup_MIPS_PC21_S2))); 3940b57cec5SDimitry Andric return 0; 3950b57cec5SDimitry Andric } 3960b57cec5SDimitry Andric 3970b57cec5SDimitry Andric /// getBranchTarget21OpValueMM - Return binary encoding of the branch 3980b57cec5SDimitry Andric /// target operand for microMIPS. If the machine operand requires 3990b57cec5SDimitry Andric /// relocation, record the relocation and return zero. 4000b57cec5SDimitry Andric unsigned MipsMCCodeEmitter:: 4010b57cec5SDimitry Andric getBranchTarget21OpValueMM(const MCInst &MI, unsigned OpNo, 4020b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 4030b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 4040b57cec5SDimitry Andric const MCOperand &MO = MI.getOperand(OpNo); 4050b57cec5SDimitry Andric 4060b57cec5SDimitry Andric // If the destination is an immediate, divide by 4. 4070b57cec5SDimitry Andric if (MO.isImm()) return MO.getImm() >> 2; 4080b57cec5SDimitry Andric 4090b57cec5SDimitry Andric assert(MO.isExpr() && 4100b57cec5SDimitry Andric "getBranchTarget21OpValueMM expects only expressions or immediates"); 4110b57cec5SDimitry Andric 4120b57cec5SDimitry Andric const MCExpr *FixupExpression = MCBinaryExpr::createAdd( 4130b57cec5SDimitry Andric MO.getExpr(), MCConstantExpr::create(-4, Ctx), Ctx); 4140b57cec5SDimitry Andric Fixups.push_back(MCFixup::create(0, FixupExpression, 4150b57cec5SDimitry Andric MCFixupKind(Mips::fixup_MICROMIPS_PC21_S1))); 4160b57cec5SDimitry Andric return 0; 4170b57cec5SDimitry Andric } 4180b57cec5SDimitry Andric 4190b57cec5SDimitry Andric /// getBranchTarget26OpValue - Return binary encoding of the branch 4200b57cec5SDimitry Andric /// target operand. If the machine operand requires relocation, 4210b57cec5SDimitry Andric /// record the relocation and return zero. 4220b57cec5SDimitry Andric unsigned MipsMCCodeEmitter:: 4230b57cec5SDimitry Andric getBranchTarget26OpValue(const MCInst &MI, unsigned OpNo, 4240b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 4250b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 4260b57cec5SDimitry Andric const MCOperand &MO = MI.getOperand(OpNo); 4270b57cec5SDimitry Andric 4280b57cec5SDimitry Andric // If the destination is an immediate, divide by 4. 4290b57cec5SDimitry Andric if (MO.isImm()) return MO.getImm() >> 2; 4300b57cec5SDimitry Andric 4310b57cec5SDimitry Andric assert(MO.isExpr() && 4320b57cec5SDimitry Andric "getBranchTarget26OpValue expects only expressions or immediates"); 4330b57cec5SDimitry Andric 4340b57cec5SDimitry Andric const MCExpr *FixupExpression = MCBinaryExpr::createAdd( 4350b57cec5SDimitry Andric MO.getExpr(), MCConstantExpr::create(-4, Ctx), Ctx); 4360b57cec5SDimitry Andric Fixups.push_back(MCFixup::create(0, FixupExpression, 4370b57cec5SDimitry Andric MCFixupKind(Mips::fixup_MIPS_PC26_S2))); 4380b57cec5SDimitry Andric return 0; 4390b57cec5SDimitry Andric } 4400b57cec5SDimitry Andric 4410b57cec5SDimitry Andric /// getBranchTarget26OpValueMM - Return binary encoding of the branch 4420b57cec5SDimitry Andric /// target operand. If the machine operand requires relocation, 4430b57cec5SDimitry Andric /// record the relocation and return zero. 4440b57cec5SDimitry Andric unsigned MipsMCCodeEmitter::getBranchTarget26OpValueMM( 4450b57cec5SDimitry Andric const MCInst &MI, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups, 4460b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 4470b57cec5SDimitry Andric const MCOperand &MO = MI.getOperand(OpNo); 4480b57cec5SDimitry Andric 4490b57cec5SDimitry Andric // If the destination is an immediate, divide by 2. 4500b57cec5SDimitry Andric if (MO.isImm()) 4510b57cec5SDimitry Andric return MO.getImm() >> 1; 4520b57cec5SDimitry Andric 4530b57cec5SDimitry Andric assert(MO.isExpr() && 4540b57cec5SDimitry Andric "getBranchTarget26OpValueMM expects only expressions or immediates"); 4550b57cec5SDimitry Andric 4560b57cec5SDimitry Andric const MCExpr *FixupExpression = MCBinaryExpr::createAdd( 4570b57cec5SDimitry Andric MO.getExpr(), MCConstantExpr::create(-4, Ctx), Ctx); 4580b57cec5SDimitry Andric Fixups.push_back(MCFixup::create(0, FixupExpression, 4590b57cec5SDimitry Andric MCFixupKind(Mips::fixup_MICROMIPS_PC26_S1))); 4600b57cec5SDimitry Andric return 0; 4610b57cec5SDimitry Andric } 4620b57cec5SDimitry Andric 4630b57cec5SDimitry Andric /// getJumpOffset16OpValue - Return binary encoding of the jump 4640b57cec5SDimitry Andric /// target operand. If the machine operand requires relocation, 4650b57cec5SDimitry Andric /// record the relocation and return zero. 4660b57cec5SDimitry Andric unsigned MipsMCCodeEmitter:: 4670b57cec5SDimitry Andric getJumpOffset16OpValue(const MCInst &MI, unsigned OpNo, 4680b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 4690b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 4700b57cec5SDimitry Andric const MCOperand &MO = MI.getOperand(OpNo); 4710b57cec5SDimitry Andric 4720b57cec5SDimitry Andric if (MO.isImm()) return MO.getImm(); 4730b57cec5SDimitry Andric 4740b57cec5SDimitry Andric assert(MO.isExpr() && 4750b57cec5SDimitry Andric "getJumpOffset16OpValue expects only expressions or an immediate"); 4760b57cec5SDimitry Andric 4778bcb0991SDimitry Andric const MCExpr *Expr = MO.getExpr(); 4788bcb0991SDimitry Andric Mips::Fixups FixupKind = 4798bcb0991SDimitry Andric isMicroMips(STI) ? Mips::fixup_MICROMIPS_LO16 : Mips::fixup_Mips_LO16; 4808bcb0991SDimitry Andric Fixups.push_back(MCFixup::create(0, Expr, MCFixupKind(FixupKind))); 4810b57cec5SDimitry Andric return 0; 4820b57cec5SDimitry Andric } 4830b57cec5SDimitry Andric 4840b57cec5SDimitry Andric /// getJumpTargetOpValue - Return binary encoding of the jump 4850b57cec5SDimitry Andric /// target operand. If the machine operand requires relocation, 4860b57cec5SDimitry Andric /// record the relocation and return zero. 4870b57cec5SDimitry Andric unsigned MipsMCCodeEmitter:: 4880b57cec5SDimitry Andric getJumpTargetOpValue(const MCInst &MI, unsigned OpNo, 4890b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 4900b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 4910b57cec5SDimitry Andric const MCOperand &MO = MI.getOperand(OpNo); 4920b57cec5SDimitry Andric // If the destination is an immediate, divide by 4. 4930b57cec5SDimitry Andric if (MO.isImm()) return MO.getImm()>>2; 4940b57cec5SDimitry Andric 4950b57cec5SDimitry Andric assert(MO.isExpr() && 4960b57cec5SDimitry Andric "getJumpTargetOpValue expects only expressions or an immediate"); 4970b57cec5SDimitry Andric 4980b57cec5SDimitry Andric const MCExpr *Expr = MO.getExpr(); 4990b57cec5SDimitry Andric Fixups.push_back(MCFixup::create(0, Expr, 5000b57cec5SDimitry Andric MCFixupKind(Mips::fixup_Mips_26))); 5010b57cec5SDimitry Andric return 0; 5020b57cec5SDimitry Andric } 5030b57cec5SDimitry Andric 5040b57cec5SDimitry Andric unsigned MipsMCCodeEmitter:: 5050b57cec5SDimitry Andric getJumpTargetOpValueMM(const MCInst &MI, unsigned OpNo, 5060b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 5070b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 5080b57cec5SDimitry Andric const MCOperand &MO = MI.getOperand(OpNo); 5090b57cec5SDimitry Andric // If the destination is an immediate, divide by 2. 5100b57cec5SDimitry Andric if (MO.isImm()) return MO.getImm() >> 1; 5110b57cec5SDimitry Andric 5120b57cec5SDimitry Andric assert(MO.isExpr() && 5130b57cec5SDimitry Andric "getJumpTargetOpValueMM expects only expressions or an immediate"); 5140b57cec5SDimitry Andric 5150b57cec5SDimitry Andric const MCExpr *Expr = MO.getExpr(); 5160b57cec5SDimitry Andric Fixups.push_back(MCFixup::create(0, Expr, 5170b57cec5SDimitry Andric MCFixupKind(Mips::fixup_MICROMIPS_26_S1))); 5180b57cec5SDimitry Andric return 0; 5190b57cec5SDimitry Andric } 5200b57cec5SDimitry Andric 5210b57cec5SDimitry Andric unsigned MipsMCCodeEmitter:: 5220b57cec5SDimitry Andric getUImm5Lsl2Encoding(const MCInst &MI, unsigned OpNo, 5230b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 5240b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 5250b57cec5SDimitry Andric const MCOperand &MO = MI.getOperand(OpNo); 5260b57cec5SDimitry Andric if (MO.isImm()) { 5270b57cec5SDimitry Andric // The immediate is encoded as 'immediate << 2'. 5280b57cec5SDimitry Andric unsigned Res = getMachineOpValue(MI, MO, Fixups, STI); 5290b57cec5SDimitry Andric assert((Res & 3) == 0); 5300b57cec5SDimitry Andric return Res >> 2; 5310b57cec5SDimitry Andric } 5320b57cec5SDimitry Andric 5330b57cec5SDimitry Andric assert(MO.isExpr() && 5340b57cec5SDimitry Andric "getUImm5Lsl2Encoding expects only expressions or an immediate"); 5350b57cec5SDimitry Andric 5360b57cec5SDimitry Andric return 0; 5370b57cec5SDimitry Andric } 5380b57cec5SDimitry Andric 5390b57cec5SDimitry Andric unsigned MipsMCCodeEmitter:: 5400b57cec5SDimitry Andric getSImm3Lsa2Value(const MCInst &MI, unsigned OpNo, 5410b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 5420b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 5430b57cec5SDimitry Andric const MCOperand &MO = MI.getOperand(OpNo); 5440b57cec5SDimitry Andric if (MO.isImm()) { 5450b57cec5SDimitry Andric int Value = MO.getImm(); 5460b57cec5SDimitry Andric return Value >> 2; 5470b57cec5SDimitry Andric } 5480b57cec5SDimitry Andric 5490b57cec5SDimitry Andric return 0; 5500b57cec5SDimitry Andric } 5510b57cec5SDimitry Andric 5520b57cec5SDimitry Andric unsigned MipsMCCodeEmitter:: 5530b57cec5SDimitry Andric getUImm6Lsl2Encoding(const MCInst &MI, unsigned OpNo, 5540b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 5550b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 5560b57cec5SDimitry Andric const MCOperand &MO = MI.getOperand(OpNo); 5570b57cec5SDimitry Andric if (MO.isImm()) { 5580b57cec5SDimitry Andric unsigned Value = MO.getImm(); 5590b57cec5SDimitry Andric return Value >> 2; 5600b57cec5SDimitry Andric } 5610b57cec5SDimitry Andric 5620b57cec5SDimitry Andric return 0; 5630b57cec5SDimitry Andric } 5640b57cec5SDimitry Andric 5650b57cec5SDimitry Andric unsigned MipsMCCodeEmitter:: 5660b57cec5SDimitry Andric getSImm9AddiuspValue(const MCInst &MI, unsigned OpNo, 5670b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 5680b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 5690b57cec5SDimitry Andric const MCOperand &MO = MI.getOperand(OpNo); 5700b57cec5SDimitry Andric if (MO.isImm()) { 5710b57cec5SDimitry Andric unsigned Binary = (MO.getImm() >> 2) & 0x0000ffff; 5720b57cec5SDimitry Andric return (((Binary & 0x8000) >> 7) | (Binary & 0x00ff)); 5730b57cec5SDimitry Andric } 5740b57cec5SDimitry Andric 5750b57cec5SDimitry Andric return 0; 5760b57cec5SDimitry Andric } 5770b57cec5SDimitry Andric 5780b57cec5SDimitry Andric unsigned MipsMCCodeEmitter:: 5790b57cec5SDimitry Andric getExprOpValue(const MCExpr *Expr, SmallVectorImpl<MCFixup> &Fixups, 5800b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 5810b57cec5SDimitry Andric int64_t Res; 5820b57cec5SDimitry Andric 5830b57cec5SDimitry Andric if (Expr->evaluateAsAbsolute(Res)) 5840b57cec5SDimitry Andric return Res; 5850b57cec5SDimitry Andric 5860b57cec5SDimitry Andric MCExpr::ExprKind Kind = Expr->getKind(); 5870b57cec5SDimitry Andric if (Kind == MCExpr::Constant) { 5880b57cec5SDimitry Andric return cast<MCConstantExpr>(Expr)->getValue(); 5890b57cec5SDimitry Andric } 5900b57cec5SDimitry Andric 5910b57cec5SDimitry Andric if (Kind == MCExpr::Binary) { 592480093f4SDimitry Andric unsigned Res = 593480093f4SDimitry Andric getExprOpValue(cast<MCBinaryExpr>(Expr)->getLHS(), Fixups, STI); 5940b57cec5SDimitry Andric Res += getExprOpValue(cast<MCBinaryExpr>(Expr)->getRHS(), Fixups, STI); 5950b57cec5SDimitry Andric return Res; 5960b57cec5SDimitry Andric } 5970b57cec5SDimitry Andric 5980b57cec5SDimitry Andric if (Kind == MCExpr::Target) { 5990b57cec5SDimitry Andric const MipsMCExpr *MipsExpr = cast<MipsMCExpr>(Expr); 6000b57cec5SDimitry Andric 6010b57cec5SDimitry Andric Mips::Fixups FixupKind = Mips::Fixups(0); 6020b57cec5SDimitry Andric switch (MipsExpr->getKind()) { 6030b57cec5SDimitry Andric case MipsMCExpr::MEK_None: 6040b57cec5SDimitry Andric case MipsMCExpr::MEK_Special: 6050b57cec5SDimitry Andric llvm_unreachable("Unhandled fixup kind!"); 6060b57cec5SDimitry Andric break; 6070b57cec5SDimitry Andric case MipsMCExpr::MEK_DTPREL: 6080b57cec5SDimitry Andric // MEK_DTPREL is used for marking TLS DIEExpr only 6090b57cec5SDimitry Andric // and contains a regular sub-expression. 6100b57cec5SDimitry Andric return getExprOpValue(MipsExpr->getSubExpr(), Fixups, STI); 6110b57cec5SDimitry Andric case MipsMCExpr::MEK_CALL_HI16: 6120b57cec5SDimitry Andric FixupKind = Mips::fixup_Mips_CALL_HI16; 6130b57cec5SDimitry Andric break; 6140b57cec5SDimitry Andric case MipsMCExpr::MEK_CALL_LO16: 6150b57cec5SDimitry Andric FixupKind = Mips::fixup_Mips_CALL_LO16; 6160b57cec5SDimitry Andric break; 6170b57cec5SDimitry Andric case MipsMCExpr::MEK_DTPREL_HI: 6180b57cec5SDimitry Andric FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_DTPREL_HI16 6190b57cec5SDimitry Andric : Mips::fixup_Mips_DTPREL_HI; 6200b57cec5SDimitry Andric break; 6210b57cec5SDimitry Andric case MipsMCExpr::MEK_DTPREL_LO: 6220b57cec5SDimitry Andric FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_DTPREL_LO16 6230b57cec5SDimitry Andric : Mips::fixup_Mips_DTPREL_LO; 6240b57cec5SDimitry Andric break; 6250b57cec5SDimitry Andric case MipsMCExpr::MEK_GOTTPREL: 6260b57cec5SDimitry Andric FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOTTPREL 6270b57cec5SDimitry Andric : Mips::fixup_Mips_GOTTPREL; 6280b57cec5SDimitry Andric break; 6290b57cec5SDimitry Andric case MipsMCExpr::MEK_GOT: 6300b57cec5SDimitry Andric FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOT16 6310b57cec5SDimitry Andric : Mips::fixup_Mips_GOT; 6320b57cec5SDimitry Andric break; 6330b57cec5SDimitry Andric case MipsMCExpr::MEK_GOT_CALL: 6340b57cec5SDimitry Andric FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_CALL16 6350b57cec5SDimitry Andric : Mips::fixup_Mips_CALL16; 6360b57cec5SDimitry Andric break; 6370b57cec5SDimitry Andric case MipsMCExpr::MEK_GOT_DISP: 6380b57cec5SDimitry Andric FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOT_DISP 6390b57cec5SDimitry Andric : Mips::fixup_Mips_GOT_DISP; 6400b57cec5SDimitry Andric break; 6410b57cec5SDimitry Andric case MipsMCExpr::MEK_GOT_HI16: 6420b57cec5SDimitry Andric FixupKind = Mips::fixup_Mips_GOT_HI16; 6430b57cec5SDimitry Andric break; 6440b57cec5SDimitry Andric case MipsMCExpr::MEK_GOT_LO16: 6450b57cec5SDimitry Andric FixupKind = Mips::fixup_Mips_GOT_LO16; 6460b57cec5SDimitry Andric break; 6470b57cec5SDimitry Andric case MipsMCExpr::MEK_GOT_PAGE: 6480b57cec5SDimitry Andric FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOT_PAGE 6490b57cec5SDimitry Andric : Mips::fixup_Mips_GOT_PAGE; 6500b57cec5SDimitry Andric break; 6510b57cec5SDimitry Andric case MipsMCExpr::MEK_GOT_OFST: 6520b57cec5SDimitry Andric FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOT_OFST 6530b57cec5SDimitry Andric : Mips::fixup_Mips_GOT_OFST; 6540b57cec5SDimitry Andric break; 6550b57cec5SDimitry Andric case MipsMCExpr::MEK_GPREL: 6560b57cec5SDimitry Andric FixupKind = Mips::fixup_Mips_GPREL16; 6570b57cec5SDimitry Andric break; 6580b57cec5SDimitry Andric case MipsMCExpr::MEK_LO: 6590b57cec5SDimitry Andric // Check for %lo(%neg(%gp_rel(X))) 6600b57cec5SDimitry Andric if (MipsExpr->isGpOff()) 6610b57cec5SDimitry Andric FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GPOFF_LO 6620b57cec5SDimitry Andric : Mips::fixup_Mips_GPOFF_LO; 6630b57cec5SDimitry Andric else 6640b57cec5SDimitry Andric FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_LO16 6650b57cec5SDimitry Andric : Mips::fixup_Mips_LO16; 6660b57cec5SDimitry Andric break; 6670b57cec5SDimitry Andric case MipsMCExpr::MEK_HIGHEST: 6680b57cec5SDimitry Andric FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_HIGHEST 6690b57cec5SDimitry Andric : Mips::fixup_Mips_HIGHEST; 6700b57cec5SDimitry Andric break; 6710b57cec5SDimitry Andric case MipsMCExpr::MEK_HIGHER: 6720b57cec5SDimitry Andric FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_HIGHER 6730b57cec5SDimitry Andric : Mips::fixup_Mips_HIGHER; 6740b57cec5SDimitry Andric break; 6750b57cec5SDimitry Andric case MipsMCExpr::MEK_HI: 6760b57cec5SDimitry Andric // Check for %hi(%neg(%gp_rel(X))) 6770b57cec5SDimitry Andric if (MipsExpr->isGpOff()) 6780b57cec5SDimitry Andric FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GPOFF_HI 6790b57cec5SDimitry Andric : Mips::fixup_Mips_GPOFF_HI; 6800b57cec5SDimitry Andric else 6810b57cec5SDimitry Andric FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_HI16 6820b57cec5SDimitry Andric : Mips::fixup_Mips_HI16; 6830b57cec5SDimitry Andric break; 6840b57cec5SDimitry Andric case MipsMCExpr::MEK_PCREL_HI16: 6850b57cec5SDimitry Andric FixupKind = Mips::fixup_MIPS_PCHI16; 6860b57cec5SDimitry Andric break; 6870b57cec5SDimitry Andric case MipsMCExpr::MEK_PCREL_LO16: 6880b57cec5SDimitry Andric FixupKind = Mips::fixup_MIPS_PCLO16; 6890b57cec5SDimitry Andric break; 6900b57cec5SDimitry Andric case MipsMCExpr::MEK_TLSGD: 6910b57cec5SDimitry Andric FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_GD 6920b57cec5SDimitry Andric : Mips::fixup_Mips_TLSGD; 6930b57cec5SDimitry Andric break; 6940b57cec5SDimitry Andric case MipsMCExpr::MEK_TLSLDM: 6950b57cec5SDimitry Andric FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_LDM 6960b57cec5SDimitry Andric : Mips::fixup_Mips_TLSLDM; 6970b57cec5SDimitry Andric break; 6980b57cec5SDimitry Andric case MipsMCExpr::MEK_TPREL_HI: 6990b57cec5SDimitry Andric FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_TPREL_HI16 7000b57cec5SDimitry Andric : Mips::fixup_Mips_TPREL_HI; 7010b57cec5SDimitry Andric break; 7020b57cec5SDimitry Andric case MipsMCExpr::MEK_TPREL_LO: 7030b57cec5SDimitry Andric FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_TPREL_LO16 7040b57cec5SDimitry Andric : Mips::fixup_Mips_TPREL_LO; 7050b57cec5SDimitry Andric break; 7060b57cec5SDimitry Andric case MipsMCExpr::MEK_NEG: 7070b57cec5SDimitry Andric FixupKind = 7080b57cec5SDimitry Andric isMicroMips(STI) ? Mips::fixup_MICROMIPS_SUB : Mips::fixup_Mips_SUB; 7090b57cec5SDimitry Andric break; 7100b57cec5SDimitry Andric } 7110b57cec5SDimitry Andric Fixups.push_back(MCFixup::create(0, MipsExpr, MCFixupKind(FixupKind))); 7120b57cec5SDimitry Andric return 0; 7130b57cec5SDimitry Andric } 7140b57cec5SDimitry Andric 7155ffd83dbSDimitry Andric if (Kind == MCExpr::SymbolRef) 7165ffd83dbSDimitry Andric Ctx.reportError(Expr->getLoc(), "expected an immediate"); 7170b57cec5SDimitry Andric return 0; 7180b57cec5SDimitry Andric } 7190b57cec5SDimitry Andric 7200b57cec5SDimitry Andric /// getMachineOpValue - Return binary encoding of operand. If the machine 7210b57cec5SDimitry Andric /// operand requires relocation, record the relocation and return zero. 7220b57cec5SDimitry Andric unsigned MipsMCCodeEmitter:: 7230b57cec5SDimitry Andric getMachineOpValue(const MCInst &MI, const MCOperand &MO, 7240b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 7250b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 7260b57cec5SDimitry Andric if (MO.isReg()) { 7270b57cec5SDimitry Andric unsigned Reg = MO.getReg(); 7280b57cec5SDimitry Andric unsigned RegNo = Ctx.getRegisterInfo()->getEncodingValue(Reg); 7290b57cec5SDimitry Andric return RegNo; 7300b57cec5SDimitry Andric } else if (MO.isImm()) { 7310b57cec5SDimitry Andric return static_cast<unsigned>(MO.getImm()); 732fe6060f1SDimitry Andric } else if (MO.isDFPImm()) { 733fe6060f1SDimitry Andric return static_cast<unsigned>(bit_cast<double>(MO.getDFPImm())); 7340b57cec5SDimitry Andric } 7350b57cec5SDimitry Andric // MO must be an Expr. 7360b57cec5SDimitry Andric assert(MO.isExpr()); 7370b57cec5SDimitry Andric return getExprOpValue(MO.getExpr(),Fixups, STI); 7380b57cec5SDimitry Andric } 7390b57cec5SDimitry Andric 7400b57cec5SDimitry Andric /// Return binary encoding of memory related operand. 7410b57cec5SDimitry Andric /// If the offset operand requires relocation, record the relocation. 7420b57cec5SDimitry Andric template <unsigned ShiftAmount> 7430b57cec5SDimitry Andric unsigned MipsMCCodeEmitter::getMemEncoding(const MCInst &MI, unsigned OpNo, 7440b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 7450b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 7460b57cec5SDimitry Andric // Base register is encoded in bits 20-16, offset is encoded in bits 15-0. 7470b57cec5SDimitry Andric assert(MI.getOperand(OpNo).isReg()); 748480093f4SDimitry Andric unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI) 749480093f4SDimitry Andric << 16; 7500b57cec5SDimitry Andric unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI); 7510b57cec5SDimitry Andric 7520b57cec5SDimitry Andric // Apply the scale factor if there is one. 7530b57cec5SDimitry Andric OffBits >>= ShiftAmount; 7540b57cec5SDimitry Andric 7550b57cec5SDimitry Andric return (OffBits & 0xFFFF) | RegBits; 7560b57cec5SDimitry Andric } 7570b57cec5SDimitry Andric 7580b57cec5SDimitry Andric unsigned MipsMCCodeEmitter:: 7590b57cec5SDimitry Andric getMemEncodingMMImm4(const MCInst &MI, unsigned OpNo, 7600b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 7610b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 7620b57cec5SDimitry Andric // Base register is encoded in bits 6-4, offset is encoded in bits 3-0. 7630b57cec5SDimitry Andric assert(MI.getOperand(OpNo).isReg()); 7640b57cec5SDimitry Andric unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), 7650b57cec5SDimitry Andric Fixups, STI) << 4; 7660b57cec5SDimitry Andric unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), 7670b57cec5SDimitry Andric Fixups, STI); 7680b57cec5SDimitry Andric 7690b57cec5SDimitry Andric return (OffBits & 0xF) | RegBits; 7700b57cec5SDimitry Andric } 7710b57cec5SDimitry Andric 7720b57cec5SDimitry Andric unsigned MipsMCCodeEmitter:: 7730b57cec5SDimitry Andric getMemEncodingMMImm4Lsl1(const MCInst &MI, unsigned OpNo, 7740b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 7750b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 7760b57cec5SDimitry Andric // Base register is encoded in bits 6-4, offset is encoded in bits 3-0. 7770b57cec5SDimitry Andric assert(MI.getOperand(OpNo).isReg()); 7780b57cec5SDimitry Andric unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), 7790b57cec5SDimitry Andric Fixups, STI) << 4; 7800b57cec5SDimitry Andric unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), 7810b57cec5SDimitry Andric Fixups, STI) >> 1; 7820b57cec5SDimitry Andric 7830b57cec5SDimitry Andric return (OffBits & 0xF) | RegBits; 7840b57cec5SDimitry Andric } 7850b57cec5SDimitry Andric 7860b57cec5SDimitry Andric unsigned MipsMCCodeEmitter:: 7870b57cec5SDimitry Andric getMemEncodingMMImm4Lsl2(const MCInst &MI, unsigned OpNo, 7880b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 7890b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 7900b57cec5SDimitry Andric // Base register is encoded in bits 6-4, offset is encoded in bits 3-0. 7910b57cec5SDimitry Andric assert(MI.getOperand(OpNo).isReg()); 7920b57cec5SDimitry Andric unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), 7930b57cec5SDimitry Andric Fixups, STI) << 4; 7940b57cec5SDimitry Andric unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), 7950b57cec5SDimitry Andric Fixups, STI) >> 2; 7960b57cec5SDimitry Andric 7970b57cec5SDimitry Andric return (OffBits & 0xF) | RegBits; 7980b57cec5SDimitry Andric } 7990b57cec5SDimitry Andric 8000b57cec5SDimitry Andric unsigned MipsMCCodeEmitter:: 8010b57cec5SDimitry Andric getMemEncodingMMSPImm5Lsl2(const MCInst &MI, unsigned OpNo, 8020b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 8030b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 8040b57cec5SDimitry Andric // Register is encoded in bits 9-5, offset is encoded in bits 4-0. 8050b57cec5SDimitry Andric assert(MI.getOperand(OpNo).isReg() && 8060b57cec5SDimitry Andric (MI.getOperand(OpNo).getReg() == Mips::SP || 8070b57cec5SDimitry Andric MI.getOperand(OpNo).getReg() == Mips::SP_64) && 8080b57cec5SDimitry Andric "Unexpected base register!"); 8090b57cec5SDimitry Andric unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), 8100b57cec5SDimitry Andric Fixups, STI) >> 2; 8110b57cec5SDimitry Andric 8120b57cec5SDimitry Andric return OffBits & 0x1F; 8130b57cec5SDimitry Andric } 8140b57cec5SDimitry Andric 8150b57cec5SDimitry Andric unsigned MipsMCCodeEmitter:: 8160b57cec5SDimitry Andric getMemEncodingMMGPImm7Lsl2(const MCInst &MI, unsigned OpNo, 8170b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 8180b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 8190b57cec5SDimitry Andric // Register is encoded in bits 9-7, offset is encoded in bits 6-0. 8200b57cec5SDimitry Andric assert(MI.getOperand(OpNo).isReg() && 8210b57cec5SDimitry Andric MI.getOperand(OpNo).getReg() == Mips::GP && 8220b57cec5SDimitry Andric "Unexpected base register!"); 8230b57cec5SDimitry Andric 8240b57cec5SDimitry Andric unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), 8250b57cec5SDimitry Andric Fixups, STI) >> 2; 8260b57cec5SDimitry Andric 8270b57cec5SDimitry Andric return OffBits & 0x7F; 8280b57cec5SDimitry Andric } 8290b57cec5SDimitry Andric 8300b57cec5SDimitry Andric unsigned MipsMCCodeEmitter:: 8310b57cec5SDimitry Andric getMemEncodingMMImm9(const MCInst &MI, unsigned OpNo, 8320b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 8330b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 8340b57cec5SDimitry Andric // Base register is encoded in bits 20-16, offset is encoded in bits 8-0. 8350b57cec5SDimitry Andric assert(MI.getOperand(OpNo).isReg()); 8360b57cec5SDimitry Andric unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, 8370b57cec5SDimitry Andric STI) << 16; 838480093f4SDimitry Andric unsigned OffBits = 839480093f4SDimitry Andric getMachineOpValue(MI, MI.getOperand(OpNo + 1), Fixups, STI); 8400b57cec5SDimitry Andric 8410b57cec5SDimitry Andric return (OffBits & 0x1FF) | RegBits; 8420b57cec5SDimitry Andric } 8430b57cec5SDimitry Andric 8440b57cec5SDimitry Andric unsigned MipsMCCodeEmitter:: 8450b57cec5SDimitry Andric getMemEncodingMMImm11(const MCInst &MI, unsigned OpNo, 8460b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 8470b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 8480b57cec5SDimitry Andric // Base register is encoded in bits 20-16, offset is encoded in bits 10-0. 8490b57cec5SDimitry Andric assert(MI.getOperand(OpNo).isReg()); 8500b57cec5SDimitry Andric unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, 8510b57cec5SDimitry Andric STI) << 16; 8520b57cec5SDimitry Andric unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI); 8530b57cec5SDimitry Andric 8540b57cec5SDimitry Andric return (OffBits & 0x07FF) | RegBits; 8550b57cec5SDimitry Andric } 8560b57cec5SDimitry Andric 8570b57cec5SDimitry Andric unsigned MipsMCCodeEmitter:: 8580b57cec5SDimitry Andric getMemEncodingMMImm12(const MCInst &MI, unsigned OpNo, 8590b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 8600b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 8610b57cec5SDimitry Andric // opNum can be invalid if instruction had reglist as operand. 8620b57cec5SDimitry Andric // MemOperand is always last operand of instruction (base + offset). 8630b57cec5SDimitry Andric switch (MI.getOpcode()) { 8640b57cec5SDimitry Andric default: 8650b57cec5SDimitry Andric break; 8660b57cec5SDimitry Andric case Mips::SWM32_MM: 8670b57cec5SDimitry Andric case Mips::LWM32_MM: 8680b57cec5SDimitry Andric OpNo = MI.getNumOperands() - 2; 8690b57cec5SDimitry Andric break; 8700b57cec5SDimitry Andric } 8710b57cec5SDimitry Andric 8720b57cec5SDimitry Andric // Base register is encoded in bits 20-16, offset is encoded in bits 11-0. 8730b57cec5SDimitry Andric assert(MI.getOperand(OpNo).isReg()); 874480093f4SDimitry Andric unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI) 875480093f4SDimitry Andric << 16; 8760b57cec5SDimitry Andric unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI); 8770b57cec5SDimitry Andric 8780b57cec5SDimitry Andric return (OffBits & 0x0FFF) | RegBits; 8790b57cec5SDimitry Andric } 8800b57cec5SDimitry Andric 8810b57cec5SDimitry Andric unsigned MipsMCCodeEmitter:: 8820b57cec5SDimitry Andric getMemEncodingMMImm16(const MCInst &MI, unsigned OpNo, 8830b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 8840b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 8850b57cec5SDimitry Andric // Base register is encoded in bits 20-16, offset is encoded in bits 15-0. 8860b57cec5SDimitry Andric assert(MI.getOperand(OpNo).isReg()); 8870b57cec5SDimitry Andric unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, 8880b57cec5SDimitry Andric STI) << 16; 8890b57cec5SDimitry Andric unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI); 8900b57cec5SDimitry Andric 8910b57cec5SDimitry Andric return (OffBits & 0xFFFF) | RegBits; 8920b57cec5SDimitry Andric } 8930b57cec5SDimitry Andric 8940b57cec5SDimitry Andric unsigned MipsMCCodeEmitter:: 8950b57cec5SDimitry Andric getMemEncodingMMImm4sp(const MCInst &MI, unsigned OpNo, 8960b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 8970b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 8980b57cec5SDimitry Andric // opNum can be invalid if instruction had reglist as operand 8990b57cec5SDimitry Andric // MemOperand is always last operand of instruction (base + offset) 9000b57cec5SDimitry Andric switch (MI.getOpcode()) { 9010b57cec5SDimitry Andric default: 9020b57cec5SDimitry Andric break; 9030b57cec5SDimitry Andric case Mips::SWM16_MM: 9040b57cec5SDimitry Andric case Mips::SWM16_MMR6: 9050b57cec5SDimitry Andric case Mips::LWM16_MM: 9060b57cec5SDimitry Andric case Mips::LWM16_MMR6: 9070b57cec5SDimitry Andric OpNo = MI.getNumOperands() - 2; 9080b57cec5SDimitry Andric break; 9090b57cec5SDimitry Andric } 9100b57cec5SDimitry Andric 9110b57cec5SDimitry Andric // Offset is encoded in bits 4-0. 9120b57cec5SDimitry Andric assert(MI.getOperand(OpNo).isReg()); 9130b57cec5SDimitry Andric // Base register is always SP - thus it is not encoded. 9140b57cec5SDimitry Andric assert(MI.getOperand(OpNo+1).isImm()); 9150b57cec5SDimitry Andric unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI); 9160b57cec5SDimitry Andric 9170b57cec5SDimitry Andric return ((OffBits >> 2) & 0x0F); 9180b57cec5SDimitry Andric } 9190b57cec5SDimitry Andric 9200b57cec5SDimitry Andric // FIXME: should be called getMSBEncoding 9210b57cec5SDimitry Andric // 9220b57cec5SDimitry Andric unsigned 9230b57cec5SDimitry Andric MipsMCCodeEmitter::getSizeInsEncoding(const MCInst &MI, unsigned OpNo, 9240b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 9250b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 9260b57cec5SDimitry Andric assert(MI.getOperand(OpNo-1).isImm()); 9270b57cec5SDimitry Andric assert(MI.getOperand(OpNo).isImm()); 9280b57cec5SDimitry Andric unsigned Position = getMachineOpValue(MI, MI.getOperand(OpNo-1), Fixups, STI); 9290b57cec5SDimitry Andric unsigned Size = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI); 9300b57cec5SDimitry Andric 9310b57cec5SDimitry Andric return Position + Size - 1; 9320b57cec5SDimitry Andric } 9330b57cec5SDimitry Andric 9340b57cec5SDimitry Andric template <unsigned Bits, int Offset> 9350b57cec5SDimitry Andric unsigned 9360b57cec5SDimitry Andric MipsMCCodeEmitter::getUImmWithOffsetEncoding(const MCInst &MI, unsigned OpNo, 9370b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 9380b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 9390b57cec5SDimitry Andric assert(MI.getOperand(OpNo).isImm()); 9400b57cec5SDimitry Andric unsigned Value = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI); 9410b57cec5SDimitry Andric Value -= Offset; 9420b57cec5SDimitry Andric return Value; 9430b57cec5SDimitry Andric } 9440b57cec5SDimitry Andric 9450b57cec5SDimitry Andric unsigned 9460b57cec5SDimitry Andric MipsMCCodeEmitter::getSimm19Lsl2Encoding(const MCInst &MI, unsigned OpNo, 9470b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 9480b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 9490b57cec5SDimitry Andric const MCOperand &MO = MI.getOperand(OpNo); 9500b57cec5SDimitry Andric if (MO.isImm()) { 9510b57cec5SDimitry Andric // The immediate is encoded as 'immediate << 2'. 9520b57cec5SDimitry Andric unsigned Res = getMachineOpValue(MI, MO, Fixups, STI); 9530b57cec5SDimitry Andric assert((Res & 3) == 0); 9540b57cec5SDimitry Andric return Res >> 2; 9550b57cec5SDimitry Andric } 9560b57cec5SDimitry Andric 9570b57cec5SDimitry Andric assert(MO.isExpr() && 9580b57cec5SDimitry Andric "getSimm19Lsl2Encoding expects only expressions or an immediate"); 9590b57cec5SDimitry Andric 9600b57cec5SDimitry Andric const MCExpr *Expr = MO.getExpr(); 9610b57cec5SDimitry Andric Mips::Fixups FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_PC19_S2 9620b57cec5SDimitry Andric : Mips::fixup_MIPS_PC19_S2; 9630b57cec5SDimitry Andric Fixups.push_back(MCFixup::create(0, Expr, MCFixupKind(FixupKind))); 9640b57cec5SDimitry Andric return 0; 9650b57cec5SDimitry Andric } 9660b57cec5SDimitry Andric 9670b57cec5SDimitry Andric unsigned 9680b57cec5SDimitry Andric MipsMCCodeEmitter::getSimm18Lsl3Encoding(const MCInst &MI, unsigned OpNo, 9690b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 9700b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 9710b57cec5SDimitry Andric const MCOperand &MO = MI.getOperand(OpNo); 9720b57cec5SDimitry Andric if (MO.isImm()) { 9730b57cec5SDimitry Andric // The immediate is encoded as 'immediate << 3'. 9740b57cec5SDimitry Andric unsigned Res = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI); 9750b57cec5SDimitry Andric assert((Res & 7) == 0); 9760b57cec5SDimitry Andric return Res >> 3; 9770b57cec5SDimitry Andric } 9780b57cec5SDimitry Andric 9790b57cec5SDimitry Andric assert(MO.isExpr() && 9800b57cec5SDimitry Andric "getSimm18Lsl2Encoding expects only expressions or an immediate"); 9810b57cec5SDimitry Andric 9820b57cec5SDimitry Andric const MCExpr *Expr = MO.getExpr(); 9830b57cec5SDimitry Andric Mips::Fixups FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_PC18_S3 9840b57cec5SDimitry Andric : Mips::fixup_MIPS_PC18_S3; 9850b57cec5SDimitry Andric Fixups.push_back(MCFixup::create(0, Expr, MCFixupKind(FixupKind))); 9860b57cec5SDimitry Andric return 0; 9870b57cec5SDimitry Andric } 9880b57cec5SDimitry Andric 9890b57cec5SDimitry Andric unsigned 9900b57cec5SDimitry Andric MipsMCCodeEmitter::getUImm3Mod8Encoding(const MCInst &MI, unsigned OpNo, 9910b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 9920b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 9930b57cec5SDimitry Andric assert(MI.getOperand(OpNo).isImm()); 9940b57cec5SDimitry Andric const MCOperand &MO = MI.getOperand(OpNo); 9950b57cec5SDimitry Andric return MO.getImm() % 8; 9960b57cec5SDimitry Andric } 9970b57cec5SDimitry Andric 9980b57cec5SDimitry Andric unsigned 9990b57cec5SDimitry Andric MipsMCCodeEmitter::getUImm4AndValue(const MCInst &MI, unsigned OpNo, 10000b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 10010b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 10020b57cec5SDimitry Andric assert(MI.getOperand(OpNo).isImm()); 10030b57cec5SDimitry Andric const MCOperand &MO = MI.getOperand(OpNo); 10040b57cec5SDimitry Andric unsigned Value = MO.getImm(); 10050b57cec5SDimitry Andric switch (Value) { 10060b57cec5SDimitry Andric case 128: return 0x0; 10070b57cec5SDimitry Andric case 1: return 0x1; 10080b57cec5SDimitry Andric case 2: return 0x2; 10090b57cec5SDimitry Andric case 3: return 0x3; 10100b57cec5SDimitry Andric case 4: return 0x4; 10110b57cec5SDimitry Andric case 7: return 0x5; 10120b57cec5SDimitry Andric case 8: return 0x6; 10130b57cec5SDimitry Andric case 15: return 0x7; 10140b57cec5SDimitry Andric case 16: return 0x8; 10150b57cec5SDimitry Andric case 31: return 0x9; 10160b57cec5SDimitry Andric case 32: return 0xa; 10170b57cec5SDimitry Andric case 63: return 0xb; 10180b57cec5SDimitry Andric case 64: return 0xc; 10190b57cec5SDimitry Andric case 255: return 0xd; 10200b57cec5SDimitry Andric case 32768: return 0xe; 10210b57cec5SDimitry Andric case 65535: return 0xf; 10220b57cec5SDimitry Andric } 10230b57cec5SDimitry Andric llvm_unreachable("Unexpected value"); 10240b57cec5SDimitry Andric } 10250b57cec5SDimitry Andric 10260b57cec5SDimitry Andric unsigned 10270b57cec5SDimitry Andric MipsMCCodeEmitter::getRegisterListOpValue(const MCInst &MI, unsigned OpNo, 10280b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 10290b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 10300b57cec5SDimitry Andric unsigned res = 0; 10310b57cec5SDimitry Andric 10320b57cec5SDimitry Andric // Register list operand is always first operand of instruction and it is 10330b57cec5SDimitry Andric // placed before memory operand (register + imm). 10340b57cec5SDimitry Andric 10350b57cec5SDimitry Andric for (unsigned I = OpNo, E = MI.getNumOperands() - 2; I < E; ++I) { 10360b57cec5SDimitry Andric unsigned Reg = MI.getOperand(I).getReg(); 10370b57cec5SDimitry Andric unsigned RegNo = Ctx.getRegisterInfo()->getEncodingValue(Reg); 10380b57cec5SDimitry Andric if (RegNo != 31) 10390b57cec5SDimitry Andric res++; 10400b57cec5SDimitry Andric else 10410b57cec5SDimitry Andric res |= 0x10; 10420b57cec5SDimitry Andric } 10430b57cec5SDimitry Andric return res; 10440b57cec5SDimitry Andric } 10450b57cec5SDimitry Andric 10460b57cec5SDimitry Andric unsigned 10470b57cec5SDimitry Andric MipsMCCodeEmitter::getRegisterListOpValue16(const MCInst &MI, unsigned OpNo, 10480b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 10490b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 10500b57cec5SDimitry Andric return (MI.getNumOperands() - 4); 10510b57cec5SDimitry Andric } 10520b57cec5SDimitry Andric 10530b57cec5SDimitry Andric unsigned 10540b57cec5SDimitry Andric MipsMCCodeEmitter::getMovePRegPairOpValue(const MCInst &MI, unsigned OpNo, 10550b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 10560b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 10570b57cec5SDimitry Andric unsigned res = 0; 10580b57cec5SDimitry Andric 10590b57cec5SDimitry Andric if (MI.getOperand(0).getReg() == Mips::A1 && 10600b57cec5SDimitry Andric MI.getOperand(1).getReg() == Mips::A2) 10610b57cec5SDimitry Andric res = 0; 10620b57cec5SDimitry Andric else if (MI.getOperand(0).getReg() == Mips::A1 && 10630b57cec5SDimitry Andric MI.getOperand(1).getReg() == Mips::A3) 10640b57cec5SDimitry Andric res = 1; 10650b57cec5SDimitry Andric else if (MI.getOperand(0).getReg() == Mips::A2 && 10660b57cec5SDimitry Andric MI.getOperand(1).getReg() == Mips::A3) 10670b57cec5SDimitry Andric res = 2; 10680b57cec5SDimitry Andric else if (MI.getOperand(0).getReg() == Mips::A0 && 10690b57cec5SDimitry Andric MI.getOperand(1).getReg() == Mips::S5) 10700b57cec5SDimitry Andric res = 3; 10710b57cec5SDimitry Andric else if (MI.getOperand(0).getReg() == Mips::A0 && 10720b57cec5SDimitry Andric MI.getOperand(1).getReg() == Mips::S6) 10730b57cec5SDimitry Andric res = 4; 10740b57cec5SDimitry Andric else if (MI.getOperand(0).getReg() == Mips::A0 && 10750b57cec5SDimitry Andric MI.getOperand(1).getReg() == Mips::A1) 10760b57cec5SDimitry Andric res = 5; 10770b57cec5SDimitry Andric else if (MI.getOperand(0).getReg() == Mips::A0 && 10780b57cec5SDimitry Andric MI.getOperand(1).getReg() == Mips::A2) 10790b57cec5SDimitry Andric res = 6; 10800b57cec5SDimitry Andric else if (MI.getOperand(0).getReg() == Mips::A0 && 10810b57cec5SDimitry Andric MI.getOperand(1).getReg() == Mips::A3) 10820b57cec5SDimitry Andric res = 7; 10830b57cec5SDimitry Andric 10840b57cec5SDimitry Andric return res; 10850b57cec5SDimitry Andric } 10860b57cec5SDimitry Andric 10870b57cec5SDimitry Andric unsigned 10880b57cec5SDimitry Andric MipsMCCodeEmitter::getMovePRegSingleOpValue(const MCInst &MI, unsigned OpNo, 10890b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 10900b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 10910b57cec5SDimitry Andric assert(((OpNo == 2) || (OpNo == 3)) && 10920b57cec5SDimitry Andric "Unexpected OpNo for movep operand encoding!"); 10930b57cec5SDimitry Andric 10940b57cec5SDimitry Andric MCOperand Op = MI.getOperand(OpNo); 10950b57cec5SDimitry Andric assert(Op.isReg() && "Operand of movep is not a register!"); 10960b57cec5SDimitry Andric switch (Op.getReg()) { 10970b57cec5SDimitry Andric default: 10980b57cec5SDimitry Andric llvm_unreachable("Unknown register for movep!"); 10990b57cec5SDimitry Andric case Mips::ZERO: return 0; 11000b57cec5SDimitry Andric case Mips::S1: return 1; 11010b57cec5SDimitry Andric case Mips::V0: return 2; 11020b57cec5SDimitry Andric case Mips::V1: return 3; 11030b57cec5SDimitry Andric case Mips::S0: return 4; 11040b57cec5SDimitry Andric case Mips::S2: return 5; 11050b57cec5SDimitry Andric case Mips::S3: return 6; 11060b57cec5SDimitry Andric case Mips::S4: return 7; 11070b57cec5SDimitry Andric } 11080b57cec5SDimitry Andric } 11090b57cec5SDimitry Andric 11100b57cec5SDimitry Andric unsigned 11110b57cec5SDimitry Andric MipsMCCodeEmitter::getSimm23Lsl2Encoding(const MCInst &MI, unsigned OpNo, 11120b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 11130b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 11140b57cec5SDimitry Andric const MCOperand &MO = MI.getOperand(OpNo); 11150b57cec5SDimitry Andric assert(MO.isImm() && "getSimm23Lsl2Encoding expects only an immediate"); 11160b57cec5SDimitry Andric // The immediate is encoded as 'immediate >> 2'. 11170b57cec5SDimitry Andric unsigned Res = static_cast<unsigned>(MO.getImm()); 11180b57cec5SDimitry Andric assert((Res & 3) == 0); 11190b57cec5SDimitry Andric return Res >> 2; 11200b57cec5SDimitry Andric } 11210b57cec5SDimitry Andric 11220b57cec5SDimitry Andric #include "MipsGenMCCodeEmitter.inc" 1123