void Interpreter::SingleStep() { SingleStepInner(); CoreTiming::slicelength = 1; PowerPC::ppcState.downcount = 0; CoreTiming::Advance(); if (PowerPC::ppcState.Exceptions) { PowerPC::CheckExceptions(); PC = NPC; } }
void Interpreter::SingleStep() { // Declare start of new slice CoreTiming::Advance(); SingleStepInner(); // The interpreter ignores instruction timing information outside the 'fast runloop'. CoreTiming::g.slice_length = 1; PowerPC::ppcState.downcount = 0; if (PowerPC::ppcState.Exceptions) { PowerPC::CheckExceptions(); PC = NPC; } }
// FastRun - inspired by GCemu (to imitate the JIT so that they can be compared). void Interpreter::Run() { while (!PowerPC::GetState()) { //we have to check exceptions at branches apparently (or maybe just rfi?) if (SConfig::GetInstance().bEnableDebugging) { #ifdef SHOW_HISTORY PCBlockVec.push_back(PC); if (PCBlockVec.size() > ShowBlocks) PCBlockVec.erase(PCBlockVec.begin()); #endif // Debugging friendly version of inner loop. Tries to do the timing as similarly to the // JIT as possible. Does not take into account that some instructions take multiple cycles. while (PowerPC::ppcState.downcount > 0) { m_EndBlock = false; int i; for (i = 0; !m_EndBlock; i++) { #ifdef SHOW_HISTORY PCVec.push_back(PC); if (PCVec.size() > ShowSteps) PCVec.erase(PCVec.begin()); #endif //2: check for breakpoint if (PowerPC::breakpoints.IsAddressBreakPoint(PC)) { #ifdef SHOW_HISTORY NOTICE_LOG(POWERPC, "----------------------------"); NOTICE_LOG(POWERPC, "Blocks:"); for (int j = 0; j < PCBlockVec.size(); j++) NOTICE_LOG(POWERPC, "PC: 0x%08x", PCBlockVec.at(j)); NOTICE_LOG(POWERPC, "----------------------------"); NOTICE_LOG(POWERPC, "Steps:"); for (int j = 0; j < PCVec.size(); j++) { // Write space if (j > 0) { if (PCVec.at(j) != PCVec.at(j-1) + 4) NOTICE_LOG(POWERPC, ""); } NOTICE_LOG(POWERPC, "PC: 0x%08x", PCVec.at(j)); } #endif INFO_LOG(POWERPC, "Hit Breakpoint - %08x", PC); CCPU::Break(); if (PowerPC::breakpoints.IsTempBreakPoint(PC)) PowerPC::breakpoints.Remove(PC); Host_UpdateDisasmDialog(); return; } SingleStepInner(); } PowerPC::ppcState.downcount -= i; } } else { // "fast" version of inner loop. well, it's not so fast. while (PowerPC::ppcState.downcount > 0) { m_EndBlock = false; int cycles = 0; while (!m_EndBlock) { cycles += SingleStepInner(); } PowerPC::ppcState.downcount -= cycles; } } CoreTiming::Advance(); if (PowerPC::ppcState.Exceptions) { PowerPC::CheckExceptions(); PC = NPC; } } // Let the waiting thread know we are done leaving PowerPC::FinishStateMove(); }
// FastRun - inspired by GCemu (to imitate the JIT so that they can be compared). void Interpreter::Run() { while (CPU::GetState() == CPU::State::Running) { // CoreTiming Advance() ends the previous slice and declares the start of the next // one so it must always be called at the start. At boot, we are in slice -1 and must // advance into slice 0 to get a correct slice length before executing any cycles. CoreTiming::Advance(); // we have to check exceptions at branches apparently (or maybe just rfi?) if (SConfig::GetInstance().bEnableDebugging) { #ifdef SHOW_HISTORY PCBlockVec.push_back(PC); if (PCBlockVec.size() > ShowBlocks) PCBlockVec.erase(PCBlockVec.begin()); #endif // Debugging friendly version of inner loop. Tries to do the timing as similarly to the // JIT as possible. Does not take into account that some instructions take multiple cycles. while (PowerPC::ppcState.downcount > 0) { m_end_block = false; int i; for (i = 0; !m_end_block; i++) { #ifdef SHOW_HISTORY PCVec.push_back(PC); if (PCVec.size() > ShowSteps) PCVec.erase(PCVec.begin()); #endif // 2: check for breakpoint if (PowerPC::breakpoints.IsAddressBreakPoint(PC)) { #ifdef SHOW_HISTORY NOTICE_LOG(POWERPC, "----------------------------"); NOTICE_LOG(POWERPC, "Blocks:"); for (int j = 0; j < PCBlockVec.size(); j++) NOTICE_LOG(POWERPC, "PC: 0x%08x", PCBlockVec.at(j)); NOTICE_LOG(POWERPC, "----------------------------"); NOTICE_LOG(POWERPC, "Steps:"); for (int j = 0; j < PCVec.size(); j++) { // Write space if (j > 0) { if (PCVec.at(j) != PCVec.at(j - 1) + 4) NOTICE_LOG(POWERPC, ""); } NOTICE_LOG(POWERPC, "PC: 0x%08x", PCVec.at(j)); } #endif INFO_LOG(POWERPC, "Hit Breakpoint - %08x", PC); CPU::Break(); if (PowerPC::breakpoints.IsTempBreakPoint(PC)) PowerPC::breakpoints.Remove(PC); Host_UpdateDisasmDialog(); return; } SingleStepInner(); } PowerPC::ppcState.downcount -= i; } } else { // "fast" version of inner loop. well, it's not so fast. while (PowerPC::ppcState.downcount > 0) { m_end_block = false; int cycles = 0; while (!m_end_block) { cycles += SingleStepInner(); } PowerPC::ppcState.downcount -= cycles; } } } }