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