diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2014-02-26 17:20:06 +0000 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2014-02-26 17:20:06 +0000 |
commit | 9cfa0b4e4c3076683b6c528a1a3b43d5a202a497 (patch) | |
tree | ee64227b9a748713fab27c7fc75d2812d4fdad5d /target-arm/op_helper.c | |
parent | 4cc35614a056839df8b0675cd16f55e758cd570d (diff) |
target-arm: A64: Implement MSR (immediate) instructions
Implement the MSR (immediate) instructions, which can update the
PSTATE SP and DAIF fields.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Diffstat (limited to 'target-arm/op_helper.c')
-rw-r--r-- | target-arm/op_helper.c | 25 |
1 files changed, 25 insertions, 0 deletions
diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c index eb0fccd98f..7d06d2f9a5 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. */ |