[flang][cuda] Adding atomicadd as a cudadevice intrinsic and converting it LLVM diale...
[llvm-project.git] / llvm / lib / Target / Xtensa / Disassembler / XtensaDisassembler.cpp
blobc11c4b7038bdb7fd5c654b449a427392a4c20454
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 //===----------------------------------------------------------------------===//
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"
26 using namespace llvm;
28 #define DEBUG_TYPE "Xtensa-disassembler"
30 using DecodeStatus = MCDisassembler::DecodeStatus;
32 namespace {
34 class XtensaDisassembler : public MCDisassembler {
35 bool IsLittleEndian;
37 public:
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,
51 MCContext &Ctx) {
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,
66 uint64_t Address,
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,
79 uint64_t Address,
80 const void *Decoder) {
81 if (RegNo > 255)
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()) {
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)));
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,
156 int64_t Address,
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,
192 int64_t Address,
193 const void *Decoder) {
194 assert(isUInt<4>(Imm) && "Invalid immediate");
195 if (!Imm)
196 Inst.addOperand(MCOperand::createImm(-1));
197 else
198 Inst.addOperand(MCOperand::createImm(Imm));
199 return MCDisassembler::Success;
202 static DecodeStatus decodeImm32n_95Operand(MCInst &Inst, uint64_t Imm,
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
209 Inst.addOperand(MCOperand::createImm(Imm));
210 return MCDisassembler::Success;
213 static DecodeStatus decodeShimm1_31Operand(MCInst &Inst, uint64_t Imm,
214 int64_t Address,
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,
234 int64_t Address,
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) {
281 Size = 0;
282 return MCDisassembler::Fail;
285 if (!IsLittleEndian) {
286 report_fatal_error("Big-endian mode currently is not supported!");
287 } else {
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) {
300 Size = 0;
301 return MCDisassembler::Fail;
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);
310 return MCDisassembler::Success;
313 #include "XtensaGenDisassemblerTables.inc"
315 DecodeStatus XtensaDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
316 ArrayRef<uint8_t> Bytes,
317 uint64_t Address,
318 raw_ostream &CS) const {
319 uint64_t Insn;
320 DecodeStatus Result;
322 // Parse 16-bit instructions
323 if (hasDensity()) {
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) {
330 Size = 2;
331 return Result;
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) {
342 Size = 3;
343 return Result;
345 return Result;