aboutsummaryrefslogtreecommitdiff
path: root/target/arm/translate-a64.c
diff options
context:
space:
mode:
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;
}