1 //===-- XtensaDisassembler.cpp - Disassembler for Xtensa ------------------===//
3 // The LLVM Compiler Infrastructure
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
9 //===----------------------------------------------------------------------===//
11 // This file implements the XtensaDisassembler class.
13 //===----------------------------------------------------------------------===//
15 #include "MCTargetDesc/XtensaMCTargetDesc.h"
16 #include "TargetInfo/XtensaTargetInfo.h"
17 #include "llvm/MC/MCContext.h"
18 #include "llvm/MC/MCDecoderOps.h"
19 #include "llvm/MC/MCDisassembler/MCDisassembler.h"
20 #include "llvm/MC/MCInst.h"
21 #include "llvm/MC/MCRegisterInfo.h"
22 #include "llvm/MC/MCSubtargetInfo.h"
23 #include "llvm/MC/TargetRegistry.h"
24 #include "llvm/Support/Endian.h"
28 #define DEBUG_TYPE "Xtensa-disassembler"
30 using DecodeStatus
= MCDisassembler::DecodeStatus
;
34 class XtensaDisassembler
: public MCDisassembler
{
38 XtensaDisassembler(const MCSubtargetInfo
&STI
, MCContext
&Ctx
, bool isLE
)
39 : MCDisassembler(STI
, Ctx
), IsLittleEndian(isLE
) {}
41 bool hasDensity() const { return STI
.hasFeature(Xtensa::FeatureDensity
); }
43 DecodeStatus
getInstruction(MCInst
&Instr
, uint64_t &Size
,
44 ArrayRef
<uint8_t> Bytes
, uint64_t Address
,
45 raw_ostream
&CStream
) const override
;
47 } // end anonymous namespace
49 static MCDisassembler
*createXtensaDisassembler(const Target
&T
,
50 const MCSubtargetInfo
&STI
,
52 return new XtensaDisassembler(STI
, Ctx
, true);
55 extern "C" LLVM_EXTERNAL_VISIBILITY
void LLVMInitializeXtensaDisassembler() {
56 TargetRegistry::RegisterMCDisassembler(getTheXtensaTarget(),
57 createXtensaDisassembler
);
60 static 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
};
65 static DecodeStatus
DecodeARRegisterClass(MCInst
&Inst
, uint64_t RegNo
,
67 const void *Decoder
) {
68 if (RegNo
>= std::size(ARDecoderTable
))
69 return MCDisassembler::Fail
;
71 unsigned Reg
= ARDecoderTable
[RegNo
];
72 Inst
.addOperand(MCOperand::createReg(Reg
));
73 return MCDisassembler::Success
;
76 static const unsigned SRDecoderTable
[] = {Xtensa::SAR
, 3};
78 static DecodeStatus
DecodeSRRegisterClass(MCInst
&Inst
, uint64_t RegNo
,
80 const void *Decoder
) {
82 return MCDisassembler::Fail
;
84 for (unsigned i
= 0; i
< std::size(SRDecoderTable
); i
+= 2) {
85 if (SRDecoderTable
[i
+ 1] == RegNo
) {
86 unsigned Reg
= SRDecoderTable
[i
];
87 Inst
.addOperand(MCOperand::createReg(Reg
));
88 return MCDisassembler::Success
;
92 return MCDisassembler::Fail
;
95 static 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
);
100 return Dis
->tryAddingSymbolicOperand(MI
, Value
, Address
, isBranch
, Offset
,
101 /*OpSize=*/0, InstSize
);
104 static DecodeStatus
decodeCallOperand(MCInst
&Inst
, uint64_t Imm
,
105 int64_t Address
, const void *Decoder
) {
106 assert(isUInt
<18>(Imm
) && "Invalid immediate");
107 Inst
.addOperand(MCOperand::createImm(SignExtend64
<20>(Imm
<< 2)));
108 return MCDisassembler::Success
;
111 static DecodeStatus
decodeJumpOperand(MCInst
&Inst
, uint64_t Imm
,
112 int64_t Address
, const void *Decoder
) {
113 assert(isUInt
<18>(Imm
) && "Invalid immediate");
114 Inst
.addOperand(MCOperand::createImm(SignExtend64
<18>(Imm
)));
115 return MCDisassembler::Success
;
118 static DecodeStatus
decodeBranchOperand(MCInst
&Inst
, uint64_t Imm
,
119 int64_t Address
, const void *Decoder
) {
120 switch (Inst
.getOpcode()) {
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
)));
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
)));
136 return MCDisassembler::Success
;
139 static DecodeStatus
decodeL32ROperand(MCInst
&Inst
, uint64_t Imm
,
140 int64_t Address
, const void *Decoder
) {
142 assert(isUInt
<16>(Imm
) && "Invalid immediate");
143 Inst
.addOperand(MCOperand::createImm(
144 SignExtend64
<17>((Imm
<< 2) + 0x40000 + (Address
& 0x3))));
145 return MCDisassembler::Success
;
148 static DecodeStatus
decodeImm8Operand(MCInst
&Inst
, uint64_t Imm
,
149 int64_t Address
, const void *Decoder
) {
150 assert(isUInt
<8>(Imm
) && "Invalid immediate");
151 Inst
.addOperand(MCOperand::createImm(SignExtend64
<8>(Imm
)));
152 return MCDisassembler::Success
;
155 static DecodeStatus
decodeImm8_sh8Operand(MCInst
&Inst
, uint64_t Imm
,
157 const void *Decoder
) {
158 assert(isUInt
<8>(Imm
) && "Invalid immediate");
159 Inst
.addOperand(MCOperand::createImm(SignExtend64
<16>(Imm
<< 8)));
160 return MCDisassembler::Success
;
163 static DecodeStatus
decodeImm12Operand(MCInst
&Inst
, uint64_t Imm
,
164 int64_t Address
, const void *Decoder
) {
165 assert(isUInt
<12>(Imm
) && "Invalid immediate");
166 Inst
.addOperand(MCOperand::createImm(SignExtend64
<12>(Imm
)));
167 return MCDisassembler::Success
;
170 static DecodeStatus
decodeUimm4Operand(MCInst
&Inst
, uint64_t Imm
,
171 int64_t Address
, const void *Decoder
) {
172 assert(isUInt
<4>(Imm
) && "Invalid immediate");
173 Inst
.addOperand(MCOperand::createImm(Imm
));
174 return MCDisassembler::Success
;
177 static DecodeStatus
decodeUimm5Operand(MCInst
&Inst
, uint64_t Imm
,
178 int64_t Address
, const void *Decoder
) {
179 assert(isUInt
<5>(Imm
) && "Invalid immediate");
180 Inst
.addOperand(MCOperand::createImm(Imm
));
181 return MCDisassembler::Success
;
184 static DecodeStatus
decodeImm1_16Operand(MCInst
&Inst
, uint64_t Imm
,
185 int64_t Address
, const void *Decoder
) {
186 assert(isUInt
<4>(Imm
) && "Invalid immediate");
187 Inst
.addOperand(MCOperand::createImm(Imm
+ 1));
188 return MCDisassembler::Success
;
191 static DecodeStatus
decodeImm1n_15Operand(MCInst
&Inst
, uint64_t Imm
,
193 const void *Decoder
) {
194 assert(isUInt
<4>(Imm
) && "Invalid immediate");
196 Inst
.addOperand(MCOperand::createImm(-1));
198 Inst
.addOperand(MCOperand::createImm(Imm
));
199 return MCDisassembler::Success
;
202 static DecodeStatus
decodeImm32n_95Operand(MCInst
&Inst
, uint64_t Imm
,
204 const void *Decoder
) {
205 assert(isUInt
<7>(Imm
) && "Invalid immediate");
206 if ((Imm
& 0x60) == 0x60)
207 Inst
.addOperand(MCOperand::createImm((~0x1f) | Imm
));
209 Inst
.addOperand(MCOperand::createImm(Imm
));
210 return MCDisassembler::Success
;
213 static DecodeStatus
decodeShimm1_31Operand(MCInst
&Inst
, uint64_t Imm
,
215 const void *Decoder
) {
216 assert(isUInt
<5>(Imm
) && "Invalid immediate");
217 Inst
.addOperand(MCOperand::createImm(32 - Imm
));
218 return MCDisassembler::Success
;
221 static int64_t TableB4const
[16] = {-1, 1, 2, 3, 4, 5, 6, 7,
222 8, 10, 12, 16, 32, 64, 128, 256};
223 static DecodeStatus
decodeB4constOperand(MCInst
&Inst
, uint64_t Imm
,
224 int64_t Address
, const void *Decoder
) {
225 assert(isUInt
<4>(Imm
) && "Invalid immediate");
227 Inst
.addOperand(MCOperand::createImm(TableB4const
[Imm
]));
228 return MCDisassembler::Success
;
231 static int64_t TableB4constu
[16] = {32768, 65536, 2, 3, 4, 5, 6, 7,
232 8, 10, 12, 16, 32, 64, 128, 256};
233 static DecodeStatus
decodeB4constuOperand(MCInst
&Inst
, uint64_t Imm
,
235 const void *Decoder
) {
236 assert(isUInt
<4>(Imm
) && "Invalid immediate");
238 Inst
.addOperand(MCOperand::createImm(TableB4constu
[Imm
]));
239 return MCDisassembler::Success
;
242 static DecodeStatus
decodeMem8Operand(MCInst
&Inst
, uint64_t Imm
,
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));
247 return MCDisassembler::Success
;
250 static DecodeStatus
decodeMem16Operand(MCInst
&Inst
, uint64_t Imm
,
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));
255 return MCDisassembler::Success
;
258 static DecodeStatus
decodeMem32Operand(MCInst
&Inst
, uint64_t Imm
,
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));
263 return MCDisassembler::Success
;
266 static DecodeStatus
decodeMem32nOperand(MCInst
&Inst
, uint64_t Imm
,
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));
271 return MCDisassembler::Success
;
274 /// Read two bytes from the ArrayRef and return 16 bit data sorted
275 /// according to the given endianness.
276 static DecodeStatus
readInstruction16(ArrayRef
<uint8_t> Bytes
, uint64_t Address
,
277 uint64_t &Size
, uint64_t &Insn
,
278 bool IsLittleEndian
) {
279 // We want to read exactly 2 Bytes of data.
280 if (Bytes
.size() < 2) {
282 return MCDisassembler::Fail
;
285 if (!IsLittleEndian
) {
286 report_fatal_error("Big-endian mode currently is not supported!");
288 Insn
= (Bytes
[1] << 8) | Bytes
[0];
291 return MCDisassembler::Success
;
294 /// Read three bytes from the ArrayRef and return 24 bit data
295 static DecodeStatus
readInstruction24(ArrayRef
<uint8_t> Bytes
, uint64_t Address
,
296 uint64_t &Size
, uint64_t &Insn
,
297 bool IsLittleEndian
) {
298 // We want to read exactly 3 Bytes of data.
299 if (Bytes
.size() < 3) {
301 return MCDisassembler::Fail
;
304 if (!IsLittleEndian
) {
305 report_fatal_error("Big-endian mode currently is not supported!");
307 Insn
= (Bytes
[2] << 16) | (Bytes
[1] << 8) | (Bytes
[0] << 0);
310 return MCDisassembler::Success
;
313 #include "XtensaGenDisassemblerTables.inc"
315 DecodeStatus
XtensaDisassembler::getInstruction(MCInst
&MI
, uint64_t &Size
,
316 ArrayRef
<uint8_t> Bytes
,
318 raw_ostream
&CS
) const {
322 // Parse 16-bit instructions
324 Result
= readInstruction16(Bytes
, Address
, Size
, Insn
, IsLittleEndian
);
325 if (Result
== MCDisassembler::Fail
)
326 return 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
) {
335 // Parse Core 24-bit instructions
336 Result
= readInstruction24(Bytes
, Address
, Size
, Insn
, IsLittleEndian
);
337 if (Result
== MCDisassembler::Fail
)
338 return 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
) {