/* 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 */ //===-- XtensaDisassembler.cpp - Disassembler for Xtensa ------------------===// // // The LLVM Compiler Infrastructure // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This file implements the XtensaDisassembler class. // //===----------------------------------------------------------------------===// #include #include #include #include #include "../../MathExtras.h" #include "../../MCDisassembler.h" #include "../../MCFixedLenDisassembler.h" #include "../../SStream.h" #include "../../cs_priv.h" #include "../../utils.h" #include "priv.h" #define GET_INSTRINFO_MC_DESC #include "XtensaGenInstrInfo.inc" #define CONCAT(a, b) CONCAT_(a, b) #define CONCAT_(a, b) a##_##b #define DEBUG_TYPE "Xtensa-disassembler" static const unsigned ARDecoderTable[] = { Xtensa_A0, Xtensa_SP, Xtensa_A2, Xtensa_A3, Xtensa_A4, Xtensa_A5, Xtensa_A6, Xtensa_A7, Xtensa_A8, Xtensa_A9, Xtensa_A10, Xtensa_A11, Xtensa_A12, Xtensa_A13, Xtensa_A14, Xtensa_A15 }; static const unsigned AE_DRDecoderTable[] = { Xtensa_AED0, Xtensa_AED1, Xtensa_AED2, Xtensa_AED3, Xtensa_AED4, Xtensa_AED5, Xtensa_AED6, Xtensa_AED7, Xtensa_AED8, Xtensa_AED9, Xtensa_AED10, Xtensa_AED11, Xtensa_AED12, Xtensa_AED13, Xtensa_AED14, Xtensa_AED15 }; static const unsigned AE_VALIGNDecoderTable[] = { Xtensa_U0, Xtensa_U1, Xtensa_U2, Xtensa_U3 }; static DecodeStatus DecodeAE_DRRegisterClass(MCInst *Inst, uint64_t RegNo, uint64_t Address, const void *Decoder) { if (RegNo >= ARR_SIZE(AE_DRDecoderTable)) return MCDisassembler_Fail; unsigned Reg = AE_DRDecoderTable[RegNo]; MCOperand_CreateReg0(Inst, (Reg)); return MCDisassembler_Success; } static DecodeStatus DecodeAE_VALIGNRegisterClass(MCInst *Inst, uint64_t RegNo, uint64_t Address, const void *Decoder) { if (RegNo >= ARR_SIZE(AE_VALIGNDecoderTable)) return MCDisassembler_Fail; unsigned Reg = AE_VALIGNDecoderTable[RegNo]; MCOperand_CreateReg0(Inst, (Reg)); return MCDisassembler_Success; } static DecodeStatus DecodeARRegisterClass(MCInst *Inst, uint64_t RegNo, uint64_t Address, const void *Decoder) { if (RegNo >= ARR_SIZE(ARDecoderTable)) return MCDisassembler_Fail; unsigned Reg = ARDecoderTable[RegNo]; MCOperand_CreateReg0(Inst, (Reg)); return MCDisassembler_Success; } static const unsigned QRDecoderTable[] = { Xtensa_Q0, Xtensa_Q1, Xtensa_Q2, Xtensa_Q3, Xtensa_Q4, Xtensa_Q5, Xtensa_Q6, Xtensa_Q7 }; static DecodeStatus DecodeQRRegisterClass(MCInst *Inst, uint64_t RegNo, uint64_t Address, const void *Decoder) { if (RegNo >= ARR_SIZE(QRDecoderTable)) return MCDisassembler_Fail; unsigned Reg = QRDecoderTable[RegNo]; MCOperand_CreateReg0(Inst, (Reg)); return MCDisassembler_Success; } static const unsigned FPRDecoderTable[] = { Xtensa_F0, Xtensa_F1, Xtensa_F2, Xtensa_F3, Xtensa_F4, Xtensa_F5, Xtensa_F6, Xtensa_F7, Xtensa_F8, Xtensa_F9, Xtensa_F10, Xtensa_F11, Xtensa_F12, Xtensa_F13, Xtensa_F14, Xtensa_F15 }; static DecodeStatus DecodeFPRRegisterClass(MCInst *Inst, uint64_t RegNo, uint64_t Address, const void *Decoder) { if (RegNo >= ARR_SIZE(FPRDecoderTable)) return MCDisassembler_Fail; unsigned Reg = FPRDecoderTable[RegNo]; MCOperand_CreateReg0(Inst, (Reg)); return MCDisassembler_Success; } static const unsigned BRDecoderTable[] = { Xtensa_B0, Xtensa_B1, Xtensa_B2, Xtensa_B3, Xtensa_B4, Xtensa_B5, Xtensa_B6, Xtensa_B7, Xtensa_B8, Xtensa_B9, Xtensa_B10, Xtensa_B11, Xtensa_B12, Xtensa_B13, Xtensa_B14, Xtensa_B15 }; static const unsigned BR2DecoderTable[] = { Xtensa_B0_B1, Xtensa_B2_B3, Xtensa_B4_B5, Xtensa_B6_B7, Xtensa_B8_B9, Xtensa_B10_B11, Xtensa_B12_B13, Xtensa_B14_B15 }; static const unsigned BR4DecoderTable[] = { Xtensa_B0_B1_B2_B3, Xtensa_B4_B5_B6_B7, Xtensa_B8_B9_B10_B11, Xtensa_B12_B13_B14_B15 }; static DecodeStatus DecodeXtensaRegisterClass(MCInst *Inst, uint64_t RegNo, uint64_t Address, const void *Decoder, const unsigned *DecoderTable, size_t DecoderTableLen) { if (RegNo >= DecoderTableLen) return MCDisassembler_Fail; unsigned Reg = DecoderTable[RegNo]; MCOperand_CreateReg0(Inst, (Reg)); return MCDisassembler_Success; } static DecodeStatus DecodeBR2RegisterClass(MCInst *Inst, uint64_t RegNo, uint64_t Address, const void *Decoder) { return DecodeXtensaRegisterClass(Inst, RegNo, Address, Decoder, BR2DecoderTable, ARR_SIZE(BR2DecoderTable)); } static DecodeStatus DecodeBR4RegisterClass(MCInst *Inst, uint64_t RegNo, uint64_t Address, const void *Decoder) { return DecodeXtensaRegisterClass(Inst, RegNo, Address, Decoder, BR4DecoderTable, ARR_SIZE(BR4DecoderTable)); } static DecodeStatus DecodeBRRegisterClass(MCInst *Inst, uint64_t RegNo, uint64_t Address, const void *Decoder) { if (RegNo >= ARR_SIZE(BRDecoderTable)) return MCDisassembler_Fail; unsigned Reg = BRDecoderTable[RegNo]; MCOperand_CreateReg0(Inst, (Reg)); return MCDisassembler_Success; } static const unsigned MRDecoderTable[] = { Xtensa_M0, Xtensa_M1, Xtensa_M2, Xtensa_M3 }; static DecodeStatus DecodeMRRegisterClass(MCInst *Inst, uint64_t RegNo, uint64_t Address, const void *Decoder) { if (RegNo >= ARR_SIZE(MRDecoderTable)) return MCDisassembler_Fail; unsigned Reg = MRDecoderTable[RegNo]; MCOperand_CreateReg0(Inst, (Reg)); return MCDisassembler_Success; } static const unsigned MR01DecoderTable[] = { Xtensa_M0, Xtensa_M1 }; static DecodeStatus DecodeMR01RegisterClass(MCInst *Inst, uint64_t RegNo, uint64_t Address, const void *Decoder) { if (RegNo >= ARR_SIZE(MR01DecoderTable)) return MCDisassembler_Fail; unsigned Reg = MR01DecoderTable[RegNo]; MCOperand_CreateReg0(Inst, (Reg)); return MCDisassembler_Success; } static const unsigned MR23DecoderTable[] = { Xtensa_M2, Xtensa_M3 }; static DecodeStatus DecodeMR23RegisterClass(MCInst *Inst, uint64_t RegNo, uint64_t Address, const void *Decoder) { if (RegNo >= ARR_SIZE(MR23DecoderTable)) return MCDisassembler_Fail; unsigned Reg = MR23DecoderTable[RegNo]; MCOperand_CreateReg0(Inst, (Reg)); return MCDisassembler_Success; } bool Xtensa_getFeatureBits(unsigned int mode, unsigned int feature) { // we support everything return true; } // Verify SR and UR bool CheckRegister(MCInst *Inst, unsigned RegNo) { unsigned NumIntLevels = 0; unsigned NumTimers = 0; unsigned NumMiscSR = 0; bool IsESP32 = false; bool IsESP32S2 = false; bool Res = true; // Assume that CPU is esp32 by default if ((Inst->csh->mode & CS_MODE_XTENSA_ESP32)) { NumIntLevels = 6; NumTimers = 3; NumMiscSR = 4; IsESP32 = true; } else if (Inst->csh->mode & CS_MODE_XTENSA_ESP32S2) { NumIntLevels = 6; NumTimers = 3; NumMiscSR = 4; IsESP32S2 = true; } else if (Inst->csh->mode & CS_MODE_XTENSA_ESP8266) { NumIntLevels = 2; NumTimers = 1; } switch (RegNo) { case Xtensa_LBEG: case Xtensa_LEND: case Xtensa_LCOUNT: Res = Xtensa_getFeatureBits(Inst->csh->mode, Xtensa_FeatureLoop); break; case Xtensa_BREG: Res = Xtensa_getFeatureBits(Inst->csh->mode, Xtensa_FeatureBoolean); break; case Xtensa_LITBASE: Res = Xtensa_getFeatureBits(Inst->csh->mode, Xtensa_FeatureExtendedL32R); break; case Xtensa_SCOMPARE1: Res = Xtensa_getFeatureBits(Inst->csh->mode, Xtensa_FeatureS32C1I); break; case Xtensa_ACCLO: case Xtensa_ACCHI: case Xtensa_M0: case Xtensa_M1: case Xtensa_M2: case Xtensa_M3: Res = Xtensa_getFeatureBits(Inst->csh->mode, Xtensa_FeatureMAC16); break; case Xtensa_WINDOWBASE: case Xtensa_WINDOWSTART: Res = Xtensa_getFeatureBits(Inst->csh->mode, Xtensa_FeatureWindowed); break; case Xtensa_IBREAKENABLE: case Xtensa_IBREAKA0: case Xtensa_IBREAKA1: case Xtensa_DBREAKA0: case Xtensa_DBREAKA1: case Xtensa_DBREAKC0: case Xtensa_DBREAKC1: case Xtensa_DEBUGCAUSE: case Xtensa_ICOUNT: case Xtensa_ICOUNTLEVEL: Res = Xtensa_getFeatureBits(Inst->csh->mode, Xtensa_FeatureDebug); break; case Xtensa_ATOMCTL: Res = Xtensa_getFeatureBits(Inst->csh->mode, Xtensa_FeatureATOMCTL); break; case Xtensa_MEMCTL: Res = Xtensa_getFeatureBits(Inst->csh->mode, Xtensa_FeatureMEMCTL); break; case Xtensa_EPC1: Res = Xtensa_getFeatureBits(Inst->csh->mode, Xtensa_FeatureException); break; case Xtensa_EPC2: case Xtensa_EPC3: case Xtensa_EPC4: case Xtensa_EPC5: case Xtensa_EPC6: case Xtensa_EPC7: Res = Xtensa_getFeatureBits(Inst->csh->mode, Xtensa_FeatureHighPriInterrupts); Res = Res & (NumIntLevels >= (RegNo - Xtensa_EPC1)); break; case Xtensa_EPS2: case Xtensa_EPS3: case Xtensa_EPS4: case Xtensa_EPS5: case Xtensa_EPS6: case Xtensa_EPS7: Res = Xtensa_getFeatureBits(Inst->csh->mode, Xtensa_FeatureHighPriInterrupts); Res = Res & (NumIntLevels > (RegNo - Xtensa_EPS2)); break; case Xtensa_EXCSAVE1: Res = Xtensa_getFeatureBits(Inst->csh->mode, Xtensa_FeatureException); break; case Xtensa_EXCSAVE2: case Xtensa_EXCSAVE3: case Xtensa_EXCSAVE4: case Xtensa_EXCSAVE5: case Xtensa_EXCSAVE6: case Xtensa_EXCSAVE7: Res = Xtensa_getFeatureBits(Inst->csh->mode, Xtensa_FeatureHighPriInterrupts); Res = Res & (NumIntLevels >= (RegNo - Xtensa_EXCSAVE1)); break; case Xtensa_DEPC: case Xtensa_EXCCAUSE: case Xtensa_EXCVADDR: Res = Xtensa_getFeatureBits(Inst->csh->mode, Xtensa_FeatureException); break; case Xtensa_CPENABLE: Res = Xtensa_getFeatureBits(Inst->csh->mode, Xtensa_FeatureCoprocessor); break; case Xtensa_VECBASE: Res = Xtensa_getFeatureBits(Inst->csh->mode, Xtensa_FeatureRelocatableVector); break; case Xtensa_CCOUNT: Res = Xtensa_getFeatureBits(Inst->csh->mode, Xtensa_FeatureTimerInt); Res &= (NumTimers > 0); break; case Xtensa_CCOMPARE0: case Xtensa_CCOMPARE1: case Xtensa_CCOMPARE2: Res = Xtensa_getFeatureBits(Inst->csh->mode, Xtensa_FeatureTimerInt); Res &= (NumTimers > (RegNo - Xtensa_CCOMPARE0)); break; case Xtensa_PRID: Res = Xtensa_getFeatureBits(Inst->csh->mode, Xtensa_FeaturePRID); break; case Xtensa_INTERRUPT: case Xtensa_INTCLEAR: case Xtensa_INTENABLE: Res = Xtensa_getFeatureBits(Inst->csh->mode, Xtensa_FeatureInterrupt); break; case Xtensa_MISC0: case Xtensa_MISC1: case Xtensa_MISC2: case Xtensa_MISC3: Res = Xtensa_getFeatureBits(Inst->csh->mode, Xtensa_FeatureMiscSR); Res &= (NumMiscSR > (RegNo - Xtensa_MISC0)); break; case Xtensa_THREADPTR: Res = Xtensa_getFeatureBits(Inst->csh->mode, Xtensa_FeatureTHREADPTR); break; case Xtensa_GPIO_OUT: Res = IsESP32S2; break; case Xtensa_EXPSTATE: Res = IsESP32; break; case Xtensa_FCR: case Xtensa_FSR: Res = Xtensa_getFeatureBits(Inst->csh->mode, Xtensa_FeatureSingleFloat); break; case Xtensa_F64R_LO: case Xtensa_F64R_HI: case Xtensa_F64S: Res = Xtensa_getFeatureBits(Inst->csh->mode, Xtensa_FeatureDFPAccel); break; } return Res; } static const unsigned SRDecoderTable[] = { Xtensa_LBEG, 0, Xtensa_LEND, 1, Xtensa_LCOUNT, 2, Xtensa_SAR, 3, Xtensa_BREG, 4, Xtensa_LITBASE, 5, Xtensa_SCOMPARE1, 12, Xtensa_ACCLO, 16, Xtensa_ACCHI, 17, Xtensa_M0, 32, Xtensa_M1, 33, Xtensa_M2, 34, Xtensa_M3, 35, Xtensa_WINDOWBASE, 72, Xtensa_WINDOWSTART, 73, Xtensa_IBREAKENABLE, 96, Xtensa_MEMCTL, 97, Xtensa_ATOMCTL, 99, Xtensa_DDR, 104, Xtensa_IBREAKA0, 128, Xtensa_IBREAKA1, 129, Xtensa_DBREAKA0, 144, Xtensa_DBREAKA1, 145, Xtensa_DBREAKC0, 160, Xtensa_DBREAKC1, 161, Xtensa_CONFIGID0, 176, Xtensa_EPC1, 177, Xtensa_EPC2, 178, Xtensa_EPC3, 179, Xtensa_EPC4, 180, Xtensa_EPC5, 181, Xtensa_EPC6, 182, Xtensa_EPC7, 183, Xtensa_DEPC, 192, Xtensa_EPS2, 194, Xtensa_EPS3, 195, Xtensa_EPS4, 196, Xtensa_EPS5, 197, Xtensa_EPS6, 198, Xtensa_EPS7, 199, Xtensa_CONFIGID1, 208, Xtensa_EXCSAVE1, 209, Xtensa_EXCSAVE2, 210, Xtensa_EXCSAVE3, 211, Xtensa_EXCSAVE4, 212, Xtensa_EXCSAVE5, 213, Xtensa_EXCSAVE6, 214, Xtensa_EXCSAVE7, 215, Xtensa_CPENABLE, 224, Xtensa_INTERRUPT, 226, Xtensa_INTCLEAR, 227, Xtensa_INTENABLE, 228, Xtensa_PS, 230, Xtensa_VECBASE, 231, Xtensa_EXCCAUSE, 232, Xtensa_DEBUGCAUSE, 233, Xtensa_CCOUNT, 234, Xtensa_PRID, 235, Xtensa_ICOUNT, 236, Xtensa_ICOUNTLEVEL, 237, Xtensa_EXCVADDR, 238, Xtensa_CCOMPARE0, 240, Xtensa_CCOMPARE1, 241, Xtensa_CCOMPARE2, 242, Xtensa_MISC0, 244, Xtensa_MISC1, 245, Xtensa_MISC2, 246, Xtensa_MISC3, 247 }; static DecodeStatus DecodeSRRegisterClass(MCInst *Inst, uint64_t RegNo, uint64_t Address, const void *Decoder) { // const llvm_MCSubtargetInfo STI = // ((const MCDisassembler *)Decoder)->getSubtargetInfo(); if (RegNo > 255) return MCDisassembler_Fail; for (unsigned i = 0; i < ARR_SIZE(SRDecoderTable); i += 2) { if (SRDecoderTable[i + 1] == RegNo) { unsigned Reg = SRDecoderTable[i]; if (!CheckRegister(Inst, Reg)) return MCDisassembler_Fail; MCOperand_CreateReg0(Inst, (Reg)); return MCDisassembler_Success; } } return MCDisassembler_Fail; } static const unsigned URDecoderTable[] = { Xtensa_GPIO_OUT, 0, Xtensa_EXPSTATE, 230, Xtensa_THREADPTR, 231, Xtensa_FCR, 232, Xtensa_FSR, 233, Xtensa_F64R_LO, 234, Xtensa_F64R_HI, 235, Xtensa_F64S, 236 }; static DecodeStatus DecodeURRegisterClass(MCInst *Inst, uint64_t RegNo, uint64_t Address, const void *Decoder) { if (RegNo > 255) return MCDisassembler_Fail; for (unsigned i = 0; i < ARR_SIZE(URDecoderTable); i += 2) { if (URDecoderTable[i + 1] == RegNo) { unsigned Reg = URDecoderTable[i]; if (!CheckRegister(Inst, Reg)) return MCDisassembler_Fail; MCOperand_CreateReg0(Inst, (Reg)); return MCDisassembler_Success; } } return MCDisassembler_Fail; } static bool tryAddingSymbolicOperand(int64_t Value, bool isBranch, uint64_t Address, uint64_t Offset, uint64_t InstSize, MCInst *MI, const void *Decoder) { // return Dis->tryAddingSymbolicOperand(MI, Value, Address, isBranch, // Offset, /*OpSize=*/0, InstSize); return false; } static DecodeStatus decodeCallOperand(MCInst *Inst, uint64_t Imm, int64_t Address, const void *Decoder) { CS_ASSERT(isUIntN(18, Imm) && "Invalid immediate"); MCOperand_CreateImm0(Inst, (SignExtend64((Imm << 2), 20))); return MCDisassembler_Success; } static DecodeStatus decodeJumpOperand(MCInst *Inst, uint64_t Imm, int64_t Address, const void *Decoder) { CS_ASSERT(isUIntN(18, Imm) && "Invalid immediate"); MCOperand_CreateImm0(Inst, (SignExtend64((Imm), 18))); return MCDisassembler_Success; } static DecodeStatus decodeBranchOperand(MCInst *Inst, uint64_t Imm, int64_t Address, const void *Decoder) { switch (MCInst_getOpcode(Inst)) { case Xtensa_BEQZ: case Xtensa_BGEZ: case Xtensa_BLTZ: case Xtensa_BNEZ: CS_ASSERT(isUIntN(12, Imm) && "Invalid immediate"); if (!tryAddingSymbolicOperand( SignExtend64((Imm), 12) + 4 + Address, true, Address, 0, 3, Inst, Decoder)) MCOperand_CreateImm0(Inst, (SignExtend64((Imm), 12))); break; default: CS_ASSERT(isUIntN(8, Imm) && "Invalid immediate"); if (!tryAddingSymbolicOperand( SignExtend64((Imm), 8) + 4 + Address, true, Address, 0, 3, Inst, Decoder)) MCOperand_CreateImm0(Inst, (SignExtend64((Imm), 8))); } return MCDisassembler_Success; } static DecodeStatus decodeLoopOperand(MCInst *Inst, uint64_t Imm, int64_t Address, const void *Decoder) { CS_ASSERT(isUIntN(8, Imm) && "Invalid immediate"); if (!tryAddingSymbolicOperand(Imm + 4 + Address, true, Address, 0, 3, Inst, Decoder)) MCOperand_CreateImm0(Inst, (Imm)); return MCDisassembler_Success; } static DecodeStatus decodeL32ROperand(MCInst *Inst, uint64_t Imm, int64_t Address, const void *Decoder) { CS_ASSERT(isUIntN(16, Imm) && "Invalid immediate"); MCOperand_CreateImm0(Inst, OneExtend64(Imm << 2, 18)); return MCDisassembler_Success; } static DecodeStatus decodeImm8Operand(MCInst *Inst, uint64_t Imm, int64_t Address, const void *Decoder) { CS_ASSERT(isUIntN(8, Imm) && "Invalid immediate"); MCOperand_CreateImm0(Inst, (SignExtend64((Imm), 8))); return MCDisassembler_Success; } static DecodeStatus decodeImm8_sh8Operand(MCInst *Inst, uint64_t Imm, int64_t Address, const void *Decoder) { CS_ASSERT(isUIntN(16, Imm) && ((Imm & 0xff) == 0) && "Invalid immediate"); MCOperand_CreateImm0(Inst, (SignExtend64((Imm), 16))); return MCDisassembler_Success; } static DecodeStatus decodeImm12Operand(MCInst *Inst, uint64_t Imm, int64_t Address, const void *Decoder) { CS_ASSERT(isUIntN(12, Imm) && "Invalid immediate"); MCOperand_CreateImm0(Inst, (SignExtend64((Imm), 12))); return MCDisassembler_Success; } static DecodeStatus decodeUimm4Operand(MCInst *Inst, uint64_t Imm, int64_t Address, const void *Decoder) { CS_ASSERT(isUIntN(4, Imm) && "Invalid immediate"); MCOperand_CreateImm0(Inst, (Imm)); return MCDisassembler_Success; } static DecodeStatus decodeUimm5Operand(MCInst *Inst, uint64_t Imm, int64_t Address, const void *Decoder) { CS_ASSERT(isUIntN(5, Imm) && "Invalid immediate"); MCOperand_CreateImm0(Inst, (Imm)); return MCDisassembler_Success; } static DecodeStatus decodeImm1_16Operand(MCInst *Inst, uint64_t Imm, int64_t Address, const void *Decoder) { CS_ASSERT(isUIntN(4, Imm) && "Invalid immediate"); MCOperand_CreateImm0(Inst, (Imm + 1)); return MCDisassembler_Success; } static DecodeStatus decodeImm1n_15Operand(MCInst *Inst, uint64_t Imm, int64_t Address, const void *Decoder) { CS_ASSERT(isUIntN(4, Imm) && "Invalid immediate"); if (!Imm) MCOperand_CreateImm0(Inst, (-1)); else MCOperand_CreateImm0(Inst, (Imm)); return MCDisassembler_Success; } static DecodeStatus decodeImm32n_95Operand(MCInst *Inst, uint64_t Imm, int64_t Address, const void *Decoder) { CS_ASSERT(isUIntN(7, Imm) && "Invalid immediate"); if ((Imm & 0x60) == 0x60) MCOperand_CreateImm0(Inst, ((~0x1f) | Imm)); else MCOperand_CreateImm0(Inst, (Imm)); return MCDisassembler_Success; } static DecodeStatus decodeImm8n_7Operand(MCInst *Inst, uint64_t Imm, int64_t Address, const void *Decoder) { CS_ASSERT(isUIntN(4, Imm) && "Invalid immediate"); if (Imm > 7) MCOperand_CreateImm0(Inst, (Imm - 16)); else MCOperand_CreateImm0(Inst, (Imm)); return MCDisassembler_Success; } static DecodeStatus decodeImm64n_4nOperand(MCInst *Inst, uint64_t Imm, int64_t Address, const void *Decoder) { CS_ASSERT(isUIntN(6, Imm) && ((Imm & 0x3) == 0) && "Invalid immediate"); MCOperand_CreateImm0(Inst, ((~0x3f) | (Imm))); return MCDisassembler_Success; } static DecodeStatus decodeOffset8m32Operand(MCInst *Inst, uint64_t Imm, int64_t Address, const void *Decoder) { CS_ASSERT(isUIntN(10, Imm) && ((Imm & 0x3) == 0) && "Invalid immediate"); MCOperand_CreateImm0(Inst, (Imm)); return MCDisassembler_Success; } static DecodeStatus decodeEntry_Imm12OpValue(MCInst *Inst, uint64_t Imm, int64_t Address, const void *Decoder) { CS_ASSERT(isUIntN(15, Imm) && ((Imm & 0x7) == 0) && "Invalid immediate"); MCOperand_CreateImm0(Inst, (Imm)); return MCDisassembler_Success; } static DecodeStatus decodeShimm1_31Operand(MCInst *Inst, uint64_t Imm, int64_t Address, const void *Decoder) { CS_ASSERT(isUIntN(5, Imm) && "Invalid immediate"); MCOperand_CreateImm0(Inst, (32 - Imm)); return MCDisassembler_Success; } //static DecodeStatus decodeShimm0_31Operand(MCInst *Inst, uint64_t Imm, // int64_t Address, const void *Decoder) //{ // CS_ASSERT(isUIntN(5, Imm) && "Invalid immediate"); // MCOperand_CreateImm0(Inst, (32 - Imm)); // return MCDisassembler_Success; //} static DecodeStatus decodeImm7_22Operand(MCInst *Inst, uint64_t Imm, int64_t Address, const void *Decoder) { CS_ASSERT(isUIntN(4, Imm) && "Invalid immediate"); MCOperand_CreateImm0(Inst, (Imm + 7)); return MCDisassembler_Success; } static DecodeStatus decodeSelect_2Operand(MCInst *Inst, uint64_t Imm, int64_t Address, const void *Decoder) { CS_ASSERT(isUIntN(8, Imm) && "Invalid immediate"); MCOperand_CreateImm0(Inst, (Imm)); return MCDisassembler_Success; } static DecodeStatus decodeSelect_4Operand(MCInst *Inst, uint64_t Imm, int64_t Address, const void *Decoder) { CS_ASSERT(isUIntN(8, Imm) && "Invalid immediate"); MCOperand_CreateImm0(Inst, (Imm)); return MCDisassembler_Success; } static DecodeStatus decodeSelect_8Operand(MCInst *Inst, uint64_t Imm, int64_t Address, const void *Decoder) { CS_ASSERT(isUIntN(8, Imm) && "Invalid immediate"); MCOperand_CreateImm0(Inst, (Imm)); return MCDisassembler_Success; } static DecodeStatus decodeSelect_16Operand(MCInst *Inst, uint64_t Imm, int64_t Address, const void *Decoder) { CS_ASSERT(isUIntN(8, Imm) && "Invalid immediate"); MCOperand_CreateImm0(Inst, (Imm)); return MCDisassembler_Success; } static DecodeStatus decodeSelect_256Operand(MCInst *Inst, uint64_t Imm, int64_t Address, const void *Decoder) { CS_ASSERT(isUIntN(8, Imm) && "Invalid immediate"); MCOperand_CreateImm0(Inst, (Imm)); return MCDisassembler_Success; } static DecodeStatus decodeOffset_16_16Operand(MCInst *Inst, uint64_t Imm, int64_t Address, const void *Decoder) { CS_ASSERT(isIntN(Imm, 8) && "Invalid immediate"); if ((Imm & 0xf) != 0) MCOperand_CreateImm0(Inst, (Imm << 4)); else MCOperand_CreateImm0(Inst, (Imm)); return MCDisassembler_Success; } static DecodeStatus decodeOffset_256_8Operand(MCInst *Inst, uint64_t Imm, int64_t Address, const void *Decoder) { CS_ASSERT(isIntN(16, Imm) && "Invalid immediate"); if ((Imm & 0x7) != 0) MCOperand_CreateImm0(Inst, (Imm << 3)); else MCOperand_CreateImm0(Inst, (Imm)); return MCDisassembler_Success; } static DecodeStatus decodeOffset_256_16Operand(MCInst *Inst, uint64_t Imm, int64_t Address, const void *Decoder) { CS_ASSERT(isIntN(16, Imm) && "Invalid immediate"); if ((Imm & 0xf) != 0) MCOperand_CreateImm0(Inst, (Imm << 4)); else MCOperand_CreateImm0(Inst, (Imm)); return MCDisassembler_Success; } static DecodeStatus decodeOffset_256_4Operand(MCInst *Inst, uint64_t Imm, int64_t Address, const void *Decoder) { CS_ASSERT(isIntN(16, Imm) && "Invalid immediate"); if ((Imm & 0x2) != 0) MCOperand_CreateImm0(Inst, (Imm << 2)); else MCOperand_CreateImm0(Inst, (Imm)); return MCDisassembler_Success; } static DecodeStatus decodeOffset_128_2Operand(MCInst *Inst, uint64_t Imm, int64_t Address, const void *Decoder) { CS_ASSERT(isUIntN(8, Imm) && "Invalid immediate"); if ((Imm & 0x1) != 0) MCOperand_CreateImm0(Inst, (Imm << 1)); else MCOperand_CreateImm0(Inst, (Imm)); return MCDisassembler_Success; } static DecodeStatus decodeOffset_128_1Operand(MCInst *Inst, uint64_t Imm, int64_t Address, const void *Decoder) { CS_ASSERT(isUIntN(8, Imm) && "Invalid immediate"); MCOperand_CreateImm0(Inst, (Imm)); return MCDisassembler_Success; } static DecodeStatus decodeOffset_64_16Operand(MCInst *Inst, uint64_t Imm, int64_t Address, const void *Decoder) { CS_ASSERT(isIntN(16, Imm) && "Invalid immediate"); if ((Imm & 0xf) != 0) MCOperand_CreateImm0(Inst, (Imm << 4)); else MCOperand_CreateImm0(Inst, (Imm)); return MCDisassembler_Success; } static int64_t TableB4const[16] = { -1, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 16, 32, 64, 128, 256 }; static DecodeStatus decodeB4constOperand(MCInst *Inst, uint64_t Imm, int64_t Address, const void *Decoder) { CS_ASSERT(isUIntN(4, Imm) && "Invalid immediate"); MCOperand_CreateImm0(Inst, (TableB4const[Imm])); return MCDisassembler_Success; } static int64_t TableB4constu[16] = { 32768, 65536, 2, 3, 4, 5, 6, 7, 8, 10, 12, 16, 32, 64, 128, 256 }; static DecodeStatus decodeB4constuOperand(MCInst *Inst, uint64_t Imm, int64_t Address, const void *Decoder) { CS_ASSERT(isUIntN(4, Imm) && "Invalid immediate"); MCOperand_CreateImm0(Inst, (TableB4constu[Imm])); return MCDisassembler_Success; } static DecodeStatus decodeMem8Operand(MCInst *Inst, uint64_t Imm, int64_t Address, const void *Decoder) { CS_ASSERT(isUIntN(12, Imm) && "Invalid immediate"); DecodeARRegisterClass(Inst, Imm & 0xf, Address, Decoder); MCOperand_CreateImm0(Inst, ((Imm >> 4) & 0xff)); return MCDisassembler_Success; } static DecodeStatus decodeMem16Operand(MCInst *Inst, uint64_t Imm, int64_t Address, const void *Decoder) { CS_ASSERT(isUIntN(12, Imm) && "Invalid immediate"); DecodeARRegisterClass(Inst, Imm & 0xf, Address, Decoder); MCOperand_CreateImm0(Inst, ((Imm >> 3) & 0x1fe)); return MCDisassembler_Success; } static DecodeStatus decodeMem32Operand(MCInst *Inst, uint64_t Imm, int64_t Address, const void *Decoder) { CS_ASSERT(isUIntN(12, Imm) && "Invalid immediate"); DecodeARRegisterClass(Inst, Imm & 0xf, Address, Decoder); MCOperand_CreateImm0(Inst, ((Imm >> 2) & 0x3fc)); return MCDisassembler_Success; } static DecodeStatus decodeMem32nOperand(MCInst *Inst, uint64_t Imm, int64_t Address, const void *Decoder) { CS_ASSERT(isUIntN(8, Imm) && "Invalid immediate"); DecodeARRegisterClass(Inst, Imm & 0xf, Address, Decoder); MCOperand_CreateImm0(Inst, ((Imm >> 2) & 0x3c)); return MCDisassembler_Success; } /// Read two bytes from the ArrayRef and return 16 bit data sorted /// according to the given endianness. static DecodeStatus readInstruction16(MCInst *MI, const uint8_t *Bytes, size_t BytesLen, uint64_t Address, uint64_t *Size, uint64_t *Insn, bool IsLittleEndian) { // We want to read exactly 2 Bytes of data. if (BytesLen < 2) { *Size = 0; return MCDisassembler_Fail; } *Insn = readBytes16(MI, Bytes); *Size = 2; return MCDisassembler_Success; } /// Read three bytes from the ArrayRef and return 24 bit data static DecodeStatus readInstruction24(MCInst *MI, const uint8_t *Bytes, size_t BytesLen, uint64_t Address, uint64_t *Size, uint64_t *Insn, bool IsLittleEndian, bool CheckTIE) { // We want to read exactly 3 Bytes of data. if (BytesLen < 3) { *Size = 0; return MCDisassembler_Fail; } if (CheckTIE && (Bytes[0] & 0x8) != 0) return MCDisassembler_Fail; *Insn = readBytes24(MI, Bytes); *Size = 3; return MCDisassembler_Success; } /// Read three bytes from the ArrayRef and return 32 bit data static DecodeStatus readInstruction32(MCInst *MI, const uint8_t *Bytes, size_t BytesLen, uint64_t Address, uint64_t *Size, uint64_t *Insn, bool IsLittleEndian) { // We want to read exactly 4 Bytes of data. if (BytesLen < 4) { *Size = 0; return MCDisassembler_Fail; } if ((Bytes[0] & 0x8) == 0) return MCDisassembler_Fail; *Insn = readBytes32(MI, Bytes); *Size = 4; return MCDisassembler_Success; } /// Read InstSize bytes from the ArrayRef and return 24 bit data static DecodeStatus readInstructionN(const uint8_t *Bytes, size_t BytesLen, uint64_t Address, unsigned InstSize, uint64_t *Size, uint64_t *Insn, bool IsLittleEndian) { // We want to read exactly 3 Bytes of data. if (BytesLen < InstSize) { *Size = 0; return MCDisassembler_Fail; } *Insn = 0; for (unsigned i = 0; i < InstSize; i++) *Insn |= (uint64_t)(Bytes[i]) << (8 * i); *Size = InstSize; return MCDisassembler_Success; } #include "XtensaGenDisassemblerTables.inc" FieldFromInstruction(fieldFromInstruction_2, uint64_t); DecodeToMCInst(decodeToMCInst_2, fieldFromInstruction_2, uint64_t); DecodeInstruction(decodeInstruction_2, fieldFromInstruction_2, decodeToMCInst_2, uint64_t); FieldFromInstruction(fieldFromInstruction_4, uint64_t); DecodeToMCInst(decodeToMCInst_4, fieldFromInstruction_4, uint64_t); DecodeInstruction(decodeInstruction_4, fieldFromInstruction_4, decodeToMCInst_4, uint64_t); FieldFromInstruction(fieldFromInstruction_6, uint64_t); DecodeToMCInst(decodeToMCInst_6, fieldFromInstruction_6, uint64_t); DecodeInstruction(decodeInstruction_6, fieldFromInstruction_6, decodeToMCInst_6, uint64_t); static bool hasDensity() { return true; } static bool hasESP32S3Ops() { return true; } static bool hasHIFI3() { return true; } static DecodeStatus getInstruction(MCInst *MI, uint64_t *Size, const uint8_t *Bytes, size_t BytesLen, uint64_t Address) { uint64_t Insn; DecodeStatus Result; bool IsLittleEndian = MI->csh->mode & CS_MODE_LITTLE_ENDIAN; // Parse 16-bit instructions if (hasDensity()) { Result = readInstruction16(MI, Bytes, BytesLen, Address, Size, &Insn, IsLittleEndian); if (Result == MCDisassembler_Fail) return MCDisassembler_Fail; Result = decodeInstruction_2(DecoderTable16, MI, Insn, Address, NULL); if (Result != MCDisassembler_Fail) { *Size = 2; return Result; } } // Parse Core 24-bit instructions Result = readInstruction24(MI, Bytes, BytesLen, Address, Size, &Insn, IsLittleEndian, false); if (Result == MCDisassembler_Fail) return MCDisassembler_Fail; Result = decodeInstruction_3(DecoderTable24, MI, Insn, Address, NULL); if (Result != MCDisassembler_Fail) { *Size = 3; return Result; } if (hasESP32S3Ops()) { // Parse ESP32S3 24-bit instructions Result = readInstruction24(MI, Bytes, BytesLen, Address, Size, &Insn, IsLittleEndian, true); if (Result != MCDisassembler_Fail) { Result = decodeInstruction_3(DecoderTableESP32S324, MI, Insn, Address, NULL); if (Result != MCDisassembler_Fail) { *Size = 3; return Result; } } // Parse ESP32S3 32-bit instructions Result = readInstruction32(MI, Bytes, BytesLen, Address, Size, &Insn, IsLittleEndian); if (Result == MCDisassembler_Fail) return MCDisassembler_Fail; Result = decodeInstruction_4(DecoderTableESP32S332, MI, Insn, Address, NULL); if (Result != MCDisassembler_Fail) { *Size = 4; return Result; } } if (hasHIFI3()) { Result = decodeInstruction_3(DecoderTableHIFI324, MI, Insn, Address, NULL); if (Result != MCDisassembler_Fail) return Result; Result = readInstructionN(Bytes, BytesLen, Address, 48, Size, &Insn, IsLittleEndian); if (Result == MCDisassembler_Fail) return MCDisassembler_Fail; Result = decodeInstruction_6(DecoderTableHIFI348, MI, Insn, Address, NULL); if (Result != MCDisassembler_Fail) return Result; } return Result; } DecodeStatus Xtensa_LLVM_getInstruction(MCInst *MI, uint16_t *size16, const uint8_t *Bytes, unsigned BytesSize, uint64_t Address) { uint64_t size64; DecodeStatus status = getInstruction(MI, &size64, Bytes, BytesSize, Address); CS_ASSERT_RET_VAL(size64 < 0xffff, MCDisassembler_Fail); *size16 = size64; return status; }