JIT: properly remove FIFO write addresses when code is invalidated

Fixes a bug caused by interaction with carry optimizations; might fix other
issues too.
This commit is contained in:
Fiora 2014-09-26 13:45:24 -07:00
parent a9b4016cd3
commit 85547d94be
9 changed files with 27 additions and 16 deletions

View File

@ -66,7 +66,7 @@ void BreakPoints::Add(const TBreakPoint& bp)
{
m_BreakPoints.push_back(bp);
if (jit)
jit->GetBlockCache()->InvalidateICache(bp.iAddress, 4);
jit->GetBlockCache()->InvalidateICache(bp.iAddress, 4, true);
}
}
@ -82,7 +82,7 @@ void BreakPoints::Add(u32 em_address, bool temp)
m_BreakPoints.push_back(pt);
if (jit)
jit->GetBlockCache()->InvalidateICache(em_address, 4);
jit->GetBlockCache()->InvalidateICache(em_address, 4, true);
}
}
@ -94,7 +94,7 @@ void BreakPoints::Remove(u32 em_address)
{
m_BreakPoints.erase(i);
if (jit)
jit->GetBlockCache()->InvalidateICache(em_address, 4);
jit->GetBlockCache()->InvalidateICache(em_address, 4, true);
return;
}
}
@ -106,7 +106,7 @@ void BreakPoints::Clear()
{
for (const TBreakPoint& bp : m_BreakPoints)
{
jit->GetBlockCache()->InvalidateICache(bp.iAddress, 4);
jit->GetBlockCache()->InvalidateICache(bp.iAddress, 4, true);
}
}

View File

@ -327,7 +327,7 @@ void Interpreter::dcbf(UGeckoInstruction _inst)
NPC = PC + 12;
}*/
u32 address = Helper_Get_EA_X(_inst);
JitInterface::InvalidateICache(address & ~0x1f, 32);
JitInterface::InvalidateICache(address & ~0x1f, 32, false);
}
void Interpreter::dcbi(UGeckoInstruction _inst)
@ -335,7 +335,7 @@ void Interpreter::dcbi(UGeckoInstruction _inst)
// Removes a block from data cache. Since we don't emulate the data cache, we don't need to do anything to the data cache
// However, we invalidate the jit block cache on dcbi
u32 address = Helper_Get_EA_X(_inst);
JitInterface::InvalidateICache(address & ~0x1f, 32);
JitInterface::InvalidateICache(address & ~0x1f, 32, false);
// The following detects a situation where the game is writing to the dcache at the address being DMA'd. As we do not
// have dcache emulation, invalid data is being DMA'd causing audio glitches. The following code detects this and
@ -359,7 +359,7 @@ void Interpreter::dcbst(UGeckoInstruction _inst)
// Cache line flush. Since we don't emulate the data cache, we don't need to do anything.
// Invalidate the jit block cache on dcbst in case new code has been loaded via the data cache
u32 address = Helper_Get_EA_X(_inst);
JitInterface::InvalidateICache(address & ~0x1f, 32);
JitInterface::InvalidateICache(address & ~0x1f, 32, false);
}
void Interpreter::dcbt(UGeckoInstruction _inst)

View File

@ -159,7 +159,7 @@ bool Jit64::HandleFault(uintptr_t access_address, SContext* ctx)
// CALLs, but we can't yet. Fake the downcount so we're forced to the
// dispatcher (no block linking), and clear the cache so we're sent to
// Jit. Yeah, it's kind of gross.
GetBlockCache()->InvalidateICache(0, 0xffffffff);
GetBlockCache()->InvalidateICache(0, 0xffffffff, true);
CoreTiming::ForceExceptionCheck(0);
m_clear_cache_asap = true;

View File

@ -327,7 +327,7 @@ using namespace Gen;
WriteDestroyBlock(b.checkedEntry, b.originalAddress);
}
void JitBaseBlockCache::InvalidateICache(u32 address, const u32 length)
void JitBaseBlockCache::InvalidateICache(u32 address, const u32 length, bool forced)
{
// Convert the logical address to a physical address for the block map
u32 pAddr = address & 0x1FFFFFFF;
@ -358,6 +358,16 @@ using namespace Gen;
{
block_map.erase(it1, it2);
}
// If the code was actually modified, we need to clear the relevant entries from the
// FIFO write address cache, so we don't end up with FIFO checks in places they shouldn't
// be (this can clobber flags, and thus break any optimization that relies on flags
// being in the right place between instructions).
if (!forced)
{
for (u32 i = address; i < address + length; i += 4)
jit->js.fifoWriteAddresses.erase(i);
}
}
}

View File

@ -161,7 +161,7 @@ public:
CompiledCode GetCompiledCodeFromBlock(int block_num);
// DOES NOT WORK CORRECTLY WITH INLINING
void InvalidateICache(u32 address, const u32 length);
void InvalidateICache(u32 address, const u32 length, bool forced);
void DestroyBlock(int block_num, bool invalidate);
};

View File

@ -210,10 +210,10 @@ namespace JitInterface
jit->GetBlockCache()->Clear();
}
void InvalidateICache(u32 address, u32 size)
void InvalidateICache(u32 address, u32 size, bool forced)
{
if (jit)
jit->GetBlockCache()->InvalidateICache(address, size);
jit->GetBlockCache()->InvalidateICache(address, size, forced);
}
u32 ReadOpcodeJIT(u32 _Address)
@ -263,7 +263,7 @@ namespace JitInterface
exception_addresses->insert(PC);
// Invalidate the JIT block so that it gets recompiled with the external exception check included.
jit->GetBlockCache()->InvalidateICache(PC, 4);
jit->GetBlockCache()->InvalidateICache(PC, 4, true);
}
}
}

View File

@ -36,7 +36,8 @@ namespace JitInterface
void ClearSafe();
void InvalidateICache(u32 address, u32 size);
// If "forced" is true, a recompile is being requested on code that hasn't been modified.
void InvalidateICache(u32 address, u32 size, bool forced);
void CompileExceptionCheck(int type);

View File

@ -95,7 +95,7 @@ namespace PowerPC
lookup_table[((tags[set][i] << 7) | set) & 0xfffff] = 0xff;
}
valid[set] = 0;
JitInterface::InvalidateICache(addr & ~0x1f, 32);
JitInterface::InvalidateICache(addr & ~0x1f, 32, false);
}
u32 InstructionCache::ReadInstruction(u32 addr)

View File

@ -288,7 +288,7 @@ void CCodeWindow::SingleStep()
{
if (CCPU::IsStepping())
{
JitInterface::InvalidateICache(PC, 4);
JitInterface::InvalidateICache(PC, 4, true);
CCPU::StepOpcode(&sync_event);
wxThread::Sleep(20);
// need a short wait here