diff options
-rw-r--r-- | target-arm/cpu.h | 12 | ||||
-rw-r--r-- | target-arm/op_helper.c | 2 | ||||
-rw-r--r-- | target-arm/translate.c | 13 |
3 files changed, 18 insertions, 9 deletions
diff --git a/target-arm/cpu.h b/target-arm/cpu.h index 79205ba335..8380c136e2 100644 --- a/target-arm/cpu.h +++ b/target-arm/cpu.h @@ -411,7 +411,13 @@ int arm_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int rw, #define CPSR_E (1U << 9) #define CPSR_IT_2_7 (0xfc00U) #define CPSR_GE (0xfU << 16) -#define CPSR_RESERVED (0xfU << 20) +#define CPSR_IL (1U << 20) +/* Note that the RESERVED bits include bit 21, which is PSTATE_SS in + * an AArch64 SPSR but RES0 in AArch32 SPSR and CPSR. In QEMU we use + * env->uncached_cpsr bit 21 to store PSTATE.SS when executing in AArch32, + * where it is live state but not accessible to the AArch32 code. + */ +#define CPSR_RESERVED (0x7U << 21) #define CPSR_J (1U << 24) #define CPSR_IT_0_1 (3U << 25) #define CPSR_Q (1U << 27) @@ -428,7 +434,9 @@ int arm_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int rw, /* Bits writable in user mode. */ #define CPSR_USER (CPSR_NZCV | CPSR_Q | CPSR_GE) /* Execution state bits. MRS read as zero, MSR writes ignored. */ -#define CPSR_EXEC (CPSR_T | CPSR_IT | CPSR_J) +#define CPSR_EXEC (CPSR_T | CPSR_IT | CPSR_J | CPSR_IL) +/* Mask of bits which may be set by exception return copying them from SPSR */ +#define CPSR_ERET_MASK (~CPSR_RESERVED) #define TTBCR_N (7U << 0) /* TTBCR.EAE==0 */ #define TTBCR_T0SZ (7U << 0) /* TTBCR.EAE==1 */ diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c index 25ad902e04..180a4a096b 100644 --- a/target-arm/op_helper.c +++ b/target-arm/op_helper.c @@ -258,7 +258,7 @@ void HELPER(exception_with_syndrome)(CPUARMState *env, uint32_t excp, uint32_t HELPER(cpsr_read)(CPUARMState *env) { - return cpsr_read(env) & ~CPSR_EXEC; + return cpsr_read(env) & ~(CPSR_EXEC | CPSR_RESERVED); } void HELPER(cpsr_write)(CPUARMState *env, uint32_t val, uint32_t mask) diff --git a/target-arm/translate.c b/target-arm/translate.c index 40121858d6..4cde3096d4 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -3908,9 +3908,10 @@ static uint32_t msr_mask(CPUARMState *env, DisasContext *s, int flags, int spsr) mask &= ~(CPSR_E | CPSR_GE); if (!arm_feature(env, ARM_FEATURE_THUMB2)) mask &= ~CPSR_IT; - /* Mask out execution state bits. */ - if (!spsr) - mask &= ~CPSR_EXEC; + /* Mask out execution state and reserved bits. */ + if (!spsr) { + mask &= ~(CPSR_EXEC | CPSR_RESERVED); + } /* Mask out privileged bits. */ if (IS_USER(s)) mask &= CPSR_USER; @@ -3954,7 +3955,7 @@ static void gen_exception_return(DisasContext *s, TCGv_i32 pc) TCGv_i32 tmp; store_reg(s, 15, pc); tmp = load_cpu_field(spsr); - gen_set_cpsr(tmp, 0xffffffff); + gen_set_cpsr(tmp, CPSR_ERET_MASK); tcg_temp_free_i32(tmp); s->is_jmp = DISAS_UPDATE; } @@ -3962,7 +3963,7 @@ static void gen_exception_return(DisasContext *s, TCGv_i32 pc) /* Generate a v6 exception return. Marks both values as dead. */ static void gen_rfe(DisasContext *s, TCGv_i32 pc, TCGv_i32 cpsr) { - gen_set_cpsr(cpsr, 0xffffffff); + gen_set_cpsr(cpsr, CPSR_ERET_MASK); tcg_temp_free_i32(cpsr); store_reg(s, 15, pc); s->is_jmp = DISAS_UPDATE; @@ -8836,7 +8837,7 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s) if ((insn & (1 << 22)) && !user) { /* Restore CPSR from SPSR. */ tmp = load_cpu_field(spsr); - gen_set_cpsr(tmp, 0xffffffff); + gen_set_cpsr(tmp, CPSR_ERET_MASK); tcg_temp_free_i32(tmp); s->is_jmp = DISAS_UPDATE; } |