Skip to content

Commit

Permalink
AArch64 issues (capstone-engine#2473)
Browse files Browse the repository at this point in the history
* Fix Pn was printed as register, not predicate.

* Fix: is_alias must be an int to allow for -1 as false.

* Fix, shift immediate was casted to incorrect width.

* Store theexact float also in fp field for convenience.

* Fix: MRS has no implicit write of NCVZ

* Fix signs of Imm8 shifted operands.

* Fix another MRS test

* Fix: Src operand of CASAL had write flag set.

* Fix sysop access in Python data structures.
  • Loading branch information
Rot127 authored Sep 24, 2024
1 parent 5430745 commit 823bfd5
Show file tree
Hide file tree
Showing 15 changed files with 1,970 additions and 1,730 deletions.
14 changes: 7 additions & 7 deletions arch/AArch64/AArch64GenCSMappingInsn.inc
Original file line number Diff line number Diff line change
Expand Up @@ -13190,47 +13190,47 @@
/* bl $addr */
AArch64_BL /* 1828 */, AARCH64_INS_BL,
#ifndef CAPSTONE_DIET
{ AARCH64_REG_SP, 0 }, { AARCH64_REG_LR, 0 }, { AARCH64_GRP_CALL, AARCH64_GRP_BRANCH_RELATIVE, 0 }, 0, 0, { .aarch64 = { .mem_acc = CS_AC_INVALID }}
{ 0 }, { AARCH64_REG_LR, 0 }, { AARCH64_GRP_CALL, AARCH64_GRP_BRANCH_RELATIVE, 0 }, 0, 0, { .aarch64 = { .mem_acc = CS_AC_INVALID }}

#endif
},
{
/* blr $Rn */
AArch64_BLR /* 1829 */, AARCH64_INS_BLR,
#ifndef CAPSTONE_DIET
{ AARCH64_REG_SP, 0 }, { AARCH64_REG_LR, 0 }, { AARCH64_GRP_CALL, 0 }, 0, 0, { .aarch64 = { .mem_acc = CS_AC_INVALID }}
{ 0 }, { AARCH64_REG_LR, 0 }, { AARCH64_GRP_CALL, 0 }, 0, 0, { .aarch64 = { .mem_acc = CS_AC_INVALID }}

#endif
},
{
/* blraa $Rn, $Rm */
AArch64_BLRAA /* 1830 */, AARCH64_INS_BLRAA,
#ifndef CAPSTONE_DIET
{ AARCH64_REG_SP, 0 }, { AARCH64_REG_LR, 0 }, { AARCH64_GRP_CALL, AARCH64_FEATURE_HASPAUTH, 0 }, 0, 0, { .aarch64 = { .mem_acc = CS_AC_INVALID }}
{ 0 }, { AARCH64_REG_LR, 0 }, { AARCH64_GRP_CALL, AARCH64_FEATURE_HASPAUTH, 0 }, 0, 0, { .aarch64 = { .mem_acc = CS_AC_INVALID }}

#endif
},
{
/* blraaz $Rn */
AArch64_BLRAAZ /* 1831 */, AARCH64_INS_BLRAAZ,
#ifndef CAPSTONE_DIET
{ AARCH64_REG_SP, 0 }, { AARCH64_REG_LR, 0 }, { AARCH64_GRP_CALL, AARCH64_FEATURE_HASPAUTH, 0 }, 0, 0, { .aarch64 = { .mem_acc = CS_AC_INVALID }}
{ 0 }, { AARCH64_REG_LR, 0 }, { AARCH64_GRP_CALL, AARCH64_FEATURE_HASPAUTH, 0 }, 0, 0, { .aarch64 = { .mem_acc = CS_AC_INVALID }}

#endif
},
{
/* blrab $Rn, $Rm */
AArch64_BLRAB /* 1832 */, AARCH64_INS_BLRAB,
#ifndef CAPSTONE_DIET
{ AARCH64_REG_SP, 0 }, { AARCH64_REG_LR, 0 }, { AARCH64_GRP_CALL, AARCH64_FEATURE_HASPAUTH, 0 }, 0, 0, { .aarch64 = { .mem_acc = CS_AC_INVALID }}
{ 0 }, { AARCH64_REG_LR, 0 }, { AARCH64_GRP_CALL, AARCH64_FEATURE_HASPAUTH, 0 }, 0, 0, { .aarch64 = { .mem_acc = CS_AC_INVALID }}

#endif
},
{
/* blrabz $Rn */
AArch64_BLRABZ /* 1833 */, AARCH64_INS_BLRABZ,
#ifndef CAPSTONE_DIET
{ AARCH64_REG_SP, 0 }, { AARCH64_REG_LR, 0 }, { AARCH64_GRP_CALL, AARCH64_FEATURE_HASPAUTH, 0 }, 0, 0, { .aarch64 = { .mem_acc = CS_AC_INVALID }}
{ 0 }, { AARCH64_REG_LR, 0 }, { AARCH64_GRP_CALL, AARCH64_FEATURE_HASPAUTH, 0 }, 0, 0, { .aarch64 = { .mem_acc = CS_AC_INVALID }}

#endif
},
Expand Down Expand Up @@ -37390,7 +37390,7 @@
/* mrs $Rt, $systemreg */
AArch64_MRS /* 4853 */, AARCH64_INS_MRS,
#ifndef CAPSTONE_DIET
{ 0 }, { AARCH64_REG_NZCV, 0 }, { 0 }, 0, 0, { .aarch64 = { .mem_acc = CS_AC_INVALID }}
{ 0 }, { 0 }, { 0 }, 0, 0, { .aarch64 = { .mem_acc = CS_AC_INVALID }}

#endif
},
Expand Down
2,064 changes: 1,038 additions & 1,026 deletions arch/AArch64/AArch64GenDisassemblerTables.inc

Large diffs are not rendered by default.

1,333 changes: 667 additions & 666 deletions arch/AArch64/AArch64GenInstrInfo.inc

Large diffs are not rendered by default.

82 changes: 66 additions & 16 deletions arch/AArch64/AArch64Mapping.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,24 @@
#include "AArch64Linkage.h"
#include "AArch64Mapping.h"

#define CHAR(c) #c[0]

static float aarch64_exact_fp_to_fp(aarch64_exactfpimm exact) {
switch (exact) {
default:
CS_ASSERT(0 && "Not handled.");
return 999.0;
case AARCH64_EXACTFPIMM_HALF:
return 0.5;
case AARCH64_EXACTFPIMM_ONE:
return 1.0;
case AARCH64_EXACTFPIMM_TWO:
return 2.0;
case AARCH64_EXACTFPIMM_ZERO:
return 0.0;
}
}

#ifndef CAPSTONE_DIET
static const aarch64_reg aarch64_flag_regs[] = {
AARCH64_REG_NZCV,
Expand Down Expand Up @@ -1747,28 +1765,53 @@ static void add_cs_detail_template_1(MCInst *MI, aarch64_op_group op_group,
// Shift is handled in printShifter()
break;
}

#define SCALE_SET(T) \
do { \
T Val; \
if (CHAR(T) == 'i') /* Signed */ \
Val = (int8_t)UnscaledVal * \
(1 << AArch64_AM_getShiftValue(Shift)); \
else \
Val = (uint8_t)UnscaledVal * \
(1 << AArch64_AM_getShiftValue(Shift)); \
AArch64_set_detail_op_imm(MI, OpNum, AARCH64_OP_IMM, Val); \
} while (0)

switch (op_group) {
default:
assert(0 &&
"Operand group for Imm8OptLsl not handled.");
case AArch64_OP_GROUP_Imm8OptLsl_int16_t:
case AArch64_OP_GROUP_Imm8OptLsl_int32_t:
case AArch64_OP_GROUP_Imm8OptLsl_int64_t:
case AArch64_OP_GROUP_Imm8OptLsl_int16_t: {
SCALE_SET(int16_t);
break;
}
case AArch64_OP_GROUP_Imm8OptLsl_int32_t: {
SCALE_SET(int32_t);
break;
}
case AArch64_OP_GROUP_Imm8OptLsl_int64_t: {
SCALE_SET(int64_t);
break;
}
case AArch64_OP_GROUP_Imm8OptLsl_int8_t: {
int8_t Val = (int8_t)UnscaledVal *
(1 << AArch64_AM_getShiftValue(Shift));
AArch64_set_detail_op_imm(MI, OpNum, AARCH64_OP_IMM,
Val);
SCALE_SET(int8_t);
break;
}
case AArch64_OP_GROUP_Imm8OptLsl_uint16_t: {
SCALE_SET(uint16_t);
break;
}
case AArch64_OP_GROUP_Imm8OptLsl_uint32_t: {
SCALE_SET(uint32_t);
break;
}
case AArch64_OP_GROUP_Imm8OptLsl_uint64_t: {
SCALE_SET(uint64_t);
break;
}
case AArch64_OP_GROUP_Imm8OptLsl_uint16_t:
case AArch64_OP_GROUP_Imm8OptLsl_uint32_t:
case AArch64_OP_GROUP_Imm8OptLsl_uint64_t:
case AArch64_OP_GROUP_Imm8OptLsl_uint8_t: {
uint8_t Val = (uint8_t)UnscaledVal *
(1 << AArch64_AM_getShiftValue(Shift));
AArch64_set_detail_op_imm(MI, OpNum, AARCH64_OP_IMM,
Val);
SCALE_SET(uint8_t);
break;
}
}
Expand Down Expand Up @@ -1875,7 +1918,7 @@ static void add_cs_detail_template_1(MCInst *MI, aarch64_op_group op_group,
unsigned EltSize = temp_arg_0;
AArch64_get_detail_op(MI, 0)->vas = EltSize;
AArch64_set_detail_op_reg(
MI, OpNum, MCInst_getOpVal(MI, OpNum) - AArch64_PN0);
MI, OpNum, MCInst_getOpVal(MI, OpNum));
break;
}
case AArch64_OP_GROUP_PrefetchOp_0:
Expand Down Expand Up @@ -2483,7 +2526,8 @@ void AArch64_set_detail_op_reg(MCInst *MI, unsigned OpNum, aarch64_reg Reg)
AArch64_set_detail_op_sme(MI, OpNum, AARCH64_SME_MATRIX_TILE,
sme_reg_to_vas(Reg));
return;
} else if ((Reg >= AARCH64_REG_P0) && (Reg <= AARCH64_REG_P15)) {
} else if (((Reg >= AARCH64_REG_P0) && (Reg <= AARCH64_REG_P15)) ||
((Reg >= AARCH64_REG_PN0) && (Reg <= AARCH64_REG_PN15))) {
// SME/SVE predicate register.
AArch64_set_detail_op_pred(MI, OpNum);
return;
Expand Down Expand Up @@ -2695,6 +2739,9 @@ void AArch64_set_detail_op_sys(MCInst *MI, unsigned OpNum, aarch64_sysop sys_op,

AArch64_get_detail_op(MI, 0)->type = type;
AArch64_get_detail_op(MI, 0)->sysop = sys_op;
if (sys_op.sub_type == AARCH64_OP_EXACTFPIMM) {
AArch64_get_detail_op(MI, 0)->fp = aarch64_exact_fp_to_fp(sys_op.imm.exactfpimm);
}
AArch64_inc_op_count(MI);
}

Expand Down Expand Up @@ -2891,6 +2938,9 @@ void AArch64_insert_detail_op_sys(MCInst *MI, unsigned index, aarch64_sysop sys_
AArch64_setup_op(&op);
op.type = type;
op.sysop = sys_op;
if (op.sysop.sub_type == AARCH64_OP_EXACTFPIMM) {
op.fp = aarch64_exact_fp_to_fp(op.sysop.imm.exactfpimm);
}
insert_op(MI, index, op);
}

Expand Down
4 changes: 2 additions & 2 deletions bindings/python/capstone/aarch64.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,6 @@ class AArch64OpValue(ctypes.Union):
('imm_range', AArch64ImmRange),
('fp', ctypes.c_double),
('mem', AArch64OpMem),
('sysop', AArch64SysOp),
('sme', AArch64OpSme),
('pred', AArch64OpPred),
)
Expand All @@ -110,6 +109,7 @@ class AArch64Op(ctypes.Structure):
('type', ctypes.c_uint),
('is_vreg', ctypes.c_bool),
('value', AArch64OpValue),
('sysop', AArch64SysOp),
('access', ctypes.c_uint8),
('is_list_member', ctypes.c_bool),
)
Expand All @@ -136,7 +136,7 @@ def imm_range(self):

@property
def sysop(self):
return self.value.sysop
return self.sysop

@property
def sme(self):
Expand Down
17 changes: 11 additions & 6 deletions bindings/python/cstest_py/src/cstest_py/details.py
Original file line number Diff line number Diff line change
Expand Up @@ -752,29 +752,34 @@ def test_expected_aarch64(actual: CsInsn, expected: dict) -> bool:
return False
elif aop.type == AARCH64_OP_SYSREG:
if not compare_enum(
aop.value.sysop.sub_type, eop.get("sub_type"), "sub_type"
aop.sysop.sub_type, eop.get("sub_type"), "sub_type"
):
return False
if not compare_uint64(
aop.value.sysop.reg.raw_val, eop.get("sys_raw_val"), "sys_raw_val"
aop.sysop.reg.raw_val, eop.get("sys_raw_val"), "sys_raw_val"
):
return False
elif aop.type == AARCH64_OP_SYSIMM:
if not compare_enum(
aop.value.sysop.sub_type, eop.get("sub_type"), "sub_type"
aop.sysop.sub_type, eop.get("sub_type"), "sub_type"
):
return False
if not compare_uint64(
aop.value.sysop.imm.raw_val, eop.get("sys_raw_val"), "sys_raw_val"
aop.sysop.imm.raw_val, eop.get("sys_raw_val"), "sys_raw_val"
):
return False
# EXACTFPIMM operands
if not compare_fp(
aop.fp, eop.get("fp"), "fp"
):
return False
elif aop.type == AARCH64_OP_SYSALIAS:
if not compare_enum(
aop.value.sysop.sub_type, eop.get("sub_type"), "sub_type"
aop.sysop.sub_type, eop.get("sub_type"), "sub_type"
):
return False
if not compare_uint64(
aop.value.sysop.alias.raw_val, eop.get("sys_raw_val"), "sys_raw_val"
aop.sysop.alias.raw_val, eop.get("sys_raw_val"), "sys_raw_val"
):
return False
elif aop.type == AARCH64_OP_PRED:
Expand Down
1 change: 1 addition & 0 deletions cstool/cstool_aarch64.c
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ void print_insn_detail_aarch64(csh handle, cs_insn *ins)
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);
Expand Down
3 changes: 2 additions & 1 deletion docs/cs_v6_release_guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,9 @@ Nonetheless, we hope this additional information is useful to you.
**AArch64**

- Updated to LLVM-18
- Adding new instructions of SME, SVE2 extensions. With it the `sme` and `pred` operands are added.
- Adding new instructions of SME, SVE2 extensions. With it the new `sme` and `pred` operands are added.
- System operands are provided with way more detail in separated operand.
- The `EXACTFPIMM` operand also sets the `fp` field.

**PPC**

Expand Down
2 changes: 1 addition & 1 deletion include/capstone/aarch64.h
Original file line number Diff line number Diff line change
Expand Up @@ -2836,10 +2836,10 @@ typedef struct cs_aarch64_op {
aarch64_imm_range imm_range; ///< An immediate range
double fp; ///< floating point value for FP operand
aarch64_op_mem mem; ///< base/index/scale/disp value for MEM operand
aarch64_sysop sysop; ///< System operand
aarch64_op_sme sme; ///< SME matrix operand
aarch64_op_pred pred; ///< Predicate register
};
aarch64_sysop sysop; ///< System operand

/// How is this operand accessed? (READ, WRITE or READ|WRITE)
/// This field is combined of cs_ac_type.
Expand Down
2 changes: 1 addition & 1 deletion suite/cstest/include/test_case.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ static const cyaml_schema_field_t test_insn_data_mapping_schema[] = {
CYAML_FIELD_STRING_PTR(
"op_str", CYAML_FLAG_POINTER_NULL_STR | CYAML_FLAG_OPTIONAL,
TestInsnData, op_str, 0, CYAML_UNLIMITED),
CYAML_FIELD_UINT("is_alias", CYAML_FLAG_OPTIONAL, TestInsnData,
CYAML_FIELD_INT("is_alias", CYAML_FLAG_OPTIONAL, TestInsnData,
is_alias),
CYAML_FIELD_INT("alias_id",
CYAML_FLAG_SCALAR_PLAIN | CYAML_FLAG_OPTIONAL,
Expand Down
2 changes: 2 additions & 0 deletions suite/cstest/include/test_detail_aarch64.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ typedef struct {
int8_t imm_range_first;
int8_t imm_range_offset;
double fp;
bool fp_set; /// Only relevant for SysOps with EXACTFPIMM
uint64_t sys_raw_val;

TestDetailAArch64SME *sme;
Expand Down Expand Up @@ -103,6 +104,7 @@ static const cyaml_schema_field_t test_detail_aarch64_op_mapping_schema[] = {
CYAML_FIELD_INT("imm_range_offset", CYAML_FLAG_OPTIONAL,
TestDetailAArch64Op, imm_range_offset),
CYAML_FIELD_FLOAT("fp", CYAML_FLAG_OPTIONAL, TestDetailAArch64Op, fp),
CYAML_FIELD_BOOL("fp_set", CYAML_FLAG_OPTIONAL, TestDetailAArch64Op, fp_set),
CYAML_FIELD_UINT("sys_raw_val", CYAML_FLAG_OPTIONAL,
TestDetailAArch64Op, sys_raw_val),
CYAML_FIELD_MAPPING_PTR("sme", CYAML_FLAG_OPTIONAL, TestDetailAArch64Op,
Expand Down
4 changes: 4 additions & 0 deletions suite/cstest/src/test_detail_aarch64.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ TestDetailAArch64Op *test_detail_aarch64_op_clone(TestDetailAArch64Op *op)
clone->imm_range_first = op->imm_range_first;
clone->imm_range_offset = op->imm_range_offset;
clone->fp = op->fp;
clone->fp_set = op->fp_set;
clone->sys_raw_val = op->sys_raw_val;
clone->shift_value = op->shift_value;
clone->is_vreg = op->is_vreg;
Expand Down Expand Up @@ -187,6 +188,9 @@ bool test_expected_aarch64(csh *handle, cs_aarch64 *actual,
false);
compare_uint64_ret(op->sysop.imm.raw_val,
eop->sys_raw_val, false);
if (eop->fp_set) {
compare_fp_ret(op->fp, eop->fp, false);
}
break;
case AARCH64_OP_SYSALIAS:
compare_enum_ret(op->sysop.sub_type, eop->sub_type,
Expand Down
3 changes: 1 addition & 2 deletions tests/details/aarch64.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,7 @@ test_cases:
sub_type: AARCH64_OP_REG_MRS
sys_raw_val: 0xc000
cc: AArch64CC_Invalid
update_flags: 1
regs_write: [ nzcv, x9 ]
regs_write: [ x9 ]

-
asm_text: "msr SPSel, #0"
Expand Down
2 changes: 1 addition & 1 deletion tests/details/cs_common_details.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,7 @@ test_cases:
mnemonic: "mrs"
op_str: "x9, MIDR_EL1"
details:
regs_impl_write: []
regs_impl_write: [ ]
groups: [ privilege ]
-
asm_text: "msr SPSel, #0"
Expand Down
Loading

0 comments on commit 823bfd5

Please sign in to comment.