19f610119SJia Liu //===-- MipsMCCodeEmitter.cpp - Convert Mips Code to Machine Code ---------===//
2750ecec7SAkira Hatanaka //
3750ecec7SAkira Hatanaka //                     The LLVM Compiler Infrastructure
4750ecec7SAkira Hatanaka //
5750ecec7SAkira Hatanaka // This file is distributed under the University of Illinois Open Source
6750ecec7SAkira Hatanaka // License. See LICENSE.TXT for details.
7750ecec7SAkira Hatanaka //
8750ecec7SAkira Hatanaka //===----------------------------------------------------------------------===//
9750ecec7SAkira Hatanaka //
10750ecec7SAkira Hatanaka // This file implements the MipsMCCodeEmitter class.
11750ecec7SAkira Hatanaka //
12750ecec7SAkira Hatanaka //===----------------------------------------------------------------------===//
13750ecec7SAkira Hatanaka //
149e1450bcSMatheus Almeida 
159e1450bcSMatheus Almeida #include "MipsMCCodeEmitter.h"
16c85e3ff3SBruno Cardoso Lopes #include "MCTargetDesc/MipsFixupKinds.h"
17a5da588bSPetar Jovanovic #include "MCTargetDesc/MipsMCExpr.h"
18c85e3ff3SBruno Cardoso Lopes #include "MCTargetDesc/MipsMCTargetDesc.h"
19c85e3ff3SBruno Cardoso Lopes #include "llvm/ADT/APFloat.h"
209e1450bcSMatheus Almeida #include "llvm/ADT/SmallVector.h"
215d6faed1SAkira Hatanaka #include "llvm/MC/MCContext.h"
22750ecec7SAkira Hatanaka #include "llvm/MC/MCExpr.h"
23d9903888SChandler Carruth #include "llvm/MC/MCFixup.h"
24750ecec7SAkira Hatanaka #include "llvm/MC/MCInst.h"
25750ecec7SAkira Hatanaka #include "llvm/MC/MCInstrInfo.h"
263de83e40SPete Cooper #include "llvm/MC/MCRegisterInfo.h"
27750ecec7SAkira Hatanaka #include "llvm/MC/MCSubtargetInfo.h"
28750ecec7SAkira Hatanaka #include "llvm/Support/raw_ostream.h"
29750ecec7SAkira Hatanaka 
3084e68b29SChandler Carruth #define DEBUG_TYPE "mccodeemitter"
3184e68b29SChandler Carruth 
32be6a818fSAkira Hatanaka #define GET_INSTRMAP_INFO
33be6a818fSAkira Hatanaka #include "MipsGenInstrInfo.inc"
349e1450bcSMatheus Almeida #undef GET_INSTRMAP_INFO
35be6a818fSAkira Hatanaka 
369e1450bcSMatheus Almeida namespace llvm {
379e1450bcSMatheus Almeida MCCodeEmitter *createMipsMCCodeEmitterEB(const MCInstrInfo &MCII,
38c3b04279SJim Grosbach                                          const MCRegisterInfo &MRI,
399e1450bcSMatheus Almeida                                          MCContext &Ctx) {
40d2cca113SDavid Woodhouse   return new MipsMCCodeEmitter(MCII, Ctx, false);
411ee768dbSAkira Hatanaka }
421ee768dbSAkira Hatanaka 
439e1450bcSMatheus Almeida MCCodeEmitter *createMipsMCCodeEmitterEL(const MCInstrInfo &MCII,
44c3b04279SJim Grosbach                                          const MCRegisterInfo &MRI,
459e1450bcSMatheus Almeida                                          MCContext &Ctx) {
46d2cca113SDavid Woodhouse   return new MipsMCCodeEmitter(MCII, Ctx, true);
47750ecec7SAkira Hatanaka }
489e1450bcSMatheus Almeida } // End of namespace llvm.
49f30f2cceSRafael Espindola 
50f30f2cceSRafael Espindola // If the D<shift> instruction has a shift amount that is greater
51f30f2cceSRafael Espindola // than 31 (checked in calling routine), lower it to a D<shift>32 instruction
52f30f2cceSRafael Espindola static void LowerLargeShift(MCInst& Inst) {
53f30f2cceSRafael Espindola 
54f30f2cceSRafael Espindola   assert(Inst.getNumOperands() == 3 && "Invalid no. of operands for shift!");
55f30f2cceSRafael Espindola   assert(Inst.getOperand(2).isImm());
56f30f2cceSRafael Espindola 
57f30f2cceSRafael Espindola   int64_t Shift = Inst.getOperand(2).getImm();
58f30f2cceSRafael Espindola   if (Shift <= 31)
59f30f2cceSRafael Espindola     return; // Do nothing
60f30f2cceSRafael Espindola   Shift -= 32;
61f30f2cceSRafael Espindola 
62f30f2cceSRafael Espindola   // saminus32
63f30f2cceSRafael Espindola   Inst.getOperand(2).setImm(Shift);
64f30f2cceSRafael Espindola 
65f30f2cceSRafael Espindola   switch (Inst.getOpcode()) {
66f30f2cceSRafael Espindola   default:
67f30f2cceSRafael Espindola     // Calling function is not synchronized
68f30f2cceSRafael Espindola     llvm_unreachable("Unexpected shift instruction");
69f30f2cceSRafael Espindola   case Mips::DSLL:
70f30f2cceSRafael Espindola     Inst.setOpcode(Mips::DSLL32);
71f30f2cceSRafael Espindola     return;
72f30f2cceSRafael Espindola   case Mips::DSRL:
73f30f2cceSRafael Espindola     Inst.setOpcode(Mips::DSRL32);
74f30f2cceSRafael Espindola     return;
75f30f2cceSRafael Espindola   case Mips::DSRA:
76f30f2cceSRafael Espindola     Inst.setOpcode(Mips::DSRA32);
77f30f2cceSRafael Espindola     return;
786a3fe574SAkira Hatanaka   case Mips::DROTR:
796a3fe574SAkira Hatanaka     Inst.setOpcode(Mips::DROTR32);
806a3fe574SAkira Hatanaka     return;
81f30f2cceSRafael Espindola   }
82f30f2cceSRafael Espindola }
83f30f2cceSRafael Espindola 
84611eb829SDaniel Sanders // Pick a DINS instruction variant based on the pos and size operands
85611eb829SDaniel Sanders static void LowerDins(MCInst& InstIn) {
86f30f2cceSRafael Espindola   assert(InstIn.getNumOperands() == 5 &&
87f30f2cceSRafael Espindola          "Invalid no. of machine operands for DINS!");
88f30f2cceSRafael Espindola 
89f30f2cceSRafael Espindola   assert(InstIn.getOperand(2).isImm());
90f30f2cceSRafael Espindola   int64_t pos = InstIn.getOperand(2).getImm();
91f30f2cceSRafael Espindola   assert(InstIn.getOperand(3).isImm());
92f30f2cceSRafael Espindola   int64_t size = InstIn.getOperand(3).getImm();
93f30f2cceSRafael Espindola 
94f30f2cceSRafael Espindola   if (size <= 32) {
95611eb829SDaniel Sanders     if (pos < 32)  // DINS, do nothing
96f30f2cceSRafael Espindola       return;
97611eb829SDaniel Sanders     // DINSU
98f30f2cceSRafael Espindola     InstIn.getOperand(2).setImm(pos - 32);
99611eb829SDaniel Sanders     InstIn.setOpcode(Mips::DINSU);
100f30f2cceSRafael Espindola     return;
101f30f2cceSRafael Espindola   }
102611eb829SDaniel Sanders   // DINSM
103611eb829SDaniel Sanders   assert(pos < 32 && "DINS cannot have both size and pos > 32");
104f30f2cceSRafael Espindola   InstIn.getOperand(3).setImm(size - 32);
105611eb829SDaniel Sanders   InstIn.setOpcode(Mips::DINSM);
106f30f2cceSRafael Espindola   return;
107f30f2cceSRafael Espindola }
108f30f2cceSRafael Espindola 
1099e1450bcSMatheus Almeida bool MipsMCCodeEmitter::isMicroMips(const MCSubtargetInfo &STI) const {
110db0712f9SMichael Kuperstein   return STI.getFeatureBits()[Mips::FeatureMicroMips];
1119e1450bcSMatheus Almeida }
1129e1450bcSMatheus Almeida 
113c22555d9SJozef Kolek bool MipsMCCodeEmitter::isMips32r6(const MCSubtargetInfo &STI) const {
114db0712f9SMichael Kuperstein   return STI.getFeatureBits()[Mips::FeatureMips32r6];
115c22555d9SJozef Kolek }
116c22555d9SJozef Kolek 
1179e1450bcSMatheus Almeida void MipsMCCodeEmitter::EmitByte(unsigned char C, raw_ostream &OS) const {
1189e1450bcSMatheus Almeida   OS << (char)C;
1199e1450bcSMatheus Almeida }
1209e1450bcSMatheus Almeida 
1219e1450bcSMatheus Almeida void MipsMCCodeEmitter::EmitInstruction(uint64_t Val, unsigned Size,
1229e1450bcSMatheus Almeida                                         const MCSubtargetInfo &STI,
1239e1450bcSMatheus Almeida                                         raw_ostream &OS) const {
1249e1450bcSMatheus Almeida   // Output the instruction encoding in little endian byte order.
1259e1450bcSMatheus Almeida   // Little-endian byte ordering:
1269e1450bcSMatheus Almeida   //   mips32r2:   4 | 3 | 2 | 1
1279e1450bcSMatheus Almeida   //   microMIPS:  2 | 1 | 4 | 3
1289e1450bcSMatheus Almeida   if (IsLittleEndian && Size == 4 && isMicroMips(STI)) {
1299e1450bcSMatheus Almeida     EmitInstruction(Val >> 16, 2, STI, OS);
1309e1450bcSMatheus Almeida     EmitInstruction(Val, 2, STI, OS);
1319e1450bcSMatheus Almeida   } else {
1329e1450bcSMatheus Almeida     for (unsigned i = 0; i < Size; ++i) {
1339e1450bcSMatheus Almeida       unsigned Shift = IsLittleEndian ? i * 8 : (Size - 1 - i) * 8;
1349e1450bcSMatheus Almeida       EmitByte((Val >> Shift) & 0xff, OS);
1359e1450bcSMatheus Almeida     }
1369e1450bcSMatheus Almeida   }
1379e1450bcSMatheus Almeida }
1389e1450bcSMatheus Almeida 
13991df21f7SJim Grosbach /// encodeInstruction - Emit the instruction.
1404e07b95dSJack Carter /// Size the instruction with Desc.getSize().
141c85e3ff3SBruno Cardoso Lopes void MipsMCCodeEmitter::
14291df21f7SJim Grosbach encodeInstruction(const MCInst &MI, raw_ostream &OS,
1439784cef3SDavid Woodhouse                   SmallVectorImpl<MCFixup> &Fixups,
1449784cef3SDavid Woodhouse                   const MCSubtargetInfo &STI) const
145c85e3ff3SBruno Cardoso Lopes {
146aa7aeaa0SJack Carter 
147aa7aeaa0SJack Carter   // Non-pseudo instructions that get changed for direct object
148aa7aeaa0SJack Carter   // only based on operand values.
149aa7aeaa0SJack Carter   // If this list of instructions get much longer we will move
150aa7aeaa0SJack Carter   // the check to a function call. Until then, this is more efficient.
151aa7aeaa0SJack Carter   MCInst TmpInst = MI;
152aa7aeaa0SJack Carter   switch (MI.getOpcode()) {
153aa7aeaa0SJack Carter   // If shift amount is >= 32 it the inst needs to be lowered further
154aa7aeaa0SJack Carter   case Mips::DSLL:
155aa7aeaa0SJack Carter   case Mips::DSRL:
156aa7aeaa0SJack Carter   case Mips::DSRA:
1576a3fe574SAkira Hatanaka   case Mips::DROTR:
158f30f2cceSRafael Espindola     LowerLargeShift(TmpInst);
159aa7aeaa0SJack Carter     break;
160aa7aeaa0SJack Carter     // Double extract instruction is chosen by pos and size operands
161aa7aeaa0SJack Carter   case Mips::DINS:
162611eb829SDaniel Sanders     LowerDins(TmpInst);
163aa7aeaa0SJack Carter   }
164aa7aeaa0SJack Carter 
16597700977SJack Carter   unsigned long N = Fixups.size();
1663fa98a65SDavid Woodhouse   uint32_t Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);
167c85e3ff3SBruno Cardoso Lopes 
168c85e3ff3SBruno Cardoso Lopes   // Check for unimplemented opcodes.
169aa7aeaa0SJack Carter   // Unfortunately in MIPS both NOP and SLL will come in with Binary == 0
170c85e3ff3SBruno Cardoso Lopes   // so we have to special check for them.
171aa7aeaa0SJack Carter   unsigned Opcode = TmpInst.getOpcode();
172c7e220f6SJozef Kolek   if ((Opcode != Mips::NOP) && (Opcode != Mips::SLL) &&
173c7e220f6SJozef Kolek       (Opcode != Mips::SLL_MM) && !Binary)
17491df21f7SJim Grosbach     llvm_unreachable("unimplemented opcode in encodeInstruction()");
175c85e3ff3SBruno Cardoso Lopes 
176b59a5419SZoran Jovanovic   int NewOpcode = -1;
1776ca13eafSJozef Kolek   if (isMicroMips(STI)) {
178b59a5419SZoran Jovanovic     if (isMips32r6(STI)) {
179b59a5419SZoran Jovanovic       NewOpcode = Mips::MipsR62MicroMipsR6(Opcode, Mips::Arch_micromipsr6);
180b59a5419SZoran Jovanovic       if (NewOpcode == -1)
181b59a5419SZoran Jovanovic         NewOpcode = Mips::Std2MicroMipsR6(Opcode, Mips::Arch_micromipsr6);
182b59a5419SZoran Jovanovic     }
183b59a5419SZoran Jovanovic     else
184b59a5419SZoran Jovanovic       NewOpcode = Mips::Std2MicroMips(Opcode, Mips::Arch_micromips);
185b59a5419SZoran Jovanovic 
1862e386d3dSZoran Jovanovic     // Check whether it is Dsp instruction.
1872e386d3dSZoran Jovanovic     if (NewOpcode == -1)
1882e386d3dSZoran Jovanovic       NewOpcode = Mips::Dsp2MicroMips(Opcode, Mips::Arch_mmdsp);
1892e386d3dSZoran Jovanovic 
190be6a818fSAkira Hatanaka     if (NewOpcode != -1) {
19197700977SJack Carter       if (Fixups.size() > N)
19297700977SJack Carter         Fixups.pop_back();
193b59a5419SZoran Jovanovic 
194be6a818fSAkira Hatanaka       Opcode = NewOpcode;
195be6a818fSAkira Hatanaka       TmpInst.setOpcode (NewOpcode);
1963fa98a65SDavid Woodhouse       Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);
197be6a818fSAkira Hatanaka     }
198be6a818fSAkira Hatanaka   }
199be6a818fSAkira Hatanaka 
200aa7aeaa0SJack Carter   const MCInstrDesc &Desc = MCII.get(TmpInst.getOpcode());
201c85e3ff3SBruno Cardoso Lopes 
2025b5559d3SJack Carter   // Get byte count of instruction
2035b5559d3SJack Carter   unsigned Size = Desc.getSize();
2045b5559d3SJack Carter   if (!Size)
2055b5559d3SJack Carter     llvm_unreachable("Desc.getSize() returns 0");
206c85e3ff3SBruno Cardoso Lopes 
207d2cca113SDavid Woodhouse   EmitInstruction(Binary, Size, STI, OS);
208c85e3ff3SBruno Cardoso Lopes }
209c85e3ff3SBruno Cardoso Lopes 
210c85e3ff3SBruno Cardoso Lopes /// getBranchTargetOpValue - Return binary encoding of the branch
211c85e3ff3SBruno Cardoso Lopes /// target operand. If the machine operand requires relocation,
212c85e3ff3SBruno Cardoso Lopes /// record the relocation and return zero.
213c85e3ff3SBruno Cardoso Lopes unsigned MipsMCCodeEmitter::
214c85e3ff3SBruno Cardoso Lopes getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
2153fa98a65SDavid Woodhouse                        SmallVectorImpl<MCFixup> &Fixups,
2163fa98a65SDavid Woodhouse                        const MCSubtargetInfo &STI) const {
217c85e3ff3SBruno Cardoso Lopes 
218c85e3ff3SBruno Cardoso Lopes   const MCOperand &MO = MI.getOperand(OpNo);
21971e6a749SJack Carter 
2204f69a0f2SJack Carter   // If the destination is an immediate, divide by 4.
2214f69a0f2SJack Carter   if (MO.isImm()) return MO.getImm() >> 2;
2224f69a0f2SJack Carter 
22371e6a749SJack Carter   assert(MO.isExpr() &&
22471e6a749SJack Carter          "getBranchTargetOpValue expects only expressions or immediates");
225c85e3ff3SBruno Cardoso Lopes 
226b7915a1fSPetar Jovanovic   const MCExpr *FixupExpression = MCBinaryExpr::createAdd(
227b7915a1fSPetar Jovanovic       MO.getExpr(), MCConstantExpr::create(-4, Ctx), Ctx);
228b7915a1fSPetar Jovanovic   Fixups.push_back(MCFixup::create(0, FixupExpression,
229c85e3ff3SBruno Cardoso Lopes                                    MCFixupKind(Mips::fixup_Mips_PC16)));
230c85e3ff3SBruno Cardoso Lopes   return 0;
231c85e3ff3SBruno Cardoso Lopes }
232c85e3ff3SBruno Cardoso Lopes 
2336f09cdfdSHrvoje Varga /// getBranchTargetOpValue1SImm16 - Return binary encoding of the branch
2346f09cdfdSHrvoje Varga /// target operand. If the machine operand requires relocation,
2356f09cdfdSHrvoje Varga /// record the relocation and return zero.
2366f09cdfdSHrvoje Varga unsigned MipsMCCodeEmitter::
2376f09cdfdSHrvoje Varga getBranchTargetOpValue1SImm16(const MCInst &MI, unsigned OpNo,
2386f09cdfdSHrvoje Varga                               SmallVectorImpl<MCFixup> &Fixups,
2396f09cdfdSHrvoje Varga                               const MCSubtargetInfo &STI) const {
2406f09cdfdSHrvoje Varga 
2416f09cdfdSHrvoje Varga   const MCOperand &MO = MI.getOperand(OpNo);
2426f09cdfdSHrvoje Varga 
2436f09cdfdSHrvoje Varga   // If the destination is an immediate, divide by 2.
2446f09cdfdSHrvoje Varga   if (MO.isImm()) return MO.getImm() >> 1;
2456f09cdfdSHrvoje Varga 
2466f09cdfdSHrvoje Varga   assert(MO.isExpr() &&
2476f09cdfdSHrvoje Varga          "getBranchTargetOpValue expects only expressions or immediates");
2486f09cdfdSHrvoje Varga 
2496f09cdfdSHrvoje Varga   const MCExpr *FixupExpression = MCBinaryExpr::createAdd(
2506f09cdfdSHrvoje Varga       MO.getExpr(), MCConstantExpr::create(-4, Ctx), Ctx);
2516f09cdfdSHrvoje Varga   Fixups.push_back(MCFixup::create(0, FixupExpression,
2526f09cdfdSHrvoje Varga                                    MCFixupKind(Mips::fixup_Mips_PC16)));
2536f09cdfdSHrvoje Varga   return 0;
2546f09cdfdSHrvoje Varga }
2556f09cdfdSHrvoje Varga 
2569761e96bSJozef Kolek /// getBranchTarget7OpValueMM - Return binary encoding of the microMIPS branch
2579761e96bSJozef Kolek /// target operand. If the machine operand requires relocation,
2589761e96bSJozef Kolek /// record the relocation and return zero.
2599761e96bSJozef Kolek unsigned MipsMCCodeEmitter::
2609761e96bSJozef Kolek getBranchTarget7OpValueMM(const MCInst &MI, unsigned OpNo,
2619761e96bSJozef Kolek                           SmallVectorImpl<MCFixup> &Fixups,
2629761e96bSJozef Kolek                           const MCSubtargetInfo &STI) const {
2639761e96bSJozef Kolek 
2649761e96bSJozef Kolek   const MCOperand &MO = MI.getOperand(OpNo);
2659761e96bSJozef Kolek 
2669761e96bSJozef Kolek   // If the destination is an immediate, divide by 2.
2679761e96bSJozef Kolek   if (MO.isImm()) return MO.getImm() >> 1;
2689761e96bSJozef Kolek 
2699761e96bSJozef Kolek   assert(MO.isExpr() &&
2709761e96bSJozef Kolek          "getBranchTargetOpValueMM expects only expressions or immediates");
2719761e96bSJozef Kolek 
2729761e96bSJozef Kolek   const MCExpr *Expr = MO.getExpr();
27363661f8dSJim Grosbach   Fixups.push_back(MCFixup::create(0, Expr,
2749761e96bSJozef Kolek                                    MCFixupKind(Mips::fixup_MICROMIPS_PC7_S1)));
2759761e96bSJozef Kolek   return 0;
2769761e96bSJozef Kolek }
2779761e96bSJozef Kolek 
2785cfebddeSJozef Kolek /// getBranchTargetOpValueMMPC10 - Return binary encoding of the microMIPS
2795cfebddeSJozef Kolek /// 10-bit branch target operand. If the machine operand requires relocation,
2805cfebddeSJozef Kolek /// record the relocation and return zero.
2815cfebddeSJozef Kolek unsigned MipsMCCodeEmitter::
2825cfebddeSJozef Kolek getBranchTargetOpValueMMPC10(const MCInst &MI, unsigned OpNo,
2835cfebddeSJozef Kolek                              SmallVectorImpl<MCFixup> &Fixups,
2845cfebddeSJozef Kolek                              const MCSubtargetInfo &STI) const {
2855cfebddeSJozef Kolek 
2865cfebddeSJozef Kolek   const MCOperand &MO = MI.getOperand(OpNo);
2875cfebddeSJozef Kolek 
2885cfebddeSJozef Kolek   // If the destination is an immediate, divide by 2.
2895cfebddeSJozef Kolek   if (MO.isImm()) return MO.getImm() >> 1;
2905cfebddeSJozef Kolek 
2915cfebddeSJozef Kolek   assert(MO.isExpr() &&
2925cfebddeSJozef Kolek          "getBranchTargetOpValuePC10 expects only expressions or immediates");
2935cfebddeSJozef Kolek 
2945cfebddeSJozef Kolek   const MCExpr *Expr = MO.getExpr();
29563661f8dSJim Grosbach   Fixups.push_back(MCFixup::create(0, Expr,
2965cfebddeSJozef Kolek                    MCFixupKind(Mips::fixup_MICROMIPS_PC10_S1)));
2975cfebddeSJozef Kolek   return 0;
2985cfebddeSJozef Kolek }
2995cfebddeSJozef Kolek 
3008a80aa76SZoran Jovanovic /// getBranchTargetOpValue - Return binary encoding of the microMIPS branch
3018a80aa76SZoran Jovanovic /// target operand. If the machine operand requires relocation,
3028a80aa76SZoran Jovanovic /// record the relocation and return zero.
3038a80aa76SZoran Jovanovic unsigned MipsMCCodeEmitter::
3048a80aa76SZoran Jovanovic getBranchTargetOpValueMM(const MCInst &MI, unsigned OpNo,
3053fa98a65SDavid Woodhouse                          SmallVectorImpl<MCFixup> &Fixups,
3063fa98a65SDavid Woodhouse                          const MCSubtargetInfo &STI) const {
3078a80aa76SZoran Jovanovic 
3088a80aa76SZoran Jovanovic   const MCOperand &MO = MI.getOperand(OpNo);
3098a80aa76SZoran Jovanovic 
3108a80aa76SZoran Jovanovic   // If the destination is an immediate, divide by 2.
3118a80aa76SZoran Jovanovic   if (MO.isImm()) return MO.getImm() >> 1;
3128a80aa76SZoran Jovanovic 
3138a80aa76SZoran Jovanovic   assert(MO.isExpr() &&
3148a80aa76SZoran Jovanovic          "getBranchTargetOpValueMM expects only expressions or immediates");
3158a80aa76SZoran Jovanovic 
3168a80aa76SZoran Jovanovic   const MCExpr *Expr = MO.getExpr();
31763661f8dSJim Grosbach   Fixups.push_back(MCFixup::create(0, Expr,
3188a80aa76SZoran Jovanovic                    MCFixupKind(Mips::
3198a80aa76SZoran Jovanovic                                fixup_MICROMIPS_PC16_S1)));
3208a80aa76SZoran Jovanovic   return 0;
3218a80aa76SZoran Jovanovic }
3228a80aa76SZoran Jovanovic 
3233c8869dcSZoran Jovanovic /// getBranchTarget21OpValue - Return binary encoding of the branch
3243c8869dcSZoran Jovanovic /// target operand. If the machine operand requires relocation,
3253c8869dcSZoran Jovanovic /// record the relocation and return zero.
3263c8869dcSZoran Jovanovic unsigned MipsMCCodeEmitter::
3273c8869dcSZoran Jovanovic getBranchTarget21OpValue(const MCInst &MI, unsigned OpNo,
3283c8869dcSZoran Jovanovic                          SmallVectorImpl<MCFixup> &Fixups,
3293c8869dcSZoran Jovanovic                          const MCSubtargetInfo &STI) const {
3303c8869dcSZoran Jovanovic 
3313c8869dcSZoran Jovanovic   const MCOperand &MO = MI.getOperand(OpNo);
3323c8869dcSZoran Jovanovic 
3333c8869dcSZoran Jovanovic   // If the destination is an immediate, divide by 4.
3343c8869dcSZoran Jovanovic   if (MO.isImm()) return MO.getImm() >> 2;
3353c8869dcSZoran Jovanovic 
3363c8869dcSZoran Jovanovic   assert(MO.isExpr() &&
3373c8869dcSZoran Jovanovic          "getBranchTarget21OpValue expects only expressions or immediates");
3383c8869dcSZoran Jovanovic 
339b7915a1fSPetar Jovanovic   const MCExpr *FixupExpression = MCBinaryExpr::createAdd(
340b7915a1fSPetar Jovanovic       MO.getExpr(), MCConstantExpr::create(-4, Ctx), Ctx);
341b7915a1fSPetar Jovanovic   Fixups.push_back(MCFixup::create(0, FixupExpression,
34210e06da0SZoran Jovanovic                                    MCFixupKind(Mips::fixup_MIPS_PC21_S2)));
3433c8869dcSZoran Jovanovic   return 0;
3443c8869dcSZoran Jovanovic }
3453c8869dcSZoran Jovanovic 
346*84e4d59eSZoran Jovanovic /// getBranchTarget21OpValueMM - Return binary encoding of the branch
347*84e4d59eSZoran Jovanovic /// target operand for microMIPS. If the machine operand requires
348*84e4d59eSZoran Jovanovic /// relocation, record the relocation and return zero.
349*84e4d59eSZoran Jovanovic unsigned MipsMCCodeEmitter::
350*84e4d59eSZoran Jovanovic getBranchTarget21OpValueMM(const MCInst &MI, unsigned OpNo,
351*84e4d59eSZoran Jovanovic                            SmallVectorImpl<MCFixup> &Fixups,
352*84e4d59eSZoran Jovanovic                            const MCSubtargetInfo &STI) const {
353*84e4d59eSZoran Jovanovic 
354*84e4d59eSZoran Jovanovic   const MCOperand &MO = MI.getOperand(OpNo);
355*84e4d59eSZoran Jovanovic 
356*84e4d59eSZoran Jovanovic   // If the destination is an immediate, divide by 2.
357*84e4d59eSZoran Jovanovic   if (MO.isImm()) return MO.getImm() >> 1;
358*84e4d59eSZoran Jovanovic 
359*84e4d59eSZoran Jovanovic   assert(MO.isExpr() &&
360*84e4d59eSZoran Jovanovic     "getBranchTarget21OpValueMM expects only expressions or immediates");
361*84e4d59eSZoran Jovanovic 
362*84e4d59eSZoran Jovanovic   // TODO: Push fixup.
363*84e4d59eSZoran Jovanovic   return 0;
364*84e4d59eSZoran Jovanovic }
365*84e4d59eSZoran Jovanovic 
3663c8869dcSZoran Jovanovic /// getBranchTarget26OpValue - Return binary encoding of the branch
3673c8869dcSZoran Jovanovic /// target operand. If the machine operand requires relocation,
3683c8869dcSZoran Jovanovic /// record the relocation and return zero.
3693c8869dcSZoran Jovanovic unsigned MipsMCCodeEmitter::
3703c8869dcSZoran Jovanovic getBranchTarget26OpValue(const MCInst &MI, unsigned OpNo,
3713c8869dcSZoran Jovanovic                          SmallVectorImpl<MCFixup> &Fixups,
3723c8869dcSZoran Jovanovic                          const MCSubtargetInfo &STI) const {
3733c8869dcSZoran Jovanovic 
3743c8869dcSZoran Jovanovic   const MCOperand &MO = MI.getOperand(OpNo);
3753c8869dcSZoran Jovanovic 
3763c8869dcSZoran Jovanovic   // If the destination is an immediate, divide by 4.
3773c8869dcSZoran Jovanovic   if (MO.isImm()) return MO.getImm() >> 2;
3783c8869dcSZoran Jovanovic 
3793c8869dcSZoran Jovanovic   assert(MO.isExpr() &&
3803c8869dcSZoran Jovanovic          "getBranchTarget26OpValue expects only expressions or immediates");
3813c8869dcSZoran Jovanovic 
382b7915a1fSPetar Jovanovic   const MCExpr *FixupExpression = MCBinaryExpr::createAdd(
383b7915a1fSPetar Jovanovic       MO.getExpr(), MCConstantExpr::create(-4, Ctx), Ctx);
384b7915a1fSPetar Jovanovic   Fixups.push_back(MCFixup::create(0, FixupExpression,
38510e06da0SZoran Jovanovic                                    MCFixupKind(Mips::fixup_MIPS_PC26_S2)));
3863c8869dcSZoran Jovanovic   return 0;
3873c8869dcSZoran Jovanovic }
3883c8869dcSZoran Jovanovic 
389a887b361SZoran Jovanovic /// getBranchTarget26OpValueMM - Return binary encoding of the branch
390a887b361SZoran Jovanovic /// target operand. If the machine operand requires relocation,
391a887b361SZoran Jovanovic /// record the relocation and return zero.
392a887b361SZoran Jovanovic unsigned MipsMCCodeEmitter::getBranchTarget26OpValueMM(
393a887b361SZoran Jovanovic     const MCInst &MI, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups,
394a887b361SZoran Jovanovic     const MCSubtargetInfo &STI) const {
395a887b361SZoran Jovanovic 
396a887b361SZoran Jovanovic   const MCOperand &MO = MI.getOperand(OpNo);
397a887b361SZoran Jovanovic 
398a887b361SZoran Jovanovic   // If the destination is an immediate, divide by 2.
399a887b361SZoran Jovanovic   if (MO.isImm())
400a887b361SZoran Jovanovic     return MO.getImm() >> 1;
401a887b361SZoran Jovanovic 
40202b70030SZoran Jovanovic   assert(MO.isExpr() &&
40302b70030SZoran Jovanovic          "getBranchTarget26OpValueMM expects only expressions or immediates");
40402b70030SZoran Jovanovic 
40502b70030SZoran Jovanovic   const MCExpr *FixupExpression = MCBinaryExpr::createAdd(
40602b70030SZoran Jovanovic       MO.getExpr(), MCConstantExpr::create(-4, Ctx), Ctx);
40702b70030SZoran Jovanovic   Fixups.push_back(MCFixup::create(0, FixupExpression,
40802b70030SZoran Jovanovic                                    MCFixupKind(Mips::fixup_MICROMIPS_PC26_S1)));
409a887b361SZoran Jovanovic   return 0;
410a887b361SZoran Jovanovic }
411a887b361SZoran Jovanovic 
41252c56b93SZoran Jovanovic /// getJumpOffset16OpValue - Return binary encoding of the jump
41352c56b93SZoran Jovanovic /// target operand. If the machine operand requires relocation,
41452c56b93SZoran Jovanovic /// record the relocation and return zero.
41552c56b93SZoran Jovanovic unsigned MipsMCCodeEmitter::
41652c56b93SZoran Jovanovic getJumpOffset16OpValue(const MCInst &MI, unsigned OpNo,
41752c56b93SZoran Jovanovic                        SmallVectorImpl<MCFixup> &Fixups,
41852c56b93SZoran Jovanovic                        const MCSubtargetInfo &STI) const {
41952c56b93SZoran Jovanovic 
42052c56b93SZoran Jovanovic   const MCOperand &MO = MI.getOperand(OpNo);
42152c56b93SZoran Jovanovic 
42252c56b93SZoran Jovanovic   if (MO.isImm()) return MO.getImm();
42352c56b93SZoran Jovanovic 
42452c56b93SZoran Jovanovic   assert(MO.isExpr() &&
42552c56b93SZoran Jovanovic          "getJumpOffset16OpValue expects only expressions or an immediate");
42652c56b93SZoran Jovanovic 
42752c56b93SZoran Jovanovic    // TODO: Push fixup.
42852c56b93SZoran Jovanovic    return 0;
42952c56b93SZoran Jovanovic }
43052c56b93SZoran Jovanovic 
431c85e3ff3SBruno Cardoso Lopes /// getJumpTargetOpValue - Return binary encoding of the jump
432c85e3ff3SBruno Cardoso Lopes /// target operand. If the machine operand requires relocation,
433c85e3ff3SBruno Cardoso Lopes /// record the relocation and return zero.
434c85e3ff3SBruno Cardoso Lopes unsigned MipsMCCodeEmitter::
435c85e3ff3SBruno Cardoso Lopes getJumpTargetOpValue(const MCInst &MI, unsigned OpNo,
4363fa98a65SDavid Woodhouse                      SmallVectorImpl<MCFixup> &Fixups,
4373fa98a65SDavid Woodhouse                      const MCSubtargetInfo &STI) const {
438c85e3ff3SBruno Cardoso Lopes 
439c85e3ff3SBruno Cardoso Lopes   const MCOperand &MO = MI.getOperand(OpNo);
4404f69a0f2SJack Carter   // If the destination is an immediate, divide by 4.
4414f69a0f2SJack Carter   if (MO.isImm()) return MO.getImm()>>2;
4424f69a0f2SJack Carter 
44371e6a749SJack Carter   assert(MO.isExpr() &&
44471e6a749SJack Carter          "getJumpTargetOpValue expects only expressions or an immediate");
445c85e3ff3SBruno Cardoso Lopes 
446c85e3ff3SBruno Cardoso Lopes   const MCExpr *Expr = MO.getExpr();
44763661f8dSJim Grosbach   Fixups.push_back(MCFixup::create(0, Expr,
448c85e3ff3SBruno Cardoso Lopes                                    MCFixupKind(Mips::fixup_Mips_26)));
449c85e3ff3SBruno Cardoso Lopes   return 0;
450c85e3ff3SBruno Cardoso Lopes }
451c85e3ff3SBruno Cardoso Lopes 
452c85e3ff3SBruno Cardoso Lopes unsigned MipsMCCodeEmitter::
453507e084aSZoran Jovanovic getJumpTargetOpValueMM(const MCInst &MI, unsigned OpNo,
4543fa98a65SDavid Woodhouse                        SmallVectorImpl<MCFixup> &Fixups,
4553fa98a65SDavid Woodhouse                        const MCSubtargetInfo &STI) const {
456507e084aSZoran Jovanovic 
457507e084aSZoran Jovanovic   const MCOperand &MO = MI.getOperand(OpNo);
458507e084aSZoran Jovanovic   // If the destination is an immediate, divide by 2.
459507e084aSZoran Jovanovic   if (MO.isImm()) return MO.getImm() >> 1;
460507e084aSZoran Jovanovic 
461507e084aSZoran Jovanovic   assert(MO.isExpr() &&
462507e084aSZoran Jovanovic          "getJumpTargetOpValueMM expects only expressions or an immediate");
463507e084aSZoran Jovanovic 
464507e084aSZoran Jovanovic   const MCExpr *Expr = MO.getExpr();
46563661f8dSJim Grosbach   Fixups.push_back(MCFixup::create(0, Expr,
466507e084aSZoran Jovanovic                                    MCFixupKind(Mips::fixup_MICROMIPS_26_S1)));
467507e084aSZoran Jovanovic   return 0;
468507e084aSZoran Jovanovic }
469507e084aSZoran Jovanovic 
470507e084aSZoran Jovanovic unsigned MipsMCCodeEmitter::
471c74e3eb9SZoran Jovanovic getUImm5Lsl2Encoding(const MCInst &MI, unsigned OpNo,
472c74e3eb9SZoran Jovanovic                      SmallVectorImpl<MCFixup> &Fixups,
473c74e3eb9SZoran Jovanovic                      const MCSubtargetInfo &STI) const {
474c74e3eb9SZoran Jovanovic 
475c74e3eb9SZoran Jovanovic   const MCOperand &MO = MI.getOperand(OpNo);
476c74e3eb9SZoran Jovanovic   if (MO.isImm()) {
477c74e3eb9SZoran Jovanovic     // The immediate is encoded as 'immediate << 2'.
478c74e3eb9SZoran Jovanovic     unsigned Res = getMachineOpValue(MI, MO, Fixups, STI);
479c74e3eb9SZoran Jovanovic     assert((Res & 3) == 0);
480c74e3eb9SZoran Jovanovic     return Res >> 2;
481c74e3eb9SZoran Jovanovic   }
482c74e3eb9SZoran Jovanovic 
483c74e3eb9SZoran Jovanovic   assert(MO.isExpr() &&
484c74e3eb9SZoran Jovanovic          "getUImm5Lsl2Encoding expects only expressions or an immediate");
485c74e3eb9SZoran Jovanovic 
486c74e3eb9SZoran Jovanovic   return 0;
487c74e3eb9SZoran Jovanovic }
488c74e3eb9SZoran Jovanovic 
489c74e3eb9SZoran Jovanovic unsigned MipsMCCodeEmitter::
490bac3619bSZoran Jovanovic getSImm3Lsa2Value(const MCInst &MI, unsigned OpNo,
491bac3619bSZoran Jovanovic                   SmallVectorImpl<MCFixup> &Fixups,
492bac3619bSZoran Jovanovic                   const MCSubtargetInfo &STI) const {
493bac3619bSZoran Jovanovic 
494bac3619bSZoran Jovanovic   const MCOperand &MO = MI.getOperand(OpNo);
495bac3619bSZoran Jovanovic   if (MO.isImm()) {
496bac3619bSZoran Jovanovic     int Value = MO.getImm();
497bac3619bSZoran Jovanovic     return Value >> 2;
498bac3619bSZoran Jovanovic   }
499bac3619bSZoran Jovanovic 
500bac3619bSZoran Jovanovic   return 0;
501bac3619bSZoran Jovanovic }
502bac3619bSZoran Jovanovic 
503bac3619bSZoran Jovanovic unsigned MipsMCCodeEmitter::
50442b84443SZoran Jovanovic getUImm6Lsl2Encoding(const MCInst &MI, unsigned OpNo,
50542b84443SZoran Jovanovic                      SmallVectorImpl<MCFixup> &Fixups,
50642b84443SZoran Jovanovic                      const MCSubtargetInfo &STI) const {
50742b84443SZoran Jovanovic 
50842b84443SZoran Jovanovic   const MCOperand &MO = MI.getOperand(OpNo);
50942b84443SZoran Jovanovic   if (MO.isImm()) {
51042b84443SZoran Jovanovic     unsigned Value = MO.getImm();
51142b84443SZoran Jovanovic     return Value >> 2;
51242b84443SZoran Jovanovic   }
51342b84443SZoran Jovanovic 
51442b84443SZoran Jovanovic   return 0;
51542b84443SZoran Jovanovic }
51642b84443SZoran Jovanovic 
51742b84443SZoran Jovanovic unsigned MipsMCCodeEmitter::
51898bd58caSZoran Jovanovic getSImm9AddiuspValue(const MCInst &MI, unsigned OpNo,
51998bd58caSZoran Jovanovic                      SmallVectorImpl<MCFixup> &Fixups,
52098bd58caSZoran Jovanovic                      const MCSubtargetInfo &STI) const {
52198bd58caSZoran Jovanovic 
52298bd58caSZoran Jovanovic   const MCOperand &MO = MI.getOperand(OpNo);
52398bd58caSZoran Jovanovic   if (MO.isImm()) {
52498bd58caSZoran Jovanovic     unsigned Binary = (MO.getImm() >> 2) & 0x0000ffff;
52598bd58caSZoran Jovanovic     return (((Binary & 0x8000) >> 7) | (Binary & 0x00ff));
52698bd58caSZoran Jovanovic   }
52798bd58caSZoran Jovanovic 
52898bd58caSZoran Jovanovic   return 0;
52998bd58caSZoran Jovanovic }
53098bd58caSZoran Jovanovic 
53198bd58caSZoran Jovanovic unsigned MipsMCCodeEmitter::
5323fa98a65SDavid Woodhouse getExprOpValue(const MCExpr *Expr, SmallVectorImpl<MCFixup> &Fixups,
5333fa98a65SDavid Woodhouse                const MCSubtargetInfo &STI) const {
534b5cf5909SJack Carter   int64_t Res;
535049e9e4dSAkira Hatanaka 
53613760bd1SJim Grosbach   if (Expr->evaluateAsAbsolute(Res))
537b5cf5909SJack Carter     return Res;
538fe384a2cSAkira Hatanaka 
539fe384a2cSAkira Hatanaka   MCExpr::ExprKind Kind = Expr->getKind();
540b5cf5909SJack Carter   if (Kind == MCExpr::Constant) {
541b5cf5909SJack Carter     return cast<MCConstantExpr>(Expr)->getValue();
542b5cf5909SJack Carter   }
543fe384a2cSAkira Hatanaka 
544fe384a2cSAkira Hatanaka   if (Kind == MCExpr::Binary) {
5453fa98a65SDavid Woodhouse     unsigned Res = getExprOpValue(cast<MCBinaryExpr>(Expr)->getLHS(), Fixups, STI);
5463fa98a65SDavid Woodhouse     Res += getExprOpValue(cast<MCBinaryExpr>(Expr)->getRHS(), Fixups, STI);
547b5cf5909SJack Carter     return Res;
548fe384a2cSAkira Hatanaka   }
549a5da588bSPetar Jovanovic 
550a5da588bSPetar Jovanovic   if (Kind == MCExpr::Target) {
551a5da588bSPetar Jovanovic     const MipsMCExpr *MipsExpr = cast<MipsMCExpr>(Expr);
552a5da588bSPetar Jovanovic 
553a5da588bSPetar Jovanovic     Mips::Fixups FixupKind = Mips::Fixups(0);
554a5da588bSPetar Jovanovic     switch (MipsExpr->getKind()) {
555fe98b2f5SDaniel Sanders     case MipsMCExpr::MEK_NEG:
556fe98b2f5SDaniel Sanders     case MipsMCExpr::MEK_None:
557fe98b2f5SDaniel Sanders     case MipsMCExpr::MEK_Special:
558fe98b2f5SDaniel Sanders       llvm_unreachable("Unhandled fixup kind!");
559fe98b2f5SDaniel Sanders       break;
560fe98b2f5SDaniel Sanders     case MipsMCExpr::MEK_CALL_HI16:
561fe98b2f5SDaniel Sanders       FixupKind = Mips::fixup_Mips_CALL_HI16;
562fe98b2f5SDaniel Sanders       break;
563fe98b2f5SDaniel Sanders     case MipsMCExpr::MEK_CALL_LO16:
564fe98b2f5SDaniel Sanders       FixupKind = Mips::fixup_Mips_CALL_LO16;
565fe98b2f5SDaniel Sanders       break;
566fe98b2f5SDaniel Sanders     case MipsMCExpr::MEK_DTPREL_HI:
567fe98b2f5SDaniel Sanders       FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_DTPREL_HI16
568fe98b2f5SDaniel Sanders                                    : Mips::fixup_Mips_DTPREL_HI;
569fe98b2f5SDaniel Sanders       break;
570fe98b2f5SDaniel Sanders     case MipsMCExpr::MEK_DTPREL_LO:
571fe98b2f5SDaniel Sanders       FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_DTPREL_LO16
572fe98b2f5SDaniel Sanders                                    : Mips::fixup_Mips_DTPREL_LO;
573fe98b2f5SDaniel Sanders       break;
574fe98b2f5SDaniel Sanders     case MipsMCExpr::MEK_GOTTPREL:
575fe98b2f5SDaniel Sanders       FixupKind = Mips::fixup_Mips_GOTTPREL;
576fe98b2f5SDaniel Sanders       break;
577fe98b2f5SDaniel Sanders     case MipsMCExpr::MEK_GOT:
578fe98b2f5SDaniel Sanders       FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOT16
579fe98b2f5SDaniel Sanders                                    : Mips::fixup_Mips_GOT;
580fe98b2f5SDaniel Sanders       break;
581fe98b2f5SDaniel Sanders     case MipsMCExpr::MEK_GOT_CALL:
582fe98b2f5SDaniel Sanders       FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_CALL16
583fe98b2f5SDaniel Sanders                                    : Mips::fixup_Mips_CALL16;
584fe98b2f5SDaniel Sanders       break;
585fe98b2f5SDaniel Sanders     case MipsMCExpr::MEK_GOT_DISP:
586fe98b2f5SDaniel Sanders       FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOT_DISP
587fe98b2f5SDaniel Sanders                                    : Mips::fixup_Mips_GOT_DISP;
588fe98b2f5SDaniel Sanders       break;
589fe98b2f5SDaniel Sanders     case MipsMCExpr::MEK_GOT_HI16:
590fe98b2f5SDaniel Sanders       FixupKind = Mips::fixup_Mips_GOT_HI16;
591fe98b2f5SDaniel Sanders       break;
592fe98b2f5SDaniel Sanders     case MipsMCExpr::MEK_GOT_LO16:
593fe98b2f5SDaniel Sanders       FixupKind = Mips::fixup_Mips_GOT_LO16;
594fe98b2f5SDaniel Sanders       break;
595fe98b2f5SDaniel Sanders     case MipsMCExpr::MEK_GOT_PAGE:
596fe98b2f5SDaniel Sanders       FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOT_PAGE
597fe98b2f5SDaniel Sanders                                    : Mips::fixup_Mips_GOT_PAGE;
598fe98b2f5SDaniel Sanders       break;
599fe98b2f5SDaniel Sanders     case MipsMCExpr::MEK_GOT_OFST:
600fe98b2f5SDaniel Sanders       FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOT_OFST
601fe98b2f5SDaniel Sanders                                    : Mips::fixup_Mips_GOT_OFST;
602fe98b2f5SDaniel Sanders       break;
603fe98b2f5SDaniel Sanders     case MipsMCExpr::MEK_GPREL:
604fe98b2f5SDaniel Sanders       FixupKind = Mips::fixup_Mips_GPREL16;
605fe98b2f5SDaniel Sanders       break;
606fe98b2f5SDaniel Sanders     case MipsMCExpr::MEK_LO: {
607fe98b2f5SDaniel Sanders       // Check for %lo(%neg(%gp_rel(X)))
608fe98b2f5SDaniel Sanders       if (MipsExpr->isGpOff()) {
609fe98b2f5SDaniel Sanders         FixupKind = Mips::fixup_Mips_GPOFF_LO;
610fe98b2f5SDaniel Sanders         break;
611fe98b2f5SDaniel Sanders       }
612fe98b2f5SDaniel Sanders       FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_LO16
613fe98b2f5SDaniel Sanders                                    : Mips::fixup_Mips_LO16;
614fe98b2f5SDaniel Sanders       break;
615fe98b2f5SDaniel Sanders     }
616fe98b2f5SDaniel Sanders     case MipsMCExpr::MEK_HIGHEST:
61706c47803SSasa Stankovic       FixupKind = Mips::fixup_Mips_HIGHEST;
61806c47803SSasa Stankovic       break;
619fe98b2f5SDaniel Sanders     case MipsMCExpr::MEK_HIGHER:
62006c47803SSasa Stankovic       FixupKind = Mips::fixup_Mips_HIGHER;
62106c47803SSasa Stankovic       break;
622fe98b2f5SDaniel Sanders     case MipsMCExpr::MEK_HI:
623fe98b2f5SDaniel Sanders       // Check for %hi(%neg(%gp_rel(X)))
624fe98b2f5SDaniel Sanders       if (MipsExpr->isGpOff()) {
625fe98b2f5SDaniel Sanders         FixupKind = Mips::fixup_Mips_GPOFF_HI;
626fe98b2f5SDaniel Sanders         break;
627fe98b2f5SDaniel Sanders       }
628a5da588bSPetar Jovanovic       FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_HI16
629a5da588bSPetar Jovanovic                                    : Mips::fixup_Mips_HI16;
630a5da588bSPetar Jovanovic       break;
631fe98b2f5SDaniel Sanders     case MipsMCExpr::MEK_PCREL_HI16:
632fe98b2f5SDaniel Sanders       FixupKind = Mips::fixup_MIPS_PCHI16;
633fe98b2f5SDaniel Sanders       break;
634fe98b2f5SDaniel Sanders     case MipsMCExpr::MEK_PCREL_LO16:
635fe98b2f5SDaniel Sanders       FixupKind = Mips::fixup_MIPS_PCLO16;
636fe98b2f5SDaniel Sanders       break;
637fe98b2f5SDaniel Sanders     case MipsMCExpr::MEK_TLSGD:
638fe98b2f5SDaniel Sanders       FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_GD
639fe98b2f5SDaniel Sanders                                    : Mips::fixup_Mips_TLSGD;
640fe98b2f5SDaniel Sanders       break;
641fe98b2f5SDaniel Sanders     case MipsMCExpr::MEK_TLSLDM:
642fe98b2f5SDaniel Sanders       FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_LDM
643fe98b2f5SDaniel Sanders                                    : Mips::fixup_Mips_TLSLDM;
644fe98b2f5SDaniel Sanders       break;
645fe98b2f5SDaniel Sanders     case MipsMCExpr::MEK_TPREL_HI:
646fe98b2f5SDaniel Sanders       FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_TPREL_HI16
647fe98b2f5SDaniel Sanders                                    : Mips::fixup_Mips_TPREL_HI;
648fe98b2f5SDaniel Sanders       break;
649fe98b2f5SDaniel Sanders     case MipsMCExpr::MEK_TPREL_LO:
650fe98b2f5SDaniel Sanders       FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_TPREL_LO16
651fe98b2f5SDaniel Sanders                                    : Mips::fixup_Mips_TPREL_LO;
652a5da588bSPetar Jovanovic       break;
653a5da588bSPetar Jovanovic     }
65463661f8dSJim Grosbach     Fixups.push_back(MCFixup::create(0, MipsExpr, MCFixupKind(FixupKind)));
655a5da588bSPetar Jovanovic     return 0;
656a5da588bSPetar Jovanovic   }
657a5da588bSPetar Jovanovic 
658b5cf5909SJack Carter   if (Kind == MCExpr::SymbolRef) {
659f9774c32SBill Wendling     Mips::Fixups FixupKind = Mips::Fixups(0);
660e2eed964SAkira Hatanaka 
661049e9e4dSAkira Hatanaka     switch(cast<MCSymbolRefExpr>(Expr)->getKind()) {
662b9f9de93SJack Carter     default: llvm_unreachable("Unknown fixup kind!");
66360f1db05SDaniel Sanders       break;
66460f1db05SDaniel Sanders     case MCSymbolRefExpr::VK_None:
66560f1db05SDaniel Sanders       FixupKind = Mips::fixup_Mips_32; // FIXME: This is ok for O32/N32 but not N64.
666b9f9de93SJack Carter       break;
667c85e3ff3SBruno Cardoso Lopes     } // switch
668fe384a2cSAkira Hatanaka 
66963661f8dSJim Grosbach     Fixups.push_back(MCFixup::create(0, Expr, MCFixupKind(FixupKind)));
670fe384a2cSAkira Hatanaka     return 0;
671c85e3ff3SBruno Cardoso Lopes   }
672b5cf5909SJack Carter   return 0;
673b5cf5909SJack Carter }
674b5cf5909SJack Carter 
675b5cf5909SJack Carter /// getMachineOpValue - Return binary encoding of operand. If the machine
676b5cf5909SJack Carter /// operand requires relocation, record the relocation and return zero.
677b5cf5909SJack Carter unsigned MipsMCCodeEmitter::
678b5cf5909SJack Carter getMachineOpValue(const MCInst &MI, const MCOperand &MO,
6793fa98a65SDavid Woodhouse                   SmallVectorImpl<MCFixup> &Fixups,
6803fa98a65SDavid Woodhouse                   const MCSubtargetInfo &STI) const {
681b5cf5909SJack Carter   if (MO.isReg()) {
682b5cf5909SJack Carter     unsigned Reg = MO.getReg();
683bc07a890SBill Wendling     unsigned RegNo = Ctx.getRegisterInfo()->getEncodingValue(Reg);
684b5cf5909SJack Carter     return RegNo;
685b5cf5909SJack Carter   } else if (MO.isImm()) {
686b5cf5909SJack Carter     return static_cast<unsigned>(MO.getImm());
687b5cf5909SJack Carter   } else if (MO.isFPImm()) {
688b5cf5909SJack Carter     return static_cast<unsigned>(APFloat(MO.getFPImm())
689b5cf5909SJack Carter         .bitcastToAPInt().getHiBits(32).getLimitedValue());
690b5cf5909SJack Carter   }
691b5cf5909SJack Carter   // MO must be an Expr.
692b5cf5909SJack Carter   assert(MO.isExpr());
6933fa98a65SDavid Woodhouse   return getExprOpValue(MO.getExpr(),Fixups, STI);
694b5cf5909SJack Carter }
695c85e3ff3SBruno Cardoso Lopes 
696dc0602a2SDaniel Sanders /// Return binary encoding of memory related operand.
697c85e3ff3SBruno Cardoso Lopes /// If the offset operand requires relocation, record the relocation.
698dc0602a2SDaniel Sanders template <unsigned ShiftAmount>
699dc0602a2SDaniel Sanders unsigned MipsMCCodeEmitter::getMemEncoding(const MCInst &MI, unsigned OpNo,
7003fa98a65SDavid Woodhouse                                            SmallVectorImpl<MCFixup> &Fixups,
7013fa98a65SDavid Woodhouse                                            const MCSubtargetInfo &STI) const {
702c85e3ff3SBruno Cardoso Lopes   // Base register is encoded in bits 20-16, offset is encoded in bits 15-0.
703c85e3ff3SBruno Cardoso Lopes   assert(MI.getOperand(OpNo).isReg());
7043fa98a65SDavid Woodhouse   unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo),Fixups, STI) << 16;
7053fa98a65SDavid Woodhouse   unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI);
706c85e3ff3SBruno Cardoso Lopes 
707dc0602a2SDaniel Sanders   // Apply the scale factor if there is one.
708dc0602a2SDaniel Sanders   OffBits >>= ShiftAmount;
709dc0602a2SDaniel Sanders 
710c85e3ff3SBruno Cardoso Lopes   return (OffBits & 0xFFFF) | RegBits;
711c85e3ff3SBruno Cardoso Lopes }
712c85e3ff3SBruno Cardoso Lopes 
71397700977SJack Carter unsigned MipsMCCodeEmitter::
714e8c9d1eaSJozef Kolek getMemEncodingMMImm4(const MCInst &MI, unsigned OpNo,
715e8c9d1eaSJozef Kolek                      SmallVectorImpl<MCFixup> &Fixups,
716e8c9d1eaSJozef Kolek                      const MCSubtargetInfo &STI) const {
717e8c9d1eaSJozef Kolek   // Base register is encoded in bits 6-4, offset is encoded in bits 3-0.
718e8c9d1eaSJozef Kolek   assert(MI.getOperand(OpNo).isReg());
719e8c9d1eaSJozef Kolek   unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo),
720e8c9d1eaSJozef Kolek                                        Fixups, STI) << 4;
721e8c9d1eaSJozef Kolek   unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1),
722e8c9d1eaSJozef Kolek                                        Fixups, STI);
723e8c9d1eaSJozef Kolek 
724e8c9d1eaSJozef Kolek   return (OffBits & 0xF) | RegBits;
725e8c9d1eaSJozef Kolek }
726e8c9d1eaSJozef Kolek 
727e8c9d1eaSJozef Kolek unsigned MipsMCCodeEmitter::
728e8c9d1eaSJozef Kolek getMemEncodingMMImm4Lsl1(const MCInst &MI, unsigned OpNo,
729e8c9d1eaSJozef Kolek                          SmallVectorImpl<MCFixup> &Fixups,
730e8c9d1eaSJozef Kolek                          const MCSubtargetInfo &STI) const {
731e8c9d1eaSJozef Kolek   // Base register is encoded in bits 6-4, offset is encoded in bits 3-0.
732e8c9d1eaSJozef Kolek   assert(MI.getOperand(OpNo).isReg());
733e8c9d1eaSJozef Kolek   unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo),
734e8c9d1eaSJozef Kolek                                        Fixups, STI) << 4;
735e8c9d1eaSJozef Kolek   unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1),
736e8c9d1eaSJozef Kolek                                        Fixups, STI) >> 1;
737e8c9d1eaSJozef Kolek 
738e8c9d1eaSJozef Kolek   return (OffBits & 0xF) | RegBits;
739e8c9d1eaSJozef Kolek }
740e8c9d1eaSJozef Kolek 
741e8c9d1eaSJozef Kolek unsigned MipsMCCodeEmitter::
742e8c9d1eaSJozef Kolek getMemEncodingMMImm4Lsl2(const MCInst &MI, unsigned OpNo,
743e8c9d1eaSJozef Kolek                          SmallVectorImpl<MCFixup> &Fixups,
744e8c9d1eaSJozef Kolek                          const MCSubtargetInfo &STI) const {
745e8c9d1eaSJozef Kolek   // Base register is encoded in bits 6-4, offset is encoded in bits 3-0.
746e8c9d1eaSJozef Kolek   assert(MI.getOperand(OpNo).isReg());
747e8c9d1eaSJozef Kolek   unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo),
748e8c9d1eaSJozef Kolek                                        Fixups, STI) << 4;
749e8c9d1eaSJozef Kolek   unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1),
750e8c9d1eaSJozef Kolek                                        Fixups, STI) >> 2;
751e8c9d1eaSJozef Kolek 
752e8c9d1eaSJozef Kolek   return (OffBits & 0xF) | RegBits;
753e8c9d1eaSJozef Kolek }
754e8c9d1eaSJozef Kolek 
755e8c9d1eaSJozef Kolek unsigned MipsMCCodeEmitter::
75612c6982bSJozef Kolek getMemEncodingMMSPImm5Lsl2(const MCInst &MI, unsigned OpNo,
75712c6982bSJozef Kolek                            SmallVectorImpl<MCFixup> &Fixups,
75812c6982bSJozef Kolek                            const MCSubtargetInfo &STI) const {
75912c6982bSJozef Kolek   // Register is encoded in bits 9-5, offset is encoded in bits 4-0.
76012c6982bSJozef Kolek   assert(MI.getOperand(OpNo).isReg() &&
76168be5f21SZoran Jovanovic          (MI.getOperand(OpNo).getReg() == Mips::SP ||
76268be5f21SZoran Jovanovic          MI.getOperand(OpNo).getReg() == Mips::SP_64) &&
76312c6982bSJozef Kolek          "Unexpected base register!");
76412c6982bSJozef Kolek   unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1),
76512c6982bSJozef Kolek                                        Fixups, STI) >> 2;
76612c6982bSJozef Kolek 
76712c6982bSJozef Kolek   return OffBits & 0x1F;
76812c6982bSJozef Kolek }
76912c6982bSJozef Kolek 
77012c6982bSJozef Kolek unsigned MipsMCCodeEmitter::
771e10a02ecSJozef Kolek getMemEncodingMMGPImm7Lsl2(const MCInst &MI, unsigned OpNo,
772e10a02ecSJozef Kolek                            SmallVectorImpl<MCFixup> &Fixups,
773e10a02ecSJozef Kolek                            const MCSubtargetInfo &STI) const {
774e10a02ecSJozef Kolek   // Register is encoded in bits 9-7, offset is encoded in bits 6-0.
775e10a02ecSJozef Kolek   assert(MI.getOperand(OpNo).isReg() &&
776e10a02ecSJozef Kolek          MI.getOperand(OpNo).getReg() == Mips::GP &&
777e10a02ecSJozef Kolek          "Unexpected base register!");
778e10a02ecSJozef Kolek 
779e10a02ecSJozef Kolek   unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1),
780e10a02ecSJozef Kolek                                        Fixups, STI) >> 2;
781e10a02ecSJozef Kolek 
782e10a02ecSJozef Kolek   return OffBits & 0x7F;
783e10a02ecSJozef Kolek }
784e10a02ecSJozef Kolek 
7859eaa30d2SZoran Jovanovic unsigned MipsMCCodeEmitter::
7869eaa30d2SZoran Jovanovic getMemEncodingMMImm9(const MCInst &MI, unsigned OpNo,
7879eaa30d2SZoran Jovanovic                      SmallVectorImpl<MCFixup> &Fixups,
7889eaa30d2SZoran Jovanovic                      const MCSubtargetInfo &STI) const {
7899eaa30d2SZoran Jovanovic   // Base register is encoded in bits 20-16, offset is encoded in bits 8-0.
7909eaa30d2SZoran Jovanovic   assert(MI.getOperand(OpNo).isReg());
7919eaa30d2SZoran Jovanovic   unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups,
7929eaa30d2SZoran Jovanovic                                        STI) << 16;
7939eaa30d2SZoran Jovanovic   unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo + 1), Fixups, STI);
7949eaa30d2SZoran Jovanovic 
7959eaa30d2SZoran Jovanovic   return (OffBits & 0x1FF) | RegBits;
7969eaa30d2SZoran Jovanovic }
7979eaa30d2SZoran Jovanovic 
798e10a02ecSJozef Kolek unsigned MipsMCCodeEmitter::
79997700977SJack Carter getMemEncodingMMImm12(const MCInst &MI, unsigned OpNo,
8003fa98a65SDavid Woodhouse                       SmallVectorImpl<MCFixup> &Fixups,
8013fa98a65SDavid Woodhouse                       const MCSubtargetInfo &STI) const {
802a4c4b5fcSZoran Jovanovic   // opNum can be invalid if instruction had reglist as operand.
803a4c4b5fcSZoran Jovanovic   // MemOperand is always last operand of instruction (base + offset).
804a4c4b5fcSZoran Jovanovic   switch (MI.getOpcode()) {
805a4c4b5fcSZoran Jovanovic   default:
806a4c4b5fcSZoran Jovanovic     break;
807a4c4b5fcSZoran Jovanovic   case Mips::SWM32_MM:
808a4c4b5fcSZoran Jovanovic   case Mips::LWM32_MM:
809a4c4b5fcSZoran Jovanovic     OpNo = MI.getNumOperands() - 2;
810a4c4b5fcSZoran Jovanovic     break;
811a4c4b5fcSZoran Jovanovic   }
812a4c4b5fcSZoran Jovanovic 
81397700977SJack Carter   // Base register is encoded in bits 20-16, offset is encoded in bits 11-0.
81497700977SJack Carter   assert(MI.getOperand(OpNo).isReg());
8153fa98a65SDavid Woodhouse   unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI) << 16;
8163fa98a65SDavid Woodhouse   unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI);
81797700977SJack Carter 
81897700977SJack Carter   return (OffBits & 0x0FFF) | RegBits;
8193c88fbd3SHrvoje Varga }
8203c88fbd3SHrvoje Varga 
8213c88fbd3SHrvoje Varga unsigned MipsMCCodeEmitter::
8223c88fbd3SHrvoje Varga getMemEncodingMMImm16(const MCInst &MI, unsigned OpNo,
8233c88fbd3SHrvoje Varga                       SmallVectorImpl<MCFixup> &Fixups,
8243c88fbd3SHrvoje Varga                       const MCSubtargetInfo &STI) const {
8253c88fbd3SHrvoje Varga   // Base register is encoded in bits 20-16, offset is encoded in bits 15-0.
8263c88fbd3SHrvoje Varga   assert(MI.getOperand(OpNo).isReg());
8273c88fbd3SHrvoje Varga   unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups,
8283c88fbd3SHrvoje Varga                                        STI) << 16;
8293c88fbd3SHrvoje Varga   unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI);
8303c88fbd3SHrvoje Varga 
8313c88fbd3SHrvoje Varga   return (OffBits & 0xFFFF) | RegBits;
83297700977SJack Carter }
83397700977SJack Carter 
834f9a02500SZoran Jovanovic unsigned MipsMCCodeEmitter::
835f9a02500SZoran Jovanovic getMemEncodingMMImm4sp(const MCInst &MI, unsigned OpNo,
836f9a02500SZoran Jovanovic                        SmallVectorImpl<MCFixup> &Fixups,
837f9a02500SZoran Jovanovic                        const MCSubtargetInfo &STI) const {
838f9a02500SZoran Jovanovic   // opNum can be invalid if instruction had reglist as operand
839f9a02500SZoran Jovanovic   // MemOperand is always last operand of instruction (base + offset)
840f9a02500SZoran Jovanovic   switch (MI.getOpcode()) {
841f9a02500SZoran Jovanovic   default:
842f9a02500SZoran Jovanovic     break;
843f9a02500SZoran Jovanovic   case Mips::SWM16_MM:
844797c2aecSZlatko Buljan   case Mips::SWM16_MMR6:
845f9a02500SZoran Jovanovic   case Mips::LWM16_MM:
846797c2aecSZlatko Buljan   case Mips::LWM16_MMR6:
847f9a02500SZoran Jovanovic     OpNo = MI.getNumOperands() - 2;
848f9a02500SZoran Jovanovic     break;
849f9a02500SZoran Jovanovic   }
850f9a02500SZoran Jovanovic 
851f9a02500SZoran Jovanovic   // Offset is encoded in bits 4-0.
852f9a02500SZoran Jovanovic   assert(MI.getOperand(OpNo).isReg());
853f9a02500SZoran Jovanovic   // Base register is always SP - thus it is not encoded.
854f9a02500SZoran Jovanovic   assert(MI.getOperand(OpNo+1).isImm());
855f9a02500SZoran Jovanovic   unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI);
856f9a02500SZoran Jovanovic 
857f9a02500SZoran Jovanovic   return ((OffBits >> 2) & 0x0F);
858f9a02500SZoran Jovanovic }
859f9a02500SZoran Jovanovic 
860049e9e4dSAkira Hatanaka // FIXME: should be called getMSBEncoding
861049e9e4dSAkira Hatanaka //
862c85e3ff3SBruno Cardoso Lopes unsigned
863c85e3ff3SBruno Cardoso Lopes MipsMCCodeEmitter::getSizeInsEncoding(const MCInst &MI, unsigned OpNo,
8643fa98a65SDavid Woodhouse                                       SmallVectorImpl<MCFixup> &Fixups,
8653fa98a65SDavid Woodhouse                                       const MCSubtargetInfo &STI) const {
866049e9e4dSAkira Hatanaka   assert(MI.getOperand(OpNo-1).isImm());
867049e9e4dSAkira Hatanaka   assert(MI.getOperand(OpNo).isImm());
8683fa98a65SDavid Woodhouse   unsigned Position = getMachineOpValue(MI, MI.getOperand(OpNo-1), Fixups, STI);
8693fa98a65SDavid Woodhouse   unsigned Size = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI);
870049e9e4dSAkira Hatanaka 
87156b70de0SBruno Cardoso Lopes   return Position + Size - 1;
872c85e3ff3SBruno Cardoso Lopes }
873c85e3ff3SBruno Cardoso Lopes 
874ea4f653dSDaniel Sanders template <unsigned Bits, int Offset>
875779c5937SMatheus Almeida unsigned
876ea4f653dSDaniel Sanders MipsMCCodeEmitter::getUImmWithOffsetEncoding(const MCInst &MI, unsigned OpNo,
8773fa98a65SDavid Woodhouse                                              SmallVectorImpl<MCFixup> &Fixups,
8783fa98a65SDavid Woodhouse                                              const MCSubtargetInfo &STI) const {
879779c5937SMatheus Almeida   assert(MI.getOperand(OpNo).isImm());
880ea4f653dSDaniel Sanders   unsigned Value = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI);
881ea4f653dSDaniel Sanders   Value -= Offset;
882ea4f653dSDaniel Sanders   return Value;
883779c5937SMatheus Almeida }
884779c5937SMatheus Almeida 
885b59e1a41SDaniel Sanders unsigned
886b59e1a41SDaniel Sanders MipsMCCodeEmitter::getSimm19Lsl2Encoding(const MCInst &MI, unsigned OpNo,
887b59e1a41SDaniel Sanders                                          SmallVectorImpl<MCFixup> &Fixups,
888b59e1a41SDaniel Sanders                                          const MCSubtargetInfo &STI) const {
889b9c07f3bSZoran Jovanovic   const MCOperand &MO = MI.getOperand(OpNo);
890b9c07f3bSZoran Jovanovic   if (MO.isImm()) {
891b59e1a41SDaniel Sanders     // The immediate is encoded as 'immediate << 2'.
892b9c07f3bSZoran Jovanovic     unsigned Res = getMachineOpValue(MI, MO, Fixups, STI);
893b59e1a41SDaniel Sanders     assert((Res & 3) == 0);
894b59e1a41SDaniel Sanders     return Res >> 2;
895b59e1a41SDaniel Sanders   }
896c85e3ff3SBruno Cardoso Lopes 
897b9c07f3bSZoran Jovanovic   assert(MO.isExpr() &&
898b9c07f3bSZoran Jovanovic          "getSimm19Lsl2Encoding expects only expressions or an immediate");
899b9c07f3bSZoran Jovanovic 
900b9c07f3bSZoran Jovanovic   const MCExpr *Expr = MO.getExpr();
9016764fa78SZoran Jovanovic   Mips::Fixups FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_PC19_S2
9026764fa78SZoran Jovanovic                                             : Mips::fixup_MIPS_PC19_S2;
9036764fa78SZoran Jovanovic   Fixups.push_back(MCFixup::create(0, Expr, MCFixupKind(FixupKind)));
904b9c07f3bSZoran Jovanovic   return 0;
905b9c07f3bSZoran Jovanovic }
906b9c07f3bSZoran Jovanovic 
9072855142aSZoran Jovanovic unsigned
9082855142aSZoran Jovanovic MipsMCCodeEmitter::getSimm18Lsl3Encoding(const MCInst &MI, unsigned OpNo,
9092855142aSZoran Jovanovic                                          SmallVectorImpl<MCFixup> &Fixups,
9102855142aSZoran Jovanovic                                          const MCSubtargetInfo &STI) const {
911a5acdcf9SZoran Jovanovic   const MCOperand &MO = MI.getOperand(OpNo);
912a5acdcf9SZoran Jovanovic   if (MO.isImm()) {
9132855142aSZoran Jovanovic     // The immediate is encoded as 'immediate << 3'.
9142855142aSZoran Jovanovic     unsigned Res = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI);
9152855142aSZoran Jovanovic     assert((Res & 7) == 0);
9162855142aSZoran Jovanovic     return Res >> 3;
9172855142aSZoran Jovanovic   }
9182855142aSZoran Jovanovic 
919a5acdcf9SZoran Jovanovic   assert(MO.isExpr() &&
920a5acdcf9SZoran Jovanovic          "getSimm18Lsl2Encoding expects only expressions or an immediate");
921a5acdcf9SZoran Jovanovic 
922a5acdcf9SZoran Jovanovic   const MCExpr *Expr = MO.getExpr();
9238e366822SZoran Jovanovic   Mips::Fixups FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_PC18_S3
9248e366822SZoran Jovanovic                                             : Mips::fixup_MIPS_PC18_S3;
9258e366822SZoran Jovanovic   Fixups.push_back(MCFixup::create(0, Expr, MCFixupKind(FixupKind)));
926a5acdcf9SZoran Jovanovic   return 0;
927a5acdcf9SZoran Jovanovic }
928a5acdcf9SZoran Jovanovic 
9294a00fdc2SZoran Jovanovic unsigned
9304a00fdc2SZoran Jovanovic MipsMCCodeEmitter::getUImm3Mod8Encoding(const MCInst &MI, unsigned OpNo,
9314a00fdc2SZoran Jovanovic                                         SmallVectorImpl<MCFixup> &Fixups,
9324a00fdc2SZoran Jovanovic                                         const MCSubtargetInfo &STI) const {
9334a00fdc2SZoran Jovanovic   assert(MI.getOperand(OpNo).isImm());
9344a00fdc2SZoran Jovanovic   const MCOperand &MO = MI.getOperand(OpNo);
9354a00fdc2SZoran Jovanovic   return MO.getImm() % 8;
9364a00fdc2SZoran Jovanovic }
9374a00fdc2SZoran Jovanovic 
9388853171bSZoran Jovanovic unsigned
9398853171bSZoran Jovanovic MipsMCCodeEmitter::getUImm4AndValue(const MCInst &MI, unsigned OpNo,
9408853171bSZoran Jovanovic                                     SmallVectorImpl<MCFixup> &Fixups,
9418853171bSZoran Jovanovic                                     const MCSubtargetInfo &STI) const {
9428853171bSZoran Jovanovic   assert(MI.getOperand(OpNo).isImm());
9438853171bSZoran Jovanovic   const MCOperand &MO = MI.getOperand(OpNo);
9448853171bSZoran Jovanovic   unsigned Value = MO.getImm();
9458853171bSZoran Jovanovic   switch (Value) {
9468853171bSZoran Jovanovic     case 128:   return 0x0;
9478853171bSZoran Jovanovic     case 1:     return 0x1;
9488853171bSZoran Jovanovic     case 2:     return 0x2;
9498853171bSZoran Jovanovic     case 3:     return 0x3;
9508853171bSZoran Jovanovic     case 4:     return 0x4;
9518853171bSZoran Jovanovic     case 7:     return 0x5;
9528853171bSZoran Jovanovic     case 8:     return 0x6;
9538853171bSZoran Jovanovic     case 15:    return 0x7;
9548853171bSZoran Jovanovic     case 16:    return 0x8;
9558853171bSZoran Jovanovic     case 31:    return 0x9;
9568853171bSZoran Jovanovic     case 32:    return 0xa;
9578853171bSZoran Jovanovic     case 63:    return 0xb;
9588853171bSZoran Jovanovic     case 64:    return 0xc;
9598853171bSZoran Jovanovic     case 255:   return 0xd;
9608853171bSZoran Jovanovic     case 32768: return 0xe;
9618853171bSZoran Jovanovic     case 65535: return 0xf;
9628853171bSZoran Jovanovic   }
9638853171bSZoran Jovanovic   llvm_unreachable("Unexpected value");
9648853171bSZoran Jovanovic }
9658853171bSZoran Jovanovic 
966a4c4b5fcSZoran Jovanovic unsigned
967a4c4b5fcSZoran Jovanovic MipsMCCodeEmitter::getRegisterListOpValue(const MCInst &MI, unsigned OpNo,
968a4c4b5fcSZoran Jovanovic                                           SmallVectorImpl<MCFixup> &Fixups,
969a4c4b5fcSZoran Jovanovic                                           const MCSubtargetInfo &STI) const {
970a4c4b5fcSZoran Jovanovic   unsigned res = 0;
971a4c4b5fcSZoran Jovanovic 
972a4c4b5fcSZoran Jovanovic   // Register list operand is always first operand of instruction and it is
973a4c4b5fcSZoran Jovanovic   // placed before memory operand (register + imm).
974a4c4b5fcSZoran Jovanovic 
975a4c4b5fcSZoran Jovanovic   for (unsigned I = OpNo, E = MI.getNumOperands() - 2; I < E; ++I) {
976a4c4b5fcSZoran Jovanovic     unsigned Reg = MI.getOperand(I).getReg();
977a4c4b5fcSZoran Jovanovic     unsigned RegNo = Ctx.getRegisterInfo()->getEncodingValue(Reg);
978a4c4b5fcSZoran Jovanovic     if (RegNo != 31)
979a4c4b5fcSZoran Jovanovic       res++;
980a4c4b5fcSZoran Jovanovic     else
981a4c4b5fcSZoran Jovanovic       res |= 0x10;
982a4c4b5fcSZoran Jovanovic   }
983a4c4b5fcSZoran Jovanovic   return res;
984a4c4b5fcSZoran Jovanovic }
985a4c4b5fcSZoran Jovanovic 
986f9a02500SZoran Jovanovic unsigned
987f9a02500SZoran Jovanovic MipsMCCodeEmitter::getRegisterListOpValue16(const MCInst &MI, unsigned OpNo,
988f9a02500SZoran Jovanovic                                             SmallVectorImpl<MCFixup> &Fixups,
989f9a02500SZoran Jovanovic                                             const MCSubtargetInfo &STI) const {
990f9a02500SZoran Jovanovic   return (MI.getNumOperands() - 4);
991f9a02500SZoran Jovanovic }
992f9a02500SZoran Jovanovic 
9932deca348SZoran Jovanovic unsigned
9942deca348SZoran Jovanovic MipsMCCodeEmitter::getRegisterPairOpValue(const MCInst &MI, unsigned OpNo,
9952deca348SZoran Jovanovic                                           SmallVectorImpl<MCFixup> &Fixups,
9962deca348SZoran Jovanovic                                           const MCSubtargetInfo &STI) const {
9972deca348SZoran Jovanovic   return getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI);
9982deca348SZoran Jovanovic }
9992deca348SZoran Jovanovic 
10002c6d7320SJozef Kolek unsigned
100141688679SZoran Jovanovic MipsMCCodeEmitter::getMovePRegPairOpValue(const MCInst &MI, unsigned OpNo,
100241688679SZoran Jovanovic                                           SmallVectorImpl<MCFixup> &Fixups,
100341688679SZoran Jovanovic                                           const MCSubtargetInfo &STI) const {
100441688679SZoran Jovanovic   unsigned res = 0;
100541688679SZoran Jovanovic 
100641688679SZoran Jovanovic   if (MI.getOperand(0).getReg() == Mips::A1 &&
100741688679SZoran Jovanovic       MI.getOperand(1).getReg() == Mips::A2)
100841688679SZoran Jovanovic     res = 0;
100941688679SZoran Jovanovic   else if (MI.getOperand(0).getReg() == Mips::A1 &&
101041688679SZoran Jovanovic            MI.getOperand(1).getReg() == Mips::A3)
101141688679SZoran Jovanovic     res = 1;
101241688679SZoran Jovanovic   else if (MI.getOperand(0).getReg() == Mips::A2 &&
101341688679SZoran Jovanovic            MI.getOperand(1).getReg() == Mips::A3)
101441688679SZoran Jovanovic     res = 2;
101541688679SZoran Jovanovic   else if (MI.getOperand(0).getReg() == Mips::A0 &&
101641688679SZoran Jovanovic            MI.getOperand(1).getReg() == Mips::S5)
101741688679SZoran Jovanovic     res = 3;
101841688679SZoran Jovanovic   else if (MI.getOperand(0).getReg() == Mips::A0 &&
101941688679SZoran Jovanovic            MI.getOperand(1).getReg() == Mips::S6)
102041688679SZoran Jovanovic     res = 4;
102141688679SZoran Jovanovic   else if (MI.getOperand(0).getReg() == Mips::A0 &&
102241688679SZoran Jovanovic            MI.getOperand(1).getReg() == Mips::A1)
102341688679SZoran Jovanovic     res = 5;
102441688679SZoran Jovanovic   else if (MI.getOperand(0).getReg() == Mips::A0 &&
102541688679SZoran Jovanovic            MI.getOperand(1).getReg() == Mips::A2)
102641688679SZoran Jovanovic     res = 6;
102741688679SZoran Jovanovic   else if (MI.getOperand(0).getReg() == Mips::A0 &&
102841688679SZoran Jovanovic            MI.getOperand(1).getReg() == Mips::A3)
102941688679SZoran Jovanovic     res = 7;
103041688679SZoran Jovanovic 
103141688679SZoran Jovanovic   return res;
103241688679SZoran Jovanovic }
103341688679SZoran Jovanovic 
103441688679SZoran Jovanovic unsigned
10352c6d7320SJozef Kolek MipsMCCodeEmitter::getSimm23Lsl2Encoding(const MCInst &MI, unsigned OpNo,
10362c6d7320SJozef Kolek                                          SmallVectorImpl<MCFixup> &Fixups,
10372c6d7320SJozef Kolek                                          const MCSubtargetInfo &STI) const {
10382c6d7320SJozef Kolek   const MCOperand &MO = MI.getOperand(OpNo);
10392c6d7320SJozef Kolek   assert(MO.isImm() && "getSimm23Lsl2Encoding expects only an immediate");
10402c6d7320SJozef Kolek   // The immediate is encoded as 'immediate >> 2'.
10412c6d7320SJozef Kolek   unsigned Res = static_cast<unsigned>(MO.getImm());
10422c6d7320SJozef Kolek   assert((Res & 3) == 0);
10432c6d7320SJozef Kolek   return Res >> 2;
10442c6d7320SJozef Kolek }
10452c6d7320SJozef Kolek 
1046b59e1a41SDaniel Sanders #include "MipsGenMCCodeEmitter.inc"
1047