static Bits IOFaultCore(void) { CPU_CycleLeft+=CPU_Cycles; CPU_Cycles=1; Bits ret=CPU_Core_Full_Run(); CPU_CycleLeft+=CPU_Cycles; if (ret<0) E_Exit("Got a dosbox close machine in IO-fault core?"); if (ret) return ret; if (!iof_queue.used) E_Exit("IO-faul Core without IO-faul"); IOF_Entry * entry=&iof_queue.entries[iof_queue.used-1]; if (entry->cs == SegValue(cs) && entry->eip==reg_eip) return -1; return 0; }
Bits CPU_Core_Dynrec_Run(void) { for (;;) { // Determine the linear address of CS:EIP PhysPt ip_point=SegPhys(cs)+reg_eip; #if C_HEAVY_DEBUG if (DEBUG_HeavyIsBreakpoint()) return debugCallback; #endif CodePageHandlerDynRec * chandler=0; // see if the current page is present and contains code if (GCC_UNLIKELY(MakeCodePage(ip_point,chandler))) { // page not present, throw the exception CPU_Exception(cpu.exception.which,cpu.exception.error); continue; } // page doesn't contain code or is special if (GCC_UNLIKELY(!chandler)) return CPU_Core_Normal_Run(); // find correct Dynamic Block to run CacheBlockDynRec * block=chandler->FindCacheBlock(ip_point&4095); if (!block) { // no block found, thus translate the instruction stream // unless the instruction is known to be modified if (!chandler->invalidation_map || (chandler->invalidation_map[ip_point&4095]<4)) { // translate up to 32 instructions block=CreateCacheBlock(chandler,ip_point,32); } else { // let the normal core handle this instruction to avoid zero-sized blocks Bitu old_cycles=CPU_Cycles; CPU_Cycles=1; Bits nc_retcode=CPU_Core_Normal_Run(); if (!nc_retcode) { CPU_Cycles=old_cycles-1; continue; } CPU_CycleLeft+=old_cycles; return nc_retcode; } } run_block: cache.block.running=0; // now we're ready to run the dynamic code block // BlockReturn ret=((BlockReturn (*)(void))(block->cache.start))(); BlockReturn ret=core_dynrec.runcode(block->cache.start); switch (ret) { case BR_Iret: #if C_HEAVY_DEBUG if (DEBUG_HeavyIsBreakpoint()) return debugCallback; #endif if (!GETFLAG(TF)) { if (GETFLAG(IF) && PIC_IRQCheck) return CBRET_NONE; break; } // trapflag is set, switch to the trap-aware decoder cpudecoder=CPU_Core_Dynrec_Trap_Run; return CBRET_NONE; case BR_Normal: // the block was exited due to a non-predictable control flow // modifying instruction (like ret) or some nontrivial cpu state // changing instruction (for example switch to/from pmode), // or the maximal number of instructions to translate was reached #if C_HEAVY_DEBUG if (DEBUG_HeavyIsBreakpoint()) return debugCallback; #endif break; case BR_Cycles: // cycles went negative, return from the core to handle // external events, schedule the pic... #if C_HEAVY_DEBUG if (DEBUG_HeavyIsBreakpoint()) return debugCallback; #endif return CBRET_NONE; case BR_CallBack: // the callback code is executed in dosbox.conf, return the callback number FillFlags(); return core_dynrec.callback; case BR_SMCBlock: // LOG_MSG("selfmodification of running block at %x:%x",SegValue(cs),reg_eip); cpu.exception.which=0; // fallthrough, let the normal core handle the block-modifying instruction case BR_Opcode: // some instruction has been encountered that could not be translated // (thus it is not part of the code block), the normal core will // handle this instruction CPU_CycleLeft+=CPU_Cycles; CPU_Cycles=1; return CPU_Core_Normal_Run(); #if (C_DEBUG) case BR_OpcodeFull: CPU_CycleLeft+=CPU_Cycles; CPU_Cycles=1; return CPU_Core_Full_Run(); #endif case BR_Link1: case BR_Link2: block=LinkBlocks(ret); if (block) goto run_block; break; default: E_Exit("Invalid return code %d", ret); } } return CBRET_NONE; }