LLVM 19.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 {
42 return STI.hasFeature(Xtensa::FeatureDensity);
43 }
44
46 ArrayRef<uint8_t> Bytes, uint64_t Address,
47 raw_ostream &CStream) const override;
48};
49} // end anonymous namespace
50
52 const MCSubtargetInfo &STI,
53 MCContext &Ctx) {
54 return new XtensaDisassembler(STI, Ctx, true);
55}
56
60}
61
62static const unsigned ARDecoderTable[] = {
63 Xtensa::A0, Xtensa::SP, Xtensa::A2, Xtensa::A3, Xtensa::A4, Xtensa::A5,
64 Xtensa::A6, Xtensa::A7, Xtensa::A8, Xtensa::A9, Xtensa::A10, Xtensa::A11,
65 Xtensa::A12, Xtensa::A13, Xtensa::A14, Xtensa::A15};
66
68 uint64_t Address,
69 const void *Decoder) {
70 if (RegNo >= std::size(ARDecoderTable))
72
73 unsigned Reg = ARDecoderTable[RegNo];
76}
77
78static const unsigned SRDecoderTable[] = {Xtensa::SAR, 3};
79
81 uint64_t Address,
82 const void *Decoder) {
83 if (RegNo > 255)
85
86 for (unsigned i = 0; i < std::size(SRDecoderTable); i += 2) {
87 if (SRDecoderTable[i + 1] == RegNo) {
88 unsigned Reg = SRDecoderTable[i];
91 }
92 }
93
95}
96
97static bool tryAddingSymbolicOperand(int64_t Value, bool isBranch,
98 uint64_t Address, uint64_t Offset,
99 uint64_t InstSize, MCInst &MI,
100 const void *Decoder) {
101 const MCDisassembler *Dis = static_cast<const MCDisassembler *>(Decoder);
102 return Dis->tryAddingSymbolicOperand(MI, Value, Address, isBranch, Offset, /*OpSize=*/0,
103 InstSize);
104}
105
107 int64_t Address, const void *Decoder) {
108 assert(isUInt<18>(Imm) && "Invalid immediate");
109 Inst.addOperand(MCOperand::createImm(SignExtend64<20>(Imm << 2)));
111}
112
114 int64_t Address, const void *Decoder) {
115 assert(isUInt<18>(Imm) && "Invalid immediate");
116 Inst.addOperand(MCOperand::createImm(SignExtend64<18>(Imm)));
118}
119
121 int64_t Address, const void *Decoder) {
122 switch (Inst.getOpcode()) {
123 case Xtensa::BEQZ:
124 case Xtensa::BGEZ:
125 case Xtensa::BLTZ:
126 case Xtensa::BNEZ:
127 assert(isUInt<12>(Imm) && "Invalid immediate");
128 if (!tryAddingSymbolicOperand(SignExtend64<12>(Imm) + 4 + Address, true,
129 Address, 0, 3, Inst, Decoder))
130 Inst.addOperand(MCOperand::createImm(SignExtend64<12>(Imm)));
131 break;
132 default:
133 assert(isUInt<8>(Imm) && "Invalid immediate");
134 if (!tryAddingSymbolicOperand(SignExtend64<8>(Imm) + 4 + Address, true,
135 Address, 0, 3, Inst, Decoder))
136 Inst.addOperand(MCOperand::createImm(SignExtend64<8>(Imm)));
137 }
139}
140
142 int64_t Address, const void *Decoder) {
143
144 assert(isUInt<16>(Imm) && "Invalid immediate");
146 SignExtend64<17>((Imm << 2) + 0x40000 + (Address & 0x3))));
148}
149
151 int64_t Address, const void *Decoder) {
152 assert(isUInt<8>(Imm) && "Invalid immediate");
153 Inst.addOperand(MCOperand::createImm(SignExtend64<8>(Imm)));
155}
156
158 int64_t Address,
159 const void *Decoder) {
160 assert(isUInt<8>(Imm) && "Invalid immediate");
161 Inst.addOperand(MCOperand::createImm(SignExtend64<16>(Imm << 8)));
163}
164
166 int64_t Address, const void *Decoder) {
167 assert(isUInt<12>(Imm) && "Invalid immediate");
168 Inst.addOperand(MCOperand::createImm(SignExtend64<12>(Imm)));
170}
171
173 int64_t Address, const void *Decoder) {
174 assert(isUInt<4>(Imm) && "Invalid immediate");
177}
178
180 int64_t Address, const void *Decoder) {
181 assert(isUInt<5>(Imm) && "Invalid immediate");
184}
185
187 int64_t Address, const void *Decoder) {
188 assert(isUInt<4>(Imm) && "Invalid immediate");
189 Inst.addOperand(MCOperand::createImm(Imm + 1));
191}
192
194 int64_t Address,
195 const void *Decoder) {
196 assert(isUInt<5>(Imm) && "Invalid immediate");
197 Inst.addOperand(MCOperand::createImm(32 - Imm));
199}
200
201static int64_t TableB4const[16] = {-1, 1, 2, 3, 4, 5, 6, 7,
202 8, 10, 12, 16, 32, 64, 128, 256};
204 int64_t Address, const void *Decoder) {
205 assert(isUInt<4>(Imm) && "Invalid immediate");
206
209}
210
211static int64_t TableB4constu[16] = {32768, 65536, 2, 3, 4, 5, 6, 7,
212 8, 10, 12, 16, 32, 64, 128, 256};
214 int64_t Address,
215 const void *Decoder) {
216 assert(isUInt<4>(Imm) && "Invalid immediate");
217
220}
221
223 int64_t Address, const void *Decoder) {
224 assert(isUInt<12>(Imm) && "Invalid immediate");
225 DecodeARRegisterClass(Inst, Imm & 0xf, Address, Decoder);
226 Inst.addOperand(MCOperand::createImm((Imm >> 4) & 0xff));
228}
229
231 int64_t Address, const void *Decoder) {
232 assert(isUInt<12>(Imm) && "Invalid immediate");
233 DecodeARRegisterClass(Inst, Imm & 0xf, Address, Decoder);
234 Inst.addOperand(MCOperand::createImm((Imm >> 3) & 0x1fe));
236}
237
239 int64_t Address, const void *Decoder) {
240 assert(isUInt<12>(Imm) && "Invalid immediate");
241 DecodeARRegisterClass(Inst, Imm & 0xf, Address, Decoder);
242 Inst.addOperand(MCOperand::createImm((Imm >> 2) & 0x3fc));
244}
245
246/// Read three bytes from the ArrayRef and return 24 bit data
249 bool IsLittleEndian) {
250 // We want to read exactly 3 Bytes of data.
251 if (Bytes.size() < 3) {
252 Size = 0;
254 }
255
256 if (!IsLittleEndian) {
257 report_fatal_error("Big-endian mode currently is not supported!");
258 } else {
259 Insn = (Bytes[2] << 16) | (Bytes[1] << 8) | (Bytes[0] << 0);
260 }
261
262 Size = 3;
264}
265
266#include "XtensaGenDisassemblerTables.inc"
267
268DecodeStatus XtensaDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
269 ArrayRef<uint8_t> Bytes,
270 uint64_t Address,
271 raw_ostream &CS) const {
274
275 Result = readInstruction24(Bytes, Address, Size, Insn, IsLittleEndian);
276 if (Result == MCDisassembler::Fail)
278 LLVM_DEBUG(dbgs() << "Trying Xtensa 24-bit instruction table :\n");
279 Result = decodeInstruction(DecoderTable24, MI, Insn, Address, this, STI);
280 return Result;
281}
SmallVector< AArch64_IMM::ImmInsnModel, 4 > Insn
#define LLVM_EXTERNAL_VISIBILITY
Definition: Compiler.h:135
#define LLVM_DEBUG(X)
Definition: Debug.h:101
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]
LLVM_EXTERNAL_VISIBILITY void LLVMInitializeXtensaDisassembler()
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 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 readInstruction24(ArrayRef< uint8_t > Bytes, uint64_t Address, uint64_t &Size, uint32_t &Insn, bool IsLittleEndian)
Read three bytes from the ArrayRef and return 24 bit data.
static DecodeStatus decodeUimm5Operand(MCInst &Inst, uint64_t Imm, int64_t Address, const void *Decoder)
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:165
Context object for machine code objects.
Definition: MCContext.h:81
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:184
unsigned getOpcode() const
Definition: MCInst.h:198
void addOperand(const MCOperand Op)
Definition: MCInst.h:210
static MCOperand createReg(unsigned Reg)
Definition: MCInst.h:134
static MCOperand createImm(int64_t Val)
Definition: MCInst.h:141
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:456
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:156
Target & getTheXtensaTarget()
static void RegisterMCDisassembler(Target &T, Target::MCDisassemblerCtorTy Fn)
RegisterMCDisassembler - Register a MCDisassembler implementation for the given target.