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
752template <unsigned Shift>
753unsigned
754MipsMCCodeEmitter::getScaledImmOpValue(const MCInst &MI, unsigned OpNo,
755 SmallVectorImpl<MCFixup> &Fixups,
756 const MCSubtargetInfo &STI) const {
757 return getMachineOpValue(MI, MO: MI.getOperand(i: OpNo), Fixups, STI) >> Shift;
758}
759
760template <unsigned FromEnd, unsigned Shift>
761unsigned
762MipsMCCodeEmitter::getOperandFromEndValue(const MCInst &MI, unsigned OpNo,
763 SmallVectorImpl<MCFixup> &Fixups,
764 const MCSubtargetInfo &STI) const {
765 return getScaledImmOpValue<Shift>(MI, MI.getNumOperands() - FromEnd, Fixups,
766 STI);
767}
768
769// FIXME: should be called getMSBEncoding
770//
771unsigned
772MipsMCCodeEmitter::getSizeInsEncoding(const MCInst &MI, unsigned OpNo,
773 SmallVectorImpl<MCFixup> &Fixups,
774 const MCSubtargetInfo &STI) const {
775 assert(MI.getOperand(OpNo-1).isImm());
776 assert(MI.getOperand(OpNo).isImm());
777 unsigned Position = getMachineOpValue(MI, MO: MI.getOperand(i: OpNo-1), Fixups, STI);
778 unsigned Size = getMachineOpValue(MI, MO: MI.getOperand(i: OpNo), Fixups, STI);
779
780 return Position + Size - 1;
781}
782
783template <unsigned Bits, int Offset>
784unsigned
785MipsMCCodeEmitter::getUImmWithOffsetEncoding(const MCInst &MI, unsigned OpNo,
786 SmallVectorImpl<MCFixup> &Fixups,
787 const MCSubtargetInfo &STI) const {
788 assert(MI.getOperand(OpNo).isImm());
789 unsigned Value = getMachineOpValue(MI, MO: MI.getOperand(i: OpNo), Fixups, STI);
790 Value -= Offset;
791 return Value;
792}
793
794unsigned
795MipsMCCodeEmitter::getSimm19Lsl2Encoding(const MCInst &MI, unsigned OpNo,
796 SmallVectorImpl<MCFixup> &Fixups,
797 const MCSubtargetInfo &STI) const {
798 const MCOperand &MO = MI.getOperand(i: OpNo);
799 if (MO.isImm()) {
800 // The immediate is encoded as 'immediate << 2'.
801 unsigned Res = getMachineOpValue(MI, MO, Fixups, STI);
802 assert((Res & 3) == 0);
803 return Res >> 2;
804 }
805
806 assert(MO.isExpr() &&
807 "getSimm19Lsl2Encoding expects only expressions or an immediate");
808
809 const MCExpr *Expr = MO.getExpr();
810 Mips::Fixups FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_PC19_S2
811 : Mips::fixup_MIPS_PC19_S2;
812 addFixup(Fixups, Offset: 0, Value: Expr, Kind: MCFixupKind(FixupKind));
813 return 0;
814}
815
816unsigned
817MipsMCCodeEmitter::getSimm18Lsl3Encoding(const MCInst &MI, unsigned OpNo,
818 SmallVectorImpl<MCFixup> &Fixups,
819 const MCSubtargetInfo &STI) const {
820 const MCOperand &MO = MI.getOperand(i: OpNo);
821 if (MO.isImm()) {
822 // The immediate is encoded as 'immediate << 3'.
823 unsigned Res = getMachineOpValue(MI, MO: MI.getOperand(i: OpNo), Fixups, STI);
824 assert((Res & 7) == 0);
825 return Res >> 3;
826 }
827
828 assert(MO.isExpr() &&
829 "getSimm18Lsl2Encoding expects only expressions or an immediate");
830
831 const MCExpr *Expr = MO.getExpr();
832 Mips::Fixups FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_PC18_S3
833 : Mips::fixup_MIPS_PC18_S3;
834 addFixup(Fixups, Offset: 0, Value: Expr, Kind: MCFixupKind(FixupKind));
835 return 0;
836}
837
838unsigned
839MipsMCCodeEmitter::getUImm3Mod8Encoding(const MCInst &MI, unsigned OpNo,
840 SmallVectorImpl<MCFixup> &Fixups,
841 const MCSubtargetInfo &STI) const {
842 assert(MI.getOperand(OpNo).isImm());
843 const MCOperand &MO = MI.getOperand(i: OpNo);
844 return MO.getImm() % 8;
845}
846
847unsigned
848MipsMCCodeEmitter::getUImm4AndValue(const MCInst &MI, unsigned OpNo,
849 SmallVectorImpl<MCFixup> &Fixups,
850 const MCSubtargetInfo &STI) const {
851 assert(MI.getOperand(OpNo).isImm());
852 const MCOperand &MO = MI.getOperand(i: OpNo);
853 unsigned Value = MO.getImm();
854 switch (Value) {
855 case 128: return 0x0;
856 case 1: return 0x1;
857 case 2: return 0x2;
858 case 3: return 0x3;
859 case 4: return 0x4;
860 case 7: return 0x5;
861 case 8: return 0x6;
862 case 15: return 0x7;
863 case 16: return 0x8;
864 case 31: return 0x9;
865 case 32: return 0xa;
866 case 63: return 0xb;
867 case 64: return 0xc;
868 case 255: return 0xd;
869 case 32768: return 0xe;
870 case 65535: return 0xf;
871 }
872 llvm_unreachable("Unexpected value");
873}
874
875unsigned
876MipsMCCodeEmitter::getRegisterListOpValue(const MCInst &MI, unsigned OpNo,
877 SmallVectorImpl<MCFixup> &Fixups,
878 const MCSubtargetInfo &STI) const {
879 unsigned res = 0;
880
881 // Register list operand is always first operand of instruction and it is
882 // placed before memory operand (register + imm).
883
884 for (unsigned I = OpNo, E = MI.getNumOperands() - 2; I < E; ++I) {
885 MCRegister Reg = MI.getOperand(i: I).getReg();
886 unsigned RegNo = Ctx.getRegisterInfo()->getEncodingValue(Reg);
887 if (RegNo != 31)
888 res++;
889 else
890 res |= 0x10;
891 }
892 return res;
893}
894
895unsigned
896MipsMCCodeEmitter::getRegisterListOpValue16(const MCInst &MI, unsigned OpNo,
897 SmallVectorImpl<MCFixup> &Fixups,
898 const MCSubtargetInfo &STI) const {
899 return (MI.getNumOperands() - 4);
900}
901
902unsigned
903MipsMCCodeEmitter::getMovePRegPairOpValue(const MCInst &MI, unsigned OpNo,
904 SmallVectorImpl<MCFixup> &Fixups,
905 const MCSubtargetInfo &STI) const {
906 unsigned res = 0;
907
908 if (MI.getOperand(i: 0).getReg() == Mips::R5 &&
909 MI.getOperand(i: 1).getReg() == Mips::R6)
910 res = 0;
911 else if (MI.getOperand(i: 0).getReg() == Mips::R5 &&
912 MI.getOperand(i: 1).getReg() == Mips::R7)
913 res = 1;
914 else if (MI.getOperand(i: 0).getReg() == Mips::R6 &&
915 MI.getOperand(i: 1).getReg() == Mips::R7)
916 res = 2;
917 else if (MI.getOperand(i: 0).getReg() == Mips::R4 &&
918 MI.getOperand(i: 1).getReg() == Mips::R21)
919 res = 3;
920 else if (MI.getOperand(i: 0).getReg() == Mips::R4 &&
921 MI.getOperand(i: 1).getReg() == Mips::R22)
922 res = 4;
923 else if (MI.getOperand(i: 0).getReg() == Mips::R4 &&
924 MI.getOperand(i: 1).getReg() == Mips::R5)
925 res = 5;
926 else if (MI.getOperand(i: 0).getReg() == Mips::R4 &&
927 MI.getOperand(i: 1).getReg() == Mips::R6)
928 res = 6;
929 else if (MI.getOperand(i: 0).getReg() == Mips::R4 &&
930 MI.getOperand(i: 1).getReg() == Mips::R7)
931 res = 7;
932
933 return res;
934}
935
936unsigned
937MipsMCCodeEmitter::getMovePRegSingleOpValue(const MCInst &MI, unsigned OpNo,
938 SmallVectorImpl<MCFixup> &Fixups,
939 const MCSubtargetInfo &STI) const {
940 assert(((OpNo == 2) || (OpNo == 3)) &&
941 "Unexpected OpNo for movep operand encoding!");
942
943 MCOperand Op = MI.getOperand(i: OpNo);
944 assert(Op.isReg() && "Operand of movep is not a register!");
945 switch (Op.getReg().id()) {
946 default:
947 llvm_unreachable("Unknown register for movep!");
948 case Mips::R0:
949 return 0;
950 case Mips::R17:
951 return 1;
952 case Mips::R2:
953 return 2;
954 case Mips::R3:
955 return 3;
956 case Mips::R16:
957 return 4;
958 case Mips::R18:
959 return 5;
960 case Mips::R19:
961 return 6;
962 case Mips::R20:
963 return 7;
964 }
965}
966
967unsigned
968MipsMCCodeEmitter::getSimm23Lsl2Encoding(const MCInst &MI, unsigned OpNo,
969 SmallVectorImpl<MCFixup> &Fixups,
970 const MCSubtargetInfo &STI) const {
971 const MCOperand &MO = MI.getOperand(i: OpNo);
972 assert(MO.isImm() && "getSimm23Lsl2Encoding expects only an immediate");
973 // The immediate is encoded as 'immediate >> 2'.
974 unsigned Res = static_cast<unsigned>(MO.getImm());
975 assert((Res & 3) == 0);
976 return Res >> 2;
977}
978
979#include "MipsGenMCCodeEmitter.inc"
980