2 changes: 1 addition & 1 deletion Source/Core/Core/HW/SystemTimers.cpp
Expand Up @@ -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()
Expand Down
5 changes: 3 additions & 2 deletions Source/Core/Core/IOS/IOS.cpp
Expand Up @@ -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()
Expand Down
16 changes: 8 additions & 8 deletions Source/Core/Core/IOS/MIOS.cpp
Expand Up @@ -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();
Expand Down Expand Up @@ -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.");
Expand Down
10 changes: 8 additions & 2 deletions Source/Core/Core/IOS/Network/SSL.cpp
Expand Up @@ -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;
}
Expand All @@ -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;
}
Expand Down
14 changes: 7 additions & 7 deletions Source/Core/Core/IOS/Network/Socket.cpp
Expand Up @@ -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);
}
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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}, {}), "
Expand Down Expand Up @@ -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}, "
Expand Down Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion Source/Core/Core/PatchEngine.cpp
Expand Up @@ -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);
}
}

Expand Down
34 changes: 23 additions & 11 deletions Source/Core/Core/PowerPC/BreakPoints.cpp
Expand Up @@ -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(),
Expand Down Expand Up @@ -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));
}
Expand Down Expand Up @@ -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)
Expand All @@ -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();
Expand All @@ -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
Expand All @@ -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;
Expand Down Expand Up @@ -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();
});
}

Expand Down Expand Up @@ -309,17 +321,17 @@ 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();
});
}

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();
});
}

Expand Down
20 changes: 20 additions & 0 deletions Source/Core/Core/PowerPC/BreakPoints.h
Expand Up @@ -15,6 +15,10 @@ namespace Common
{
class DebugInterface;
}
namespace Core
{
class System;
}

struct TBreakPoint
{
Expand Down Expand Up @@ -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<TBreakPoint>;
using TBreakPointsStr = std::vector<std::string>;

Expand Down Expand Up @@ -82,12 +93,20 @@ class BreakPoints

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<TMemCheck>;
using TMemChecksStr = std::vector<std::string>;

Expand All @@ -109,4 +128,5 @@ class MemChecks

private:
TMemChecks m_mem_checks;
Core::System& m_system;
};
13 changes: 7 additions & 6 deletions Source/Core/Core/PowerPC/CachedInterpreter/CachedInterpreter.cpp
Expand Up @@ -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;
}
Expand All @@ -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;
}
Expand All @@ -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;
}
Expand All @@ -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;
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
Expand Down
16 changes: 10 additions & 6 deletions Source/Core/Core/PowerPC/GDBStub.cpp
Expand Up @@ -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);
}
}
Expand Down Expand Up @@ -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<int>(type), len, addr);
}
Expand All @@ -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<int>(type),
len, addr);
}
Expand Down
11 changes: 6 additions & 5 deletions Source/Core/Core/PowerPC/Interpreter/Interpreter.cpp
Expand Up @@ -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;
}
}
Expand All @@ -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
Expand Down Expand Up @@ -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, "----------------------------");
Expand All @@ -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;
Expand Down Expand Up @@ -347,7 +348,7 @@ void Interpreter::ClearCache()

void Interpreter::CheckExceptions()
{
PowerPC::CheckExceptions();
m_system.GetPowerPC().CheckExceptions();
m_end_block = true;
}

Expand Down
Expand Up @@ -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;
}
5 changes: 3 additions & 2 deletions Source/Core/Core/PowerPC/Interpreter/Interpreter_Integer.cpp
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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
}
}
Expand Down Expand Up @@ -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
}
}
Expand Down
Expand Up @@ -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)
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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:
Expand Down
14 changes: 8 additions & 6 deletions Source/Core/Core/PowerPC/Jit64/Jit.cpp
Expand Up @@ -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);
Expand All @@ -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);
Expand All @@ -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);
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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));
Expand Down
16 changes: 9 additions & 7 deletions Source/Core/Core/PowerPC/JitArm64/Jit.cpp
Expand Up @@ -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));
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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);
Expand All @@ -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()));
Expand Down
Expand Up @@ -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);
Expand Down
7 changes: 5 additions & 2 deletions Source/Core/Core/PowerPC/JitCommon/JitBase.cpp
Expand Up @@ -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;
}
Expand All @@ -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;
Expand Down
22 changes: 11 additions & 11 deletions Source/Core/Core/PowerPC/MMU.cpp
Expand Up @@ -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())
{
}

Expand Down Expand Up @@ -530,10 +530,10 @@ std::optional<ReadResult<u32>> 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;

Expand All @@ -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;

Expand Down Expand Up @@ -892,7 +892,7 @@ std::optional<ReadResult<std::string>> 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)
Expand Down Expand Up @@ -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)
Expand All @@ -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)
Expand Down Expand Up @@ -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).
Expand All @@ -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;
Expand Down
4 changes: 3 additions & 1 deletion Source/Core/Core/PowerPC/MMU.h
Expand Up @@ -23,6 +23,7 @@ class MemoryManager;

namespace PowerPC
{
class PowerPCManager;
struct PowerPCState;

enum class RequestedAddressSpace
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -318,6 +319,7 @@ class MMU

Core::System& m_system;
Memory::MemoryManager& m_memory;
PowerPC::PowerPCManager& m_power_pc;
PowerPC::PowerPCState& m_ppc_state;

BatTable m_ibat_table;
Expand Down
7 changes: 4 additions & 3 deletions Source/Core/Core/PowerPC/PPCAnalyst.cpp
Expand Up @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion Source/Core/Core/PowerPC/PPCSymbolDB.cpp
Expand Up @@ -27,7 +27,7 @@

PPCSymbolDB g_symbolDB;

PPCSymbolDB::PPCSymbolDB() : debugger{&PowerPC::debug_interface}
PPCSymbolDB::PPCSymbolDB() : debugger{&Core::System::GetInstance().GetPowerPC().GetDebugInterface()}
{
}

Expand Down
426 changes: 213 additions & 213 deletions Source/Core/Core/PowerPC/PowerPC.cpp

Large diffs are not rendered by default.

115 changes: 78 additions & 37 deletions Source/Core/Core/PowerPC/PowerPC.h
Expand Up @@ -20,6 +20,10 @@

class CPUCoreBase;
class PointerWrap;
namespace CoreTiming
{
struct EventType;
}

namespace PowerPC
{
Expand Down Expand Up @@ -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<CPUCore>& AvailableCPUCores();
CPUCore DefaultCPUCore();

void Init(CPUCore cpu_core);
void Reset();
void Shutdown();
void DoState(PointerWrap& p);
void ScheduleInvalidateCacheThreadSafe(u32 address);

CoreMode GetMode();
// [NOT THREADSAFE] CPU Thread or CPU::PauseAndLock or Core::State::Uninitialized
void SetMode(CoreMode _coreType);
const char* GetCPUName();

// 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);

// 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();
void WriteFullTimeBaseValue(u64 value);
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();

void Init(CPUCore cpu_core);
void Reset();
void Shutdown();
void DoState(PointerWrap& p);
void ScheduleInvalidateCacheThreadSafe(u32 address);

CoreMode GetMode() const;
// [NOT THREADSAFE] CPU Thread or CPU::PauseAndLock or Core::State::Uninitialized
void SetMode(CoreMode _coreType);
const char* GetCPUName() const;

// 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);

// 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])
Expand All @@ -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
2 changes: 1 addition & 1 deletion Source/Core/Core/State.cpp
Expand Up @@ -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)
Expand Down
20 changes: 13 additions & 7 deletions Source/Core/Core/System.cpp
Expand Up @@ -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)
{
}

Expand All @@ -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;
Expand Down Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions Source/Core/Core/System.h
Expand Up @@ -73,6 +73,7 @@ class PixelEngineManager;
namespace PowerPC
{
class MMU;
class PowerPCManager;
struct PowerPCState;
} // namespace PowerPC
namespace ProcessorInterface
Expand Down Expand Up @@ -142,6 +143,7 @@ class System
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;
Expand Down
54 changes: 32 additions & 22 deletions Source/Core/DolphinQt/Debugger/BreakpointWidget.cpp
Expand Up @@ -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"
Expand All @@ -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"));
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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 =
Expand Down Expand Up @@ -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();
Expand All @@ -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);
Expand All @@ -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();
}

Expand All @@ -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();
Expand All @@ -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");
}

Expand All @@ -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; });
Expand All @@ -390,15 +400,15 @@ 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();
});
}
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; });
Expand All @@ -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();
Expand All @@ -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);

Expand All @@ -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();
Expand All @@ -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();
Expand Down
6 changes: 6 additions & 0 deletions Source/Core/DolphinQt/Debugger/BreakpointWidget.h
Expand Up @@ -12,6 +12,10 @@ class QCloseEvent;
class QShowEvent;
class QTableWidget;
class QToolBar;
namespace Core
{
class System;
}

class BreakpointWidget : public QDockWidget
{
Expand Down Expand Up @@ -51,6 +55,8 @@ class BreakpointWidget : public QDockWidget

void UpdateIcons();

Core::System& m_system;

QToolBar* m_toolbar;
QTableWidget* m_table;
QAction* m_new;
Expand Down
5 changes: 3 additions & 2 deletions Source/Core/DolphinQt/Debugger/CodeDiffDialog.cpp
Expand Up @@ -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();
Expand Down
65 changes: 36 additions & 29 deletions Source/Core/DolphinQt/Debugger/CodeViewWidget.cpp
Expand Up @@ -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)
Expand Down Expand Up @@ -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<u32> 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;

Expand All @@ -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.
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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<u32> target_addr =
PowerPC::debug_interface.GetMemoryAddressFromInstruction(code_line);
m_system.GetPowerPC().GetDebugInterface().GetMemoryAddressFromInstruction(code_line);

if (target_addr)
{
Expand All @@ -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<u32> target_addr =
PowerPC::debug_interface.GetMemoryAddressFromInstruction(code_line);
m_system.GetPowerPC().GetDebugInterface().GetMemoryAddressFromInstruction(code_line);

if (target_addr)
emit ShowMemory(*target_addr);
Expand All @@ -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));
Expand All @@ -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);
}
}
Expand All @@ -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(
Expand All @@ -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();
}

Expand Down Expand Up @@ -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);
}
}
Expand All @@ -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);
}

Expand Down Expand Up @@ -1091,18 +1097,19 @@ 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();
}

void CodeViewWidget::AddBreakpoint()
{
PowerPC::breakpoints.Add(GetContextAddress());
m_system.GetPowerPC().GetBreakPoints().Add(GetContextAddress());

emit BreakpointsChanged();
Update();
Expand Down
38 changes: 21 additions & 17 deletions Source/Core/DolphinQt/Debugger/CodeWidget.cpp
Expand Up @@ -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.
}
Expand All @@ -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);
}
Expand Down Expand Up @@ -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
Expand All @@ -518,7 +522,7 @@ void CodeWidget::StepOut()
{
if (WillInstructionReturn(m_system, inst))
{
PowerPC::SingleStep();
power_pc.SingleStep();
break;
}

Expand All @@ -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);
Expand Down
15 changes: 9 additions & 6 deletions Source/Core/DolphinQt/Debugger/MemoryViewWidget.cpp
Expand Up @@ -170,7 +170,8 @@ class MemoryViewTable final : public QTableWidget
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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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)
{
Expand All @@ -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);
}
}

Expand Down
5 changes: 4 additions & 1 deletion Source/Core/DolphinQt/Debugger/MemoryViewWidget.h
Expand Up @@ -18,7 +18,8 @@ enum class Type;
namespace Core
{
class CPUThreadGuard;
}
class System;
} // namespace Core

class MemoryViewTable;

Expand Down Expand Up @@ -85,6 +86,8 @@ class MemoryViewWidget final : public QWidget
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{};
Expand Down
4 changes: 3 additions & 1 deletion Source/Core/DolphinQt/Debugger/RegisterWidget.cpp
Expand Up @@ -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(
Expand Down
9 changes: 5 additions & 4 deletions Source/Core/DolphinQt/Debugger/ThreadWidget.cpp
Expand Up @@ -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);
Expand Down Expand Up @@ -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
{
Expand Down
80 changes: 44 additions & 36 deletions Source/Core/DolphinQt/Debugger/WatchWidget.cpp
Expand Up @@ -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.
Expand Down Expand Up @@ -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<int>(PowerPC::debug_interface.GetWatches().size());
int size = static_cast<int>(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 =
Expand Down Expand Up @@ -263,7 +265,7 @@ void WatchWidget::OnDelete()

void WatchWidget::OnClear()
{
PowerPC::debug_interface.ClearWatches();
m_system.GetPowerPC().GetDebugInterface().ClearWatches();
Update();
}

Expand Down Expand Up @@ -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();
Expand All @@ -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");
}

Expand Down Expand Up @@ -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:
Expand All @@ -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
Expand All @@ -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;
}
}
Expand All @@ -455,13 +460,13 @@ void WatchWidget::LockWatchAddress(const Core::CPUThreadGuard& guard, u32 addres
bytes.push_back(static_cast<u8>(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<int> row_indices;
for (const auto& index : m_table->selectionModel()->selectedRows())
{
Expand All @@ -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);
}

Expand All @@ -502,35 +508,36 @@ 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());
const auto row_variant = item->data(Qt::UserRole);
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);
}
}
Expand All @@ -541,19 +548,20 @@ 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());
const auto row_variant = item->data(Qt::UserRole);
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);
}
}

Expand Down
5 changes: 4 additions & 1 deletion Source/Core/DolphinQt/Debugger/WatchWidget.h
Expand Up @@ -17,7 +17,8 @@ class QToolBar;
namespace Core
{
class CPUThreadGuard;
};
class System;
}; // namespace Core

class WatchWidget : public QDockWidget
{
Expand Down Expand Up @@ -62,6 +63,8 @@ class WatchWidget : public QDockWidget
void LockSelectedWatches();
void UnlockSelectedWatches();

Core::System& m_system;

QAction* m_new;
QAction* m_delete;
QAction* m_clear;
Expand Down
3 changes: 2 additions & 1 deletion Source/Core/DolphinQt/MenuBar.cpp
Expand Up @@ -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();
Expand Down
41 changes: 23 additions & 18 deletions Source/UnitTests/Core/CoreTimingTest.cpp
Expand Up @@ -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())
{
Expand All @@ -48,8 +48,7 @@ class ScopeInit final
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();
}
Expand All @@ -59,10 +58,9 @@ class ScopeInit final
{
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();
Expand All @@ -71,6 +69,7 @@ class ScopeInit final
bool UserDirectoryExists() const { return !m_profile_path.empty(); }

private:
Core::System& m_system;
std::string m_profile_path;
};

Expand All @@ -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();

Expand Down Expand Up @@ -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();

Expand Down Expand Up @@ -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>);
Expand Down Expand Up @@ -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();

Expand Down Expand Up @@ -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();

Expand Down Expand Up @@ -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();

Expand Down