Files
kaizen/MCInst.c
irisz64 16a2cf3873 Squashed 'external/capstone/' changes from b102f1b8..5af28808
5af28808 Update Auto-Sync to Python 3.13 and tree-sitter-py 24.0 (#2705)
99f018ac Python binding: (#2742)
a07baf83 Auto-Sync update Sparc LLVM-18 (#2704)
81c5c93d Enable to generate legacy MC tests for the fuzzer. (#2733)
a25d4980 Add warning about naive search and replace to patch reg names. (#2728)
7ac87d17 Print immediate only memory operands for AArch64. (#2732)
c34034c8 Add x30 implicit read to the RET alias. (#2739)
95a4ca3e Update source list before installing valgrind. (#2730)
6909724e Make assertion hit warnings optional in release builds. (#2729)
fe6bdc6e Make SStream respect the CS_OPT_UNSIGNED flag. (#2723)
21ce3624 Use cs_ac_type for operand access mode in all arches and use cs_xtensa_op_type for Xtensa operand type (#2721)
df26583f clang-format: change license to BSD-3-Clause (#2724)
280b749e Remove unused files. (#2709)
87908ece Add flag for the SoftFail case of the LLVM disassembler. (#2707)
efc0ba44 Fix missing operand for smstart, due to space replaced by tab (#2720)
2ae64133 Fix missing sp register read in ret instruction (#2719)
8df252a6 Fix arm pop reg access (#2718)
14612272 ARM: fix typo, cspr -> cpsr (#2716)
f2f0a3c3 Fix LoongArch ld/st instructions register info (#2701)
829be2bf LoongArch: Compute absolute address for address operand (#2699)
42fbce6c Add jump group for generic jirl (#2698)
fc525c73 Apple AArch64 proprietary (#2692)
895f2f2e Build PDB for debugging on Windows (#2685)
5c3aef03 Version: Update to v6.0.0-alpha4 (#2682)
106f7d3b Update read/written registers for x87 comparison instructions (#2680)
ebe3ef2a Add workflow for building on Windows (#2675)
72f7d305 Revert "Add a script to compare the inc file content with the latest generate…" (#2678)
5b5c5ed8 Fix nanomips decoding of jalrc (#2672)
ae03cca4 Mips32r6_64r632 is for both mips32r6 and mips64r6 (#2673)
21178aea Add a script to compare the inc file content with the latest generated ones. (#2667)
81a6ba03 MIPS: Fix MIPS16 decoding, wrong flags and ghost registers (#2665)
98a393e3 Stringify BH fields when printing ppc details (#2663)
2607d0f3 Remove undefined constants in riscv_const.py (#2660) (#2661)
5058c634 Decode BH field in print_insn_detail_ppc (#2662)
6461ed08 Add Call group to svc, smc and hvc. (#2651)
e2f1dc8d Tms32c64x Little Endian (#2648)
5464c91d Fix build for compilers requiring explicit static for inline functions.. (#2645)
bb2f6579 Enhance shift value and types of shift instructions. (#2638)
cd282ef5 Update operand type enums of all arch modules to the one in `capstone.h` (#2633)
dc0c0909 cmake: Fix building capstone as sub-project (#2629)
cd8dd20c - Added missing files for sdist archive (#2624)
9affd99b Give the user some guidance where to add missing enumeration values. (#2639)
1bea3fab Add checks for MIPS details on cstest_py (#2640)
ace8056c Add aliases mapping for MIPS & test for id, alias_id (#2635)
1abe1868 Build Tarball before DEB/RPM package. (#2627)
0a012190 Switch to ubuntu-24.04-arm runner image (#2625)
4e0b8c48 Fix wrong version requirement of tricore instructions: (#2620)
8ac2843b chore(version): Update Version to 6.0.0-Alpha3 (#2616)
d7ef910b Rebased #2570 (#2614)
c831cd5e Fix SystemZ macro in Makefile (#2603)
30601176 Apply new EVM opcode updates (#2602)
3c4d7fc8 Add tricore tc1.8 instructions (#2595)
5f290cad Create debian and rpm package on releases (#2590)
0f09210a delete travis (#2600)
5c5f756f Downgrade labeler to v4 due to https://github.com/actions/labeler/issues/710. (#2598)

git-subtree-dir: external/capstone
git-subtree-split: 5af288083e9f03e32723f9708c305692f866b666
2025-06-26 22:15:44 +02:00

332 lines
7.4 KiB
C

/* Capstone Disassembly Engine */
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */
#if defined(CAPSTONE_HAS_OSXKERNEL)
#include <Availability.h>
#include <libkern/libkern.h>
#else
#include <stdio.h>
#include <stdlib.h>
#endif
#include <string.h>
#include <assert.h>
#include "MCInstrDesc.h"
#include "MCInst.h"
#include "utils.h"
#define MCINST_CACHE (ARR_SIZE(mcInst->Operands) - 1)
void MCInst_Init(MCInst *inst, cs_arch arch)
{
memset(inst, 0, sizeof(MCInst));
// unnecessary to initialize in loop . its expensive and inst->size should be honored
inst->Operands[0].Kind = kInvalid;
inst->Operands[0].ImmVal = 0;
inst->Opcode = 0;
inst->OpcodePub = 0;
inst->size = 0;
inst->has_imm = false;
inst->op1_size = 0;
inst->ac_idx = 0;
inst->popcode_adjust = 0;
inst->assembly[0] = '\0';
inst->wasm_data.type = WASM_OP_INVALID;
inst->xAcquireRelease = 0;
for (int i = 0; i < MAX_MC_OPS; ++i)
inst->tied_op_idx[i] = -1;
inst->isAliasInstr = false;
inst->fillDetailOps = false;
memset(&inst->hppa_ext, 0, sizeof(inst->hppa_ext));
// Set default assembly dialect.
switch (arch) {
default:
break;
case CS_ARCH_SYSTEMZ:
inst->MAI.assemblerDialect = SYSTEMZASMDIALECT_AD_HLASM;
break;
}
}
void MCInst_clear(MCInst *inst)
{
inst->size = 0;
}
// does not free @Op
void MCInst_insert0(MCInst *inst, int index, MCOperand *Op)
{
CS_ASSERT_RET(index < MAX_MC_OPS);
int i;
for(i = inst->size; i > index; i--)
//memcpy(&(inst->Operands[i]), &(inst->Operands[i-1]), sizeof(MCOperand));
inst->Operands[i] = inst->Operands[i-1];
inst->Operands[index] = *Op;
inst->size++;
}
void MCInst_setOpcode(MCInst *inst, unsigned Op)
{
inst->Opcode = Op;
}
void MCInst_setOpcodePub(MCInst *inst, unsigned Op)
{
inst->OpcodePub = Op;
}
unsigned MCInst_getOpcode(const MCInst *inst)
{
return inst->Opcode;
}
unsigned MCInst_getOpcodePub(const MCInst *inst)
{
return inst->OpcodePub;
}
MCOperand *MCInst_getOperand(MCInst *inst, unsigned i)
{
assert(i < MAX_MC_OPS);
return &inst->Operands[i];
}
unsigned MCInst_getNumOperands(const MCInst *inst)
{
return inst->size;
}
// This addOperand2 function doesn't free Op
void MCInst_addOperand2(MCInst *inst, MCOperand *Op)
{
CS_ASSERT_RET(inst->size < MAX_MC_OPS);
inst->Operands[inst->size] = *Op;
inst->size++;
}
bool MCOperand_isValid(const MCOperand *op)
{
return op->Kind != kInvalid;
}
bool MCOperand_isReg(const MCOperand *op)
{
return op->Kind == kRegister || op->MachineOperandType == kRegister;
}
bool MCOperand_isImm(const MCOperand *op)
{
return op->Kind == kImmediate || op->MachineOperandType == kImmediate;
}
bool MCOperand_isFPImm(const MCOperand *op)
{
return op->Kind == kFPImmediate;
}
bool MCOperand_isDFPImm(const MCOperand *op)
{
return op->Kind == kDFPImmediate;
}
bool MCOperand_isExpr(const MCOperand *op)
{
return op->Kind == kExpr;
}
bool MCOperand_isInst(const MCOperand *op)
{
return op->Kind == kInst;
}
/// getReg - Returns the register number.
unsigned MCOperand_getReg(const MCOperand *op)
{
return op->RegVal;
}
/// setReg - Set the register number.
void MCOperand_setReg(MCOperand *op, unsigned Reg)
{
op->RegVal = Reg;
}
int64_t MCOperand_getImm(const MCOperand *op)
{
return op->ImmVal;
}
int64_t MCOperand_getExpr(const MCOperand *op)
{
return op->ImmVal;
}
void MCOperand_setImm(MCOperand *op, int64_t Val)
{
op->ImmVal = Val;
}
double MCOperand_getFPImm(const MCOperand *op)
{
return op->FPImmVal;
}
void MCOperand_setFPImm(MCOperand *op, double Val)
{
op->FPImmVal = Val;
}
MCOperand *MCOperand_CreateReg1(MCInst *mcInst, unsigned Reg)
{
MCOperand *op = &(mcInst->Operands[MCINST_CACHE]);
op->MachineOperandType = kRegister;
op->Kind = kRegister;
op->RegVal = Reg;
return op;
}
void MCOperand_CreateReg0(MCInst *mcInst, unsigned Reg)
{
MCOperand *op = &(mcInst->Operands[mcInst->size]);
mcInst->size++;
op->MachineOperandType = kRegister;
op->Kind = kRegister;
op->RegVal = Reg;
}
MCOperand *MCOperand_CreateImm1(MCInst *mcInst, int64_t Val)
{
MCOperand *op = &(mcInst->Operands[MCINST_CACHE]);
op->MachineOperandType = kImmediate;
op->Kind = kImmediate;
op->ImmVal = Val;
return op;
}
void MCOperand_CreateImm0(MCInst *mcInst, int64_t Val)
{
assert(mcInst->size < MAX_MC_OPS);
MCOperand *op = &(mcInst->Operands[mcInst->size]);
mcInst->size++;
op->MachineOperandType = kImmediate;
op->Kind = kImmediate;
op->ImmVal = Val;
}
/// Check if any operand of the MCInstrDesc is predicable
bool MCInst_isPredicable(const MCInstrDesc *MIDesc)
{
const MCOperandInfo *OpInfo = MIDesc->OpInfo;
unsigned NumOps = MIDesc->NumOperands;
for (unsigned i = 0; i < NumOps; ++i) {
if (MCOperandInfo_isPredicate(&OpInfo[i])) {
return true;
}
}
return false;
}
/// Checks if tied operands exist in the instruction and sets
/// - The writeback flag in detail
/// - Saves the indices of the tied destination operands.
void MCInst_handleWriteback(MCInst *MI, const MCInstrDesc *InstDescTable, unsigned tbl_size)
{
const MCInstrDesc *InstDesc = NULL;
const MCOperandInfo *OpInfo = NULL;
unsigned short NumOps = 0;
InstDesc = MCInstrDesc_get(MCInst_getOpcode(MI), InstDescTable, tbl_size);
OpInfo = InstDesc->OpInfo;
NumOps = InstDesc->NumOperands;
for (unsigned i = 0; i < NumOps; ++i) {
if (MCOperandInfo_isTiedToOp(&OpInfo[i])) {
int idx = MCOperandInfo_getOperandConstraint(
InstDesc, i,
MCOI_TIED_TO);
if (idx == -1)
continue;
if (i >= MAX_MC_OPS) {
assert(0 &&
"Maximum number of MC operands reached.");
}
MI->tied_op_idx[i] = idx;
if (MI->flat_insn->detail)
MI->flat_insn->detail->writeback = true;
}
}
}
/// Check if operand with OpNum is tied by another operand
/// (operand is tying destination).
bool MCInst_opIsTied(const MCInst *MI, unsigned OpNum)
{
assert(OpNum < MAX_MC_OPS && "Maximum number of MC operands exceeded.");
for (int i = 0; i < MAX_MC_OPS; ++i) {
if (MI->tied_op_idx[i] == OpNum)
return true;
}
return false;
}
/// Check if operand with OpNum is tying another operand
/// (operand is tying src).
bool MCInst_opIsTying(const MCInst *MI, unsigned OpNum)
{
assert(OpNum < MAX_MC_OPS && "Maximum number of MC operands exceeded.");
return MI->tied_op_idx[OpNum] != -1;
}
/// Returns the value of the @MCInst operand at index @OpNum.
uint64_t MCInst_getOpVal(MCInst *MI, unsigned OpNum)
{
assert(OpNum < MAX_MC_OPS);
MCOperand *op = MCInst_getOperand(MI, OpNum);
if (MCOperand_isReg(op))
return MCOperand_getReg(op);
else if (MCOperand_isImm(op))
return MCOperand_getImm(op);
else
assert(0 && "Operand type not handled in this getter.");
return MCOperand_getImm(op);
}
void MCInst_setIsAlias(MCInst *MI, bool Flag) {
assert(MI);
MI->isAliasInstr = Flag;
MI->flat_insn->is_alias = Flag;
}
/// @brief Copies the relevant members of a temporary MCInst to
/// the main MCInst. This is used if TryDecode was run on a temporary MCInst.
/// @param MI The main MCInst
/// @param TmpMI The temporary MCInst.
void MCInst_updateWithTmpMI(MCInst *MI, MCInst *TmpMI) {
MI->size = TmpMI->size;
MI->Opcode = TmpMI->Opcode;
assert(MI->size < MAX_MC_OPS);
memcpy(MI->Operands, TmpMI->Operands, sizeof(MI->Operands[0]) * MI->size);
}
/// @brief Sets the softfail/illegal flag in the cs_insn.
/// Setting it indicates the instruction can be decoded, but is invalid
/// due to not allowed operands or an illegal context.
///
/// @param MI The MCInst holding the cs_insn currently decoded.
void MCInst_setSoftFail(MCInst *MI) {
assert(MI && MI->flat_insn);
MI->flat_insn->illegal = true;
}