qemu/target/microblaze/translate.c
/* generate intermediate code for basic block 'tb'.  */
generate intermediate code for basic block 'tb'.
generate intermediate code for basic block ' tb ' .
void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb)
{
    CPUMBState *env = cs->env_ptr;
    MicroBlazeCPU *cpu = mb_env_get_cpu(env);
    uint32_t pc_start;
    struct DisasContext ctx;
    struct DisasContext *dc = &ctx;
    uint32_t page_start, org_flags;
    uint32_t npc;
    int num_insns;
    int max_insns;
    pc_start = tb->pc;
    dc->cpu = cpu;
    dc->tb = tb;
    org_flags = dc->synced_flags = dc->tb_flags = tb->flags;
    dc->is_jmp = DISAS_NEXT;
    dc->jmp = 0;
    dc->delayed_branch = !!(dc->tb_flags & D_FLAG);
    if (dc->delayed_branch) {
        dc->jmp = JMP_INDIRECT;
    }
    dc->pc = pc_start;
    dc->singlestep_enabled = cs->singlestep_enabled;
    dc->cpustate_changed = 0;
    dc->abort_at_next_insn = 0;
    if (pc_start & 3) {
        cpu_abort(cs, "Microblaze: unaligned PC=%x\n", pc_start);
    }
    page_start = pc_start & TARGET_PAGE_MASK;
    num_insns = 0;
    max_insns = tb_cflags(tb) & CF_COUNT_MASK;
    if (max_insns == 0) {
        max_insns = CF_COUNT_MASK;
    }
    if (max_insns > TCG_MAX_INSNS) {
        max_insns = TCG_MAX_INSNS;
    }
    gen_tb_start(tb);
    do
    {
        tcg_gen_insn_start(dc->pc);
        num_insns++;
#if SIM_COMPAT
        if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
            tcg_gen_movi_i64(cpu_SR[SR_PC], dc->pc);
            gen_helper_debug();
        }
#endif
        if (unlikely(cpu_breakpoint_test(cs, dc->pc, BP_ANY))) {
            t_gen_raise_exception(dc, EXCP_DEBUG);
            dc->is_jmp = DISAS_UPDATE;
            dc->pc += 4;
            break;
        }
        LOG_DIS("%8.8x:\t", dc->pc);
        if (num_insns == max_insns && (tb_cflags(tb) & CF_LAST_IO)) {
            gen_io_start();
        }
        dc->clear_imm = 1;
        decode(dc, cpu_ldl_code(env, dc->pc));
        if (dc->clear_imm)
            dc->tb_flags &= ~IMM_FLAG;
        dc->pc += 4;
        if (dc->delayed_branch) {
            dc->delayed_branch--;
            if (!dc->delayed_branch) {
                if (dc->tb_flags & DRTI_FLAG)
                    do_rti(dc);
                 if (dc->tb_flags & DRTB_FLAG)
                    do_rtb(dc);
                if (dc->tb_flags & DRTE_FLAG)
                    do_rte(dc);
                dc->tb_flags &= ~D_FLAG;
                if (dc->jmp == JMP_INDIRECT) {
                    eval_cond_jmp(dc, env_btarget, tcg_const_i64(dc->pc));
                    dc->is_jmp = DISAS_JUMP;
                } else if (dc->jmp == JMP_DIRECT) {
                    t_sync_flags(dc);
                    gen_goto_tb(dc, 0, dc->jmp_pc);
                    dc->is_jmp = DISAS_TB_JUMP;
                } else if (dc->jmp == JMP_DIRECT_CC) {
                    TCGLabel *l1 = gen_new_label();
                    t_sync_flags(dc);
                    tcg_gen_brcondi_i32(TCG_COND_NE, env_btaken, 0, l1);
                    gen_goto_tb(dc, 1, dc->pc);
                    gen_set_label(l1);
                    gen_goto_tb(dc, 0, dc->jmp_pc);
                    dc->is_jmp = DISAS_TB_JUMP;
                }
                break;
            }
        }
        if (cs->singlestep_enabled) {
            break;
        }
    } while (!dc->is_jmp && !dc->cpustate_changed
             && !tcg_op_buf_full()
             && !singlestep
             && (dc->pc - page_start < TARGET_PAGE_SIZE)
             && num_insns < max_insns);
    npc = dc->pc;
    if (dc->jmp == JMP_DIRECT || dc->jmp == JMP_DIRECT_CC) {
        if (dc->tb_flags & D_FLAG) {
            dc->is_jmp = DISAS_UPDATE;
            tcg_gen_movi_i64(cpu_SR[SR_PC], npc);
            sync_jmpstate(dc);
        } else
            npc = dc->jmp_pc;
    }
    if (tb_cflags(tb) & CF_LAST_IO)
        gen_io_end();
    if (dc->is_jmp == DISAS_NEXT
        && (dc->cpustate_changed || org_flags != dc->tb_flags)) {
        dc->is_jmp = DISAS_UPDATE;
        tcg_gen_movi_i64(cpu_SR[SR_PC], npc);
    }
    t_sync_flags(dc);
    if (unlikely(cs->singlestep_enabled)) {
        TCGv_i32 tmp = tcg_const_i32(EXCP_DEBUG);
        if (dc->is_jmp != DISAS_JUMP) {
            tcg_gen_movi_i64(cpu_SR[SR_PC], npc);
        }
        gen_helper_raise_exception(cpu_env, tmp);
        tcg_temp_free_i32(tmp);
    } else {
        switch(dc->is_jmp) {
            case DISAS_NEXT:
                gen_goto_tb(dc, 1, npc);
                break;
            default:
            case DISAS_JUMP:
            case DISAS_UPDATE:
                tcg_gen_exit_tb(NULL, 0);
                break;
            case DISAS_TB_JUMP:
                break;
        }
    }
    gen_tb_end(tb, num_insns);
    tb->size = dc->pc - pc_start;
    tb->icount = num_insns;
#ifdef DEBUG_DISAS
#if !SIM_COMPAT
    if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
        && qemu_log_in_addr_range(pc_start)) {
        qemu_log_lock();
        qemu_log("--------------\n");
        log_target_disas(cs, pc_start, dc->pc - pc_start);
        qemu_log_unlock();
    }
#endif
#endif
    assert(!dc->abort_at_next_insn);
}
void gen_intermediate_code ( CPUState * cs , struct TranslationBlock * tb ) { CPUMBState * env = cs -> env_ptr ; MicroBlazeCPU * cpu = mb_env_get_cpu ( env ) ; uint32_t pc_start ; struct DisasContext ctx ; struct DisasContext * dc = & ctx ; uint32_t page_start , org_flags ; uint32_t npc ; int num_insns ; int max_insns ; pc_start = tb -> pc ; dc -> cpu = cpu ; dc -> tb = tb ; org_flags = dc -> synced_flags = dc -> tb_flags = tb -> flags ; dc -> is_jmp = DISAS_NEXT ; dc -> jmp = 0 ; dc -> delayed_branch = ! ! ( dc -> tb_flags & D_FLAG ) ; if ( dc -> delayed_branch ) { dc -> jmp = JMP_INDIRECT ; } dc -> pc = pc_start ; dc -> singlestep_enabled = cs -> singlestep_enabled ; dc -> cpustate_changed = 0 ; dc -> abort_at_next_insn = 0 ; if ( pc_start & 3 ) { cpu_abort ( cs , " \n " , pc_start ) ; } page_start = pc_start & TARGET_PAGE_MASK ; num_insns = 0 ; max_insns = tb_cflags ( tb ) & CF_COUNT_MASK ; if ( max_insns == 0 ) { max_insns = CF_COUNT_MASK ; } if ( max_insns > TCG_MAX_INSNS ) { max_insns = TCG_MAX_INSNS ; } gen_tb_start ( tb ) ; do { tcg_gen_insn_start ( dc -> pc ) ; num_insns ++ ; #if SIM_COMPAT if ( qemu_loglevel_mask ( CPU_LOG_TB_IN_ASM ) ) { tcg_gen_movi_i64 ( cpu_SR [ SR_PC ] , dc -> pc ) ; gen_helper_debug ( ) ; } #endif if ( unlikely ( cpu_breakpoint_test ( cs , dc -> pc , BP_ANY ) ) ) { t_gen_raise_exception ( dc , EXCP_DEBUG ) ; dc -> is_jmp = DISAS_UPDATE ; dc -> pc += 4 ; break ; } LOG_DIS ( " \t " , dc -> pc ) ; if ( num_insns == max_insns && ( tb_cflags ( tb ) & CF_LAST_IO ) ) { gen_io_start ( ) ; } dc -> clear_imm = 1 ; decode ( dc , cpu_ldl_code ( env , dc -> pc ) ) ; if ( dc -> clear_imm ) dc -> tb_flags &= ~ IMM_FLAG ; dc -> pc += 4 ; if ( dc -> delayed_branch ) { dc -> delayed_branch -- ; if ( ! dc -> delayed_branch ) { if ( dc -> tb_flags & DRTI_FLAG ) do_rti ( dc ) ; if ( dc -> tb_flags & DRTB_FLAG ) do_rtb ( dc ) ; if ( dc -> tb_flags & DRTE_FLAG ) do_rte ( dc ) ; dc -> tb_flags &= ~ D_FLAG ; if ( dc -> jmp == JMP_INDIRECT ) { eval_cond_jmp ( dc , env_btarget , tcg_const_i64 ( dc -> pc ) ) ; dc -> is_jmp = DISAS_JUMP ; } else if ( dc -> jmp == JMP_DIRECT ) { t_sync_flags ( dc ) ; gen_goto_tb ( dc , 0 , dc -> jmp_pc ) ; dc -> is_jmp = DISAS_TB_JUMP ; } else if ( dc -> jmp == JMP_DIRECT_CC ) { TCGLabel * l1 = gen_new_label ( ) ; t_sync_flags ( dc ) ; tcg_gen_brcondi_i32 ( TCG_COND_NE , env_btaken , 0 , l1 ) ; gen_goto_tb ( dc , 1 , dc -> pc ) ; gen_set_label ( l1 ) ; gen_goto_tb ( dc , 0 , dc -> jmp_pc ) ; dc -> is_jmp = DISAS_TB_JUMP ; } break ; } } if ( cs -> singlestep_enabled ) { break ; } } while ( ! dc -> is_jmp && ! dc -> cpustate_changed && ! tcg_op_buf_full ( ) && ! singlestep && ( dc -> pc - page_start < TARGET_PAGE_SIZE ) && num_insns < max_insns ) ; npc = dc -> pc ; if ( dc -> jmp == JMP_DIRECT || dc -> jmp == JMP_DIRECT_CC ) { if ( dc -> tb_flags & D_FLAG ) { dc -> is_jmp = DISAS_UPDATE ; tcg_gen_movi_i64 ( cpu_SR [ SR_PC ] , npc ) ; sync_jmpstate ( dc ) ; } else npc = dc -> jmp_pc ; } if ( tb_cflags ( tb ) & CF_LAST_IO ) gen_io_end ( ) ; if ( dc -> is_jmp == DISAS_NEXT && ( dc -> cpustate_changed || org_flags != dc -> tb_flags ) ) { dc -> is_jmp = DISAS_UPDATE ; tcg_gen_movi_i64 ( cpu_SR [ SR_PC ] , npc ) ; } t_sync_flags ( dc ) ; if ( unlikely ( cs -> singlestep_enabled ) ) { TCGv_i32 tmp = tcg_const_i32 ( EXCP_DEBUG ) ; if ( dc -> is_jmp != DISAS_JUMP ) { tcg_gen_movi_i64 ( cpu_SR [ SR_PC ] , npc ) ; } gen_helper_raise_exception ( cpu_env , tmp ) ; tcg_temp_free_i32 ( tmp ) ; } else { switch ( dc -> is_jmp ) { case DISAS_NEXT : gen_goto_tb ( dc , 1 , npc ) ; break ; default : case DISAS_JUMP : case DISAS_UPDATE : tcg_gen_exit_tb ( NULL , 0 ) ; break ; case DISAS_TB_JUMP : break ; } } gen_tb_end ( tb , num_insns ) ; tb -> size = dc -> pc - pc_start ; tb -> icount = num_insns ; #ifdef DEBUG_DISAS #if ! SIM_COMPAT if ( qemu_loglevel_mask ( CPU_LOG_TB_IN_ASM ) && qemu_log_in_addr_range ( pc_start ) ) { qemu_log_lock ( ) ; qemu_log ( " \n " ) ; log_target_disas ( cs , pc_start , dc -> pc - pc_start ) ; qemu_log_unlock ( ) ; } #endif #endif assert ( ! dc -> abort_at_next_insn ) ; }
generate intermediate code for basic block 'tb'.
generate intermediate code for basic block ' tb ' .
/* 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.  */ /* Pretty disas.  */ /* Clear the delay slot flag.  */ /* If it is a direct jump, try direct chaining.  */ /* Conditional jmp.  */ /* Force an update if the per-tb cpu state has changed.  */ /* indicate that the hash table must be used
                   to find the next TB */ /* nothing more to generate */