target/arm: [tcg,a64] Port to tb_stop

Incrementally paves the way towards using the generic instruction translation
loop.

Backports commit be4079641f1bc755fc5d3ff194cf505c506227d8 from qemu
This commit is contained in:
Lluís Vilanova 2018-03-04 20:02:41 -05:00 committed by Lioncash
parent d8def0cdb5
commit 7a02cb360c
No known key found for this signature in database
GPG key ID: 4E3C3CC1031BA9C7

View file

@ -11576,6 +11576,73 @@ static void aarch64_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
dc->base.pc_next = dc->pc; dc->base.pc_next = dc->pc;
} }
static void aarch64_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
{
DisasContext *dc = container_of(dcbase, DisasContext, base);
TCGContext *tcg_ctx = cpu->uc->tcg_ctx;
if (unlikely(dc->base.singlestep_enabled || dc->ss_active)) {
/* 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).
*/
switch (dc->base.is_jmp) {
default:
gen_a64_set_pc_im(dc, dc->pc);
/* fall through */
case DISAS_JUMP:
if (dc->base.singlestep_enabled) {
gen_exception_internal(dc, EXCP_DEBUG);
} else {
gen_step_complete_exception(dc);
}
break;
case DISAS_NORETURN:
break;
}
} 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, dc->pc);
/* fall through */
case DISAS_JUMP:
tcg_gen_lookup_and_goto_ptr(tcg_ctx, tcg_ctx->cpu_pc);
break;
case DISAS_EXIT:
tcg_gen_exit_tb(tcg_ctx, 0);
break;
case DISAS_NORETURN:
case DISAS_SWI:
break;
case DISAS_WFE:
gen_a64_set_pc_im(dc, dc->pc);
gen_helper_wfe(tcg_ctx, tcg_ctx->cpu_env);
break;
case DISAS_YIELD:
gen_a64_set_pc_im(dc, dc->pc);
gen_helper_yield(tcg_ctx, tcg_ctx->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, dc->pc);
gen_helper_wfi(tcg_ctx, tcg_ctx->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(tcg_ctx, 0);
break;
}
}
}
void gen_intermediate_code_a64(DisasContextBase *dcbase, CPUState *cs, void gen_intermediate_code_a64(DisasContextBase *dcbase, CPUState *cs,
TranslationBlock *tb) TranslationBlock *tb)
{ {
@ -11676,66 +11743,7 @@ void gen_intermediate_code_a64(DisasContextBase *dcbase, CPUState *cs,
//} //}
tb_end: tb_end:
if (unlikely(cs->singlestep_enabled || dc->ss_active)) { aarch64_tr_tb_stop(&dc->base, cs);
/* 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).
*/
switch (dc->base.is_jmp) {
default:
gen_a64_set_pc_im(dc, dc->pc);
/* fall through */
case DISAS_JUMP:
if (cs->singlestep_enabled) {
gen_exception_internal(dc, EXCP_DEBUG);
} else {
gen_step_complete_exception(dc);
}
break;
case DISAS_NORETURN:
break;
}
} else {
switch (dc->base.is_jmp) {
case DISAS_NEXT:
case DISAS_TOO_MANY:
gen_goto_tb(dc, 1, dc->pc);
break;
case DISAS_JUMP:
tcg_gen_lookup_and_goto_ptr(tcg_ctx, tcg_ctx->cpu_pc);
break;
case DISAS_NORETURN:
case DISAS_SWI:
break;
case DISAS_WFE:
gen_a64_set_pc_im(dc, dc->pc);
gen_helper_wfe(tcg_ctx, tcg_ctx->cpu_env);
break;
case DISAS_YIELD:
gen_a64_set_pc_im(dc, dc->pc);
gen_helper_yield(tcg_ctx, tcg_ctx->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, dc->pc);
gen_helper_wfi(tcg_ctx, tcg_ctx->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(tcg_ctx, 0);
break;
case DISAS_UPDATE:
gen_a64_set_pc_im(dc, dc->pc);
/* fall through */
case DISAS_EXIT:
default:
tcg_gen_exit_tb(tcg_ctx, 0);
break;
}
}
gen_tb_end(tcg_ctx, tb, dc->base.num_insns); gen_tb_end(tcg_ctx, tb, dc->base.num_insns);