示例#1
0
文件: CPU.cpp 项目: Catnips/dolphin
void CCPU::Run()
{
	std::lock_guard<std::mutex> lk(m_csCpuOccupied);
	Host_UpdateDisasmDialog();

	while (true)
	{
reswitch:
		switch (PowerPC::GetState())
		{
		case PowerPC::CPU_RUNNING:
			//1: enter a fast runloop
			PowerPC::RunLoop();
			break;

		case PowerPC::CPU_STEPPING:
			m_csCpuOccupied.unlock();

			//1: wait for step command..
			m_StepEvent.Wait();

			m_csCpuOccupied.lock();
			if (PowerPC::GetState() == PowerPC::CPU_POWERDOWN)
				return;
			if (PowerPC::GetState() != PowerPC::CPU_STEPPING)
				goto reswitch;

			//3: do a step
			PowerPC::SingleStep();

			//4: update disasm dialog
			if (m_SyncEvent)
			{
				m_SyncEvent->Set();
				m_SyncEvent = nullptr;
			}
			Host_UpdateDisasmDialog();
			break;

		case PowerPC::CPU_POWERDOWN:
			//1: Exit loop!!
			return;
		}
	}
}
示例#2
0
void Stop()
{
	volatile CPUState old_state = state;
	state = CPU_POWERDOWN;

	// Wait for the CPU core to leave
	if (old_state == CPU_RUNNING)
		s_state_change.WaitFor(std::chrono::seconds(1));
	Host_UpdateDisasmDialog();
}
示例#3
0
void gdb_handle_exception()
{
  while (gdb_active())
  {
    if (!gdb_data_available())
      continue;
    gdb_read_command();
    if (cmd_len == 0)
      continue;

    switch (cmd_bfr[0])
    {
    case 'q':
      gdb_handle_query();
      break;
    case 'H':
      gdb_handle_set_thread();
      break;
    case '?':
      gdb_handle_signal();
      break;
    case 'k':
      gdb_deinit();
      INFO_LOG(GDB_STUB, "killed by gdb");
      return;
    case 'g':
      gdb_read_registers();
      break;
    case 'G':
      gdb_write_registers();
      break;
    case 'p':
      gdb_read_register();
      break;
    case 'P':
      gdb_write_register();
      break;
    case 'm':
      gdb_read_mem();
      break;
    case 'M':
      gdb_write_mem();
      PowerPC::ppcState.iCache.Reset();
      Host_UpdateDisasmDialog();
      break;
    case 's':
      gdb_step();
      return;
    case 'C':
    case 'c':
      gdb_continue();
      return;
    case 'z':
      gdb_remove_bp();
      break;
    case 'Z':
      _gdb_add_bp();
      break;
    default:
      gdb_reply("");
      break;
    }
  }
}
示例#4
0
void Start()
{
	state = CPU_RUNNING;
	Host_UpdateDisasmDialog();
}
示例#5
0
void RunLoop()
{
	state = CPU_RUNNING;
	cpu_core_base->Run();
	Host_UpdateDisasmDialog();
}
示例#6
0
void RunLoop()
{
	s_cpu_core_base->Run();
	Host_UpdateDisasmDialog();
}
// Initialize and create emulation thread
// Call browser: Init():s_emu_thread().
// See the BootManager.cpp file description for a complete call schedule.
void EmuThread()
{
	const SCoreStartupParameter& core_parameter =
		SConfig::GetInstance().m_LocalCoreStartupParameter;

	Common::SetCurrentThreadName("Emuthread - Starting");

	if (SConfig::GetInstance().m_OCEnable)
		DisplayMessage("WARNING: running at non-native CPU clock! Game may not be stable.", 8000);
	DisplayMessage(cpu_info.brand_string, 8000);
	DisplayMessage(cpu_info.Summarize(), 8000);
	DisplayMessage(core_parameter.m_strFilename, 3000);

	Movie::Init();

	HW::Init();

	if (!g_video_backend->Initialize(s_window_handle))
	{
		PanicAlert("Failed to initialize video backend!");
		Host_Message(WM_USER_STOP);
		return;
	}

	OSD::AddMessage("Dolphin " + g_video_backend->GetName() + " Video Backend.", 5000);

	if (cpu_info.HTT)
		SConfig::GetInstance().m_LocalCoreStartupParameter.bDSPThread = cpu_info.num_cores > 4;
	else
		SConfig::GetInstance().m_LocalCoreStartupParameter.bDSPThread = cpu_info.num_cores > 2;

	if (!DSP::GetDSPEmulator()->Initialize(core_parameter.bWii, core_parameter.bDSPThread))
	{
		HW::Shutdown();
		g_video_backend->Shutdown();
		PanicAlert("Failed to initialize DSP emulator!");
		Host_Message(WM_USER_STOP);
		return;
	}

	Keyboard::Initialize(s_window_handle);
	Pad::Initialize(s_window_handle);

	// Load and Init Wiimotes - only if we are booting in Wii mode
	if (core_parameter.bWii)
	{
		Wiimote::Initialize(s_window_handle, !s_state_filename.empty());

		// Activate Wiimotes which don't have source set to "None"
		for (unsigned int i = 0; i != MAX_BBMOTES; ++i)
			if (g_wiimote_sources[i])
				GetUsbPointer()->AccessWiiMote(i | 0x100)->Activate(true);

	}

	AudioCommon::InitSoundStream();

	// The hardware is initialized.
	s_hardware_initialized = true;

	// Boot to pause or not
	Core::SetState(core_parameter.bBootToPause ? Core::CORE_PAUSE : Core::CORE_RUN);

	// Load GCM/DOL/ELF whatever ... we boot with the interpreter core
	PowerPC::SetMode(PowerPC::MODE_INTERPRETER);

	CBoot::BootUp();

	// Setup our core, but can't use dynarec if we are compare server
	if (core_parameter.iCPUCore != SCoreStartupParameter::CORE_INTERPRETER
	    && (!core_parameter.bRunCompareServer || core_parameter.bRunCompareClient))
	{
		PowerPC::SetMode(PowerPC::MODE_JIT);
	}
	else
	{
		PowerPC::SetMode(PowerPC::MODE_INTERPRETER);
	}

	// Update the window again because all stuff is initialized
	Host_UpdateDisasmDialog();
	Host_UpdateMainFrame();

	// Determine the CPU thread function
	void (*cpuThreadFunc)(void);
	if (core_parameter.m_BootType == SCoreStartupParameter::BOOT_DFF)
		cpuThreadFunc = FifoPlayerThread;
	else
		cpuThreadFunc = CpuThread;

	// ENTER THE VIDEO THREAD LOOP
	if (core_parameter.bCPUThread)
	{
		// This thread, after creating the EmuWindow, spawns a CPU
		// thread, and then takes over and becomes the video thread
		Common::SetCurrentThreadName("Video thread");

		g_video_backend->Video_Prepare();

		// Spawn the CPU thread
		s_cpu_thread = std::thread(cpuThreadFunc);

		// become the GPU thread
		g_video_backend->Video_EnterLoop();

		// We have now exited the Video Loop
		INFO_LOG(CONSOLE, "%s", StopMessage(false, "Video Loop Ended").c_str());
	}
	else // SingleCore mode
	{
		// The spawned CPU Thread also does the graphics.
		// The EmuThread is thus an idle thread, which sleeps while
		// waiting for the program to terminate. Without this extra
		// thread, the video backend window hangs in single core mode
		// because no one is pumping messages.
		Common::SetCurrentThreadName("Emuthread - Idle");

		// Spawn the CPU+GPU thread
		s_cpu_thread = std::thread(cpuThreadFunc);

		while (PowerPC::GetState() != PowerPC::CPU_POWERDOWN)
		{
			g_video_backend->PeekMessages();
			Common::SleepCurrentThread(20);
		}
	}

	INFO_LOG(CONSOLE, "%s", StopMessage(true, "Stopping Emu thread ...").c_str());

	// Wait for s_cpu_thread to exit
	INFO_LOG(CONSOLE, "%s", StopMessage(true, "Stopping CPU-GPU thread ...").c_str());

	#ifdef USE_GDBSTUB
	INFO_LOG(CONSOLE, "%s", StopMessage(true, "Stopping GDB ...").c_str());
	gdb_deinit();
	INFO_LOG(CONSOLE, "%s", StopMessage(true, "GDB stopped.").c_str());
	#endif

	s_cpu_thread.join();

	INFO_LOG(CONSOLE, "%s", StopMessage(true, "CPU thread stopped.").c_str());

	if (core_parameter.bCPUThread)
		g_video_backend->Video_Cleanup();

	VolumeHandler::EjectVolume();
	FileMon::Close();

	// Stop audio thread - Actually this does nothing when using HLE
	// emulation, but stops the DSP Interpreter when using LLE emulation.
	DSP::GetDSPEmulator()->DSP_StopSoundStream();

	// We must set up this flag before executing HW::Shutdown()
	s_hardware_initialized = false;
	INFO_LOG(CONSOLE, "%s", StopMessage(false, "Shutting down HW").c_str());
	HW::Shutdown();
	INFO_LOG(CONSOLE, "%s", StopMessage(false, "HW shutdown").c_str());

	Wiimote::Shutdown();

	Keyboard::Shutdown();
	Pad::Shutdown();

	g_video_backend->Shutdown();
	AudioCommon::ShutdownSoundStream();

	INFO_LOG(CONSOLE, "%s", StopMessage(true, "Main Emu thread stopped").c_str());

	// Clear on screen messages that haven't expired
	g_video_backend->Video_ClearMessages();

	// Reload sysconf file in order to see changes committed during emulation
	if (core_parameter.bWii)
		SConfig::GetInstance().m_SYSCONF->Reload();

	INFO_LOG(CONSOLE, "Stop [Video Thread]\t\t---- Shutdown complete ----");
	Movie::Shutdown();
	PatchEngine::Shutdown();

	s_is_stopping = false;

	if (s_on_stopped_callback)
		s_on_stopped_callback();
}
示例#8
0
int Interpreter::SingleStepInner()
{
	static UGeckoInstruction instCode;
	u32 function = HLE::GetFunctionIndex(PC);
	if (function != 0)
	{
		int type = HLE::GetFunctionTypeByIndex(function);
		if (type == HLE::HLE_HOOK_START || type == HLE::HLE_HOOK_REPLACE)
		{
			int flags = HLE::GetFunctionFlagsByIndex(function);
			if (HLE::IsEnabled(flags))
			{
				HLEFunction(function);
				if (type == HLE::HLE_HOOK_START)
				{
					// Run the original.
					function = 0;
				}
			}
			else
			{
				function = 0;
			}
		}
	}

	if (function == 0)
	{
		#ifdef USE_GDBSTUB
		if (gdb_active() && gdb_bp_x(PC))
		{
			Host_UpdateDisasmDialog();

			gdb_signal(SIGTRAP);
			gdb_handle_exception();
		}
		#endif

		NPC = PC + sizeof(UGeckoInstruction);
		instCode.hex = PowerPC::Read_Opcode(PC);

		// Uncomment to trace the interpreter
		//if ((PC & 0xffffff)>=0x0ab54c && (PC & 0xffffff)<=0x0ab624)
		//	startTrace = 1;
		//else
		//	startTrace = 0;

		if (startTrace)
		{
			Trace(instCode);
		}

		if (instCode.hex != 0)
		{
			UReg_MSR& msr = (UReg_MSR&)MSR;
			if (msr.FP)  //If FPU is enabled, just execute
			{
				m_opTable[instCode.OPCD](instCode);
				if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI)
				{
					PowerPC::CheckExceptions();
					m_EndBlock = true;
				}
			}
			else
			{
				// check if we have to generate a FPU unavailable exception
				if (!PPCTables::UsesFPU(instCode))
				{
					m_opTable[instCode.OPCD](instCode);
					if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI)
					{
						PowerPC::CheckExceptions();
						m_EndBlock = true;
					}
				}
				else
				{
					PowerPC::ppcState.Exceptions |= EXCEPTION_FPU_UNAVAILABLE;
					PowerPC::CheckExceptions();
					m_EndBlock = true;
				}
			}
		}
		else
		{
			// Memory exception on instruction fetch
			PowerPC::CheckExceptions();
			m_EndBlock = true;
		}
	}
	last_pc = PC;
	PC = NPC;

	GekkoOPInfo *opinfo = GetOpInfo(instCode);
	return opinfo->numCycles;
}
示例#9
0
// 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();
}
示例#10
0
void Stop()
{
	state = CPU_POWERDOWN;
	Host_UpdateDisasmDialog();
}
示例#11
0
void Pause()
{
	state = CPU_STEPPING;
	Host_UpdateDisasmDialog();
}
示例#12
0
// 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;
      }
    }
  }
}
示例#13
0
// Initalize and create emulation thread
// Call browser: Init():g_EmuThread().
// See the BootManager.cpp file description for a complete call schedule.
void EmuThread()
{
	const SCoreStartupParameter& _CoreParameter =
		SConfig::GetInstance().m_LocalCoreStartupParameter;

	Common::SetCurrentThreadName("Emuthread - Starting");

	DisplayMessage(cpu_info.brand_string, 8000);
	DisplayMessage(cpu_info.Summarize(), 8000);
	DisplayMessage(_CoreParameter.m_strFilename, 3000);
	if (cpu_info.IsUnsafe() && (NetPlay::IsNetPlayRunning() || Movie::IsRecordingInput() || Movie::IsPlayingInput()))
	{
		PanicAlertT("Warning: Netplay/movies will desync because your CPU does not support DAZ and Dolphin does not emulate it anymore.");
	}

	Movie::Init();

	HW::Init();

	if (!g_video_backend->Initialize(g_pWindowHandle))
	{
		PanicAlert("Failed to initialize video backend!");
		Host_Message(WM_USER_STOP);
		return;
	}

	OSD::AddMessage("Dolphin " + g_video_backend->GetName() + " Video Backend.", 5000);

	if (!DSP::GetDSPEmulator()->Initialize(g_pWindowHandle,
		_CoreParameter.bWii, _CoreParameter.bDSPThread))
	{
		HW::Shutdown();
		g_video_backend->Shutdown();
		PanicAlert("Failed to initialize DSP emulator!");
		Host_Message(WM_USER_STOP);
		return;
	}

	Pad::Initialize(g_pWindowHandle);
	// Load and Init Wiimotes - only if we are booting in wii mode
	if (g_CoreStartupParameter.bWii)
	{
		Wiimote::Initialize(g_pWindowHandle, !g_stateFileName.empty());

		// Activate wiimotes which don't have source set to "None"
		for (unsigned int i = 0; i != MAX_BBMOTES; ++i)
			if (g_wiimote_sources[i])
				GetUsbPointer()->AccessWiiMote(i | 0x100)->Activate(true);

	}

	AudioCommon::InitSoundStream(g_pWindowHandle);

	// The hardware is initialized.
	g_bHwInit = true;

	// Boot to pause or not
	Core::SetState(_CoreParameter.bBootToPause ? Core::CORE_PAUSE : Core::CORE_RUN);

	// Load GCM/DOL/ELF whatever ... we boot with the interpreter core
	PowerPC::SetMode(PowerPC::MODE_INTERPRETER);

	CBoot::BootUp();

	// Setup our core, but can't use dynarec if we are compare server
	if (_CoreParameter.iCPUCore && (!_CoreParameter.bRunCompareServer ||
					_CoreParameter.bRunCompareClient))
		PowerPC::SetMode(PowerPC::MODE_JIT);
	else
		PowerPC::SetMode(PowerPC::MODE_INTERPRETER);

	// Update the window again because all stuff is initialized
	Host_UpdateDisasmDialog();
	Host_UpdateMainFrame();

	// Determine the cpu thread function
	void (*cpuThreadFunc)(void);
	if (_CoreParameter.m_BootType == SCoreStartupParameter::BOOT_DFF)
		cpuThreadFunc = FifoPlayerThread;
	else
		cpuThreadFunc = CpuThread;

	// ENTER THE VIDEO THREAD LOOP
	if (_CoreParameter.bCPUThread)
	{
		// This thread, after creating the EmuWindow, spawns a CPU
		// thread, and then takes over and becomes the video thread
		Common::SetCurrentThreadName("Video thread");

		g_video_backend->Video_Prepare();

		// Spawn the CPU thread
		g_cpu_thread = std::thread(cpuThreadFunc);

		// become the GPU thread
		g_video_backend->Video_EnterLoop();

		// We have now exited the Video Loop
		INFO_LOG(CONSOLE, "%s", StopMessage(false, "Video Loop Ended").c_str());
	}
	else // SingleCore mode
	{
		// The spawned CPU Thread also does the graphics.
		// The EmuThread is thus an idle thread, which sleeps while
		// waiting for the program to terminate. Without this extra
		// thread, the video backend window hangs in single core mode
		// because noone is pumping messages.
		Common::SetCurrentThreadName("Emuthread - Idle");

		// Spawn the CPU+GPU thread
		g_cpu_thread = std::thread(cpuThreadFunc);

		while (PowerPC::GetState() != PowerPC::CPU_POWERDOWN)
		{
			g_video_backend->PeekMessages();
			Common::SleepCurrentThread(20);
		}
	}

	// Wait for g_cpu_thread to exit
	INFO_LOG(CONSOLE, "%s", StopMessage(true, "Stopping CPU-GPU thread ...").c_str());

	#ifdef USE_GDBSTUB
	INFO_LOG(CONSOLE, "%s", StopMessage(true, "Stopping GDB ...").c_str());
	gdb_deinit();
	INFO_LOG(CONSOLE, "%s", StopMessage(true, "GDB stopped.").c_str());
	#endif

	g_cpu_thread.join();

	INFO_LOG(CONSOLE, "%s", StopMessage(true, "CPU thread stopped.").c_str());

	if (_CoreParameter.bCPUThread)
		g_video_backend->Video_Cleanup();

	VolumeHandler::EjectVolume();
	FileMon::Close();

	// Stop audio thread - Actually this does nothing when using HLE
	// emulation, but stops the DSP Interpreter when using LLE emulation.
	DSP::GetDSPEmulator()->DSP_StopSoundStream();

	// We must set up this flag before executing HW::Shutdown()
	g_bHwInit = false;
	INFO_LOG(CONSOLE, "%s", StopMessage(false, "Shutting down HW").c_str());
	HW::Shutdown();
	INFO_LOG(CONSOLE, "%s", StopMessage(false, "HW shutdown").c_str());
	Pad::Shutdown();
	Wiimote::Shutdown();
	g_video_backend->Shutdown();
	AudioCommon::ShutdownSoundStream();
}
示例#14
0
int Interpreter::SingleStepInner(void)
{
	static UGeckoInstruction instCode;
	u32 function = m_EndBlock ? HLE::GetFunctionIndex(PC) : 0; // Check for HLE functions after branches
	if (function != 0)
	{
		int type = HLE::GetFunctionTypeByIndex(function);
		if (type == HLE::HLE_HOOK_START || type == HLE::HLE_HOOK_REPLACE)
		{
			int flags = HLE::GetFunctionFlagsByIndex(function);
			if (HLE::IsEnabled(flags))
			{
				HLEFunction(function);
				if (type == HLE::HLE_HOOK_START)
				{
					// Run the original.
					function = 0;
				}
			}
			else
			{
				function = 0;
			}
		}
	}

	if (function == 0)
	{
		#ifdef USE_GDBSTUB
		if (gdb_active() && gdb_bp_x(PC)) {

			Host_UpdateDisasmDialog();

			gdb_signal(SIGTRAP);
			gdb_handle_exception();
		}
		#endif

		NPC = PC + sizeof(UGeckoInstruction);
		instCode.hex = Memory::Read_Opcode(PC);

		// Uncomment to trace the interpreter
		//if ((PC & 0xffffff)>=0x0ab54c && (PC & 0xffffff)<=0x0ab624)
		//	startTrace = 1;
		//else
		//	startTrace = 0;

		if (startTrace)
		{
			Trace(instCode);
		}

		if (instCode.hex != 0)
		{
			UReg_MSR& msr = (UReg_MSR&)MSR;
			if (msr.FP)  //If FPU is enabled, just execute
			{
				m_opTable[instCode.OPCD](instCode);
				if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI)
				{
					PowerPC::CheckExceptions();
					m_EndBlock = true;
				}
			}
			else
			{
				// check if we have to generate a FPU unavailable exception
				if (!PPCTables::UsesFPU(instCode))
				{
					m_opTable[instCode.OPCD](instCode);
					if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI)
					{
						PowerPC::CheckExceptions();
						m_EndBlock = true;
					}
				}
				else
				{
					Common::AtomicOr(PowerPC::ppcState.Exceptions, EXCEPTION_FPU_UNAVAILABLE);
					PowerPC::CheckExceptions();
					m_EndBlock = true;
				}
			}
		}
		else
		{
			// Memory exception on instruction fetch
			PowerPC::CheckExceptions();
			m_EndBlock = true;
		}
	}
	last_pc = PC;
	PC = NPC;

#if defined(_DEBUG) || defined(DEBUGFAST)
	if (PowerPC::ppcState.gpr[1] == 0)
	{
		WARN_LOG(POWERPC, "%i Corrupt stack", PowerPC::ppcState.DebugCount);
	}
	PowerPC::ppcState.DebugCount++;
#endif
	patches();

	GekkoOPInfo *opinfo = GetOpInfo(instCode);
	return opinfo->numCyclesMinusOne + 1;
}
示例#15
0
int Interpreter::SingleStepInner()
{
  if (HandleFunctionHooking(PC))
  {
    UpdatePC();
    return PPCTables::GetOpInfo(m_prev_inst)->numCycles;
  }

#ifdef USE_GDBSTUB
  if (gdb_active() && gdb_bp_x(PC))
  {
    Host_UpdateDisasmDialog();

    gdb_signal(GDB_SIGTRAP);
    gdb_handle_exception();
  }
#endif

  NPC = PC + sizeof(UGeckoInstruction);
  m_prev_inst.hex = PowerPC::Read_Opcode(PC);

  // Uncomment to trace the interpreter
  // if ((PC & 0xffffff)>=0x0ab54c && (PC & 0xffffff)<=0x0ab624)
  //	startTrace = 1;
  // else
  //	startTrace = 0;

  if (startTrace)
  {
    Trace(m_prev_inst);
  }

  if (m_prev_inst.hex != 0)
  {
    if (IsInvalidPairedSingleExecution(m_prev_inst))
    {
      GenerateProgramException();
      CheckExceptions();
    }
    else if (MSR.FP)
    {
      m_op_table[m_prev_inst.OPCD](m_prev_inst);
      if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI)
      {
        CheckExceptions();
      }
    }
    else
    {
      // check if we have to generate a FPU unavailable exception or a program exception.
      if (PPCTables::UsesFPU(m_prev_inst))
      {
        PowerPC::ppcState.Exceptions |= EXCEPTION_FPU_UNAVAILABLE;
        CheckExceptions();
      }
      else
      {
        m_op_table[m_prev_inst.OPCD](m_prev_inst);
        if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI)
        {
          CheckExceptions();
        }
      }
    }
  }
  else
  {
    // Memory exception on instruction fetch
    CheckExceptions();
  }

  UpdatePC();
  return PPCTables::GetOpInfo(m_prev_inst)->numCycles;
}
示例#16
0
int Interpreter::SingleStepInner()
{
  if (!HandleFunctionHooking(PC))
  {
#ifdef USE_GDBSTUB
    if (gdb_active() && gdb_bp_x(PC))
    {
      Host_UpdateDisasmDialog();

      gdb_signal(SIGTRAP);
      gdb_handle_exception();
    }
#endif

    NPC = PC + sizeof(UGeckoInstruction);
    m_prev_inst.hex = PowerPC::Read_Opcode(PC);

    // Uncomment to trace the interpreter
    // if ((PC & 0xffffff)>=0x0ab54c && (PC & 0xffffff)<=0x0ab624)
    //	startTrace = 1;
    // else
    //	startTrace = 0;

    if (startTrace)
    {
      Trace(m_prev_inst);
    }

    if (m_prev_inst.hex != 0)
    {
      if (MSR.FP)  // If FPU is enabled, just execute
      {
        m_op_table[m_prev_inst.OPCD](m_prev_inst);
        if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI)
        {
          PowerPC::CheckExceptions();
          m_end_block = true;
        }
      }
      else
      {
        // check if we have to generate a FPU unavailable exception
        if (!PPCTables::UsesFPU(m_prev_inst))
        {
          m_op_table[m_prev_inst.OPCD](m_prev_inst);
          if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI)
          {
            PowerPC::CheckExceptions();
            m_end_block = true;
          }
        }
        else
        {
          PowerPC::ppcState.Exceptions |= EXCEPTION_FPU_UNAVAILABLE;
          PowerPC::CheckExceptions();
          m_end_block = true;
        }
      }
    }
    else
    {
      // Memory exception on instruction fetch
      PowerPC::CheckExceptions();
      m_end_block = true;
    }
  }
  last_pc = PC;
  PC = NPC;

  const GekkoOPInfo* opinfo = PPCTables::GetOpInfo(m_prev_inst);
  return opinfo->numCycles;
}