@@ -191,7 +191,7 @@ static T ReadFromHardware(Memory::MemoryManager& memory, u32 em_address)

bool wi = false;

if (!never_translate && MSR.DR)
if (!never_translate && PowerPC::ppcState.msr.DR)
{
auto translated_addr = TranslateAddress<flag>(em_address);
if (!translated_addr.Success())
@@ -235,7 +235,7 @@ static T ReadFromHardware(Memory::MemoryManager& memory, u32 em_address)
else
{
ppcState.dCache.Read(em_address, &value, sizeof(T),
HID0.DLOCK || flag != XCheckTLBFlag::Read);
HID0(PowerPC::ppcState).DLOCK || flag != XCheckTLBFlag::Read);
}

return bswap(value);
@@ -254,7 +254,7 @@ static T ReadFromHardware(Memory::MemoryManager& memory, u32 em_address)
else
{
ppcState.dCache.Read(em_address + 0x10000000, &value, sizeof(T),
HID0.DLOCK || flag != XCheckTLBFlag::Read);
HID0(PowerPC::ppcState).DLOCK || flag != XCheckTLBFlag::Read);
}

return bswap(value);
@@ -270,7 +270,7 @@ static T ReadFromHardware(Memory::MemoryManager& memory, u32 em_address)
return bswap(value);
}

PanicAlertFmt("Unable to resolve read address {:x} PC {:x}", em_address, PC);
PanicAlertFmt("Unable to resolve read address {:x} PC {:x}", em_address, PowerPC::ppcState.pc);
if (Core::System::GetInstance().IsPauseOnPanicMode())
{
CPU::Break();
@@ -303,7 +303,7 @@ static void WriteToHardware(Core::System& system, Memory::MemoryManager& memory,

bool wi = false;

if (!never_translate && MSR.DR)
if (!never_translate && PowerPC::ppcState.msr.DR)
{
auto translated_addr = TranslateAddress<flag>(em_address);
if (!translated_addr.Success())
@@ -425,7 +425,7 @@ static void WriteToHardware(Core::System& system, Memory::MemoryManager& memory,
em_address &= memory.GetRamMask();

if (ppcState.m_enable_dcache && !wi)
ppcState.dCache.Write(em_address, &swapped_data, size, HID0.DLOCK);
ppcState.dCache.Write(em_address, &swapped_data, size, HID0(PowerPC::ppcState).DLOCK);

if (!ppcState.m_enable_dcache || wi || flag != XCheckTLBFlag::Write)
std::memcpy(&memory.GetRAM()[em_address], &swapped_data, size);
@@ -439,7 +439,10 @@ static void WriteToHardware(Core::System& system, Memory::MemoryManager& memory,
em_address &= 0x0FFFFFFF;

if (ppcState.m_enable_dcache && !wi)
ppcState.dCache.Write(em_address + 0x10000000, &swapped_data, size, HID0.DLOCK);
{
ppcState.dCache.Write(em_address + 0x10000000, &swapped_data, size,
HID0(PowerPC::ppcState).DLOCK);
}

if (!ppcState.m_enable_dcache || wi || flag != XCheckTLBFlag::Write)
std::memcpy(&memory.GetEXRAM()[em_address], &swapped_data, size);
@@ -456,7 +459,7 @@ static void WriteToHardware(Core::System& system, Memory::MemoryManager& memory,
return;
}

PanicAlertFmt("Unable to resolve write address {:x} PC {:x}", em_address, PC);
PanicAlertFmt("Unable to resolve write address {:x} PC {:x}", em_address, PowerPC::ppcState.pc);
if (Core::System::GetInstance().IsPauseOnPanicMode())
{
CPU::Break();
@@ -486,7 +489,7 @@ u32 Read_Opcode(u32 address)
TryReadInstResult TryReadInstruction(u32 address)
{
bool from_bat = true;
if (MSR.IR)
if (PowerPC::ppcState.msr.IR)
{
auto tlb_addr = TranslateAddress<XCheckTLBFlag::Opcode>(address);
if (!tlb_addr.Success())
@@ -537,7 +540,7 @@ std::optional<ReadResult<u32>> HostTryReadInstruction(const u32 address,
case RequestedAddressSpace::Effective:
{
const u32 value = ReadFromHardware<XCheckTLBFlag::OpcodeNoException, u32>(memory, address);
return ReadResult<u32>(!!MSR.DR, value);
return ReadResult<u32>(!!PowerPC::ppcState.msr.DR, value);
}
case RequestedAddressSpace::Physical:
{
@@ -547,7 +550,7 @@ std::optional<ReadResult<u32>> HostTryReadInstruction(const u32 address,
}
case RequestedAddressSpace::Virtual:
{
if (!MSR.DR)
if (!PowerPC::ppcState.msr.DR)
return std::nullopt;
const u32 value = ReadFromHardware<XCheckTLBFlag::OpcodeNoException, u32>(memory, address);
return ReadResult<u32>(true, value);
@@ -575,7 +578,7 @@ static void Memcheck(u32 address, u64 var, bool write, size_t size)

mc->num_hits++;

const bool pause = mc->Action(&debug_interface, var, address, write, size, PC);
const bool pause = mc->Action(&debug_interface, var, address, write, size, PowerPC::ppcState.pc);
if (!pause)
return;

@@ -658,7 +661,7 @@ static std::optional<ReadResult<T>> HostTryReadUX(const u32 address, RequestedAd
case RequestedAddressSpace::Effective:
{
T value = ReadFromHardware<XCheckTLBFlag::NoException, T>(memory, address);
return ReadResult<T>(!!MSR.DR, std::move(value));
return ReadResult<T>(!!PowerPC::ppcState.msr.DR, std::move(value));
}
case RequestedAddressSpace::Physical:
{
@@ -667,7 +670,7 @@ static std::optional<ReadResult<T>> HostTryReadUX(const u32 address, RequestedAd
}
case RequestedAddressSpace::Virtual:
{
if (!MSR.DR)
if (!PowerPC::ppcState.msr.DR)
return std::nullopt;
T value = ReadFromHardware<XCheckTLBFlag::NoException, T>(memory, address);
return ReadResult<T>(true, std::move(value));
@@ -877,12 +880,12 @@ static std::optional<WriteResult> HostTryWriteUX(const u32 var, const u32 addres
{
case RequestedAddressSpace::Effective:
WriteToHardware<XCheckTLBFlag::NoException>(system, memory, address, var, size);
return WriteResult(!!MSR.DR);
return WriteResult(!!PowerPC::ppcState.msr.DR);
case RequestedAddressSpace::Physical:
WriteToHardware<XCheckTLBFlag::NoException, true>(system, memory, address, var, size);
return WriteResult(false);
case RequestedAddressSpace::Virtual:
if (!MSR.DR)
if (!PowerPC::ppcState.msr.DR)
return std::nullopt;
WriteToHardware<XCheckTLBFlag::NoException>(system, memory, address, var, size);
return WriteResult(true);
@@ -977,7 +980,7 @@ bool IsOptimizableRAMAddress(const u32 address)
if (PowerPC::memchecks.HasAny())
return false;

if (!MSR.DR)
if (!PowerPC::ppcState.msr.DR)
return false;

// TODO: This API needs to take an access size
@@ -1029,11 +1032,11 @@ bool HostIsRAMAddress(u32 address, RequestedAddressSpace space)
switch (space)
{
case RequestedAddressSpace::Effective:
return IsRAMAddress<XCheckTLBFlag::NoException>(memory, address, MSR.DR);
return IsRAMAddress<XCheckTLBFlag::NoException>(memory, address, PowerPC::ppcState.msr.DR);
case RequestedAddressSpace::Physical:
return IsRAMAddress<XCheckTLBFlag::NoException>(memory, address, false);
case RequestedAddressSpace::Virtual:
if (!MSR.DR)
if (!PowerPC::ppcState.msr.DR)
return false;
return IsRAMAddress<XCheckTLBFlag::NoException>(memory, address, true);
}
@@ -1054,11 +1057,12 @@ bool HostIsInstructionRAMAddress(u32 address, RequestedAddressSpace space)
switch (space)
{
case RequestedAddressSpace::Effective:
return IsRAMAddress<XCheckTLBFlag::OpcodeNoException>(memory, address, MSR.IR);
return IsRAMAddress<XCheckTLBFlag::OpcodeNoException>(memory, address,
PowerPC::ppcState.msr.IR);
case RequestedAddressSpace::Physical:
return IsRAMAddress<XCheckTLBFlag::OpcodeNoException>(memory, address, false);
case RequestedAddressSpace::Virtual:
if (!MSR.IR)
if (!PowerPC::ppcState.msr.IR)
return false;
return IsRAMAddress<XCheckTLBFlag::OpcodeNoException>(memory, address, true);
}
@@ -1148,7 +1152,7 @@ void DMA_MemoryToLC(const u32 cache_address, const u32 mem_address, const u32 nu
void ClearDCacheLine(u32 address)
{
DEBUG_ASSERT((address & 0x1F) == 0);
if (MSR.DR)
if (PowerPC::ppcState.msr.DR)
{
auto translated_address = TranslateAddress<XCheckTLBFlag::Write>(address);
if (translated_address.result == TranslateAddressResultEnum::DIRECT_STORE_SEGMENT)
@@ -1180,7 +1184,7 @@ void StoreDCacheLine(u32 address)
{
address &= ~0x1F;

if (MSR.DR)
if (PowerPC::ppcState.msr.DR)
{
auto translated_address = TranslateAddress<XCheckTLBFlag::Write>(address);
if (translated_address.result == TranslateAddressResultEnum::DIRECT_STORE_SEGMENT)
@@ -1204,7 +1208,7 @@ void InvalidateDCacheLine(u32 address)
{
address &= ~0x1F;

if (MSR.DR)
if (PowerPC::ppcState.msr.DR)
{
auto translated_address = TranslateAddress<XCheckTLBFlag::Write>(address);
if (translated_address.result == TranslateAddressResultEnum::DIRECT_STORE_SEGMENT)
@@ -1226,7 +1230,7 @@ void FlushDCacheLine(u32 address)
{
address &= ~0x1F;

if (MSR.DR)
if (PowerPC::ppcState.msr.DR)
{
auto translated_address = TranslateAddress<XCheckTLBFlag::Write>(address);
if (translated_address.result == TranslateAddressResultEnum::DIRECT_STORE_SEGMENT)
@@ -1250,7 +1254,7 @@ void TouchDCacheLine(u32 address, bool store)
{
address &= ~0x1F;

if (MSR.DR)
if (PowerPC::ppcState.msr.DR)
{
auto translated_address = TranslateAddress<XCheckTLBFlag::Write>(address);
if (translated_address.result == TranslateAddressResultEnum::DIRECT_STORE_SEGMENT)
@@ -1275,7 +1279,7 @@ u32 IsOptimizableMMIOAccess(u32 address, u32 access_size)
if (PowerPC::memchecks.HasAny())
return 0;

if (!MSR.DR)
if (!PowerPC::ppcState.msr.DR)
return 0;

// Translate address
@@ -1298,7 +1302,7 @@ bool IsOptimizableGatherPipeWrite(u32 address)
if (PowerPC::memchecks.HasAny())
return false;

if (!MSR.DR)
if (!PowerPC::ppcState.msr.DR)
return false;

// Translate address, only check BAT mapping.
@@ -1314,7 +1318,7 @@ bool IsOptimizableGatherPipeWrite(u32 address)

TranslateResult JitCache_TranslateAddress(u32 address)
{
if (!MSR.IR)
if (!PowerPC::ppcState.msr.IR)
return TranslateResult{address};

// TODO: We shouldn't use FLAG_OPCODE if the caller is the debugger.
@@ -1362,7 +1366,7 @@ static void GenerateDSIException(u32 effective_address, bool write)
if (!Core::System::GetInstance().IsMMUMode())
{
PanicAlertFmt("Invalid {} {:#010x}, PC = {:#010x}", write ? "write to" : "read from",
effective_address, PC);
effective_address, PowerPC::ppcState.pc);
if (Core::System::GetInstance().IsPauseOnPanicMode())
{
CPU::Break();
@@ -1387,10 +1391,10 @@ static void GenerateDSIException(u32 effective_address, bool write)
static void GenerateISIException(u32 effective_address)
{
// Address of instruction could not be translated
NPC = effective_address;
PowerPC::ppcState.npc = effective_address;

PowerPC::ppcState.Exceptions |= EXCEPTION_ISI;
WARN_LOG_FMT(POWERPC, "ISI exception at {:#010x}", PC);
WARN_LOG_FMT(POWERPC, "ISI exception at {:#010x}", PowerPC::ppcState.pc);
}

void SDRUpdated()
@@ -1733,7 +1737,7 @@ void DBATUpdated()

dbat_table = {};
UpdateBATs(dbat_table, SPR_DBAT0U);
bool extended_bats = SConfig::GetInstance().bWii && HID4.SBE;
bool extended_bats = SConfig::GetInstance().bWii && HID4(PowerPC::ppcState).SBE;
if (extended_bats)
UpdateBATs(dbat_table, SPR_DBAT4U);
if (memory.GetFakeVMEM())
@@ -1758,7 +1762,7 @@ void IBATUpdated()

ibat_table = {};
UpdateBATs(ibat_table, SPR_IBAT0U);
bool extended_bats = SConfig::GetInstance().bWii && HID4.SBE;
bool extended_bats = SConfig::GetInstance().bWii && HID4(PowerPC::ppcState).SBE;
if (extended_bats)
UpdateBATs(ibat_table, SPR_IBAT4U);
if (memory.GetFakeVMEM())
@@ -394,17 +394,17 @@ u32 InstructionCache::ReadInstruction(u32 addr)
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

if (!HID0.ICE || m_disable_icache) // instruction cache is disabled
if (!HID0(PowerPC::ppcState).ICE || m_disable_icache) // instruction cache is disabled
return memory.Read_U32(addr);

u32 value;
Read(addr, &value, sizeof(value), HID0.ILOCK);
Read(addr, &value, sizeof(value), HID0(PowerPC::ppcState).ILOCK);
return Common::swap32(value);
}

void InstructionCache::Invalidate(u32 addr)
{
if (!HID0.ICE || m_disable_icache)
if (!HID0(PowerPC::ppcState).ICE || m_disable_icache)
return;

// Invalidates the whole set
@@ -51,15 +51,17 @@ GekkoOPInfo* GetOpInfo(UGeckoInstruction inst)
case 63:
return m_infoTable63[inst.SUBOP10];
default:
ASSERT_MSG(POWERPC, 0, "GetOpInfo - invalid subtable op {:08x} @ {:08x}", inst.hex, PC);
ASSERT_MSG(POWERPC, 0, "GetOpInfo - invalid subtable op {:08x} @ {:08x}", inst.hex,
PowerPC::ppcState.pc);
return nullptr;
}
}
else
{
if (info->type == OpType::Invalid)
{
ASSERT_MSG(POWERPC, 0, "GetOpInfo - invalid op {:08x} @ {:08x}", inst.hex, PC);
ASSERT_MSG(POWERPC, 0, "GetOpInfo - invalid op {:08x} @ {:08x}", inst.hex,
PowerPC::ppcState.pc);
return nullptr;
}
return m_infoTable[inst.OPCD];
@@ -85,15 +87,16 @@ Interpreter::Instruction GetInterpreterOp(UGeckoInstruction inst)
return Interpreter::m_op_table63[inst.SUBOP10];
default:
ASSERT_MSG(POWERPC, 0, "GetInterpreterOp - invalid subtable op {:08x} @ {:08x}", inst.hex,
PC);
PowerPC::ppcState.pc);
return nullptr;
}
}
else
{
if (info->type == OpType::Invalid)
{
ASSERT_MSG(POWERPC, 0, "GetInterpreterOp - invalid op {:08x} @ {:08x}", inst.hex, PC);
ASSERT_MSG(POWERPC, 0, "GetInterpreterOp - invalid op {:08x} @ {:08x}", inst.hex,
PowerPC::ppcState.pc);
return nullptr;
}
return Interpreter::m_op_table[inst.OPCD];
@@ -45,7 +45,7 @@ static CoreMode s_mode = CoreMode::Interpreter;

BreakPoints breakpoints;
MemChecks memchecks;
PPCDebugInterface debug_interface;
PPCDebugInterface debug_interface(Core::System::GetInstance());

static CoreTiming::EventType* s_invalidate_cache_thread_safe;

@@ -106,9 +106,9 @@ 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.

// rSPR(SPR_DEC) = SystemTimers::GetFakeDecrementer();
// *((u64 *)&TL) = SystemTimers::GetFakeTimeBase(); //works since we are little endian and TL
// comes first :)
// PowerPC::ppcState.spr[SPR_DEC] = SystemTimers::GetFakeDecrementer();
// *((u64 *)&TL(PowerPC::ppcState)) = SystemTimers::GetFakeTimeBase(); //works since we are little
// endian and TL comes first :)

p.DoArray(ppcState.gpr);
p.Do(ppcState.pc);
@@ -200,19 +200,19 @@ static void ResetRegisters()
{
v = 0x8000000000000001;
}
SetXER({});
ppcState.SetXER({});

RoundingModeUpdated();
DBATUpdated();
IBATUpdated();

TL = 0;
TU = 0;
TL(PowerPC::ppcState) = 0;
TU(PowerPC::ppcState) = 0;
SystemTimers::TimeBaseSet();

// MSR should be 0x40, but we don't emulate BS1, so it would never be turned off :}
ppcState.msr.Hex = 0;
rDEC = 0xFFFFFFFF;
ppcState.spr[SPR_DEC] = 0xFFFFFFFF;
SystemTimers::DecrementerSet();
}

@@ -394,72 +394,75 @@ void RunLoop()
u64 ReadFullTimeBaseValue()
{
u64 value;
std::memcpy(&value, &TL, sizeof(value));
std::memcpy(&value, &TL(PowerPC::ppcState), sizeof(value));
return value;
}

void WriteFullTimeBaseValue(u64 value)
{
std::memcpy(&TL, &value, sizeof(value));
std::memcpy(&TL(PowerPC::ppcState), &value, sizeof(value));
}

void UpdatePerformanceMonitor(u32 cycles, u32 num_load_stores, u32 num_fp_inst)
void UpdatePerformanceMonitor(u32 cycles, u32 num_load_stores, u32 num_fp_inst,
PowerPCState& ppc_state)
{
switch (MMCR0.PMC1SELECT)
switch (MMCR0(ppc_state).PMC1SELECT)
{
case 0: // No change
break;
case 1: // Processor cycles
PowerPC::ppcState.spr[SPR_PMC1] += cycles;
ppc_state.spr[SPR_PMC1] += cycles;
break;
default:
break;
}

switch (MMCR0.PMC2SELECT)
switch (MMCR0(ppc_state).PMC2SELECT)
{
case 0: // No change
break;
case 1: // Processor cycles
PowerPC::ppcState.spr[SPR_PMC2] += cycles;
ppc_state.spr[SPR_PMC2] += cycles;
break;
case 11: // Number of loads and stores completed
PowerPC::ppcState.spr[SPR_PMC2] += num_load_stores;
ppc_state.spr[SPR_PMC2] += num_load_stores;
break;
default:
break;
}

switch (MMCR1.PMC3SELECT)
switch (MMCR1(ppc_state).PMC3SELECT)
{
case 0: // No change
break;
case 1: // Processor cycles
PowerPC::ppcState.spr[SPR_PMC3] += cycles;
ppc_state.spr[SPR_PMC3] += cycles;
break;
case 11: // Number of FPU instructions completed
PowerPC::ppcState.spr[SPR_PMC3] += num_fp_inst;
ppc_state.spr[SPR_PMC3] += num_fp_inst;
break;
default:
break;
}

switch (MMCR1.PMC4SELECT)
switch (MMCR1(ppc_state).PMC4SELECT)
{
case 0: // No change
break;
case 1: // Processor cycles
PowerPC::ppcState.spr[SPR_PMC4] += cycles;
ppc_state.spr[SPR_PMC4] += cycles;
break;
default:
break;
}

if ((MMCR0.PMC1INTCONTROL && (PowerPC::ppcState.spr[SPR_PMC1] & 0x80000000) != 0) ||
(MMCR0.PMCINTCONTROL && (PowerPC::ppcState.spr[SPR_PMC2] & 0x80000000) != 0) ||
(MMCR0.PMCINTCONTROL && (PowerPC::ppcState.spr[SPR_PMC3] & 0x80000000) != 0) ||
(MMCR0.PMCINTCONTROL && (PowerPC::ppcState.spr[SPR_PMC4] & 0x80000000) != 0))
PowerPC::ppcState.Exceptions |= EXCEPTION_PERFORMANCE_MONITOR;
if ((MMCR0(ppc_state).PMC1INTCONTROL && (ppc_state.spr[SPR_PMC1] & 0x80000000) != 0) ||
(MMCR0(ppc_state).PMCINTCONTROL && (ppc_state.spr[SPR_PMC2] & 0x80000000) != 0) ||
(MMCR0(ppc_state).PMCINTCONTROL && (ppc_state.spr[SPR_PMC3] & 0x80000000) != 0) ||
(MMCR0(ppc_state).PMCINTCONTROL && (ppc_state.spr[SPR_PMC4] & 0x80000000) != 0))
{
ppc_state.Exceptions |= EXCEPTION_PERFORMANCE_MONITOR;
}
}

void CheckExceptions()
@@ -489,47 +492,47 @@ void CheckExceptions()

if (exceptions & EXCEPTION_ISI)
{
SRR0 = NPC;
SRR0(PowerPC::ppcState) = PowerPC::ppcState.npc;
// Page fault occurred
SRR1 = (MSR.Hex & 0x87C0FFFF) | (1 << 30);
MSR.LE = MSR.ILE;
MSR.Hex &= ~0x04EF36;
PC = NPC = 0x00000400;
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;

DEBUG_LOG_FMT(POWERPC, "EXCEPTION_ISI");
ppcState.Exceptions &= ~EXCEPTION_ISI;
}
else if (exceptions & EXCEPTION_PROGRAM)
{
SRR0 = PC;
SRR0(PowerPC::ppcState) = PowerPC::ppcState.pc;
// SRR1 was partially set by GenerateProgramException, so bitwise or is used here
SRR1 |= MSR.Hex & 0x87C0FFFF;
MSR.LE = MSR.ILE;
MSR.Hex &= ~0x04EF36;
PC = NPC = 0x00000700;
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;

DEBUG_LOG_FMT(POWERPC, "EXCEPTION_PROGRAM");
ppcState.Exceptions &= ~EXCEPTION_PROGRAM;
}
else if (exceptions & EXCEPTION_SYSCALL)
{
SRR0 = NPC;
SRR1 = MSR.Hex & 0x87C0FFFF;
MSR.LE = MSR.ILE;
MSR.Hex &= ~0x04EF36;
PC = NPC = 0x00000C00;
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;

DEBUG_LOG_FMT(POWERPC, "EXCEPTION_SYSCALL (PC={:08x})", PC);
DEBUG_LOG_FMT(POWERPC, "EXCEPTION_SYSCALL (PC={:08x})", PowerPC::ppcState.pc);
ppcState.Exceptions &= ~EXCEPTION_SYSCALL;
}
else if (exceptions & EXCEPTION_FPU_UNAVAILABLE)
{
// This happens a lot - GameCube OS uses deferred FPU context switching
SRR0 = PC; // re-execute the instruction
SRR1 = MSR.Hex & 0x87C0FFFF;
MSR.LE = MSR.ILE;
MSR.Hex &= ~0x04EF36;
PC = NPC = 0x00000800;
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;

DEBUG_LOG_FMT(POWERPC, "EXCEPTION_FPU_UNAVAILABLE");
ppcState.Exceptions &= ~EXCEPTION_FPU_UNAVAILABLE;
@@ -540,23 +543,23 @@ void CheckExceptions()
}
else if (exceptions & EXCEPTION_DSI)
{
SRR0 = PC;
SRR1 = MSR.Hex & 0x87C0FFFF;
MSR.LE = MSR.ILE;
MSR.Hex &= ~0x04EF36;
PC = NPC = 0x00000300;
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;
// DSISR and DAR regs are changed in GenerateDSIException()

DEBUG_LOG_FMT(POWERPC, "EXCEPTION_DSI");
ppcState.Exceptions &= ~EXCEPTION_DSI;
}
else if (exceptions & EXCEPTION_ALIGNMENT)
{
SRR0 = PC;
SRR1 = MSR.Hex & 0x87C0FFFF;
MSR.LE = MSR.ILE;
MSR.Hex &= ~0x04EF36;
PC = NPC = 0x00000600;
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;

// TODO crazy amount of DSISR options to check out

@@ -577,40 +580,41 @@ void CheckExternalExceptions()

// EXTERNAL INTERRUPT
// Handling is delayed until MSR.EE=1.
if (exceptions && MSR.EE)
if (exceptions && PowerPC::ppcState.msr.EE)
{
if (exceptions & EXCEPTION_EXTERNAL_INT)
{
// Pokemon gets this "too early", it hasn't a handler yet
SRR0 = NPC;
SRR1 = MSR.Hex & 0x87C0FFFF;
MSR.LE = MSR.ILE;
MSR.Hex &= ~0x04EF36;
PC = NPC = 0x00000500;
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;

DEBUG_LOG_FMT(POWERPC, "EXCEPTION_EXTERNAL_INT");
ppcState.Exceptions &= ~EXCEPTION_EXTERNAL_INT;

DEBUG_ASSERT_MSG(POWERPC, (SRR1 & 0x02) != 0, "EXTERNAL_INT unrecoverable???");
DEBUG_ASSERT_MSG(POWERPC, (SRR1(PowerPC::ppcState) & 0x02) != 0,
"EXTERNAL_INT unrecoverable???");
}
else if (exceptions & EXCEPTION_PERFORMANCE_MONITOR)
{
SRR0 = NPC;
SRR1 = MSR.Hex & 0x87C0FFFF;
MSR.LE = MSR.ILE;
MSR.Hex &= ~0x04EF36;
PC = NPC = 0x00000F00;
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;

DEBUG_LOG_FMT(POWERPC, "EXCEPTION_PERFORMANCE_MONITOR");
ppcState.Exceptions &= ~EXCEPTION_PERFORMANCE_MONITOR;
}
else if (exceptions & EXCEPTION_DECREMENTER)
{
SRR0 = NPC;
SRR1 = MSR.Hex & 0x87C0FFFF;
MSR.LE = MSR.ILE;
MSR.Hex &= ~0x04EF36;
PC = NPC = 0x00000900;
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;

DEBUG_LOG_FMT(POWERPC, "EXCEPTION_DECREMENTER");
ppcState.Exceptions &= ~EXCEPTION_DECREMENTER;
@@ -626,7 +630,7 @@ void CheckExternalExceptions()

void CheckBreakPoints()
{
const TBreakPoint* bp = PowerPC::breakpoints.GetBreakpoint(PC);
const TBreakPoint* bp = PowerPC::breakpoints.GetBreakpoint(PowerPC::ppcState.pc);

if (!bp || !bp->is_enabled || !EvaluateCondition(bp->condition))
return;
@@ -642,11 +646,14 @@ void CheckBreakPoints()
NOTICE_LOG_FMT(MEMMAP,
"BP {:08x} {}({:08x} {:08x} {:08x} {:08x} {:08x} {:08x} {:08x} {:08x} {:08x} "
"{:08x}) LR={:08x}",
PC, g_symbolDB.GetDescription(PC), GPR(3), GPR(4), GPR(5), GPR(6), GPR(7),
GPR(8), GPR(9), GPR(10), GPR(11), GPR(12), LR);
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));
}
if (PowerPC::breakpoints.IsTempBreakPoint(PC))
PowerPC::breakpoints.Remove(PC);
if (PowerPC::breakpoints.IsTempBreakPoint(PowerPC::ppcState.pc))
PowerPC::breakpoints.Remove(PowerPC::ppcState.pc);
}

void PowerPCState::SetSR(u32 index, u32 value)
@@ -657,22 +664,22 @@ void PowerPCState::SetSR(u32 index, u32 value)

// FPSCR update functions

void UpdateFPRFDouble(double dvalue)
void PowerPCState::UpdateFPRFDouble(double dvalue)
{
FPSCR.FPRF = Common::ClassifyDouble(dvalue);
fpscr.FPRF = Common::ClassifyDouble(dvalue);
}

void UpdateFPRFSingle(float fvalue)
void PowerPCState::UpdateFPRFSingle(float fvalue)
{
FPSCR.FPRF = Common::ClassifyFloat(fvalue);
fpscr.FPRF = Common::ClassifyFloat(fvalue);
}

void RoundingModeUpdated()
{
// The rounding mode is separate for each thread, so this must run on the CPU thread
ASSERT(Core::IsCPUThread());

FPURoundMode::SetSIMDMode(FPSCR.RN, FPSCR.NI);
FPURoundMode::SetSIMDMode(PowerPC::ppcState.fpscr.RN, PowerPC::ppcState.fpscr.NI);
}

} // namespace PowerPC
@@ -185,6 +185,41 @@ struct PowerPCState
}

void SetSR(u32 index, u32 value);

void SetCarry(u32 ca) { xer_ca = ca; }

u32 GetCarry() const { return xer_ca; }

UReg_XER GetXER() const
{
u32 xer = 0;
xer |= xer_stringctrl;
xer |= xer_ca << XER_CA_SHIFT;
xer |= xer_so_ov << XER_OV_SHIFT;
return UReg_XER{xer};
}

void SetXER(UReg_XER new_xer)
{
xer_stringctrl = new_xer.BYTE_COUNT + (new_xer.BYTE_CMP << 8);
xer_ca = new_xer.CA;
xer_so_ov = (new_xer.SO << 1) + new_xer.OV;
}

u32 GetXER_SO() const { return xer_so_ov >> 1; }

void SetXER_SO(bool value) { xer_so_ov |= static_cast<u32>(value) << 1; }

u32 GetXER_OV() const { return xer_so_ov & 1; }

void SetXER_OV(bool value)
{
xer_so_ov = (xer_so_ov & 0xFE) | static_cast<u32>(value);
SetXER_SO(value);
}

void UpdateFPRFDouble(double dvalue);
void UpdateFPRFSingle(float fvalue);
};

#if _M_X86_64
@@ -232,91 +267,28 @@ void RunLoop();
u64 ReadFullTimeBaseValue();
void WriteFullTimeBaseValue(u64 value);

void UpdatePerformanceMonitor(u32 cycles, u32 num_load_stores, u32 num_fp_inst);
void UpdatePerformanceMonitor(u32 cycles, u32 num_load_stores, u32 num_fp_inst,
PowerPCState& ppc_state);

// Easy register access macros.
#define HID0 ((UReg_HID0&)PowerPC::ppcState.spr[SPR_HID0])
#define HID2 ((UReg_HID2&)PowerPC::ppcState.spr[SPR_HID2])
#define HID4 ((UReg_HID4&)PowerPC::ppcState.spr[SPR_HID4])
#define DMAU (*(UReg_DMAU*)&PowerPC::ppcState.spr[SPR_DMAU])
#define DMAL (*(UReg_DMAL*)&PowerPC::ppcState.spr[SPR_DMAL])
#define MMCR0 ((UReg_MMCR0&)PowerPC::ppcState.spr[SPR_MMCR0])
#define MMCR1 ((UReg_MMCR1&)PowerPC::ppcState.spr[SPR_MMCR1])
#define THRM1 ((UReg_THRM12&)PowerPC::ppcState.spr[SPR_THRM1])
#define THRM2 ((UReg_THRM12&)PowerPC::ppcState.spr[SPR_THRM2])
#define THRM3 ((UReg_THRM3&)PowerPC::ppcState.spr[SPR_THRM3])
#define PC PowerPC::ppcState.pc
#define NPC PowerPC::ppcState.npc
#define FPSCR PowerPC::ppcState.fpscr
#define MSR PowerPC::ppcState.msr
#define GPR(n) PowerPC::ppcState.gpr[n]

#define rGPR PowerPC::ppcState.gpr
#define rSPR(i) PowerPC::ppcState.spr[i]
#define LR PowerPC::ppcState.spr[SPR_LR]
#define CTR PowerPC::ppcState.spr[SPR_CTR]
#define rDEC PowerPC::ppcState.spr[SPR_DEC]
#define SRR0 PowerPC::ppcState.spr[SPR_SRR0]
#define SRR1 PowerPC::ppcState.spr[SPR_SRR1]
#define SPRG0 PowerPC::ppcState.spr[SPR_SPRG0]
#define SPRG1 PowerPC::ppcState.spr[SPR_SPRG1]
#define SPRG2 PowerPC::ppcState.spr[SPR_SPRG2]
#define SPRG3 PowerPC::ppcState.spr[SPR_SPRG3]
#define GQR(x) PowerPC::ppcState.spr[SPR_GQR0 + (x)]
#define TL PowerPC::ppcState.spr[SPR_TL]
#define TU PowerPC::ppcState.spr[SPR_TU]

#define rPS(i) (PowerPC::ppcState.ps[(i)])

inline void SetCarry(u32 ca)
{
PowerPC::ppcState.xer_ca = ca;
}

inline u32 GetCarry()
{
return PowerPC::ppcState.xer_ca;
}

inline UReg_XER GetXER()
{
u32 xer = 0;
xer |= PowerPC::ppcState.xer_stringctrl;
xer |= PowerPC::ppcState.xer_ca << XER_CA_SHIFT;
xer |= PowerPC::ppcState.xer_so_ov << XER_OV_SHIFT;
return UReg_XER{xer};
}

inline void SetXER(UReg_XER new_xer)
{
PowerPC::ppcState.xer_stringctrl = new_xer.BYTE_COUNT + (new_xer.BYTE_CMP << 8);
PowerPC::ppcState.xer_ca = new_xer.CA;
PowerPC::ppcState.xer_so_ov = (new_xer.SO << 1) + new_xer.OV;
}

inline u32 GetXER_SO()
{
return PowerPC::ppcState.xer_so_ov >> 1;
}

inline void SetXER_SO(bool value)
{
PowerPC::ppcState.xer_so_ov |= static_cast<u32>(value) << 1;
}

inline u32 GetXER_OV()
{
return PowerPC::ppcState.xer_so_ov & 1;
}

inline void SetXER_OV(bool value)
{
PowerPC::ppcState.xer_so_ov = (PowerPC::ppcState.xer_so_ov & 0xFE) | static_cast<u32>(value);
SetXER_SO(value);
}

void UpdateFPRFDouble(double dvalue);
void UpdateFPRFSingle(float fvalue);
#define HID0(ppc_state) ((UReg_HID0&)(ppc_state).spr[SPR_HID0])
#define HID2(ppc_state) ((UReg_HID2&)(ppc_state).spr[SPR_HID2])
#define HID4(ppc_state) ((UReg_HID4&)(ppc_state).spr[SPR_HID4])
#define DMAU(ppc_state) (*(UReg_DMAU*)&(ppc_state).spr[SPR_DMAU])
#define DMAL(ppc_state) (*(UReg_DMAL*)&(ppc_state).spr[SPR_DMAL])
#define MMCR0(ppc_state) ((UReg_MMCR0&)(ppc_state).spr[SPR_MMCR0])
#define MMCR1(ppc_state) ((UReg_MMCR1&)(ppc_state).spr[SPR_MMCR1])
#define THRM1(ppc_state) ((UReg_THRM12&)(ppc_state).spr[SPR_THRM1])
#define THRM2(ppc_state) ((UReg_THRM12&)(ppc_state).spr[SPR_THRM2])
#define THRM3(ppc_state) ((UReg_THRM3&)(ppc_state).spr[SPR_THRM3])

#define LR(ppc_state) (ppc_state).spr[SPR_LR]
#define CTR(ppc_state) (ppc_state).spr[SPR_CTR]
#define SRR0(ppc_state) (ppc_state).spr[SPR_SRR0]
#define SRR1(ppc_state) (ppc_state).spr[SPR_SRR1]
#define GQR(ppc_state, x) (ppc_state).spr[SPR_GQR0 + (x)]
#define TL(ppc_state) (ppc_state).spr[SPR_TL]
#define TU(ppc_state) (ppc_state).spr[SPR_TU]

void RoundingModeUpdated();

@@ -20,6 +20,7 @@
#include "Core/HW/SI/SI.h"
#include "Core/HW/Sram.h"
#include "Core/HW/VideoInterface.h"
#include "Core/PowerPC/PowerPC.h"
#include "IOS/USB/Emulated/Skylander.h"
#include "VideoCommon/CommandProcessor.h"
#include "VideoCommon/Fifo.h"
@@ -32,7 +33,10 @@ namespace Core
{
struct System::Impl
{
explicit Impl(System& system) : m_gp_fifo(system) {}
explicit Impl(System& system)
: m_core_timing(system), m_gp_fifo(system), m_ppc_state(PowerPC::ppcState)
{
}

std::unique_ptr<SoundStream> m_sound_stream;
bool m_sound_stream_running = false;
@@ -53,6 +57,7 @@ struct System::Impl
MemoryInterface::MemoryInterfaceState m_memory_interface_state;
PixelEngine::PixelEngineManager m_pixel_engine;
PixelShaderManager m_pixel_shader_manager;
PowerPC::PowerPCState& m_ppc_state;
ProcessorInterface::ProcessorInterfaceManager m_processor_interface;
SerialInterface::SerialInterfaceState m_serial_interface_state;
Sram m_sram;
@@ -178,6 +183,11 @@ PixelShaderManager& System::GetPixelShaderManager() const
return m_impl->m_pixel_shader_manager;
}

PowerPC::PowerPCState& System::GetPPCState() const
{
return m_impl->m_ppc_state;
}

ProcessorInterface::ProcessorInterfaceManager& System::GetProcessorInterface() const
{
return m_impl->m_processor_interface;
@@ -63,6 +63,10 @@ namespace PixelEngine
{
class PixelEngineManager;
};
namespace PowerPC
{
struct PowerPCState;
}
namespace ProcessorInterface
{
class ProcessorInterfaceManager;
@@ -125,6 +129,7 @@ class System
MemoryInterface::MemoryInterfaceState& GetMemoryInterfaceState() const;
PixelEngine::PixelEngineManager& GetPixelEngine() const;
PixelShaderManager& GetPixelShaderManager() const;
PowerPC::PowerPCState& GetPPCState() const;
ProcessorInterface::ProcessorInterfaceManager& GetProcessorInterface() const;
SerialInterface::SerialInterfaceState& GetSerialInterfaceState() const;
Sram& GetSRAM() const;
@@ -497,10 +497,11 @@ static void ApplyMemoryPatch(u32 offset, const std::vector<u8>& value,
if (!original.empty() && !MemoryMatchesAt(offset, original))
return;

auto& system = Core::System::GetInstance();
const u32 size = static_cast<u32>(value.size());
for (u32 i = 0; i < size; ++i)
PowerPC::HostTryWriteU8(value[i], offset + i);
const u32 overlapping_hook_count = HLE::UnpatchRange(offset, offset + size);
const u32 overlapping_hook_count = HLE::UnpatchRange(system, offset, offset + size);
if (overlapping_hook_count != 0)
{
WARN_LOG_FMT(OSHLE, "Riivolution memory patch overlaps {} HLE hook(s) at {:08x} (size: {})",
@@ -551,6 +552,7 @@ static void ApplyOcarinaMemoryPatch(const Patch& patch, const Memory& memory_pat
if (value.empty())
return;

auto& system = Core::System::GetInstance();
for (u32 i = 0; i < length; i += 4)
{
// first find the pattern
@@ -568,7 +570,8 @@ static void ApplyOcarinaMemoryPatch(const Patch& patch, const Memory& memory_pat
const u32 target = memory_patch.m_offset | 0x80000000;
const u32 jmp = ((target - blr_address) & 0x03fffffc) | 0x48000000;
PowerPC::HostTryWriteU32(jmp, blr_address);
const u32 overlapping_hook_count = HLE::UnpatchRange(blr_address, blr_address + 4);
const u32 overlapping_hook_count =
HLE::UnpatchRange(system, blr_address, blr_address + 4);
if (overlapping_hook_count != 0)
{
WARN_LOG_FMT(OSHLE, "Riivolution ocarina patch overlaps HLE hook at {}", blr_address);
@@ -167,11 +167,11 @@ CodeViewWidget::CodeViewWidget()
&CodeViewWidget::FontBasedSizing);

connect(&Settings::Instance(), &Settings::EmulationStateChanged, this, [this] {
m_address = PC;
m_address = PowerPC::ppcState.pc;
Update();
});
connect(Host::GetInstance(), &Host::UpdateDisasmDialog, this, [this] {
m_address = PC;
m_address = PowerPC::ppcState.pc;
Update();
});

@@ -567,9 +567,9 @@ void CodeViewWidget::OnContextMenu()
menu->addAction(tr("Restore instruction"), this, &CodeViewWidget::OnRestoreInstruction);

QString target;
if (addr == PC && running && Core::GetState() == Core::State::Paused)
if (addr == PowerPC::ppcState.pc && running && Core::GetState() == Core::State::Paused)
{
const std::string line = PowerPC::debug_interface.Disassemble(PC);
const std::string line = PowerPC::debug_interface.Disassemble(PowerPC::ppcState.pc);
const auto target_it = std::find(line.begin(), line.end(), '\t');
const auto target_end = std::find(target_it, line.end(), ',');

@@ -24,6 +24,7 @@
#include "Core/PowerPC/MMU.h"
#include "Core/PowerPC/PPCSymbolDB.h"
#include "Core/PowerPC/PowerPC.h"
#include "Core/System.h"
#include "DolphinQt/Host.h"
#include "DolphinQt/Settings.h"

@@ -328,7 +329,7 @@ void CodeWidget::UpdateCallstack()

std::vector<Dolphin_Debugger::CallstackEntry> stack;

bool success = Dolphin_Debugger::GetCallstack(stack);
bool success = Dolphin_Debugger::GetCallstack(Core::System::GetInstance(), stack);

if (!success)
{
@@ -451,11 +452,11 @@ void CodeWidget::StepOver()
if (!CPU::IsStepping())
return;

UGeckoInstruction inst = PowerPC::HostRead_Instruction(PC);
UGeckoInstruction inst = PowerPC::HostRead_Instruction(PowerPC::ppcState.pc);
if (inst.LK)
{
PowerPC::breakpoints.ClearAllTemporary();
PowerPC::breakpoints.Add(PC + 4, true);
PowerPC::breakpoints.Add(PowerPC::ppcState.pc + 4, true);
CPU::EnableStepping(false);
Core::DisplayMessage(tr("Step over in progress...").toStdString(), 2000);
}
@@ -471,7 +472,8 @@ static bool WillInstructionReturn(UGeckoInstruction inst)
// Is a rfi instruction
if (inst.hex == 0x4C000064u)
return true;
bool counter = (inst.BO_2 >> 2 & 1) != 0 || (CTR != 0) != ((inst.BO_2 >> 1 & 1) != 0);
bool counter =
(inst.BO_2 >> 2 & 1) != 0 || (CTR(PowerPC::ppcState) != 0) != ((inst.BO_2 >> 1 & 1) != 0);
bool condition =
inst.BO_2 >> 4 != 0 || PowerPC::ppcState.cr.GetBit(inst.BI_2) == (inst.BO_2 >> 3 & 1);
bool isBclr = inst.OPCD_7 == 0b010011 && (inst.hex >> 1 & 0b10000) != 0;
@@ -495,7 +497,7 @@ void CodeWidget::StepOut()
// 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
// on a breakpoint, skip it.
UGeckoInstruction inst = PowerPC::HostRead_Instruction(PC);
UGeckoInstruction inst = PowerPC::HostRead_Instruction(PowerPC::ppcState.pc);
do
{
if (WillInstructionReturn(inst))
@@ -507,27 +509,28 @@ void CodeWidget::StepOut()
if (inst.LK)
{
// Step over branches
u32 next_pc = PC + 4;
u32 next_pc = PowerPC::ppcState.pc + 4;
do
{
PowerPC::SingleStep();
} while (PC != next_pc && clock::now() < timeout &&
!PowerPC::breakpoints.IsAddressBreakPoint(PC));
} while (PowerPC::ppcState.pc != next_pc && clock::now() < timeout &&
!PowerPC::breakpoints.IsAddressBreakPoint(PowerPC::ppcState.pc));
}
else
{
PowerPC::SingleStep();
}

inst = PowerPC::HostRead_Instruction(PC);
} while (clock::now() < timeout && !PowerPC::breakpoints.IsAddressBreakPoint(PC));
inst = PowerPC::HostRead_Instruction(PowerPC::ppcState.pc);
} while (clock::now() < timeout &&
!PowerPC::breakpoints.IsAddressBreakPoint(PowerPC::ppcState.pc));

PowerPC::SetMode(old_mode);
CPU::PauseAndLock(false, false);

emit Host::GetInstance()->UpdateDisasmDialog();

if (PowerPC::breakpoints.IsAddressBreakPoint(PC))
if (PowerPC::breakpoints.IsAddressBreakPoint(PowerPC::ppcState.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);
@@ -537,19 +540,19 @@ void CodeWidget::StepOut()

void CodeWidget::Skip()
{
PC += 4;
PowerPC::ppcState.pc += 4;
ShowPC();
}

void CodeWidget::ShowPC()
{
m_code_view->SetAddress(PC, CodeViewWidget::SetAddressUpdate::WithUpdate);
m_code_view->SetAddress(PowerPC::ppcState.pc, CodeViewWidget::SetAddressUpdate::WithUpdate);
Update();
}

void CodeWidget::SetPC()
{
PC = m_code_view->GetAddress();
PowerPC::ppcState.pc = m_code_view->GetAddress();
Update();
}

@@ -314,17 +314,18 @@ void RegisterWidget::PopulateTable()
{
// General purpose registers (int)
AddRegister(
i, 0, RegisterType::gpr, "r" + std::to_string(i), [i] { return GPR(i); },
[i](u64 value) { GPR(i) = value; });
i, 0, RegisterType::gpr, "r" + std::to_string(i), [i] { return PowerPC::ppcState.gpr[i]; },
[i](u64 value) { PowerPC::ppcState.gpr[i] = value; });

// Floating point registers (double)
AddRegister(
i, 2, RegisterType::fpr, "f" + std::to_string(i), [i] { return rPS(i).PS0AsU64(); },
[i](u64 value) { rPS(i).SetPS0(value); });
i, 2, RegisterType::fpr, "f" + std::to_string(i),
[i] { return PowerPC::ppcState.ps[i].PS0AsU64(); },
[i](u64 value) { PowerPC::ppcState.ps[i].SetPS0(value); });

AddRegister(
i, 4, RegisterType::fpr, "", [i] { return rPS(i).PS1AsU64(); },
[i](u64 value) { rPS(i).SetPS1(value); });
i, 4, RegisterType::fpr, "", [i] { return PowerPC::ppcState.ps[i].PS1AsU64(); },
[i](u64 value) { PowerPC::ppcState.ps[i].SetPS1(value); });
}

// The IBAT and DBAT registers have a large gap between
@@ -421,8 +422,8 @@ void RegisterWidget::PopulateTable()

// XER
AddRegister(
21, 5, RegisterType::xer, "XER", [] { return PowerPC::GetXER().Hex; },
[](u64 value) { PowerPC::SetXER(UReg_XER(value)); });
21, 5, RegisterType::xer, "XER", [] { return PowerPC::ppcState.GetXER().Hex; },
[](u64 value) { PowerPC::ppcState.SetXER(UReg_XER(value)); });

// FPSCR
AddRegister(
@@ -1438,7 +1438,7 @@ void MenuBar::LoadSymbolMap()
tr("Loaded symbols from '%1'").arg(existing_map_file_path));
}

HLE::PatchFunctions();
HLE::PatchFunctions(system);
emit NotifySymbolsUpdated();
}

@@ -1462,7 +1462,8 @@ void MenuBar::LoadOtherSymbolMap()
if (!TryLoadMapFile(file))
return;

HLE::PatchFunctions();
auto& system = Core::System::GetInstance();
HLE::PatchFunctions(system);
emit NotifySymbolsUpdated();
}

@@ -1478,7 +1479,8 @@ void MenuBar::LoadBadSymbolMap()
if (!TryLoadMapFile(file, true))
return;

HLE::PatchFunctions();
auto& system = Core::System::GetInstance();
HLE::PatchFunctions(system);
emit NotifySymbolsUpdated();
}

@@ -1597,7 +1599,8 @@ void MenuBar::ApplySignatureFile()
db.Load(load_path);
db.Apply(&g_symbolDB);
db.List();
HLE::PatchFunctions();
auto& system = Core::System::GetInstance();
HLE::PatchFunctions(system);
emit NotifySymbolsUpdated();
}

@@ -1636,7 +1639,8 @@ void MenuBar::CombineSignatureFiles()

void MenuBar::PatchHLEFunctions()
{
HLE::PatchFunctions();
auto& system = Core::System::GetInstance();
HLE::PatchFunctions(system);
}

void MenuBar::ClearCache()
@@ -6,9 +6,6 @@
#include <sstream>

#if defined(HAVE_LLVM)
// PowerPC.h defines PC.
// This conflicts with a function that has an argument named PC
#undef PC
#include <fmt/format.h>
#include <llvm-c/Disassembler.h>
#include <llvm-c/Target.h>
@@ -684,7 +684,8 @@ void CommandProcessorManager::HandleUnknownOpcode(u8 cmd_byte, const u8* buffer,
fifo.bFF_Breakpoint.load(std::memory_order_relaxed) ? "true" : "false",
fifo.bFF_GPLinkEnable.load(std::memory_order_relaxed) ? "true" : "false",
fifo.bFF_HiWatermarkInt.load(std::memory_order_relaxed) ? "true" : "false",
fifo.bFF_LoWatermarkInt.load(std::memory_order_relaxed) ? "true" : "false", PC, LR);
fifo.bFF_LoWatermarkInt.load(std::memory_order_relaxed) ? "true" : "false",
PowerPC::ppcState.pc, LR(PowerPC::ppcState));

if (!m_is_fifo_error_seen && !suppress_panic_alert)
{
@@ -71,15 +71,15 @@ TEST(JitArm64, FPRF)

for (const u64 double_input : double_test_values)
{
const u32 expected_double =
RunUpdateFPRF([&] { PowerPC::UpdateFPRFDouble(Common::BitCast<double>(double_input)); });
const u32 expected_double = RunUpdateFPRF(
[&] { PowerPC::ppcState.UpdateFPRFDouble(Common::BitCast<double>(double_input)); });
const u32 actual_double = RunUpdateFPRF([&] { test.fprf_double(double_input); });
EXPECT_EQ(expected_double, actual_double);

const u32 single_input = ConvertToSingle(double_input);

const u32 expected_single =
RunUpdateFPRF([&] { PowerPC::UpdateFPRFSingle(Common::BitCast<float>(single_input)); });
const u32 expected_single = RunUpdateFPRF(
[&] { PowerPC::ppcState.UpdateFPRFSingle(Common::BitCast<float>(single_input)); });
const u32 actual_single = RunUpdateFPRF([&] { test.fprf_single(single_input); });
EXPECT_EQ(expected_single, actual_single);
}