Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/Target/Xtensa/Disassembler/XtensaDisassembler.cpp
35295 views
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
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"
25
26
using namespace llvm;
27
28
#define DEBUG_TYPE "Xtensa-disassembler"
29
30
using DecodeStatus = MCDisassembler::DecodeStatus;
31
32
namespace {
33
34
class XtensaDisassembler : public MCDisassembler {
35
bool IsLittleEndian;
36
37
public:
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
45
DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size,
46
ArrayRef<uint8_t> Bytes, uint64_t Address,
47
raw_ostream &CStream) const override;
48
};
49
} // end anonymous namespace
50
51
static MCDisassembler *createXtensaDisassembler(const Target &T,
52
const MCSubtargetInfo &STI,
53
MCContext &Ctx) {
54
return new XtensaDisassembler(STI, Ctx, true);
55
}
56
57
extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeXtensaDisassembler() {
58
TargetRegistry::RegisterMCDisassembler(getTheXtensaTarget(),
59
createXtensaDisassembler);
60
}
61
62
static 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
67
static DecodeStatus DecodeARRegisterClass(MCInst &Inst, uint64_t RegNo,
68
uint64_t Address,
69
const void *Decoder) {
70
if (RegNo >= std::size(ARDecoderTable))
71
return MCDisassembler::Fail;
72
73
unsigned Reg = ARDecoderTable[RegNo];
74
Inst.addOperand(MCOperand::createReg(Reg));
75
return MCDisassembler::Success;
76
}
77
78
static const unsigned SRDecoderTable[] = {Xtensa::SAR, 3};
79
80
static DecodeStatus DecodeSRRegisterClass(MCInst &Inst, uint64_t RegNo,
81
uint64_t Address,
82
const void *Decoder) {
83
if (RegNo > 255)
84
return MCDisassembler::Fail;
85
86
for (unsigned i = 0; i < std::size(SRDecoderTable); i += 2) {
87
if (SRDecoderTable[i + 1] == RegNo) {
88
unsigned Reg = SRDecoderTable[i];
89
Inst.addOperand(MCOperand::createReg(Reg));
90
return MCDisassembler::Success;
91
}
92
}
93
94
return MCDisassembler::Fail;
95
}
96
97
static 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
106
static DecodeStatus decodeCallOperand(MCInst &Inst, uint64_t Imm,
107
int64_t Address, const void *Decoder) {
108
assert(isUInt<18>(Imm) && "Invalid immediate");
109
Inst.addOperand(MCOperand::createImm(SignExtend64<20>(Imm << 2)));
110
return MCDisassembler::Success;
111
}
112
113
static DecodeStatus decodeJumpOperand(MCInst &Inst, uint64_t Imm,
114
int64_t Address, const void *Decoder) {
115
assert(isUInt<18>(Imm) && "Invalid immediate");
116
Inst.addOperand(MCOperand::createImm(SignExtend64<18>(Imm)));
117
return MCDisassembler::Success;
118
}
119
120
static DecodeStatus decodeBranchOperand(MCInst &Inst, uint64_t Imm,
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
}
138
return MCDisassembler::Success;
139
}
140
141
static DecodeStatus decodeL32ROperand(MCInst &Inst, uint64_t Imm,
142
int64_t Address, const void *Decoder) {
143
144
assert(isUInt<16>(Imm) && "Invalid immediate");
145
Inst.addOperand(MCOperand::createImm(
146
SignExtend64<17>((Imm << 2) + 0x40000 + (Address & 0x3))));
147
return MCDisassembler::Success;
148
}
149
150
static DecodeStatus decodeImm8Operand(MCInst &Inst, uint64_t Imm,
151
int64_t Address, const void *Decoder) {
152
assert(isUInt<8>(Imm) && "Invalid immediate");
153
Inst.addOperand(MCOperand::createImm(SignExtend64<8>(Imm)));
154
return MCDisassembler::Success;
155
}
156
157
static DecodeStatus decodeImm8_sh8Operand(MCInst &Inst, uint64_t Imm,
158
int64_t Address,
159
const void *Decoder) {
160
assert(isUInt<8>(Imm) && "Invalid immediate");
161
Inst.addOperand(MCOperand::createImm(SignExtend64<16>(Imm << 8)));
162
return MCDisassembler::Success;
163
}
164
165
static DecodeStatus decodeImm12Operand(MCInst &Inst, uint64_t Imm,
166
int64_t Address, const void *Decoder) {
167
assert(isUInt<12>(Imm) && "Invalid immediate");
168
Inst.addOperand(MCOperand::createImm(SignExtend64<12>(Imm)));
169
return MCDisassembler::Success;
170
}
171
172
static DecodeStatus decodeUimm4Operand(MCInst &Inst, uint64_t Imm,
173
int64_t Address, const void *Decoder) {
174
assert(isUInt<4>(Imm) && "Invalid immediate");
175
Inst.addOperand(MCOperand::createImm(Imm));
176
return MCDisassembler::Success;
177
}
178
179
static DecodeStatus decodeUimm5Operand(MCInst &Inst, uint64_t Imm,
180
int64_t Address, const void *Decoder) {
181
assert(isUInt<5>(Imm) && "Invalid immediate");
182
Inst.addOperand(MCOperand::createImm(Imm));
183
return MCDisassembler::Success;
184
}
185
186
static DecodeStatus decodeImm1_16Operand(MCInst &Inst, uint64_t Imm,
187
int64_t Address, const void *Decoder) {
188
assert(isUInt<4>(Imm) && "Invalid immediate");
189
Inst.addOperand(MCOperand::createImm(Imm + 1));
190
return MCDisassembler::Success;
191
}
192
193
static DecodeStatus decodeShimm1_31Operand(MCInst &Inst, uint64_t Imm,
194
int64_t Address,
195
const void *Decoder) {
196
assert(isUInt<5>(Imm) && "Invalid immediate");
197
Inst.addOperand(MCOperand::createImm(32 - Imm));
198
return MCDisassembler::Success;
199
}
200
201
static int64_t TableB4const[16] = {-1, 1, 2, 3, 4, 5, 6, 7,
202
8, 10, 12, 16, 32, 64, 128, 256};
203
static DecodeStatus decodeB4constOperand(MCInst &Inst, uint64_t Imm,
204
int64_t Address, const void *Decoder) {
205
assert(isUInt<4>(Imm) && "Invalid immediate");
206
207
Inst.addOperand(MCOperand::createImm(TableB4const[Imm]));
208
return MCDisassembler::Success;
209
}
210
211
static int64_t TableB4constu[16] = {32768, 65536, 2, 3, 4, 5, 6, 7,
212
8, 10, 12, 16, 32, 64, 128, 256};
213
static DecodeStatus decodeB4constuOperand(MCInst &Inst, uint64_t Imm,
214
int64_t Address,
215
const void *Decoder) {
216
assert(isUInt<4>(Imm) && "Invalid immediate");
217
218
Inst.addOperand(MCOperand::createImm(TableB4constu[Imm]));
219
return MCDisassembler::Success;
220
}
221
222
static DecodeStatus decodeMem8Operand(MCInst &Inst, uint64_t Imm,
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));
227
return MCDisassembler::Success;
228
}
229
230
static DecodeStatus decodeMem16Operand(MCInst &Inst, uint64_t Imm,
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));
235
return MCDisassembler::Success;
236
}
237
238
static DecodeStatus decodeMem32Operand(MCInst &Inst, uint64_t Imm,
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));
243
return MCDisassembler::Success;
244
}
245
246
/// Read three bytes from the ArrayRef and return 24 bit data
247
static DecodeStatus readInstruction24(ArrayRef<uint8_t> Bytes, uint64_t Address,
248
uint64_t &Size, uint32_t &Insn,
249
bool IsLittleEndian) {
250
// We want to read exactly 3 Bytes of data.
251
if (Bytes.size() < 3) {
252
Size = 0;
253
return MCDisassembler::Fail;
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;
263
return MCDisassembler::Success;
264
}
265
266
#include "XtensaGenDisassemblerTables.inc"
267
268
DecodeStatus XtensaDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
269
ArrayRef<uint8_t> Bytes,
270
uint64_t Address,
271
raw_ostream &CS) const {
272
uint32_t Insn;
273
DecodeStatus Result;
274
275
Result = readInstruction24(Bytes, Address, Size, Insn, IsLittleEndian);
276
if (Result == MCDisassembler::Fail)
277
return 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
}
282
283