On Sun, Feb 16, 2014 at 2:07 AM, Peter Maydell <peter.mayd...@linaro.org> wrote: > Implement the MSR (immediate) instructions, which can update the > PSTATE SP and DAIF fields. > > Signed-off-by: Peter Maydell <peter.mayd...@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwa...@xilinx.com> > --- > target-arm/helper.h | 2 ++ > target-arm/op_helper.c | 25 +++++++++++++++++++++++++ > target-arm/translate-a64.c | 25 ++++++++++++++++++++++++- > 3 files changed, 51 insertions(+), 1 deletion(-) > > diff --git a/target-arm/helper.h b/target-arm/helper.h > index 19bd620..4a063c1 100644 > --- a/target-arm/helper.h > +++ b/target-arm/helper.h > @@ -63,6 +63,8 @@ DEF_HELPER_2(get_cp_reg, i32, env, ptr) > DEF_HELPER_3(set_cp_reg64, void, env, ptr, i64) > DEF_HELPER_2(get_cp_reg64, i64, env, ptr) > > +DEF_HELPER_3(msr_i_pstate, void, env, i32, i32) > + > DEF_HELPER_2(get_r13_banked, i32, env, i32) > DEF_HELPER_3(set_r13_banked, void, env, i32, i32) > > diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c > index eb0fccd..7d06d2f 100644 > --- a/target-arm/op_helper.c > +++ b/target-arm/op_helper.c > @@ -319,6 +319,31 @@ uint64_t HELPER(get_cp_reg64)(CPUARMState *env, void > *rip) > return ri->readfn(env, ri); > } > > +void HELPER(msr_i_pstate)(CPUARMState *env, uint32_t op, uint32_t imm) > +{ > + /* MSR_i to update PSTATE. This is OK from EL0 only if UMA is set. > + * Note that SPSel is never OK from EL0; we rely on handle_msr_i() > + * to catch that case at translate time. > + */ > + if (arm_current_pl(env) == 0 && !(env->cp15.c1_sys & SCTLR_UMA)) { > + raise_exception(env, EXCP_UDEF); > + } > + > + switch (op) { > + case 0x05: /* SPSel */ > + env->pstate = deposit32(env->pstate, 0, 1, imm); > + break; > + case 0x1e: /* DAIFSet */ > + env->daif |= (imm << 6) & PSTATE_DAIF; > + break; > + case 0x1f: /* DAIFClear */ > + env->daif &= ~((imm << 6) & PSTATE_DAIF); > + break; > + default: > + g_assert_not_reached(); > + } > +} > + > /* ??? Flag setting arithmetic is awkward because we need to do comparisons. > The only way to do that in TCG is a conditional branch, which clobbers > all our temporaries. For now implement these as helper functions. */ > diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c > index 948470f..1054e38 100644 > --- a/target-arm/translate-a64.c > +++ b/target-arm/translate-a64.c > @@ -1113,7 +1113,30 @@ static void handle_sync(DisasContext *s, uint32_t insn, > static void handle_msr_i(DisasContext *s, uint32_t insn, > unsigned int op1, unsigned int op2, unsigned int > crm) > { > - unsupported_encoding(s, insn); > + int op = op1 << 3 | op2; > + switch (op) { > + case 0x05: /* SPSel */ > + if (s->current_pl == 0) { > + unallocated_encoding(s); > + return; > + } > + /* fall through */ > + case 0x1e: /* DAIFSet */ > + case 0x1f: /* DAIFClear */ > + { > + TCGv_i32 tcg_imm = tcg_const_i32(crm); > + TCGv_i32 tcg_op = tcg_const_i32(op); > + gen_a64_set_pc_im(s->pc - 4); > + gen_helper_msr_i_pstate(cpu_env, tcg_op, tcg_imm); > + tcg_temp_free_i32(tcg_imm); > + tcg_temp_free_i32(tcg_op); > + s->is_jmp = DISAS_UPDATE; > + break; > + } > + default: > + unallocated_encoding(s); > + return; > + } > } > > static void gen_get_nzcv(TCGv_i64 tcg_rt) > -- > 1.8.5 > >