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