10b57cec5SDimitry Andric //===- ARCDisassembler.cpp - Disassembler for ARC ---------------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric ///
90b57cec5SDimitry Andric /// \file
100b57cec5SDimitry Andric /// This file is part of the ARC Disassembler.
110b57cec5SDimitry Andric ///
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #include "ARC.h"
150b57cec5SDimitry Andric #include "ARCRegisterInfo.h"
160b57cec5SDimitry Andric #include "MCTargetDesc/ARCMCTargetDesc.h"
170b57cec5SDimitry Andric #include "TargetInfo/ARCTargetInfo.h"
180b57cec5SDimitry Andric #include "llvm/MC/MCContext.h"
1981ad6265SDimitry Andric #include "llvm/MC/MCDecoderOps.h"
200b57cec5SDimitry Andric #include "llvm/MC/MCDisassembler/MCDisassembler.h"
210b57cec5SDimitry Andric #include "llvm/MC/MCInst.h"
220b57cec5SDimitry Andric #include "llvm/MC/MCInstrInfo.h"
230b57cec5SDimitry Andric #include "llvm/MC/MCSubtargetInfo.h"
24349cc55cSDimitry Andric #include "llvm/MC/TargetRegistry.h"
250b57cec5SDimitry Andric 
260b57cec5SDimitry Andric using namespace llvm;
270b57cec5SDimitry Andric 
280b57cec5SDimitry Andric #define DEBUG_TYPE "arc-disassembler"
290b57cec5SDimitry Andric 
300b57cec5SDimitry Andric using DecodeStatus = MCDisassembler::DecodeStatus;
310b57cec5SDimitry Andric 
320b57cec5SDimitry Andric namespace {
330b57cec5SDimitry Andric 
340b57cec5SDimitry Andric /// A disassembler class for ARC.
350b57cec5SDimitry Andric class ARCDisassembler : public MCDisassembler {
360b57cec5SDimitry Andric public:
370b57cec5SDimitry Andric   std::unique_ptr<MCInstrInfo const> const MCII;
380b57cec5SDimitry Andric 
ARCDisassembler(const MCSubtargetInfo & STI,MCContext & Ctx,MCInstrInfo const * MCII)390b57cec5SDimitry Andric   ARCDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx,
400b57cec5SDimitry Andric                   MCInstrInfo const *MCII)
410b57cec5SDimitry Andric       : MCDisassembler(STI, Ctx), MCII(MCII) {}
420b57cec5SDimitry Andric 
430b57cec5SDimitry Andric   DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size,
440b57cec5SDimitry Andric                               ArrayRef<uint8_t> Bytes, uint64_t Address,
450b57cec5SDimitry Andric                               raw_ostream &CStream) const override;
460b57cec5SDimitry Andric };
470b57cec5SDimitry Andric 
480b57cec5SDimitry Andric } // end anonymous namespace
490b57cec5SDimitry Andric 
readInstruction32(ArrayRef<uint8_t> Bytes,uint64_t Address,uint64_t & Size,uint32_t & Insn)500b57cec5SDimitry Andric static bool readInstruction32(ArrayRef<uint8_t> Bytes, uint64_t Address,
510b57cec5SDimitry Andric                               uint64_t &Size, uint32_t &Insn) {
520b57cec5SDimitry Andric   Size = 4;
530b57cec5SDimitry Andric   // Read 2 16-bit values, but swap hi/lo parts.
540b57cec5SDimitry Andric   Insn =
550b57cec5SDimitry Andric       (Bytes[0] << 16) | (Bytes[1] << 24) | (Bytes[2] << 0) | (Bytes[3] << 8);
560b57cec5SDimitry Andric   return true;
570b57cec5SDimitry Andric }
580b57cec5SDimitry Andric 
readInstruction64(ArrayRef<uint8_t> Bytes,uint64_t Address,uint64_t & Size,uint64_t & Insn)590b57cec5SDimitry Andric static bool readInstruction64(ArrayRef<uint8_t> Bytes, uint64_t Address,
600b57cec5SDimitry Andric                               uint64_t &Size, uint64_t &Insn) {
610b57cec5SDimitry Andric   Size = 8;
620b57cec5SDimitry Andric   Insn = ((uint64_t)Bytes[0] << 16) | ((uint64_t)Bytes[1] << 24) |
630b57cec5SDimitry Andric          ((uint64_t)Bytes[2] << 0) | ((uint64_t)Bytes[3] << 8) |
640b57cec5SDimitry Andric          ((uint64_t)Bytes[4] << 48) | ((uint64_t)Bytes[5] << 56) |
650b57cec5SDimitry Andric          ((uint64_t)Bytes[6] << 32) | ((uint64_t)Bytes[7] << 40);
660b57cec5SDimitry Andric   return true;
670b57cec5SDimitry Andric }
680b57cec5SDimitry Andric 
readInstruction48(ArrayRef<uint8_t> Bytes,uint64_t Address,uint64_t & Size,uint64_t & Insn)690b57cec5SDimitry Andric static bool readInstruction48(ArrayRef<uint8_t> Bytes, uint64_t Address,
700b57cec5SDimitry Andric                               uint64_t &Size, uint64_t &Insn) {
710b57cec5SDimitry Andric   Size = 6;
720b57cec5SDimitry Andric   Insn = ((uint64_t)Bytes[0] << 0) | ((uint64_t)Bytes[1] << 8) |
730b57cec5SDimitry Andric          ((uint64_t)Bytes[2] << 32) | ((uint64_t)Bytes[3] << 40) |
740b57cec5SDimitry Andric          ((uint64_t)Bytes[4] << 16) | ((uint64_t)Bytes[5] << 24);
750b57cec5SDimitry Andric   return true;
760b57cec5SDimitry Andric }
770b57cec5SDimitry Andric 
readInstruction16(ArrayRef<uint8_t> Bytes,uint64_t Address,uint64_t & Size,uint32_t & Insn)780b57cec5SDimitry Andric static bool readInstruction16(ArrayRef<uint8_t> Bytes, uint64_t Address,
790b57cec5SDimitry Andric                               uint64_t &Size, uint32_t &Insn) {
800b57cec5SDimitry Andric   Size = 2;
810b57cec5SDimitry Andric   Insn = (Bytes[0] << 0) | (Bytes[1] << 8);
820b57cec5SDimitry Andric   return true;
830b57cec5SDimitry Andric }
840b57cec5SDimitry Andric 
850b57cec5SDimitry Andric template <unsigned B>
8681ad6265SDimitry Andric static DecodeStatus
8781ad6265SDimitry Andric DecodeSignedOperand(MCInst &Inst, unsigned InsnS, uint64_t Address = 0,
8881ad6265SDimitry Andric                     const MCDisassembler *Decoder = nullptr);
890b57cec5SDimitry Andric 
900b57cec5SDimitry Andric template <unsigned B>
9181ad6265SDimitry Andric static DecodeStatus
9281ad6265SDimitry Andric DecodeFromCyclicRange(MCInst &Inst, unsigned InsnS, uint64_t Address = 0,
9381ad6265SDimitry Andric                       const MCDisassembler *Decoder = nullptr);
940b57cec5SDimitry Andric 
950b57cec5SDimitry Andric template <unsigned B>
960b57cec5SDimitry Andric static DecodeStatus DecodeBranchTargetS(MCInst &Inst, unsigned InsnS,
9781ad6265SDimitry Andric                                         uint64_t Address,
9881ad6265SDimitry Andric                                         const MCDisassembler *Decoder);
990b57cec5SDimitry Andric 
10081ad6265SDimitry Andric static DecodeStatus DecodeMEMrs9(MCInst &, unsigned, uint64_t,
10181ad6265SDimitry Andric                                  const MCDisassembler *);
1020b57cec5SDimitry Andric 
1030b57cec5SDimitry Andric static DecodeStatus DecodeLdLImmInstruction(MCInst &, uint64_t, uint64_t,
10481ad6265SDimitry Andric                                             const MCDisassembler *);
1050b57cec5SDimitry Andric 
1060b57cec5SDimitry Andric static DecodeStatus DecodeStLImmInstruction(MCInst &, uint64_t, uint64_t,
10781ad6265SDimitry Andric                                             const MCDisassembler *);
1080b57cec5SDimitry Andric 
1090b57cec5SDimitry Andric static DecodeStatus DecodeLdRLImmInstruction(MCInst &, uint64_t, uint64_t,
11081ad6265SDimitry Andric                                              const MCDisassembler *);
1110b57cec5SDimitry Andric 
112349cc55cSDimitry Andric static DecodeStatus DecodeSOPwithRS12(MCInst &, uint64_t, uint64_t,
11381ad6265SDimitry Andric                                       const MCDisassembler *);
114349cc55cSDimitry Andric 
115349cc55cSDimitry Andric static DecodeStatus DecodeSOPwithRU6(MCInst &, uint64_t, uint64_t,
11681ad6265SDimitry Andric                                      const MCDisassembler *);
117349cc55cSDimitry Andric 
118fe6060f1SDimitry Andric static DecodeStatus DecodeCCRU6Instruction(MCInst &, uint64_t, uint64_t,
11981ad6265SDimitry Andric                                            const MCDisassembler *);
120fe6060f1SDimitry Andric 
1210b57cec5SDimitry Andric static DecodeStatus DecodeMoveHRegInstruction(MCInst &Inst, uint64_t, uint64_t,
12281ad6265SDimitry Andric                                               const MCDisassembler *);
1230b57cec5SDimitry Andric 
1240b57cec5SDimitry Andric static const uint16_t GPR32DecoderTable[] = {
1250b57cec5SDimitry Andric     ARC::R0,  ARC::R1,    ARC::R2,  ARC::R3,   ARC::R4,  ARC::R5,  ARC::R6,
1260b57cec5SDimitry Andric     ARC::R7,  ARC::R8,    ARC::R9,  ARC::R10,  ARC::R11, ARC::R12, ARC::R13,
1270b57cec5SDimitry Andric     ARC::R14, ARC::R15,   ARC::R16, ARC::R17,  ARC::R18, ARC::R19, ARC::R20,
1280b57cec5SDimitry Andric     ARC::R21, ARC::R22,   ARC::R23, ARC::R24,  ARC::R25, ARC::GP,  ARC::FP,
1290b57cec5SDimitry Andric     ARC::SP,  ARC::ILINK, ARC::R30, ARC::BLINK};
1300b57cec5SDimitry Andric 
DecodeGPR32RegisterClass(MCInst & Inst,unsigned RegNo,uint64_t Address,const MCDisassembler * Decoder)1310b57cec5SDimitry Andric static DecodeStatus DecodeGPR32RegisterClass(MCInst &Inst, unsigned RegNo,
1320b57cec5SDimitry Andric                                              uint64_t Address,
13381ad6265SDimitry Andric                                              const MCDisassembler *Decoder) {
1340b57cec5SDimitry Andric   if (RegNo >= 32) {
1350b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "Not a GPR32 register.");
1360b57cec5SDimitry Andric     return MCDisassembler::Fail;
1370b57cec5SDimitry Andric   }
1380b57cec5SDimitry Andric 
1390b57cec5SDimitry Andric   unsigned Reg = GPR32DecoderTable[RegNo];
1400b57cec5SDimitry Andric   Inst.addOperand(MCOperand::createReg(Reg));
1410b57cec5SDimitry Andric   return MCDisassembler::Success;
1420b57cec5SDimitry Andric }
1430b57cec5SDimitry Andric 
DecodeGBR32ShortRegister(MCInst & Inst,unsigned RegNo,uint64_t Address,const MCDisassembler * Decoder)1440b57cec5SDimitry Andric static DecodeStatus DecodeGBR32ShortRegister(MCInst &Inst, unsigned RegNo,
1450b57cec5SDimitry Andric                                              uint64_t Address,
14681ad6265SDimitry Andric                                              const MCDisassembler *Decoder) {
1470b57cec5SDimitry Andric   // Enumerates registers from ranges [r0-r3],[r12-r15].
1480b57cec5SDimitry Andric   if (RegNo > 3)
1490b57cec5SDimitry Andric     RegNo += 8; // 4 for r12, etc...
1500b57cec5SDimitry Andric 
1510b57cec5SDimitry Andric   return DecodeGPR32RegisterClass(Inst, RegNo, Address, Decoder);
1520b57cec5SDimitry Andric }
1530b57cec5SDimitry Andric 
1540b57cec5SDimitry Andric #include "ARCGenDisassemblerTables.inc"
1550b57cec5SDimitry Andric 
decodeCField(unsigned Insn)1560b57cec5SDimitry Andric static unsigned decodeCField(unsigned Insn) {
1570b57cec5SDimitry Andric   return fieldFromInstruction(Insn, 6, 6);
1580b57cec5SDimitry Andric }
1590b57cec5SDimitry Andric 
decodeBField(unsigned Insn)1600b57cec5SDimitry Andric static unsigned decodeBField(unsigned Insn) {
1610b57cec5SDimitry Andric   return (fieldFromInstruction(Insn, 12, 3) << 3) |
1620b57cec5SDimitry Andric          fieldFromInstruction(Insn, 24, 3);
1630b57cec5SDimitry Andric }
1640b57cec5SDimitry Andric 
decodeAField(unsigned Insn)1650b57cec5SDimitry Andric static unsigned decodeAField(unsigned Insn) {
1660b57cec5SDimitry Andric   return fieldFromInstruction(Insn, 0, 6);
1670b57cec5SDimitry Andric }
1680b57cec5SDimitry Andric 
DecodeMEMrs9(MCInst & Inst,unsigned Insn,uint64_t Address,const MCDisassembler * Dec)1690b57cec5SDimitry Andric static DecodeStatus DecodeMEMrs9(MCInst &Inst, unsigned Insn, uint64_t Address,
17081ad6265SDimitry Andric                                  const MCDisassembler *Dec) {
1710b57cec5SDimitry Andric   // We have the 9-bit immediate in the low bits, 6-bit register in high bits.
1720b57cec5SDimitry Andric   unsigned S9 = Insn & 0x1ff;
1730b57cec5SDimitry Andric   unsigned R = (Insn & (0x7fff & ~0x1ff)) >> 9;
1740b57cec5SDimitry Andric   DecodeGPR32RegisterClass(Inst, R, Address, Dec);
1750b57cec5SDimitry Andric   Inst.addOperand(MCOperand::createImm(SignExtend32<9>(S9)));
1760b57cec5SDimitry Andric   return MCDisassembler::Success;
1770b57cec5SDimitry Andric }
1780b57cec5SDimitry Andric 
DecodeSymbolicOperand(MCInst & Inst,uint64_t Address,uint64_t Value,const MCDisassembler * Decoder)1790b57cec5SDimitry Andric static bool DecodeSymbolicOperand(MCInst &Inst, uint64_t Address,
18081ad6265SDimitry Andric                                   uint64_t Value,
18181ad6265SDimitry Andric                                   const MCDisassembler *Decoder) {
182fe6060f1SDimitry Andric   static const uint64_t AtLeast = 2;
18381ad6265SDimitry Andric   return (nullptr != Decoder && Decoder->tryAddingSymbolicOperand(
18481ad6265SDimitry Andric                                     Inst, Value, Address, true, 0, AtLeast, 0));
1850b57cec5SDimitry Andric }
1860b57cec5SDimitry Andric 
DecodeSymbolicOperandOff(MCInst & Inst,uint64_t Address,uint64_t Offset,const MCDisassembler * Decoder)1870b57cec5SDimitry Andric static void DecodeSymbolicOperandOff(MCInst &Inst, uint64_t Address,
18881ad6265SDimitry Andric                                      uint64_t Offset,
18981ad6265SDimitry Andric                                      const MCDisassembler *Decoder) {
190fe6060f1SDimitry Andric   uint64_t NextAddress = Address + Offset;
1910b57cec5SDimitry Andric 
192fe6060f1SDimitry Andric   if (!DecodeSymbolicOperand(Inst, Address, NextAddress, Decoder))
1930b57cec5SDimitry Andric     Inst.addOperand(MCOperand::createImm(Offset));
1940b57cec5SDimitry Andric }
1950b57cec5SDimitry Andric 
1960b57cec5SDimitry Andric template <unsigned B>
DecodeBranchTargetS(MCInst & Inst,unsigned InsnS,uint64_t Address,const MCDisassembler * Decoder)1970b57cec5SDimitry Andric static DecodeStatus DecodeBranchTargetS(MCInst &Inst, unsigned InsnS,
19881ad6265SDimitry Andric                                         uint64_t Address,
19981ad6265SDimitry Andric                                         const MCDisassembler *Decoder) {
2000b57cec5SDimitry Andric 
2010b57cec5SDimitry Andric   static_assert(B > 0, "field is empty");
2020b57cec5SDimitry Andric   DecodeSymbolicOperandOff(Inst, Address, SignExtend32<B>(InsnS), Decoder);
2030b57cec5SDimitry Andric   return MCDisassembler::Success;
2040b57cec5SDimitry Andric }
2050b57cec5SDimitry Andric 
2060b57cec5SDimitry Andric template <unsigned B>
DecodeSignedOperand(MCInst & Inst,unsigned InsnS,uint64_t,const MCDisassembler *)2070b57cec5SDimitry Andric static DecodeStatus DecodeSignedOperand(MCInst &Inst, unsigned InsnS,
2080b57cec5SDimitry Andric                                         uint64_t /*Address*/,
20981ad6265SDimitry Andric                                         const MCDisassembler * /*Decoder*/) {
2100b57cec5SDimitry Andric 
2110b57cec5SDimitry Andric   static_assert(B > 0, "field is empty");
2120b57cec5SDimitry Andric   Inst.addOperand(MCOperand::createImm(
2130b57cec5SDimitry Andric       SignExtend32<B>(maskTrailingOnes<decltype(InsnS)>(B) & InsnS)));
2140b57cec5SDimitry Andric   return MCDisassembler::Success;
2150b57cec5SDimitry Andric }
2160b57cec5SDimitry Andric 
2170b57cec5SDimitry Andric template <unsigned B>
DecodeFromCyclicRange(MCInst & Inst,unsigned InsnS,uint64_t,const MCDisassembler *)2180b57cec5SDimitry Andric static DecodeStatus DecodeFromCyclicRange(MCInst &Inst, unsigned InsnS,
2190b57cec5SDimitry Andric                                           uint64_t /*Address*/,
22081ad6265SDimitry Andric                                           const MCDisassembler * /*Decoder*/) {
2210b57cec5SDimitry Andric 
2220b57cec5SDimitry Andric   static_assert(B > 0, "field is empty");
2230b57cec5SDimitry Andric   const unsigned max = (1u << B) - 1;
2240b57cec5SDimitry Andric   Inst.addOperand(
2250b57cec5SDimitry Andric       MCOperand::createImm(InsnS < max ? static_cast<int>(InsnS) : -1));
2260b57cec5SDimitry Andric   return MCDisassembler::Success;
2270b57cec5SDimitry Andric }
2280b57cec5SDimitry Andric 
DecodeStLImmInstruction(MCInst & Inst,uint64_t Insn,uint64_t Address,const MCDisassembler * Decoder)2290b57cec5SDimitry Andric static DecodeStatus DecodeStLImmInstruction(MCInst &Inst, uint64_t Insn,
2300b57cec5SDimitry Andric                                             uint64_t Address,
23181ad6265SDimitry Andric                                             const MCDisassembler *Decoder) {
2320b57cec5SDimitry Andric   unsigned SrcC, DstB, LImm;
2330b57cec5SDimitry Andric   DstB = decodeBField(Insn);
2340b57cec5SDimitry Andric   if (DstB != 62) {
2350b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "Decoding StLImm found non-limm register.");
2360b57cec5SDimitry Andric     return MCDisassembler::Fail;
2370b57cec5SDimitry Andric   }
2380b57cec5SDimitry Andric   SrcC = decodeCField(Insn);
2390b57cec5SDimitry Andric   DecodeGPR32RegisterClass(Inst, SrcC, Address, Decoder);
2400b57cec5SDimitry Andric   LImm = (Insn >> 32);
2410b57cec5SDimitry Andric   Inst.addOperand(MCOperand::createImm(LImm));
2420b57cec5SDimitry Andric   Inst.addOperand(MCOperand::createImm(0));
2430b57cec5SDimitry Andric   return MCDisassembler::Success;
2440b57cec5SDimitry Andric }
2450b57cec5SDimitry Andric 
DecodeLdLImmInstruction(MCInst & Inst,uint64_t Insn,uint64_t Address,const MCDisassembler * Decoder)2460b57cec5SDimitry Andric static DecodeStatus DecodeLdLImmInstruction(MCInst &Inst, uint64_t Insn,
2470b57cec5SDimitry Andric                                             uint64_t Address,
24881ad6265SDimitry Andric                                             const MCDisassembler *Decoder) {
2490b57cec5SDimitry Andric   unsigned DstA, SrcB, LImm;
2500b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "Decoding LdLImm:\n");
2510b57cec5SDimitry Andric   SrcB = decodeBField(Insn);
2520b57cec5SDimitry Andric   if (SrcB != 62) {
2530b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "Decoding LdLImm found non-limm register.");
2540b57cec5SDimitry Andric     return MCDisassembler::Fail;
2550b57cec5SDimitry Andric   }
2560b57cec5SDimitry Andric   DstA = decodeAField(Insn);
2570b57cec5SDimitry Andric   DecodeGPR32RegisterClass(Inst, DstA, Address, Decoder);
2580b57cec5SDimitry Andric   LImm = (Insn >> 32);
2590b57cec5SDimitry Andric   Inst.addOperand(MCOperand::createImm(LImm));
2600b57cec5SDimitry Andric   Inst.addOperand(MCOperand::createImm(0));
2610b57cec5SDimitry Andric   return MCDisassembler::Success;
2620b57cec5SDimitry Andric }
2630b57cec5SDimitry Andric 
DecodeLdRLImmInstruction(MCInst & Inst,uint64_t Insn,uint64_t Address,const MCDisassembler * Decoder)2640b57cec5SDimitry Andric static DecodeStatus DecodeLdRLImmInstruction(MCInst &Inst, uint64_t Insn,
2650b57cec5SDimitry Andric                                              uint64_t Address,
26681ad6265SDimitry Andric                                              const MCDisassembler *Decoder) {
2670b57cec5SDimitry Andric   unsigned DstA, SrcB;
2680b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "Decoding LdRLimm\n");
2690b57cec5SDimitry Andric   DstA = decodeAField(Insn);
2700b57cec5SDimitry Andric   DecodeGPR32RegisterClass(Inst, DstA, Address, Decoder);
2710b57cec5SDimitry Andric   SrcB = decodeBField(Insn);
2720b57cec5SDimitry Andric   DecodeGPR32RegisterClass(Inst, SrcB, Address, Decoder);
2730b57cec5SDimitry Andric   if (decodeCField(Insn) != 62) {
2740b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "Decoding LdRLimm found non-limm register.");
2750b57cec5SDimitry Andric     return MCDisassembler::Fail;
2760b57cec5SDimitry Andric   }
2770b57cec5SDimitry Andric   Inst.addOperand(MCOperand::createImm((uint32_t)(Insn >> 32)));
2780b57cec5SDimitry Andric   return MCDisassembler::Success;
2790b57cec5SDimitry Andric }
2800b57cec5SDimitry Andric 
DecodeMoveHRegInstruction(MCInst & Inst,uint64_t Insn,uint64_t Address,const MCDisassembler * Decoder)2810b57cec5SDimitry Andric static DecodeStatus DecodeMoveHRegInstruction(MCInst &Inst, uint64_t Insn,
2820b57cec5SDimitry Andric                                               uint64_t Address,
28381ad6265SDimitry Andric                                               const MCDisassembler *Decoder) {
2840b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "Decoding MOV_S h-register\n");
2850b57cec5SDimitry Andric   using Field = decltype(Insn);
286fe6060f1SDimitry Andric   Field H = fieldFromInstruction(Insn, 5, 3) |
2870b57cec5SDimitry Andric             (fieldFromInstruction(Insn, 0, 2) << 3);
288fe6060f1SDimitry Andric   Field G = fieldFromInstruction(Insn, 8, 3) |
2890b57cec5SDimitry Andric             (fieldFromInstruction(Insn, 3, 2) << 3);
2900b57cec5SDimitry Andric 
2910b57cec5SDimitry Andric   auto DecodeRegisterOrImm = [&Inst, Address, Decoder](Field RegNum,
2920b57cec5SDimitry Andric                                                        Field Value) {
2930b57cec5SDimitry Andric     if (30 == RegNum) {
2940b57cec5SDimitry Andric       Inst.addOperand(MCOperand::createImm(Value));
2950b57cec5SDimitry Andric       return MCDisassembler::Success;
2960b57cec5SDimitry Andric     }
2970b57cec5SDimitry Andric 
2980b57cec5SDimitry Andric     return DecodeGPR32RegisterClass(Inst, RegNum, Address, Decoder);
2990b57cec5SDimitry Andric   };
3000b57cec5SDimitry Andric 
301fe6060f1SDimitry Andric   if (MCDisassembler::Success != DecodeRegisterOrImm(G, 0))
3020b57cec5SDimitry Andric     return MCDisassembler::Fail;
3030b57cec5SDimitry Andric 
304fe6060f1SDimitry Andric   return DecodeRegisterOrImm(H, Insn >> 16u);
305fe6060f1SDimitry Andric }
306fe6060f1SDimitry Andric 
DecodeCCRU6Instruction(MCInst & Inst,uint64_t Insn,uint64_t Address,const MCDisassembler * Decoder)307fe6060f1SDimitry Andric static DecodeStatus DecodeCCRU6Instruction(MCInst &Inst, uint64_t Insn,
308fe6060f1SDimitry Andric                                            uint64_t Address,
30981ad6265SDimitry Andric                                            const MCDisassembler *Decoder) {
310fe6060f1SDimitry Andric   unsigned DstB;
311fe6060f1SDimitry Andric   LLVM_DEBUG(dbgs() << "Decoding CCRU6 instruction:\n");
312fe6060f1SDimitry Andric   DstB = decodeBField(Insn);
313fe6060f1SDimitry Andric   DecodeGPR32RegisterClass(Inst, DstB, Address, Decoder);
314fe6060f1SDimitry Andric   using Field = decltype(Insn);
315349cc55cSDimitry Andric   Field U6Field = fieldFromInstruction(Insn, 6, 6);
316fe6060f1SDimitry Andric   Inst.addOperand(MCOperand::createImm(U6Field));
317fe6060f1SDimitry Andric   Field CCField = fieldFromInstruction(Insn, 0, 4);
318fe6060f1SDimitry Andric   Inst.addOperand(MCOperand::createImm(CCField));
319fe6060f1SDimitry Andric   return MCDisassembler::Success;
3200b57cec5SDimitry Andric }
3210b57cec5SDimitry Andric 
DecodeSOPwithRU6(MCInst & Inst,uint64_t Insn,uint64_t Address,const MCDisassembler * Decoder)322349cc55cSDimitry Andric static DecodeStatus DecodeSOPwithRU6(MCInst &Inst, uint64_t Insn,
32381ad6265SDimitry Andric                                      uint64_t Address,
32481ad6265SDimitry Andric                                      const MCDisassembler *Decoder) {
325349cc55cSDimitry Andric   unsigned DstB = decodeBField(Insn);
326349cc55cSDimitry Andric   DecodeGPR32RegisterClass(Inst, DstB, Address, Decoder);
327349cc55cSDimitry Andric   using Field = decltype(Insn);
328349cc55cSDimitry Andric   Field U6 = fieldFromInstruction(Insn, 6, 6);
329349cc55cSDimitry Andric   Inst.addOperand(MCOperand::createImm(U6));
330349cc55cSDimitry Andric   return MCDisassembler::Success;
331349cc55cSDimitry Andric }
332349cc55cSDimitry Andric 
DecodeSOPwithRS12(MCInst & Inst,uint64_t Insn,uint64_t Address,const MCDisassembler * Decoder)333349cc55cSDimitry Andric static DecodeStatus DecodeSOPwithRS12(MCInst &Inst, uint64_t Insn,
33481ad6265SDimitry Andric                                       uint64_t Address,
33581ad6265SDimitry Andric                                       const MCDisassembler *Decoder) {
336349cc55cSDimitry Andric   unsigned DstB = decodeBField(Insn);
337349cc55cSDimitry Andric   DecodeGPR32RegisterClass(Inst, DstB, Address, Decoder);
338349cc55cSDimitry Andric   using Field = decltype(Insn);
339349cc55cSDimitry Andric   Field Lower = fieldFromInstruction(Insn, 6, 6);
340349cc55cSDimitry Andric   Field Upper = fieldFromInstruction(Insn, 0, 5);
341349cc55cSDimitry Andric   Field Sign = fieldFromInstruction(Insn, 5, 1) ? -1 : 1;
342349cc55cSDimitry Andric   Field Result = Sign * ((Upper << 6) + Lower);
343349cc55cSDimitry Andric   Inst.addOperand(MCOperand::createImm(Result));
344349cc55cSDimitry Andric   return MCDisassembler::Success;
345349cc55cSDimitry Andric }
346349cc55cSDimitry Andric 
getInstruction(MCInst & Instr,uint64_t & Size,ArrayRef<uint8_t> Bytes,uint64_t Address,raw_ostream & cStream) const3470b57cec5SDimitry Andric DecodeStatus ARCDisassembler::getInstruction(MCInst &Instr, uint64_t &Size,
3480b57cec5SDimitry Andric                                              ArrayRef<uint8_t> Bytes,
3490b57cec5SDimitry Andric                                              uint64_t Address,
3500b57cec5SDimitry Andric                                              raw_ostream &cStream) const {
3510b57cec5SDimitry Andric   MCDisassembler::DecodeStatus Result;
3520b57cec5SDimitry Andric   if (Bytes.size() < 2) {
3530b57cec5SDimitry Andric     Size = 0;
3540b57cec5SDimitry Andric     return Fail;
3550b57cec5SDimitry Andric   }
3560b57cec5SDimitry Andric   uint8_t DecodeByte = (Bytes[1] & 0xF7) >> 3;
3570b57cec5SDimitry Andric   // 0x00 -> 0x07 are 32-bit instructions.
3580b57cec5SDimitry Andric   // 0x08 -> 0x1F are 16-bit instructions.
3590b57cec5SDimitry Andric   if (DecodeByte < 0x08) {
3600b57cec5SDimitry Andric     // 32-bit instruction.
3610b57cec5SDimitry Andric     if (Bytes.size() < 4) {
3620b57cec5SDimitry Andric       // Did we decode garbage?
3630b57cec5SDimitry Andric       Size = 0;
3640b57cec5SDimitry Andric       return Fail;
3650b57cec5SDimitry Andric     }
3660b57cec5SDimitry Andric     if (Bytes.size() >= 8) {
3670b57cec5SDimitry Andric       // Attempt to decode 64-bit instruction.
3680b57cec5SDimitry Andric       uint64_t Insn64;
3690b57cec5SDimitry Andric       if (!readInstruction64(Bytes, Address, Size, Insn64))
3700b57cec5SDimitry Andric         return Fail;
3710b57cec5SDimitry Andric       Result =
3720b57cec5SDimitry Andric           decodeInstruction(DecoderTable64, Instr, Insn64, Address, this, STI);
3730b57cec5SDimitry Andric       if (Success == Result) {
3740b57cec5SDimitry Andric         LLVM_DEBUG(dbgs() << "Successfully decoded 64-bit instruction.");
3750b57cec5SDimitry Andric         return Result;
3760b57cec5SDimitry Andric       }
3770b57cec5SDimitry Andric       LLVM_DEBUG(dbgs() << "Not a 64-bit instruction, falling back to 32-bit.");
3780b57cec5SDimitry Andric     }
3790b57cec5SDimitry Andric     uint32_t Insn32;
3800b57cec5SDimitry Andric     if (!readInstruction32(Bytes, Address, Size, Insn32)) {
3810b57cec5SDimitry Andric       return Fail;
3820b57cec5SDimitry Andric     }
3830b57cec5SDimitry Andric     // Calling the auto-generated decoder function.
3840b57cec5SDimitry Andric     return decodeInstruction(DecoderTable32, Instr, Insn32, Address, this, STI);
3850b57cec5SDimitry Andric   } else {
3860b57cec5SDimitry Andric     if (Bytes.size() >= 6) {
3870b57cec5SDimitry Andric       // Attempt to treat as instr. with limm data.
3880b57cec5SDimitry Andric       uint64_t Insn48;
3890b57cec5SDimitry Andric       if (!readInstruction48(Bytes, Address, Size, Insn48))
3900b57cec5SDimitry Andric         return Fail;
3910b57cec5SDimitry Andric       Result =
3920b57cec5SDimitry Andric           decodeInstruction(DecoderTable48, Instr, Insn48, Address, this, STI);
3930b57cec5SDimitry Andric       if (Success == Result) {
3940b57cec5SDimitry Andric         LLVM_DEBUG(
3950b57cec5SDimitry Andric             dbgs() << "Successfully decoded 16-bit instruction with limm.");
3960b57cec5SDimitry Andric         return Result;
3970b57cec5SDimitry Andric       }
3980b57cec5SDimitry Andric       LLVM_DEBUG(
3990b57cec5SDimitry Andric           dbgs() << "Not a 16-bit instruction with limm, try without it.");
4000b57cec5SDimitry Andric     }
4010b57cec5SDimitry Andric 
4020b57cec5SDimitry Andric     uint32_t Insn16;
4030b57cec5SDimitry Andric     if (!readInstruction16(Bytes, Address, Size, Insn16))
4040b57cec5SDimitry Andric       return Fail;
4050b57cec5SDimitry Andric 
4060b57cec5SDimitry Andric     // Calling the auto-generated decoder function.
4070b57cec5SDimitry Andric     return decodeInstruction(DecoderTable16, Instr, Insn16, Address, this, STI);
4080b57cec5SDimitry Andric   }
4090b57cec5SDimitry Andric }
4100b57cec5SDimitry Andric 
createARCDisassembler(const Target & T,const MCSubtargetInfo & STI,MCContext & Ctx)4110b57cec5SDimitry Andric static MCDisassembler *createARCDisassembler(const Target &T,
4120b57cec5SDimitry Andric                                              const MCSubtargetInfo &STI,
4130b57cec5SDimitry Andric                                              MCContext &Ctx) {
4140b57cec5SDimitry Andric   return new ARCDisassembler(STI, Ctx, T.createMCInstrInfo());
4150b57cec5SDimitry Andric }
4160b57cec5SDimitry Andric 
LLVMInitializeARCDisassembler()417480093f4SDimitry Andric extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeARCDisassembler() {
4180b57cec5SDimitry Andric   // Register the disassembler.
4190b57cec5SDimitry Andric   TargetRegistry::RegisterMCDisassembler(getTheARCTarget(),
4200b57cec5SDimitry Andric                                          createARCDisassembler);
4210b57cec5SDimitry Andric }
422