xref: /freebsd/contrib/llvm-project/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
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