EE JIT: Error on jump to unaligned address

This commit is contained in:
Ziemas
2026-03-17 11:31:56 -04:00
committed by Ty
parent dde3c73af7
commit ec8f3b0414
3 changed files with 73 additions and 92 deletions
+1 -1
View File
@@ -64,7 +64,7 @@ void SaveBranchState();
void LoadBranchState();
void recompileNextInstruction(bool delayslot, bool swapped_delay_slot);
void SetBranchReg(u32 reg);
void SetBranchReg();
void SetBranchImm(u32 imm);
void iFlushCall(int flushtype);
+25 -68
View File
@@ -348,7 +348,7 @@ void recCall(void (*func)())
static void recRecompile(const u32 startpc);
static void dyna_block_discard(u32 start, u32 sz);
static void dyna_page_reset(u32 start, u32 sz);
static void HitUnmappedRecLUTPage();
static void recError(u32 error);
static const void* DispatcherEvent = nullptr;
static const void* DispatcherReg = nullptr;
@@ -468,7 +468,7 @@ static const void* _DynGen_DispatchPageReset()
static const void* _DynGen_UnmappedRecLUTPage()
{
u8* retval = xGetPtr();
xFastCall((const void*)HitUnmappedRecLUTPage);
xFastCall((const void*)recError, 0);
return retval;
}
@@ -496,9 +496,18 @@ static void _DynGen_Dispatchers()
//////////////////////////////////////////////////////////////////////////////////////////
//
static void HitUnmappedRecLUTPage()
static void recError(u32 error)
{
Host::ReportErrorAsync("R5900 Exception", fmt::format("Jump to unmapped recLUT page (PC: 0x{:08x})", cpuRegs.pc));
switch (error)
{
case 0:
Host::ReportErrorAsync("R5900 Exception", fmt::format("Jump to unmapped recLUT page (PC: 0x{:08x})", cpuRegs.pc));
break;
case 1:
Host::ReportErrorAsync("R5900 Exception", fmt::format("Jump to unaligned address (PC: 0x{:08x})", cpuRegs.pc));
break;
}
VMManager::SetPaused(true);
recExitExecution();
}
@@ -829,77 +838,25 @@ void recClear(u32 addr, u32 size)
static int* s_pCode;
void SetBranchReg(u32 reg)
// Branch to a runtime variable target
// pass the target in eax
void SetBranchReg()
{
g_branch = 1;
if (reg != 0xffffffff)
{
// if (GPR_IS_CONST1(reg))
// xMOV(ptr32[&cpuRegs.pc], g_cpuConstRegs[reg].UL[0]);
// else
// {
// int mmreg;
//
// if ((mmreg = _checkXMMreg(XMMTYPE_GPRREG, reg, MODE_READ)) >= 0)
// {
// xMOVSS(ptr[&cpuRegs.pc], xRegisterSSE(mmreg));
// }
// else
// {
// xMOV(eax, ptr[(void*)((int)&cpuRegs.GPR.r[reg].UL[0])]);
// xMOV(ptr[&cpuRegs.pc], eax);
// }
// }
const bool swap = EmuConfig.Gamefixes.GoemonTlbHack ? false : TrySwapDelaySlot(reg, 0, 0, true);
if (!swap)
{
const int wbreg = _allocX86reg(X86TYPE_PCWRITEBACK, 0, MODE_WRITE | MODE_CALLEESAVED);
_eeMoveGPRtoR(xRegister32(wbreg), reg);
xMOV(ptr32[&cpuRegs.pc], eax);
if (EmuConfig.Gamefixes.GoemonTlbHack)
{
xMOV(ecx, xRegister32(wbreg));
vtlb_DynV2P();
xMOV(xRegister32(wbreg), eax);
}
recompileNextInstruction(true, false);
// the next instruction may have flushed the register.. so reload it if so.
if (x86regs[wbreg].inuse && x86regs[wbreg].type == X86TYPE_PCWRITEBACK)
{
xMOV(ptr[&cpuRegs.pc], xRegister32(wbreg));
x86regs[wbreg].inuse = 0;
}
else
{
xMOV(eax, ptr[&cpuRegs.pcWriteback]);
xMOV(ptr[&cpuRegs.pc], eax);
}
}
else
{
if (GPR_IS_DIRTY_CONST(reg) || _hasX86reg(X86TYPE_GPR, reg, 0))
{
const int x86reg = _allocX86reg(X86TYPE_GPR, reg, MODE_READ);
xMOV(ptr32[&cpuRegs.pc], xRegister32(x86reg));
}
else
{
_eeMoveGPRtoM((uptr)&cpuRegs.pc, reg);
}
}
}
// xCMP(ptr32[&cpuRegs.pc], 0);
// j8Ptr[5] = JNE8(0);
// xFastCall((void*)(uptr)tempfn);
// x86SetJ8(j8Ptr[5]);
// Test for jump to unaligned, only needed for register branches
// since unaligned targets can't be encoded with imm
xTEST(eax, 3);
xForwardJNZ32 unaligned;
iFlushCall(FLUSH_EVERYTHING);
iBranchTest();
unaligned.SetTarget();
xFastCall((const void*)recError, 1);
}
void SetBranchImm(u32 imm)
+47 -23
View File
@@ -75,7 +75,48 @@ void recJR()
{
EE::Profiler.EmitOp(eeOpcode::JR);
SetBranchReg(_Rs_);
const bool swap = EmuConfig.Gamefixes.GoemonTlbHack ? false : TrySwapDelaySlot(_Rs_, 0, 0, true);
if (!swap)
{
const int wbreg = _allocX86reg(X86TYPE_PCWRITEBACK, 0, MODE_WRITE | MODE_CALLEESAVED);
_eeMoveGPRtoR(xRegister32(wbreg), _Rs_);
if (EmuConfig.Gamefixes.GoemonTlbHack)
{
xMOV(ecx, xRegister32(wbreg));
vtlb_DynV2P();
xMOV(xRegister32(wbreg), eax);
}
recompileNextInstruction(true, false);
// the next instruction may have flushed the register.. so reload it if so.
if (x86regs[wbreg].inuse && x86regs[wbreg].type == X86TYPE_PCWRITEBACK)
{
xMOV(eax, xRegister32(wbreg));
x86regs[wbreg].inuse = 0;
}
else
{
xMOV(eax, ptr[&cpuRegs.pcWriteback]);
}
}
else
{
if (GPR_IS_DIRTY_CONST(_Rs_) || _hasX86reg(X86TYPE_GPR, _Rs_, 0))
{
const int x86reg = _allocX86reg(X86TYPE_GPR, _Rs_, MODE_READ);
xMOV(eax, xRegister32(x86reg));
}
else
{
_eeMoveGPRtoR(eax, _Rs_);
}
}
// Target passed in eax
SetBranchReg();
}
////////////////////////////////////////////////////
@@ -86,23 +127,6 @@ void recJALR()
const u32 newpc = pc + 4;
const bool swap = (EmuConfig.Gamefixes.GoemonTlbHack || _Rd_ == _Rs_) ? false : TrySwapDelaySlot(_Rs_, 0, _Rd_, true);
// uncomment when there are NO instructions that need to call interpreter
// int mmreg;
// if (GPR_IS_CONST1(_Rs_))
// xMOV(ptr32[&cpuRegs.pc], g_cpuConstRegs[_Rs_].UL[0]);
// else
// {
// int mmreg;
//
// if ((mmreg = _checkXMMreg(XMMTYPE_GPRREG, _Rs_, MODE_READ)) >= 0)
// {
// xMOVSS(ptr[&cpuRegs.pc], xRegisterSSE(mmreg));
// }
// else {
// xMOV(eax, ptr[(void*)((int)&cpuRegs.GPR.r[_Rs_].UL[0])]);
// xMOV(ptr[&cpuRegs.pc], eax);
// }
// }
int wbreg = -1;
if (!swap)
@@ -139,13 +163,12 @@ void recJALR()
// the next instruction may have flushed the register.. so reload it if so.
if (x86regs[wbreg].inuse && x86regs[wbreg].type == X86TYPE_PCWRITEBACK)
{
xMOV(ptr[&cpuRegs.pc], xRegister32(wbreg));
xMOV(eax, xRegister32(wbreg));
x86regs[wbreg].inuse = 0;
}
else
{
xMOV(eax, ptr[&cpuRegs.pcWriteback]);
xMOV(ptr[&cpuRegs.pc], eax);
}
}
else
@@ -153,15 +176,16 @@ void recJALR()
if (GPR_IS_DIRTY_CONST(_Rs_) || _hasX86reg(X86TYPE_GPR, _Rs_, 0))
{
const int x86reg = _allocX86reg(X86TYPE_GPR, _Rs_, MODE_READ);
xMOV(ptr32[&cpuRegs.pc], xRegister32(x86reg));
xMOV(eax, xRegister32(x86reg));
}
else
{
_eeMoveGPRtoM((uptr)&cpuRegs.pc, _Rs_);
_eeMoveGPRtoR(eax, _Rs_);
}
}
SetBranchReg(0xffffffff);
// Target passed in eax
SetBranchReg();
}
#endif