|  | //===-- 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.hasFeature(CSKY::FeatureFPUV3_HF) && | 
|  | !STI.hasFeature(CSKY::FeatureFPUV3_SF) && | 
|  | !STI.hasFeature(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; | 
|  | } |