Write CPSR as it is initiated from instructions to allow regs switch

This commit is contained in:
lazymio 2021-11-24 17:10:51 +01:00
parent 78e0ddbc4d
commit 221cde18df
No known key found for this signature in database
GPG Key ID: DFF27E34A47CB873
2 changed files with 46 additions and 3 deletions

View File

@ -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;

View File

@ -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}};