diff --git a/Source/Core/Core/PowerPC/Interpreter/ExceptionUtils.h b/Source/Core/Core/PowerPC/Interpreter/ExceptionUtils.h index 9ad4e04cdc..123cffdcaa 100644 --- a/Source/Core/Core/PowerPC/Interpreter/ExceptionUtils.h +++ b/Source/Core/Core/PowerPC/Interpreter/ExceptionUtils.h @@ -7,6 +7,14 @@ #include "Core/PowerPC/Gekko.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) { PowerPC::ppcState.Exceptions |= EXCEPTION_ALIGNMENT; @@ -19,7 +27,8 @@ inline void GenerateDSIException(u32 address) PowerPC::ppcState.spr[SPR_DAR] = address; } -inline void GenerateProgramException() +inline void GenerateProgramException(ProgramExceptionCause cause) { PowerPC::ppcState.Exceptions |= EXCEPTION_PROGRAM; + PowerPC::ppcState.spr[SPR_SRR1] = static_cast(cause); } diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter.cpp b/Source/Core/Core/PowerPC/Interpreter/Interpreter.cpp index 9d110ffddd..c8944b73cf 100644 --- a/Source/Core/Core/PowerPC/Interpreter/Interpreter.cpp +++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter.cpp @@ -180,7 +180,7 @@ int Interpreter::SingleStepInner() { if (IsInvalidPairedSingleExecution(m_prev_inst)) { - GenerateProgramException(); + GenerateProgramException(ProgramExceptionCause::IllegalInstruction); CheckExceptions(); } else if (MSR.FP) diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter_Branch.cpp b/Source/Core/Core/PowerPC/Interpreter/Interpreter_Branch.cpp index 27877673fe..54fe1ae73e 100644 --- a/Source/Core/Core/PowerPC/Interpreter/Interpreter_Branch.cpp +++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter_Branch.cpp @@ -101,7 +101,7 @@ void Interpreter::rfi(UGeckoInstruction inst) { if (MSR.PR) { - GenerateProgramException(); + GenerateProgramException(ProgramExceptionCause::PrivilegedInstruction); return; } diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter_Integer.cpp b/Source/Core/Core/PowerPC/Interpreter/Interpreter_Integer.cpp index effce996f7..b10f55ab79 100644 --- a/Source/Core/Core/PowerPC/Interpreter/Interpreter_Integer.cpp +++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter_Integer.cpp @@ -6,6 +6,7 @@ #include "Common/BitUtils.h" #include "Common/CommonTypes.h" #include "Common/Logging/Log.h" +#include "Core/PowerPC/Interpreter/ExceptionUtils.h" #include "Core/PowerPC/PowerPC.h" 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) || (u32(a) < u32(b) && (TO & 0x02) != 0) || (u32(a) > u32(b) && (TO & 0x01) != 0)) { - PowerPC::ppcState.Exceptions |= EXCEPTION_PROGRAM; + GenerateProgramException(ProgramExceptionCause::Trap); PowerPC::CheckExceptions(); 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) || ((u32(a) < u32(b)) && (TO & 0x02) != 0) || ((u32(a) > u32(b)) && (TO & 0x01) != 0)) { - PowerPC::ppcState.Exceptions |= EXCEPTION_PROGRAM; + GenerateProgramException(ProgramExceptionCause::Trap); PowerPC::CheckExceptions(); m_end_block = true; // Dunno about this } diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter_LoadStore.cpp b/Source/Core/Core/PowerPC/Interpreter/Interpreter_LoadStore.cpp index 74b9173a31..9989024bb1 100644 --- a/Source/Core/Core/PowerPC/Interpreter/Interpreter_LoadStore.cpp +++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter_LoadStore.cpp @@ -450,7 +450,7 @@ void Interpreter::dcbi(UGeckoInstruction inst) { if (MSR.PR) { - GenerateProgramException(); + GenerateProgramException(ProgramExceptionCause::PrivilegedInstruction); return; } @@ -514,7 +514,7 @@ void Interpreter::dcbz_l(UGeckoInstruction inst) { if (!HID2.LCE) { - GenerateProgramException(); + GenerateProgramException(ProgramExceptionCause::IllegalInstruction); return; } @@ -1041,7 +1041,7 @@ void Interpreter::tlbie(UGeckoInstruction inst) { if (MSR.PR) { - GenerateProgramException(); + GenerateProgramException(ProgramExceptionCause::PrivilegedInstruction); return; } @@ -1055,7 +1055,7 @@ void Interpreter::tlbsync(UGeckoInstruction inst) { if (MSR.PR) { - GenerateProgramException(); + GenerateProgramException(ProgramExceptionCause::PrivilegedInstruction); } // Ignored diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter_LoadStorePaired.cpp b/Source/Core/Core/PowerPC/Interpreter/Interpreter_LoadStorePaired.cpp index 9384985a30..a09bbc7770 100644 --- a/Source/Core/Core/PowerPC/Interpreter/Interpreter_LoadStorePaired.cpp +++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter_LoadStorePaired.cpp @@ -311,7 +311,7 @@ void Interpreter::psq_l(UGeckoInstruction inst) { if (HID2.LSQE == 0) { - GenerateProgramException(); + GenerateProgramException(ProgramExceptionCause::IllegalInstruction); return; } @@ -323,7 +323,7 @@ void Interpreter::psq_lu(UGeckoInstruction inst) { if (HID2.LSQE == 0) { - GenerateProgramException(); + GenerateProgramException(ProgramExceptionCause::IllegalInstruction); return; } @@ -342,7 +342,7 @@ void Interpreter::psq_st(UGeckoInstruction inst) { if (HID2.LSQE == 0) { - GenerateProgramException(); + GenerateProgramException(ProgramExceptionCause::IllegalInstruction); return; } @@ -354,7 +354,7 @@ void Interpreter::psq_stu(UGeckoInstruction inst) { if (HID2.LSQE == 0) { - GenerateProgramException(); + GenerateProgramException(ProgramExceptionCause::IllegalInstruction); return; } diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter_SystemRegisters.cpp b/Source/Core/Core/PowerPC/Interpreter/Interpreter_SystemRegisters.cpp index 81fb4e5346..7917eba188 100644 --- a/Source/Core/Core/PowerPC/Interpreter/Interpreter_SystemRegisters.cpp +++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter_SystemRegisters.cpp @@ -141,7 +141,7 @@ void Interpreter::mfmsr(UGeckoInstruction inst) { if (MSR.PR) { - GenerateProgramException(); + GenerateProgramException(ProgramExceptionCause::PrivilegedInstruction); return; } @@ -152,7 +152,7 @@ void Interpreter::mfsr(UGeckoInstruction inst) { if (MSR.PR) { - GenerateProgramException(); + GenerateProgramException(ProgramExceptionCause::PrivilegedInstruction); return; } @@ -163,7 +163,7 @@ void Interpreter::mfsrin(UGeckoInstruction inst) { if (MSR.PR) { - GenerateProgramException(); + GenerateProgramException(ProgramExceptionCause::PrivilegedInstruction); return; } @@ -175,7 +175,7 @@ void Interpreter::mtmsr(UGeckoInstruction inst) { if (MSR.PR) { - GenerateProgramException(); + GenerateProgramException(ProgramExceptionCause::PrivilegedInstruction); return; } @@ -190,7 +190,7 @@ void Interpreter::mtsr(UGeckoInstruction inst) { if (MSR.PR) { - GenerateProgramException(); + GenerateProgramException(ProgramExceptionCause::PrivilegedInstruction); return; } @@ -203,7 +203,7 @@ void Interpreter::mtsrin(UGeckoInstruction inst) { if (MSR.PR) { - GenerateProgramException(); + GenerateProgramException(ProgramExceptionCause::PrivilegedInstruction); 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 && index != SPR_TU) { - GenerateProgramException(); + GenerateProgramException(ProgramExceptionCause::PrivilegedInstruction); 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 if (MSR.PR && index != SPR_XER && index != SPR_LR && index != SPR_CTR) { - GenerateProgramException(); + GenerateProgramException(ProgramExceptionCause::PrivilegedInstruction); return; } diff --git a/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp b/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp index be61b048cf..7cc7723b76 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp @@ -11,7 +11,9 @@ #include "Common/CommonTypes.h" #include "Common/MathUtil.h" #include "Common/x64Emitter.h" + #include "Core/CoreTiming.h" +#include "Core/PowerPC/Interpreter/ExceptionUtils.h" #include "Core/PowerPC/Jit64/Jit.h" #include "Core/PowerPC/Jit64/RegCache/JitRegCache.h" #include "Core/PowerPC/Jit64Common/Jit64PowerPCState.h" @@ -2562,6 +2564,7 @@ void Jit64::twX(UGeckoInstruction inst) } LOCK(); OR(32, PPCSTATE(Exceptions), Imm32(EXCEPTION_PROGRAM)); + MOV(32, PPCSTATE_SRR1, Imm32(static_cast(ProgramExceptionCause::Trap))); gpr.Flush(); fpr.Flush(); diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64_SystemRegisters.cpp b/Source/Core/Core/PowerPC/JitArm64/JitArm64_SystemRegisters.cpp index 47283eb10d..d3de831872 100644 --- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_SystemRegisters.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_SystemRegisters.cpp @@ -7,6 +7,7 @@ #include "Core/Core.h" #include "Core/CoreTiming.h" +#include "Core/PowerPC/Interpreter/ExceptionUtils.h" #include "Core/PowerPC/JitArm64/Jit.h" #include "Core/PowerPC/PPCTables.h" #include "Core/PowerPC/PowerPC.h" @@ -233,6 +234,9 @@ void JitArm64::twx(UGeckoInstruction inst) ORR(WA, WA, LogicalImm(EXCEPTION_PROGRAM, 32)); STR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(Exceptions)); + MOVI2R(WA, static_cast(ProgramExceptionCause::Trap)); + STR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF_SPR(SPR_SRR1)); + WriteExceptionExit(js.compilerPC, false, true); SwitchToNearCode(); diff --git a/Source/Core/Core/PowerPC/PowerPC.cpp b/Source/Core/Core/PowerPC/PowerPC.cpp index f838911927..0e4b641200 100644 --- a/Source/Core/Core/PowerPC/PowerPC.cpp +++ b/Source/Core/Core/PowerPC/PowerPC.cpp @@ -483,8 +483,8 @@ void CheckExceptions() else if (exceptions & EXCEPTION_PROGRAM) { SRR0 = PC; - // say that it's a trap exception - SRR1 = (MSR.Hex & 0x87C0FFFF) | 0x20000; + // 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;