LLVM 20.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
60static const 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
76static const unsigned SRDecoderTable[] = {Xtensa::SAR, 3};
77
79 uint64_t Address,
80 const void *Decoder) {
81 if (RegNo > 255)
83
84 for (unsigned i = 0; i < std::size(SRDecoderTable); i += 2) {
85 if (SRDecoderTable[i + 1] == RegNo) {
86 unsigned Reg = SRDecoderTable[i];
89 }
90 }
91
93}
94
95static bool tryAddingSymbolicOperand(int64_t Value, bool isBranch,
96 uint64_t Address, uint64_t Offset,
97 uint64_t InstSize, MCInst &MI,
98 const void *Decoder) {
99 const MCDisassembler *Dis = static_cast<const MCDisassembler *>(Decoder);
101 /*OpSize=*/0, InstSize);
102}
103
105 int64_t Address, const void *Decoder) {
106 assert(isUInt<18>(Imm) && "Invalid immediate");
107 Inst.addOperand(MCOperand::createImm(SignExtend64<20>(Imm << 2)));
109}
110
112 int64_t Address, const void *Decoder) {
113 assert(isUInt<18>(Imm) && "Invalid immediate");
114 Inst.addOperand(MCOperand::createImm(SignExtend64<18>(Imm)));
116}
117
119 int64_t Address, const void *Decoder) {
120 switch (Inst.getOpcode()) {
121 case Xtensa::BEQZ:
122 case Xtensa::BGEZ:
123 case Xtensa::BLTZ:
124 case Xtensa::BNEZ:
125 assert(isUInt<12>(Imm) && "Invalid immediate");
126 if (!tryAddingSymbolicOperand(SignExtend64<12>(Imm) + 4 + Address, true,
127 Address, 0, 3, Inst, Decoder))
128 Inst.addOperand(MCOperand::createImm(SignExtend64<12>(Imm)));
129 break;
130 default:
131 assert(isUInt<8>(Imm) && "Invalid immediate");
132 if (!tryAddingSymbolicOperand(SignExtend64<8>(Imm) + 4 + Address, true,
133 Address, 0, 3, Inst, Decoder))
134 Inst.addOperand(MCOperand::createImm(SignExtend64<8>(Imm)));
135 }
137}
138
140 int64_t Address, const void *Decoder) {
141
142 assert(isUInt<16>(Imm) && "Invalid immediate");
144 SignExtend64<17>((Imm << 2) + 0x40000 + (Address & 0x3))));
146}
147
149 int64_t Address, const void *Decoder) {
150 assert(isUInt<8>(Imm) && "Invalid immediate");
151 Inst.addOperand(MCOperand::createImm(SignExtend64<8>(Imm)));
153}
154
156 int64_t Address,
157 const void *Decoder) {
158 assert(isUInt<8>(Imm) && "Invalid immediate");
159 Inst.addOperand(MCOperand::createImm(SignExtend64<16>(Imm << 8)));
161}
162
164 int64_t Address, const void *Decoder) {
165 assert(isUInt<12>(Imm) && "Invalid immediate");
166 Inst.addOperand(MCOperand::createImm(SignExtend64<12>(Imm)));
168}
169
171 int64_t Address, const void *Decoder) {
172 assert(isUInt<4>(Imm) && "Invalid immediate");
175}
176
178 int64_t Address, const void *Decoder) {
179 assert(isUInt<5>(Imm) && "Invalid immediate");
182}
183
185 int64_t Address, const void *Decoder) {
186 assert(isUInt<4>(Imm) && "Invalid immediate");
187 Inst.addOperand(MCOperand::createImm(Imm + 1));
189}
190
192 int64_t Address,
193 const void *Decoder) {
194 assert(isUInt<4>(Imm) && "Invalid immediate");
195 if (!Imm)
197 else
200}
201
203 int64_t Address,
204 const void *Decoder) {
205 assert(isUInt<7>(Imm) && "Invalid immediate");
206 if ((Imm & 0x60) == 0x60)
207 Inst.addOperand(MCOperand::createImm((~0x1f) | Imm));
208 else
211}
212
214 int64_t Address,
215 const void *Decoder) {
216 assert(isUInt<5>(Imm) && "Invalid immediate");
217 Inst.addOperand(MCOperand::createImm(32 - Imm));
219}
220
221static int64_t TableB4const[16] = {-1, 1, 2, 3, 4, 5, 6, 7,
222 8, 10, 12, 16, 32, 64, 128, 256};
224 int64_t Address, const void *Decoder) {
225 assert(isUInt<4>(Imm) && "Invalid immediate");
226
229}
230
231static int64_t TableB4constu[16] = {32768, 65536, 2, 3, 4, 5, 6, 7,
232 8, 10, 12, 16, 32, 64, 128, 256};
234 int64_t Address,
235 const void *Decoder) {
236 assert(isUInt<4>(Imm) && "Invalid immediate");
237
240}
241
243 int64_t Address, const void *Decoder) {
244 assert(isUInt<12>(Imm) && "Invalid immediate");
245 DecodeARRegisterClass(Inst, Imm & 0xf, Address, Decoder);
246 Inst.addOperand(MCOperand::createImm((Imm >> 4) & 0xff));
248}
249
251 int64_t Address, const void *Decoder) {
252 assert(isUInt<12>(Imm) && "Invalid immediate");
253 DecodeARRegisterClass(Inst, Imm & 0xf, Address, Decoder);
254 Inst.addOperand(MCOperand::createImm((Imm >> 3) & 0x1fe));
256}
257
259 int64_t Address, const void *Decoder) {
260 assert(isUInt<12>(Imm) && "Invalid immediate");
261 DecodeARRegisterClass(Inst, Imm & 0xf, Address, Decoder);
262 Inst.addOperand(MCOperand::createImm((Imm >> 2) & 0x3fc));
264}
265
267 int64_t Address, const void *Decoder) {
268 assert(isUInt<8>(Imm) && "Invalid immediate");
269 DecodeARRegisterClass(Inst, Imm & 0xf, Address, Decoder);
270 Inst.addOperand(MCOperand::createImm((Imm >> 2) & 0x3c));
272}
273
274/// Read two bytes from the ArrayRef and return 16 bit data sorted
275/// according to the given endianness.
278 bool IsLittleEndian) {
279 // We want to read exactly 2 Bytes of data.
280 if (Bytes.size() < 2) {
281 Size = 0;
283 }
284
285 if (!IsLittleEndian) {
286 report_fatal_error("Big-endian mode currently is not supported!");
287 } else {
288 Insn = (Bytes[1] << 8) | Bytes[0];
289 }
290
292}
293
294/// Read three bytes from the ArrayRef and return 24 bit data
297 bool IsLittleEndian) {
298 // We want to read exactly 3 Bytes of data.
299 if (Bytes.size() < 3) {
300 Size = 0;
302 }
303
304 if (!IsLittleEndian) {
305 report_fatal_error("Big-endian mode currently is not supported!");
306 } else {
307 Insn = (Bytes[2] << 16) | (Bytes[1] << 8) | (Bytes[0] << 0);
308 }
309
311}
312
313#include "XtensaGenDisassemblerTables.inc"
314
315DecodeStatus XtensaDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
316 ArrayRef<uint8_t> Bytes,
317 uint64_t Address,
318 raw_ostream &CS) const {
321
322 // Parse 16-bit instructions
323 if (hasDensity()) {
324 Result = readInstruction16(Bytes, Address, Size, Insn, IsLittleEndian);
325 if (Result == MCDisassembler::Fail)
327 LLVM_DEBUG(dbgs() << "Trying Xtensa 16-bit instruction table :\n");
328 Result = decodeInstruction(DecoderTable16, MI, Insn, Address, this, STI);
329 if (Result != MCDisassembler::Fail) {
330 Size = 2;
331 return Result;
332 }
333 }
334
335 // Parse Core 24-bit instructions
336 Result = readInstruction24(Bytes, Address, Size, Insn, IsLittleEndian);
337 if (Result == MCDisassembler::Fail)
339 LLVM_DEBUG(dbgs() << "Trying Xtensa 24-bit instruction table :\n");
340 Result = decodeInstruction(DecoderTable24, MI, Insn, Address, this, STI);
341 if (Result != MCDisassembler::Fail) {
342 Size = 3;
343 return Result;
344 }
345 return Result;
346}
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 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)
static const unsigned SRDecoderTable[]
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)
static const unsigned ARDecoderTable[]
static DecodeStatus decodeB4constOperand(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 void *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
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
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
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.