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
247 lines
8.4 KiB
C
247 lines
8.4 KiB
C
/* Capstone Disassembler Engine */
|
|
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013> */
|
|
|
|
#include "capstone/aarch64.h"
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
#include <capstone/capstone.h>
|
|
#include "cstool.h"
|
|
|
|
void print_insn_detail_aarch64(csh handle, cs_insn *ins)
|
|
{
|
|
cs_aarch64 *aarch64;
|
|
int i;
|
|
cs_regs regs_read, regs_write;
|
|
uint8_t regs_read_count, regs_write_count;
|
|
uint8_t access;
|
|
|
|
// detail can be NULL if SKIPDATA option is turned ON
|
|
if (ins->detail == NULL)
|
|
return;
|
|
|
|
aarch64 = &(ins->detail->aarch64);
|
|
if (aarch64->op_count)
|
|
printf("\top_count: %u\n", aarch64->op_count);
|
|
|
|
for (i = 0; i < aarch64->op_count; i++) {
|
|
cs_aarch64_op *op = &(aarch64->operands[i]);
|
|
switch(op->type) {
|
|
default:
|
|
printf("\t\tOperand type %" PRId32 " not handled\n", op->type);
|
|
break;
|
|
case AARCH64_OP_REG:
|
|
printf("\t\toperands[%u].type: REG = %s%s\n", i, cs_reg_name(handle, op->reg), op->is_vreg ? " (vreg)" : "");
|
|
if (op->is_list_member) {
|
|
printf("\t\toperands[%u].is_list_member: true\n", i);
|
|
}
|
|
break;
|
|
case AARCH64_OP_IMM:
|
|
printf("\t\toperands[%u].type: IMM = 0x%" PRIx64 "\n", i, op->imm);
|
|
break;
|
|
case AARCH64_OP_FP:
|
|
#if defined(_KERNEL_MODE)
|
|
// Issue #681: Windows kernel does not support formatting float point
|
|
printf("\t\toperands[%u].type: FP = <float_point_unsupported>\n", i);
|
|
#else
|
|
printf("\t\toperands[%u].type: FP = %f\n", i, op->fp);
|
|
#endif
|
|
break;
|
|
case AARCH64_OP_MEM:
|
|
printf("\t\toperands[%u].type: MEM\n", i);
|
|
if (op->mem.base != AARCH64_REG_INVALID)
|
|
printf("\t\t\toperands[%u].mem.base: REG = %s\n", i, cs_reg_name(handle, op->mem.base));
|
|
if (op->mem.index != AARCH64_REG_INVALID)
|
|
printf("\t\t\toperands[%u].mem.index: REG = %s\n", i, cs_reg_name(handle, op->mem.index));
|
|
if (op->mem.disp != 0)
|
|
printf("\t\t\toperands[%u].mem.disp: 0x%x\n", i, op->mem.disp);
|
|
if (ins->detail->aarch64.post_index)
|
|
printf("\t\t\tpost-indexed: true\n");
|
|
|
|
break;
|
|
case AARCH64_OP_SME:
|
|
printf("\t\toperands[%u].type: SME_MATRIX\n", i);
|
|
printf("\t\toperands[%u].sme.type: %d\n", i, op->sme.type);
|
|
|
|
if (op->sme.tile != AARCH64_REG_INVALID)
|
|
printf("\t\toperands[%u].sme.tile: %s\n", i, cs_reg_name(handle, op->sme.tile));
|
|
if (op->sme.slice_reg != AARCH64_REG_INVALID)
|
|
printf("\t\toperands[%u].sme.slice_reg: %s\n", i, cs_reg_name(handle, op->sme.slice_reg));
|
|
if (op->sme.slice_offset.imm != AARCH64_SLICE_IMM_INVALID || op->sme.slice_offset.imm_range.first != AARCH64_SLICE_IMM_RANGE_INVALID) {
|
|
printf("\t\toperands[%u].sme.slice_offset: ", i);
|
|
if (op->sme.has_range_offset)
|
|
printf("%hhd:%hhd\n", op->sme.slice_offset.imm_range.first, op->sme.slice_offset.imm_range.offset);
|
|
else
|
|
printf("%d\n", op->sme.slice_offset.imm);
|
|
}
|
|
if (op->sme.slice_reg != AARCH64_REG_INVALID || op->sme.slice_offset.imm != AARCH64_SLICE_IMM_INVALID)
|
|
printf("\t\toperands[%u].sme.is_vertical: %s\n", i, (op->sme.is_vertical ? "true" : "false"));
|
|
break;
|
|
case AARCH64_OP_PRED:
|
|
printf("\t\toperands[%u].type: PREDICATE\n", i);
|
|
if (op->pred.reg != AARCH64_REG_INVALID)
|
|
printf("\t\toperands[%u].pred.reg: %s\n", i, cs_reg_name(handle, op->pred.reg));
|
|
if (op->pred.vec_select != AARCH64_REG_INVALID)
|
|
printf("\t\toperands[%u].pred.vec_select: %s\n", i, cs_reg_name(handle, op->pred.vec_select));
|
|
if (op->pred.imm_index != -1)
|
|
printf("\t\toperands[%u].pred.imm_index: %d\n", i, op->pred.imm_index);
|
|
break;
|
|
case AARCH64_OP_CIMM:
|
|
printf("\t\toperands[%u].type: C-IMM = %u\n", i, (int)op->imm);
|
|
break;
|
|
case AARCH64_OP_SYSREG:
|
|
printf("\t\toperands[%u].type: SYS REG:\n", i);
|
|
switch (op->sysop.sub_type) {
|
|
default:
|
|
printf("Sub type %d not handled.\n", op->sysop.sub_type);
|
|
break;
|
|
case AARCH64_OP_REG_MRS:
|
|
printf("\t\toperands[%u].subtype: REG_MRS = 0x%x\n", i, op->sysop.reg.sysreg);
|
|
break;
|
|
case AARCH64_OP_REG_MSR:
|
|
printf("\t\toperands[%u].subtype: REG_MSR = 0x%x\n", i, op->sysop.reg.sysreg);
|
|
break;
|
|
case AARCH64_OP_TLBI:
|
|
printf("\t\toperands[%u].subtype TLBI = 0x%x\n", i, op->sysop.reg.tlbi);
|
|
break;
|
|
case AARCH64_OP_IC:
|
|
printf("\t\toperands[%u].subtype IC = 0x%x\n", i, op->sysop.reg.ic);
|
|
break;
|
|
}
|
|
break;
|
|
case AARCH64_OP_SYSALIAS:
|
|
printf("\t\toperands[%u].type: SYS ALIAS:\n", i);
|
|
switch (op->sysop.sub_type) {
|
|
default:
|
|
printf("Sub type %d not handled.\n", op->sysop.sub_type);
|
|
break;
|
|
case AARCH64_OP_SVCR:
|
|
if(op->sysop.alias.svcr == AARCH64_SVCR_SVCRSM)
|
|
printf("\t\t\toperands[%u].svcr: BIT = SM\n", i);
|
|
else if(op->sysop.alias.svcr == AARCH64_SVCR_SVCRZA)
|
|
printf("\t\t\toperands[%u].svcr: BIT = ZA\n", i);
|
|
else if(op->sysop.alias.svcr == AARCH64_SVCR_SVCRSMZA)
|
|
printf("\t\t\toperands[%u].svcr: BIT = SM & ZA\n", i);
|
|
break;
|
|
case AARCH64_OP_AT:
|
|
printf("\t\toperands[%u].subtype AT = 0x%x\n", i, op->sysop.alias.at);
|
|
break;
|
|
case AARCH64_OP_DB:
|
|
printf("\t\toperands[%u].subtype DB = 0x%x\n", i, op->sysop.alias.db);
|
|
break;
|
|
case AARCH64_OP_DC:
|
|
printf("\t\toperands[%u].subtype DC = 0x%x\n", i, op->sysop.alias.dc);
|
|
break;
|
|
case AARCH64_OP_ISB:
|
|
printf("\t\toperands[%u].subtype ISB = 0x%x\n", i, op->sysop.alias.isb);
|
|
break;
|
|
case AARCH64_OP_TSB:
|
|
printf("\t\toperands[%u].subtype TSB = 0x%x\n", i, op->sysop.alias.tsb);
|
|
break;
|
|
case AARCH64_OP_PRFM:
|
|
printf("\t\toperands[%u].subtype PRFM = 0x%x\n", i, op->sysop.alias.prfm);
|
|
break;
|
|
case AARCH64_OP_SVEPRFM:
|
|
printf("\t\toperands[%u].subtype SVEPRFM = 0x%x\n", i, op->sysop.alias.sveprfm);
|
|
break;
|
|
case AARCH64_OP_RPRFM:
|
|
printf("\t\toperands[%u].subtype RPRFM = 0x%x\n", i, op->sysop.alias.rprfm);
|
|
break;
|
|
case AARCH64_OP_PSTATEIMM0_15:
|
|
printf("\t\toperands[%u].subtype PSTATEIMM0_15 = 0x%x\n", i, op->sysop.alias.pstateimm0_15);
|
|
break;
|
|
case AARCH64_OP_PSTATEIMM0_1:
|
|
printf("\t\toperands[%u].subtype PSTATEIMM0_1 = 0x%x\n", i, op->sysop.alias.pstateimm0_1);
|
|
break;
|
|
case AARCH64_OP_PSB:
|
|
printf("\t\toperands[%u].subtype PSB = 0x%x\n", i, op->sysop.alias.psb);
|
|
break;
|
|
case AARCH64_OP_BTI:
|
|
printf("\t\toperands[%u].subtype BTI = 0x%x\n", i, op->sysop.alias.bti);
|
|
break;
|
|
case AARCH64_OP_SVEPREDPAT:
|
|
printf("\t\toperands[%u].subtype SVEPREDPAT = 0x%x\n", i, op->sysop.alias.svepredpat);
|
|
break;
|
|
case AARCH64_OP_SVEVECLENSPECIFIER:
|
|
printf("\t\toperands[%u].subtype SVEVECLENSPECIFIER = 0x%x\n", i, op->sysop.alias.sveveclenspecifier);
|
|
break;
|
|
}
|
|
break;
|
|
case AARCH64_OP_SYSIMM:
|
|
printf("\t\toperands[%u].type: SYS IMM:\n", i);
|
|
switch(op->sysop.sub_type) {
|
|
default:
|
|
printf("Sub type %d not handled.\n", op->sysop.sub_type);
|
|
break;
|
|
case AARCH64_OP_EXACTFPIMM:
|
|
printf("\t\toperands[%u].subtype EXACTFPIMM = %d\n", i, op->sysop.imm.exactfpimm);
|
|
printf("\t\toperands[%u].fp = %.1f\n", i, op->fp);
|
|
break;
|
|
case AARCH64_OP_DBNXS:
|
|
printf("\t\toperands[%u].subtype DBNXS = %d\n", i, op->sysop.imm.dbnxs);
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
|
|
access = op->access;
|
|
switch(access) {
|
|
default:
|
|
break;
|
|
case CS_AC_READ:
|
|
printf("\t\toperands[%u].access: READ\n", i);
|
|
break;
|
|
case CS_AC_WRITE:
|
|
printf("\t\toperands[%u].access: WRITE\n", i);
|
|
break;
|
|
case CS_AC_READ | CS_AC_WRITE:
|
|
printf("\t\toperands[%u].access: READ | WRITE\n", i);
|
|
break;
|
|
}
|
|
|
|
if (op->shift.type != AARCH64_SFT_INVALID &&
|
|
op->shift.value)
|
|
printf("\t\t\tShift: type = %u, value = %u\n",
|
|
op->shift.type, op->shift.value);
|
|
|
|
if (op->ext != AARCH64_EXT_INVALID)
|
|
printf("\t\t\tExt: %u\n", op->ext);
|
|
|
|
if (op->vas != AARCH64LAYOUT_INVALID)
|
|
printf("\t\t\tVector Arrangement Specifier: 0x%x\n", op->vas);
|
|
|
|
if (op->vector_index != -1)
|
|
printf("\t\t\tVector Index: %u\n", op->vector_index);
|
|
}
|
|
|
|
if (aarch64->update_flags)
|
|
printf("\tUpdate-flags: True\n");
|
|
|
|
if (ins->detail->writeback)
|
|
printf("\tWrite-back: True\n");
|
|
|
|
if (aarch64->cc != AArch64CC_Invalid)
|
|
printf("\tCode-condition: %u\n", aarch64->cc);
|
|
|
|
// Print out all registers accessed by this instruction (either implicit or explicit)
|
|
if (!cs_regs_access(handle, ins,
|
|
regs_read, ®s_read_count,
|
|
regs_write, ®s_write_count)) {
|
|
if (regs_read_count) {
|
|
printf("\tRegisters read:");
|
|
for(i = 0; i < regs_read_count; i++) {
|
|
printf(" %s", cs_reg_name(handle, regs_read[i]));
|
|
}
|
|
printf("\n");
|
|
}
|
|
|
|
if (regs_write_count) {
|
|
printf("\tRegisters modified:");
|
|
for(i = 0; i < regs_write_count; i++) {
|
|
printf(" %s", cs_reg_name(handle, regs_write[i]));
|
|
}
|
|
printf("\n");
|
|
}
|
|
}
|
|
}
|