feat(arm): add an ESR register (#2155)
This allows users to read/write from the ARM syndrome value like in AArch64.
This commit is contained in:
@@ -187,7 +187,8 @@ module Arm =
|
|||||||
let UC_ARM_REG_XPSR_G = 137
|
let UC_ARM_REG_XPSR_G = 137
|
||||||
let UC_ARM_REG_XPSR_NZCVQG = 138
|
let UC_ARM_REG_XPSR_NZCVQG = 138
|
||||||
let UC_ARM_REG_CP_REG = 139
|
let UC_ARM_REG_CP_REG = 139
|
||||||
let UC_ARM_REG_ENDING = 140
|
let UC_ARM_REG_ESR = 140
|
||||||
|
let UC_ARM_REG_ENDING = 141
|
||||||
|
|
||||||
// alias registers
|
// alias registers
|
||||||
let UC_ARM_REG_R13 = 12
|
let UC_ARM_REG_R13 = 12
|
||||||
|
|||||||
@@ -182,7 +182,8 @@ const (
|
|||||||
ARM_REG_XPSR_G = 137
|
ARM_REG_XPSR_G = 137
|
||||||
ARM_REG_XPSR_NZCVQG = 138
|
ARM_REG_XPSR_NZCVQG = 138
|
||||||
ARM_REG_CP_REG = 139
|
ARM_REG_CP_REG = 139
|
||||||
ARM_REG_ENDING = 140
|
ARM_REG_ESR = 140
|
||||||
|
ARM_REG_ENDING = 141
|
||||||
|
|
||||||
// alias registers
|
// alias registers
|
||||||
ARM_REG_R13 = 12
|
ARM_REG_R13 = 12
|
||||||
|
|||||||
@@ -184,7 +184,8 @@ public interface ArmConst {
|
|||||||
public static final int UC_ARM_REG_XPSR_G = 137;
|
public static final int UC_ARM_REG_XPSR_G = 137;
|
||||||
public static final int UC_ARM_REG_XPSR_NZCVQG = 138;
|
public static final int UC_ARM_REG_XPSR_NZCVQG = 138;
|
||||||
public static final int UC_ARM_REG_CP_REG = 139;
|
public static final int UC_ARM_REG_CP_REG = 139;
|
||||||
public static final int UC_ARM_REG_ENDING = 140;
|
public static final int UC_ARM_REG_ESR = 140;
|
||||||
|
public static final int UC_ARM_REG_ENDING = 141;
|
||||||
|
|
||||||
// alias registers
|
// alias registers
|
||||||
public static final int UC_ARM_REG_R13 = 12;
|
public static final int UC_ARM_REG_R13 = 12;
|
||||||
|
|||||||
@@ -185,7 +185,8 @@ const
|
|||||||
UC_ARM_REG_XPSR_G = 137;
|
UC_ARM_REG_XPSR_G = 137;
|
||||||
UC_ARM_REG_XPSR_NZCVQG = 138;
|
UC_ARM_REG_XPSR_NZCVQG = 138;
|
||||||
UC_ARM_REG_CP_REG = 139;
|
UC_ARM_REG_CP_REG = 139;
|
||||||
UC_ARM_REG_ENDING = 140;
|
UC_ARM_REG_ESR = 140;
|
||||||
|
UC_ARM_REG_ENDING = 141;
|
||||||
|
|
||||||
// alias registers
|
// alias registers
|
||||||
UC_ARM_REG_R13 = 12;
|
UC_ARM_REG_R13 = 12;
|
||||||
|
|||||||
@@ -180,7 +180,8 @@ UC_ARM_REG_XPSR_NZCVQ = 136
|
|||||||
UC_ARM_REG_XPSR_G = 137
|
UC_ARM_REG_XPSR_G = 137
|
||||||
UC_ARM_REG_XPSR_NZCVQG = 138
|
UC_ARM_REG_XPSR_NZCVQG = 138
|
||||||
UC_ARM_REG_CP_REG = 139
|
UC_ARM_REG_CP_REG = 139
|
||||||
UC_ARM_REG_ENDING = 140
|
UC_ARM_REG_ESR = 140
|
||||||
|
UC_ARM_REG_ENDING = 141
|
||||||
|
|
||||||
# alias registers
|
# alias registers
|
||||||
UC_ARM_REG_R13 = 12
|
UC_ARM_REG_R13 = 12
|
||||||
|
|||||||
@@ -182,7 +182,8 @@ module UnicornEngine
|
|||||||
UC_ARM_REG_XPSR_G = 137
|
UC_ARM_REG_XPSR_G = 137
|
||||||
UC_ARM_REG_XPSR_NZCVQG = 138
|
UC_ARM_REG_XPSR_NZCVQG = 138
|
||||||
UC_ARM_REG_CP_REG = 139
|
UC_ARM_REG_CP_REG = 139
|
||||||
UC_ARM_REG_ENDING = 140
|
UC_ARM_REG_ESR = 140
|
||||||
|
UC_ARM_REG_ENDING = 141
|
||||||
|
|
||||||
# alias registers
|
# alias registers
|
||||||
UC_ARM_REG_R13 = 12
|
UC_ARM_REG_R13 = 12
|
||||||
|
|||||||
@@ -145,7 +145,8 @@ pub enum RegisterARM {
|
|||||||
XPSR_G = 137,
|
XPSR_G = 137,
|
||||||
XPSR_NZCVQG = 138,
|
XPSR_NZCVQG = 138,
|
||||||
CP_REG = 139,
|
CP_REG = 139,
|
||||||
ENDING = 140,
|
ESR = 140,
|
||||||
|
ENDING = 141,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RegisterARM {
|
impl RegisterARM {
|
||||||
|
|||||||
@@ -182,7 +182,8 @@ pub const armConst = enum(c_int) {
|
|||||||
ARM_REG_XPSR_G = 137,
|
ARM_REG_XPSR_G = 137,
|
||||||
ARM_REG_XPSR_NZCVQG = 138,
|
ARM_REG_XPSR_NZCVQG = 138,
|
||||||
ARM_REG_CP_REG = 139,
|
ARM_REG_CP_REG = 139,
|
||||||
ARM_REG_ENDING = 140,
|
ARM_REG_ESR = 140,
|
||||||
|
ARM_REG_ENDING = 141,
|
||||||
|
|
||||||
// alias registers
|
// alias registers
|
||||||
ARM_REG_R13 = 12,
|
ARM_REG_R13 = 12,
|
||||||
|
|||||||
@@ -212,6 +212,9 @@ typedef enum uc_arm_reg {
|
|||||||
UC_ARM_REG_XPSR_G,
|
UC_ARM_REG_XPSR_G,
|
||||||
UC_ARM_REG_XPSR_NZCVQG,
|
UC_ARM_REG_XPSR_NZCVQG,
|
||||||
UC_ARM_REG_CP_REG,
|
UC_ARM_REG_CP_REG,
|
||||||
|
// A pseudo-register for fetching the exception syndrome
|
||||||
|
// from the CPU state. This is not a real register.
|
||||||
|
UC_ARM_REG_ESR,
|
||||||
UC_ARM_REG_ENDING, // <-- mark the end of the list or registers
|
UC_ARM_REG_ENDING, // <-- mark the end of the list or registers
|
||||||
|
|
||||||
//> alias registers
|
//> alias registers
|
||||||
|
|||||||
@@ -352,6 +352,10 @@ uc_err reg_read(void *_env, int mode, unsigned int regid, void *value,
|
|||||||
CHECK_REG_TYPE(uc_arm_cp_reg);
|
CHECK_REG_TYPE(uc_arm_cp_reg);
|
||||||
ret = read_cp_reg(env, (uc_arm_cp_reg *)value);
|
ret = read_cp_reg(env, (uc_arm_cp_reg *)value);
|
||||||
break;
|
break;
|
||||||
|
case UC_ARM_REG_ESR:
|
||||||
|
CHECK_REG_TYPE(uint32_t);
|
||||||
|
*(uint32_t *)value = env->exception.syndrome;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -556,6 +560,10 @@ uc_err reg_write(void *_env, int mode, unsigned int regid, const void *value,
|
|||||||
ret = write_cp_reg(env, (uc_arm_cp_reg *)value);
|
ret = write_cp_reg(env, (uc_arm_cp_reg *)value);
|
||||||
arm_rebuild_hflags_arm(env);
|
arm_rebuild_hflags_arm(env);
|
||||||
break;
|
break;
|
||||||
|
case UC_ARM_REG_ESR:
|
||||||
|
CHECK_REG_TYPE(uint32_t);
|
||||||
|
env->exception.syndrome = *(uint32_t *)value;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -966,8 +966,8 @@ static bool test_arm_v7_lpae_hook_tlb(uc_engine *uc, uint64_t addr,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void test_arm_v7_lpae_hook_read(uc_engine *uc, uc_mem_type type,
|
static void test_arm_v7_lpae_hook_read(uc_engine *uc, uc_mem_type type,
|
||||||
uint64_t address, int size, uint64_t value,
|
uint64_t address, int size,
|
||||||
void *user_data)
|
uint64_t value, void *user_data)
|
||||||
{
|
{
|
||||||
TEST_CHECK(address == 0x100001000);
|
TEST_CHECK(address == 0x100001000);
|
||||||
}
|
}
|
||||||
@@ -981,10 +981,11 @@ static void test_arm_v7_lpae(void)
|
|||||||
OK(uc_open(UC_ARCH_ARM, UC_MODE_ARM, &uc));
|
OK(uc_open(UC_ARCH_ARM, UC_MODE_ARM, &uc));
|
||||||
OK(uc_ctl_set_cpu_model(uc, UC_CPU_ARM_CORTEX_A7));
|
OK(uc_ctl_set_cpu_model(uc, UC_CPU_ARM_CORTEX_A7));
|
||||||
|
|
||||||
|
|
||||||
OK(uc_ctl_tlb_mode(uc, UC_TLB_VIRTUAL));
|
OK(uc_ctl_tlb_mode(uc, UC_TLB_VIRTUAL));
|
||||||
OK(uc_hook_add(uc, &hook_tlb, UC_HOOK_TLB_FILL, test_arm_v7_lpae_hook_tlb, NULL, 1, 0));
|
OK(uc_hook_add(uc, &hook_tlb, UC_HOOK_TLB_FILL, test_arm_v7_lpae_hook_tlb,
|
||||||
OK(uc_hook_add(uc, &hook_read, UC_HOOK_MEM_READ, test_arm_v7_lpae_hook_read, NULL, 1, 0));
|
NULL, 1, 0));
|
||||||
|
OK(uc_hook_add(uc, &hook_read, UC_HOOK_MEM_READ, test_arm_v7_lpae_hook_read,
|
||||||
|
NULL, 1, 0));
|
||||||
|
|
||||||
reg = 0x1000;
|
reg = 0x1000;
|
||||||
OK(uc_reg_write(uc, UC_ARM_REG_R0, ®));
|
OK(uc_reg_write(uc, UC_ARM_REG_R0, ®));
|
||||||
@@ -997,6 +998,42 @@ static void test_arm_v7_lpae(void)
|
|||||||
OK(uc_close(uc));
|
OK(uc_close(uc));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_arm_svc_interrupt(uc_engine *uc, int intno, void *user_data)
|
||||||
|
{
|
||||||
|
uint32_t esr;
|
||||||
|
OK(uc_reg_read(uc, UC_ARM_REG_ESR, &esr));
|
||||||
|
switch (intno) {
|
||||||
|
// SVC
|
||||||
|
case 2:
|
||||||
|
TEST_CHECK((esr & 0xff) == 0x42);
|
||||||
|
break;
|
||||||
|
// HVC
|
||||||
|
case 3:
|
||||||
|
TEST_CHECK((esr & 0xff) == 0x33);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_arm_svc_hvc_syndrome(void)
|
||||||
|
{
|
||||||
|
uc_engine *uc;
|
||||||
|
uint8_t code[] = {
|
||||||
|
0x42, 0x00, 0x00, 0xef, // svc #0x42
|
||||||
|
0x73, 0x03, 0x40, 0xe1, // hvc #0x33
|
||||||
|
};
|
||||||
|
|
||||||
|
uc_common_setup(&uc, UC_ARCH_ARM, UC_MODE_ARM, (char *)code, sizeof(code),
|
||||||
|
UC_CPU_ARM_CORTEX_A15);
|
||||||
|
|
||||||
|
uc_hook hook;
|
||||||
|
OK(uc_hook_add(uc, &hook, UC_HOOK_INTR, test_arm_svc_interrupt, NULL, 1,
|
||||||
|
0));
|
||||||
|
|
||||||
|
OK(uc_emu_start(uc, code_start, code_start + 4, 0, 0));
|
||||||
|
|
||||||
|
OK(uc_close(uc));
|
||||||
|
}
|
||||||
|
|
||||||
TEST_LIST = {{"test_arm_nop", test_arm_nop},
|
TEST_LIST = {{"test_arm_nop", test_arm_nop},
|
||||||
{"test_arm_thumb_sub", test_arm_thumb_sub},
|
{"test_arm_thumb_sub", test_arm_thumb_sub},
|
||||||
{"test_armeb_sub", test_armeb_sub},
|
{"test_armeb_sub", test_armeb_sub},
|
||||||
@@ -1027,4 +1064,5 @@ TEST_LIST = {{"test_arm_nop", test_arm_nop},
|
|||||||
{"test_arm_thumb_tcg_opcode_cmn", test_arm_thumb_tcg_opcode_cmn},
|
{"test_arm_thumb_tcg_opcode_cmn", test_arm_thumb_tcg_opcode_cmn},
|
||||||
{"test_arm_cp15_c1_c0_2", test_arm_cp15_c1_c0_2},
|
{"test_arm_cp15_c1_c0_2", test_arm_cp15_c1_c0_2},
|
||||||
{"test_arm_v7_lpae", test_arm_v7_lpae},
|
{"test_arm_v7_lpae", test_arm_v7_lpae},
|
||||||
|
{"test_arm_svc_hvc_syndrome", test_arm_svc_hvc_syndrome},
|
||||||
{NULL, NULL}};
|
{NULL, NULL}};
|
||||||
|
|||||||
Reference in New Issue
Block a user