aboutsummaryrefslogtreecommitdiff
path: root/target/arm/translate-a64.c
diff options
context:
space:
mode:
authorRichard Henderson <richard.henderson@linaro.org>2019-03-01 12:04:55 -0800
committerPeter Maydell <peter.maydell@linaro.org>2019-03-05 15:55:08 +0000
commitff730e9666a716b669ac4a8ca7c521177d1d2b15 (patch)
tree2e77ada8f7f17180307dda34c33207d087e79dd7 /target/arm/translate-a64.c
parentcb570bd318beb2ecce83cabf8016dacceb824dce (diff)
target/arm: Split helper_msr_i_pstate into 3
The EL0+UMA check is unique to DAIF. While SPSel had avoided the check by nature of already checking EL >= 1, the other post v8.0 extensions to MSR (imm) allow EL0 and do not require UMA. Avoid the unconditional write to pc and use raise_exception_ra to unwind. Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20190301200501.16533-5-richard.henderson@linaro.org Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'target/arm/translate-a64.c')
-rw-r--r--target/arm/translate-a64.c35
1 files changed, 22 insertions, 13 deletions
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index 4aa5a307e4..1e49d33365 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -1661,29 +1661,38 @@ 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)
{
+ TCGv_i32 t1;
int op = op1 << 3 | op2;
+
+ /* End the TB by default, chaining is ok. */
+ s->base.is_jmp = DISAS_TOO_MANY;
+
switch (op) {
case 0x05: /* SPSel */
if (s->current_el == 0) {
- unallocated_encoding(s);
- return;
+ goto do_unallocated;
}
- /* fall through */
+ t1 = tcg_const_i32(crm & PSTATE_SP);
+ gen_helper_msr_i_spsel(cpu_env, t1);
+ tcg_temp_free_i32(t1);
+ break;
+
case 0x1e: /* DAIFSet */
+ t1 = tcg_const_i32(crm);
+ gen_helper_msr_i_daifset(cpu_env, t1);
+ tcg_temp_free_i32(t1);
+ break;
+
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);
+ t1 = tcg_const_i32(crm);
+ gen_helper_msr_i_daifclear(cpu_env, t1);
+ tcg_temp_free_i32(t1);
/* For DAIFClear, exit the cpu loop to re-evaluate pending IRQs. */
- gen_a64_set_pc_im(s->pc);
- s->base.is_jmp = (op == 0x1f ? DISAS_EXIT : DISAS_JUMP);
+ s->base.is_jmp = DISAS_UPDATE;
break;
- }
+
default:
+ do_unallocated:
unallocated_encoding(s);
return;
}