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:
LoongArchMCCodeEmitter(MCContext & ctx,MCInstrInfo const & MCII)38 LoongArchMCCodeEmitter(MCContext &ctx, MCInstrInfo const &MCII)
39 : Ctx(ctx), MCII(MCII) {}
40
~LoongArchMCCodeEmitter()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>
getImmOpValueAsr(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const78 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
getMachineOpValue(const MCInst & MI,const MCOperand & MO,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const97 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
getImmOpValueSub1(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const113 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
getExprOpValue(const MCInst & MI,const MCOperand & MO,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const120 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>
expandToVectorLDI(const MCInst & MI,SmallVectorImpl<char> & CB,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const293 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
encodeInstruction(const MCInst & MI,SmallVectorImpl<char> & CB,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const319 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
createLoongArchMCCodeEmitter(const MCInstrInfo & MCII,MCContext & Ctx)352 MCCodeEmitter *llvm::createLoongArchMCCodeEmitter(const MCInstrInfo &MCII,
353 MCContext &Ctx) {
354 return new LoongArchMCCodeEmitter(Ctx, MCII);
355 }
356
357 #include "LoongArchGenMCCodeEmitter.inc"
358