12d1f6d67SPete Couperus //===- ARCDisassembler.cpp - Disassembler for ARC ---------------*- C++ -*-===//
22d1f6d67SPete Couperus //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
62d1f6d67SPete Couperus //
72d1f6d67SPete Couperus //===----------------------------------------------------------------------===//
82d1f6d67SPete Couperus ///
92d1f6d67SPete Couperus /// \file
105f8f34e4SAdrian Prantl /// This file is part of the ARC Disassembler.
112d1f6d67SPete Couperus ///
122d1f6d67SPete Couperus //===----------------------------------------------------------------------===//
132d1f6d67SPete Couperus
142d1f6d67SPete Couperus #include "ARC.h"
152d1f6d67SPete Couperus #include "ARCRegisterInfo.h"
162d1f6d67SPete Couperus #include "MCTargetDesc/ARCMCTargetDesc.h"
177f9a008aSRichard Trieu #include "TargetInfo/ARCTargetInfo.h"
182d1f6d67SPete Couperus #include "llvm/MC/MCContext.h"
19c644488aSSheng #include "llvm/MC/MCDecoderOps.h"
202d1f6d67SPete Couperus #include "llvm/MC/MCDisassembler/MCDisassembler.h"
212d1f6d67SPete Couperus #include "llvm/MC/MCInst.h"
222d1f6d67SPete Couperus #include "llvm/MC/MCInstrInfo.h"
232d1f6d67SPete Couperus #include "llvm/MC/MCSubtargetInfo.h"
2489b57061SReid Kleckner #include "llvm/MC/TargetRegistry.h"
252d1f6d67SPete Couperus
262d1f6d67SPete Couperus using namespace llvm;
272d1f6d67SPete Couperus
282d1f6d67SPete Couperus #define DEBUG_TYPE "arc-disassembler"
292d1f6d67SPete Couperus
302d1f6d67SPete Couperus using DecodeStatus = MCDisassembler::DecodeStatus;
312d1f6d67SPete Couperus
322d1f6d67SPete Couperus namespace {
332d1f6d67SPete Couperus
345f8f34e4SAdrian Prantl /// A disassembler class for ARC.
352d1f6d67SPete Couperus class ARCDisassembler : public MCDisassembler {
362d1f6d67SPete Couperus public:
372d1f6d67SPete Couperus std::unique_ptr<MCInstrInfo const> const MCII;
382d1f6d67SPete Couperus
ARCDisassembler(const MCSubtargetInfo & STI,MCContext & Ctx,MCInstrInfo const * MCII)392d1f6d67SPete Couperus ARCDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx,
402d1f6d67SPete Couperus MCInstrInfo const *MCII)
412d1f6d67SPete Couperus : MCDisassembler(STI, Ctx), MCII(MCII) {}
422d1f6d67SPete Couperus
432d1f6d67SPete Couperus DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size,
442d1f6d67SPete Couperus ArrayRef<uint8_t> Bytes, uint64_t Address,
452d1f6d67SPete Couperus raw_ostream &CStream) const override;
462d1f6d67SPete Couperus };
472d1f6d67SPete Couperus
482d1f6d67SPete Couperus } // end anonymous namespace
492d1f6d67SPete Couperus
readInstruction32(ArrayRef<uint8_t> Bytes,uint64_t Address,uint64_t & Size,uint32_t & Insn)502d1f6d67SPete Couperus static bool readInstruction32(ArrayRef<uint8_t> Bytes, uint64_t Address,
512d1f6d67SPete Couperus uint64_t &Size, uint32_t &Insn) {
522d1f6d67SPete Couperus Size = 4;
532d1f6d67SPete Couperus // Read 2 16-bit values, but swap hi/lo parts.
542d1f6d67SPete Couperus Insn =
552d1f6d67SPete Couperus (Bytes[0] << 16) | (Bytes[1] << 24) | (Bytes[2] << 0) | (Bytes[3] << 8);
562d1f6d67SPete Couperus return true;
572d1f6d67SPete Couperus }
582d1f6d67SPete Couperus
readInstruction64(ArrayRef<uint8_t> Bytes,uint64_t Address,uint64_t & Size,uint64_t & Insn)592d1f6d67SPete Couperus static bool readInstruction64(ArrayRef<uint8_t> Bytes, uint64_t Address,
602d1f6d67SPete Couperus uint64_t &Size, uint64_t &Insn) {
612d1f6d67SPete Couperus Size = 8;
622d1f6d67SPete Couperus Insn = ((uint64_t)Bytes[0] << 16) | ((uint64_t)Bytes[1] << 24) |
632d1f6d67SPete Couperus ((uint64_t)Bytes[2] << 0) | ((uint64_t)Bytes[3] << 8) |
642d1f6d67SPete Couperus ((uint64_t)Bytes[4] << 48) | ((uint64_t)Bytes[5] << 56) |
652d1f6d67SPete Couperus ((uint64_t)Bytes[6] << 32) | ((uint64_t)Bytes[7] << 40);
662d1f6d67SPete Couperus return true;
672d1f6d67SPete Couperus }
682d1f6d67SPete Couperus
readInstruction48(ArrayRef<uint8_t> Bytes,uint64_t Address,uint64_t & Size,uint64_t & Insn)69f665f6a2STatyana Krasnukha static bool readInstruction48(ArrayRef<uint8_t> Bytes, uint64_t Address,
70f665f6a2STatyana Krasnukha uint64_t &Size, uint64_t &Insn) {
71f665f6a2STatyana Krasnukha Size = 6;
72f665f6a2STatyana Krasnukha Insn = ((uint64_t)Bytes[0] << 0) | ((uint64_t)Bytes[1] << 8) |
73f665f6a2STatyana Krasnukha ((uint64_t)Bytes[2] << 32) | ((uint64_t)Bytes[3] << 40) |
74f665f6a2STatyana Krasnukha ((uint64_t)Bytes[4] << 16) | ((uint64_t)Bytes[5] << 24);
75f665f6a2STatyana Krasnukha return true;
76f665f6a2STatyana Krasnukha }
77f665f6a2STatyana Krasnukha
readInstruction16(ArrayRef<uint8_t> Bytes,uint64_t Address,uint64_t & Size,uint32_t & Insn)782d1f6d67SPete Couperus static bool readInstruction16(ArrayRef<uint8_t> Bytes, uint64_t Address,
792d1f6d67SPete Couperus uint64_t &Size, uint32_t &Insn) {
802d1f6d67SPete Couperus Size = 2;
812d1f6d67SPete Couperus Insn = (Bytes[0] << 0) | (Bytes[1] << 8);
822d1f6d67SPete Couperus return true;
832d1f6d67SPete Couperus }
842d1f6d67SPete Couperus
85f665f6a2STatyana Krasnukha template <unsigned B>
864ae9745aSMaksim Panchenko static DecodeStatus
874ae9745aSMaksim Panchenko DecodeSignedOperand(MCInst &Inst, unsigned InsnS, uint64_t Address = 0,
884ae9745aSMaksim Panchenko const MCDisassembler *Decoder = nullptr);
892d1f6d67SPete Couperus
90f665f6a2STatyana Krasnukha template <unsigned B>
914ae9745aSMaksim Panchenko static DecodeStatus
924ae9745aSMaksim Panchenko DecodeFromCyclicRange(MCInst &Inst, unsigned InsnS, uint64_t Address = 0,
934ae9745aSMaksim Panchenko const MCDisassembler *Decoder = nullptr);
942d1f6d67SPete Couperus
95f665f6a2STatyana Krasnukha template <unsigned B>
96f665f6a2STatyana Krasnukha static DecodeStatus DecodeBranchTargetS(MCInst &Inst, unsigned InsnS,
974ae9745aSMaksim Panchenko uint64_t Address,
984ae9745aSMaksim Panchenko const MCDisassembler *Decoder);
992d1f6d67SPete Couperus
1004ae9745aSMaksim Panchenko static DecodeStatus DecodeMEMrs9(MCInst &, unsigned, uint64_t,
1014ae9745aSMaksim Panchenko const MCDisassembler *);
1022d1f6d67SPete Couperus
103f665f6a2STatyana Krasnukha static DecodeStatus DecodeLdLImmInstruction(MCInst &, uint64_t, uint64_t,
1044ae9745aSMaksim Panchenko const MCDisassembler *);
1052d1f6d67SPete Couperus
106f665f6a2STatyana Krasnukha static DecodeStatus DecodeStLImmInstruction(MCInst &, uint64_t, uint64_t,
1074ae9745aSMaksim Panchenko const MCDisassembler *);
1082d1f6d67SPete Couperus
109f665f6a2STatyana Krasnukha static DecodeStatus DecodeLdRLImmInstruction(MCInst &, uint64_t, uint64_t,
1104ae9745aSMaksim Panchenko const MCDisassembler *);
1112d1f6d67SPete Couperus
112ce1dc9d6SThomas Johnson static DecodeStatus DecodeSOPwithRS12(MCInst &, uint64_t, uint64_t,
1134ae9745aSMaksim Panchenko const MCDisassembler *);
114ce1dc9d6SThomas Johnson
115ce1dc9d6SThomas Johnson static DecodeStatus DecodeSOPwithRU6(MCInst &, uint64_t, uint64_t,
1164ae9745aSMaksim Panchenko const MCDisassembler *);
117ce1dc9d6SThomas Johnson
1186b3eba7cSThomas Johnson static DecodeStatus DecodeCCRU6Instruction(MCInst &, uint64_t, uint64_t,
1194ae9745aSMaksim Panchenko const MCDisassembler *);
1206b3eba7cSThomas Johnson
121f665f6a2STatyana Krasnukha static DecodeStatus DecodeMoveHRegInstruction(MCInst &Inst, uint64_t, uint64_t,
1224ae9745aSMaksim Panchenko const MCDisassembler *);
1232d1f6d67SPete Couperus
1242d1f6d67SPete Couperus static const uint16_t GPR32DecoderTable[] = {
1252d1f6d67SPete Couperus ARC::R0, ARC::R1, ARC::R2, ARC::R3, ARC::R4, ARC::R5, ARC::R6,
1262d1f6d67SPete Couperus ARC::R7, ARC::R8, ARC::R9, ARC::R10, ARC::R11, ARC::R12, ARC::R13,
1272d1f6d67SPete Couperus ARC::R14, ARC::R15, ARC::R16, ARC::R17, ARC::R18, ARC::R19, ARC::R20,
1282d1f6d67SPete Couperus ARC::R21, ARC::R22, ARC::R23, ARC::R24, ARC::R25, ARC::GP, ARC::FP,
1292d1f6d67SPete Couperus ARC::SP, ARC::ILINK, ARC::R30, ARC::BLINK};
1302d1f6d67SPete Couperus
DecodeGPR32RegisterClass(MCInst & Inst,unsigned RegNo,uint64_t Address,const MCDisassembler * Decoder)1312d1f6d67SPete Couperus static DecodeStatus DecodeGPR32RegisterClass(MCInst &Inst, unsigned RegNo,
1322d1f6d67SPete Couperus uint64_t Address,
1334ae9745aSMaksim Panchenko const MCDisassembler *Decoder) {
1342d1f6d67SPete Couperus if (RegNo >= 32) {
135d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << "Not a GPR32 register.");
1362d1f6d67SPete Couperus return MCDisassembler::Fail;
1372d1f6d67SPete Couperus }
138f665f6a2STatyana Krasnukha
1392d1f6d67SPete Couperus unsigned Reg = GPR32DecoderTable[RegNo];
1402d1f6d67SPete Couperus Inst.addOperand(MCOperand::createReg(Reg));
1412d1f6d67SPete Couperus return MCDisassembler::Success;
1422d1f6d67SPete Couperus }
1432d1f6d67SPete Couperus
DecodeGBR32ShortRegister(MCInst & Inst,unsigned RegNo,uint64_t Address,const MCDisassembler * Decoder)144f665f6a2STatyana Krasnukha static DecodeStatus DecodeGBR32ShortRegister(MCInst &Inst, unsigned RegNo,
145f665f6a2STatyana Krasnukha uint64_t Address,
1464ae9745aSMaksim Panchenko const MCDisassembler *Decoder) {
147f665f6a2STatyana Krasnukha // Enumerates registers from ranges [r0-r3],[r12-r15].
148f665f6a2STatyana Krasnukha if (RegNo > 3)
149f665f6a2STatyana Krasnukha RegNo += 8; // 4 for r12, etc...
150f665f6a2STatyana Krasnukha
151f665f6a2STatyana Krasnukha return DecodeGPR32RegisterClass(Inst, RegNo, Address, Decoder);
152f665f6a2STatyana Krasnukha }
153f665f6a2STatyana Krasnukha
1542d1f6d67SPete Couperus #include "ARCGenDisassemblerTables.inc"
1552d1f6d67SPete Couperus
decodeCField(unsigned Insn)1562d1f6d67SPete Couperus static unsigned decodeCField(unsigned Insn) {
1572d1f6d67SPete Couperus return fieldFromInstruction(Insn, 6, 6);
1582d1f6d67SPete Couperus }
1592d1f6d67SPete Couperus
decodeBField(unsigned Insn)1602d1f6d67SPete Couperus static unsigned decodeBField(unsigned Insn) {
1612d1f6d67SPete Couperus return (fieldFromInstruction(Insn, 12, 3) << 3) |
1622d1f6d67SPete Couperus fieldFromInstruction(Insn, 24, 3);
1632d1f6d67SPete Couperus }
1642d1f6d67SPete Couperus
decodeAField(unsigned Insn)1652d1f6d67SPete Couperus static unsigned decodeAField(unsigned Insn) {
1662d1f6d67SPete Couperus return fieldFromInstruction(Insn, 0, 6);
1672d1f6d67SPete Couperus }
1682d1f6d67SPete Couperus
DecodeMEMrs9(MCInst & Inst,unsigned Insn,uint64_t Address,const MCDisassembler * Dec)169f665f6a2STatyana Krasnukha static DecodeStatus DecodeMEMrs9(MCInst &Inst, unsigned Insn, uint64_t Address,
1704ae9745aSMaksim Panchenko const MCDisassembler *Dec) {
1712d1f6d67SPete Couperus // We have the 9-bit immediate in the low bits, 6-bit register in high bits.
1722d1f6d67SPete Couperus unsigned S9 = Insn & 0x1ff;
1732d1f6d67SPete Couperus unsigned R = (Insn & (0x7fff & ~0x1ff)) >> 9;
1742d1f6d67SPete Couperus DecodeGPR32RegisterClass(Inst, R, Address, Dec);
1752d1f6d67SPete Couperus Inst.addOperand(MCOperand::createImm(SignExtend32<9>(S9)));
1762d1f6d67SPete Couperus return MCDisassembler::Success;
1772d1f6d67SPete Couperus }
1782d1f6d67SPete Couperus
DecodeSymbolicOperand(MCInst & Inst,uint64_t Address,uint64_t Value,const MCDisassembler * Decoder)179f665f6a2STatyana Krasnukha static bool DecodeSymbolicOperand(MCInst &Inst, uint64_t Address,
1804ae9745aSMaksim Panchenko uint64_t Value,
1814ae9745aSMaksim Panchenko const MCDisassembler *Decoder) {
1826b3eba7cSThomas Johnson static const uint64_t AtLeast = 2;
1834ae9745aSMaksim Panchenko return (nullptr != Decoder && Decoder->tryAddingSymbolicOperand(
184*bed9efedSMaksim Panchenko Inst, Value, Address, true, 0, AtLeast, 0));
185f665f6a2STatyana Krasnukha }
186f665f6a2STatyana Krasnukha
DecodeSymbolicOperandOff(MCInst & Inst,uint64_t Address,uint64_t Offset,const MCDisassembler * Decoder)187f665f6a2STatyana Krasnukha static void DecodeSymbolicOperandOff(MCInst &Inst, uint64_t Address,
1884ae9745aSMaksim Panchenko uint64_t Offset,
1894ae9745aSMaksim Panchenko const MCDisassembler *Decoder) {
1906b3eba7cSThomas Johnson uint64_t NextAddress = Address + Offset;
191f665f6a2STatyana Krasnukha
1926b3eba7cSThomas Johnson if (!DecodeSymbolicOperand(Inst, Address, NextAddress, Decoder))
193f665f6a2STatyana Krasnukha Inst.addOperand(MCOperand::createImm(Offset));
194f665f6a2STatyana Krasnukha }
195f665f6a2STatyana Krasnukha
196f665f6a2STatyana Krasnukha template <unsigned B>
DecodeBranchTargetS(MCInst & Inst,unsigned InsnS,uint64_t Address,const MCDisassembler * Decoder)197f665f6a2STatyana Krasnukha static DecodeStatus DecodeBranchTargetS(MCInst &Inst, unsigned InsnS,
1984ae9745aSMaksim Panchenko uint64_t Address,
1994ae9745aSMaksim Panchenko const MCDisassembler *Decoder) {
200f665f6a2STatyana Krasnukha
201f665f6a2STatyana Krasnukha static_assert(B > 0, "field is empty");
202f665f6a2STatyana Krasnukha DecodeSymbolicOperandOff(Inst, Address, SignExtend32<B>(InsnS), Decoder);
2032d1f6d67SPete Couperus return MCDisassembler::Success;
2042d1f6d67SPete Couperus }
2052d1f6d67SPete Couperus
206f665f6a2STatyana Krasnukha template <unsigned B>
DecodeSignedOperand(MCInst & Inst,unsigned InsnS,uint64_t,const MCDisassembler *)207f665f6a2STatyana Krasnukha static DecodeStatus DecodeSignedOperand(MCInst &Inst, unsigned InsnS,
208f665f6a2STatyana Krasnukha uint64_t /*Address*/,
2094ae9745aSMaksim Panchenko const MCDisassembler * /*Decoder*/) {
210f665f6a2STatyana Krasnukha
211f665f6a2STatyana Krasnukha static_assert(B > 0, "field is empty");
212f665f6a2STatyana Krasnukha Inst.addOperand(MCOperand::createImm(
213f665f6a2STatyana Krasnukha SignExtend32<B>(maskTrailingOnes<decltype(InsnS)>(B) & InsnS)));
2142d1f6d67SPete Couperus return MCDisassembler::Success;
2152d1f6d67SPete Couperus }
2162d1f6d67SPete Couperus
217f665f6a2STatyana Krasnukha template <unsigned B>
DecodeFromCyclicRange(MCInst & Inst,unsigned InsnS,uint64_t,const MCDisassembler *)218f665f6a2STatyana Krasnukha static DecodeStatus DecodeFromCyclicRange(MCInst &Inst, unsigned InsnS,
219f665f6a2STatyana Krasnukha uint64_t /*Address*/,
2204ae9745aSMaksim Panchenko const MCDisassembler * /*Decoder*/) {
221f665f6a2STatyana Krasnukha
222f665f6a2STatyana Krasnukha static_assert(B > 0, "field is empty");
223f665f6a2STatyana Krasnukha const unsigned max = (1u << B) - 1;
224f665f6a2STatyana Krasnukha Inst.addOperand(
225f665f6a2STatyana Krasnukha MCOperand::createImm(InsnS < max ? static_cast<int>(InsnS) : -1));
2262d1f6d67SPete Couperus return MCDisassembler::Success;
2272d1f6d67SPete Couperus }
2282d1f6d67SPete Couperus
DecodeStLImmInstruction(MCInst & Inst,uint64_t Insn,uint64_t Address,const MCDisassembler * Decoder)229f665f6a2STatyana Krasnukha static DecodeStatus DecodeStLImmInstruction(MCInst &Inst, uint64_t Insn,
2302d1f6d67SPete Couperus uint64_t Address,
2314ae9745aSMaksim Panchenko const MCDisassembler *Decoder) {
2322d1f6d67SPete Couperus unsigned SrcC, DstB, LImm;
2332d1f6d67SPete Couperus DstB = decodeBField(Insn);
2342d1f6d67SPete Couperus if (DstB != 62) {
235d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << "Decoding StLImm found non-limm register.");
2362d1f6d67SPete Couperus return MCDisassembler::Fail;
2372d1f6d67SPete Couperus }
2382d1f6d67SPete Couperus SrcC = decodeCField(Insn);
2392d1f6d67SPete Couperus DecodeGPR32RegisterClass(Inst, SrcC, Address, Decoder);
2402d1f6d67SPete Couperus LImm = (Insn >> 32);
2412d1f6d67SPete Couperus Inst.addOperand(MCOperand::createImm(LImm));
2422d1f6d67SPete Couperus Inst.addOperand(MCOperand::createImm(0));
2432d1f6d67SPete Couperus return MCDisassembler::Success;
2442d1f6d67SPete Couperus }
2452d1f6d67SPete Couperus
DecodeLdLImmInstruction(MCInst & Inst,uint64_t Insn,uint64_t Address,const MCDisassembler * Decoder)246f665f6a2STatyana Krasnukha static DecodeStatus DecodeLdLImmInstruction(MCInst &Inst, uint64_t Insn,
247f665f6a2STatyana Krasnukha uint64_t Address,
2484ae9745aSMaksim Panchenko const MCDisassembler *Decoder) {
2492d1f6d67SPete Couperus unsigned DstA, SrcB, LImm;
250d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << "Decoding LdLImm:\n");
2512d1f6d67SPete Couperus SrcB = decodeBField(Insn);
2522d1f6d67SPete Couperus if (SrcB != 62) {
253d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << "Decoding LdLImm found non-limm register.");
2542d1f6d67SPete Couperus return MCDisassembler::Fail;
2552d1f6d67SPete Couperus }
2562d1f6d67SPete Couperus DstA = decodeAField(Insn);
2572d1f6d67SPete Couperus DecodeGPR32RegisterClass(Inst, DstA, Address, Decoder);
2582d1f6d67SPete Couperus LImm = (Insn >> 32);
2592d1f6d67SPete Couperus Inst.addOperand(MCOperand::createImm(LImm));
2602d1f6d67SPete Couperus Inst.addOperand(MCOperand::createImm(0));
2612d1f6d67SPete Couperus return MCDisassembler::Success;
2622d1f6d67SPete Couperus }
2632d1f6d67SPete Couperus
DecodeLdRLImmInstruction(MCInst & Inst,uint64_t Insn,uint64_t Address,const MCDisassembler * Decoder)264f665f6a2STatyana Krasnukha static DecodeStatus DecodeLdRLImmInstruction(MCInst &Inst, uint64_t Insn,
265f665f6a2STatyana Krasnukha uint64_t Address,
2664ae9745aSMaksim Panchenko const MCDisassembler *Decoder) {
2672d1f6d67SPete Couperus unsigned DstA, SrcB;
268d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << "Decoding LdRLimm\n");
2692d1f6d67SPete Couperus DstA = decodeAField(Insn);
2702d1f6d67SPete Couperus DecodeGPR32RegisterClass(Inst, DstA, Address, Decoder);
2712d1f6d67SPete Couperus SrcB = decodeBField(Insn);
2722d1f6d67SPete Couperus DecodeGPR32RegisterClass(Inst, SrcB, Address, Decoder);
2732d1f6d67SPete Couperus if (decodeCField(Insn) != 62) {
274d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << "Decoding LdRLimm found non-limm register.");
2752d1f6d67SPete Couperus return MCDisassembler::Fail;
2762d1f6d67SPete Couperus }
2772d1f6d67SPete Couperus Inst.addOperand(MCOperand::createImm((uint32_t)(Insn >> 32)));
2782d1f6d67SPete Couperus return MCDisassembler::Success;
2792d1f6d67SPete Couperus }
2802d1f6d67SPete Couperus
DecodeMoveHRegInstruction(MCInst & Inst,uint64_t Insn,uint64_t Address,const MCDisassembler * Decoder)281f665f6a2STatyana Krasnukha static DecodeStatus DecodeMoveHRegInstruction(MCInst &Inst, uint64_t Insn,
282f665f6a2STatyana Krasnukha uint64_t Address,
2834ae9745aSMaksim Panchenko const MCDisassembler *Decoder) {
284d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << "Decoding MOV_S h-register\n");
285f665f6a2STatyana Krasnukha using Field = decltype(Insn);
2866b3eba7cSThomas Johnson Field H = fieldFromInstruction(Insn, 5, 3) |
287f665f6a2STatyana Krasnukha (fieldFromInstruction(Insn, 0, 2) << 3);
2886b3eba7cSThomas Johnson Field G = fieldFromInstruction(Insn, 8, 3) |
289f665f6a2STatyana Krasnukha (fieldFromInstruction(Insn, 3, 2) << 3);
290f665f6a2STatyana Krasnukha
291f665f6a2STatyana Krasnukha auto DecodeRegisterOrImm = [&Inst, Address, Decoder](Field RegNum,
292f665f6a2STatyana Krasnukha Field Value) {
293f665f6a2STatyana Krasnukha if (30 == RegNum) {
294f665f6a2STatyana Krasnukha Inst.addOperand(MCOperand::createImm(Value));
295f665f6a2STatyana Krasnukha return MCDisassembler::Success;
296f665f6a2STatyana Krasnukha }
297f665f6a2STatyana Krasnukha
298f665f6a2STatyana Krasnukha return DecodeGPR32RegisterClass(Inst, RegNum, Address, Decoder);
299f665f6a2STatyana Krasnukha };
300f665f6a2STatyana Krasnukha
3016b3eba7cSThomas Johnson if (MCDisassembler::Success != DecodeRegisterOrImm(G, 0))
302f665f6a2STatyana Krasnukha return MCDisassembler::Fail;
303f665f6a2STatyana Krasnukha
3046b3eba7cSThomas Johnson return DecodeRegisterOrImm(H, Insn >> 16u);
3056b3eba7cSThomas Johnson }
3066b3eba7cSThomas Johnson
DecodeCCRU6Instruction(MCInst & Inst,uint64_t Insn,uint64_t Address,const MCDisassembler * Decoder)3076b3eba7cSThomas Johnson static DecodeStatus DecodeCCRU6Instruction(MCInst &Inst, uint64_t Insn,
3086b3eba7cSThomas Johnson uint64_t Address,
3094ae9745aSMaksim Panchenko const MCDisassembler *Decoder) {
3106b3eba7cSThomas Johnson unsigned DstB;
3116b3eba7cSThomas Johnson LLVM_DEBUG(dbgs() << "Decoding CCRU6 instruction:\n");
3126b3eba7cSThomas Johnson DstB = decodeBField(Insn);
3136b3eba7cSThomas Johnson DecodeGPR32RegisterClass(Inst, DstB, Address, Decoder);
3146b3eba7cSThomas Johnson using Field = decltype(Insn);
315cc238a6eSThomas Johnson Field U6Field = fieldFromInstruction(Insn, 6, 6);
3166b3eba7cSThomas Johnson Inst.addOperand(MCOperand::createImm(U6Field));
3176b3eba7cSThomas Johnson Field CCField = fieldFromInstruction(Insn, 0, 4);
3186b3eba7cSThomas Johnson Inst.addOperand(MCOperand::createImm(CCField));
3196b3eba7cSThomas Johnson return MCDisassembler::Success;
320f665f6a2STatyana Krasnukha }
321f665f6a2STatyana Krasnukha
DecodeSOPwithRU6(MCInst & Inst,uint64_t Insn,uint64_t Address,const MCDisassembler * Decoder)322ce1dc9d6SThomas Johnson static DecodeStatus DecodeSOPwithRU6(MCInst &Inst, uint64_t Insn,
3234ae9745aSMaksim Panchenko uint64_t Address,
3244ae9745aSMaksim Panchenko const MCDisassembler *Decoder) {
325ce1dc9d6SThomas Johnson unsigned DstB = decodeBField(Insn);
326ce1dc9d6SThomas Johnson DecodeGPR32RegisterClass(Inst, DstB, Address, Decoder);
327ce1dc9d6SThomas Johnson using Field = decltype(Insn);
328ce1dc9d6SThomas Johnson Field U6 = fieldFromInstruction(Insn, 6, 6);
329ce1dc9d6SThomas Johnson Inst.addOperand(MCOperand::createImm(U6));
330ce1dc9d6SThomas Johnson return MCDisassembler::Success;
331ce1dc9d6SThomas Johnson }
332ce1dc9d6SThomas Johnson
DecodeSOPwithRS12(MCInst & Inst,uint64_t Insn,uint64_t Address,const MCDisassembler * Decoder)333ce1dc9d6SThomas Johnson static DecodeStatus DecodeSOPwithRS12(MCInst &Inst, uint64_t Insn,
3344ae9745aSMaksim Panchenko uint64_t Address,
3354ae9745aSMaksim Panchenko const MCDisassembler *Decoder) {
336ce1dc9d6SThomas Johnson unsigned DstB = decodeBField(Insn);
337ce1dc9d6SThomas Johnson DecodeGPR32RegisterClass(Inst, DstB, Address, Decoder);
338ce1dc9d6SThomas Johnson using Field = decltype(Insn);
339ce1dc9d6SThomas Johnson Field Lower = fieldFromInstruction(Insn, 6, 6);
340ce1dc9d6SThomas Johnson Field Upper = fieldFromInstruction(Insn, 0, 5);
341ce1dc9d6SThomas Johnson Field Sign = fieldFromInstruction(Insn, 5, 1) ? -1 : 1;
342ce1dc9d6SThomas Johnson Field Result = Sign * ((Upper << 6) + Lower);
343ce1dc9d6SThomas Johnson Inst.addOperand(MCOperand::createImm(Result));
344ce1dc9d6SThomas Johnson return MCDisassembler::Success;
345ce1dc9d6SThomas Johnson }
346ce1dc9d6SThomas Johnson
getInstruction(MCInst & Instr,uint64_t & Size,ArrayRef<uint8_t> Bytes,uint64_t Address,raw_ostream & cStream) const347f665f6a2STatyana Krasnukha DecodeStatus ARCDisassembler::getInstruction(MCInst &Instr, uint64_t &Size,
348f665f6a2STatyana Krasnukha ArrayRef<uint8_t> Bytes,
349f665f6a2STatyana Krasnukha uint64_t Address,
350f665f6a2STatyana Krasnukha raw_ostream &cStream) const {
3512d1f6d67SPete Couperus MCDisassembler::DecodeStatus Result;
3522d1f6d67SPete Couperus if (Bytes.size() < 2) {
3532d1f6d67SPete Couperus Size = 0;
3542d1f6d67SPete Couperus return Fail;
3552d1f6d67SPete Couperus }
3562d1f6d67SPete Couperus uint8_t DecodeByte = (Bytes[1] & 0xF7) >> 3;
3572d1f6d67SPete Couperus // 0x00 -> 0x07 are 32-bit instructions.
3582d1f6d67SPete Couperus // 0x08 -> 0x1F are 16-bit instructions.
3592d1f6d67SPete Couperus if (DecodeByte < 0x08) {
3602d1f6d67SPete Couperus // 32-bit instruction.
3612d1f6d67SPete Couperus if (Bytes.size() < 4) {
3622d1f6d67SPete Couperus // Did we decode garbage?
3632d1f6d67SPete Couperus Size = 0;
3642d1f6d67SPete Couperus return Fail;
3652d1f6d67SPete Couperus }
3662d1f6d67SPete Couperus if (Bytes.size() >= 8) {
3672d1f6d67SPete Couperus // Attempt to decode 64-bit instruction.
3682d1f6d67SPete Couperus uint64_t Insn64;
3692d1f6d67SPete Couperus if (!readInstruction64(Bytes, Address, Size, Insn64))
3702d1f6d67SPete Couperus return Fail;
3712d1f6d67SPete Couperus Result =
3722d1f6d67SPete Couperus decodeInstruction(DecoderTable64, Instr, Insn64, Address, this, STI);
373f665f6a2STatyana Krasnukha if (Success == Result) {
374d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << "Successfully decoded 64-bit instruction.");
375f665f6a2STatyana Krasnukha return Result;
3762d1f6d67SPete Couperus }
377d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << "Not a 64-bit instruction, falling back to 32-bit.");
3782d1f6d67SPete Couperus }
3792d1f6d67SPete Couperus uint32_t Insn32;
3802d1f6d67SPete Couperus if (!readInstruction32(Bytes, Address, Size, Insn32)) {
3812d1f6d67SPete Couperus return Fail;
3822d1f6d67SPete Couperus }
3832d1f6d67SPete Couperus // Calling the auto-generated decoder function.
3842d1f6d67SPete Couperus return decodeInstruction(DecoderTable32, Instr, Insn32, Address, this, STI);
385f665f6a2STatyana Krasnukha } else {
386f665f6a2STatyana Krasnukha if (Bytes.size() >= 6) {
387f665f6a2STatyana Krasnukha // Attempt to treat as instr. with limm data.
388f665f6a2STatyana Krasnukha uint64_t Insn48;
389f665f6a2STatyana Krasnukha if (!readInstruction48(Bytes, Address, Size, Insn48))
390f665f6a2STatyana Krasnukha return Fail;
391f665f6a2STatyana Krasnukha Result =
392f665f6a2STatyana Krasnukha decodeInstruction(DecoderTable48, Instr, Insn48, Address, this, STI);
393f665f6a2STatyana Krasnukha if (Success == Result) {
394d34e60caSNicola Zaghen LLVM_DEBUG(
395d34e60caSNicola Zaghen dbgs() << "Successfully decoded 16-bit instruction with limm.");
396f665f6a2STatyana Krasnukha return Result;
397f665f6a2STatyana Krasnukha }
398d34e60caSNicola Zaghen LLVM_DEBUG(
399d34e60caSNicola Zaghen dbgs() << "Not a 16-bit instruction with limm, try without it.");
4002d1f6d67SPete Couperus }
4012d1f6d67SPete Couperus
4022d1f6d67SPete Couperus uint32_t Insn16;
403f665f6a2STatyana Krasnukha if (!readInstruction16(Bytes, Address, Size, Insn16))
4042d1f6d67SPete Couperus return Fail;
405f665f6a2STatyana Krasnukha
4062d1f6d67SPete Couperus // Calling the auto-generated decoder function.
4072d1f6d67SPete Couperus return decodeInstruction(DecoderTable16, Instr, Insn16, Address, this, STI);
4082d1f6d67SPete Couperus }
409f665f6a2STatyana Krasnukha }
4102d1f6d67SPete Couperus
createARCDisassembler(const Target & T,const MCSubtargetInfo & STI,MCContext & Ctx)4112d1f6d67SPete Couperus static MCDisassembler *createARCDisassembler(const Target &T,
4122d1f6d67SPete Couperus const MCSubtargetInfo &STI,
4132d1f6d67SPete Couperus MCContext &Ctx) {
4142d1f6d67SPete Couperus return new ARCDisassembler(STI, Ctx, T.createMCInstrInfo());
4152d1f6d67SPete Couperus }
4162d1f6d67SPete Couperus
LLVMInitializeARCDisassembler()4170dbcb363STom Stellard extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeARCDisassembler() {
4182d1f6d67SPete Couperus // Register the disassembler.
4192d1f6d67SPete Couperus TargetRegistry::RegisterMCDisassembler(getTheARCTarget(),
4202d1f6d67SPete Couperus createARCDisassembler);
4212d1f6d67SPete Couperus }
422