R5900: Remove exceptions

This commit is contained in:
Stenzek 2022-12-28 17:44:34 +10:00 committed by refractionpcsx2
parent 94226e83ba
commit d12fa690c0
13 changed files with 188 additions and 387 deletions

View File

@ -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. :)

View File

@ -202,7 +202,6 @@ set(pcsx2Headers
PerformanceMetrics.h
PrecompiledHeader.h
R3000A.h
R5900Exceptions.h
R5900.h
R5900OpcodeTables.h
SaveState.h

View File

@ -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;

View File

@ -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<GSDumpFile> 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()
{
}

View File

@ -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 <float.h>
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
};

View File

@ -25,7 +25,6 @@
#include "VUmicro.h"
#include "COP0.h"
#include "MTVU.h"
#include "R5900Exceptions.h"
#include "VMManager.h"
#include "Hardware.h"

View File

@ -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

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#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" );
}
};
}

View File

@ -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]);
}

View File

@ -744,7 +744,6 @@
<ClInclude Include="SPR.h" />
<ClInclude Include="Gif.h" />
<ClInclude Include="R5900.h" />
<ClInclude Include="R5900Exceptions.h" />
<ClInclude Include="R5900OpcodeTables.h" />
<ClInclude Include="COP0.h" />
<ClInclude Include="x86\iCOP0.h" />

View File

@ -1504,9 +1504,6 @@
<ClInclude Include="R5900.h">
<Filter>System\Ps2\EmotionEngine\EE</Filter>
</ClInclude>
<ClInclude Include="R5900Exceptions.h">
<Filter>System\Ps2\EmotionEngine\EE</Filter>
</ClInclude>
<ClInclude Include="R5900OpcodeTables.h">
<Filter>System\Ps2\EmotionEngine\EE</Filter>
</ClInclude>

View File

@ -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

View File

@ -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<BaseR5900Exception> m_cpuException;
static std::unique_ptr<BaseException> 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<BaseR5900Exception>(ex.Clone());
recExitExecution();
}
static void recThrowException(const BaseException& ex)
{
if (!eeCpuExecuting)
ex.Rethrow();
m_Exception = std::unique_ptr<BaseException>(ex.Clone());
recExitExecution();
}
R5900cpu recCpu = {
recReserve,
recShutdown,
@ -2716,6 +2691,5 @@ R5900cpu recCpu = {
recExecute,
recSafeExitExecution,
recThrowException,
recThrowException,
recCancelInstruction,
recClear};