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:
LoongArchMCCodeEmitter(MCContext & ctx,MCInstrInfo const & MCII)37 LoongArchMCCodeEmitter(MCContext &ctx, MCInstrInfo const &MCII)
38 : Ctx(ctx), MCII(MCII) {}
39
~LoongArchMCCodeEmitter()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
getMachineOpValue(const MCInst & MI,const MCOperand & MO,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const82 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
getImmOpValueSub1(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const98 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
getImmOpValueAsr2(const MCInst & MI,unsigned OpNo,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const105 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
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 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
encodeInstruction(const MCInst & MI,raw_ostream & OS,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const276 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
createLoongArchMCCodeEmitter(const MCInstrInfo & MCII,MCContext & Ctx)294 MCCodeEmitter *llvm::createLoongArchMCCodeEmitter(const MCInstrInfo &MCII,
295 MCContext &Ctx) {
296 return new LoongArchMCCodeEmitter(Ctx, MCII);
297 }
298
299 #include "LoongArchGenMCCodeEmitter.inc"
300