diff --git a/include/unicorn/arm.h b/include/unicorn/arm.h index 783e418f..1293be0d 100644 --- a/include/unicorn/arm.h +++ b/include/unicorn/arm.h @@ -24,6 +24,9 @@ typedef enum uc_arm_reg { UC_ARM_REG_FPSCR_NZCV, UC_ARM_REG_FPSID, UC_ARM_REG_ITSTATE, + UC_ARM_REG_C1_C0_2, + UC_ARM_REG_C13_C0_2, + UC_ARM_REG_C13_C0_3, UC_ARM_REG_LR, UC_ARM_REG_PC, UC_ARM_REG_SP, diff --git a/qemu/target-arm/unicorn_arm.c b/qemu/target-arm/unicorn_arm.c index 69f7363a..7bb985e2 100644 --- a/qemu/target-arm/unicorn_arm.c +++ b/qemu/target-arm/unicorn_arm.c @@ -77,6 +77,15 @@ int arm_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int coun case UC_ARM_REG_R15: *(int32_t *)value = ARM_CPU(uc, mycpu)->env.regs[15]; break; + case UC_ARM_REG_C1_C0_2: + *(int32_t *)value = ARM_CPU(uc, mycpu)->env.cp15.c1_coproc; + break; + case UC_ARM_REG_C13_C0_3: + *(int32_t *)value = ARM_CPU(uc, mycpu)->env.cp15.tpidrro_el0; + break; + case UC_ARM_REG_FPEXC: + *(int32_t *)value = ARM_CPU(uc, mycpu)->env.vfp.xregs[ARM_VFP_FPEXC]; + break; } } } @@ -119,6 +128,16 @@ int arm_reg_write(struct uc_struct *uc, unsigned int *regs, void* const* vals, i uc->quit_request = true; uc_emu_stop(uc); + break; + case UC_ARM_REG_C1_C0_2: + ARM_CPU(uc, mycpu)->env.cp15.c1_coproc = *(int32_t *)value; + break; + + case UC_ARM_REG_C13_C0_3: + ARM_CPU(uc, mycpu)->env.cp15.tpidrro_el0 = *(int32_t *)value; + break; + case UC_ARM_REG_FPEXC: + ARM_CPU(uc, mycpu)->env.vfp.xregs[ARM_VFP_FPEXC] = *(int32_t *)value; break; } } diff --git a/tests/regress/arm_enable_vfp.c b/tests/regress/arm_enable_vfp.c new file mode 100644 index 00000000..aebcd983 --- /dev/null +++ b/tests/regress/arm_enable_vfp.c @@ -0,0 +1,65 @@ +#include +#include +#include +#include + +#define ADDRESS 0x1000 +#define ARM_VMOV "\xC0\xEF\x10\x00" // VMOV.I32 D16, #0 ; Vector Move + +int main() +{ + uc_engine *uc; + uc_err err; + + err = uc_open(UC_ARCH_ARM, UC_MODE_ARM, &uc); + if (err) { + printf("uc_open %d\n", err); + return 1; + } + + uint64_t tmp_val; + + err = uc_reg_read(uc, UC_ARM_REG_C1_C0_2, &tmp_val); + if (err) { + printf("uc_open %d\n", err); + return 1; + } + + tmp_val = tmp_val | (0xf << 20); + err = uc_reg_write(uc, UC_ARM_REG_C1_C0_2, &tmp_val); + if (err) { + printf("uc_open %d\n", err); + return 1; + } + + size_t enable_vfp = 0x40000000; + err = uc_reg_write(uc, UC_ARM_REG_FPEXC, &enable_vfp); + if (err) { + printf("uc_open %d\n", err); + return 1; + } + + err = uc_mem_map(uc, ADDRESS, 4 * 1024, UC_PROT_ALL); + if (err) { + printf("uc_mem_map %d\n", err); + return 1; + } + + err = uc_mem_write(uc, ADDRESS, ARM_VMOV, sizeof(ARM_VMOV) - 1); + if (err) { + printf("uc_mem_map %s\n", uc_strerror(err)); + return 1; + } + + err = uc_emu_start(uc, ADDRESS, 0, 0, 1); + if (err) { + printf("uc_emu_start: %s\n", uc_strerror(err)); + return 1; + } + + printf("Success\n"); + + uc_close(uc); + + return 0; +}