xref: /src/contrib/llvm-project/llvm/lib/Target/ARC/Disassembler/ARCDisassembler.cpp (revision 81ad626541db97eb356e2c1d4a20eb2a26a766ab)
1044eb2f6SDimitry Andric //===- ARCDisassembler.cpp - Disassembler for ARC ---------------*- C++ -*-===//
2044eb2f6SDimitry Andric //
3e6d15924SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e6d15924SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e6d15924SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6044eb2f6SDimitry Andric //
7044eb2f6SDimitry Andric //===----------------------------------------------------------------------===//
8044eb2f6SDimitry Andric ///
9044eb2f6SDimitry Andric /// \file
10eb11fae6SDimitry Andric /// This file is part of the ARC Disassembler.
11044eb2f6SDimitry Andric ///
12044eb2f6SDimitry Andric //===----------------------------------------------------------------------===//
13044eb2f6SDimitry Andric 
14044eb2f6SDimitry Andric #include "ARC.h"
15044eb2f6SDimitry Andric #include "ARCRegisterInfo.h"
16044eb2f6SDimitry Andric #include "MCTargetDesc/ARCMCTargetDesc.h"
17e6d15924SDimitry Andric #include "TargetInfo/ARCTargetInfo.h"
18044eb2f6SDimitry Andric #include "llvm/MC/MCContext.h"
19145449b1SDimitry Andric #include "llvm/MC/MCDecoderOps.h"
20044eb2f6SDimitry Andric #include "llvm/MC/MCDisassembler/MCDisassembler.h"
21044eb2f6SDimitry Andric #include "llvm/MC/MCInst.h"
22044eb2f6SDimitry Andric #include "llvm/MC/MCInstrInfo.h"
23044eb2f6SDimitry Andric #include "llvm/MC/MCSubtargetInfo.h"
24c0981da4SDimitry Andric #include "llvm/MC/TargetRegistry.h"
25044eb2f6SDimitry Andric 
26044eb2f6SDimitry Andric using namespace llvm;
27044eb2f6SDimitry Andric 
28044eb2f6SDimitry Andric #define DEBUG_TYPE "arc-disassembler"
29044eb2f6SDimitry Andric 
30044eb2f6SDimitry Andric using DecodeStatus = MCDisassembler::DecodeStatus;
31044eb2f6SDimitry Andric 
32044eb2f6SDimitry Andric namespace {
33044eb2f6SDimitry Andric 
34eb11fae6SDimitry Andric /// A disassembler class for ARC.
35044eb2f6SDimitry Andric class ARCDisassembler : public MCDisassembler {
36044eb2f6SDimitry Andric public:
37044eb2f6SDimitry Andric   std::unique_ptr<MCInstrInfo const> const MCII;
38044eb2f6SDimitry Andric 
ARCDisassembler(const MCSubtargetInfo & STI,MCContext & Ctx,MCInstrInfo const * MCII)39044eb2f6SDimitry Andric   ARCDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx,
40044eb2f6SDimitry Andric                   MCInstrInfo const *MCII)
41044eb2f6SDimitry Andric       : MCDisassembler(STI, Ctx), MCII(MCII) {}
42044eb2f6SDimitry Andric 
43044eb2f6SDimitry Andric   DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size,
44044eb2f6SDimitry Andric                               ArrayRef<uint8_t> Bytes, uint64_t Address,
45044eb2f6SDimitry Andric                               raw_ostream &CStream) const override;
46044eb2f6SDimitry Andric };
47044eb2f6SDimitry Andric 
48044eb2f6SDimitry Andric } // end anonymous namespace
49044eb2f6SDimitry Andric 
readInstruction32(ArrayRef<uint8_t> Bytes,uint64_t Address,uint64_t & Size,uint32_t & Insn)50044eb2f6SDimitry Andric static bool readInstruction32(ArrayRef<uint8_t> Bytes, uint64_t Address,
51044eb2f6SDimitry Andric                               uint64_t &Size, uint32_t &Insn) {
52044eb2f6SDimitry Andric   Size = 4;
53044eb2f6SDimitry Andric   // Read 2 16-bit values, but swap hi/lo parts.
54044eb2f6SDimitry Andric   Insn =
55044eb2f6SDimitry Andric       (Bytes[0] << 16) | (Bytes[1] << 24) | (Bytes[2] << 0) | (Bytes[3] << 8);
56044eb2f6SDimitry Andric   return true;
57044eb2f6SDimitry Andric }
58044eb2f6SDimitry Andric 
readInstruction64(ArrayRef<uint8_t> Bytes,uint64_t Address,uint64_t & Size,uint64_t & Insn)59044eb2f6SDimitry Andric static bool readInstruction64(ArrayRef<uint8_t> Bytes, uint64_t Address,
60044eb2f6SDimitry Andric                               uint64_t &Size, uint64_t &Insn) {
61044eb2f6SDimitry Andric   Size = 8;
62044eb2f6SDimitry Andric   Insn = ((uint64_t)Bytes[0] << 16) | ((uint64_t)Bytes[1] << 24) |
63044eb2f6SDimitry Andric          ((uint64_t)Bytes[2] << 0) | ((uint64_t)Bytes[3] << 8) |
64044eb2f6SDimitry Andric          ((uint64_t)Bytes[4] << 48) | ((uint64_t)Bytes[5] << 56) |
65044eb2f6SDimitry Andric          ((uint64_t)Bytes[6] << 32) | ((uint64_t)Bytes[7] << 40);
66044eb2f6SDimitry Andric   return true;
67044eb2f6SDimitry Andric }
68044eb2f6SDimitry Andric 
readInstruction48(ArrayRef<uint8_t> Bytes,uint64_t Address,uint64_t & Size,uint64_t & Insn)69044eb2f6SDimitry Andric static bool readInstruction48(ArrayRef<uint8_t> Bytes, uint64_t Address,
70044eb2f6SDimitry Andric                               uint64_t &Size, uint64_t &Insn) {
71044eb2f6SDimitry Andric   Size = 6;
72044eb2f6SDimitry Andric   Insn = ((uint64_t)Bytes[0] << 0) | ((uint64_t)Bytes[1] << 8) |
73044eb2f6SDimitry Andric          ((uint64_t)Bytes[2] << 32) | ((uint64_t)Bytes[3] << 40) |
74044eb2f6SDimitry Andric          ((uint64_t)Bytes[4] << 16) | ((uint64_t)Bytes[5] << 24);
75044eb2f6SDimitry Andric   return true;
76044eb2f6SDimitry Andric }
77044eb2f6SDimitry Andric 
readInstruction16(ArrayRef<uint8_t> Bytes,uint64_t Address,uint64_t & Size,uint32_t & Insn)78044eb2f6SDimitry Andric static bool readInstruction16(ArrayRef<uint8_t> Bytes, uint64_t Address,
79044eb2f6SDimitry Andric                               uint64_t &Size, uint32_t &Insn) {
80044eb2f6SDimitry Andric   Size = 2;
81044eb2f6SDimitry Andric   Insn = (Bytes[0] << 0) | (Bytes[1] << 8);
82044eb2f6SDimitry Andric   return true;
83044eb2f6SDimitry Andric }
84044eb2f6SDimitry Andric 
85044eb2f6SDimitry Andric template <unsigned B>
86145449b1SDimitry Andric static DecodeStatus
87145449b1SDimitry Andric DecodeSignedOperand(MCInst &Inst, unsigned InsnS, uint64_t Address = 0,
88145449b1SDimitry Andric                     const MCDisassembler *Decoder = nullptr);
89044eb2f6SDimitry Andric 
90044eb2f6SDimitry Andric template <unsigned B>
91145449b1SDimitry Andric static DecodeStatus
92145449b1SDimitry Andric DecodeFromCyclicRange(MCInst &Inst, unsigned InsnS, uint64_t Address = 0,
93145449b1SDimitry Andric                       const MCDisassembler *Decoder = nullptr);
94044eb2f6SDimitry Andric 
95044eb2f6SDimitry Andric template <unsigned B>
96044eb2f6SDimitry Andric static DecodeStatus DecodeBranchTargetS(MCInst &Inst, unsigned InsnS,
97145449b1SDimitry Andric                                         uint64_t Address,
98145449b1SDimitry Andric                                         const MCDisassembler *Decoder);
99044eb2f6SDimitry Andric 
100145449b1SDimitry Andric static DecodeStatus DecodeMEMrs9(MCInst &, unsigned, uint64_t,
101145449b1SDimitry Andric                                  const MCDisassembler *);
102044eb2f6SDimitry Andric 
103044eb2f6SDimitry Andric static DecodeStatus DecodeLdLImmInstruction(MCInst &, uint64_t, uint64_t,
104145449b1SDimitry Andric                                             const MCDisassembler *);
105044eb2f6SDimitry Andric 
106044eb2f6SDimitry Andric static DecodeStatus DecodeStLImmInstruction(MCInst &, uint64_t, uint64_t,
107145449b1SDimitry Andric                                             const MCDisassembler *);
108044eb2f6SDimitry Andric 
109044eb2f6SDimitry Andric static DecodeStatus DecodeLdRLImmInstruction(MCInst &, uint64_t, uint64_t,
110145449b1SDimitry Andric                                              const MCDisassembler *);
111044eb2f6SDimitry Andric 
112c0981da4SDimitry Andric static DecodeStatus DecodeSOPwithRS12(MCInst &, uint64_t, uint64_t,
113145449b1SDimitry Andric                                       const MCDisassembler *);
114c0981da4SDimitry Andric 
115c0981da4SDimitry Andric static DecodeStatus DecodeSOPwithRU6(MCInst &, uint64_t, uint64_t,
116145449b1SDimitry Andric                                      const MCDisassembler *);
117c0981da4SDimitry Andric 
118344a3780SDimitry Andric static DecodeStatus DecodeCCRU6Instruction(MCInst &, uint64_t, uint64_t,
119145449b1SDimitry Andric                                            const MCDisassembler *);
120344a3780SDimitry Andric 
121044eb2f6SDimitry Andric static DecodeStatus DecodeMoveHRegInstruction(MCInst &Inst, uint64_t, uint64_t,
122145449b1SDimitry Andric                                               const MCDisassembler *);
123044eb2f6SDimitry Andric 
124044eb2f6SDimitry Andric static const uint16_t GPR32DecoderTable[] = {
125044eb2f6SDimitry Andric     ARC::R0,  ARC::R1,    ARC::R2,  ARC::R3,   ARC::R4,  ARC::R5,  ARC::R6,
126044eb2f6SDimitry Andric     ARC::R7,  ARC::R8,    ARC::R9,  ARC::R10,  ARC::R11, ARC::R12, ARC::R13,
127044eb2f6SDimitry Andric     ARC::R14, ARC::R15,   ARC::R16, ARC::R17,  ARC::R18, ARC::R19, ARC::R20,
128044eb2f6SDimitry Andric     ARC::R21, ARC::R22,   ARC::R23, ARC::R24,  ARC::R25, ARC::GP,  ARC::FP,
129044eb2f6SDimitry Andric     ARC::SP,  ARC::ILINK, ARC::R30, ARC::BLINK};
130044eb2f6SDimitry Andric 
DecodeGPR32RegisterClass(MCInst & Inst,unsigned RegNo,uint64_t Address,const MCDisassembler * Decoder)131044eb2f6SDimitry Andric static DecodeStatus DecodeGPR32RegisterClass(MCInst &Inst, unsigned RegNo,
132044eb2f6SDimitry Andric                                              uint64_t Address,
133145449b1SDimitry Andric                                              const MCDisassembler *Decoder) {
134044eb2f6SDimitry Andric   if (RegNo >= 32) {
135eb11fae6SDimitry Andric     LLVM_DEBUG(dbgs() << "Not a GPR32 register.");
136044eb2f6SDimitry Andric     return MCDisassembler::Fail;
137044eb2f6SDimitry Andric   }
138044eb2f6SDimitry Andric 
139044eb2f6SDimitry Andric   unsigned Reg = GPR32DecoderTable[RegNo];
140044eb2f6SDimitry Andric   Inst.addOperand(MCOperand::createReg(Reg));
141044eb2f6SDimitry Andric   return MCDisassembler::Success;
142044eb2f6SDimitry Andric }
143044eb2f6SDimitry Andric 
DecodeGBR32ShortRegister(MCInst & Inst,unsigned RegNo,uint64_t Address,const MCDisassembler * Decoder)144044eb2f6SDimitry Andric static DecodeStatus DecodeGBR32ShortRegister(MCInst &Inst, unsigned RegNo,
145044eb2f6SDimitry Andric                                              uint64_t Address,
146145449b1SDimitry Andric                                              const MCDisassembler *Decoder) {
147044eb2f6SDimitry Andric   // Enumerates registers from ranges [r0-r3],[r12-r15].
148044eb2f6SDimitry Andric   if (RegNo > 3)
149044eb2f6SDimitry Andric     RegNo += 8; // 4 for r12, etc...
150044eb2f6SDimitry Andric 
151044eb2f6SDimitry Andric   return DecodeGPR32RegisterClass(Inst, RegNo, Address, Decoder);
152044eb2f6SDimitry Andric }
153044eb2f6SDimitry Andric 
154044eb2f6SDimitry Andric #include "ARCGenDisassemblerTables.inc"
155044eb2f6SDimitry Andric 
decodeCField(unsigned Insn)156044eb2f6SDimitry Andric static unsigned decodeCField(unsigned Insn) {
157044eb2f6SDimitry Andric   return fieldFromInstruction(Insn, 6, 6);
158044eb2f6SDimitry Andric }
159044eb2f6SDimitry Andric 
decodeBField(unsigned Insn)160044eb2f6SDimitry Andric static unsigned decodeBField(unsigned Insn) {
161044eb2f6SDimitry Andric   return (fieldFromInstruction(Insn, 12, 3) << 3) |
162044eb2f6SDimitry Andric          fieldFromInstruction(Insn, 24, 3);
163044eb2f6SDimitry Andric }
164044eb2f6SDimitry Andric 
decodeAField(unsigned Insn)165044eb2f6SDimitry Andric static unsigned decodeAField(unsigned Insn) {
166044eb2f6SDimitry Andric   return fieldFromInstruction(Insn, 0, 6);
167044eb2f6SDimitry Andric }
168044eb2f6SDimitry Andric 
DecodeMEMrs9(MCInst & Inst,unsigned Insn,uint64_t Address,const MCDisassembler * Dec)169044eb2f6SDimitry Andric static DecodeStatus DecodeMEMrs9(MCInst &Inst, unsigned Insn, uint64_t Address,
170145449b1SDimitry Andric                                  const MCDisassembler *Dec) {
171044eb2f6SDimitry Andric   // We have the 9-bit immediate in the low bits, 6-bit register in high bits.
172044eb2f6SDimitry Andric   unsigned S9 = Insn & 0x1ff;
173044eb2f6SDimitry Andric   unsigned R = (Insn & (0x7fff & ~0x1ff)) >> 9;
174044eb2f6SDimitry Andric   DecodeGPR32RegisterClass(Inst, R, Address, Dec);
175044eb2f6SDimitry Andric   Inst.addOperand(MCOperand::createImm(SignExtend32<9>(S9)));
176044eb2f6SDimitry Andric   return MCDisassembler::Success;
177044eb2f6SDimitry Andric }
178044eb2f6SDimitry Andric 
DecodeSymbolicOperand(MCInst & Inst,uint64_t Address,uint64_t Value,const MCDisassembler * Decoder)179044eb2f6SDimitry Andric static bool DecodeSymbolicOperand(MCInst &Inst, uint64_t Address,
180145449b1SDimitry Andric                                   uint64_t Value,
181145449b1SDimitry Andric                                   const MCDisassembler *Decoder) {
182344a3780SDimitry Andric   static const uint64_t AtLeast = 2;
183145449b1SDimitry Andric   return (nullptr != Decoder && Decoder->tryAddingSymbolicOperand(
184145449b1SDimitry Andric                                     Inst, Value, Address, true, 0, AtLeast, 0));
185044eb2f6SDimitry Andric }
186044eb2f6SDimitry Andric 
DecodeSymbolicOperandOff(MCInst & Inst,uint64_t Address,uint64_t Offset,const MCDisassembler * Decoder)187044eb2f6SDimitry Andric static void DecodeSymbolicOperandOff(MCInst &Inst, uint64_t Address,
188145449b1SDimitry Andric                                      uint64_t Offset,
189145449b1SDimitry Andric                                      const MCDisassembler *Decoder) {
190344a3780SDimitry Andric   uint64_t NextAddress = Address + Offset;
191044eb2f6SDimitry Andric 
192344a3780SDimitry Andric   if (!DecodeSymbolicOperand(Inst, Address, NextAddress, Decoder))
193044eb2f6SDimitry Andric     Inst.addOperand(MCOperand::createImm(Offset));
194044eb2f6SDimitry Andric }
195044eb2f6SDimitry Andric 
196044eb2f6SDimitry Andric template <unsigned B>
DecodeBranchTargetS(MCInst & Inst,unsigned InsnS,uint64_t Address,const MCDisassembler * Decoder)197044eb2f6SDimitry Andric static DecodeStatus DecodeBranchTargetS(MCInst &Inst, unsigned InsnS,
198145449b1SDimitry Andric                                         uint64_t Address,
199145449b1SDimitry Andric                                         const MCDisassembler *Decoder) {
200044eb2f6SDimitry Andric 
201044eb2f6SDimitry Andric   static_assert(B > 0, "field is empty");
202044eb2f6SDimitry Andric   DecodeSymbolicOperandOff(Inst, Address, SignExtend32<B>(InsnS), Decoder);
203044eb2f6SDimitry Andric   return MCDisassembler::Success;
204044eb2f6SDimitry Andric }
205044eb2f6SDimitry Andric 
206044eb2f6SDimitry Andric template <unsigned B>
DecodeSignedOperand(MCInst & Inst,unsigned InsnS,uint64_t,const MCDisassembler *)207044eb2f6SDimitry Andric static DecodeStatus DecodeSignedOperand(MCInst &Inst, unsigned InsnS,
208044eb2f6SDimitry Andric                                         uint64_t /*Address*/,
209145449b1SDimitry Andric                                         const MCDisassembler * /*Decoder*/) {
210044eb2f6SDimitry Andric 
211044eb2f6SDimitry Andric   static_assert(B > 0, "field is empty");
212044eb2f6SDimitry Andric   Inst.addOperand(MCOperand::createImm(
213044eb2f6SDimitry Andric       SignExtend32<B>(maskTrailingOnes<decltype(InsnS)>(B) & InsnS)));
214044eb2f6SDimitry Andric   return MCDisassembler::Success;
215044eb2f6SDimitry Andric }
216044eb2f6SDimitry Andric 
217044eb2f6SDimitry Andric template <unsigned B>
DecodeFromCyclicRange(MCInst & Inst,unsigned InsnS,uint64_t,const MCDisassembler *)218044eb2f6SDimitry Andric static DecodeStatus DecodeFromCyclicRange(MCInst &Inst, unsigned InsnS,
219044eb2f6SDimitry Andric                                           uint64_t /*Address*/,
220145449b1SDimitry Andric                                           const MCDisassembler * /*Decoder*/) {
221044eb2f6SDimitry Andric 
222044eb2f6SDimitry Andric   static_assert(B > 0, "field is empty");
223044eb2f6SDimitry Andric   const unsigned max = (1u << B) - 1;
224044eb2f6SDimitry Andric   Inst.addOperand(
225044eb2f6SDimitry Andric       MCOperand::createImm(InsnS < max ? static_cast<int>(InsnS) : -1));
226044eb2f6SDimitry Andric   return MCDisassembler::Success;
227044eb2f6SDimitry Andric }
228044eb2f6SDimitry Andric 
DecodeStLImmInstruction(MCInst & Inst,uint64_t Insn,uint64_t Address,const MCDisassembler * Decoder)229044eb2f6SDimitry Andric static DecodeStatus DecodeStLImmInstruction(MCInst &Inst, uint64_t Insn,
230044eb2f6SDimitry Andric                                             uint64_t Address,
231145449b1SDimitry Andric                                             const MCDisassembler *Decoder) {
232044eb2f6SDimitry Andric   unsigned SrcC, DstB, LImm;
233044eb2f6SDimitry Andric   DstB = decodeBField(Insn);
234044eb2f6SDimitry Andric   if (DstB != 62) {
235eb11fae6SDimitry Andric     LLVM_DEBUG(dbgs() << "Decoding StLImm found non-limm register.");
236044eb2f6SDimitry Andric     return MCDisassembler::Fail;
237044eb2f6SDimitry Andric   }
238044eb2f6SDimitry Andric   SrcC = decodeCField(Insn);
239044eb2f6SDimitry Andric   DecodeGPR32RegisterClass(Inst, SrcC, Address, Decoder);
240044eb2f6SDimitry Andric   LImm = (Insn >> 32);
241044eb2f6SDimitry Andric   Inst.addOperand(MCOperand::createImm(LImm));
242044eb2f6SDimitry Andric   Inst.addOperand(MCOperand::createImm(0));
243044eb2f6SDimitry Andric   return MCDisassembler::Success;
244044eb2f6SDimitry Andric }
245044eb2f6SDimitry Andric 
DecodeLdLImmInstruction(MCInst & Inst,uint64_t Insn,uint64_t Address,const MCDisassembler * Decoder)246044eb2f6SDimitry Andric static DecodeStatus DecodeLdLImmInstruction(MCInst &Inst, uint64_t Insn,
247044eb2f6SDimitry Andric                                             uint64_t Address,
248145449b1SDimitry Andric                                             const MCDisassembler *Decoder) {
249044eb2f6SDimitry Andric   unsigned DstA, SrcB, LImm;
250eb11fae6SDimitry Andric   LLVM_DEBUG(dbgs() << "Decoding LdLImm:\n");
251044eb2f6SDimitry Andric   SrcB = decodeBField(Insn);
252044eb2f6SDimitry Andric   if (SrcB != 62) {
253eb11fae6SDimitry Andric     LLVM_DEBUG(dbgs() << "Decoding LdLImm found non-limm register.");
254044eb2f6SDimitry Andric     return MCDisassembler::Fail;
255044eb2f6SDimitry Andric   }
256044eb2f6SDimitry Andric   DstA = decodeAField(Insn);
257044eb2f6SDimitry Andric   DecodeGPR32RegisterClass(Inst, DstA, Address, Decoder);
258044eb2f6SDimitry Andric   LImm = (Insn >> 32);
259044eb2f6SDimitry Andric   Inst.addOperand(MCOperand::createImm(LImm));
260044eb2f6SDimitry Andric   Inst.addOperand(MCOperand::createImm(0));
261044eb2f6SDimitry Andric   return MCDisassembler::Success;
262044eb2f6SDimitry Andric }
263044eb2f6SDimitry Andric 
DecodeLdRLImmInstruction(MCInst & Inst,uint64_t Insn,uint64_t Address,const MCDisassembler * Decoder)264044eb2f6SDimitry Andric static DecodeStatus DecodeLdRLImmInstruction(MCInst &Inst, uint64_t Insn,
265044eb2f6SDimitry Andric                                              uint64_t Address,
266145449b1SDimitry Andric                                              const MCDisassembler *Decoder) {
267044eb2f6SDimitry Andric   unsigned DstA, SrcB;
268eb11fae6SDimitry Andric   LLVM_DEBUG(dbgs() << "Decoding LdRLimm\n");
269044eb2f6SDimitry Andric   DstA = decodeAField(Insn);
270044eb2f6SDimitry Andric   DecodeGPR32RegisterClass(Inst, DstA, Address, Decoder);
271044eb2f6SDimitry Andric   SrcB = decodeBField(Insn);
272044eb2f6SDimitry Andric   DecodeGPR32RegisterClass(Inst, SrcB, Address, Decoder);
273044eb2f6SDimitry Andric   if (decodeCField(Insn) != 62) {
274eb11fae6SDimitry Andric     LLVM_DEBUG(dbgs() << "Decoding LdRLimm found non-limm register.");
275044eb2f6SDimitry Andric     return MCDisassembler::Fail;
276044eb2f6SDimitry Andric   }
277044eb2f6SDimitry Andric   Inst.addOperand(MCOperand::createImm((uint32_t)(Insn >> 32)));
278044eb2f6SDimitry Andric   return MCDisassembler::Success;
279044eb2f6SDimitry Andric }
280044eb2f6SDimitry Andric 
DecodeMoveHRegInstruction(MCInst & Inst,uint64_t Insn,uint64_t Address,const MCDisassembler * Decoder)281044eb2f6SDimitry Andric static DecodeStatus DecodeMoveHRegInstruction(MCInst &Inst, uint64_t Insn,
282044eb2f6SDimitry Andric                                               uint64_t Address,
283145449b1SDimitry Andric                                               const MCDisassembler *Decoder) {
284eb11fae6SDimitry Andric   LLVM_DEBUG(dbgs() << "Decoding MOV_S h-register\n");
285044eb2f6SDimitry Andric   using Field = decltype(Insn);
286344a3780SDimitry Andric   Field H = fieldFromInstruction(Insn, 5, 3) |
287044eb2f6SDimitry Andric             (fieldFromInstruction(Insn, 0, 2) << 3);
288344a3780SDimitry Andric   Field G = fieldFromInstruction(Insn, 8, 3) |
289044eb2f6SDimitry Andric             (fieldFromInstruction(Insn, 3, 2) << 3);
290044eb2f6SDimitry Andric 
291044eb2f6SDimitry Andric   auto DecodeRegisterOrImm = [&Inst, Address, Decoder](Field RegNum,
292044eb2f6SDimitry Andric                                                        Field Value) {
293044eb2f6SDimitry Andric     if (30 == RegNum) {
294044eb2f6SDimitry Andric       Inst.addOperand(MCOperand::createImm(Value));
295044eb2f6SDimitry Andric       return MCDisassembler::Success;
296044eb2f6SDimitry Andric     }
297044eb2f6SDimitry Andric 
298044eb2f6SDimitry Andric     return DecodeGPR32RegisterClass(Inst, RegNum, Address, Decoder);
299044eb2f6SDimitry Andric   };
300044eb2f6SDimitry Andric 
301344a3780SDimitry Andric   if (MCDisassembler::Success != DecodeRegisterOrImm(G, 0))
302044eb2f6SDimitry Andric     return MCDisassembler::Fail;
303044eb2f6SDimitry Andric 
304344a3780SDimitry Andric   return DecodeRegisterOrImm(H, Insn >> 16u);
305344a3780SDimitry Andric }
306344a3780SDimitry Andric 
DecodeCCRU6Instruction(MCInst & Inst,uint64_t Insn,uint64_t Address,const MCDisassembler * Decoder)307344a3780SDimitry Andric static DecodeStatus DecodeCCRU6Instruction(MCInst &Inst, uint64_t Insn,
308344a3780SDimitry Andric                                            uint64_t Address,
309145449b1SDimitry Andric                                            const MCDisassembler *Decoder) {
310344a3780SDimitry Andric   unsigned DstB;
311344a3780SDimitry Andric   LLVM_DEBUG(dbgs() << "Decoding CCRU6 instruction:\n");
312344a3780SDimitry Andric   DstB = decodeBField(Insn);
313344a3780SDimitry Andric   DecodeGPR32RegisterClass(Inst, DstB, Address, Decoder);
314344a3780SDimitry Andric   using Field = decltype(Insn);
315c0981da4SDimitry Andric   Field U6Field = fieldFromInstruction(Insn, 6, 6);
316344a3780SDimitry Andric   Inst.addOperand(MCOperand::createImm(U6Field));
317344a3780SDimitry Andric   Field CCField = fieldFromInstruction(Insn, 0, 4);
318344a3780SDimitry Andric   Inst.addOperand(MCOperand::createImm(CCField));
319344a3780SDimitry Andric   return MCDisassembler::Success;
320044eb2f6SDimitry Andric }
321044eb2f6SDimitry Andric 
DecodeSOPwithRU6(MCInst & Inst,uint64_t Insn,uint64_t Address,const MCDisassembler * Decoder)322c0981da4SDimitry Andric static DecodeStatus DecodeSOPwithRU6(MCInst &Inst, uint64_t Insn,
323145449b1SDimitry Andric                                      uint64_t Address,
324145449b1SDimitry Andric                                      const MCDisassembler *Decoder) {
325c0981da4SDimitry Andric   unsigned DstB = decodeBField(Insn);
326c0981da4SDimitry Andric   DecodeGPR32RegisterClass(Inst, DstB, Address, Decoder);
327c0981da4SDimitry Andric   using Field = decltype(Insn);
328c0981da4SDimitry Andric   Field U6 = fieldFromInstruction(Insn, 6, 6);
329c0981da4SDimitry Andric   Inst.addOperand(MCOperand::createImm(U6));
330c0981da4SDimitry Andric   return MCDisassembler::Success;
331c0981da4SDimitry Andric }
332c0981da4SDimitry Andric 
DecodeSOPwithRS12(MCInst & Inst,uint64_t Insn,uint64_t Address,const MCDisassembler * Decoder)333c0981da4SDimitry Andric static DecodeStatus DecodeSOPwithRS12(MCInst &Inst, uint64_t Insn,
334145449b1SDimitry Andric                                       uint64_t Address,
335145449b1SDimitry Andric                                       const MCDisassembler *Decoder) {
336c0981da4SDimitry Andric   unsigned DstB = decodeBField(Insn);
337c0981da4SDimitry Andric   DecodeGPR32RegisterClass(Inst, DstB, Address, Decoder);
338c0981da4SDimitry Andric   using Field = decltype(Insn);
339c0981da4SDimitry Andric   Field Lower = fieldFromInstruction(Insn, 6, 6);
340c0981da4SDimitry Andric   Field Upper = fieldFromInstruction(Insn, 0, 5);
341c0981da4SDimitry Andric   Field Sign = fieldFromInstruction(Insn, 5, 1) ? -1 : 1;
342c0981da4SDimitry Andric   Field Result = Sign * ((Upper << 6) + Lower);
343c0981da4SDimitry Andric   Inst.addOperand(MCOperand::createImm(Result));
344c0981da4SDimitry Andric   return MCDisassembler::Success;
345c0981da4SDimitry Andric }
346c0981da4SDimitry Andric 
getInstruction(MCInst & Instr,uint64_t & Size,ArrayRef<uint8_t> Bytes,uint64_t Address,raw_ostream & cStream) const347044eb2f6SDimitry Andric DecodeStatus ARCDisassembler::getInstruction(MCInst &Instr, uint64_t &Size,
348044eb2f6SDimitry Andric                                              ArrayRef<uint8_t> Bytes,
349044eb2f6SDimitry Andric                                              uint64_t Address,
350044eb2f6SDimitry Andric                                              raw_ostream &cStream) const {
351044eb2f6SDimitry Andric   MCDisassembler::DecodeStatus Result;
352044eb2f6SDimitry Andric   if (Bytes.size() < 2) {
353044eb2f6SDimitry Andric     Size = 0;
354044eb2f6SDimitry Andric     return Fail;
355044eb2f6SDimitry Andric   }
356044eb2f6SDimitry Andric   uint8_t DecodeByte = (Bytes[1] & 0xF7) >> 3;
357044eb2f6SDimitry Andric   // 0x00 -> 0x07 are 32-bit instructions.
358044eb2f6SDimitry Andric   // 0x08 -> 0x1F are 16-bit instructions.
359044eb2f6SDimitry Andric   if (DecodeByte < 0x08) {
360044eb2f6SDimitry Andric     // 32-bit instruction.
361044eb2f6SDimitry Andric     if (Bytes.size() < 4) {
362044eb2f6SDimitry Andric       // Did we decode garbage?
363044eb2f6SDimitry Andric       Size = 0;
364044eb2f6SDimitry Andric       return Fail;
365044eb2f6SDimitry Andric     }
366044eb2f6SDimitry Andric     if (Bytes.size() >= 8) {
367044eb2f6SDimitry Andric       // Attempt to decode 64-bit instruction.
368044eb2f6SDimitry Andric       uint64_t Insn64;
369044eb2f6SDimitry Andric       if (!readInstruction64(Bytes, Address, Size, Insn64))
370044eb2f6SDimitry Andric         return Fail;
371044eb2f6SDimitry Andric       Result =
372044eb2f6SDimitry Andric           decodeInstruction(DecoderTable64, Instr, Insn64, Address, this, STI);
373044eb2f6SDimitry Andric       if (Success == Result) {
374eb11fae6SDimitry Andric         LLVM_DEBUG(dbgs() << "Successfully decoded 64-bit instruction.");
375044eb2f6SDimitry Andric         return Result;
376044eb2f6SDimitry Andric       }
377eb11fae6SDimitry Andric       LLVM_DEBUG(dbgs() << "Not a 64-bit instruction, falling back to 32-bit.");
378044eb2f6SDimitry Andric     }
379044eb2f6SDimitry Andric     uint32_t Insn32;
380044eb2f6SDimitry Andric     if (!readInstruction32(Bytes, Address, Size, Insn32)) {
381044eb2f6SDimitry Andric       return Fail;
382044eb2f6SDimitry Andric     }
383044eb2f6SDimitry Andric     // Calling the auto-generated decoder function.
384044eb2f6SDimitry Andric     return decodeInstruction(DecoderTable32, Instr, Insn32, Address, this, STI);
385044eb2f6SDimitry Andric   } else {
386044eb2f6SDimitry Andric     if (Bytes.size() >= 6) {
387044eb2f6SDimitry Andric       // Attempt to treat as instr. with limm data.
388044eb2f6SDimitry Andric       uint64_t Insn48;
389044eb2f6SDimitry Andric       if (!readInstruction48(Bytes, Address, Size, Insn48))
390044eb2f6SDimitry Andric         return Fail;
391044eb2f6SDimitry Andric       Result =
392044eb2f6SDimitry Andric           decodeInstruction(DecoderTable48, Instr, Insn48, Address, this, STI);
393044eb2f6SDimitry Andric       if (Success == Result) {
394eb11fae6SDimitry Andric         LLVM_DEBUG(
395eb11fae6SDimitry Andric             dbgs() << "Successfully decoded 16-bit instruction with limm.");
396044eb2f6SDimitry Andric         return Result;
397044eb2f6SDimitry Andric       }
398eb11fae6SDimitry Andric       LLVM_DEBUG(
399eb11fae6SDimitry Andric           dbgs() << "Not a 16-bit instruction with limm, try without it.");
400044eb2f6SDimitry Andric     }
401044eb2f6SDimitry Andric 
402044eb2f6SDimitry Andric     uint32_t Insn16;
403044eb2f6SDimitry Andric     if (!readInstruction16(Bytes, Address, Size, Insn16))
404044eb2f6SDimitry Andric       return Fail;
405044eb2f6SDimitry Andric 
406044eb2f6SDimitry Andric     // Calling the auto-generated decoder function.
407044eb2f6SDimitry Andric     return decodeInstruction(DecoderTable16, Instr, Insn16, Address, this, STI);
408044eb2f6SDimitry Andric   }
409044eb2f6SDimitry Andric }
410044eb2f6SDimitry Andric 
createARCDisassembler(const Target & T,const MCSubtargetInfo & STI,MCContext & Ctx)411044eb2f6SDimitry Andric static MCDisassembler *createARCDisassembler(const Target &T,
412044eb2f6SDimitry Andric                                              const MCSubtargetInfo &STI,
413044eb2f6SDimitry Andric                                              MCContext &Ctx) {
414044eb2f6SDimitry Andric   return new ARCDisassembler(STI, Ctx, T.createMCInstrInfo());
415044eb2f6SDimitry Andric }
416044eb2f6SDimitry Andric 
LLVMInitializeARCDisassembler()417706b4fc4SDimitry Andric extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeARCDisassembler() {
418044eb2f6SDimitry Andric   // Register the disassembler.
419044eb2f6SDimitry Andric   TargetRegistry::RegisterMCDisassembler(getTheARCTarget(),
420044eb2f6SDimitry Andric                                          createARCDisassembler);
421044eb2f6SDimitry Andric }
422