xref: /freebsd/contrib/llvm-project/llvm/lib/Target/Xtensa/Disassembler/XtensaDisassembler.cpp (revision 700637cbb5e582861067a11aaca4d053546871d2)
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:
XtensaDisassembler(const MCSubtargetInfo & STI,MCContext & Ctx,bool isLE)38   XtensaDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx, bool isLE)
39       : MCDisassembler(STI, Ctx), IsLittleEndian(isLE) {}
40 
hasDensity() const41   bool hasDensity() const { return STI.hasFeature(Xtensa::FeatureDensity); }
42 
43   DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size,
44                               ArrayRef<uint8_t> Bytes, uint64_t Address,
45                               raw_ostream &CStream) const override;
46 };
47 } // end anonymous namespace
48 
createXtensaDisassembler(const Target & T,const MCSubtargetInfo & STI,MCContext & Ctx)49 static MCDisassembler *createXtensaDisassembler(const Target &T,
50                                                 const MCSubtargetInfo &STI,
51                                                 MCContext &Ctx) {
52   return new XtensaDisassembler(STI, Ctx, true);
53 }
54 
LLVMInitializeXtensaDisassembler()55 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeXtensaDisassembler() {
56   TargetRegistry::RegisterMCDisassembler(getTheXtensaTarget(),
57                                          createXtensaDisassembler);
58 }
59 
60 const MCPhysReg 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};
64 
DecodeARRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const void * Decoder)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;
70 
71   MCPhysReg Reg = ARDecoderTable[RegNo];
72   Inst.addOperand(MCOperand::createReg(Reg));
73   return MCDisassembler::Success;
74 }
75 
DecodeMRRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const void * Decoder)76 static DecodeStatus DecodeMRRegisterClass(MCInst &Inst, uint64_t RegNo,
77                                           uint64_t Address,
78                                           const void *Decoder) {
79   if (RegNo > 3)
80     return MCDisassembler::Fail;
81 
82   MCPhysReg Reg = Xtensa::M0 + RegNo;
83   Inst.addOperand(MCOperand::createReg(Reg));
84   return MCDisassembler::Success;
85 }
86 
DecodeMR01RegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const void * Decoder)87 static DecodeStatus DecodeMR01RegisterClass(MCInst &Inst, uint64_t RegNo,
88                                             uint64_t Address,
89                                             const void *Decoder) {
90   if (RegNo > 1)
91     return MCDisassembler::Fail;
92 
93   MCPhysReg Reg = Xtensa::M0 + RegNo;
94   Inst.addOperand(MCOperand::createReg(Reg));
95   return MCDisassembler::Success;
96 }
97 
DecodeMR23RegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const void * Decoder)98 static DecodeStatus DecodeMR23RegisterClass(MCInst &Inst, uint64_t RegNo,
99                                             uint64_t Address,
100                                             const void *Decoder) {
101   if (RegNo > 1)
102     return MCDisassembler::Fail;
103 
104   MCPhysReg Reg = Xtensa::M2 + RegNo;
105   Inst.addOperand(MCOperand::createReg(Reg));
106   return MCDisassembler::Success;
107 }
108 
DecodeFPRRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const void * Decoder)109 static DecodeStatus DecodeFPRRegisterClass(MCInst &Inst, uint64_t RegNo,
110                                            uint64_t Address,
111                                            const void *Decoder) {
112   if (RegNo > 15)
113     return MCDisassembler::Fail;
114 
115   MCPhysReg Reg = Xtensa::F0 + RegNo;
116   Inst.addOperand(MCOperand::createReg(Reg));
117   return MCDisassembler::Success;
118 }
119 
DecodeURRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)120 static DecodeStatus DecodeURRegisterClass(MCInst &Inst, uint64_t RegNo,
121                                           uint64_t Address,
122                                           const MCDisassembler *Decoder) {
123   if (RegNo > 255)
124     return MCDisassembler::Fail;
125 
126   Xtensa::RegisterAccessType RAType = Inst.getOpcode() == Xtensa::WUR
127                                           ? Xtensa::REGISTER_WRITE
128                                           : Xtensa::REGISTER_READ;
129 
130   const XtensaDisassembler *Dis =
131       static_cast<const XtensaDisassembler *>(Decoder);
132   const MCRegisterInfo *MRI = Dis->getContext().getRegisterInfo();
133   MCPhysReg Reg = Xtensa::getUserRegister(RegNo, *MRI);
134   if (!Xtensa::checkRegister(Reg, Decoder->getSubtargetInfo().getFeatureBits(),
135                              RAType))
136     return MCDisassembler::Fail;
137 
138   Inst.addOperand(MCOperand::createReg(Reg));
139   return MCDisassembler::Success;
140 }
141 
142 struct DecodeRegister {
143   MCPhysReg Reg;
144   uint32_t RegNo;
145 };
146 
147 const DecodeRegister SRDecoderTable[] = {
148     {Xtensa::LBEG, 0},          {Xtensa::LEND, 1},
149     {Xtensa::LCOUNT, 2},        {Xtensa::SAR, 3},
150     {Xtensa::BREG, 4},          {Xtensa::LITBASE, 5},
151     {Xtensa::ACCLO, 16},        {Xtensa::ACCHI, 17},
152     {Xtensa::M0, 32},           {Xtensa::M1, 33},
153     {Xtensa::M2, 34},           {Xtensa::M3, 35},
154     {Xtensa::WINDOWBASE, 72},   {Xtensa::WINDOWSTART, 73},
155     {Xtensa::IBREAKENABLE, 96}, {Xtensa::MEMCTL, 97},
156     {Xtensa::DDR, 104},         {Xtensa::IBREAKA0, 128},
157     {Xtensa::IBREAKA1, 129},    {Xtensa::DBREAKA0, 144},
158     {Xtensa::DBREAKA1, 145},    {Xtensa::DBREAKC0, 160},
159     {Xtensa::DBREAKC1, 161},    {Xtensa::CONFIGID0, 176},
160     {Xtensa::EPC1, 177},        {Xtensa::EPC2, 178},
161     {Xtensa::EPC3, 179},        {Xtensa::EPC4, 180},
162     {Xtensa::EPC5, 181},        {Xtensa::EPC6, 182},
163     {Xtensa::EPC7, 183},        {Xtensa::DEPC, 192},
164     {Xtensa::EPS2, 194},        {Xtensa::EPS3, 195},
165     {Xtensa::EPS4, 196},        {Xtensa::EPS5, 197},
166     {Xtensa::EPS6, 198},        {Xtensa::EPS7, 199},
167     {Xtensa::CONFIGID1, 208},   {Xtensa::EXCSAVE1, 209},
168     {Xtensa::EXCSAVE2, 210},    {Xtensa::EXCSAVE3, 211},
169     {Xtensa::EXCSAVE4, 212},    {Xtensa::EXCSAVE5, 213},
170     {Xtensa::EXCSAVE6, 214},    {Xtensa::EXCSAVE7, 215},
171     {Xtensa::CPENABLE, 224},    {Xtensa::INTERRUPT, 226},
172     {Xtensa::INTCLEAR, 227},    {Xtensa::INTENABLE, 228},
173     {Xtensa::PS, 230},          {Xtensa::VECBASE, 231},
174     {Xtensa::EXCCAUSE, 232},    {Xtensa::DEBUGCAUSE, 233},
175     {Xtensa::CCOUNT, 234},      {Xtensa::PRID, 235},
176     {Xtensa::ICOUNT, 236},      {Xtensa::ICOUNTLEVEL, 237},
177     {Xtensa::EXCVADDR, 238},    {Xtensa::CCOMPARE0, 240},
178     {Xtensa::CCOMPARE1, 241},   {Xtensa::CCOMPARE2, 242},
179     {Xtensa::MISC0, 244},       {Xtensa::MISC1, 245},
180     {Xtensa::MISC2, 246},       {Xtensa::MISC3, 247}};
181 
DecodeSRRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)182 static DecodeStatus DecodeSRRegisterClass(MCInst &Inst, uint64_t RegNo,
183                                           uint64_t Address,
184                                           const MCDisassembler *Decoder) {
185   if (RegNo > 255)
186     return MCDisassembler::Fail;
187 
188   Xtensa::RegisterAccessType RAType =
189       Inst.getOpcode() == Xtensa::WSR
190           ? Xtensa::REGISTER_WRITE
191           : (Inst.getOpcode() == Xtensa::RSR ? Xtensa::REGISTER_READ
192                                              : Xtensa::REGISTER_EXCHANGE);
193 
194   for (unsigned i = 0; i < std::size(SRDecoderTable); i++) {
195     if (SRDecoderTable[i].RegNo == RegNo) {
196       MCPhysReg Reg = SRDecoderTable[i].Reg;
197 
198       // Handle special case. The INTERRUPT/INTSET registers use the same
199       // encoding, but INTERRUPT used for read and INTSET for write.
200       if (Reg == Xtensa::INTERRUPT && RAType == Xtensa::REGISTER_WRITE) {
201         Reg = Xtensa::INTSET;
202       }
203 
204       if (!Xtensa::checkRegister(
205               Reg, Decoder->getSubtargetInfo().getFeatureBits(), RAType))
206         return MCDisassembler::Fail;
207 
208       Inst.addOperand(MCOperand::createReg(Reg));
209       return MCDisassembler::Success;
210     }
211   }
212 
213   return MCDisassembler::Fail;
214 }
215 
DecodeBRRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const void * Decoder)216 static DecodeStatus DecodeBRRegisterClass(MCInst &Inst, uint64_t RegNo,
217                                           uint64_t Address,
218                                           const void *Decoder) {
219   if (RegNo > 15)
220     return MCDisassembler::Fail;
221 
222   MCPhysReg Reg = Xtensa::B0 + RegNo;
223   Inst.addOperand(MCOperand::createReg(Reg));
224   return MCDisassembler::Success;
225 }
226 
tryAddingSymbolicOperand(int64_t Value,bool isBranch,uint64_t Address,uint64_t Offset,uint64_t InstSize,MCInst & MI,const void * Decoder)227 static bool tryAddingSymbolicOperand(int64_t Value, bool isBranch,
228                                      uint64_t Address, uint64_t Offset,
229                                      uint64_t InstSize, MCInst &MI,
230                                      const void *Decoder) {
231   const MCDisassembler *Dis = static_cast<const MCDisassembler *>(Decoder);
232   return Dis->tryAddingSymbolicOperand(MI, Value, Address, isBranch, Offset,
233                                        /*OpSize=*/0, InstSize);
234 }
235 
decodeCallOperand(MCInst & Inst,uint64_t Imm,int64_t Address,const void * Decoder)236 static DecodeStatus decodeCallOperand(MCInst &Inst, uint64_t Imm,
237                                       int64_t Address, const void *Decoder) {
238   assert(isUInt<18>(Imm) && "Invalid immediate");
239   Inst.addOperand(
240       MCOperand::createImm(SignExtend64<20>(Imm << 2) + (Address & 0x3)));
241   return MCDisassembler::Success;
242 }
243 
decodeJumpOperand(MCInst & Inst,uint64_t Imm,int64_t Address,const void * Decoder)244 static DecodeStatus decodeJumpOperand(MCInst &Inst, uint64_t Imm,
245                                       int64_t Address, const void *Decoder) {
246   assert(isUInt<18>(Imm) && "Invalid immediate");
247   Inst.addOperand(MCOperand::createImm(SignExtend64<18>(Imm)));
248   return MCDisassembler::Success;
249 }
250 
decodeBranchOperand(MCInst & Inst,uint64_t Imm,int64_t Address,const void * Decoder)251 static DecodeStatus decodeBranchOperand(MCInst &Inst, uint64_t Imm,
252                                         int64_t Address, const void *Decoder) {
253   switch (Inst.getOpcode()) {
254   case Xtensa::BEQZ:
255   case Xtensa::BGEZ:
256   case Xtensa::BLTZ:
257   case Xtensa::BNEZ:
258     assert(isUInt<12>(Imm) && "Invalid immediate");
259     if (!tryAddingSymbolicOperand(SignExtend64<12>(Imm) + 4 + Address, true,
260                                   Address, 0, 3, Inst, Decoder))
261       Inst.addOperand(MCOperand::createImm(SignExtend64<12>(Imm)));
262     break;
263   default:
264     assert(isUInt<8>(Imm) && "Invalid immediate");
265     if (!tryAddingSymbolicOperand(SignExtend64<8>(Imm) + 4 + Address, true,
266                                   Address, 0, 3, Inst, Decoder))
267       Inst.addOperand(MCOperand::createImm(SignExtend64<8>(Imm)));
268   }
269   return MCDisassembler::Success;
270 }
271 
decodeLoopOperand(MCInst & Inst,uint64_t Imm,int64_t Address,const void * Decoder)272 static DecodeStatus decodeLoopOperand(MCInst &Inst, uint64_t Imm,
273                                       int64_t Address, const void *Decoder) {
274 
275   assert(isUInt<8>(Imm) && "Invalid immediate");
276   if (!tryAddingSymbolicOperand(Imm + 4 + Address, true, Address, 0, 3, Inst,
277                                 Decoder))
278     Inst.addOperand(MCOperand::createImm(Imm));
279   return MCDisassembler::Success;
280 }
281 
decodeL32ROperand(MCInst & Inst,uint64_t Imm,int64_t Address,const void * Decoder)282 static DecodeStatus decodeL32ROperand(MCInst &Inst, uint64_t Imm,
283                                       int64_t Address, const void *Decoder) {
284 
285   assert(isUInt<16>(Imm) && "Invalid immediate");
286   Inst.addOperand(MCOperand::createImm(
287       SignExtend64<17>((Imm << 2) + 0x40000 + (Address & 0x3))));
288   return MCDisassembler::Success;
289 }
290 
decodeImm8Operand(MCInst & Inst,uint64_t Imm,int64_t Address,const void * Decoder)291 static DecodeStatus decodeImm8Operand(MCInst &Inst, uint64_t Imm,
292                                       int64_t Address, const void *Decoder) {
293   assert(isUInt<8>(Imm) && "Invalid immediate");
294   Inst.addOperand(MCOperand::createImm(SignExtend64<8>(Imm)));
295   return MCDisassembler::Success;
296 }
297 
decodeImm8_sh8Operand(MCInst & Inst,uint64_t Imm,int64_t Address,const void * Decoder)298 static DecodeStatus decodeImm8_sh8Operand(MCInst &Inst, uint64_t Imm,
299                                           int64_t Address,
300                                           const void *Decoder) {
301   assert(isUInt<8>(Imm) && "Invalid immediate");
302   Inst.addOperand(MCOperand::createImm(SignExtend64<16>(Imm << 8)));
303   return MCDisassembler::Success;
304 }
305 
decodeImm12Operand(MCInst & Inst,uint64_t Imm,int64_t Address,const void * Decoder)306 static DecodeStatus decodeImm12Operand(MCInst &Inst, uint64_t Imm,
307                                        int64_t Address, const void *Decoder) {
308   assert(isUInt<12>(Imm) && "Invalid immediate");
309   Inst.addOperand(MCOperand::createImm(SignExtend64<12>(Imm)));
310   return MCDisassembler::Success;
311 }
312 
decodeUimm4Operand(MCInst & Inst,uint64_t Imm,int64_t Address,const void * Decoder)313 static DecodeStatus decodeUimm4Operand(MCInst &Inst, uint64_t Imm,
314                                        int64_t Address, const void *Decoder) {
315   assert(isUInt<4>(Imm) && "Invalid immediate");
316   Inst.addOperand(MCOperand::createImm(Imm));
317   return MCDisassembler::Success;
318 }
319 
decodeUimm5Operand(MCInst & Inst,uint64_t Imm,int64_t Address,const void * Decoder)320 static DecodeStatus decodeUimm5Operand(MCInst &Inst, uint64_t Imm,
321                                        int64_t Address, const void *Decoder) {
322   assert(isUInt<5>(Imm) && "Invalid immediate");
323   Inst.addOperand(MCOperand::createImm(Imm));
324   return MCDisassembler::Success;
325 }
326 
decodeImm1_16Operand(MCInst & Inst,uint64_t Imm,int64_t Address,const void * Decoder)327 static DecodeStatus decodeImm1_16Operand(MCInst &Inst, uint64_t Imm,
328                                          int64_t Address, const void *Decoder) {
329   assert(isUInt<4>(Imm) && "Invalid immediate");
330   Inst.addOperand(MCOperand::createImm(Imm + 1));
331   return MCDisassembler::Success;
332 }
333 
decodeImm1n_15Operand(MCInst & Inst,uint64_t Imm,int64_t Address,const void * Decoder)334 static DecodeStatus decodeImm1n_15Operand(MCInst &Inst, uint64_t Imm,
335                                           int64_t Address,
336                                           const void *Decoder) {
337   assert(isUInt<4>(Imm) && "Invalid immediate");
338   if (!Imm)
339     Inst.addOperand(MCOperand::createImm(-1));
340   else
341     Inst.addOperand(MCOperand::createImm(Imm));
342   return MCDisassembler::Success;
343 }
344 
decodeImm32n_95Operand(MCInst & Inst,uint64_t Imm,int64_t Address,const void * Decoder)345 static DecodeStatus decodeImm32n_95Operand(MCInst &Inst, uint64_t Imm,
346                                            int64_t Address,
347                                            const void *Decoder) {
348   assert(isUInt<7>(Imm) && "Invalid immediate");
349   if ((Imm & 0x60) == 0x60)
350     Inst.addOperand(MCOperand::createImm((~0x1f) | Imm));
351   else
352     Inst.addOperand(MCOperand::createImm(Imm));
353   return MCDisassembler::Success;
354 }
355 
decodeImm8n_7Operand(MCInst & Inst,uint64_t Imm,int64_t Address,const void * Decoder)356 static DecodeStatus decodeImm8n_7Operand(MCInst &Inst, uint64_t Imm,
357                                          int64_t Address, const void *Decoder) {
358   assert(isUInt<4>(Imm) && "Invalid immediate");
359   Inst.addOperand(MCOperand::createImm(Imm > 7 ? Imm - 16 : Imm));
360   return MCDisassembler::Success;
361 }
362 
decodeImm64n_4nOperand(MCInst & Inst,uint64_t Imm,int64_t Address,const void * Decoder)363 static DecodeStatus decodeImm64n_4nOperand(MCInst &Inst, uint64_t Imm,
364                                            int64_t Address,
365                                            const void *Decoder) {
366   assert(isUInt<6>(Imm) && ((Imm & 0x3) == 0) && "Invalid immediate");
367   Inst.addOperand(MCOperand::createImm((~0x3f) | (Imm)));
368   return MCDisassembler::Success;
369 }
370 
decodeEntry_Imm12OpValue(MCInst & Inst,uint64_t Imm,int64_t Address,const void * Decoder)371 static DecodeStatus decodeEntry_Imm12OpValue(MCInst &Inst, uint64_t Imm,
372                                              int64_t Address,
373                                              const void *Decoder) {
374   assert(isUInt<15>(Imm) && ((Imm & 0x7) == 0) && "Invalid immediate");
375   Inst.addOperand(MCOperand::createImm(Imm));
376   return MCDisassembler::Success;
377 }
378 
decodeShimm1_31Operand(MCInst & Inst,uint64_t Imm,int64_t Address,const void * Decoder)379 static DecodeStatus decodeShimm1_31Operand(MCInst &Inst, uint64_t Imm,
380                                            int64_t Address,
381                                            const void *Decoder) {
382   assert(isUInt<5>(Imm) && "Invalid immediate");
383   Inst.addOperand(MCOperand::createImm(32 - Imm));
384   return MCDisassembler::Success;
385 }
386 
387 static int64_t TableB4const[16] = {-1, 1,  2,  3,  4,  5,  6,   7,
388                                    8,  10, 12, 16, 32, 64, 128, 256};
decodeB4constOperand(MCInst & Inst,uint64_t Imm,int64_t Address,const void * Decoder)389 static DecodeStatus decodeB4constOperand(MCInst &Inst, uint64_t Imm,
390                                          int64_t Address, const void *Decoder) {
391   assert(isUInt<4>(Imm) && "Invalid immediate");
392 
393   Inst.addOperand(MCOperand::createImm(TableB4const[Imm]));
394   return MCDisassembler::Success;
395 }
396 
397 static int64_t TableB4constu[16] = {32768, 65536, 2,  3,  4,  5,  6,   7,
398                                     8,     10,    12, 16, 32, 64, 128, 256};
decodeB4constuOperand(MCInst & Inst,uint64_t Imm,int64_t Address,const void * Decoder)399 static DecodeStatus decodeB4constuOperand(MCInst &Inst, uint64_t Imm,
400                                           int64_t Address,
401                                           const void *Decoder) {
402   assert(isUInt<4>(Imm) && "Invalid immediate");
403 
404   Inst.addOperand(MCOperand::createImm(TableB4constu[Imm]));
405   return MCDisassembler::Success;
406 }
407 
decodeImm7_22Operand(MCInst & Inst,uint64_t Imm,int64_t Address,const void * Decoder)408 static DecodeStatus decodeImm7_22Operand(MCInst &Inst, uint64_t Imm,
409                                          int64_t Address, const void *Decoder) {
410   assert(isUInt<4>(Imm) && "Invalid immediate");
411   Inst.addOperand(MCOperand::createImm(Imm + 7));
412   return MCDisassembler::Success;
413 }
414 
decodeMem8Operand(MCInst & Inst,uint64_t Imm,int64_t Address,const void * Decoder)415 static DecodeStatus decodeMem8Operand(MCInst &Inst, uint64_t Imm,
416                                       int64_t Address, const void *Decoder) {
417   assert(isUInt<12>(Imm) && "Invalid immediate");
418   DecodeARRegisterClass(Inst, Imm & 0xf, Address, Decoder);
419   Inst.addOperand(MCOperand::createImm((Imm >> 4) & 0xff));
420   return MCDisassembler::Success;
421 }
422 
decodeMem16Operand(MCInst & Inst,uint64_t Imm,int64_t Address,const void * Decoder)423 static DecodeStatus decodeMem16Operand(MCInst &Inst, uint64_t Imm,
424                                        int64_t Address, const void *Decoder) {
425   assert(isUInt<12>(Imm) && "Invalid immediate");
426   DecodeARRegisterClass(Inst, Imm & 0xf, Address, Decoder);
427   Inst.addOperand(MCOperand::createImm((Imm >> 3) & 0x1fe));
428   return MCDisassembler::Success;
429 }
430 
decodeMem32Operand(MCInst & Inst,uint64_t Imm,int64_t Address,const void * Decoder)431 static DecodeStatus decodeMem32Operand(MCInst &Inst, uint64_t Imm,
432                                        int64_t Address, const void *Decoder) {
433   assert(isUInt<12>(Imm) && "Invalid immediate");
434   DecodeARRegisterClass(Inst, Imm & 0xf, Address, Decoder);
435   Inst.addOperand(MCOperand::createImm((Imm >> 2) & 0x3fc));
436   return MCDisassembler::Success;
437 }
438 
decodeMem32nOperand(MCInst & Inst,uint64_t Imm,int64_t Address,const void * Decoder)439 static DecodeStatus decodeMem32nOperand(MCInst &Inst, uint64_t Imm,
440                                         int64_t Address, const void *Decoder) {
441   assert(isUInt<8>(Imm) && "Invalid immediate");
442   DecodeARRegisterClass(Inst, Imm & 0xf, Address, Decoder);
443   Inst.addOperand(MCOperand::createImm((Imm >> 2) & 0x3c));
444   return MCDisassembler::Success;
445 }
446 
447 /// Read two bytes from the ArrayRef and return 16 bit data sorted
448 /// according to the given endianness.
readInstruction16(ArrayRef<uint8_t> Bytes,uint64_t Address,uint64_t & Size,uint64_t & Insn,bool IsLittleEndian)449 static DecodeStatus readInstruction16(ArrayRef<uint8_t> Bytes, uint64_t Address,
450                                       uint64_t &Size, uint64_t &Insn,
451                                       bool IsLittleEndian) {
452   // We want to read exactly 2 Bytes of data.
453   if (Bytes.size() < 2) {
454     Size = 0;
455     return MCDisassembler::Fail;
456   }
457 
458   if (!IsLittleEndian) {
459     report_fatal_error("Big-endian mode currently is not supported!");
460   } else {
461     Insn = (Bytes[1] << 8) | Bytes[0];
462   }
463 
464   return MCDisassembler::Success;
465 }
466 
467 /// Read three bytes from the ArrayRef and return 24 bit data
readInstruction24(ArrayRef<uint8_t> Bytes,uint64_t Address,uint64_t & Size,uint64_t & Insn,bool IsLittleEndian)468 static DecodeStatus readInstruction24(ArrayRef<uint8_t> Bytes, uint64_t Address,
469                                       uint64_t &Size, uint64_t &Insn,
470                                       bool IsLittleEndian) {
471   // We want to read exactly 3 Bytes of data.
472   if (Bytes.size() < 3) {
473     Size = 0;
474     return MCDisassembler::Fail;
475   }
476 
477   if (!IsLittleEndian) {
478     report_fatal_error("Big-endian mode currently is not supported!");
479   } else {
480     Insn = (Bytes[2] << 16) | (Bytes[1] << 8) | (Bytes[0] << 0);
481   }
482 
483   return MCDisassembler::Success;
484 }
485 
486 #include "XtensaGenDisassemblerTables.inc"
487 
getInstruction(MCInst & MI,uint64_t & Size,ArrayRef<uint8_t> Bytes,uint64_t Address,raw_ostream & CS) const488 DecodeStatus XtensaDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
489                                                 ArrayRef<uint8_t> Bytes,
490                                                 uint64_t Address,
491                                                 raw_ostream &CS) const {
492   uint64_t Insn;
493   DecodeStatus Result;
494 
495   // Parse 16-bit instructions
496   if (hasDensity()) {
497     Result = readInstruction16(Bytes, Address, Size, Insn, IsLittleEndian);
498     if (Result == MCDisassembler::Fail)
499       return MCDisassembler::Fail;
500     LLVM_DEBUG(dbgs() << "Trying Xtensa 16-bit instruction table :\n");
501     Result = decodeInstruction(DecoderTable16, MI, Insn, Address, this, STI);
502     if (Result != MCDisassembler::Fail) {
503       Size = 2;
504       return Result;
505     }
506   }
507 
508   // Parse Core 24-bit instructions
509   Result = readInstruction24(Bytes, Address, Size, Insn, IsLittleEndian);
510   if (Result == MCDisassembler::Fail)
511     return MCDisassembler::Fail;
512   LLVM_DEBUG(dbgs() << "Trying Xtensa 24-bit instruction table :\n");
513   Result = decodeInstruction(DecoderTable24, MI, Insn, Address, this, STI);
514   if (Result != MCDisassembler::Fail) {
515     Size = 3;
516     return Result;
517   }
518   return Result;
519 }
520