Enhance shift value and types of shift instructions. (#2638)
* Enhance shift value and types of shift instructions. Shifts via registers now save the register id in cs_arch64_op.shift.value and set the shift type accordingly. * Sort table
This commit is contained in:
parent
cd282ef593
commit
bb2f657973
|
@ -369,12 +369,52 @@ static void AArch64_check_updates_flags(MCInst *MI)
|
|||
#endif // CAPSTONE_DIET
|
||||
}
|
||||
|
||||
static aarch64_shifter id_to_shifter(unsigned Opcode) {
|
||||
switch (Opcode) {
|
||||
default:
|
||||
return AARCH64_SFT_INVALID;
|
||||
case AArch64_RORVXr:
|
||||
case AArch64_RORVWr:
|
||||
return AARCH64_SFT_ROR_REG;
|
||||
case AArch64_LSRVXr:
|
||||
case AArch64_LSRVWr:
|
||||
return AARCH64_SFT_LSR_REG;
|
||||
case AArch64_LSLVXr:
|
||||
case AArch64_LSLVWr:
|
||||
return AARCH64_SFT_LSL_REG;
|
||||
case AArch64_ASRVXr:
|
||||
case AArch64_ASRVWr:
|
||||
return AARCH64_SFT_ASR_REG;
|
||||
}
|
||||
}
|
||||
|
||||
static void add_non_alias_details(MCInst *MI)
|
||||
{
|
||||
unsigned Opcode = MCInst_getOpcode(MI);
|
||||
switch (Opcode) {
|
||||
default:
|
||||
break;
|
||||
case AArch64_RORVXr:
|
||||
case AArch64_RORVWr:
|
||||
case AArch64_LSRVXr:
|
||||
case AArch64_LSRVWr:
|
||||
case AArch64_LSLVXr:
|
||||
case AArch64_LSLVWr:
|
||||
case AArch64_ASRVXr:
|
||||
case AArch64_ASRVWr:
|
||||
if (AArch64_get_detail(MI)->op_count != 3) {
|
||||
return;
|
||||
}
|
||||
CS_ASSERT_RET(AArch64_get_detail_op(MI, -1)->type == AARCH64_OP_REG);
|
||||
|
||||
// The shift by register instructions don't set the shift value properly.
|
||||
// Correct it here.
|
||||
uint64_t shift = AArch64_get_detail_op(MI, -1)->reg;
|
||||
cs_aarch64_op *op1 = AArch64_get_detail_op(MI, -2);
|
||||
op1->shift.type = id_to_shifter(Opcode);
|
||||
op1->shift.value = shift;
|
||||
AArch64_dec_op_count(MI);
|
||||
break;
|
||||
case AArch64_FCMPDri:
|
||||
case AArch64_FCMPEDri:
|
||||
case AArch64_FCMPEHri:
|
||||
|
@ -573,6 +613,19 @@ static void AArch64_add_not_defined_ops(MCInst *MI, const SStream *OS)
|
|||
switch (MI->flat_insn->alias_id) {
|
||||
default:
|
||||
return;
|
||||
case AARCH64_INS_ALIAS_ROR:
|
||||
if (AArch64_get_detail(MI)->op_count != 3) {
|
||||
return;
|
||||
}
|
||||
// The ROR alias doesn't set the shift value properly.
|
||||
// Correct it here.
|
||||
bool reg_shift = AArch64_get_detail_op(MI, -1)->type == AARCH64_OP_REG;
|
||||
uint64_t shift = reg_shift ? AArch64_get_detail_op(MI, -1)->reg : AArch64_get_detail_op(MI, -1)->imm;
|
||||
cs_aarch64_op *op1 = AArch64_get_detail_op(MI, -2);
|
||||
op1->shift.type = reg_shift ? AARCH64_SFT_ROR_REG : AARCH64_SFT_ROR;
|
||||
op1->shift.value = shift;
|
||||
AArch64_dec_op_count(MI);
|
||||
break;
|
||||
case AARCH64_INS_ALIAS_FMOV:
|
||||
if (AArch64_get_detail_op(MI, -1)->type == AARCH64_OP_FP) {
|
||||
break;
|
||||
|
@ -1042,6 +1095,12 @@ void AArch64_reg_access(const cs_insn *insn, cs_regs regs_read,
|
|||
default:
|
||||
break;
|
||||
}
|
||||
if (op->shift.type >= AARCH64_SFT_LSL_REG) {
|
||||
if (!arr_exist(regs_read, read_count, op->shift.value)) {
|
||||
regs_read[read_count] = (uint16_t)op->shift.value;
|
||||
read_count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*regs_read_count = read_count;
|
||||
|
|
|
@ -7,6 +7,11 @@ AARCH64_SFT_MSL = 2
|
|||
AARCH64_SFT_LSR = 3
|
||||
AARCH64_SFT_ASR = 4
|
||||
AARCH64_SFT_ROR = 5
|
||||
AARCH64_SFT_LSL_REG = 6
|
||||
AARCH64_SFT_MSL_REG = 7
|
||||
AARCH64_SFT_LSR_REG = 8
|
||||
AARCH64_SFT_ASR_REG = 9
|
||||
AARCH64_SFT_ROR_REG = 10
|
||||
|
||||
AARCH64_EXT_INVALID = 0
|
||||
AARCH64_EXT_UXTB = 1
|
||||
|
|
|
@ -18,6 +18,8 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
/// AArch64 shift type
|
||||
/// Those values do not correspond to the bit values encoded
|
||||
/// in the instruction.
|
||||
typedef enum aarch64_shifter {
|
||||
AARCH64_SFT_INVALID = 0,
|
||||
AARCH64_SFT_LSL = 1,
|
||||
|
@ -25,6 +27,11 @@ typedef enum aarch64_shifter {
|
|||
AARCH64_SFT_LSR = 3,
|
||||
AARCH64_SFT_ASR = 4,
|
||||
AARCH64_SFT_ROR = 5,
|
||||
AARCH64_SFT_LSL_REG = 6,
|
||||
AARCH64_SFT_MSL_REG = 7,
|
||||
AARCH64_SFT_LSR_REG = 8,
|
||||
AARCH64_SFT_ASR_REG = 9,
|
||||
AARCH64_SFT_ROR_REG = 10,
|
||||
} aarch64_shifter;
|
||||
|
||||
/// AArch64 extender type
|
||||
|
@ -2813,7 +2820,10 @@ typedef struct cs_aarch64_op {
|
|||
AArch64Layout_VectorLayout vas; ///< Vector Arrangement Specifier
|
||||
struct {
|
||||
aarch64_shifter type; ///< shifter type of this operand
|
||||
unsigned int value; ///< shifter value of this operand
|
||||
/// Shift value of this operand.
|
||||
/// If the type indicates a shift with a register this value should be
|
||||
/// interpreted as aarch64_reg.
|
||||
unsigned int value;
|
||||
} shift;
|
||||
aarch64_extender ext; ///< extender type of this operand
|
||||
aarch64_op_type type; ///< operand type
|
||||
|
|
|
@ -25,6 +25,11 @@ typedef enum {
|
|||
ARM64_SFT_LSR = AARCH64_SFT_LSR,
|
||||
ARM64_SFT_ASR = AARCH64_SFT_ASR,
|
||||
ARM64_SFT_ROR = AARCH64_SFT_ROR,
|
||||
ARM64_SFT_LSL_REG = AARCH64_SFT_LSL_REG,
|
||||
ARM64_SFT_MSL_REG = AARCH64_SFT_MSL_REG,
|
||||
ARM64_SFT_LSR_REG = AARCH64_SFT_LSR_REG,
|
||||
ARM64_SFT_ASR_REG = AARCH64_SFT_ASR_REG,
|
||||
ARM64_SFT_ROR_REG = AARCH64_SFT_ROR_REG,
|
||||
} arm64_shifter;
|
||||
|
||||
typedef enum {
|
||||
|
|
|
@ -289,11 +289,16 @@ static const cs_enum_id_map cs_enum_map[] = {
|
|||
{ .str = "AARCH64_OP_TLBI", .val = AARCH64_OP_TLBI },
|
||||
{ .str = "AARCH64_OP_TSB", .val = AARCH64_OP_TSB },
|
||||
{ .str = "AARCH64_SFT_ASR", .val = AARCH64_SFT_ASR },
|
||||
{ .str = "AARCH64_SFT_ASR_REG", .val = AARCH64_SFT_ASR_REG },
|
||||
{ .str = "AARCH64_SFT_INVALID", .val = AARCH64_SFT_INVALID },
|
||||
{ .str = "AARCH64_SFT_LSL", .val = AARCH64_SFT_LSL },
|
||||
{ .str = "AARCH64_SFT_LSL_REG", .val = AARCH64_SFT_LSL_REG },
|
||||
{ .str = "AARCH64_SFT_LSR", .val = AARCH64_SFT_LSR },
|
||||
{ .str = "AARCH64_SFT_LSR_REG", .val = AARCH64_SFT_LSR_REG },
|
||||
{ .str = "AARCH64_SFT_MSL", .val = AARCH64_SFT_MSL },
|
||||
{ .str = "AARCH64_SFT_MSL_REG", .val = AARCH64_SFT_MSL_REG },
|
||||
{ .str = "AARCH64_SFT_ROR", .val = AARCH64_SFT_ROR },
|
||||
{ .str = "AARCH64_SFT_ROR_REG", .val = AARCH64_SFT_ROR_REG },
|
||||
{ .str = "AARCH64_SME_OP_INVALID", .val = AARCH64_SME_OP_INVALID },
|
||||
{ .str = "AARCH64_SME_OP_TILE", .val = AARCH64_SME_OP_TILE },
|
||||
{ .str = "AARCH64_SME_OP_TILE_VEC", .val = AARCH64_SME_OP_TILE_VEC },
|
||||
|
@ -316,6 +321,10 @@ static const cs_enum_id_map cs_enum_map[] = {
|
|||
{ .str = "AArch64CC_VS", .val = AArch64CC_VS },
|
||||
{ .str = "ALPHA_OP_IMM", .val = ALPHA_OP_IMM },
|
||||
{ .str = "ALPHA_OP_REG", .val = ALPHA_OP_REG },
|
||||
{ .str = "ARC_GRP_BRANCH_RELATIVE", .val = ARC_GRP_BRANCH_RELATIVE },
|
||||
{ .str = "ARC_GRP_CALL", .val = ARC_GRP_CALL },
|
||||
{ .str = "ARC_GRP_JUMP", .val = ARC_GRP_JUMP },
|
||||
{ .str = "ARC_GRP_RET", .val = ARC_GRP_RET },
|
||||
{ .str = "ARC_OP_IMM", .val = ARC_OP_IMM },
|
||||
{ .str = "ARC_OP_REG", .val = ARC_OP_REG },
|
||||
{ .str = "ARMCC_AL", .val = ARMCC_AL },
|
||||
|
@ -466,10 +475,6 @@ static const cs_enum_id_map cs_enum_map[] = {
|
|||
{ .str = "Alpha_GRP_CALL", .val = Alpha_GRP_CALL },
|
||||
{ .str = "Alpha_GRP_ENDING", .val = Alpha_GRP_ENDING },
|
||||
{ .str = "Alpha_GRP_JUMP", .val = Alpha_GRP_JUMP },
|
||||
{ .str = "ARC_GRP_JUMP", .val = ARC_GRP_JUMP },
|
||||
{ .str = "ARC_GRP_CALL", .val = ARC_GRP_CALL },
|
||||
{ .str = "ARC_GRP_RET", .val = ARC_GRP_RET },
|
||||
{ .str = "ARC_GRP_BRANCH_RELATIVE", .val = ARC_GRP_BRANCH_RELATIVE },
|
||||
{ .str = "BPF_EXT_LEN", .val = BPF_EXT_LEN },
|
||||
{ .str = "BPF_GRP_ALU", .val = BPF_GRP_ALU },
|
||||
{ .str = "BPF_GRP_CALL", .val = BPF_GRP_CALL },
|
||||
|
@ -1671,4 +1676,4 @@ static const cs_enum_id_map cs_enum_map[] = {
|
|||
.val = 0xffffff }, // For testing
|
||||
};
|
||||
|
||||
#endif // TEST_MAPPING_H
|
||||
#endif // TEST_MAPPING_H
|
||||
|
|
|
@ -869,3 +869,278 @@ test_cases:
|
|||
regs_read: [ zt0, z30, z31 ]
|
||||
regs_write: [ z19, z23, z27, z31 ]
|
||||
groups: [ HasSME2p1, HasSME_LUTv2 ]
|
||||
-
|
||||
input:
|
||||
bytes: [0x41,0x7c,0x82,0x13]
|
||||
arch: "CS_ARCH_AARCH64"
|
||||
options: [ CS_OPT_DETAIL ]
|
||||
address: 0x0
|
||||
expected:
|
||||
insns:
|
||||
-
|
||||
asm_text: "ror w1, w2, #31"
|
||||
details:
|
||||
aarch64:
|
||||
operands:
|
||||
-
|
||||
type: AARCH64_OP_REG
|
||||
reg: w1
|
||||
access: CS_AC_WRITE
|
||||
-
|
||||
type: AARCH64_OP_REG
|
||||
reg: w2
|
||||
access: CS_AC_READ
|
||||
shift_type: AARCH64_SFT_ROR
|
||||
shift_value: 31
|
||||
regs_read: [ w2 ]
|
||||
regs_write: [ w1 ]
|
||||
-
|
||||
input:
|
||||
bytes: [0x41,0x7c,0x1f,0x53]
|
||||
arch: "CS_ARCH_AARCH64"
|
||||
options: [ CS_OPT_DETAIL ]
|
||||
address: 0x0
|
||||
expected:
|
||||
insns:
|
||||
-
|
||||
asm_text: "lsr w1, w2, #31"
|
||||
details:
|
||||
aarch64:
|
||||
operands:
|
||||
-
|
||||
type: AARCH64_OP_REG
|
||||
reg: w1
|
||||
access: CS_AC_WRITE
|
||||
-
|
||||
type: AARCH64_OP_REG
|
||||
reg: w2
|
||||
access: CS_AC_READ
|
||||
shift_type: AARCH64_SFT_LSR
|
||||
shift_value: 31
|
||||
regs_read: [ w2 ]
|
||||
regs_write: [ w1 ]
|
||||
-
|
||||
input:
|
||||
bytes: [0x41,0x7c,0x1f,0x13]
|
||||
arch: "CS_ARCH_AARCH64"
|
||||
options: [ CS_OPT_DETAIL ]
|
||||
address: 0x0
|
||||
expected:
|
||||
insns:
|
||||
-
|
||||
asm_text: "asr w1, w2, #31"
|
||||
details:
|
||||
aarch64:
|
||||
operands:
|
||||
-
|
||||
type: AARCH64_OP_REG
|
||||
reg: w1
|
||||
access: CS_AC_WRITE
|
||||
-
|
||||
type: AARCH64_OP_REG
|
||||
reg: w2
|
||||
access: CS_AC_READ
|
||||
shift_type: AARCH64_SFT_ASR
|
||||
shift_value: 31
|
||||
regs_read: [ w2 ]
|
||||
regs_write: [ w1 ]
|
||||
-
|
||||
input:
|
||||
bytes: [0x41,0x00,0x01,0x53]
|
||||
arch: "CS_ARCH_AARCH64"
|
||||
options: [ CS_OPT_DETAIL ]
|
||||
address: 0x0
|
||||
expected:
|
||||
insns:
|
||||
-
|
||||
asm_text: "lsl w1, w2, #31"
|
||||
details:
|
||||
aarch64:
|
||||
operands:
|
||||
-
|
||||
type: AARCH64_OP_REG
|
||||
reg: w1
|
||||
access: CS_AC_WRITE
|
||||
-
|
||||
type: AARCH64_OP_REG
|
||||
reg: w2
|
||||
access: CS_AC_READ
|
||||
shift_type: AARCH64_SFT_LSL
|
||||
shift_value: 31
|
||||
regs_read: [ w2 ]
|
||||
regs_write: [ w1 ]
|
||||
-
|
||||
input:
|
||||
bytes: [0x41,0x2c,0xc3,0x1a]
|
||||
arch: "CS_ARCH_AARCH64"
|
||||
options: [ CS_OPT_DETAIL ]
|
||||
address: 0x0
|
||||
expected:
|
||||
insns:
|
||||
-
|
||||
asm_text: "ror w1, w2, w3"
|
||||
details:
|
||||
aarch64:
|
||||
operands:
|
||||
-
|
||||
type: AARCH64_OP_REG
|
||||
reg: w1
|
||||
access: CS_AC_WRITE
|
||||
-
|
||||
type: AARCH64_OP_REG
|
||||
reg: w2
|
||||
access: CS_AC_READ
|
||||
shift_type: AARCH64_SFT_ROR_REG
|
||||
shift_value: 207 # Absolute number of W3 enum value. Might change with an update.
|
||||
regs_read: [ w2, w3 ]
|
||||
regs_write: [ w1 ]
|
||||
-
|
||||
input:
|
||||
bytes: [0x41,0x24,0xc3,0x1a]
|
||||
arch: "CS_ARCH_AARCH64"
|
||||
options: [ CS_OPT_DETAIL ]
|
||||
address: 0x0
|
||||
expected:
|
||||
insns:
|
||||
-
|
||||
asm_text: "lsr w1, w2, w3"
|
||||
details:
|
||||
aarch64:
|
||||
operands:
|
||||
-
|
||||
type: AARCH64_OP_REG
|
||||
reg: w1
|
||||
access: CS_AC_WRITE
|
||||
-
|
||||
type: AARCH64_OP_REG
|
||||
reg: w2
|
||||
access: CS_AC_READ
|
||||
shift_type: AARCH64_SFT_LSR_REG
|
||||
shift_value: 207 # Absolute number of W3 enum value. Might change with an update.
|
||||
regs_read: [ w2, w3 ]
|
||||
regs_write: [ w1 ]
|
||||
-
|
||||
input:
|
||||
bytes: [0x41,0x28,0xc3,0x1a]
|
||||
arch: "CS_ARCH_AARCH64"
|
||||
options: [ CS_OPT_DETAIL ]
|
||||
address: 0x0
|
||||
expected:
|
||||
insns:
|
||||
-
|
||||
asm_text: "asr w1, w2, w3"
|
||||
details:
|
||||
aarch64:
|
||||
operands:
|
||||
-
|
||||
type: AARCH64_OP_REG
|
||||
reg: w1
|
||||
access: CS_AC_WRITE
|
||||
-
|
||||
type: AARCH64_OP_REG
|
||||
reg: w2
|
||||
access: CS_AC_READ
|
||||
shift_type: AARCH64_SFT_ASR_REG
|
||||
shift_value: 207 # Absolute number of W3 enum value. Might change with an update.
|
||||
regs_read: [ w2, w3 ]
|
||||
regs_write: [ w1 ]
|
||||
-
|
||||
input:
|
||||
bytes: [0x41,0x20,0xc3,0x1a]
|
||||
arch: "CS_ARCH_AARCH64"
|
||||
options: [ CS_OPT_DETAIL ]
|
||||
address: 0x0
|
||||
expected:
|
||||
insns:
|
||||
-
|
||||
asm_text: "lsl w1, w2, w3"
|
||||
details:
|
||||
aarch64:
|
||||
operands:
|
||||
-
|
||||
type: AARCH64_OP_REG
|
||||
reg: w1
|
||||
access: CS_AC_WRITE
|
||||
-
|
||||
type: AARCH64_OP_REG
|
||||
reg: w2
|
||||
access: CS_AC_READ
|
||||
shift_type: AARCH64_SFT_LSL_REG
|
||||
shift_value: 207 # Absolute number of W3 enum value. Might change with an update.
|
||||
regs_read: [ w2, w3 ]
|
||||
regs_write: [ w1 ]
|
||||
-
|
||||
input:
|
||||
bytes: [0x41,0x2c,0xc3,0x1a]
|
||||
arch: "CS_ARCH_AARCH64"
|
||||
options: [ CS_OPT_DETAIL ]
|
||||
address: 0x0
|
||||
expected:
|
||||
insns:
|
||||
-
|
||||
asm_text: "ror w1, w2, w3"
|
||||
details:
|
||||
aarch64:
|
||||
operands:
|
||||
-
|
||||
type: AARCH64_OP_REG
|
||||
reg: w1
|
||||
access: CS_AC_WRITE
|
||||
-
|
||||
type: AARCH64_OP_REG
|
||||
reg: w2
|
||||
access: CS_AC_READ
|
||||
shift_type: AARCH64_SFT_ROR_REG
|
||||
shift_value: 207 # Absolute number of W3 enum value. Might change with an update.
|
||||
regs_read: [ w2, w3 ]
|
||||
regs_write: [ w1 ]
|
||||
-
|
||||
input:
|
||||
bytes: [0x41,0x24,0xc3,0x1a]
|
||||
arch: "CS_ARCH_AARCH64"
|
||||
options: [ CS_OPT_DETAIL ]
|
||||
address: 0x0
|
||||
expected:
|
||||
insns:
|
||||
-
|
||||
asm_text: "lsr w1, w2, w3"
|
||||
details:
|
||||
aarch64:
|
||||
operands:
|
||||
-
|
||||
type: AARCH64_OP_REG
|
||||
reg: w1
|
||||
access: CS_AC_WRITE
|
||||
-
|
||||
type: AARCH64_OP_REG
|
||||
reg: w2
|
||||
access: CS_AC_READ
|
||||
shift_type: AARCH64_SFT_LSR_REG
|
||||
shift_value: 207 # Absolute number of W3 enum value. Might change with an update.
|
||||
regs_read: [ w2, w3 ]
|
||||
regs_write: [ w1 ]
|
||||
-
|
||||
input:
|
||||
bytes: [0x41,0x28,0xc3,0x1a]
|
||||
arch: "CS_ARCH_AARCH64"
|
||||
options: [ CS_OPT_DETAIL ]
|
||||
address: 0x0
|
||||
expected:
|
||||
insns:
|
||||
-
|
||||
asm_text: "asr w1, w2, w3"
|
||||
details:
|
||||
aarch64:
|
||||
operands:
|
||||
-
|
||||
type: AARCH64_OP_REG
|
||||
reg: w1
|
||||
access: CS_AC_WRITE
|
||||
-
|
||||
type: AARCH64_OP_REG
|
||||
reg: w2
|
||||
access: CS_AC_READ
|
||||
shift_type: AARCH64_SFT_ASR_REG
|
||||
shift_value: 207 # Absolute number of W3 enum value. Might change with an update.
|
||||
regs_read: [ w2, w3 ]
|
||||
regs_write: [ w1 ]
|
||||
|
|
Loading…
Reference in New Issue