VirtualBox

Changeset 13301

Show
Ignore:
Timestamp:
10/15/08 22:17:20 (3 months ago)
Author:
vboxsync
Message:

more synchronization with QEMU - things get pretty hairy

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/src/recompiler_new/cpu-exec.c

    r13117 r13301  
    2828 */ 
    2929#include "config.h" 
     30#define CPU_NO_GLOBAL_REGS 
    3031#include "exec.h" 
    3132#include "disas.h" 
     33#include "tcg.h" 
    3234 
    3335#if !defined(CONFIG_SOFTMMU) 
     
    4547#endif 
    4648 
     49#if defined(__sparc__) && !defined(HOST_SOLARIS) 
     50// Work around ugly bugs in glibc that mangle global register contents 
     51#undef env 
     52#define env cpu_single_env 
     53#endif 
     54 
    4755int tb_invalidated_flag; 
    4856 
     
    5058//#define DEBUG_SIGNAL 
    5159 
    52 #if defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_M68K) 
    53 /* XXX: unify with i386 target */ 
     60 
    5461void cpu_loop_exit(void) 
    5562{ 
     63    /* NOTE: the register at this point must be saved by hand because 
     64       longjmp restore them */ 
     65    regs_to_env(); 
    5666    longjmp(env->jmp_env, 1); 
    5767} 
    58 #endif 
     68 
    5969#if !(defined(TARGET_SPARC) || defined(TARGET_SH4) || defined(TARGET_M68K)) 
    6070#define reg_T2 
     
    8393} 
    8494 
     95/* Execute the code without caching the generated code. An interpreter 
     96   could be used if available. */ 
     97static void cpu_exec_nocache(int max_cycles, TranslationBlock *orig_tb) 
     98{ 
     99    unsigned long next_tb; 
     100    TranslationBlock *tb; 
     101 
     102    /* Should never happen. 
     103       We only end up here when an existing TB is too long.  */ 
     104    if (max_cycles > CF_COUNT_MASK) 
     105        max_cycles = CF_COUNT_MASK; 
     106 
     107    tb = tb_gen_code(env, orig_tb->pc, orig_tb->cs_base, orig_tb->flags, 
     108                     max_cycles); 
     109    env->current_tb = tb; 
     110    /* execute the generated code */ 
     111    next_tb = tcg_qemu_tb_exec(tb->tc_ptr); 
     112 
     113    if ((next_tb & 3) == 2) { 
     114        /* Restore PC.  This may happen if async event occurs before 
     115           the TB starts executing.  */ 
     116        CPU_PC_FROM_TB(env, tb); 
     117    } 
     118    tb_phys_invalidate(tb, -1); 
     119    tb_free(tb); 
     120} 
    85121 
    86122static TranslationBlock *tb_find_slow(target_ulong pc, 
    87123                                      target_ulong cs_base, 
    88                                       unsigned int flags) 
     124                                      uint64_t flags) 
    89125{ 
    90126    TranslationBlock *tb, **ptb1; 
    91     int code_gen_size; 
    92127    unsigned int h; 
    93128    target_ulong phys_pc, phys_page1, phys_page2, virt_page2; 
    94     uint8_t *tc_ptr; 
    95  
    96     spin_lock(&tb_lock); 
    97129 
    98130    tb_invalidated_flag = 0; 
     
    128160    } 
    129161 not_found: 
    130     /* if no translated code available, then translate it now */ 
    131     tb = tb_alloc(pc); 
    132     if (!tb) { 
    133         /* flush must be done */ 
    134         tb_flush(env); 
    135         /* cannot fail at this point */ 
    136         tb = tb_alloc(pc); 
    137         /* don't forget to invalidate previous TB info */ 
    138         tb_invalidated_flag = 1; 
    139     } 
    140     tc_ptr = code_gen_ptr; 
    141     tb->tc_ptr = tc_ptr; 
    142     tb->cs_base = cs_base; 
    143     tb->flags = flags; 
    144     cpu_gen_code(env, tb, CODE_GEN_MAX_SIZE, &code_gen_size); 
    145     code_gen_ptr = (void *)(((unsigned long)code_gen_ptr + code_gen_size + CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1)); 
    146  
    147     /* check next page if needed */ 
    148     virt_page2 = (pc + tb->size - 1) & TARGET_PAGE_MASK; 
    149     phys_page2 = -1; 
    150     if ((pc & TARGET_PAGE_MASK) != virt_page2) { 
    151         phys_page2 = get_phys_addr_code(env, virt_page2); 
    152     } 
    153     tb_link_phys(tb, phys_pc, phys_page2); 
     162   /* if no translated code available, then translate it now */ 
     163    tb = tb_gen_code(env, pc, cs_base, flags, 0); 
    154164 
    155165 found: 
    156166    /* we add the TB in the virtual pc hash table */ 
    157167    env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)] = tb; 
    158     spin_unlock(&tb_lock); 
    159168    return tb; 
    160169} 
     
    164173    TranslationBlock *tb; 
    165174    target_ulong cs_base, pc; 
    166     unsigned int flags; 
     175    uint64_t flags; 
    167176 
    168177    /* we record a subset of the CPU state. It will 
     
    181190    if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)) 
    182191        flags |= (1 << 7); 
     192    flags |= (env->condexec_bits << 8); 
    183193    cs_base = 0; 
    184194    pc = env->regs[15]; 
    185195#elif defined(TARGET_SPARC) 
    186196#ifdef TARGET_SPARC64 
    187     // Combined FPU enable bits . PRIV . DMMU enabled . IMMU enabled 
    188     flags = (((env->pstate & PS_PEF) >> 1) | ((env->fprs & FPRS_FEF) << 2)) 
     197    // AM . Combined FPU enable bits . PRIV . DMMU enabled . IMMU enabled 
     198    flags = ((env->pstate & PS_AM) << 2) 
     199        | (((env->pstate & PS_PEF) >> 1) | ((env->fprs & FPRS_FEF) << 2)) 
    189200        | (env->pstate & PS_PRIV) | ((env->lsu & (DMMU_E | IMMU_E)) >> 2); 
    190201#else 
    191     // FPU enable . MMU enabled . MMU no-fault . Supervisor 
    192     flags = (env->psref << 3) | ((env->mmuregs[0] & (MMU_E | MMU_NF)) << 1) 
    193         | env->psrs; 
     202    // FPU enable . Supervisor 
     203    flags = (env->psref << 4) | env->psrs; 
    194204#endif 
    195205    cs_base = env->npc; 
    196206    pc = env->pc; 
    197207#elif defined(TARGET_PPC) 
    198     flags = (msr_pr << MSR_PR) | (msr_fp << MSR_FP) | 
    199         (msr_se << MSR_SE) | (msr_le << MSR_LE); 
     208    flags = env->hflags; 
    200209    cs_base = 0; 
    201210    pc = env->nip; 
     
    203212    flags = env->hflags & (MIPS_HFLAG_TMASK | MIPS_HFLAG_BMASK); 
    204213    cs_base = 0; 
    205     pc = env->PC; 
     214    pc = env->active_tc.PC; 
    206215#elif defined(TARGET_M68K) 
    207     flags = env->fpcr & M68K_FPCR_PREC; 
     216    flags = (env->fpcr & M68K_FPCR_PREC)  /* Bit  6 */ 
     217            | (env->sr & SR_S)            /* Bit  13 */ 
     218            | ((env->macsr >> 4) & 0xf);  /* Bits 0-3 */ 
    208219    cs_base = 0; 
    209220    pc = env->pc; 
    210221#elif defined(TARGET_SH4) 
    211     flags = env->sr & (SR_MD | SR_RB); 
    212     cs_base = 0;         /* XXXXX */ 
     222    flags = (env->flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL 
     223                    | DELAY_SLOT_TRUE | DELAY_SLOT_CLEARME))   /* Bits  0- 3 */ 
     224            | (env->fpscr & (FPSCR_FR | FPSCR_SZ | FPSCR_PR))  /* Bits 19-21 */ 
     225            | (env->sr & (SR_MD | SR_RB));                     /* Bits 29-30 */ 
     226    cs_base = 0; 
     227    pc = env->pc; 
     228#elif defined(TARGET_ALPHA) 
     229    flags = env->ps; 
     230    cs_base = 0; 
     231    pc = env->pc; 
     232#elif defined(TARGET_CRIS) 
     233    flags = env->pregs[PR_CCS] & (S_FLAG | P_FLAG | U_FLAG | X_FLAG); 
     234    flags |= env->dslot; 
     235    cs_base = 0; 
    213236    pc = env->pc; 
    214237#else 
     
    216239#endif 
    217240    tb = env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)]; 
    218     if (__builtin_expect(!tb || tb->pc != pc || tb->cs_base != cs_base || 
    219                          tb->flags != flags, 0)) { 
     241    if (unlikely(!tb || tb->pc != pc || tb->cs_base != cs_base || 
     242                 tb->flags != flags)) { 
    220243        tb = tb_find_slow(pc, cs_base, flags); 
    221         /* Note: we do it here to avoid a gcc bug on Mac OS X when 
    222            doing it in tb_find_slow */ 
    223         if (tb_invalidated_flag) { 
    224             /* as some TB could have been invalidated because 
    225                of memory exceptions while generating the code, we 
    226                must recompute the hash index here */ 
    227             T0 = 0; 
    228         } 
    229244    } 
    230245    return tb; 
    231246} 
    232  
    233247 
    234248/* main execution loop */ 
     
    241255#include "hostregs_helper.h" 
    242256    int ret, interrupt_request; 
    243     void (*gen_func)(void); 
    244257    TranslationBlock *tb; 
    245258    uint8_t *tc_ptr; 
    246  
    247 #if defined(TARGET_I386) 
    248     /* handle exit of HALTED state */ 
    249     if (env1->hflags & HF_HALTED_MASK) { 
    250         /* disable halt condition */ 
    251         if ((env1->interrupt_request & CPU_INTERRUPT_HARD) && 
    252             (env1->eflags & IF_MASK)) { 
    253             env1->hflags &= ~HF_HALTED_MASK; 
    254         } else { 
    255             return EXCP_HALTED; 
    256         } 
    257     } 
    258 #elif defined(TARGET_PPC) 
    259     if (env1->halted) { 
    260         if (env1->msr[MSR_EE] && 
    261             (env1->interrupt_request & 
    262              (CPU_INTERRUPT_HARD | CPU_INTERRUPT_TIMER))) { 
    263             env1->halted = 0; 
    264         } else { 
    265             return EXCP_HALTED; 
    266         } 
    267     } 
    268 #elif defined(TARGET_SPARC) 
    269     if (env1->halted) { 
    270         if ((env1->interrupt_request & CPU_INTERRUPT_HARD) && 
    271             (env1->psret != 0)) { 
    272             env1->halted = 0; 
    273         } else { 
    274             return EXCP_HALTED; 
    275         } 
    276     } 
    277 #elif defined(TARGET_ARM) 
    278     if (env1->halted) { 
    279         /* An interrupt wakes the CPU even if the I and F CPSR bits are 
    280            set.  */ 
    281         if (env1->interrupt_request 
    282             & (CPU_INTERRUPT_FIQ | CPU_INTERRUPT_HARD)) { 
    283             env1->halted = 0; 
    284         } else { 
    285             return EXCP_HALTED; 
    286         } 
    287     } 
    288 #elif defined(TARGET_MIPS) 
    289     if (env1->halted) { 
    290         if (env1->interrupt_request & 
    291             (CPU_INTERRUPT_HARD | CPU_INTERRUPT_TIMER)) { 
    292             env1->halted = 0; 
    293         } else { 
    294             return EXCP_HALTED; 
    295         } 
    296     } 
    297 #endif 
     259    unsigned long next_tb; 
     260 
     261    if (cpu_halted(env1) == EXCP_HALTED) 
     262        return EXCP_HALTED; 
    298263 
    299264    cpu_single_env = env1; 
     
    303268#include "hostregs_helper.h" 
    304269    env = env1; 
    305 #if defined(__sparc__) && !defined(HOST_SOLARIS) 
    306     /* we also save i7 because longjmp may not restore it */ 
    307     asm volatile ("mov %%i7, %0" : "=r" (saved_i7)); 
    308 #endif 
    309  
     270 
     271    env_to_regs(); 
    310272#if defined(TARGET_I386) 
    311  
    312     env_to_regs(); 
    313273    /* put eflags in CPU temporary format */ 
    314274    CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C); 
     
    316276    CC_OP = CC_OP_EFLAGS; 
    317277    env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C); 
     278#elif defined(TARGET_SPARC) 
     279#elif defined(TARGET_M68K) 
     280    env->cc_op = CC_OP_FLAGS; 
     281    env->cc_dest = env->sr & 0xf; 
     282    env->cc_x = (env->sr >> 4) & 1; 
     283#elif defined(TARGET_ALPHA) 
    318284#elif defined(TARGET_ARM) 
    319 #elif defined(TARGET_SPARC) 
    320 #if defined(reg_REGWPTR) 
    321     saved_regwptr = REGWPTR; 
    322 #endif 
    323285#elif defined(TARGET_PPC) 
    324286#elif defined(TARGET_MIPS) 
    325287#elif defined(TARGET_SH4) 
     288#elif defined(TARGET_CRIS) 
    326289    /* XXXXX */ 
    327290#else 
     
    345308            if (env->interrupt_request & CPU_INTERRUPT_RC) { 
    346309                env->exception_index = EXCP_RC; 
    347                 ASMAtomicAndS32(&env->interrupt_request, ~CPU_INTERRUPT_RC); 
     310                ASMAtomicAndS32((int32_t volatile *)&env->interrupt_request, ~CPU_INTERRUPT_RC); 
    348311                ret = env->exception_index; 
    349312                cpu_loop_exit(); 
     
    367330                                 env->error_code, 
    368331                                 env->exception_next_eip, 0); 
     332                    /* successfully delivered */ 
     333                    env->old_exception = -1; 
    369334                    RAWEx_ProfileStop(env, STATS_IRQ_HANDLING); 
    370335                } 
     
    372337            } 
    373338 
    374             T0 = 0; /* force lookup of first TB */ 
     339            next_tb = 0; /* force lookup of first TB */ 
    375340            for(;;) 
    376341            { 
     
    378343                if (__builtin_expect(interrupt_request, 0)) 
    379344                { 
     345                    /** @todo: reconscille with what QEMU really does */ 
     346 
    380347                    /* Single instruction exec request, we execute it and return (one way or the other). 
    381348                       The caller will always reschedule after doing this operation! */ 
     
    385352                        if (!(env->interrupt_request & CPU_INTERRUPT_SINGLE_INSTR_IN_FLIGHT)) 
    386353                        { 
    387                             ASMAtomicOrS32(&env->interrupt_request, CPU_INTERRUPT_SINGLE_INSTR_IN_FLIGHT); 
     354                            ASMAtomicOrS32((int32_t volatile *)&env->interrupt_request, CPU_INTERRUPT_SINGLE_INSTR_IN_FLIGHT); 
    388355                            env->exception_index = EXCP_SINGLE_INSTR; 
    389356                            if (emulate_single_instr(env) == -1) 
     
    405372                        } 
    406373                        /* Clear CPU_INTERRUPT_SINGLE_INSTR and leave CPU_INTERRUPT_SINGLE_INSTR_IN_FLIGHT set. */ 
    407                         ASMAtomicAndS32(&env->interrupt_request, ~CPU_INTERRUPT_SINGLE_INSTR); 
     374                        ASMAtomicAndS32((int32_t volatile *)&env->interrupt_request, ~CPU_INTERRUPT_SINGLE_INSTR); 
    408375                    } 
    409376 
     
    413380                        env->interrupt_request &= ~CPU_INTERRUPT_SMI; 
    414381                        do_smm_enter(); 
    415                         T0 = 0; 
     382                        next_tb = 0; 
    416383                    } 
    417384                    else if ((interrupt_request & CPU_INTERRUPT_HARD) && 
     
    421388                        /* if hardware interrupt pending, we execute it */ 
    422389                        int intno; 
    423                         ASMAtomicAndS32(&env->interrupt_request, ~CPU_INTERRUPT_HARD); 
     390                        ASMAtomicAndS32((int32_t volatile *)&env->interrupt_request, ~CPU_INTERRUPT_HARD); 
    424391                        intno = cpu_get_pic_interrupt(env); 
    425392                        if (intno >= 0) 
     
    430397                        /* ensure that no TB jump will be modified as 
    431398                           the program flow was changed */ 
    432                         T0 = 0; 
     399                        next_tb = 0; 
    433400                    } 
    434401                    if (env->interrupt_request & CPU_INTERRUPT_EXITTB) 
    435402                    { 
    436                         ASMAtomicAndS32(&env->interrupt_request, ~CPU_INTERRUPT_EXITTB); 
     403                        ASMAtomicAndS32((int32_t volatile *)&env->interrupt_request, ~CPU_INTERRUPT_EXITTB); 
    437404                        /* ensure that no TB jump will be modified as 
    438405                           the program flow was changed */ 
    439                         T0 = 0; 
     406                        next_tb = 0; 
    440407                    } 
    441408                    RAWEx_ProfileStop(env, STATS_IRQ_HANDLING); 
     
    443410                    { 
    444411                        env->exception_index = EXCP_INTERRUPT; 
    445                         ASMAtomicAndS32(&env->interrupt_request, ~CPU_INTERRUPT_EXIT); 
     412                        ASMAtomicAndS32((int32_t volatile *)&env->interrupt_request, ~CPU_INTERRUPT_EXIT); 
    446413                        ret = env->exception_index; 
    447414                        cpu_loop_exit(); 
     
    450417                    { 
    451418                        env->exception_index = EXCP_RC; 
    452                         ASMAtomicAndS32(&env->interrupt_request, ~CPU_INTERRUPT_RC); 
     419                        ASMAtomicAndS32((int32_t volatile *)&env->interrupt_request, ~CPU_INTERRUPT_RC); 
    453420                        ret = env->exception_index; 
    454421                        cpu_loop_exit(); 
     
    472439 
    473440                RAWEx_ProfileStart(env, STATS_TLB_LOOKUP); 
     441                spin_lock(&tb_lock); 
    474442                tb = tb_find_fast(); 
     443                 /* Note: we do it here to avoid a gcc bug on Mac OS X when 
     444                   doing it in tb_find_slow */ 
     445                if (tb_invalidated_flag) { 
     446                    /* as some TB could have been invalidated because 
     447                       of memory exceptions while generating the code, we 
     448                       must recompute the hash index here */ 
     449                    next_tb = 0; 
     450                    tb_invalidated_flag = 0; 
     451                } 
    475452 
    476453                /* see if we can patch the calling TB. When the TB 
    477454                   spans two pages, we cannot safely do a direct 
    478455                   jump. */ 
    479                 if (T0 != 0 
     456                if (next_tb != 0 
    480457                    && !(tb->cflags & CF_RAW_MODE) 
    481458                    && tb->page_addr[1] == -1) 
    482459                { 
    483                     spin_lock(&tb_lock); 
    484                     tb_add_jump((TranslationBlock *)(long)(T0 & ~3), T0 & 3, tb); 
    485                     spin_unlock(&tb_lock); 
     460                    tb_add_jump((TranslationBlock *)(long)(next_tb & ~3), next_tb & 3, tb); 
    486461                } 
    487                 tc_ptr = tb->tc_ptr; 
     462                spin_unlock(&tb_lock); 
     463                RAWEx_ProfileStop(env, STATS_TLB_LOOKUP); 
     464 
    488465                env->current_tb = tb; 
    489                 /* execute the generated code */ 
    490                 gen_func = (void *)tc_ptr; 
    491                 RAWEx_ProfileStop(env, STATS_TLB_LOOKUP); 
    492  
    493 #if defined(DEBUG) && defined(VBOX) && !defined(DEBUG_dmik) 
    494 #if !defined(DEBUG_bird) 
    495                 if (((env->hflags >> HF_CPL_SHIFT) & 3) == 0 && (env->hflags & HF_PE_MASK) && (env->cr[0] & CR0_PG_MASK)) 
    496                 { 
    497                     if(!(env->state & CPU_EMULATE_SINGLE_STEP)) 
    498                     { 
    499                         Log(("EMR0: %VGv ESP=%VGv IF=%d TF=%d CPL=%d\n", env->eip, ESP, (env->eflags & IF_MASK) ? 1 : 0, (env->eflags & TF_MASK) ? 1 : 0, (env->hflags >> HF_CPL_SHIFT) & 3)); 
    500                     } 
     466                while (env->current_tb) { 
     467                    tc_ptr = tb->tc_ptr; 
     468                    /* execute the generated code */ 
     469                    RAWEx_ProfileStart(env, STATS_QEMU_RUN_EMULATED_CODE); 
     470                    next_tb = tcg_qemu_tb_exec(tc_ptr); 
     471                    RAWEx_ProfileStop(env, STATS_QEMU_RUN_EMULATED_CODE); 
     472                    env->current_tb = NULL; 
     473                     if ((next_tb & 3) == 2) { 
     474                        /* Instruction counter expired.  */ 
     475                        int insns_left; 
     476                        tb = (TranslationBlock *)(long)(next_tb & ~3); 
     477                        /* Restore PC.  */ 
     478                        CPU_PC_FROM_TB(env, tb); 
     479                        insns_left = env->icount_decr.u32; 
     480                        if (env->icount_extra && insns_left >= 0) { 
     481                            /* Refill decrementer and continue execution.  */ 
     482                            env->icount_extra += insns_left; 
     483                            if (env->icount_extra > 0xffff) { 
     484                                insns_left = 0xffff; 
     485                            } else { 
     486                                insns_left = env->icount_extra; 
     487                            } 
     488                            env->icount_extra -= insns_left; 
     489                            env->icount_decr.u16.low = insns_left; 
     490                        } else { 
     491                            if (insns_left > 0) { 
     492                                /* Execute remaining instructions.  */ 
     493                                cpu_exec_nocache(insns_left, tb); 
     494                            } 
     495                            env->exception_index = EXCP_INTERRUPT; 
     496                            next_tb = 0; 
     497                            cpu_loop_exit(); 
     498                        } 
     499                     } 
    501500                } 
    502                 else 
    503                 if (((env->hflags >> HF_CPL_SHIFT) & 3) == 3 && (env->hflags & HF_PE_MASK) && (env->cr[0] & CR0_PG_MASK)) 
    504                 { 
    505                     if(!(env->state & CPU_EMULATE_SINGLE_STEP)) 
    506                     { 
    507                         if(env->eflags & VM_MASK) 
    508                         { 
    509                             Log(("EMV86: %04X:%VGv IF=%d TF=%d CPL=%d CR0=%RGr\n", env->segs[R_CS].selector, env->eip, (env->eflags & IF_MASK) ? 1 : 0, (env->eflags & TF_MASK) ? 1 : 0, (env->hflags >> HF_CPL_SHIFT) & 3, env->cr[0])); 
    510                         } 
    511                         else 
    512                         { 
    513                             Log(("EMR3: %VGv ESP=%VGv IF=%d TF=%d CPL=%d IOPL=%d CR0=%RGr\n", env->eip, ESP, (env->eflags & IF_MASK) ? 1 : 0, (env->eflags & TF_MASK) ? 1 : 0, (env->hflags >> HF_CPL_SHIFT) & 3, ((env->eflags >> IOPL_SHIFT) & 3), env->cr[0])); 
    514                         } 
    515                     } 
    516                 } 
    517                 else 
    518                 { 
    519                     /* Seriously slows down realmode booting. */ 
    520                     LogFlow(("EMRM: %04X:%VGv SS:ESP=%04X:%VGv IF=%d TF=%d CPL=%d PE=%d PG=%d\n", env->segs[R_CS].selector, env->eip, env->segs[R_SS].selector, ESP, (env->eflags & IF_MASK) ? 1 : 0, (env->eflags & TF_MASK) ? 1 : 0, (env->hflags >> HF_CPL_SHIFT) & 3, env->cr[0] & X86_CR0_PE, env->cr[0] & X86_CR0_PG)); 
    521                 } 
    522 #endif /* !DEBUG_bird */ 
    523                 if(env->state & CPU_EMULATE_SINGLE_STEP) 
    524                 { 
    525 #ifdef DEBUG_bird 
    526                     static int s_cTimes = 0; 
    527                     if (s_cTimes++ > 1000000) 
    528                     { 
    529                         RTLogPrintf("Enough stepping!\n"); 
    530                         #if 0 
    531                         env->exception_index = EXCP_DEBUG; 
    532                         ret = env->exception_index; 
    533                         cpu_loop_exit(); 
    534                         #else 
    535                         env->state &= ~CPU_EMULATE_SINGLE_STEP; 
    536                         #endif 
    537                     } 
    538 #endif 
    539                     TMCpuTickPause(env->pVM); 
    540                     remR3DisasInstr(env, -1, NULL); 
    541                     TMCpuTickResume(env->pVM); 
    542                     if(emulate_single_instr(env) == -1) 
    543                     { 
    544                         Log(("emulate_single_instr failed for EIP=%VGv!!\n", env->eip)); 
    545                     } 
    546                 } 
    547                 else 
    548                 { 
    549                     RAWEx_ProfileStart(env, STATS_QEMU_RUN_EMULATED_CODE); 
    550                     gen_func(); 
    551                     RAWEx_ProfileStop(env, STATS_QEMU_RUN_EMULATED_CODE); 
    552                 } 
    553 #else /* !DEBUG || !VBOX || DEBUG_dmik */ 
    554  
    555                 RAWEx_ProfileStart(env, STATS_QEMU_RUN_EMULATED_CODE); 
    556                 gen_func(); 
    557                 RAWEx_ProfileStop(env, STATS_QEMU_RUN_EMULATED_CODE); 
    558  
    559 #endif /* !DEBUG || !VBOX || DEBUG_dmik */ 
    560                 env->current_tb = NULL; 
     501                     
    561502                /* reset soft MMU for next block (it can currently 
    562503                   only be set by a memory fault) */ 
     
    565506                    env->hflags &= ~HF_SOFTMMU_MASK; 
    566507                    /* do not allow linking to another block */ 
    567                     T0 = 0; 
     508                    next_tb = 0; 
    568509                } 
    569510#endif 
    570             } 
     511            } /* for(;;) */ 
    571512        } else { 
    572513            env_to_regs(); 
     
    590531} 
    591532 
    592  
    593533#else /* !VBOX */ 
    594  
    595  
    596534int cpu_exec(CPUState *env1) 
    597535{ 
    598536#define DECLARE_HOST_REGS 1 
    599537#include "hostregs_helper.h" 
    600 #if defined(__sparc__) && !defined(HOST_SOLARIS) 
    601     int saved_i7; 
    602     target_ulong tmp_T0; 
    603 #endif 
    604538    int ret, interrupt_request; 
    605     void (*gen_func)(void); 
    606539    TranslationBlock *tb; 
    607540    uint8_t *tc_ptr; 
    608  
    609 #if defined(TARGET_I386) 
    610     /* handle exit of HALTED state */ 
    611     if (env1->hflags & HF_HALTED_MASK) { 
    612         /* disable halt condition */ 
    613         if ((env1->interrupt_request & CPU_INTERRUPT_HARD) && 
    614             (env1->eflags & IF_MASK)) { 
    615             env1->hflags &= ~HF_HALTED_MASK; 
    616         } else { 
    617             return EXCP_HALTED; 
    618         } 
    619     } 
    620 #elif defined(TARGET_PPC) 
    621     if (env1->halted) { 
    622         if (env1->msr[MSR_EE] && 
    623             (env1->interrupt_request & 
    624              (CPU_INTERRUPT_HARD | CPU_INTERRUPT_TIMER))) { 
    625             env1->halted = 0; 
    626         } else { 
    627             return EXCP_HALTED; 
    628         } 
    629     } 
    630 #elif defined(TARGET_SPARC) 
    631     if (env1->halted) { 
    632         if ((env1->interrupt_request & CPU_INTERRUPT_HARD) && 
    633             (env1->psret != 0)) { 
    634             env1->halted = 0; 
    635         } else { 
    636             return EXCP_HALTED; 
    637         } 
    638     } 
    639 #elif defined(TARGET_ARM) 
    640     if (env1->halted) { 
    641         /* An interrupt wakes the CPU even if the I and F CPSR bits are 
    642            set.  */ 
    643         if (env1->interrupt_request 
    644             & (CPU_INTERRUPT_FIQ | CPU_INTERRUPT_HARD)) { 
    645             env1->halted = 0; 
    646         } else { 
    647             return EXCP_HALTED; 
    648         } 
    649     } 
    650 #elif defined(TARGET_MIPS) 
    651     if (env1->halted) { 
    652         if (env1->interrupt_request & 
    653             (CPU_INTERRUPT_HARD | CPU_INTERRUPT_TIMER)) { 
    654             env1->halted = 0; 
    655         } else { 
    656             return EXCP_HALTED; 
    657         } 
    658     } 
    659 #endif 
     541    unsigned long next_tb; 
     542 
     543    if (cpu_halted(env1) == EXCP_HALTED) 
     544        return EXCP_HALTED; 
    660545 
    661546    cpu_single_env = env1; 
     
    665550#include "hostregs_helper.h" 
    666551    env = env1; 
    667 #if defined(__sparc__) && !defined(HOST_SOLARIS) 
    668     /* we also save i7 because longjmp may not restore it */ 
    669     asm volatile ("mov %%i7, %0" : "=r" (saved_i7)); 
    670 #endif 
    671  
     552 
     553    env_to_regs(); 
    672554#if defined(TARGET_I386) 
    673     env_to_regs(); 
    674555    /* put eflags in CPU temporary format */ 
    675556    CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C); 
     
    677558    CC_OP = CC_OP_EFLAGS; 
    678559    env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C); 
    679 #elif defined(TARGET_ARM) 
    680560#elif defined(TARGET_SPARC) 
    681 #if defined(reg_REGWPTR) 
    682     saved_regwptr = REGWPTR; 
    683 #endif 
    684 #elif defined(TARGET_PPC) 
    685561#elif defined(TARGET_M68K) 
    686562    env->cc_op = CC_OP_FLAGS; 
    687563    env->cc_dest = env->sr & 0xf; 
    688564    env->cc_x = (env->sr >> 4) & 1; 
     565#elif defined(TARGET_ALPHA) 
     566#elif defined(TARGET_ARM) 
     567#elif defined(TARGET_PPC) 
    689568#elif defined(TARGET_MIPS) 
    690569#elif defined(TARGET_SH4) 
     570#elif defined(TARGET_CRIS) 
    691571    /* XXXXX */ 
    692572#else 
    693573#error unsupported target CPU 
    694574#endif 
    695 #ifndef VBOX /* VBOX: We need to raise traps and suchlike from the outside. */ 
    696575    env->exception_index = -1; 
    697 #endif 
    698576 
    699577    /* prepare setjmp context for exception handling */ 
     
    701579        if (setjmp(env->jmp_env) == 0) { 
    702580            env->current_tb = NULL; 
    703 #ifdef VBOX 
    704             VMMR3Unlock(env->pVM); 
    705             VMMR3Lock(env->pVM); 
    706  
    707             /* Check for high priority requests first (like fatal 
    708                errors). */ 
    709             if (env->interrupt_request & CPU_INTERRUPT_RC) { 
    710                 env->exception_index = EXCP_RC; 
    711                 ASMAtomicAndS32(&env->interrupt_request, ~CPU_INTERRUPT_RC); 
    712                 ret = env->exception_index; 
    713                 cpu_loop_exit(); 
    714             } 
    715 #endif /* VBOX */ 
    716  
    717  
    718581            /* if an exception is pending, we execute it here */ 
    719582            if (env->exception_index >= 0) { 
     
    731594                                      env->error_code, 
    732595                                      env->exception_next_eip); 
     596                    /* successfully delivered */ 
     597                    env->old_exception = -1; 
    733598#endif 
    734599                    ret = env->exception_index; 
     
    743608                                 env->error_code, 
    744609                                 env->exception_next_eip, 0); 
     610                    /* successfully delivered */ 
     611                    env->old_exception = -1; 
    745612#elif defined(TARGET_PPC) 
    746613                    do_interrupt(env); 
     
    748615                    do_interrupt(env); 
    749616#elif defined(TARGET_SPARC) 
    750                     do_interrupt(env->exception_index); 
     617                    do_interrupt(env); 
    751618#elif defined(TARGET_ARM) 
    752619                    do_interrupt(env); 
    753620#elif defined(TARGET_SH4) 
    754621                    do_interrupt(env); 
     622#elif defined(TARGET_ALPHA) 
     623                    do_interrupt(env); 
     624#elif defined(TARGET_CRIS) 
     625                    do_interrupt(env); 
     626#elif defined(TARGET_M68K) 
     627                    do_interrupt(0); 
    755628#endif 
    756629                } 
     
    783656#endif 
    784657 
    785             T0 = 0; /* force lookup of first TB */ 
     658            next_tb = 0; /* force lookup of first TB */ 
    786659            for(;;) { 
    787 #if defined(__sparc__) && !defined(HOST_SOLARIS) 
    788                 /* g1 can be modified by some libc? functions */ 
    789                 tmp_T0 = T0; 
    790 #endif 
    791660                interrupt_request = env->interrupt_request; 
    792                 if (__builtin_expect(interrupt_request, 0)) { 
    793 #ifdef VBOX 
    794                     /* Single instruction exec request, we execute it and return (one way or the other). 
    795                        The caller will always reschedule after doing this operation! */ 
    796                     if (interrupt_request & CPU_INTERRUPT_SINGLE_INSTR) 
    797                     { 
    798                         /* not in flight are we? */ 
    799                         if (!(env->interrupt_request & CPU_INTERRUPT_SINGLE_INSTR_IN_FLIGHT)) 
    800                         { 
    801                             ASMAtomicOrS32(&env->interrupt_request, CPU_INTERRUPT_SINGLE_INSTR_IN_FLIGHT); 
    802                             env->exception_index = EXCP_SINGLE_INSTR; 
    803                             if (emulate_single_instr(env) == -1) 
    804                                 AssertMsgFailed(("REM: emulate_single_instr failed for EIP=%VGv!!\n", env->eip)); 
    805  
    806                             /* When we receive an external interrupt during execution of this single 
    807                                instruction, then we should stay here. We will leave when we're ready 
    808                                for raw-mode or when interrupted by pending EMT requests.  */ 
    809                             interrupt_request = env->interrupt_request; /* reload this! */ 
    810                             if (   !(interrupt_request & CPU_INTERRUPT_HARD) 
    811                                 || !(env->eflags & IF_MASK) 
    812                                 ||  (env->hflags & HF_INHIBIT_IRQ_MASK) 
    813                                ) 
    814                             { 
    815                                 env->exception_index = ret = EXCP_SINGLE_INSTR; 
    816                                 cpu_loop_exit(); 
     661                if (unlikely(interrupt_request) && 
     662                    likely(!(env->singlestep_enabled & SSTEP_NOIRQ))) { 
     663                    if (interrupt_request & CPU_INTERRUPT_DEBUG) { 
     664                        env->interrupt_request &= ~CPU_INTERRUPT_DEBUG; 
     665                        env->exception_index = EXCP_DEBUG; 
     666                        cpu_loop_exit(); 
     667                    } 
     668#if defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_MIPS) || \ 
     669    defined(TARGET_PPC) || defined(TARGET_ALPHA) || defined(TARGET_CRIS) 
     670                    if (interrupt_request & CPU_INTERRUPT_HALT) { 
     671                        env->interrupt_request &= ~CPU_INTERRUPT_HALT; 
     672                        env->halted = 1; 
     673                        env->exception_index = EXCP_HLT; 
     674                        cpu_loop_exit(); 
     675                    } 
     676#endif 
     677#if defined(TARGET_I386) 
     678                    if (env->hflags2 & HF2_GIF_MASK) { 
     679                        if ((interrupt_request & CPU_INTERRUPT_SMI) && 
     680                            !(env->hflags & HF_SMM_MASK)) { 
     681                            svm_check_intercept(SVM_EXIT_SMI); 
     682                            env->interrupt_request &= ~CPU_INTERRUPT_SMI; 
     683                            do_smm_enter(); 
     684                            next_tb = 0; 
     685                        } else if ((interrupt_request & CPU_INTERRUPT_NMI) && 
     686                                   !(env->hflags2 & HF2_NMI_MASK)) { 
     687                            env->interrupt_request &= ~CPU_INTERRUPT_NMI; 
     688                            env->hflags2 |= HF2_NMI_MASK; 
     689                            do_interrupt(EXCP02_NMI, 0, 0, 0, 1); 
     690                            next_tb = 0; 
     691                        } else if ((interrupt_request & CPU_INTERRUPT_HARD) && 
     692                                   (((env->hflags2 & HF2_VINTR_MASK) &&  
     693                                     (env->hflags2 & HF2_HIF_MASK)) || 
     694                                    (!(env->hflags2 & HF2_VINTR_MASK) &&  
     695                                     (env->eflags & IF_MASK &&  
     696                                      !(env->hflags & HF_INHIBIT_IRQ_MASK))))) { 
     697                            int intno; 
     698                            svm_check_intercept(SVM_EXIT_INTR); 
     699                            env->interrupt_request &= ~(CPU_INTERRUPT_HARD | CPU_INTERRUPT_VIRQ); 
     700                            intno = cpu_get_pic_interrupt(env); 
     701                            if (loglevel & CPU_LOG_TB_IN_ASM) { 
     702                                fprintf(logfile, "Servicing hardware INT=0x%02x\n", intno); 
    817703                            } 
     704                            do_interrupt(intno, 0, 0, 0, 1); 
     705                            /* ensure that no TB jump will be modified as 
     706                               the program flow was changed */ 
     707                            next_tb = 0; 
     708#if !defined(CONFIG_USER_ONLY) 
     709                        } else if ((interrupt_request & CPU_INTERRUPT_VIRQ) && 
     710                                   (env->eflags & IF_MASK) &&  
     711                                   !(env->hflags & HF_INHIBIT_IRQ_MASK)) { 
     712                            int intno; 
     713                            /* FIXME: this should respect TPR */ 
     714                            svm_check_intercept(SVM_EXIT_VINTR); 
     715                            env->interrupt_request &= ~CPU_INTERRUPT_VIRQ; 
     716                            intno = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_vector)); 
     717                            if (loglevel & CPU_LOG_TB_IN_ASM) 
     718                                fprintf(logfile, "Servicing virtual hardware INT=0x%02x\n", intno); 
     719                            do_interrupt(intno, 0, 0, 0, 1); 
     720                            next_tb = 0; 
     721#endif 
    818722                        } 
    819                         env->exception_index = EXCP_SINGLE_INSTR; 
    820                         cpu_loop_exit(); 
    821                     } 
    822  
    823                     RAWEx_ProfileStart(env, STATS_IRQ_HANDLING); 
    824 #endif /* VBOX */ 
    825 #if defined(TARGET_I386) 
    826                     if ((interrupt_request & CPU_INTERRUPT_SMI) && 
    827                         !(env->hflags & HF_SMM_MASK)) { 
    828                         env->interrupt_request &= ~CPU_INTERRUPT_SMI; 
    829                         do_smm_enter(); 
    830 #if defined(__sparc__) && !defined(HOST_SOLARIS) 
    831                         tmp_T0 = 0; 
    832 #else 
    833                         T0 = 0; 
    834 #endif 
    835                     } else if ((interrupt_request & CPU_INTERRUPT_HARD) && 
    836                         (env->eflags & IF_MASK) && 
    837                         !(env->hflags & HF_INHIBIT_IRQ_MASK)) { 
    838                         int intno; 
    839 #if defined(VBOX) 
    840                         ASMAtomicAndS32(&env->interrupt_request, ~CPU_INTERRUPT_HARD); 
    841 #else 
    842                         env->interrupt_request &= ~CPU_INTERRUPT_HARD; 
    843 #endif 
    844                         intno = cpu_get_pic_interrupt(env); 
    845                         if (loglevel & CPU_LOG_TB_IN_ASM) { 
    846                             fprintf(logfile, "Servicing hardware INT=0x%02x\n", intno); 
    847                         } 
    848 #if defined(VBOX) 
    849                         if (intno >= 0) 
    850 #endif 
    851                         do_interrupt(intno, 0, 0, 0, 1); 
    852                         /* ensure that no TB jump will be modified as 
    853                            the program flow was changed */ 
    854 #if defined(__sparc__) && !defined(HOST_SOLARIS) 
    855                         tmp_T0 = 0; 
    856 #else 
    857                         T0 = 0; 
    858 #endif 
    859723                    } 
    860724#elif defined(TARGET_PPC) 
     
    864728                    } 
    865729#endif 
    866                     if (msr_ee != 0) { 
    867                         if ((interrupt_request & CPU_INTERRUPT_HARD)) { 
    868                             /* Raise it */ 
    869                             env->exception_index = EXCP_EXTERNAL; 
    870