From c3c39de2128e582121415d3cf232ed4a7c0f306f Mon Sep 17 00:00:00 2001 From: Lioncache Date: Mon, 18 Dec 2023 13:33:05 -0500 Subject: [PATCH 1/5] HLE_Misc: Get rid of global system accessors Thread guards provide access to the current active system instance. --- Source/Core/Core/HLE/HLE_Misc.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/Source/Core/Core/HLE/HLE_Misc.cpp b/Source/Core/Core/HLE/HLE_Misc.cpp index e2adaffebb..91ca651342 100644 --- a/Source/Core/Core/HLE/HLE_Misc.cpp +++ b/Source/Core/Core/HLE/HLE_Misc.cpp @@ -5,6 +5,7 @@ #include "Common/Common.h" #include "Common/CommonTypes.h" +#include "Core/Core.h" #include "Core/GeckoCode.h" #include "Core/HW/CPU.h" #include "Core/Host.h" @@ -16,24 +17,24 @@ namespace HLE_Misc { // If you just want to kill a function, one of the three following are usually appropriate. // According to the PPC ABI, the return value is always in r3. -void UnimplementedFunction(const Core::CPUThreadGuard&) +void UnimplementedFunction(const Core::CPUThreadGuard& guard) { - auto& system = Core::System::GetInstance(); + auto& system = guard.GetSystem(); auto& ppc_state = system.GetPPCState(); ppc_state.npc = LR(ppc_state); } -void HBReload(const Core::CPUThreadGuard&) +void HBReload(const Core::CPUThreadGuard& guard) { // There isn't much we can do. Just stop cleanly. - auto& system = Core::System::GetInstance(); + auto& system = guard.GetSystem(); system.GetCPU().Break(); Host_Message(HostMessageID::WMUserStop); } void GeckoCodeHandlerICacheFlush(const Core::CPUThreadGuard& guard) { - auto& system = Core::System::GetInstance(); + auto& system = guard.GetSystem(); auto& ppc_state = system.GetPPCState(); // Work around the codehandler not properly invalidating the icache, but @@ -62,11 +63,11 @@ void GeckoCodeHandlerICacheFlush(const Core::CPUThreadGuard& guard) // and PC before the magic, invisible BL instruction happened. void GeckoReturnTrampoline(const Core::CPUThreadGuard& guard) { - auto& system = Core::System::GetInstance(); + auto& system = guard.GetSystem(); auto& ppc_state = system.GetPPCState(); // Stack frame is built in GeckoCode.cpp, Gecko::RunCodeHandler. - u32 SP = ppc_state.gpr[1]; + const u32 SP = ppc_state.gpr[1]; ppc_state.gpr[1] = PowerPC::MMU::HostRead_U32(guard, SP + 8); ppc_state.npc = PowerPC::MMU::HostRead_U32(guard, SP + 12); LR(ppc_state) = PowerPC::MMU::HostRead_U32(guard, SP + 16); From c4df659e21fdfb3e3fadb66a73deaebd7d26507a Mon Sep 17 00:00:00 2001 From: Lioncache Date: Mon, 18 Dec 2023 13:39:31 -0500 Subject: [PATCH 2/5] HLE_OS: Get rid of global system accessors Thread guards provide access to the current active system instance. --- Source/Core/Core/HLE/HLE_OS.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Source/Core/Core/HLE/HLE_OS.cpp b/Source/Core/Core/HLE/HLE_OS.cpp index 52f3b43deb..7565e11936 100644 --- a/Source/Core/Core/HLE/HLE_OS.cpp +++ b/Source/Core/Core/HLE/HLE_OS.cpp @@ -38,7 +38,7 @@ void HLE_LogFPrint(const Core::CPUThreadGuard& guard, ParameterType parameter_ty void HLE_OSPanic(const Core::CPUThreadGuard& guard) { - auto& system = Core::System::GetInstance(); + auto& system = guard.GetSystem(); auto& ppc_state = system.GetPPCState(); std::string error = GetStringVA(system, guard); @@ -57,8 +57,8 @@ void HLE_OSPanic(const Core::CPUThreadGuard& guard) // Generalized function for printing formatted string. void HLE_GeneralDebugPrint(const Core::CPUThreadGuard& guard, ParameterType parameter_type) { - auto& system = Core::System::GetInstance(); - auto& ppc_state = system.GetPPCState(); + auto& system = guard.GetSystem(); + const auto& ppc_state = system.GetPPCState(); std::string report_message; @@ -114,7 +114,7 @@ void HLE_GeneralDebugVPrint(const Core::CPUThreadGuard& guard) void HLE_write_console(const Core::CPUThreadGuard& guard) { auto& system = guard.GetSystem(); - auto& ppc_state = system.GetPPCState(); + const auto& ppc_state = system.GetPPCState(); std::string report_message = GetStringVA(system, guard, 4); if (PowerPC::MMU::HostIsRAMAddress(guard, ppc_state.gpr[5])) @@ -141,8 +141,8 @@ void HLE_write_console(const Core::CPUThreadGuard& guard) // Log (v)dprintf message if fd is 1 (stdout) or 2 (stderr) void HLE_LogDPrint(const Core::CPUThreadGuard& guard, ParameterType parameter_type) { - auto& system = Core::System::GetInstance(); - auto& ppc_state = system.GetPPCState(); + auto& system = guard.GetSystem(); + const auto& ppc_state = system.GetPPCState(); if (ppc_state.gpr[3] != 1 && ppc_state.gpr[3] != 2) return; @@ -170,8 +170,8 @@ void HLE_LogVDPrint(const Core::CPUThreadGuard& guard) // Log (v)fprintf message if FILE is stdout or stderr void HLE_LogFPrint(const Core::CPUThreadGuard& guard, ParameterType parameter_type) { - auto& system = Core::System::GetInstance(); - auto& ppc_state = system.GetPPCState(); + auto& system = guard.GetSystem(); + const auto& ppc_state = system.GetPPCState(); // The structure FILE is implementation defined. // Both libogc and Dolphin SDK seem to store the fd at the same address. From 04300114f78d1d9562aab6192ad589b87fc12baf Mon Sep 17 00:00:00 2001 From: Lioncache Date: Mon, 18 Dec 2023 13:44:52 -0500 Subject: [PATCH 3/5] Core/HLE/HLE_OS: Mark helpers as static where applicable Previously, these were given external linkage when they're only used within this translation unit. --- Source/Core/Core/HLE/HLE_OS.cpp | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/Source/Core/Core/HLE/HLE_OS.cpp b/Source/Core/Core/HLE/HLE_OS.cpp index 7565e11936..084bd0ee25 100644 --- a/Source/Core/Core/HLE/HLE_OS.cpp +++ b/Source/Core/Core/HLE/HLE_OS.cpp @@ -30,11 +30,9 @@ enum class ParameterType : bool VariableArgumentList = true }; -std::string GetStringVA(Core::System& system, const Core::CPUThreadGuard& guard, u32 str_reg = 3, - ParameterType parameter_type = ParameterType::ParameterList); -void HLE_GeneralDebugPrint(const Core::CPUThreadGuard& guard, ParameterType parameter_type); -void HLE_LogDPrint(const Core::CPUThreadGuard& guard, ParameterType parameter_type); -void HLE_LogFPrint(const Core::CPUThreadGuard& guard, ParameterType parameter_type); +static std::string GetStringVA(Core::System& system, const Core::CPUThreadGuard& guard, + u32 str_reg = 3, + ParameterType parameter_type = ParameterType::ParameterList); void HLE_OSPanic(const Core::CPUThreadGuard& guard) { @@ -55,7 +53,7 @@ void HLE_OSPanic(const Core::CPUThreadGuard& guard) } // Generalized function for printing formatted string. -void HLE_GeneralDebugPrint(const Core::CPUThreadGuard& guard, ParameterType parameter_type) +static void HLE_GeneralDebugPrint(const Core::CPUThreadGuard& guard, ParameterType parameter_type) { auto& system = guard.GetSystem(); const auto& ppc_state = system.GetPPCState(); @@ -139,7 +137,7 @@ void HLE_write_console(const Core::CPUThreadGuard& guard) } // Log (v)dprintf message if fd is 1 (stdout) or 2 (stderr) -void HLE_LogDPrint(const Core::CPUThreadGuard& guard, ParameterType parameter_type) +static void HLE_LogDPrint(const Core::CPUThreadGuard& guard, ParameterType parameter_type) { auto& system = guard.GetSystem(); const auto& ppc_state = system.GetPPCState(); @@ -168,7 +166,7 @@ void HLE_LogVDPrint(const Core::CPUThreadGuard& guard) } // Log (v)fprintf message if FILE is stdout or stderr -void HLE_LogFPrint(const Core::CPUThreadGuard& guard, ParameterType parameter_type) +static void HLE_LogFPrint(const Core::CPUThreadGuard& guard, ParameterType parameter_type) { auto& system = guard.GetSystem(); const auto& ppc_state = system.GetPPCState(); @@ -242,8 +240,8 @@ private: }; } // namespace -std::string GetStringVA(Core::System& system, const Core::CPUThreadGuard& guard, u32 str_reg, - ParameterType parameter_type) +static std::string GetStringVA(Core::System& system, const Core::CPUThreadGuard& guard, u32 str_reg, + ParameterType parameter_type) { auto& ppc_state = system.GetPPCState(); From f4277a901aa9f36e25d2acdb53c0ea2b0aa30573 Mon Sep 17 00:00:00 2001 From: Lioncache Date: Mon, 18 Dec 2023 14:05:03 -0500 Subject: [PATCH 4/5] Core/HLE/HLE: Remove global system accessors We can get rid of the global system accessors by requiring passing in relevant state that the function needs and making callsites do the work. This *does* add a global accessor to the PPCAnalyzer, however, this already has global accessors present elsewhere within its code, so they can be removed all at once in a follow up change. --- Source/Core/Core/HLE/HLE.cpp | 8 ++++---- Source/Core/Core/HLE/HLE.h | 9 +++++++-- .../Core/PowerPC/CachedInterpreter/CachedInterpreter.cpp | 4 +++- Source/Core/Core/PowerPC/Interpreter/Interpreter.cpp | 2 +- Source/Core/Core/PowerPC/Jit64/Jit.cpp | 2 +- Source/Core/Core/PowerPC/JitArm64/Jit.cpp | 2 +- Source/Core/Core/PowerPC/PPCAnalyst.cpp | 3 ++- 7 files changed, 19 insertions(+), 11 deletions(-) diff --git a/Source/Core/Core/HLE/HLE.cpp b/Source/Core/Core/HLE/HLE.cpp index c25a3232f5..1707709f2d 100644 --- a/Source/Core/Core/HLE/HLE.cpp +++ b/Source/Core/Core/HLE/HLE.cpp @@ -200,7 +200,7 @@ HookFlag GetHookFlagsByIndex(u32 index) return os_patches[index].flags; } -TryReplaceFunctionResult TryReplaceFunction(u32 address) +TryReplaceFunctionResult TryReplaceFunction(u32 address, PowerPC::CoreMode mode) { const u32 hook_index = GetHookByFunctionAddress(address); if (hook_index == 0) @@ -211,16 +211,16 @@ TryReplaceFunctionResult TryReplaceFunction(u32 address) return {}; const HookFlag flags = GetHookFlagsByIndex(hook_index); - if (!IsEnabled(flags)) + if (!IsEnabled(flags, mode)) return {}; return {type, hook_index}; } -bool IsEnabled(HookFlag flag) +bool IsEnabled(HookFlag flag, PowerPC::CoreMode mode) { return flag != HLE::HookFlag::Debug || Config::IsDebuggingEnabled() || - Core::System::GetInstance().GetPowerPC().GetMode() == PowerPC::CoreMode::Interpreter; + mode == PowerPC::CoreMode::Interpreter; } u32 UnPatch(Core::System& system, std::string_view patch_name) diff --git a/Source/Core/Core/HLE/HLE.h b/Source/Core/Core/HLE/HLE.h index 725ef1aa54..a43ada5adf 100644 --- a/Source/Core/Core/HLE/HLE.h +++ b/Source/Core/Core/HLE/HLE.h @@ -13,6 +13,11 @@ class CPUThreadGuard; class System; } // namespace Core +namespace PowerPC +{ +enum class CoreMode; +} + namespace HLE { using HookFunction = void (*)(const Core::CPUThreadGuard&); @@ -65,10 +70,10 @@ u32 GetHookByFunctionAddress(u32 address); HookType GetHookTypeByIndex(u32 index); HookFlag GetHookFlagsByIndex(u32 index); -bool IsEnabled(HookFlag flag); +bool IsEnabled(HookFlag flag, PowerPC::CoreMode mode); // Performs the backend-independent preliminary checking for whether a function // can be HLEd. If it can be, the information needed for HLEing it is returned. -TryReplaceFunctionResult TryReplaceFunction(u32 address); +TryReplaceFunctionResult TryReplaceFunction(u32 address, PowerPC::CoreMode mode); } // namespace HLE diff --git a/Source/Core/Core/PowerPC/CachedInterpreter/CachedInterpreter.cpp b/Source/Core/Core/PowerPC/CachedInterpreter/CachedInterpreter.cpp index 8a836b6fe5..291321f97a 100644 --- a/Source/Core/Core/PowerPC/CachedInterpreter/CachedInterpreter.cpp +++ b/Source/Core/Core/PowerPC/CachedInterpreter/CachedInterpreter.cpp @@ -269,7 +269,9 @@ bool CachedInterpreter::CheckIdle(CachedInterpreter& cached_interpreter, u32 idl bool CachedInterpreter::HandleFunctionHooking(u32 address) { - const auto result = HLE::TryReplaceFunction(address); + // CachedInterpreter inherits from JitBase and is considered a JIT by relevant code. + // (see JitInterface and how m_mode is set within PowerPC.cpp) + const auto result = HLE::TryReplaceFunction(address, PowerPC::CoreMode::JIT); if (!result) return false; diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter.cpp b/Source/Core/Core/PowerPC/Interpreter/Interpreter.cpp index 6b475e1204..3b1f6ed4f4 100644 --- a/Source/Core/Core/PowerPC/Interpreter/Interpreter.cpp +++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter.cpp @@ -106,7 +106,7 @@ void Interpreter::Trace(const UGeckoInstruction& inst) bool Interpreter::HandleFunctionHooking(u32 address) { - const auto result = HLE::TryReplaceFunction(address); + const auto result = HLE::TryReplaceFunction(address, PowerPC::CoreMode::Interpreter); if (!result) return false; diff --git a/Source/Core/Core/PowerPC/Jit64/Jit.cpp b/Source/Core/Core/PowerPC/Jit64/Jit.cpp index 5938080b0e..83e99da156 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit.cpp @@ -1274,7 +1274,7 @@ void Jit64::IntializeSpeculativeConstants() bool Jit64::HandleFunctionHooking(u32 address) { - const auto result = HLE::TryReplaceFunction(address); + const auto result = HLE::TryReplaceFunction(address, PowerPC::CoreMode::JIT); if (!result) return false; diff --git a/Source/Core/Core/PowerPC/JitArm64/Jit.cpp b/Source/Core/Core/PowerPC/JitArm64/Jit.cpp index 311f5d40d8..26e7ce2aeb 100644 --- a/Source/Core/Core/PowerPC/JitArm64/Jit.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/Jit.cpp @@ -781,7 +781,7 @@ void JitArm64::WriteConditionalExceptionExit(int exception, ARM64Reg temp_gpr, A bool JitArm64::HandleFunctionHooking(u32 address) { - const auto result = HLE::TryReplaceFunction(address); + const auto result = HLE::TryReplaceFunction(address, PowerPC::CoreMode::JIT); if (!result) return false; diff --git a/Source/Core/Core/PowerPC/PPCAnalyst.cpp b/Source/Core/Core/PowerPC/PPCAnalyst.cpp index eaf49c7c46..3bf85b3dfb 100644 --- a/Source/Core/Core/PowerPC/PPCAnalyst.cpp +++ b/Source/Core/Core/PowerPC/PPCAnalyst.cpp @@ -998,7 +998,8 @@ u32 PPCAnalyzer::Analyze(u32 address, CodeBlock* block, CodeBuffer* buffer, crDiscardable = BitSet8{}; } - const bool hle = !!HLE::TryReplaceFunction(op.address); + const auto ppc_mode = Core::System::GetInstance().GetPowerPC().GetMode(); + const bool hle = !!HLE::TryReplaceFunction(op.address, ppc_mode); const bool may_exit_block = hle || op.canEndBlock || op.canCauseException; const bool opWantsFPRF = op.wantsFPRF; From c0b7e9cd94f273288e150bca69305aa86d6838b4 Mon Sep 17 00:00:00 2001 From: Lioncache Date: Mon, 18 Dec 2023 14:33:34 -0500 Subject: [PATCH 5/5] Core/HLE/HLE: Remove global system accessor from ExecuteFromJIT() We can just pass in our system instance via the ABI function helpers. --- Source/Core/Core/HLE/HLE.cpp | 4 ++-- Source/Core/Core/HLE/HLE.h | 2 +- Source/Core/Core/PowerPC/Jit64/Jit.cpp | 2 +- Source/Core/Core/PowerPC/JitArm64/Jit.cpp | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Source/Core/Core/HLE/HLE.cpp b/Source/Core/Core/HLE/HLE.cpp index 1707709f2d..5d7de6eccf 100644 --- a/Source/Core/Core/HLE/HLE.cpp +++ b/Source/Core/Core/HLE/HLE.cpp @@ -166,10 +166,10 @@ void Execute(const Core::CPUThreadGuard& guard, u32 current_pc, u32 hook_index) } } -void ExecuteFromJIT(u32 current_pc, u32 hook_index) +void ExecuteFromJIT(u32 current_pc, u32 hook_index, Core::System& system) { ASSERT(Core::IsCPUThread()); - Core::CPUThreadGuard guard(Core::System::GetInstance()); + Core::CPUThreadGuard guard(system); Execute(guard, current_pc, hook_index); } diff --git a/Source/Core/Core/HLE/HLE.h b/Source/Core/Core/HLE/HLE.h index a43ada5adf..3935ce4c5e 100644 --- a/Source/Core/Core/HLE/HLE.h +++ b/Source/Core/Core/HLE/HLE.h @@ -61,7 +61,7 @@ void Patch(Core::System& system, u32 pc, std::string_view func_name); u32 UnPatch(Core::System& system, std::string_view patch_name); u32 UnpatchRange(Core::System& system, u32 start_addr, u32 end_addr); void Execute(const Core::CPUThreadGuard& guard, u32 current_pc, u32 hook_index); -void ExecuteFromJIT(u32 current_pc, u32 hook_index); +void ExecuteFromJIT(u32 current_pc, u32 hook_index, Core::System& system); // Returns the HLE hook index of the address u32 GetHookByAddress(u32 address); diff --git a/Source/Core/Core/PowerPC/Jit64/Jit.cpp b/Source/Core/Core/PowerPC/Jit64/Jit.cpp index 83e99da156..4e8fa16889 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit.cpp @@ -396,7 +396,7 @@ void Jit64::HLEFunction(u32 hook_index) gpr.Flush(); fpr.Flush(); ABI_PushRegistersAndAdjustStack({}, 0); - ABI_CallFunctionCC(HLE::ExecuteFromJIT, js.compilerPC, hook_index); + ABI_CallFunctionCCP(HLE::ExecuteFromJIT, js.compilerPC, hook_index, &m_system); ABI_PopRegistersAndAdjustStack({}, 0); } diff --git a/Source/Core/Core/PowerPC/JitArm64/Jit.cpp b/Source/Core/Core/PowerPC/JitArm64/Jit.cpp index 26e7ce2aeb..5d7e9b2831 100644 --- a/Source/Core/Core/PowerPC/JitArm64/Jit.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/Jit.cpp @@ -248,7 +248,7 @@ void JitArm64::HLEFunction(u32 hook_index) gpr.Flush(FlushMode::All, ARM64Reg::INVALID_REG); fpr.Flush(FlushMode::All, ARM64Reg::INVALID_REG); - ABI_CallFunction(&HLE::ExecuteFromJIT, js.compilerPC, hook_index); + ABI_CallFunction(&HLE::ExecuteFromJIT, js.compilerPC, hook_index, &m_system); } void JitArm64::DoNothing(UGeckoInstruction inst)