| //===-- CSKYDisassembler.cpp - Disassembler for CSKY ----------------------===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This file implements the CSKYDisassembler class. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "MCTargetDesc/CSKYBaseInfo.h" |
| #include "MCTargetDesc/CSKYMCTargetDesc.h" |
| #include "TargetInfo/CSKYTargetInfo.h" |
| #include "llvm/ADT/DenseMap.h" |
| #include "llvm/MC/MCContext.h" |
| #include "llvm/MC/MCDecoderOps.h" |
| #include "llvm/MC/MCDisassembler/MCDisassembler.h" |
| #include "llvm/MC/MCInst.h" |
| #include "llvm/MC/MCInstrInfo.h" |
| #include "llvm/MC/MCRegisterInfo.h" |
| #include "llvm/MC/MCSubtargetInfo.h" |
| #include "llvm/MC/TargetRegistry.h" |
| #include "llvm/Support/Endian.h" |
| |
| using namespace llvm; |
| |
| #define DEBUG_TYPE "csky-disassembler" |
| |
| typedef MCDisassembler::DecodeStatus DecodeStatus; |
| |
| namespace { |
| class CSKYDisassembler : public MCDisassembler { |
| std::unique_ptr<MCInstrInfo const> const MCII; |
| mutable StringRef symbolName; |
| |
| DecodeStatus handleCROperand(MCInst &Instr) const; |
| |
| public: |
| CSKYDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx, |
| MCInstrInfo const *MCII); |
| |
| DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size, |
| ArrayRef<uint8_t> Bytes, uint64_t Address, |
| raw_ostream &CStream) const override; |
| }; |
| } // end anonymous namespace |
| |
| CSKYDisassembler::CSKYDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx, |
| MCInstrInfo const *MCII) |
| : MCDisassembler(STI, Ctx), MCII(MCII) {} |
| |
| static MCDisassembler *createCSKYDisassembler(const Target &T, |
| const MCSubtargetInfo &STI, |
| MCContext &Ctx) { |
| return new CSKYDisassembler(STI, Ctx, T.createMCInstrInfo()); |
| } |
| |
| extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeCSKYDisassembler() { |
| TargetRegistry::RegisterMCDisassembler(getTheCSKYTarget(), |
| createCSKYDisassembler); |
| } |
| |
| static const uint16_t GPRDecoderTable[] = { |
| CSKY::R0, CSKY::R1, CSKY::R2, CSKY::R3, CSKY::R4, CSKY::R5, CSKY::R6, |
| CSKY::R7, CSKY::R8, CSKY::R9, CSKY::R10, CSKY::R11, CSKY::R12, CSKY::R13, |
| CSKY::R14, CSKY::R15, CSKY::R16, CSKY::R17, CSKY::R18, CSKY::R19, CSKY::R20, |
| CSKY::R21, CSKY::R22, CSKY::R23, CSKY::R24, CSKY::R25, CSKY::R26, CSKY::R27, |
| CSKY::R28, CSKY::R29, CSKY::R30, CSKY::R31}; |
| |
| static const uint16_t GPRPairDecoderTable[] = { |
| CSKY::R0_R1, CSKY::R1_R2, CSKY::R2_R3, CSKY::R3_R4, CSKY::R4_R5, |
| CSKY::R5_R6, CSKY::R6_R7, CSKY::R7_R8, CSKY::R8_R9, CSKY::R9_R10, |
| CSKY::R10_R11, CSKY::R11_R12, CSKY::R12_R13, CSKY::R13_R14, CSKY::R14_R15, |
| CSKY::R15_R16, CSKY::R16_R17, CSKY::R17_R18, CSKY::R18_R19, CSKY::R19_R20, |
| CSKY::R20_R21, CSKY::R21_R22, CSKY::R22_R23, CSKY::R23_R24, CSKY::R24_R25, |
| CSKY::R25_R26, CSKY::R26_R27, CSKY::R27_R28, CSKY::R28_R29, CSKY::R29_R30, |
| CSKY::R30_R31, CSKY::R31_R32}; |
| |
| static const uint16_t FPR32DecoderTable[] = { |
| CSKY::F0_32, CSKY::F1_32, CSKY::F2_32, CSKY::F3_32, CSKY::F4_32, |
| CSKY::F5_32, CSKY::F6_32, CSKY::F7_32, CSKY::F8_32, CSKY::F9_32, |
| CSKY::F10_32, CSKY::F11_32, CSKY::F12_32, CSKY::F13_32, CSKY::F14_32, |
| CSKY::F15_32, CSKY::F16_32, CSKY::F17_32, CSKY::F18_32, CSKY::F19_32, |
| CSKY::F20_32, CSKY::F21_32, CSKY::F22_32, CSKY::F23_32, CSKY::F24_32, |
| CSKY::F25_32, CSKY::F26_32, CSKY::F27_32, CSKY::F28_32, CSKY::F29_32, |
| CSKY::F30_32, CSKY::F31_32}; |
| |
| static const uint16_t FPR64DecoderTable[] = { |
| CSKY::F0_64, CSKY::F1_64, CSKY::F2_64, CSKY::F3_64, CSKY::F4_64, |
| CSKY::F5_64, CSKY::F6_64, CSKY::F7_64, CSKY::F8_64, CSKY::F9_64, |
| CSKY::F10_64, CSKY::F11_64, CSKY::F12_64, CSKY::F13_64, CSKY::F14_64, |
| CSKY::F15_64, CSKY::F16_64, CSKY::F17_64, CSKY::F18_64, CSKY::F19_64, |
| CSKY::F20_64, CSKY::F21_64, CSKY::F22_64, CSKY::F23_64, CSKY::F24_64, |
| CSKY::F25_64, CSKY::F26_64, CSKY::F27_64, CSKY::F28_64, CSKY::F29_64, |
| CSKY::F30_64, CSKY::F31_64}; |
| |
| static const uint16_t FPR128DecoderTable[] = { |
| CSKY::F0_128, CSKY::F1_128, CSKY::F2_128, CSKY::F3_128, CSKY::F4_128, |
| CSKY::F5_128, CSKY::F6_128, CSKY::F7_128, CSKY::F8_128, CSKY::F9_128, |
| CSKY::F10_128, CSKY::F11_128, CSKY::F12_128, CSKY::F13_128, CSKY::F14_128, |
| CSKY::F15_128, CSKY::F16_128, CSKY::F17_128, CSKY::F18_128, CSKY::F19_128, |
| CSKY::F20_128, CSKY::F21_128, CSKY::F22_128, CSKY::F23_128, CSKY::F24_128, |
| CSKY::F25_128, CSKY::F26_128, CSKY::F27_128, CSKY::F28_128, CSKY::F29_128, |
| CSKY::F30_128, CSKY::F31_128}; |
| |
| static DecodeStatus DecodeGPRRegisterClass(MCInst &Inst, uint64_t RegNo, |
| uint64_t Address, |
| const MCDisassembler *Decoder) { |
| if (RegNo >= 32) |
| return MCDisassembler::Fail; |
| |
| Inst.addOperand(MCOperand::createReg(GPRDecoderTable[RegNo])); |
| return MCDisassembler::Success; |
| } |
| |
| static DecodeStatus DecodeFPR32RegisterClass(MCInst &Inst, uint64_t RegNo, |
| uint64_t Address, |
| const MCDisassembler *Decoder) { |
| if (RegNo >= 32) |
| return MCDisassembler::Fail; |
| |
| Inst.addOperand(MCOperand::createReg(FPR32DecoderTable[RegNo])); |
| return MCDisassembler::Success; |
| } |
| |
| static DecodeStatus DecodesFPR32RegisterClass(MCInst &Inst, uint64_t RegNo, |
| uint64_t Address, |
| const MCDisassembler *Decoder) { |
| if (RegNo >= 16) |
| return MCDisassembler::Fail; |
| |
| Inst.addOperand(MCOperand::createReg(FPR32DecoderTable[RegNo])); |
| return MCDisassembler::Success; |
| } |
| |
| static DecodeStatus DecodesFPR64RegisterClass(MCInst &Inst, uint64_t RegNo, |
| uint64_t Address, |
| const MCDisassembler *Decoder) { |
| if (RegNo >= 16) |
| return MCDisassembler::Fail; |
| |
| Inst.addOperand(MCOperand::createReg(FPR64DecoderTable[RegNo])); |
| return MCDisassembler::Success; |
| } |
| |
| static DecodeStatus DecodesFPR64_VRegisterClass(MCInst &Inst, uint64_t RegNo, |
| uint64_t Address, |
| const MCDisassembler *Decoder) { |
| if (RegNo >= 16) |
| return MCDisassembler::Fail; |
| |
| Inst.addOperand(MCOperand::createReg(FPR64DecoderTable[RegNo])); |
| return MCDisassembler::Success; |
| } |
| |
| static DecodeStatus DecodeFPR64RegisterClass(MCInst &Inst, uint64_t RegNo, |
| uint64_t Address, |
| const MCDisassembler *Decoder) { |
| if (RegNo >= 32) |
| return MCDisassembler::Fail; |
| |
| Inst.addOperand(MCOperand::createReg(FPR64DecoderTable[RegNo])); |
| return MCDisassembler::Success; |
| } |
| |
| // TODO |
| LLVM_ATTRIBUTE_UNUSED |
| static DecodeStatus DecodesFPR128RegisterClass(MCInst &Inst, uint64_t RegNo, |
| uint64_t Address, |
| const MCDisassembler *Decoder) { |
| if (RegNo >= 16) |
| return MCDisassembler::Fail; |
| |
| Inst.addOperand(MCOperand::createReg(FPR128DecoderTable[RegNo])); |
| return MCDisassembler::Success; |
| } |
| |
| static DecodeStatus DecodesGPRRegisterClass(MCInst &Inst, uint64_t RegNo, |
| uint64_t Address, |
| const MCDisassembler *Decoder) { |
| if (RegNo >= 16) |
| return MCDisassembler::Fail; |
| |
| Inst.addOperand(MCOperand::createReg(GPRDecoderTable[RegNo])); |
| return MCDisassembler::Success; |
| } |
| |
| static DecodeStatus DecodemGPRRegisterClass(MCInst &Inst, uint64_t RegNo, |
| uint64_t Address, |
| const MCDisassembler *Decoder) { |
| if (RegNo >= 8) |
| return MCDisassembler::Fail; |
| |
| Inst.addOperand(MCOperand::createReg(GPRDecoderTable[RegNo])); |
| return MCDisassembler::Success; |
| } |
| |
| // TODO |
| LLVM_ATTRIBUTE_UNUSED |
| static DecodeStatus DecodeGPRSPRegisterClass(MCInst &Inst, uint64_t RegNo, |
| uint64_t Address, |
| const MCDisassembler *Decoder) { |
| if (RegNo != 14) |
| return MCDisassembler::Fail; |
| |
| Inst.addOperand(MCOperand::createReg(GPRDecoderTable[RegNo])); |
| return MCDisassembler::Success; |
| } |
| |
| static DecodeStatus DecodeGPRPairRegisterClass(MCInst &Inst, uint64_t RegNo, |
| uint64_t Address, |
| const MCDisassembler *Decoder) { |
| const FeatureBitset &FeatureBits = |
| Decoder->getSubtargetInfo().getFeatureBits(); |
| bool hasHighReg = FeatureBits[CSKY::FeatureHighreg]; |
| |
| if (RegNo >= 32 || (!hasHighReg && RegNo >= 16)) |
| return MCDisassembler::Fail; |
| |
| Inst.addOperand(MCOperand::createReg(GPRPairDecoderTable[RegNo])); |
| return MCDisassembler::Success; |
| } |
| |
| template <unsigned N, unsigned S> |
| static DecodeStatus decodeUImmOperand(MCInst &Inst, uint64_t Imm, |
| int64_t Address, |
| const MCDisassembler *Decoder) { |
| assert(isUInt<N>(Imm) && "Invalid immediate"); |
| Inst.addOperand(MCOperand::createImm(Imm << S)); |
| return MCDisassembler::Success; |
| } |
| |
| template <unsigned N> |
| static DecodeStatus decodeOImmOperand(MCInst &Inst, uint64_t Imm, |
| int64_t Address, |
| const MCDisassembler *Decoder) { |
| assert(isUInt<N>(Imm) && "Invalid immediate"); |
| Inst.addOperand(MCOperand::createImm(Imm + 1)); |
| return MCDisassembler::Success; |
| } |
| |
| static DecodeStatus decodeLRW16Imm8(MCInst &Inst, uint64_t Imm, int64_t Address, |
| const MCDisassembler *Decoder) { |
| assert(isUInt<8>(Imm) && "Invalid immediate"); |
| if ((Imm >> 7) & 0x1) { |
| Inst.addOperand(MCOperand::createImm((Imm & 0x7F) << 2)); |
| } else { |
| uint64_t V = ((Imm ^ 0xFFFFFFFF) & 0xFF); |
| Inst.addOperand(MCOperand::createImm(V << 2)); |
| } |
| |
| return MCDisassembler::Success; |
| } |
| |
| static DecodeStatus decodeJMPIXImmOperand(MCInst &Inst, uint64_t Imm, |
| int64_t Address, |
| const MCDisassembler *Decoder) { |
| assert(isUInt<2>(Imm) && "Invalid immediate"); |
| |
| if (Imm == 0) |
| Inst.addOperand(MCOperand::createImm(16)); |
| else if (Imm == 1) |
| Inst.addOperand(MCOperand::createImm(24)); |
| else if (Imm == 2) |
| Inst.addOperand(MCOperand::createImm(32)); |
| else if (Imm == 3) |
| Inst.addOperand(MCOperand::createImm(40)); |
| else |
| return MCDisassembler::Fail; |
| |
| return MCDisassembler::Success; |
| } |
| |
| static DecodeStatus DecodeRegSeqOperand(MCInst &Inst, uint64_t Imm, |
| int64_t Address, |
| const MCDisassembler *Decoder) { |
| assert(isUInt<10>(Imm) && "Invalid immediate"); |
| |
| auto Imm5 = Imm & 0x1f; |
| auto Ry = (Imm >> 5) & 0x1f; |
| |
| if (DecodeGPRRegisterClass(Inst, Ry, Address, Decoder) == |
| MCDisassembler::Fail) |
| return MCDisassembler::Fail; |
| |
| Inst.addOperand(MCOperand::createReg(GPRDecoderTable[Ry + Imm5])); |
| |
| return MCDisassembler::Success; |
| } |
| |
| static DecodeStatus DecodeRegSeqOperandF1(MCInst &Inst, uint64_t Imm, |
| int64_t Address, |
| const MCDisassembler *Decoder) { |
| assert(isUInt<10>(Imm) && "Invalid immediate"); |
| |
| auto Imm5 = Imm & 0x1f; |
| auto Ry = (Imm >> 5) & 0x1f; |
| |
| if (DecodesFPR32RegisterClass(Inst, Ry, Address, Decoder) == |
| MCDisassembler::Fail) |
| return MCDisassembler::Fail; |
| |
| Inst.addOperand(MCOperand::createReg(FPR32DecoderTable[Ry + Imm5])); |
| |
| return MCDisassembler::Success; |
| } |
| |
| static DecodeStatus DecodeRegSeqOperandD1(MCInst &Inst, uint64_t Imm, |
| int64_t Address, |
| const MCDisassembler *Decoder) { |
| assert(isUInt<10>(Imm) && "Invalid immediate"); |
| |
| auto Imm5 = Imm & 0x1f; |
| auto Ry = (Imm >> 5) & 0x1f; |
| |
| if (DecodesFPR64RegisterClass(Inst, Ry, Address, Decoder) == |
| MCDisassembler::Fail) |
| return MCDisassembler::Fail; |
| |
| Inst.addOperand(MCOperand::createReg(FPR64DecoderTable[Ry + Imm5])); |
| |
| return MCDisassembler::Success; |
| } |
| |
| static DecodeStatus DecodeRegSeqOperandF2(MCInst &Inst, uint64_t Imm, |
| int64_t Address, |
| const MCDisassembler *Decoder) { |
| assert(isUInt<10>(Imm) && "Invalid immediate"); |
| |
| auto Imm5 = Imm & 0x1f; |
| auto Ry = (Imm >> 5) & 0x1f; |
| |
| if (DecodeFPR32RegisterClass(Inst, Ry, Address, Decoder) == |
| MCDisassembler::Fail) |
| return MCDisassembler::Fail; |
| |
| Inst.addOperand(MCOperand::createReg(FPR32DecoderTable[Ry + Imm5])); |
| |
| return MCDisassembler::Success; |
| } |
| |
| static DecodeStatus DecodeRegSeqOperandD2(MCInst &Inst, uint64_t Imm, |
| int64_t Address, |
| const MCDisassembler *Decoder) { |
| assert(isUInt<10>(Imm) && "Invalid immediate"); |
| |
| auto Imm5 = Imm & 0x1f; |
| auto Ry = (Imm >> 5) & 0x1f; |
| |
| if (DecodeFPR64RegisterClass(Inst, Ry, Address, Decoder) == |
| MCDisassembler::Fail) |
| return MCDisassembler::Fail; |
| |
| Inst.addOperand(MCOperand::createReg(FPR64DecoderTable[Ry + Imm5])); |
| |
| return MCDisassembler::Success; |
| } |
| |
| static DecodeStatus decodeImmShiftOpValue(MCInst &Inst, uint64_t Imm, |
| int64_t Address, |
| const MCDisassembler *Decoder) { |
| Inst.addOperand(MCOperand::createImm(Log2_64(Imm))); |
| return MCDisassembler::Success; |
| } |
| |
| template <unsigned N, unsigned S> |
| static DecodeStatus decodeSImmOperand(MCInst &Inst, uint64_t Imm, |
| int64_t Address, |
| const MCDisassembler *Decoder) { |
| assert(isUInt<N>(Imm) && "Invalid immediate"); |
| // Sign-extend the number in the bottom N bits of Imm |
| Inst.addOperand(MCOperand::createImm(SignExtend64<N>(Imm) << S)); |
| return MCDisassembler::Success; |
| } |
| |
| #include "CSKYGenDisassemblerTables.inc" |
| |
| DecodeStatus CSKYDisassembler::handleCROperand(MCInst &MI) const { |
| |
| // FIXME: To query instruction info from td file or a table inc file |
| switch (MI.getOpcode()) { |
| default: |
| return MCDisassembler::Success; |
| case CSKY::LD16WSP: |
| case CSKY::ST16WSP: |
| case CSKY::ADDI16ZSP: |
| MI.insert(std::next(MI.begin()), MCOperand::createReg(CSKY::R14)); |
| return MCDisassembler::Success; |
| case CSKY::ADDI16SPSP: |
| case CSKY::SUBI16SPSP: |
| MI.insert(MI.begin(), MCOperand::createReg(CSKY::R14)); |
| MI.insert(MI.begin(), MCOperand::createReg(CSKY::R14)); |
| return MCDisassembler::Success; |
| case CSKY::FCMPHS_S: |
| case CSKY::FCMPHS_D: |
| case CSKY::FCMPLT_S: |
| case CSKY::FCMPLT_D: |
| case CSKY::FCMPNE_S: |
| case CSKY::FCMPNE_D: |
| case CSKY::FCMPUO_S: |
| case CSKY::FCMPUO_D: |
| case CSKY::FCMPZHS_S: |
| case CSKY::FCMPZHS_D: |
| case CSKY::FCMPZLS_S: |
| case CSKY::FCMPZLS_D: |
| case CSKY::FCMPZNE_S: |
| case CSKY::FCMPZNE_D: |
| case CSKY::FCMPZUO_S: |
| case CSKY::FCMPZUO_D: |
| case CSKY::f2FCMPHS_S: |
| case CSKY::f2FCMPHS_D: |
| case CSKY::f2FCMPLT_S: |
| case CSKY::f2FCMPLT_D: |
| case CSKY::f2FCMPNE_S: |
| case CSKY::f2FCMPNE_D: |
| case CSKY::f2FCMPUO_S: |
| case CSKY::f2FCMPUO_D: |
| case CSKY::f2FCMPHSZ_S: |
| case CSKY::f2FCMPHSZ_D: |
| case CSKY::f2FCMPHZ_S: |
| case CSKY::f2FCMPHZ_D: |
| case CSKY::f2FCMPLSZ_S: |
| case CSKY::f2FCMPLSZ_D: |
| case CSKY::f2FCMPLTZ_S: |
| case CSKY::f2FCMPLTZ_D: |
| case CSKY::f2FCMPNEZ_S: |
| case CSKY::f2FCMPNEZ_D: |
| case CSKY::f2FCMPUOZ_S: |
| case CSKY::f2FCMPUOZ_D: |
| |
| case CSKY::BT32: |
| case CSKY::BF32: |
| case CSKY::BT16: |
| case CSKY::BF16: |
| case CSKY::CMPNEI32: |
| case CSKY::CMPNEI16: |
| case CSKY::CMPNE32: |
| case CSKY::CMPNE16: |
| case CSKY::CMPHSI32: |
| case CSKY::CMPHSI16: |
| case CSKY::CMPHS32: |
| case CSKY::CMPHS16: |
| case CSKY::CMPLTI32: |
| case CSKY::CMPLTI16: |
| case CSKY::CMPLT32: |
| case CSKY::CMPLT16: |
| case CSKY::BTSTI32: |
| case CSKY::BTSTI16: |
| case CSKY::TSTNBZ32: |
| case CSKY::TSTNBZ16: |
| case CSKY::TST32: |
| case CSKY::TST16: |
| MI.insert(MI.begin(), MCOperand::createReg(CSKY::C)); |
| return MCDisassembler::Success; |
| case CSKY::LSLC32: |
| case CSKY::LSRC32: |
| case CSKY::ASRC32: |
| MI.insert(std::next(MI.begin()), MCOperand::createReg(CSKY::C)); |
| return MCDisassembler::Success; |
| case CSKY::MOVF32: |
| case CSKY::MOVT32: |
| case CSKY::MVC32: |
| case CSKY::MVCV32: |
| case CSKY::MVCV16: |
| case CSKY::INCT32: |
| case CSKY::INCF32: |
| case CSKY::DECT32: |
| case CSKY::DECF32: |
| case CSKY::DECGT32: |
| case CSKY::DECLT32: |
| case CSKY::DECNE32: |
| case CSKY::CLRF32: |
| case CSKY::CLRT32: |
| case CSKY::f2FSEL_S: |
| case CSKY::f2FSEL_D: |
| MI.insert(std::next(MI.begin()), MCOperand::createReg(CSKY::C)); |
| return MCDisassembler::Success; |
| case CSKY::ADDC32: |
| case CSKY::ADDC16: |
| case CSKY::SUBC32: |
| case CSKY::SUBC16: |
| case CSKY::XSR32: |
| MI.insert(std::next(MI.begin()), MCOperand::createReg(CSKY::C)); |
| MI.insert(MI.end(), MCOperand::createReg(CSKY::C)); |
| return MCDisassembler::Success; |
| case CSKY::INS32: |
| MI.getOperand(3).setImm(MI.getOperand(3).getImm() + |
| MI.getOperand(4).getImm()); |
| return MCDisassembler::Success; |
| } |
| } |
| |
| static bool decodeFPUV3Instruction(MCInst &MI, uint32_t insn, uint64_t Address, |
| const MCDisassembler *DisAsm, |
| const MCSubtargetInfo &STI) { |
| LLVM_DEBUG(dbgs() << "Trying CSKY 32-bit fpuv3 table :\n"); |
| if (!STI.getFeatureBits()[CSKY::FeatureFPUV3_HF] && |
| !STI.getFeatureBits()[CSKY::FeatureFPUV3_SF] && |
| !STI.getFeatureBits()[CSKY::FeatureFPUV3_DF]) |
| return false; |
| |
| DecodeStatus Result = |
| decodeInstruction(DecoderTableFPUV332, MI, insn, Address, DisAsm, STI); |
| |
| if (Result == MCDisassembler::Fail) { |
| MI.clear(); |
| return false; |
| } |
| |
| return true; |
| } |
| |
| DecodeStatus CSKYDisassembler::getInstruction(MCInst &MI, uint64_t &Size, |
| ArrayRef<uint8_t> Bytes, |
| uint64_t Address, |
| raw_ostream &CS) const { |
| |
| uint32_t Insn; |
| DecodeStatus Result = MCDisassembler::Fail; |
| |
| Insn = support::endian::read16le(Bytes.data()); |
| |
| if ((Insn >> 14) == 0x3) { |
| if (Bytes.size() < 4) { |
| Size = 0; |
| return MCDisassembler::Fail; |
| } |
| Insn = (Insn << 16) | support::endian::read16le(&Bytes[2]); |
| |
| if (decodeFPUV3Instruction(MI, Insn, Address, this, STI)) |
| Result = MCDisassembler::Success; |
| else { |
| LLVM_DEBUG(dbgs() << "Trying CSKY 32-bit table :\n"); |
| Result = decodeInstruction(DecoderTable32, MI, Insn, Address, this, STI); |
| } |
| |
| Size = 4; |
| } else { |
| if (Bytes.size() < 2) { |
| Size = 0; |
| return MCDisassembler::Fail; |
| } |
| LLVM_DEBUG(dbgs() << "Trying CSKY 16-bit table :\n"); |
| Result = decodeInstruction(DecoderTable16, MI, Insn, Address, this, STI); |
| Size = 2; |
| } |
| |
| handleCROperand(MI); |
| |
| return Result; |
| } |