LLVM 21.0.0git
XtensaDisassembler.cpp
Go to the documentation of this file.
1//===-- XtensaDisassembler.cpp - Disassembler for Xtensa ------------------===//
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 XtensaDisassembler class.
12//
13//===----------------------------------------------------------------------===//
14
17#include "llvm/MC/MCContext.h"
20#include "llvm/MC/MCInst.h"
24#include "llvm/Support/Endian.h"
25
26using namespace llvm;
27
28#define DEBUG_TYPE "Xtensa-disassembler"
29
31
32namespace {
33
34class XtensaDisassembler : public MCDisassembler {
35 bool IsLittleEndian;
36
37public:
38 XtensaDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx, bool isLE)
39 : MCDisassembler(STI, Ctx), IsLittleEndian(isLE) {}
40
41 bool hasDensity() const { return STI.hasFeature(Xtensa::FeatureDensity); }
42
45 raw_ostream &CStream) const override;
46};
47} // end anonymous namespace
48
50 const MCSubtargetInfo &STI,
51 MCContext &Ctx) {
52 return new XtensaDisassembler(STI, Ctx, true);
53}
54
58}
59
60const unsigned ARDecoderTable[] = {
61 Xtensa::A0, Xtensa::SP, Xtensa::A2, Xtensa::A3, Xtensa::A4, Xtensa::A5,
62 Xtensa::A6, Xtensa::A7, Xtensa::A8, Xtensa::A9, Xtensa::A10, Xtensa::A11,
63 Xtensa::A12, Xtensa::A13, Xtensa::A14, Xtensa::A15};
64
66 uint64_t Address,
67 const void *Decoder) {
68 if (RegNo >= std::size(ARDecoderTable))
70
71 unsigned Reg = ARDecoderTable[RegNo];
74}
75
76const unsigned SRDecoderTable[] = {
77 Xtensa::SAR, 3, Xtensa::WINDOWBASE, 72, Xtensa::WINDOWSTART, 73};
78
80 uint64_t Address,
81 const MCDisassembler *Decoder) {
82 if (RegNo > 255)
84
85 for (unsigned i = 0; i < std::size(SRDecoderTable); i += 2) {
86 if (SRDecoderTable[i + 1] == RegNo) {
87 unsigned Reg = SRDecoderTable[i];
88
89 if (!Xtensa::checkRegister(Reg,
90 Decoder->getSubtargetInfo().getFeatureBits()))
92
95 }
96 }
97
99}
100
101static bool tryAddingSymbolicOperand(int64_t Value, bool isBranch,
102 uint64_t Address, uint64_t Offset,
103 uint64_t InstSize, MCInst &MI,
104 const void *Decoder) {
105 const MCDisassembler *Dis = static_cast<const MCDisassembler *>(Decoder);
107 /*OpSize=*/0, InstSize);
108}
109
111 int64_t Address, const void *Decoder) {
112 assert(isUInt<18>(Imm) && "Invalid immediate");
113 Inst.addOperand(MCOperand::createImm(SignExtend64<20>(Imm << 2)));
115}
116
118 int64_t Address, const void *Decoder) {
119 assert(isUInt<18>(Imm) && "Invalid immediate");
120 Inst.addOperand(MCOperand::createImm(SignExtend64<18>(Imm)));
122}
123
125 int64_t Address, const void *Decoder) {
126 switch (Inst.getOpcode()) {
127 case Xtensa::BEQZ:
128 case Xtensa::BGEZ:
129 case Xtensa::BLTZ:
130 case Xtensa::BNEZ:
131 assert(isUInt<12>(Imm) && "Invalid immediate");
132 if (!tryAddingSymbolicOperand(SignExtend64<12>(Imm) + 4 + Address, true,
133 Address, 0, 3, Inst, Decoder))
134 Inst.addOperand(MCOperand::createImm(SignExtend64<12>(Imm)));
135 break;
136 default:
137 assert(isUInt<8>(Imm) && "Invalid immediate");
138 if (!tryAddingSymbolicOperand(SignExtend64<8>(Imm) + 4 + Address, true,
139 Address, 0, 3, Inst, Decoder))
140 Inst.addOperand(MCOperand::createImm(SignExtend64<8>(Imm)));
141 }
143}
144
146 int64_t Address, const void *Decoder) {
147
148 assert(isUInt<16>(Imm) && "Invalid immediate");
150 SignExtend64<17>((Imm << 2) + 0x40000 + (Address & 0x3))));
152}
153
155 int64_t Address, const void *Decoder) {
156 assert(isUInt<8>(Imm) && "Invalid immediate");
157 Inst.addOperand(MCOperand::createImm(SignExtend64<8>(Imm)));
159}
160
162 int64_t Address,
163 const void *Decoder) {
164 assert(isUInt<8>(Imm) && "Invalid immediate");
165 Inst.addOperand(MCOperand::createImm(SignExtend64<16>(Imm << 8)));
167}
168
170 int64_t Address, const void *Decoder) {
171 assert(isUInt<12>(Imm) && "Invalid immediate");
172 Inst.addOperand(MCOperand::createImm(SignExtend64<12>(Imm)));
174}
175
177 int64_t Address, const void *Decoder) {
178 assert(isUInt<4>(Imm) && "Invalid immediate");
181}
182
184 int64_t Address, const void *Decoder) {
185 assert(isUInt<5>(Imm) && "Invalid immediate");
188}
189
191 int64_t Address, const void *Decoder) {
192 assert(isUInt<4>(Imm) && "Invalid immediate");
193 Inst.addOperand(MCOperand::createImm(Imm + 1));
195}
196
198 int64_t Address,
199 const void *Decoder) {
200 assert(isUInt<4>(Imm) && "Invalid immediate");
201 if (!Imm)
203 else
206}
207
209 int64_t Address,
210 const void *Decoder) {
211 assert(isUInt<7>(Imm) && "Invalid immediate");
212 if ((Imm & 0x60) == 0x60)
213 Inst.addOperand(MCOperand::createImm((~0x1f) | Imm));
214 else
217}
218
220 int64_t Address, const void *Decoder) {
221 assert(isUInt<4>(Imm) && "Invalid immediate");
222 Inst.addOperand(MCOperand::createImm(Imm > 7 ? Imm - 16 : Imm));
224}
225
227 int64_t Address,
228 const void *Decoder) {
229 assert(isUInt<6>(Imm) && ((Imm & 0x3) == 0) && "Invalid immediate");
230 Inst.addOperand(MCOperand::createImm((~0x3f) | (Imm)));
232}
233
235 int64_t Address,
236 const void *Decoder) {
237 assert(isUInt<15>(Imm) && ((Imm & 0x7) == 0) && "Invalid immediate");
240}
241
243 int64_t Address,
244 const void *Decoder) {
245 assert(isUInt<5>(Imm) && "Invalid immediate");
246 Inst.addOperand(MCOperand::createImm(32 - Imm));
248}
249
250static int64_t TableB4const[16] = {-1, 1, 2, 3, 4, 5, 6, 7,
251 8, 10, 12, 16, 32, 64, 128, 256};
253 int64_t Address, const void *Decoder) {
254 assert(isUInt<4>(Imm) && "Invalid immediate");
255
258}
259
260static int64_t TableB4constu[16] = {32768, 65536, 2, 3, 4, 5, 6, 7,
261 8, 10, 12, 16, 32, 64, 128, 256};
263 int64_t Address,
264 const void *Decoder) {
265 assert(isUInt<4>(Imm) && "Invalid immediate");
266
269}
270
272 int64_t Address, const void *Decoder) {
273 assert(isUInt<12>(Imm) && "Invalid immediate");
274 DecodeARRegisterClass(Inst, Imm & 0xf, Address, Decoder);
275 Inst.addOperand(MCOperand::createImm((Imm >> 4) & 0xff));
277}
278
280 int64_t Address, const void *Decoder) {
281 assert(isUInt<12>(Imm) && "Invalid immediate");
282 DecodeARRegisterClass(Inst, Imm & 0xf, Address, Decoder);
283 Inst.addOperand(MCOperand::createImm((Imm >> 3) & 0x1fe));
285}
286
288 int64_t Address, const void *Decoder) {
289 assert(isUInt<12>(Imm) && "Invalid immediate");
290 DecodeARRegisterClass(Inst, Imm & 0xf, Address, Decoder);
291 Inst.addOperand(MCOperand::createImm((Imm >> 2) & 0x3fc));
293}
294
296 int64_t Address, const void *Decoder) {
297 assert(isUInt<8>(Imm) && "Invalid immediate");
298 DecodeARRegisterClass(Inst, Imm & 0xf, Address, Decoder);
299 Inst.addOperand(MCOperand::createImm((Imm >> 2) & 0x3c));
301}
302
303/// Read two bytes from the ArrayRef and return 16 bit data sorted
304/// according to the given endianness.
307 bool IsLittleEndian) {
308 // We want to read exactly 2 Bytes of data.
309 if (Bytes.size() < 2) {
310 Size = 0;
312 }
313
314 if (!IsLittleEndian) {
315 report_fatal_error("Big-endian mode currently is not supported!");
316 } else {
317 Insn = (Bytes[1] << 8) | Bytes[0];
318 }
319
321}
322
323/// Read three bytes from the ArrayRef and return 24 bit data
326 bool IsLittleEndian) {
327 // We want to read exactly 3 Bytes of data.
328 if (Bytes.size() < 3) {
329 Size = 0;
331 }
332
333 if (!IsLittleEndian) {
334 report_fatal_error("Big-endian mode currently is not supported!");
335 } else {
336 Insn = (Bytes[2] << 16) | (Bytes[1] << 8) | (Bytes[0] << 0);
337 }
338
340}
341
342#include "XtensaGenDisassemblerTables.inc"
343
344DecodeStatus XtensaDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
345 ArrayRef<uint8_t> Bytes,
346 uint64_t Address,
347 raw_ostream &CS) const {
350
351 // Parse 16-bit instructions
352 if (hasDensity()) {
353 Result = readInstruction16(Bytes, Address, Size, Insn, IsLittleEndian);
354 if (Result == MCDisassembler::Fail)
356 LLVM_DEBUG(dbgs() << "Trying Xtensa 16-bit instruction table :\n");
357 Result = decodeInstruction(DecoderTable16, MI, Insn, Address, this, STI);
358 if (Result != MCDisassembler::Fail) {
359 Size = 2;
360 return Result;
361 }
362 }
363
364 // Parse Core 24-bit instructions
365 Result = readInstruction24(Bytes, Address, Size, Insn, IsLittleEndian);
366 if (Result == MCDisassembler::Fail)
368 LLVM_DEBUG(dbgs() << "Trying Xtensa 24-bit instruction table :\n");
369 Result = decodeInstruction(DecoderTable24, MI, Insn, Address, this, STI);
370 if (Result != MCDisassembler::Fail) {
371 Size = 3;
372 return Result;
373 }
374 return Result;
375}
SmallVector< AArch64_IMM::ImmInsnModel, 4 > Insn
#define LLVM_EXTERNAL_VISIBILITY
Definition: Compiler.h:128
#define LLVM_DEBUG(...)
Definition: Debug.h:106
uint64_t Size
IRTranslator LLVM IR MI
static bool isBranch(unsigned Opcode)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static DecodeStatus decodeMem16Operand(MCInst &Inst, uint64_t Imm, int64_t Address, const void *Decoder)
static int64_t TableB4const[16]
static DecodeStatus decodeImm1n_15Operand(MCInst &Inst, uint64_t Imm, int64_t Address, const void *Decoder)
LLVM_EXTERNAL_VISIBILITY void LLVMInitializeXtensaDisassembler()
static DecodeStatus readInstruction24(ArrayRef< uint8_t > Bytes, uint64_t Address, uint64_t &Size, uint64_t &Insn, bool IsLittleEndian)
Read three bytes from the ArrayRef and return 24 bit data.
static DecodeStatus decodeImm8_sh8Operand(MCInst &Inst, uint64_t Imm, int64_t Address, const void *Decoder)
static DecodeStatus decodeImm8Operand(MCInst &Inst, uint64_t Imm, int64_t Address, const void *Decoder)
static DecodeStatus decodeL32ROperand(MCInst &Inst, uint64_t Imm, int64_t Address, const void *Decoder)
static DecodeStatus decodeEntry_Imm12OpValue(MCInst &Inst, uint64_t Imm, int64_t Address, const void *Decoder)
static DecodeStatus decodeMem32nOperand(MCInst &Inst, uint64_t Imm, int64_t Address, const void *Decoder)
static DecodeStatus decodeImm12Operand(MCInst &Inst, uint64_t Imm, int64_t Address, const void *Decoder)
static DecodeStatus DecodeARRegisterClass(MCInst &Inst, uint64_t RegNo, uint64_t Address, const void *Decoder)
static bool tryAddingSymbolicOperand(int64_t Value, bool isBranch, uint64_t Address, uint64_t Offset, uint64_t InstSize, MCInst &MI, const void *Decoder)
static DecodeStatus decodeMem32Operand(MCInst &Inst, uint64_t Imm, int64_t Address, const void *Decoder)
static DecodeStatus decodeUimm4Operand(MCInst &Inst, uint64_t Imm, int64_t Address, const void *Decoder)
const unsigned SRDecoderTable[]
static DecodeStatus decodeImm64n_4nOperand(MCInst &Inst, uint64_t Imm, int64_t Address, const void *Decoder)
static DecodeStatus decodeImm1_16Operand(MCInst &Inst, uint64_t Imm, int64_t Address, const void *Decoder)
static DecodeStatus decodeMem8Operand(MCInst &Inst, uint64_t Imm, int64_t Address, const void *Decoder)
static DecodeStatus decodeUimm5Operand(MCInst &Inst, uint64_t Imm, int64_t Address, const void *Decoder)
static DecodeStatus decodeImm32n_95Operand(MCInst &Inst, uint64_t Imm, int64_t Address, const void *Decoder)
static DecodeStatus readInstruction16(ArrayRef< uint8_t > Bytes, uint64_t Address, uint64_t &Size, uint64_t &Insn, bool IsLittleEndian)
Read two bytes from the ArrayRef and return 16 bit data sorted according to the given endianness.
static MCDisassembler * createXtensaDisassembler(const Target &T, const MCSubtargetInfo &STI, MCContext &Ctx)
static DecodeStatus decodeCallOperand(MCInst &Inst, uint64_t Imm, int64_t Address, const void *Decoder)
static DecodeStatus decodeB4constuOperand(MCInst &Inst, uint64_t Imm, int64_t Address, const void *Decoder)
const unsigned ARDecoderTable[]
static DecodeStatus decodeB4constOperand(MCInst &Inst, uint64_t Imm, int64_t Address, const void *Decoder)
static DecodeStatus decodeImm8n_7Operand(MCInst &Inst, uint64_t Imm, int64_t Address, const void *Decoder)
static int64_t TableB4constu[16]
static DecodeStatus DecodeSRRegisterClass(MCInst &Inst, uint64_t RegNo, uint64_t Address, const MCDisassembler *Decoder)
static DecodeStatus decodeShimm1_31Operand(MCInst &Inst, uint64_t Imm, int64_t Address, const void *Decoder)
static DecodeStatus decodeJumpOperand(MCInst &Inst, uint64_t Imm, int64_t Address, const void *Decoder)
static DecodeStatus decodeBranchOperand(MCInst &Inst, uint64_t Imm, int64_t Address, const void *Decoder)
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
size_t size() const
size - Get the array size.
Definition: ArrayRef.h:168
Context object for machine code objects.
Definition: MCContext.h:83
Superclass for all disassemblers.
bool tryAddingSymbolicOperand(MCInst &Inst, int64_t Value, uint64_t Address, bool IsBranch, uint64_t Offset, uint64_t OpSize, uint64_t InstSize) const
const MCSubtargetInfo & getSubtargetInfo() const
DecodeStatus
Ternary decode status.
virtual DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size, ArrayRef< uint8_t > Bytes, uint64_t Address, raw_ostream &CStream) const =0
Returns the disassembly of a single instruction.
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:185
unsigned getOpcode() const
Definition: MCInst.h:199
void addOperand(const MCOperand Op)
Definition: MCInst.h:211
static MCOperand createReg(MCRegister Reg)
Definition: MCInst.h:135
static MCOperand createImm(int64_t Val)
Definition: MCInst.h:142
Generic base class for all target subtargets.
bool hasFeature(unsigned Feature) const
const FeatureBitset & getFeatureBits() const
Target - Wrapper for Target specific information.
LLVM Value Representation.
Definition: Value.h:74
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:52
bool checkRegister(MCRegister RegNo, const FeatureBitset &FeatureBits)
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:480
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:167
Target & getTheXtensaTarget()
static void RegisterMCDisassembler(Target &T, Target::MCDisassemblerCtorTy Fn)
RegisterMCDisassembler - Register a MCDisassembler implementation for the given target.