From 23843583bf2fcc349bef18b37e1a8539be3db17d Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Tue, 28 Mar 2023 20:26:52 +0200 Subject: [PATCH] PowerPC: Refactor to class, move to System. --- Source/Core/Common/Debug/CodeTrace.cpp | 19 +- Source/Core/Core/Boot/Boot_BS2Emu.cpp | 5 +- Source/Core/Core/Core.cpp | 18 +- Source/Core/Core/CoreTiming.cpp | 8 +- .../Core/Core/Debugger/Debugger_SymbolMap.cpp | 2 +- .../Core/Core/Debugger/PPCDebugInterface.cpp | 28 +- Source/Core/Core/HLE/HLE.cpp | 2 +- Source/Core/Core/HW/CPU.cpp | 30 +- Source/Core/Core/HW/CPU.h | 9 +- .../Core/Core/HW/EXI/EXI_DeviceEthernet.cpp | 5 +- Source/Core/Core/HW/SystemTimers.cpp | 2 +- Source/Core/Core/IOS/IOS.cpp | 5 +- Source/Core/Core/IOS/MIOS.cpp | 16 +- Source/Core/Core/IOS/Network/SSL.cpp | 10 +- Source/Core/Core/IOS/Network/Socket.cpp | 14 +- Source/Core/Core/PatchEngine.cpp | 2 +- Source/Core/Core/PowerPC/BreakPoints.cpp | 34 +- Source/Core/Core/PowerPC/BreakPoints.h | 20 + .../CachedInterpreter/CachedInterpreter.cpp | 13 +- Source/Core/Core/PowerPC/GDBStub.cpp | 16 +- .../Core/PowerPC/Interpreter/Interpreter.cpp | 11 +- .../Interpreter/Interpreter_Branch.cpp | 2 +- .../Interpreter/Interpreter_Integer.cpp | 5 +- .../Interpreter_SystemRegisters.cpp | 6 +- Source/Core/Core/PowerPC/Jit64/Jit.cpp | 14 +- Source/Core/Core/PowerPC/JitArm64/Jit.cpp | 16 +- .../JitArm64/JitArm64_SystemRegisters.cpp | 1 + .../Core/Core/PowerPC/JitCommon/JitBase.cpp | 7 +- Source/Core/Core/PowerPC/MMU.cpp | 22 +- Source/Core/Core/PowerPC/MMU.h | 4 +- Source/Core/Core/PowerPC/PPCAnalyst.cpp | 7 +- Source/Core/Core/PowerPC/PPCSymbolDB.cpp | 2 +- Source/Core/Core/PowerPC/PowerPC.cpp | 420 +++++++++--------- Source/Core/Core/PowerPC/PowerPC.h | 107 +++-- Source/Core/Core/State.cpp | 2 +- Source/Core/Core/System.cpp | 20 +- Source/Core/Core/System.h | 2 + .../DolphinQt/Debugger/BreakpointWidget.cpp | 54 ++- .../DolphinQt/Debugger/BreakpointWidget.h | 6 + .../DolphinQt/Debugger/CodeDiffDialog.cpp | 5 +- .../DolphinQt/Debugger/CodeViewWidget.cpp | 65 +-- Source/Core/DolphinQt/Debugger/CodeWidget.cpp | 38 +- .../DolphinQt/Debugger/MemoryViewWidget.cpp | 15 +- .../DolphinQt/Debugger/MemoryViewWidget.h | 5 +- .../DolphinQt/Debugger/RegisterWidget.cpp | 4 +- .../Core/DolphinQt/Debugger/ThreadWidget.cpp | 9 +- .../Core/DolphinQt/Debugger/WatchWidget.cpp | 80 ++-- Source/Core/DolphinQt/Debugger/WatchWidget.h | 5 +- Source/Core/DolphinQt/MenuBar.cpp | 3 +- Source/UnitTests/Core/CoreTimingTest.cpp | 41 +- 50 files changed, 705 insertions(+), 531 deletions(-) diff --git a/Source/Core/Common/Debug/CodeTrace.cpp b/Source/Core/Common/Debug/CodeTrace.cpp index 49ad967382..88ff656a92 100644 --- a/Source/Core/Common/Debug/CodeTrace.cpp +++ b/Source/Core/Common/Debug/CodeTrace.cpp @@ -126,16 +126,18 @@ InstructionAttributes CodeTrace::GetInstructionAttributes(const TraceOutput& ins TraceOutput CodeTrace::SaveCurrentInstruction(const Core::CPUThreadGuard& guard) const { auto& system = guard.GetSystem(); - auto& ppc_state = system.GetPPCState(); + auto& power_pc = system.GetPowerPC(); + auto& ppc_state = power_pc.GetPPCState(); + auto& debug_interface = power_pc.GetDebugInterface(); // Quickly save instruction and memory target for fast logging. TraceOutput output; - const std::string instr = PowerPC::debug_interface.Disassemble(&guard, ppc_state.pc); + const std::string instr = debug_interface.Disassemble(&guard, ppc_state.pc); output.instruction = instr; output.address = ppc_state.pc; if (IsInstructionLoadStore(output.instruction)) - output.memory_target = PowerPC::debug_interface.GetMemoryAddressFromInstruction(instr); + output.memory_target = debug_interface.GetMemoryAddressFromInstruction(instr); return output; } @@ -189,16 +191,17 @@ AutoStepResults CodeTrace::AutoStepping(const Core::CPUThreadGuard& guard, bool else if (stop_on == AutoStop::Changed) stop_condition = HitType::ACTIVE; - PowerPC::breakpoints.ClearAllTemporary(); + auto& power_pc = guard.GetSystem().GetPowerPC(); + power_pc.GetBreakPoints().ClearAllTemporary(); using clock = std::chrono::steady_clock; clock::time_point timeout = clock::now() + std::chrono::seconds(4); - PowerPC::CoreMode old_mode = PowerPC::GetMode(); - PowerPC::SetMode(PowerPC::CoreMode::Interpreter); + PowerPC::CoreMode old_mode = power_pc.GetMode(); + power_pc.SetMode(PowerPC::CoreMode::Interpreter); do { - PowerPC::SingleStep(); + power_pc.SingleStep(); pc_instr = SaveCurrentInstruction(guard); hit = TraceLogic(pc_instr); @@ -210,7 +213,7 @@ AutoStepResults CodeTrace::AutoStepping(const Core::CPUThreadGuard& guard, bool if (clock::now() >= timeout) results.timed_out = true; - PowerPC::SetMode(old_mode); + power_pc.SetMode(old_mode); m_recording = false; results.reg_tracked = m_reg_autotrack; diff --git a/Source/Core/Core/Boot/Boot_BS2Emu.cpp b/Source/Core/Core/Boot/Boot_BS2Emu.cpp index be799ab1a2..c79c4a4520 100644 --- a/Source/Core/Core/Boot/Boot_BS2Emu.cpp +++ b/Source/Core/Core/Boot/Boot_BS2Emu.cpp @@ -57,13 +57,14 @@ void PresetTimeBaseTicks(Core::System& system, const Core::CPUThreadGuard& guard void CBoot::RunFunction(Core::System& system, u32 address) { - auto& ppc_state = system.GetPPCState(); + auto& power_pc = system.GetPowerPC(); + auto& ppc_state = power_pc.GetPPCState(); ppc_state.pc = address; LR(ppc_state) = 0x00; while (ppc_state.pc != 0x00) - PowerPC::SingleStep(); + power_pc.SingleStep(); } void CBoot::SetupMSR(PowerPC::PowerPCState& ppc_state) diff --git a/Source/Core/Core/Core.cpp b/Source/Core/Core/Core.cpp index fbc87d18fd..4294faaf45 100644 --- a/Source/Core/Core/Core.cpp +++ b/Source/Core/Core/Core.cpp @@ -435,7 +435,8 @@ static void FifoPlayerThread(const std::optional& savestate_path, { DeclareAsCPUThread(); - if (Core::System::GetInstance().IsDualCoreMode()) + auto& system = Core::System::GetInstance(); + if (system.IsDualCoreMode()) Common::SetCurrentThreadName("FIFO player thread"); else Common::SetCurrentThreadName("FIFO-GPU thread"); @@ -443,15 +444,14 @@ static void FifoPlayerThread(const std::optional& savestate_path, // Enter CPU run loop. When we leave it - we are done. if (auto cpu_core = FifoPlayer::GetInstance().GetCPUCore()) { - PowerPC::InjectExternalCPUCore(cpu_core.get()); + system.GetPowerPC().InjectExternalCPUCore(cpu_core.get()); s_is_started = true; CPUSetInitialExecutionState(); - auto& system = Core::System::GetInstance(); system.GetCPU().Run(); s_is_started = false; - PowerPC::InjectExternalCPUCore(nullptr); + system.GetPowerPC().InjectExternalCPUCore(nullptr); FifoPlayer::GetInstance().Close(); } else @@ -552,7 +552,7 @@ static void EmuThread(std::unique_ptr boot, WindowSystemInfo wsi HLE::Clear(); CPUThreadGuard guard(system); - PowerPC::debug_interface.Clear(guard); + system.GetPowerPC().GetDebugInterface().Clear(guard); }}; VideoBackendBase::PopulateBackendInfo(); @@ -590,7 +590,7 @@ static void EmuThread(std::unique_ptr boot, WindowSystemInfo wsi system.GetCPU().Break(); // Load GCM/DOL/ELF whatever ... we boot with the interpreter core - PowerPC::SetMode(PowerPC::CoreMode::Interpreter); + system.GetPowerPC().SetMode(PowerPC::CoreMode::Interpreter); // Determine the CPU thread function void (*cpuThreadFunc)(const std::optional& savestate_path, bool delete_savestate); @@ -628,11 +628,11 @@ static void EmuThread(std::unique_ptr boot, WindowSystemInfo wsi // Setup our core if (Config::Get(Config::MAIN_CPU_CORE) != PowerPC::CPUCore::Interpreter) { - PowerPC::SetMode(PowerPC::CoreMode::JIT); + system.GetPowerPC().SetMode(PowerPC::CoreMode::JIT); } else { - PowerPC::SetMode(PowerPC::CoreMode::Interpreter); + system.GetPowerPC().SetMode(PowerPC::CoreMode::Interpreter); } UpdateTitle(); @@ -901,7 +901,7 @@ void UpdateTitle() { // Settings are shown the same for both extended and summary info const std::string SSettings = fmt::format( - "{} {} | {} | {}", PowerPC::GetCPUName(), + "{} {} | {} | {}", Core::System::GetInstance().GetPowerPC().GetCPUName(), Core::System::GetInstance().IsDualCoreMode() ? "DC" : "SC", g_video_backend->GetDisplayName(), Config::Get(Config::MAIN_DSP_HLE) ? "HLE" : "LLE"); diff --git a/Source/Core/Core/CoreTiming.cpp b/Source/Core/Core/CoreTiming.cpp index aa7c501c92..3659d4fb80 100644 --- a/Source/Core/Core/CoreTiming.cpp +++ b/Source/Core/Core/CoreTiming.cpp @@ -303,8 +303,8 @@ void CoreTimingManager::MoveEvents() void CoreTimingManager::Advance() { - auto& system = m_system; - auto& ppc_state = m_system.GetPPCState(); + auto& power_pc = m_system.GetPowerPC(); + auto& ppc_state = power_pc.GetPPCState(); MoveEvents(); @@ -323,7 +323,7 @@ void CoreTimingManager::Advance() m_event_queue.pop_back(); Throttle(evt.time); - evt.type->callback(system, evt.userdata, m_globals.global_timer - evt.time); + evt.type->callback(m_system, evt.userdata, m_globals.global_timer - evt.time); } m_is_global_timer_sane = false; @@ -341,7 +341,7 @@ void CoreTimingManager::Advance() // It's important to do this after processing events otherwise any exceptions will be delayed // until the next slice: // Pokemon Box refuses to boot if the first exception from the audio DMA is received late - PowerPC::CheckExternalExceptions(); + power_pc.CheckExternalExceptions(); } void CoreTimingManager::Throttle(const s64 target_cycle) diff --git a/Source/Core/Core/Debugger/Debugger_SymbolMap.cpp b/Source/Core/Core/Debugger/Debugger_SymbolMap.cpp index cab601c83d..c44ef40245 100644 --- a/Source/Core/Core/Debugger/Debugger_SymbolMap.cpp +++ b/Source/Core/Core/Debugger/Debugger_SymbolMap.cpp @@ -32,7 +32,7 @@ void AddAutoBreakpoints() { Common::Symbol* symbol = g_symbolDB.GetSymbolFromName(bp); if (symbol) - PowerPC::breakpoints.Add(symbol->address, false); + Core::System::GetInstance().GetPowerPC().GetBreakPoints().Add(symbol->address, false); } #endif #endif diff --git a/Source/Core/Core/Debugger/PPCDebugInterface.cpp b/Source/Core/Core/Debugger/PPCDebugInterface.cpp index 6d363fd6bf..ff87e82300 100644 --- a/Source/Core/Core/Debugger/PPCDebugInterface.cpp +++ b/Source/Core/Core/Debugger/PPCDebugInterface.cpp @@ -36,6 +36,7 @@ void ApplyMemoryPatch(const Core::CPUThreadGuard& guard, Common::Debug::MemoryPa if (!PowerPC::MMU::HostIsRAMAddress(guard, address)) return; + auto& power_pc = guard.GetSystem().GetPowerPC(); for (u32 offset = 0; offset < size; ++offset) { if (store_existing_value) @@ -50,11 +51,11 @@ void ApplyMemoryPatch(const Core::CPUThreadGuard& guard, Common::Debug::MemoryPa } if (((address + offset) % 4) == 3) - PowerPC::ScheduleInvalidateCacheThreadSafe(Common::AlignDown(address + offset, 4)); + power_pc.ScheduleInvalidateCacheThreadSafe(Common::AlignDown(address + offset, 4)); } if (((address + size) % 4) != 0) { - PowerPC::ScheduleInvalidateCacheThreadSafe( + power_pc.ScheduleInvalidateCacheThreadSafe( Common::AlignDown(address + static_cast(size), 4)); } } @@ -347,40 +348,41 @@ bool PPCDebugInterface::IsAlive() const bool PPCDebugInterface::IsBreakpoint(u32 address) const { - return PowerPC::breakpoints.IsAddressBreakPoint(address); + return m_system.GetPowerPC().GetBreakPoints().IsAddressBreakPoint(address); } void PPCDebugInterface::SetBreakpoint(u32 address) { - PowerPC::breakpoints.Add(address); + m_system.GetPowerPC().GetBreakPoints().Add(address); } void PPCDebugInterface::ClearBreakpoint(u32 address) { - PowerPC::breakpoints.Remove(address); + m_system.GetPowerPC().GetBreakPoints().Remove(address); } void PPCDebugInterface::ClearAllBreakpoints() { - PowerPC::breakpoints.Clear(); + m_system.GetPowerPC().GetBreakPoints().Clear(); } void PPCDebugInterface::ToggleBreakpoint(u32 address) { - if (PowerPC::breakpoints.IsAddressBreakPoint(address)) - PowerPC::breakpoints.Remove(address); + auto& breakpoints = m_system.GetPowerPC().GetBreakPoints(); + if (breakpoints.IsAddressBreakPoint(address)) + breakpoints.Remove(address); else - PowerPC::breakpoints.Add(address); + breakpoints.Add(address); } void PPCDebugInterface::ClearAllMemChecks() { - PowerPC::memchecks.Clear(); + m_system.GetPowerPC().GetMemChecks().Clear(); } bool PPCDebugInterface::IsMemCheck(u32 address, size_t size) const { - return PowerPC::memchecks.GetMemCheck(address, size) != nullptr; + return m_system.GetPowerPC().GetMemChecks().GetMemCheck(address, size) != nullptr; } void PPCDebugInterface::ToggleMemCheck(u32 address, bool read, bool write, bool log) @@ -397,11 +399,11 @@ void PPCDebugInterface::ToggleMemCheck(u32 address, bool read, bool write, bool MemCheck.log_on_hit = log; MemCheck.break_on_hit = true; - PowerPC::memchecks.Add(std::move(MemCheck)); + m_system.GetPowerPC().GetMemChecks().Add(std::move(MemCheck)); } else { - PowerPC::memchecks.Remove(address); + m_system.GetPowerPC().GetMemChecks().Remove(address); } } diff --git a/Source/Core/Core/HLE/HLE.cpp b/Source/Core/Core/HLE/HLE.cpp index 6728160ae7..310aec6620 100644 --- a/Source/Core/Core/HLE/HLE.cpp +++ b/Source/Core/Core/HLE/HLE.cpp @@ -203,7 +203,7 @@ HookFlag GetHookFlagsByIndex(u32 index) bool IsEnabled(HookFlag flag) { return flag != HLE::HookFlag::Debug || Config::Get(Config::MAIN_ENABLE_DEBUGGING) || - PowerPC::GetMode() == PowerPC::CoreMode::Interpreter; + Core::System::GetInstance().GetPowerPC().GetMode() == PowerPC::CoreMode::Interpreter; } u32 UnPatch(Core::System& system, std::string_view patch_name) diff --git a/Source/Core/Core/HW/CPU.cpp b/Source/Core/Core/HW/CPU.cpp index 14031ef5d0..aa90ab54d2 100644 --- a/Source/Core/Core/HW/CPU.cpp +++ b/Source/Core/Core/HW/CPU.cpp @@ -19,19 +19,21 @@ namespace CPU { -CPUManager::CPUManager() = default; +CPUManager::CPUManager(Core::System& system) : m_system(system) +{ +} CPUManager::~CPUManager() = default; void CPUManager::Init(PowerPC::CPUCore cpu_core) { - PowerPC::Init(cpu_core); + m_system.GetPowerPC().Init(cpu_core); m_state = State::Stepping; } void CPUManager::Shutdown() { Stop(); - PowerPC::Shutdown(); + m_system.GetPowerPC().Shutdown(); } // Requires holding m_state_change_lock @@ -62,11 +64,11 @@ void CPUManager::ExecutePendingJobs(std::unique_lock& state_lock) void CPUManager::Run() { - auto& system = Core::System::GetInstance(); + auto& power_pc = m_system.GetPowerPC(); // Updating the host CPU's rounding mode must be done on the CPU thread. // We can't rely on PowerPC::Init doing it, since it's called from EmuThread. - PowerPC::RoundingModeUpdated(); + PowerPC::RoundingModeUpdated(power_pc.GetPPCState()); std::unique_lock state_lock(m_state_change_lock); while (m_state != State::PowerDown) @@ -85,22 +87,22 @@ void CPUManager::Run() // SingleStep so that the "continue", "step over" and "step out" debugger functions // work when the PC is at a breakpoint at the beginning of the block // If watchpoints are enabled, any instruction could be a breakpoint. - if (PowerPC::GetMode() != PowerPC::CoreMode::Interpreter) + if (power_pc.GetMode() != PowerPC::CoreMode::Interpreter) { - if (PowerPC::breakpoints.IsAddressBreakPoint(system.GetPPCState().pc) || - PowerPC::memchecks.HasAny()) + if (power_pc.GetBreakPoints().IsAddressBreakPoint(power_pc.GetPPCState().pc) || + power_pc.GetMemChecks().HasAny()) { m_state = State::Stepping; - PowerPC::CoreMode old_mode = PowerPC::GetMode(); - PowerPC::SetMode(PowerPC::CoreMode::Interpreter); - PowerPC::SingleStep(); - PowerPC::SetMode(old_mode); + PowerPC::CoreMode old_mode = power_pc.GetMode(); + power_pc.SetMode(PowerPC::CoreMode::Interpreter); + power_pc.SingleStep(); + power_pc.SetMode(old_mode); m_state = State::Running; } } // Enter a fast runloop - PowerPC::RunLoop(); + power_pc.RunLoop(); state_lock.lock(); m_state_cpu_thread_active = false; @@ -147,7 +149,7 @@ void CPUManager::Run() m_state_cpu_thread_active = true; state_lock.unlock(); - PowerPC::SingleStep(); + power_pc.SingleStep(); state_lock.lock(); m_state_cpu_thread_active = false; diff --git a/Source/Core/Core/HW/CPU.h b/Source/Core/Core/HW/CPU.h index 85f8885026..e328f645e8 100644 --- a/Source/Core/Core/HW/CPU.h +++ b/Source/Core/Core/HW/CPU.h @@ -12,7 +12,10 @@ namespace Common { class Event; } - +namespace Core +{ +class System; +} namespace PowerPC { enum class CPUCore; @@ -30,7 +33,7 @@ enum class State class CPUManager { public: - CPUManager(); + explicit CPUManager(Core::System& system); CPUManager(const CPUManager& other) = delete; CPUManager(CPUManager&& other) = delete; CPUManager& operator=(const CPUManager& other) = delete; @@ -130,5 +133,7 @@ private: bool m_state_cpu_step_instruction = false; Common::Event* m_state_cpu_step_instruction_sync = nullptr; std::queue> m_pending_jobs; + + Core::System& m_system; }; } // namespace CPU diff --git a/Source/Core/Core/HW/EXI/EXI_DeviceEthernet.cpp b/Source/Core/Core/HW/EXI/EXI_DeviceEthernet.cpp index 83134941dc..0e7a1d0276 100644 --- a/Source/Core/Core/HW/EXI/EXI_DeviceEthernet.cpp +++ b/Source/Core/Core/HW/EXI/EXI_DeviceEthernet.cpp @@ -448,7 +448,7 @@ void CEXIETHERNET::SendFromDirectFIFO() const u8* frame = tx_fifo.get(); const u16 size = Common::BitCastPtr(&mBbaMem[BBA_TXFIFOCNT]); if (m_network_interface->SendFrame(frame, size)) - PowerPC::debug_interface.NetworkLogger()->LogBBA(frame, size); + m_system.GetPowerPC().GetDebugInterface().NetworkLogger()->LogBBA(frame, size); } void CEXIETHERNET::SendFromPacketBuffer() @@ -561,7 +561,8 @@ bool CEXIETHERNET::RecvHandlePacket() INFO_LOG_FMT(SP1, "{:x} {:x} {:x} {:x}", page_ptr(BBA_BP), page_ptr(BBA_RRP), page_ptr(BBA_RWP), page_ptr(BBA_RHBP)); #endif - PowerPC::debug_interface.NetworkLogger()->LogBBA(mRecvBuffer.get(), mRecvBufferLength); + m_system.GetPowerPC().GetDebugInterface().NetworkLogger()->LogBBA(mRecvBuffer.get(), + mRecvBufferLength); write_ptr = &mBbaMem[page_ptr(BBA_RWP) << 8]; descriptor = (Descriptor*)write_ptr; diff --git a/Source/Core/Core/HW/SystemTimers.cpp b/Source/Core/Core/HW/SystemTimers.cpp index 4f4089782d..988604d926 100644 --- a/Source/Core/Core/HW/SystemTimers.cpp +++ b/Source/Core/Core/HW/SystemTimers.cpp @@ -223,7 +223,7 @@ void TimeBaseSet() auto& system = Core::System::GetInstance(); auto& core_timing = system.GetCoreTiming(); core_timing.SetFakeTBStartTicks(core_timing.GetTicks()); - core_timing.SetFakeTBStartValue(PowerPC::ReadFullTimeBaseValue()); + core_timing.SetFakeTBStartValue(system.GetPowerPC().ReadFullTimeBaseValue()); } u64 GetFakeTimeBase() diff --git a/Source/Core/Core/IOS/IOS.cpp b/Source/Core/Core/IOS/IOS.cpp index 9f9478dc71..82f51dac33 100644 --- a/Source/Core/Core/IOS/IOS.cpp +++ b/Source/Core/Core/IOS/IOS.cpp @@ -200,8 +200,9 @@ static void ResetAndPausePPC() auto& system = Core::System::GetInstance(); auto& memory = system.GetMemory(); memory.Write_U32(0x48000000, 0x00000000); // b 0x0 - PowerPC::Reset(); - system.GetPPCState().pc = 0; + auto& power_pc = system.GetPowerPC(); + power_pc.Reset(); + power_pc.GetPPCState().pc = 0; } static void ReleasePPC() diff --git a/Source/Core/Core/IOS/MIOS.cpp b/Source/Core/Core/IOS/MIOS.cpp index ecd7a992a4..52fcb553c2 100644 --- a/Source/Core/Core/IOS/MIOS.cpp +++ b/Source/Core/Core/IOS/MIOS.cpp @@ -43,7 +43,7 @@ static void ReinitHardware() // (and not by MIOS), causing games that use DTK to break. Perhaps MIOS doesn't actually // reset DI fully, in such a way that the DTK config isn't cleared? // system.GetDVDInterface().ResetDrive(true); - PowerPC::Reset(); + system.GetPowerPC().Reset(); Wiimote::ResetAllWiimotes(); // Note: this is specific to Dolphin and is required because we initialised it in Wii mode. auto& dsp = system.GetDSP(); @@ -83,18 +83,18 @@ bool Load() Host_NotifyMapLoaded(); } - auto& ppc_state = system.GetPPCState(); - const PowerPC::CoreMode core_mode = PowerPC::GetMode(); - PowerPC::SetMode(PowerPC::CoreMode::Interpreter); - ppc_state.msr.Hex = 0; - ppc_state.pc = 0x3400; + auto& power_pc = system.GetPowerPC(); + const PowerPC::CoreMode core_mode = power_pc.GetMode(); + power_pc.SetMode(PowerPC::CoreMode::Interpreter); + power_pc.GetPPCState().msr.Hex = 0; + power_pc.GetPPCState().pc = 0x3400; NOTICE_LOG_FMT(IOS, "Loaded MIOS and bootstrapped PPC."); // IOS writes 0 to 0x30f8 before bootstrapping the PPC. Once started, the IPL eventually writes // 0xdeadbeef there, then waits for it to be cleared by IOS before continuing. while (memory.Read_U32(ADDRESS_INIT_SEMAPHORE) != 0xdeadbeef) - PowerPC::SingleStep(); - PowerPC::SetMode(core_mode); + power_pc.SingleStep(); + power_pc.SetMode(core_mode); memory.Write_U32(0x00000000, ADDRESS_INIT_SEMAPHORE); NOTICE_LOG_FMT(IOS, "IPL ready."); diff --git a/Source/Core/Core/IOS/Network/SSL.cpp b/Source/Core/Core/IOS/Network/SSL.cpp index 524f2b81e8..a26d2451db 100644 --- a/Source/Core/Core/IOS/Network/SSL.cpp +++ b/Source/Core/Core/IOS/Network/SSL.cpp @@ -63,7 +63,10 @@ int SSLSendWithoutSNI(void* ctx, const unsigned char* buf, size_t len) // Log raw SSL packets if we don't dump unencrypted SSL writes if (!Config::Get(Config::MAIN_NETWORK_SSL_DUMP_WRITE) && ret > 0) - PowerPC::debug_interface.NetworkLogger()->LogWrite(buf, ret, *fd, nullptr); + { + Core::System::GetInstance().GetPowerPC().GetDebugInterface().NetworkLogger()->LogWrite( + buf, ret, *fd, nullptr); + } return ret; } @@ -76,7 +79,10 @@ int SSLRecv(void* ctx, unsigned char* buf, size_t len) // Log raw SSL packets if we don't dump unencrypted SSL reads if (!Config::Get(Config::MAIN_NETWORK_SSL_DUMP_READ) && ret > 0) - PowerPC::debug_interface.NetworkLogger()->LogRead(buf, ret, *fd, nullptr); + { + Core::System::GetInstance().GetPowerPC().GetDebugInterface().NetworkLogger()->LogRead( + buf, ret, *fd, nullptr); + } return ret; } diff --git a/Source/Core/Core/IOS/Network/Socket.cpp b/Source/Core/Core/IOS/Network/Socket.cpp index a1fe3d6a27..ff60c09b20 100644 --- a/Source/Core/Core/IOS/Network/Socket.cpp +++ b/Source/Core/Core/IOS/Network/Socket.cpp @@ -487,8 +487,8 @@ void WiiSocket::Update(bool read, bool write, bool except) if (ret >= 0) { - PowerPC::debug_interface.NetworkLogger()->LogSSLWrite(memory.GetPointer(BufferOut2), - ret, ssl->hostfd); + system.GetPowerPC().GetDebugInterface().NetworkLogger()->LogSSLWrite( + memory.GetPointer(BufferOut2), ret, ssl->hostfd); // Return bytes written or SSL_ERR_ZERO if none WriteReturnValue((ret == 0) ? SSL_ERR_ZERO : ret, BufferIn); } @@ -521,8 +521,8 @@ void WiiSocket::Update(bool read, bool write, bool except) if (ret >= 0) { - PowerPC::debug_interface.NetworkLogger()->LogSSLRead(memory.GetPointer(BufferIn2), - ret, ssl->hostfd); + system.GetPowerPC().GetDebugInterface().NetworkLogger()->LogSSLRead( + memory.GetPointer(BufferIn2), ret, ssl->hostfd); // Return bytes read or SSL_ERR_ZERO if none WriteReturnValue((ret == 0) ? SSL_ERR_ZERO : ret, BufferIn); } @@ -595,7 +595,7 @@ void WiiSocket::Update(bool read, bool write, bool except) const int ret = sendto(fd, data, BufferInSize, flags, to, tolen); ReturnValue = WiiSockMan::GetNetErrorCode(ret, "SO_SENDTO", true); if (ret > 0) - PowerPC::debug_interface.NetworkLogger()->LogWrite(data, ret, fd, to); + system.GetPowerPC().GetDebugInterface().NetworkLogger()->LogWrite(data, ret, fd, to); INFO_LOG_FMT(IOS_NET, "{} = {} Socket: {:08x}, BufferIn: ({:08x}, {}), BufferIn2: ({:08x}, {}), " @@ -654,7 +654,7 @@ void WiiSocket::Update(bool read, bool write, bool except) ReturnValue = WiiSockMan::GetNetErrorCode(ret, BufferOutSize2 ? "SO_RECVFROM" : "SO_RECV", true); if (ret > 0) - PowerPC::debug_interface.NetworkLogger()->LogRead(data, ret, fd, from); + system.GetPowerPC().GetDebugInterface().NetworkLogger()->LogRead(data, ret, fd, from); INFO_LOG_FMT(IOS_NET, "{}({}, {}) Socket: {:08X}, Flags: {:08X}, " @@ -865,7 +865,7 @@ s32 WiiSockMan::AddSocket(s32 fd, bool is_rw) WiiSocket& sock = WiiSockets[wii_fd]; sock.SetFd(fd); sock.SetWiiFd(wii_fd); - PowerPC::debug_interface.NetworkLogger()->OnNewSocket(fd); + Core::System::GetInstance().GetPowerPC().GetDebugInterface().NetworkLogger()->OnNewSocket(fd); #ifdef __APPLE__ int opt_no_sigpipe = 1; diff --git a/Source/Core/Core/PatchEngine.cpp b/Source/Core/Core/PatchEngine.cpp index b180991522..21187dd9b6 100644 --- a/Source/Core/Core/PatchEngine.cpp +++ b/Source/Core/Core/PatchEngine.cpp @@ -277,7 +277,7 @@ static void ApplyMemoryPatches(const Core::CPUThreadGuard& guard, std::lock_guard lock(s_on_frame_memory_mutex); for (std::size_t index : memory_patch_indices) { - PowerPC::debug_interface.ApplyExistingPatch(guard, index); + guard.GetSystem().GetPowerPC().GetDebugInterface().ApplyExistingPatch(guard, index); } } diff --git a/Source/Core/Core/PowerPC/BreakPoints.cpp b/Source/Core/Core/PowerPC/BreakPoints.cpp index 473871e74f..c4555c7569 100644 --- a/Source/Core/Core/PowerPC/BreakPoints.cpp +++ b/Source/Core/Core/PowerPC/BreakPoints.cpp @@ -19,6 +19,12 @@ #include "Core/PowerPC/PowerPC.h" #include "Core/System.h" +BreakPoints::BreakPoints(Core::System& system) : m_system(system) +{ +} + +BreakPoints::~BreakPoints() = default; + bool BreakPoints::IsAddressBreakPoint(u32 address) const { return std::any_of(m_breakpoints.begin(), m_breakpoints.end(), @@ -107,7 +113,7 @@ void BreakPoints::Add(TBreakPoint bp) if (IsAddressBreakPoint(bp.address)) return; - Core::System::GetInstance().GetJitInterface().InvalidateICache(bp.address, 4, true); + m_system.GetJitInterface().InvalidateICache(bp.address, 4, true); m_breakpoints.emplace_back(std::move(bp)); } @@ -143,7 +149,7 @@ void BreakPoints::Add(u32 address, bool temp, bool break_on_hit, bool log_on_hit m_breakpoints.emplace_back(std::move(bp)); } - Core::System::GetInstance().GetJitInterface().InvalidateICache(address, 4, true); + m_system.GetJitInterface().InvalidateICache(address, 4, true); } bool BreakPoints::ToggleBreakPoint(u32 address) @@ -167,14 +173,14 @@ void BreakPoints::Remove(u32 address) return; m_breakpoints.erase(iter); - Core::System::GetInstance().GetJitInterface().InvalidateICache(address, 4, true); + m_system.GetJitInterface().InvalidateICache(address, 4, true); } void BreakPoints::Clear() { for (const TBreakPoint& bp : m_breakpoints) { - Core::System::GetInstance().GetJitInterface().InvalidateICache(bp.address, 4, true); + m_system.GetJitInterface().InvalidateICache(bp.address, 4, true); } m_breakpoints.clear(); @@ -187,7 +193,7 @@ void BreakPoints::ClearAllTemporary() { if (bp->is_temporary) { - Core::System::GetInstance().GetJitInterface().InvalidateICache(bp->address, 4, true); + m_system.GetJitInterface().InvalidateICache(bp->address, 4, true); bp = m_breakpoints.erase(bp); } else @@ -197,6 +203,12 @@ void BreakPoints::ClearAllTemporary() } } +MemChecks::MemChecks(Core::System& system) : m_system(system) +{ +} + +MemChecks::~MemChecks() = default; + MemChecks::TMemChecksStr MemChecks::GetStrings() const { TMemChecksStr mc_strings; @@ -280,8 +292,8 @@ void MemChecks::Add(TMemCheck memory_check) // If this is the first one, clear the JIT cache so it can switch to // watchpoint-compatible code. if (!had_any) - Core::System::GetInstance().GetJitInterface().ClearCache(); - Core::System::GetInstance().GetMMU().DBATUpdated(); + m_system.GetJitInterface().ClearCache(); + m_system.GetMMU().DBATUpdated(); }); } @@ -309,8 +321,8 @@ void MemChecks::Remove(u32 address) Core::RunAsCPUThread([&] { m_mem_checks.erase(iter); if (!HasAny()) - Core::System::GetInstance().GetJitInterface().ClearCache(); - Core::System::GetInstance().GetMMU().DBATUpdated(); + m_system.GetJitInterface().ClearCache(); + m_system.GetMMU().DBATUpdated(); }); } @@ -318,8 +330,8 @@ void MemChecks::Clear() { Core::RunAsCPUThread([&] { m_mem_checks.clear(); - Core::System::GetInstance().GetJitInterface().ClearCache(); - Core::System::GetInstance().GetMMU().DBATUpdated(); + m_system.GetJitInterface().ClearCache(); + m_system.GetMMU().DBATUpdated(); }); } diff --git a/Source/Core/Core/PowerPC/BreakPoints.h b/Source/Core/Core/PowerPC/BreakPoints.h index 111e1bb365..5494ee73e3 100644 --- a/Source/Core/Core/PowerPC/BreakPoints.h +++ b/Source/Core/Core/PowerPC/BreakPoints.h @@ -15,6 +15,10 @@ namespace Common { class DebugInterface; } +namespace Core +{ +class System; +} struct TBreakPoint { @@ -53,6 +57,13 @@ struct TMemCheck class BreakPoints { public: + explicit BreakPoints(Core::System& system); + BreakPoints(const BreakPoints& other) = delete; + BreakPoints(BreakPoints&& other) = delete; + BreakPoints& operator=(const BreakPoints& other) = delete; + BreakPoints& operator=(BreakPoints&& other) = delete; + ~BreakPoints(); + using TBreakPoints = std::vector; using TBreakPointsStr = std::vector; @@ -82,12 +93,20 @@ public: private: TBreakPoints m_breakpoints; + Core::System& m_system; }; // Memory breakpoints class MemChecks { public: + explicit MemChecks(Core::System& system); + MemChecks(const MemChecks& other) = delete; + MemChecks(MemChecks&& other) = delete; + MemChecks& operator=(const MemChecks& other) = delete; + MemChecks& operator=(MemChecks&& other) = delete; + ~MemChecks(); + using TMemChecks = std::vector; using TMemChecksStr = std::vector; @@ -109,4 +128,5 @@ public: private: TMemChecks m_mem_checks; + Core::System& m_system; }; diff --git a/Source/Core/Core/PowerPC/CachedInterpreter/CachedInterpreter.cpp b/Source/Core/Core/PowerPC/CachedInterpreter/CachedInterpreter.cpp index bf75e3d0f1..28ee8fd77e 100644 --- a/Source/Core/Core/PowerPC/CachedInterpreter/CachedInterpreter.cpp +++ b/Source/Core/Core/PowerPC/CachedInterpreter/CachedInterpreter.cpp @@ -214,7 +214,7 @@ bool CachedInterpreter::CheckFPU(CachedInterpreter& cached_interpreter, u32 data if (!ppc_state.msr.FP) { ppc_state.Exceptions |= EXCEPTION_FPU_UNAVAILABLE; - PowerPC::CheckExceptions(); + cached_interpreter.m_system.GetPowerPC().CheckExceptions(); ppc_state.downcount -= data; return true; } @@ -226,7 +226,7 @@ bool CachedInterpreter::CheckDSI(CachedInterpreter& cached_interpreter, u32 data auto& ppc_state = cached_interpreter.m_ppc_state; if (ppc_state.Exceptions & EXCEPTION_DSI) { - PowerPC::CheckExceptions(); + cached_interpreter.m_system.GetPowerPC().CheckExceptions(); ppc_state.downcount -= data; return true; } @@ -238,7 +238,7 @@ bool CachedInterpreter::CheckProgramException(CachedInterpreter& cached_interpre auto& ppc_state = cached_interpreter.m_ppc_state; if (ppc_state.Exceptions & EXCEPTION_PROGRAM) { - PowerPC::CheckExceptions(); + cached_interpreter.m_system.GetPowerPC().CheckExceptions(); ppc_state.downcount -= data; return true; } @@ -247,7 +247,7 @@ bool CachedInterpreter::CheckProgramException(CachedInterpreter& cached_interpre bool CachedInterpreter::CheckBreakpoint(CachedInterpreter& cached_interpreter, u32 data) { - PowerPC::CheckBreakPoints(); + cached_interpreter.m_system.GetPowerPC().CheckBreakPoints(); if (cached_interpreter.m_system.GetCPU().GetState() != CPU::State::Running) { cached_interpreter.m_ppc_state.downcount -= data; @@ -295,7 +295,7 @@ void CachedInterpreter::Jit(u32 address) // Address of instruction could not be translated m_ppc_state.npc = nextPC; m_ppc_state.Exceptions |= EXCEPTION_ISI; - PowerPC::CheckExceptions(); + m_system.GetPowerPC().CheckExceptions(); WARN_LOG_FMT(POWERPC, "ISI exception at {:#010x}", nextPC); return; } @@ -329,7 +329,8 @@ void CachedInterpreter::Jit(u32 address) if (!op.skip) { const bool breakpoint = - m_enable_debugging && PowerPC::breakpoints.IsAddressBreakPoint(op.address); + m_enable_debugging && + m_system.GetPowerPC().GetBreakPoints().IsAddressBreakPoint(op.address); const bool check_fpu = (op.opinfo->flags & FL_USE_FPU) && !js.firstFPInstructionFound; const bool endblock = (op.opinfo->flags & FL_ENDBLOCK) != 0; const bool memcheck = (op.opinfo->flags & FL_LOADSTORE) && jo.memcheck; diff --git a/Source/Core/Core/PowerPC/GDBStub.cpp b/Source/Core/Core/PowerPC/GDBStub.cpp index 7a702e7188..99cdae0ce0 100644 --- a/Source/Core/Core/PowerPC/GDBStub.cpp +++ b/Source/Core/Core/PowerPC/GDBStub.cpp @@ -163,17 +163,19 @@ static void RemoveBreakpoint(BreakpointType type, u32 addr, u32 len) { if (type == BreakpointType::ExecuteHard || type == BreakpointType::ExecuteSoft) { - while (PowerPC::breakpoints.IsAddressBreakPoint(addr)) + auto& breakpoints = Core::System::GetInstance().GetPowerPC().GetBreakPoints(); + while (breakpoints.IsAddressBreakPoint(addr)) { - PowerPC::breakpoints.Remove(addr); + breakpoints.Remove(addr); INFO_LOG_FMT(GDB_STUB, "gdb: removed a breakpoint: {:08x} bytes at {:08x}", len, addr); } } else { - while (PowerPC::memchecks.GetMemCheck(addr, len) != nullptr) + auto& memchecks = Core::System::GetInstance().GetPowerPC().GetMemChecks(); + while (memchecks.GetMemCheck(addr, len) != nullptr) { - PowerPC::memchecks.Remove(addr); + memchecks.Remove(addr); INFO_LOG_FMT(GDB_STUB, "gdb: removed a memcheck: {:08x} bytes at {:08x}", len, addr); } } @@ -869,7 +871,8 @@ static bool AddBreakpoint(BreakpointType type, u32 addr, u32 len) { if (type == BreakpointType::ExecuteHard || type == BreakpointType::ExecuteSoft) { - PowerPC::breakpoints.Add(addr); + auto& breakpoints = Core::System::GetInstance().GetPowerPC().GetBreakPoints(); + breakpoints.Add(addr); INFO_LOG_FMT(GDB_STUB, "gdb: added {} breakpoint: {:08x} bytes at {:08x}", static_cast(type), len, addr); } @@ -886,7 +889,8 @@ static bool AddBreakpoint(BreakpointType type, u32 addr, u32 len) new_memcheck.break_on_hit = true; new_memcheck.log_on_hit = false; new_memcheck.is_enabled = true; - PowerPC::memchecks.Add(std::move(new_memcheck)); + auto& memchecks = Core::System::GetInstance().GetPowerPC().GetMemChecks(); + memchecks.Add(std::move(new_memcheck)); INFO_LOG_FMT(GDB_STUB, "gdb: added {} memcheck: {:08x} bytes at {:08x}", static_cast(type), len, addr); } diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter.cpp b/Source/Core/Core/PowerPC/Interpreter/Interpreter.cpp index b4ba4e777d..168df8deaf 100644 --- a/Source/Core/Core/PowerPC/Interpreter/Interpreter.cpp +++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter.cpp @@ -206,7 +206,7 @@ void Interpreter::SingleStep() if (m_ppc_state.Exceptions != 0) { - PowerPC::CheckExceptions(); + m_system.GetPowerPC().CheckExceptions(); m_ppc_state.pc = m_ppc_state.npc; } } @@ -224,6 +224,7 @@ void Interpreter::Run() { auto& core_timing = m_system.GetCoreTiming(); auto& cpu = m_system.GetCPU(); + auto& power_pc = m_system.GetPowerPC(); while (cpu.GetState() == CPU::State::Running) { // CoreTiming Advance() ends the previous slice and declares the start of the next @@ -255,7 +256,7 @@ void Interpreter::Run() #endif // 2: check for breakpoint - if (PowerPC::breakpoints.IsAddressBreakPoint(m_ppc_state.pc)) + if (power_pc.GetBreakPoints().IsAddressBreakPoint(m_ppc_state.pc)) { #ifdef SHOW_HISTORY NOTICE_LOG_FMT(POWERPC, "----------------------------"); @@ -280,8 +281,8 @@ void Interpreter::Run() cpu.Break(); if (GDBStub::IsActive()) GDBStub::TakeControl(); - if (PowerPC::breakpoints.IsTempBreakPoint(m_ppc_state.pc)) - PowerPC::breakpoints.Remove(m_ppc_state.pc); + if (power_pc.GetBreakPoints().IsTempBreakPoint(m_ppc_state.pc)) + power_pc.GetBreakPoints().Remove(m_ppc_state.pc); Host_UpdateDisasmDialog(); return; @@ -347,7 +348,7 @@ void Interpreter::ClearCache() void Interpreter::CheckExceptions() { - PowerPC::CheckExceptions(); + m_system.GetPowerPC().CheckExceptions(); m_end_block = true; } diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter_Branch.cpp b/Source/Core/Core/PowerPC/Interpreter/Interpreter_Branch.cpp index a1e3a5687d..e2cdff4fd6 100644 --- a/Source/Core/Core/PowerPC/Interpreter/Interpreter_Branch.cpp +++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter_Branch.cpp @@ -145,6 +145,6 @@ void Interpreter::sc(Interpreter& interpreter, UGeckoInstruction inst) auto& ppc_state = interpreter.m_ppc_state; ppc_state.Exceptions |= EXCEPTION_SYSCALL; - PowerPC::CheckExceptions(); + interpreter.m_system.GetPowerPC().CheckExceptions(); interpreter.m_end_block = true; } diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter_Integer.cpp b/Source/Core/Core/PowerPC/Interpreter/Interpreter_Integer.cpp index 5cc41be37e..3cf0be2178 100644 --- a/Source/Core/Core/PowerPC/Interpreter/Interpreter_Integer.cpp +++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter_Integer.cpp @@ -10,6 +10,7 @@ #include "Common/Logging/Log.h" #include "Core/PowerPC/Interpreter/ExceptionUtils.h" #include "Core/PowerPC/PowerPC.h" +#include "Core/System.h" void Interpreter::Helper_UpdateCR0(PowerPC::PowerPCState& ppc_state, u32 value) { @@ -150,7 +151,7 @@ void Interpreter::twi(Interpreter& interpreter, UGeckoInstruction inst) (u32(a) < u32(b) && (TO & 0x02) != 0) || (u32(a) > u32(b) && (TO & 0x01) != 0)) { GenerateProgramException(ppc_state, ProgramExceptionCause::Trap); - PowerPC::CheckExceptions(); + interpreter.m_system.GetPowerPC().CheckExceptions(); interpreter.m_end_block = true; // Dunno about this } } @@ -381,7 +382,7 @@ void Interpreter::tw(Interpreter& interpreter, UGeckoInstruction inst) ((u32(a) < u32(b)) && (TO & 0x02) != 0) || ((u32(a) > u32(b)) && (TO & 0x01) != 0)) { GenerateProgramException(ppc_state, ProgramExceptionCause::Trap); - PowerPC::CheckExceptions(); + interpreter.m_system.GetPowerPC().CheckExceptions(); interpreter.m_end_block = true; // Dunno about this } } diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter_SystemRegisters.cpp b/Source/Core/Core/PowerPC/Interpreter/Interpreter_SystemRegisters.cpp index 88314990da..80ddc8efc3 100644 --- a/Source/Core/Core/PowerPC/Interpreter/Interpreter_SystemRegisters.cpp +++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter_SystemRegisters.cpp @@ -29,7 +29,7 @@ mffsx: 80036650 (huh?) static void FPSCRUpdated(PowerPC::PowerPCState& ppc_state) { UpdateFPExceptionSummary(ppc_state); - PowerPC::RoundingModeUpdated(); + PowerPC::RoundingModeUpdated(ppc_state); } void Interpreter::mtfsb0x(Interpreter& interpreter, UGeckoInstruction inst) @@ -184,7 +184,7 @@ void Interpreter::mtmsr(Interpreter& interpreter, UGeckoInstruction inst) // FE0/FE1 may have been set CheckFPExceptions(ppc_state); - PowerPC::CheckExceptions(); + interpreter.m_system.GetPowerPC().CheckExceptions(); interpreter.m_end_block = true; } @@ -249,7 +249,7 @@ void Interpreter::mfspr(Interpreter& interpreter, UGeckoInstruction inst) case SPR_TL: case SPR_TU: - PowerPC::WriteFullTimeBaseValue(SystemTimers::GetFakeTimeBase()); + interpreter.m_system.GetPowerPC().WriteFullTimeBaseValue(SystemTimers::GetFakeTimeBase()); break; case SPR_WPAR: diff --git a/Source/Core/Core/PowerPC/Jit64/Jit.cpp b/Source/Core/Core/PowerPC/Jit64/Jit.cpp index 145a2c9d7e..c23414e930 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit.cpp @@ -593,7 +593,7 @@ void Jit64::WriteRfiExitDestInRSCRATCH() MOV(32, PPCSTATE(npc), R(RSCRATCH)); Cleanup(); ABI_PushRegistersAndAdjustStack({}, 0); - ABI_CallFunction(PowerPC::CheckExceptions); + ABI_CallFunctionP(PowerPC::CheckExceptionsFromJIT, &m_system.GetPowerPC()); ABI_PopRegistersAndAdjustStack({}, 0); SUB(32, PPCSTATE(downcount), Imm32(js.downcountAmount)); JMP(asm_routines.dispatcher, true); @@ -614,7 +614,7 @@ void Jit64::WriteExceptionExit() MOV(32, R(RSCRATCH), PPCSTATE(pc)); MOV(32, PPCSTATE(npc), R(RSCRATCH)); ABI_PushRegistersAndAdjustStack({}, 0); - ABI_CallFunction(PowerPC::CheckExceptions); + ABI_CallFunctionP(PowerPC::CheckExceptionsFromJIT, &m_system.GetPowerPC()); ABI_PopRegistersAndAdjustStack({}, 0); SUB(32, PPCSTATE(downcount), Imm32(js.downcountAmount)); JMP(asm_routines.dispatcher, true); @@ -626,7 +626,7 @@ void Jit64::WriteExternalExceptionExit() MOV(32, R(RSCRATCH), PPCSTATE(pc)); MOV(32, PPCSTATE(npc), R(RSCRATCH)); ABI_PushRegistersAndAdjustStack({}, 0); - ABI_CallFunction(PowerPC::CheckExternalExceptions); + ABI_CallFunctionP(PowerPC::CheckExternalExceptionsFromJIT, &m_system.GetPowerPC()); ABI_PopRegistersAndAdjustStack({}, 0); SUB(32, PPCSTATE(downcount), Imm32(js.downcountAmount)); JMP(asm_routines.dispatcher, true); @@ -740,7 +740,7 @@ void Jit64::Jit(u32 em_address, bool clear_cache_and_retry_on_failure) // Address of instruction could not be translated m_ppc_state.npc = nextPC; m_ppc_state.Exceptions |= EXCEPTION_ISI; - PowerPC::CheckExceptions(); + m_system.GetPowerPC().CheckExceptions(); WARN_LOG_FMT(POWERPC, "ISI exception at {:#010x}", nextPC); return; } @@ -1006,14 +1006,16 @@ bool Jit64::DoJit(u32 em_address, JitBlock* b, u32 nextPC) } auto& cpu = m_system.GetCPU(); - if (m_enable_debugging && breakpoints.IsAddressBreakPoint(op.address) && !cpu.IsStepping()) + auto& power_pc = m_system.GetPowerPC(); + if (m_enable_debugging && power_pc.GetBreakPoints().IsAddressBreakPoint(op.address) && + !cpu.IsStepping()) { gpr.Flush(); fpr.Flush(); MOV(32, PPCSTATE(pc), Imm32(op.address)); ABI_PushRegistersAndAdjustStack({}, 0); - ABI_CallFunction(PowerPC::CheckBreakPoints); + ABI_CallFunctionP(PowerPC::CheckBreakPointsFromJIT, &power_pc); ABI_PopRegistersAndAdjustStack({}, 0); MOV(64, R(RSCRATCH), ImmPtr(cpu.GetStatePtr())); TEST(32, MatR(RSCRATCH), Imm32(0xFFFFFFFF)); diff --git a/Source/Core/Core/PowerPC/JitArm64/Jit.cpp b/Source/Core/Core/PowerPC/JitArm64/Jit.cpp index ce01d560e2..ef0dd426ab 100644 --- a/Source/Core/Core/PowerPC/JitArm64/Jit.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/Jit.cpp @@ -514,10 +514,11 @@ void JitArm64::WriteExceptionExit(ARM64Reg dest, bool only_external, bool always static_assert(PPCSTATE_OFF(pc) + 4 == PPCSTATE_OFF(npc)); STP(IndexType::Signed, DISPATCHER_PC, DISPATCHER_PC, PPC_REG, PPCSTATE_OFF(pc)); + MOVP2R(ARM64Reg::X0, &m_system.GetPowerPC()); if (only_external) - MOVP2R(EncodeRegTo64(DISPATCHER_PC), &PowerPC::CheckExternalExceptions); + MOVP2R(EncodeRegTo64(DISPATCHER_PC), &PowerPC::CheckExternalExceptionsFromJIT); else - MOVP2R(EncodeRegTo64(DISPATCHER_PC), &PowerPC::CheckExceptions); + MOVP2R(EncodeRegTo64(DISPATCHER_PC), &PowerPC::CheckExceptionsFromJIT); BLR(EncodeRegTo64(DISPATCHER_PC)); LDR(IndexType::Unsigned, DISPATCHER_PC, PPC_REG, PPCSTATE_OFF(npc)); @@ -742,7 +743,7 @@ void JitArm64::Jit(u32 em_address, bool clear_cache_and_retry_on_failure) // Address of instruction could not be translated m_ppc_state.npc = nextPC; m_ppc_state.Exceptions |= EXCEPTION_ISI; - PowerPC::CheckExceptions(); + m_system.GetPowerPC().CheckExceptions(); WARN_LOG_FMT(POWERPC, "ISI exception at {:#010x}", nextPC); return; } @@ -1033,8 +1034,8 @@ bool JitArm64::DoJit(u32 em_address, JitBlock* b, u32 nextPC) js.firstFPInstructionFound = true; } - if (m_enable_debugging && PowerPC::breakpoints.IsAddressBreakPoint(op.address) && - !cpu.IsStepping()) + if (m_enable_debugging && !cpu.IsStepping() && + m_system.GetPowerPC().GetBreakPoints().IsAddressBreakPoint(op.address)) { FlushCarry(); gpr.Flush(FlushMode::All, ARM64Reg::INVALID_REG); @@ -1045,8 +1046,9 @@ bool JitArm64::DoJit(u32 em_address, JitBlock* b, u32 nextPC) MOVI2R(DISPATCHER_PC, op.address); STP(IndexType::Signed, DISPATCHER_PC, DISPATCHER_PC, PPC_REG, PPCSTATE_OFF(pc)); - MOVP2R(ARM64Reg::X0, &PowerPC::CheckBreakPoints); - BLR(ARM64Reg::X0); + MOVP2R(ARM64Reg::X0, &m_system.GetPowerPC()); + MOVP2R(ARM64Reg::X1, &PowerPC::CheckBreakPointsFromJIT); + BLR(ARM64Reg::X1); LDR(IndexType::Unsigned, ARM64Reg::W0, ARM64Reg::X0, MOVPage2R(ARM64Reg::X0, cpu.GetStatePtr())); diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64_SystemRegisters.cpp b/Source/Core/Core/PowerPC/JitArm64/JitArm64_SystemRegisters.cpp index ceabebb3c9..f01a0f0cf9 100644 --- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_SystemRegisters.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_SystemRegisters.cpp @@ -78,6 +78,7 @@ void JitArm64::UpdateRoundingMode() ABI_PushRegisters(gprs_to_save); m_float_emit.ABI_PushRegisters(fprs_to_save, ARM64Reg::X8); + MOVP2R(ARM64Reg::X0, &m_ppc_state); MOVP2R(ARM64Reg::X8, &PowerPC::RoundingModeUpdated); BLR(ARM64Reg::X8); m_float_emit.ABI_PopRegisters(fprs_to_save, ARM64Reg::X8); diff --git a/Source/Core/Core/PowerPC/JitCommon/JitBase.cpp b/Source/Core/Core/PowerPC/JitCommon/JitBase.cpp index d0c32c743b..887e73a402 100644 --- a/Source/Core/Core/PowerPC/JitCommon/JitBase.cpp +++ b/Source/Core/Core/PowerPC/JitCommon/JitBase.cpp @@ -220,8 +220,11 @@ bool JitBase::CanMergeNextInstructions(int count) const // Be careful: a breakpoint kills flags in between instructions for (int i = 1; i <= count; i++) { - if (m_enable_debugging && PowerPC::breakpoints.IsAddressBreakPoint(js.op[i].address)) + if (m_enable_debugging && + m_system.GetPowerPC().GetBreakPoints().IsAddressBreakPoint(js.op[i].address)) + { return false; + } if (js.op[i].isBranchTarget) return false; } @@ -230,7 +233,7 @@ bool JitBase::CanMergeNextInstructions(int count) const void JitBase::UpdateMemoryAndExceptionOptions() { - bool any_watchpoints = PowerPC::memchecks.HasAny(); + bool any_watchpoints = m_system.GetPowerPC().GetMemChecks().HasAny(); jo.fastmem = m_fastmem_enabled && jo.fastmem_arena && (m_ppc_state.msr.DR || !any_watchpoints); jo.memcheck = m_mmu_enabled || m_pause_on_panic_enabled || any_watchpoints; jo.fp_exceptions = m_enable_float_exceptions; diff --git a/Source/Core/Core/PowerPC/MMU.cpp b/Source/Core/Core/PowerPC/MMU.cpp index bfbc25c655..a1597b96a5 100644 --- a/Source/Core/Core/PowerPC/MMU.cpp +++ b/Source/Core/Core/PowerPC/MMU.cpp @@ -52,8 +52,8 @@ namespace PowerPC { -MMU::MMU(Core::System& system, Memory::MemoryManager& memory, PowerPC::PowerPCState& ppc_state) - : m_system(system), m_memory(memory), m_ppc_state(ppc_state) +MMU::MMU(Core::System& system, Memory::MemoryManager& memory, PowerPC::PowerPCManager& power_pc) + : m_system(system), m_memory(memory), m_power_pc(power_pc), m_ppc_state(power_pc.GetPPCState()) { } @@ -530,10 +530,10 @@ std::optional> MMU::HostTryReadInstruction(const Core::CPUThread void MMU::Memcheck(u32 address, u64 var, bool write, size_t size) { - if (!memchecks.HasAny()) + if (!m_power_pc.GetMemChecks().HasAny()) return; - TMemCheck* mc = memchecks.GetMemCheck(address, size); + TMemCheck* mc = m_power_pc.GetMemChecks().GetMemCheck(address, size); if (mc == nullptr) return; @@ -545,8 +545,8 @@ void MMU::Memcheck(u32 address, u64 var, bool write, size_t size) mc->num_hits++; - const bool pause = - mc->Action(m_system, &debug_interface, var, address, write, size, m_ppc_state.pc); + const bool pause = mc->Action(m_system, &m_power_pc.GetDebugInterface(), var, address, write, + size, m_ppc_state.pc); if (!pause) return; @@ -892,7 +892,7 @@ std::optional> MMU::HostTryReadString(const Core::CPUThr bool MMU::IsOptimizableRAMAddress(const u32 address) const { - if (PowerPC::memchecks.HasAny()) + if (m_power_pc.GetMemChecks().HasAny()) return false; if (!m_ppc_state.msr.DR) @@ -1189,7 +1189,7 @@ void MMU::TouchDCacheLine(u32 address, bool store) u32 MMU::IsOptimizableMMIOAccess(u32 address, u32 access_size) const { - if (PowerPC::memchecks.HasAny()) + if (m_power_pc.GetMemChecks().HasAny()) return 0; if (!m_ppc_state.msr.DR) @@ -1212,7 +1212,7 @@ u32 MMU::IsOptimizableMMIOAccess(u32 address, u32 access_size) const bool MMU::IsOptimizableGatherPipeWrite(u32 address) const { - if (PowerPC::memchecks.HasAny()) + if (m_power_pc.GetMemChecks().HasAny()) return false; if (!m_ppc_state.msr.DR) @@ -1566,7 +1566,7 @@ void MMU::UpdateBATs(BatTable& bat_table, u32 base_spr) } // Fastmem doesn't support memchecks, so disable it for all overlapping virtual pages. - if (PowerPC::memchecks.OverlapsMemcheck(virtual_address, BAT_PAGE_SIZE)) + if (m_power_pc.GetMemChecks().OverlapsMemcheck(virtual_address, BAT_PAGE_SIZE)) valid_bit &= ~BAT_PHYSICAL_BIT; // (BEPI | j) == (BEPI & ~BL) | (j & BL). @@ -1586,7 +1586,7 @@ void MMU::UpdateFakeMMUBat(BatTable& bat_table, u32 start_addr) u32 p_address = 0x7E000000 | (i << BAT_INDEX_SHIFT & m_memory.GetFakeVMemMask()); u32 flags = BAT_MAPPED_BIT | BAT_PHYSICAL_BIT; - if (PowerPC::memchecks.OverlapsMemcheck(e_address << BAT_INDEX_SHIFT, BAT_PAGE_SIZE)) + if (m_power_pc.GetMemChecks().OverlapsMemcheck(e_address << BAT_INDEX_SHIFT, BAT_PAGE_SIZE)) flags &= ~BAT_PHYSICAL_BIT; bat_table[e_address] = p_address | flags; diff --git a/Source/Core/Core/PowerPC/MMU.h b/Source/Core/Core/PowerPC/MMU.h index a5dda345b8..2ee0173eb5 100644 --- a/Source/Core/Core/PowerPC/MMU.h +++ b/Source/Core/Core/PowerPC/MMU.h @@ -23,6 +23,7 @@ class MemoryManager; namespace PowerPC { +class PowerPCManager; struct PowerPCState; enum class RequestedAddressSpace @@ -108,7 +109,7 @@ enum class XCheckTLBFlag class MMU { public: - MMU(Core::System& system, Memory::MemoryManager& memory, PowerPC::PowerPCState& ppc_state); + MMU(Core::System& system, Memory::MemoryManager& memory, PowerPC::PowerPCManager& power_pc); MMU(const MMU& other) = delete; MMU(MMU&& other) = delete; MMU& operator=(const MMU& other) = delete; @@ -318,6 +319,7 @@ private: Core::System& m_system; Memory::MemoryManager& m_memory; + PowerPC::PowerPCManager& m_power_pc; PowerPC::PowerPCState& m_ppc_state; BatTable m_ibat_table; diff --git a/Source/Core/Core/PowerPC/PPCAnalyst.cpp b/Source/Core/Core/PowerPC/PPCAnalyst.cpp index 029aecb87b..34501a5bbe 100644 --- a/Source/Core/Core/PowerPC/PPCAnalyst.cpp +++ b/Source/Core/Core/PowerPC/PPCAnalyst.cpp @@ -209,10 +209,11 @@ bool PPCAnalyzer::CanSwapAdjacentOps(const CodeOp& a, const CodeOp& b) const u64 b_flags = b_info->flags; // can't reorder around breakpoints - if (m_is_debugging_enabled && (PowerPC::breakpoints.IsAddressBreakPoint(a.address) || - PowerPC::breakpoints.IsAddressBreakPoint(b.address))) + if (m_is_debugging_enabled) { - return false; + auto& breakpoints = Core::System::GetInstance().GetPowerPC().GetBreakPoints(); + if (breakpoints.IsAddressBreakPoint(a.address) || breakpoints.IsAddressBreakPoint(b.address)) + return false; } // Any instruction which can raise an interrupt is *not* a possible swap candidate: // see [1] for an example of a crash caused by this error. diff --git a/Source/Core/Core/PowerPC/PPCSymbolDB.cpp b/Source/Core/Core/PowerPC/PPCSymbolDB.cpp index 61e620248d..fea9a0b586 100644 --- a/Source/Core/Core/PowerPC/PPCSymbolDB.cpp +++ b/Source/Core/Core/PowerPC/PPCSymbolDB.cpp @@ -27,7 +27,7 @@ PPCSymbolDB g_symbolDB; -PPCSymbolDB::PPCSymbolDB() : debugger{&PowerPC::debug_interface} +PPCSymbolDB::PPCSymbolDB() : debugger{&Core::System::GetInstance().GetPowerPC().GetDebugInterface()} { } diff --git a/Source/Core/Core/PowerPC/PowerPC.cpp b/Source/Core/Core/PowerPC/PowerPC.cpp index 6f18fad090..0f88f696a8 100644 --- a/Source/Core/Core/PowerPC/PowerPC.cpp +++ b/Source/Core/Core/PowerPC/PowerPC.cpp @@ -35,19 +35,6 @@ namespace PowerPC { -// STATE_TO_SAVE -PowerPCState ppcState; - -static CPUCoreBase* s_cpu_core_base = nullptr; -static bool s_cpu_core_base_is_injected = false; -static CoreMode s_mode = CoreMode::Interpreter; - -BreakPoints breakpoints; -MemChecks memchecks; -PPCDebugInterface debug_interface(Core::System::GetInstance()); - -static CoreTiming::EventType* s_invalidate_cache_thread_safe; - double PairedSingle::PS0AsDouble() const { return Common::BitCast(ps0); @@ -70,7 +57,7 @@ void PairedSingle::SetPS1(double value) static void InvalidateCacheThreadSafe(Core::System& system, u64 userdata, s64 cyclesLate) { - ppcState.iCache.Invalidate(static_cast(userdata)); + system.GetPPCState().iCache.Invalidate(static_cast(userdata)); } std::istream& operator>>(std::istream& is, CPUCore& core) @@ -97,7 +84,14 @@ std::ostream& operator<<(std::ostream& os, CPUCore core) return os; } -void DoState(PointerWrap& p) +PowerPCManager::PowerPCManager(Core::System& system) + : m_breakpoints(system), m_memchecks(system), m_debug_interface(system), m_system(system) +{ +} + +PowerPCManager::~PowerPCManager() = default; + +void PowerPCManager::DoState(PointerWrap& p) { // some of this code has been disabled, because // it changes registers even in Mode::Measure (which is suspicious and seems like it could cause @@ -105,49 +99,49 @@ void DoState(PointerWrap& p) // and because the values it's changing have been added to CoreTiming::DoState, so it might // conflict to mess with them here. - // PowerPC::ppcState.spr[SPR_DEC] = SystemTimers::GetFakeDecrementer(); - // *((u64 *)&TL(PowerPC::ppcState)) = SystemTimers::GetFakeTimeBase(); //works since we are little + // m_ppc_state.spr[SPR_DEC] = SystemTimers::GetFakeDecrementer(); + // *((u64 *)&TL(m_ppc_state)) = SystemTimers::GetFakeTimeBase(); //works since we are little // endian and TL comes first :) - p.DoArray(ppcState.gpr); - p.Do(ppcState.pc); - p.Do(ppcState.npc); - p.DoArray(ppcState.cr.fields); - p.Do(ppcState.msr); - p.Do(ppcState.fpscr); - p.Do(ppcState.Exceptions); - p.Do(ppcState.downcount); - p.Do(ppcState.xer_ca); - p.Do(ppcState.xer_so_ov); - p.Do(ppcState.xer_stringctrl); - p.DoArray(ppcState.ps); - p.DoArray(ppcState.sr); - p.DoArray(ppcState.spr); - p.DoArray(ppcState.tlb); - p.Do(ppcState.pagetable_base); - p.Do(ppcState.pagetable_hashmask); + p.DoArray(m_ppc_state.gpr); + p.Do(m_ppc_state.pc); + p.Do(m_ppc_state.npc); + p.DoArray(m_ppc_state.cr.fields); + p.Do(m_ppc_state.msr); + p.Do(m_ppc_state.fpscr); + p.Do(m_ppc_state.Exceptions); + p.Do(m_ppc_state.downcount); + p.Do(m_ppc_state.xer_ca); + p.Do(m_ppc_state.xer_so_ov); + p.Do(m_ppc_state.xer_stringctrl); + p.DoArray(m_ppc_state.ps); + p.DoArray(m_ppc_state.sr); + p.DoArray(m_ppc_state.spr); + p.DoArray(m_ppc_state.tlb); + p.Do(m_ppc_state.pagetable_base); + p.Do(m_ppc_state.pagetable_hashmask); - p.Do(ppcState.reserve); - p.Do(ppcState.reserve_address); + p.Do(m_ppc_state.reserve); + p.Do(m_ppc_state.reserve_address); - ppcState.iCache.DoState(p); - ppcState.dCache.DoState(p); + m_ppc_state.iCache.DoState(p); + m_ppc_state.dCache.DoState(p); if (p.IsReadMode()) { - if (!ppcState.m_enable_dcache) + if (!m_ppc_state.m_enable_dcache) { INFO_LOG_FMT(POWERPC, "Flushing data cache"); - ppcState.dCache.FlushAll(); + m_ppc_state.dCache.FlushAll(); } else { - ppcState.dCache.Reset(); + m_ppc_state.dCache.Reset(); } - RoundingModeUpdated(); + RoundingModeUpdated(m_ppc_state); - auto& mmu = Core::System::GetInstance().GetMMU(); + auto& mmu = m_system.GetMMU(); mmu.IBATUpdated(); mmu.DBATUpdated(); } @@ -155,15 +149,15 @@ void DoState(PointerWrap& p) // SystemTimers::DecrementerSet(); // SystemTimers::TimeBaseSet(); - Core::System::GetInstance().GetJitInterface().DoState(p); + m_system.GetJitInterface().DoState(p); } -static void ResetRegisters() +void PowerPCManager::ResetRegisters() { - std::fill(std::begin(ppcState.ps), std::end(ppcState.ps), PairedSingle{}); - std::fill(std::begin(ppcState.sr), std::end(ppcState.sr), 0U); - std::fill(std::begin(ppcState.gpr), std::end(ppcState.gpr), 0U); - std::fill(std::begin(ppcState.spr), std::end(ppcState.spr), 0U); + std::fill(std::begin(m_ppc_state.ps), std::end(m_ppc_state.ps), PairedSingle{}); + std::fill(std::begin(m_ppc_state.sr), std::end(m_ppc_state.sr), 0U); + std::fill(std::begin(m_ppc_state.gpr), std::end(m_ppc_state.gpr), 0U); + std::fill(std::begin(m_ppc_state.spr), std::end(m_ppc_state.spr), 0U); // Gamecube: // 0x00080200 = lonestar 2.0 @@ -178,73 +172,72 @@ static void ResetRegisters() // 0x00087102 = broadway retail hw if (SConfig::GetInstance().bWii) { - ppcState.spr[SPR_PVR] = 0x00087102; + m_ppc_state.spr[SPR_PVR] = 0x00087102; } else { - ppcState.spr[SPR_PVR] = 0x00083214; + m_ppc_state.spr[SPR_PVR] = 0x00083214; } - ppcState.spr[SPR_HID1] = 0x80000000; // We're running at 3x the bus clock - ppcState.spr[SPR_ECID_U] = 0x0d96e200; - ppcState.spr[SPR_ECID_M] = 0x1840c00d; - ppcState.spr[SPR_ECID_L] = 0x82bb08e8; + m_ppc_state.spr[SPR_HID1] = 0x80000000; // We're running at 3x the bus clock + m_ppc_state.spr[SPR_ECID_U] = 0x0d96e200; + m_ppc_state.spr[SPR_ECID_M] = 0x1840c00d; + m_ppc_state.spr[SPR_ECID_L] = 0x82bb08e8; - ppcState.fpscr.Hex = 0; - ppcState.pc = 0; - ppcState.npc = 0; - ppcState.Exceptions = 0; + m_ppc_state.fpscr.Hex = 0; + m_ppc_state.pc = 0; + m_ppc_state.npc = 0; + m_ppc_state.Exceptions = 0; - ppcState.reserve = false; - ppcState.reserve_address = 0; + m_ppc_state.reserve = false; + m_ppc_state.reserve_address = 0; - for (auto& v : ppcState.cr.fields) + for (auto& v : m_ppc_state.cr.fields) { v = 0x8000000000000001; } - ppcState.SetXER({}); + m_ppc_state.SetXER({}); - RoundingModeUpdated(); + RoundingModeUpdated(m_ppc_state); - auto& mmu = Core::System::GetInstance().GetMMU(); + auto& mmu = m_system.GetMMU(); mmu.DBATUpdated(); mmu.IBATUpdated(); - TL(PowerPC::ppcState) = 0; - TU(PowerPC::ppcState) = 0; + TL(m_ppc_state) = 0; + TU(m_ppc_state) = 0; SystemTimers::TimeBaseSet(); // MSR should be 0x40, but we don't emulate BS1, so it would never be turned off :} - ppcState.msr.Hex = 0; - ppcState.spr[SPR_DEC] = 0xFFFFFFFF; + m_ppc_state.msr.Hex = 0; + m_ppc_state.spr[SPR_DEC] = 0xFFFFFFFF; SystemTimers::DecrementerSet(); } -static void InitializeCPUCore(CPUCore cpu_core) +void PowerPCManager::InitializeCPUCore(CPUCore cpu_core) { // We initialize the interpreter because // it is used on boot and code window independently. - auto& system = Core::System::GetInstance(); - auto& interpreter = system.GetInterpreter(); + auto& interpreter = m_system.GetInterpreter(); interpreter.Init(); switch (cpu_core) { case CPUCore::Interpreter: - s_cpu_core_base = &interpreter; + m_cpu_core_base = &interpreter; break; default: - s_cpu_core_base = system.GetJitInterface().InitJitCore(cpu_core); - if (!s_cpu_core_base) // Handle Situations where JIT core isn't available + m_cpu_core_base = m_system.GetJitInterface().InitJitCore(cpu_core); + if (!m_cpu_core_base) // Handle Situations where JIT core isn't available { WARN_LOG_FMT(POWERPC, "CPU core {} not available. Falling back to default.", static_cast(cpu_core)); - s_cpu_core_base = system.GetJitInterface().InitJitCore(DefaultCPUCore()); + m_cpu_core_base = m_system.GetJitInterface().InitJitCore(DefaultCPUCore()); } break; } - s_mode = s_cpu_core_base == &interpreter ? CoreMode::Interpreter : CoreMode::JIT; + m_mode = m_cpu_core_base == &interpreter ? CoreMode::Interpreter : CoreMode::JIT; } const std::vector& AvailableCPUCores() @@ -273,147 +266,143 @@ CPUCore DefaultCPUCore() #endif } -void Init(CPUCore cpu_core) +void PowerPCManager::Init(CPUCore cpu_core) { - s_invalidate_cache_thread_safe = Core::System::GetInstance().GetCoreTiming().RegisterEvent( - "invalidateEmulatedCache", InvalidateCacheThreadSafe); + m_invalidate_cache_thread_safe = + m_system.GetCoreTiming().RegisterEvent("invalidateEmulatedCache", InvalidateCacheThreadSafe); Reset(); InitializeCPUCore(cpu_core); - ppcState.iCache.Init(); - ppcState.dCache.Init(); + m_ppc_state.iCache.Init(); + m_ppc_state.dCache.Init(); - ppcState.m_enable_dcache = Config::Get(Config::MAIN_ACCURATE_CPU_CACHE); + m_ppc_state.m_enable_dcache = Config::Get(Config::MAIN_ACCURATE_CPU_CACHE); if (Config::Get(Config::MAIN_ENABLE_DEBUGGING)) - breakpoints.ClearAllTemporary(); + m_breakpoints.ClearAllTemporary(); } -void Reset() +void PowerPCManager::Reset() { - ppcState.pagetable_base = 0; - ppcState.pagetable_hashmask = 0; - ppcState.tlb = {}; + m_ppc_state.pagetable_base = 0; + m_ppc_state.pagetable_hashmask = 0; + m_ppc_state.tlb = {}; ResetRegisters(); - ppcState.iCache.Reset(); - ppcState.dCache.Reset(); + m_ppc_state.iCache.Reset(); + m_ppc_state.dCache.Reset(); } -void ScheduleInvalidateCacheThreadSafe(u32 address) +void PowerPCManager::ScheduleInvalidateCacheThreadSafe(u32 address) { - auto& system = Core::System::GetInstance(); - auto& cpu = system.GetCPU(); + auto& cpu = m_system.GetCPU(); if (cpu.GetState() == CPU::State::Running && !Core::IsCPUThread()) { - system.GetCoreTiming().ScheduleEvent(0, s_invalidate_cache_thread_safe, address, - CoreTiming::FromThread::NON_CPU); + m_system.GetCoreTiming().ScheduleEvent(0, m_invalidate_cache_thread_safe, address, + CoreTiming::FromThread::NON_CPU); } else { - PowerPC::ppcState.iCache.Invalidate(static_cast(address)); + m_ppc_state.iCache.Invalidate(static_cast(address)); } } -void Shutdown() +void PowerPCManager::Shutdown() { InjectExternalCPUCore(nullptr); - auto& system = Core::System::GetInstance(); - system.GetJitInterface().Shutdown(); - auto& interpreter = system.GetInterpreter(); - interpreter.Shutdown(); - s_cpu_core_base = nullptr; + m_system.GetJitInterface().Shutdown(); + m_system.GetInterpreter().Shutdown(); + m_cpu_core_base = nullptr; } -CoreMode GetMode() +CoreMode PowerPCManager::GetMode() const { - return !s_cpu_core_base_is_injected ? s_mode : CoreMode::Interpreter; + return !m_cpu_core_base_is_injected ? m_mode : CoreMode::Interpreter; } -static void ApplyMode() +void PowerPCManager::ApplyMode() { - auto& system = Core::System::GetInstance(); - auto& interpreter = system.GetInterpreter(); + auto& interpreter = m_system.GetInterpreter(); - switch (s_mode) + switch (m_mode) { case CoreMode::Interpreter: // Switching from JIT to interpreter - s_cpu_core_base = &interpreter; + m_cpu_core_base = &interpreter; break; case CoreMode::JIT: // Switching from interpreter to JIT. // Don't really need to do much. It'll work, the cache will refill itself. - s_cpu_core_base = system.GetJitInterface().GetCore(); - if (!s_cpu_core_base) // Has a chance to not get a working JIT core if one isn't active on host - s_cpu_core_base = &interpreter; + m_cpu_core_base = m_system.GetJitInterface().GetCore(); + if (!m_cpu_core_base) // Has a chance to not get a working JIT core if one isn't active on host + m_cpu_core_base = &interpreter; break; } } -void SetMode(CoreMode new_mode) +void PowerPCManager::SetMode(CoreMode new_mode) { - if (new_mode == s_mode) + if (new_mode == m_mode) return; // We don't need to do anything. - s_mode = new_mode; + m_mode = new_mode; // If we're using an external CPU core implementation then don't do anything. - if (s_cpu_core_base_is_injected) + if (m_cpu_core_base_is_injected) return; ApplyMode(); } -const char* GetCPUName() +const char* PowerPCManager::GetCPUName() const { - return s_cpu_core_base->GetName(); + return m_cpu_core_base->GetName(); } -void InjectExternalCPUCore(CPUCoreBase* new_cpu) +void PowerPCManager::InjectExternalCPUCore(CPUCoreBase* new_cpu) { // Previously injected. - if (s_cpu_core_base_is_injected) - s_cpu_core_base->Shutdown(); + if (m_cpu_core_base_is_injected) + m_cpu_core_base->Shutdown(); // nullptr means just remove if (!new_cpu) { - if (s_cpu_core_base_is_injected) + if (m_cpu_core_base_is_injected) { - s_cpu_core_base_is_injected = false; + m_cpu_core_base_is_injected = false; ApplyMode(); } return; } new_cpu->Init(); - s_cpu_core_base = new_cpu; - s_cpu_core_base_is_injected = true; + m_cpu_core_base = new_cpu; + m_cpu_core_base_is_injected = true; } -void SingleStep() +void PowerPCManager::SingleStep() { - s_cpu_core_base->SingleStep(); + m_cpu_core_base->SingleStep(); } -void RunLoop() +void PowerPCManager::RunLoop() { - s_cpu_core_base->Run(); + m_cpu_core_base->Run(); Host_UpdateDisasmDialog(); } -u64 ReadFullTimeBaseValue() +u64 PowerPCManager::ReadFullTimeBaseValue() const { u64 value; - std::memcpy(&value, &TL(PowerPC::ppcState), sizeof(value)); + std::memcpy(&value, &TL(m_ppc_state), sizeof(value)); return value; } -void WriteFullTimeBaseValue(u64 value) +void PowerPCManager::WriteFullTimeBaseValue(u64 value) { - std::memcpy(&TL(PowerPC::ppcState), &value, sizeof(value)); + std::memcpy(&TL(m_ppc_state), &value, sizeof(value)); } void UpdatePerformanceMonitor(u32 cycles, u32 num_load_stores, u32 num_fp_inst, @@ -478,9 +467,9 @@ void UpdatePerformanceMonitor(u32 cycles, u32 num_load_stores, u32 num_fp_inst, } } -void CheckExceptions() +void PowerPCManager::CheckExceptions() { - u32 exceptions = ppcState.Exceptions; + u32 exceptions = m_ppc_state.Exceptions; // Example procedure: // Set SRR0 to either PC or NPC @@ -505,79 +494,79 @@ void CheckExceptions() if (exceptions & EXCEPTION_ISI) { - SRR0(PowerPC::ppcState) = PowerPC::ppcState.npc; + SRR0(m_ppc_state) = m_ppc_state.npc; // Page fault occurred - SRR1(PowerPC::ppcState) = (PowerPC::ppcState.msr.Hex & 0x87C0FFFF) | (1 << 30); - PowerPC::ppcState.msr.LE = PowerPC::ppcState.msr.ILE; - PowerPC::ppcState.msr.Hex &= ~0x04EF36; - PowerPC::ppcState.pc = PowerPC::ppcState.npc = 0x00000400; + SRR1(m_ppc_state) = (m_ppc_state.msr.Hex & 0x87C0FFFF) | (1 << 30); + m_ppc_state.msr.LE = m_ppc_state.msr.ILE; + m_ppc_state.msr.Hex &= ~0x04EF36; + m_ppc_state.pc = m_ppc_state.npc = 0x00000400; DEBUG_LOG_FMT(POWERPC, "EXCEPTION_ISI"); - ppcState.Exceptions &= ~EXCEPTION_ISI; + m_ppc_state.Exceptions &= ~EXCEPTION_ISI; } else if (exceptions & EXCEPTION_PROGRAM) { - SRR0(PowerPC::ppcState) = PowerPC::ppcState.pc; + SRR0(m_ppc_state) = m_ppc_state.pc; // SRR1 was partially set by GenerateProgramException, so bitwise or is used here - SRR1(PowerPC::ppcState) |= PowerPC::ppcState.msr.Hex & 0x87C0FFFF; - PowerPC::ppcState.msr.LE = PowerPC::ppcState.msr.ILE; - PowerPC::ppcState.msr.Hex &= ~0x04EF36; - PowerPC::ppcState.pc = PowerPC::ppcState.npc = 0x00000700; + SRR1(m_ppc_state) |= m_ppc_state.msr.Hex & 0x87C0FFFF; + m_ppc_state.msr.LE = m_ppc_state.msr.ILE; + m_ppc_state.msr.Hex &= ~0x04EF36; + m_ppc_state.pc = m_ppc_state.npc = 0x00000700; DEBUG_LOG_FMT(POWERPC, "EXCEPTION_PROGRAM"); - ppcState.Exceptions &= ~EXCEPTION_PROGRAM; + m_ppc_state.Exceptions &= ~EXCEPTION_PROGRAM; } else if (exceptions & EXCEPTION_SYSCALL) { - SRR0(PowerPC::ppcState) = PowerPC::ppcState.npc; - SRR1(PowerPC::ppcState) = PowerPC::ppcState.msr.Hex & 0x87C0FFFF; - PowerPC::ppcState.msr.LE = PowerPC::ppcState.msr.ILE; - PowerPC::ppcState.msr.Hex &= ~0x04EF36; - PowerPC::ppcState.pc = PowerPC::ppcState.npc = 0x00000C00; + SRR0(m_ppc_state) = m_ppc_state.npc; + SRR1(m_ppc_state) = m_ppc_state.msr.Hex & 0x87C0FFFF; + m_ppc_state.msr.LE = m_ppc_state.msr.ILE; + m_ppc_state.msr.Hex &= ~0x04EF36; + m_ppc_state.pc = m_ppc_state.npc = 0x00000C00; - DEBUG_LOG_FMT(POWERPC, "EXCEPTION_SYSCALL (PC={:08x})", PowerPC::ppcState.pc); - ppcState.Exceptions &= ~EXCEPTION_SYSCALL; + DEBUG_LOG_FMT(POWERPC, "EXCEPTION_SYSCALL (PC={:08x})", m_ppc_state.pc); + m_ppc_state.Exceptions &= ~EXCEPTION_SYSCALL; } else if (exceptions & EXCEPTION_FPU_UNAVAILABLE) { // This happens a lot - GameCube OS uses deferred FPU context switching - SRR0(PowerPC::ppcState) = PowerPC::ppcState.pc; // re-execute the instruction - SRR1(PowerPC::ppcState) = PowerPC::ppcState.msr.Hex & 0x87C0FFFF; - PowerPC::ppcState.msr.LE = PowerPC::ppcState.msr.ILE; - PowerPC::ppcState.msr.Hex &= ~0x04EF36; - PowerPC::ppcState.pc = PowerPC::ppcState.npc = 0x00000800; + SRR0(m_ppc_state) = m_ppc_state.pc; // re-execute the instruction + SRR1(m_ppc_state) = m_ppc_state.msr.Hex & 0x87C0FFFF; + m_ppc_state.msr.LE = m_ppc_state.msr.ILE; + m_ppc_state.msr.Hex &= ~0x04EF36; + m_ppc_state.pc = m_ppc_state.npc = 0x00000800; DEBUG_LOG_FMT(POWERPC, "EXCEPTION_FPU_UNAVAILABLE"); - ppcState.Exceptions &= ~EXCEPTION_FPU_UNAVAILABLE; + m_ppc_state.Exceptions &= ~EXCEPTION_FPU_UNAVAILABLE; } else if (exceptions & EXCEPTION_FAKE_MEMCHECK_HIT) { - ppcState.Exceptions &= ~EXCEPTION_DSI & ~EXCEPTION_FAKE_MEMCHECK_HIT; + m_ppc_state.Exceptions &= ~EXCEPTION_DSI & ~EXCEPTION_FAKE_MEMCHECK_HIT; } else if (exceptions & EXCEPTION_DSI) { - SRR0(PowerPC::ppcState) = PowerPC::ppcState.pc; - SRR1(PowerPC::ppcState) = PowerPC::ppcState.msr.Hex & 0x87C0FFFF; - PowerPC::ppcState.msr.LE = PowerPC::ppcState.msr.ILE; - PowerPC::ppcState.msr.Hex &= ~0x04EF36; - PowerPC::ppcState.pc = PowerPC::ppcState.npc = 0x00000300; + SRR0(m_ppc_state) = m_ppc_state.pc; + SRR1(m_ppc_state) = m_ppc_state.msr.Hex & 0x87C0FFFF; + m_ppc_state.msr.LE = m_ppc_state.msr.ILE; + m_ppc_state.msr.Hex &= ~0x04EF36; + m_ppc_state.pc = m_ppc_state.npc = 0x00000300; // DSISR and DAR regs are changed in GenerateDSIException() DEBUG_LOG_FMT(POWERPC, "EXCEPTION_DSI"); - ppcState.Exceptions &= ~EXCEPTION_DSI; + m_ppc_state.Exceptions &= ~EXCEPTION_DSI; } else if (exceptions & EXCEPTION_ALIGNMENT) { - SRR0(PowerPC::ppcState) = PowerPC::ppcState.pc; - SRR1(PowerPC::ppcState) = PowerPC::ppcState.msr.Hex & 0x87C0FFFF; - PowerPC::ppcState.msr.LE = PowerPC::ppcState.msr.ILE; - PowerPC::ppcState.msr.Hex &= ~0x04EF36; - PowerPC::ppcState.pc = PowerPC::ppcState.npc = 0x00000600; + SRR0(m_ppc_state) = m_ppc_state.pc; + SRR1(m_ppc_state) = m_ppc_state.msr.Hex & 0x87C0FFFF; + m_ppc_state.msr.LE = m_ppc_state.msr.ILE; + m_ppc_state.msr.Hex &= ~0x04EF36; + m_ppc_state.pc = m_ppc_state.npc = 0x00000600; // TODO crazy amount of DSISR options to check out DEBUG_LOG_FMT(POWERPC, "EXCEPTION_ALIGNMENT"); - ppcState.Exceptions &= ~EXCEPTION_ALIGNMENT; + m_ppc_state.Exceptions &= ~EXCEPTION_ALIGNMENT; } // EXTERNAL INTERRUPT @@ -587,50 +576,49 @@ void CheckExceptions() } } -void CheckExternalExceptions() +void PowerPCManager::CheckExternalExceptions() { - u32 exceptions = ppcState.Exceptions; + u32 exceptions = m_ppc_state.Exceptions; // EXTERNAL INTERRUPT // Handling is delayed until MSR.EE=1. - if (exceptions && PowerPC::ppcState.msr.EE) + if (exceptions && m_ppc_state.msr.EE) { if (exceptions & EXCEPTION_EXTERNAL_INT) { // Pokemon gets this "too early", it hasn't a handler yet - SRR0(PowerPC::ppcState) = PowerPC::ppcState.npc; - SRR1(PowerPC::ppcState) = PowerPC::ppcState.msr.Hex & 0x87C0FFFF; - PowerPC::ppcState.msr.LE = PowerPC::ppcState.msr.ILE; - PowerPC::ppcState.msr.Hex &= ~0x04EF36; - PowerPC::ppcState.pc = PowerPC::ppcState.npc = 0x00000500; + SRR0(m_ppc_state) = m_ppc_state.npc; + SRR1(m_ppc_state) = m_ppc_state.msr.Hex & 0x87C0FFFF; + m_ppc_state.msr.LE = m_ppc_state.msr.ILE; + m_ppc_state.msr.Hex &= ~0x04EF36; + m_ppc_state.pc = m_ppc_state.npc = 0x00000500; DEBUG_LOG_FMT(POWERPC, "EXCEPTION_EXTERNAL_INT"); - ppcState.Exceptions &= ~EXCEPTION_EXTERNAL_INT; + m_ppc_state.Exceptions &= ~EXCEPTION_EXTERNAL_INT; - DEBUG_ASSERT_MSG(POWERPC, (SRR1(PowerPC::ppcState) & 0x02) != 0, - "EXTERNAL_INT unrecoverable???"); + DEBUG_ASSERT_MSG(POWERPC, (SRR1(m_ppc_state) & 0x02) != 0, "EXTERNAL_INT unrecoverable???"); } else if (exceptions & EXCEPTION_PERFORMANCE_MONITOR) { - SRR0(PowerPC::ppcState) = PowerPC::ppcState.npc; - SRR1(PowerPC::ppcState) = PowerPC::ppcState.msr.Hex & 0x87C0FFFF; - PowerPC::ppcState.msr.LE = PowerPC::ppcState.msr.ILE; - PowerPC::ppcState.msr.Hex &= ~0x04EF36; - PowerPC::ppcState.pc = PowerPC::ppcState.npc = 0x00000F00; + SRR0(m_ppc_state) = m_ppc_state.npc; + SRR1(m_ppc_state) = m_ppc_state.msr.Hex & 0x87C0FFFF; + m_ppc_state.msr.LE = m_ppc_state.msr.ILE; + m_ppc_state.msr.Hex &= ~0x04EF36; + m_ppc_state.pc = m_ppc_state.npc = 0x00000F00; DEBUG_LOG_FMT(POWERPC, "EXCEPTION_PERFORMANCE_MONITOR"); - ppcState.Exceptions &= ~EXCEPTION_PERFORMANCE_MONITOR; + m_ppc_state.Exceptions &= ~EXCEPTION_PERFORMANCE_MONITOR; } else if (exceptions & EXCEPTION_DECREMENTER) { - SRR0(PowerPC::ppcState) = PowerPC::ppcState.npc; - SRR1(PowerPC::ppcState) = PowerPC::ppcState.msr.Hex & 0x87C0FFFF; - PowerPC::ppcState.msr.LE = PowerPC::ppcState.msr.ILE; - PowerPC::ppcState.msr.Hex &= ~0x04EF36; - PowerPC::ppcState.pc = PowerPC::ppcState.npc = 0x00000900; + SRR0(m_ppc_state) = m_ppc_state.npc; + SRR1(m_ppc_state) = m_ppc_state.msr.Hex & 0x87C0FFFF; + m_ppc_state.msr.LE = m_ppc_state.msr.ILE; + m_ppc_state.msr.Hex &= ~0x04EF36; + m_ppc_state.pc = m_ppc_state.npc = 0x00000900; DEBUG_LOG_FMT(POWERPC, "EXCEPTION_DECREMENTER"); - ppcState.Exceptions &= ~EXCEPTION_DECREMENTER; + m_ppc_state.Exceptions &= ~EXCEPTION_DECREMENTER; } else { @@ -641,17 +629,16 @@ void CheckExternalExceptions() } } -void CheckBreakPoints() +void PowerPCManager::CheckBreakPoints() { - const TBreakPoint* bp = PowerPC::breakpoints.GetBreakpoint(PowerPC::ppcState.pc); + const TBreakPoint* bp = m_breakpoints.GetBreakpoint(m_ppc_state.pc); - if (!bp || !bp->is_enabled || !EvaluateCondition(Core::System::GetInstance(), bp->condition)) + if (!bp || !bp->is_enabled || !EvaluateCondition(m_system, bp->condition)) return; if (bp->break_on_hit) { - auto& system = Core::System::GetInstance(); - system.GetCPU().Break(); + m_system.GetCPU().Break(); if (GDBStub::IsActive()) GDBStub::TakeControl(); } @@ -660,14 +647,13 @@ void CheckBreakPoints() NOTICE_LOG_FMT(MEMMAP, "BP {:08x} {}({:08x} {:08x} {:08x} {:08x} {:08x} {:08x} {:08x} {:08x} {:08x} " "{:08x}) LR={:08x}", - PowerPC::ppcState.pc, g_symbolDB.GetDescription(PowerPC::ppcState.pc), - PowerPC::ppcState.gpr[3], PowerPC::ppcState.gpr[4], PowerPC::ppcState.gpr[5], - PowerPC::ppcState.gpr[6], PowerPC::ppcState.gpr[7], PowerPC::ppcState.gpr[8], - PowerPC::ppcState.gpr[9], PowerPC::ppcState.gpr[10], PowerPC::ppcState.gpr[11], - PowerPC::ppcState.gpr[12], LR(PowerPC::ppcState)); + m_ppc_state.pc, g_symbolDB.GetDescription(m_ppc_state.pc), m_ppc_state.gpr[3], + m_ppc_state.gpr[4], m_ppc_state.gpr[5], m_ppc_state.gpr[6], m_ppc_state.gpr[7], + m_ppc_state.gpr[8], m_ppc_state.gpr[9], m_ppc_state.gpr[10], m_ppc_state.gpr[11], + m_ppc_state.gpr[12], LR(m_ppc_state)); } - if (PowerPC::breakpoints.IsTempBreakPoint(PowerPC::ppcState.pc)) - PowerPC::breakpoints.Remove(PowerPC::ppcState.pc); + if (m_breakpoints.IsTempBreakPoint(m_ppc_state.pc)) + m_breakpoints.Remove(m_ppc_state.pc); } void PowerPCState::SetSR(u32 index, u32 value) @@ -688,12 +674,26 @@ void PowerPCState::UpdateFPRFSingle(float fvalue) fpscr.FPRF = Common::ClassifyFloat(fvalue); } -void RoundingModeUpdated() +void RoundingModeUpdated(PowerPCState& ppc_state) { // The rounding mode is separate for each thread, so this must run on the CPU thread ASSERT(Core::IsCPUThread()); - Common::FPU::SetSIMDMode(PowerPC::ppcState.fpscr.RN, PowerPC::ppcState.fpscr.NI); + Common::FPU::SetSIMDMode(ppc_state.fpscr.RN, ppc_state.fpscr.NI); } +void CheckExceptionsFromJIT(PowerPCManager& power_pc) +{ + power_pc.CheckExceptions(); +} + +void CheckExternalExceptionsFromJIT(PowerPCManager& power_pc) +{ + power_pc.CheckExternalExceptions(); +} + +void CheckBreakPointsFromJIT(PowerPCManager& power_pc) +{ + power_pc.CheckBreakPoints(); +} } // namespace PowerPC diff --git a/Source/Core/Core/PowerPC/PowerPC.h b/Source/Core/Core/PowerPC/PowerPC.h index 53697cd0ef..42545f2c1f 100644 --- a/Source/Core/Core/PowerPC/PowerPC.h +++ b/Source/Core/Core/PowerPC/PowerPC.h @@ -20,6 +20,10 @@ class CPUCoreBase; class PointerWrap; +namespace CoreTiming +{ +struct EventType; +} namespace PowerPC { @@ -234,49 +238,86 @@ static_assert(offsetof(PowerPC::PowerPCState, above_fits_in_first_0x100) <= 0x10 #endif #endif -extern PowerPCState ppcState; - -extern BreakPoints breakpoints; -extern MemChecks memchecks; -extern PPCDebugInterface debug_interface; - const std::vector& AvailableCPUCores(); CPUCore DefaultCPUCore(); -void Init(CPUCore cpu_core); -void Reset(); -void Shutdown(); -void DoState(PointerWrap& p); -void ScheduleInvalidateCacheThreadSafe(u32 address); +class PowerPCManager +{ +public: + explicit PowerPCManager(Core::System& system); + PowerPCManager(const PowerPCManager& other) = delete; + PowerPCManager(PowerPCManager&& other) = delete; + PowerPCManager& operator=(const PowerPCManager& other) = delete; + PowerPCManager& operator=(PowerPCManager&& other) = delete; + ~PowerPCManager(); -CoreMode GetMode(); -// [NOT THREADSAFE] CPU Thread or CPU::PauseAndLock or Core::State::Uninitialized -void SetMode(CoreMode _coreType); -const char* GetCPUName(); + void Init(CPUCore cpu_core); + void Reset(); + void Shutdown(); + void DoState(PointerWrap& p); + void ScheduleInvalidateCacheThreadSafe(u32 address); -// Set the current CPU Core to the given implementation until removed. -// Remove the current injected CPU Core by passing nullptr. -// While an external CPUCoreBase is injected, GetMode() will return CoreMode::Interpreter. -// Init() will be called when added and Shutdown() when removed. -// [Threadsafety: Same as SetMode(), except it cannot be called from inside the CPU -// run loop on the CPU Thread - it doesn't make sense for a CPU to remove itself -// while it is in State::Running] -void InjectExternalCPUCore(CPUCoreBase* core); + CoreMode GetMode() const; + // [NOT THREADSAFE] CPU Thread or CPU::PauseAndLock or Core::State::Uninitialized + void SetMode(CoreMode _coreType); + const char* GetCPUName() const; -// Stepping requires the CPU Execution lock (CPU::PauseAndLock or CPU Thread) -// It's not threadsafe otherwise. -void SingleStep(); -void CheckExceptions(); -void CheckExternalExceptions(); -void CheckBreakPoints(); -void RunLoop(); + // Set the current CPU Core to the given implementation until removed. + // Remove the current injected CPU Core by passing nullptr. + // While an external CPUCoreBase is injected, GetMode() will return CoreMode::Interpreter. + // Init() will be called when added and Shutdown() when removed. + // [Threadsafety: Same as SetMode(), except it cannot be called from inside the CPU + // run loop on the CPU Thread - it doesn't make sense for a CPU to remove itself + // while it is in State::Running] + void InjectExternalCPUCore(CPUCoreBase* core); -u64 ReadFullTimeBaseValue(); -void WriteFullTimeBaseValue(u64 value); + // Stepping requires the CPU Execution lock (CPU::PauseAndLock or CPU Thread) + // It's not threadsafe otherwise. + void SingleStep(); + void CheckExceptions(); + void CheckExternalExceptions(); + void CheckBreakPoints(); + void RunLoop(); + + u64 ReadFullTimeBaseValue() const; + void WriteFullTimeBaseValue(u64 value); + + PowerPCState& GetPPCState() { return m_ppc_state; } + const PowerPCState& GetPPCState() const { return m_ppc_state; } + BreakPoints& GetBreakPoints() { return m_breakpoints; } + const BreakPoints& GetBreakPoints() const { return m_breakpoints; } + MemChecks& GetMemChecks() { return m_memchecks; } + const MemChecks& GetMemChecks() const { return m_memchecks; } + PPCDebugInterface& GetDebugInterface() { return m_debug_interface; } + const PPCDebugInterface& GetDebugInterface() const { return m_debug_interface; } + +private: + void InitializeCPUCore(CPUCore cpu_core); + void ApplyMode(); + void ResetRegisters(); + + PowerPCState m_ppc_state; + + CPUCoreBase* m_cpu_core_base = nullptr; + bool m_cpu_core_base_is_injected = false; + CoreMode m_mode = CoreMode::Interpreter; + + BreakPoints m_breakpoints; + MemChecks m_memchecks; + PPCDebugInterface m_debug_interface; + + CoreTiming::EventType* m_invalidate_cache_thread_safe = nullptr; + + Core::System& m_system; +}; void UpdatePerformanceMonitor(u32 cycles, u32 num_load_stores, u32 num_fp_inst, PowerPCState& ppc_state); +void CheckExceptionsFromJIT(PowerPCManager& power_pc); +void CheckExternalExceptionsFromJIT(PowerPCManager& power_pc); +void CheckBreakPointsFromJIT(PowerPCManager& power_pc); + // Easy register access macros. #define HID0(ppc_state) ((UReg_HID0&)(ppc_state).spr[SPR_HID0]) #define HID2(ppc_state) ((UReg_HID2&)(ppc_state).spr[SPR_HID2]) @@ -297,6 +338,6 @@ void UpdatePerformanceMonitor(u32 cycles, u32 num_load_stores, u32 num_fp_inst, #define TL(ppc_state) (ppc_state).spr[SPR_TL] #define TU(ppc_state) (ppc_state).spr[SPR_TU] -void RoundingModeUpdated(); +void RoundingModeUpdated(PowerPCState& ppc_state); } // namespace PowerPC diff --git a/Source/Core/Core/State.cpp b/Source/Core/Core/State.cpp index e8ab5a85ab..a82da71663 100644 --- a/Source/Core/Core/State.cpp +++ b/Source/Core/Core/State.cpp @@ -233,7 +233,7 @@ static void DoState(PointerWrap& p) HW::DoState(system, p); p.DoMarker("HW"); - PowerPC::DoState(p); + system.GetPowerPC().DoState(p); p.DoMarker("PowerPC"); if (SConfig::GetInstance().bWii) diff --git a/Source/Core/Core/System.cpp b/Source/Core/Core/System.cpp index 438b3c3014..33fb4a862f 100644 --- a/Source/Core/Core/System.cpp +++ b/Source/Core/Core/System.cpp @@ -38,11 +38,12 @@ namespace Core struct System::Impl { explicit Impl(System& system) - : m_audio_interface(system), m_core_timing(system), m_dsp(system), m_dvd_interface(system), - m_dvd_thread(system), m_expansion_interface(system), m_gp_fifo(system), m_memory(system), - m_ppc_state(PowerPC::ppcState), m_mmu(system, m_memory, m_ppc_state), - m_processor_interface(system), m_serial_interface(system), m_video_interface(system), - m_interpreter(system, m_ppc_state, m_mmu), m_jit_interface(system) + : m_audio_interface(system), m_core_timing(system), m_cpu(system), m_dsp(system), + m_dvd_interface(system), m_dvd_thread(system), m_expansion_interface(system), + m_gp_fifo(system), m_memory(system), m_power_pc(system), + m_mmu(system, m_memory, m_power_pc), m_processor_interface(system), + m_serial_interface(system), m_video_interface(system), + m_interpreter(system, m_power_pc.GetPPCState(), m_mmu), m_jit_interface(system) { } @@ -67,7 +68,7 @@ struct System::Impl MemoryInterface::MemoryInterfaceManager m_memory_interface; PixelEngine::PixelEngineManager m_pixel_engine; PixelShaderManager m_pixel_shader_manager; - PowerPC::PowerPCState& m_ppc_state; + PowerPC::PowerPCManager m_power_pc; PowerPC::MMU m_mmu; ProcessorInterface::ProcessorInterfaceManager m_processor_interface; SerialInterface::SerialInterfaceManager m_serial_interface; @@ -221,9 +222,14 @@ PixelShaderManager& System::GetPixelShaderManager() const return m_impl->m_pixel_shader_manager; } +PowerPC::PowerPCManager& System::GetPowerPC() const +{ + return m_impl->m_power_pc; +} + PowerPC::PowerPCState& System::GetPPCState() const { - return m_impl->m_ppc_state; + return m_impl->m_power_pc.GetPPCState(); } ProcessorInterface::ProcessorInterfaceManager& System::GetProcessorInterface() const diff --git a/Source/Core/Core/System.h b/Source/Core/Core/System.h index 6a6375f0d9..630be2abe7 100644 --- a/Source/Core/Core/System.h +++ b/Source/Core/Core/System.h @@ -73,6 +73,7 @@ class PixelEngineManager; namespace PowerPC { class MMU; +class PowerPCManager; struct PowerPCState; } // namespace PowerPC namespace ProcessorInterface @@ -142,6 +143,7 @@ public: PowerPC::MMU& GetMMU() const; PixelEngine::PixelEngineManager& GetPixelEngine() const; PixelShaderManager& GetPixelShaderManager() const; + PowerPC::PowerPCManager& GetPowerPC() const; PowerPC::PowerPCState& GetPPCState() const; ProcessorInterface::ProcessorInterfaceManager& GetProcessorInterface() const; SerialInterface::SerialInterfaceManager& GetSerialInterface() const; diff --git a/Source/Core/DolphinQt/Debugger/BreakpointWidget.cpp b/Source/Core/DolphinQt/Debugger/BreakpointWidget.cpp index 019494491b..c21ae91e6f 100644 --- a/Source/Core/DolphinQt/Debugger/BreakpointWidget.cpp +++ b/Source/Core/DolphinQt/Debugger/BreakpointWidget.cpp @@ -18,6 +18,7 @@ #include "Core/PowerPC/Expression.h" #include "Core/PowerPC/PPCSymbolDB.h" #include "Core/PowerPC/PowerPC.h" +#include "Core/System.h" #include "DolphinQt/Debugger/BreakpointDialog.h" #include "DolphinQt/Debugger/MemoryWidget.h" @@ -34,7 +35,8 @@ enum CustomRole }; } -BreakpointWidget::BreakpointWidget(QWidget* parent) : QDockWidget(parent) +BreakpointWidget::BreakpointWidget(QWidget* parent) + : QDockWidget(parent), m_system(Core::System::GetInstance()) { setWindowTitle(tr("Breakpoints")); setObjectName(QStringLiteral("breakpoints")); @@ -172,8 +174,12 @@ void BreakpointWidget::Update() return item; }; + auto& power_pc = m_system.GetPowerPC(); + auto& breakpoints = power_pc.GetBreakPoints(); + auto& memchecks = power_pc.GetMemChecks(); + // Breakpoints - for (const auto& bp : PowerPC::breakpoints.GetBreakPoints()) + for (const auto& bp : breakpoints.GetBreakPoints()) { m_table->setRowCount(i + 1); @@ -215,7 +221,7 @@ void BreakpointWidget::Update() } // Memory Breakpoints - for (const auto& mbp : PowerPC::memchecks.GetMemChecks()) + for (const auto& mbp : memchecks.GetMemChecks()) { m_table->setRowCount(i + 1); auto* active = @@ -279,11 +285,11 @@ void BreakpointWidget::OnDelete() if (is_memcheck) { const QSignalBlocker blocker(Settings::Instance()); - PowerPC::memchecks.Remove(address); + m_system.GetPowerPC().GetMemChecks().Remove(address); } else { - PowerPC::breakpoints.Remove(address); + m_system.GetPowerPC().GetBreakPoints().Remove(address); } emit BreakpointsChanged(); @@ -292,10 +298,10 @@ void BreakpointWidget::OnDelete() void BreakpointWidget::OnClear() { - PowerPC::debug_interface.ClearAllBreakpoints(); + m_system.GetPowerPC().GetDebugInterface().ClearAllBreakpoints(); { const QSignalBlocker blocker(Settings::Instance()); - PowerPC::debug_interface.ClearAllMemChecks(); + m_system.GetPowerPC().GetDebugInterface().ClearAllMemChecks(); } m_table->setRowCount(0); @@ -314,12 +320,14 @@ void BreakpointWidget::OnEditBreakpoint(u32 address, bool is_instruction_bp) { if (is_instruction_bp) { - auto* dialog = new BreakpointDialog(this, PowerPC::breakpoints.GetBreakpoint(address)); + auto* dialog = + new BreakpointDialog(this, m_system.GetPowerPC().GetBreakPoints().GetBreakpoint(address)); dialog->exec(); } else { - auto* dialog = new BreakpointDialog(this, PowerPC::memchecks.GetMemCheck(address)); + auto* dialog = + new BreakpointDialog(this, m_system.GetPowerPC().GetMemChecks().GetMemCheck(address)); dialog->exec(); } @@ -339,16 +347,18 @@ void BreakpointWidget::OnLoad() BreakPoints::TBreakPointsStr new_bps; if (ini.GetLines("BreakPoints", &new_bps, false)) { - PowerPC::breakpoints.Clear(); - PowerPC::breakpoints.AddFromStrings(new_bps); + auto& breakpoints = m_system.GetPowerPC().GetBreakPoints(); + breakpoints.Clear(); + breakpoints.AddFromStrings(new_bps); } MemChecks::TMemChecksStr new_mcs; if (ini.GetLines("MemoryBreakPoints", &new_mcs, false)) { - PowerPC::memchecks.Clear(); + auto& memchecks = m_system.GetPowerPC().GetMemChecks(); + memchecks.Clear(); const QSignalBlocker blocker(Settings::Instance()); - PowerPC::memchecks.AddFromStrings(new_mcs); + memchecks.AddFromStrings(new_mcs); } emit BreakpointsChanged(); @@ -360,8 +370,8 @@ void BreakpointWidget::OnSave() IniFile ini; ini.Load(File::GetUserPath(D_GAMESETTINGS_IDX) + SConfig::GetInstance().GetGameID() + ".ini", false); - ini.SetLines("BreakPoints", PowerPC::breakpoints.GetStrings()); - ini.SetLines("MemoryBreakPoints", PowerPC::memchecks.GetStrings()); + ini.SetLines("BreakPoints", m_system.GetPowerPC().GetBreakPoints().GetStrings()); + ini.SetLines("MemoryBreakPoints", m_system.GetPowerPC().GetMemChecks().GetStrings()); ini.Save(File::GetUserPath(D_GAMESETTINGS_IDX) + SConfig::GetInstance().GetGameID() + ".ini"); } @@ -381,7 +391,7 @@ void BreakpointWidget::OnContextMenu() if (!is_memory_breakpoint) { - const auto& inst_breakpoints = PowerPC::breakpoints.GetBreakPoints(); + const auto& inst_breakpoints = m_system.GetPowerPC().GetBreakPoints().GetBreakPoints(); const auto bp_iter = std::find_if(inst_breakpoints.begin(), inst_breakpoints.end(), [bp_address](const auto& bp) { return bp.address == bp_address; }); @@ -390,7 +400,7 @@ void BreakpointWidget::OnContextMenu() menu->addAction(tr("Show in Code"), [this, bp_address] { emit ShowCode(bp_address); }); menu->addAction(bp_iter->is_enabled ? tr("Disable") : tr("Enable"), [this, &bp_address]() { - PowerPC::breakpoints.ToggleBreakPoint(bp_address); + m_system.GetPowerPC().GetBreakPoints().ToggleBreakPoint(bp_address); emit BreakpointsChanged(); Update(); @@ -398,7 +408,7 @@ void BreakpointWidget::OnContextMenu() } else { - const auto& memory_breakpoints = PowerPC::memchecks.GetMemChecks(); + const auto& memory_breakpoints = m_system.GetPowerPC().GetMemChecks().GetMemChecks(); const auto mb_iter = std::find_if(memory_breakpoints.begin(), memory_breakpoints.end(), [bp_address](const auto& bp) { return bp.start_address == bp_address; }); @@ -407,7 +417,7 @@ void BreakpointWidget::OnContextMenu() menu->addAction(tr("Show in Memory"), [this, bp_address] { emit ShowMemory(bp_address); }); menu->addAction(mb_iter->is_enabled ? tr("Disable") : tr("Enable"), [this, &bp_address]() { - PowerPC::memchecks.ToggleBreakPoint(bp_address); + m_system.GetPowerPC().GetMemChecks().ToggleBreakPoint(bp_address); emit BreakpointsChanged(); Update(); @@ -428,7 +438,7 @@ void BreakpointWidget::AddBP(u32 addr) void BreakpointWidget::AddBP(u32 addr, bool temp, bool break_on_hit, bool log_on_hit, const QString& condition) { - PowerPC::breakpoints.Add( + m_system.GetPowerPC().GetBreakPoints().Add( addr, temp, break_on_hit, log_on_hit, !condition.isEmpty() ? Expression::TryParse(condition.toUtf8().constData()) : std::nullopt); @@ -452,7 +462,7 @@ void BreakpointWidget::AddAddressMBP(u32 addr, bool on_read, bool on_write, bool !condition.isEmpty() ? Expression::TryParse(condition.toUtf8().constData()) : std::nullopt; { const QSignalBlocker blocker(Settings::Instance()); - PowerPC::memchecks.Add(std::move(check)); + m_system.GetPowerPC().GetMemChecks().Add(std::move(check)); } emit BreakpointsChanged(); @@ -475,7 +485,7 @@ void BreakpointWidget::AddRangedMBP(u32 from, u32 to, bool on_read, bool on_writ !condition.isEmpty() ? Expression::TryParse(condition.toUtf8().constData()) : std::nullopt; { const QSignalBlocker blocker(Settings::Instance()); - PowerPC::memchecks.Add(std::move(check)); + m_system.GetPowerPC().GetMemChecks().Add(std::move(check)); } emit BreakpointsChanged(); diff --git a/Source/Core/DolphinQt/Debugger/BreakpointWidget.h b/Source/Core/DolphinQt/Debugger/BreakpointWidget.h index bff6d2b883..587366c1d0 100644 --- a/Source/Core/DolphinQt/Debugger/BreakpointWidget.h +++ b/Source/Core/DolphinQt/Debugger/BreakpointWidget.h @@ -12,6 +12,10 @@ class QCloseEvent; class QShowEvent; class QTableWidget; class QToolBar; +namespace Core +{ +class System; +} class BreakpointWidget : public QDockWidget { @@ -51,6 +55,8 @@ private: void UpdateIcons(); + Core::System& m_system; + QToolBar* m_toolbar; QTableWidget* m_table; QAction* m_new; diff --git a/Source/Core/DolphinQt/Debugger/CodeDiffDialog.cpp b/Source/Core/DolphinQt/Debugger/CodeDiffDialog.cpp index 11f2a9a287..533fa5e55f 100644 --- a/Source/Core/DolphinQt/Debugger/CodeDiffDialog.cpp +++ b/Source/Core/DolphinQt/Debugger/CodeDiffDialog.cpp @@ -487,8 +487,9 @@ void CodeDiffDialog::OnSetBLR() return; { - Core::CPUThreadGuard guard(Core::System::GetInstance()); - PowerPC::debug_interface.SetPatch(guard, symbol->address, 0x4E800020); + auto& system = Core::System::GetInstance(); + Core::CPUThreadGuard guard(system); + system.GetPowerPC().GetDebugInterface().SetPatch(guard, symbol->address, 0x4E800020); } int row = item->row(); diff --git a/Source/Core/DolphinQt/Debugger/CodeViewWidget.cpp b/Source/Core/DolphinQt/Debugger/CodeViewWidget.cpp index 8e8b535b7f..312cc1f190 100644 --- a/Source/Core/DolphinQt/Debugger/CodeViewWidget.cpp +++ b/Source/Core/DolphinQt/Debugger/CodeViewWidget.cpp @@ -184,7 +184,7 @@ CodeViewWidget::~CodeViewWidget() = default; static u32 GetBranchFromAddress(const Core::CPUThreadGuard& guard, u32 addr) { - std::string disasm = PowerPC::debug_interface.Disassemble(&guard, addr); + std::string disasm = guard.GetSystem().GetPowerPC().GetDebugInterface().Disassemble(&guard, addr); size_t pos = disasm.find("->0x"); if (pos == std::string::npos) @@ -294,8 +294,11 @@ void CodeViewWidget::Update(const Core::CPUThreadGuard* guard) for (int i = 0; i < rows; i++) setRowHeight(i, rowh); + auto& power_pc = m_system.GetPowerPC(); + auto& debug_interface = power_pc.GetDebugInterface(); + const std::optional pc = - guard ? std::make_optional(m_system.GetPPCState().pc) : std::nullopt; + guard ? std::make_optional(power_pc.GetPPCState().pc) : std::nullopt; const bool dark_theme = qApp->palette().color(QPalette::Base).valueF() < 0.5; @@ -304,16 +307,16 @@ void CodeViewWidget::Update(const Core::CPUThreadGuard* guard) for (int i = 0; i < rowCount(); i++) { const u32 addr = AddressForRow(i); - const u32 color = PowerPC::debug_interface.GetColor(guard, addr); + const u32 color = debug_interface.GetColor(guard, addr); auto* bp_item = new QTableWidgetItem; auto* addr_item = new QTableWidgetItem(QStringLiteral("%1").arg(addr, 8, 16, QLatin1Char('0'))); - std::string disas = PowerPC::debug_interface.Disassemble(guard, addr); + std::string disas = debug_interface.Disassemble(guard, addr); auto split = disas.find('\t'); std::string ins = (split == std::string::npos ? disas : disas.substr(0, split)); std::string param = (split == std::string::npos ? "" : disas.substr(split + 1)); - std::string desc = PowerPC::debug_interface.GetDescription(addr); + std::string desc = debug_interface.GetDescription(addr); // Adds whitespace and a minimum size to ins and param. Helps to prevent frequent resizing while // scrolling. @@ -360,19 +363,19 @@ void CodeViewWidget::Update(const Core::CPUThreadGuard* guard) branch.dst_addr = branch_addr; branch.is_link = IsBranchInstructionWithLink(ins); - description_item->setText(tr("--> %1").arg( - QString::fromStdString(PowerPC::debug_interface.GetDescription(branch_addr)))); + description_item->setText( + tr("--> %1").arg(QString::fromStdString(debug_interface.GetDescription(branch_addr)))); param_item->setForeground(Qt::magenta); } if (ins == "blr") ins_item->setForeground(dark_theme ? QColor(0xa0FFa0) : Qt::darkGreen); - if (PowerPC::debug_interface.IsBreakpoint(addr)) + if (debug_interface.IsBreakpoint(addr)) { auto icon = Resources::GetScaledThemeIcon("debugger_breakpoint").pixmap(QSize(rowh - 2, rowh - 2)); - if (!PowerPC::breakpoints.IsBreakPointEnable(addr)) + if (!m_system.GetPowerPC().GetBreakPoints().IsBreakPointEnable(addr)) { QPixmap disabled_icon(icon.size()); disabled_icon.fill(Qt::transparent); @@ -536,8 +539,8 @@ void CodeViewWidget::ReplaceAddress(u32 address, ReplaceWith replace) { Core::CPUThreadGuard guard(m_system); - PowerPC::debug_interface.SetPatch(guard, address, - replace == ReplaceWith::BLR ? 0x4e800020 : 0x60000000); + m_system.GetPowerPC().GetDebugInterface().SetPatch( + guard, address, replace == ReplaceWith::BLR ? 0x4e800020 : 0x60000000); Update(&guard); } @@ -598,7 +601,7 @@ void CodeViewWidget::OnContextMenu() { Core::CPUThreadGuard guard(m_system); const u32 pc = m_system.GetPPCState().pc; - const std::string disasm = PowerPC::debug_interface.Disassemble(&guard, pc); + const std::string disasm = m_system.GetPowerPC().GetDebugInterface().Disassemble(&guard, pc); if (addr == pc) { @@ -642,7 +645,8 @@ void CodeViewWidget::OnContextMenu() action->setEnabled(valid_load_store); } - restore_action->setEnabled(running && PowerPC::debug_interface.HasEnabledPatch(addr)); + restore_action->setEnabled(running && + m_system.GetPowerPC().GetDebugInterface().HasEnabledPatch(addr)); menu->exec(QCursor::pos()); Update(); @@ -745,14 +749,14 @@ void CodeViewWidget::OnCopyTargetAddress() const std::string code_line = [this, addr] { Core::CPUThreadGuard guard(m_system); - return PowerPC::debug_interface.Disassemble(&guard, addr); + return m_system.GetPowerPC().GetDebugInterface().Disassemble(&guard, addr); }(); if (!IsInstructionLoadStore(code_line)) return; const std::optional target_addr = - PowerPC::debug_interface.GetMemoryAddressFromInstruction(code_line); + m_system.GetPowerPC().GetDebugInterface().GetMemoryAddressFromInstruction(code_line); if (target_addr) { @@ -775,14 +779,14 @@ void CodeViewWidget::OnShowTargetInMemory() const std::string code_line = [this, addr] { Core::CPUThreadGuard guard(m_system); - return PowerPC::debug_interface.Disassemble(&guard, addr); + return m_system.GetPowerPC().GetDebugInterface().Disassemble(&guard, addr); }(); if (!IsInstructionLoadStore(code_line)) return; const std::optional target_addr = - PowerPC::debug_interface.GetMemoryAddressFromInstruction(code_line); + m_system.GetPowerPC().GetDebugInterface().GetMemoryAddressFromInstruction(code_line); if (target_addr) emit ShowMemory(*target_addr); @@ -794,7 +798,7 @@ void CodeViewWidget::OnCopyCode() const std::string text = [this, addr] { Core::CPUThreadGuard guard(m_system); - return PowerPC::debug_interface.Disassemble(&guard, addr); + return m_system.GetPowerPC().GetDebugInterface().Disassemble(&guard, addr); }(); QApplication::clipboard()->setText(QString::fromStdString(text)); @@ -818,7 +822,8 @@ void CodeViewWidget::OnCopyFunction() const u32 end = start + symbol->size; for (u32 addr = start; addr != end; addr += 4) { - const std::string disasm = PowerPC::debug_interface.Disassemble(&guard, addr); + const std::string disasm = + m_system.GetPowerPC().GetDebugInterface().Disassemble(&guard, addr); fmt::format_to(std::back_inserter(text), "{:08x}: {}\r\n", addr, disasm); } } @@ -832,7 +837,7 @@ void CodeViewWidget::OnCopyHex() const u32 instruction = [this, addr] { Core::CPUThreadGuard guard(m_system); - return PowerPC::debug_interface.ReadInstruction(guard, addr); + return m_system.GetPowerPC().GetDebugInterface().ReadInstruction(guard, addr); }(); QApplication::clipboard()->setText( @@ -843,8 +848,8 @@ void CodeViewWidget::OnRunToHere() { const u32 addr = GetContextAddress(); - PowerPC::debug_interface.SetBreakpoint(addr); - PowerPC::debug_interface.RunToBreakpoint(); + m_system.GetPowerPC().GetDebugInterface().SetBreakpoint(addr); + m_system.GetPowerPC().GetDebugInterface().RunToBreakpoint(); Update(); } @@ -997,11 +1002,12 @@ void CodeViewWidget::OnReplaceInstruction() if (!read_result.valid) return; - PatchInstructionDialog dialog(this, addr, PowerPC::debug_interface.ReadInstruction(guard, addr)); + auto& debug_interface = m_system.GetPowerPC().GetDebugInterface(); + PatchInstructionDialog dialog(this, addr, debug_interface.ReadInstruction(guard, addr)); if (dialog.exec() == QDialog::Accepted) { - PowerPC::debug_interface.SetPatch(guard, addr, dialog.GetCode()); + debug_interface.SetPatch(guard, addr, dialog.GetCode()); Update(&guard); } } @@ -1012,7 +1018,7 @@ void CodeViewWidget::OnRestoreInstruction() const u32 addr = GetContextAddress(); - PowerPC::debug_interface.UnsetPatch(guard, addr); + m_system.GetPowerPC().GetDebugInterface().UnsetPatch(guard, addr); Update(&guard); } @@ -1091,10 +1097,11 @@ void CodeViewWidget::showEvent(QShowEvent* event) void CodeViewWidget::ToggleBreakpoint() { - if (PowerPC::debug_interface.IsBreakpoint(GetContextAddress())) - PowerPC::breakpoints.Remove(GetContextAddress()); + auto& power_pc = m_system.GetPowerPC(); + if (power_pc.GetDebugInterface().IsBreakpoint(GetContextAddress())) + power_pc.GetBreakPoints().Remove(GetContextAddress()); else - PowerPC::breakpoints.Add(GetContextAddress()); + power_pc.GetBreakPoints().Add(GetContextAddress()); emit BreakpointsChanged(); Update(); @@ -1102,7 +1109,7 @@ void CodeViewWidget::ToggleBreakpoint() void CodeViewWidget::AddBreakpoint() { - PowerPC::breakpoints.Add(GetContextAddress()); + m_system.GetPowerPC().GetBreakPoints().Add(GetContextAddress()); emit BreakpointsChanged(); Update(); diff --git a/Source/Core/DolphinQt/Debugger/CodeWidget.cpp b/Source/Core/DolphinQt/Debugger/CodeWidget.cpp index 02286fa8b1..1f82c969de 100644 --- a/Source/Core/DolphinQt/Debugger/CodeWidget.cpp +++ b/Source/Core/DolphinQt/Debugger/CodeWidget.cpp @@ -442,12 +442,13 @@ void CodeWidget::Step() Common::Event sync_event; - PowerPC::CoreMode old_mode = PowerPC::GetMode(); - PowerPC::SetMode(PowerPC::CoreMode::Interpreter); - PowerPC::breakpoints.ClearAllTemporary(); + auto& power_pc = m_system.GetPowerPC(); + PowerPC::CoreMode old_mode = power_pc.GetMode(); + power_pc.SetMode(PowerPC::CoreMode::Interpreter); + power_pc.GetBreakPoints().ClearAllTemporary(); cpu.StepOpcode(&sync_event); sync_event.WaitFor(std::chrono::milliseconds(20)); - PowerPC::SetMode(old_mode); + power_pc.SetMode(old_mode); Core::DisplayMessage(tr("Step successful!").toStdString(), 2000); // Will get a UpdateDisasmDialog(), don't update the GUI here. } @@ -466,8 +467,9 @@ void CodeWidget::StepOver() if (inst.LK) { - PowerPC::breakpoints.ClearAllTemporary(); - PowerPC::breakpoints.Add(m_system.GetPPCState().pc + 4, true); + auto& breakpoints = m_system.GetPowerPC().GetBreakPoints(); + breakpoints.ClearAllTemporary(); + breakpoints.Add(m_system.GetPPCState().pc + 4, true); cpu.EnableStepping(false); Core::DisplayMessage(tr("Step over in progress...").toStdString(), 2000); } @@ -501,14 +503,16 @@ void CodeWidget::StepOut() using clock = std::chrono::steady_clock; clock::time_point timeout = clock::now() + std::chrono::seconds(5); - auto& ppc_state = m_system.GetPPCState(); + auto& power_pc = m_system.GetPowerPC(); + auto& ppc_state = power_pc.GetPPCState(); + auto& breakpoints = power_pc.GetBreakPoints(); { Core::CPUThreadGuard guard(m_system); - PowerPC::breakpoints.ClearAllTemporary(); + breakpoints.ClearAllTemporary(); - PowerPC::CoreMode old_mode = PowerPC::GetMode(); - PowerPC::SetMode(PowerPC::CoreMode::Interpreter); + PowerPC::CoreMode old_mode = power_pc.GetMode(); + power_pc.SetMode(PowerPC::CoreMode::Interpreter); // Loop until either the current instruction is a return instruction with no Link flag // or a breakpoint is detected so it can step at the breakpoint. If the PC is currently @@ -518,7 +522,7 @@ void CodeWidget::StepOut() { if (WillInstructionReturn(m_system, inst)) { - PowerPC::SingleStep(); + power_pc.SingleStep(); break; } @@ -528,24 +532,24 @@ void CodeWidget::StepOut() u32 next_pc = ppc_state.pc + 4; do { - PowerPC::SingleStep(); + power_pc.SingleStep(); } while (ppc_state.pc != next_pc && clock::now() < timeout && - !PowerPC::breakpoints.IsAddressBreakPoint(ppc_state.pc)); + !breakpoints.IsAddressBreakPoint(ppc_state.pc)); } else { - PowerPC::SingleStep(); + power_pc.SingleStep(); } inst = PowerPC::MMU::HostRead_Instruction(guard, ppc_state.pc); - } while (clock::now() < timeout && !PowerPC::breakpoints.IsAddressBreakPoint(ppc_state.pc)); + } while (clock::now() < timeout && !breakpoints.IsAddressBreakPoint(ppc_state.pc)); - PowerPC::SetMode(old_mode); + power_pc.SetMode(old_mode); } emit Host::GetInstance()->UpdateDisasmDialog(); - if (PowerPC::breakpoints.IsAddressBreakPoint(ppc_state.pc)) + if (breakpoints.IsAddressBreakPoint(ppc_state.pc)) Core::DisplayMessage(tr("Breakpoint encountered! Step out aborted.").toStdString(), 2000); else if (clock::now() >= timeout) Core::DisplayMessage(tr("Step out timed out!").toStdString(), 2000); diff --git a/Source/Core/DolphinQt/Debugger/MemoryViewWidget.cpp b/Source/Core/DolphinQt/Debugger/MemoryViewWidget.cpp index e5983a5675..d05e043da1 100644 --- a/Source/Core/DolphinQt/Debugger/MemoryViewWidget.cpp +++ b/Source/Core/DolphinQt/Debugger/MemoryViewWidget.cpp @@ -170,7 +170,8 @@ private: MemoryViewWidget* m_view; }; -MemoryViewWidget::MemoryViewWidget(QWidget* parent) : QWidget(parent) +MemoryViewWidget::MemoryViewWidget(QWidget* parent) + : QWidget(parent), m_system(Core::System::GetInstance()) { auto* layout = new QHBoxLayout(); layout->setContentsMargins(0, 0, 0, 0); @@ -571,7 +572,7 @@ void MemoryViewWidget::UpdateBreakpointTags() } if (m_address_space == AddressSpace::Type::Effective && - PowerPC::memchecks.GetMemCheck(address, GetTypeSize(m_type)) != nullptr) + m_system.GetPowerPC().GetMemChecks().GetMemCheck(address, GetTypeSize(m_type)) != nullptr) { row_breakpoint = true; cell->setBackground(Qt::red); @@ -808,15 +809,17 @@ void MemoryViewWidget::ToggleBreakpoint(u32 addr, bool row) const int breaks = row ? (m_bytes_per_row / length) : 1; bool overlap = false; + auto& memchecks = m_system.GetPowerPC().GetMemChecks(); + // Row breakpoint should either remove any breakpoint left on the row, or activate all // breakpoints. - if (row && PowerPC::memchecks.OverlapsMemcheck(addr, m_bytes_per_row)) + if (row && memchecks.OverlapsMemcheck(addr, m_bytes_per_row)) overlap = true; for (int i = 0; i < breaks; i++) { u32 address = addr + length * i; - TMemCheck* check_ptr = PowerPC::memchecks.GetMemCheck(address, length); + TMemCheck* check_ptr = memchecks.GetMemCheck(address, length); if (check_ptr == nullptr && !overlap) { @@ -829,12 +832,12 @@ void MemoryViewWidget::ToggleBreakpoint(u32 addr, bool row) check.log_on_hit = m_do_log; check.break_on_hit = true; - PowerPC::memchecks.Add(std::move(check)); + memchecks.Add(std::move(check)); } else if (check_ptr != nullptr) { // Using the pointer fixes misaligned breakpoints (0x11 breakpoint in 0x10 aligned view). - PowerPC::memchecks.Remove(check_ptr->start_address); + memchecks.Remove(check_ptr->start_address); } } diff --git a/Source/Core/DolphinQt/Debugger/MemoryViewWidget.h b/Source/Core/DolphinQt/Debugger/MemoryViewWidget.h index e5e15f5abe..1b8bed117a 100644 --- a/Source/Core/DolphinQt/Debugger/MemoryViewWidget.h +++ b/Source/Core/DolphinQt/Debugger/MemoryViewWidget.h @@ -18,7 +18,8 @@ enum class Type; namespace Core { class CPUThreadGuard; -} +class System; +} // namespace Core class MemoryViewTable; @@ -85,6 +86,8 @@ private: void ScrollbarSliderReleased(); QString ValueToString(const Core::CPUThreadGuard& guard, u32 address, Type type); + Core::System& m_system; + MemoryViewTable* m_table; QScrollBar* m_scrollbar; AddressSpace::Type m_address_space{}; diff --git a/Source/Core/DolphinQt/Debugger/RegisterWidget.cpp b/Source/Core/DolphinQt/Debugger/RegisterWidget.cpp index f11df86444..b41fffb39a 100644 --- a/Source/Core/DolphinQt/Debugger/RegisterWidget.cpp +++ b/Source/Core/DolphinQt/Debugger/RegisterWidget.cpp @@ -409,7 +409,9 @@ void RegisterWidget::PopulateTable() // Special registers // TB - AddRegister(16, 5, RegisterType::tb, "TB", PowerPC::ReadFullTimeBaseValue, nullptr); + AddRegister( + 16, 5, RegisterType::tb, "TB", + [this] { return m_system.GetPowerPC().ReadFullTimeBaseValue(); }, nullptr); // PC AddRegister( diff --git a/Source/Core/DolphinQt/Debugger/ThreadWidget.cpp b/Source/Core/DolphinQt/Debugger/ThreadWidget.cpp index 3905700f2b..3ba804acb1 100644 --- a/Source/Core/DolphinQt/Debugger/ThreadWidget.cpp +++ b/Source/Core/DolphinQt/Debugger/ThreadWidget.cpp @@ -314,7 +314,7 @@ void ThreadWidget::Update() m_queue_tail->setText(format_hex_from(guard, 0x800000E0)); // Thread group - m_threads = PowerPC::debug_interface.GetThreads(guard); + m_threads = guard.GetSystem().GetPowerPC().GetDebugInterface().GetThreads(guard); int i = 0; m_thread_table->setRowCount(i); @@ -458,9 +458,10 @@ void ThreadWidget::UpdateThreadCallstack(const Core::CPUThreadGuard& guard, { const u32 lr_save = PowerPC::MMU::HostRead_U32(guard, sp + 4); m_callstack_table->setItem(i, 2, new QTableWidgetItem(format_hex(lr_save))); - m_callstack_table->setItem(i, 3, - new QTableWidgetItem(QString::fromStdString( - PowerPC::debug_interface.GetDescription(lr_save)))); + m_callstack_table->setItem( + i, 3, + new QTableWidgetItem(QString::fromStdString( + guard.GetSystem().GetPowerPC().GetDebugInterface().GetDescription(lr_save)))); } else { diff --git a/Source/Core/DolphinQt/Debugger/WatchWidget.cpp b/Source/Core/DolphinQt/Debugger/WatchWidget.cpp index fdb1279072..2be4a2a2f7 100644 --- a/Source/Core/DolphinQt/Debugger/WatchWidget.cpp +++ b/Source/Core/DolphinQt/Debugger/WatchWidget.cpp @@ -23,7 +23,8 @@ #include "DolphinQt/Resources.h" #include "DolphinQt/Settings.h" -WatchWidget::WatchWidget(QWidget* parent) : QDockWidget(parent) +WatchWidget::WatchWidget(QWidget* parent) + : QDockWidget(parent), m_system(Core::System::GetInstance()) { // i18n: This kind of "watch" is used for watching emulated memory. // It's not related to timekeeping devices. @@ -167,15 +168,16 @@ void WatchWidget::Update() m_table->setDisabled(false); m_table->clearContents(); - Core::CPUThreadGuard guard(Core::System::GetInstance()); + Core::CPUThreadGuard guard(m_system); + auto& debug_interface = guard.GetSystem().GetPowerPC().GetDebugInterface(); - int size = static_cast(PowerPC::debug_interface.GetWatches().size()); + int size = static_cast(debug_interface.GetWatches().size()); m_table->setRowCount(size + 1); for (int i = 0; i < size; i++) { - const auto& entry = PowerPC::debug_interface.GetWatch(i); + const auto& entry = debug_interface.GetWatch(i); auto* label = new QTableWidgetItem(QString::fromStdString(entry.name)); auto* address = @@ -263,7 +265,7 @@ void WatchWidget::OnDelete() void WatchWidget::OnClear() { - PowerPC::debug_interface.ClearWatches(); + m_system.GetPowerPC().GetDebugInterface().ClearWatches(); Update(); } @@ -297,16 +299,17 @@ void WatchWidget::OnLoad() return; } - Core::CPUThreadGuard guard(Core::System::GetInstance()); + Core::CPUThreadGuard guard(m_system); if (ini.GetLines("Watches", &watches, false)) { - for (const auto& watch : PowerPC::debug_interface.GetWatches()) + auto& debug_interface = guard.GetSystem().GetPowerPC().GetDebugInterface(); + for (const auto& watch : debug_interface.GetWatches()) { - PowerPC::debug_interface.UnsetPatch(guard, watch.address); + debug_interface.UnsetPatch(guard, watch.address); } - PowerPC::debug_interface.ClearWatches(); - PowerPC::debug_interface.LoadWatchesFromStrings(watches); + debug_interface.ClearWatches(); + debug_interface.LoadWatchesFromStrings(watches); } Update(); @@ -317,7 +320,7 @@ void WatchWidget::OnSave() IniFile ini; ini.Load(File::GetUserPath(D_GAMESETTINGS_IDX) + SConfig::GetInstance().GetGameID() + ".ini", false); - ini.SetLines("Watches", PowerPC::debug_interface.SaveWatchesToStrings()); + ini.SetLines("Watches", m_system.GetPowerPC().GetDebugInterface().SaveWatchesToStrings()); ini.Save(File::GetUserPath(D_GAMESETTINGS_IDX) + SConfig::GetInstance().GetGameID() + ".ini"); } @@ -394,7 +397,7 @@ void WatchWidget::OnItemChanged(QTableWidgetItem* item) if (item->text().isEmpty()) DeleteWatchAndUpdate(row); else - PowerPC::debug_interface.UpdateWatchName(row, item->text().toStdString()); + m_system.GetPowerPC().GetDebugInterface().UpdateWatchName(row, item->text().toStdString()); break; case COLUMN_INDEX_ADDRESS: case COLUMN_INDEX_HEX: @@ -407,19 +410,20 @@ void WatchWidget::OnItemChanged(QTableWidgetItem* item) if (good) { - Core::CPUThreadGuard guard(Core::System::GetInstance()); + Core::CPUThreadGuard guard(m_system); + auto& debug_interface = m_system.GetPowerPC().GetDebugInterface(); if (column == COLUMN_INDEX_ADDRESS) { - const auto& watch = PowerPC::debug_interface.GetWatch(row); - PowerPC::debug_interface.UnsetPatch(guard, watch.address); - PowerPC::debug_interface.UpdateWatchAddress(row, value); + const auto& watch = debug_interface.GetWatch(row); + debug_interface.UnsetPatch(guard, watch.address); + debug_interface.UpdateWatchAddress(row, value); if (watch.locked) LockWatchAddress(guard, value); } else { - PowerPC::MMU::HostWrite_U32(guard, value, PowerPC::debug_interface.GetWatch(row).address); + PowerPC::MMU::HostWrite_U32(guard, value, debug_interface.GetWatch(row).address); } } else @@ -430,13 +434,14 @@ void WatchWidget::OnItemChanged(QTableWidgetItem* item) } case COLUMN_INDEX_LOCK: { - PowerPC::debug_interface.UpdateWatchLockedState(row, item->checkState() == Qt::Checked); - const auto& watch = PowerPC::debug_interface.GetWatch(row); - Core::CPUThreadGuard guard(Core::System::GetInstance()); + auto& debug_interface = m_system.GetPowerPC().GetDebugInterface(); + debug_interface.UpdateWatchLockedState(row, item->checkState() == Qt::Checked); + const auto& watch = debug_interface.GetWatch(row); + Core::CPUThreadGuard guard(m_system); if (watch.locked) LockWatchAddress(guard, watch.address); else - PowerPC::debug_interface.UnsetPatch(guard, watch.address); + debug_interface.UnsetPatch(guard, watch.address); break; } } @@ -455,13 +460,13 @@ void WatchWidget::LockWatchAddress(const Core::CPUThreadGuard& guard, u32 addres bytes.push_back(static_cast(c)); } - PowerPC::debug_interface.SetFramePatch(guard, address, bytes); + m_system.GetPowerPC().GetDebugInterface().SetFramePatch(guard, address, bytes); } void WatchWidget::DeleteSelectedWatches() { { - Core::CPUThreadGuard guard(Core::System::GetInstance()); + Core::CPUThreadGuard guard(m_system); std::vector row_indices; for (const auto& index : m_table->selectionModel()->selectedRows()) { @@ -486,14 +491,15 @@ void WatchWidget::DeleteSelectedWatches() void WatchWidget::DeleteWatch(const Core::CPUThreadGuard& guard, int row) { - PowerPC::debug_interface.UnsetPatch(guard, PowerPC::debug_interface.GetWatch(row).address); - PowerPC::debug_interface.RemoveWatch(row); + auto& debug_interface = m_system.GetPowerPC().GetDebugInterface(); + debug_interface.UnsetPatch(guard, debug_interface.GetWatch(row).address); + debug_interface.RemoveWatch(row); } void WatchWidget::DeleteWatchAndUpdate(int row) { { - Core::CPUThreadGuard guard(Core::System::GetInstance()); + Core::CPUThreadGuard guard(m_system); DeleteWatch(guard, row); } @@ -502,24 +508,25 @@ void WatchWidget::DeleteWatchAndUpdate(int row) void WatchWidget::AddWatchBreakpoint(int row) { - emit RequestMemoryBreakpoint(PowerPC::debug_interface.GetWatch(row).address); + emit RequestMemoryBreakpoint(m_system.GetPowerPC().GetDebugInterface().GetWatch(row).address); } void WatchWidget::ShowInMemory(int row) { - emit ShowMemory(PowerPC::debug_interface.GetWatch(row).address); + emit ShowMemory(m_system.GetPowerPC().GetDebugInterface().GetWatch(row).address); } void WatchWidget::AddWatch(QString name, u32 addr) { - PowerPC::debug_interface.SetWatch(addr, name.toStdString()); + m_system.GetPowerPC().GetDebugInterface().SetWatch(addr, name.toStdString()); Update(); } void WatchWidget::LockSelectedWatches() { { - Core::CPUThreadGuard guard(Core::System::GetInstance()); + Core::CPUThreadGuard guard(m_system); + auto& debug_interface = m_system.GetPowerPC().GetDebugInterface(); for (const auto& index : m_table->selectionModel()->selectedRows()) { const auto* item = m_table->item(index.row(), index.column()); @@ -527,10 +534,10 @@ void WatchWidget::LockSelectedWatches() if (row_variant.isNull()) continue; const int row = row_variant.toInt(); - const auto& watch = PowerPC::debug_interface.GetWatch(row); + const auto& watch = debug_interface.GetWatch(row); if (watch.locked) continue; - PowerPC::debug_interface.UpdateWatchLockedState(row, true); + debug_interface.UpdateWatchLockedState(row, true); LockWatchAddress(guard, watch.address); } } @@ -541,7 +548,8 @@ void WatchWidget::LockSelectedWatches() void WatchWidget::UnlockSelectedWatches() { { - Core::CPUThreadGuard guard(Core::System::GetInstance()); + auto& debug_interface = m_system.GetPowerPC().GetDebugInterface(); + Core::CPUThreadGuard guard(m_system); for (const auto& index : m_table->selectionModel()->selectedRows()) { const auto* item = m_table->item(index.row(), index.column()); @@ -549,11 +557,11 @@ void WatchWidget::UnlockSelectedWatches() if (row_variant.isNull()) continue; const int row = row_variant.toInt(); - const auto& watch = PowerPC::debug_interface.GetWatch(row); + const auto& watch = debug_interface.GetWatch(row); if (!watch.locked) continue; - PowerPC::debug_interface.UpdateWatchLockedState(row, false); - PowerPC::debug_interface.UnsetPatch(guard, watch.address); + debug_interface.UpdateWatchLockedState(row, false); + debug_interface.UnsetPatch(guard, watch.address); } } diff --git a/Source/Core/DolphinQt/Debugger/WatchWidget.h b/Source/Core/DolphinQt/Debugger/WatchWidget.h index 7d8711e39c..62e5c7b42a 100644 --- a/Source/Core/DolphinQt/Debugger/WatchWidget.h +++ b/Source/Core/DolphinQt/Debugger/WatchWidget.h @@ -17,7 +17,8 @@ class QToolBar; namespace Core { class CPUThreadGuard; -}; +class System; +}; // namespace Core class WatchWidget : public QDockWidget { @@ -62,6 +63,8 @@ private: void LockSelectedWatches(); void UnlockSelectedWatches(); + Core::System& m_system; + QAction* m_new; QAction* m_delete; QAction* m_clear; diff --git a/Source/Core/DolphinQt/MenuBar.cpp b/Source/Core/DolphinQt/MenuBar.cpp index 4d764f2fac..07391cb65b 100644 --- a/Source/Core/DolphinQt/MenuBar.cpp +++ b/Source/Core/DolphinQt/MenuBar.cpp @@ -800,7 +800,8 @@ void MenuBar::AddJITMenu() PowerPC::CPUCore::Interpreter); connect(m_jit_interpreter_core, &QAction::toggled, [](bool enabled) { - PowerPC::SetMode(enabled ? PowerPC::CoreMode::Interpreter : PowerPC::CoreMode::JIT); + Core::System::GetInstance().GetPowerPC().SetMode(enabled ? PowerPC::CoreMode::Interpreter : + PowerPC::CoreMode::JIT); }); m_jit->addSeparator(); diff --git a/Source/UnitTests/Core/CoreTimingTest.cpp b/Source/UnitTests/Core/CoreTimingTest.cpp index 3a8012cdf0..8857ef8aba 100644 --- a/Source/UnitTests/Core/CoreTimingTest.cpp +++ b/Source/UnitTests/Core/CoreTimingTest.cpp @@ -38,7 +38,7 @@ void CallbackTemplate(Core::System& system, u64 userdata, s64 lateness) class ScopeInit final { public: - ScopeInit() : m_profile_path(File::CreateTempDir()) + explicit ScopeInit(Core::System& system) : m_system(system), m_profile_path(File::CreateTempDir()) { if (!UserDirectoryExists()) { @@ -48,8 +48,7 @@ public: UICommon::SetUserDirectory(m_profile_path); Config::Init(); SConfig::Init(); - PowerPC::Init(PowerPC::CPUCore::Interpreter); - auto& system = Core::System::GetInstance(); + system.GetPowerPC().Init(PowerPC::CPUCore::Interpreter); auto& core_timing = system.GetCoreTiming(); core_timing.Init(); } @@ -59,10 +58,9 @@ public: { return; } - auto& system = Core::System::GetInstance(); - auto& core_timing = system.GetCoreTiming(); + auto& core_timing = m_system.GetCoreTiming(); core_timing.Shutdown(); - PowerPC::Shutdown(); + m_system.GetPowerPC().Shutdown(); SConfig::Shutdown(); Config::Shutdown(); Core::UndeclareAsCPUThread(); @@ -71,6 +69,7 @@ public: bool UserDirectoryExists() const { return !m_profile_path.empty(); } private: + Core::System& m_system; std::string m_profile_path; }; @@ -92,10 +91,11 @@ static void AdvanceAndCheck(Core::System& system, u32 idx, int downcount, int ex TEST(CoreTiming, BasicOrder) { - ScopeInit guard; + auto& system = Core::System::GetInstance(); + + ScopeInit guard(system); ASSERT_TRUE(guard.UserDirectoryExists()); - auto& system = Core::System::GetInstance(); auto& core_timing = system.GetCoreTiming(); auto& ppc_state = system.GetPPCState(); @@ -147,10 +147,11 @@ TEST(CoreTiming, SharedSlot) { using namespace SharedSlotTest; - ScopeInit guard; + auto& system = Core::System::GetInstance(); + + ScopeInit guard(system); ASSERT_TRUE(guard.UserDirectoryExists()); - auto& system = Core::System::GetInstance(); auto& core_timing = system.GetCoreTiming(); auto& ppc_state = system.GetPPCState(); @@ -181,10 +182,11 @@ TEST(CoreTiming, SharedSlot) TEST(CoreTiming, PredictableLateness) { - ScopeInit guard; + auto& system = Core::System::GetInstance(); + + ScopeInit guard(system); ASSERT_TRUE(guard.UserDirectoryExists()); - auto& system = Core::System::GetInstance(); auto& core_timing = system.GetCoreTiming(); CoreTiming::EventType* cb_a = core_timing.RegisterEvent("callbackA", CallbackTemplate<0>); @@ -222,10 +224,11 @@ TEST(CoreTiming, ChainScheduling) { using namespace ChainSchedulingTest; - ScopeInit guard; + auto& system = Core::System::GetInstance(); + + ScopeInit guard(system); ASSERT_TRUE(guard.UserDirectoryExists()); - auto& system = Core::System::GetInstance(); auto& core_timing = system.GetCoreTiming(); auto& ppc_state = system.GetPPCState(); @@ -282,10 +285,11 @@ TEST(CoreTiming, ScheduleIntoPast) { using namespace ScheduleIntoPastTest; - ScopeInit guard; + auto& system = Core::System::GetInstance(); + + ScopeInit guard(system); ASSERT_TRUE(guard.UserDirectoryExists()); - auto& system = Core::System::GetInstance(); auto& core_timing = system.GetCoreTiming(); auto& ppc_state = system.GetPPCState(); @@ -325,10 +329,11 @@ TEST(CoreTiming, ScheduleIntoPast) TEST(CoreTiming, Overclocking) { - ScopeInit guard; + auto& system = Core::System::GetInstance(); + + ScopeInit guard(system); ASSERT_TRUE(guard.UserDirectoryExists()); - auto& system = Core::System::GetInstance(); auto& core_timing = system.GetCoreTiming(); auto& ppc_state = system.GetPPCState();