On 15.02.2016 20:22, Peter Maydell wrote: > 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 <peter.mayd...@linaro.org>
Reviewed-by: Sergey Fedorov <serge.f...@gmail.com> > --- > 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 c98e9ce..ea13202 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 538887c..e3ddd5a 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 e69145d..413f7de 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; > }