b102f1b8 Update Actions (#2593) 86293136 Fix LoongArch aliases and CS_OPT_SYNTAX_NO_DOLLAR support (#2594) 27da950c Clarify between machine used vs. Capstone module affected. (#2586) 186f7aa0 Fix linking issue on Windows. (#2587) e160cbc5 Fix complex atomic instructions handling (#2584) 9907b22d Update v6 to have Debian Packages (#2579) efbbc3bb cstest: use DOWNLOAD_EXTRACT_TIMESTAMP conditionally (#2581) be6be784 x86: update read/write registers for transfer instructions (#2578) 812e654c Update BPF arch (#2568) 2c4b05f6 Clean up the cstest documentation and build instructions. (#2580) 4dc14ba1 Fix 2572 (#2574) b25aa841 PPC regressions (#2575) 0a29bf80 Small arm64 compat header fixes (#2563) b42e0903 Make thumb, v8 and m-class positional cstool arguments. (#2557) 89aee400 Add arm64 and sysz compatibility layer to Python bindings (#2559) a4281337 Python bindings: Enable more archs + bump cibuildwheel action to the v2.22.0 (#2558) ef74d449 Arm regressions (#2556) 93a104c0 PPC LLVM 18 (#2540) e46838ed Merge branch 'v6' into next cf3600e7 Update Changelog Version to 6.0.0-Alpha2 (#2553) b295cf57 Prepare for update (#2552) fc59da4d fix xtensa DecodeMR23RegisterClass and add tests for MAC16 instru… (#2551) 7d01d7e7 Auto-Sync reproducability + ARM update (#2532) 6ad2608d Python package building rework (#2538) e3bc578d Move debian package generation to a dispatch only workflow (#2543) abbf32b4 fix coverity (#2546) 1ecfb5b0 xtensa: update to espressif/llvm-project (#2533) 379e2a41 Rename build arguments: (#2534) d7be5f9f Change CI to create Debian Package to Release (#2521) f6f96796 tricore: fixes #2474 (#2523) 09f35961 This time actually fix big endian issue. (#2530) 306d5716 Fix endianess issue during assignment. (#2528) 2cfca35e Add CC and VAS compatibility macros (#2525) 32519c01 Fix stringop-truncation warning some compilers raise. (#2522) 5026c2c4 Merge pull request #2507 from thestr4ng3r/no-varargs-aarch64 cecb5ede Fix #2509. (#2510) f97e2705 xtensa: Fix Branch Target (#2516) 1d13a12f AArch64: Replace vararg add_cs_detail by multiple concrete functions 8b618528 Update libcyaml dependency in cstest to 1.4.2 (#2508) ea081286 Tricore EA calculation (#2504) 7db9a080 Fix cstest build with Ninja (#2506) 76242699 Only trigger on released action. (#2497) 981d648b Add hard asserts to all SStream functions and memset MCInst. (#2501) d667a627 Update labeler with Xtensa and v6 files. (#2500) 52b54ee3 Fixing UB santizer, `LITBASE` and assert errors. (#2499) 97db712c Remove irrelevant changes. (#2496) 5bd05e34 Remove irrelevant changes. (#2495) 616488c7 Update changelog for V6.0.0-Alpha1 (#2493) (#2494) c5955b92 Update changelog for V6.0.0-Alpha1 (#2493) a424e709 Be ready for V6-Alpha1 (#2492) 235ba8e0 SystemZ fixes (#2488) 5dffa75b Fix LDR not assigning immediate as memory offset. (#2487) 21f7bc85 Xtensa Support (#2380) 29d87734 Several small fixups (#2489) a34901e9 Update sponsors and remove empty file. (#2485) 3120932d Fix Coverity CID 509730: overflow before widen (#2486) 1014864d Rename CS_OPT_NO_BRANCH_OFFSET and corresponding flag to better name. (#2482) 0c90fe13 Replace `assert` with `CS_ASSERT` in modules (#2478) 823bfd53 AArch64 issues (#2473) git-subtree-dir: external/capstone git-subtree-split: b102f1b89e0455c072a751d287ab64378c14205f
220 lines
6.3 KiB
C
220 lines
6.3 KiB
C
/* Capstone Disassembly Engine */
|
|
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */
|
|
/* Rot127 <unisono@quyllur.org>, 2022-2023 */
|
|
|
|
#include "ARMDisassemblerExtension.h"
|
|
#include "ARMBaseInfo.h"
|
|
|
|
bool ITBlock_push_back(ARM_ITBlock *it, char v)
|
|
{
|
|
if (it->size >= sizeof(it->ITStates)) {
|
|
// TODO: consider warning user.
|
|
it->size = 0;
|
|
}
|
|
it->ITStates[it->size] = v;
|
|
it->size++;
|
|
|
|
return true;
|
|
}
|
|
|
|
// Returns true if the current instruction is in an IT block
|
|
bool ITBlock_instrInITBlock(ARM_ITBlock *it)
|
|
{
|
|
return (it->size > 0);
|
|
}
|
|
|
|
// Returns true if current instruction is the last instruction in an IT block
|
|
bool ITBlock_instrLastInITBlock(ARM_ITBlock *it)
|
|
{
|
|
return (it->size == 1);
|
|
}
|
|
|
|
// Returns the condition code for instruction in IT block
|
|
unsigned ITBlock_getITCC(ARM_ITBlock *it)
|
|
{
|
|
unsigned CC = ARMCC_AL;
|
|
|
|
if (ITBlock_instrInITBlock(it))
|
|
CC = it->ITStates[it->size - 1];
|
|
|
|
return CC;
|
|
}
|
|
|
|
// Advances the IT block state to the next T or E
|
|
void ITBlock_advanceITState(ARM_ITBlock *it)
|
|
{
|
|
it->size--;
|
|
}
|
|
|
|
// Called when decoding an IT instruction. Sets the IT state for the following
|
|
// instructions that for the IT block. Firstcond and Mask correspond to the
|
|
// fields in the IT instruction encoding.
|
|
void ITBlock_setITState(ARM_ITBlock *it, char Firstcond, char Mask)
|
|
{
|
|
// (3 - the number of trailing zeros) is the number of then / else.
|
|
unsigned NumTZ = CountTrailingZeros_8(Mask);
|
|
unsigned char CCBits = (unsigned char)(Firstcond & 0xf);
|
|
CS_ASSERT_RET(NumTZ <= 3 && "Invalid IT mask!");
|
|
// push condition codes onto the stack the correct order for the pops
|
|
for (unsigned Pos = NumTZ + 1; Pos <= 3; ++Pos) {
|
|
unsigned Else = (Mask >> Pos) & 1;
|
|
ITBlock_push_back(it, CCBits ^ Else);
|
|
}
|
|
ITBlock_push_back(it, CCBits);
|
|
}
|
|
|
|
bool VPTBlock_push_back(ARM_VPTBlock *it, char v)
|
|
{
|
|
if (it->size >= sizeof(it->VPTStates)) {
|
|
// TODO: consider warning user.
|
|
it->size = 0;
|
|
}
|
|
it->VPTStates[it->size] = v;
|
|
it->size++;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool VPTBlock_instrInVPTBlock(ARM_VPTBlock *VPT)
|
|
{
|
|
return VPT->size > 0;
|
|
}
|
|
|
|
unsigned VPTBlock_getVPTPred(ARM_VPTBlock *VPT)
|
|
{
|
|
unsigned Pred = ARMVCC_None;
|
|
if (VPTBlock_instrInVPTBlock(VPT))
|
|
Pred = VPT->VPTStates[VPT->size - 1];
|
|
return Pred;
|
|
}
|
|
|
|
void VPTBlock_advanceVPTState(ARM_VPTBlock *VPT)
|
|
{
|
|
VPT->size--;
|
|
}
|
|
|
|
void VPTBlock_setVPTState(ARM_VPTBlock *VPT, char Mask)
|
|
{
|
|
// (3 - the number of trailing zeros) is the number of then / else.
|
|
unsigned NumTZ = CountTrailingZeros_8(Mask);
|
|
CS_ASSERT_RET(NumTZ <= 3 && "Invalid VPT mask!");
|
|
// push predicates onto the stack the correct order for the pops
|
|
for (unsigned Pos = NumTZ + 1; Pos <= 3; ++Pos) {
|
|
bool T = ((Mask >> Pos) & 1) == 0;
|
|
if (T)
|
|
VPTBlock_push_back(VPT, ARMVCC_Then);
|
|
else
|
|
VPTBlock_push_back(VPT, ARMVCC_Else);
|
|
}
|
|
VPTBlock_push_back(VPT, ARMVCC_Then);
|
|
}
|
|
|
|
// Imported from ARMBaseInstrInfo.h
|
|
//
|
|
/// isValidCoprocessorNumber - decide whether an explicit coprocessor
|
|
/// number is legal in generic instructions like CDP. The answer can
|
|
/// vary with the subtarget.
|
|
bool isValidCoprocessorNumber(MCInst *Inst, unsigned Num)
|
|
{
|
|
// In Armv7 and Armv8-M CP10 and CP11 clash with VFP/NEON, however, the
|
|
// coprocessor is still valid for CDP/MCR/MRC and friends. Allowing it is
|
|
// useful for code which is shared with older architectures which do not
|
|
// know the new VFP/NEON mnemonics.
|
|
|
|
// Armv8-A disallows everything *other* than 111x (CP14 and CP15).
|
|
if (ARM_getFeatureBits(Inst->csh->mode, ARM_HasV8Ops) &&
|
|
(Num & 0xE) != 0xE)
|
|
return false;
|
|
|
|
// Armv8.1-M disallows 100x (CP8,CP9) and 111x (CP14,CP15)
|
|
// which clash with MVE.
|
|
if (ARM_getFeatureBits(Inst->csh->mode, ARM_HasV8_1MMainlineOps) &&
|
|
((Num & 0xE) == 0x8 || (Num & 0xE) == 0xE))
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
// Imported from ARMMCTargetDesc.h
|
|
bool ARM_isVpred(arm_op_type op)
|
|
{
|
|
return op == ARM_OP_VPRED_R || op == ARM_OP_VPRED_N;
|
|
}
|
|
|
|
// Imported from ARMBaseInstrInfo.h
|
|
//
|
|
// This table shows the VPT instruction variants, i.e. the different
|
|
// mask field encodings, see also B5.6. Predication/conditional execution in
|
|
// the ArmARM.
|
|
bool isVPTOpcode(int Opc)
|
|
{
|
|
return Opc == ARM_MVE_VPTv16i8 || Opc == ARM_MVE_VPTv16u8 ||
|
|
Opc == ARM_MVE_VPTv16s8 || Opc == ARM_MVE_VPTv8i16 ||
|
|
Opc == ARM_MVE_VPTv8u16 || Opc == ARM_MVE_VPTv8s16 ||
|
|
Opc == ARM_MVE_VPTv4i32 || Opc == ARM_MVE_VPTv4u32 ||
|
|
Opc == ARM_MVE_VPTv4s32 || Opc == ARM_MVE_VPTv4f32 ||
|
|
Opc == ARM_MVE_VPTv8f16 || Opc == ARM_MVE_VPTv16i8r ||
|
|
Opc == ARM_MVE_VPTv16u8r || Opc == ARM_MVE_VPTv16s8r ||
|
|
Opc == ARM_MVE_VPTv8i16r || Opc == ARM_MVE_VPTv8u16r ||
|
|
Opc == ARM_MVE_VPTv8s16r || Opc == ARM_MVE_VPTv4i32r ||
|
|
Opc == ARM_MVE_VPTv4u32r || Opc == ARM_MVE_VPTv4s32r ||
|
|
Opc == ARM_MVE_VPTv4f32r || Opc == ARM_MVE_VPTv8f16r ||
|
|
Opc == ARM_MVE_VPST;
|
|
}
|
|
|
|
// Imported from ARMMCTargetDesc.cpp
|
|
bool ARM_isCDECoproc(size_t Coproc, const MCInst *MI)
|
|
{
|
|
// Unfortunately we don't have ARMTargetInfo in the disassembler, so we have
|
|
// to rely on feature bits.
|
|
if (Coproc >= 8)
|
|
return false;
|
|
|
|
return ARM_getFeatureBits(MI->csh->mode,
|
|
ARM_FeatureCoprocCDE0 + Coproc);
|
|
}
|
|
|
|
// Hacky: enable all features for disassembler
|
|
bool ARM_getFeatureBits(unsigned int mode, unsigned int feature)
|
|
{
|
|
if (feature == ARM_ModeThumb) {
|
|
if (mode & CS_MODE_THUMB)
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
if (feature == ARM_FeatureDFB)
|
|
return false;
|
|
|
|
if (feature == ARM_FeatureRAS)
|
|
return false;
|
|
|
|
if (feature == ARM_FeatureMClass && (mode & CS_MODE_MCLASS) == 0)
|
|
return false;
|
|
|
|
if ((feature == ARM_HasMVEIntegerOps || feature == ARM_HasMVEFloatOps ||
|
|
feature == ARM_FeatureMVEVectorCostFactor1 ||
|
|
feature == ARM_FeatureMVEVectorCostFactor2 ||
|
|
feature == ARM_FeatureMVEVectorCostFactor4) &&
|
|
(mode & CS_MODE_MCLASS) == 0)
|
|
return false;
|
|
|
|
if ((feature == ARM_HasV8Ops || feature == ARM_HasV8_1MMainlineOps ||
|
|
feature == ARM_HasV8_1aOps || feature == ARM_HasV8_2aOps ||
|
|
feature == ARM_HasV8_3aOps || feature == ARM_HasV8_4aOps ||
|
|
feature == ARM_HasV8_5aOps || feature == ARM_HasV8_6aOps ||
|
|
feature == ARM_HasV8_7aOps || feature == ARM_HasV8_8aOps ||
|
|
feature == ARM_HasV8_9aOps) &&
|
|
(mode & CS_MODE_V8) == 0)
|
|
return false;
|
|
|
|
if (feature >= ARM_FeatureCoprocCDE0 &&
|
|
feature <= ARM_FeatureCoprocCDE7)
|
|
// We currently have no way to detect CDE (Custom-Datapath-Extension)
|
|
// coprocessors.
|
|
return false;
|
|
|
|
// we support everything
|
|
return true;
|
|
}
|