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.
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
190XtensaMCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO,
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
205XtensaMCCodeEmitter::getJumpTargetEncoding(const MCInst &MI, unsigned int OpNum,
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
244XtensaMCCodeEmitter::getLoopTargetEncoding(const MCInst &MI, unsigned int OpNum,
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
260XtensaMCCodeEmitter::getCallEncoding(const MCInst &MI, unsigned int OpNum,
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
280XtensaMCCodeEmitter::getL32RTargetEncoding(const MCInst &MI, unsigned OpNum,
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
299XtensaMCCodeEmitter::getMemRegEncoding(const MCInst &MI, unsigned OpNo,
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,
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
359XtensaMCCodeEmitter::getImm8_sh8OpValue(const MCInst &MI, unsigned OpNo,
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
372XtensaMCCodeEmitter::getImm12OpValue(const MCInst &MI, unsigned OpNo,
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
384XtensaMCCodeEmitter::getUimm4OpValue(const MCInst &MI, unsigned OpNo,
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
396XtensaMCCodeEmitter::getUimm5OpValue(const MCInst &MI, unsigned OpNo,
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
408XtensaMCCodeEmitter::getShimm1_31OpValue(const MCInst &MI, unsigned OpNo,
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
420XtensaMCCodeEmitter::getImm1_16OpValue(const MCInst &MI, unsigned OpNo,
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
432XtensaMCCodeEmitter::getImm1n_15OpValue(const MCInst &MI, unsigned OpNo,
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
448XtensaMCCodeEmitter::getImm32n_95OpValue(const MCInst &MI, unsigned OpNo,
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
460XtensaMCCodeEmitter::getImm8n_7OpValue(const MCInst &MI, unsigned OpNo,
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
475XtensaMCCodeEmitter::getImm64n_4nOpValue(const MCInst &MI, unsigned OpNo,
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
488XtensaMCCodeEmitter::getEntry_Imm12OpValue(const MCInst &MI, unsigned OpNo,
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
500XtensaMCCodeEmitter::getB4constOpValue(const MCInst &MI, unsigned OpNo,
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
548XtensaMCCodeEmitter::getB4constuOpValue(const MCInst &MI, unsigned OpNo,
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
598XtensaMCCodeEmitter::getImm7_22OpValue(const MCInst &MI, unsigned OpNo,
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"
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
uint64_t Size
IRTranslator LLVM IR MI
#define I(x, y, z)
Definition: MD5.cpp:58
static void addFixup(SmallVectorImpl< MCFixup > &Fixups, uint32_t Offset, const MCExpr *Value, uint16_t Kind)
MCCodeEmitter - Generic instruction encoding interface.
Definition: MCCodeEmitter.h:23
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, 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
Interface to description of machine instruction set.
Definition: MCInstrInfo.h:27
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
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:574
void push_back(const T &Elt)
Definition: SmallVector.h:414
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.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:477
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition: Error.cpp:167
MCCodeEmitter * createXtensaMCCodeEmitter(const MCInstrInfo &MCII, MCContext &Ctx)