mirror of
https://github.com/capstone-engine/capstone.git
synced 2024-11-23 05:29:53 +00:00
ARM fixes (#2477)
* 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:
parent
40dffb2668
commit
5430745e96
@ -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) {
|
||||
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];
|
||||
}
|
||||
|
@ -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.
|
||||
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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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),
|
||||
)
|
||||
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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**
|
||||
|
@ -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
|
||||
|
@ -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 },
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
Loading…
Reference in New Issue
Block a user