@@ -168,7 +168,7 @@ static void GenerateDSIException(u32 _EffectiveAddress, bool _bWrite);
template <XCheckTLBFlag flag, typename T, bool never_translate = false>
static T ReadFromHardware(u32 em_address)
{
if (!never_translate && UReg_MSR(MSR).DR)
if (!never_translate && MSR.DR)
{
auto translated_addr = TranslateAddress<flag>(em_address);
if (!translated_addr.Success())
@@ -256,7 +256,7 @@ static T ReadFromHardware(u32 em_address)
template <XCheckTLBFlag flag, typename T, bool never_translate = false>
static void WriteToHardware(u32 em_address, const T data)
{
if (!never_translate && UReg_MSR(MSR).DR)
if (!never_translate && MSR.DR)
{
auto translated_addr = TranslateAddress<flag>(em_address);
if (!translated_addr.Success())
@@ -393,7 +393,7 @@ u32 Read_Opcode(u32 address)
TryReadInstResult TryReadInstruction(u32 address)
{
bool from_bat = true;
if (UReg_MSR(MSR).IR)
if (MSR.IR)
{
auto tlb_addr = TranslateAddress<XCheckTLBFlag::Opcode>(address);
if (!tlb_addr.Success())
@@ -658,7 +658,7 @@ bool IsOptimizableRAMAddress(const u32 address)
if (PowerPC::memchecks.HasAny())
return false;

if (!UReg_MSR(MSR).DR)
if (!MSR.DR)
return false;

// TODO: This API needs to take an access size
@@ -694,14 +694,13 @@ static bool IsRAMAddress(u32 address, bool translate)

bool HostIsRAMAddress(u32 address)
{
return IsRAMAddress<XCheckTLBFlag::NoException>(address, UReg_MSR(MSR).DR);
return IsRAMAddress<XCheckTLBFlag::NoException>(address, MSR.DR);
}

bool HostIsInstructionRAMAddress(u32 address)
{
// Instructions are always 32bit aligned.
return !(address & 3) &&
IsRAMAddress<XCheckTLBFlag::OpcodeNoException>(address, UReg_MSR(MSR).IR);
return !(address & 3) && IsRAMAddress<XCheckTLBFlag::OpcodeNoException>(address, MSR.IR);
}

void DMA_LCToMemory(const u32 memAddr, const u32 cacheAddr, const u32 numBlocks)
@@ -779,7 +778,7 @@ void DMA_MemoryToLC(const u32 cacheAddr, const u32 memAddr, const u32 numBlocks)
void ClearCacheLine(u32 address)
{
DEBUG_ASSERT((address & 0x1F) == 0);
if (UReg_MSR(MSR).DR)
if (MSR.DR)
{
auto translated_address = TranslateAddress<XCheckTLBFlag::Write>(address);
if (translated_address.result == TranslateAddressResult::DIRECT_STORE_SEGMENT)
@@ -809,7 +808,7 @@ u32 IsOptimizableMMIOAccess(u32 address, u32 accessSize)
if (PowerPC::memchecks.HasAny())
return 0;

if (!UReg_MSR(MSR).DR)
if (!MSR.DR)
return 0;

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

if (!UReg_MSR(MSR).DR)
if (!MSR.DR)
return false;

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

TranslateResult JitCache_TranslateAddress(u32 address)
{
if (!UReg_MSR(MSR).IR)
if (!MSR.IR)
return TranslateResult{true, true, address};

// TODO: We shouldn't use FLAG_OPCODE if the caller is the debugger.
@@ -144,7 +144,7 @@ static void ResetRegisters()
SystemTimers::TimeBaseSet();

// MSR should be 0x40, but we don't emulate BS1, so it would never be turned off :}
ppcState.msr = 0;
ppcState.msr.Hex = 0;
rDEC = 0xFFFFFFFF;
SystemTimers::DecrementerSet();
}
@@ -394,15 +394,19 @@ void CheckExceptions()
u32 exceptions = ppcState.Exceptions;

// Example procedure:
// set SRR0 to either PC or NPC
// Set SRR0 to either PC or NPC
// SRR0 = NPC;
// save specified MSR bits
// SRR1 = MSR & 0x87C0FFFF;
// copy ILE bit to LE
// MSR |= (MSR >> 16) & 1;
// clear MSR as specified
// MSR &= ~0x04EF36; // 0x04FF36 also clears ME (only for machine check exception)
// set to exception type entry point
//
// Save specified MSR bits
// SRR1 = MSR.Hex & 0x87C0FFFF;
//
// Copy ILE bit to LE
// MSR.LE |= MSR.ILE;
//
// Clear MSR as specified
// MSR.Hex &= ~0x04EF36; // 0x04FF36 also clears ME (only for machine check exception)
//
// Set to exception type entry point
// NPC = 0x00000x00;

// TODO(delroth): Exception priority is completely wrong here: depending on
@@ -414,9 +418,9 @@ void CheckExceptions()
{
SRR0 = NPC;
// Page fault occurred
SRR1 = (MSR & 0x87C0FFFF) | (1 << 30);
MSR |= (MSR >> 16) & 1;
MSR &= ~0x04EF36;
SRR1 = (MSR.Hex & 0x87C0FFFF) | (1 << 30);
MSR.LE |= MSR.ILE;
MSR.Hex &= ~0x04EF36;
PC = NPC = 0x00000400;

DEBUG_LOG(POWERPC, "EXCEPTION_ISI");
@@ -426,9 +430,9 @@ void CheckExceptions()
{
SRR0 = PC;
// say that it's a trap exception
SRR1 = (MSR & 0x87C0FFFF) | 0x20000;
MSR |= (MSR >> 16) & 1;
MSR &= ~0x04EF36;
SRR1 = (MSR.Hex & 0x87C0FFFF) | 0x20000;
MSR.LE |= MSR.ILE;
MSR.Hex &= ~0x04EF36;
PC = NPC = 0x00000700;

DEBUG_LOG(POWERPC, "EXCEPTION_PROGRAM");
@@ -437,9 +441,9 @@ void CheckExceptions()
else if (exceptions & EXCEPTION_SYSCALL)
{
SRR0 = NPC;
SRR1 = MSR & 0x87C0FFFF;
MSR |= (MSR >> 16) & 1;
MSR &= ~0x04EF36;
SRR1 = MSR.Hex & 0x87C0FFFF;
MSR.LE |= MSR.ILE;
MSR.Hex &= ~0x04EF36;
PC = NPC = 0x00000C00;

DEBUG_LOG(POWERPC, "EXCEPTION_SYSCALL (PC=%08x)", PC);
@@ -449,9 +453,9 @@ void CheckExceptions()
{
// This happens a lot - GameCube OS uses deferred FPU context switching
SRR0 = PC; // re-execute the instruction
SRR1 = MSR & 0x87C0FFFF;
MSR |= (MSR >> 16) & 1;
MSR &= ~0x04EF36;
SRR1 = MSR.Hex & 0x87C0FFFF;
MSR.LE |= MSR.ILE;
MSR.Hex &= ~0x04EF36;
PC = NPC = 0x00000800;

DEBUG_LOG(POWERPC, "EXCEPTION_FPU_UNAVAILABLE");
@@ -464,9 +468,9 @@ void CheckExceptions()
else if (exceptions & EXCEPTION_DSI)
{
SRR0 = PC;
SRR1 = MSR & 0x87C0FFFF;
MSR |= (MSR >> 16) & 1;
MSR &= ~0x04EF36;
SRR1 = MSR.Hex & 0x87C0FFFF;
MSR.LE |= MSR.ILE;
MSR.Hex &= ~0x04EF36;
PC = NPC = 0x00000300;
// DSISR and DAR regs are changed in GenerateDSIException()

@@ -476,9 +480,9 @@ void CheckExceptions()
else if (exceptions & EXCEPTION_ALIGNMENT)
{
SRR0 = PC;
SRR1 = MSR & 0x87C0FFFF;
MSR |= (MSR >> 16) & 1;
MSR &= ~0x04EF36;
SRR1 = MSR.Hex & 0x87C0FFFF;
MSR.LE |= MSR.ILE;
MSR.Hex &= ~0x04EF36;
PC = NPC = 0x00000600;

// TODO crazy amount of DSISR options to check out
@@ -499,15 +503,16 @@ void CheckExternalExceptions()
u32 exceptions = ppcState.Exceptions;

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

DEBUG_LOG(POWERPC, "EXCEPTION_EXTERNAL_INT");
@@ -518,9 +523,9 @@ void CheckExternalExceptions()
else if (exceptions & EXCEPTION_PERFORMANCE_MONITOR)
{
SRR0 = NPC;
SRR1 = MSR & 0x87C0FFFF;
MSR |= (MSR >> 16) & 1;
MSR &= ~0x04EF36;
SRR1 = MSR.Hex & 0x87C0FFFF;
MSR.LE |= MSR.ILE;
MSR.Hex &= ~0x04EF36;
PC = NPC = 0x00000F00;

DEBUG_LOG(POWERPC, "EXCEPTION_PERFORMANCE_MONITOR");
@@ -529,9 +534,9 @@ void CheckExternalExceptions()
else if (exceptions & EXCEPTION_DECREMENTER)
{
SRR0 = NPC;
SRR1 = MSR & 0x87C0FFFF;
MSR |= (MSR >> 16) & 1;
MSR &= ~0x04EF36;
SRR1 = MSR.Hex & 0x87C0FFFF;
MSR.LE |= MSR.ILE;
MSR.Hex &= ~0x04EF36;
PC = NPC = 0x00000900;

DEBUG_LOG(POWERPC, "EXCEPTION_DECREMENTER");
@@ -75,8 +75,8 @@ struct PowerPCState
// be manipulated bit by bit fairly easily.
u64 cr_val[8];

u32 msr; // machine specific register
u32 fpscr; // floating point flags/status bits
UReg_MSR msr; // machine state register
u32 fpscr; // floating point flags/status bits

// Exception management.
u32 Exceptions;
@@ -296,8 +296,8 @@ void RegisterWidget::PopulateTable()
[](u64 value) { PowerPC::ppcState.fpscr = value; });

// MSR
AddRegister(23, 5, RegisterType::msr, "MSR", [] { return PowerPC::ppcState.msr; },
[](u64 value) { PowerPC::ppcState.msr = value; });
AddRegister(23, 5, RegisterType::msr, "MSR", [] { return PowerPC::ppcState.msr.Hex; },
[](u64 value) { PowerPC::ppcState.msr.Hex = value; });

// SRR 0-1
AddRegister(24, 5, RegisterType::srr, "SRR0", [] { return PowerPC::ppcState.spr[SPR_SRR0]; },
@@ -82,7 +82,7 @@ u32 GetSpecialRegValue(int reg)
case 5:
return PowerPC::ppcState.fpscr;
case 6:
return PowerPC::ppcState.msr;
return PowerPC::ppcState.msr.Hex;
case 7:
return PowerPC::ppcState.spr[SPR_SRR0];
case 8:
@@ -127,7 +127,7 @@ void SetSpecialRegValue(int reg, u32 value)
PowerPC::ppcState.fpscr = value;
break;
case 6:
PowerPC::ppcState.msr = value;
PowerPC::ppcState.msr.Hex = value;
break;
case 7:
PowerPC::ppcState.spr[SPR_SRR0] = value;