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