1101 lines
31 KiB
C
1101 lines
31 KiB
C
/* Capstone Disassembly Engine, http://www.capstone-engine.org */
|
|
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2022, */
|
|
/* Rot127 <unisono@quyllur.org> 2022-2023 */
|
|
/* Automatically translated source file from LLVM. */
|
|
|
|
/* LLVM-commit: <commit> */
|
|
/* LLVM-tag: <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 <stdio.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <capstone/platform.h>
|
|
|
|
#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;
|
|
}
|