1//===-- MipsMCCodeEmitter.cpp - Convert Mips Code to Machine Code ---------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file implements the MipsMCCodeEmitter class.
10//
11//===----------------------------------------------------------------------===//
12
13#include "MipsMCCodeEmitter.h"
14#include "MCTargetDesc/MipsBaseInfo.h"
15#include "MCTargetDesc/MipsFixupKinds.h"
16#include "MCTargetDesc/MipsMCAsmInfo.h"
17#include "MCTargetDesc/MipsMCTargetDesc.h"
18#include "llvm/ADT/APFloat.h"
19#include "llvm/ADT/APInt.h"
20#include "llvm/ADT/SmallVector.h"
21#include "llvm/MC/MCContext.h"
22#include "llvm/MC/MCExpr.h"
23#include "llvm/MC/MCFixup.h"
24#include "llvm/MC/MCInst.h"
25#include "llvm/MC/MCInstrDesc.h"
26#include "llvm/MC/MCInstrInfo.h"
27#include "llvm/MC/MCRegisterInfo.h"
28#include "llvm/MC/MCSubtargetInfo.h"
29#include "llvm/Support/Casting.h"
30#include "llvm/Support/EndianStream.h"
31#include "llvm/Support/raw_ostream.h"
32#include <cassert>
33#include <cstdint>
34
35using namespace llvm;
36
37#define DEBUG_TYPE "mccodeemitter"
38
39#define GET_INSTRMAP_INFO
40#include "MipsGenInstrInfo.inc"
41#undef GET_INSTRMAP_INFO
42
43namespace llvm {
44
45MCCodeEmitter *createMipsMCCodeEmitterEB(const MCInstrInfo &MCII,
46 MCContext &Ctx) {
47 return new MipsMCCodeEmitter(MCII, Ctx, false);
48}
49
50MCCodeEmitter *createMipsMCCodeEmitterEL(const MCInstrInfo &MCII,
51 MCContext &Ctx) {
52 return new MipsMCCodeEmitter(MCII, Ctx, true);
53}
54
55} // end namespace llvm
56
57static void addFixup(SmallVectorImpl<MCFixup> &Fixups, uint32_t Offset,
58 const MCExpr *Value, uint16_t Kind) {
59 bool PCRel = false;
60 switch (Kind) {
61 case Mips::fixup_Mips_PC16:
62 case Mips::fixup_Mips_Branch_PCRel:
63 case Mips::fixup_MIPS_PC18_S3:
64 case Mips::fixup_MIPS_PC19_S2:
65 case Mips::fixup_MIPS_PC21_S2:
66 case Mips::fixup_MIPS_PC26_S2:
67 case Mips::fixup_MIPS_PCHI16:
68 case Mips::fixup_MIPS_PCLO16:
69 case Mips::fixup_MICROMIPS_PC7_S1:
70 case Mips::fixup_MICROMIPS_PC10_S1:
71 case Mips::fixup_MICROMIPS_PC16_S1:
72 case Mips::fixup_MICROMIPS_PC26_S1:
73 case Mips::fixup_MICROMIPS_PC19_S2:
74 case Mips::fixup_MICROMIPS_PC18_S3:
75 case Mips::fixup_MICROMIPS_PC21_S1:
76 PCRel = true;
77 }
78 Fixups.push_back(Elt: MCFixup::create(Offset, Value, Kind, PCRel));
79}
80
81// If the D<shift> instruction has a shift amount that is greater
82// than 31 (checked in calling routine), lower it to a D<shift>32 instruction
83static void LowerLargeShift(MCInst& Inst) {
84 assert(Inst.getNumOperands() == 3 && "Invalid no. of operands for shift!");
85 assert(Inst.getOperand(2).isImm());
86
87 int64_t Shift = Inst.getOperand(i: 2).getImm();
88 if (Shift <= 31)
89 return; // Do nothing
90 Shift -= 32;
91
92 // saminus32
93 Inst.getOperand(i: 2).setImm(Shift);
94
95 switch (Inst.getOpcode()) {
96 default:
97 // Calling function is not synchronized
98 llvm_unreachable("Unexpected shift instruction");
99 case Mips::DSLL:
100 Inst.setOpcode(Mips::DSLL32);
101 return;
102 case Mips::DSRL:
103 Inst.setOpcode(Mips::DSRL32);
104 return;
105 case Mips::DSRA:
106 Inst.setOpcode(Mips::DSRA32);
107 return;
108 case Mips::DROTR:
109 Inst.setOpcode(Mips::DROTR32);
110 return;
111 }
112}
113
114// Fix a bad compact branch encoding for beqc/bnec.
115void MipsMCCodeEmitter::LowerCompactBranch(MCInst& Inst) const {
116 // Encoding may be illegal !(rs < rt), but this situation is
117 // easily fixed.
118 MCRegister RegOp0 = Inst.getOperand(i: 0).getReg();
119 MCRegister RegOp1 = Inst.getOperand(i: 1).getReg();
120
121 unsigned Reg0 = Ctx.getRegisterInfo()->getEncodingValue(Reg: RegOp0);
122 unsigned Reg1 = Ctx.getRegisterInfo()->getEncodingValue(Reg: RegOp1);
123
124 if (Inst.getOpcode() == Mips::BNEC || Inst.getOpcode() == Mips::BEQC ||
125 Inst.getOpcode() == Mips::BNEC64 || Inst.getOpcode() == Mips::BEQC64) {
126 assert(Reg0 != Reg1 && "Instruction has bad operands ($rs == $rt)!");
127 if (Reg0 < Reg1)
128 return;
129 } else if (Inst.getOpcode() == Mips::BNVC || Inst.getOpcode() == Mips::BOVC) {
130 if (Reg0 >= Reg1)
131 return;
132 } else if (Inst.getOpcode() == Mips::BNVC_MMR6 ||
133 Inst.getOpcode() == Mips::BOVC_MMR6) {
134 if (Reg1 >= Reg0)
135 return;
136 } else
137 llvm_unreachable("Cannot rewrite unknown branch!");
138
139 Inst.getOperand(i: 0).setReg(RegOp1);
140 Inst.getOperand(i: 1).setReg(RegOp0);
141}
142
143bool MipsMCCodeEmitter::isMicroMips(const MCSubtargetInfo &STI) const {
144 return STI.hasFeature(Feature: Mips::FeatureMicroMips);
145}
146
147bool MipsMCCodeEmitter::isMips32r6(const MCSubtargetInfo &STI) const {
148 return STI.hasFeature(Feature: Mips::FeatureMips32r6);
149}
150
151void MipsMCCodeEmitter::EmitByte(unsigned char C, raw_ostream &OS) const {
152 OS << (char)C;
153}
154
155/// encodeInstruction - Emit the instruction.
156/// Size the instruction with Desc.getSize().
157void MipsMCCodeEmitter::encodeInstruction(const MCInst &MI,
158 SmallVectorImpl<char> &CB,
159 SmallVectorImpl<MCFixup> &Fixups,
160 const MCSubtargetInfo &STI) const {
161 // Non-pseudo instructions that get changed for direct object
162 // only based on operand values.
163 // If this list of instructions get much longer we will move
164 // the check to a function call. Until then, this is more efficient.
165 MCInst TmpInst = MI;
166 switch (MI.getOpcode()) {
167 // If shift amount is >= 32 it the inst needs to be lowered further
168 case Mips::DSLL:
169 case Mips::DSRL:
170 case Mips::DSRA:
171 case Mips::DROTR:
172 LowerLargeShift(Inst&: TmpInst);
173 break;
174 // Compact branches, enforce encoding restrictions.
175 case Mips::BEQC:
176 case Mips::BNEC:
177 case Mips::BEQC64:
178 case Mips::BNEC64:
179 case Mips::BOVC:
180 case Mips::BOVC_MMR6:
181 case Mips::BNVC:
182 case Mips::BNVC_MMR6:
183 LowerCompactBranch(Inst&: TmpInst);
184 }
185
186 size_t N = Fixups.size();
187 uint32_t Binary = getBinaryCodeForInstr(MI: TmpInst, Fixups, STI);
188
189 // Check for unimplemented opcodes.
190 // Unfortunately in MIPS both NOP and SLL will come in with Binary == 0
191 // so we have to special check for them.
192 const unsigned Opcode = TmpInst.getOpcode();
193 if ((Opcode != Mips::NOP) && (Opcode != Mips::SLL) &&
194 (Opcode != Mips::SLL_MM) && (Opcode != Mips::SLL_MMR6) && !Binary)
195 llvm_unreachable("unimplemented opcode in encodeInstruction()");
196
197 int NewOpcode = -1;
198 if (isMicroMips(STI)) {
199 if (isMips32r6(STI)) {
200 NewOpcode = Mips::MipsR62MicroMipsR6(Opcode, inArch: Mips::Arch_micromipsr6);
201 if (NewOpcode == -1)
202 NewOpcode = Mips::Std2MicroMipsR6(Opcode, inArch: Mips::Arch_micromipsr6);
203 }
204 else
205 NewOpcode = Mips::Std2MicroMips(Opcode, inArch: Mips::Arch_micromips);
206
207 // Check whether it is Dsp instruction.
208 if (NewOpcode == -1)
209 NewOpcode = Mips::Dsp2MicroMips(Opcode, inArch: Mips::Arch_mmdsp);
210
211 if (NewOpcode != -1) {
212 if (Fixups.size() > N)
213 Fixups.pop_back();
214
215 TmpInst.setOpcode (NewOpcode);
216 Binary = getBinaryCodeForInstr(MI: TmpInst, Fixups, STI);
217 }
218
219 if (((MI.getOpcode() == Mips::MOVEP_MM) ||
220 (MI.getOpcode() == Mips::MOVEP_MMR6))) {
221 unsigned RegPair = getMovePRegPairOpValue(MI, OpNo: 0, Fixups, STI);
222 Binary = (Binary & 0xFFFFFC7F) | (RegPair << 7);
223 }
224 }
225
226 const MCInstrDesc &Desc = MCII.get(Opcode: TmpInst.getOpcode());
227
228 // Get byte count of instruction
229 unsigned Size = Desc.getSize();
230 if (!Size)
231 llvm_unreachable("Desc.getSize() returns 0");
232
233 auto Endian =
234 IsLittleEndian ? llvm::endianness::little : llvm::endianness::big;
235 if (Size == 2) {
236 support::endian::write<uint16_t>(Out&: CB, V: Binary, E: Endian);
237 } else if (IsLittleEndian && isMicroMips(STI)) {
238 support::endian::write<uint16_t>(Out&: CB, V: Binary >> 16, E: Endian);
239 support::endian::write<uint16_t>(Out&: CB, V: Binary & 0xffff, E: Endian);
240 } else {
241 support::endian::write<uint32_t>(Out&: CB, V: Binary, E: Endian);
242 }
243}
244
245/// getBranchTargetOpValue - Return binary encoding of the branch
246/// target operand. If the machine operand requires relocation,
247/// record the relocation and return zero.
248unsigned MipsMCCodeEmitter::
249getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
250 SmallVectorImpl<MCFixup> &Fixups,
251 const MCSubtargetInfo &STI) const {
252 const MCOperand &MO = MI.getOperand(i: OpNo);
253
254 // If the destination is an immediate, divide by 4.
255 if (MO.isImm()) return MO.getImm() >> 2;
256
257 assert(MO.isExpr() &&
258 "getBranchTargetOpValue expects only expressions or immediates");
259
260 const MCExpr *FixupExpression = MCBinaryExpr::createAdd(
261 LHS: MO.getExpr(), RHS: MCConstantExpr::create(Value: -4, Ctx), Ctx);
262 addFixup(Fixups, Offset: 0, Value: FixupExpression, Kind: Mips::fixup_Mips_PC16);
263 return 0;
264}
265
266/// getBranchTargetOpValue1SImm16 - Return binary encoding of the branch
267/// target operand. If the machine operand requires relocation,
268/// record the relocation and return zero.
269unsigned MipsMCCodeEmitter::
270getBranchTargetOpValue1SImm16(const MCInst &MI, unsigned OpNo,
271 SmallVectorImpl<MCFixup> &Fixups,
272 const MCSubtargetInfo &STI) const {
273 const MCOperand &MO = MI.getOperand(i: OpNo);
274
275 // If the destination is an immediate, divide by 2.
276 if (MO.isImm()) return MO.getImm() >> 1;
277
278 assert(MO.isExpr() &&
279 "getBranchTargetOpValue expects only expressions or immediates");
280
281 const MCExpr *FixupExpression = MCBinaryExpr::createAdd(
282 LHS: MO.getExpr(), RHS: MCConstantExpr::create(Value: -4, Ctx), Ctx);
283 addFixup(Fixups, Offset: 0, Value: FixupExpression, Kind: Mips::fixup_Mips_PC16);
284 return 0;
285}
286
287/// getBranchTargetOpValueMMR6 - Return binary encoding of the branch
288/// target operand. If the machine operand requires relocation,
289/// record the relocation and return zero.
290unsigned MipsMCCodeEmitter::
291getBranchTargetOpValueMMR6(const MCInst &MI, unsigned OpNo,
292 SmallVectorImpl<MCFixup> &Fixups,
293 const MCSubtargetInfo &STI) const {
294 const MCOperand &MO = MI.getOperand(i: OpNo);
295
296 // If the destination is an immediate, divide by 2.
297 if (MO.isImm())
298 return MO.getImm() >> 1;
299
300 assert(MO.isExpr() &&
301 "getBranchTargetOpValueMMR6 expects only expressions or immediates");
302
303 const MCExpr *FixupExpression = MCBinaryExpr::createAdd(
304 LHS: MO.getExpr(), RHS: MCConstantExpr::create(Value: -2, Ctx), Ctx);
305 addFixup(Fixups, Offset: 0, Value: FixupExpression, Kind: Mips::fixup_Mips_PC16);
306 return 0;
307}
308
309/// getBranchTargetOpValueLsl2MMR6 - Return binary encoding of the branch
310/// target operand. If the machine operand requires relocation,
311/// record the relocation and return zero.
312unsigned MipsMCCodeEmitter::
313getBranchTargetOpValueLsl2MMR6(const MCInst &MI, unsigned OpNo,
314 SmallVectorImpl<MCFixup> &Fixups,
315 const MCSubtargetInfo &STI) const {
316 const MCOperand &MO = MI.getOperand(i: OpNo);
317
318 // If the destination is an immediate, divide by 4.
319 if (MO.isImm())
320 return MO.getImm() >> 2;
321
322 assert(MO.isExpr() &&
323 "getBranchTargetOpValueLsl2MMR6 expects only expressions or immediates");
324
325 const MCExpr *FixupExpression = MCBinaryExpr::createAdd(
326 LHS: MO.getExpr(), RHS: MCConstantExpr::create(Value: -4, Ctx), Ctx);
327 addFixup(Fixups, Offset: 0, Value: FixupExpression, Kind: Mips::fixup_Mips_PC16);
328 return 0;
329}
330
331/// getBranchTarget7OpValueMM - Return binary encoding of the microMIPS branch
332/// target operand. If the machine operand requires relocation,
333/// record the relocation and return zero.
334unsigned MipsMCCodeEmitter::
335getBranchTarget7OpValueMM(const MCInst &MI, unsigned OpNo,
336 SmallVectorImpl<MCFixup> &Fixups,
337 const MCSubtargetInfo &STI) const {
338 const MCOperand &MO = MI.getOperand(i: OpNo);
339
340 // If the destination is an immediate, divide by 2.
341 if (MO.isImm()) return MO.getImm() >> 1;
342
343 assert(MO.isExpr() &&
344 "getBranchTargetOpValueMM expects only expressions or immediates");
345
346 const MCExpr *Expr = MO.getExpr();
347 addFixup(Fixups, Offset: 0, Value: Expr, Kind: Mips::fixup_MICROMIPS_PC7_S1);
348 return 0;
349}
350
351/// getBranchTargetOpValueMMPC10 - Return binary encoding of the microMIPS
352/// 10-bit branch target operand. If the machine operand requires relocation,
353/// record the relocation and return zero.
354unsigned MipsMCCodeEmitter::
355getBranchTargetOpValueMMPC10(const MCInst &MI, unsigned OpNo,
356 SmallVectorImpl<MCFixup> &Fixups,
357 const MCSubtargetInfo &STI) const {
358 const MCOperand &MO = MI.getOperand(i: OpNo);
359
360 // If the destination is an immediate, divide by 2.
361 if (MO.isImm()) return MO.getImm() >> 1;
362
363 assert(MO.isExpr() &&
364 "getBranchTargetOpValuePC10 expects only expressions or immediates");
365
366 const MCExpr *Expr = MO.getExpr();
367 addFixup(Fixups, Offset: 0, Value: Expr, Kind: Mips::fixup_MICROMIPS_PC10_S1);
368 return 0;
369}
370
371/// getBranchTargetOpValue - Return binary encoding of the microMIPS branch
372/// target operand. If the machine operand requires relocation,
373/// record the relocation and return zero.
374unsigned MipsMCCodeEmitter::
375getBranchTargetOpValueMM(const MCInst &MI, unsigned OpNo,
376 SmallVectorImpl<MCFixup> &Fixups,
377 const MCSubtargetInfo &STI) const {
378 const MCOperand &MO = MI.getOperand(i: OpNo);
379
380 // If the destination is an immediate, divide by 2.
381 if (MO.isImm()) return MO.getImm() >> 1;
382
383 assert(MO.isExpr() &&
384 "getBranchTargetOpValueMM expects only expressions or immediates");
385
386 const MCExpr *Expr = MO.getExpr();
387 addFixup(Fixups, Offset: 0, Value: Expr, Kind: Mips::fixup_MICROMIPS_PC16_S1);
388 return 0;
389}
390
391/// getBranchTarget21OpValue - Return binary encoding of the branch
392/// target operand. If the machine operand requires relocation,
393/// record the relocation and return zero.
394unsigned MipsMCCodeEmitter::
395getBranchTarget21OpValue(const MCInst &MI, unsigned OpNo,
396 SmallVectorImpl<MCFixup> &Fixups,
397 const MCSubtargetInfo &STI) const {
398 const MCOperand &MO = MI.getOperand(i: OpNo);
399
400 // If the destination is an immediate, divide by 4.
401 if (MO.isImm()) return MO.getImm() >> 2;
402
403 assert(MO.isExpr() &&
404 "getBranchTarget21OpValue expects only expressions or immediates");
405
406 const MCExpr *FixupExpression = MCBinaryExpr::createAdd(
407 LHS: MO.getExpr(), RHS: MCConstantExpr::create(Value: -4, Ctx), Ctx);
408 addFixup(Fixups, Offset: 0, Value: FixupExpression, Kind: Mips::fixup_MIPS_PC21_S2);
409 return 0;
410}
411
412/// getBranchTarget21OpValueMM - Return binary encoding of the branch
413/// target operand for microMIPS. If the machine operand requires
414/// relocation, record the relocation and return zero.
415unsigned MipsMCCodeEmitter::
416getBranchTarget21OpValueMM(const MCInst &MI, unsigned OpNo,
417 SmallVectorImpl<MCFixup> &Fixups,
418 const MCSubtargetInfo &STI) const {
419 const MCOperand &MO = MI.getOperand(i: OpNo);
420
421 // If the destination is an immediate, divide by 4.
422 if (MO.isImm()) return MO.getImm() >> 2;
423
424 assert(MO.isExpr() &&
425 "getBranchTarget21OpValueMM expects only expressions or immediates");
426
427 const MCExpr *FixupExpression = MCBinaryExpr::createAdd(
428 LHS: MO.getExpr(), RHS: MCConstantExpr::create(Value: -4, Ctx), Ctx);
429 addFixup(Fixups, Offset: 0, Value: FixupExpression, Kind: Mips::fixup_MICROMIPS_PC21_S1);
430 return 0;
431}
432
433/// getBranchTarget26OpValue - Return binary encoding of the branch
434/// target operand. If the machine operand requires relocation,
435/// record the relocation and return zero.
436unsigned MipsMCCodeEmitter::
437getBranchTarget26OpValue(const MCInst &MI, unsigned OpNo,
438 SmallVectorImpl<MCFixup> &Fixups,
439 const MCSubtargetInfo &STI) const {
440 const MCOperand &MO = MI.getOperand(i: OpNo);
441
442 // If the destination is an immediate, divide by 4.
443 if (MO.isImm()) return MO.getImm() >> 2;
444
445 assert(MO.isExpr() &&
446 "getBranchTarget26OpValue expects only expressions or immediates");
447
448 const MCExpr *FixupExpression = MCBinaryExpr::createAdd(
449 LHS: MO.getExpr(), RHS: MCConstantExpr::create(Value: -4, Ctx), Ctx);
450 addFixup(Fixups, Offset: 0, Value: FixupExpression, Kind: Mips::fixup_MIPS_PC26_S2);
451 return 0;
452}
453
454/// getBranchTarget26OpValueMM - Return binary encoding of the branch
455/// target operand. If the machine operand requires relocation,
456/// record the relocation and return zero.
457unsigned MipsMCCodeEmitter::getBranchTarget26OpValueMM(
458 const MCInst &MI, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups,
459 const MCSubtargetInfo &STI) const {
460 const MCOperand &MO = MI.getOperand(i: OpNo);
461
462 // If the destination is an immediate, divide by 2.
463 if (MO.isImm())
464 return MO.getImm() >> 1;
465
466 assert(MO.isExpr() &&
467 "getBranchTarget26OpValueMM expects only expressions or immediates");
468
469 const MCExpr *FixupExpression = MCBinaryExpr::createAdd(
470 LHS: MO.getExpr(), RHS: MCConstantExpr::create(Value: -4, Ctx), Ctx);
471 addFixup(Fixups, Offset: 0, Value: FixupExpression, Kind: Mips::fixup_MICROMIPS_PC26_S1);
472 return 0;
473}
474
475/// getJumpOffset16OpValue - Return binary encoding of the jump
476/// target operand. If the machine operand requires relocation,
477/// record the relocation and return zero.
478unsigned MipsMCCodeEmitter::
479getJumpOffset16OpValue(const MCInst &MI, unsigned OpNo,
480 SmallVectorImpl<MCFixup> &Fixups,
481 const MCSubtargetInfo &STI) const {
482 const MCOperand &MO = MI.getOperand(i: OpNo);
483
484 if (MO.isImm()) return MO.getImm();
485
486 assert(MO.isExpr() &&
487 "getJumpOffset16OpValue expects only expressions or an immediate");
488
489 const MCExpr *Expr = MO.getExpr();
490 Mips::Fixups FixupKind =
491 isMicroMips(STI) ? Mips::fixup_MICROMIPS_LO16 : Mips::fixup_Mips_LO16;
492 addFixup(Fixups, Offset: 0, Value: Expr, Kind: MCFixupKind(FixupKind));
493 return 0;
494}
495
496/// getJumpTargetOpValue - Return binary encoding of the jump
497/// target operand. If the machine operand requires relocation,
498/// record the relocation and return zero.
499unsigned MipsMCCodeEmitter::
500getJumpTargetOpValue(const MCInst &MI, unsigned OpNo,
501 SmallVectorImpl<MCFixup> &Fixups,
502 const MCSubtargetInfo &STI) const {
503 const MCOperand &MO = MI.getOperand(i: OpNo);
504 // If the destination is an immediate, divide by 4.
505 if (MO.isImm()) return MO.getImm()>>2;
506
507 assert(MO.isExpr() &&
508 "getJumpTargetOpValue expects only expressions or an immediate");
509
510 const MCExpr *Expr = MO.getExpr();
511 addFixup(Fixups, Offset: 0, Value: Expr, Kind: Mips::fixup_Mips_26);
512 return 0;
513}
514
515unsigned MipsMCCodeEmitter::
516getJumpTargetOpValueMM(const MCInst &MI, unsigned OpNo,
517 SmallVectorImpl<MCFixup> &Fixups,
518 const MCSubtargetInfo &STI) const {
519 const MCOperand &MO = MI.getOperand(i: OpNo);
520 // If the destination is an immediate, divide by 2.
521 if (MO.isImm()) return MO.getImm() >> 1;
522
523 assert(MO.isExpr() &&
524 "getJumpTargetOpValueMM expects only expressions or an immediate");
525
526 const MCExpr *Expr = MO.getExpr();
527 addFixup(Fixups, Offset: 0, Value: Expr, Kind: Mips::fixup_MICROMIPS_26_S1);
528 return 0;
529}
530
531unsigned MipsMCCodeEmitter::
532getUImm5Lsl2Encoding(const MCInst &MI, unsigned OpNo,
533 SmallVectorImpl<MCFixup> &Fixups,
534 const MCSubtargetInfo &STI) const {
535 const MCOperand &MO = MI.getOperand(i: OpNo);
536 if (MO.isImm()) {
537 // The immediate is encoded as 'immediate << 2'.
538 unsigned Res = getMachineOpValue(MI, MO, Fixups, STI);
539 assert((Res & 3) == 0);
540 return Res >> 2;
541 }
542
543 assert(MO.isExpr() &&
544 "getUImm5Lsl2Encoding expects only expressions or an immediate");
545
546 return 0;
547}
548
549unsigned MipsMCCodeEmitter::
550getSImm3Lsa2Value(const MCInst &MI, unsigned OpNo,
551 SmallVectorImpl<MCFixup> &Fixups,
552 const MCSubtargetInfo &STI) const {
553 const MCOperand &MO = MI.getOperand(i: OpNo);
554 if (MO.isImm()) {
555 int Value = MO.getImm();
556 return Value >> 2;
557 }
558
559 return 0;
560}
561
562unsigned MipsMCCodeEmitter::
563getUImm6Lsl2Encoding(const MCInst &MI, unsigned OpNo,
564 SmallVectorImpl<MCFixup> &Fixups,
565 const MCSubtargetInfo &STI) const {
566 const MCOperand &MO = MI.getOperand(i: OpNo);
567 if (MO.isImm()) {
568 unsigned Value = MO.getImm();
569 return Value >> 2;
570 }
571
572 return 0;
573}
574
575unsigned MipsMCCodeEmitter::
576getSImm9AddiuspValue(const MCInst &MI, unsigned OpNo,
577 SmallVectorImpl<MCFixup> &Fixups,
578 const MCSubtargetInfo &STI) const {
579 const MCOperand &MO = MI.getOperand(i: OpNo);
580 if (MO.isImm()) {
581 unsigned Binary = (MO.getImm() >> 2) & 0x0000ffff;
582 return (((Binary & 0x8000) >> 7) | (Binary & 0x00ff));
583 }
584
585 return 0;
586}
587
588unsigned MipsMCCodeEmitter::
589getExprOpValue(const MCExpr *Expr, SmallVectorImpl<MCFixup> &Fixups,
590 const MCSubtargetInfo &STI) const {
591 MCExpr::ExprKind Kind = Expr->getKind();
592 if (Kind == MCExpr::Specifier) {
593 const auto *MipsExpr = cast<MCSpecifierExpr>(Val: Expr);
594
595 Mips::Fixups FixupKind = Mips::Fixups(0);
596 switch (MipsExpr->getSpecifier()) {
597 case Mips::S_None:
598 case Mips::S_Special:
599 llvm_unreachable("Unhandled fixup kind!");
600 break;
601 case Mips::S_DTPREL:
602 // MEK_DTPREL is used for marking TLS DIEExpr only
603 // and contains a regular sub-expression.
604 return getExprOpValue(Expr: MipsExpr->getSubExpr(), Fixups, STI);
605 case Mips::S_CALL_HI16:
606 FixupKind = Mips::fixup_Mips_CALL_HI16;
607 break;
608 case Mips::S_CALL_LO16:
609 FixupKind = Mips::fixup_Mips_CALL_LO16;
610 break;
611 case Mips::S_DTPREL_HI:
612 FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_DTPREL_HI16
613 : Mips::fixup_Mips_DTPREL_HI;
614 break;
615 case Mips::S_DTPREL_LO:
616 FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_DTPREL_LO16
617 : Mips::fixup_Mips_DTPREL_LO;
618 break;
619 case Mips::S_GOTTPREL:
620 FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOTTPREL
621 : Mips::fixup_Mips_GOTTPREL;
622 break;
623 case Mips::S_GOT:
624 FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOT16
625 : Mips::fixup_Mips_GOT;
626 break;
627 case Mips::S_GOT_CALL:
628 FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_CALL16
629 : Mips::fixup_Mips_CALL16;
630 break;
631 case Mips::S_GOT_DISP:
632 FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOT_DISP
633 : Mips::fixup_Mips_GOT_DISP;
634 break;
635 case Mips::S_GOT_HI16:
636 FixupKind = Mips::fixup_Mips_GOT_HI16;
637 break;
638 case Mips::S_GOT_LO16:
639 FixupKind = Mips::fixup_Mips_GOT_LO16;
640 break;
641 case Mips::S_GOT_PAGE:
642 FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOT_PAGE
643 : Mips::fixup_Mips_GOT_PAGE;
644 break;
645 case Mips::S_GOT_OFST:
646 FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOT_OFST
647 : Mips::fixup_Mips_GOT_OFST;
648 break;
649 case Mips::S_GPREL:
650 FixupKind = Mips::fixup_Mips_GPREL16;
651 break;
652 case Mips::S_LO:
653 // Check for %lo(%neg(%gp_rel(X)))
654 if (Mips::isGpOff(E: *MipsExpr))
655 FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GPOFF_LO
656 : Mips::fixup_Mips_GPOFF_LO;
657 else
658 FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_LO16
659 : Mips::fixup_Mips_LO16;
660 break;
661 case Mips::S_HIGHEST:
662 FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_HIGHEST
663 : Mips::fixup_Mips_HIGHEST;
664 break;
665 case Mips::S_HIGHER:
666 FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_HIGHER
667 : Mips::fixup_Mips_HIGHER;
668 break;
669 case Mips::S_HI:
670 // Check for %hi(%neg(%gp_rel(X)))
671 if (Mips::isGpOff(E: *MipsExpr))
672 FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GPOFF_HI
673 : Mips::fixup_Mips_GPOFF_HI;
674 else
675 FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_HI16
676 : Mips::fixup_Mips_HI16;
677 break;
678 case Mips::S_PCREL_HI16:
679 FixupKind = Mips::fixup_MIPS_PCHI16;
680 break;
681 case Mips::S_PCREL_LO16:
682 FixupKind = Mips::fixup_MIPS_PCLO16;
683 break;
684 case Mips::S_TLSGD:
685 FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_GD
686 : Mips::fixup_Mips_TLSGD;
687 break;
688 case Mips::S_TLSLDM:
689 FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_LDM
690 : Mips::fixup_Mips_TLSLDM;
691 break;
692 case Mips::S_TPREL_HI:
693 FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_TPREL_HI16
694 : Mips::fixup_Mips_TPREL_HI;
695 break;
696 case Mips::S_TPREL_LO:
697 FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_TPREL_LO16
698 : Mips::fixup_Mips_TPREL_LO;
699 break;
700 case Mips::S_NEG:
701 FixupKind =
702 isMicroMips(STI) ? Mips::fixup_MICROMIPS_SUB : Mips::fixup_Mips_SUB;
703 break;
704 }
705 addFixup(Fixups, Offset: 0, Value: MipsExpr, Kind: MCFixupKind(FixupKind));
706 return 0;
707 }
708
709 Ctx.reportError(L: Expr->getLoc(), Msg: "expected an immediate");
710 return 0;
711}
712
713/// getMachineOpValue - Return binary encoding of operand. If the machine
714/// operand requires relocation, record the relocation and return zero.
715unsigned MipsMCCodeEmitter::
716getMachineOpValue(const MCInst &MI, const MCOperand &MO,
717 SmallVectorImpl<MCFixup> &Fixups,
718 const MCSubtargetInfo &STI) const {
719 if (MO.isReg()) {
720 MCRegister Reg = MO.getReg();
721 unsigned RegNo = Ctx.getRegisterInfo()->getEncodingValue(Reg);
722 return RegNo;
723 } else if (MO.isImm()) {
724 return static_cast<unsigned>(MO.getImm());
725 } else if (MO.isDFPImm()) {
726 return static_cast<unsigned>(bit_cast<double>(from: MO.getDFPImm()));
727 }
728 // TODO: Set EncoderMethod to "getImmOpValue" for imm Operand so that
729 // getMachineOpValue will not be called for isExpr code paths.
730 assert(MO.isExpr());
731 return getImmOpValue(MI, MO, Fixups, STI);
732}
733
734unsigned MipsMCCodeEmitter::getImmOpValue(const MCInst &MI, const MCOperand &MO,
735 SmallVectorImpl<MCFixup> &Fixups,
736 const MCSubtargetInfo &STI) const {
737 if (MO.isImm())
738 return MO.getImm();
739 assert(MO.isExpr() && "getImmOpValue expects only expressions or immediates");
740 const MCExpr *Expr = MO.getExpr();
741 int64_t Res;
742 if (Expr->evaluateAsAbsolute(Res))
743 return Res;
744 unsigned MIFrm = MipsII::getFormat(TSFlags: MCII.get(Opcode: MI.getOpcode()).TSFlags);
745 if (!isa<MCSpecifierExpr>(Val: Expr) && MIFrm == MipsII::FrmI) {
746 addFixup(Fixups, Offset: 0, Value: Expr, Kind: Mips::fixup_Mips_AnyImm16);
747 return 0;
748 }
749 return getExprOpValue(Expr, Fixups, STI);
750}
751
752/// Return binary encoding of memory related operand.
753/// If the offset operand requires relocation, record the relocation.
754template <unsigned ShiftAmount>
755unsigned MipsMCCodeEmitter::getMemEncoding(const MCInst &MI, unsigned OpNo,
756 SmallVectorImpl<MCFixup> &Fixups,
757 const MCSubtargetInfo &STI) const {
758 // Base register is encoded in bits 20-16, offset is encoded in bits 15-0.
759 assert(MI.getOperand(OpNo).isReg());
760 unsigned RegBits = getMachineOpValue(MI, MO: MI.getOperand(i: OpNo), Fixups, STI)
761 << 16;
762 unsigned OffBits = getMachineOpValue(MI, MO: MI.getOperand(i: OpNo+1), Fixups, STI);
763
764 // Apply the scale factor if there is one.
765 OffBits >>= ShiftAmount;
766
767 return (OffBits & 0xFFFF) | RegBits;
768}
769
770unsigned MipsMCCodeEmitter::
771getMemEncodingMMImm4(const MCInst &MI, unsigned OpNo,
772 SmallVectorImpl<MCFixup> &Fixups,
773 const MCSubtargetInfo &STI) const {
774 // Base register is encoded in bits 6-4, offset is encoded in bits 3-0.
775 assert(MI.getOperand(OpNo).isReg());
776 unsigned RegBits = getMachineOpValue(MI, MO: MI.getOperand(i: OpNo),
777 Fixups, STI) << 4;
778 unsigned OffBits = getMachineOpValue(MI, MO: MI.getOperand(i: OpNo+1),
779 Fixups, STI);
780
781 return (OffBits & 0xF) | RegBits;
782}
783
784unsigned MipsMCCodeEmitter::
785getMemEncodingMMImm4Lsl1(const MCInst &MI, unsigned OpNo,
786 SmallVectorImpl<MCFixup> &Fixups,
787 const MCSubtargetInfo &STI) const {
788 // Base register is encoded in bits 6-4, offset is encoded in bits 3-0.
789 assert(MI.getOperand(OpNo).isReg());
790 unsigned RegBits = getMachineOpValue(MI, MO: MI.getOperand(i: OpNo),
791 Fixups, STI) << 4;
792 unsigned OffBits = getMachineOpValue(MI, MO: MI.getOperand(i: OpNo+1),
793 Fixups, STI) >> 1;
794
795 return (OffBits & 0xF) | RegBits;
796}
797
798unsigned MipsMCCodeEmitter::
799getMemEncodingMMImm4Lsl2(const MCInst &MI, unsigned OpNo,
800 SmallVectorImpl<MCFixup> &Fixups,
801 const MCSubtargetInfo &STI) const {
802 // Base register is encoded in bits 6-4, offset is encoded in bits 3-0.
803 assert(MI.getOperand(OpNo).isReg());
804 unsigned RegBits = getMachineOpValue(MI, MO: MI.getOperand(i: OpNo),
805 Fixups, STI) << 4;
806 unsigned OffBits = getMachineOpValue(MI, MO: MI.getOperand(i: OpNo+1),
807 Fixups, STI) >> 2;
808
809 return (OffBits & 0xF) | RegBits;
810}
811
812unsigned MipsMCCodeEmitter::
813getMemEncodingMMSPImm5Lsl2(const MCInst &MI, unsigned OpNo,
814 SmallVectorImpl<MCFixup> &Fixups,
815 const MCSubtargetInfo &STI) const {
816 // Register is encoded in bits 9-5, offset is encoded in bits 4-0.
817 assert(MI.getOperand(OpNo).isReg() &&
818 (MI.getOperand(OpNo).getReg() == Mips::SP ||
819 MI.getOperand(OpNo).getReg() == Mips::SP_64) &&
820 "Unexpected base register!");
821 unsigned OffBits = getMachineOpValue(MI, MO: MI.getOperand(i: OpNo+1),
822 Fixups, STI) >> 2;
823
824 return OffBits & 0x1F;
825}
826
827unsigned MipsMCCodeEmitter::
828getMemEncodingMMGPImm7Lsl2(const MCInst &MI, unsigned OpNo,
829 SmallVectorImpl<MCFixup> &Fixups,
830 const MCSubtargetInfo &STI) const {
831 // Register is encoded in bits 9-7, offset is encoded in bits 6-0.
832 assert(MI.getOperand(OpNo).isReg() &&
833 MI.getOperand(OpNo).getReg() == Mips::GP &&
834 "Unexpected base register!");
835
836 unsigned OffBits = getMachineOpValue(MI, MO: MI.getOperand(i: OpNo+1),
837 Fixups, STI) >> 2;
838
839 return OffBits & 0x7F;
840}
841
842unsigned MipsMCCodeEmitter::
843getMemEncodingMMImm9(const MCInst &MI, unsigned OpNo,
844 SmallVectorImpl<MCFixup> &Fixups,
845 const MCSubtargetInfo &STI) const {
846 // Base register is encoded in bits 20-16, offset is encoded in bits 8-0.
847 assert(MI.getOperand(OpNo).isReg());
848 unsigned RegBits = getMachineOpValue(MI, MO: MI.getOperand(i: OpNo), Fixups,
849 STI) << 16;
850 unsigned OffBits =
851 getMachineOpValue(MI, MO: MI.getOperand(i: OpNo + 1), Fixups, STI);
852
853 return (OffBits & 0x1FF) | RegBits;
854}
855
856unsigned MipsMCCodeEmitter::
857getMemEncodingMMImm11(const MCInst &MI, unsigned OpNo,
858 SmallVectorImpl<MCFixup> &Fixups,
859 const MCSubtargetInfo &STI) const {
860 // Base register is encoded in bits 20-16, offset is encoded in bits 10-0.
861 assert(MI.getOperand(OpNo).isReg());
862 unsigned RegBits = getMachineOpValue(MI, MO: MI.getOperand(i: OpNo), Fixups,
863 STI) << 16;
864 unsigned OffBits = getMachineOpValue(MI, MO: MI.getOperand(i: OpNo+1), Fixups, STI);
865
866 return (OffBits & 0x07FF) | RegBits;
867}
868
869unsigned MipsMCCodeEmitter::
870getMemEncodingMMImm12(const MCInst &MI, unsigned OpNo,
871 SmallVectorImpl<MCFixup> &Fixups,
872 const MCSubtargetInfo &STI) const {
873 // opNum can be invalid if instruction had reglist as operand.
874 // MemOperand is always last operand of instruction (base + offset).
875 switch (MI.getOpcode()) {
876 default:
877 break;
878 case Mips::SWM32_MM:
879 case Mips::LWM32_MM:
880 OpNo = MI.getNumOperands() - 2;
881 break;
882 }
883
884 // Base register is encoded in bits 20-16, offset is encoded in bits 11-0.
885 assert(MI.getOperand(OpNo).isReg());
886 unsigned RegBits = getMachineOpValue(MI, MO: MI.getOperand(i: OpNo), Fixups, STI)
887 << 16;
888 unsigned OffBits = getMachineOpValue(MI, MO: MI.getOperand(i: OpNo+1), Fixups, STI);
889
890 return (OffBits & 0x0FFF) | RegBits;
891}
892
893unsigned MipsMCCodeEmitter::
894getMemEncodingMMImm16(const MCInst &MI, unsigned OpNo,
895 SmallVectorImpl<MCFixup> &Fixups,
896 const MCSubtargetInfo &STI) const {
897 // Base register is encoded in bits 20-16, offset is encoded in bits 15-0.
898 assert(MI.getOperand(OpNo).isReg());
899 unsigned RegBits = getMachineOpValue(MI, MO: MI.getOperand(i: OpNo), Fixups,
900 STI) << 16;
901 unsigned OffBits = getMachineOpValue(MI, MO: MI.getOperand(i: OpNo+1), Fixups, STI);
902
903 return (OffBits & 0xFFFF) | RegBits;
904}
905
906unsigned MipsMCCodeEmitter::
907getMemEncodingMMImm4sp(const MCInst &MI, unsigned OpNo,
908 SmallVectorImpl<MCFixup> &Fixups,
909 const MCSubtargetInfo &STI) const {
910 // opNum can be invalid if instruction had reglist as operand
911 // MemOperand is always last operand of instruction (base + offset)
912 switch (MI.getOpcode()) {
913 default:
914 break;
915 case Mips::SWM16_MM:
916 case Mips::SWM16_MMR6:
917 case Mips::LWM16_MM:
918 case Mips::LWM16_MMR6:
919 OpNo = MI.getNumOperands() - 2;
920 break;
921 }
922
923 // Offset is encoded in bits 4-0.
924 assert(MI.getOperand(OpNo).isReg());
925 // Base register is always SP - thus it is not encoded.
926 assert(MI.getOperand(OpNo+1).isImm());
927 unsigned OffBits = getMachineOpValue(MI, MO: MI.getOperand(i: OpNo+1), Fixups, STI);
928
929 return ((OffBits >> 2) & 0x0F);
930}
931
932// FIXME: should be called getMSBEncoding
933//
934unsigned
935MipsMCCodeEmitter::getSizeInsEncoding(const MCInst &MI, unsigned OpNo,
936 SmallVectorImpl<MCFixup> &Fixups,
937 const MCSubtargetInfo &STI) const {
938 assert(MI.getOperand(OpNo-1).isImm());
939 assert(MI.getOperand(OpNo).isImm());
940 unsigned Position = getMachineOpValue(MI, MO: MI.getOperand(i: OpNo-1), Fixups, STI);
941 unsigned Size = getMachineOpValue(MI, MO: MI.getOperand(i: OpNo), Fixups, STI);
942
943 return Position + Size - 1;
944}
945
946template <unsigned Bits, int Offset>
947unsigned
948MipsMCCodeEmitter::getUImmWithOffsetEncoding(const MCInst &MI, unsigned OpNo,
949 SmallVectorImpl<MCFixup> &Fixups,
950 const MCSubtargetInfo &STI) const {
951 assert(MI.getOperand(OpNo).isImm());
952 unsigned Value = getMachineOpValue(MI, MO: MI.getOperand(i: OpNo), Fixups, STI);
953 Value -= Offset;
954 return Value;
955}
956
957unsigned
958MipsMCCodeEmitter::getSimm19Lsl2Encoding(const MCInst &MI, unsigned OpNo,
959 SmallVectorImpl<MCFixup> &Fixups,
960 const MCSubtargetInfo &STI) const {
961 const MCOperand &MO = MI.getOperand(i: OpNo);
962 if (MO.isImm()) {
963 // The immediate is encoded as 'immediate << 2'.
964 unsigned Res = getMachineOpValue(MI, MO, Fixups, STI);
965 assert((Res & 3) == 0);
966 return Res >> 2;
967 }
968
969 assert(MO.isExpr() &&
970 "getSimm19Lsl2Encoding expects only expressions or an immediate");
971
972 const MCExpr *Expr = MO.getExpr();
973 Mips::Fixups FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_PC19_S2
974 : Mips::fixup_MIPS_PC19_S2;
975 addFixup(Fixups, Offset: 0, Value: Expr, Kind: MCFixupKind(FixupKind));
976 return 0;
977}
978
979unsigned
980MipsMCCodeEmitter::getSimm18Lsl3Encoding(const MCInst &MI, unsigned OpNo,
981 SmallVectorImpl<MCFixup> &Fixups,
982 const MCSubtargetInfo &STI) const {
983 const MCOperand &MO = MI.getOperand(i: OpNo);
984 if (MO.isImm()) {
985 // The immediate is encoded as 'immediate << 3'.
986 unsigned Res = getMachineOpValue(MI, MO: MI.getOperand(i: OpNo), Fixups, STI);
987 assert((Res & 7) == 0);
988 return Res >> 3;
989 }
990
991 assert(MO.isExpr() &&
992 "getSimm18Lsl2Encoding expects only expressions or an immediate");
993
994 const MCExpr *Expr = MO.getExpr();
995 Mips::Fixups FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_PC18_S3
996 : Mips::fixup_MIPS_PC18_S3;
997 addFixup(Fixups, Offset: 0, Value: Expr, Kind: MCFixupKind(FixupKind));
998 return 0;
999}
1000
1001unsigned
1002MipsMCCodeEmitter::getUImm3Mod8Encoding(const MCInst &MI, unsigned OpNo,
1003 SmallVectorImpl<MCFixup> &Fixups,
1004 const MCSubtargetInfo &STI) const {
1005 assert(MI.getOperand(OpNo).isImm());
1006 const MCOperand &MO = MI.getOperand(i: OpNo);
1007 return MO.getImm() % 8;
1008}
1009
1010unsigned
1011MipsMCCodeEmitter::getUImm4AndValue(const MCInst &MI, unsigned OpNo,
1012 SmallVectorImpl<MCFixup> &Fixups,
1013 const MCSubtargetInfo &STI) const {
1014 assert(MI.getOperand(OpNo).isImm());
1015 const MCOperand &MO = MI.getOperand(i: OpNo);
1016 unsigned Value = MO.getImm();
1017 switch (Value) {
1018 case 128: return 0x0;
1019 case 1: return 0x1;
1020 case 2: return 0x2;
1021 case 3: return 0x3;
1022 case 4: return 0x4;
1023 case 7: return 0x5;
1024 case 8: return 0x6;
1025 case 15: return 0x7;
1026 case 16: return 0x8;
1027 case 31: return 0x9;
1028 case 32: return 0xa;
1029 case 63: return 0xb;
1030 case 64: return 0xc;
1031 case 255: return 0xd;
1032 case 32768: return 0xe;
1033 case 65535: return 0xf;
1034 }
1035 llvm_unreachable("Unexpected value");
1036}
1037
1038unsigned
1039MipsMCCodeEmitter::getRegisterListOpValue(const MCInst &MI, unsigned OpNo,
1040 SmallVectorImpl<MCFixup> &Fixups,
1041 const MCSubtargetInfo &STI) const {
1042 unsigned res = 0;
1043
1044 // Register list operand is always first operand of instruction and it is
1045 // placed before memory operand (register + imm).
1046
1047 for (unsigned I = OpNo, E = MI.getNumOperands() - 2; I < E; ++I) {
1048 MCRegister Reg = MI.getOperand(i: I).getReg();
1049 unsigned RegNo = Ctx.getRegisterInfo()->getEncodingValue(Reg);
1050 if (RegNo != 31)
1051 res++;
1052 else
1053 res |= 0x10;
1054 }
1055 return res;
1056}
1057
1058unsigned
1059MipsMCCodeEmitter::getRegisterListOpValue16(const MCInst &MI, unsigned OpNo,
1060 SmallVectorImpl<MCFixup> &Fixups,
1061 const MCSubtargetInfo &STI) const {
1062 return (MI.getNumOperands() - 4);
1063}
1064
1065unsigned
1066MipsMCCodeEmitter::getMovePRegPairOpValue(const MCInst &MI, unsigned OpNo,
1067 SmallVectorImpl<MCFixup> &Fixups,
1068 const MCSubtargetInfo &STI) const {
1069 unsigned res = 0;
1070
1071 if (MI.getOperand(i: 0).getReg() == Mips::A1 &&
1072 MI.getOperand(i: 1).getReg() == Mips::A2)
1073 res = 0;
1074 else if (MI.getOperand(i: 0).getReg() == Mips::A1 &&
1075 MI.getOperand(i: 1).getReg() == Mips::A3)
1076 res = 1;
1077 else if (MI.getOperand(i: 0).getReg() == Mips::A2 &&
1078 MI.getOperand(i: 1).getReg() == Mips::A3)
1079 res = 2;
1080 else if (MI.getOperand(i: 0).getReg() == Mips::A0 &&
1081 MI.getOperand(i: 1).getReg() == Mips::S5)
1082 res = 3;
1083 else if (MI.getOperand(i: 0).getReg() == Mips::A0 &&
1084 MI.getOperand(i: 1).getReg() == Mips::S6)
1085 res = 4;
1086 else if (MI.getOperand(i: 0).getReg() == Mips::A0 &&
1087 MI.getOperand(i: 1).getReg() == Mips::A1)
1088 res = 5;
1089 else if (MI.getOperand(i: 0).getReg() == Mips::A0 &&
1090 MI.getOperand(i: 1).getReg() == Mips::A2)
1091 res = 6;
1092 else if (MI.getOperand(i: 0).getReg() == Mips::A0 &&
1093 MI.getOperand(i: 1).getReg() == Mips::A3)
1094 res = 7;
1095
1096 return res;
1097}
1098
1099unsigned
1100MipsMCCodeEmitter::getMovePRegSingleOpValue(const MCInst &MI, unsigned OpNo,
1101 SmallVectorImpl<MCFixup> &Fixups,
1102 const MCSubtargetInfo &STI) const {
1103 assert(((OpNo == 2) || (OpNo == 3)) &&
1104 "Unexpected OpNo for movep operand encoding!");
1105
1106 MCOperand Op = MI.getOperand(i: OpNo);
1107 assert(Op.isReg() && "Operand of movep is not a register!");
1108 switch (Op.getReg().id()) {
1109 default:
1110 llvm_unreachable("Unknown register for movep!");
1111 case Mips::ZERO: return 0;
1112 case Mips::S1: return 1;
1113 case Mips::V0: return 2;
1114 case Mips::V1: return 3;
1115 case Mips::S0: return 4;
1116 case Mips::S2: return 5;
1117 case Mips::S3: return 6;
1118 case Mips::S4: return 7;
1119 }
1120}
1121
1122unsigned
1123MipsMCCodeEmitter::getSimm23Lsl2Encoding(const MCInst &MI, unsigned OpNo,
1124 SmallVectorImpl<MCFixup> &Fixups,
1125 const MCSubtargetInfo &STI) const {
1126 const MCOperand &MO = MI.getOperand(i: OpNo);
1127 assert(MO.isImm() && "getSimm23Lsl2Encoding expects only an immediate");
1128 // The immediate is encoded as 'immediate >> 2'.
1129 unsigned Res = static_cast<unsigned>(MO.getImm());
1130 assert((Res & 3) == 0);
1131 return Res >> 2;
1132}
1133
1134#include "MipsGenMCCodeEmitter.inc"
1135