Commit be407964 authored by Lluís Vilanova's avatar Lluís Vilanova Committed by Richard Henderson
Browse files

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



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

Reviewed-by: default avatarEmilio G. Cota <cota@braap.org>
Reviewed-by: default avatarRichard Henderson <rth@twiddle.net>
Signed-off-by: default avatarLluís Vilanova <vilanova@ac.upc.edu>
Message-Id: <150002558503.22386.1149037590886263349.stgit@frigg.lan>
Signed-off-by: default avatarRichard Henderson <rth@twiddle.net>
parent 70d3c035
Loading
Loading
Loading
Loading
+67 −60
Original line number Diff line number Diff line
@@ -11327,6 +11327,72 @@ static void aarch64_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
    dc->base.pc_next = 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)) {
        /* 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->pc);
            /* fall through */
        case DISAS_JUMP:
            if (dc->base.singlestep_enabled) {
                gen_exception_internal(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->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_NORETURN:
        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)
{
@@ -11398,66 +11464,7 @@ void gen_intermediate_code_a64(DisasContextBase *dcbase, CPUState *cs,
        gen_io_end();
    }

    if (unlikely(cs->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->pc);
            /* fall through */
        case DISAS_JUMP:
            if (cs->singlestep_enabled) {
                gen_exception_internal(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(cpu_pc);
            break;
        case DISAS_NORETURN:
        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;
        case DISAS_UPDATE:
            gen_a64_set_pc_im(dc->pc);
            /* fall through */
        case DISAS_EXIT:
        default:
            tcg_gen_exit_tb(0);
            break;
        }
    }
    aarch64_tr_tb_stop(&dc->base, cs);

    gen_tb_end(tb, dc->base.num_insns);