19f610119SJia Liu //===-- MipsMCCodeEmitter.cpp - Convert Mips Code to Machine Code ---------===//
2750ecec7SAkira Hatanaka //
3750ecec7SAkira Hatanaka //                     The LLVM Compiler Infrastructure
4750ecec7SAkira Hatanaka //
5750ecec7SAkira Hatanaka // This file is distributed under the University of Illinois Open Source
6750ecec7SAkira Hatanaka // License. See LICENSE.TXT for details.
7750ecec7SAkira Hatanaka //
8750ecec7SAkira Hatanaka //===----------------------------------------------------------------------===//
9750ecec7SAkira Hatanaka //
10750ecec7SAkira Hatanaka // This file implements the MipsMCCodeEmitter class.
11750ecec7SAkira Hatanaka //
12750ecec7SAkira Hatanaka //===----------------------------------------------------------------------===//
139e1450bcSMatheus Almeida 
14c85e3ff3SBruno Cardoso Lopes #include "MCTargetDesc/MipsFixupKinds.h"
15a5da588bSPetar Jovanovic #include "MCTargetDesc/MipsMCExpr.h"
16c85e3ff3SBruno Cardoso Lopes #include "MCTargetDesc/MipsMCTargetDesc.h"
17*926883e1SEugene Zelenko #include "MipsMCCodeEmitter.h"
18c85e3ff3SBruno Cardoso Lopes #include "llvm/ADT/APFloat.h"
19*926883e1SEugene Zelenko #include "llvm/ADT/APInt.h"
209e1450bcSMatheus Almeida #include "llvm/ADT/SmallVector.h"
215d6faed1SAkira Hatanaka #include "llvm/MC/MCContext.h"
22750ecec7SAkira Hatanaka #include "llvm/MC/MCExpr.h"
23d9903888SChandler Carruth #include "llvm/MC/MCFixup.h"
24750ecec7SAkira Hatanaka #include "llvm/MC/MCInst.h"
25*926883e1SEugene Zelenko #include "llvm/MC/MCInstrDesc.h"
26750ecec7SAkira Hatanaka #include "llvm/MC/MCInstrInfo.h"
273de83e40SPete Cooper #include "llvm/MC/MCRegisterInfo.h"
28750ecec7SAkira Hatanaka #include "llvm/MC/MCSubtargetInfo.h"
29*926883e1SEugene Zelenko #include "llvm/Support/Casting.h"
30*926883e1SEugene Zelenko #include "llvm/Support/ErrorHandling.h"
31750ecec7SAkira Hatanaka #include "llvm/Support/raw_ostream.h"
32*926883e1SEugene Zelenko #include <cassert>
33*926883e1SEugene Zelenko #include <cstdint>
34*926883e1SEugene Zelenko 
35*926883e1SEugene Zelenko using namespace llvm;
36750ecec7SAkira Hatanaka 
3784e68b29SChandler Carruth #define DEBUG_TYPE "mccodeemitter"
3884e68b29SChandler Carruth 
39be6a818fSAkira Hatanaka #define GET_INSTRMAP_INFO
40be6a818fSAkira Hatanaka #include "MipsGenInstrInfo.inc"
419e1450bcSMatheus Almeida #undef GET_INSTRMAP_INFO
42be6a818fSAkira Hatanaka 
439e1450bcSMatheus Almeida namespace llvm {
44*926883e1SEugene Zelenko 
459e1450bcSMatheus Almeida MCCodeEmitter *createMipsMCCodeEmitterEB(const MCInstrInfo &MCII,
46c3b04279SJim Grosbach                                          const MCRegisterInfo &MRI,
479e1450bcSMatheus Almeida                                          MCContext &Ctx) {
48d2cca113SDavid Woodhouse   return new MipsMCCodeEmitter(MCII, Ctx, false);
491ee768dbSAkira Hatanaka }
501ee768dbSAkira Hatanaka 
519e1450bcSMatheus Almeida MCCodeEmitter *createMipsMCCodeEmitterEL(const MCInstrInfo &MCII,
52c3b04279SJim Grosbach                                          const MCRegisterInfo &MRI,
539e1450bcSMatheus Almeida                                          MCContext &Ctx) {
54d2cca113SDavid Woodhouse   return new MipsMCCodeEmitter(MCII, Ctx, true);
55750ecec7SAkira Hatanaka }
56*926883e1SEugene Zelenko 
57*926883e1SEugene Zelenko } // end namespace llvm
58f30f2cceSRafael Espindola 
59f30f2cceSRafael Espindola // If the D<shift> instruction has a shift amount that is greater
60f30f2cceSRafael Espindola // than 31 (checked in calling routine), lower it to a D<shift>32 instruction
61f30f2cceSRafael Espindola static void LowerLargeShift(MCInst& Inst) {
62f30f2cceSRafael Espindola   assert(Inst.getNumOperands() == 3 && "Invalid no. of operands for shift!");
63f30f2cceSRafael Espindola   assert(Inst.getOperand(2).isImm());
64f30f2cceSRafael Espindola 
65f30f2cceSRafael Espindola   int64_t Shift = Inst.getOperand(2).getImm();
66f30f2cceSRafael Espindola   if (Shift <= 31)
67f30f2cceSRafael Espindola     return; // Do nothing
68f30f2cceSRafael Espindola   Shift -= 32;
69f30f2cceSRafael Espindola 
70f30f2cceSRafael Espindola   // saminus32
71f30f2cceSRafael Espindola   Inst.getOperand(2).setImm(Shift);
72f30f2cceSRafael Espindola 
73f30f2cceSRafael Espindola   switch (Inst.getOpcode()) {
74f30f2cceSRafael Espindola   default:
75f30f2cceSRafael Espindola     // Calling function is not synchronized
76f30f2cceSRafael Espindola     llvm_unreachable("Unexpected shift instruction");
77f30f2cceSRafael Espindola   case Mips::DSLL:
78f30f2cceSRafael Espindola     Inst.setOpcode(Mips::DSLL32);
79f30f2cceSRafael Espindola     return;
80f30f2cceSRafael Espindola   case Mips::DSRL:
81f30f2cceSRafael Espindola     Inst.setOpcode(Mips::DSRL32);
82f30f2cceSRafael Espindola     return;
83f30f2cceSRafael Espindola   case Mips::DSRA:
84f30f2cceSRafael Espindola     Inst.setOpcode(Mips::DSRA32);
85f30f2cceSRafael Espindola     return;
866a3fe574SAkira Hatanaka   case Mips::DROTR:
876a3fe574SAkira Hatanaka     Inst.setOpcode(Mips::DROTR32);
886a3fe574SAkira Hatanaka     return;
89f1e0a03dSHrvoje Varga   case Mips::DSLL_MM64R6:
90f1e0a03dSHrvoje Varga     Inst.setOpcode(Mips::DSLL32_MM64R6);
91f1e0a03dSHrvoje Varga     return;
9224b975dcSHrvoje Varga   case Mips::DSRL_MM64R6:
9324b975dcSHrvoje Varga     Inst.setOpcode(Mips::DSRL32_MM64R6);
9424b975dcSHrvoje Varga     return;
95f1e0a03dSHrvoje Varga   case Mips::DSRA_MM64R6:
96f1e0a03dSHrvoje Varga     Inst.setOpcode(Mips::DSRA32_MM64R6);
97f1e0a03dSHrvoje Varga     return;
98f1e0a03dSHrvoje Varga   case Mips::DROTR_MM64R6:
99f1e0a03dSHrvoje Varga     Inst.setOpcode(Mips::DROTR32_MM64R6);
100f1e0a03dSHrvoje Varga     return;
101f30f2cceSRafael Espindola   }
102f30f2cceSRafael Espindola }
103f30f2cceSRafael Espindola 
104611eb829SDaniel Sanders // Pick a DINS instruction variant based on the pos and size operands
105611eb829SDaniel Sanders static void LowerDins(MCInst& InstIn) {
106f30f2cceSRafael Espindola   assert(InstIn.getNumOperands() == 5 &&
107f30f2cceSRafael Espindola          "Invalid no. of machine operands for DINS!");
108f30f2cceSRafael Espindola 
109f30f2cceSRafael Espindola   assert(InstIn.getOperand(2).isImm());
110f30f2cceSRafael Espindola   int64_t pos = InstIn.getOperand(2).getImm();
111f30f2cceSRafael Espindola   assert(InstIn.getOperand(3).isImm());
112f30f2cceSRafael Espindola   int64_t size = InstIn.getOperand(3).getImm();
113f30f2cceSRafael Espindola 
114f30f2cceSRafael Espindola   if (size <= 32) {
115611eb829SDaniel Sanders     if (pos < 32)  // DINS, do nothing
116f30f2cceSRafael Espindola       return;
117611eb829SDaniel Sanders     // DINSU
118f30f2cceSRafael Espindola     InstIn.getOperand(2).setImm(pos - 32);
119611eb829SDaniel Sanders     InstIn.setOpcode(Mips::DINSU);
120f30f2cceSRafael Espindola     return;
121f30f2cceSRafael Espindola   }
122611eb829SDaniel Sanders   // DINSM
123611eb829SDaniel Sanders   assert(pos < 32 && "DINS cannot have both size and pos > 32");
124f30f2cceSRafael Espindola   InstIn.getOperand(3).setImm(size - 32);
125611eb829SDaniel Sanders   InstIn.setOpcode(Mips::DINSM);
126f30f2cceSRafael Espindola }
127f30f2cceSRafael Espindola 
128669d8dd8SSimon Dardis // Fix a bad compact branch encoding for beqc/bnec.
129669d8dd8SSimon Dardis void MipsMCCodeEmitter::LowerCompactBranch(MCInst& Inst) const {
130669d8dd8SSimon Dardis   // Encoding may be illegal !(rs < rt), but this situation is
131669d8dd8SSimon Dardis   // easily fixed.
132669d8dd8SSimon Dardis   unsigned RegOp0 = Inst.getOperand(0).getReg();
133669d8dd8SSimon Dardis   unsigned RegOp1 = Inst.getOperand(1).getReg();
134669d8dd8SSimon Dardis 
135669d8dd8SSimon Dardis   unsigned Reg0 =  Ctx.getRegisterInfo()->getEncodingValue(RegOp0);
136669d8dd8SSimon Dardis   unsigned Reg1 =  Ctx.getRegisterInfo()->getEncodingValue(RegOp1);
137669d8dd8SSimon Dardis 
13868a204ddSSimon Dardis   if (Inst.getOpcode() == Mips::BNEC || Inst.getOpcode() == Mips::BEQC ||
13968a204ddSSimon Dardis       Inst.getOpcode() == Mips::BNEC64 || Inst.getOpcode() == Mips::BEQC64) {
140669d8dd8SSimon Dardis     assert(Reg0 != Reg1 && "Instruction has bad operands ($rs == $rt)!");
141669d8dd8SSimon Dardis     if (Reg0 < Reg1)
142669d8dd8SSimon Dardis       return;
143b60833c0SSimon Dardis   } else if (Inst.getOpcode() == Mips::BNVC || Inst.getOpcode() == Mips::BOVC) {
144b60833c0SSimon Dardis     if (Reg0 >= Reg1)
145b60833c0SSimon Dardis       return;
146c962c493SHrvoje Varga   } else if (Inst.getOpcode() == Mips::BNVC_MMR6 ||
147c962c493SHrvoje Varga              Inst.getOpcode() == Mips::BOVC_MMR6) {
148c962c493SHrvoje Varga     if (Reg1 >= Reg0)
149c962c493SHrvoje Varga       return;
150b60833c0SSimon Dardis   } else
151b60833c0SSimon Dardis     llvm_unreachable("Cannot rewrite unknown branch!");
152669d8dd8SSimon Dardis 
153669d8dd8SSimon Dardis   Inst.getOperand(0).setReg(RegOp1);
154669d8dd8SSimon Dardis   Inst.getOperand(1).setReg(RegOp0);
155669d8dd8SSimon Dardis }
156669d8dd8SSimon Dardis 
1579e1450bcSMatheus Almeida bool MipsMCCodeEmitter::isMicroMips(const MCSubtargetInfo &STI) const {
158db0712f9SMichael Kuperstein   return STI.getFeatureBits()[Mips::FeatureMicroMips];
1599e1450bcSMatheus Almeida }
1609e1450bcSMatheus Almeida 
161c22555d9SJozef Kolek bool MipsMCCodeEmitter::isMips32r6(const MCSubtargetInfo &STI) const {
162db0712f9SMichael Kuperstein   return STI.getFeatureBits()[Mips::FeatureMips32r6];
163c22555d9SJozef Kolek }
164c22555d9SJozef Kolek 
1659e1450bcSMatheus Almeida void MipsMCCodeEmitter::EmitByte(unsigned char C, raw_ostream &OS) const {
1669e1450bcSMatheus Almeida   OS << (char)C;
1679e1450bcSMatheus Almeida }
1689e1450bcSMatheus Almeida 
1699e1450bcSMatheus Almeida void MipsMCCodeEmitter::EmitInstruction(uint64_t Val, unsigned Size,
1709e1450bcSMatheus Almeida                                         const MCSubtargetInfo &STI,
1719e1450bcSMatheus Almeida                                         raw_ostream &OS) const {
1729e1450bcSMatheus Almeida   // Output the instruction encoding in little endian byte order.
1739e1450bcSMatheus Almeida   // Little-endian byte ordering:
1749e1450bcSMatheus Almeida   //   mips32r2:   4 | 3 | 2 | 1
1759e1450bcSMatheus Almeida   //   microMIPS:  2 | 1 | 4 | 3
1769e1450bcSMatheus Almeida   if (IsLittleEndian && Size == 4 && isMicroMips(STI)) {
1779e1450bcSMatheus Almeida     EmitInstruction(Val >> 16, 2, STI, OS);
1789e1450bcSMatheus Almeida     EmitInstruction(Val, 2, STI, OS);
1799e1450bcSMatheus Almeida   } else {
1809e1450bcSMatheus Almeida     for (unsigned i = 0; i < Size; ++i) {
1819e1450bcSMatheus Almeida       unsigned Shift = IsLittleEndian ? i * 8 : (Size - 1 - i) * 8;
1829e1450bcSMatheus Almeida       EmitByte((Val >> Shift) & 0xff, OS);
1839e1450bcSMatheus Almeida     }
1849e1450bcSMatheus Almeida   }
1859e1450bcSMatheus Almeida }
1869e1450bcSMatheus Almeida 
18791df21f7SJim Grosbach /// encodeInstruction - Emit the instruction.
1884e07b95dSJack Carter /// Size the instruction with Desc.getSize().
189c85e3ff3SBruno Cardoso Lopes void MipsMCCodeEmitter::
19091df21f7SJim Grosbach encodeInstruction(const MCInst &MI, raw_ostream &OS,
1919784cef3SDavid Woodhouse                   SmallVectorImpl<MCFixup> &Fixups,
1929784cef3SDavid Woodhouse                   const MCSubtargetInfo &STI) const
193c85e3ff3SBruno Cardoso Lopes {
194aa7aeaa0SJack Carter   // Non-pseudo instructions that get changed for direct object
195aa7aeaa0SJack Carter   // only based on operand values.
196aa7aeaa0SJack Carter   // If this list of instructions get much longer we will move
197aa7aeaa0SJack Carter   // the check to a function call. Until then, this is more efficient.
198aa7aeaa0SJack Carter   MCInst TmpInst = MI;
199aa7aeaa0SJack Carter   switch (MI.getOpcode()) {
200aa7aeaa0SJack Carter   // If shift amount is >= 32 it the inst needs to be lowered further
201aa7aeaa0SJack Carter   case Mips::DSLL:
202aa7aeaa0SJack Carter   case Mips::DSRL:
203aa7aeaa0SJack Carter   case Mips::DSRA:
2046a3fe574SAkira Hatanaka   case Mips::DROTR:
205f1e0a03dSHrvoje Varga   case Mips::DSLL_MM64R6:
20624b975dcSHrvoje Varga   case Mips::DSRL_MM64R6:
207f1e0a03dSHrvoje Varga   case Mips::DSRA_MM64R6:
208f1e0a03dSHrvoje Varga   case Mips::DROTR_MM64R6:
209f30f2cceSRafael Espindola     LowerLargeShift(TmpInst);
210aa7aeaa0SJack Carter     break;
211aa7aeaa0SJack Carter     // Double extract instruction is chosen by pos and size operands
212aa7aeaa0SJack Carter   case Mips::DINS:
213611eb829SDaniel Sanders     LowerDins(TmpInst);
214669d8dd8SSimon Dardis     break;
215b60833c0SSimon Dardis   // Compact branches, enforce encoding restrictions.
216669d8dd8SSimon Dardis   case Mips::BEQC:
217669d8dd8SSimon Dardis   case Mips::BNEC:
21868a204ddSSimon Dardis   case Mips::BEQC64:
21968a204ddSSimon Dardis   case Mips::BNEC64:
220b60833c0SSimon Dardis   case Mips::BOVC:
221c962c493SHrvoje Varga   case Mips::BOVC_MMR6:
222b60833c0SSimon Dardis   case Mips::BNVC:
223c962c493SHrvoje Varga   case Mips::BNVC_MMR6:
224669d8dd8SSimon Dardis     LowerCompactBranch(TmpInst);
225aa7aeaa0SJack Carter   }
226aa7aeaa0SJack Carter 
22797700977SJack Carter   unsigned long N = Fixups.size();
2283fa98a65SDavid Woodhouse   uint32_t Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);
229c85e3ff3SBruno Cardoso Lopes 
230c85e3ff3SBruno Cardoso Lopes   // Check for unimplemented opcodes.
231aa7aeaa0SJack Carter   // Unfortunately in MIPS both NOP and SLL will come in with Binary == 0
232c85e3ff3SBruno Cardoso Lopes   // so we have to special check for them.
233aa7aeaa0SJack Carter   unsigned Opcode = TmpInst.getOpcode();
234c7e220f6SJozef Kolek   if ((Opcode != Mips::NOP) && (Opcode != Mips::SLL) &&
235c7e220f6SJozef Kolek       (Opcode != Mips::SLL_MM) && !Binary)
23691df21f7SJim Grosbach     llvm_unreachable("unimplemented opcode in encodeInstruction()");
237c85e3ff3SBruno Cardoso Lopes 
238b59a5419SZoran Jovanovic   int NewOpcode = -1;
2396ca13eafSJozef Kolek   if (isMicroMips(STI)) {
240b59a5419SZoran Jovanovic     if (isMips32r6(STI)) {
241b59a5419SZoran Jovanovic       NewOpcode = Mips::MipsR62MicroMipsR6(Opcode, Mips::Arch_micromipsr6);
242b59a5419SZoran Jovanovic       if (NewOpcode == -1)
243b59a5419SZoran Jovanovic         NewOpcode = Mips::Std2MicroMipsR6(Opcode, Mips::Arch_micromipsr6);
244b59a5419SZoran Jovanovic     }
245b59a5419SZoran Jovanovic     else
246b59a5419SZoran Jovanovic       NewOpcode = Mips::Std2MicroMips(Opcode, Mips::Arch_micromips);
247b59a5419SZoran Jovanovic 
2482e386d3dSZoran Jovanovic     // Check whether it is Dsp instruction.
2492e386d3dSZoran Jovanovic     if (NewOpcode == -1)
2502e386d3dSZoran Jovanovic       NewOpcode = Mips::Dsp2MicroMips(Opcode, Mips::Arch_mmdsp);
2512e386d3dSZoran Jovanovic 
252be6a818fSAkira Hatanaka     if (NewOpcode != -1) {
25397700977SJack Carter       if (Fixups.size() > N)
25497700977SJack Carter         Fixups.pop_back();
255b59a5419SZoran Jovanovic 
256be6a818fSAkira Hatanaka       Opcode = NewOpcode;
257be6a818fSAkira Hatanaka       TmpInst.setOpcode (NewOpcode);
2583fa98a65SDavid Woodhouse       Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);
259be6a818fSAkira Hatanaka     }
260be6a818fSAkira Hatanaka   }
261be6a818fSAkira Hatanaka 
262aa7aeaa0SJack Carter   const MCInstrDesc &Desc = MCII.get(TmpInst.getOpcode());
263c85e3ff3SBruno Cardoso Lopes 
2645b5559d3SJack Carter   // Get byte count of instruction
2655b5559d3SJack Carter   unsigned Size = Desc.getSize();
2665b5559d3SJack Carter   if (!Size)
2675b5559d3SJack Carter     llvm_unreachable("Desc.getSize() returns 0");
268c85e3ff3SBruno Cardoso Lopes 
269d2cca113SDavid Woodhouse   EmitInstruction(Binary, Size, STI, OS);
270c85e3ff3SBruno Cardoso Lopes }
271c85e3ff3SBruno Cardoso Lopes 
272c85e3ff3SBruno Cardoso Lopes /// getBranchTargetOpValue - Return binary encoding of the branch
273c85e3ff3SBruno Cardoso Lopes /// target operand. If the machine operand requires relocation,
274c85e3ff3SBruno Cardoso Lopes /// record the relocation and return zero.
275c85e3ff3SBruno Cardoso Lopes unsigned MipsMCCodeEmitter::
276c85e3ff3SBruno Cardoso Lopes getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
2773fa98a65SDavid Woodhouse                        SmallVectorImpl<MCFixup> &Fixups,
2783fa98a65SDavid Woodhouse                        const MCSubtargetInfo &STI) const {
279c85e3ff3SBruno Cardoso Lopes   const MCOperand &MO = MI.getOperand(OpNo);
28071e6a749SJack Carter 
2814f69a0f2SJack Carter   // If the destination is an immediate, divide by 4.
2824f69a0f2SJack Carter   if (MO.isImm()) return MO.getImm() >> 2;
2834f69a0f2SJack Carter 
28471e6a749SJack Carter   assert(MO.isExpr() &&
28571e6a749SJack Carter          "getBranchTargetOpValue expects only expressions or immediates");
286c85e3ff3SBruno Cardoso Lopes 
287b7915a1fSPetar Jovanovic   const MCExpr *FixupExpression = MCBinaryExpr::createAdd(
288b7915a1fSPetar Jovanovic       MO.getExpr(), MCConstantExpr::create(-4, Ctx), Ctx);
289b7915a1fSPetar Jovanovic   Fixups.push_back(MCFixup::create(0, FixupExpression,
290c85e3ff3SBruno Cardoso Lopes                                    MCFixupKind(Mips::fixup_Mips_PC16)));
291c85e3ff3SBruno Cardoso Lopes   return 0;
292c85e3ff3SBruno Cardoso Lopes }
293c85e3ff3SBruno Cardoso Lopes 
2946f09cdfdSHrvoje Varga /// getBranchTargetOpValue1SImm16 - Return binary encoding of the branch
2956f09cdfdSHrvoje Varga /// target operand. If the machine operand requires relocation,
2966f09cdfdSHrvoje Varga /// record the relocation and return zero.
2976f09cdfdSHrvoje Varga unsigned MipsMCCodeEmitter::
2986f09cdfdSHrvoje Varga getBranchTargetOpValue1SImm16(const MCInst &MI, unsigned OpNo,
2996f09cdfdSHrvoje Varga                               SmallVectorImpl<MCFixup> &Fixups,
3006f09cdfdSHrvoje Varga                               const MCSubtargetInfo &STI) const {
3016f09cdfdSHrvoje Varga   const MCOperand &MO = MI.getOperand(OpNo);
3026f09cdfdSHrvoje Varga 
3036f09cdfdSHrvoje Varga   // If the destination is an immediate, divide by 2.
3046f09cdfdSHrvoje Varga   if (MO.isImm()) return MO.getImm() >> 1;
3056f09cdfdSHrvoje Varga 
3066f09cdfdSHrvoje Varga   assert(MO.isExpr() &&
3076f09cdfdSHrvoje Varga          "getBranchTargetOpValue expects only expressions or immediates");
3086f09cdfdSHrvoje Varga 
3096f09cdfdSHrvoje Varga   const MCExpr *FixupExpression = MCBinaryExpr::createAdd(
3106f09cdfdSHrvoje Varga       MO.getExpr(), MCConstantExpr::create(-4, Ctx), Ctx);
3116f09cdfdSHrvoje Varga   Fixups.push_back(MCFixup::create(0, FixupExpression,
3126f09cdfdSHrvoje Varga                                    MCFixupKind(Mips::fixup_Mips_PC16)));
3136f09cdfdSHrvoje Varga   return 0;
3146f09cdfdSHrvoje Varga }
3156f09cdfdSHrvoje Varga 
316c962c493SHrvoje Varga /// getBranchTargetOpValueMMR6 - Return binary encoding of the branch
317c962c493SHrvoje Varga /// target operand. If the machine operand requires relocation,
318c962c493SHrvoje Varga /// record the relocation and return zero.
319c962c493SHrvoje Varga unsigned MipsMCCodeEmitter::
320c962c493SHrvoje Varga getBranchTargetOpValueMMR6(const MCInst &MI, unsigned OpNo,
321c962c493SHrvoje Varga                            SmallVectorImpl<MCFixup> &Fixups,
322c962c493SHrvoje Varga                            const MCSubtargetInfo &STI) const {
323c962c493SHrvoje Varga   const MCOperand &MO = MI.getOperand(OpNo);
324c962c493SHrvoje Varga 
325c962c493SHrvoje Varga   // If the destination is an immediate, divide by 2.
326c962c493SHrvoje Varga   if (MO.isImm())
327c962c493SHrvoje Varga     return MO.getImm() >> 1;
328c962c493SHrvoje Varga 
329c962c493SHrvoje Varga   assert(MO.isExpr() &&
330c962c493SHrvoje Varga          "getBranchTargetOpValueMMR6 expects only expressions or immediates");
331c962c493SHrvoje Varga 
332c962c493SHrvoje Varga   const MCExpr *FixupExpression = MCBinaryExpr::createAdd(
333c962c493SHrvoje Varga       MO.getExpr(), MCConstantExpr::create(-2, Ctx), Ctx);
334c962c493SHrvoje Varga   Fixups.push_back(MCFixup::create(0, FixupExpression,
335c962c493SHrvoje Varga                                    MCFixupKind(Mips::fixup_Mips_PC16)));
336c962c493SHrvoje Varga   return 0;
337c962c493SHrvoje Varga }
338c962c493SHrvoje Varga 
339f0ed16eaSHrvoje Varga /// getBranchTargetOpValueLsl2MMR6 - Return binary encoding of the branch
340f0ed16eaSHrvoje Varga /// target operand. If the machine operand requires relocation,
341f0ed16eaSHrvoje Varga /// record the relocation and return zero.
342f0ed16eaSHrvoje Varga unsigned MipsMCCodeEmitter::
343f0ed16eaSHrvoje Varga getBranchTargetOpValueLsl2MMR6(const MCInst &MI, unsigned OpNo,
344f0ed16eaSHrvoje Varga                                SmallVectorImpl<MCFixup> &Fixups,
345f0ed16eaSHrvoje Varga                                const MCSubtargetInfo &STI) const {
346f0ed16eaSHrvoje Varga   const MCOperand &MO = MI.getOperand(OpNo);
347f0ed16eaSHrvoje Varga 
348f0ed16eaSHrvoje Varga   // If the destination is an immediate, divide by 4.
349f0ed16eaSHrvoje Varga   if (MO.isImm())
350f0ed16eaSHrvoje Varga     return MO.getImm() >> 2;
351f0ed16eaSHrvoje Varga 
352f0ed16eaSHrvoje Varga   assert(MO.isExpr() &&
353f0ed16eaSHrvoje Varga          "getBranchTargetOpValueLsl2MMR6 expects only expressions or immediates");
354f0ed16eaSHrvoje Varga 
355f0ed16eaSHrvoje Varga   const MCExpr *FixupExpression = MCBinaryExpr::createAdd(
356f0ed16eaSHrvoje Varga       MO.getExpr(), MCConstantExpr::create(-4, Ctx), Ctx);
357f0ed16eaSHrvoje Varga   Fixups.push_back(MCFixup::create(0, FixupExpression,
358f0ed16eaSHrvoje Varga                                    MCFixupKind(Mips::fixup_Mips_PC16)));
359f0ed16eaSHrvoje Varga   return 0;
360f0ed16eaSHrvoje Varga }
361f0ed16eaSHrvoje Varga 
3629761e96bSJozef Kolek /// getBranchTarget7OpValueMM - Return binary encoding of the microMIPS branch
3639761e96bSJozef Kolek /// target operand. If the machine operand requires relocation,
3649761e96bSJozef Kolek /// record the relocation and return zero.
3659761e96bSJozef Kolek unsigned MipsMCCodeEmitter::
3669761e96bSJozef Kolek getBranchTarget7OpValueMM(const MCInst &MI, unsigned OpNo,
3679761e96bSJozef Kolek                           SmallVectorImpl<MCFixup> &Fixups,
3689761e96bSJozef Kolek                           const MCSubtargetInfo &STI) const {
3699761e96bSJozef Kolek   const MCOperand &MO = MI.getOperand(OpNo);
3709761e96bSJozef Kolek 
3719761e96bSJozef Kolek   // If the destination is an immediate, divide by 2.
3729761e96bSJozef Kolek   if (MO.isImm()) return MO.getImm() >> 1;
3739761e96bSJozef Kolek 
3749761e96bSJozef Kolek   assert(MO.isExpr() &&
3759761e96bSJozef Kolek          "getBranchTargetOpValueMM expects only expressions or immediates");
3769761e96bSJozef Kolek 
3779761e96bSJozef Kolek   const MCExpr *Expr = MO.getExpr();
37863661f8dSJim Grosbach   Fixups.push_back(MCFixup::create(0, Expr,
3799761e96bSJozef Kolek                                    MCFixupKind(Mips::fixup_MICROMIPS_PC7_S1)));
3809761e96bSJozef Kolek   return 0;
3819761e96bSJozef Kolek }
3829761e96bSJozef Kolek 
3835cfebddeSJozef Kolek /// getBranchTargetOpValueMMPC10 - Return binary encoding of the microMIPS
3845cfebddeSJozef Kolek /// 10-bit branch target operand. If the machine operand requires relocation,
3855cfebddeSJozef Kolek /// record the relocation and return zero.
3865cfebddeSJozef Kolek unsigned MipsMCCodeEmitter::
3875cfebddeSJozef Kolek getBranchTargetOpValueMMPC10(const MCInst &MI, unsigned OpNo,
3885cfebddeSJozef Kolek                              SmallVectorImpl<MCFixup> &Fixups,
3895cfebddeSJozef Kolek                              const MCSubtargetInfo &STI) const {
3905cfebddeSJozef Kolek   const MCOperand &MO = MI.getOperand(OpNo);
3915cfebddeSJozef Kolek 
3925cfebddeSJozef Kolek   // If the destination is an immediate, divide by 2.
3935cfebddeSJozef Kolek   if (MO.isImm()) return MO.getImm() >> 1;
3945cfebddeSJozef Kolek 
3955cfebddeSJozef Kolek   assert(MO.isExpr() &&
3965cfebddeSJozef Kolek          "getBranchTargetOpValuePC10 expects only expressions or immediates");
3975cfebddeSJozef Kolek 
3985cfebddeSJozef Kolek   const MCExpr *Expr = MO.getExpr();
39963661f8dSJim Grosbach   Fixups.push_back(MCFixup::create(0, Expr,
4005cfebddeSJozef Kolek                    MCFixupKind(Mips::fixup_MICROMIPS_PC10_S1)));
4015cfebddeSJozef Kolek   return 0;
4025cfebddeSJozef Kolek }
4035cfebddeSJozef Kolek 
4048a80aa76SZoran Jovanovic /// getBranchTargetOpValue - Return binary encoding of the microMIPS branch
4058a80aa76SZoran Jovanovic /// target operand. If the machine operand requires relocation,
4068a80aa76SZoran Jovanovic /// record the relocation and return zero.
4078a80aa76SZoran Jovanovic unsigned MipsMCCodeEmitter::
4088a80aa76SZoran Jovanovic getBranchTargetOpValueMM(const MCInst &MI, unsigned OpNo,
4093fa98a65SDavid Woodhouse                          SmallVectorImpl<MCFixup> &Fixups,
4103fa98a65SDavid Woodhouse                          const MCSubtargetInfo &STI) const {
4118a80aa76SZoran Jovanovic   const MCOperand &MO = MI.getOperand(OpNo);
4128a80aa76SZoran Jovanovic 
4138a80aa76SZoran Jovanovic   // If the destination is an immediate, divide by 2.
4148a80aa76SZoran Jovanovic   if (MO.isImm()) return MO.getImm() >> 1;
4158a80aa76SZoran Jovanovic 
4168a80aa76SZoran Jovanovic   assert(MO.isExpr() &&
4178a80aa76SZoran Jovanovic          "getBranchTargetOpValueMM expects only expressions or immediates");
4188a80aa76SZoran Jovanovic 
4198a80aa76SZoran Jovanovic   const MCExpr *Expr = MO.getExpr();
42063661f8dSJim Grosbach   Fixups.push_back(MCFixup::create(0, Expr,
4218a80aa76SZoran Jovanovic                    MCFixupKind(Mips::
4228a80aa76SZoran Jovanovic                                fixup_MICROMIPS_PC16_S1)));
4238a80aa76SZoran Jovanovic   return 0;
4248a80aa76SZoran Jovanovic }
4258a80aa76SZoran Jovanovic 
4263c8869dcSZoran Jovanovic /// getBranchTarget21OpValue - Return binary encoding of the branch
4273c8869dcSZoran Jovanovic /// target operand. If the machine operand requires relocation,
4283c8869dcSZoran Jovanovic /// record the relocation and return zero.
4293c8869dcSZoran Jovanovic unsigned MipsMCCodeEmitter::
4303c8869dcSZoran Jovanovic getBranchTarget21OpValue(const MCInst &MI, unsigned OpNo,
4313c8869dcSZoran Jovanovic                          SmallVectorImpl<MCFixup> &Fixups,
4323c8869dcSZoran Jovanovic                          const MCSubtargetInfo &STI) const {
4333c8869dcSZoran Jovanovic   const MCOperand &MO = MI.getOperand(OpNo);
4343c8869dcSZoran Jovanovic 
4353c8869dcSZoran Jovanovic   // If the destination is an immediate, divide by 4.
4363c8869dcSZoran Jovanovic   if (MO.isImm()) return MO.getImm() >> 2;
4373c8869dcSZoran Jovanovic 
4383c8869dcSZoran Jovanovic   assert(MO.isExpr() &&
4393c8869dcSZoran Jovanovic          "getBranchTarget21OpValue expects only expressions or immediates");
4403c8869dcSZoran Jovanovic 
441b7915a1fSPetar Jovanovic   const MCExpr *FixupExpression = MCBinaryExpr::createAdd(
442b7915a1fSPetar Jovanovic       MO.getExpr(), MCConstantExpr::create(-4, Ctx), Ctx);
443b7915a1fSPetar Jovanovic   Fixups.push_back(MCFixup::create(0, FixupExpression,
44410e06da0SZoran Jovanovic                                    MCFixupKind(Mips::fixup_MIPS_PC21_S2)));
4453c8869dcSZoran Jovanovic   return 0;
4463c8869dcSZoran Jovanovic }
4473c8869dcSZoran Jovanovic 
44884e4d59eSZoran Jovanovic /// getBranchTarget21OpValueMM - Return binary encoding of the branch
44984e4d59eSZoran Jovanovic /// target operand for microMIPS. If the machine operand requires
45084e4d59eSZoran Jovanovic /// relocation, record the relocation and return zero.
45184e4d59eSZoran Jovanovic unsigned MipsMCCodeEmitter::
45284e4d59eSZoran Jovanovic getBranchTarget21OpValueMM(const MCInst &MI, unsigned OpNo,
45384e4d59eSZoran Jovanovic                            SmallVectorImpl<MCFixup> &Fixups,
45484e4d59eSZoran Jovanovic                            const MCSubtargetInfo &STI) const {
45584e4d59eSZoran Jovanovic   const MCOperand &MO = MI.getOperand(OpNo);
45684e4d59eSZoran Jovanovic 
457f0ed16eaSHrvoje Varga   // If the destination is an immediate, divide by 4.
458f0ed16eaSHrvoje Varga   if (MO.isImm()) return MO.getImm() >> 2;
45984e4d59eSZoran Jovanovic 
46084e4d59eSZoran Jovanovic   assert(MO.isExpr() &&
46184e4d59eSZoran Jovanovic     "getBranchTarget21OpValueMM expects only expressions or immediates");
46284e4d59eSZoran Jovanovic 
4635f94cedeSZoran Jovanovic   const MCExpr *FixupExpression = MCBinaryExpr::createAdd(
4645f94cedeSZoran Jovanovic       MO.getExpr(), MCConstantExpr::create(-4, Ctx), Ctx);
4655f94cedeSZoran Jovanovic   Fixups.push_back(MCFixup::create(0, FixupExpression,
4665f94cedeSZoran Jovanovic                                    MCFixupKind(Mips::fixup_MICROMIPS_PC21_S1)));
46784e4d59eSZoran Jovanovic   return 0;
46884e4d59eSZoran Jovanovic }
46984e4d59eSZoran Jovanovic 
4703c8869dcSZoran Jovanovic /// getBranchTarget26OpValue - Return binary encoding of the branch
4713c8869dcSZoran Jovanovic /// target operand. If the machine operand requires relocation,
4723c8869dcSZoran Jovanovic /// record the relocation and return zero.
4733c8869dcSZoran Jovanovic unsigned MipsMCCodeEmitter::
4743c8869dcSZoran Jovanovic getBranchTarget26OpValue(const MCInst &MI, unsigned OpNo,
4753c8869dcSZoran Jovanovic                          SmallVectorImpl<MCFixup> &Fixups,
4763c8869dcSZoran Jovanovic                          const MCSubtargetInfo &STI) const {
4773c8869dcSZoran Jovanovic   const MCOperand &MO = MI.getOperand(OpNo);
4783c8869dcSZoran Jovanovic 
4793c8869dcSZoran Jovanovic   // If the destination is an immediate, divide by 4.
4803c8869dcSZoran Jovanovic   if (MO.isImm()) return MO.getImm() >> 2;
4813c8869dcSZoran Jovanovic 
4823c8869dcSZoran Jovanovic   assert(MO.isExpr() &&
4833c8869dcSZoran Jovanovic          "getBranchTarget26OpValue expects only expressions or immediates");
4843c8869dcSZoran Jovanovic 
485b7915a1fSPetar Jovanovic   const MCExpr *FixupExpression = MCBinaryExpr::createAdd(
486b7915a1fSPetar Jovanovic       MO.getExpr(), MCConstantExpr::create(-4, Ctx), Ctx);
487b7915a1fSPetar Jovanovic   Fixups.push_back(MCFixup::create(0, FixupExpression,
48810e06da0SZoran Jovanovic                                    MCFixupKind(Mips::fixup_MIPS_PC26_S2)));
4893c8869dcSZoran Jovanovic   return 0;
4903c8869dcSZoran Jovanovic }
4913c8869dcSZoran Jovanovic 
492a887b361SZoran Jovanovic /// getBranchTarget26OpValueMM - Return binary encoding of the branch
493a887b361SZoran Jovanovic /// target operand. If the machine operand requires relocation,
494a887b361SZoran Jovanovic /// record the relocation and return zero.
495a887b361SZoran Jovanovic unsigned MipsMCCodeEmitter::getBranchTarget26OpValueMM(
496a887b361SZoran Jovanovic     const MCInst &MI, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups,
497a887b361SZoran Jovanovic     const MCSubtargetInfo &STI) const {
498a887b361SZoran Jovanovic   const MCOperand &MO = MI.getOperand(OpNo);
499a887b361SZoran Jovanovic 
500a887b361SZoran Jovanovic   // If the destination is an immediate, divide by 2.
501a887b361SZoran Jovanovic   if (MO.isImm())
502a887b361SZoran Jovanovic     return MO.getImm() >> 1;
503a887b361SZoran Jovanovic 
50402b70030SZoran Jovanovic   assert(MO.isExpr() &&
50502b70030SZoran Jovanovic          "getBranchTarget26OpValueMM expects only expressions or immediates");
50602b70030SZoran Jovanovic 
50702b70030SZoran Jovanovic   const MCExpr *FixupExpression = MCBinaryExpr::createAdd(
50802b70030SZoran Jovanovic       MO.getExpr(), MCConstantExpr::create(-4, Ctx), Ctx);
50902b70030SZoran Jovanovic   Fixups.push_back(MCFixup::create(0, FixupExpression,
51002b70030SZoran Jovanovic                                    MCFixupKind(Mips::fixup_MICROMIPS_PC26_S1)));
511a887b361SZoran Jovanovic   return 0;
512a887b361SZoran Jovanovic }
513a887b361SZoran Jovanovic 
51452c56b93SZoran Jovanovic /// getJumpOffset16OpValue - Return binary encoding of the jump
51552c56b93SZoran Jovanovic /// target operand. If the machine operand requires relocation,
51652c56b93SZoran Jovanovic /// record the relocation and return zero.
51752c56b93SZoran Jovanovic unsigned MipsMCCodeEmitter::
51852c56b93SZoran Jovanovic getJumpOffset16OpValue(const MCInst &MI, unsigned OpNo,
51952c56b93SZoran Jovanovic                        SmallVectorImpl<MCFixup> &Fixups,
52052c56b93SZoran Jovanovic                        const MCSubtargetInfo &STI) const {
52152c56b93SZoran Jovanovic   const MCOperand &MO = MI.getOperand(OpNo);
52252c56b93SZoran Jovanovic 
52352c56b93SZoran Jovanovic   if (MO.isImm()) return MO.getImm();
52452c56b93SZoran Jovanovic 
52552c56b93SZoran Jovanovic   assert(MO.isExpr() &&
52652c56b93SZoran Jovanovic          "getJumpOffset16OpValue expects only expressions or an immediate");
52752c56b93SZoran Jovanovic 
52852c56b93SZoran Jovanovic    // TODO: Push fixup.
52952c56b93SZoran Jovanovic    return 0;
53052c56b93SZoran Jovanovic }
53152c56b93SZoran Jovanovic 
532c85e3ff3SBruno Cardoso Lopes /// getJumpTargetOpValue - Return binary encoding of the jump
533c85e3ff3SBruno Cardoso Lopes /// target operand. If the machine operand requires relocation,
534c85e3ff3SBruno Cardoso Lopes /// record the relocation and return zero.
535c85e3ff3SBruno Cardoso Lopes unsigned MipsMCCodeEmitter::
536c85e3ff3SBruno Cardoso Lopes getJumpTargetOpValue(const MCInst &MI, unsigned OpNo,
5373fa98a65SDavid Woodhouse                      SmallVectorImpl<MCFixup> &Fixups,
5383fa98a65SDavid Woodhouse                      const MCSubtargetInfo &STI) const {
539c85e3ff3SBruno Cardoso Lopes   const MCOperand &MO = MI.getOperand(OpNo);
5404f69a0f2SJack Carter   // If the destination is an immediate, divide by 4.
5414f69a0f2SJack Carter   if (MO.isImm()) return MO.getImm()>>2;
5424f69a0f2SJack Carter 
54371e6a749SJack Carter   assert(MO.isExpr() &&
54471e6a749SJack Carter          "getJumpTargetOpValue expects only expressions or an immediate");
545c85e3ff3SBruno Cardoso Lopes 
546c85e3ff3SBruno Cardoso Lopes   const MCExpr *Expr = MO.getExpr();
54763661f8dSJim Grosbach   Fixups.push_back(MCFixup::create(0, Expr,
548c85e3ff3SBruno Cardoso Lopes                                    MCFixupKind(Mips::fixup_Mips_26)));
549c85e3ff3SBruno Cardoso Lopes   return 0;
550c85e3ff3SBruno Cardoso Lopes }
551c85e3ff3SBruno Cardoso Lopes 
552c85e3ff3SBruno Cardoso Lopes unsigned MipsMCCodeEmitter::
553507e084aSZoran Jovanovic getJumpTargetOpValueMM(const MCInst &MI, unsigned OpNo,
5543fa98a65SDavid Woodhouse                        SmallVectorImpl<MCFixup> &Fixups,
5553fa98a65SDavid Woodhouse                        const MCSubtargetInfo &STI) const {
556507e084aSZoran Jovanovic   const MCOperand &MO = MI.getOperand(OpNo);
557507e084aSZoran Jovanovic   // If the destination is an immediate, divide by 2.
558507e084aSZoran Jovanovic   if (MO.isImm()) return MO.getImm() >> 1;
559507e084aSZoran Jovanovic 
560507e084aSZoran Jovanovic   assert(MO.isExpr() &&
561507e084aSZoran Jovanovic          "getJumpTargetOpValueMM expects only expressions or an immediate");
562507e084aSZoran Jovanovic 
563507e084aSZoran Jovanovic   const MCExpr *Expr = MO.getExpr();
56463661f8dSJim Grosbach   Fixups.push_back(MCFixup::create(0, Expr,
565507e084aSZoran Jovanovic                                    MCFixupKind(Mips::fixup_MICROMIPS_26_S1)));
566507e084aSZoran Jovanovic   return 0;
567507e084aSZoran Jovanovic }
568507e084aSZoran Jovanovic 
569507e084aSZoran Jovanovic unsigned MipsMCCodeEmitter::
570c74e3eb9SZoran Jovanovic getUImm5Lsl2Encoding(const MCInst &MI, unsigned OpNo,
571c74e3eb9SZoran Jovanovic                      SmallVectorImpl<MCFixup> &Fixups,
572c74e3eb9SZoran Jovanovic                      const MCSubtargetInfo &STI) const {
573c74e3eb9SZoran Jovanovic   const MCOperand &MO = MI.getOperand(OpNo);
574c74e3eb9SZoran Jovanovic   if (MO.isImm()) {
575c74e3eb9SZoran Jovanovic     // The immediate is encoded as 'immediate << 2'.
576c74e3eb9SZoran Jovanovic     unsigned Res = getMachineOpValue(MI, MO, Fixups, STI);
577c74e3eb9SZoran Jovanovic     assert((Res & 3) == 0);
578c74e3eb9SZoran Jovanovic     return Res >> 2;
579c74e3eb9SZoran Jovanovic   }
580c74e3eb9SZoran Jovanovic 
581c74e3eb9SZoran Jovanovic   assert(MO.isExpr() &&
582c74e3eb9SZoran Jovanovic          "getUImm5Lsl2Encoding expects only expressions or an immediate");
583c74e3eb9SZoran Jovanovic 
584c74e3eb9SZoran Jovanovic   return 0;
585c74e3eb9SZoran Jovanovic }
586c74e3eb9SZoran Jovanovic 
587c74e3eb9SZoran Jovanovic unsigned MipsMCCodeEmitter::
588bac3619bSZoran Jovanovic getSImm3Lsa2Value(const MCInst &MI, unsigned OpNo,
589bac3619bSZoran Jovanovic                   SmallVectorImpl<MCFixup> &Fixups,
590bac3619bSZoran Jovanovic                   const MCSubtargetInfo &STI) const {
591bac3619bSZoran Jovanovic   const MCOperand &MO = MI.getOperand(OpNo);
592bac3619bSZoran Jovanovic   if (MO.isImm()) {
593bac3619bSZoran Jovanovic     int Value = MO.getImm();
594bac3619bSZoran Jovanovic     return Value >> 2;
595bac3619bSZoran Jovanovic   }
596bac3619bSZoran Jovanovic 
597bac3619bSZoran Jovanovic   return 0;
598bac3619bSZoran Jovanovic }
599bac3619bSZoran Jovanovic 
600bac3619bSZoran Jovanovic unsigned MipsMCCodeEmitter::
60142b84443SZoran Jovanovic getUImm6Lsl2Encoding(const MCInst &MI, unsigned OpNo,
60242b84443SZoran Jovanovic                      SmallVectorImpl<MCFixup> &Fixups,
60342b84443SZoran Jovanovic                      const MCSubtargetInfo &STI) const {
60442b84443SZoran Jovanovic   const MCOperand &MO = MI.getOperand(OpNo);
60542b84443SZoran Jovanovic   if (MO.isImm()) {
60642b84443SZoran Jovanovic     unsigned Value = MO.getImm();
60742b84443SZoran Jovanovic     return Value >> 2;
60842b84443SZoran Jovanovic   }
60942b84443SZoran Jovanovic 
61042b84443SZoran Jovanovic   return 0;
61142b84443SZoran Jovanovic }
61242b84443SZoran Jovanovic 
61342b84443SZoran Jovanovic unsigned MipsMCCodeEmitter::
61498bd58caSZoran Jovanovic getSImm9AddiuspValue(const MCInst &MI, unsigned OpNo,
61598bd58caSZoran Jovanovic                      SmallVectorImpl<MCFixup> &Fixups,
61698bd58caSZoran Jovanovic                      const MCSubtargetInfo &STI) const {
61798bd58caSZoran Jovanovic   const MCOperand &MO = MI.getOperand(OpNo);
61898bd58caSZoran Jovanovic   if (MO.isImm()) {
61998bd58caSZoran Jovanovic     unsigned Binary = (MO.getImm() >> 2) & 0x0000ffff;
62098bd58caSZoran Jovanovic     return (((Binary & 0x8000) >> 7) | (Binary & 0x00ff));
62198bd58caSZoran Jovanovic   }
62298bd58caSZoran Jovanovic 
62398bd58caSZoran Jovanovic   return 0;
62498bd58caSZoran Jovanovic }
62598bd58caSZoran Jovanovic 
62698bd58caSZoran Jovanovic unsigned MipsMCCodeEmitter::
6273fa98a65SDavid Woodhouse getExprOpValue(const MCExpr *Expr, SmallVectorImpl<MCFixup> &Fixups,
6283fa98a65SDavid Woodhouse                const MCSubtargetInfo &STI) const {
629b5cf5909SJack Carter   int64_t Res;
630049e9e4dSAkira Hatanaka 
63113760bd1SJim Grosbach   if (Expr->evaluateAsAbsolute(Res))
632b5cf5909SJack Carter     return Res;
633fe384a2cSAkira Hatanaka 
634fe384a2cSAkira Hatanaka   MCExpr::ExprKind Kind = Expr->getKind();
635b5cf5909SJack Carter   if (Kind == MCExpr::Constant) {
636b5cf5909SJack Carter     return cast<MCConstantExpr>(Expr)->getValue();
637b5cf5909SJack Carter   }
638fe384a2cSAkira Hatanaka 
639fe384a2cSAkira Hatanaka   if (Kind == MCExpr::Binary) {
6403fa98a65SDavid Woodhouse     unsigned Res = getExprOpValue(cast<MCBinaryExpr>(Expr)->getLHS(), Fixups, STI);
6413fa98a65SDavid Woodhouse     Res += getExprOpValue(cast<MCBinaryExpr>(Expr)->getRHS(), Fixups, STI);
642b5cf5909SJack Carter     return Res;
643fe384a2cSAkira Hatanaka   }
644a5da588bSPetar Jovanovic 
645a5da588bSPetar Jovanovic   if (Kind == MCExpr::Target) {
646a5da588bSPetar Jovanovic     const MipsMCExpr *MipsExpr = cast<MipsMCExpr>(Expr);
647a5da588bSPetar Jovanovic 
648a5da588bSPetar Jovanovic     Mips::Fixups FixupKind = Mips::Fixups(0);
649a5da588bSPetar Jovanovic     switch (MipsExpr->getKind()) {
650fe98b2f5SDaniel Sanders     case MipsMCExpr::MEK_None:
651fe98b2f5SDaniel Sanders     case MipsMCExpr::MEK_Special:
652fe98b2f5SDaniel Sanders       llvm_unreachable("Unhandled fixup kind!");
653fe98b2f5SDaniel Sanders       break;
654fe98b2f5SDaniel Sanders     case MipsMCExpr::MEK_CALL_HI16:
655fe98b2f5SDaniel Sanders       FixupKind = Mips::fixup_Mips_CALL_HI16;
656fe98b2f5SDaniel Sanders       break;
657fe98b2f5SDaniel Sanders     case MipsMCExpr::MEK_CALL_LO16:
658fe98b2f5SDaniel Sanders       FixupKind = Mips::fixup_Mips_CALL_LO16;
659fe98b2f5SDaniel Sanders       break;
660fe98b2f5SDaniel Sanders     case MipsMCExpr::MEK_DTPREL_HI:
661fe98b2f5SDaniel Sanders       FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_DTPREL_HI16
662fe98b2f5SDaniel Sanders                                    : Mips::fixup_Mips_DTPREL_HI;
663fe98b2f5SDaniel Sanders       break;
664fe98b2f5SDaniel Sanders     case MipsMCExpr::MEK_DTPREL_LO:
665fe98b2f5SDaniel Sanders       FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_DTPREL_LO16
666fe98b2f5SDaniel Sanders                                    : Mips::fixup_Mips_DTPREL_LO;
667fe98b2f5SDaniel Sanders       break;
668fe98b2f5SDaniel Sanders     case MipsMCExpr::MEK_GOTTPREL:
669fe98b2f5SDaniel Sanders       FixupKind = Mips::fixup_Mips_GOTTPREL;
670fe98b2f5SDaniel Sanders       break;
671fe98b2f5SDaniel Sanders     case MipsMCExpr::MEK_GOT:
672fe98b2f5SDaniel Sanders       FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOT16
673fe98b2f5SDaniel Sanders                                    : Mips::fixup_Mips_GOT;
674fe98b2f5SDaniel Sanders       break;
675fe98b2f5SDaniel Sanders     case MipsMCExpr::MEK_GOT_CALL:
676fe98b2f5SDaniel Sanders       FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_CALL16
677fe98b2f5SDaniel Sanders                                    : Mips::fixup_Mips_CALL16;
678fe98b2f5SDaniel Sanders       break;
679fe98b2f5SDaniel Sanders     case MipsMCExpr::MEK_GOT_DISP:
680fe98b2f5SDaniel Sanders       FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOT_DISP
681fe98b2f5SDaniel Sanders                                    : Mips::fixup_Mips_GOT_DISP;
682fe98b2f5SDaniel Sanders       break;
683fe98b2f5SDaniel Sanders     case MipsMCExpr::MEK_GOT_HI16:
684fe98b2f5SDaniel Sanders       FixupKind = Mips::fixup_Mips_GOT_HI16;
685fe98b2f5SDaniel Sanders       break;
686fe98b2f5SDaniel Sanders     case MipsMCExpr::MEK_GOT_LO16:
687fe98b2f5SDaniel Sanders       FixupKind = Mips::fixup_Mips_GOT_LO16;
688fe98b2f5SDaniel Sanders       break;
689fe98b2f5SDaniel Sanders     case MipsMCExpr::MEK_GOT_PAGE:
690fe98b2f5SDaniel Sanders       FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOT_PAGE
691fe98b2f5SDaniel Sanders                                    : Mips::fixup_Mips_GOT_PAGE;
692fe98b2f5SDaniel Sanders       break;
693fe98b2f5SDaniel Sanders     case MipsMCExpr::MEK_GOT_OFST:
694fe98b2f5SDaniel Sanders       FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOT_OFST
695fe98b2f5SDaniel Sanders                                    : Mips::fixup_Mips_GOT_OFST;
696fe98b2f5SDaniel Sanders       break;
697fe98b2f5SDaniel Sanders     case MipsMCExpr::MEK_GPREL:
698fe98b2f5SDaniel Sanders       FixupKind = Mips::fixup_Mips_GPREL16;
699fe98b2f5SDaniel Sanders       break;
700*926883e1SEugene Zelenko     case MipsMCExpr::MEK_LO:
701fe98b2f5SDaniel Sanders       // Check for %lo(%neg(%gp_rel(X)))
702fe98b2f5SDaniel Sanders       if (MipsExpr->isGpOff()) {
703fe98b2f5SDaniel Sanders         FixupKind = Mips::fixup_Mips_GPOFF_LO;
704fe98b2f5SDaniel Sanders         break;
705fe98b2f5SDaniel Sanders       }
706fe98b2f5SDaniel Sanders       FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_LO16
707fe98b2f5SDaniel Sanders                                    : Mips::fixup_Mips_LO16;
708fe98b2f5SDaniel Sanders       break;
709fe98b2f5SDaniel Sanders     case MipsMCExpr::MEK_HIGHEST:
71006c47803SSasa Stankovic       FixupKind = Mips::fixup_Mips_HIGHEST;
71106c47803SSasa Stankovic       break;
712fe98b2f5SDaniel Sanders     case MipsMCExpr::MEK_HIGHER:
71306c47803SSasa Stankovic       FixupKind = Mips::fixup_Mips_HIGHER;
71406c47803SSasa Stankovic       break;
715fe98b2f5SDaniel Sanders     case MipsMCExpr::MEK_HI:
716fe98b2f5SDaniel Sanders       // Check for %hi(%neg(%gp_rel(X)))
717fe98b2f5SDaniel Sanders       if (MipsExpr->isGpOff()) {
718fe98b2f5SDaniel Sanders         FixupKind = Mips::fixup_Mips_GPOFF_HI;
719fe98b2f5SDaniel Sanders         break;
720fe98b2f5SDaniel Sanders       }
721a5da588bSPetar Jovanovic       FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_HI16
722a5da588bSPetar Jovanovic                                    : Mips::fixup_Mips_HI16;
723a5da588bSPetar Jovanovic       break;
724fe98b2f5SDaniel Sanders     case MipsMCExpr::MEK_PCREL_HI16:
725fe98b2f5SDaniel Sanders       FixupKind = Mips::fixup_MIPS_PCHI16;
726fe98b2f5SDaniel Sanders       break;
727fe98b2f5SDaniel Sanders     case MipsMCExpr::MEK_PCREL_LO16:
728fe98b2f5SDaniel Sanders       FixupKind = Mips::fixup_MIPS_PCLO16;
729fe98b2f5SDaniel Sanders       break;
730fe98b2f5SDaniel Sanders     case MipsMCExpr::MEK_TLSGD:
731fe98b2f5SDaniel Sanders       FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_GD
732fe98b2f5SDaniel Sanders                                    : Mips::fixup_Mips_TLSGD;
733fe98b2f5SDaniel Sanders       break;
734fe98b2f5SDaniel Sanders     case MipsMCExpr::MEK_TLSLDM:
735fe98b2f5SDaniel Sanders       FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_LDM
736fe98b2f5SDaniel Sanders                                    : Mips::fixup_Mips_TLSLDM;
737fe98b2f5SDaniel Sanders       break;
738fe98b2f5SDaniel Sanders     case MipsMCExpr::MEK_TPREL_HI:
739fe98b2f5SDaniel Sanders       FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_TPREL_HI16
740fe98b2f5SDaniel Sanders                                    : Mips::fixup_Mips_TPREL_HI;
741fe98b2f5SDaniel Sanders       break;
742fe98b2f5SDaniel Sanders     case MipsMCExpr::MEK_TPREL_LO:
743fe98b2f5SDaniel Sanders       FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_TPREL_LO16
744fe98b2f5SDaniel Sanders                                    : Mips::fixup_Mips_TPREL_LO;
745a5da588bSPetar Jovanovic       break;
7463feeb9c8SDaniel Sanders     case MipsMCExpr::MEK_NEG:
7473feeb9c8SDaniel Sanders       FixupKind =
7483feeb9c8SDaniel Sanders           isMicroMips(STI) ? Mips::fixup_MICROMIPS_SUB : Mips::fixup_Mips_SUB;
7493feeb9c8SDaniel Sanders       break;
750a5da588bSPetar Jovanovic     }
75163661f8dSJim Grosbach     Fixups.push_back(MCFixup::create(0, MipsExpr, MCFixupKind(FixupKind)));
752a5da588bSPetar Jovanovic     return 0;
753a5da588bSPetar Jovanovic   }
754a5da588bSPetar Jovanovic 
755b5cf5909SJack Carter   if (Kind == MCExpr::SymbolRef) {
756f9774c32SBill Wendling     Mips::Fixups FixupKind = Mips::Fixups(0);
757e2eed964SAkira Hatanaka 
758049e9e4dSAkira Hatanaka     switch(cast<MCSymbolRefExpr>(Expr)->getKind()) {
759b9f9de93SJack Carter     default: llvm_unreachable("Unknown fixup kind!");
76060f1db05SDaniel Sanders       break;
76160f1db05SDaniel Sanders     case MCSymbolRefExpr::VK_None:
76260f1db05SDaniel Sanders       FixupKind = Mips::fixup_Mips_32; // FIXME: This is ok for O32/N32 but not N64.
763b9f9de93SJack Carter       break;
764c85e3ff3SBruno Cardoso Lopes     } // switch
765fe384a2cSAkira Hatanaka 
76663661f8dSJim Grosbach     Fixups.push_back(MCFixup::create(0, Expr, MCFixupKind(FixupKind)));
767fe384a2cSAkira Hatanaka     return 0;
768c85e3ff3SBruno Cardoso Lopes   }
769b5cf5909SJack Carter   return 0;
770b5cf5909SJack Carter }
771b5cf5909SJack Carter 
772b5cf5909SJack Carter /// getMachineOpValue - Return binary encoding of operand. If the machine
773b5cf5909SJack Carter /// operand requires relocation, record the relocation and return zero.
774b5cf5909SJack Carter unsigned MipsMCCodeEmitter::
775b5cf5909SJack Carter getMachineOpValue(const MCInst &MI, const MCOperand &MO,
7763fa98a65SDavid Woodhouse                   SmallVectorImpl<MCFixup> &Fixups,
7773fa98a65SDavid Woodhouse                   const MCSubtargetInfo &STI) const {
778b5cf5909SJack Carter   if (MO.isReg()) {
779b5cf5909SJack Carter     unsigned Reg = MO.getReg();
780bc07a890SBill Wendling     unsigned RegNo = Ctx.getRegisterInfo()->getEncodingValue(Reg);
781b5cf5909SJack Carter     return RegNo;
782b5cf5909SJack Carter   } else if (MO.isImm()) {
783b5cf5909SJack Carter     return static_cast<unsigned>(MO.getImm());
784b5cf5909SJack Carter   } else if (MO.isFPImm()) {
785b5cf5909SJack Carter     return static_cast<unsigned>(APFloat(MO.getFPImm())
786b5cf5909SJack Carter         .bitcastToAPInt().getHiBits(32).getLimitedValue());
787b5cf5909SJack Carter   }
788b5cf5909SJack Carter   // MO must be an Expr.
789b5cf5909SJack Carter   assert(MO.isExpr());
7903fa98a65SDavid Woodhouse   return getExprOpValue(MO.getExpr(),Fixups, STI);
791b5cf5909SJack Carter }
792c85e3ff3SBruno Cardoso Lopes 
793dc0602a2SDaniel Sanders /// Return binary encoding of memory related operand.
794c85e3ff3SBruno Cardoso Lopes /// If the offset operand requires relocation, record the relocation.
795dc0602a2SDaniel Sanders template <unsigned ShiftAmount>
796dc0602a2SDaniel Sanders unsigned MipsMCCodeEmitter::getMemEncoding(const MCInst &MI, unsigned OpNo,
7973fa98a65SDavid Woodhouse                                            SmallVectorImpl<MCFixup> &Fixups,
7983fa98a65SDavid Woodhouse                                            const MCSubtargetInfo &STI) const {
799c85e3ff3SBruno Cardoso Lopes   // Base register is encoded in bits 20-16, offset is encoded in bits 15-0.
800c85e3ff3SBruno Cardoso Lopes   assert(MI.getOperand(OpNo).isReg());
8013fa98a65SDavid Woodhouse   unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo),Fixups, STI) << 16;
8023fa98a65SDavid Woodhouse   unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI);
803c85e3ff3SBruno Cardoso Lopes 
804dc0602a2SDaniel Sanders   // Apply the scale factor if there is one.
805dc0602a2SDaniel Sanders   OffBits >>= ShiftAmount;
806dc0602a2SDaniel Sanders 
807c85e3ff3SBruno Cardoso Lopes   return (OffBits & 0xFFFF) | RegBits;
808c85e3ff3SBruno Cardoso Lopes }
809c85e3ff3SBruno Cardoso Lopes 
81097700977SJack Carter unsigned MipsMCCodeEmitter::
811e8c9d1eaSJozef Kolek getMemEncodingMMImm4(const MCInst &MI, unsigned OpNo,
812e8c9d1eaSJozef Kolek                      SmallVectorImpl<MCFixup> &Fixups,
813e8c9d1eaSJozef Kolek                      const MCSubtargetInfo &STI) const {
814e8c9d1eaSJozef Kolek   // Base register is encoded in bits 6-4, offset is encoded in bits 3-0.
815e8c9d1eaSJozef Kolek   assert(MI.getOperand(OpNo).isReg());
816e8c9d1eaSJozef Kolek   unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo),
817e8c9d1eaSJozef Kolek                                        Fixups, STI) << 4;
818e8c9d1eaSJozef Kolek   unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1),
819e8c9d1eaSJozef Kolek                                        Fixups, STI);
820e8c9d1eaSJozef Kolek 
821e8c9d1eaSJozef Kolek   return (OffBits & 0xF) | RegBits;
822e8c9d1eaSJozef Kolek }
823e8c9d1eaSJozef Kolek 
824e8c9d1eaSJozef Kolek unsigned MipsMCCodeEmitter::
825e8c9d1eaSJozef Kolek getMemEncodingMMImm4Lsl1(const MCInst &MI, unsigned OpNo,
826e8c9d1eaSJozef Kolek                          SmallVectorImpl<MCFixup> &Fixups,
827e8c9d1eaSJozef Kolek                          const MCSubtargetInfo &STI) const {
828e8c9d1eaSJozef Kolek   // Base register is encoded in bits 6-4, offset is encoded in bits 3-0.
829e8c9d1eaSJozef Kolek   assert(MI.getOperand(OpNo).isReg());
830e8c9d1eaSJozef Kolek   unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo),
831e8c9d1eaSJozef Kolek                                        Fixups, STI) << 4;
832e8c9d1eaSJozef Kolek   unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1),
833e8c9d1eaSJozef Kolek                                        Fixups, STI) >> 1;
834e8c9d1eaSJozef Kolek 
835e8c9d1eaSJozef Kolek   return (OffBits & 0xF) | RegBits;
836e8c9d1eaSJozef Kolek }
837e8c9d1eaSJozef Kolek 
838e8c9d1eaSJozef Kolek unsigned MipsMCCodeEmitter::
839e8c9d1eaSJozef Kolek getMemEncodingMMImm4Lsl2(const MCInst &MI, unsigned OpNo,
840e8c9d1eaSJozef Kolek                          SmallVectorImpl<MCFixup> &Fixups,
841e8c9d1eaSJozef Kolek                          const MCSubtargetInfo &STI) const {
842e8c9d1eaSJozef Kolek   // Base register is encoded in bits 6-4, offset is encoded in bits 3-0.
843e8c9d1eaSJozef Kolek   assert(MI.getOperand(OpNo).isReg());
844e8c9d1eaSJozef Kolek   unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo),
845e8c9d1eaSJozef Kolek                                        Fixups, STI) << 4;
846e8c9d1eaSJozef Kolek   unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1),
847e8c9d1eaSJozef Kolek                                        Fixups, STI) >> 2;
848e8c9d1eaSJozef Kolek 
849e8c9d1eaSJozef Kolek   return (OffBits & 0xF) | RegBits;
850e8c9d1eaSJozef Kolek }
851e8c9d1eaSJozef Kolek 
852e8c9d1eaSJozef Kolek unsigned MipsMCCodeEmitter::
85312c6982bSJozef Kolek getMemEncodingMMSPImm5Lsl2(const MCInst &MI, unsigned OpNo,
85412c6982bSJozef Kolek                            SmallVectorImpl<MCFixup> &Fixups,
85512c6982bSJozef Kolek                            const MCSubtargetInfo &STI) const {
85612c6982bSJozef Kolek   // Register is encoded in bits 9-5, offset is encoded in bits 4-0.
85712c6982bSJozef Kolek   assert(MI.getOperand(OpNo).isReg() &&
85868be5f21SZoran Jovanovic          (MI.getOperand(OpNo).getReg() == Mips::SP ||
85968be5f21SZoran Jovanovic          MI.getOperand(OpNo).getReg() == Mips::SP_64) &&
86012c6982bSJozef Kolek          "Unexpected base register!");
86112c6982bSJozef Kolek   unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1),
86212c6982bSJozef Kolek                                        Fixups, STI) >> 2;
86312c6982bSJozef Kolek 
86412c6982bSJozef Kolek   return OffBits & 0x1F;
86512c6982bSJozef Kolek }
86612c6982bSJozef Kolek 
86712c6982bSJozef Kolek unsigned MipsMCCodeEmitter::
868e10a02ecSJozef Kolek getMemEncodingMMGPImm7Lsl2(const MCInst &MI, unsigned OpNo,
869e10a02ecSJozef Kolek                            SmallVectorImpl<MCFixup> &Fixups,
870e10a02ecSJozef Kolek                            const MCSubtargetInfo &STI) const {
871e10a02ecSJozef Kolek   // Register is encoded in bits 9-7, offset is encoded in bits 6-0.
872e10a02ecSJozef Kolek   assert(MI.getOperand(OpNo).isReg() &&
873e10a02ecSJozef Kolek          MI.getOperand(OpNo).getReg() == Mips::GP &&
874e10a02ecSJozef Kolek          "Unexpected base register!");
875e10a02ecSJozef Kolek 
876e10a02ecSJozef Kolek   unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1),
877e10a02ecSJozef Kolek                                        Fixups, STI) >> 2;
878e10a02ecSJozef Kolek 
879e10a02ecSJozef Kolek   return OffBits & 0x7F;
880e10a02ecSJozef Kolek }
881e10a02ecSJozef Kolek 
8829eaa30d2SZoran Jovanovic unsigned MipsMCCodeEmitter::
8839eaa30d2SZoran Jovanovic getMemEncodingMMImm9(const MCInst &MI, unsigned OpNo,
8849eaa30d2SZoran Jovanovic                      SmallVectorImpl<MCFixup> &Fixups,
8859eaa30d2SZoran Jovanovic                      const MCSubtargetInfo &STI) const {
8869eaa30d2SZoran Jovanovic   // Base register is encoded in bits 20-16, offset is encoded in bits 8-0.
8879eaa30d2SZoran Jovanovic   assert(MI.getOperand(OpNo).isReg());
8889eaa30d2SZoran Jovanovic   unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups,
8899eaa30d2SZoran Jovanovic                                        STI) << 16;
8909eaa30d2SZoran Jovanovic   unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo + 1), Fixups, STI);
8919eaa30d2SZoran Jovanovic 
8929eaa30d2SZoran Jovanovic   return (OffBits & 0x1FF) | RegBits;
8939eaa30d2SZoran Jovanovic }
8949eaa30d2SZoran Jovanovic 
895e10a02ecSJozef Kolek unsigned MipsMCCodeEmitter::
896cba9f80bSZlatko Buljan getMemEncodingMMImm11(const MCInst &MI, unsigned OpNo,
897cba9f80bSZlatko Buljan                       SmallVectorImpl<MCFixup> &Fixups,
898cba9f80bSZlatko Buljan                       const MCSubtargetInfo &STI) const {
899cba9f80bSZlatko Buljan   // Base register is encoded in bits 20-16, offset is encoded in bits 10-0.
900cba9f80bSZlatko Buljan   assert(MI.getOperand(OpNo).isReg());
901cba9f80bSZlatko Buljan   unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups,
902cba9f80bSZlatko Buljan                                        STI) << 16;
903cba9f80bSZlatko Buljan   unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI);
904cba9f80bSZlatko Buljan 
905cba9f80bSZlatko Buljan   return (OffBits & 0x07FF) | RegBits;
906cba9f80bSZlatko Buljan }
907cba9f80bSZlatko Buljan 
908cba9f80bSZlatko Buljan unsigned MipsMCCodeEmitter::
90997700977SJack Carter getMemEncodingMMImm12(const MCInst &MI, unsigned OpNo,
9103fa98a65SDavid Woodhouse                       SmallVectorImpl<MCFixup> &Fixups,
9113fa98a65SDavid Woodhouse                       const MCSubtargetInfo &STI) const {
912a4c4b5fcSZoran Jovanovic   // opNum can be invalid if instruction had reglist as operand.
913a4c4b5fcSZoran Jovanovic   // MemOperand is always last operand of instruction (base + offset).
914a4c4b5fcSZoran Jovanovic   switch (MI.getOpcode()) {
915a4c4b5fcSZoran Jovanovic   default:
916a4c4b5fcSZoran Jovanovic     break;
917a4c4b5fcSZoran Jovanovic   case Mips::SWM32_MM:
918a4c4b5fcSZoran Jovanovic   case Mips::LWM32_MM:
919a4c4b5fcSZoran Jovanovic     OpNo = MI.getNumOperands() - 2;
920a4c4b5fcSZoran Jovanovic     break;
921a4c4b5fcSZoran Jovanovic   }
922a4c4b5fcSZoran Jovanovic 
92397700977SJack Carter   // Base register is encoded in bits 20-16, offset is encoded in bits 11-0.
92497700977SJack Carter   assert(MI.getOperand(OpNo).isReg());
9253fa98a65SDavid Woodhouse   unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI) << 16;
9263fa98a65SDavid Woodhouse   unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI);
92797700977SJack Carter 
92897700977SJack Carter   return (OffBits & 0x0FFF) | RegBits;
9293c88fbd3SHrvoje Varga }
9303c88fbd3SHrvoje Varga 
9313c88fbd3SHrvoje Varga unsigned MipsMCCodeEmitter::
9323c88fbd3SHrvoje Varga getMemEncodingMMImm16(const MCInst &MI, unsigned OpNo,
9333c88fbd3SHrvoje Varga                       SmallVectorImpl<MCFixup> &Fixups,
9343c88fbd3SHrvoje Varga                       const MCSubtargetInfo &STI) const {
9353c88fbd3SHrvoje Varga   // Base register is encoded in bits 20-16, offset is encoded in bits 15-0.
9363c88fbd3SHrvoje Varga   assert(MI.getOperand(OpNo).isReg());
9373c88fbd3SHrvoje Varga   unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups,
9383c88fbd3SHrvoje Varga                                        STI) << 16;
9393c88fbd3SHrvoje Varga   unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI);
9403c88fbd3SHrvoje Varga 
9413c88fbd3SHrvoje Varga   return (OffBits & 0xFFFF) | RegBits;
94297700977SJack Carter }
94397700977SJack Carter 
944f9a02500SZoran Jovanovic unsigned MipsMCCodeEmitter::
945f9a02500SZoran Jovanovic getMemEncodingMMImm4sp(const MCInst &MI, unsigned OpNo,
946f9a02500SZoran Jovanovic                        SmallVectorImpl<MCFixup> &Fixups,
947f9a02500SZoran Jovanovic                        const MCSubtargetInfo &STI) const {
948f9a02500SZoran Jovanovic   // opNum can be invalid if instruction had reglist as operand
949f9a02500SZoran Jovanovic   // MemOperand is always last operand of instruction (base + offset)
950f9a02500SZoran Jovanovic   switch (MI.getOpcode()) {
951f9a02500SZoran Jovanovic   default:
952f9a02500SZoran Jovanovic     break;
953f9a02500SZoran Jovanovic   case Mips::SWM16_MM:
954797c2aecSZlatko Buljan   case Mips::SWM16_MMR6:
955f9a02500SZoran Jovanovic   case Mips::LWM16_MM:
956797c2aecSZlatko Buljan   case Mips::LWM16_MMR6:
957f9a02500SZoran Jovanovic     OpNo = MI.getNumOperands() - 2;
958f9a02500SZoran Jovanovic     break;
959f9a02500SZoran Jovanovic   }
960f9a02500SZoran Jovanovic 
961f9a02500SZoran Jovanovic   // Offset is encoded in bits 4-0.
962f9a02500SZoran Jovanovic   assert(MI.getOperand(OpNo).isReg());
963f9a02500SZoran Jovanovic   // Base register is always SP - thus it is not encoded.
964f9a02500SZoran Jovanovic   assert(MI.getOperand(OpNo+1).isImm());
965f9a02500SZoran Jovanovic   unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI);
966f9a02500SZoran Jovanovic 
967f9a02500SZoran Jovanovic   return ((OffBits >> 2) & 0x0F);
968f9a02500SZoran Jovanovic }
969f9a02500SZoran Jovanovic 
970049e9e4dSAkira Hatanaka // FIXME: should be called getMSBEncoding
971049e9e4dSAkira Hatanaka //
972c85e3ff3SBruno Cardoso Lopes unsigned
973c85e3ff3SBruno Cardoso Lopes MipsMCCodeEmitter::getSizeInsEncoding(const MCInst &MI, unsigned OpNo,
9743fa98a65SDavid Woodhouse                                       SmallVectorImpl<MCFixup> &Fixups,
9753fa98a65SDavid Woodhouse                                       const MCSubtargetInfo &STI) const {
976049e9e4dSAkira Hatanaka   assert(MI.getOperand(OpNo-1).isImm());
977049e9e4dSAkira Hatanaka   assert(MI.getOperand(OpNo).isImm());
9783fa98a65SDavid Woodhouse   unsigned Position = getMachineOpValue(MI, MI.getOperand(OpNo-1), Fixups, STI);
9793fa98a65SDavid Woodhouse   unsigned Size = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI);
980049e9e4dSAkira Hatanaka 
98156b70de0SBruno Cardoso Lopes   return Position + Size - 1;
982c85e3ff3SBruno Cardoso Lopes }
983c85e3ff3SBruno Cardoso Lopes 
984ea4f653dSDaniel Sanders template <unsigned Bits, int Offset>
985779c5937SMatheus Almeida unsigned
986ea4f653dSDaniel Sanders MipsMCCodeEmitter::getUImmWithOffsetEncoding(const MCInst &MI, unsigned OpNo,
9873fa98a65SDavid Woodhouse                                              SmallVectorImpl<MCFixup> &Fixups,
9883fa98a65SDavid Woodhouse                                              const MCSubtargetInfo &STI) const {
989779c5937SMatheus Almeida   assert(MI.getOperand(OpNo).isImm());
990ea4f653dSDaniel Sanders   unsigned Value = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI);
991ea4f653dSDaniel Sanders   Value -= Offset;
992ea4f653dSDaniel Sanders   return Value;
993779c5937SMatheus Almeida }
994779c5937SMatheus Almeida 
995b59e1a41SDaniel Sanders unsigned
996b59e1a41SDaniel Sanders MipsMCCodeEmitter::getSimm19Lsl2Encoding(const MCInst &MI, unsigned OpNo,
997b59e1a41SDaniel Sanders                                          SmallVectorImpl<MCFixup> &Fixups,
998b59e1a41SDaniel Sanders                                          const MCSubtargetInfo &STI) const {
999b9c07f3bSZoran Jovanovic   const MCOperand &MO = MI.getOperand(OpNo);
1000b9c07f3bSZoran Jovanovic   if (MO.isImm()) {
1001b59e1a41SDaniel Sanders     // The immediate is encoded as 'immediate << 2'.
1002b9c07f3bSZoran Jovanovic     unsigned Res = getMachineOpValue(MI, MO, Fixups, STI);
1003b59e1a41SDaniel Sanders     assert((Res & 3) == 0);
1004b59e1a41SDaniel Sanders     return Res >> 2;
1005b59e1a41SDaniel Sanders   }
1006c85e3ff3SBruno Cardoso Lopes 
1007b9c07f3bSZoran Jovanovic   assert(MO.isExpr() &&
1008b9c07f3bSZoran Jovanovic          "getSimm19Lsl2Encoding expects only expressions or an immediate");
1009b9c07f3bSZoran Jovanovic 
1010b9c07f3bSZoran Jovanovic   const MCExpr *Expr = MO.getExpr();
10116764fa78SZoran Jovanovic   Mips::Fixups FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_PC19_S2
10126764fa78SZoran Jovanovic                                             : Mips::fixup_MIPS_PC19_S2;
10136764fa78SZoran Jovanovic   Fixups.push_back(MCFixup::create(0, Expr, MCFixupKind(FixupKind)));
1014b9c07f3bSZoran Jovanovic   return 0;
1015b9c07f3bSZoran Jovanovic }
1016b9c07f3bSZoran Jovanovic 
10172855142aSZoran Jovanovic unsigned
10182855142aSZoran Jovanovic MipsMCCodeEmitter::getSimm18Lsl3Encoding(const MCInst &MI, unsigned OpNo,
10192855142aSZoran Jovanovic                                          SmallVectorImpl<MCFixup> &Fixups,
10202855142aSZoran Jovanovic                                          const MCSubtargetInfo &STI) const {
1021a5acdcf9SZoran Jovanovic   const MCOperand &MO = MI.getOperand(OpNo);
1022a5acdcf9SZoran Jovanovic   if (MO.isImm()) {
10232855142aSZoran Jovanovic     // The immediate is encoded as 'immediate << 3'.
10242855142aSZoran Jovanovic     unsigned Res = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI);
10252855142aSZoran Jovanovic     assert((Res & 7) == 0);
10262855142aSZoran Jovanovic     return Res >> 3;
10272855142aSZoran Jovanovic   }
10282855142aSZoran Jovanovic 
1029a5acdcf9SZoran Jovanovic   assert(MO.isExpr() &&
1030a5acdcf9SZoran Jovanovic          "getSimm18Lsl2Encoding expects only expressions or an immediate");
1031a5acdcf9SZoran Jovanovic 
1032a5acdcf9SZoran Jovanovic   const MCExpr *Expr = MO.getExpr();
10338e366822SZoran Jovanovic   Mips::Fixups FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_PC18_S3
10348e366822SZoran Jovanovic                                             : Mips::fixup_MIPS_PC18_S3;
10358e366822SZoran Jovanovic   Fixups.push_back(MCFixup::create(0, Expr, MCFixupKind(FixupKind)));
1036a5acdcf9SZoran Jovanovic   return 0;
1037a5acdcf9SZoran Jovanovic }
1038a5acdcf9SZoran Jovanovic 
10394a00fdc2SZoran Jovanovic unsigned
10404a00fdc2SZoran Jovanovic MipsMCCodeEmitter::getUImm3Mod8Encoding(const MCInst &MI, unsigned OpNo,
10414a00fdc2SZoran Jovanovic                                         SmallVectorImpl<MCFixup> &Fixups,
10424a00fdc2SZoran Jovanovic                                         const MCSubtargetInfo &STI) const {
10434a00fdc2SZoran Jovanovic   assert(MI.getOperand(OpNo).isImm());
10444a00fdc2SZoran Jovanovic   const MCOperand &MO = MI.getOperand(OpNo);
10454a00fdc2SZoran Jovanovic   return MO.getImm() % 8;
10464a00fdc2SZoran Jovanovic }
10474a00fdc2SZoran Jovanovic 
10488853171bSZoran Jovanovic unsigned
10498853171bSZoran Jovanovic MipsMCCodeEmitter::getUImm4AndValue(const MCInst &MI, unsigned OpNo,
10508853171bSZoran Jovanovic                                     SmallVectorImpl<MCFixup> &Fixups,
10518853171bSZoran Jovanovic                                     const MCSubtargetInfo &STI) const {
10528853171bSZoran Jovanovic   assert(MI.getOperand(OpNo).isImm());
10538853171bSZoran Jovanovic   const MCOperand &MO = MI.getOperand(OpNo);
10548853171bSZoran Jovanovic   unsigned Value = MO.getImm();
10558853171bSZoran Jovanovic   switch (Value) {
10568853171bSZoran Jovanovic     case 128:   return 0x0;
10578853171bSZoran Jovanovic     case 1:     return 0x1;
10588853171bSZoran Jovanovic     case 2:     return 0x2;
10598853171bSZoran Jovanovic     case 3:     return 0x3;
10608853171bSZoran Jovanovic     case 4:     return 0x4;
10618853171bSZoran Jovanovic     case 7:     return 0x5;
10628853171bSZoran Jovanovic     case 8:     return 0x6;
10638853171bSZoran Jovanovic     case 15:    return 0x7;
10648853171bSZoran Jovanovic     case 16:    return 0x8;
10658853171bSZoran Jovanovic     case 31:    return 0x9;
10668853171bSZoran Jovanovic     case 32:    return 0xa;
10678853171bSZoran Jovanovic     case 63:    return 0xb;
10688853171bSZoran Jovanovic     case 64:    return 0xc;
10698853171bSZoran Jovanovic     case 255:   return 0xd;
10708853171bSZoran Jovanovic     case 32768: return 0xe;
10718853171bSZoran Jovanovic     case 65535: return 0xf;
10728853171bSZoran Jovanovic   }
10738853171bSZoran Jovanovic   llvm_unreachable("Unexpected value");
10748853171bSZoran Jovanovic }
10758853171bSZoran Jovanovic 
1076a4c4b5fcSZoran Jovanovic unsigned
1077a4c4b5fcSZoran Jovanovic MipsMCCodeEmitter::getRegisterListOpValue(const MCInst &MI, unsigned OpNo,
1078a4c4b5fcSZoran Jovanovic                                           SmallVectorImpl<MCFixup> &Fixups,
1079a4c4b5fcSZoran Jovanovic                                           const MCSubtargetInfo &STI) const {
1080a4c4b5fcSZoran Jovanovic   unsigned res = 0;
1081a4c4b5fcSZoran Jovanovic 
1082a4c4b5fcSZoran Jovanovic   // Register list operand is always first operand of instruction and it is
1083a4c4b5fcSZoran Jovanovic   // placed before memory operand (register + imm).
1084a4c4b5fcSZoran Jovanovic 
1085a4c4b5fcSZoran Jovanovic   for (unsigned I = OpNo, E = MI.getNumOperands() - 2; I < E; ++I) {
1086a4c4b5fcSZoran Jovanovic     unsigned Reg = MI.getOperand(I).getReg();
1087a4c4b5fcSZoran Jovanovic     unsigned RegNo = Ctx.getRegisterInfo()->getEncodingValue(Reg);
1088a4c4b5fcSZoran Jovanovic     if (RegNo != 31)
1089a4c4b5fcSZoran Jovanovic       res++;
1090a4c4b5fcSZoran Jovanovic     else
1091a4c4b5fcSZoran Jovanovic       res |= 0x10;
1092a4c4b5fcSZoran Jovanovic   }
1093a4c4b5fcSZoran Jovanovic   return res;
1094a4c4b5fcSZoran Jovanovic }
1095a4c4b5fcSZoran Jovanovic 
1096f9a02500SZoran Jovanovic unsigned
1097f9a02500SZoran Jovanovic MipsMCCodeEmitter::getRegisterListOpValue16(const MCInst &MI, unsigned OpNo,
1098f9a02500SZoran Jovanovic                                             SmallVectorImpl<MCFixup> &Fixups,
1099f9a02500SZoran Jovanovic                                             const MCSubtargetInfo &STI) const {
1100f9a02500SZoran Jovanovic   return (MI.getNumOperands() - 4);
1101f9a02500SZoran Jovanovic }
1102f9a02500SZoran Jovanovic 
11032deca348SZoran Jovanovic unsigned
11042deca348SZoran Jovanovic MipsMCCodeEmitter::getRegisterPairOpValue(const MCInst &MI, unsigned OpNo,
11052deca348SZoran Jovanovic                                           SmallVectorImpl<MCFixup> &Fixups,
11062deca348SZoran Jovanovic                                           const MCSubtargetInfo &STI) const {
11072deca348SZoran Jovanovic   return getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI);
11082deca348SZoran Jovanovic }
11092deca348SZoran Jovanovic 
11102c6d7320SJozef Kolek unsigned
111141688679SZoran Jovanovic MipsMCCodeEmitter::getMovePRegPairOpValue(const MCInst &MI, unsigned OpNo,
111241688679SZoran Jovanovic                                           SmallVectorImpl<MCFixup> &Fixups,
111341688679SZoran Jovanovic                                           const MCSubtargetInfo &STI) const {
111441688679SZoran Jovanovic   unsigned res = 0;
111541688679SZoran Jovanovic 
111641688679SZoran Jovanovic   if (MI.getOperand(0).getReg() == Mips::A1 &&
111741688679SZoran Jovanovic       MI.getOperand(1).getReg() == Mips::A2)
111841688679SZoran Jovanovic     res = 0;
111941688679SZoran Jovanovic   else if (MI.getOperand(0).getReg() == Mips::A1 &&
112041688679SZoran Jovanovic            MI.getOperand(1).getReg() == Mips::A3)
112141688679SZoran Jovanovic     res = 1;
112241688679SZoran Jovanovic   else if (MI.getOperand(0).getReg() == Mips::A2 &&
112341688679SZoran Jovanovic            MI.getOperand(1).getReg() == Mips::A3)
112441688679SZoran Jovanovic     res = 2;
112541688679SZoran Jovanovic   else if (MI.getOperand(0).getReg() == Mips::A0 &&
112641688679SZoran Jovanovic            MI.getOperand(1).getReg() == Mips::S5)
112741688679SZoran Jovanovic     res = 3;
112841688679SZoran Jovanovic   else if (MI.getOperand(0).getReg() == Mips::A0 &&
112941688679SZoran Jovanovic            MI.getOperand(1).getReg() == Mips::S6)
113041688679SZoran Jovanovic     res = 4;
113141688679SZoran Jovanovic   else if (MI.getOperand(0).getReg() == Mips::A0 &&
113241688679SZoran Jovanovic            MI.getOperand(1).getReg() == Mips::A1)
113341688679SZoran Jovanovic     res = 5;
113441688679SZoran Jovanovic   else if (MI.getOperand(0).getReg() == Mips::A0 &&
113541688679SZoran Jovanovic            MI.getOperand(1).getReg() == Mips::A2)
113641688679SZoran Jovanovic     res = 6;
113741688679SZoran Jovanovic   else if (MI.getOperand(0).getReg() == Mips::A0 &&
113841688679SZoran Jovanovic            MI.getOperand(1).getReg() == Mips::A3)
113941688679SZoran Jovanovic     res = 7;
114041688679SZoran Jovanovic 
114141688679SZoran Jovanovic   return res;
114241688679SZoran Jovanovic }
114341688679SZoran Jovanovic 
114441688679SZoran Jovanovic unsigned
11452c6d7320SJozef Kolek MipsMCCodeEmitter::getSimm23Lsl2Encoding(const MCInst &MI, unsigned OpNo,
11462c6d7320SJozef Kolek                                          SmallVectorImpl<MCFixup> &Fixups,
11472c6d7320SJozef Kolek                                          const MCSubtargetInfo &STI) const {
11482c6d7320SJozef Kolek   const MCOperand &MO = MI.getOperand(OpNo);
11492c6d7320SJozef Kolek   assert(MO.isImm() && "getSimm23Lsl2Encoding expects only an immediate");
11502c6d7320SJozef Kolek   // The immediate is encoded as 'immediate >> 2'.
11512c6d7320SJozef Kolek   unsigned Res = static_cast<unsigned>(MO.getImm());
11522c6d7320SJozef Kolek   assert((Res & 3) == 0);
11532c6d7320SJozef Kolek   return Res >> 2;
11542c6d7320SJozef Kolek }
11552c6d7320SJozef Kolek 
1156b59e1a41SDaniel Sanders #include "MipsGenMCCodeEmitter.inc"
1157