blob: d47440bda79695bfd140db0dea6fa33f268defc0 [file] [log] [blame]
Jia Liu9f610112012-02-17 08:55:11 +00001//===-- MipsMCCodeEmitter.cpp - Convert Mips Code to Machine Code ---------===//
Akira Hatanaka750ecec2011-09-30 20:40:03 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the MipsMCCodeEmitter class.
11//
12//===----------------------------------------------------------------------===//
13//
14#define DEBUG_TYPE "mccodeemitter"
Bruno Cardoso Lopesc85e3ff2011-11-11 22:58:42 +000015#include "MCTargetDesc/MipsBaseInfo.h"
16#include "MCTargetDesc/MipsFixupKinds.h"
Petar Jovanovica5da5882014-02-04 18:41:57 +000017#include "MCTargetDesc/MipsMCExpr.h"
Bruno Cardoso Lopesc85e3ff2011-11-11 22:58:42 +000018#include "MCTargetDesc/MipsMCTargetDesc.h"
19#include "llvm/ADT/APFloat.h"
20#include "llvm/ADT/Statistic.h"
Akira Hatanaka750ecec2011-09-30 20:40:03 +000021#include "llvm/MC/MCCodeEmitter.h"
Akira Hatanaka5d6faed2012-12-10 20:04:40 +000022#include "llvm/MC/MCContext.h"
Akira Hatanaka750ecec2011-09-30 20:40:03 +000023#include "llvm/MC/MCExpr.h"
24#include "llvm/MC/MCInst.h"
25#include "llvm/MC/MCInstrInfo.h"
26#include "llvm/MC/MCRegisterInfo.h"
27#include "llvm/MC/MCSubtargetInfo.h"
Akira Hatanaka750ecec2011-09-30 20:40:03 +000028#include "llvm/Support/raw_ostream.h"
Akira Hatanaka750ecec2011-09-30 20:40:03 +000029
Akira Hatanakabe6a8182013-04-19 19:03:11 +000030#define GET_INSTRMAP_INFO
31#include "MipsGenInstrInfo.inc"
32
Akira Hatanaka750ecec2011-09-30 20:40:03 +000033using namespace llvm;
34
35namespace {
36class MipsMCCodeEmitter : public MCCodeEmitter {
Craig Topper2ed23ce2012-09-15 17:08:51 +000037 MipsMCCodeEmitter(const MipsMCCodeEmitter &) LLVM_DELETED_FUNCTION;
38 void operator=(const MipsMCCodeEmitter &) LLVM_DELETED_FUNCTION;
Akira Hatanaka750ecec2011-09-30 20:40:03 +000039 const MCInstrInfo &MCII;
Akira Hatanaka5d6faed2012-12-10 20:04:40 +000040 MCContext &Ctx;
Akira Hatanaka1ee768d2012-03-01 01:53:15 +000041 bool IsLittleEndian;
David Woodhoused2cca112014-01-28 23:13:25 +000042
43 bool isMicroMips(const MCSubtargetInfo &STI) const {
44 return STI.getFeatureBits() & Mips::FeatureMicroMips;
45 }
Akira Hatanaka750ecec2011-09-30 20:40:03 +000046
47public:
David Woodhoused2cca112014-01-28 23:13:25 +000048 MipsMCCodeEmitter(const MCInstrInfo &mcii, MCContext &Ctx_, bool IsLittle) :
49 MCII(mcii), Ctx(Ctx_), IsLittleEndian(IsLittle) { }
Akira Hatanaka750ecec2011-09-30 20:40:03 +000050
51 ~MipsMCCodeEmitter() {}
52
Bruno Cardoso Lopesc85e3ff2011-11-11 22:58:42 +000053 void EmitByte(unsigned char C, raw_ostream &OS) const {
54 OS << (char)C;
Akira Hatanaka750ecec2011-09-30 20:40:03 +000055 }
Bruno Cardoso Lopesc85e3ff2011-11-11 22:58:42 +000056
David Woodhoused2cca112014-01-28 23:13:25 +000057 void EmitInstruction(uint64_t Val, unsigned Size, const MCSubtargetInfo &STI,
58 raw_ostream &OS) const {
Bruno Cardoso Lopesc85e3ff2011-11-11 22:58:42 +000059 // Output the instruction encoding in little endian byte order.
Jack Carter7bd3c7d2013-08-08 23:30:40 +000060 // Little-endian byte ordering:
61 // mips32r2: 4 | 3 | 2 | 1
62 // microMIPS: 2 | 1 | 4 | 3
David Woodhoused2cca112014-01-28 23:13:25 +000063 if (IsLittleEndian && Size == 4 && isMicroMips(STI)) {
64 EmitInstruction(Val>>16, 2, STI, OS);
65 EmitInstruction(Val, 2, STI, OS);
Jack Carter7bd3c7d2013-08-08 23:30:40 +000066 } else {
67 for (unsigned i = 0; i < Size; ++i) {
68 unsigned Shift = IsLittleEndian ? i * 8 : (Size - 1 - i) * 8;
69 EmitByte((Val >> Shift) & 0xff, OS);
70 }
Bruno Cardoso Lopesc85e3ff2011-11-11 22:58:42 +000071 }
72 }
73
74 void EncodeInstruction(const MCInst &MI, raw_ostream &OS,
David Woodhouse9784cef2014-01-28 23:13:07 +000075 SmallVectorImpl<MCFixup> &Fixups,
76 const MCSubtargetInfo &STI) const;
Bruno Cardoso Lopesc85e3ff2011-11-11 22:58:42 +000077
78 // getBinaryCodeForInstr - TableGen'erated function for getting the
79 // binary encoding for an instruction.
Owen Andersond845d9d2012-01-24 18:37:29 +000080 uint64_t getBinaryCodeForInstr(const MCInst &MI,
David Woodhouse3fa98a62014-01-28 23:13:18 +000081 SmallVectorImpl<MCFixup> &Fixups,
82 const MCSubtargetInfo &STI) const;
Bruno Cardoso Lopesc85e3ff2011-11-11 22:58:42 +000083
84 // getBranchJumpOpValue - Return binary encoding of the jump
85 // target operand. If the machine operand requires relocation,
86 // record the relocation and return zero.
Mark Seaborn774c2432013-12-29 10:47:04 +000087 unsigned getJumpTargetOpValue(const MCInst &MI, unsigned OpNo,
David Woodhouse3fa98a62014-01-28 23:13:18 +000088 SmallVectorImpl<MCFixup> &Fixups,
89 const MCSubtargetInfo &STI) const;
Bruno Cardoso Lopesc85e3ff2011-11-11 22:58:42 +000090
Zoran Jovanovic507e0842013-10-29 16:38:59 +000091 // getBranchJumpOpValueMM - Return binary encoding of the microMIPS jump
92 // target operand. If the machine operand requires relocation,
93 // record the relocation and return zero.
94 unsigned getJumpTargetOpValueMM(const MCInst &MI, unsigned OpNo,
David Woodhouse3fa98a62014-01-28 23:13:18 +000095 SmallVectorImpl<MCFixup> &Fixups,
96 const MCSubtargetInfo &STI) const;
Zoran Jovanovic507e0842013-10-29 16:38:59 +000097
Bruno Cardoso Lopesc85e3ff2011-11-11 22:58:42 +000098 // getBranchTargetOpValue - Return binary encoding of the branch
99 // target operand. If the machine operand requires relocation,
100 // record the relocation and return zero.
101 unsigned getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
David Woodhouse3fa98a62014-01-28 23:13:18 +0000102 SmallVectorImpl<MCFixup> &Fixups,
103 const MCSubtargetInfo &STI) const;
Bruno Cardoso Lopesc85e3ff2011-11-11 22:58:42 +0000104
Zoran Jovanovic8a80aa72013-11-04 14:53:22 +0000105 // getBranchTargetOpValue - Return binary encoding of the microMIPS branch
106 // target operand. If the machine operand requires relocation,
107 // record the relocation and return zero.
108 unsigned getBranchTargetOpValueMM(const MCInst &MI, unsigned OpNo,
David Woodhouse3fa98a62014-01-28 23:13:18 +0000109 SmallVectorImpl<MCFixup> &Fixups,
110 const MCSubtargetInfo &STI) const;
Zoran Jovanovic8a80aa72013-11-04 14:53:22 +0000111
Bruno Cardoso Lopesc85e3ff2011-11-11 22:58:42 +0000112 // getMachineOpValue - Return binary encoding of operand. If the machin
113 // operand requires relocation, record the relocation and return zero.
114 unsigned getMachineOpValue(const MCInst &MI,const MCOperand &MO,
David Woodhouse3fa98a62014-01-28 23:13:18 +0000115 SmallVectorImpl<MCFixup> &Fixups,
116 const MCSubtargetInfo &STI) const;
Bruno Cardoso Lopesc85e3ff2011-11-11 22:58:42 +0000117
Matheus Almeida6b59c442013-12-05 11:06:22 +0000118 unsigned getMSAMemEncoding(const MCInst &MI, unsigned OpNo,
David Woodhouse3fa98a62014-01-28 23:13:18 +0000119 SmallVectorImpl<MCFixup> &Fixups,
120 const MCSubtargetInfo &STI) const;
Matheus Almeida6b59c442013-12-05 11:06:22 +0000121
Bruno Cardoso Lopesc85e3ff2011-11-11 22:58:42 +0000122 unsigned getMemEncoding(const MCInst &MI, unsigned OpNo,
David Woodhouse3fa98a62014-01-28 23:13:18 +0000123 SmallVectorImpl<MCFixup> &Fixups,
124 const MCSubtargetInfo &STI) const;
Jack Carter97700972013-08-13 20:19:16 +0000125 unsigned getMemEncodingMMImm12(const MCInst &MI, unsigned OpNo,
David Woodhouse3fa98a62014-01-28 23:13:18 +0000126 SmallVectorImpl<MCFixup> &Fixups,
127 const MCSubtargetInfo &STI) const;
Bruno Cardoso Lopesc85e3ff2011-11-11 22:58:42 +0000128 unsigned getSizeExtEncoding(const MCInst &MI, unsigned OpNo,
David Woodhouse3fa98a62014-01-28 23:13:18 +0000129 SmallVectorImpl<MCFixup> &Fixups,
130 const MCSubtargetInfo &STI) const;
Bruno Cardoso Lopesc85e3ff2011-11-11 22:58:42 +0000131 unsigned getSizeInsEncoding(const MCInst &MI, unsigned OpNo,
David Woodhouse3fa98a62014-01-28 23:13:18 +0000132 SmallVectorImpl<MCFixup> &Fixups,
133 const MCSubtargetInfo &STI) const;
Bruno Cardoso Lopesc85e3ff2011-11-11 22:58:42 +0000134
Matheus Almeida779c5932013-11-18 12:32:49 +0000135 // getLSAImmEncoding - Return binary encoding of LSA immediate.
136 unsigned getLSAImmEncoding(const MCInst &MI, unsigned OpNo,
David Woodhouse3fa98a62014-01-28 23:13:18 +0000137 SmallVectorImpl<MCFixup> &Fixups,
138 const MCSubtargetInfo &STI) const;
Matheus Almeida779c5932013-11-18 12:32:49 +0000139
Jack Carterb5cf5902013-04-17 00:18:04 +0000140 unsigned
David Woodhouse3fa98a62014-01-28 23:13:18 +0000141 getExprOpValue(const MCExpr *Expr,SmallVectorImpl<MCFixup> &Fixups,
142 const MCSubtargetInfo &STI) const;
Jack Carterb5cf5902013-04-17 00:18:04 +0000143
Akira Hatanaka750ecec2011-09-30 20:40:03 +0000144}; // class MipsMCCodeEmitter
145} // namespace
146
Akira Hatanaka1ee768d2012-03-01 01:53:15 +0000147MCCodeEmitter *llvm::createMipsMCCodeEmitterEB(const MCInstrInfo &MCII,
Jim Grosbachc3b04272012-05-15 17:35:52 +0000148 const MCRegisterInfo &MRI,
Akira Hatanaka1ee768d2012-03-01 01:53:15 +0000149 const MCSubtargetInfo &STI,
150 MCContext &Ctx)
Bruno Cardoso Lopesc85e3ff2011-11-11 22:58:42 +0000151{
David Woodhoused2cca112014-01-28 23:13:25 +0000152 return new MipsMCCodeEmitter(MCII, Ctx, false);
Akira Hatanaka1ee768d2012-03-01 01:53:15 +0000153}
154
155MCCodeEmitter *llvm::createMipsMCCodeEmitterEL(const MCInstrInfo &MCII,
Jim Grosbachc3b04272012-05-15 17:35:52 +0000156 const MCRegisterInfo &MRI,
Akira Hatanaka1ee768d2012-03-01 01:53:15 +0000157 const MCSubtargetInfo &STI,
158 MCContext &Ctx)
159{
David Woodhoused2cca112014-01-28 23:13:25 +0000160 return new MipsMCCodeEmitter(MCII, Ctx, true);
Akira Hatanaka750ecec2011-09-30 20:40:03 +0000161}
Bruno Cardoso Lopesc85e3ff2011-11-11 22:58:42 +0000162
Rafael Espindolaf30f2cc2013-05-27 22:34:59 +0000163
164// If the D<shift> instruction has a shift amount that is greater
165// than 31 (checked in calling routine), lower it to a D<shift>32 instruction
166static void LowerLargeShift(MCInst& Inst) {
167
168 assert(Inst.getNumOperands() == 3 && "Invalid no. of operands for shift!");
169 assert(Inst.getOperand(2).isImm());
170
171 int64_t Shift = Inst.getOperand(2).getImm();
172 if (Shift <= 31)
173 return; // Do nothing
174 Shift -= 32;
175
176 // saminus32
177 Inst.getOperand(2).setImm(Shift);
178
179 switch (Inst.getOpcode()) {
180 default:
181 // Calling function is not synchronized
182 llvm_unreachable("Unexpected shift instruction");
183 case Mips::DSLL:
184 Inst.setOpcode(Mips::DSLL32);
185 return;
186 case Mips::DSRL:
187 Inst.setOpcode(Mips::DSRL32);
188 return;
189 case Mips::DSRA:
190 Inst.setOpcode(Mips::DSRA32);
191 return;
Akira Hatanaka6a3fe572013-09-07 00:18:01 +0000192 case Mips::DROTR:
193 Inst.setOpcode(Mips::DROTR32);
194 return;
Rafael Espindolaf30f2cc2013-05-27 22:34:59 +0000195 }
196}
197
198// Pick a DEXT or DINS instruction variant based on the pos and size operands
199static void LowerDextDins(MCInst& InstIn) {
200 int Opcode = InstIn.getOpcode();
201
202 if (Opcode == Mips::DEXT)
203 assert(InstIn.getNumOperands() == 4 &&
204 "Invalid no. of machine operands for DEXT!");
205 else // Only DEXT and DINS are possible
206 assert(InstIn.getNumOperands() == 5 &&
207 "Invalid no. of machine operands for DINS!");
208
209 assert(InstIn.getOperand(2).isImm());
210 int64_t pos = InstIn.getOperand(2).getImm();
211 assert(InstIn.getOperand(3).isImm());
212 int64_t size = InstIn.getOperand(3).getImm();
213
214 if (size <= 32) {
215 if (pos < 32) // DEXT/DINS, do nothing
216 return;
217 // DEXTU/DINSU
218 InstIn.getOperand(2).setImm(pos - 32);
219 InstIn.setOpcode((Opcode == Mips::DEXT) ? Mips::DEXTU : Mips::DINSU);
220 return;
221 }
222 // DEXTM/DINSM
223 assert(pos < 32 && "DEXT/DINS cannot have both size and pos > 32");
224 InstIn.getOperand(3).setImm(size - 32);
225 InstIn.setOpcode((Opcode == Mips::DEXT) ? Mips::DEXTM : Mips::DINSM);
226 return;
227}
228
Bruno Cardoso Lopesc85e3ff2011-11-11 22:58:42 +0000229/// EncodeInstruction - Emit the instruction.
Jack Carter4e07b95d2013-08-27 19:45:28 +0000230/// Size the instruction with Desc.getSize().
Bruno Cardoso Lopesc85e3ff2011-11-11 22:58:42 +0000231void MipsMCCodeEmitter::
232EncodeInstruction(const MCInst &MI, raw_ostream &OS,
David Woodhouse9784cef2014-01-28 23:13:07 +0000233 SmallVectorImpl<MCFixup> &Fixups,
234 const MCSubtargetInfo &STI) const
Bruno Cardoso Lopesc85e3ff2011-11-11 22:58:42 +0000235{
Jack Carteraa7aeaa2012-10-02 23:09:40 +0000236
237 // Non-pseudo instructions that get changed for direct object
238 // only based on operand values.
239 // If this list of instructions get much longer we will move
240 // the check to a function call. Until then, this is more efficient.
241 MCInst TmpInst = MI;
242 switch (MI.getOpcode()) {
243 // If shift amount is >= 32 it the inst needs to be lowered further
244 case Mips::DSLL:
245 case Mips::DSRL:
246 case Mips::DSRA:
Akira Hatanaka6a3fe572013-09-07 00:18:01 +0000247 case Mips::DROTR:
Rafael Espindolaf30f2cc2013-05-27 22:34:59 +0000248 LowerLargeShift(TmpInst);
Jack Carteraa7aeaa2012-10-02 23:09:40 +0000249 break;
250 // Double extract instruction is chosen by pos and size operands
251 case Mips::DEXT:
252 case Mips::DINS:
Rafael Espindolaf30f2cc2013-05-27 22:34:59 +0000253 LowerDextDins(TmpInst);
Jack Carteraa7aeaa2012-10-02 23:09:40 +0000254 }
255
Jack Carter97700972013-08-13 20:19:16 +0000256 unsigned long N = Fixups.size();
David Woodhouse3fa98a62014-01-28 23:13:18 +0000257 uint32_t Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);
Bruno Cardoso Lopesc85e3ff2011-11-11 22:58:42 +0000258
259 // Check for unimplemented opcodes.
Jack Carteraa7aeaa2012-10-02 23:09:40 +0000260 // Unfortunately in MIPS both NOP and SLL will come in with Binary == 0
Bruno Cardoso Lopesc85e3ff2011-11-11 22:58:42 +0000261 // so we have to special check for them.
Jack Carteraa7aeaa2012-10-02 23:09:40 +0000262 unsigned Opcode = TmpInst.getOpcode();
Bruno Cardoso Lopesc85e3ff2011-11-11 22:58:42 +0000263 if ((Opcode != Mips::NOP) && (Opcode != Mips::SLL) && !Binary)
264 llvm_unreachable("unimplemented opcode in EncodeInstruction()");
265
Akira Hatanakabe6a8182013-04-19 19:03:11 +0000266 if (STI.getFeatureBits() & Mips::FeatureMicroMips) {
267 int NewOpcode = Mips::Std2MicroMips (Opcode, Mips::Arch_micromips);
268 if (NewOpcode != -1) {
Jack Carter97700972013-08-13 20:19:16 +0000269 if (Fixups.size() > N)
270 Fixups.pop_back();
Akira Hatanakabe6a8182013-04-19 19:03:11 +0000271 Opcode = NewOpcode;
272 TmpInst.setOpcode (NewOpcode);
David Woodhouse3fa98a62014-01-28 23:13:18 +0000273 Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);
Akira Hatanakabe6a8182013-04-19 19:03:11 +0000274 }
275 }
276
Jack Carteraa7aeaa2012-10-02 23:09:40 +0000277 const MCInstrDesc &Desc = MCII.get(TmpInst.getOpcode());
Bruno Cardoso Lopesc85e3ff2011-11-11 22:58:42 +0000278
Jack Carter5b5559d2012-10-03 21:58:54 +0000279 // Get byte count of instruction
280 unsigned Size = Desc.getSize();
281 if (!Size)
282 llvm_unreachable("Desc.getSize() returns 0");
Bruno Cardoso Lopesc85e3ff2011-11-11 22:58:42 +0000283
David Woodhoused2cca112014-01-28 23:13:25 +0000284 EmitInstruction(Binary, Size, STI, OS);
Bruno Cardoso Lopesc85e3ff2011-11-11 22:58:42 +0000285}
286
287/// getBranchTargetOpValue - Return binary encoding of the branch
288/// target operand. If the machine operand requires relocation,
289/// record the relocation and return zero.
290unsigned MipsMCCodeEmitter::
291getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
David Woodhouse3fa98a62014-01-28 23:13:18 +0000292 SmallVectorImpl<MCFixup> &Fixups,
293 const MCSubtargetInfo &STI) const {
Bruno Cardoso Lopesc85e3ff2011-11-11 22:58:42 +0000294
295 const MCOperand &MO = MI.getOperand(OpNo);
Jack Carter71e6a742012-09-06 00:43:26 +0000296
Jack Carter4f69a0f2013-03-22 00:29:10 +0000297 // If the destination is an immediate, divide by 4.
298 if (MO.isImm()) return MO.getImm() >> 2;
299
Jack Carter71e6a742012-09-06 00:43:26 +0000300 assert(MO.isExpr() &&
301 "getBranchTargetOpValue expects only expressions or immediates");
Bruno Cardoso Lopesc85e3ff2011-11-11 22:58:42 +0000302
303 const MCExpr *Expr = MO.getExpr();
304 Fixups.push_back(MCFixup::Create(0, Expr,
305 MCFixupKind(Mips::fixup_Mips_PC16)));
306 return 0;
307}
308
Zoran Jovanovic8a80aa72013-11-04 14:53:22 +0000309/// getBranchTargetOpValue - Return binary encoding of the microMIPS branch
310/// target operand. If the machine operand requires relocation,
311/// record the relocation and return zero.
312unsigned MipsMCCodeEmitter::
313getBranchTargetOpValueMM(const MCInst &MI, unsigned OpNo,
David Woodhouse3fa98a62014-01-28 23:13:18 +0000314 SmallVectorImpl<MCFixup> &Fixups,
315 const MCSubtargetInfo &STI) const {
Zoran Jovanovic8a80aa72013-11-04 14:53:22 +0000316
317 const MCOperand &MO = MI.getOperand(OpNo);
318
319 // If the destination is an immediate, divide by 2.
320 if (MO.isImm()) return MO.getImm() >> 1;
321
322 assert(MO.isExpr() &&
323 "getBranchTargetOpValueMM expects only expressions or immediates");
324
325 const MCExpr *Expr = MO.getExpr();
326 Fixups.push_back(MCFixup::Create(0, Expr,
327 MCFixupKind(Mips::
328 fixup_MICROMIPS_PC16_S1)));
329 return 0;
330}
331
Bruno Cardoso Lopesc85e3ff2011-11-11 22:58:42 +0000332/// getJumpTargetOpValue - Return binary encoding of the jump
333/// target operand. If the machine operand requires relocation,
334/// record the relocation and return zero.
335unsigned MipsMCCodeEmitter::
336getJumpTargetOpValue(const MCInst &MI, unsigned OpNo,
David Woodhouse3fa98a62014-01-28 23:13:18 +0000337 SmallVectorImpl<MCFixup> &Fixups,
338 const MCSubtargetInfo &STI) const {
Bruno Cardoso Lopesc85e3ff2011-11-11 22:58:42 +0000339
340 const MCOperand &MO = MI.getOperand(OpNo);
Jack Carter4f69a0f2013-03-22 00:29:10 +0000341 // If the destination is an immediate, divide by 4.
342 if (MO.isImm()) return MO.getImm()>>2;
343
Jack Carter71e6a742012-09-06 00:43:26 +0000344 assert(MO.isExpr() &&
345 "getJumpTargetOpValue expects only expressions or an immediate");
Bruno Cardoso Lopesc85e3ff2011-11-11 22:58:42 +0000346
347 const MCExpr *Expr = MO.getExpr();
348 Fixups.push_back(MCFixup::Create(0, Expr,
349 MCFixupKind(Mips::fixup_Mips_26)));
350 return 0;
351}
352
Bruno Cardoso Lopesc85e3ff2011-11-11 22:58:42 +0000353unsigned MipsMCCodeEmitter::
Zoran Jovanovic507e0842013-10-29 16:38:59 +0000354getJumpTargetOpValueMM(const MCInst &MI, unsigned OpNo,
David Woodhouse3fa98a62014-01-28 23:13:18 +0000355 SmallVectorImpl<MCFixup> &Fixups,
356 const MCSubtargetInfo &STI) const {
Zoran Jovanovic507e0842013-10-29 16:38:59 +0000357
358 const MCOperand &MO = MI.getOperand(OpNo);
359 // If the destination is an immediate, divide by 2.
360 if (MO.isImm()) return MO.getImm() >> 1;
361
362 assert(MO.isExpr() &&
363 "getJumpTargetOpValueMM expects only expressions or an immediate");
364
365 const MCExpr *Expr = MO.getExpr();
366 Fixups.push_back(MCFixup::Create(0, Expr,
367 MCFixupKind(Mips::fixup_MICROMIPS_26_S1)));
368 return 0;
369}
370
371unsigned MipsMCCodeEmitter::
David Woodhouse3fa98a62014-01-28 23:13:18 +0000372getExprOpValue(const MCExpr *Expr,SmallVectorImpl<MCFixup> &Fixups,
373 const MCSubtargetInfo &STI) const {
Jack Carterb5cf5902013-04-17 00:18:04 +0000374 int64_t Res;
Akira Hatanaka049e9e42011-11-23 22:19:28 +0000375
Jack Carterb5cf5902013-04-17 00:18:04 +0000376 if (Expr->EvaluateAsAbsolute(Res))
377 return Res;
Akira Hatanaka049e9e42011-11-23 22:19:28 +0000378
Akira Hatanakafe384a22012-03-27 02:33:05 +0000379 MCExpr::ExprKind Kind = Expr->getKind();
Jack Carterb5cf5902013-04-17 00:18:04 +0000380 if (Kind == MCExpr::Constant) {
381 return cast<MCConstantExpr>(Expr)->getValue();
382 }
Akira Hatanakae2eed962011-12-22 01:05:17 +0000383
Akira Hatanakafe384a22012-03-27 02:33:05 +0000384 if (Kind == MCExpr::Binary) {
David Woodhouse3fa98a62014-01-28 23:13:18 +0000385 unsigned Res = getExprOpValue(cast<MCBinaryExpr>(Expr)->getLHS(), Fixups, STI);
386 Res += getExprOpValue(cast<MCBinaryExpr>(Expr)->getRHS(), Fixups, STI);
Jack Carterb5cf5902013-04-17 00:18:04 +0000387 return Res;
Bruno Cardoso Lopesc85e3ff2011-11-11 22:58:42 +0000388 }
Petar Jovanovica5da5882014-02-04 18:41:57 +0000389
390 if (Kind == MCExpr::Target) {
391 const MipsMCExpr *MipsExpr = cast<MipsMCExpr>(Expr);
392
393 Mips::Fixups FixupKind = Mips::Fixups(0);
394 switch (MipsExpr->getKind()) {
395 default: llvm_unreachable("Unsupported fixup kind for target expression!");
396 case MipsMCExpr::VK_Mips_ABS_HI:
397 FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_HI16
398 : Mips::fixup_Mips_HI16;
399 break;
400 case MipsMCExpr::VK_Mips_ABS_LO:
401 FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_LO16
402 : Mips::fixup_Mips_LO16;
403 break;
404 }
405 Fixups.push_back(MCFixup::Create(0, MipsExpr, MCFixupKind(FixupKind)));
406 return 0;
407 }
408
Jack Carterb5cf5902013-04-17 00:18:04 +0000409 if (Kind == MCExpr::SymbolRef) {
Mark Seabornc3bd1772013-12-31 13:05:15 +0000410 Mips::Fixups FixupKind = Mips::Fixups(0);
Akira Hatanakafe384a22012-03-27 02:33:05 +0000411
Mark Seabornc3bd1772013-12-31 13:05:15 +0000412 switch(cast<MCSymbolRefExpr>(Expr)->getKind()) {
413 default: llvm_unreachable("Unknown fixup kind!");
414 break;
415 case MCSymbolRefExpr::VK_Mips_GPOFF_HI :
416 FixupKind = Mips::fixup_Mips_GPOFF_HI;
417 break;
418 case MCSymbolRefExpr::VK_Mips_GPOFF_LO :
419 FixupKind = Mips::fixup_Mips_GPOFF_LO;
420 break;
421 case MCSymbolRefExpr::VK_Mips_GOT_PAGE :
David Woodhoused2cca112014-01-28 23:13:25 +0000422 FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOT_PAGE
Mark Seabornc3bd1772013-12-31 13:05:15 +0000423 : Mips::fixup_Mips_GOT_PAGE;
424 break;
425 case MCSymbolRefExpr::VK_Mips_GOT_OFST :
David Woodhoused2cca112014-01-28 23:13:25 +0000426 FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOT_OFST
Mark Seabornc3bd1772013-12-31 13:05:15 +0000427 : Mips::fixup_Mips_GOT_OFST;
428 break;
429 case MCSymbolRefExpr::VK_Mips_GOT_DISP :
David Woodhoused2cca112014-01-28 23:13:25 +0000430 FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOT_DISP
Mark Seabornc3bd1772013-12-31 13:05:15 +0000431 : Mips::fixup_Mips_GOT_DISP;
432 break;
433 case MCSymbolRefExpr::VK_Mips_GPREL:
434 FixupKind = Mips::fixup_Mips_GPREL16;
435 break;
436 case MCSymbolRefExpr::VK_Mips_GOT_CALL:
David Woodhoused2cca112014-01-28 23:13:25 +0000437 FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_CALL16
Mark Seabornc3bd1772013-12-31 13:05:15 +0000438 : Mips::fixup_Mips_CALL16;
439 break;
440 case MCSymbolRefExpr::VK_Mips_GOT16:
David Woodhoused2cca112014-01-28 23:13:25 +0000441 FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOT16
Mark Seabornc3bd1772013-12-31 13:05:15 +0000442 : Mips::fixup_Mips_GOT_Global;
443 break;
444 case MCSymbolRefExpr::VK_Mips_GOT:
David Woodhoused2cca112014-01-28 23:13:25 +0000445 FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOT16
Mark Seabornc3bd1772013-12-31 13:05:15 +0000446 : Mips::fixup_Mips_GOT_Local;
447 break;
448 case MCSymbolRefExpr::VK_Mips_ABS_HI:
David Woodhoused2cca112014-01-28 23:13:25 +0000449 FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_HI16
Mark Seabornc3bd1772013-12-31 13:05:15 +0000450 : Mips::fixup_Mips_HI16;
451 break;
452 case MCSymbolRefExpr::VK_Mips_ABS_LO:
David Woodhoused2cca112014-01-28 23:13:25 +0000453 FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_LO16
Mark Seabornc3bd1772013-12-31 13:05:15 +0000454 : Mips::fixup_Mips_LO16;
455 break;
456 case MCSymbolRefExpr::VK_Mips_TLSGD:
David Woodhoused2cca112014-01-28 23:13:25 +0000457 FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_GD
Mark Seabornc3bd1772013-12-31 13:05:15 +0000458 : Mips::fixup_Mips_TLSGD;
459 break;
460 case MCSymbolRefExpr::VK_Mips_TLSLDM:
David Woodhoused2cca112014-01-28 23:13:25 +0000461 FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_LDM
Mark Seabornc3bd1772013-12-31 13:05:15 +0000462 : Mips::fixup_Mips_TLSLDM;
463 break;
464 case MCSymbolRefExpr::VK_Mips_DTPREL_HI:
David Woodhoused2cca112014-01-28 23:13:25 +0000465 FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_DTPREL_HI16
Mark Seabornc3bd1772013-12-31 13:05:15 +0000466 : Mips::fixup_Mips_DTPREL_HI;
467 break;
468 case MCSymbolRefExpr::VK_Mips_DTPREL_LO:
David Woodhoused2cca112014-01-28 23:13:25 +0000469 FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_DTPREL_LO16
Mark Seabornc3bd1772013-12-31 13:05:15 +0000470 : Mips::fixup_Mips_DTPREL_LO;
471 break;
472 case MCSymbolRefExpr::VK_Mips_GOTTPREL:
473 FixupKind = Mips::fixup_Mips_GOTTPREL;
474 break;
475 case MCSymbolRefExpr::VK_Mips_TPREL_HI:
David Woodhoused2cca112014-01-28 23:13:25 +0000476 FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_TPREL_HI16
Mark Seabornc3bd1772013-12-31 13:05:15 +0000477 : Mips::fixup_Mips_TPREL_HI;
478 break;
479 case MCSymbolRefExpr::VK_Mips_TPREL_LO:
David Woodhoused2cca112014-01-28 23:13:25 +0000480 FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_TPREL_LO16
Mark Seabornc3bd1772013-12-31 13:05:15 +0000481 : Mips::fixup_Mips_TPREL_LO;
482 break;
483 case MCSymbolRefExpr::VK_Mips_HIGHER:
484 FixupKind = Mips::fixup_Mips_HIGHER;
485 break;
486 case MCSymbolRefExpr::VK_Mips_HIGHEST:
487 FixupKind = Mips::fixup_Mips_HIGHEST;
488 break;
489 case MCSymbolRefExpr::VK_Mips_GOT_HI16:
490 FixupKind = Mips::fixup_Mips_GOT_HI16;
491 break;
492 case MCSymbolRefExpr::VK_Mips_GOT_LO16:
493 FixupKind = Mips::fixup_Mips_GOT_LO16;
494 break;
495 case MCSymbolRefExpr::VK_Mips_CALL_HI16:
496 FixupKind = Mips::fixup_Mips_CALL_HI16;
497 break;
498 case MCSymbolRefExpr::VK_Mips_CALL_LO16:
499 FixupKind = Mips::fixup_Mips_CALL_LO16;
500 break;
501 } // switch
Akira Hatanakafe384a22012-03-27 02:33:05 +0000502
Jack Carterb5cf5902013-04-17 00:18:04 +0000503 Fixups.push_back(MCFixup::Create(0, Expr, MCFixupKind(FixupKind)));
504 return 0;
505 }
Akira Hatanakafe384a22012-03-27 02:33:05 +0000506 return 0;
Bruno Cardoso Lopesc85e3ff2011-11-11 22:58:42 +0000507}
508
Jack Carterb5cf5902013-04-17 00:18:04 +0000509/// getMachineOpValue - Return binary encoding of operand. If the machine
510/// operand requires relocation, record the relocation and return zero.
511unsigned MipsMCCodeEmitter::
512getMachineOpValue(const MCInst &MI, const MCOperand &MO,
David Woodhouse3fa98a62014-01-28 23:13:18 +0000513 SmallVectorImpl<MCFixup> &Fixups,
514 const MCSubtargetInfo &STI) const {
Jack Carterb5cf5902013-04-17 00:18:04 +0000515 if (MO.isReg()) {
516 unsigned Reg = MO.getReg();
Bill Wendlingbc07a892013-06-18 07:20:20 +0000517 unsigned RegNo = Ctx.getRegisterInfo()->getEncodingValue(Reg);
Jack Carterb5cf5902013-04-17 00:18:04 +0000518 return RegNo;
519 } else if (MO.isImm()) {
520 return static_cast<unsigned>(MO.getImm());
521 } else if (MO.isFPImm()) {
522 return static_cast<unsigned>(APFloat(MO.getFPImm())
523 .bitcastToAPInt().getHiBits(32).getLimitedValue());
524 }
525 // MO must be an Expr.
526 assert(MO.isExpr());
David Woodhouse3fa98a62014-01-28 23:13:18 +0000527 return getExprOpValue(MO.getExpr(),Fixups, STI);
Jack Carterb5cf5902013-04-17 00:18:04 +0000528}
529
Matheus Almeida6b59c442013-12-05 11:06:22 +0000530/// getMSAMemEncoding - Return binary encoding of memory operand for LD/ST
531/// instructions.
532unsigned
533MipsMCCodeEmitter::getMSAMemEncoding(const MCInst &MI, unsigned OpNo,
David Woodhouse3fa98a62014-01-28 23:13:18 +0000534 SmallVectorImpl<MCFixup> &Fixups,
535 const MCSubtargetInfo &STI) const {
Matheus Almeida6b59c442013-12-05 11:06:22 +0000536 // Base register is encoded in bits 20-16, offset is encoded in bits 15-0.
537 assert(MI.getOperand(OpNo).isReg());
David Woodhouse3fa98a62014-01-28 23:13:18 +0000538 unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo),Fixups, STI) << 16;
539 unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI);
Matheus Almeida6b59c442013-12-05 11:06:22 +0000540
541 // The immediate field of an LD/ST instruction is scaled which means it must
542 // be divided (when encoding) by the size (in bytes) of the instructions'
543 // data format.
544 // .b - 1 byte
545 // .h - 2 bytes
546 // .w - 4 bytes
547 // .d - 8 bytes
548 switch(MI.getOpcode())
549 {
550 default:
551 assert (0 && "Unexpected instruction");
552 break;
553 case Mips::LD_B:
554 case Mips::ST_B:
555 // We don't need to scale the offset in this case
556 break;
557 case Mips::LD_H:
558 case Mips::ST_H:
559 OffBits >>= 1;
560 break;
561 case Mips::LD_W:
562 case Mips::ST_W:
563 OffBits >>= 2;
564 break;
565 case Mips::LD_D:
566 case Mips::ST_D:
567 OffBits >>= 3;
568 break;
569 }
570
571 return (OffBits & 0xFFFF) | RegBits;
572}
573
Bruno Cardoso Lopesc85e3ff2011-11-11 22:58:42 +0000574/// getMemEncoding - Return binary encoding of memory related operand.
575/// If the offset operand requires relocation, record the relocation.
576unsigned
577MipsMCCodeEmitter::getMemEncoding(const MCInst &MI, unsigned OpNo,
David Woodhouse3fa98a62014-01-28 23:13:18 +0000578 SmallVectorImpl<MCFixup> &Fixups,
579 const MCSubtargetInfo &STI) const {
Bruno Cardoso Lopesc85e3ff2011-11-11 22:58:42 +0000580 // Base register is encoded in bits 20-16, offset is encoded in bits 15-0.
581 assert(MI.getOperand(OpNo).isReg());
David Woodhouse3fa98a62014-01-28 23:13:18 +0000582 unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo),Fixups, STI) << 16;
583 unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI);
Bruno Cardoso Lopesc85e3ff2011-11-11 22:58:42 +0000584
585 return (OffBits & 0xFFFF) | RegBits;
586}
587
Jack Carter97700972013-08-13 20:19:16 +0000588unsigned MipsMCCodeEmitter::
589getMemEncodingMMImm12(const MCInst &MI, unsigned OpNo,
David Woodhouse3fa98a62014-01-28 23:13:18 +0000590 SmallVectorImpl<MCFixup> &Fixups,
591 const MCSubtargetInfo &STI) const {
Jack Carter97700972013-08-13 20:19:16 +0000592 // Base register is encoded in bits 20-16, offset is encoded in bits 11-0.
593 assert(MI.getOperand(OpNo).isReg());
David Woodhouse3fa98a62014-01-28 23:13:18 +0000594 unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI) << 16;
595 unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI);
Jack Carter97700972013-08-13 20:19:16 +0000596
597 return (OffBits & 0x0FFF) | RegBits;
598}
599
Bruno Cardoso Lopesc85e3ff2011-11-11 22:58:42 +0000600unsigned
601MipsMCCodeEmitter::getSizeExtEncoding(const MCInst &MI, unsigned OpNo,
David Woodhouse3fa98a62014-01-28 23:13:18 +0000602 SmallVectorImpl<MCFixup> &Fixups,
603 const MCSubtargetInfo &STI) const {
Akira Hatanaka049e9e42011-11-23 22:19:28 +0000604 assert(MI.getOperand(OpNo).isImm());
David Woodhouse3fa98a62014-01-28 23:13:18 +0000605 unsigned SizeEncoding = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI);
Bruno Cardoso Lopes56b70de2011-12-07 22:35:30 +0000606 return SizeEncoding - 1;
Bruno Cardoso Lopesc85e3ff2011-11-11 22:58:42 +0000607}
608
Akira Hatanaka049e9e42011-11-23 22:19:28 +0000609// FIXME: should be called getMSBEncoding
610//
Bruno Cardoso Lopesc85e3ff2011-11-11 22:58:42 +0000611unsigned
612MipsMCCodeEmitter::getSizeInsEncoding(const MCInst &MI, unsigned OpNo,
David Woodhouse3fa98a62014-01-28 23:13:18 +0000613 SmallVectorImpl<MCFixup> &Fixups,
614 const MCSubtargetInfo &STI) const {
Akira Hatanaka049e9e42011-11-23 22:19:28 +0000615 assert(MI.getOperand(OpNo-1).isImm());
616 assert(MI.getOperand(OpNo).isImm());
David Woodhouse3fa98a62014-01-28 23:13:18 +0000617 unsigned Position = getMachineOpValue(MI, MI.getOperand(OpNo-1), Fixups, STI);
618 unsigned Size = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI);
Akira Hatanaka049e9e42011-11-23 22:19:28 +0000619
Bruno Cardoso Lopes56b70de2011-12-07 22:35:30 +0000620 return Position + Size - 1;
Bruno Cardoso Lopesc85e3ff2011-11-11 22:58:42 +0000621}
622
Matheus Almeida779c5932013-11-18 12:32:49 +0000623unsigned
624MipsMCCodeEmitter::getLSAImmEncoding(const MCInst &MI, unsigned OpNo,
David Woodhouse3fa98a62014-01-28 23:13:18 +0000625 SmallVectorImpl<MCFixup> &Fixups,
626 const MCSubtargetInfo &STI) const {
Matheus Almeida779c5932013-11-18 12:32:49 +0000627 assert(MI.getOperand(OpNo).isImm());
628 // The immediate is encoded as 'immediate - 1'.
David Woodhouse3fa98a62014-01-28 23:13:18 +0000629 return getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI) - 1;
Matheus Almeida779c5932013-11-18 12:32:49 +0000630}
631
Bruno Cardoso Lopesc85e3ff2011-11-11 22:58:42 +0000632#include "MipsGenMCCodeEmitter.inc"
633