12cab237bSDimitry Andric //===- ARCDisassembler.cpp - Disassembler for ARC ---------------*- C++ -*-===//
22cab237bSDimitry Andric //
32cab237bSDimitry Andric //                     The LLVM Compiler Infrastructure
42cab237bSDimitry Andric //
52cab237bSDimitry Andric // This file is distributed under the University of Illinois Open Source
62cab237bSDimitry Andric // License. See LICENSE.TXT for details.
72cab237bSDimitry Andric //
82cab237bSDimitry Andric //===----------------------------------------------------------------------===//
92cab237bSDimitry Andric ///
102cab237bSDimitry Andric /// \file
11*4ba319b5SDimitry Andric /// This file is part of the ARC Disassembler.
122cab237bSDimitry Andric ///
132cab237bSDimitry Andric //===----------------------------------------------------------------------===//
142cab237bSDimitry Andric 
152cab237bSDimitry Andric #include "ARC.h"
162cab237bSDimitry Andric #include "ARCRegisterInfo.h"
172cab237bSDimitry Andric #include "MCTargetDesc/ARCMCTargetDesc.h"
182cab237bSDimitry Andric #include "llvm/MC/MCContext.h"
192cab237bSDimitry Andric #include "llvm/MC/MCDisassembler/MCDisassembler.h"
202cab237bSDimitry Andric #include "llvm/MC/MCFixedLenDisassembler.h"
212cab237bSDimitry Andric #include "llvm/MC/MCInst.h"
222cab237bSDimitry Andric #include "llvm/MC/MCInstrInfo.h"
232cab237bSDimitry Andric #include "llvm/MC/MCSubtargetInfo.h"
242cab237bSDimitry Andric #include "llvm/Support/TargetRegistry.h"
252cab237bSDimitry Andric 
262cab237bSDimitry Andric using namespace llvm;
272cab237bSDimitry Andric 
282cab237bSDimitry Andric #define DEBUG_TYPE "arc-disassembler"
292cab237bSDimitry Andric 
302cab237bSDimitry Andric using DecodeStatus = MCDisassembler::DecodeStatus;
312cab237bSDimitry Andric 
322cab237bSDimitry Andric namespace {
332cab237bSDimitry Andric 
34*4ba319b5SDimitry Andric /// A disassembler class for ARC.
352cab237bSDimitry Andric class ARCDisassembler : public MCDisassembler {
362cab237bSDimitry Andric public:
372cab237bSDimitry Andric   std::unique_ptr<MCInstrInfo const> const MCII;
382cab237bSDimitry Andric 
ARCDisassembler(const MCSubtargetInfo & STI,MCContext & Ctx,MCInstrInfo const * MCII)392cab237bSDimitry Andric   ARCDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx,
402cab237bSDimitry Andric                   MCInstrInfo const *MCII)
412cab237bSDimitry Andric       : MCDisassembler(STI, Ctx), MCII(MCII) {}
422cab237bSDimitry Andric 
432cab237bSDimitry Andric   DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size,
442cab237bSDimitry Andric                               ArrayRef<uint8_t> Bytes, uint64_t Address,
452cab237bSDimitry Andric                               raw_ostream &VStream,
462cab237bSDimitry Andric                               raw_ostream &CStream) const override;
472cab237bSDimitry Andric };
482cab237bSDimitry Andric 
492cab237bSDimitry Andric } // end anonymous namespace
502cab237bSDimitry Andric 
readInstruction32(ArrayRef<uint8_t> Bytes,uint64_t Address,uint64_t & Size,uint32_t & Insn)512cab237bSDimitry Andric static bool readInstruction32(ArrayRef<uint8_t> Bytes, uint64_t Address,
522cab237bSDimitry Andric                               uint64_t &Size, uint32_t &Insn) {
532cab237bSDimitry Andric   Size = 4;
542cab237bSDimitry Andric   // Read 2 16-bit values, but swap hi/lo parts.
552cab237bSDimitry Andric   Insn =
562cab237bSDimitry Andric       (Bytes[0] << 16) | (Bytes[1] << 24) | (Bytes[2] << 0) | (Bytes[3] << 8);
572cab237bSDimitry Andric   return true;
582cab237bSDimitry Andric }
592cab237bSDimitry Andric 
readInstruction64(ArrayRef<uint8_t> Bytes,uint64_t Address,uint64_t & Size,uint64_t & Insn)602cab237bSDimitry Andric static bool readInstruction64(ArrayRef<uint8_t> Bytes, uint64_t Address,
612cab237bSDimitry Andric                               uint64_t &Size, uint64_t &Insn) {
622cab237bSDimitry Andric   Size = 8;
632cab237bSDimitry Andric   Insn = ((uint64_t)Bytes[0] << 16) | ((uint64_t)Bytes[1] << 24) |
642cab237bSDimitry Andric          ((uint64_t)Bytes[2] << 0) | ((uint64_t)Bytes[3] << 8) |
652cab237bSDimitry Andric          ((uint64_t)Bytes[4] << 48) | ((uint64_t)Bytes[5] << 56) |
662cab237bSDimitry Andric          ((uint64_t)Bytes[6] << 32) | ((uint64_t)Bytes[7] << 40);
672cab237bSDimitry Andric   return true;
682cab237bSDimitry Andric }
692cab237bSDimitry Andric 
readInstruction48(ArrayRef<uint8_t> Bytes,uint64_t Address,uint64_t & Size,uint64_t & Insn)702cab237bSDimitry Andric static bool readInstruction48(ArrayRef<uint8_t> Bytes, uint64_t Address,
712cab237bSDimitry Andric                               uint64_t &Size, uint64_t &Insn) {
722cab237bSDimitry Andric   Size = 6;
732cab237bSDimitry Andric   Insn = ((uint64_t)Bytes[0] << 0) | ((uint64_t)Bytes[1] << 8) |
742cab237bSDimitry Andric          ((uint64_t)Bytes[2] << 32) | ((uint64_t)Bytes[3] << 40) |
752cab237bSDimitry Andric          ((uint64_t)Bytes[4] << 16) | ((uint64_t)Bytes[5] << 24);
762cab237bSDimitry Andric   return true;
772cab237bSDimitry Andric }
782cab237bSDimitry Andric 
readInstruction16(ArrayRef<uint8_t> Bytes,uint64_t Address,uint64_t & Size,uint32_t & Insn)792cab237bSDimitry Andric static bool readInstruction16(ArrayRef<uint8_t> Bytes, uint64_t Address,
802cab237bSDimitry Andric                               uint64_t &Size, uint32_t &Insn) {
812cab237bSDimitry Andric   Size = 2;
822cab237bSDimitry Andric   Insn = (Bytes[0] << 0) | (Bytes[1] << 8);
832cab237bSDimitry Andric   return true;
842cab237bSDimitry Andric }
852cab237bSDimitry Andric 
862cab237bSDimitry Andric template <unsigned B>
872cab237bSDimitry Andric static DecodeStatus DecodeSignedOperand(MCInst &Inst, unsigned InsnS,
882cab237bSDimitry Andric                                         uint64_t Address = 0,
892cab237bSDimitry Andric                                         const void *Decoder = nullptr);
902cab237bSDimitry Andric 
912cab237bSDimitry Andric template <unsigned B>
922cab237bSDimitry Andric static DecodeStatus DecodeFromCyclicRange(MCInst &Inst, unsigned InsnS,
932cab237bSDimitry Andric                                         uint64_t Address = 0,
942cab237bSDimitry Andric                                         const void *Decoder = nullptr);
952cab237bSDimitry Andric 
962cab237bSDimitry Andric template <unsigned B>
972cab237bSDimitry Andric static DecodeStatus DecodeBranchTargetS(MCInst &Inst, unsigned InsnS,
982cab237bSDimitry Andric                                         uint64_t Address, const void *Decoder);
992cab237bSDimitry Andric 
1002cab237bSDimitry Andric static DecodeStatus DecodeMEMrs9(MCInst &, unsigned, uint64_t, const void *);
1012cab237bSDimitry Andric 
1022cab237bSDimitry Andric static DecodeStatus DecodeLdLImmInstruction(MCInst &, uint64_t, uint64_t,
1032cab237bSDimitry Andric                                             const void *);
1042cab237bSDimitry Andric 
1052cab237bSDimitry Andric static DecodeStatus DecodeStLImmInstruction(MCInst &, uint64_t, uint64_t,
1062cab237bSDimitry Andric                                             const void *);
1072cab237bSDimitry Andric 
1082cab237bSDimitry Andric static DecodeStatus DecodeLdRLImmInstruction(MCInst &, uint64_t, uint64_t,
1092cab237bSDimitry Andric                                              const void *);
1102cab237bSDimitry Andric 
1112cab237bSDimitry Andric static DecodeStatus DecodeMoveHRegInstruction(MCInst &Inst, uint64_t, uint64_t,
1122cab237bSDimitry Andric                                               const void *);
1132cab237bSDimitry Andric 
1142cab237bSDimitry Andric static const uint16_t GPR32DecoderTable[] = {
1152cab237bSDimitry Andric     ARC::R0,  ARC::R1,    ARC::R2,  ARC::R3,   ARC::R4,  ARC::R5,  ARC::R6,
1162cab237bSDimitry Andric     ARC::R7,  ARC::R8,    ARC::R9,  ARC::R10,  ARC::R11, ARC::R12, ARC::R13,
1172cab237bSDimitry Andric     ARC::R14, ARC::R15,   ARC::R16, ARC::R17,  ARC::R18, ARC::R19, ARC::R20,
1182cab237bSDimitry Andric     ARC::R21, ARC::R22,   ARC::R23, ARC::R24,  ARC::R25, ARC::GP,  ARC::FP,
1192cab237bSDimitry Andric     ARC::SP,  ARC::ILINK, ARC::R30, ARC::BLINK};
1202cab237bSDimitry Andric 
DecodeGPR32RegisterClass(MCInst & Inst,unsigned RegNo,uint64_t Address,const void * Decoder)1212cab237bSDimitry Andric static DecodeStatus DecodeGPR32RegisterClass(MCInst &Inst, unsigned RegNo,
1222cab237bSDimitry Andric                                              uint64_t Address,
1232cab237bSDimitry Andric                                              const void *Decoder) {
1242cab237bSDimitry Andric   if (RegNo >= 32) {
125*4ba319b5SDimitry Andric     LLVM_DEBUG(dbgs() << "Not a GPR32 register.");
1262cab237bSDimitry Andric     return MCDisassembler::Fail;
1272cab237bSDimitry Andric   }
1282cab237bSDimitry Andric 
1292cab237bSDimitry Andric   unsigned Reg = GPR32DecoderTable[RegNo];
1302cab237bSDimitry Andric   Inst.addOperand(MCOperand::createReg(Reg));
1312cab237bSDimitry Andric   return MCDisassembler::Success;
1322cab237bSDimitry Andric }
1332cab237bSDimitry Andric 
DecodeGBR32ShortRegister(MCInst & Inst,unsigned RegNo,uint64_t Address,const void * Decoder)1342cab237bSDimitry Andric static DecodeStatus DecodeGBR32ShortRegister(MCInst &Inst, unsigned RegNo,
1352cab237bSDimitry Andric                                                uint64_t Address,
1362cab237bSDimitry Andric                                                const void *Decoder) {
1372cab237bSDimitry Andric   // Enumerates registers from ranges [r0-r3],[r12-r15].
1382cab237bSDimitry Andric   if (RegNo > 3)
1392cab237bSDimitry Andric     RegNo += 8; // 4 for r12, etc...
1402cab237bSDimitry Andric 
1412cab237bSDimitry Andric   return DecodeGPR32RegisterClass(Inst, RegNo, Address, Decoder);
1422cab237bSDimitry Andric }
1432cab237bSDimitry Andric 
1442cab237bSDimitry Andric #include "ARCGenDisassemblerTables.inc"
1452cab237bSDimitry Andric 
decodeCField(unsigned Insn)1462cab237bSDimitry Andric static unsigned decodeCField(unsigned Insn) {
1472cab237bSDimitry Andric   return fieldFromInstruction(Insn, 6, 6);
1482cab237bSDimitry Andric }
1492cab237bSDimitry Andric 
decodeBField(unsigned Insn)1502cab237bSDimitry Andric static unsigned decodeBField(unsigned Insn) {
1512cab237bSDimitry Andric   return (fieldFromInstruction(Insn, 12, 3) << 3) |
1522cab237bSDimitry Andric          fieldFromInstruction(Insn, 24, 3);
1532cab237bSDimitry Andric }
1542cab237bSDimitry Andric 
decodeAField(unsigned Insn)1552cab237bSDimitry Andric static unsigned decodeAField(unsigned Insn) {
1562cab237bSDimitry Andric   return fieldFromInstruction(Insn, 0, 6);
1572cab237bSDimitry Andric }
1582cab237bSDimitry Andric 
DecodeMEMrs9(MCInst & Inst,unsigned Insn,uint64_t Address,const void * Dec)1592cab237bSDimitry Andric static DecodeStatus DecodeMEMrs9(MCInst &Inst, unsigned Insn, uint64_t Address,
1602cab237bSDimitry Andric                                  const void *Dec) {
1612cab237bSDimitry Andric   // We have the 9-bit immediate in the low bits, 6-bit register in high bits.
1622cab237bSDimitry Andric   unsigned S9 = Insn & 0x1ff;
1632cab237bSDimitry Andric   unsigned R = (Insn & (0x7fff & ~0x1ff)) >> 9;
1642cab237bSDimitry Andric   DecodeGPR32RegisterClass(Inst, R, Address, Dec);
1652cab237bSDimitry Andric   Inst.addOperand(MCOperand::createImm(SignExtend32<9>(S9)));
1662cab237bSDimitry Andric   return MCDisassembler::Success;
1672cab237bSDimitry Andric }
1682cab237bSDimitry Andric 
DecodeSymbolicOperand(MCInst & Inst,uint64_t Address,uint64_t Value,const void * Decoder)1692cab237bSDimitry Andric static bool DecodeSymbolicOperand(MCInst &Inst, uint64_t Address,
1702cab237bSDimitry Andric                                   uint64_t Value, const void *Decoder) {
1712cab237bSDimitry Andric   static const uint64_t atLeast = 2;
1722cab237bSDimitry Andric   // TODO: Try to force emitter to use MCDisassembler* instead of void*.
1732cab237bSDimitry Andric   auto Disassembler = static_cast<const MCDisassembler *>(Decoder);
1742cab237bSDimitry Andric   return (nullptr != Disassembler &&
1752cab237bSDimitry Andric           Disassembler->tryAddingSymbolicOperand(Inst, Value, Address, true, 0,
1762cab237bSDimitry Andric                                                  atLeast));
1772cab237bSDimitry Andric }
1782cab237bSDimitry Andric 
DecodeSymbolicOperandOff(MCInst & Inst,uint64_t Address,uint64_t Offset,const void * Decoder)1792cab237bSDimitry Andric static void DecodeSymbolicOperandOff(MCInst &Inst, uint64_t Address,
1802cab237bSDimitry Andric                                      uint64_t Offset, const void *Decoder) {
1812cab237bSDimitry Andric   uint64_t nextAddress = Address + Offset;
1822cab237bSDimitry Andric 
1832cab237bSDimitry Andric   if (!DecodeSymbolicOperand(Inst, Address, nextAddress, Decoder))
1842cab237bSDimitry Andric     Inst.addOperand(MCOperand::createImm(Offset));
1852cab237bSDimitry Andric }
1862cab237bSDimitry Andric 
1872cab237bSDimitry Andric template <unsigned B>
DecodeBranchTargetS(MCInst & Inst,unsigned InsnS,uint64_t Address,const void * Decoder)1882cab237bSDimitry Andric static DecodeStatus DecodeBranchTargetS(MCInst &Inst, unsigned InsnS,
1892cab237bSDimitry Andric                                         uint64_t Address, const void *Decoder) {
1902cab237bSDimitry Andric 
1912cab237bSDimitry Andric   static_assert(B > 0, "field is empty");
1922cab237bSDimitry Andric   DecodeSymbolicOperandOff(Inst, Address, SignExtend32<B>(InsnS), Decoder);
1932cab237bSDimitry Andric   return MCDisassembler::Success;
1942cab237bSDimitry Andric }
1952cab237bSDimitry Andric 
1962cab237bSDimitry Andric template <unsigned B>
DecodeSignedOperand(MCInst & Inst,unsigned InsnS,uint64_t,const void *)1972cab237bSDimitry Andric static DecodeStatus DecodeSignedOperand(MCInst &Inst, unsigned InsnS,
1982cab237bSDimitry Andric                                         uint64_t /*Address*/,
1992cab237bSDimitry Andric                                         const void * /*Decoder*/) {
2002cab237bSDimitry Andric 
2012cab237bSDimitry Andric   static_assert(B > 0, "field is empty");
2022cab237bSDimitry Andric   Inst.addOperand(MCOperand::createImm(
2032cab237bSDimitry Andric       SignExtend32<B>(maskTrailingOnes<decltype(InsnS)>(B) & InsnS)));
2042cab237bSDimitry Andric   return MCDisassembler::Success;
2052cab237bSDimitry Andric }
2062cab237bSDimitry Andric 
2072cab237bSDimitry Andric template <unsigned B>
DecodeFromCyclicRange(MCInst & Inst,unsigned InsnS,uint64_t,const void *)2082cab237bSDimitry Andric static DecodeStatus DecodeFromCyclicRange(MCInst &Inst, unsigned InsnS,
2092cab237bSDimitry Andric                                           uint64_t /*Address*/,
2102cab237bSDimitry Andric                                           const void * /*Decoder*/) {
2112cab237bSDimitry Andric 
2122cab237bSDimitry Andric   static_assert(B > 0, "field is empty");
2132cab237bSDimitry Andric   const unsigned max = (1u << B) - 1;
2142cab237bSDimitry Andric   Inst.addOperand(
2152cab237bSDimitry Andric       MCOperand::createImm(InsnS < max ? static_cast<int>(InsnS) : -1));
2162cab237bSDimitry Andric   return MCDisassembler::Success;
2172cab237bSDimitry Andric }
2182cab237bSDimitry Andric 
DecodeStLImmInstruction(MCInst & Inst,uint64_t Insn,uint64_t Address,const void * Decoder)2192cab237bSDimitry Andric static DecodeStatus DecodeStLImmInstruction(MCInst &Inst, uint64_t Insn,
2202cab237bSDimitry Andric                                             uint64_t Address,
2212cab237bSDimitry Andric                                             const void *Decoder) {
2222cab237bSDimitry Andric   unsigned SrcC, DstB, LImm;
2232cab237bSDimitry Andric   DstB = decodeBField(Insn);
2242cab237bSDimitry Andric   if (DstB != 62) {
225*4ba319b5SDimitry Andric     LLVM_DEBUG(dbgs() << "Decoding StLImm found non-limm register.");
2262cab237bSDimitry Andric     return MCDisassembler::Fail;
2272cab237bSDimitry Andric   }
2282cab237bSDimitry Andric   SrcC = decodeCField(Insn);
2292cab237bSDimitry Andric   DecodeGPR32RegisterClass(Inst, SrcC, Address, Decoder);
2302cab237bSDimitry Andric   LImm = (Insn >> 32);
2312cab237bSDimitry Andric   Inst.addOperand(MCOperand::createImm(LImm));
2322cab237bSDimitry Andric   Inst.addOperand(MCOperand::createImm(0));
2332cab237bSDimitry Andric   return MCDisassembler::Success;
2342cab237bSDimitry Andric }
2352cab237bSDimitry Andric 
DecodeLdLImmInstruction(MCInst & Inst,uint64_t Insn,uint64_t Address,const void * Decoder)2362cab237bSDimitry Andric static DecodeStatus DecodeLdLImmInstruction(MCInst &Inst, uint64_t Insn,
2372cab237bSDimitry Andric                                             uint64_t Address,
2382cab237bSDimitry Andric                                             const void *Decoder) {
2392cab237bSDimitry Andric   unsigned DstA, SrcB, LImm;
240*4ba319b5SDimitry Andric   LLVM_DEBUG(dbgs() << "Decoding LdLImm:\n");
2412cab237bSDimitry Andric   SrcB = decodeBField(Insn);
2422cab237bSDimitry Andric   if (SrcB != 62) {
243*4ba319b5SDimitry Andric     LLVM_DEBUG(dbgs() << "Decoding LdLImm found non-limm register.");
2442cab237bSDimitry Andric     return MCDisassembler::Fail;
2452cab237bSDimitry Andric   }
2462cab237bSDimitry Andric   DstA = decodeAField(Insn);
2472cab237bSDimitry Andric   DecodeGPR32RegisterClass(Inst, DstA, Address, Decoder);
2482cab237bSDimitry Andric   LImm = (Insn >> 32);
2492cab237bSDimitry Andric   Inst.addOperand(MCOperand::createImm(LImm));
2502cab237bSDimitry Andric   Inst.addOperand(MCOperand::createImm(0));
2512cab237bSDimitry Andric   return MCDisassembler::Success;
2522cab237bSDimitry Andric }
2532cab237bSDimitry Andric 
DecodeLdRLImmInstruction(MCInst & Inst,uint64_t Insn,uint64_t Address,const void * Decoder)2542cab237bSDimitry Andric static DecodeStatus DecodeLdRLImmInstruction(MCInst &Inst, uint64_t Insn,
2552cab237bSDimitry Andric                                              uint64_t Address,
2562cab237bSDimitry Andric                                              const void *Decoder) {
2572cab237bSDimitry Andric   unsigned DstA, SrcB;
258*4ba319b5SDimitry Andric   LLVM_DEBUG(dbgs() << "Decoding LdRLimm\n");
2592cab237bSDimitry Andric   DstA = decodeAField(Insn);
2602cab237bSDimitry Andric   DecodeGPR32RegisterClass(Inst, DstA, Address, Decoder);
2612cab237bSDimitry Andric   SrcB = decodeBField(Insn);
2622cab237bSDimitry Andric   DecodeGPR32RegisterClass(Inst, SrcB, Address, Decoder);
2632cab237bSDimitry Andric   if (decodeCField(Insn) != 62) {
264*4ba319b5SDimitry Andric     LLVM_DEBUG(dbgs() << "Decoding LdRLimm found non-limm register.");
2652cab237bSDimitry Andric     return MCDisassembler::Fail;
2662cab237bSDimitry Andric   }
2672cab237bSDimitry Andric   Inst.addOperand(MCOperand::createImm((uint32_t)(Insn >> 32)));
2682cab237bSDimitry Andric   return MCDisassembler::Success;
2692cab237bSDimitry Andric }
2702cab237bSDimitry Andric 
DecodeMoveHRegInstruction(MCInst & Inst,uint64_t Insn,uint64_t Address,const void * Decoder)2712cab237bSDimitry Andric static DecodeStatus DecodeMoveHRegInstruction(MCInst &Inst, uint64_t Insn,
2722cab237bSDimitry Andric                                               uint64_t Address,
2732cab237bSDimitry Andric                                               const void *Decoder) {
274*4ba319b5SDimitry Andric   LLVM_DEBUG(dbgs() << "Decoding MOV_S h-register\n");
2752cab237bSDimitry Andric   using Field = decltype(Insn);
2762cab237bSDimitry Andric   Field h = fieldFromInstruction(Insn, 5, 3) |
2772cab237bSDimitry Andric             (fieldFromInstruction(Insn, 0, 2) << 3);
2782cab237bSDimitry Andric   Field g = fieldFromInstruction(Insn, 8, 3) |
2792cab237bSDimitry Andric             (fieldFromInstruction(Insn, 3, 2) << 3);
2802cab237bSDimitry Andric 
2812cab237bSDimitry Andric   auto DecodeRegisterOrImm = [&Inst, Address, Decoder](Field RegNum,
2822cab237bSDimitry Andric                                                        Field Value) {
2832cab237bSDimitry Andric     if (30 == RegNum) {
2842cab237bSDimitry Andric       Inst.addOperand(MCOperand::createImm(Value));
2852cab237bSDimitry Andric       return MCDisassembler::Success;
2862cab237bSDimitry Andric     }
2872cab237bSDimitry Andric 
2882cab237bSDimitry Andric     return DecodeGPR32RegisterClass(Inst, RegNum, Address, Decoder);
2892cab237bSDimitry Andric   };
2902cab237bSDimitry Andric 
2912cab237bSDimitry Andric   if (MCDisassembler::Success != DecodeRegisterOrImm(g, 0))
2922cab237bSDimitry Andric     return MCDisassembler::Fail;
2932cab237bSDimitry Andric 
2942cab237bSDimitry Andric   return DecodeRegisterOrImm(h, Insn >> 16u);
2952cab237bSDimitry Andric }
2962cab237bSDimitry Andric 
getInstruction(MCInst & Instr,uint64_t & Size,ArrayRef<uint8_t> Bytes,uint64_t Address,raw_ostream & vStream,raw_ostream & cStream) const2972cab237bSDimitry Andric DecodeStatus ARCDisassembler::getInstruction(MCInst &Instr, uint64_t &Size,
2982cab237bSDimitry Andric                                              ArrayRef<uint8_t> Bytes,
2992cab237bSDimitry Andric                                              uint64_t Address,
3002cab237bSDimitry Andric                                              raw_ostream &vStream,
3012cab237bSDimitry Andric                                              raw_ostream &cStream) const {
3022cab237bSDimitry Andric   MCDisassembler::DecodeStatus Result;
3032cab237bSDimitry Andric   if (Bytes.size() < 2) {
3042cab237bSDimitry Andric     Size = 0;
3052cab237bSDimitry Andric     return Fail;
3062cab237bSDimitry Andric   }
3072cab237bSDimitry Andric   uint8_t DecodeByte = (Bytes[1] & 0xF7) >> 3;
3082cab237bSDimitry Andric   // 0x00 -> 0x07 are 32-bit instructions.
3092cab237bSDimitry Andric   // 0x08 -> 0x1F are 16-bit instructions.
3102cab237bSDimitry Andric   if (DecodeByte < 0x08) {
3112cab237bSDimitry Andric     // 32-bit instruction.
3122cab237bSDimitry Andric     if (Bytes.size() < 4) {
3132cab237bSDimitry Andric       // Did we decode garbage?
3142cab237bSDimitry Andric       Size = 0;
3152cab237bSDimitry Andric       return Fail;
3162cab237bSDimitry Andric     }
3172cab237bSDimitry Andric     if (Bytes.size() >= 8) {
3182cab237bSDimitry Andric       // Attempt to decode 64-bit instruction.
3192cab237bSDimitry Andric       uint64_t Insn64;
3202cab237bSDimitry Andric       if (!readInstruction64(Bytes, Address, Size, Insn64))
3212cab237bSDimitry Andric         return Fail;
3222cab237bSDimitry Andric       Result =
3232cab237bSDimitry Andric           decodeInstruction(DecoderTable64, Instr, Insn64, Address, this, STI);
3242cab237bSDimitry Andric       if (Success == Result) {
325*4ba319b5SDimitry Andric         LLVM_DEBUG(dbgs() << "Successfully decoded 64-bit instruction.");
3262cab237bSDimitry Andric         return Result;
3272cab237bSDimitry Andric       }
328*4ba319b5SDimitry Andric       LLVM_DEBUG(dbgs() << "Not a 64-bit instruction, falling back to 32-bit.");
3292cab237bSDimitry Andric     }
3302cab237bSDimitry Andric     uint32_t Insn32;
3312cab237bSDimitry Andric     if (!readInstruction32(Bytes, Address, Size, Insn32)) {
3322cab237bSDimitry Andric       return Fail;
3332cab237bSDimitry Andric     }
3342cab237bSDimitry Andric     // Calling the auto-generated decoder function.
3352cab237bSDimitry Andric     return decodeInstruction(DecoderTable32, Instr, Insn32, Address, this, STI);
3362cab237bSDimitry Andric   } else {
3372cab237bSDimitry Andric     if (Bytes.size() >= 6) {
3382cab237bSDimitry Andric       // Attempt to treat as instr. with limm data.
3392cab237bSDimitry Andric       uint64_t Insn48;
3402cab237bSDimitry Andric       if (!readInstruction48(Bytes, Address, Size, Insn48))
3412cab237bSDimitry Andric         return Fail;
3422cab237bSDimitry Andric       Result =
3432cab237bSDimitry Andric           decodeInstruction(DecoderTable48, Instr, Insn48, Address, this, STI);
3442cab237bSDimitry Andric       if (Success == Result) {
345*4ba319b5SDimitry Andric         LLVM_DEBUG(
346*4ba319b5SDimitry Andric             dbgs() << "Successfully decoded 16-bit instruction with limm.");
3472cab237bSDimitry Andric         return Result;
3482cab237bSDimitry Andric       }
349*4ba319b5SDimitry Andric       LLVM_DEBUG(
350*4ba319b5SDimitry Andric           dbgs() << "Not a 16-bit instruction with limm, try without it.");
3512cab237bSDimitry Andric     }
3522cab237bSDimitry Andric 
3532cab237bSDimitry Andric     uint32_t Insn16;
3542cab237bSDimitry Andric     if (!readInstruction16(Bytes, Address, Size, Insn16))
3552cab237bSDimitry Andric       return Fail;
3562cab237bSDimitry Andric 
3572cab237bSDimitry Andric     // Calling the auto-generated decoder function.
3582cab237bSDimitry Andric     return decodeInstruction(DecoderTable16, Instr, Insn16, Address, this, STI);
3592cab237bSDimitry Andric   }
3602cab237bSDimitry Andric }
3612cab237bSDimitry Andric 
createARCDisassembler(const Target & T,const MCSubtargetInfo & STI,MCContext & Ctx)3622cab237bSDimitry Andric static MCDisassembler *createARCDisassembler(const Target &T,
3632cab237bSDimitry Andric                                              const MCSubtargetInfo &STI,
3642cab237bSDimitry Andric                                              MCContext &Ctx) {
3652cab237bSDimitry Andric   return new ARCDisassembler(STI, Ctx, T.createMCInstrInfo());
3662cab237bSDimitry Andric }
3672cab237bSDimitry Andric 
LLVMInitializeARCDisassembler()3682cab237bSDimitry Andric extern "C" void LLVMInitializeARCDisassembler() {
3692cab237bSDimitry Andric   // Register the disassembler.
3702cab237bSDimitry Andric   TargetRegistry::RegisterMCDisassembler(getTheARCTarget(),
3712cab237bSDimitry Andric                                          createARCDisassembler);
3722cab237bSDimitry Andric }
373