xref: /freebsd/contrib/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCCodeEmitter.cpp (revision 5b56413d04e608379c9a306373554a8e4d321bc0)
1 //=- LoongArchMCCodeEmitter.cpp - Convert LoongArch 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 LoongArchMCCodeEmitter class.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "LoongArchFixupKinds.h"
14 #include "MCTargetDesc/LoongArchBaseInfo.h"
15 #include "MCTargetDesc/LoongArchMCExpr.h"
16 #include "MCTargetDesc/LoongArchMCTargetDesc.h"
17 #include "llvm/MC/MCCodeEmitter.h"
18 #include "llvm/MC/MCContext.h"
19 #include "llvm/MC/MCInstBuilder.h"
20 #include "llvm/MC/MCInstrInfo.h"
21 #include "llvm/MC/MCRegisterInfo.h"
22 #include "llvm/MC/MCSubtargetInfo.h"
23 #include "llvm/Support/Casting.h"
24 #include "llvm/Support/EndianStream.h"
25 
26 using namespace llvm;
27 
28 #define DEBUG_TYPE "mccodeemitter"
29 
30 namespace {
31 class LoongArchMCCodeEmitter : public MCCodeEmitter {
32   LoongArchMCCodeEmitter(const LoongArchMCCodeEmitter &) = delete;
33   void operator=(const LoongArchMCCodeEmitter &) = delete;
34   MCContext &Ctx;
35   MCInstrInfo const &MCII;
36 
37 public:
38   LoongArchMCCodeEmitter(MCContext &ctx, MCInstrInfo const &MCII)
39       : Ctx(ctx), MCII(MCII) {}
40 
41   ~LoongArchMCCodeEmitter() override {}
42 
43   void encodeInstruction(const MCInst &MI, SmallVectorImpl<char> &CB,
44                          SmallVectorImpl<MCFixup> &Fixups,
45                          const MCSubtargetInfo &STI) const override;
46 
47   template <unsigned Opc>
48   void expandToVectorLDI(const MCInst &MI, SmallVectorImpl<char> &CB,
49                          SmallVectorImpl<MCFixup> &Fixups,
50                          const MCSubtargetInfo &STI) const;
51 
52   /// TableGen'erated function for getting the binary encoding for an
53   /// instruction.
54   uint64_t getBinaryCodeForInstr(const MCInst &MI,
55                                  SmallVectorImpl<MCFixup> &Fixups,
56                                  const MCSubtargetInfo &STI) const;
57 
58   /// Return binary encoding of operand. If the machine operand requires
59   /// relocation, record the relocation and return zero.
60   unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO,
61                              SmallVectorImpl<MCFixup> &Fixups,
62                              const MCSubtargetInfo &STI) const;
63 
64   /// Return binary encoding of an immediate operand specified by OpNo.
65   /// The value returned is the value of the immediate minus 1.
66   /// Note that this function is dedicated to specific immediate types,
67   /// e.g. uimm2_plus1.
68   unsigned getImmOpValueSub1(const MCInst &MI, unsigned OpNo,
69                              SmallVectorImpl<MCFixup> &Fixups,
70                              const MCSubtargetInfo &STI) const;
71 
72   /// Return binary encoding of an immediate operand specified by OpNo.
73   /// The value returned is the value of the immediate shifted right
74   //  arithmetically by N.
75   /// Note that this function is dedicated to specific immediate types,
76   /// e.g. simm14_lsl2, simm16_lsl2, simm21_lsl2 and simm26_lsl2.
77   template <unsigned N>
78   unsigned getImmOpValueAsr(const MCInst &MI, unsigned OpNo,
79                             SmallVectorImpl<MCFixup> &Fixups,
80                             const MCSubtargetInfo &STI) const {
81     const MCOperand &MO = MI.getOperand(OpNo);
82     if (MO.isImm()) {
83       unsigned Res = MI.getOperand(OpNo).getImm();
84       assert((Res & ((1U << N) - 1U)) == 0 && "lowest N bits are non-zero");
85       return Res >> N;
86     }
87     return getExprOpValue(MI, MO, Fixups, STI);
88   }
89 
90   unsigned getExprOpValue(const MCInst &MI, const MCOperand &MO,
91                           SmallVectorImpl<MCFixup> &Fixups,
92                           const MCSubtargetInfo &STI) const;
93 };
94 } // end namespace
95 
96 unsigned
97 LoongArchMCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO,
98                                           SmallVectorImpl<MCFixup> &Fixups,
99                                           const MCSubtargetInfo &STI) const {
100 
101   if (MO.isReg())
102     return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());
103 
104   if (MO.isImm())
105     return static_cast<unsigned>(MO.getImm());
106 
107   // MO must be an Expr.
108   assert(MO.isExpr());
109   return getExprOpValue(MI, MO, Fixups, STI);
110 }
111 
112 unsigned
113 LoongArchMCCodeEmitter::getImmOpValueSub1(const MCInst &MI, unsigned OpNo,
114                                           SmallVectorImpl<MCFixup> &Fixups,
115                                           const MCSubtargetInfo &STI) const {
116   return MI.getOperand(OpNo).getImm() - 1;
117 }
118 
119 unsigned
120 LoongArchMCCodeEmitter::getExprOpValue(const MCInst &MI, const MCOperand &MO,
121                                        SmallVectorImpl<MCFixup> &Fixups,
122                                        const MCSubtargetInfo &STI) const {
123   assert(MO.isExpr() && "getExprOpValue expects only expressions");
124   bool RelaxCandidate = false;
125   bool EnableRelax = STI.hasFeature(LoongArch::FeatureRelax);
126   const MCExpr *Expr = MO.getExpr();
127   MCExpr::ExprKind Kind = Expr->getKind();
128   LoongArch::Fixups FixupKind = LoongArch::fixup_loongarch_invalid;
129   if (Kind == MCExpr::Target) {
130     const LoongArchMCExpr *LAExpr = cast<LoongArchMCExpr>(Expr);
131 
132     RelaxCandidate = LAExpr->getRelaxHint();
133     switch (LAExpr->getKind()) {
134     case LoongArchMCExpr::VK_LoongArch_None:
135     case LoongArchMCExpr::VK_LoongArch_Invalid:
136       llvm_unreachable("Unhandled fixup kind!");
137     case LoongArchMCExpr::VK_LoongArch_B16:
138       FixupKind = LoongArch::fixup_loongarch_b16;
139       break;
140     case LoongArchMCExpr::VK_LoongArch_B21:
141       FixupKind = LoongArch::fixup_loongarch_b21;
142       break;
143     case LoongArchMCExpr::VK_LoongArch_B26:
144     case LoongArchMCExpr::VK_LoongArch_CALL:
145     case LoongArchMCExpr::VK_LoongArch_CALL_PLT:
146       FixupKind = LoongArch::fixup_loongarch_b26;
147       break;
148     case LoongArchMCExpr::VK_LoongArch_ABS_HI20:
149       FixupKind = LoongArch::fixup_loongarch_abs_hi20;
150       break;
151     case LoongArchMCExpr::VK_LoongArch_ABS_LO12:
152       FixupKind = LoongArch::fixup_loongarch_abs_lo12;
153       break;
154     case LoongArchMCExpr::VK_LoongArch_ABS64_LO20:
155       FixupKind = LoongArch::fixup_loongarch_abs64_lo20;
156       break;
157     case LoongArchMCExpr::VK_LoongArch_ABS64_HI12:
158       FixupKind = LoongArch::fixup_loongarch_abs64_hi12;
159       break;
160     case LoongArchMCExpr::VK_LoongArch_PCALA_HI20:
161       FixupKind = LoongArch::fixup_loongarch_pcala_hi20;
162       break;
163     case LoongArchMCExpr::VK_LoongArch_PCALA_LO12:
164       FixupKind = LoongArch::fixup_loongarch_pcala_lo12;
165       break;
166     case LoongArchMCExpr::VK_LoongArch_PCALA64_LO20:
167       FixupKind = LoongArch::fixup_loongarch_pcala64_lo20;
168       break;
169     case LoongArchMCExpr::VK_LoongArch_PCALA64_HI12:
170       FixupKind = LoongArch::fixup_loongarch_pcala64_hi12;
171       break;
172     case LoongArchMCExpr::VK_LoongArch_GOT_PC_HI20:
173       FixupKind = LoongArch::fixup_loongarch_got_pc_hi20;
174       break;
175     case LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12:
176       FixupKind = LoongArch::fixup_loongarch_got_pc_lo12;
177       break;
178     case LoongArchMCExpr::VK_LoongArch_GOT64_PC_LO20:
179       FixupKind = LoongArch::fixup_loongarch_got64_pc_lo20;
180       break;
181     case LoongArchMCExpr::VK_LoongArch_GOT64_PC_HI12:
182       FixupKind = LoongArch::fixup_loongarch_got64_pc_hi12;
183       break;
184     case LoongArchMCExpr::VK_LoongArch_GOT_HI20:
185       FixupKind = LoongArch::fixup_loongarch_got_hi20;
186       break;
187     case LoongArchMCExpr::VK_LoongArch_GOT_LO12:
188       FixupKind = LoongArch::fixup_loongarch_got_lo12;
189       break;
190     case LoongArchMCExpr::VK_LoongArch_GOT64_LO20:
191       FixupKind = LoongArch::fixup_loongarch_got64_lo20;
192       break;
193     case LoongArchMCExpr::VK_LoongArch_GOT64_HI12:
194       FixupKind = LoongArch::fixup_loongarch_got64_hi12;
195       break;
196     case LoongArchMCExpr::VK_LoongArch_TLS_LE_HI20:
197       FixupKind = LoongArch::fixup_loongarch_tls_le_hi20;
198       break;
199     case LoongArchMCExpr::VK_LoongArch_TLS_LE_LO12:
200       FixupKind = LoongArch::fixup_loongarch_tls_le_lo12;
201       break;
202     case LoongArchMCExpr::VK_LoongArch_TLS_LE64_LO20:
203       FixupKind = LoongArch::fixup_loongarch_tls_le64_lo20;
204       break;
205     case LoongArchMCExpr::VK_LoongArch_TLS_LE64_HI12:
206       FixupKind = LoongArch::fixup_loongarch_tls_le64_hi12;
207       break;
208     case LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_HI20:
209       FixupKind = LoongArch::fixup_loongarch_tls_ie_pc_hi20;
210       break;
211     case LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_LO12:
212       FixupKind = LoongArch::fixup_loongarch_tls_ie_pc_lo12;
213       break;
214     case LoongArchMCExpr::VK_LoongArch_TLS_IE64_PC_LO20:
215       FixupKind = LoongArch::fixup_loongarch_tls_ie64_pc_lo20;
216       break;
217     case LoongArchMCExpr::VK_LoongArch_TLS_IE64_PC_HI12:
218       FixupKind = LoongArch::fixup_loongarch_tls_ie64_pc_hi12;
219       break;
220     case LoongArchMCExpr::VK_LoongArch_TLS_IE_HI20:
221       FixupKind = LoongArch::fixup_loongarch_tls_ie_hi20;
222       break;
223     case LoongArchMCExpr::VK_LoongArch_TLS_IE_LO12:
224       FixupKind = LoongArch::fixup_loongarch_tls_ie_lo12;
225       break;
226     case LoongArchMCExpr::VK_LoongArch_TLS_IE64_LO20:
227       FixupKind = LoongArch::fixup_loongarch_tls_ie64_lo20;
228       break;
229     case LoongArchMCExpr::VK_LoongArch_TLS_IE64_HI12:
230       FixupKind = LoongArch::fixup_loongarch_tls_ie64_hi12;
231       break;
232     case LoongArchMCExpr::VK_LoongArch_TLS_LD_PC_HI20:
233       FixupKind = LoongArch::fixup_loongarch_tls_ld_pc_hi20;
234       break;
235     case LoongArchMCExpr::VK_LoongArch_TLS_LD_HI20:
236       FixupKind = LoongArch::fixup_loongarch_tls_ld_hi20;
237       break;
238     case LoongArchMCExpr::VK_LoongArch_TLS_GD_PC_HI20:
239       FixupKind = LoongArch::fixup_loongarch_tls_gd_pc_hi20;
240       break;
241     case LoongArchMCExpr::VK_LoongArch_TLS_GD_HI20:
242       FixupKind = LoongArch::fixup_loongarch_tls_gd_hi20;
243       break;
244     case LoongArchMCExpr::VK_LoongArch_CALL36:
245       FixupKind = LoongArch::fixup_loongarch_call36;
246       break;
247     }
248   } else if (Kind == MCExpr::SymbolRef &&
249              cast<MCSymbolRefExpr>(Expr)->getKind() ==
250                  MCSymbolRefExpr::VK_None) {
251     switch (MI.getOpcode()) {
252     default:
253       break;
254     case LoongArch::BEQ:
255     case LoongArch::BNE:
256     case LoongArch::BLT:
257     case LoongArch::BGE:
258     case LoongArch::BLTU:
259     case LoongArch::BGEU:
260       FixupKind = LoongArch::fixup_loongarch_b16;
261       break;
262     case LoongArch::BEQZ:
263     case LoongArch::BNEZ:
264     case LoongArch::BCEQZ:
265     case LoongArch::BCNEZ:
266       FixupKind = LoongArch::fixup_loongarch_b21;
267       break;
268     case LoongArch::B:
269     case LoongArch::BL:
270       FixupKind = LoongArch::fixup_loongarch_b26;
271       break;
272     }
273   }
274 
275   assert(FixupKind != LoongArch::fixup_loongarch_invalid &&
276          "Unhandled expression!");
277 
278   Fixups.push_back(
279       MCFixup::create(0, Expr, MCFixupKind(FixupKind), MI.getLoc()));
280 
281   // Emit an R_LARCH_RELAX if linker relaxation is enabled and LAExpr has relax
282   // hint.
283   if (EnableRelax && RelaxCandidate) {
284     const MCConstantExpr *Dummy = MCConstantExpr::create(0, Ctx);
285     Fixups.push_back(MCFixup::create(
286         0, Dummy, MCFixupKind(LoongArch::fixup_loongarch_relax), MI.getLoc()));
287   }
288 
289   return 0;
290 }
291 
292 template <unsigned Opc>
293 void LoongArchMCCodeEmitter::expandToVectorLDI(
294     const MCInst &MI, SmallVectorImpl<char> &CB,
295     SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const {
296   int64_t Imm = MI.getOperand(1).getImm() & 0x3FF;
297   switch (MI.getOpcode()) {
298   case LoongArch::PseudoVREPLI_B:
299   case LoongArch::PseudoXVREPLI_B:
300     break;
301   case LoongArch::PseudoVREPLI_H:
302   case LoongArch::PseudoXVREPLI_H:
303     Imm |= 0x400;
304     break;
305   case LoongArch::PseudoVREPLI_W:
306   case LoongArch::PseudoXVREPLI_W:
307     Imm |= 0x800;
308     break;
309   case LoongArch::PseudoVREPLI_D:
310   case LoongArch::PseudoXVREPLI_D:
311     Imm |= 0xC00;
312     break;
313   }
314   MCInst TmpInst = MCInstBuilder(Opc).addOperand(MI.getOperand(0)).addImm(Imm);
315   uint32_t Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);
316   support::endian::write(CB, Binary, llvm::endianness::little);
317 }
318 
319 void LoongArchMCCodeEmitter::encodeInstruction(
320     const MCInst &MI, SmallVectorImpl<char> &CB,
321     SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const {
322   const MCInstrDesc &Desc = MCII.get(MI.getOpcode());
323   // Get byte count of instruction.
324   unsigned Size = Desc.getSize();
325 
326   switch (MI.getOpcode()) {
327   default:
328     break;
329   case LoongArch::PseudoVREPLI_B:
330   case LoongArch::PseudoVREPLI_H:
331   case LoongArch::PseudoVREPLI_W:
332   case LoongArch::PseudoVREPLI_D:
333     return expandToVectorLDI<LoongArch::VLDI>(MI, CB, Fixups, STI);
334   case LoongArch::PseudoXVREPLI_B:
335   case LoongArch::PseudoXVREPLI_H:
336   case LoongArch::PseudoXVREPLI_W:
337   case LoongArch::PseudoXVREPLI_D:
338     return expandToVectorLDI<LoongArch::XVLDI>(MI, CB, Fixups, STI);
339   }
340 
341   switch (Size) {
342   default:
343     llvm_unreachable("Unhandled encodeInstruction length!");
344   case 4: {
345     uint32_t Bits = getBinaryCodeForInstr(MI, Fixups, STI);
346     support::endian::write(CB, Bits, llvm::endianness::little);
347     break;
348   }
349   }
350 }
351 
352 MCCodeEmitter *llvm::createLoongArchMCCodeEmitter(const MCInstrInfo &MCII,
353                                                   MCContext &Ctx) {
354   return new LoongArchMCCodeEmitter(Ctx, MCII);
355 }
356 
357 #include "LoongArchGenMCCodeEmitter.inc"
358