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