LLVM 17.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, raw_ostream &OS,
127 const MCSubtargetInfo &STI) const {
128 uint64_t Bits = getBinaryCodeForInstr(MI, Fixups, STI);
129 unsigned Size = MCII.get(MI.getOpcode()).getSize();
130
131 if (IsLittleEndian) {
132 // Little-endian insertion of Size bytes.
133 unsigned ShiftValue = 0;
134 for (unsigned I = 0; I != Size; ++I) {
135 OS << uint8_t(Bits >> ShiftValue);
136 ShiftValue += 8;
137 }
138 } else {
139 // TODO Big-endian insertion of Size bytes.
140 report_fatal_error("Big-endian mode currently is not supported!");
141 }
142}
143
145XtensaMCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO,
147 const MCSubtargetInfo &STI) const {
148 if (MO.isReg())
149 return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());
150 if (MO.isImm()) {
151 uint32_t Res = static_cast<uint32_t>(MO.getImm());
152 return Res;
153 }
154
155 report_fatal_error("Unhandled expression!");
156 return 0;
157}
158
160XtensaMCCodeEmitter::getJumpTargetEncoding(const MCInst &MI, unsigned int OpNum,
162 const MCSubtargetInfo &STI) const {
163 const MCOperand &MO = MI.getOperand(OpNum);
164
165 if (MO.isImm())
166 return MO.getImm();
167
168 const MCExpr *Expr = MO.getExpr();
169 Fixups.push_back(MCFixup::create(
170 0, Expr, MCFixupKind(Xtensa::fixup_xtensa_jump_18), MI.getLoc()));
171 return 0;
172}
173
174uint32_t XtensaMCCodeEmitter::getBranchTargetEncoding(
175 const MCInst &MI, unsigned int OpNum, SmallVectorImpl<MCFixup> &Fixups,
176 const MCSubtargetInfo &STI) const {
177 const MCOperand &MO = MI.getOperand(OpNum);
178 if (MO.isImm())
179 return static_cast<uint32_t>(MO.getImm());
180
181 const MCExpr *Expr = MO.getExpr();
182 switch (MI.getOpcode()) {
183 case Xtensa::BEQZ:
184 case Xtensa::BGEZ:
185 case Xtensa::BLTZ:
186 case Xtensa::BNEZ:
187 Fixups.push_back(MCFixup::create(
188 0, Expr, MCFixupKind(Xtensa::fixup_xtensa_branch_12), MI.getLoc()));
189 return 0;
190 default:
191 Fixups.push_back(MCFixup::create(
192 0, Expr, MCFixupKind(Xtensa::fixup_xtensa_branch_8), MI.getLoc()));
193 return 0;
194 }
195}
196
198XtensaMCCodeEmitter::getCallEncoding(const MCInst &MI, unsigned int OpNum,
200 const MCSubtargetInfo &STI) const {
201 const MCOperand &MO = MI.getOperand(OpNum);
202 if (MO.isImm()) {
203 int32_t Res = MO.getImm();
204 if (Res & 0x3) {
205 llvm_unreachable("Unexpected operand value!");
206 }
207 Res >>= 2;
208 return Res;
209 }
210
211 assert((MO.isExpr()) && "Unexpected operand value!");
212 const MCExpr *Expr = MO.getExpr();
213 Fixups.push_back(MCFixup::create(
214 0, Expr, MCFixupKind(Xtensa::fixup_xtensa_call_18), MI.getLoc()));
215 return 0;
216}
217
219XtensaMCCodeEmitter::getL32RTargetEncoding(const MCInst &MI, unsigned OpNum,
221 const MCSubtargetInfo &STI) const {
222 const MCOperand &MO = MI.getOperand(OpNum);
223 if (MO.isImm()) {
224 int32_t Res = MO.getImm();
225 // We don't check first 2 bits, because in these bits we could store first 2
226 // bits of instruction address
227 Res >>= 2;
228 return Res;
229 }
230
231 assert((MO.isExpr()) && "Unexpected operand value!");
232
233 Fixups.push_back(MCFixup::create(
235 return 0;
236}
237
239XtensaMCCodeEmitter::getMemRegEncoding(const MCInst &MI, unsigned OpNo,
241 const MCSubtargetInfo &STI) const {
242 assert(MI.getOperand(OpNo + 1).isImm());
243
244 uint32_t Res = static_cast<uint32_t>(MI.getOperand(OpNo + 1).getImm());
245
246 switch (MI.getOpcode()) {
247 case Xtensa::S16I:
248 case Xtensa::L16SI:
249 case Xtensa::L16UI:
250 if (Res & 0x1) {
251 report_fatal_error("Unexpected operand value!");
252 }
253 Res >>= 1;
254 break;
255 case Xtensa::S32I:
256 case Xtensa::L32I:
257 if (Res & 0x3) {
258 report_fatal_error("Unexpected operand value!");
259 }
260 Res >>= 2;
261 break;
262 }
263
264 assert((isUInt<8>(Res)) && "Unexpected operand value!");
265
266 uint32_t OffBits = Res << 4;
267 uint32_t RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI);
268
269 return ((OffBits & 0xFF0) | RegBits);
270}
271
272uint32_t XtensaMCCodeEmitter::getImm8OpValue(const MCInst &MI, unsigned OpNo,
274 const MCSubtargetInfo &STI) const {
275 const MCOperand &MO = MI.getOperand(OpNo);
276 int32_t Res = MO.getImm();
277
278 assert(((Res >= -128) && (Res <= 127)) && "Unexpected operand value!");
279
280 return (Res & 0xff);
281}
282
284XtensaMCCodeEmitter::getImm8_sh8OpValue(const MCInst &MI, unsigned OpNo,
286 const MCSubtargetInfo &STI) const {
287 const MCOperand &MO = MI.getOperand(OpNo);
288 int32_t Res = MO.getImm();
289
290 assert(((Res >= -32768) && (Res <= 32512) && ((Res & 0xff) == 0)) &&
291 "Unexpected operand value!");
292
293 return (Res & 0xffff);
294}
295
297XtensaMCCodeEmitter::getImm12OpValue(const MCInst &MI, unsigned OpNo,
299 const MCSubtargetInfo &STI) const {
300 const MCOperand &MO = MI.getOperand(OpNo);
301 int32_t Res = MO.getImm();
302
303 assert(((Res >= -2048) && (Res <= 2047)) && "Unexpected operand value!");
304
305 return (Res & 0xfff);
306}
307
309XtensaMCCodeEmitter::getUimm4OpValue(const MCInst &MI, unsigned OpNo,
311 const MCSubtargetInfo &STI) const {
312 const MCOperand &MO = MI.getOperand(OpNo);
313 uint32_t Res = static_cast<uint32_t>(MO.getImm());
314
315 assert((Res <= 15) && "Unexpected operand value!");
316
317 return Res & 0xf;
318}
319
321XtensaMCCodeEmitter::getUimm5OpValue(const MCInst &MI, unsigned OpNo,
323 const MCSubtargetInfo &STI) const {
324 const MCOperand &MO = MI.getOperand(OpNo);
325 uint32_t Res = static_cast<uint32_t>(MO.getImm());
326
327 assert((Res <= 31) && "Unexpected operand value!");
328
329 return (Res & 0x1f);
330}
331
333XtensaMCCodeEmitter::getShimm1_31OpValue(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 >= 1) && (Res <= 31)) && "Unexpected operand value!");
340
341 return ((32 - Res) & 0x1f);
342}
343
345XtensaMCCodeEmitter::getImm1_16OpValue(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 >= 1) && (Res <= 16)) && "Unexpected operand value!");
352
353 return (Res - 1);
354}
355
357XtensaMCCodeEmitter::getB4constOpValue(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 switch (Res) {
364 case 0xffffffff:
365 Res = 0;
366 break;
367 case 1:
368 case 2:
369 case 3:
370 case 4:
371 case 5:
372 case 6:
373 case 7:
374 case 8:
375 break;
376 case 10:
377 Res = 9;
378 break;
379 case 12:
380 Res = 10;
381 break;
382 case 16:
383 Res = 11;
384 break;
385 case 32:
386 Res = 12;
387 break;
388 case 64:
389 Res = 13;
390 break;
391 case 128:
392 Res = 14;
393 break;
394 case 256:
395 Res = 15;
396 break;
397 default:
398 llvm_unreachable("Unexpected operand value!");
399 }
400
401 return Res;
402}
403
405XtensaMCCodeEmitter::getB4constuOpValue(const MCInst &MI, unsigned OpNo,
407 const MCSubtargetInfo &STI) const {
408 const MCOperand &MO = MI.getOperand(OpNo);
409 uint32_t Res = static_cast<uint32_t>(MO.getImm());
410
411 switch (Res) {
412 case 32768:
413 Res = 0;
414 break;
415 case 65536:
416 Res = 1;
417 break;
418 case 2:
419 case 3:
420 case 4:
421 case 5:
422 case 6:
423 case 7:
424 case 8:
425 break;
426 case 10:
427 Res = 9;
428 break;
429 case 12:
430 Res = 10;
431 break;
432 case 16:
433 Res = 11;
434 break;
435 case 32:
436 Res = 12;
437 break;
438 case 64:
439 Res = 13;
440 break;
441 case 128:
442 Res = 14;
443 break;
444 case 256:
445 Res = 15;
446 break;
447 default:
448 llvm_unreachable("Unexpected operand value!");
449 }
450
451 return Res;
452}
453#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())
raw_pwrite_stream & OS
MCCodeEmitter - Generic instruction encoding interface.
Definition: MCCodeEmitter.h:21
virtual void encodeInstruction(const MCInst &Inst, raw_ostream &OS, SmallVectorImpl< MCFixup > &Fixups, const MCSubtargetInfo &STI) const
EncodeInstruction - Encode the given Inst to bytes on the output stream OS.
Definition: MCCodeEmitter.h:28
Context object for machine code objects.
Definition: MCContext.h:76
Base class for the full range of assembler expressions which are needed for parsing.
Definition: MCExpr.h:35
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:577
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:52
#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:145
MCFixupKind
Extensible enumeration to represent the type of a fixup.
Definition: MCFixup.h:21
MCCodeEmitter * createXtensaMCCodeEmitter(const MCInstrInfo &MCII, MCContext &Ctx)