00cc9309cb
de6e324bdseparate emu thread10d3daf86Roms List improvements95d202f37Let's make the rom list process on a separate thread so the emulator doesnt take ages to load.fc306967fWow the ROM Header was just completely busted. Game list view works nowbad1691eefuck this shit2b59e5f46game list in progressd26417b83remappable inputs in progressac4af8106inpute72abc240update readme430139dc9Qt6 frontend3080d4d45Fix this small bug too08cd13b85Cop0 unused functions do not actually pose a threat (as per manual). They don't do anything, so shall we.61bb4fb44make idle loop detection a little more specific with where the load goesb037de4c3SAZDFsdff12e81e73eneed to figure out why n64-systemtest loops indefinitely at some address that appears to be valid (i think it's me not invalidating the cache properly)204f0e13bidle skipping seems to work!cb8bb634asdkfjlasdf58e5c89c1Fix compilation issue on my machine (no idea)24fb2898eattempting more serious idle skipping214719577Place rsp.Step inside cached interpreter. Gains about 3 more fpsbb97dcc23mmmmm920b77d38wjkhasdfjhkasdf430ccdab4it's a start...4f42a673aCached interpreter plays Mario 64. Start looking into RSP as wellc9a030787idle skipping works!5fbda03cenew idea366637abaIdle skipping... maybe?609fa2fb0Cache instructions implemented but broken lmao. Commented out for nowe140a6d12- Stop using inheritance for CPU, instead use composition. - Introduce KAIZEN_JIT_ENABLED optional define instead of relying on __aarch64__ and the like. - More cache work68e613057prep cache impl811b4d809fix clang formatfda755f7didkd5024ebbfsmall MI refactor in preparation of (eventually) implementing the RDRAM interface properly694b45341Merge commit '206dcdedf195fb320913584180edb12c7731e396' as 'external/SDL'206dcdedfSquashed 'external/SDL/' content from commit 4d17b99d0a4d16e1cb4need to update sdl848b19920Fix compilation errordb61b5299Merge commit 'e94a94559f28e49678fbcf72199a5258137b0fe9' as 'external/imgui'e94a94559Squashed 'external/imgui/' content from commit 02e9b8cac52edb3757need to update imguic1a705e86Emulate weird JALR behaviour4b4c32f4bFix exception for "unusable COP1" in 4 instructions i missed accidentally (again)df5828142Bug putting 0s in the log everywheref8b580048Make isviewer a sink to file8241e9735Fix exception for "unusable COP1" in 4 instructions i missed accidentallyb29715f20small changesd9a620bc1make use of my new small utility library0d1aa938eAdd 'external/ircolib/' from commit 'ce3cd726c8df8388d554abf8bb55d55020eb4450'e64eb40b3Fuck git git-subtree-dir: external/ircolib git-subtree-split:de6e324bde
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;
|
|
}
|