* Fix #2381

* Fix #2382

* Fix post-index correction only for pop with single register

* Fix missing memory index register scale

* Remove faulty and duplicated lshift field.

* Add shift information to shift alias instructions and add several tests.

* Fix scale tests

---------

Co-authored-by: Wu ChenXu <kabeor00@gmail.com>
This commit is contained in:
Rot127 2024-09-23 03:30:33 +00:00 committed by GitHub
parent 40dffb2668
commit 5430745e96
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 722 additions and 98 deletions

View File

@ -377,8 +377,13 @@ void map_set_is_alias_insn(MCInst *MI, bool Val, uint64_t Alias) {
MI->flat_insn->alias_id = Alias;
}
static inline bool char_ends_mnem(const char c) {
return (!c || c == ' ' || c == '\t');
static inline bool char_ends_mnem(const char c, cs_arch arch) {
switch (arch) {
default:
return (!c || c == ' ' || c == '\t' || c == '.');
case CS_ARCH_PPC:
return (!c || c == ' ' || c == '\t');
}
}
/// Sets an alternative id for some instruction.
@ -400,7 +405,7 @@ void map_set_alias_id(MCInst *MI, const SStream *O, const name_map *alias_mnem_i
++i;
}
for (; j < sizeof(alias_mnem) - 1; ++j, ++i) {
if (char_ends_mnem(asm_str_buf[i]))
if (char_ends_mnem(asm_str_buf[i], MI->csh->arch))
break;
alias_mnem[j] = asm_str_buf[i];
}

View File

@ -171,6 +171,7 @@ static void check_pop_return(MCInst *MI) {
cs_arm_op *op = &ARM_get_detail(MI)->operands[i];
if (op->type == ARM_OP_REG && op->reg == ARM_REG_PC) {
add_group(MI, ARM_GRP_RET);
return;
}
}
}
@ -225,7 +226,12 @@ static void add_alias_details(MCInst *MI) {
return;
case ARM_INS_ALIAS_POP:
// Doesn't get set because memop is not printed.
ARM_get_detail(MI)->post_index = true;
if (ARM_get_detail(MI)->op_count == 1) {
CS_ASSERT(MI->flat_insn->usesAliasDetails && "Not valid assumption for non alias details.");
// Only single register pop is post-indexed
// Assumes only alias details are passed here.
ARM_get_detail(MI)->post_index = true;
}
// fallthrough
case ARM_INS_ALIAS_PUSH:
case ARM_INS_ALIAS_VPUSH:
@ -246,6 +252,39 @@ static void add_alias_details(MCInst *MI) {
}
break;
}
case ARM_INS_ALIAS_ASR:
case ARM_INS_ALIAS_LSL:
case ARM_INS_ALIAS_LSR:
case ARM_INS_ALIAS_ROR: {
unsigned shift_value = 0;
arm_shifter shift_type = ARM_SFT_INVALID;
switch (MCInst_getOpcode(MI)) {
default:
CS_ASSERT(0 && "ASR, LSL, LSR, ROR alias not handled");
return;
case ARM_MOVsi: {
MCOperand *MO2 = MCInst_getOperand(MI, 2);
shift_type = (arm_shifter) ARM_AM_getSORegShOp(MCOperand_getImm(MO2));
if (ARM_AM_getSORegShOp(MCOperand_getImm(MO2)) == ARM_AM_rrx) {
break;
}
shift_value = translateShiftImm(ARM_AM_getSORegOffset(
MCOperand_getImm(MO2)));
ARM_insert_detail_op_imm_at(MI, -1, shift_value, CS_AC_READ);
break;
}
case ARM_MOVsr: {
MCOperand *MO3 = MCInst_getOperand(MI, (3));
shift_type = ARM_AM_getSORegShOp(MCOperand_getImm(MO3)) + ARM_SFT_REG;
shift_value = MCInst_getOpVal(MI, 2);
break;
}
}
ARM_get_detail_op(MI, -2)->shift.type = shift_type;
ARM_get_detail_op(MI, -2)->shift.value = shift_value;
break;
}
}
}
@ -277,7 +316,7 @@ static void ARM_add_not_defined_ops(MCInst *MI)
case ARM_VCMPEZS:
case ARM_VCMPZH:
case ARM_VCMPZS:
ARM_insert_detail_op_imm_at(MI, 1, 0, CS_AC_READ);
ARM_insert_detail_op_imm_at(MI, -1, 0, CS_AC_READ);
break;
case ARM_MVE_VSHLL_lws16bh:
case ARM_MVE_VSHLL_lws16th:
@ -494,8 +533,7 @@ static void ARM_add_not_defined_ops(MCInst *MI)
// Add shift information
ARM_get_detail(MI)->operands[1].shift.type =
(arm_shifter)ARM_AM_getSORegShOp(
MCInst_getOpVal(MI, 3)) +
ARM_SFT_ASR_REG - 1;
MCInst_getOpVal(MI, 3)) + ARM_SFT_REG;
ARM_get_detail(MI)->operands[1].shift.value =
MCInst_getOpVal(MI, 2);
break;
@ -1013,7 +1051,7 @@ static void add_cs_detail_general(MCInst *MI, arm_op_group op_group,
case ARM_OP_GROUP_Operand:
if (op_type == CS_OP_IMM) {
if (doing_mem(MI)) {
ARM_set_detail_op_mem(MI, OpNum, false, 0, 0,
ARM_set_detail_op_mem(MI, OpNum, false, 0,
MCInst_getOpVal(MI,
OpNum));
} else {
@ -1027,7 +1065,7 @@ static void add_cs_detail_general(MCInst *MI, arm_op_group op_group,
bool is_index_reg = map_get_op_type(MI, OpNum) &
CS_OP_MEM;
ARM_set_detail_op_mem(
MI, OpNum, is_index_reg, 0, 0,
MI, OpNum, is_index_reg, is_index_reg ? 1 : 0,
MCInst_getOpVal(MI, OpNum));
} else {
ARM_set_detail_op_reg(
@ -1047,7 +1085,7 @@ static void add_cs_detail_general(MCInst *MI, arm_op_group op_group,
case ARM_OP_GROUP_AddrMode6Operand:
if (!doing_mem(MI))
ARM_set_mem_access(MI, true);
ARM_set_detail_op_mem(MI, OpNum, false, 0, 0,
ARM_set_detail_op_mem(MI, OpNum, false, 0,
MCInst_getOpVal(MI, OpNum));
ARM_get_detail_op(MI, 0)->mem.align =
MCInst_getOpVal(MI, OpNum + 1) << 3;
@ -1063,7 +1101,7 @@ static void add_cs_detail_general(MCInst *MI, arm_op_group op_group,
case ARM_OP_GROUP_AddrMode7Operand:
if (!doing_mem(MI))
ARM_set_mem_access(MI, true);
ARM_set_detail_op_mem(MI, OpNum, false, 0, 0,
ARM_set_detail_op_mem(MI, OpNum, false, 0,
MCInst_getOpVal(MI, OpNum));
ARM_set_mem_access(MI, false);
break;
@ -1321,7 +1359,7 @@ static void add_cs_detail_general(MCInst *MI, arm_op_group op_group,
int64_t imm =
MCOperand_getImm(MCInst_getOperand(MI, OpNum + 2));
ARM_get_detail_op(MI, 0)->shift.type =
(imm & 7) + ARM_SFT_ASR_REG - 1;
ARM_AM_getSORegShOp(imm) + ARM_SFT_REG;
if (ARM_AM_getSORegShOp(imm) != ARM_AM_rrx)
ARM_get_detail_op(MI, 0)->shift.value =
MCInst_getOpVal(MI, OpNum + 1);
@ -1408,14 +1446,13 @@ static void add_cs_detail_general(MCInst *MI, arm_op_group op_group,
case ARM_OP_GROUP_AddrModeTBB:
case ARM_OP_GROUP_AddrModeTBH:
ARM_set_mem_access(MI, true);
ARM_set_detail_op_mem(MI, OpNum, false, 0, 0,
ARM_set_detail_op_mem(MI, OpNum, false, 0,
MCInst_getOpVal(MI, OpNum));
ARM_set_detail_op_mem(MI, OpNum + 1, true, 0, 0,
ARM_set_detail_op_mem(MI, OpNum + 1, true, 1,
MCInst_getOpVal(MI, OpNum + 1));
if (op_group == ARM_OP_GROUP_AddrModeTBH) {
ARM_get_detail_op(MI, 0)->shift.type = ARM_SFT_LSL;
ARM_get_detail_op(MI, 0)->shift.value = 1;
ARM_get_detail_op(MI, 0)->mem.lshift = 1;
}
ARM_set_mem_access(MI, false);
break;
@ -1426,23 +1463,20 @@ static void add_cs_detail_general(MCInst *MI, arm_op_group op_group,
break;
ARM_set_mem_access(MI, true);
ARM_set_detail_op_mem(MI, OpNum, false, 0, 0,
ARM_set_detail_op_mem(MI, OpNum, false, 0,
MCInst_getOpVal(MI, OpNum));
unsigned int imm3 = MCInst_getOpVal(MI, OpNum + 2);
unsigned ShOff = ARM_AM_getAM2Offset(imm3);
ARM_AM_AddrOpc subtracted = ARM_AM_getAM2Op(imm3);
if (!MCOperand_getReg(MCInst_getOperand(MI, OpNum + 1)) &&
ShOff) {
ARM_get_detail_op(MI, 0)->shift.type =
(arm_shifter)subtracted;
ARM_get_detail_op(MI, 0)->shift.value = ShOff;
ARM_get_detail_op(MI, 0)->subtracted = subtracted ==
ARM_AM_sub;
ARM_set_mem_access(MI, false);
break;
}
ARM_get_detail_op(MI, 0)->shift.type = subtracted == ARM_AM_sub;
ARM_set_detail_op_mem(MI, OpNum + 1, true, 0, 0,
ARM_set_detail_op_mem(MI, OpNum + 1, true, subtracted == ARM_AM_sub ? -1 : 1,
MCInst_getOpVal(MI, OpNum + 1));
add_cs_detail_RegImmShift(MI, ARM_AM_getAM2ShiftOpc(imm3),
ARM_AM_getAM2Offset(imm3));
@ -1496,7 +1530,7 @@ static void add_cs_detail_general(MCInst *MI, arm_op_group op_group,
break;
ARM_set_mem_access(MI, true);
ARM_set_detail_op_mem(MI, OpNum, false, 0, 0,
ARM_set_detail_op_mem(MI, OpNum, false, 0,
MCInst_getOpVal(MI, OpNum));
unsigned ImmOffs = MCInst_getOpVal(MI, OpNum + 1);
if (ImmOffs) {
@ -1516,7 +1550,7 @@ static void add_cs_detail_general(MCInst *MI, arm_op_group op_group,
Scale = 4;
break;
}
ARM_set_detail_op_mem(MI, OpNum + 1, false, 0, 0,
ARM_set_detail_op_mem(MI, OpNum + 1, false, 0,
ImmOffs * Scale);
}
ARM_set_mem_access(MI, false);
@ -1529,11 +1563,11 @@ static void add_cs_detail_general(MCInst *MI, arm_op_group op_group,
break;
ARM_set_mem_access(MI, true);
ARM_set_detail_op_mem(MI, OpNum, false, 0, 0,
ARM_set_detail_op_mem(MI, OpNum, false, 0,
MCInst_getOpVal(MI, OpNum));
arm_reg RegNum = MCInst_getOpVal(MI, OpNum + 1);
if (RegNum)
ARM_set_detail_op_mem(MI, OpNum + 1, true, 0, 0,
ARM_set_detail_op_mem(MI, OpNum + 1, true, 1,
RegNum);
ARM_set_mem_access(MI, false);
break;
@ -1555,9 +1589,9 @@ static void add_cs_detail_general(MCInst *MI, arm_op_group op_group,
if (!doing_mem(MI))
ARM_set_mem_access(MI, true);
ARM_set_detail_op_mem(MI, OpNum, false, 0, 0,
ARM_set_detail_op_mem(MI, OpNum, false, 0,
MCInst_getOpVal(MI, OpNum));
ARM_set_detail_op_mem(MI, OpNum + 1, true, 0, 0,
ARM_set_detail_op_mem(MI, OpNum + 1, true, 1,
MCInst_getOpVal(MI, OpNum + 1));
unsigned ShAmt = MCInst_getOpVal(MI, OpNum + 2);
if (ShAmt) {
@ -1569,11 +1603,11 @@ static void add_cs_detail_general(MCInst *MI, arm_op_group op_group,
}
case ARM_OP_GROUP_T2AddrModeImm0_1020s4Operand:
ARM_set_mem_access(MI, true);
ARM_set_detail_op_mem(MI, OpNum, false, 0, 0,
ARM_set_detail_op_mem(MI, OpNum, false, 0,
MCInst_getOpVal(MI, OpNum));
int64_t Imm0_1024s4 = MCInst_getOpVal(MI, OpNum + 1);
if (Imm0_1024s4)
ARM_set_detail_op_mem(MI, OpNum + 1, false, 0, 0,
ARM_set_detail_op_mem(MI, OpNum + 1, false, 0,
Imm0_1024s4 * 4);
ARM_set_mem_access(MI, false);
break;
@ -1732,12 +1766,12 @@ static void add_cs_detail_template_1(MCInst *MI, arm_op_group op_group,
case ARM_OP_GROUP_T2AddrModeImm8Operand_1: {
bool AlwaysPrintImm0 = temp_arg_0;
ARM_set_mem_access(MI, true);
ARM_set_detail_op_mem(MI, OpNum, false, 0, 0,
ARM_set_detail_op_mem(MI, OpNum, false, 0,
MCInst_getOpVal(MI, OpNum));
int32_t Imm8 = MCInst_getOpVal(MI, OpNum + 1);
if (Imm8 == INT32_MIN)
Imm8 = 0;
ARM_set_detail_op_mem(MI, OpNum + 1, false, 0, 0, Imm8);
ARM_set_detail_op_mem(MI, OpNum + 1, false, 0, Imm8);
if (AlwaysPrintImm0)
map_add_implicit_write(MI, MCInst_getOpVal(MI, OpNum));
@ -1762,7 +1796,7 @@ static void add_cs_detail_template_1(MCInst *MI, arm_op_group op_group,
break;
ARM_set_mem_access(MI, true);
ARM_set_detail_op_mem(MI, OpNum, false, 0, 0,
ARM_set_detail_op_mem(MI, OpNum, false, 0,
MCInst_getOpVal(MI, OpNum));
MCOperand *MO2 = MCInst_getOperand(MI, OpNum + 1);
@ -1770,7 +1804,7 @@ static void add_cs_detail_template_1(MCInst *MI, arm_op_group op_group,
ARM_AM_getAM3Op(MCInst_getOpVal(MI, OpNum + 2));
if (MCOperand_getReg(MO2)) {
ARM_set_detail_op_mem(MI, OpNum + 1, true, 0, 0,
ARM_set_detail_op_mem(MI, OpNum + 1, true, Sign == ARM_AM_sub ? -1 : 1,
MCInst_getOpVal(MI, OpNum + 1));
ARM_get_detail_op(MI, 0)->subtracted = Sign ==
ARM_AM_sub;
@ -1781,7 +1815,7 @@ static void add_cs_detail_template_1(MCInst *MI, arm_op_group op_group,
ARM_AM_getAM3Offset(MCInst_getOpVal(MI, OpNum + 2));
if (AlwaysPrintImm0 || ImmOffs || Sign == ARM_AM_sub) {
ARM_set_detail_op_mem(MI, OpNum + 2, false, 0, 0,
ARM_set_detail_op_mem(MI, OpNum + 2, false, 0,
ImmOffs);
ARM_get_detail_op(MI, 0)->subtracted = Sign ==
ARM_AM_sub;
@ -1828,9 +1862,9 @@ static void add_cs_detail_template_1(MCInst *MI, arm_op_group op_group,
case ARM_OP_GROUP_MveAddrModeRQOperand_3: {
unsigned Shift = temp_arg_0;
ARM_set_mem_access(MI, true);
ARM_set_detail_op_mem(MI, OpNum, false, 0, 0,
ARM_set_detail_op_mem(MI, OpNum, false, 0,
MCInst_getOpVal(MI, OpNum));
ARM_set_detail_op_mem(MI, OpNum + 1, true, 0, 0,
ARM_set_detail_op_mem(MI, OpNum + 1, true, 1,
MCInst_getOpVal(MI, OpNum + 1));
if (Shift > 0) {
add_cs_detail_RegImmShift(MI, ARM_AM_uxtw, Shift);
@ -1929,24 +1963,20 @@ void ARM_add_cs_detail(MCInst *MI, int /* arm_op_group */ op_group,
add_cs_detail_general(MI, op_group, op_num);
}
/// Inserts a register to the detail operands at @index.
/// Already present operands are moved.
void ARM_insert_detail_op_reg_at(MCInst *MI, unsigned index, arm_reg Reg,
cs_ac_type access)
static void insert_op(MCInst *MI, unsigned index, cs_arm_op op)
{
if (!detail_is_set(MI))
if (!detail_is_set(MI)) {
return;
}
ARM_check_safe_inc();
cs_arm_op op;
ARM_setup_op(&op);
op.type = ARM_OP_REG;
op.reg = Reg;
op.access = access;
cs_arm_op *ops = ARM_get_detail(MI)->operands;
int i = ARM_get_detail(MI)->op_count;
if (index == -1) {
ops[i] = op;
ARM_inc_op_count(MI);
return;
}
for (; i > 0 && i > index; --i) {
ops[i] = ops[i - 1];
}
@ -1954,8 +1984,26 @@ void ARM_insert_detail_op_reg_at(MCInst *MI, unsigned index, arm_reg Reg,
ARM_inc_op_count(MI);
}
/// Inserts a register to the detail operands at @index.
/// Already present operands are moved.
/// If @index is -1 the operand is appended.
void ARM_insert_detail_op_reg_at(MCInst *MI, unsigned index, arm_reg Reg,
cs_ac_type access)
{
if (!detail_is_set(MI))
return;
cs_arm_op op;
ARM_setup_op(&op);
op.type = ARM_OP_REG;
op.reg = Reg;
op.access = access;
insert_op(MI, index, op);
}
/// Inserts a immediate to the detail operands at @index.
/// Already present operands are moved.
/// If @index is -1 the operand is appended.
void ARM_insert_detail_op_imm_at(MCInst *MI, unsigned index, int64_t Val,
cs_ac_type access)
{
@ -1969,13 +2017,7 @@ void ARM_insert_detail_op_imm_at(MCInst *MI, unsigned index, int64_t Val,
op.imm = Val;
op.access = access;
cs_arm_op *ops = ARM_get_detail(MI)->operands;
int i = ARM_get_detail(MI)->op_count;
for (; i > 0 && i > index; --i) {
ops[i] = ops[i - 1];
}
ops[index] = op;
ARM_inc_op_count(MI);
insert_op(MI, index, op);
}
/// Adds a register ARM operand at position OpNum and increases the op_count by
@ -2026,9 +2068,9 @@ void ARM_set_detail_op_mem_offset(MCInst *MI, unsigned OpNum, uint64_t Val,
}
if ((map_get_op_type(MI, OpNum) & ~CS_OP_MEM) == CS_OP_IMM)
ARM_set_detail_op_mem(MI, OpNum, false, 0, 0, Val);
ARM_set_detail_op_mem(MI, OpNum, false, 0, Val);
else if ((map_get_op_type(MI, OpNum) & ~CS_OP_MEM) == CS_OP_REG)
ARM_set_detail_op_mem(MI, OpNum, true, 0, 0, Val);
ARM_set_detail_op_mem(MI, OpNum, true, subtracted ? -1 : 1, Val);
else
assert(0 && "Memory type incorrect.");
ARM_get_detail_op(MI, 0)->subtracted = subtracted;
@ -2040,7 +2082,7 @@ void ARM_set_detail_op_mem_offset(MCInst *MI, unsigned OpNum, uint64_t Val,
/// Adds a memory ARM operand at position OpNum. op_count is *not* increased by
/// one. This is done by ARM_set_mem_access().
void ARM_set_detail_op_mem(MCInst *MI, unsigned OpNum, bool is_index_reg,
int scale, int lshift, uint64_t Val)
int scale, uint64_t Val)
{
if (!detail_is_set(MI))
return;
@ -2073,7 +2115,6 @@ void ARM_set_detail_op_mem(MCInst *MI, unsigned OpNum, bool is_index_reg,
ARM_get_detail_op(MI, 0)->mem.index = Val;
}
ARM_get_detail_op(MI, 0)->mem.scale = scale;
ARM_get_detail_op(MI, 0)->mem.lshift = lshift;
break;
}

View File

@ -74,7 +74,7 @@ void ARM_set_detail_op_imm(MCInst *MI, unsigned OpNum, arm_op_type ImmType,
int64_t Imm);
void ARM_set_detail_op_float(MCInst *MI, unsigned OpNum, uint64_t Imm);
void ARM_set_detail_op_mem(MCInst *MI, unsigned OpNum, bool is_index_reg,
int scale, int lshift, uint64_t Val);
int scale, uint64_t Val);
void ARM_set_detail_op_mem_offset(MCInst *MI, unsigned OpNum, uint64_t Val,
bool subtracted);
void ARM_set_detail_op_neon_lane(MCInst *MI, unsigned OpNum);

View File

@ -7,11 +7,10 @@ from .arm_const import *
# define the API
class ArmOpMem(ctypes.Structure):
_fields_ = (
('base', ctypes.c_uint),
('index', ctypes.c_uint),
('base', ctypes.c_int),
('index', ctypes.c_int),
('scale', ctypes.c_int),
('disp', ctypes.c_int),
('lshift', ctypes.c_int),
('align', ctypes.c_uint),
)

View File

@ -45,11 +45,12 @@ ARM_SFT_LSL = 2
ARM_SFT_LSR = 3
ARM_SFT_ROR = 4
ARM_SFT_RRX = 5
ARM_SFT_ASR_REG = 6
ARM_SFT_LSL_REG = 7
ARM_SFT_LSR_REG = 8
ARM_SFT_ROR_REG = 9
ARM_SFT_RRX_REG = 10
ARM_SFT_UXTW = 6
ARM_SFT_REG = 7
ARM_SFT_ASR_REG = 8
ARM_SFT_LSL_REG = 9
ARM_SFT_LSR_REG = 10
ARM_SFT_ROR_REG = 11
ARM_MB_RESERVED_0 = 0
ARM_MB_OSHLD = 1

View File

@ -54,14 +54,12 @@ void print_insn_detail_arm(csh handle, cs_insn *ins)
if (op->mem.index != ARM_REG_INVALID)
printf("\t\t\toperands[%u].mem.index: REG = %s\n",
i, cs_reg_name(handle, op->mem.index));
if (op->mem.scale != 1)
if (op->mem.scale != 0)
printf("\t\t\toperands[%u].mem.scale: %d\n", i, op->mem.scale);
if (op->mem.disp != 0)
printf("\t\t\toperands[%u].mem.disp: 0x%x\n", i, op->mem.disp);
if (op->mem.align != 0)
printf("\t\t\toperands[%u].mem.align: 0x%x\n", i, op->mem.align);
if (op->mem.lshift != 0)
printf("\t\t\toperands[%u].mem.lshift: 0x%x\n", i, op->mem.lshift);
break;
case ARM_OP_PIMM:
@ -125,14 +123,15 @@ void print_insn_detail_arm(csh handle, cs_insn *ins)
break;
}
if (op->shift.type != ARM_SFT_INVALID && op->shift.value) {
if (op->shift.type < ARM_SFT_ASR_REG)
if (op->shift.type != ARM_SFT_INVALID) {
if (op->shift.type < ARM_SFT_REG) {
// shift with constant value
printf("\t\t\tShift: %u = %u\n", op->shift.type, op->shift.value);
else
} else {
// shift with register
printf("\t\t\tShift: %u = %s\n", op->shift.type,
cs_reg_name(handle, op->shift.value));
op->shift.value > 0 ? cs_reg_name(handle, op->shift.value) : "-");
}
}
if (op->vector_index != -1) {

View File

@ -277,8 +277,21 @@ Such an instruction is ill-defined in LLVM and should be fixed upstream.
**All `Auto-Sync` architectures**
| Keyword | Change | Justification |
|---------|--------|---------------|
| Keyword | Change | Justification | Possible revert |
|---------|--------|---------------|-----------------|
| Post-index | Post-index memory access has the disponent now set in the `MEMORY` operand! No longer as separated `reg`/`imm` operand. | The CS memory operand had a field which was there for disponents. Not having it set, for post-index operands was inconsistent. | Edit `ARM_set_detail_op_mem()` and add an immediate operand instead of setting the disponent. |
| Sign `mem.disp` | `mem.disp` is now always positive and the `subtracted` flag indicates if it should be subtracted. | It was inconsistent before. | Change behavior in `ARM_set_detail_op_mem()` |
| `ARM_CC` | `ARM_CC``ARMCC` and value change | They match the same LLVM enum. Better for LLVM compatibility and code generation. | Change it manually. |
| `ARMCC_*` | `ARMCC_EQ == 0` but `ARMCC_INVALID != 0` | They match the LLVM enum. Better for LLVM compatibility and code generation. | Change by hand. |
| System registers | System registers are no longer saved in `cs_arm->reg`, but are separated and have more detail. | System operands follow their own encoding logic. Hence, they should be separated in the details as well. | None |
| System operands | System operands have now the encoding of LLVM (SYSm value mostly) | See note about system registers. | None |
| Instruction enum | Multiple instructions which were only alias were removed from the instruction enum. | Alias are always disassembled as their real instructions and an additional field identifies which alias it is. | None |
| Instruction groups| Instruction groups, which actually were CPU features, were renamed to reflect that. | Names now match the ones in LLVM. Better for code generation. | Replace IDs with macros. |
| CPU features | CPU features get checked more strictly (`MCLASS`, `V8` etc.) | With many new supported extensions, some instruction bytes decode to a different instruction, depending on the enabled features. Hence, it becomes necessary. | None. |
| `writeback` | `writeback` member was moved to detail. | More architectures need a `writeback` flag. This is a simplification. | None. |
| Register alias | Register alias (`r15 = pc` etc.) are not printed if LLVM doesn't do it. Old Capstone register alias can be enabled by `CS_OPT_SYNTAX_CS_REG_ALIAS`. | Mimic LLVM as close as possible. | Enable `CS_OPT_SYNTAX_CS_REG_ALIAS` option. |
| Immediate | Immediate values (`arm_op.imm`) type changed to `int64_t` | Prevent loss of precision in some cases. | None. |
| `mem.lshift` | The `mem.lshift` field was removed. It was not set properly before and just duplicates information in `shift` | Remove faulty and duplicate code. | None. |
| Instr. alias | Capstone now clearly separates real instructions and their aliases. Previously many aliases were treated as real instructions. See above for details. | This became a simple necessity because CS operates with a copy of the LLVMs decoder without changes to the decoder logic. |
**ARM**

View File

@ -252,16 +252,21 @@ inline static unsigned ARMCondCodeFromString(const char *CC)
/// ARM shift type
typedef enum arm_shifter {
ARM_SFT_INVALID = 0,
ARM_SFT_ASR, ///< shift with immediate const
ARM_SFT_LSL, ///< shift with immediate const
ARM_SFT_LSR, ///< shift with immediate const
ARM_SFT_ROR, ///< shift with immediate const
ARM_SFT_RRX, ///< shift with immediate const
ARM_SFT_ASR_REG, ///< shift with register
ARM_SFT_LSL_REG, ///< shift with register
ARM_SFT_LSR_REG, ///< shift with register
ARM_SFT_ROR_REG, ///< shift with register
ARM_SFT_RRX_REG, ///< shift with register
ARM_SFT_ASR,
ARM_SFT_LSL,
ARM_SFT_LSR,
ARM_SFT_ROR,
ARM_SFT_RRX,
ARM_SFT_UXTW,
// Added by Capstone to signal that the shift amount is stored in a register.
// shift.val should be interpreted as register id.
ARM_SFT_REG,
ARM_SFT_ASR_REG,
ARM_SFT_LSL_REG,
ARM_SFT_LSR_REG,
ARM_SFT_ROR_REG,
// Others are not defined in the ISA.
} arm_shifter;
/// The memory barrier constants map directly to the 4-bit encoding of
@ -841,11 +846,8 @@ typedef enum arm_reg {
typedef struct arm_op_mem {
arm_reg base; ///< base register
arm_reg index; ///< index register
int scale; ///< scale for index register (can be 1, or -1)
int scale; ///< scale for index register. Can be 1 if index reg is added, -1 if it is subtracted or 0 if unset.
int disp; ///< displacement/offset value
/// left-shift on index register, or 0 if irrelevant
/// NOTE: this value can also be fetched via operand.shift.value
int lshift;
unsigned align; ///< Alignment of base register. 0 If not set.
} arm_op_mem;
@ -861,8 +863,8 @@ typedef struct cs_arm_op {
int vector_index; ///< Vector Index for some vector operands (or -1 if irrelevant)
struct {
arm_shifter type;
unsigned int value;
arm_shifter type; ///< The shift type
unsigned int value; ///< The amount to shift. If shift.type > ARM_SFT_REG, the value must be interpreted as register id.
} shift;
arm_op_type type; ///< operand type

View File

@ -388,7 +388,7 @@ static const cs_enum_id_map cs_enum_map[] = {
{ .str = "ARM_SFT_ROR", .val = ARM_SFT_ROR },
{ .str = "ARM_SFT_ROR_REG", .val = ARM_SFT_ROR_REG },
{ .str = "ARM_SFT_RRX", .val = ARM_SFT_RRX },
{ .str = "ARM_SFT_RRX_REG", .val = ARM_SFT_RRX_REG },
{ .str = "ARM_SFT_UXTW", .val = ARM_SFT_UXTW },
{ .str = "ARM_T", .val = ARM_T },
{ .str = "ARM_TE", .val = ARM_TE },
{ .str = "ARM_TEE", .val = ARM_TEE },

View File

@ -624,7 +624,8 @@ test_cases:
access: CS_AC_WRITE
post_indexed: -1
writeback: 1
regs_write: [ r11, r15 ]
regs_read: [ r13 ]
regs_write: [ r13, r11, r15 ]
-
asm_text: "tbb [r1, r0]"
details:
@ -2289,3 +2290,467 @@ test_cases:
regs_read: [ cpsr, r1 ]
regs_write: [ r15 ]
groups: [ IsARM, jump ]
-
input:
bytes: [ 0x41,0x04,0xa0,0xe1 ]
arch: "CS_ARCH_ARM"
options: [ CS_MODE_ARM, CS_OPT_DETAIL, CS_OPT_DETAIL_REAL ]
address: 0x0
expected:
insns:
-
asm_text: "asr r0, r1, #8"
is_alias: 1
details:
arm:
operands:
-
type: ARM_OP_REG
reg: r0
access: CS_AC_WRITE
-
type: ARM_OP_REG
reg: r1
access: CS_AC_READ
shift_type: ARM_SFT_ASR
shift_value: 8
-
input:
bytes: [ 0x01,0x04,0xa0,0xe1 ]
arch: "CS_ARCH_ARM"
options: [ CS_MODE_ARM, CS_OPT_DETAIL, CS_OPT_DETAIL_REAL ]
address: 0x0
expected:
insns:
-
asm_text: "lsl r0, r1, #8"
is_alias: 1
details:
arm:
operands:
-
type: ARM_OP_REG
reg: r0
access: CS_AC_WRITE
-
type: ARM_OP_REG
reg: r1
access: CS_AC_READ
shift_type: ARM_SFT_LSL
shift_value: 8
-
input:
bytes: [ 0x21,0x04,0xa0,0xe1 ]
arch: "CS_ARCH_ARM"
options: [ CS_MODE_ARM, CS_OPT_DETAIL, CS_OPT_DETAIL_REAL ]
address: 0x0
expected:
insns:
-
asm_text: "lsr r0, r1, #8"
is_alias: 1
details:
arm:
operands:
-
type: ARM_OP_REG
reg: r0
access: CS_AC_WRITE
-
type: ARM_OP_REG
reg: r1
access: CS_AC_READ
shift_type: ARM_SFT_LSR
shift_value: 8
-
input:
bytes: [ 0x61,0x04,0xa0,0xe1 ]
arch: "CS_ARCH_ARM"
options: [ CS_MODE_ARM, CS_OPT_DETAIL, CS_OPT_DETAIL_REAL ]
address: 0x0
expected:
insns:
-
asm_text: "ror r0, r1, #8"
is_alias: 1
details:
arm:
operands:
-
type: ARM_OP_REG
reg: r0
access: CS_AC_WRITE
-
type: ARM_OP_REG
reg: r1
access: CS_AC_READ
shift_type: ARM_SFT_ROR
shift_value: 8
-
input:
bytes: [ 0x51,0x02,0xa0,0xe1 ]
arch: "CS_ARCH_ARM"
options: [ CS_MODE_ARM, CS_OPT_DETAIL, CS_OPT_DETAIL_REAL ]
address: 0x0
expected:
insns:
-
asm_text: "asr r0, r1, r2"
is_alias: 1
details:
arm:
operands:
-
type: ARM_OP_REG
reg: r0
access: CS_AC_WRITE
-
type: ARM_OP_REG
reg: r1
access: CS_AC_READ
shift_type: ARM_SFT_ASR_REG
shift_value: 75
-
input:
bytes: [ 0x11,0x02,0xa0,0xe1 ]
arch: "CS_ARCH_ARM"
options: [ CS_MODE_ARM, CS_OPT_DETAIL, CS_OPT_DETAIL_REAL ]
address: 0x0
expected:
insns:
-
asm_text: "lsl r0, r1, r2"
is_alias: 1
details:
arm:
operands:
-
type: ARM_OP_REG
reg: r0
access: CS_AC_WRITE
-
type: ARM_OP_REG
reg: r1
access: CS_AC_READ
shift_type: ARM_SFT_LSL_REG
shift_value: 75
-
input:
bytes: [ 0x31,0x02,0xa0,0xe1 ]
arch: "CS_ARCH_ARM"
options: [ CS_MODE_ARM, CS_OPT_DETAIL, CS_OPT_DETAIL_REAL ]
address: 0x0
expected:
insns:
-
asm_text: "lsr r0, r1, r2"
is_alias: 1
details:
arm:
operands:
-
type: ARM_OP_REG
reg: r0
access: CS_AC_WRITE
-
type: ARM_OP_REG
reg: r1
access: CS_AC_READ
shift_type: ARM_SFT_LSR_REG
shift_value: 75
-
input:
bytes: [ 0x71,0x02,0xa0,0xe1 ]
arch: "CS_ARCH_ARM"
options: [ CS_MODE_ARM, CS_OPT_DETAIL, CS_OPT_DETAIL_REAL ]
address: 0x0
expected:
insns:
-
asm_text: "ror r0, r1, r2"
is_alias: 1
details:
arm:
operands:
-
type: ARM_OP_REG
reg: r0
access: CS_AC_WRITE
-
type: ARM_OP_REG
reg: r1
access: CS_AC_READ
shift_type: ARM_SFT_ROR_REG
shift_value: 75
-
input:
bytes: [ 0x41,0x04,0xa0,0xe1 ]
arch: "CS_ARCH_ARM"
options: [ CS_MODE_ARM, CS_OPT_DETAIL ]
address: 0x0
expected:
insns:
-
asm_text: "asr r0, r1, #8"
is_alias: 1
details:
arm:
operands:
-
type: ARM_OP_REG
reg: r0
access: CS_AC_WRITE
-
type: ARM_OP_REG
reg: r1
access: CS_AC_READ
shift_type: ARM_SFT_ASR
shift_value: 8
-
type: ARM_OP_IMM
imm: 8
access: CS_AC_READ
-
input:
bytes: [ 0x01,0x04,0xa0,0xe1 ]
arch: "CS_ARCH_ARM"
options: [ CS_MODE_ARM, CS_OPT_DETAIL ]
address: 0x0
expected:
insns:
-
asm_text: "lsl r0, r1, #8"
is_alias: 1
details:
arm:
operands:
-
type: ARM_OP_REG
reg: r0
access: CS_AC_WRITE
-
type: ARM_OP_REG
reg: r1
access: CS_AC_READ
shift_type: ARM_SFT_LSL
shift_value: 8
-
type: ARM_OP_IMM
imm: 8
access: CS_AC_READ
-
input:
bytes: [ 0x21,0x04,0xa0,0xe1 ]
arch: "CS_ARCH_ARM"
options: [ CS_MODE_ARM, CS_OPT_DETAIL ]
address: 0x0
expected:
insns:
-
asm_text: "lsr r0, r1, #8"
is_alias: 1
details:
arm:
operands:
-
type: ARM_OP_REG
reg: r0
access: CS_AC_WRITE
-
type: ARM_OP_REG
reg: r1
access: CS_AC_READ
shift_type: ARM_SFT_LSR
shift_value: 8
-
type: ARM_OP_IMM
imm: 8
access: CS_AC_READ
-
input:
bytes: [ 0x61,0x04,0xa0,0xe1 ]
arch: "CS_ARCH_ARM"
options: [ CS_MODE_ARM, CS_OPT_DETAIL ]
address: 0x0
expected:
insns:
-
asm_text: "ror r0, r1, #8"
is_alias: 1
details:
arm:
operands:
-
type: ARM_OP_REG
reg: r0
access: CS_AC_WRITE
-
type: ARM_OP_REG
reg: r1
access: CS_AC_READ
shift_type: ARM_SFT_ROR
shift_value: 8
-
type: ARM_OP_IMM
imm: 8
access: CS_AC_READ
-
input:
bytes: [ 0x51,0x02,0xa0,0xe1 ]
arch: "CS_ARCH_ARM"
options: [ CS_MODE_ARM, CS_OPT_DETAIL ]
address: 0x0
expected:
insns:
-
asm_text: "asr r0, r1, r2"
is_alias: 1
details:
arm:
operands:
-
type: ARM_OP_REG
reg: r0
access: CS_AC_WRITE
-
type: ARM_OP_REG
reg: r1
access: CS_AC_READ
shift_type: ARM_SFT_ASR_REG
shift_value: 75
-
type: ARM_OP_REG
reg: r2
access: CS_AC_READ
-
input:
bytes: [ 0x11,0x02,0xa0,0xe1 ]
arch: "CS_ARCH_ARM"
options: [ CS_MODE_ARM, CS_OPT_DETAIL ]
address: 0x0
expected:
insns:
-
asm_text: "lsl r0, r1, r2"
is_alias: 1
details:
arm:
operands:
-
type: ARM_OP_REG
reg: r0
access: CS_AC_WRITE
-
type: ARM_OP_REG
reg: r1
access: CS_AC_READ
shift_type: ARM_SFT_LSL_REG
shift_value: 75
-
type: ARM_OP_REG
reg: r2
access: CS_AC_READ
-
input:
bytes: [ 0x31,0x02,0xa0,0xe1 ]
arch: "CS_ARCH_ARM"
options: [ CS_MODE_ARM, CS_OPT_DETAIL ]
address: 0x0
expected:
insns:
-
asm_text: "lsr r0, r1, r2"
is_alias: 1
details:
arm:
operands:
-
type: ARM_OP_REG
reg: r0
access: CS_AC_WRITE
-
type: ARM_OP_REG
reg: r1
access: CS_AC_READ
shift_type: ARM_SFT_LSR_REG
shift_value: 75
-
type: ARM_OP_REG
reg: r2
access: CS_AC_READ
-
input:
bytes: [ 0x71,0x02,0xa0,0xe1 ]
arch: "CS_ARCH_ARM"
options: [ CS_MODE_ARM, CS_OPT_DETAIL ]
address: 0x0
expected:
insns:
-
asm_text: "ror r0, r1, r2"
is_alias: 1
details:
arm:
operands:
-
type: ARM_OP_REG
reg: r0
access: CS_AC_WRITE
-
type: ARM_OP_REG
reg: r1
access: CS_AC_READ
shift_type: ARM_SFT_ROR_REG
shift_value: 75
-
type: ARM_OP_REG
reg: r2
access: CS_AC_READ
-
input:
bytes: [ 0x60,0x00,0x80,0xe7 ]
arch: "CS_ARCH_ARM"
options: [ CS_MODE_ARM, CS_OPT_DETAIL, CS_OPT_DETAIL_REAL ]
address: 0x0
expected:
insns:
-
asm_text: "str r0, [r0, r0, rrx]"
details:
arm:
operands:
-
type: ARM_OP_REG
reg: r0
access: CS_AC_READ
-
type: ARM_OP_MEM
mem_base: r0
mem_index: r0
access: CS_AC_WRITE
shift_type: ARM_SFT_RRX
-
input:
bytes: [ 0x90,0xfc,0x93,0x0e ]
arch: "CS_ARCH_ARM"
options: [ CS_MODE_MCLASS, CS_MODE_V8, CS_MODE_THUMB, CS_OPT_DETAIL ]
address: 0x0
expected:
insns:
-
asm_text: "vldrh.u16 q0, [r0, q1, uxtw #1]"
details:
arm:
operands:
-
type: ARM_OP_REG
reg: q0
access: CS_AC_WRITE
-
type: ARM_OP_MEM
mem_base: r0
mem_index: q1
mem_scale: 1
access: CS_AC_READ
shift_type: ARM_SFT_UXTW
shift_value: 1

View File

@ -249,7 +249,7 @@ test_cases:
mnemonic: "pop.w"
op_str: "{r11, pc}"
details:
groups: [ IsThumb2, jump ]
groups: [ IsThumb2, return, jump ]
-
asm_text: "tbb [r1, r0]"
mnemonic: "tbb"
@ -309,7 +309,7 @@ test_cases:
mnemonic: "mrs"
op_str: "x9, MIDR_EL1"
details:
regs_impl_write: [ nzcv ]
regs_impl_write: []
groups: [ privilege ]
-
asm_text: "msr SPSel, #0"

View File

@ -3651,7 +3651,7 @@ test_cases:
type: ARM_OP_MEM
mem_base: r1
mem_index: r3
mem_scale: 0
mem_scale: -1
access: CS_AC_READ
subtracted: 1
regs_read: [ r1, r3 ]
@ -4090,7 +4090,7 @@ test_cases:
type: ARM_OP_MEM
mem_base: r2
mem_index: r3
mem_scale: 0
mem_scale: 1
shift_type: ARM_SFT_LSL
shift_value: 2
regs_read: [ r2, r3 ]
@ -5126,6 +5126,105 @@ test_cases:
regs_read: [ za0.d, za1.d, za2.d, za3.d, za4.d, za5.d, za6.d, za7.d ]
groups: [ HasSME ]
-
input:
address: 0x0
name: "issue 2382"
bytes: [ 0x42, 0x40 ]
arch: "CS_ARCH_ARM"
options: [ CS_MODE_BIG_ENDIAN, CS_MODE_THUMB, CS_OPT_DETAIL ]
expected:
insns:
-
asm_text: "rsbs r0, r0, #0"
details:
arm:
operands:
-
type: ARM_OP_REG
reg: r0
access: CS_AC_WRITE
-
type: ARM_OP_REG
reg: r0
access: CS_AC_READ
-
type: ARM_OP_IMM
imm: 0
access: CS_AC_READ
-
input:
address: 0x0
name: "issue 2281 - Negative memory index register scale not set"
bytes: [ 0x02, 0x00, 0x11, 0xe7 ]
arch: "CS_ARCH_ARM"
options: [ CS_MODE_ARM, CS_OPT_DETAIL ]
expected:
insns:
-
asm_text: "ldr r0, [r1, -r2]"
details:
arm:
operands:
-
type: ARM_OP_REG
reg: r0
access: CS_AC_WRITE
-
type: ARM_OP_MEM
mem_base: r1
mem_index: r2
mem_scale: -1
access: CS_AC_READ
-
input:
address: 0x0
name: "issue 2281 - Positive memory index register scale not set"
bytes: [ 0x02, 0x00, 0x91, 0xe7 ]
arch: "CS_ARCH_ARM"
options: [ CS_MODE_ARM, CS_OPT_DETAIL ]
expected:
insns:
-
asm_text: "ldr r0, [r1, r2]"
details:
arm:
operands:
-
type: ARM_OP_REG
reg: r0
access: CS_AC_WRITE
-
type: ARM_OP_MEM
mem_base: r1
mem_index: r2
mem_scale: 1
access: CS_AC_READ
-
input:
address: 0x0
name: "issue 2281 - rrx"
bytes: [ 0x61, 0x00, 0x10, 0xe7 ]
arch: "CS_ARCH_ARM"
options: [ CS_MODE_ARM, CS_OPT_DETAIL ]
expected:
insns:
-
asm_text: "ldr r0, [r0, -r1, rrx]"
details:
arm:
operands:
-
type: ARM_OP_REG
reg: r0
access: CS_AC_WRITE
-
type: ARM_OP_MEM
mem_base: r0
mem_index: r1
mem_scale: -1
access: CS_AC_READ
shift_type: ARM_SFT_RRX
-
input:
name: "issue 2424"