From 221cde18df830c65f832b6d1429192417d8d1774 Mon Sep 17 00:00:00 2001 From: lazymio Date: Wed, 24 Nov 2021 17:10:51 +0100 Subject: [PATCH] Write CPSR as it is initiated from instructions to allow regs switch --- qemu/target/arm/unicorn_arm.c | 6 ++--- tests/unit/test_arm.c | 43 +++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 3 deletions(-) diff --git a/qemu/target/arm/unicorn_arm.c b/qemu/target/arm/unicorn_arm.c index 17c71431..95bd93b5 100644 --- a/qemu/target/arm/unicorn_arm.c +++ b/qemu/target/arm/unicorn_arm.c @@ -251,17 +251,17 @@ static void reg_write(CPUARMState *env, unsigned int regid, const void *value) case UC_ARM_REG_APSR: if (!arm_feature(env, ARM_FEATURE_M)) { cpsr_write(env, *(uint32_t *)value, - (CPSR_NZCV | CPSR_Q | CPSR_GE), CPSRWriteRaw); + (CPSR_NZCV | CPSR_Q | CPSR_GE), CPSRWriteByInstr); } else { // Same with UC_ARM_REG_APSR_NZCVQ v7m_msr_xpsr(env, 0b1000, 0, *(uint32_t *)value); } break; case UC_ARM_REG_APSR_NZCV: - cpsr_write(env, *(uint32_t *)value, CPSR_NZCV, CPSRWriteRaw); + cpsr_write(env, *(uint32_t *)value, CPSR_NZCV, CPSRWriteByInstr); break; case UC_ARM_REG_CPSR: - cpsr_write(env, *(uint32_t *)value, ~0, CPSRWriteRaw); + cpsr_write(env, *(uint32_t *)value, ~0, CPSRWriteByInstr); break; case UC_ARM_REG_SPSR: env->spsr = *(uint32_t *)value; diff --git a/tests/unit/test_arm.c b/tests/unit/test_arm.c index 4bfd3127..b44d5372 100644 --- a/tests/unit/test_arm.c +++ b/tests/unit/test_arm.c @@ -266,6 +266,48 @@ static void test_arm_m_exc_return() OK(uc_close(uc)); } +// For details, see https://github.com/unicorn-engine/unicorn/issues/1494. +static void test_arm_und32_to_svc32() +{ + uc_engine *uc; + // # MVN r0, #0 + // # MOVS pc, lr + // # MVN r0, #0 + // # MVN r0, #0 + char code[] = + "\x00\x00\xe0\xe3\x0e\xf0\xb0\xe1\x00\x00\xe0\xe3\x00\x00\xe0\xe3"; + int r_cpsr, r_sp, r_spsr, r_lr; + + OK(uc_open(UC_ARCH_ARM, UC_MODE_ARM, &uc)); + OK(uc_ctl_set_cpu_model(uc, UC_CPU_ARM_CORTEX_A9)); + + OK(uc_mem_map(uc, code_start, code_len, UC_PROT_ALL)); + OK(uc_mem_write(uc, code_start, code, sizeof(code) - 1)); + + // https://www.keil.com/pack/doc/CMSIS/Core_A/html/group__CMSIS__CPSR__M.html + r_cpsr = 0x40000093; // SVC32 + OK(uc_reg_write(uc, UC_ARM_REG_CPSR, &r_cpsr)); + r_sp = 0x12345678; + OK(uc_reg_write(uc, UC_ARM_REG_SP, &r_sp)); + + r_cpsr = 0x4000009b; // UND32 + OK(uc_reg_write(uc, UC_ARM_REG_CPSR, &r_cpsr)); + r_spsr = 0x40000093; // Save previous CPSR + OK(uc_reg_write(uc, UC_ARM_REG_SPSR, &r_spsr)); + r_sp = 0xDEAD0000; + OK(uc_reg_write(uc, UC_ARM_REG_SP, &r_sp)); + r_lr = code_start + 8; + OK(uc_reg_write(uc, UC_ARM_REG_LR, &r_lr)); + + OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 3)); + + OK(uc_reg_read(uc, UC_ARM_REG_SP, &r_sp)); + + TEST_CHECK(r_sp == 0x12345678); + + OK(uc_close(uc)); +} + TEST_LIST = {{"test_arm_nop", test_arm_nop}, {"test_arm_thumb_sub", test_arm_thumb_sub}, {"test_armeb_sub", test_armeb_sub}, @@ -274,4 +316,5 @@ TEST_LIST = {{"test_arm_nop", test_arm_nop}, {"test_arm_m_thumb_mrs", test_arm_m_thumb_mrs}, {"test_arm_m_control", test_arm_m_control}, {"test_arm_m_exc_return", test_arm_m_exc_return}, + {"test_arm_und32_to_svc32", test_arm_und32_to_svc32}, {NULL, NULL}}; \ No newline at end of file