mirror of https://github.com/PCSX2/pcsx2.git
R5900: Remove exceptions
This commit is contained in:
parent
94226e83ba
commit
d12fa690c0
|
@ -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. :)
|
||||
|
|
|
@ -202,7 +202,6 @@ set(pcsx2Headers
|
|||
PerformanceMetrics.h
|
||||
PrecompiledHeader.h
|
||||
R3000A.h
|
||||
R5900Exceptions.h
|
||||
R5900.h
|
||||
R5900OpcodeTables.h
|
||||
SaveState.h
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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()
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
#include "VUmicro.h"
|
||||
#include "COP0.h"
|
||||
#include "MTVU.h"
|
||||
#include "R5900Exceptions.h"
|
||||
#include "VMManager.h"
|
||||
|
||||
#include "Hardware.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
|
||||
|
|
|
@ -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" );
|
||||
}
|
||||
};
|
||||
}
|
|
@ -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]);
|
||||
}
|
||||
|
|
|
@ -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" />
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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};
|
||||
|
|
Loading…
Reference in New Issue