From 235ea1f5c89abf30e452539b973b0dbe43d3fe2b Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 23 Feb 2016 15:36:43 +0000 Subject: target-arm: Give CPSR setting on 32-bit exception return its own helper The rules for setting the CPSR on a 32-bit exception return are subtly different from those for setting the CPSR via an instruction like MSR or CPS. (In particular, in Hyp mode changing the mode bits is not valid via MSR or CPS.) Split the exception-return case into its own helper for setting CPSR, so we can eventually handle them differently in the helper function. Signed-off-by: Peter Maydell Reviewed-by: Sergey Fedorov Message-id: 1455556977-3644-2-git-send-email-peter.maydell@linaro.org --- target-arm/helper.h | 1 + target-arm/op_helper.c | 6 ++++++ target-arm/translate.c | 6 +++--- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/target-arm/helper.h b/target-arm/helper.h index c98e9cea3d..ea13202b17 100644 --- a/target-arm/helper.h +++ b/target-arm/helper.h @@ -57,6 +57,7 @@ DEF_HELPER_2(pre_smc, void, env, i32) DEF_HELPER_1(check_breakpoints, void, env) DEF_HELPER_3(cpsr_write, void, env, i32, i32) +DEF_HELPER_2(cpsr_write_eret, void, env, i32) DEF_HELPER_1(cpsr_read, i32, env) DEF_HELPER_3(v7m_msr, void, env, i32, i32) diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c index 538887ce0c..e3ddd5ad34 100644 --- a/target-arm/op_helper.c +++ b/target-arm/op_helper.c @@ -425,6 +425,12 @@ void HELPER(cpsr_write)(CPUARMState *env, uint32_t val, uint32_t mask) cpsr_write(env, val, mask); } +/* Write the CPSR for a 32-bit exception return */ +void HELPER(cpsr_write_eret)(CPUARMState *env, uint32_t val) +{ + cpsr_write(env, val, CPSR_ERET_MASK); +} + /* Access to user mode registers from privileged modes. */ uint32_t HELPER(get_user_reg)(CPUARMState *env, uint32_t regno) { diff --git a/target-arm/translate.c b/target-arm/translate.c index e69145d401..413f7de686 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -4094,7 +4094,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, CPSR_ERET_MASK); + gen_helper_cpsr_write_eret(cpu_env, tmp); tcg_temp_free_i32(tmp); s->is_jmp = DISAS_JUMP; } @@ -4102,7 +4102,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, CPSR_ERET_MASK); + gen_helper_cpsr_write_eret(cpu_env, cpsr); tcg_temp_free_i32(cpsr); store_reg(s, 15, pc); s->is_jmp = DISAS_JUMP; @@ -9094,7 +9094,7 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn) if (exc_return) { /* Restore CPSR from SPSR. */ tmp = load_cpu_field(spsr); - gen_set_cpsr(tmp, CPSR_ERET_MASK); + gen_helper_cpsr_write_eret(cpu_env, tmp); tcg_temp_free_i32(tmp); s->is_jmp = DISAS_JUMP; } -- cgit v1.2.3