LLVM 22.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"
18#include "llvm/MC/MCDecoder.h"
21#include "llvm/MC/MCInst.h"
25#include "llvm/Support/Endian.h"
26
27using namespace llvm;
28
29#define DEBUG_TYPE "Xtensa-disassembler"
30
32
33namespace {
34
35class XtensaDisassembler : public MCDisassembler {
36 bool IsLittleEndian;
37
38public:
39 XtensaDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx, bool isLE)
40 : MCDisassembler(STI, Ctx), IsLittleEndian(isLE) {}
41
42 bool hasDensity() const { return STI.hasFeature(Xtensa::FeatureDensity); }
43
46 raw_ostream &CStream) const override;
47};
48} // end anonymous namespace
49
51 const MCSubtargetInfo &STI,
52 MCContext &Ctx) {
53 return new XtensaDisassembler(STI, Ctx, true);
54}
55
59}
60
62 Xtensa::A0, Xtensa::SP, Xtensa::A2, Xtensa::A3, Xtensa::A4, Xtensa::A5,
63 Xtensa::A6, Xtensa::A7, Xtensa::A8, Xtensa::A9, Xtensa::A10, Xtensa::A11,
64 Xtensa::A12, Xtensa::A13, Xtensa::A14, Xtensa::A15};
65
67 uint64_t Address,
68 const void *Decoder) {
69 if (RegNo >= std::size(ARDecoderTable))
71
72 MCPhysReg Reg = ARDecoderTable[RegNo];
75}
76
78 uint64_t Address,
79 const void *Decoder) {
80 if (RegNo > 3)
82
83 MCPhysReg Reg = Xtensa::M0 + RegNo;
86}
87
89 uint64_t Address,
90 const void *Decoder) {
91 if (RegNo > 1)
93
94 MCPhysReg Reg = Xtensa::M0 + RegNo;
97}
98
100 uint64_t Address,
101 const void *Decoder) {
102 if (RegNo > 1)
104
105 MCPhysReg Reg = Xtensa::M2 + RegNo;
108}
109
111 uint64_t Address,
112 const void *Decoder) {
113 if (RegNo > 15)
115
116 MCPhysReg Reg = Xtensa::F0 + RegNo;
119}
120
122 uint64_t Address,
123 const MCDisassembler *Decoder) {
124 if (RegNo > 255)
126
127 Xtensa::RegisterAccessType RAType = Inst.getOpcode() == Xtensa::WUR
130
131 const XtensaDisassembler *Dis =
132 static_cast<const XtensaDisassembler *>(Decoder);
133 const MCRegisterInfo *MRI = Dis->getContext().getRegisterInfo();
136 RAType))
138
141}
142
146};
147
149 {Xtensa::LBEG, 0}, {Xtensa::LEND, 1},
150 {Xtensa::LCOUNT, 2}, {Xtensa::SAR, 3},
151 {Xtensa::BREG, 4}, {Xtensa::LITBASE, 5},
152 {Xtensa::SCOMPARE1, 12}, {Xtensa::ACCLO, 16},
153 {Xtensa::ACCHI, 17}, {Xtensa::M0, 32},
154 {Xtensa::M1, 33}, {Xtensa::M2, 34},
155 {Xtensa::M3, 35}, {Xtensa::WINDOWBASE, 72},
156 {Xtensa::WINDOWSTART, 73}, {Xtensa::IBREAKENABLE, 96},
157 {Xtensa::MEMCTL, 97}, {Xtensa::ATOMCTL, 99},
158 {Xtensa::DDR, 104}, {Xtensa::IBREAKA0, 128},
159 {Xtensa::IBREAKA1, 129}, {Xtensa::DBREAKA0, 144},
160 {Xtensa::DBREAKA1, 145}, {Xtensa::DBREAKC0, 160},
161 {Xtensa::DBREAKC1, 161}, {Xtensa::CONFIGID0, 176},
162 {Xtensa::EPC1, 177}, {Xtensa::EPC2, 178},
163 {Xtensa::EPC3, 179}, {Xtensa::EPC4, 180},
164 {Xtensa::EPC5, 181}, {Xtensa::EPC6, 182},
165 {Xtensa::EPC7, 183}, {Xtensa::DEPC, 192},
166 {Xtensa::EPS2, 194}, {Xtensa::EPS3, 195},
167 {Xtensa::EPS4, 196}, {Xtensa::EPS5, 197},
168 {Xtensa::EPS6, 198}, {Xtensa::EPS7, 199},
169 {Xtensa::CONFIGID1, 208}, {Xtensa::EXCSAVE1, 209},
170 {Xtensa::EXCSAVE2, 210}, {Xtensa::EXCSAVE3, 211},
171 {Xtensa::EXCSAVE4, 212}, {Xtensa::EXCSAVE5, 213},
172 {Xtensa::EXCSAVE6, 214}, {Xtensa::EXCSAVE7, 215},
173 {Xtensa::CPENABLE, 224}, {Xtensa::INTERRUPT, 226},
174 {Xtensa::INTCLEAR, 227}, {Xtensa::INTENABLE, 228},
175 {Xtensa::PS, 230}, {Xtensa::VECBASE, 231},
176 {Xtensa::EXCCAUSE, 232}, {Xtensa::DEBUGCAUSE, 233},
177 {Xtensa::CCOUNT, 234}, {Xtensa::PRID, 235},
178 {Xtensa::ICOUNT, 236}, {Xtensa::ICOUNTLEVEL, 237},
179 {Xtensa::EXCVADDR, 238}, {Xtensa::CCOMPARE0, 240},
180 {Xtensa::CCOMPARE1, 241}, {Xtensa::CCOMPARE2, 242},
181 {Xtensa::MISC0, 244}, {Xtensa::MISC1, 245},
182 {Xtensa::MISC2, 246}, {Xtensa::MISC3, 247}};
183
185 uint64_t Address,
186 const MCDisassembler *Decoder) {
187 if (RegNo > 255)
189
191 Inst.getOpcode() == Xtensa::WSR
193 : (Inst.getOpcode() == Xtensa::RSR ? Xtensa::REGISTER_READ
195
196 for (unsigned i = 0; i < std::size(SRDecoderTable); i++) {
197 if (SRDecoderTable[i].RegNo == RegNo) {
199
200 // Handle special case. The INTERRUPT/INTSET registers use the same
201 // encoding, but INTERRUPT used for read and INTSET for write.
202 if (Reg == Xtensa::INTERRUPT && RAType == Xtensa::REGISTER_WRITE) {
203 Reg = Xtensa::INTSET;
204 }
205
207 Reg, Decoder->getSubtargetInfo().getFeatureBits(), RAType))
209
212 }
213 }
214
216}
217
219 uint64_t Address,
220 const void *Decoder) {
221 if (RegNo > 15)
223
224 MCPhysReg Reg = Xtensa::B0 + RegNo;
227}
228
229static bool tryAddingSymbolicOperand(int64_t Value, bool isBranch,
230 uint64_t Address, uint64_t Offset,
231 uint64_t InstSize, MCInst &MI,
232 const void *Decoder) {
233 const MCDisassembler *Dis = static_cast<const MCDisassembler *>(Decoder);
235 /*OpSize=*/0, InstSize);
236}
237
239 int64_t Address, const void *Decoder) {
240 assert(isUInt<18>(Imm) && "Invalid immediate");
241 Inst.addOperand(
242 MCOperand::createImm(SignExtend64<20>(Imm << 2) + (Address & 0x3)));
244}
245
247 int64_t Address, const void *Decoder) {
248 assert(isUInt<18>(Imm) && "Invalid immediate");
249 Inst.addOperand(MCOperand::createImm(SignExtend64<18>(Imm)));
251}
252
254 int64_t Address, const void *Decoder) {
255 switch (Inst.getOpcode()) {
256 case Xtensa::BEQZ:
257 case Xtensa::BGEZ:
258 case Xtensa::BLTZ:
259 case Xtensa::BNEZ:
260 assert(isUInt<12>(Imm) && "Invalid immediate");
261 if (!tryAddingSymbolicOperand(SignExtend64<12>(Imm) + 4 + Address, true,
262 Address, 0, 3, Inst, Decoder))
263 Inst.addOperand(MCOperand::createImm(SignExtend64<12>(Imm)));
264 break;
265 default:
266 assert(isUInt<8>(Imm) && "Invalid immediate");
267 if (!tryAddingSymbolicOperand(SignExtend64<8>(Imm) + 4 + Address, true,
268 Address, 0, 3, Inst, Decoder))
269 Inst.addOperand(MCOperand::createImm(SignExtend64<8>(Imm)));
270 }
272}
273
275 int64_t Address, const void *Decoder) {
276
277 assert(isUInt<8>(Imm) && "Invalid immediate");
278 if (!tryAddingSymbolicOperand(Imm + 4 + Address, true, Address, 0, 3, Inst,
279 Decoder))
282}
283
285 int64_t Address, const void *Decoder) {
286
287 assert(isUInt<16>(Imm) && "Invalid immediate");
289 SignExtend64<17>((Imm << 2) + 0x40000 + (Address & 0x3))));
291}
292
294 int64_t Address, const void *Decoder) {
295 assert(isUInt<8>(Imm) && "Invalid immediate");
296 Inst.addOperand(MCOperand::createImm(SignExtend64<8>(Imm)));
298}
299
301 int64_t Address,
302 const void *Decoder) {
303 assert(isUInt<8>(Imm) && "Invalid immediate");
304 Inst.addOperand(MCOperand::createImm(SignExtend64<16>(Imm << 8)));
306}
307
309 int64_t Address, const void *Decoder) {
310 assert(isUInt<12>(Imm) && "Invalid immediate");
311 Inst.addOperand(MCOperand::createImm(SignExtend64<12>(Imm)));
313}
314
316 int64_t Address, const void *Decoder) {
317 assert(isUInt<4>(Imm) && "Invalid immediate");
320}
321
323 int64_t Address, const void *Decoder) {
324 assert(isUInt<5>(Imm) && "Invalid immediate");
327}
328
330 int64_t Address, const void *Decoder) {
331 assert(isUInt<4>(Imm) && "Invalid immediate");
332 Inst.addOperand(MCOperand::createImm(Imm + 1));
334}
335
337 int64_t Address,
338 const void *Decoder) {
339 assert(isUInt<4>(Imm) && "Invalid immediate");
340 if (!Imm)
342 else
345}
346
348 int64_t Address,
349 const void *Decoder) {
350 assert(isUInt<7>(Imm) && "Invalid immediate");
351 if ((Imm & 0x60) == 0x60)
352 Inst.addOperand(MCOperand::createImm((~0x1f) | Imm));
353 else
356}
357
359 int64_t Address, const void *Decoder) {
360 assert(isUInt<4>(Imm) && "Invalid immediate");
361 Inst.addOperand(MCOperand::createImm(Imm > 7 ? Imm - 16 : Imm));
363}
364
366 int64_t Address,
367 const void *Decoder) {
368 assert(isUInt<6>(Imm) && ((Imm & 0x3) == 0) && "Invalid immediate");
369 Inst.addOperand(MCOperand::createImm((~0x3f) | (Imm)));
371}
372
374 int64_t Address,
375 const void *Decoder) {
376 assert(isUInt<15>(Imm) && ((Imm & 0x7) == 0) && "Invalid immediate");
379}
380
382 int64_t Address,
383 const void *Decoder) {
384 assert(isUInt<5>(Imm) && "Invalid immediate");
385 Inst.addOperand(MCOperand::createImm(32 - Imm));
387}
388
389static int64_t TableB4const[16] = {-1, 1, 2, 3, 4, 5, 6, 7,
390 8, 10, 12, 16, 32, 64, 128, 256};
392 int64_t Address, const void *Decoder) {
393 assert(isUInt<4>(Imm) && "Invalid immediate");
394
397}
398
399static int64_t TableB4constu[16] = {32768, 65536, 2, 3, 4, 5, 6, 7,
400 8, 10, 12, 16, 32, 64, 128, 256};
402 int64_t Address,
403 const void *Decoder) {
404 assert(isUInt<4>(Imm) && "Invalid immediate");
405
408}
409
411 int64_t Address, const void *Decoder) {
412 assert(isUInt<4>(Imm) && "Invalid immediate");
413 Inst.addOperand(MCOperand::createImm(Imm + 7));
415}
416
418 int64_t Address, const void *Decoder) {
419 assert(isUInt<12>(Imm) && "Invalid immediate");
420 DecodeARRegisterClass(Inst, Imm & 0xf, Address, Decoder);
421 Inst.addOperand(MCOperand::createImm((Imm >> 4) & 0xff));
423}
424
426 int64_t Address, const void *Decoder) {
427 assert(isUInt<12>(Imm) && "Invalid immediate");
428 DecodeARRegisterClass(Inst, Imm & 0xf, Address, Decoder);
429 Inst.addOperand(MCOperand::createImm((Imm >> 3) & 0x1fe));
431}
432
434 int64_t Address, const void *Decoder) {
435 assert(isUInt<12>(Imm) && "Invalid immediate");
436 DecodeARRegisterClass(Inst, Imm & 0xf, Address, Decoder);
437 Inst.addOperand(MCOperand::createImm((Imm >> 2) & 0x3fc));
439}
440
442 int64_t Address, const void *Decoder) {
443 assert(isUInt<8>(Imm) && "Invalid immediate");
444 DecodeARRegisterClass(Inst, Imm & 0xf, Address, Decoder);
445 Inst.addOperand(MCOperand::createImm((Imm >> 2) & 0x3c));
447}
448
449/// Read two bytes from the ArrayRef and return 16 bit data sorted
450/// according to the given endianness.
452 uint64_t &Size, uint64_t &Insn,
453 bool IsLittleEndian) {
454 // We want to read exactly 2 Bytes of data.
455 if (Bytes.size() < 2) {
456 Size = 0;
458 }
459
460 if (!IsLittleEndian) {
461 report_fatal_error("Big-endian mode currently is not supported!");
462 } else {
463 Insn = (Bytes[1] << 8) | Bytes[0];
464 }
465
467}
468
469/// Read three bytes from the ArrayRef and return 24 bit data
471 uint64_t &Size, uint64_t &Insn,
472 bool IsLittleEndian) {
473 // We want to read exactly 3 Bytes of data.
474 if (Bytes.size() < 3) {
475 Size = 0;
477 }
478
479 if (!IsLittleEndian) {
480 report_fatal_error("Big-endian mode currently is not supported!");
481 } else {
482 Insn = (Bytes[2] << 16) | (Bytes[1] << 8) | (Bytes[0] << 0);
483 }
484
486}
487
488#include "XtensaGenDisassemblerTables.inc"
489
490DecodeStatus XtensaDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
491 ArrayRef<uint8_t> Bytes,
492 uint64_t Address,
493 raw_ostream &CS) const {
494 uint64_t Insn;
496
497 // Parse 16-bit instructions
498 if (hasDensity()) {
499 Result = readInstruction16(Bytes, Address, Size, Insn, IsLittleEndian);
500 if (Result == MCDisassembler::Fail)
502 LLVM_DEBUG(dbgs() << "Trying Xtensa 16-bit instruction table :\n");
503 Result = decodeInstruction(DecoderTable16, MI, Insn, Address, this, STI);
504 if (Result != MCDisassembler::Fail) {
505 Size = 2;
506 return Result;
507 }
508 }
509
510 // Parse Core 24-bit instructions
511 Result = readInstruction24(Bytes, Address, Size, Insn, IsLittleEndian);
512 if (Result == MCDisassembler::Fail)
514 LLVM_DEBUG(dbgs() << "Trying Xtensa 24-bit instruction table :\n");
515 Result = decodeInstruction(DecoderTable24, MI, Insn, Address, this, STI);
516 if (Result != MCDisassembler::Fail) {
517 Size = 3;
518 return Result;
519 }
520 return Result;
521}
unsigned const MachineRegisterInfo * MRI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
#define LLVM_EXTERNAL_VISIBILITY
Definition: Compiler.h:132
uint64_t Size
IRTranslator LLVM IR MI
static bool isBranch(unsigned Opcode)
#define LLVM_DEBUG(...)
Definition: Debug.h:119
static DecodeStatus decodeMem16Operand(MCInst &Inst, uint64_t Imm, int64_t Address, const void *Decoder)
static DecodeStatus DecodeMR23RegisterClass(MCInst &Inst, uint64_t RegNo, uint64_t Address, const void *Decoder)
static DecodeStatus DecodeMRRegisterClass(MCInst &Inst, uint64_t RegNo, uint64_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)
static DecodeStatus DecodeFPRRegisterClass(MCInst &Inst, uint64_t RegNo, uint64_t Address, const void *Decoder)
LLVM_EXTERNAL_VISIBILITY void LLVMInitializeXtensaDisassembler()
static DecodeStatus DecodeMR01RegisterClass(MCInst &Inst, uint64_t RegNo, uint64_t Address, const void *Decoder)
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)
const MCPhysReg ARDecoderTable[]
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 DecodeStatus DecodeURRegisterClass(MCInst &Inst, uint64_t RegNo, uint64_t Address, const MCDisassembler *Decoder)
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 decodeImm7_22Operand(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 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 DecodeBRRegisterClass(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 decodeLoopOperand(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)
const DecodeRegister SRDecoderTable[]
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:147
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:188
unsigned getOpcode() const
Definition: MCInst.h:202
void addOperand(const MCOperand Op)
Definition: MCInst.h:215
static MCOperand createReg(MCRegister Reg)
Definition: MCInst.h:138
static MCOperand createImm(int64_t Val)
Definition: MCInst.h:145
MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...
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:75
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:53
bool checkRegister(MCRegister RegNo, const FeatureBitset &FeatureBits, RegisterAccessType RA)
MCRegister getUserRegister(unsigned Code, const MCRegisterInfo &MRI)
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:477
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:207
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition: Error.cpp:167
Target & getTheXtensaTarget()
static void RegisterMCDisassembler(Target &T, Target::MCDisassemblerCtorTy Fn)
RegisterMCDisassembler - Register a MCDisassembler implementation for the given target.