Fix #1520
This commit is contained in:
@ -1264,6 +1264,7 @@ typedef enum CPSRWriteType {
|
|||||||
CPSRWriteExceptionReturn = 1, /* from guest exception return insn */
|
CPSRWriteExceptionReturn = 1, /* from guest exception return insn */
|
||||||
CPSRWriteRaw = 2, /* trust values, do not switch reg banks */
|
CPSRWriteRaw = 2, /* trust values, do not switch reg banks */
|
||||||
CPSRWriteByGDBStub = 3, /* from the GDB stub */
|
CPSRWriteByGDBStub = 3, /* from the GDB stub */
|
||||||
|
CPSRWriteByUnicorn = 4 /* from uc_reg_write */
|
||||||
} CPSRWriteType;
|
} CPSRWriteType;
|
||||||
|
|
||||||
/* Set the CPSR. Note that some bits of mask must be all-set or all-clear.*/
|
/* Set the CPSR. Note that some bits of mask must be all-set or all-clear.*/
|
||||||
|
@ -7983,9 +7983,12 @@ void cpsr_write(CPUARMState *env, uint32_t val, uint32_t mask,
|
|||||||
* to switch mode. (Those are caught by translate.c for writes
|
* to switch mode. (Those are caught by translate.c for writes
|
||||||
* triggered by guest instructions.)
|
* triggered by guest instructions.)
|
||||||
*/
|
*/
|
||||||
// mask &= ~CPSR_M;
|
mask &= ~CPSR_M;
|
||||||
// Unicorn: No, it can also be uc_reg_write
|
|
||||||
|
// Unicorn: No, it can also be uc_reg_write, let user switch registers banks.
|
||||||
|
if (write_type == CPSRWriteByUnicorn) {
|
||||||
switch_mode(env, val & CPSR_M);
|
switch_mode(env, val & CPSR_M);
|
||||||
|
}
|
||||||
} else if (bad_mode_switch(env, val & CPSR_M, write_type)) {
|
} else if (bad_mode_switch(env, val & CPSR_M, write_type)) {
|
||||||
/* Attempt to switch to an invalid mode: this is UNPREDICTABLE in
|
/* Attempt to switch to an invalid mode: this is UNPREDICTABLE in
|
||||||
* v7, and has defined behaviour in v8:
|
* v7, and has defined behaviour in v8:
|
||||||
|
@ -251,17 +251,17 @@ static void reg_write(CPUARMState *env, unsigned int regid, const void *value)
|
|||||||
case UC_ARM_REG_APSR:
|
case UC_ARM_REG_APSR:
|
||||||
if (!arm_feature(env, ARM_FEATURE_M)) {
|
if (!arm_feature(env, ARM_FEATURE_M)) {
|
||||||
cpsr_write(env, *(uint32_t *)value,
|
cpsr_write(env, *(uint32_t *)value,
|
||||||
(CPSR_NZCV | CPSR_Q | CPSR_GE), CPSRWriteByInstr);
|
(CPSR_NZCV | CPSR_Q | CPSR_GE), CPSRWriteByUnicorn);
|
||||||
} else {
|
} else {
|
||||||
// Same with UC_ARM_REG_APSR_NZCVQ
|
// Same with UC_ARM_REG_APSR_NZCVQ
|
||||||
v7m_msr_xpsr(env, 0b1000, 0, *(uint32_t *)value);
|
v7m_msr_xpsr(env, 0b1000, 0, *(uint32_t *)value);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case UC_ARM_REG_APSR_NZCV:
|
case UC_ARM_REG_APSR_NZCV:
|
||||||
cpsr_write(env, *(uint32_t *)value, CPSR_NZCV, CPSRWriteByInstr);
|
cpsr_write(env, *(uint32_t *)value, CPSR_NZCV, CPSRWriteByUnicorn);
|
||||||
break;
|
break;
|
||||||
case UC_ARM_REG_CPSR:
|
case UC_ARM_REG_CPSR:
|
||||||
cpsr_write(env, *(uint32_t *)value, ~0, CPSRWriteByInstr);
|
cpsr_write(env, *(uint32_t *)value, ~0, CPSRWriteByUnicorn);
|
||||||
break;
|
break;
|
||||||
case UC_ARM_REG_SPSR:
|
case UC_ARM_REG_SPSR:
|
||||||
env->spsr = *(uint32_t *)value;
|
env->spsr = *(uint32_t *)value;
|
||||||
|
Reference in New Issue
Block a user