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.c48
1 files changed, 31 insertions, 17 deletions
diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index 0b192a1f5b..ffa6cb8e56 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -197,12 +197,15 @@ static void gen_exception_internal(int excp)
tcg_temp_free_i32(tcg_excp);
}
-static void gen_exception(int excp, uint32_t syndrome)
+static void gen_exception(int excp, uint32_t syndrome, uint32_t target_el)
{
TCGv_i32 tcg_excp = tcg_const_i32(excp);
TCGv_i32 tcg_syn = tcg_const_i32(syndrome);
+ TCGv_i32 tcg_el = tcg_const_i32(target_el);
- gen_helper_exception_with_syndrome(cpu_env, tcg_excp, tcg_syn);
+ gen_helper_exception_with_syndrome(cpu_env, tcg_excp,
+ tcg_syn, tcg_el);
+ tcg_temp_free_i32(tcg_el);
tcg_temp_free_i32(tcg_syn);
tcg_temp_free_i32(tcg_excp);
}
@@ -215,10 +218,10 @@ static void gen_exception_internal_insn(DisasContext *s, int offset, int excp)
}
static void gen_exception_insn(DisasContext *s, int offset, int excp,
- uint32_t syndrome)
+ uint32_t syndrome, uint32_t target_el)
{
gen_a64_set_pc_im(s->pc - offset);
- gen_exception(excp, syndrome);
+ gen_exception(excp, syndrome, target_el);
s->is_jmp = DISAS_EXC;
}
@@ -245,7 +248,8 @@ static void gen_step_complete_exception(DisasContext *s)
* of the exception, and our syndrome information is always correct.
*/
gen_ss_advance(s);
- gen_exception(EXCP_UDEF, syn_swstep(s->ss_same_el, 1, s->is_ldex));
+ gen_exception(EXCP_UDEF, syn_swstep(s->ss_same_el, 1, s->is_ldex),
+ default_exception_el(s));
s->is_jmp = DISAS_EXC;
}
@@ -292,7 +296,8 @@ static inline void gen_goto_tb(DisasContext *s, int n, uint64_t dest)
static void unallocated_encoding(DisasContext *s)
{
/* Unallocated and reserved encodings are uncategorized */
- gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized());
+ gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized(),
+ default_exception_el(s));
}
#define unsupported_encoding(s, insn) \
@@ -407,7 +412,7 @@ static TCGv_i64 read_cpu_reg_sp(DisasContext *s, int reg, int sf)
static inline void assert_fp_access_checked(DisasContext *s)
{
#ifdef CONFIG_DEBUG_TCG
- if (unlikely(!s->fp_access_checked || !s->cpacr_fpen)) {
+ if (unlikely(!s->fp_access_checked || s->fp_excp_el)) {
fprintf(stderr, "target-arm: FP access check missing for "
"instruction 0x%08x\n", s->insn);
abort();
@@ -967,11 +972,12 @@ static inline bool fp_access_check(DisasContext *s)
assert(!s->fp_access_checked);
s->fp_access_checked = true;
- if (s->cpacr_fpen) {
+ if (!s->fp_excp_el) {
return true;
}
- gen_exception_insn(s, 4, EXCP_UDEF, syn_fp_access_trap(1, 0xe, false));
+ gen_exception_insn(s, 4, EXCP_UDEF, syn_fp_access_trap(1, 0xe, false),
+ s->fp_excp_el);
return false;
}
@@ -1498,7 +1504,8 @@ static void disas_exc(DisasContext *s, uint32_t insn)
switch (op2_ll) {
case 1:
gen_ss_advance(s);
- gen_exception_insn(s, 0, EXCP_SWI, syn_aa64_svc(imm16));
+ gen_exception_insn(s, 0, EXCP_SWI, syn_aa64_svc(imm16),
+ default_exception_el(s));
break;
case 2:
if (s->current_el == 0) {
@@ -1511,7 +1518,7 @@ static void disas_exc(DisasContext *s, uint32_t insn)
gen_a64_set_pc_im(s->pc - 4);
gen_helper_pre_hvc(cpu_env);
gen_ss_advance(s);
- gen_exception_insn(s, 0, EXCP_HVC, syn_aa64_hvc(imm16));
+ gen_exception_insn(s, 0, EXCP_HVC, syn_aa64_hvc(imm16), 2);
break;
case 3:
if (s->current_el == 0) {
@@ -1523,7 +1530,7 @@ static void disas_exc(DisasContext *s, uint32_t insn)
gen_helper_pre_smc(cpu_env, tmp);
tcg_temp_free_i32(tmp);
gen_ss_advance(s);
- gen_exception_insn(s, 0, EXCP_SMC, syn_aa64_smc(imm16));
+ gen_exception_insn(s, 0, EXCP_SMC, syn_aa64_smc(imm16), 3);
break;
default:
unallocated_encoding(s);
@@ -1536,7 +1543,8 @@ static void disas_exc(DisasContext *s, uint32_t insn)
break;
}
/* BRK */
- gen_exception_insn(s, 4, EXCP_BKPT, syn_aa64_bkpt(imm16));
+ gen_exception_insn(s, 4, EXCP_BKPT, syn_aa64_bkpt(imm16),
+ default_exception_el(s));
break;
case 2:
if (op2_ll != 0) {
@@ -10936,6 +10944,7 @@ void gen_intermediate_code_internal_a64(ARMCPU *cpu,
dc->condjmp = 0;
dc->aarch64 = 1;
+ dc->el3_is_aa64 = arm_el_is_aa64(env, 3);
dc->thumb = 0;
dc->bswap_code = 0;
dc->condexec_mask = 0;
@@ -10945,7 +10954,7 @@ void gen_intermediate_code_internal_a64(ARMCPU *cpu,
#if !defined(CONFIG_USER_ONLY)
dc->user = (dc->current_el == 0);
#endif
- dc->cpacr_fpen = ARM_TBFLAG_AA64_FPEN(tb->flags);
+ dc->fp_excp_el = ARM_TBFLAG_FPEXC_EL(tb->flags);
dc->vec_len = 0;
dc->vec_stride = 0;
dc->cp_regs = cpu->cp_regs;
@@ -10966,8 +10975,8 @@ void gen_intermediate_code_internal_a64(ARMCPU *cpu,
* emit code to generate a software step exception
* end the TB
*/
- dc->ss_active = ARM_TBFLAG_AA64_SS_ACTIVE(tb->flags);
- dc->pstate_ss = ARM_TBFLAG_AA64_PSTATE_SS(tb->flags);
+ dc->ss_active = ARM_TBFLAG_SS_ACTIVE(tb->flags);
+ dc->pstate_ss = ARM_TBFLAG_PSTATE_SS(tb->flags);
dc->is_ldex = false;
dc->ss_same_el = (arm_debug_target_el(env) == dc->current_el);
@@ -11031,7 +11040,8 @@ void gen_intermediate_code_internal_a64(ARMCPU *cpu,
* bits should be zero.
*/
assert(num_insns == 0);
- gen_exception(EXCP_UDEF, syn_swstep(dc->ss_same_el, 0, 0));
+ gen_exception(EXCP_UDEF, syn_swstep(dc->ss_same_el, 0, 0),
+ default_exception_el(dc));
dc->is_jmp = DISAS_EXC;
break;
}
@@ -11103,6 +11113,10 @@ void gen_intermediate_code_internal_a64(ARMCPU *cpu,
*/
gen_a64_set_pc_im(dc->pc);
gen_helper_wfi(cpu_env);
+ /* The helper doesn't necessarily throw an exception, but we
+ * must go back to the main loop to check for interrupts anyway.
+ */
+ tcg_gen_exit_tb(0);
break;
}
}