@@ -11317,6 +11317,69 @@ static target_ulong aarch64_tr_translate_insn(DisasContextBase *dcbase,
return dc->pc;
}
+static void aarch64_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
+{
+ DisasContext *dc = container_of(dcbase, DisasContext, base);
+
+ if (unlikely(dc->base.singlestep_enabled || dc->ss_active)
+ && dc->base.is_jmp != DISAS_EXC) {
+ /* Note that this means single stepping WFI doesn't halt the CPU.
+ * For conditional branch insns this is harmless unreachable code as
+ * gen_goto_tb() has already handled emitting the debug exception
+ * (and thus a tb-jump is not possible when singlestepping).
+ */
+ assert(dc->base.is_jmp != DISAS_TB_JUMP);
+ if (dc->base.is_jmp != DISAS_JUMP) {
+ gen_a64_set_pc_im(dc->pc);
+ }
+ if (dc->base.singlestep_enabled) {
+ gen_exception_internal(EXCP_DEBUG);
+ } else {
+ gen_step_complete_exception(dc);
+ }
+ } else {
+ switch (dc->base.is_jmp) {
+ case DISAS_NEXT:
+ case DISAS_TOO_MANY:
+ gen_goto_tb(dc, 1, dc->pc);
+ break;
+ default:
+ case DISAS_UPDATE:
+ gen_a64_set_pc_im(dc->pc);
+ /* fall through */
+ case DISAS_JUMP:
+ tcg_gen_lookup_and_goto_ptr(cpu_pc);
+ break;
+ case DISAS_EXIT:
+ tcg_gen_exit_tb(0);
+ break;
+ case DISAS_TB_JUMP:
+ case DISAS_EXC:
+ case DISAS_SWI:
+ break;
+ case DISAS_WFE:
+ gen_a64_set_pc_im(dc->pc);
+ gen_helper_wfe(cpu_env);
+ break;
+ case DISAS_YIELD:
+ gen_a64_set_pc_im(dc->pc);
+ gen_helper_yield(cpu_env);
+ break;
+ case DISAS_WFI:
+ /* 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);
+ /* 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;
+ }
+ }
+}
+
void gen_intermediate_code_a64(DisasContextBase *dcbase, CPUState *cs,
TranslationBlock *tb)
{
@@ -11385,68 +11448,12 @@ void gen_intermediate_code_a64(DisasContextBase *dcbase, CPUState *cs,
*/
} while (!dc->base.is_jmp);
+ aarch64_tr_tb_stop(&dc->base, cs);
+
if (dc->base.tb->cflags & CF_LAST_IO) {
gen_io_end();
}
- if (unlikely(cs->singlestep_enabled || dc->ss_active)
- && dc->base.is_jmp != DISAS_EXC) {
- /* Note that this means single stepping WFI doesn't halt the CPU.
- * For conditional branch insns this is harmless unreachable code as
- * gen_goto_tb() has already handled emitting the debug exception
- * (and thus a tb-jump is not possible when singlestepping).
- */
- assert(dc->base.is_jmp != DISAS_TB_JUMP);
- if (dc->base.is_jmp != DISAS_JUMP) {
- gen_a64_set_pc_im(dc->pc);
- }
- if (cs->singlestep_enabled) {
- gen_exception_internal(EXCP_DEBUG);
- } else {
- gen_step_complete_exception(dc);
- }
- } else {
- switch (dc->base.is_jmp) {
- case DISAS_NEXT:
- case DISAS_TOO_MANY:
- gen_goto_tb(dc, 1, dc->pc);
- break;
- default:
- case DISAS_UPDATE:
- gen_a64_set_pc_im(dc->pc);
- /* fall through */
- case DISAS_JUMP:
- tcg_gen_lookup_and_goto_ptr(cpu_pc);
- break;
- case DISAS_EXIT:
- tcg_gen_exit_tb(0);
- break;
- case DISAS_TB_JUMP:
- case DISAS_EXC:
- case DISAS_SWI:
- break;
- case DISAS_WFE:
- gen_a64_set_pc_im(dc->pc);
- gen_helper_wfe(cpu_env);
- break;
- case DISAS_YIELD:
- gen_a64_set_pc_im(dc->pc);
- gen_helper_yield(cpu_env);
- break;
- case DISAS_WFI:
- /* 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);
- /* 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;
- }
- }
-
gen_tb_end(tb, dc->base.num_insns);
#ifdef DEBUG_DISAS