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.c39
1 files changed, 36 insertions, 3 deletions
diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index 8752e7e16c..08ac6591b6 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -1080,9 +1080,11 @@ static void handle_hint(DisasContext *s, uint32_t insn,
switch (selector) {
case 0: /* NOP */
return;
+ case 3: /* WFI */
+ s->is_jmp = DISAS_WFI;
+ return;
case 1: /* YIELD */
case 2: /* WFE */
- case 3: /* WFI */
case 4: /* SEV */
case 5: /* SEVL */
/* we treat all as NOP at least for now */
@@ -1126,7 +1128,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)
@@ -1231,6 +1256,13 @@ static void handle_sys(DisasContext *s, uint32_t insn, bool isread,
gen_set_nzcv(tcg_rt);
}
return;
+ case ARM_CP_CURRENTEL:
+ /* Reads as current EL value from pstate, which is
+ * guaranteed to be constant by the tb flags.
+ */
+ tcg_rt = cpu_reg(s, rt);
+ tcg_gen_movi_i64(tcg_rt, s->current_pl << 2);
+ return;
default:
break;
}
@@ -9006,7 +9038,7 @@ void gen_intermediate_code_internal_a64(ARMCPU *cpu,
dc->condexec_mask = 0;
dc->condexec_cond = 0;
#if !defined(CONFIG_USER_ONLY)
- dc->user = 0;
+ dc->user = (ARM_TBFLAG_AA64_EL(tb->flags) == 0);
#endif
dc->vfp_enabled = 0;
dc->vec_len = 0;
@@ -9117,6 +9149,7 @@ void gen_intermediate_code_internal_a64(ARMCPU *cpu,
/* This is a special case because we don't want to just halt the CPU
* if trying to debug across a WFI.
*/
+ gen_a64_set_pc_im(dc->pc);
gen_helper_wfi(cpu_env);
break;
}