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