/* Capstone Disassembly Engine, http://www.capstone-engine.org */ /* By Nguyen Anh Quynh , 2013-2022, */ /* Rot127 2022-2023 */ /* Automatically translated source file from LLVM. */ /* LLVM-commit: */ /* LLVM-tag: */ /* Only small edits allowed. */ /* For multiple similar edits, please create a Patch for the translator. */ /* Capstone's C++ file translator: */ /* https://github.com/capstone-engine/capstone/tree/next/suite/auto-sync */ //===- MipsDisassembler.cpp - Disassembler for Mips -----------------------===// // // 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 is part of the Mips Disassembler. // //===----------------------------------------------------------------------===// #include #include #include #include #include "../../MCInst.h" #include "../../MathExtras.h" #include "../../MCInstPrinter.h" #include "../../MCDisassembler.h" #include "../../MCRegisterInfo.h" #include "../../MCFixedLenDisassembler.h" #include "../../cs_priv.h" #include "../../utils.h" #define GET_SUBTARGETINFO_ENUM #include "MipsGenSubtargetInfo.inc" #define GET_INSTRINFO_ENUM #include "MipsGenInstrInfo.inc" #define GET_REGINFO_ENUM #include "MipsGenRegisterInfo.inc" #define CONCAT(a, b) CONCAT_(a, b) #define CONCAT_(a, b) a##_##b #define DEBUG_TYPE "mips-disassembler" bool Mips_getFeatureBits(unsigned int mode, unsigned int feature) { switch(feature) { case Mips_FeatureGP64Bit: return mode & (CS_MODE_MIPS3 | CS_MODE_MIPS4 | CS_MODE_MIPS5 | CS_MODE_MIPS64 | CS_MODE_MIPS64R2 | CS_MODE_MIPS64R3 | CS_MODE_MIPS64R5 | CS_MODE_MIPS64R6 | CS_MODE_OCTEON | CS_MODE_OCTEONP); case Mips_FeatureFP64Bit: return mode & (CS_MODE_MIPS32R6 | CS_MODE_MIPS3 | CS_MODE_MIPS4 | CS_MODE_MIPS5 | CS_MODE_MIPS32R2 | CS_MODE_MIPS32R3 | CS_MODE_MIPS32R5 | CS_MODE_MIPS64 | CS_MODE_MIPS64R2 | CS_MODE_MIPS64R3 | CS_MODE_MIPS64R5 | CS_MODE_MIPS64R6 | CS_MODE_OCTEON | CS_MODE_OCTEONP); case Mips_FeatureNaN2008: return mode & (CS_MODE_MIPS32R6 | CS_MODE_MIPS64R6); case Mips_FeatureAbs2008: return mode & (CS_MODE_MIPS32R6 | CS_MODE_MIPS64R6); case Mips_FeatureMips1: return mode & (CS_MODE_MIPS1 | CS_MODE_MIPS2 | CS_MODE_MIPS32 | CS_MODE_MIPS32R2 | CS_MODE_MIPS32R3 | CS_MODE_MIPS32R5 | CS_MODE_MIPS32R6 | CS_MODE_MIPS3 | CS_MODE_MIPS4 | CS_MODE_MIPS5 | CS_MODE_MIPS64 | CS_MODE_MIPS64R2 | CS_MODE_MIPS64R3 | CS_MODE_MIPS64R5 | CS_MODE_MIPS64R6 | CS_MODE_OCTEON | CS_MODE_OCTEONP); case Mips_FeatureMips2: return mode & (CS_MODE_MIPS2 | CS_MODE_MIPS32 | CS_MODE_MIPS32R2 | CS_MODE_MIPS32R3 | CS_MODE_MIPS32R5 | CS_MODE_MIPS32R6 | CS_MODE_MIPS3 | CS_MODE_MIPS4 | CS_MODE_MIPS5 | CS_MODE_MIPS64 | CS_MODE_MIPS64R2 | CS_MODE_MIPS64R3 | CS_MODE_MIPS64R5 | CS_MODE_MIPS64R6 | CS_MODE_OCTEON | CS_MODE_OCTEONP); case Mips_FeatureMips3_32: return mode & (CS_MODE_MIPS32 | CS_MODE_MIPS32R2 | CS_MODE_MIPS32R3 | CS_MODE_MIPS32R5 | CS_MODE_MIPS32R6 | CS_MODE_MIPS3 | CS_MODE_MIPS4 | CS_MODE_MIPS5 | CS_MODE_MIPS64 | CS_MODE_MIPS64R2 | CS_MODE_MIPS64R3 | CS_MODE_MIPS64R5 | CS_MODE_MIPS64R6 | CS_MODE_OCTEON | CS_MODE_OCTEONP); case Mips_FeatureMips3_32r2: return mode & (CS_MODE_MIPS32R2 | CS_MODE_MIPS32R3 | CS_MODE_MIPS32R5 | CS_MODE_MIPS32R6 | CS_MODE_MIPS3 | CS_MODE_MIPS4 | CS_MODE_MIPS5 | CS_MODE_MIPS64 | CS_MODE_MIPS64R2 | CS_MODE_MIPS64R3 | CS_MODE_MIPS64R5 | CS_MODE_MIPS64R6 | CS_MODE_OCTEON | CS_MODE_OCTEONP); case Mips_FeatureMips3: return mode & (CS_MODE_MIPS3 | CS_MODE_MIPS4 | CS_MODE_MIPS5 | CS_MODE_MIPS64 | CS_MODE_MIPS64R2 | CS_MODE_MIPS64R3 | CS_MODE_MIPS64R5 | CS_MODE_MIPS64R6 | CS_MODE_OCTEON | CS_MODE_OCTEONP); case Mips_FeatureMips4_32: return mode & (CS_MODE_MIPS32 | CS_MODE_MIPS32R2 | CS_MODE_MIPS32R3 | CS_MODE_MIPS32R5 | CS_MODE_MIPS32R6 | CS_MODE_MIPS4 | CS_MODE_MIPS5 | CS_MODE_MIPS64 | CS_MODE_MIPS64R2 | CS_MODE_MIPS64R3 | CS_MODE_MIPS64R5 | CS_MODE_MIPS64R6 | CS_MODE_OCTEON | CS_MODE_OCTEONP); case Mips_FeatureMips4_32r2: return mode & (CS_MODE_MIPS32R2 | CS_MODE_MIPS32R3 | CS_MODE_MIPS32R5 | CS_MODE_MIPS32R6 | CS_MODE_MIPS4 | CS_MODE_MIPS5 | CS_MODE_MIPS64 | CS_MODE_MIPS64R2 | CS_MODE_MIPS64R3 | CS_MODE_MIPS64R5 | CS_MODE_MIPS64R6 | CS_MODE_OCTEON | CS_MODE_OCTEONP); case Mips_FeatureMips4: return mode & (CS_MODE_MIPS4 | CS_MODE_MIPS5 | CS_MODE_MIPS64 | CS_MODE_MIPS64R2 | CS_MODE_MIPS64R3 | CS_MODE_MIPS64R5 | CS_MODE_MIPS64R6 | CS_MODE_OCTEON | CS_MODE_OCTEONP); case Mips_FeatureMips5_32r2: return mode & (CS_MODE_MIPS32R2 | CS_MODE_MIPS32R3 | CS_MODE_MIPS32R5 | CS_MODE_MIPS32R6 | CS_MODE_MIPS5 | CS_MODE_MIPS64 | CS_MODE_MIPS64R2 | CS_MODE_MIPS64R3 | CS_MODE_MIPS64R5 | CS_MODE_MIPS64R6 | CS_MODE_OCTEON | CS_MODE_OCTEONP); case Mips_FeatureMips5: return mode & (CS_MODE_MIPS5 | CS_MODE_MIPS64 | CS_MODE_MIPS64R2 | CS_MODE_MIPS64R3 | CS_MODE_MIPS64R5 | CS_MODE_MIPS64R6 | CS_MODE_OCTEON | CS_MODE_OCTEONP); case Mips_FeatureMips32: return mode & (CS_MODE_MIPS32 | CS_MODE_MIPS32R2 | CS_MODE_MIPS32R3 | CS_MODE_MIPS32R5 | CS_MODE_MIPS32R6 | CS_MODE_MIPS64 | CS_MODE_MIPS64R2 | CS_MODE_MIPS64R3 | CS_MODE_MIPS64R5 | CS_MODE_MIPS64R6 | CS_MODE_OCTEON | CS_MODE_OCTEONP); case Mips_FeatureMips32r2: return mode & (CS_MODE_MIPS32R2 | CS_MODE_MIPS32R3 | CS_MODE_MIPS32R5 | CS_MODE_MIPS32R6 | CS_MODE_MIPS64R2 | CS_MODE_MIPS64R3 | CS_MODE_MIPS64R5 | CS_MODE_MIPS64R6 | CS_MODE_OCTEON | CS_MODE_OCTEONP); case Mips_FeatureMips32r3: return mode & (CS_MODE_MIPS32R3 | CS_MODE_MIPS32R5 | CS_MODE_MIPS32R6 | CS_MODE_MIPS64R3 | CS_MODE_MIPS64R5 | CS_MODE_MIPS64R6); case Mips_FeatureMips32r5: return mode & (CS_MODE_MIPS32R5 | CS_MODE_MIPS32R6 | CS_MODE_MIPS64R5 | CS_MODE_MIPS64R6); case Mips_FeatureMips32r6: return mode & (CS_MODE_MIPS32R6 | CS_MODE_MIPS64R6); case Mips_FeatureMips64: return mode & (CS_MODE_MIPS64 | CS_MODE_MIPS64R2 | CS_MODE_MIPS64R3 | CS_MODE_MIPS64R5 | CS_MODE_MIPS64R6 | CS_MODE_OCTEON | CS_MODE_OCTEONP); case Mips_FeatureMips64r2: return mode & (CS_MODE_MIPS64R2 | CS_MODE_MIPS64R3 | CS_MODE_MIPS64R5 | CS_MODE_MIPS64R6 | CS_MODE_OCTEON | CS_MODE_OCTEONP); case Mips_FeatureMips64r3: return mode & (CS_MODE_MIPS64R3 | CS_MODE_MIPS64R5 | CS_MODE_MIPS64R6); case Mips_FeatureMips64r5: return mode & (CS_MODE_MIPS64R5 | CS_MODE_MIPS64R6); case Mips_FeatureMips64r6: return mode & CS_MODE_MIPS64R6; case Mips_FeatureMips16: return mode & CS_MODE_MIPS16; case Mips_FeatureMicroMips: return mode & CS_MODE_MICRO; case Mips_FeatureNanoMips: return mode & (CS_MODE_NANOMIPS | CS_MODE_NMS1 | CS_MODE_I7200); case Mips_FeatureNMS1: return mode & CS_MODE_NMS1; case Mips_FeatureTLB: return mode & CS_MODE_I7200; case Mips_FeatureCnMips: return mode & (CS_MODE_OCTEON | CS_MODE_OCTEONP); case Mips_FeatureCnMipsP: return mode & CS_MODE_OCTEONP; case Mips_FeaturePTR64Bit: return mode & CS_MODE_MIPS_PTR64; case Mips_FeatureSoftFloat: return mode & CS_MODE_MIPS_NOFLOAT; case Mips_FeatureI7200: return mode & CS_MODE_I7200; // optional features always enabled case Mips_FeatureDSP: // Mips DSP ASE return true; case Mips_FeatureDSPR2: // Mips DSP-R2 ASE return true; case Mips_FeatureDSPR3: // Mips DSP-R3 ASE return true; case Mips_FeatureMips3D: // Mips 3D ASE return true; case Mips_FeatureMSA: // Mips MSA ASE return true; case Mips_FeatureEVA: { // Mips EVA ASE if (mode & CS_MODE_NANOMIPS) { return mode & CS_MODE_I7200; } return true; } case Mips_FeatureCRC: // Mips R6 CRC ASE return true; case Mips_FeatureVirt: // Mips Virtualization ASE return true; case Mips_FeatureGINV: // Mips Global Invalidate ASE return true; case Mips_FeatureMT: { // Mips MT ASE if (mode & CS_MODE_NANOMIPS) { return mode & CS_MODE_I7200; } return true; } default: return false; } } static DecodeStatus getInstruction(MCInst *Instr, uint64_t *Size, const uint8_t *Bytes, size_t BytesLen, uint64_t Address, SStream *CStream); // end anonymous namespace // Forward declare these because the autogenerated code will reference them. // Definitions are further down. static DecodeStatus DecodeGPR64RegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodeCPU16RegsRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodeGPRMM16RegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodeGPRMM16ZeroRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodeGPRMM16MovePRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodeGPR32RegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodeGPRNM3RegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodeGPRNM4RegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodeGPRNMRARegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodeGPRNM3ZRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodeGPRNM4ZRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodeGPRNM32NZRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodeGPRNM32RegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodeGPRNM2R1RegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodeGPRNM1R1RegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodePtrRegisterClass(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeDSPRRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodeFGR64RegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodeFGR32RegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodeCCRRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodeFCCRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodeFGRCCRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodeHWRegsRegisterClass(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeAFGR64RegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodeACC64DSPRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodeHI32DSPRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodeLO32DSPRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodeMSA128BRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodeMSA128HRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodeMSA128WRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodeMSA128DRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodeMSACtrlRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodeCOP0RegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodeCOP0SelRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodeCOP2RegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodeBranchTarget(MCInst *Inst, unsigned Offset, uint64_t Address, const void *Decoder); static DecodeStatus DecodeBranchTarget1SImm16(MCInst *Inst, unsigned Offset, uint64_t Address, const void *Decoder); static DecodeStatus DecodeJumpTarget(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeBranchTarget21(MCInst *Inst, unsigned Offset, uint64_t Address, const void *Decoder); static DecodeStatus DecodeBranchTarget21MM(MCInst *Inst, unsigned Offset, uint64_t Address, const void *Decoder); static DecodeStatus DecodeBranchTarget26(MCInst *Inst, unsigned Offset, uint64_t Address, const void *Decoder); // DecodeBranchTarget7MM - Decode microMIPS branch offset, which is // shifted left by 1 bit. static DecodeStatus DecodeBranchTarget7MM(MCInst *Inst, unsigned Offset, uint64_t Address, const void *Decoder); // DecodeBranchTarget10MM - Decode microMIPS branch offset, which is // shifted left by 1 bit. static DecodeStatus DecodeBranchTarget10MM(MCInst *Inst, unsigned Offset, uint64_t Address, const void *Decoder); // DecodeBranchTargetMM - Decode microMIPS branch offset, which is // shifted left by 1 bit. static DecodeStatus DecodeBranchTargetMM(MCInst *Inst, unsigned Offset, uint64_t Address, const void *Decoder); // DecodeBranchTarget26MM - Decode microMIPS branch offset, which is // shifted left by 1 bit. static DecodeStatus DecodeBranchTarget26MM(MCInst *Inst, unsigned Offset, uint64_t Address, const void *Decoder); // DecodeBranchTargetMM - Decode nanoMIPS branch offset, which is // shifted left by 1 bit. #define DECLARE_DecodeBranchTargetNM(bits) \ static DecodeStatus CONCAT(DecodeBranchTargetNM, bits)( \ MCInst * Inst, unsigned Offset, uint64_t Address, \ const void *Decoder); DECLARE_DecodeBranchTargetNM(10); DECLARE_DecodeBranchTargetNM(7); DECLARE_DecodeBranchTargetNM(21); DECLARE_DecodeBranchTargetNM(25); DECLARE_DecodeBranchTargetNM(14); DECLARE_DecodeBranchTargetNM(11); DECLARE_DecodeBranchTargetNM(5); // DecodeJumpTargetMM - Decode microMIPS jump target, which is // shifted left by 1 bit. static DecodeStatus DecodeJumpTargetMM(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder); // DecodeJumpTargetXMM - Decode microMIPS jump and link exchange target, // which is shifted left by 2 bit. static DecodeStatus DecodeJumpTargetXMM(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeMem(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder); #define DECLARE_DecodeMemNM(Offbits, isSigned, rt) \ static DecodeStatus CONCAT(DecodeMemNM, \ CONCAT(Offbits, CONCAT(isSigned, rt)))( \ MCInst * Inst, uint32_t Insn, uint64_t Address, \ const void *Decoder); DECLARE_DecodeMemNM(6, 0, Mips_GPRNM3RegClassID); DECLARE_DecodeMemNM(7, 0, Mips_GPRNMSPRegClassID); DECLARE_DecodeMemNM(9, 0, Mips_GPRNMGPRegClassID); DECLARE_DecodeMemNM(2, 0, Mips_GPRNM3RegClassID); DECLARE_DecodeMemNM(3, 0, Mips_GPRNM3RegClassID); DECLARE_DecodeMemNM(21, 0, Mips_GPRNMGPRegClassID); DECLARE_DecodeMemNM(18, 0, Mips_GPRNMGPRegClassID); DECLARE_DecodeMemNM(12, 0, Mips_GPRNM32RegClassID); DECLARE_DecodeMemNM(9, 1, Mips_GPRNM32RegClassID); static DecodeStatus DecodeMemZeroNM(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder); #define DECLARE_DecodeMemNMRX(rt) \ static DecodeStatus CONCAT(DecodeMemNMRX, \ rt)(MCInst * Inst, uint32_t Insn, \ uint64_t Address, const void *Decoder); DECLARE_DecodeMemNMRX(Mips_GPRNM3RegClassID); DECLARE_DecodeMemNMRX(Mips_GPRNM32RegClassID); static DecodeStatus DecodeMemNM4x4(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeMemEVA(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeLoadByte15(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeCacheOp(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeCacheeOp_CacheOpR6(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeCacheOpMM(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodePrefeOpMM(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeSyncI(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeSyncI_MM(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeSynciR6(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeMSA128Mem(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeMemMMImm4(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeMemMMSPImm5Lsl2(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeMemMMGPImm7Lsl2(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeMemMMReglistImm4Lsl2(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeMemMMImm9(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeMemMMImm12(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeMemMMImm16(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeFMem(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeFMemMMR2(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeFMem2(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeFMem3(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeFMemCop2R6(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeFMemCop2MMR6(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeSpecial3LlSc(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeAddiur2Simm7(MCInst *Inst, unsigned Value, uint64_t Address, const void *Decoder); static DecodeStatus DecodeLi16Imm(MCInst *Inst, unsigned Value, uint64_t Address, const void *Decoder); static DecodeStatus DecodePOOL16BEncodedField(MCInst *Inst, unsigned Value, uint64_t Address, const void *Decoder); #define DECLARE_DecodeUImmWithOffsetAndScale(Bits, Offset, Scale) \ static DecodeStatus CONCAT(DecodeUImmWithOffsetAndScale, \ CONCAT(Bits, CONCAT(Offset, Scale)))( \ MCInst * Inst, unsigned Value, uint64_t Address, \ const void *Decoder); DECLARE_DecodeUImmWithOffsetAndScale(5, 0, 4); DECLARE_DecodeUImmWithOffsetAndScale(6, 0, 4); DECLARE_DecodeUImmWithOffsetAndScale(2, 1, 1); DECLARE_DecodeUImmWithOffsetAndScale(5, 1, 1); DECLARE_DecodeUImmWithOffsetAndScale(8, 0, 1); DECLARE_DecodeUImmWithOffsetAndScale(18, 0, 1); DECLARE_DecodeUImmWithOffsetAndScale(21, 0, 1); #define DEFINE_DecodeUImmWithOffset(Bits, Offset) \ static DecodeStatus CONCAT(DecodeUImmWithOffset, \ CONCAT(Bits, Offset))(MCInst * Inst, \ unsigned Value, \ uint64_t Address, \ const void *Decoder) \ { \ return CONCAT(DecodeUImmWithOffsetAndScale, \ CONCAT(Bits, CONCAT(Offset, 1)))( \ Inst, Value, Address, Decoder); \ } DEFINE_DecodeUImmWithOffset(5, 1); DEFINE_DecodeUImmWithOffset(2, 1); #define DECLARE_DecodeSImmWithOffsetAndScale(Bits, Offset, ScaleBy) \ static DecodeStatus CONCAT( \ DecodeSImmWithOffsetAndScale, \ CONCAT(Bits, CONCAT(Offset, ScaleBy)))( \ MCInst * Inst, unsigned Value, uint64_t Address, \ const void *Decoder); #define DECLARE_DecodeSImmWithOffsetAndScale_2(Bits, Offset) DECLARE_DecodeSImmWithOffsetAndScale(Bits, Offset, 1) #define DECLARE_DecodeSImmWithOffsetAndScale_3(Bits) DECLARE_DecodeSImmWithOffsetAndScale(Bits, 0, 1) DECLARE_DecodeSImmWithOffsetAndScale_3(16); DECLARE_DecodeSImmWithOffsetAndScale_3(10); DECLARE_DecodeSImmWithOffsetAndScale_3(4); DECLARE_DecodeSImmWithOffsetAndScale_3(6); DECLARE_DecodeSImmWithOffsetAndScale_3(32); static DecodeStatus DecodeInsSize(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeImmM1To126(MCInst *Inst, unsigned Value, uint64_t Address, const void *Decoder); static DecodeStatus DecodeUImm4Mask(MCInst *Inst, unsigned Value, uint64_t Address, const void *Decoder); static DecodeStatus DecodeUImm3Shift(MCInst *Inst, unsigned Value, uint64_t Address, const void *Decoder); static DecodeStatus DecodeNMRegListOperand(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeNMRegList16Operand(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeNegImm12(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder); #define DECLARE_DecodeSImmWithReg(Bits, Offset, Scale, RegNum) \ static DecodeStatus CONCAT( \ DecodeSImmWithReg, \ CONCAT(Bits, CONCAT(Offset, CONCAT(Scale, RegNum))))( \ MCInst * Inst, unsigned Value, uint64_t Address, \ const void *Decoder); DECLARE_DecodeSImmWithReg(32, 0, 1, Mips_GP_NM); #define DECLARE_DecodeUImmWithReg(Bits, Offset, Scale, RegNum) \ static DecodeStatus CONCAT( \ DecodeUImmWithReg, \ CONCAT(Bits, CONCAT(Offset, CONCAT(Scale, RegNum))))( \ MCInst * Inst, unsigned Value, uint64_t Address, \ const void *Decoder); DECLARE_DecodeUImmWithReg(8, 0, 1, Mips_SP_NM); DECLARE_DecodeUImmWithReg(21, 0, 1, Mips_GP_NM); DECLARE_DecodeUImmWithReg(18, 0, 1, Mips_GP_NM); static DecodeStatus DecodeSImm32s12(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder); #define DECLARE_DecodeAddressPCRelNM(Bits) \ static DecodeStatus CONCAT(DecodeAddressPCRelNM, Bits)( \ MCInst * Inst, uint32_t Insn, uint64_t Address, \ const void *Decoder); DECLARE_DecodeAddressPCRelNM(22); DECLARE_DecodeAddressPCRelNM(32); static DecodeStatus DecodeBranchConflictNM(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeSimm19Lsl2(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeSimm18Lsl3(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeSimm9SP(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeANDI16Imm(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeSimm23Lsl2(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder); /// INSVE_[BHWD] have an implicit operand that the generated decoder doesn't /// handle. static DecodeStatus DecodeINSVE_DF(MCInst *MI, uint32_t insn, uint64_t Address, const void *Decoder); /* static DecodeStatus DecodeDAHIDATIMMR6(MCInst *MI, uint32_t insn, uint64_t Address, const void *Decoder); */ static DecodeStatus DecodeDAHIDATI(MCInst *MI, uint32_t insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeAddiGroupBranch(MCInst *MI, uint32_t insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodePOP35GroupBranchMMR6(MCInst *MI, uint32_t insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeDaddiGroupBranch(MCInst *MI, uint32_t insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodePOP37GroupBranchMMR6(MCInst *MI, uint32_t insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodePOP65GroupBranchMMR6(MCInst *MI, uint32_t insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodePOP75GroupBranchMMR6(MCInst *MI, uint32_t insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeBlezlGroupBranch(MCInst *MI, uint32_t insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeBgtzlGroupBranch(MCInst *MI, uint32_t insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeBgtzGroupBranch(MCInst *MI, uint32_t insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeBlezGroupBranch(MCInst *MI, uint32_t insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeBgtzGroupBranchMMR6(MCInst *MI, uint32_t insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeBlezGroupBranchMMR6(MCInst *MI, uint32_t insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeDINS(MCInst *MI, uint32_t Insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeDEXT(MCInst *MI, uint32_t Insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeCRC(MCInst *MI, uint32_t Insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeRegListOperand(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeRegListOperand16(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeMovePRegPair(MCInst *Inst, unsigned RegPair, uint64_t Address, const void *Decoder); static DecodeStatus DecodeMovePOperands(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeFIXMEInstruction(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder); #include "MipsGenDisassemblerTables.inc" static unsigned getReg(const MCInst *Inst, unsigned RC, unsigned RegNo) { const MCRegisterClass* c = MCRegisterInfo_getRegClass(Inst->MRI, RC); return MCRegisterClass_getRegister(c, RegNo); } typedef DecodeStatus (*DecodeFN)(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeINSVE_DF(MCInst *MI, uint32_t insn, uint64_t Address, const void *Decoder) { // The size of the n field depends on the element size // The register class also depends on this. uint32_t tmp = fieldFromInstruction_4(insn, 17, 5); unsigned NSize = 0; DecodeFN RegDecoder = NULL; if ((tmp & 0x18) == 0x00) { // INSVE_B NSize = 4; RegDecoder = DecodeMSA128BRegisterClass; } else if ((tmp & 0x1c) == 0x10) { // INSVE_H NSize = 3; RegDecoder = DecodeMSA128HRegisterClass; } else if ((tmp & 0x1e) == 0x18) { // INSVE_W NSize = 2; RegDecoder = DecodeMSA128WRegisterClass; } else if ((tmp & 0x1f) == 0x1c) { // INSVE_D NSize = 1; RegDecoder = DecodeMSA128DRegisterClass; } else CS_ASSERT_RET_VAL(0 && "Invalid encoding", MCDisassembler_Fail); // $wd tmp = fieldFromInstruction_4(insn, 6, 5); if (RegDecoder(MI, tmp, Address, Decoder) == MCDisassembler_Fail) return MCDisassembler_Fail; // $wd_in if (RegDecoder(MI, tmp, Address, Decoder) == MCDisassembler_Fail) return MCDisassembler_Fail; // $n tmp = fieldFromInstruction_4(insn, 16, NSize); MCOperand_CreateImm0(MI, (tmp)); // $ws tmp = fieldFromInstruction_4(insn, 11, 5); if (RegDecoder(MI, tmp, Address, Decoder) == MCDisassembler_Fail) return MCDisassembler_Fail; // $n2 MCOperand_CreateImm0(MI, (0)); return MCDisassembler_Success; } /* static DecodeStatus DecodeDAHIDATIMMR6(MCInst *MI, uint32_t insn, uint64_t Address, const void *Decoder) { uint32_t Rs = fieldFromInstruction_4(insn, 16, 5); uint32_t Imm = fieldFromInstruction_4(insn, 0, 16); MCOperand_CreateReg0(MI, (getReg(MI, Mips_GPR64RegClassID, Rs))); MCOperand_CreateReg0(MI, (getReg(MI, Mips_GPR64RegClassID, Rs))); MCOperand_CreateImm0(MI, (Imm)); return MCDisassembler_Success; } */ static DecodeStatus DecodeDAHIDATI(MCInst *MI, uint32_t insn, uint64_t Address, const void *Decoder) { uint32_t Rs = fieldFromInstruction_4(insn, 21, 5); uint32_t Imm = fieldFromInstruction_4(insn, 0, 16); MCOperand_CreateReg0(MI, (getReg(MI, Mips_GPR64RegClassID, Rs))); MCOperand_CreateReg0(MI, (getReg(MI, Mips_GPR64RegClassID, Rs))); MCOperand_CreateImm0(MI, (Imm)); return MCDisassembler_Success; } static DecodeStatus DecodeAddiGroupBranch(MCInst *MI, uint32_t insn, uint64_t Address, const void *Decoder) { // If we are called then we can assume that MIPS32r6/MIPS64r6 is enabled // (otherwise we would have matched the ADDI instruction from the earlier // ISA's instead). // // We have: // 0b001000 sssss ttttt iiiiiiiiiiiiiiii // BOVC if rs >= rt // BEQZALC if rs == 0 && rt != 0 // BEQC if rs < rt && rs != 0 uint32_t Rs = fieldFromInstruction_4(insn, 21, 5); uint32_t Rt = fieldFromInstruction_4(insn, 16, 5); int64_t Imm = SignExtend64(fieldFromInstruction_4(insn, 0, 16), 16) * 4 + 4; bool HasRs = false; if (Rs >= Rt) { MCInst_setOpcode(MI, (Mips_BOVC)); HasRs = true; } else if (Rs != 0 && Rs < Rt) { MCInst_setOpcode(MI, (Mips_BEQC)); HasRs = true; } else MCInst_setOpcode(MI, (Mips_BEQZALC)); if (HasRs) MCOperand_CreateReg0( MI, (getReg(MI, Mips_GPR32RegClassID, Rs))); MCOperand_CreateReg0(MI, (getReg(MI, Mips_GPR32RegClassID, Rt))); MCOperand_CreateImm0(MI, (Imm)); return MCDisassembler_Success; } static DecodeStatus DecodePOP35GroupBranchMMR6(MCInst *MI, uint32_t insn, uint64_t Address, const void *Decoder) { uint32_t Rt = fieldFromInstruction_4(insn, 21, 5); uint32_t Rs = fieldFromInstruction_4(insn, 16, 5); int64_t Imm = 0; if (Rs >= Rt) { MCInst_setOpcode(MI, (Mips_BOVC_MMR6)); MCOperand_CreateReg0( MI, (getReg(MI, Mips_GPR32RegClassID, Rt))); MCOperand_CreateReg0( MI, (getReg(MI, Mips_GPR32RegClassID, Rs))); Imm = SignExtend64(fieldFromInstruction_4(insn, 0, 16), 16) * 2 + 4; } else if (Rs != 0 && Rs < Rt) { MCInst_setOpcode(MI, (Mips_BEQC_MMR6)); MCOperand_CreateReg0( MI, (getReg(MI, Mips_GPR32RegClassID, Rs))); MCOperand_CreateReg0( MI, (getReg(MI, Mips_GPR32RegClassID, Rt))); Imm = SignExtend64(fieldFromInstruction_4(insn, 0, 16), 16) * 4 + 4; } else { MCInst_setOpcode(MI, (Mips_BEQZALC_MMR6)); MCOperand_CreateReg0( MI, (getReg(MI, Mips_GPR32RegClassID, Rt))); Imm = SignExtend64(fieldFromInstruction_4(insn, 0, 16), 16) * 2 + 4; } MCOperand_CreateImm0(MI, (Imm)); return MCDisassembler_Success; } static DecodeStatus DecodeDaddiGroupBranch(MCInst *MI, uint32_t insn, uint64_t Address, const void *Decoder) { // If we are called then we can assume that MIPS32r6/MIPS64r6 is enabled // (otherwise we would have matched the ADDI instruction from the earlier // ISA's instead). // // We have: // 0b011000 sssss ttttt iiiiiiiiiiiiiiii // BNVC if rs >= rt // BNEZALC if rs == 0 && rt != 0 // BNEC if rs < rt && rs != 0 uint32_t Rs = fieldFromInstruction_4(insn, 21, 5); uint32_t Rt = fieldFromInstruction_4(insn, 16, 5); int64_t Imm = SignExtend64(fieldFromInstruction_4(insn, 0, 16), 16) * 4 + 4; bool HasRs = false; if (Rs >= Rt) { MCInst_setOpcode(MI, (Mips_BNVC)); HasRs = true; } else if (Rs != 0 && Rs < Rt) { MCInst_setOpcode(MI, (Mips_BNEC)); HasRs = true; } else MCInst_setOpcode(MI, (Mips_BNEZALC)); if (HasRs) MCOperand_CreateReg0( MI, (getReg(MI, Mips_GPR32RegClassID, Rs))); MCOperand_CreateReg0(MI, (getReg(MI, Mips_GPR32RegClassID, Rt))); MCOperand_CreateImm0(MI, (Imm)); return MCDisassembler_Success; } static DecodeStatus DecodePOP37GroupBranchMMR6(MCInst *MI, uint32_t insn, uint64_t Address, const void *Decoder) { uint32_t Rt = fieldFromInstruction_4(insn, 21, 5); uint32_t Rs = fieldFromInstruction_4(insn, 16, 5); int64_t Imm = 0; if (Rs >= Rt) { MCInst_setOpcode(MI, (Mips_BNVC_MMR6)); MCOperand_CreateReg0( MI, (getReg(MI, Mips_GPR32RegClassID, Rt))); MCOperand_CreateReg0( MI, (getReg(MI, Mips_GPR32RegClassID, Rs))); Imm = SignExtend64(fieldFromInstruction_4(insn, 0, 16), 16) * 2 + 4; } else if (Rs != 0 && Rs < Rt) { MCInst_setOpcode(MI, (Mips_BNEC_MMR6)); MCOperand_CreateReg0( MI, (getReg(MI, Mips_GPR32RegClassID, Rs))); MCOperand_CreateReg0( MI, (getReg(MI, Mips_GPR32RegClassID, Rt))); Imm = SignExtend64(fieldFromInstruction_4(insn, 0, 16), 16) * 4 + 4; } else { MCInst_setOpcode(MI, (Mips_BNEZALC_MMR6)); MCOperand_CreateReg0( MI, (getReg(MI, Mips_GPR32RegClassID, Rt))); Imm = SignExtend64(fieldFromInstruction_4(insn, 0, 16), 16) * 2 + 4; } MCOperand_CreateImm0(MI, (Imm)); return MCDisassembler_Success; } static DecodeStatus DecodePOP65GroupBranchMMR6(MCInst *MI, uint32_t insn, uint64_t Address, const void *Decoder) { // We have: // 0b110101 ttttt sssss iiiiiiiiiiiiiiii // Invalid if rt == 0 // BGTZC_MMR6 if rs == 0 && rt != 0 // BLTZC_MMR6 if rs == rt && rt != 0 // BLTC_MMR6 if rs != rt && rs != 0 && rt != 0 uint32_t Rt = fieldFromInstruction_4(insn, 21, 5); uint32_t Rs = fieldFromInstruction_4(insn, 16, 5); int64_t Imm = SignExtend64(fieldFromInstruction_4(insn, 0, 16), 16) * 4 + 4; bool HasRs = false; if (Rt == 0) return MCDisassembler_Fail; else if (Rs == 0) MCInst_setOpcode(MI, (Mips_BGTZC_MMR6)); else if (Rs == Rt) MCInst_setOpcode(MI, (Mips_BLTZC_MMR6)); else { MCInst_setOpcode(MI, (Mips_BLTC_MMR6)); HasRs = true; } if (HasRs) MCOperand_CreateReg0( MI, (getReg(MI, Mips_GPR32RegClassID, Rs))); MCOperand_CreateReg0(MI, (getReg(MI, Mips_GPR32RegClassID, Rt))); MCOperand_CreateImm0(MI, (Imm)); return MCDisassembler_Success; } static DecodeStatus DecodePOP75GroupBranchMMR6(MCInst *MI, uint32_t insn, uint64_t Address, const void *Decoder) { // We have: // 0b111101 ttttt sssss iiiiiiiiiiiiiiii // Invalid if rt == 0 // BLEZC_MMR6 if rs == 0 && rt != 0 // BGEZC_MMR6 if rs == rt && rt != 0 // BGEC_MMR6 if rs != rt && rs != 0 && rt != 0 uint32_t Rt = fieldFromInstruction_4(insn, 21, 5); uint32_t Rs = fieldFromInstruction_4(insn, 16, 5); int64_t Imm = SignExtend64(fieldFromInstruction_4(insn, 0, 16), 16) * 4 + 4; bool HasRs = false; if (Rt == 0) return MCDisassembler_Fail; else if (Rs == 0) MCInst_setOpcode(MI, (Mips_BLEZC_MMR6)); else if (Rs == Rt) MCInst_setOpcode(MI, (Mips_BGEZC_MMR6)); else { HasRs = true; MCInst_setOpcode(MI, (Mips_BGEC_MMR6)); } if (HasRs) MCOperand_CreateReg0( MI, (getReg(MI, Mips_GPR32RegClassID, Rs))); MCOperand_CreateReg0(MI, (getReg(MI, Mips_GPR32RegClassID, Rt))); MCOperand_CreateImm0(MI, (Imm)); return MCDisassembler_Success; } static DecodeStatus DecodeBlezlGroupBranch(MCInst *MI, uint32_t insn, uint64_t Address, const void *Decoder) { // If we are called then we can assume that MIPS32r6/MIPS64r6 is enabled // (otherwise we would have matched the BLEZL instruction from the earlier // ISA's instead). // // We have: // 0b010110 sssss ttttt iiiiiiiiiiiiiiii // Invalid if rs == 0 // BLEZC if rs == 0 && rt != 0 // BGEZC if rs == rt && rt != 0 // BGEC if rs != rt && rs != 0 && rt != 0 uint32_t Rs = fieldFromInstruction_4(insn, 21, 5); uint32_t Rt = fieldFromInstruction_4(insn, 16, 5); int64_t Imm = SignExtend64(fieldFromInstruction_4(insn, 0, 16), 16) * 4 + 4; bool HasRs = false; if (Rt == 0) return MCDisassembler_Fail; else if (Rs == 0) MCInst_setOpcode(MI, (Mips_BLEZC)); else if (Rs == Rt) MCInst_setOpcode(MI, (Mips_BGEZC)); else { HasRs = true; MCInst_setOpcode(MI, (Mips_BGEC)); } if (HasRs) MCOperand_CreateReg0( MI, (getReg(MI, Mips_GPR32RegClassID, Rs))); MCOperand_CreateReg0(MI, (getReg(MI, Mips_GPR32RegClassID, Rt))); MCOperand_CreateImm0(MI, (Imm)); return MCDisassembler_Success; } static DecodeStatus DecodeBgtzlGroupBranch(MCInst *MI, uint32_t insn, uint64_t Address, const void *Decoder) { // If we are called then we can assume that MIPS32r6/MIPS64r6 is enabled // (otherwise we would have matched the BGTZL instruction from the earlier // ISA's instead). // // We have: // 0b010111 sssss ttttt iiiiiiiiiiiiiiii // Invalid if rs == 0 // BGTZC if rs == 0 && rt != 0 // BLTZC if rs == rt && rt != 0 // BLTC if rs != rt && rs != 0 && rt != 0 bool HasRs = false; uint32_t Rs = fieldFromInstruction_4(insn, 21, 5); uint32_t Rt = fieldFromInstruction_4(insn, 16, 5); int64_t Imm = SignExtend64(fieldFromInstruction_4(insn, 0, 16), 16) * 4 + 4; if (Rt == 0) return MCDisassembler_Fail; else if (Rs == 0) MCInst_setOpcode(MI, (Mips_BGTZC)); else if (Rs == Rt) MCInst_setOpcode(MI, (Mips_BLTZC)); else { MCInst_setOpcode(MI, (Mips_BLTC)); HasRs = true; } if (HasRs) MCOperand_CreateReg0( MI, (getReg(MI, Mips_GPR32RegClassID, Rs))); MCOperand_CreateReg0(MI, (getReg(MI, Mips_GPR32RegClassID, Rt))); MCOperand_CreateImm0(MI, (Imm)); return MCDisassembler_Success; } static DecodeStatus DecodeBgtzGroupBranch(MCInst *MI, uint32_t insn, uint64_t Address, const void *Decoder) { // If we are called then we can assume that MIPS32r6/MIPS64r6 is enabled // (otherwise we would have matched the BGTZ instruction from the earlier // ISA's instead). // // We have: // 0b000111 sssss ttttt iiiiiiiiiiiiiiii // BGTZ if rt == 0 // BGTZALC if rs == 0 && rt != 0 // BLTZALC if rs != 0 && rs == rt // BLTUC if rs != 0 && rs != rt uint32_t Rs = fieldFromInstruction_4(insn, 21, 5); uint32_t Rt = fieldFromInstruction_4(insn, 16, 5); int64_t Imm = SignExtend64(fieldFromInstruction_4(insn, 0, 16), 16) * 4 + 4; bool HasRs = false; bool HasRt = false; if (Rt == 0) { MCInst_setOpcode(MI, (Mips_BGTZ)); HasRs = true; } else if (Rs == 0) { MCInst_setOpcode(MI, (Mips_BGTZALC)); HasRt = true; } else if (Rs == Rt) { MCInst_setOpcode(MI, (Mips_BLTZALC)); HasRs = true; } else { MCInst_setOpcode(MI, (Mips_BLTUC)); HasRs = true; HasRt = true; } if (HasRs) MCOperand_CreateReg0( MI, (getReg(MI, Mips_GPR32RegClassID, Rs))); if (HasRt) MCOperand_CreateReg0( MI, (getReg(MI, Mips_GPR32RegClassID, Rt))); MCOperand_CreateImm0(MI, (Imm)); return MCDisassembler_Success; } static DecodeStatus DecodeBlezGroupBranch(MCInst *MI, uint32_t insn, uint64_t Address, const void *Decoder) { // If we are called then we can assume that MIPS32r6/MIPS64r6 is enabled // (otherwise we would have matched the BLEZL instruction from the earlier // ISA's instead). // // We have: // 0b000110 sssss ttttt iiiiiiiiiiiiiiii // Invalid if rs == 0 // BLEZALC if rs == 0 && rt != 0 // BGEZALC if rs == rt && rt != 0 // BGEUC if rs != rt && rs != 0 && rt != 0 uint32_t Rs = fieldFromInstruction_4(insn, 21, 5); uint32_t Rt = fieldFromInstruction_4(insn, 16, 5); int64_t Imm = SignExtend64(fieldFromInstruction_4(insn, 0, 16), 16) * 4 + 4; bool HasRs = false; if (Rt == 0) return MCDisassembler_Fail; else if (Rs == 0) MCInst_setOpcode(MI, (Mips_BLEZALC)); else if (Rs == Rt) MCInst_setOpcode(MI, (Mips_BGEZALC)); else { HasRs = true; MCInst_setOpcode(MI, (Mips_BGEUC)); } if (HasRs) MCOperand_CreateReg0( MI, (getReg(MI, Mips_GPR32RegClassID, Rs))); MCOperand_CreateReg0(MI, (getReg(MI, Mips_GPR32RegClassID, Rt))); MCOperand_CreateImm0(MI, (Imm)); return MCDisassembler_Success; } // Override the generated disassembler to produce DEXT all the time. This is // for feature / behaviour parity with binutils. static DecodeStatus DecodeDEXT(MCInst *MI, uint32_t Insn, uint64_t Address, const void *Decoder) { unsigned Msbd = fieldFromInstruction_4(Insn, 11, 5); unsigned Lsb = fieldFromInstruction_4(Insn, 6, 5); unsigned Size = 0; unsigned Pos = 0; switch (MCInst_getOpcode(MI)) { case Mips_DEXT: Pos = Lsb; Size = Msbd + 1; break; case Mips_DEXTM: Pos = Lsb; Size = Msbd + 1 + 32; break; case Mips_DEXTU: Pos = Lsb + 32; Size = Msbd + 1; break; default: CS_ASSERT_RET_VAL(0 && "Unknown DEXT instruction!", MCDisassembler_Fail); } MCInst_setOpcode(MI, (Mips_DEXT)); uint32_t Rs = fieldFromInstruction_4(Insn, 21, 5); uint32_t Rt = fieldFromInstruction_4(Insn, 16, 5); MCOperand_CreateReg0(MI, (getReg(MI, Mips_GPR64RegClassID, Rt))); MCOperand_CreateReg0(MI, (getReg(MI, Mips_GPR64RegClassID, Rs))); MCOperand_CreateImm0(MI, (Pos)); MCOperand_CreateImm0(MI, (Size)); return MCDisassembler_Success; } // Override the generated disassembler to produce DINS all the time. This is // for feature / behaviour parity with binutils. static DecodeStatus DecodeDINS(MCInst *MI, uint32_t Insn, uint64_t Address, const void *Decoder) { unsigned Msbd = fieldFromInstruction_4(Insn, 11, 5); unsigned Lsb = fieldFromInstruction_4(Insn, 6, 5); unsigned Size = 0; unsigned Pos = 0; switch (MCInst_getOpcode(MI)) { case Mips_DINS: Pos = Lsb; Size = Msbd + 1 - Pos; break; case Mips_DINSM: Pos = Lsb; Size = Msbd + 33 - Pos; break; case Mips_DINSU: Pos = Lsb + 32; // mbsd = pos + size - 33 // mbsd - pos + 33 = size Size = Msbd + 33 - Pos; break; default: CS_ASSERT_RET_VAL(0 && "Unknown DINS instruction!", MCDisassembler_Fail); } uint32_t Rs = fieldFromInstruction_4(Insn, 21, 5); uint32_t Rt = fieldFromInstruction_4(Insn, 16, 5); MCInst_setOpcode(MI, (Mips_DINS)); MCOperand_CreateReg0(MI, (getReg(MI, Mips_GPR64RegClassID, Rt))); MCOperand_CreateReg0(MI, (getReg(MI, Mips_GPR64RegClassID, Rs))); MCOperand_CreateImm0(MI, (Pos)); MCOperand_CreateImm0(MI, (Size)); return MCDisassembler_Success; } // Auto-generated decoder wouldn't add the third operand for CRC32*. static DecodeStatus DecodeCRC(MCInst *MI, uint32_t Insn, uint64_t Address, const void *Decoder) { uint32_t Rs = fieldFromInstruction_4(Insn, 21, 5); uint32_t Rt = fieldFromInstruction_4(Insn, 16, 5); MCOperand_CreateReg0(MI, (getReg(MI, Mips_GPR32RegClassID, Rt))); MCOperand_CreateReg0(MI, (getReg(MI, Mips_GPR32RegClassID, Rs))); MCOperand_CreateReg0(MI, (getReg(MI, Mips_GPR32RegClassID, Rt))); return MCDisassembler_Success; } /// Read two bytes from the ArrayRef and return 16 bit halfword sorted /// according to the given endianness. static DecodeStatus readInstruction16(const uint8_t *Bytes, size_t BytesLen, uint64_t Address, uint64_t *Size, uint64_t *Insn, bool IsBigEndian) { // We want to read exactly 2 Bytes of data. if (BytesLen < 2) { *Size = 0; return MCDisassembler_Fail; } if (IsBigEndian) { *Insn = (Bytes[0] << 8) | Bytes[1]; } else { *Insn = (Bytes[1] << 8) | Bytes[0]; } return MCDisassembler_Success; } /// Read four bytes from the ArrayRef and return 32 bit word sorted /// according to the given endianness. static DecodeStatus readInstruction32(const uint8_t *Bytes, size_t BytesLen, uint64_t Address, uint64_t *Size, uint64_t *Insn, bool IsBigEndian, bool IsMicroMips) { // We want to read exactly 4 Bytes of data. if (BytesLen < 4) { *Size = 0; return MCDisassembler_Fail; } // High 16 bits of a 32-bit microMIPS instruction (where the opcode is) // always precede the low 16 bits in the instruction stream (that is, they // are placed at lower addresses in the instruction stream). // // microMIPS byte ordering: // Big-endian: 0 | 1 | 2 | 3 // Little-endian: 1 | 0 | 3 | 2 if (IsBigEndian) { // Encoded as a big-endian 32-bit word in the stream. *Insn = (Bytes[3] << 0) | (Bytes[2] << 8) | (Bytes[1] << 16) | ((unsigned)Bytes[0] << 24); } else { if (IsMicroMips) { *Insn = (Bytes[2] << 0) | (Bytes[3] << 8) | (Bytes[0] << 16) | ((unsigned)Bytes[1] << 24); } else { *Insn = (Bytes[0] << 0) | (Bytes[1] << 8) | (Bytes[2] << 16) | ((unsigned)Bytes[3] << 24); } } return MCDisassembler_Success; } /// Read 6 bytes from the ArrayRef and return in a 64-bit bit word sorted /// according to the given endianness and encoding byte-order. static DecodeStatus readInstruction48(const uint8_t *Bytes, size_t BytesLen, uint64_t Address, uint64_t *Size, uint64_t *Insn, bool IsBigEndian, bool IsNanoMips) { // We want to read exactly 6 Bytes of little-endian data in nanoMIPS mode. if (BytesLen < 6 || IsBigEndian || !IsNanoMips) { *Size = 0; return MCDisassembler_Fail; } // High 16 bits of a 32-bit nanoMIPS instruction (where the opcode is) // always precede the low 16 bits in the instruction stream (that is, they // are placed at lower addresses in the instruction stream). // // nanoMIPS byte ordering: // Little-endian: 1 | 0 | 3 | 2 | 5 | 4 *Insn = (Bytes[0] << 0) | (Bytes[1] << 8); *Insn = ((*Insn << 32) | (Bytes[4] << 0) | (Bytes[5] << 8) | (Bytes[2] << 16) | ((unsigned)Bytes[3] << 24)); return MCDisassembler_Success; } static DecodeStatus getInstruction(MCInst *Instr, uint64_t *Size, const uint8_t *Bytes, size_t BytesLen, uint64_t Address, SStream *CStream) { uint64_t Insn; DecodeStatus Result; *Size = 0; cs_mode mode = Instr->csh->mode; bool IsBigEndian = mode & CS_MODE_BIG_ENDIAN; bool IsMicroMips = Mips_getFeatureBits(mode, Mips_FeatureMicroMips); bool IsNanoMips = Mips_getFeatureBits(mode, Mips_FeatureNanoMips); bool IsMips32r6 = Mips_getFeatureBits(mode, Mips_FeatureMips32r6); bool IsMips2 = Mips_getFeatureBits(mode, Mips_FeatureMips2); bool IsMips16 = Mips_getFeatureBits(mode, Mips_FeatureMips16); bool IsCnMips = Mips_getFeatureBits(mode, Mips_FeatureCnMips); bool IsCnMipsP = Mips_getFeatureBits(mode, Mips_FeatureCnMipsP); bool IsFP64 = Mips_getFeatureBits(mode, Mips_FeatureFP64Bit); bool IsGP64 = Mips_getFeatureBits(mode, Mips_FeatureGP64Bit); bool IsPTR64 = Mips_getFeatureBits(mode, Mips_FeaturePTR64Bit); // Only present in MIPS-I and MIPS-II bool HasCOP3 = !Mips_getFeatureBits(mode, Mips_FeatureMips32) && !Mips_getFeatureBits(mode, Mips_FeatureMips3); if (IsNanoMips) { uint64_t Insn2; Result = readInstruction48(Bytes, BytesLen, Address, Size, &Insn2, IsBigEndian, IsNanoMips); if (Result != MCDisassembler_Fail) { // Calling the auto-generated decoder function. Result = decodeInstruction_8(DecoderTableNanoMips48, Instr, Insn2, Address, NULL); if (Result != MCDisassembler_Fail) { *Size = 6; return Result; } } Result = readInstruction32(Bytes, BytesLen, Address, Size, &Insn, IsBigEndian, IsNanoMips); if (Result != MCDisassembler_Fail) { // Calling the auto-generated decoder function. Result = decodeInstruction_4(DecoderTableNanoMips32, Instr, Insn, Address, NULL); if (Result != MCDisassembler_Fail) { *Size = 4; return Result; } } Result = readInstruction16(Bytes, BytesLen, Address, Size, &Insn, IsBigEndian); if (Result != MCDisassembler_Fail) { Result = decodeInstruction_2(DecoderTableNanoMips_Conflict_Space16, Instr, Insn, Address, NULL); if (Result != MCDisassembler_Fail) { *Size = 2; return Result; } // Calling the auto-generated decoder function for NanoMips // 16-bit instructions. Result = decodeInstruction_2(DecoderTableNanoMips16, Instr, Insn, Address, NULL); if (Result != MCDisassembler_Fail) { *Size = 2; return Result; } } // This is an invalid instruction. Claim that the Size is 2 bytes. Since // nanoMIPS instructions have a minimum alignment of 2, the next 2 bytes // could form a valid instruction. *Size = 2; return MCDisassembler_Fail; } if (IsMicroMips) { Result = readInstruction16(Bytes, BytesLen, Address, Size, &Insn, IsBigEndian); if (Result == MCDisassembler_Fail) return MCDisassembler_Fail; if (IsMips32r6) { // Calling the auto-generated decoder function for microMIPS32R6 // 16-bit instructions. Result = decodeInstruction_2(DecoderTableMicroMipsR616, Instr, Insn, Address, NULL); if (Result != MCDisassembler_Fail) { *Size = 2; return Result; } } // Calling the auto-generated decoder function for microMIPS 16-bit // instructions. Result = decodeInstruction_2(DecoderTableMicroMips16, Instr, Insn, Address, NULL); if (Result != MCDisassembler_Fail) { *Size = 2; return Result; } Result = readInstruction32(Bytes, BytesLen, Address, Size, &Insn, IsBigEndian, IsMicroMips); if (Result == MCDisassembler_Fail) return MCDisassembler_Fail; if (IsMips32r6) { // Calling the auto-generated decoder function. Result = decodeInstruction_4(DecoderTableMicroMipsR6_Ambiguous32, Instr, Insn, Address, NULL); if (Result != MCDisassembler_Fail) { *Size = 4; return Result; } Result = decodeInstruction_4(DecoderTableMicroMipsR632, Instr, Insn, Address, NULL); if (Result != MCDisassembler_Fail) { *Size = 4; return Result; } } // Calling the auto-generated decoder function. Result = decodeInstruction_4(DecoderTableMicroMips32, Instr, Insn, Address, NULL); if (Result != MCDisassembler_Fail) { *Size = 4; return Result; } Result = decodeInstruction_4(DecoderTableMicroMipsDSP32, Instr, Insn, Address, NULL); if (Result != MCDisassembler_Fail) { *Size = 4; return Result; } if (IsFP64) { Result = decodeInstruction_4(DecoderTableMicroMipsFP6432, Instr, Insn, Address, NULL); if (Result != MCDisassembler_Fail) { *Size = 4; return Result; } } // This is an invalid instruction. Claim that the Size is 2 bytes. Since // microMIPS instructions have a minimum alignment of 2, the next 2 bytes // could form a valid instruction. The two bytes we rejected as an // instruction could have actually beeen an inline constant pool that is // unconditionally branched over. *Size = 2; return MCDisassembler_Fail; } if (IsMips16) { Result = readInstruction32(Bytes, BytesLen, Address, Size, &Insn, IsBigEndian, IsMicroMips); if (Result != MCDisassembler_Fail) { Result = decodeInstruction_4(DecoderTable32, Instr, Insn, Address, NULL); if (Result != MCDisassembler_Fail) { *Size = 4; return Result; } } Result = readInstruction16(Bytes, BytesLen, Address, Size, &Insn, IsBigEndian); if (Result == MCDisassembler_Fail) { return MCDisassembler_Fail; } *Size = 2; return decodeInstruction_2(DecoderTable16, Instr, Insn, Address, NULL); } // Attempt to read the instruction so that we can attempt to decode it. If // the buffer is not 4 bytes long, let the higher level logic figure out // what to do with a size of zero and MCDisassembler::Fail. Result = readInstruction32(Bytes, BytesLen, Address, Size, &Insn, IsBigEndian, IsMicroMips); if (Result == MCDisassembler_Fail) return MCDisassembler_Fail; // The only instruction size for standard encoded MIPS. *Size = 4; if (HasCOP3) { Result = decodeInstruction_4(DecoderTableCOP3_32, Instr, Insn, Address, NULL); if (Result != MCDisassembler_Fail) return Result; } if (IsMips32r6 && IsGP64) { Result = decodeInstruction_4(DecoderTableMips32r6_64r6_GP6432, Instr, Insn, Address, NULL); if (Result != MCDisassembler_Fail) return Result; } if (IsMips32r6 && IsPTR64) { Result = decodeInstruction_4(DecoderTableMips32r6_64r6_PTR6432, Instr, Insn, Address, NULL); if (Result != MCDisassembler_Fail) return Result; } if (IsMips32r6) { Result = decodeInstruction_4(DecoderTableMips32r6_64r6_Ambiguous32, Instr, Insn, Address, NULL); if (Result != MCDisassembler_Fail) return Result; Result = decodeInstruction_4(DecoderTableMips32r6_64r6_BranchZero32, Instr, Insn, Address, NULL); if (Result != MCDisassembler_Fail) return Result; Result = decodeInstruction_4(DecoderTableMips32r6_64r632, Instr, Insn, Address, NULL); if (Result != MCDisassembler_Fail) return Result; } if (IsMips2 && IsPTR64) { Result = decodeInstruction_4(DecoderTableMips32_64_PTR6432, Instr, Insn, Address, NULL); if (Result != MCDisassembler_Fail) return Result; } if (IsCnMips) { Result = decodeInstruction_4(DecoderTableCnMips32, Instr, Insn, Address, NULL); if (Result != MCDisassembler_Fail) return Result; } if (IsCnMipsP) { Result = decodeInstruction_4(DecoderTableCnMipsP32, Instr, Insn, Address, NULL); if (Result != MCDisassembler_Fail) return Result; } if (IsGP64) { Result = decodeInstruction_4(DecoderTableMips6432, Instr, Insn, Address, NULL); if (Result != MCDisassembler_Fail) return Result; } if (IsFP64) { Result = decodeInstruction_4(DecoderTableMipsFP6432, Instr, Insn, Address, NULL); if (Result != MCDisassembler_Fail) return Result; } Result = decodeInstruction_4(DecoderTableMipsDSP32, Instr, Insn, Address, NULL); if (Result != MCDisassembler_Fail) return Result; // Calling the auto-generated decoder function. Result = decodeInstruction_4(DecoderTableMips32, Instr, Insn, Address, NULL); if (Result != MCDisassembler_Fail) return Result; return MCDisassembler_Fail; } static DecodeStatus DecodeCPU16RegsRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder) { if (RegNo > 7) return MCDisassembler_Fail; if (RegNo < 2) RegNo += 16; unsigned Reg = getReg(Inst, Mips_GPR32RegClassID, RegNo); MCOperand_CreateReg0(Inst, (Reg)); return MCDisassembler_Success; } static DecodeStatus DecodeGPR64RegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder) { if (RegNo > 31) return MCDisassembler_Fail; unsigned Reg = getReg(Inst, Mips_GPR64RegClassID, RegNo); MCOperand_CreateReg0(Inst, (Reg)); return MCDisassembler_Success; } static DecodeStatus DecodeGPRMM16RegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder) { if (RegNo > 7) return MCDisassembler_Fail; unsigned Reg = getReg(Inst, Mips_GPRMM16RegClassID, RegNo); MCOperand_CreateReg0(Inst, (Reg)); return MCDisassembler_Success; } static DecodeStatus DecodeGPRMM16ZeroRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder) { if (RegNo > 7) return MCDisassembler_Fail; unsigned Reg = getReg(Inst, Mips_GPRMM16ZeroRegClassID, RegNo); MCOperand_CreateReg0(Inst, (Reg)); return MCDisassembler_Success; } static DecodeStatus DecodeGPRMM16MovePRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder) { if (RegNo > 7) return MCDisassembler_Fail; unsigned Reg = getReg(Inst, Mips_GPRMM16MovePRegClassID, RegNo); MCOperand_CreateReg0(Inst, (Reg)); return MCDisassembler_Success; } static DecodeStatus DecodeGPR32RegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder) { if (RegNo > 31) return MCDisassembler_Fail; unsigned Reg = getReg(Inst, Mips_GPR32RegClassID, RegNo); MCOperand_CreateReg0(Inst, (Reg)); return MCDisassembler_Success; } static DecodeStatus DecodeGPRNM3RegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder) { if (RegNo > 7) return MCDisassembler_Fail; RegNo |= ((RegNo & 0x4) ^ 0x4) << 2; unsigned Reg = getReg(Inst, Mips_GPRNM32RegClassID, RegNo); MCOperand_CreateReg0(Inst, (Reg)); return MCDisassembler_Success; } static DecodeStatus DecodeGPRNMRARegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder) { MCOperand_CreateReg0(Inst, (Mips_RA_NM)); return MCDisassembler_Success; } static DecodeStatus DecodeGPRNM3ZRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder) { if (RegNo > 7) return MCDisassembler_Fail; if (RegNo != 0) RegNo |= ((RegNo & 0x4) ^ 0x4) << 2; unsigned Reg = getReg(Inst, Mips_GPRNM32RegClassID, RegNo); MCOperand_CreateReg0(Inst, (Reg)); return MCDisassembler_Success; } static DecodeStatus DecodeGPRNM4RegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder) { if (RegNo > 31) return MCDisassembler_Fail; RegNo &= ~0x8; RegNo += (RegNo < 4 ? 8 : 0); unsigned Reg = getReg(Inst, Mips_GPRNM32RegClassID, RegNo); MCOperand_CreateReg0(Inst, (Reg)); return MCDisassembler_Success; } static DecodeStatus DecodeGPRNM4ZRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder) { if (RegNo > 31) return MCDisassembler_Fail; RegNo &= ~0x8; if (RegNo == 3) RegNo = 0; else RegNo += (RegNo < 3 ? 8 : 0); unsigned Reg = getReg(Inst, Mips_GPRNM32RegClassID, RegNo); MCOperand_CreateReg0(Inst, (Reg)); return MCDisassembler_Success; } static DecodeStatus DecodeGPRNM32NZRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder) { if (RegNo == 0) return MCDisassembler_Fail; unsigned Reg = getReg(Inst, Mips_GPRNM32RegClassID, RegNo); MCOperand_CreateReg0(Inst, (Reg)); return MCDisassembler_Success; } static DecodeStatus DecodeGPRNM32RegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder) { if (RegNo > 31) return MCDisassembler_Fail; unsigned Reg = getReg(Inst, Mips_GPRNM32RegClassID, RegNo); MCOperand_CreateReg0(Inst, (Reg)); return MCDisassembler_Success; } static DecodeStatus DecodeGPRNM2R1RegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder) { if (RegNo > 31) return MCDisassembler_Fail; RegNo += 4; unsigned Reg = getReg(Inst, Mips_GPRNM32RegClassID, RegNo); MCOperand_CreateReg0(Inst, (Reg)); MCOperand_CreateReg0(Inst, (Reg + 1)); return MCDisassembler_Success; } static DecodeStatus DecodeGPRNM1R1RegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder) { if (RegNo != 0 && RegNo != 1) return MCDisassembler_Fail; RegNo += 4; unsigned Reg = getReg(Inst, Mips_GPRNM32RegClassID, RegNo); MCOperand_CreateReg0(Inst, (Reg)); return MCDisassembler_Success; } static DecodeStatus DecodePtrRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder) { if (Mips_getFeatureBits(Inst->csh->mode, Mips_FeatureGP64Bit)) return DecodeGPR64RegisterClass(Inst, RegNo, Address, Decoder); return DecodeGPR32RegisterClass(Inst, RegNo, Address, Decoder); } static DecodeStatus DecodeDSPRRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder) { return DecodeGPR32RegisterClass(Inst, RegNo, Address, Decoder); } static DecodeStatus DecodeFGR64RegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder) { if (RegNo > 31) return MCDisassembler_Fail; unsigned Reg = getReg(Inst, Mips_FGR64RegClassID, RegNo); MCOperand_CreateReg0(Inst, (Reg)); return MCDisassembler_Success; } static DecodeStatus DecodeFGR32RegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder) { if (RegNo > 31) return MCDisassembler_Fail; unsigned Reg = getReg(Inst, Mips_FGR32RegClassID, RegNo); MCOperand_CreateReg0(Inst, (Reg)); return MCDisassembler_Success; } static DecodeStatus DecodeCCRRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder) { if (RegNo > 31) return MCDisassembler_Fail; unsigned Reg = getReg(Inst, Mips_CCRRegClassID, RegNo); MCOperand_CreateReg0(Inst, (Reg)); return MCDisassembler_Success; } static DecodeStatus DecodeFCCRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder) { if (RegNo > 7) return MCDisassembler_Fail; unsigned Reg = getReg(Inst, Mips_FCCRegClassID, RegNo); MCOperand_CreateReg0(Inst, (Reg)); return MCDisassembler_Success; } static DecodeStatus DecodeFGRCCRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder) { if (RegNo > 31) return MCDisassembler_Fail; unsigned Reg = getReg(Inst, Mips_FGRCCRegClassID, RegNo); MCOperand_CreateReg0(Inst, (Reg)); return MCDisassembler_Success; } static DecodeStatus DecodeMem(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder) { int Offset = SignExtend32((Insn & 0xffff), 16); unsigned Reg = fieldFromInstruction_4(Insn, 16, 5); unsigned Base = fieldFromInstruction_4(Insn, 21, 5); Reg = getReg(Inst, Mips_GPR32RegClassID, Reg); Base = getReg(Inst, Mips_GPR32RegClassID, Base); if (MCInst_getOpcode(Inst) == Mips_SC || MCInst_getOpcode(Inst) == Mips_SCD) MCOperand_CreateReg0(Inst, (Reg)); MCOperand_CreateReg0(Inst, (Reg)); MCOperand_CreateReg0(Inst, (Base)); MCOperand_CreateImm0(Inst, (Offset)); return MCDisassembler_Success; } #define DEFINE_DecodeMemNM(Offbits, isSigned, rt) \ static DecodeStatus CONCAT(DecodeMemNM, \ CONCAT(Offbits, CONCAT(isSigned, rt)))( \ MCInst * Inst, uint32_t Insn, uint64_t Address, \ const void *Decoder) \ { \ int Offset = (Insn & ((1 << Offbits) - 1)); \ if (isSigned) \ Offset = SignExtend32((Offset), Offbits); \ unsigned Base; \ \ switch (rt) { \ case Mips_GPRNMGPRegClassID: \ case Mips_GPRNMSPRegClassID: \ Base = 0; \ break; \ case Mips_GPRNM3RegClassID: \ Base = fieldFromInstruction_4(Insn, Offbits, 3); \ break; \ case Mips_GPRNM4RegClassID: \ case Mips_GPRNM4ZRegClassID: \ \ break; \ default: \ Base = fieldFromInstruction_4(Insn, Offbits, 5); \ } \ Base = getReg(Inst, rt, Base); \ \ MCOperand_CreateReg0(Inst, (Base)); \ MCOperand_CreateImm0(Inst, (Offset)); \ \ return MCDisassembler_Success; \ } DEFINE_DecodeMemNM(6, 0, Mips_GPRNM3RegClassID); DEFINE_DecodeMemNM(7, 0, Mips_GPRNMSPRegClassID); DEFINE_DecodeMemNM(9, 0, Mips_GPRNMGPRegClassID); DEFINE_DecodeMemNM(2, 0, Mips_GPRNM3RegClassID); DEFINE_DecodeMemNM(3, 0, Mips_GPRNM3RegClassID); DEFINE_DecodeMemNM(21, 0, Mips_GPRNMGPRegClassID); DEFINE_DecodeMemNM(18, 0, Mips_GPRNMGPRegClassID); DEFINE_DecodeMemNM(12, 0, Mips_GPRNM32RegClassID); DEFINE_DecodeMemNM(9, 1, Mips_GPRNM32RegClassID); static DecodeStatus DecodeMemZeroNM(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder) { unsigned Base; Base = fieldFromInstruction_4(Insn, 0, 5); Base = getReg(Inst, Mips_GPRNM32RegClassID, Base); MCOperand_CreateReg0(Inst, (Base)); return MCDisassembler_Success; } #define DEFINE_DecodeMemNMRX(RegClass) \ static DecodeStatus CONCAT(DecodeMemNMRX, RegClass)( \ MCInst * Inst, uint32_t Insn, uint64_t Address, \ const void *Decoder) \ { \ unsigned Offset; \ unsigned Base; \ Offset = fieldFromInstruction_4(Insn, 0, 5); \ Base = fieldFromInstruction_4(Insn, 5, 5); \ \ Base = getReg(Inst, RegClass, Base); \ Offset = getReg(Inst, RegClass, Offset); \ MCOperand_CreateReg0(Inst, (Base)); \ MCOperand_CreateReg0(Inst, (Offset)); \ \ return MCDisassembler_Success; \ } DEFINE_DecodeMemNMRX(Mips_GPRNM3RegClassID); DEFINE_DecodeMemNMRX(Mips_GPRNM32RegClassID); static DecodeStatus DecodeMemNM4x4(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder) { int Offset = fieldFromInstruction_4(Insn, 0, 4); unsigned Base; Base = getReg(Inst, Mips_GPRNM32RegClassID, fieldFromInstruction_4(Insn, 4, 5) & ~0x8); MCOperand_CreateReg0(Inst, (Base)); MCOperand_CreateImm0(Inst, (Offset)); return MCDisassembler_Success; } static DecodeStatus DecodeMemEVA(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder) { int Offset = SignExtend32((Insn >> 7), 9); unsigned Reg = fieldFromInstruction_4(Insn, 16, 5); unsigned Base = fieldFromInstruction_4(Insn, 21, 5); Reg = getReg(Inst, Mips_GPR32RegClassID, Reg); Base = getReg(Inst, Mips_GPR32RegClassID, Base); if (MCInst_getOpcode(Inst) == Mips_SCE) MCOperand_CreateReg0(Inst, (Reg)); MCOperand_CreateReg0(Inst, (Reg)); MCOperand_CreateReg0(Inst, (Base)); MCOperand_CreateImm0(Inst, (Offset)); return MCDisassembler_Success; } #include "MipsCP0RegisterMap.h" static DecodeStatus DecodeCOP0SelRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder) { int Reg = COP0Map_getEncIndexMap(RegNo); if (Reg != -1) { Reg = getReg(Inst, Mips_COP0SelRegClassID, Reg); MCOperand_CreateReg0(Inst, (Reg)); } else { // Not a named register encoding - print numeric register and select value switch (MCInst_getOpcode(Inst)) { case Mips_MFC0Sel_NM: MCInst_setOpcode(Inst, (Mips_MFC0_NM)); break; case Mips_MFHC0Sel_NM: MCInst_setOpcode(Inst, (Mips_MFHC0_NM)); break; case Mips_MTC0Sel_NM: MCInst_setOpcode(Inst, (Mips_MTC0_NM)); break; case Mips_MTHC0Sel_NM: MCInst_setOpcode(Inst, (Mips_MTHC0_NM)); break; default: CS_ASSERT_RET_VAL(0 && "Unknown instruction!", MCDisassembler_Fail); } Reg = getReg(Inst, Mips_COP0RegClassID, RegNo >> 5); MCOperand_CreateReg0(Inst, (Reg)); MCOperand_CreateImm0(Inst, (RegNo & 0x1f)); } return MCDisassembler_Success; } static DecodeStatus DecodeLoadByte15(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder) { int Offset = SignExtend32((Insn & 0xffff), 16); unsigned Base = fieldFromInstruction_4(Insn, 16, 5); unsigned Reg = fieldFromInstruction_4(Insn, 21, 5); Base = getReg(Inst, Mips_GPR32RegClassID, Base); Reg = getReg(Inst, Mips_GPR32RegClassID, Reg); MCOperand_CreateReg0(Inst, (Reg)); MCOperand_CreateReg0(Inst, (Base)); MCOperand_CreateImm0(Inst, (Offset)); return MCDisassembler_Success; } static DecodeStatus DecodeCacheOp(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder) { int Offset = SignExtend32((Insn & 0xffff), 16); unsigned Hint = fieldFromInstruction_4(Insn, 16, 5); unsigned Base = fieldFromInstruction_4(Insn, 21, 5); Base = getReg(Inst, Mips_GPR32RegClassID, Base); MCOperand_CreateReg0(Inst, (Base)); MCOperand_CreateImm0(Inst, (Offset)); MCOperand_CreateImm0(Inst, (Hint)); return MCDisassembler_Success; } static DecodeStatus DecodeCacheOpMM(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder) { int Offset = SignExtend32((Insn & 0xfff), 12); unsigned Base = fieldFromInstruction_4(Insn, 16, 5); unsigned Hint = fieldFromInstruction_4(Insn, 21, 5); Base = getReg(Inst, Mips_GPR32RegClassID, Base); MCOperand_CreateReg0(Inst, (Base)); MCOperand_CreateImm0(Inst, (Offset)); MCOperand_CreateImm0(Inst, (Hint)); return MCDisassembler_Success; } static DecodeStatus DecodePrefeOpMM(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder) { int Offset = SignExtend32((Insn & 0x1ff), 9); unsigned Base = fieldFromInstruction_4(Insn, 16, 5); unsigned Hint = fieldFromInstruction_4(Insn, 21, 5); Base = getReg(Inst, Mips_GPR32RegClassID, Base); MCOperand_CreateReg0(Inst, (Base)); MCOperand_CreateImm0(Inst, (Offset)); MCOperand_CreateImm0(Inst, (Hint)); return MCDisassembler_Success; } static DecodeStatus DecodeCacheeOp_CacheOpR6(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder) { int Offset = SignExtend32((Insn >> 7), 9); unsigned Hint = fieldFromInstruction_4(Insn, 16, 5); unsigned Base = fieldFromInstruction_4(Insn, 21, 5); Base = getReg(Inst, Mips_GPR32RegClassID, Base); MCOperand_CreateReg0(Inst, (Base)); MCOperand_CreateImm0(Inst, (Offset)); MCOperand_CreateImm0(Inst, (Hint)); return MCDisassembler_Success; } static DecodeStatus DecodeSyncI(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder) { int Offset = SignExtend32((Insn & 0xffff), 16); unsigned Base = fieldFromInstruction_4(Insn, 21, 5); Base = getReg(Inst, Mips_GPR32RegClassID, Base); MCOperand_CreateReg0(Inst, (Base)); MCOperand_CreateImm0(Inst, (Offset)); return MCDisassembler_Success; } static DecodeStatus DecodeSyncI_MM(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder) { int Offset = SignExtend32((Insn & 0xffff), 16); unsigned Base = fieldFromInstruction_4(Insn, 16, 5); Base = getReg(Inst, Mips_GPR32RegClassID, Base); MCOperand_CreateReg0(Inst, (Base)); MCOperand_CreateImm0(Inst, (Offset)); return MCDisassembler_Success; } static DecodeStatus DecodeSynciR6(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder) { int Immediate = SignExtend32((Insn & 0xffff), 16); unsigned Base = fieldFromInstruction_4(Insn, 16, 5); Base = getReg(Inst, Mips_GPR32RegClassID, Base); MCOperand_CreateReg0(Inst, (Base)); MCOperand_CreateImm0(Inst, (Immediate)); return MCDisassembler_Success; } static DecodeStatus DecodeMSA128Mem(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder) { int Offset = SignExtend32((fieldFromInstruction_4(Insn, 16, 10)), 10); unsigned Reg = fieldFromInstruction_4(Insn, 6, 5); unsigned Base = fieldFromInstruction_4(Insn, 11, 5); Reg = getReg(Inst, Mips_MSA128BRegClassID, Reg); Base = getReg(Inst, Mips_GPR32RegClassID, Base); MCOperand_CreateReg0(Inst, (Reg)); MCOperand_CreateReg0(Inst, (Base)); // The immediate field of an LD/ST instruction is scaled which means it must // be multiplied (when decoding) by the size (in bytes) of the instructions' // data format. // .b - 1 byte // .h - 2 bytes // .w - 4 bytes // .d - 8 bytes switch (MCInst_getOpcode(Inst)) { default: return MCDisassembler_Fail; break; case Mips_LD_B: case Mips_ST_B: MCOperand_CreateImm0(Inst, (Offset)); break; case Mips_LD_H: case Mips_ST_H: MCOperand_CreateImm0(Inst, (Offset * 2)); break; case Mips_LD_W: case Mips_ST_W: MCOperand_CreateImm0(Inst, (Offset * 4)); break; case Mips_LD_D: case Mips_ST_D: MCOperand_CreateImm0(Inst, (Offset * 8)); break; } return MCDisassembler_Success; } static DecodeStatus DecodeMemMMImm4(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder) { unsigned Offset = Insn & 0xf; unsigned Reg = fieldFromInstruction_4(Insn, 7, 3); unsigned Base = fieldFromInstruction_4(Insn, 4, 3); switch (MCInst_getOpcode(Inst)) { case Mips_LBU16_MM: case Mips_LHU16_MM: case Mips_LW16_MM: if (DecodeGPRMM16RegisterClass(Inst, Reg, Address, Decoder) == MCDisassembler_Fail) return MCDisassembler_Fail; break; case Mips_SB16_MM: case Mips_SB16_MMR6: case Mips_SH16_MM: case Mips_SH16_MMR6: case Mips_SW16_MM: case Mips_SW16_MMR6: if (DecodeGPRMM16ZeroRegisterClass( Inst, Reg, Address, Decoder) == MCDisassembler_Fail) return MCDisassembler_Fail; break; } if (DecodeGPRMM16RegisterClass(Inst, Base, Address, Decoder) == MCDisassembler_Fail) return MCDisassembler_Fail; switch (MCInst_getOpcode(Inst)) { case Mips_LBU16_MM: if (Offset == 0xf) MCOperand_CreateImm0(Inst, (-1)); else MCOperand_CreateImm0(Inst, (Offset)); break; case Mips_SB16_MM: case Mips_SB16_MMR6: MCOperand_CreateImm0(Inst, (Offset)); break; case Mips_LHU16_MM: case Mips_SH16_MM: case Mips_SH16_MMR6: MCOperand_CreateImm0(Inst, (Offset << 1)); break; case Mips_LW16_MM: case Mips_SW16_MM: case Mips_SW16_MMR6: MCOperand_CreateImm0(Inst, (Offset << 2)); break; } return MCDisassembler_Success; } static DecodeStatus DecodeMemMMSPImm5Lsl2(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder) { unsigned Offset = Insn & 0x1F; unsigned Reg = fieldFromInstruction_4(Insn, 5, 5); Reg = getReg(Inst, Mips_GPR32RegClassID, Reg); MCOperand_CreateReg0(Inst, (Reg)); MCOperand_CreateReg0(Inst, (Mips_SP)); MCOperand_CreateImm0(Inst, (Offset << 2)); return MCDisassembler_Success; } static DecodeStatus DecodeMemMMGPImm7Lsl2(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder) { unsigned Offset = Insn & 0x7F; unsigned Reg = fieldFromInstruction_4(Insn, 7, 3); Reg = getReg(Inst, Mips_GPR32RegClassID, Reg); MCOperand_CreateReg0(Inst, (Reg)); MCOperand_CreateReg0(Inst, (Mips_GP)); MCOperand_CreateImm0(Inst, (Offset << 2)); return MCDisassembler_Success; } static DecodeStatus DecodeMemMMReglistImm4Lsl2(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder) { int Offset; switch (MCInst_getOpcode(Inst)) { case Mips_LWM16_MMR6: case Mips_SWM16_MMR6: Offset = fieldFromInstruction_4(Insn, 4, 4); break; default: Offset = SignExtend32((Insn & 0xf), 4); break; } if (DecodeRegListOperand16(Inst, Insn, Address, Decoder) == MCDisassembler_Fail) return MCDisassembler_Fail; MCOperand_CreateReg0(Inst, (Mips_SP)); MCOperand_CreateImm0(Inst, (Offset << 2)); return MCDisassembler_Success; } static DecodeStatus DecodeMemMMImm9(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder) { int Offset = SignExtend32((Insn & 0x1ff), 9); unsigned Reg = fieldFromInstruction_4(Insn, 21, 5); unsigned Base = fieldFromInstruction_4(Insn, 16, 5); Reg = getReg(Inst, Mips_GPR32RegClassID, Reg); Base = getReg(Inst, Mips_GPR32RegClassID, Base); if (MCInst_getOpcode(Inst) == Mips_SCE_MM || MCInst_getOpcode(Inst) == Mips_SC_MMR6) MCOperand_CreateReg0(Inst, (Reg)); MCOperand_CreateReg0(Inst, (Reg)); MCOperand_CreateReg0(Inst, (Base)); MCOperand_CreateImm0(Inst, (Offset)); return MCDisassembler_Success; } static DecodeStatus DecodeMemMMImm12(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder) { int Offset = SignExtend32((Insn & 0x0fff), 12); unsigned Reg = fieldFromInstruction_4(Insn, 21, 5); unsigned Base = fieldFromInstruction_4(Insn, 16, 5); Reg = getReg(Inst, Mips_GPR32RegClassID, Reg); Base = getReg(Inst, Mips_GPR32RegClassID, Base); switch (MCInst_getOpcode(Inst)) { case Mips_SWM32_MM: case Mips_LWM32_MM: if (DecodeRegListOperand(Inst, Insn, Address, Decoder) == MCDisassembler_Fail) return MCDisassembler_Fail; MCOperand_CreateReg0(Inst, (Base)); MCOperand_CreateImm0(Inst, (Offset)); break; case Mips_SC_MM: MCOperand_CreateReg0(Inst, (Reg)); // fall through default: MCOperand_CreateReg0(Inst, (Reg)); if (MCInst_getOpcode(Inst) == Mips_LWP_MM || MCInst_getOpcode(Inst) == Mips_SWP_MM) MCOperand_CreateReg0(Inst, (Reg + 1)); MCOperand_CreateReg0(Inst, (Base)); MCOperand_CreateImm0(Inst, (Offset)); } return MCDisassembler_Success; } static DecodeStatus DecodeMemMMImm16(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder) { int Offset = SignExtend32((Insn & 0xffff), 16); unsigned Reg = fieldFromInstruction_4(Insn, 21, 5); unsigned Base = fieldFromInstruction_4(Insn, 16, 5); Reg = getReg(Inst, Mips_GPR32RegClassID, Reg); Base = getReg(Inst, Mips_GPR32RegClassID, Base); MCOperand_CreateReg0(Inst, (Reg)); MCOperand_CreateReg0(Inst, (Base)); MCOperand_CreateImm0(Inst, (Offset)); return MCDisassembler_Success; } static DecodeStatus DecodeFMem(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder) { int Offset = SignExtend32((Insn & 0xffff), 16); unsigned Reg = fieldFromInstruction_4(Insn, 16, 5); unsigned Base = fieldFromInstruction_4(Insn, 21, 5); Reg = getReg(Inst, Mips_FGR64RegClassID, Reg); Base = getReg(Inst, Mips_GPR32RegClassID, Base); MCOperand_CreateReg0(Inst, (Reg)); MCOperand_CreateReg0(Inst, (Base)); MCOperand_CreateImm0(Inst, (Offset)); return MCDisassembler_Success; } static DecodeStatus DecodeFMemMMR2(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder) { // This function is the same as DecodeFMem but with the Reg and Base fields // swapped according to microMIPS spec. int Offset = SignExtend32((Insn & 0xffff), 16); unsigned Base = fieldFromInstruction_4(Insn, 16, 5); unsigned Reg = fieldFromInstruction_4(Insn, 21, 5); Reg = getReg(Inst, Mips_FGR64RegClassID, Reg); Base = getReg(Inst, Mips_GPR32RegClassID, Base); MCOperand_CreateReg0(Inst, (Reg)); MCOperand_CreateReg0(Inst, (Base)); MCOperand_CreateImm0(Inst, (Offset)); return MCDisassembler_Success; } static DecodeStatus DecodeFMem2(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder) { int Offset = SignExtend32((Insn & 0xffff), 16); unsigned Reg = fieldFromInstruction_4(Insn, 16, 5); unsigned Base = fieldFromInstruction_4(Insn, 21, 5); Reg = getReg(Inst, Mips_COP2RegClassID, Reg); Base = getReg(Inst, Mips_GPR32RegClassID, Base); MCOperand_CreateReg0(Inst, (Reg)); MCOperand_CreateReg0(Inst, (Base)); MCOperand_CreateImm0(Inst, (Offset)); return MCDisassembler_Success; } static DecodeStatus DecodeFMem3(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder) { int Offset = SignExtend32((Insn & 0xffff), 16); unsigned Reg = fieldFromInstruction_4(Insn, 16, 5); unsigned Base = fieldFromInstruction_4(Insn, 21, 5); Reg = getReg(Inst, Mips_COP3RegClassID, Reg); Base = getReg(Inst, Mips_GPR32RegClassID, Base); MCOperand_CreateReg0(Inst, (Reg)); MCOperand_CreateReg0(Inst, (Base)); MCOperand_CreateImm0(Inst, (Offset)); return MCDisassembler_Success; } static DecodeStatus DecodeFMemCop2R6(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder) { int Offset = SignExtend32((Insn & 0x07ff), 11); unsigned Reg = fieldFromInstruction_4(Insn, 16, 5); unsigned Base = fieldFromInstruction_4(Insn, 11, 5); Reg = getReg(Inst, Mips_COP2RegClassID, Reg); Base = getReg(Inst, Mips_GPR32RegClassID, Base); MCOperand_CreateReg0(Inst, (Reg)); MCOperand_CreateReg0(Inst, (Base)); MCOperand_CreateImm0(Inst, (Offset)); return MCDisassembler_Success; } static DecodeStatus DecodeFMemCop2MMR6(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder) { int Offset = SignExtend32((Insn & 0x07ff), 11); unsigned Reg = fieldFromInstruction_4(Insn, 21, 5); unsigned Base = fieldFromInstruction_4(Insn, 16, 5); Reg = getReg(Inst, Mips_COP2RegClassID, Reg); Base = getReg(Inst, Mips_GPR32RegClassID, Base); MCOperand_CreateReg0(Inst, (Reg)); MCOperand_CreateReg0(Inst, (Base)); MCOperand_CreateImm0(Inst, (Offset)); return MCDisassembler_Success; } static DecodeStatus DecodeSpecial3LlSc(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder) { int64_t Offset = SignExtend64(((Insn >> 7) & 0x1ff), 9); unsigned Rt = fieldFromInstruction_4(Insn, 16, 5); unsigned Base = fieldFromInstruction_4(Insn, 21, 5); Rt = getReg(Inst, Mips_GPR32RegClassID, Rt); Base = getReg(Inst, Mips_GPR32RegClassID, Base); if (MCInst_getOpcode(Inst) == Mips_SC_R6 || MCInst_getOpcode(Inst) == Mips_SCD_R6) { MCOperand_CreateReg0(Inst, (Rt)); } MCOperand_CreateReg0(Inst, (Rt)); MCOperand_CreateReg0(Inst, (Base)); MCOperand_CreateImm0(Inst, (Offset)); return MCDisassembler_Success; } static DecodeStatus DecodeHWRegsRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder) { // Currently only hardware register 29 is supported. if (RegNo != 29) return MCDisassembler_Fail; MCOperand_CreateReg0(Inst, (Mips_HWR29)); return MCDisassembler_Success; } static DecodeStatus DecodeAFGR64RegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder) { if (RegNo > 30 || RegNo % 2) return MCDisassembler_Fail; unsigned Reg = getReg(Inst, Mips_AFGR64RegClassID, RegNo / 2); MCOperand_CreateReg0(Inst, (Reg)); return MCDisassembler_Success; } static DecodeStatus DecodeACC64DSPRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder) { if (RegNo >= 4) return MCDisassembler_Fail; unsigned Reg = getReg(Inst, Mips_ACC64DSPRegClassID, RegNo); MCOperand_CreateReg0(Inst, (Reg)); return MCDisassembler_Success; } static DecodeStatus DecodeHI32DSPRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder) { if (RegNo >= 4) return MCDisassembler_Fail; unsigned Reg = getReg(Inst, Mips_HI32DSPRegClassID, RegNo); MCOperand_CreateReg0(Inst, (Reg)); return MCDisassembler_Success; } static DecodeStatus DecodeLO32DSPRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder) { if (RegNo >= 4) return MCDisassembler_Fail; unsigned Reg = getReg(Inst, Mips_LO32DSPRegClassID, RegNo); MCOperand_CreateReg0(Inst, (Reg)); return MCDisassembler_Success; } static DecodeStatus DecodeMSA128BRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder) { if (RegNo > 31) return MCDisassembler_Fail; unsigned Reg = getReg(Inst, Mips_MSA128BRegClassID, RegNo); MCOperand_CreateReg0(Inst, (Reg)); return MCDisassembler_Success; } static DecodeStatus DecodeMSA128HRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder) { if (RegNo > 31) return MCDisassembler_Fail; unsigned Reg = getReg(Inst, Mips_MSA128HRegClassID, RegNo); MCOperand_CreateReg0(Inst, (Reg)); return MCDisassembler_Success; } static DecodeStatus DecodeMSA128WRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder) { if (RegNo > 31) return MCDisassembler_Fail; unsigned Reg = getReg(Inst, Mips_MSA128WRegClassID, RegNo); MCOperand_CreateReg0(Inst, (Reg)); return MCDisassembler_Success; } static DecodeStatus DecodeMSA128DRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder) { if (RegNo > 31) return MCDisassembler_Fail; unsigned Reg = getReg(Inst, Mips_MSA128DRegClassID, RegNo); MCOperand_CreateReg0(Inst, (Reg)); return MCDisassembler_Success; } static DecodeStatus DecodeMSACtrlRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder) { if (RegNo > 7) return MCDisassembler_Fail; unsigned Reg = getReg(Inst, Mips_MSACtrlRegClassID, RegNo); MCOperand_CreateReg0(Inst, (Reg)); return MCDisassembler_Success; } static DecodeStatus DecodeCOP0RegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder) { if (RegNo > 31) return MCDisassembler_Fail; unsigned Reg = getReg(Inst, Mips_COP0RegClassID, RegNo); MCOperand_CreateReg0(Inst, (Reg)); return MCDisassembler_Success; } static DecodeStatus DecodeCOP2RegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder) { if (RegNo > 31) return MCDisassembler_Fail; unsigned Reg = getReg(Inst, Mips_COP2RegClassID, RegNo); MCOperand_CreateReg0(Inst, (Reg)); return MCDisassembler_Success; } static DecodeStatus DecodeBranchTarget(MCInst *Inst, unsigned Offset, uint64_t Address, const void *Decoder) { int32_t BranchOffset = (SignExtend32((Offset), 16) * 4) + 4; MCOperand_CreateImm0(Inst, (BranchOffset)); return MCDisassembler_Success; } static DecodeStatus DecodeBranchTarget1SImm16(MCInst *Inst, unsigned Offset, uint64_t Address, const void *Decoder) { int32_t BranchOffset = (SignExtend32((Offset), 16) * 2); MCOperand_CreateImm0(Inst, (BranchOffset)); return MCDisassembler_Success; } static DecodeStatus DecodeJumpTarget(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder) { unsigned JumpOffset = fieldFromInstruction_4(Insn, 0, 26) << 2; MCOperand_CreateImm0(Inst, (JumpOffset)); return MCDisassembler_Success; } static DecodeStatus DecodeBranchTarget21(MCInst *Inst, unsigned Offset, uint64_t Address, const void *Decoder) { int32_t BranchOffset = SignExtend32((Offset), 21) * 4 + 4; MCOperand_CreateImm0(Inst, (BranchOffset)); return MCDisassembler_Success; } static DecodeStatus DecodeBranchTarget21MM(MCInst *Inst, unsigned Offset, uint64_t Address, const void *Decoder) { int32_t BranchOffset = SignExtend32((Offset), 21) * 4 + 4; MCOperand_CreateImm0(Inst, (BranchOffset)); return MCDisassembler_Success; } static DecodeStatus DecodeBranchTarget26(MCInst *Inst, unsigned Offset, uint64_t Address, const void *Decoder) { int32_t BranchOffset = SignExtend32((Offset), 26) * 4 + 4; MCOperand_CreateImm0(Inst, (BranchOffset)); return MCDisassembler_Success; } static DecodeStatus DecodeBranchTarget7MM(MCInst *Inst, unsigned Offset, uint64_t Address, const void *Decoder) { int32_t BranchOffset = SignExtend32((Offset << 1), 8); MCOperand_CreateImm0(Inst, (BranchOffset)); return MCDisassembler_Success; } static DecodeStatus DecodeBranchTarget10MM(MCInst *Inst, unsigned Offset, uint64_t Address, const void *Decoder) { int32_t BranchOffset = SignExtend32((Offset << 1), 11); MCOperand_CreateImm0(Inst, (BranchOffset)); return MCDisassembler_Success; } static DecodeStatus DecodeBranchTargetMM(MCInst *Inst, unsigned Offset, uint64_t Address, const void *Decoder) { int32_t BranchOffset = SignExtend32((Offset), 16) * 2 + 4; MCOperand_CreateImm0(Inst, (BranchOffset)); return MCDisassembler_Success; } static DecodeStatus DecodeBranchTarget26MM(MCInst *Inst, unsigned Offset, uint64_t Address, const void *Decoder) { int32_t BranchOffset = SignExtend32((Offset << 1), 27); MCOperand_CreateImm0(Inst, (BranchOffset)); return MCDisassembler_Success; } static DecodeStatus DecodeJumpTargetMM(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder) { unsigned JumpOffset = fieldFromInstruction_4(Insn, 0, 26) << 1; MCOperand_CreateImm0(Inst, (JumpOffset)); return MCDisassembler_Success; } #define DEFINE_DecodeBranchTargetNM(Bits) \ static DecodeStatus CONCAT(DecodeBranchTargetNM, Bits)( \ MCInst * Inst, unsigned Offset, uint64_t Address, \ const void *Decoder) \ { \ uint32_t InsnSize = (Bits <= 10) ? 2 : 4; \ int32_t BranchOffset = \ SignExtend32((Offset), Bits + 1) + InsnSize; \ \ MCOperand_CreateImm0(Inst, (BranchOffset)); \ return MCDisassembler_Success; \ } DEFINE_DecodeBranchTargetNM(10); DEFINE_DecodeBranchTargetNM(7); DEFINE_DecodeBranchTargetNM(21); DEFINE_DecodeBranchTargetNM(25); DEFINE_DecodeBranchTargetNM(14); DEFINE_DecodeBranchTargetNM(11); DEFINE_DecodeBranchTargetNM(5); static DecodeStatus DecodeJumpTargetXMM(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder) { unsigned JumpOffset = fieldFromInstruction_4(Insn, 0, 26) << 2; MCOperand_CreateImm0(Inst, (JumpOffset)); return MCDisassembler_Success; } static DecodeStatus DecodeAddiur2Simm7(MCInst *Inst, unsigned Value, uint64_t Address, const void *Decoder) { if (Value == 0) MCOperand_CreateImm0(Inst, (1)); else if (Value == 0x7) MCOperand_CreateImm0(Inst, (-1)); else MCOperand_CreateImm0(Inst, (Value << 2)); return MCDisassembler_Success; } static DecodeStatus DecodeLi16Imm(MCInst *Inst, unsigned Value, uint64_t Address, const void *Decoder) { if (Value == 0x7F) MCOperand_CreateImm0(Inst, (-1)); else MCOperand_CreateImm0(Inst, (Value)); return MCDisassembler_Success; } static DecodeStatus DecodePOOL16BEncodedField(MCInst *Inst, unsigned Value, uint64_t Address, const void *Decoder) { MCOperand_CreateImm0(Inst, (Value == 0x0 ? 8 : Value)); return MCDisassembler_Success; } #define DEFINE_DecodeUImmWithOffsetAndScale(Bits, Offset, Scale) \ static DecodeStatus CONCAT(DecodeUImmWithOffsetAndScale, \ CONCAT(Bits, CONCAT(Offset, Scale)))( \ MCInst * Inst, unsigned Value, uint64_t Address, \ const void *Decoder) \ { \ Value &= ((1 << Bits) - 1); \ Value *= Scale; \ MCOperand_CreateImm0(Inst, (Value + Offset)); \ return MCDisassembler_Success; \ } DEFINE_DecodeUImmWithOffsetAndScale(5, 0, 4); DEFINE_DecodeUImmWithOffsetAndScale(6, 0, 4); DEFINE_DecodeUImmWithOffsetAndScale(2, 1, 1); DEFINE_DecodeUImmWithOffsetAndScale(5, 1, 1); DEFINE_DecodeUImmWithOffsetAndScale(8, 0, 1); DEFINE_DecodeUImmWithOffsetAndScale(18, 0, 1); DEFINE_DecodeUImmWithOffsetAndScale(21, 0, 1); #define DEFINE_DecodeSImmWithOffsetAndScale(Bits, Offset, ScaleBy) \ static DecodeStatus CONCAT(DecodeSImmWithOffsetAndScale, \ CONCAT(Bits, CONCAT(Offset, ScaleBy)))( \ MCInst * Inst, unsigned Value, uint64_t Address, \ const void *Decoder) \ { \ int32_t Imm = SignExtend32((Value), Bits) * ScaleBy; \ MCOperand_CreateImm0(Inst, (Imm + Offset)); \ return MCDisassembler_Success; \ } #define DEFINE_DecodeSImmWithOffsetAndScale_2(Bits, Offset) DEFINE_DecodeSImmWithOffsetAndScale(Bits, Offset, 1) #define DEFINE_DecodeSImmWithOffsetAndScale_3(Bits) DEFINE_DecodeSImmWithOffsetAndScale(Bits, 0, 1) DEFINE_DecodeSImmWithOffsetAndScale_3(16); DEFINE_DecodeSImmWithOffsetAndScale_3(10); DEFINE_DecodeSImmWithOffsetAndScale_3(4); DEFINE_DecodeSImmWithOffsetAndScale_3(6); DEFINE_DecodeSImmWithOffsetAndScale_3(32); static DecodeStatus DecodeInsSize(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder) { // First we need to grab the pos(lsb) from MCInst. // This function only handles the 32 bit variants of ins, as dins // variants are handled differently. int Pos = MCOperand_getImm(MCInst_getOperand(Inst, (2))); int Size = (int)Insn - Pos + 1; MCOperand_CreateImm0(Inst, (SignExtend32((Size), 16))); return MCDisassembler_Success; } static DecodeStatus DecodeSimm19Lsl2(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder) { MCOperand_CreateImm0(Inst, (SignExtend32((Insn), 19) * 4)); return MCDisassembler_Success; } static DecodeStatus DecodeSimm18Lsl3(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder) { MCOperand_CreateImm0(Inst, (SignExtend32((Insn), 18) * 8)); return MCDisassembler_Success; } static DecodeStatus DecodeSimm9SP(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder) { int32_t DecodedValue; switch (Insn) { case 0: DecodedValue = 256; break; case 1: DecodedValue = 257; break; case 510: DecodedValue = -258; break; case 511: DecodedValue = -257; break; default: DecodedValue = SignExtend32((Insn), 9); break; } MCOperand_CreateImm0(Inst, (DecodedValue * 4)); return MCDisassembler_Success; } static DecodeStatus DecodeANDI16Imm(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder) { // Insn must be >= 0, since it is unsigned that condition is always true. int32_t DecodedValues[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16, 31, 32, 63, 64, 255, 32768, 65535 }; MCOperand_CreateImm0(Inst, (DecodedValues[Insn])); return MCDisassembler_Success; } static DecodeStatus DecodeRegListOperand(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder) { unsigned Regs[] = { Mips_S0, Mips_S1, Mips_S2, Mips_S3, Mips_S4, Mips_S5, Mips_S6, Mips_S7, Mips_FP }; unsigned RegNum; unsigned RegLst = fieldFromInstruction_4(Insn, 21, 5); // Empty register lists are not allowed. if (RegLst == 0) return MCDisassembler_Fail; RegNum = RegLst & 0xf; // RegLst values 10-15, and 26-31 are reserved. if (RegNum > 9) return MCDisassembler_Fail; for (unsigned i = 0; i < RegNum; i++) MCOperand_CreateReg0(Inst, (Regs[i])); if (RegLst & 0x10) MCOperand_CreateReg0(Inst, (Mips_RA)); return MCDisassembler_Success; } static DecodeStatus DecodeRegListOperand16(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder) { unsigned Regs[] = { Mips_S0, Mips_S1, Mips_S2, Mips_S3 }; unsigned RegLst; switch (MCInst_getOpcode(Inst)) { default: RegLst = fieldFromInstruction_4(Insn, 4, 2); break; case Mips_LWM16_MMR6: case Mips_SWM16_MMR6: RegLst = fieldFromInstruction_4(Insn, 8, 2); break; } unsigned RegNum = RegLst & 0x3; for (unsigned i = 0; i <= RegNum; i++) MCOperand_CreateReg0(Inst, (Regs[i])); MCOperand_CreateReg0(Inst, (Mips_RA)); return MCDisassembler_Success; } static DecodeStatus DecodeMovePOperands(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder) { unsigned RegPair = fieldFromInstruction_4(Insn, 7, 3); if (DecodeMovePRegPair(Inst, RegPair, Address, Decoder) == MCDisassembler_Fail) return MCDisassembler_Fail; unsigned RegRs; if (Inst->csh->mode & CS_MODE_MIPS32R6) RegRs = fieldFromInstruction_4(Insn, 0, 2) | (fieldFromInstruction_4(Insn, 3, 1) << 2); else RegRs = fieldFromInstruction_4(Insn, 1, 3); if (DecodeGPRMM16MovePRegisterClass(Inst, RegRs, Address, Decoder) == MCDisassembler_Fail) return MCDisassembler_Fail; unsigned RegRt = fieldFromInstruction_4(Insn, 4, 3); if (DecodeGPRMM16MovePRegisterClass(Inst, RegRt, Address, Decoder) == MCDisassembler_Fail) return MCDisassembler_Fail; return MCDisassembler_Success; } static DecodeStatus DecodeMovePRegPair(MCInst *Inst, unsigned RegPair, uint64_t Address, const void *Decoder) { switch (RegPair) { default: return MCDisassembler_Fail; case 0: MCOperand_CreateReg0(Inst, (Mips_A1)); MCOperand_CreateReg0(Inst, (Mips_A2)); break; case 1: MCOperand_CreateReg0(Inst, (Mips_A1)); MCOperand_CreateReg0(Inst, (Mips_A3)); break; case 2: MCOperand_CreateReg0(Inst, (Mips_A2)); MCOperand_CreateReg0(Inst, (Mips_A3)); break; case 3: MCOperand_CreateReg0(Inst, (Mips_A0)); MCOperand_CreateReg0(Inst, (Mips_S5)); break; case 4: MCOperand_CreateReg0(Inst, (Mips_A0)); MCOperand_CreateReg0(Inst, (Mips_S6)); break; case 5: MCOperand_CreateReg0(Inst, (Mips_A0)); MCOperand_CreateReg0(Inst, (Mips_A1)); break; case 6: MCOperand_CreateReg0(Inst, (Mips_A0)); MCOperand_CreateReg0(Inst, (Mips_A2)); break; case 7: MCOperand_CreateReg0(Inst, (Mips_A0)); MCOperand_CreateReg0(Inst, (Mips_A3)); break; } return MCDisassembler_Success; } static DecodeStatus DecodeSimm23Lsl2(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder) { MCOperand_CreateImm0(Inst, (SignExtend32((Insn << 2), 25))); return MCDisassembler_Success; } static DecodeStatus DecodeBgtzGroupBranchMMR6(MCInst *MI, uint32_t insn, uint64_t Address, const void *Decoder) { // We have: // 0b000111 ttttt sssss iiiiiiiiiiiiiiii // Invalid if rt == 0 // BGTZALC_MMR6 if rs == 0 && rt != 0 // BLTZALC_MMR6 if rs != 0 && rs == rt // BLTUC_MMR6 if rs != 0 && rs != rt uint32_t Rt = fieldFromInstruction_4(insn, 21, 5); uint32_t Rs = fieldFromInstruction_4(insn, 16, 5); uint32_t Imm = 0; bool HasRs = false; bool HasRt = false; if (Rt == 0) return MCDisassembler_Fail; else if (Rs == 0) { MCInst_setOpcode(MI, (Mips_BGTZALC_MMR6)); HasRt = true; Imm = SignExtend64(fieldFromInstruction_4(insn, 0, 16), 16) * 2 + 4; } else if (Rs == Rt) { MCInst_setOpcode(MI, (Mips_BLTZALC_MMR6)); HasRs = true; Imm = SignExtend64(fieldFromInstruction_4(insn, 0, 16), 16) * 2 + 4; } else { MCInst_setOpcode(MI, (Mips_BLTUC_MMR6)); HasRs = true; HasRt = true; Imm = SignExtend64(fieldFromInstruction_4(insn, 0, 16), 16) * 4 + 4; } if (HasRs) MCOperand_CreateReg0( MI, (getReg(MI, Mips_GPR32RegClassID, Rs))); if (HasRt) MCOperand_CreateReg0( MI, (getReg(MI, Mips_GPR32RegClassID, Rt))); MCOperand_CreateImm0(MI, (Imm)); return MCDisassembler_Success; } static DecodeStatus DecodeBlezGroupBranchMMR6(MCInst *MI, uint32_t insn, uint64_t Address, const void *Decoder) { // We have: // 0b000110 ttttt sssss iiiiiiiiiiiiiiii // Invalid if rt == 0 // BLEZALC_MMR6 if rs == 0 && rt != 0 // BGEZALC_MMR6 if rs == rt && rt != 0 // BGEUC_MMR6 if rs != rt && rs != 0 && rt != 0 uint32_t Rt = fieldFromInstruction_4(insn, 21, 5); uint32_t Rs = fieldFromInstruction_4(insn, 16, 5); uint32_t Imm = 0; bool HasRs = false; if (Rt == 0) return MCDisassembler_Fail; else if (Rs == 0) { MCInst_setOpcode(MI, (Mips_BLEZALC_MMR6)); Imm = SignExtend64(fieldFromInstruction_4(insn, 0, 16), 16) * 2 + 4; } else if (Rs == Rt) { MCInst_setOpcode(MI, (Mips_BGEZALC_MMR6)); Imm = SignExtend64(fieldFromInstruction_4(insn, 0, 16), 16) * 2 + 4; } else { HasRs = true; MCInst_setOpcode(MI, (Mips_BGEUC_MMR6)); Imm = SignExtend64(fieldFromInstruction_4(insn, 0, 16), 16) * 4 + 4; } if (HasRs) MCOperand_CreateReg0( MI, (getReg(MI, Mips_GPR32RegClassID, Rs))); MCOperand_CreateReg0(MI, (getReg(MI, Mips_GPR32RegClassID, Rt))); MCOperand_CreateImm0(MI, (Imm)); return MCDisassembler_Success; } // This instruction does not have a working decoder, and needs to be // fixed. This "fixme" function was introduced to keep the backend compiling, // while making changes to tablegen code. static DecodeStatus DecodeFIXMEInstruction(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder) { return MCDisassembler_Fail; } static DecodeStatus DecodeImmM1To126(MCInst *Inst, unsigned Value, uint64_t Address, const void *Decoder) { if (Value == 127) MCOperand_CreateImm0(Inst, (-1)); else MCOperand_CreateImm0(Inst, (Value)); return MCDisassembler_Success; } static DecodeStatus DecodeUImm4Mask(MCInst *Inst, unsigned Value, uint64_t Address, const void *Decoder) { if (Value == 12) MCOperand_CreateImm0(Inst, (0xff)); else if (Value == 13) MCOperand_CreateImm0(Inst, (0xffff)); else MCOperand_CreateImm0(Inst, (Value)); return MCDisassembler_Success; } static DecodeStatus DecodeUImm3Shift(MCInst *Inst, unsigned Value, uint64_t Address, const void *Decoder) { if (Value == 0) MCOperand_CreateImm0(Inst, (8)); else MCOperand_CreateImm0(Inst, (Value)); return MCDisassembler_Success; } static DecodeStatus DecodeNMRegListOperand(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder) { unsigned RegStart = fieldFromInstruction_4(Insn, 5, 5); unsigned RegCount = fieldFromInstruction_4(Insn, 1, 4); unsigned GP_bit = fieldFromInstruction_4(Insn, 0, 1); unsigned i; unsigned RegNo; MCOperand_CreateReg0( Inst, (getReg(Inst, Mips_GPRNM32RegClassID, RegStart))); for (i = RegStart + 1; i < RegStart + RegCount; i++) { if (i == RegStart + RegCount - 1 && GP_bit) RegNo = 28; else if (i > 31) RegNo = 16 + (i % 32); // $ra+1 wraps to $s0 else RegNo = i; MCOperand_CreateReg0( Inst, (getReg(Inst, Mips_GPRNM32RegClassID, RegNo))); } return MCDisassembler_Success; } static DecodeStatus DecodeNMRegList16Operand(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder) { unsigned RegStart = 30 + fieldFromInstruction_4(Insn, 4, 1); unsigned RegCount = fieldFromInstruction_4(Insn, 0, 4); // Re-encode the parameters for 32-bit instruction operand // and call it's decoder return DecodeNMRegListOperand(Inst, (RegStart << 5) | (RegCount << 1), Address, Decoder); } static DecodeStatus DecodeNegImm12(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder) { int Imm = fieldFromInstruction_4(Insn, 0, 12); MCOperand_CreateImm0(Inst, (-Imm)); return MCDisassembler_Success; } #define DEFINE_DecodeSImmWithReg(Bits, Offset, Scale, RegNum) \ static DecodeStatus CONCAT( \ DecodeSImmWithReg, \ CONCAT(Bits, CONCAT(Offset, CONCAT(Scale, RegNum))))( \ MCInst * Inst, unsigned Value, uint64_t Address, \ const void *Decoder) \ { \ MCOperand_CreateReg0(Inst, (RegNum)); \ return CONCAT(DecodeSImmWithOffsetAndScale, \ CONCAT(Bits, CONCAT(Offset, Scale)))( \ Inst, Value, Address, Decoder); \ } DEFINE_DecodeSImmWithReg(32, 0, 1, Mips_GP_NM); #define DEFINE_DecodeUImmWithReg(Bits, Offset, Scale, RegNum) \ static DecodeStatus CONCAT( \ DecodeUImmWithReg, \ CONCAT(Bits, CONCAT(Offset, CONCAT(Scale, RegNum))))( \ MCInst * Inst, unsigned Value, uint64_t Address, \ const void *Decoder) \ { \ MCOperand_CreateReg0(Inst, (RegNum)); \ return CONCAT(DecodeUImmWithOffsetAndScale, \ CONCAT(Bits, CONCAT(Offset, Scale)))( \ Inst, Value, Address, Decoder); \ } DEFINE_DecodeUImmWithReg(8, 0, 1, Mips_SP_NM); DEFINE_DecodeUImmWithReg(21, 0, 1, Mips_GP_NM); DEFINE_DecodeUImmWithReg(18, 0, 1, Mips_GP_NM); static DecodeStatus DecodeSImm32s12(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder) { uint64_t Imm = ((uint64_t)Insn) << 12; MCOperand_CreateImm0(Inst, (Imm)); return MCDisassembler_Success; } #define DEFINE_DecodeAddressPCRelNM(Bits) \ static DecodeStatus CONCAT(DecodeAddressPCRelNM, Bits)( \ MCInst * Inst, unsigned Offset, uint64_t Address, \ const void *Decoder) \ { \ uint32_t InsnSize = Bits == 32 ? 6 : 4; \ int32_t BranchOffset = \ SignExtend32((Offset), Bits) + InsnSize; \ \ MCOperand_CreateImm0(Inst, (BranchOffset)); \ return MCDisassembler_Success; \ } DEFINE_DecodeAddressPCRelNM(22); DEFINE_DecodeAddressPCRelNM(32); static DecodeStatus DecodeBranchConflictNM(MCInst *Inst, uint32_t Insn, uint64_t Address, const void *Decoder) { unsigned Rt = fieldFromInstruction_4(Insn, 7, 3); unsigned Rs = fieldFromInstruction_4(Insn, 4, 3); unsigned Offset = fieldFromInstruction_4(Insn, 0, 4) << 1; if (Rs < Rt) MCInst_setOpcode(Inst, (Mips_BEQC16_NM)); else MCInst_setOpcode(Inst, (Mips_BNEC16_NM)); if (DecodeGPRNM3RegisterClass(Inst, Rt, Address, Decoder) == MCDisassembler_Success && DecodeGPRNM3RegisterClass(Inst, Rs, Address, Decoder) == MCDisassembler_Success) return CONCAT(DecodeBranchTargetNM, 5)(Inst, Offset, Address, Decoder); else return MCDisassembler_Fail; } DecodeStatus Mips_LLVM_getInstruction(MCInst *Instr, uint64_t *Size, const uint8_t *Bytes, size_t BytesLen, uint64_t Address, SStream *CStream) { return getInstruction(Instr, Size, Bytes, BytesLen, Address, CStream); }