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:
parent
a9b4016cd3
commit
85547d94be
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue