LLVM 22.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.
46 void encodeInstruction(const MCInst &MI, SmallVectorImpl<char> &CB,
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 getLoopTargetEncoding(const MCInst &MI, unsigned int OpNum,
72 const MCSubtargetInfo &STI) const;
73
74 uint32_t getCallEncoding(const MCInst &MI, unsigned int OpNum,
76 const MCSubtargetInfo &STI) const;
77
78 uint32_t getL32RTargetEncoding(const MCInst &MI, unsigned OpNum,
80 const MCSubtargetInfo &STI) const;
81
82 uint32_t getMemRegEncoding(const MCInst &MI, unsigned OpNo,
84 const MCSubtargetInfo &STI) const;
85
86 uint32_t getImm8OpValue(const MCInst &MI, unsigned OpNo,
88 const MCSubtargetInfo &STI) const;
89
90 uint32_t getImm8_sh8OpValue(const MCInst &MI, unsigned OpNo,
92 const MCSubtargetInfo &STI) const;
93
94 uint32_t getImm12OpValue(const MCInst &MI, unsigned OpNo,
96 const MCSubtargetInfo &STI) const;
97
98 uint32_t getUimm4OpValue(const MCInst &MI, unsigned OpNo,
100 const MCSubtargetInfo &STI) const;
101
102 uint32_t getUimm5OpValue(const MCInst &MI, unsigned OpNo,
104 const MCSubtargetInfo &STI) const;
105
106 uint32_t getImm1_16OpValue(const MCInst &MI, unsigned OpNo,
108 const MCSubtargetInfo &STI) const;
109
110 uint32_t getImm1n_15OpValue(const MCInst &MI, unsigned OpNo,
112 const MCSubtargetInfo &STI) const;
113
114 uint32_t getImm32n_95OpValue(const MCInst &MI, unsigned OpNo,
116 const MCSubtargetInfo &STI) const;
117
118 uint32_t getImm8n_7OpValue(const MCInst &MI, unsigned OpNo,
120 const MCSubtargetInfo &STI) const;
121
122 uint32_t getImm64n_4nOpValue(const MCInst &MI, unsigned OpNo,
124 const MCSubtargetInfo &STI) const;
125
126 uint32_t getEntry_Imm12OpValue(const MCInst &MI, unsigned OpNo,
128 const MCSubtargetInfo &STI) const;
129
130 uint32_t getShimm1_31OpValue(const MCInst &MI, unsigned OpNo,
132 const MCSubtargetInfo &STI) const;
133
134 uint32_t getB4constOpValue(const MCInst &MI, unsigned OpNo,
136 const MCSubtargetInfo &STI) const;
137
138 uint32_t getB4constuOpValue(const MCInst &MI, unsigned OpNo,
140 const MCSubtargetInfo &STI) const;
141
142 uint32_t getImm7_22OpValue(const MCInst &MI, unsigned OpNo,
144 const MCSubtargetInfo &STI) const;
145};
146} // namespace
147
149 MCContext &Ctx) {
150 return new XtensaMCCodeEmitter(MCII, Ctx, true);
151}
152
154 const MCExpr *Value, uint16_t Kind) {
155 bool PCRel = false;
156 switch (Kind) {
164 PCRel = true;
165 }
166 Fixups.push_back(MCFixup::create(Offset, Value, Kind, PCRel));
167}
168
169void XtensaMCCodeEmitter::encodeInstruction(const MCInst &MI,
172 const MCSubtargetInfo &STI) const {
173 uint64_t Bits = getBinaryCodeForInstr(MI, Fixups, STI);
174 unsigned Size = MCII.get(MI.getOpcode()).getSize();
175
176 if (IsLittleEndian) {
177 // Little-endian insertion of Size bytes.
178 unsigned ShiftValue = 0;
179 for (unsigned I = 0; I != Size; ++I) {
180 CB.push_back(char(Bits >> ShiftValue));
181 ShiftValue += 8;
182 }
183 } else {
184 // TODO Big-endian insertion of Size bytes.
185 report_fatal_error("Big-endian mode currently is not supported!");
186 }
187}
188
189uint32_t
190XtensaMCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO,
191 SmallVectorImpl<MCFixup> &Fixups,
192 const MCSubtargetInfo &STI) const {
193 if (MO.isReg())
194 return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());
195 if (MO.isImm()) {
196 uint32_t Res = static_cast<uint32_t>(MO.getImm());
197 return Res;
198 }
199
200 report_fatal_error("Unhandled expression!");
201 return 0;
202}
203
204uint32_t
205XtensaMCCodeEmitter::getJumpTargetEncoding(const MCInst &MI, unsigned int OpNum,
206 SmallVectorImpl<MCFixup> &Fixups,
207 const MCSubtargetInfo &STI) const {
208 const MCOperand &MO = MI.getOperand(OpNum);
209
210 if (MO.isImm())
211 return MO.getImm();
212
213 const MCExpr *Expr = MO.getExpr();
214 addFixup(Fixups, 0, Expr, Xtensa::fixup_xtensa_jump_18);
215 return 0;
216}
217
218uint32_t XtensaMCCodeEmitter::getBranchTargetEncoding(
219 const MCInst &MI, unsigned int OpNum, SmallVectorImpl<MCFixup> &Fixups,
220 const MCSubtargetInfo &STI) const {
221 const MCOperand &MO = MI.getOperand(OpNum);
222 if (MO.isImm())
223 return static_cast<uint32_t>(MO.getImm());
224
225 const MCExpr *Expr = MO.getExpr();
226 switch (MI.getOpcode()) {
227 case Xtensa::BEQZ:
228 case Xtensa::BGEZ:
229 case Xtensa::BLTZ:
230 case Xtensa::BNEZ:
232 return 0;
233 case Xtensa::BEQZ_N:
234 case Xtensa::BNEZ_N:
235 addFixup(Fixups, 0, Expr, Xtensa::fixup_xtensa_branch_6);
236 return 0;
237 default:
238 addFixup(Fixups, 0, Expr, Xtensa::fixup_xtensa_branch_8);
239 return 0;
240 }
241}
242
243uint32_t
244XtensaMCCodeEmitter::getLoopTargetEncoding(const MCInst &MI, unsigned int OpNum,
245 SmallVectorImpl<MCFixup> &Fixups,
246 const MCSubtargetInfo &STI) const {
247 const MCOperand &MO = MI.getOperand(OpNum);
248 if (MO.isImm())
249 return static_cast<uint32_t>(MO.getImm());
250
251 assert((MO.isExpr()) && "Unexpected operand value!");
252
253 const MCExpr *Expr = MO.getExpr();
254
255 addFixup(Fixups, 0, Expr, Xtensa::fixup_xtensa_loop_8);
256 return 0;
257}
258
259uint32_t
260XtensaMCCodeEmitter::getCallEncoding(const MCInst &MI, unsigned int OpNum,
261 SmallVectorImpl<MCFixup> &Fixups,
262 const MCSubtargetInfo &STI) const {
263 const MCOperand &MO = MI.getOperand(OpNum);
264 if (MO.isImm()) {
265 int32_t Res = MO.getImm();
266 if (Res & 0x3) {
267 llvm_unreachable("Unexpected operand value!");
268 }
269 Res >>= 2;
270 return Res;
271 }
272
273 assert((MO.isExpr()) && "Unexpected operand value!");
274 const MCExpr *Expr = MO.getExpr();
275 addFixup(Fixups, 0, Expr, Xtensa::fixup_xtensa_call_18);
276 return 0;
277}
278
279uint32_t
280XtensaMCCodeEmitter::getL32RTargetEncoding(const MCInst &MI, unsigned OpNum,
281 SmallVectorImpl<MCFixup> &Fixups,
282 const MCSubtargetInfo &STI) const {
283 const MCOperand &MO = MI.getOperand(OpNum);
284 if (MO.isImm()) {
285 int32_t Res = MO.getImm();
286 // We don't check first 2 bits, because in these bits we could store first 2
287 // bits of instruction address
288 Res >>= 2;
289 return Res;
290 }
291
292 assert((MO.isExpr()) && "Unexpected operand value!");
293
295 return 0;
296}
297
298uint32_t
299XtensaMCCodeEmitter::getMemRegEncoding(const MCInst &MI, unsigned OpNo,
300 SmallVectorImpl<MCFixup> &Fixups,
301 const MCSubtargetInfo &STI) const {
302 assert(MI.getOperand(OpNo + 1).isImm());
303
304 uint32_t Res = static_cast<uint32_t>(MI.getOperand(OpNo + 1).getImm());
305
306 switch (MI.getOpcode()) {
307 case Xtensa::S16I:
308 case Xtensa::L16SI:
309 case Xtensa::L16UI:
310 if (Res & 0x1) {
311 report_fatal_error("Unexpected operand value!");
312 }
313 Res >>= 1;
314 break;
315 case Xtensa::S32I:
316 case Xtensa::L32I:
317 case Xtensa::S32I_N:
318 case Xtensa::L32I_N:
319 case Xtensa::SSI:
320 case Xtensa::SSIP:
321 case Xtensa::LSI:
322 case Xtensa::LSIP:
323
324 if (Res & 0x3) {
325 report_fatal_error("Unexpected operand value!");
326 }
327 Res >>= 2;
328 break;
329 }
330
331 switch (MI.getOpcode()) {
332 case Xtensa::S32I_N:
333 case Xtensa::L32I_N:
334 assert((isUInt<4>(Res)) && "Unexpected operand value!");
335 break;
336 default:
337 assert((isUInt<8>(Res)) && "Unexpected operand value!");
338 break;
339 }
340
341 uint32_t OffBits = Res << 4;
342 uint32_t RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI);
343
344 return ((OffBits & 0xFF0) | RegBits);
345}
346
347uint32_t XtensaMCCodeEmitter::getImm8OpValue(const MCInst &MI, unsigned OpNo,
348 SmallVectorImpl<MCFixup> &Fixups,
349 const MCSubtargetInfo &STI) const {
350 const MCOperand &MO = MI.getOperand(OpNo);
351 int32_t Res = MO.getImm();
352
353 assert(((Res >= -128) && (Res <= 127)) && "Unexpected operand value!");
354
355 return (Res & 0xff);
356}
357
358uint32_t
359XtensaMCCodeEmitter::getImm8_sh8OpValue(const MCInst &MI, unsigned OpNo,
360 SmallVectorImpl<MCFixup> &Fixups,
361 const MCSubtargetInfo &STI) const {
362 const MCOperand &MO = MI.getOperand(OpNo);
363 int32_t Res = MO.getImm();
364
365 assert(((Res >= -32768) && (Res <= 32512) && ((Res & 0xff) == 0)) &&
366 "Unexpected operand value!");
367
368 return (Res & 0xffff);
369}
370
371uint32_t
372XtensaMCCodeEmitter::getImm12OpValue(const MCInst &MI, unsigned OpNo,
373 SmallVectorImpl<MCFixup> &Fixups,
374 const MCSubtargetInfo &STI) const {
375 const MCOperand &MO = MI.getOperand(OpNo);
376 int32_t Res = MO.getImm();
377
378 assert(((Res >= -2048) && (Res <= 2047)) && "Unexpected operand value!");
379
380 return (Res & 0xfff);
381}
382
383uint32_t
384XtensaMCCodeEmitter::getUimm4OpValue(const MCInst &MI, unsigned OpNo,
385 SmallVectorImpl<MCFixup> &Fixups,
386 const MCSubtargetInfo &STI) const {
387 const MCOperand &MO = MI.getOperand(OpNo);
388 uint32_t Res = static_cast<uint32_t>(MO.getImm());
389
390 assert((Res <= 15) && "Unexpected operand value!");
391
392 return Res & 0xf;
393}
394
395uint32_t
396XtensaMCCodeEmitter::getUimm5OpValue(const MCInst &MI, unsigned OpNo,
397 SmallVectorImpl<MCFixup> &Fixups,
398 const MCSubtargetInfo &STI) const {
399 const MCOperand &MO = MI.getOperand(OpNo);
400 uint32_t Res = static_cast<uint32_t>(MO.getImm());
401
402 assert((Res <= 31) && "Unexpected operand value!");
403
404 return (Res & 0x1f);
405}
406
407uint32_t
408XtensaMCCodeEmitter::getShimm1_31OpValue(const MCInst &MI, unsigned OpNo,
409 SmallVectorImpl<MCFixup> &Fixups,
410 const MCSubtargetInfo &STI) const {
411 const MCOperand &MO = MI.getOperand(OpNo);
412 uint32_t Res = static_cast<uint32_t>(MO.getImm());
413
414 assert(((Res >= 1) && (Res <= 31)) && "Unexpected operand value!");
415
416 return ((32 - Res) & 0x1f);
417}
418
419uint32_t
420XtensaMCCodeEmitter::getImm1_16OpValue(const MCInst &MI, unsigned OpNo,
421 SmallVectorImpl<MCFixup> &Fixups,
422 const MCSubtargetInfo &STI) const {
423 const MCOperand &MO = MI.getOperand(OpNo);
424 uint32_t Res = static_cast<uint32_t>(MO.getImm());
425
426 assert(((Res >= 1) && (Res <= 16)) && "Unexpected operand value!");
427
428 return (Res - 1);
429}
430
431uint32_t
432XtensaMCCodeEmitter::getImm1n_15OpValue(const MCInst &MI, unsigned OpNo,
433 SmallVectorImpl<MCFixup> &Fixups,
434 const MCSubtargetInfo &STI) const {
435 const MCOperand &MO = MI.getOperand(OpNo);
436 int32_t Res = static_cast<int32_t>(MO.getImm());
437
438 assert(((Res >= -1) && (Res <= 15) && (Res != 0)) &&
439 "Unexpected operand value!");
440
441 if (Res < 0)
442 Res = 0;
443
444 return Res;
445}
446
447uint32_t
448XtensaMCCodeEmitter::getImm32n_95OpValue(const MCInst &MI, unsigned OpNo,
449 SmallVectorImpl<MCFixup> &Fixups,
450 const MCSubtargetInfo &STI) const {
451 const MCOperand &MO = MI.getOperand(OpNo);
452 int32_t Res = static_cast<int32_t>(MO.getImm());
453
454 assert(((Res >= -32) && (Res <= 95)) && "Unexpected operand value!");
455
456 return Res;
457}
458
459uint32_t
460XtensaMCCodeEmitter::getImm8n_7OpValue(const MCInst &MI, unsigned OpNo,
461 SmallVectorImpl<MCFixup> &Fixups,
462 const MCSubtargetInfo &STI) const {
463 const MCOperand &MO = MI.getOperand(OpNo);
464 int32_t Res = static_cast<int32_t>(MO.getImm());
465
466 assert(((Res >= -8) && (Res <= 7)) && "Unexpected operand value!");
467
468 if (Res < 0)
469 return Res + 16;
470
471 return Res;
472}
473
474uint32_t
475XtensaMCCodeEmitter::getImm64n_4nOpValue(const MCInst &MI, unsigned OpNo,
476 SmallVectorImpl<MCFixup> &Fixups,
477 const MCSubtargetInfo &STI) const {
478 const MCOperand &MO = MI.getOperand(OpNo);
479 int32_t Res = static_cast<int32_t>(MO.getImm());
480
481 assert(((Res >= -64) && (Res <= -4) && ((Res & 0x3) == 0)) &&
482 "Unexpected operand value!");
483
484 return Res & 0x3f;
485}
486
487uint32_t
488XtensaMCCodeEmitter::getEntry_Imm12OpValue(const MCInst &MI, unsigned OpNo,
489 SmallVectorImpl<MCFixup> &Fixups,
490 const MCSubtargetInfo &STI) const {
491 const MCOperand &MO = MI.getOperand(OpNo);
492 uint32_t res = static_cast<uint32_t>(MO.getImm());
493
494 assert(((res & 0x7) == 0) && "Unexpected operand value!");
495
496 return res;
497}
498
499uint32_t
500XtensaMCCodeEmitter::getB4constOpValue(const MCInst &MI, unsigned OpNo,
501 SmallVectorImpl<MCFixup> &Fixups,
502 const MCSubtargetInfo &STI) const {
503 const MCOperand &MO = MI.getOperand(OpNo);
504 uint32_t Res = static_cast<uint32_t>(MO.getImm());
505
506 switch (Res) {
507 case 0xffffffff:
508 Res = 0;
509 break;
510 case 1:
511 case 2:
512 case 3:
513 case 4:
514 case 5:
515 case 6:
516 case 7:
517 case 8:
518 break;
519 case 10:
520 Res = 9;
521 break;
522 case 12:
523 Res = 10;
524 break;
525 case 16:
526 Res = 11;
527 break;
528 case 32:
529 Res = 12;
530 break;
531 case 64:
532 Res = 13;
533 break;
534 case 128:
535 Res = 14;
536 break;
537 case 256:
538 Res = 15;
539 break;
540 default:
541 llvm_unreachable("Unexpected operand value!");
542 }
543
544 return Res;
545}
546
547uint32_t
548XtensaMCCodeEmitter::getB4constuOpValue(const MCInst &MI, unsigned OpNo,
549 SmallVectorImpl<MCFixup> &Fixups,
550 const MCSubtargetInfo &STI) const {
551 const MCOperand &MO = MI.getOperand(OpNo);
552 uint32_t Res = static_cast<uint32_t>(MO.getImm());
553
554 switch (Res) {
555 case 32768:
556 Res = 0;
557 break;
558 case 65536:
559 Res = 1;
560 break;
561 case 2:
562 case 3:
563 case 4:
564 case 5:
565 case 6:
566 case 7:
567 case 8:
568 break;
569 case 10:
570 Res = 9;
571 break;
572 case 12:
573 Res = 10;
574 break;
575 case 16:
576 Res = 11;
577 break;
578 case 32:
579 Res = 12;
580 break;
581 case 64:
582 Res = 13;
583 break;
584 case 128:
585 Res = 14;
586 break;
587 case 256:
588 Res = 15;
589 break;
590 default:
591 llvm_unreachable("Unexpected operand value!");
592 }
593
594 return Res;
595}
596
597uint32_t
598XtensaMCCodeEmitter::getImm7_22OpValue(const MCInst &MI, unsigned OpNo,
599 SmallVectorImpl<MCFixup> &Fixups,
600 const MCSubtargetInfo &STI) const {
601 const MCOperand &MO = MI.getOperand(OpNo);
602 uint32_t res = static_cast<uint32_t>(MO.getImm());
603
604 res -= 7;
605 assert(((res & 0xf) == res) && "Unexpected operand value!");
606
607 return res;
608}
609#include "XtensaGenMCCodeEmitter.inc"
static void addFixup(SmallVectorImpl< MCFixup > &Fixups, uint32_t Offset, const MCExpr *Value, uint16_t Kind, bool PCRel=false)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
IRTranslator LLVM IR MI
#define I(x, y, z)
Definition MD5.cpp:58
MCCodeEmitter - Generic instruction encoding interface.
Context object for machine code objects.
Definition MCContext.h:83
const MCRegisterInfo * getRegisterInfo() const
Definition MCContext.h:414
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, bool PCRel=false)
Consider bit fields if we need more flags.
Definition MCFixup.h:86
Instances of this class represent a single low-level machine instruction.
Definition MCInst.h:188
unsigned getSize() const
Return the number of bytes in the encoding of this instruction, or zero if the encoding size cannot b...
Interface to description of machine instruction set.
Definition MCInstrInfo.h:27
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode.
Definition MCInstrInfo.h:64
Instances of this class represent operands of the MCInst class.
Definition MCInst.h:40
int64_t getImm() const
Definition MCInst.h:84
bool isImm() const
Definition MCInst.h:66
bool isReg() const
Definition MCInst.h:65
MCRegister getReg() const
Returns the register number.
Definition MCInst.h:73
const MCExpr * getExpr() const
Definition MCInst.h:118
bool isExpr() const
Definition MCInst.h:69
uint16_t getEncodingValue(MCRegister Reg) const
Returns the encoding for Reg.
Generic base class for all target subtargets.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
LLVM Value Representation.
Definition Value.h:75
#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.
@ Offset
Definition DWP.cpp:477
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:167
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
Definition MathExtras.h:198
static void addFixup(SmallVectorImpl< MCFixup > &Fixups, uint32_t Offset, const MCExpr *Value, uint16_t Kind)
MCCodeEmitter * createXtensaMCCodeEmitter(const MCInstrInfo &MCII, MCContext &Ctx)