Only honor T and D bits if E bit has not been encountered.

Fixes Silent Hill 2 hanging at movies.
This commit is contained in:
Jean-Philip Desjardins 2024-09-12 13:14:56 -04:00
parent f5bcb8bb1d
commit 3fd5b7a56c
4 changed files with 24 additions and 8 deletions

View file

@ -261,7 +261,7 @@ void CBasicBlock::CompileEpilog(CMipsJitter* jitter, bool loopsOnItself)
jitter->BeginIf(Jitter::CONDITION_LE); jitter->BeginIf(Jitter::CONDITION_LE);
{ {
jitter->PushRel(offsetof(CMIPS, m_State.nHasException)); jitter->PushRel(offsetof(CMIPS, m_State.nHasException));
jitter->PushCst(MIPS_EXECUTION_STATUS_QUOTADONE); jitter->PushCst(MIPS_EXCEPTION_STATUS_QUOTADONE);
jitter->Or(); jitter->Or();
jitter->PullRel(offsetof(CMIPS, m_State.nHasException)); jitter->PullRel(offsetof(CMIPS, m_State.nHasException));
} }

View file

@ -69,7 +69,7 @@ public:
auto block = m_blockLookup.FindBlockAt(address); auto block = m_blockLookup.FindBlockAt(address);
block->Execute(); block->Execute();
} }
m_context.m_State.nHasException &= ~MIPS_EXECUTION_STATUS_QUOTADONE; m_context.m_State.nHasException &= ~MIPS_EXCEPTION_STATUS_QUOTADONE;
#ifdef DEBUGGER_INCLUDED #ifdef DEBUGGER_INCLUDED
if(m_context.m_State.nHasException == MIPS_EXCEPTION_BREAKPOINT) if(m_context.m_State.nHasException == MIPS_EXCEPTION_BREAKPOINT)
{ {

View file

@ -45,7 +45,11 @@ enum
MIPS_EXCEPTION_VU_DBIT, MIPS_EXCEPTION_VU_DBIT,
MIPS_EXCEPTION_VU_TBIT, MIPS_EXCEPTION_VU_TBIT,
MIPS_EXCEPTION_VU_EBIT, MIPS_EXCEPTION_VU_EBIT,
MIPS_EXCEPTION_MAX, //Used to make sure we don't conflict with the QUOTADONE status
}; };
static_assert(MIPS_EXCEPTION_MAX <= 0x80);
static constexpr uint32 MIPS_EXCEPTION_STATUS_QUOTADONE = 0x80;
struct TLBENTRY struct TLBENTRY
{ {
@ -55,8 +59,6 @@ struct TLBENTRY
uint32 pageMask; uint32 pageMask;
}; };
#define MIPS_EXECUTION_STATUS_QUOTADONE 0x80
struct MIPSSTATE struct MIPSSTATE
{ {
uint32 nPC; uint32 nPC;

View file

@ -30,16 +30,30 @@ void CMA_VU::CUpper::CompileInstruction(uint32 nAddress, CMipsJitter* codeGen, C
((this)->*(m_pOpVector[m_nOpcode & 0x3F]))(); ((this)->*(m_pOpVector[m_nOpcode & 0x3F]))();
auto setTDBitException = [&](uint32 exceptionValue) {
//Only set TD bit exception if there's no other outstanding
//exceptions (ie.: E bit). We could set a bit for every stop bit
//we encounter, but we assume that no game relies on multiple bits
//being set.
//This assumes that QUOTADONE is only set at the end
m_codeGen->PushRel(offsetof(CMIPS, m_State.nHasException));
m_codeGen->PushCst(0);
m_codeGen->BeginIf(Jitter::CONDITION_EQ);
{
m_codeGen->PushCst(exceptionValue);
m_codeGen->PullRel(offsetof(CMIPS, m_State.nHasException));
}
m_codeGen->EndIf();
};
if(m_nOpcode & VUShared::VU_UPPEROP_BIT_D) if(m_nOpcode & VUShared::VU_UPPEROP_BIT_D)
{ {
m_codeGen->PushCst(MIPS_EXCEPTION_VU_DBIT); setTDBitException(MIPS_EXCEPTION_VU_DBIT);
m_codeGen->PullRel(offsetof(CMIPS, m_State.nHasException));
} }
if(m_nOpcode & VUShared::VU_UPPEROP_BIT_T) if(m_nOpcode & VUShared::VU_UPPEROP_BIT_T)
{ {
m_codeGen->PushCst(MIPS_EXCEPTION_VU_TBIT); setTDBitException(MIPS_EXCEPTION_VU_TBIT);
m_codeGen->PullRel(offsetof(CMIPS, m_State.nHasException));
} }
if(m_nOpcode & VUShared::VU_UPPEROP_BIT_I) if(m_nOpcode & VUShared::VU_UPPEROP_BIT_I)