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 getShimm1_31OpValue(const MCInst &MI, unsigned OpNo,
108 const MCSubtargetInfo &STI) const;
109
110 uint32_t getB4constOpValue(const MCInst &MI, unsigned OpNo,
112 const MCSubtargetInfo &STI) const;
113
114 uint32_t getB4constuOpValue(const MCInst &MI, unsigned OpNo,
116 const MCSubtargetInfo &STI) const;
117};
118} // namespace
119
121 MCContext &Ctx) {
122 return new XtensaMCCodeEmitter(MCII, Ctx, true);
123}
124
125void XtensaMCCodeEmitter::encodeInstruction(const MCInst &MI,
128 const MCSubtargetInfo &STI) const {
129 uint64_t Bits = getBinaryCodeForInstr(MI, Fixups, STI);
130 unsigned Size = MCII.get(MI.getOpcode()).getSize();
131
132 if (IsLittleEndian) {
133 // Little-endian insertion of Size bytes.
134 unsigned ShiftValue = 0;
135 for (unsigned I = 0; I != Size; ++I) {
136 CB.push_back(char(Bits >> ShiftValue));
137 ShiftValue += 8;
138 }
139 } else {
140 // TODO Big-endian insertion of Size bytes.
141 report_fatal_error("Big-endian mode currently is not supported!");
142 }
143}
144
146XtensaMCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO,
148 const MCSubtargetInfo &STI) const {
149 if (MO.isReg())
150 return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());
151 if (MO.isImm()) {
152 uint32_t Res = static_cast<uint32_t>(MO.getImm());
153 return Res;
154 }
155
156 report_fatal_error("Unhandled expression!");
157 return 0;
158}
159
161XtensaMCCodeEmitter::getJumpTargetEncoding(const MCInst &MI, unsigned int OpNum,
163 const MCSubtargetInfo &STI) const {
164 const MCOperand &MO = MI.getOperand(OpNum);
165
166 if (MO.isImm())
167 return MO.getImm();
168
169 const MCExpr *Expr = MO.getExpr();
170 Fixups.push_back(MCFixup::create(
171 0, Expr, MCFixupKind(Xtensa::fixup_xtensa_jump_18), MI.getLoc()));
172 return 0;
173}
174
175uint32_t XtensaMCCodeEmitter::getBranchTargetEncoding(
176 const MCInst &MI, unsigned int OpNum, SmallVectorImpl<MCFixup> &Fixups,
177 const MCSubtargetInfo &STI) const {
178 const MCOperand &MO = MI.getOperand(OpNum);
179 if (MO.isImm())
180 return static_cast<uint32_t>(MO.getImm());
181
182 const MCExpr *Expr = MO.getExpr();
183 switch (MI.getOpcode()) {
184 case Xtensa::BEQZ:
185 case Xtensa::BGEZ:
186 case Xtensa::BLTZ:
187 case Xtensa::BNEZ:
188 Fixups.push_back(MCFixup::create(
189 0, Expr, MCFixupKind(Xtensa::fixup_xtensa_branch_12), MI.getLoc()));
190 return 0;
191 default:
192 Fixups.push_back(MCFixup::create(
193 0, Expr, MCFixupKind(Xtensa::fixup_xtensa_branch_8), MI.getLoc()));
194 return 0;
195 }
196}
197
199XtensaMCCodeEmitter::getCallEncoding(const MCInst &MI, unsigned int OpNum,
201 const MCSubtargetInfo &STI) const {
202 const MCOperand &MO = MI.getOperand(OpNum);
203 if (MO.isImm()) {
204 int32_t Res = MO.getImm();
205 if (Res & 0x3) {
206 llvm_unreachable("Unexpected operand value!");
207 }
208 Res >>= 2;
209 return Res;
210 }
211
212 assert((MO.isExpr()) && "Unexpected operand value!");
213 const MCExpr *Expr = MO.getExpr();
214 Fixups.push_back(MCFixup::create(
215 0, Expr, MCFixupKind(Xtensa::fixup_xtensa_call_18), MI.getLoc()));
216 return 0;
217}
218
220XtensaMCCodeEmitter::getL32RTargetEncoding(const MCInst &MI, unsigned OpNum,
222 const MCSubtargetInfo &STI) const {
223 const MCOperand &MO = MI.getOperand(OpNum);
224 if (MO.isImm()) {
225 int32_t Res = MO.getImm();
226 // We don't check first 2 bits, because in these bits we could store first 2
227 // bits of instruction address
228 Res >>= 2;
229 return Res;
230 }
231
232 assert((MO.isExpr()) && "Unexpected operand value!");
233
234 Fixups.push_back(MCFixup::create(
236 return 0;
237}
238
240XtensaMCCodeEmitter::getMemRegEncoding(const MCInst &MI, unsigned OpNo,
242 const MCSubtargetInfo &STI) const {
243 assert(MI.getOperand(OpNo + 1).isImm());
244
245 uint32_t Res = static_cast<uint32_t>(MI.getOperand(OpNo + 1).getImm());
246
247 switch (MI.getOpcode()) {
248 case Xtensa::S16I:
249 case Xtensa::L16SI:
250 case Xtensa::L16UI:
251 if (Res & 0x1) {
252 report_fatal_error("Unexpected operand value!");
253 }
254 Res >>= 1;
255 break;
256 case Xtensa::S32I:
257 case Xtensa::L32I:
258 if (Res & 0x3) {
259 report_fatal_error("Unexpected operand value!");
260 }
261 Res >>= 2;
262 break;
263 }
264
265 assert((isUInt<8>(Res)) && "Unexpected operand value!");
266
267 uint32_t OffBits = Res << 4;
268 uint32_t RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI);
269
270 return ((OffBits & 0xFF0) | RegBits);
271}
272
273uint32_t XtensaMCCodeEmitter::getImm8OpValue(const MCInst &MI, unsigned OpNo,
275 const MCSubtargetInfo &STI) const {
276 const MCOperand &MO = MI.getOperand(OpNo);
277 int32_t Res = MO.getImm();
278
279 assert(((Res >= -128) && (Res <= 127)) && "Unexpected operand value!");
280
281 return (Res & 0xff);
282}
283
285XtensaMCCodeEmitter::getImm8_sh8OpValue(const MCInst &MI, unsigned OpNo,
287 const MCSubtargetInfo &STI) const {
288 const MCOperand &MO = MI.getOperand(OpNo);
289 int32_t Res = MO.getImm();
290
291 assert(((Res >= -32768) && (Res <= 32512) && ((Res & 0xff) == 0)) &&
292 "Unexpected operand value!");
293
294 return (Res & 0xffff);
295}
296
298XtensaMCCodeEmitter::getImm12OpValue(const MCInst &MI, unsigned OpNo,
300 const MCSubtargetInfo &STI) const {
301 const MCOperand &MO = MI.getOperand(OpNo);
302 int32_t Res = MO.getImm();
303
304 assert(((Res >= -2048) && (Res <= 2047)) && "Unexpected operand value!");
305
306 return (Res & 0xfff);
307}
308
310XtensaMCCodeEmitter::getUimm4OpValue(const MCInst &MI, unsigned OpNo,
312 const MCSubtargetInfo &STI) const {
313 const MCOperand &MO = MI.getOperand(OpNo);
314 uint32_t Res = static_cast<uint32_t>(MO.getImm());
315
316 assert((Res <= 15) && "Unexpected operand value!");
317
318 return Res & 0xf;
319}
320
322XtensaMCCodeEmitter::getUimm5OpValue(const MCInst &MI, unsigned OpNo,
324 const MCSubtargetInfo &STI) const {
325 const MCOperand &MO = MI.getOperand(OpNo);
326 uint32_t Res = static_cast<uint32_t>(MO.getImm());
327
328 assert((Res <= 31) && "Unexpected operand value!");
329
330 return (Res & 0x1f);
331}
332
334XtensaMCCodeEmitter::getShimm1_31OpValue(const MCInst &MI, unsigned OpNo,
336 const MCSubtargetInfo &STI) const {
337 const MCOperand &MO = MI.getOperand(OpNo);
338 uint32_t Res = static_cast<uint32_t>(MO.getImm());
339
340 assert(((Res >= 1) && (Res <= 31)) && "Unexpected operand value!");
341
342 return ((32 - Res) & 0x1f);
343}
344
346XtensaMCCodeEmitter::getImm1_16OpValue(const MCInst &MI, unsigned OpNo,
348 const MCSubtargetInfo &STI) const {
349 const MCOperand &MO = MI.getOperand(OpNo);
350 uint32_t Res = static_cast<uint32_t>(MO.getImm());
351
352 assert(((Res >= 1) && (Res <= 16)) && "Unexpected operand value!");
353
354 return (Res - 1);
355}
356
358XtensaMCCodeEmitter::getB4constOpValue(const MCInst &MI, unsigned OpNo,
360 const MCSubtargetInfo &STI) const {
361 const MCOperand &MO = MI.getOperand(OpNo);
362 uint32_t Res = static_cast<uint32_t>(MO.getImm());
363
364 switch (Res) {
365 case 0xffffffff:
366 Res = 0;
367 break;
368 case 1:
369 case 2:
370 case 3:
371 case 4:
372 case 5:
373 case 6:
374 case 7:
375 case 8:
376 break;
377 case 10:
378 Res = 9;
379 break;
380 case 12:
381 Res = 10;
382 break;
383 case 16:
384 Res = 11;
385 break;
386 case 32:
387 Res = 12;
388 break;
389 case 64:
390 Res = 13;
391 break;
392 case 128:
393 Res = 14;
394 break;
395 case 256:
396 Res = 15;
397 break;
398 default:
399 llvm_unreachable("Unexpected operand value!");
400 }
401
402 return Res;
403}
404
406XtensaMCCodeEmitter::getB4constuOpValue(const MCInst &MI, unsigned OpNo,
408 const MCSubtargetInfo &STI) const {
409 const MCOperand &MO = MI.getOperand(OpNo);
410 uint32_t Res = static_cast<uint32_t>(MO.getImm());
411
412 switch (Res) {
413 case 32768:
414 Res = 0;
415 break;
416 case 65536:
417 Res = 1;
418 break;
419 case 2:
420 case 3:
421 case 4:
422 case 5:
423 case 6:
424 case 7:
425 case 8:
426 break;
427 case 10:
428 Res = 9;
429 break;
430 case 12:
431 Res = 10;
432 break;
433 case 16:
434 Res = 11;
435 break;
436 case 32:
437 Res = 12;
438 break;
439 case 64:
440 Res = 13;
441 break;
442 case 128:
443 Res = 14;
444 break;
445 case 256:
446 Res = 15;
447 break;
448 default:
449 llvm_unreachable("Unexpected operand value!");
450 }
451
452 return Res;
453}
454#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:184
Interface to description of machine instruction set.
Definition: MCInstrInfo.h:26
Instances of this class represent operands of the MCInst class.
Definition: MCInst.h:36
int64_t getImm() const
Definition: MCInst.h:80
bool isImm() const
Definition: MCInst.h:62
unsigned getReg() const
Returns the register number.
Definition: MCInst.h:69
bool isReg() const
Definition: MCInst.h:61
const MCExpr * getExpr() const
Definition: MCInst.h:114
bool isExpr() const
Definition: MCInst.h:65
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:586
void push_back(const T &Elt)
Definition: SmallVector.h:426
#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)