From d12fa690c0197cebe00681b861927cbe7d6bdedf Mon Sep 17 00:00:00 2001 From: Stenzek Date: Wed, 28 Dec 2022 17:44:34 +1000 Subject: [PATCH] R5900: Remove exceptions --- common/Exceptions.h | 27 ---- pcsx2/CMakeLists.txt | 1 - pcsx2/DebugTools/DebugInterface.cpp | 32 ++--- pcsx2/GSDumpReplayer.cpp | 23 ++-- pcsx2/Interpreter.cpp | 195 +++++++++++++++------------- pcsx2/R5900.cpp | 1 - pcsx2/R5900.h | 15 +-- pcsx2/R5900Exceptions.h | 148 --------------------- pcsx2/R5900OpcodeImpl.cpp | 48 ++++--- pcsx2/pcsx2core.vcxproj | 1 - pcsx2/pcsx2core.vcxproj.filters | 3 - pcsx2/vtlb.cpp | 43 +++--- pcsx2/x86/ix86-32/iR5900-32.cpp | 38 +----- 13 files changed, 188 insertions(+), 387 deletions(-) delete mode 100644 pcsx2/R5900Exceptions.h diff --git a/common/Exceptions.h b/common/Exceptions.h index 34ef3bf4d8..ce86b984a7 100644 --- a/common/Exceptions.h +++ b/common/Exceptions.h @@ -74,33 +74,6 @@ namespace Exception virtual BaseException* Clone() const = 0; }; - // -------------------------------------------------------------------------------------- - // Ps2Generic Exception - // -------------------------------------------------------------------------------------- - // This class is used as a base exception for things tossed by PS2 cpus (EE, IOP, etc). - // - // Implementation note: does not derive from BaseException, so that we can use different - // catch block hierarchies to handle them (if needed). - // - // Translation Note: Currently these exceptions are never translated. English/diagnostic - // format only. :) - // - class Ps2Generic - { - protected: - std::string m_message; // a "detailed" message of what disastrous thing has occurred! - - public: - virtual ~Ps2Generic() = default; - - virtual u32 GetPc() const = 0; - virtual bool IsDelaySlot() const = 0; - virtual std::string& Message() { return m_message; } - - virtual void Rethrow() const = 0; - virtual Ps2Generic* Clone() const = 0; - }; - // Some helper macros for defining the standard constructors of internationalized constructors // Parameters: // classname - Yeah, the name of this class being defined. :) diff --git a/pcsx2/CMakeLists.txt b/pcsx2/CMakeLists.txt index 5e35b48905..47429450dc 100644 --- a/pcsx2/CMakeLists.txt +++ b/pcsx2/CMakeLists.txt @@ -202,7 +202,6 @@ set(pcsx2Headers PerformanceMetrics.h PrecompiledHeader.h R3000A.h - R5900Exceptions.h R5900.h R5900OpcodeTables.h SaveState.h diff --git a/pcsx2/DebugTools/DebugInterface.cpp b/pcsx2/DebugTools/DebugInterface.cpp index 89dd345436..c1e802404d 100644 --- a/pcsx2/DebugTools/DebugInterface.cpp +++ b/pcsx2/DebugTools/DebugInterface.cpp @@ -247,28 +247,24 @@ char* DebugInterface::stringFromPointer(u32 p) if (!isValidAddress(p)) return NULL; - try + // This is going to blow up if it hits a TLB miss.. + // Hopefully the checks in isValidAddress() are sufficient. + for (u32 i = 0; i < BUFFER_LEN; i++) { - for (u32 i = 0; i < BUFFER_LEN; i++) - { - char c = read8(p + i); - buf[i] = c; + char c = read8(p + i); + buf[i] = c; - if (c == 0) - { - return i > 0 ? buf : NULL; - } - else if (c < 0x20 || c >= 0x7f) - { - // non printable character - return NULL; - } + if (c == 0) + { + return i > 0 ? buf : NULL; + } + else if (c < 0x20 || c >= 0x7f) + { + // non printable character + return NULL; } } - catch (Exception::Ps2Generic&) - { - return NULL; - } + buf[BUFFER_LEN - 1] = 0; buf[BUFFER_LEN - 2] = '~'; return buf; diff --git a/pcsx2/GSDumpReplayer.cpp b/pcsx2/GSDumpReplayer.cpp index 75a788a209..f9301d6a99 100644 --- a/pcsx2/GSDumpReplayer.cpp +++ b/pcsx2/GSDumpReplayer.cpp @@ -46,9 +46,8 @@ static void GSDumpReplayerCpuShutdown(); static void GSDumpReplayerCpuReset(); static void GSDumpReplayerCpuStep(); static void GSDumpReplayerCpuExecute(); -static void GSDumpReplayerCpuCheckExecutionState(); -static void GSDumpReplayerCpuThrowException(const BaseException& ex); -static void GSDumpReplayerCpuThrowCpuException(const BaseR5900Exception& ex); +static void GSDumpReplayerExitExecution(); +static void GSDumpReplayerCancelInstruction(); static void GSDumpReplayerCpuClear(u32 addr, u32 size); static std::unique_ptr s_dump_file; @@ -66,9 +65,8 @@ R5900cpu GSDumpReplayerCpu = { GSDumpReplayerCpuReset, GSDumpReplayerCpuStep, GSDumpReplayerCpuExecute, - GSDumpReplayerCpuCheckExecutionState, - GSDumpReplayerCpuThrowException, - GSDumpReplayerCpuThrowCpuException, + GSDumpReplayerExitExecution, + GSDumpReplayerCancelInstruction, GSDumpReplayerCpuClear}; static InterpVU0 gsDumpVU0; @@ -288,7 +286,7 @@ void GSDumpReplayerCpuStep() GSDumpReplayerFrameLimit(); GetMTGS().PostVsyncStart(false); VMManager::Internal::VSyncOnCPUThread(); - GSDumpReplayerCpuCheckExecutionState(); + GSDumpReplayerExitExecution(); } break; @@ -321,17 +319,12 @@ void GSDumpReplayerCpuExecute() } } -void GSDumpReplayerCpuCheckExecutionState() +void GSDumpReplayerExitExecution() { - if (VMManager::Internal::IsExecutionInterrupted()) - s_dump_running = false; + s_dump_running = false; } -void GSDumpReplayerCpuThrowException(const BaseException& ex) -{ -} - -void GSDumpReplayerCpuThrowCpuException(const BaseR5900Exception& ex) +void GSDumpReplayerCancelInstruction() { } diff --git a/pcsx2/Interpreter.cpp b/pcsx2/Interpreter.cpp index 407299837b..97fc009478 100644 --- a/pcsx2/Interpreter.cpp +++ b/pcsx2/Interpreter.cpp @@ -15,16 +15,16 @@ #include "PrecompiledHeader.h" + #include "Common.h" - #include "R5900OpcodeTables.h" -#include "R5900Exceptions.h" #include "VMManager.h" - #include "Elfheader.h" #include "DebugTools/Breakpoints.h" +#include "common/FastJmp.h" + #include using namespace R5900; // for OPCODE and OpcodeImpl @@ -35,6 +35,7 @@ static int branch2 = 0; static u32 cpuBlockCycles = 0; // 3 bit fixed point version of cycle count static std::string disOut; static bool intExitExecution = false; +static fastjmp_buf intJmpBuf; static void intEventTest(); @@ -490,84 +491,10 @@ static void intEventTest() if (intExitExecution) { intExitExecution = false; - throw Exception::ExitCpuExecute(); + fastjmp_jmp(&intJmpBuf, 1); } } -static void intExecute() -{ - bool instruction_was_cancelled; - enum ExecuteState { - RESET, - GAME_LOADING, - GAME_RUNNING - }; - ExecuteState state = RESET; - do { - instruction_was_cancelled = false; - try { - // The execution was splited in three parts so it is easier to - // resume it after a cancelled instruction. - switch (state) { - case RESET: - do - execI(); - while (cpuRegs.pc != (g_eeloadMain ? g_eeloadMain : EELOAD_START)); - if (cpuRegs.pc == EELOAD_START) - { - // The EELOAD _start function is the same across all BIOS versions afaik - u32 mainjump = memRead32(EELOAD_START + 0x9c); - if (mainjump >> 26 == 3) // JAL - g_eeloadMain = ((EELOAD_START + 0xa0) & 0xf0000000U) | (mainjump << 2 & 0x0fffffffU); - } - else if (cpuRegs.pc == g_eeloadMain) - { - eeloadHook(); - if (g_SkipBiosHack) - { - // See comments on this code in iR5900-32.cpp's recRecompile() - u32 typeAexecjump = memRead32(EELOAD_START + 0x470); - u32 typeBexecjump = memRead32(EELOAD_START + 0x5B0); - u32 typeCexecjump = memRead32(EELOAD_START + 0x618); - u32 typeDexecjump = memRead32(EELOAD_START + 0x600); - if ((typeBexecjump >> 26 == 3) || (typeCexecjump >> 26 == 3) || (typeDexecjump >> 26 == 3)) // JAL to 0x822B8 - g_eeloadExec = EELOAD_START + 0x2B8; - else if (typeAexecjump >> 26 == 3) // JAL to 0x82170 - g_eeloadExec = EELOAD_START + 0x170; - else - Console.WriteLn("intExecute: Could not enable launch arguments for fast boot mode; unidentified BIOS version! Please report this to the PCSX2 developers."); - } - } - else if (cpuRegs.pc == g_eeloadExec) - eeloadHook2(); - - if (g_GameLoading) - state = GAME_LOADING; - else - break; - - case GAME_LOADING: - if (ElfEntry != 0xFFFFFFFF) { - do - execI(); - while (cpuRegs.pc != ElfEntry); - eeGameStarting(); - } - state = GAME_RUNNING; - - case GAME_RUNNING: - while (true) - execI(); - } - } - catch( Exception::ExitCpuExecute& ) { } - catch( Exception::CancelInstruction& ) { instruction_was_cancelled = true; } - - // For example a tlb miss will throw an exception. Cpu must be resumed - // to execute the handler - } while (instruction_was_cancelled); -} - static void intSafeExitExecution() { // If we're currently processing events, we can't safely jump out of the interpreter here, because we'll @@ -575,7 +502,101 @@ static void intSafeExitExecution() if (eeEventTestIsActive) intExitExecution = true; else - throw Exception::ExitCpuExecute(); + fastjmp_jmp(&intJmpBuf, 1); +} + +static void intCancelInstruction() +{ + // See execute function. + fastjmp_jmp(&intJmpBuf, 0); +} + +static void intExecute() +{ + enum ExecuteState { + RESET, + GAME_LOADING, + GAME_RUNNING + }; + ExecuteState state = RESET; + + // This will come back as zero the first time it runs, or on instruction cancel. + // It will come back as nonzero when we exit execution. + if (fastjmp_set(&intJmpBuf) != 0) + return; + + // I hope this doesn't cause issues with the optimizer... infinite loop with a constant expression. + for (;;) + { + // The execution was splited in three parts so it is easier to + // resume it after a cancelled instruction. + switch (state) { + case RESET: + { + do + { + execI(); + } while (cpuRegs.pc != (g_eeloadMain ? g_eeloadMain : EELOAD_START)); + + if (cpuRegs.pc == EELOAD_START) + { + // The EELOAD _start function is the same across all BIOS versions afaik + u32 mainjump = memRead32(EELOAD_START + 0x9c); + if (mainjump >> 26 == 3) // JAL + g_eeloadMain = ((EELOAD_START + 0xa0) & 0xf0000000U) | (mainjump << 2 & 0x0fffffffU); + } + else if (cpuRegs.pc == g_eeloadMain) + { + eeloadHook(); + if (g_SkipBiosHack) + { + // See comments on this code in iR5900-32.cpp's recRecompile() + u32 typeAexecjump = memRead32(EELOAD_START + 0x470); + u32 typeBexecjump = memRead32(EELOAD_START + 0x5B0); + u32 typeCexecjump = memRead32(EELOAD_START + 0x618); + u32 typeDexecjump = memRead32(EELOAD_START + 0x600); + if ((typeBexecjump >> 26 == 3) || (typeCexecjump >> 26 == 3) || (typeDexecjump >> 26 == 3)) // JAL to 0x822B8 + g_eeloadExec = EELOAD_START + 0x2B8; + else if (typeAexecjump >> 26 == 3) // JAL to 0x82170 + g_eeloadExec = EELOAD_START + 0x170; + else + Console.WriteLn("intExecute: Could not enable launch arguments for fast boot mode; unidentified BIOS version! Please report this to the PCSX2 developers."); + } + } + else if (cpuRegs.pc == g_eeloadExec) + { + eeloadHook2(); + } + + if (!g_GameLoading) + break; + + state = GAME_LOADING; + [[fallthrough]]; + } + + case GAME_LOADING: + { + if (ElfEntry != 0xFFFFFFFF) + { + do + { + execI(); + } while (cpuRegs.pc != ElfEntry); + eeGameStarting(); + } + state = GAME_RUNNING; + [[fallthrough]]; + } + + case GAME_RUNNING: + { + while (true) + execI(); + } + break; + } + } } static void intStep() @@ -590,18 +611,6 @@ static void intClear(u32 Addr, u32 Size) static void intShutdown() { } -static void intThrowException( const BaseR5900Exception& ex ) -{ - // No tricks needed; C++ stack unwnding should suffice for MSW and GCC alike. - ex.Rethrow(); -} - -static void intThrowException( const BaseException& ex ) -{ - // No tricks needed; C++ stack unwnding should suffice for MSW and GCC alike. - ex.Rethrow(); -} - R5900cpu intCpu = { intReserve, @@ -612,7 +621,7 @@ R5900cpu intCpu = intExecute, intSafeExitExecution, - intThrowException, - intThrowException, + intCancelInstruction, + intClear }; diff --git a/pcsx2/R5900.cpp b/pcsx2/R5900.cpp index 82593cf584..073ca936ba 100644 --- a/pcsx2/R5900.cpp +++ b/pcsx2/R5900.cpp @@ -25,7 +25,6 @@ #include "VUmicro.h" #include "COP0.h" #include "MTVU.h" -#include "R5900Exceptions.h" #include "VMManager.h" #include "Hardware.h" diff --git a/pcsx2/R5900.h b/pcsx2/R5900.h index 3ea516431a..c3ef06db6c 100644 --- a/pcsx2/R5900.h +++ b/pcsx2/R5900.h @@ -353,18 +353,9 @@ struct R5900cpu // currently executing events or not. void (*ExitExecution)(); - // Safely throws host exceptions from executing code (either recompiled or interpreted). - // If this function is called outside the context of the CPU's code execution, then the - // given exception will be re-thrown automatically. - // - // Exception Throws: - // (SEH) Rethrows the given exception immediately. - // (setjmp) Re-throws immediately if called from outside the context of dynamically - // generated code (either non-executing contexts or interpreters). Does not throw - // otherwise. - // - void (*ThrowException)( const BaseException& ex ); - void (*ThrowCpuException)( const BaseR5900Exception& ex ); + // Cancels the currently-executing instruction, returning to the main loop. + // Currently only works for the interpreter. + void (*CancelInstruction)(); // Manual recompiled code cache clear; typically useful to recompilers only. Size is // in MIPS words (32 bits). Dev note: this callback is nearly obsolete, and might be diff --git a/pcsx2/R5900Exceptions.h b/pcsx2/R5900Exceptions.h deleted file mode 100644 index d5048a2f2d..0000000000 --- a/pcsx2/R5900Exceptions.h +++ /dev/null @@ -1,148 +0,0 @@ -/* PCSX2 - PS2 Emulator for PCs - * Copyright (C) 2002-2010 PCSX2 Dev Team - * - * PCSX2 is free software: you can redistribute it and/or modify it under the terms - * of the GNU Lesser General Public License as published by the Free Software Found- - * ation, either version 3 of the License, or (at your option) any later version. - * - * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with PCSX2. - * If not, see . - */ - -#pragma once - -#include "fmt/core.h" - -// -------------------------------------------------------------------------------------- -// BaseR5900Exception -// -------------------------------------------------------------------------------------- -// Abstract base class for R5900 exceptions; contains the cpuRegs instance at the -// time the exception is raised. -// -// Translation note: EE Emulation exceptions are untranslated only. There's really no -// point in providing translations for this hardcore mess. :) -// -class BaseR5900Exception : public Exception::Ps2Generic -{ - DEFINE_EXCEPTION_COPYTORS(BaseR5900Exception, Exception::Ps2Generic) - -public: - cpuRegisters cpuState; - -public: - u32 GetPc() const override { return cpuState.pc; } - bool IsDelaySlot() const override { return !!cpuState.IsDelaySlot; } - - std::string& Message() override { return m_message; } - std::string FormatMessage() const - { - return fmt::format("(EE pc:{:08X}) {}", cpuRegs.pc, m_message.c_str()); - } - -protected: - void Init(const char* msg) - { - m_message = msg; - cpuState = cpuRegs; - } - - void Init(std::string msg) - { - m_message = msg; - cpuState = cpuRegs; - } -}; - -namespace R5900Exception -{ - // -------------------------------------------------------------------------------------- - // BaseAddressError - // -------------------------------------------------------------------------------------- - class BaseAddressError : public BaseR5900Exception - { - DEFINE_EXCEPTION_COPYTORS(BaseAddressError, BaseR5900Exception) - - public: - bool OnWrite; - u32 Address; - - protected: - void Init( u32 ps2addr, bool onWrite, const char* msg ) - { - _parent::Init(fmt::format("{}, addr=0x{:x} [{}]", msg, ps2addr, onWrite ? "store" : "load")); - OnWrite = onWrite; - Address = ps2addr; - } - }; - - - class AddressError : public BaseAddressError - { - public: - AddressError( u32 ps2addr, bool onWrite ) - { - BaseAddressError::Init( ps2addr, onWrite, "Address error" ); - } - }; - - class TLBMiss : public BaseAddressError - { - DEFINE_EXCEPTION_COPYTORS(TLBMiss, BaseAddressError) - - public: - TLBMiss( u32 ps2addr, bool onWrite ) - { - BaseAddressError::Init( ps2addr, onWrite, "TLB Miss" ); - } - }; - - class BusError : public BaseAddressError - { - DEFINE_EXCEPTION_COPYTORS(BusError, BaseAddressError) - - public: - BusError( u32 ps2addr, bool onWrite ) - { - BaseAddressError::Init( ps2addr, onWrite, "Bus Error" ); - } - }; - - class Trap : public BaseR5900Exception - { - DEFINE_EXCEPTION_COPYTORS(Trap, BaseR5900Exception) - - public: - u16 TrapCode; - - public: - // Generates a trap for immediate-style Trap opcodes - Trap() - { - _parent::Init( "Trap" ); - TrapCode = 0; - } - - // Generates a trap for register-style Trap instructions, which contain an - // error code in the opcode - explicit Trap( u16 trapcode ) - { - _parent::Init( "Trap" ), - TrapCode = trapcode; - } - }; - - class DebugBreakpoint : public BaseR5900Exception - { - DEFINE_EXCEPTION_COPYTORS(DebugBreakpoint, BaseR5900Exception) - - public: - explicit DebugBreakpoint() - { - _parent::Init( "Debug Breakpoint" ); - } - }; -} diff --git a/pcsx2/R5900OpcodeImpl.cpp b/pcsx2/R5900OpcodeImpl.cpp index 644e10601e..2c9f087c25 100644 --- a/pcsx2/R5900OpcodeImpl.cpp +++ b/pcsx2/R5900OpcodeImpl.cpp @@ -21,12 +21,15 @@ #include "R5900.h" #include "R5900OpcodeTables.h" -#include "R5900Exceptions.h" #include "GS.h" #include "CDVD/CDVD.h" #include "ps2/BiosTools.h" #include "DebugTools/DebugInterface.h" #include "DebugTools/Breakpoints.h" +#include "Host.h" +#include "VMManager.h" + +#include "fmt/format.h" GS_VideoMode gsVideoMode = GS_VideoMode::Uninitialized; bool gsIsInterlaced = false; @@ -516,6 +519,15 @@ void DSRLV(){ if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = (u64)(cpuRegs.GPR.r // exceptions, since the lower bits of the address are used to determine the portions // of the address/register operations. +[[ noreturn ]] __noinline static void RaiseAddressError(u32 addr, bool store) +{ + const std::string message(fmt::format("Address Error, addr=0x{:x} [{}]", addr, store ? "store" : "load")); + + // TODO: This doesn't actually get raised in the CPU yet. + Console.Error(message); + + Cpu->CancelInstruction(); +} void LB() { @@ -539,8 +551,8 @@ void LH() { u32 addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; - if( addr & 1 ) - throw R5900Exception::AddressError( addr, false ); + if (unlikely(addr & 1)) + RaiseAddressError(addr, false); s16 temp = memRead16(addr); @@ -552,8 +564,8 @@ void LHU() { u32 addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; - if( addr & 1 ) - throw R5900Exception::AddressError( addr, false ); + if (unlikely(addr & 1)) + RaiseAddressError(addr, false); u16 temp = memRead16(addr); @@ -565,8 +577,8 @@ void LW() { u32 addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; - if( addr & 3 ) - throw R5900Exception::AddressError( addr, false ); + if (unlikely(addr & 3)) + RaiseAddressError(addr, false); u32 temp = memRead32(addr); @@ -578,8 +590,8 @@ void LWU() { u32 addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; - if( addr & 3 ) - throw R5900Exception::AddressError( addr, false ); + if (unlikely(addr & 3)) + RaiseAddressError(addr, false); u32 temp = memRead32(addr); @@ -666,8 +678,8 @@ void LD() { s32 addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; - if( addr & 7 ) - throw R5900Exception::AddressError( addr, false ); + if (unlikely(addr & 7)) + RaiseAddressError(addr, false); cpuRegs.GPR.r[_Rt_].UD[0] = memRead64(addr); } @@ -728,8 +740,8 @@ void SH() { u32 addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; - if( addr & 1 ) - throw R5900Exception::AddressError( addr, true ); + if (unlikely(addr & 1)) + RaiseAddressError(addr, true); memWrite16(addr, cpuRegs.GPR.r[_Rt_].US[0]); } @@ -738,10 +750,10 @@ void SW() { u32 addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; - if( addr & 3 ) - throw R5900Exception::AddressError( addr, true ); + if (unlikely(addr & 3)) + RaiseAddressError(addr, true); - memWrite32(addr, cpuRegs.GPR.r[_Rt_].UL[0]); + memWrite32(addr, cpuRegs.GPR.r[_Rt_].UL[0]); } static const u32 SWL_MASK[4] = { 0xffffff00, 0xffff0000, 0xff000000, 0x00000000 }; @@ -795,8 +807,8 @@ void SD() { u32 addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; - if( addr & 7 ) - throw R5900Exception::AddressError( addr, true ); + if (unlikely(addr & 7)) + RaiseAddressError(addr, true); memWrite64(addr,cpuRegs.GPR.r[_Rt_].UD[0]); } diff --git a/pcsx2/pcsx2core.vcxproj b/pcsx2/pcsx2core.vcxproj index ea87ed9eba..e2dd136743 100644 --- a/pcsx2/pcsx2core.vcxproj +++ b/pcsx2/pcsx2core.vcxproj @@ -744,7 +744,6 @@ - diff --git a/pcsx2/pcsx2core.vcxproj.filters b/pcsx2/pcsx2core.vcxproj.filters index 24d2729e04..2128590ee1 100644 --- a/pcsx2/pcsx2core.vcxproj.filters +++ b/pcsx2/pcsx2core.vcxproj.filters @@ -1504,9 +1504,6 @@ System\Ps2\EmotionEngine\EE - - System\Ps2\EmotionEngine\EE - System\Ps2\EmotionEngine\EE diff --git a/pcsx2/vtlb.cpp b/pcsx2/vtlb.cpp index f0432fe873..21ebdef61c 100644 --- a/pcsx2/vtlb.cpp +++ b/pcsx2/vtlb.cpp @@ -34,9 +34,9 @@ #include "vtlb.h" #include "COP0.h" #include "Cache.h" -#include "R5900Exceptions.h" #include "IopMem.h" #include "Host.h" +#include "VMManager.h" #include "common/Align.h" #include "common/MemsetFast.inl" @@ -462,17 +462,23 @@ static __ri void vtlb_Miss(u32 addr, u32 mode) cpuTlbMissR(addr, cpuRegs.branch); // Exception handled. Current instruction need to be stopped - throw Exception::CancelInstruction(); + Cpu->CancelInstruction(); + return; } - if (IsDevBuild) - Cpu->ThrowCpuException(R5900Exception::TLBMiss(addr, !!mode)); - else + const std::string message(fmt::format("TLB Miss, addr=0x{:x} [{}]", addr, mode ? "store" : "load")); + if constexpr (IsDevBuild) { - static int spamStop = 0; - if (spamStop++ < 50) - Console.Error(R5900Exception::TLBMiss(addr, !!mode).FormatMessage()); + // Pause, let the user try to figure out what went wrong in the debugger. + Host::ReportErrorAsync("R5900 Exception", message); + VMManager::SetPaused(true); + Cpu->ExitExecution(); + return; } + + static int spamStop = 0; + if (spamStop++ < 50) + Console.Error(message); } // BusError exception: more serious than a TLB miss. If properly emulated the PS2 kernel @@ -480,16 +486,17 @@ static __ri void vtlb_Miss(u32 addr, u32 mode) // time of the exception. static __ri void vtlb_BusError(u32 addr, u32 mode) { - // The exception terminate the program on linux which is very annoying - // Just disable it for the moment -#ifdef __linux__ - if (0) -#else - if (IsDevBuild) -#endif - Cpu->ThrowCpuException(R5900Exception::BusError(addr, !!mode)); - else - Console.Error(R5900Exception::TLBMiss(addr, !!mode).FormatMessage()); + const std::string message(fmt::format("Bus Error, addr=0x{:x} [{}]", addr, mode ? "store" : "load")); + if constexpr (IsDevBuild) + { + // Pause, let the user try to figure out what went wrong in the debugger. + Host::ReportErrorAsync("R5900 Exception", message); + VMManager::SetPaused(true); + Cpu->ExitExecution(); + return; + } + + Console.Error(message); } // clang-format off diff --git a/pcsx2/x86/ix86-32/iR5900-32.cpp b/pcsx2/x86/ix86-32/iR5900-32.cpp index b1b1b684b7..229ee493d1 100644 --- a/pcsx2/x86/ix86-32/iR5900-32.cpp +++ b/pcsx2/x86/ix86-32/iR5900-32.cpp @@ -19,7 +19,6 @@ #include "Memory.h" #include "R3000A.h" -#include "R5900Exceptions.h" #include "R5900OpcodeTables.h" #include "iR5900.h" #include "iR5900Analysis.h" @@ -685,8 +684,6 @@ void recStep() } static fastjmp_buf m_SetJmp_StateCheck; -static std::unique_ptr m_cpuException; -static std::unique_ptr m_Exception; static void recExitExecution() { @@ -708,6 +705,11 @@ static void recSafeExitExecution() recExitExecution(); } +static void recCancelInstruction() +{ + pxFailRel("recCancelInstruction() called, this should never happen!"); +} + static void recExecute() { // Reset before we try to execute any code, if there's one pending. @@ -717,9 +719,6 @@ static void recExecute() if (eeRecNeedsReset) recResetRaw(); - m_cpuException = nullptr; - m_Exception = nullptr; - // setjmp will save the register context and will return 0 // A call to longjmp will restore the context (included the eip/rip) // but will return the longjmp 2nd parameter (here 1) @@ -739,11 +738,6 @@ static void recExecute() eeCpuExecuting = false; - if (m_cpuException) - m_cpuException->Rethrow(); - if (m_Exception) - m_Exception->Rethrow(); - // FIXME Warning thread unsafe Perf::dump(); @@ -2688,25 +2682,6 @@ StartRecomp: s_pCurBlockEx = NULL; } -// The only *safe* way to throw exceptions from the context of recompiled code. -// The exception is cached and the recompiler is exited safely using either an -// SEH unwind (MSW) or setjmp/longjmp (GCC). -static void recThrowException(const BaseR5900Exception& ex) -{ - if (!eeCpuExecuting) - ex.Rethrow(); - m_cpuException = std::unique_ptr(ex.Clone()); - recExitExecution(); -} - -static void recThrowException(const BaseException& ex) -{ - if (!eeCpuExecuting) - ex.Rethrow(); - m_Exception = std::unique_ptr(ex.Clone()); - recExitExecution(); -} - R5900cpu recCpu = { recReserve, recShutdown, @@ -2716,6 +2691,5 @@ R5900cpu recCpu = { recExecute, recSafeExitExecution, - recThrowException, - recThrowException, + recCancelInstruction, recClear};