Commit 11ab74b0 authored by Richard Henderson's avatar Richard Henderson Committed by Laurent Vivier
Browse files

target/m68k: Convert to TranslatorOps



Signed-off-by: default avatarRichard Henderson <richard.henderson@linaro.org>
Message-Id: <20180512050250.12774-8-richard.henderson@linaro.org>
Signed-off-by: default avatarLaurent Vivier <laurent@vivier.eu>
parent a575cbe0
Loading
Loading
Loading
Loading
+88 −92
Original line number Diff line number Diff line
@@ -6059,80 +6059,72 @@ static void disas_m68k_insn(CPUM68KState * env, DisasContext *s)
    do_release(s);
}

/* generate intermediate code for basic block 'tb'.  */
void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
static void m68k_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cpu)
{
    CPUM68KState *env = cs->env_ptr;
    DisasContext dc1, *dc = &dc1;
    target_ulong pc_start;
    int pc_offset;
    int num_insns;
    int max_insns;

    /* generate intermediate code */
    pc_start = tb->pc;

    dc->base.tb = tb;
    DisasContext *dc = container_of(dcbase, DisasContext, base);
    CPUM68KState *env = cpu->env_ptr;

    dc->env = env;
    dc->base.is_jmp = DISAS_NEXT;
    dc->pc = pc_start;
    dc->pc = dc->base.pc_first;
    dc->cc_op = CC_OP_DYNAMIC;
    dc->cc_op_synced = 1;
    dc->base.singlestep_enabled = cs->singlestep_enabled;
    dc->done_mac = 0;
    dc->writeback_mask = 0;
    num_insns = 0;
    max_insns = tb_cflags(tb) & CF_COUNT_MASK;
    if (max_insns == 0) {
        max_insns = CF_COUNT_MASK;
    init_release_array(dc);
}
    if (max_insns > TCG_MAX_INSNS) {
        max_insns = TCG_MAX_INSNS;

static void m68k_tr_tb_start(DisasContextBase *dcbase, CPUState *cpu)
{
}

    init_release_array(dc);
static void m68k_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
{
    DisasContext *dc = container_of(dcbase, DisasContext, base);
    tcg_gen_insn_start(dc->base.pc_next, dc->cc_op);
}

    gen_tb_start(tb);
    do {
        pc_offset = dc->pc - pc_start;
        tcg_gen_insn_start(dc->pc, dc->cc_op);
        num_insns++;
static bool m68k_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu,
                                     const CPUBreakpoint *bp)
{
    DisasContext *dc = container_of(dcbase, DisasContext, base);

        if (unlikely(cpu_breakpoint_test(cs, dc->pc, BP_ANY))) {
            gen_exception(dc, dc->pc, EXCP_DEBUG);
    gen_exception(dc, dc->base.pc_next, EXCP_DEBUG);
    /* The address covered by the breakpoint must be included in
       [tb->pc, tb->pc + tb->size) in order to for it to be
       properly cleared -- thus we increment the PC here so that
       the logic setting tb->size below does the right thing.  */
            dc->pc += 2;
            break;
        }
    dc->base.pc_next += 2;

        if (num_insns == max_insns && (tb_cflags(tb) & CF_LAST_IO)) {
            gen_io_start();
    return true;
}

static void m68k_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
{
    DisasContext *dc = container_of(dcbase, DisasContext, base);

    disas_m68k_insn(cpu->env_ptr, dc);
    dc->base.pc_next = dc->pc;
	disas_m68k_insn(env, dc);
    } while (!dc->base.is_jmp && !tcg_op_buf_full() &&
             !cs->singlestep_enabled &&
             !singlestep &&
             (pc_offset) < (TARGET_PAGE_SIZE - 32) &&
             num_insns < max_insns);

    if (tb_cflags(tb) & CF_LAST_IO)
        gen_io_end();
    if (unlikely(cs->singlestep_enabled)) {
        /* Make sure the pc is updated, and raise a debug exception.  */
        if (!dc->base.is_jmp) {
            update_cc_op(dc);
            tcg_gen_movi_i32(QREG_PC, dc->pc);

    if (dc->base.is_jmp == DISAS_NEXT
        && dc->pc - dc->base.pc_first >= TARGET_PAGE_SIZE - 32) {
        dc->base.is_jmp = DISAS_TOO_MANY;
    }
}

static void m68k_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
{
    DisasContext *dc = container_of(dcbase, DisasContext, base);

    if (dc->base.is_jmp == DISAS_NORETURN) {
        return;
    }
    if (dc->base.singlestep_enabled) {
        gen_helper_raise_exception(cpu_env, tcg_const_i32(EXCP_DEBUG));
    } else {
        return;
    }

    switch (dc->base.is_jmp) {
        case DISAS_NEXT:
    case DISAS_TOO_MANY:
        update_cc_op(dc);
        gen_jmp_tb(dc, 0, dc->pc);
        break;
@@ -6140,32 +6132,36 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
        /* We updated CC_OP and PC in gen_jmp/gen_jmp_im.  */
        tcg_gen_lookup_and_goto_ptr();
        break;
        default:
    case DISAS_EXIT:
        /* We updated CC_OP and PC in gen_exit_tb, but also modified
           other state that may require returning to the main loop.  */
        tcg_gen_exit_tb(NULL, 0);
        break;
        case DISAS_NORETURN:
            /* nothing more to generate */
            break;
    default:
        g_assert_not_reached();
    }
}
    gen_tb_end(tb, num_insns);

#ifdef DEBUG_DISAS
    if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
        && qemu_log_in_addr_range(pc_start)) {
        qemu_log_lock();
        qemu_log("----------------\n");
        qemu_log("IN: %s\n", lookup_symbol(pc_start));
        log_target_disas(cs, pc_start, dc->pc - pc_start);
        qemu_log("\n");
        qemu_log_unlock();
static void m68k_tr_disas_log(const DisasContextBase *dcbase, CPUState *cpu)
{
    qemu_log("IN: %s\n", lookup_symbol(dcbase->pc_first));
    log_target_disas(cpu, dcbase->pc_first, dcbase->tb->size);
}
#endif
    tb->size = dc->pc - pc_start;
    tb->icount = num_insns;

static const TranslatorOps m68k_tr_ops = {
    .init_disas_context = m68k_tr_init_disas_context,
    .tb_start           = m68k_tr_tb_start,
    .insn_start         = m68k_tr_insn_start,
    .breakpoint_check   = m68k_tr_breakpoint_check,
    .translate_insn     = m68k_tr_translate_insn,
    .tb_stop            = m68k_tr_tb_stop,
    .disas_log          = m68k_tr_disas_log,
};

void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
{
    DisasContext dc;
    translator_loop(&m68k_tr_ops, &dc.base, cpu, tb);
}

static double floatx80_to_double(CPUM68KState *env, uint16_t high, uint64_t low)