PowerPC: Set SRR1 correctly for program exceptions

This commit is contained in:
JosJuice 2021-08-16 17:22:12 +02:00
parent 4541abd1c0
commit 83c6df1965
10 changed files with 40 additions and 23 deletions

View File

@ -7,6 +7,14 @@
#include "Core/PowerPC/Gekko.h" #include "Core/PowerPC/Gekko.h"
#include "Core/PowerPC/PowerPC.h" #include "Core/PowerPC/PowerPC.h"
enum class ProgramExceptionCause : u32
{
FloatingPoint = 1 << (31 - 11),
IllegalInstruction = 1 << (31 - 12),
PrivilegedInstruction = 1 << (31 - 13),
Trap = 1 << (31 - 14),
};
inline void GenerateAlignmentException(u32 address) inline void GenerateAlignmentException(u32 address)
{ {
PowerPC::ppcState.Exceptions |= EXCEPTION_ALIGNMENT; PowerPC::ppcState.Exceptions |= EXCEPTION_ALIGNMENT;
@ -19,7 +27,8 @@ inline void GenerateDSIException(u32 address)
PowerPC::ppcState.spr[SPR_DAR] = address; PowerPC::ppcState.spr[SPR_DAR] = address;
} }
inline void GenerateProgramException() inline void GenerateProgramException(ProgramExceptionCause cause)
{ {
PowerPC::ppcState.Exceptions |= EXCEPTION_PROGRAM; PowerPC::ppcState.Exceptions |= EXCEPTION_PROGRAM;
PowerPC::ppcState.spr[SPR_SRR1] = static_cast<u32>(cause);
} }

View File

@ -180,7 +180,7 @@ int Interpreter::SingleStepInner()
{ {
if (IsInvalidPairedSingleExecution(m_prev_inst)) if (IsInvalidPairedSingleExecution(m_prev_inst))
{ {
GenerateProgramException(); GenerateProgramException(ProgramExceptionCause::IllegalInstruction);
CheckExceptions(); CheckExceptions();
} }
else if (MSR.FP) else if (MSR.FP)

View File

@ -101,7 +101,7 @@ void Interpreter::rfi(UGeckoInstruction inst)
{ {
if (MSR.PR) if (MSR.PR)
{ {
GenerateProgramException(); GenerateProgramException(ProgramExceptionCause::PrivilegedInstruction);
return; return;
} }

View File

@ -6,6 +6,7 @@
#include "Common/BitUtils.h" #include "Common/BitUtils.h"
#include "Common/CommonTypes.h" #include "Common/CommonTypes.h"
#include "Common/Logging/Log.h" #include "Common/Logging/Log.h"
#include "Core/PowerPC/Interpreter/ExceptionUtils.h"
#include "Core/PowerPC/PowerPC.h" #include "Core/PowerPC/PowerPC.h"
void Interpreter::Helper_UpdateCR0(u32 value) void Interpreter::Helper_UpdateCR0(u32 value)
@ -131,7 +132,7 @@ void Interpreter::twi(UGeckoInstruction inst)
if ((a < b && (TO & 0x10) != 0) || (a > b && (TO & 0x08) != 0) || (a == b && (TO & 0x04) != 0) || if ((a < b && (TO & 0x10) != 0) || (a > b && (TO & 0x08) != 0) || (a == b && (TO & 0x04) != 0) ||
(u32(a) < u32(b) && (TO & 0x02) != 0) || (u32(a) > u32(b) && (TO & 0x01) != 0)) (u32(a) < u32(b) && (TO & 0x02) != 0) || (u32(a) > u32(b) && (TO & 0x01) != 0))
{ {
PowerPC::ppcState.Exceptions |= EXCEPTION_PROGRAM; GenerateProgramException(ProgramExceptionCause::Trap);
PowerPC::CheckExceptions(); PowerPC::CheckExceptions();
m_end_block = true; // Dunno about this m_end_block = true; // Dunno about this
} }
@ -339,7 +340,7 @@ void Interpreter::tw(UGeckoInstruction inst)
if ((a < b && (TO & 0x10) != 0) || (a > b && (TO & 0x08) != 0) || (a == b && (TO & 0x04) != 0) || if ((a < b && (TO & 0x10) != 0) || (a > b && (TO & 0x08) != 0) || (a == b && (TO & 0x04) != 0) ||
((u32(a) < u32(b)) && (TO & 0x02) != 0) || ((u32(a) > u32(b)) && (TO & 0x01) != 0)) ((u32(a) < u32(b)) && (TO & 0x02) != 0) || ((u32(a) > u32(b)) && (TO & 0x01) != 0))
{ {
PowerPC::ppcState.Exceptions |= EXCEPTION_PROGRAM; GenerateProgramException(ProgramExceptionCause::Trap);
PowerPC::CheckExceptions(); PowerPC::CheckExceptions();
m_end_block = true; // Dunno about this m_end_block = true; // Dunno about this
} }

View File

@ -450,7 +450,7 @@ void Interpreter::dcbi(UGeckoInstruction inst)
{ {
if (MSR.PR) if (MSR.PR)
{ {
GenerateProgramException(); GenerateProgramException(ProgramExceptionCause::PrivilegedInstruction);
return; return;
} }
@ -514,7 +514,7 @@ void Interpreter::dcbz_l(UGeckoInstruction inst)
{ {
if (!HID2.LCE) if (!HID2.LCE)
{ {
GenerateProgramException(); GenerateProgramException(ProgramExceptionCause::IllegalInstruction);
return; return;
} }
@ -1041,7 +1041,7 @@ void Interpreter::tlbie(UGeckoInstruction inst)
{ {
if (MSR.PR) if (MSR.PR)
{ {
GenerateProgramException(); GenerateProgramException(ProgramExceptionCause::PrivilegedInstruction);
return; return;
} }
@ -1055,7 +1055,7 @@ void Interpreter::tlbsync(UGeckoInstruction inst)
{ {
if (MSR.PR) if (MSR.PR)
{ {
GenerateProgramException(); GenerateProgramException(ProgramExceptionCause::PrivilegedInstruction);
} }
// Ignored // Ignored

View File

@ -311,7 +311,7 @@ void Interpreter::psq_l(UGeckoInstruction inst)
{ {
if (HID2.LSQE == 0) if (HID2.LSQE == 0)
{ {
GenerateProgramException(); GenerateProgramException(ProgramExceptionCause::IllegalInstruction);
return; return;
} }
@ -323,7 +323,7 @@ void Interpreter::psq_lu(UGeckoInstruction inst)
{ {
if (HID2.LSQE == 0) if (HID2.LSQE == 0)
{ {
GenerateProgramException(); GenerateProgramException(ProgramExceptionCause::IllegalInstruction);
return; return;
} }
@ -342,7 +342,7 @@ void Interpreter::psq_st(UGeckoInstruction inst)
{ {
if (HID2.LSQE == 0) if (HID2.LSQE == 0)
{ {
GenerateProgramException(); GenerateProgramException(ProgramExceptionCause::IllegalInstruction);
return; return;
} }
@ -354,7 +354,7 @@ void Interpreter::psq_stu(UGeckoInstruction inst)
{ {
if (HID2.LSQE == 0) if (HID2.LSQE == 0)
{ {
GenerateProgramException(); GenerateProgramException(ProgramExceptionCause::IllegalInstruction);
return; return;
} }

View File

@ -141,7 +141,7 @@ void Interpreter::mfmsr(UGeckoInstruction inst)
{ {
if (MSR.PR) if (MSR.PR)
{ {
GenerateProgramException(); GenerateProgramException(ProgramExceptionCause::PrivilegedInstruction);
return; return;
} }
@ -152,7 +152,7 @@ void Interpreter::mfsr(UGeckoInstruction inst)
{ {
if (MSR.PR) if (MSR.PR)
{ {
GenerateProgramException(); GenerateProgramException(ProgramExceptionCause::PrivilegedInstruction);
return; return;
} }
@ -163,7 +163,7 @@ void Interpreter::mfsrin(UGeckoInstruction inst)
{ {
if (MSR.PR) if (MSR.PR)
{ {
GenerateProgramException(); GenerateProgramException(ProgramExceptionCause::PrivilegedInstruction);
return; return;
} }
@ -175,7 +175,7 @@ void Interpreter::mtmsr(UGeckoInstruction inst)
{ {
if (MSR.PR) if (MSR.PR)
{ {
GenerateProgramException(); GenerateProgramException(ProgramExceptionCause::PrivilegedInstruction);
return; return;
} }
@ -190,7 +190,7 @@ void Interpreter::mtsr(UGeckoInstruction inst)
{ {
if (MSR.PR) if (MSR.PR)
{ {
GenerateProgramException(); GenerateProgramException(ProgramExceptionCause::PrivilegedInstruction);
return; return;
} }
@ -203,7 +203,7 @@ void Interpreter::mtsrin(UGeckoInstruction inst)
{ {
if (MSR.PR) if (MSR.PR)
{ {
GenerateProgramException(); GenerateProgramException(ProgramExceptionCause::PrivilegedInstruction);
return; return;
} }
@ -227,7 +227,7 @@ void Interpreter::mfspr(UGeckoInstruction inst)
if (MSR.PR && index != SPR_XER && index != SPR_LR && index != SPR_CTR && index != SPR_TL && if (MSR.PR && index != SPR_XER && index != SPR_LR && index != SPR_CTR && index != SPR_TL &&
index != SPR_TU) index != SPR_TU)
{ {
GenerateProgramException(); GenerateProgramException(ProgramExceptionCause::PrivilegedInstruction);
return; return;
} }
@ -270,7 +270,7 @@ void Interpreter::mtspr(UGeckoInstruction inst)
// XER, LR, and CTR are the only ones available to be written to in user mode // XER, LR, and CTR are the only ones available to be written to in user mode
if (MSR.PR && index != SPR_XER && index != SPR_LR && index != SPR_CTR) if (MSR.PR && index != SPR_XER && index != SPR_LR && index != SPR_CTR)
{ {
GenerateProgramException(); GenerateProgramException(ProgramExceptionCause::PrivilegedInstruction);
return; return;
} }

View File

@ -11,7 +11,9 @@
#include "Common/CommonTypes.h" #include "Common/CommonTypes.h"
#include "Common/MathUtil.h" #include "Common/MathUtil.h"
#include "Common/x64Emitter.h" #include "Common/x64Emitter.h"
#include "Core/CoreTiming.h" #include "Core/CoreTiming.h"
#include "Core/PowerPC/Interpreter/ExceptionUtils.h"
#include "Core/PowerPC/Jit64/Jit.h" #include "Core/PowerPC/Jit64/Jit.h"
#include "Core/PowerPC/Jit64/RegCache/JitRegCache.h" #include "Core/PowerPC/Jit64/RegCache/JitRegCache.h"
#include "Core/PowerPC/Jit64Common/Jit64PowerPCState.h" #include "Core/PowerPC/Jit64Common/Jit64PowerPCState.h"
@ -2562,6 +2564,7 @@ void Jit64::twX(UGeckoInstruction inst)
} }
LOCK(); LOCK();
OR(32, PPCSTATE(Exceptions), Imm32(EXCEPTION_PROGRAM)); OR(32, PPCSTATE(Exceptions), Imm32(EXCEPTION_PROGRAM));
MOV(32, PPCSTATE_SRR1, Imm32(static_cast<u32>(ProgramExceptionCause::Trap)));
gpr.Flush(); gpr.Flush();
fpr.Flush(); fpr.Flush();

View File

@ -7,6 +7,7 @@
#include "Core/Core.h" #include "Core/Core.h"
#include "Core/CoreTiming.h" #include "Core/CoreTiming.h"
#include "Core/PowerPC/Interpreter/ExceptionUtils.h"
#include "Core/PowerPC/JitArm64/Jit.h" #include "Core/PowerPC/JitArm64/Jit.h"
#include "Core/PowerPC/PPCTables.h" #include "Core/PowerPC/PPCTables.h"
#include "Core/PowerPC/PowerPC.h" #include "Core/PowerPC/PowerPC.h"
@ -233,6 +234,9 @@ void JitArm64::twx(UGeckoInstruction inst)
ORR(WA, WA, LogicalImm(EXCEPTION_PROGRAM, 32)); ORR(WA, WA, LogicalImm(EXCEPTION_PROGRAM, 32));
STR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(Exceptions)); STR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(Exceptions));
MOVI2R(WA, static_cast<u32>(ProgramExceptionCause::Trap));
STR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF_SPR(SPR_SRR1));
WriteExceptionExit(js.compilerPC, false, true); WriteExceptionExit(js.compilerPC, false, true);
SwitchToNearCode(); SwitchToNearCode();

View File

@ -483,8 +483,8 @@ void CheckExceptions()
else if (exceptions & EXCEPTION_PROGRAM) else if (exceptions & EXCEPTION_PROGRAM)
{ {
SRR0 = PC; SRR0 = PC;
// say that it's a trap exception // SRR1 was partially set by GenerateProgramException, so bitwise or is used here
SRR1 = (MSR.Hex & 0x87C0FFFF) | 0x20000; SRR1 |= MSR.Hex & 0x87C0FFFF;
MSR.LE = MSR.ILE; MSR.LE = MSR.ILE;
MSR.Hex &= ~0x04EF36; MSR.Hex &= ~0x04EF36;
PC = NPC = 0x00000700; PC = NPC = 0x00000700;