LLVM 20.0.0git
XtensaMCCodeEmitter.cpp
Go to the documentation of this file.
1//===-- XtensaMCCodeEmitter.cpp - Convert Xtensa Code to Machine Code -----===//
2//
3// The LLVM Compiler Infrastructure
4//
5// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
6// See https://llvm.org/LICENSE.txt for license information.
7// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
8//
9//===----------------------------------------------------------------------===//
10//
11// This file implements the XtensaMCCodeEmitter class.
12//
13//===----------------------------------------------------------------------===//
14
19#include "llvm/MC/MCContext.h"
20#include "llvm/MC/MCExpr.h"
21#include "llvm/MC/MCInst.h"
22#include "llvm/MC/MCInstrInfo.h"
24
25#define GET_INSTRMAP_INFO
26#include "XtensaGenInstrInfo.inc"
27#undef GET_INSTRMAP_INFO
28
29using namespace llvm;
30
31#define DEBUG_TYPE "mccodeemitter"
32
33namespace {
34class XtensaMCCodeEmitter : public MCCodeEmitter {
35 const MCInstrInfo &MCII;
36 MCContext &Ctx;
37 bool IsLittleEndian;
38
39public:
40 XtensaMCCodeEmitter(const MCInstrInfo &mcii, MCContext &ctx, bool isLE)
41 : MCII(mcii), Ctx(ctx), IsLittleEndian(isLE) {}
42
43 ~XtensaMCCodeEmitter() {}
44
45 // OVerride MCCodeEmitter.
48 const MCSubtargetInfo &STI) const override;
49
50private:
51 // Automatically generated by TableGen.
52 uint64_t getBinaryCodeForInstr(const MCInst &MI,
54 const MCSubtargetInfo &STI) const;
55
56 // Called by the TableGen code to get the binary encoding of operand
57 // MO in MI. Fixups is the list of fixups against MI.
58 uint32_t getMachineOpValue(const MCInst &MI, const MCOperand &MO,
60 const MCSubtargetInfo &STI) const;
61
62 uint32_t getJumpTargetEncoding(const MCInst &MI, unsigned int OpNum,
64 const MCSubtargetInfo &STI) const;
65
66 uint32_t getBranchTargetEncoding(const MCInst &MI, unsigned int OpNum,
68 const MCSubtargetInfo &STI) const;
69
70 uint32_t getCallEncoding(const MCInst &MI, unsigned int OpNum,
72 const MCSubtargetInfo &STI) const;
73
74 uint32_t getL32RTargetEncoding(const MCInst &MI, unsigned OpNum,
76 const MCSubtargetInfo &STI) const;
77
78 uint32_t getMemRegEncoding(const MCInst &MI, unsigned OpNo,
80 const MCSubtargetInfo &STI) const;
81
82 uint32_t getImm8OpValue(const MCInst &MI, unsigned OpNo,
84 const MCSubtargetInfo &STI) const;
85
86 uint32_t getImm8_sh8OpValue(const MCInst &MI, unsigned OpNo,
88 const MCSubtargetInfo &STI) const;
89
90 uint32_t getImm12OpValue(const MCInst &MI, unsigned OpNo,
92 const MCSubtargetInfo &STI) const;
93
94 uint32_t getUimm4OpValue(const MCInst &MI, unsigned OpNo,
96 const MCSubtargetInfo &STI) const;
97
98 uint32_t getUimm5OpValue(const MCInst &MI, unsigned OpNo,
100 const MCSubtargetInfo &STI) const;
101
102 uint32_t getImm1_16OpValue(const MCInst &MI, unsigned OpNo,
104 const MCSubtargetInfo &STI) const;
105
106 uint32_t getImm1n_15OpValue(const MCInst &MI, unsigned OpNo,
108 const MCSubtargetInfo &STI) const;
109
110 uint32_t getImm32n_95OpValue(const MCInst &MI, unsigned OpNo,
112 const MCSubtargetInfo &STI) const;
113
114 uint32_t getShimm1_31OpValue(const MCInst &MI, unsigned OpNo,
116 const MCSubtargetInfo &STI) const;
117
118 uint32_t getB4constOpValue(const MCInst &MI, unsigned OpNo,
120 const MCSubtargetInfo &STI) const;
121
122 uint32_t getB4constuOpValue(const MCInst &MI, unsigned OpNo,
124 const MCSubtargetInfo &STI) const;
125};
126} // namespace
127
129 MCContext &Ctx) {
130 return new XtensaMCCodeEmitter(MCII, Ctx, true);
131}
132
133void XtensaMCCodeEmitter::encodeInstruction(const MCInst &MI,
136 const MCSubtargetInfo &STI) const {
137 uint64_t Bits = getBinaryCodeForInstr(MI, Fixups, STI);
138 unsigned Size = MCII.get(MI.getOpcode()).getSize();
139
140 if (IsLittleEndian) {
141 // Little-endian insertion of Size bytes.
142 unsigned ShiftValue = 0;
143 for (unsigned I = 0; I != Size; ++I) {
144 CB.push_back(char(Bits >> ShiftValue));
145 ShiftValue += 8;
146 }
147 } else {
148 // TODO Big-endian insertion of Size bytes.
149 report_fatal_error("Big-endian mode currently is not supported!");
150 }
151}
152
154XtensaMCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO,
156 const MCSubtargetInfo &STI) const {
157 if (MO.isReg())
158 return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());
159 if (MO.isImm()) {
160 uint32_t Res = static_cast<uint32_t>(MO.getImm());
161 return Res;
162 }
163
164 report_fatal_error("Unhandled expression!");
165 return 0;
166}
167
169XtensaMCCodeEmitter::getJumpTargetEncoding(const MCInst &MI, unsigned int OpNum,
171 const MCSubtargetInfo &STI) const {
172 const MCOperand &MO = MI.getOperand(OpNum);
173
174 if (MO.isImm())
175 return MO.getImm();
176
177 const MCExpr *Expr = MO.getExpr();
178 Fixups.push_back(MCFixup::create(
179 0, Expr, MCFixupKind(Xtensa::fixup_xtensa_jump_18), MI.getLoc()));
180 return 0;
181}
182
183uint32_t XtensaMCCodeEmitter::getBranchTargetEncoding(
184 const MCInst &MI, unsigned int OpNum, SmallVectorImpl<MCFixup> &Fixups,
185 const MCSubtargetInfo &STI) const {
186 const MCOperand &MO = MI.getOperand(OpNum);
187 if (MO.isImm())
188 return static_cast<uint32_t>(MO.getImm());
189
190 const MCExpr *Expr = MO.getExpr();
191 switch (MI.getOpcode()) {
192 case Xtensa::BEQZ:
193 case Xtensa::BGEZ:
194 case Xtensa::BLTZ:
195 case Xtensa::BNEZ:
196 Fixups.push_back(MCFixup::create(
197 0, Expr, MCFixupKind(Xtensa::fixup_xtensa_branch_12), MI.getLoc()));
198 return 0;
199 case Xtensa::BEQZ_N:
200 case Xtensa::BNEZ_N:
201 Fixups.push_back(MCFixup::create(
202 0, Expr, MCFixupKind(Xtensa::fixup_xtensa_branch_6), MI.getLoc()));
203 return 0;
204 default:
205 Fixups.push_back(MCFixup::create(
206 0, Expr, MCFixupKind(Xtensa::fixup_xtensa_branch_8), MI.getLoc()));
207 return 0;
208 }
209}
210
212XtensaMCCodeEmitter::getCallEncoding(const MCInst &MI, unsigned int OpNum,
214 const MCSubtargetInfo &STI) const {
215 const MCOperand &MO = MI.getOperand(OpNum);
216 if (MO.isImm()) {
217 int32_t Res = MO.getImm();
218 if (Res & 0x3) {
219 llvm_unreachable("Unexpected operand value!");
220 }
221 Res >>= 2;
222 return Res;
223 }
224
225 assert((MO.isExpr()) && "Unexpected operand value!");
226 const MCExpr *Expr = MO.getExpr();
227 Fixups.push_back(MCFixup::create(
228 0, Expr, MCFixupKind(Xtensa::fixup_xtensa_call_18), MI.getLoc()));
229 return 0;
230}
231
233XtensaMCCodeEmitter::getL32RTargetEncoding(const MCInst &MI, unsigned OpNum,
235 const MCSubtargetInfo &STI) const {
236 const MCOperand &MO = MI.getOperand(OpNum);
237 if (MO.isImm()) {
238 int32_t Res = MO.getImm();
239 // We don't check first 2 bits, because in these bits we could store first 2
240 // bits of instruction address
241 Res >>= 2;
242 return Res;
243 }
244
245 assert((MO.isExpr()) && "Unexpected operand value!");
246
247 Fixups.push_back(MCFixup::create(
249 return 0;
250}
251
253XtensaMCCodeEmitter::getMemRegEncoding(const MCInst &MI, unsigned OpNo,
255 const MCSubtargetInfo &STI) const {
256 assert(MI.getOperand(OpNo + 1).isImm());
257
258 uint32_t Res = static_cast<uint32_t>(MI.getOperand(OpNo + 1).getImm());
259
260 switch (MI.getOpcode()) {
261 case Xtensa::S16I:
262 case Xtensa::L16SI:
263 case Xtensa::L16UI:
264 if (Res & 0x1) {
265 report_fatal_error("Unexpected operand value!");
266 }
267 Res >>= 1;
268 break;
269 case Xtensa::S32I:
270 case Xtensa::L32I:
271 case Xtensa::S32I_N:
272 case Xtensa::L32I_N:
273 if (Res & 0x3) {
274 report_fatal_error("Unexpected operand value!");
275 }
276 Res >>= 2;
277 break;
278 }
279
280 switch (MI.getOpcode()) {
281 case Xtensa::S32I_N:
282 case Xtensa::L32I_N:
283 assert((isUInt<4>(Res)) && "Unexpected operand value!");
284 break;
285 default:
286 assert((isUInt<8>(Res)) && "Unexpected operand value!");
287 break;
288 }
289
290 uint32_t OffBits = Res << 4;
291 uint32_t RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI);
292
293 return ((OffBits & 0xFF0) | RegBits);
294}
295
296uint32_t XtensaMCCodeEmitter::getImm8OpValue(const MCInst &MI, unsigned OpNo,
298 const MCSubtargetInfo &STI) const {
299 const MCOperand &MO = MI.getOperand(OpNo);
300 int32_t Res = MO.getImm();
301
302 assert(((Res >= -128) && (Res <= 127)) && "Unexpected operand value!");
303
304 return (Res & 0xff);
305}
306
308XtensaMCCodeEmitter::getImm8_sh8OpValue(const MCInst &MI, unsigned OpNo,
310 const MCSubtargetInfo &STI) const {
311 const MCOperand &MO = MI.getOperand(OpNo);
312 int32_t Res = MO.getImm();
313
314 assert(((Res >= -32768) && (Res <= 32512) && ((Res & 0xff) == 0)) &&
315 "Unexpected operand value!");
316
317 return (Res & 0xffff);
318}
319
321XtensaMCCodeEmitter::getImm12OpValue(const MCInst &MI, unsigned OpNo,
323 const MCSubtargetInfo &STI) const {
324 const MCOperand &MO = MI.getOperand(OpNo);
325 int32_t Res = MO.getImm();
326
327 assert(((Res >= -2048) && (Res <= 2047)) && "Unexpected operand value!");
328
329 return (Res & 0xfff);
330}
331
333XtensaMCCodeEmitter::getUimm4OpValue(const MCInst &MI, unsigned OpNo,
335 const MCSubtargetInfo &STI) const {
336 const MCOperand &MO = MI.getOperand(OpNo);
337 uint32_t Res = static_cast<uint32_t>(MO.getImm());
338
339 assert((Res <= 15) && "Unexpected operand value!");
340
341 return Res & 0xf;
342}
343
345XtensaMCCodeEmitter::getUimm5OpValue(const MCInst &MI, unsigned OpNo,
347 const MCSubtargetInfo &STI) const {
348 const MCOperand &MO = MI.getOperand(OpNo);
349 uint32_t Res = static_cast<uint32_t>(MO.getImm());
350
351 assert((Res <= 31) && "Unexpected operand value!");
352
353 return (Res & 0x1f);
354}
355
357XtensaMCCodeEmitter::getShimm1_31OpValue(const MCInst &MI, unsigned OpNo,
359 const MCSubtargetInfo &STI) const {
360 const MCOperand &MO = MI.getOperand(OpNo);
361 uint32_t Res = static_cast<uint32_t>(MO.getImm());
362
363 assert(((Res >= 1) && (Res <= 31)) && "Unexpected operand value!");
364
365 return ((32 - Res) & 0x1f);
366}
367
369XtensaMCCodeEmitter::getImm1_16OpValue(const MCInst &MI, unsigned OpNo,
371 const MCSubtargetInfo &STI) const {
372 const MCOperand &MO = MI.getOperand(OpNo);
373 uint32_t Res = static_cast<uint32_t>(MO.getImm());
374
375 assert(((Res >= 1) && (Res <= 16)) && "Unexpected operand value!");
376
377 return (Res - 1);
378}
379
381XtensaMCCodeEmitter::getImm1n_15OpValue(const MCInst &MI, unsigned OpNo,
383 const MCSubtargetInfo &STI) const {
384 const MCOperand &MO = MI.getOperand(OpNo);
385 int32_t Res = static_cast<int32_t>(MO.getImm());
386
387 assert(((Res >= -1) && (Res <= 15) && (Res != 0)) &&
388 "Unexpected operand value!");
389
390 if (Res < 0)
391 Res = 0;
392
393 return Res;
394}
395
397XtensaMCCodeEmitter::getImm32n_95OpValue(const MCInst &MI, unsigned OpNo,
399 const MCSubtargetInfo &STI) const {
400 const MCOperand &MO = MI.getOperand(OpNo);
401 int32_t Res = static_cast<int32_t>(MO.getImm());
402
403 assert(((Res >= -32) && (Res <= 95)) && "Unexpected operand value!");
404
405 return Res;
406}
407
409XtensaMCCodeEmitter::getB4constOpValue(const MCInst &MI, unsigned OpNo,
411 const MCSubtargetInfo &STI) const {
412 const MCOperand &MO = MI.getOperand(OpNo);
413 uint32_t Res = static_cast<uint32_t>(MO.getImm());
414
415 switch (Res) {
416 case 0xffffffff:
417 Res = 0;
418 break;
419 case 1:
420 case 2:
421 case 3:
422 case 4:
423 case 5:
424 case 6:
425 case 7:
426 case 8:
427 break;
428 case 10:
429 Res = 9;
430 break;
431 case 12:
432 Res = 10;
433 break;
434 case 16:
435 Res = 11;
436 break;
437 case 32:
438 Res = 12;
439 break;
440 case 64:
441 Res = 13;
442 break;
443 case 128:
444 Res = 14;
445 break;
446 case 256:
447 Res = 15;
448 break;
449 default:
450 llvm_unreachable("Unexpected operand value!");
451 }
452
453 return Res;
454}
455
457XtensaMCCodeEmitter::getB4constuOpValue(const MCInst &MI, unsigned OpNo,
459 const MCSubtargetInfo &STI) const {
460 const MCOperand &MO = MI.getOperand(OpNo);
461 uint32_t Res = static_cast<uint32_t>(MO.getImm());
462
463 switch (Res) {
464 case 32768:
465 Res = 0;
466 break;
467 case 65536:
468 Res = 1;
469 break;
470 case 2:
471 case 3:
472 case 4:
473 case 5:
474 case 6:
475 case 7:
476 case 8:
477 break;
478 case 10:
479 Res = 9;
480 break;
481 case 12:
482 Res = 10;
483 break;
484 case 16:
485 Res = 11;
486 break;
487 case 32:
488 Res = 12;
489 break;
490 case 64:
491 Res = 13;
492 break;
493 case 128:
494 Res = 14;
495 break;
496 case 256:
497 Res = 15;
498 break;
499 default:
500 llvm_unreachable("Unexpected operand value!");
501 }
502
503 return Res;
504}
505#include "XtensaGenMCCodeEmitter.inc"
uint64_t Size
IRTranslator LLVM IR MI
#define I(x, y, z)
Definition: MD5.cpp:58
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
MCCodeEmitter - Generic instruction encoding interface.
Definition: MCCodeEmitter.h:21
virtual void encodeInstruction(const MCInst &Inst, SmallVectorImpl< char > &CB, SmallVectorImpl< MCFixup > &Fixups, const MCSubtargetInfo &STI) const =0
Encode the given Inst to bytes and append to CB.
Context object for machine code objects.
Definition: MCContext.h:83
Base class for the full range of assembler expressions which are needed for parsing.
Definition: MCExpr.h:34
static MCFixup create(uint32_t Offset, const MCExpr *Value, MCFixupKind Kind, SMLoc Loc=SMLoc())
Definition: MCFixup.h:87
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:185
Interface to description of machine instruction set.
Definition: MCInstrInfo.h:26
Instances of this class represent operands of the MCInst class.
Definition: MCInst.h:37
int64_t getImm() const
Definition: MCInst.h:81
bool isImm() const
Definition: MCInst.h:63
bool isReg() const
Definition: MCInst.h:62
MCRegister getReg() const
Returns the register number.
Definition: MCInst.h:70
const MCExpr * getExpr() const
Definition: MCInst.h:115
bool isExpr() const
Definition: MCInst.h:66
Generic base class for all target subtargets.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:573
void push_back(const T &Elt)
Definition: SmallVector.h:413
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:167
MCFixupKind
Extensible enumeration to represent the type of a fixup.
Definition: MCFixup.h:21
MCCodeEmitter * createXtensaMCCodeEmitter(const MCInstrInfo &MCII, MCContext &Ctx)