|
@@ -14649,113 +14649,6 @@ static bool btype_destination_ok(uint32_t insn, bool bt, int btype)
|
|
return false;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
-/* C3.1 A64 instruction index by encoding */
|
|
|
|
-static void disas_a64_insn(CPUARMState *env, DisasContext *s)
|
|
|
|
-{
|
|
|
|
- uint32_t insn;
|
|
|
|
-
|
|
|
|
- s->pc_curr = s->base.pc_next;
|
|
|
|
- insn = arm_ldl_code(env, s->base.pc_next, s->sctlr_b);
|
|
|
|
- s->insn = insn;
|
|
|
|
- s->base.pc_next += 4;
|
|
|
|
-
|
|
|
|
- s->fp_access_checked = false;
|
|
|
|
- s->sve_access_checked = false;
|
|
|
|
-
|
|
|
|
- if (s->pstate_il) {
|
|
|
|
- /*
|
|
|
|
- * Illegal execution state. This has priority over BTI
|
|
|
|
- * exceptions, but comes after instruction abort exceptions.
|
|
|
|
- */
|
|
|
|
- gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
|
|
|
|
- syn_illegalstate(), default_exception_el(s));
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (dc_isar_feature(aa64_bti, s)) {
|
|
|
|
- if (s->base.num_insns == 1) {
|
|
|
|
- /*
|
|
|
|
- * At the first insn of the TB, compute s->guarded_page.
|
|
|
|
- * We delayed computing this until successfully reading
|
|
|
|
- * the first insn of the TB, above. This (mostly) ensures
|
|
|
|
- * that the softmmu tlb entry has been populated, and the
|
|
|
|
- * page table GP bit is available.
|
|
|
|
- *
|
|
|
|
- * Note that we need to compute this even if btype == 0,
|
|
|
|
- * because this value is used for BR instructions later
|
|
|
|
- * where ENV is not available.
|
|
|
|
- */
|
|
|
|
- s->guarded_page = is_guarded_page(env, s);
|
|
|
|
-
|
|
|
|
- /* First insn can have btype set to non-zero. */
|
|
|
|
- tcg_debug_assert(s->btype >= 0);
|
|
|
|
-
|
|
|
|
- /*
|
|
|
|
- * Note that the Branch Target Exception has fairly high
|
|
|
|
- * priority -- below debugging exceptions but above most
|
|
|
|
- * everything else. This allows us to handle this now
|
|
|
|
- * instead of waiting until the insn is otherwise decoded.
|
|
|
|
- */
|
|
|
|
- if (s->btype != 0
|
|
|
|
- && s->guarded_page
|
|
|
|
- && !btype_destination_ok(insn, s->bt, s->btype)) {
|
|
|
|
- gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
|
|
|
|
- syn_btitrap(s->btype),
|
|
|
|
- default_exception_el(s));
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
- } else {
|
|
|
|
- /* Not the first insn: btype must be 0. */
|
|
|
|
- tcg_debug_assert(s->btype == 0);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- switch (extract32(insn, 25, 4)) {
|
|
|
|
- case 0x0: case 0x1: case 0x3: /* UNALLOCATED */
|
|
|
|
- unallocated_encoding(s);
|
|
|
|
- break;
|
|
|
|
- case 0x2:
|
|
|
|
- if (!dc_isar_feature(aa64_sve, s) || !disas_sve(s, insn)) {
|
|
|
|
- unallocated_encoding(s);
|
|
|
|
- }
|
|
|
|
- break;
|
|
|
|
- case 0x8: case 0x9: /* Data processing - immediate */
|
|
|
|
- disas_data_proc_imm(s, insn);
|
|
|
|
- break;
|
|
|
|
- case 0xa: case 0xb: /* Branch, exception generation and system insns */
|
|
|
|
- disas_b_exc_sys(s, insn);
|
|
|
|
- break;
|
|
|
|
- case 0x4:
|
|
|
|
- case 0x6:
|
|
|
|
- case 0xc:
|
|
|
|
- case 0xe: /* Loads and stores */
|
|
|
|
- disas_ldst(s, insn);
|
|
|
|
- break;
|
|
|
|
- case 0x5:
|
|
|
|
- case 0xd: /* Data processing - register */
|
|
|
|
- disas_data_proc_reg(s, insn);
|
|
|
|
- break;
|
|
|
|
- case 0x7:
|
|
|
|
- case 0xf: /* Data processing - SIMD and floating point */
|
|
|
|
- disas_data_proc_simd_fp(s, insn);
|
|
|
|
- break;
|
|
|
|
- default:
|
|
|
|
- assert(FALSE); /* all 15 cases should be handled above */
|
|
|
|
- break;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /* if we allocated any temporaries, free them here */
|
|
|
|
- free_tmp_a64(s);
|
|
|
|
-
|
|
|
|
- /*
|
|
|
|
- * After execution of most insns, btype is reset to 0.
|
|
|
|
- * Note that we set btype == -1 when the insn sets btype.
|
|
|
|
- */
|
|
|
|
- if (s->btype > 0 && s->base.is_jmp != DISAS_NORETURN) {
|
|
|
|
- reset_btype(s);
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
static void aarch64_tr_init_disas_context(DisasContextBase *dcbase,
|
|
static void aarch64_tr_init_disas_context(DisasContextBase *dcbase,
|
|
CPUState *cpu)
|
|
CPUState *cpu)
|
|
{
|
|
{
|
|
@@ -14857,10 +14750,11 @@ static void aarch64_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
|
|
|
|
|
|
static void aarch64_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
|
|
static void aarch64_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
|
|
{
|
|
{
|
|
- DisasContext *dc = container_of(dcbase, DisasContext, base);
|
|
|
|
|
|
+ DisasContext *s = container_of(dcbase, DisasContext, base);
|
|
CPUARMState *env = cpu->env_ptr;
|
|
CPUARMState *env = cpu->env_ptr;
|
|
|
|
+ uint32_t insn;
|
|
|
|
|
|
- if (dc->ss_active && !dc->pstate_ss) {
|
|
|
|
|
|
+ if (s->ss_active && !s->pstate_ss) {
|
|
/* Singlestep state is Active-pending.
|
|
/* Singlestep state is Active-pending.
|
|
* If we're in this state at the start of a TB then either
|
|
* If we're in this state at the start of a TB then either
|
|
* a) we just took an exception to an EL which is being debugged
|
|
* a) we just took an exception to an EL which is being debugged
|
|
@@ -14871,14 +14765,114 @@ static void aarch64_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
|
|
* "did not step an insn" case, and so the syndrome ISV and EX
|
|
* "did not step an insn" case, and so the syndrome ISV and EX
|
|
* bits should be zero.
|
|
* bits should be zero.
|
|
*/
|
|
*/
|
|
- assert(dc->base.num_insns == 1);
|
|
|
|
- gen_swstep_exception(dc, 0, 0);
|
|
|
|
- dc->base.is_jmp = DISAS_NORETURN;
|
|
|
|
- } else {
|
|
|
|
- disas_a64_insn(env, dc);
|
|
|
|
|
|
+ assert(s->base.num_insns == 1);
|
|
|
|
+ gen_swstep_exception(s, 0, 0);
|
|
|
|
+ s->base.is_jmp = DISAS_NORETURN;
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ s->pc_curr = s->base.pc_next;
|
|
|
|
+ insn = arm_ldl_code(env, s->base.pc_next, s->sctlr_b);
|
|
|
|
+ s->insn = insn;
|
|
|
|
+ s->base.pc_next += 4;
|
|
|
|
+
|
|
|
|
+ s->fp_access_checked = false;
|
|
|
|
+ s->sve_access_checked = false;
|
|
|
|
+
|
|
|
|
+ if (s->pstate_il) {
|
|
|
|
+ /*
|
|
|
|
+ * Illegal execution state. This has priority over BTI
|
|
|
|
+ * exceptions, but comes after instruction abort exceptions.
|
|
|
|
+ */
|
|
|
|
+ gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
|
|
|
|
+ syn_illegalstate(), default_exception_el(s));
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (dc_isar_feature(aa64_bti, s)) {
|
|
|
|
+ if (s->base.num_insns == 1) {
|
|
|
|
+ /*
|
|
|
|
+ * At the first insn of the TB, compute s->guarded_page.
|
|
|
|
+ * We delayed computing this until successfully reading
|
|
|
|
+ * the first insn of the TB, above. This (mostly) ensures
|
|
|
|
+ * that the softmmu tlb entry has been populated, and the
|
|
|
|
+ * page table GP bit is available.
|
|
|
|
+ *
|
|
|
|
+ * Note that we need to compute this even if btype == 0,
|
|
|
|
+ * because this value is used for BR instructions later
|
|
|
|
+ * where ENV is not available.
|
|
|
|
+ */
|
|
|
|
+ s->guarded_page = is_guarded_page(env, s);
|
|
|
|
+
|
|
|
|
+ /* First insn can have btype set to non-zero. */
|
|
|
|
+ tcg_debug_assert(s->btype >= 0);
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * Note that the Branch Target Exception has fairly high
|
|
|
|
+ * priority -- below debugging exceptions but above most
|
|
|
|
+ * everything else. This allows us to handle this now
|
|
|
|
+ * instead of waiting until the insn is otherwise decoded.
|
|
|
|
+ */
|
|
|
|
+ if (s->btype != 0
|
|
|
|
+ && s->guarded_page
|
|
|
|
+ && !btype_destination_ok(insn, s->bt, s->btype)) {
|
|
|
|
+ gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
|
|
|
|
+ syn_btitrap(s->btype),
|
|
|
|
+ default_exception_el(s));
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ /* Not the first insn: btype must be 0. */
|
|
|
|
+ tcg_debug_assert(s->btype == 0);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ switch (extract32(insn, 25, 4)) {
|
|
|
|
+ case 0x0: case 0x1: case 0x3: /* UNALLOCATED */
|
|
|
|
+ unallocated_encoding(s);
|
|
|
|
+ break;
|
|
|
|
+ case 0x2:
|
|
|
|
+ if (!dc_isar_feature(aa64_sve, s) || !disas_sve(s, insn)) {
|
|
|
|
+ unallocated_encoding(s);
|
|
|
|
+ }
|
|
|
|
+ break;
|
|
|
|
+ case 0x8: case 0x9: /* Data processing - immediate */
|
|
|
|
+ disas_data_proc_imm(s, insn);
|
|
|
|
+ break;
|
|
|
|
+ case 0xa: case 0xb: /* Branch, exception generation and system insns */
|
|
|
|
+ disas_b_exc_sys(s, insn);
|
|
|
|
+ break;
|
|
|
|
+ case 0x4:
|
|
|
|
+ case 0x6:
|
|
|
|
+ case 0xc:
|
|
|
|
+ case 0xe: /* Loads and stores */
|
|
|
|
+ disas_ldst(s, insn);
|
|
|
|
+ break;
|
|
|
|
+ case 0x5:
|
|
|
|
+ case 0xd: /* Data processing - register */
|
|
|
|
+ disas_data_proc_reg(s, insn);
|
|
|
|
+ break;
|
|
|
|
+ case 0x7:
|
|
|
|
+ case 0xf: /* Data processing - SIMD and floating point */
|
|
|
|
+ disas_data_proc_simd_fp(s, insn);
|
|
|
|
+ break;
|
|
|
|
+ default:
|
|
|
|
+ assert(FALSE); /* all 15 cases should be handled above */
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* if we allocated any temporaries, free them here */
|
|
|
|
+ free_tmp_a64(s);
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * After execution of most insns, btype is reset to 0.
|
|
|
|
+ * Note that we set btype == -1 when the insn sets btype.
|
|
|
|
+ */
|
|
|
|
+ if (s->btype > 0 && s->base.is_jmp != DISAS_NORETURN) {
|
|
|
|
+ reset_btype(s);
|
|
}
|
|
}
|
|
|
|
|
|
- translator_loop_temp_check(&dc->base);
|
|
|
|
|
|
+ translator_loop_temp_check(&s->base);
|
|
}
|
|
}
|
|
|
|
|
|
static void aarch64_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
|
|
static void aarch64_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
|