static inline int gen_intermediate_code_internal(CPUState *env, 

                                                 TranslationBlock *tb, 

                                                 int search_pc)

{

    DisasContext dc1, *dc = &dc1;

    uint16_t *gen_opc_end;

    int j, lj;

    target_ulong pc_start;

    uint32_t next_page_start;

    

    /* generate intermediate code */

    pc_start = tb->pc;

       

    dc->tb = tb;



    gen_opc_ptr = gen_opc_buf;

    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;

    gen_opparam_ptr = gen_opparam_buf;



    dc->is_jmp = DISAS_NEXT;

    dc->pc = pc_start;

    dc->singlestep_enabled = env->singlestep_enabled;

    dc->condjmp = 0;

    dc->thumb = env->thumb;


#if !defined(CONFIG_USER_ONLY)

    dc->user = (env->uncached_cpsr & 0x1f) == ARM_CPU_MODE_USR;

#endif

    next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;

    nb_gen_labels = 0;

    lj = -1;

    do {

        if (env->nb_breakpoints > 0) {

            for(j = 0; j < env->nb_breakpoints; j++) {

                if (env->breakpoints[j] == dc->pc) {

                    gen_op_movl_T0_im((long)dc->pc);

                    gen_op_movl_reg_TN[0][15]();

                    gen_op_debug();

                    dc->is_jmp = DISAS_JUMP;

                    break;

                }

            }

        }

        if (search_pc) {

            j = gen_opc_ptr - gen_opc_buf;

            if (lj < j) {

                lj++;

                while (lj < j)

                    gen_opc_instr_start[lj++] = 0;

            }

            gen_opc_pc[lj] = dc->pc;

            gen_opc_instr_start[lj] = 1;

        }



        if (env->thumb)

          disas_thumb_insn(dc);

        else

          disas_arm_insn(env, dc);



        if (dc->condjmp && !dc->is_jmp) {

            gen_set_label(dc->condlabel);

            dc->condjmp = 0;

        }

        /* Terminate the TB on memory ops if watchpoints are present.  */

        /* FIXME: This should be replacd by the deterministic execution

         * IRQ raising bits.  */

        if (dc->is_mem && env->nb_watchpoints)

            break;



        /* Translation stops when a conditional branch is enoutered.

         * Otherwise the subsequent code could get translated several times.

         * Also stop translation when a page boundary is reached.  This

         * ensures prefech aborts occur at the right place.  */

    } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&

             !env->singlestep_enabled &&

             dc->pc < next_page_start);

    /* At this stage dc->condjmp will only be set when the skipped

     * instruction was a conditional branch, and the PC has already been

     * written.  */

    if (__builtin_expect(env->singlestep_enabled, 0)) {

        /* Make sure the pc is updated, and raise a debug exception.  */

        if (dc->condjmp) {

            gen_op_debug();

            gen_set_label(dc->condlabel);

        }

        if (dc->condjmp || !dc->is_jmp) {

            gen_op_movl_T0_im((long)dc->pc);

            gen_op_movl_reg_TN[0][15]();

            dc->condjmp = 0;

        }

        gen_op_debug();

    } else {

        switch(dc->is_jmp) {

        case DISAS_NEXT:

            gen_goto_tb(dc, 1, dc->pc);

            break;

        default:

        case DISAS_JUMP:

        case DISAS_UPDATE:

            /* indicate that the hash table must be used to find the next TB */

            gen_op_movl_T0_0();

            gen_op_exit_tb();

            break;

        case DISAS_TB_JUMP:

            /* nothing more to generate */

            break;

        }

        if (dc->condjmp) {

            gen_set_label(dc->condlabel);

            gen_goto_tb(dc, 1, dc->pc);

            dc->condjmp = 0;

        }

    }

    *gen_opc_ptr = INDEX_op_end;



#ifdef DEBUG_DISAS

    if (loglevel & CPU_LOG_TB_IN_ASM) {

        fprintf(logfile, "----------------\n");

        fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));

        target_disas(logfile, pc_start, dc->pc - pc_start, env->thumb);

        fprintf(logfile, "\n");

        if (loglevel & (CPU_LOG_TB_OP)) {

            fprintf(logfile, "OP:\n");

            dump_ops(gen_opc_buf, gen_opparam_buf);

            fprintf(logfile, "\n");

        }

    }

#endif

    if (search_pc) {

        j = gen_opc_ptr - gen_opc_buf;

        lj++;

        while (lj <= j)

            gen_opc_instr_start[lj++] = 0;

        tb->size = 0;

    } else {

        tb->size = dc->pc - pc_start;

    }

    return 0;

}