WIP: don't let the backpatcher hit the same location twice

If a location is hit by the backpatcher, don't fastmem it when recompiling the
block unless the block has actually been invalidated.
This commit is contained in:
Fiora 2014-10-04 21:28:21 -07:00
parent 355a2d33aa
commit 9b29fe8aed
6 changed files with 34 additions and 27 deletions

View File

@ -221,6 +221,8 @@ void Jit64::ClearCache()
{ {
blocks.Clear(); blocks.Clear();
trampolines.ClearCodeSpace(); trampolines.ClearCodeSpace();
jit->js.pcAtLoc.clear();
jit->js.registersInUseAtLoc.clear();
farcode.ClearCodeSpace(); farcode.ClearCodeSpace();
ClearCodeSpace(); ClearCodeSpace();
m_clear_cache_asap = false; m_clear_cache_asap = false;

View File

@ -65,14 +65,21 @@ bool Jitx86Base::BackPatch(u32 emAddress, SContext* ctx)
return false; return false;
} }
auto it = registersInUseAtLoc.find(codePtr); auto pc_it = jit->js.pcAtLoc.find(codePtr);
if (it == registersInUseAtLoc.end()) if (pc_it == jit->js.pcAtLoc.end())
{ {
PanicAlert("BackPatch: no register use entry for address %p", codePtr); PanicAlert("BackPatch: no pc entry for address %p", codePtr);
return nullptr;
}
u32 pc = pc_it->second;
auto reguse_it = jit->js.registersInUseAtLoc.find(pc);
if (reguse_it == jit->js.registersInUseAtLoc.end())
{
PanicAlert("BackPatch: no register use entry for PC %x", pc);
return false; return false;
} }
u32 registersInUse = reguse_it->second;
u32 registersInUse = it->second;
if (!info.isMemoryWrite) if (!info.isMemoryWrite)
{ {
@ -97,16 +104,7 @@ bool Jitx86Base::BackPatch(u32 emAddress, SContext* ctx)
} }
else else
{ {
// TODO: special case FIFO writes. Also, support 32-bit mode. // TODO: special case FIFO writes
it = pcAtLoc.find(codePtr);
if (it == pcAtLoc.end())
{
PanicAlert("BackPatch: no pc entry for address %p", codePtr);
return nullptr;
}
u32 pc = it->second;
u8 *start; u8 *start;
if (info.byteSwap || info.hasImmediate) if (info.byteSwap || info.hasImmediate)
{ {

View File

@ -98,6 +98,8 @@ protected:
JitBlock *curBlock; JitBlock *curBlock;
std::unordered_set<u32> fifoWriteAddresses; std::unordered_set<u32> fifoWriteAddresses;
std::unordered_map<u32, u32> registersInUseAtLoc;
std::unordered_map<u8 *, u32> pcAtLoc;
}; };
PPCAnalyst::CodeBlock code_block; PPCAnalyst::CodeBlock code_block;

View File

@ -359,14 +359,19 @@ using namespace Gen;
block_map.erase(it1, it2); 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) if (!forced)
{ {
for (u32 i = address; i < address + length; i += 4) for (u32 i = address; i < address + length; i += 4)
{
// 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).
jit->js.fifoWriteAddresses.erase(i); jit->js.fifoWriteAddresses.erase(i);
// We use these entries to determine whether there's a fastmem fault at this location,
// so clear it since the block is being replaced.
jit->js.registersInUseAtLoc.erase(i);
}
} }
} }
} }

View File

@ -299,7 +299,8 @@ void EmuCodeBlock::SafeLoadToReg(X64Reg reg_value, const Gen::OpArg & opAddress,
if (!SConfig::GetInstance().m_LocalCoreStartupParameter.bMMU && if (!SConfig::GetInstance().m_LocalCoreStartupParameter.bMMU &&
SConfig::GetInstance().m_LocalCoreStartupParameter.bFastmem && SConfig::GetInstance().m_LocalCoreStartupParameter.bFastmem &&
!opAddress.IsImm() && !opAddress.IsImm() &&
!(flags & (SAFE_LOADSTORE_NO_SWAP | SAFE_LOADSTORE_NO_FASTMEM)) !(flags & (SAFE_LOADSTORE_NO_SWAP | SAFE_LOADSTORE_NO_FASTMEM)) &&
jit->js.registersInUseAtLoc.find(jit->js.compilerPC) == jit->js.registersInUseAtLoc.end()
#ifdef ENABLE_MEM_CHECK #ifdef ENABLE_MEM_CHECK
&& !SConfig::GetInstance().m_LocalCoreStartupParameter.bEnableDebugging && !SConfig::GetInstance().m_LocalCoreStartupParameter.bEnableDebugging
#endif #endif
@ -307,7 +308,8 @@ void EmuCodeBlock::SafeLoadToReg(X64Reg reg_value, const Gen::OpArg & opAddress,
{ {
u8 *mov = UnsafeLoadToReg(reg_value, opAddress, accessSize, offset, signExtend); u8 *mov = UnsafeLoadToReg(reg_value, opAddress, accessSize, offset, signExtend);
registersInUseAtLoc[mov] = registersInUse; jit->js.pcAtLoc[mov] = jit->js.compilerPC;
jit->js.registersInUseAtLoc[jit->js.compilerPC] = registersInUse;
} }
else else
{ {
@ -483,7 +485,8 @@ void EmuCodeBlock::SafeWriteRegToReg(OpArg reg_value, X64Reg reg_addr, int acces
if (!SConfig::GetInstance().m_LocalCoreStartupParameter.bMMU && if (!SConfig::GetInstance().m_LocalCoreStartupParameter.bMMU &&
SConfig::GetInstance().m_LocalCoreStartupParameter.bFastmem && SConfig::GetInstance().m_LocalCoreStartupParameter.bFastmem &&
!(flags & SAFE_LOADSTORE_NO_FASTMEM) && !(flags & SAFE_LOADSTORE_NO_FASTMEM) &&
(reg_value.IsImm() || !(flags & SAFE_LOADSTORE_NO_SWAP)) (reg_value.IsImm() || !(flags & SAFE_LOADSTORE_NO_SWAP)) &&
jit->js.registersInUseAtLoc.find(jit->js.compilerPC) == jit->js.registersInUseAtLoc.end()
#ifdef ENABLE_MEM_CHECK #ifdef ENABLE_MEM_CHECK
&& !SConfig::GetInstance().m_LocalCoreStartupParameter.bEnableDebugging && !SConfig::GetInstance().m_LocalCoreStartupParameter.bEnableDebugging
#endif #endif
@ -497,8 +500,8 @@ void EmuCodeBlock::SafeWriteRegToReg(OpArg reg_value, X64Reg reg_addr, int acces
NOP(padding); NOP(padding);
} }
registersInUseAtLoc[mov] = registersInUse; jit->js.pcAtLoc[mov] = jit->js.compilerPC;
pcAtLoc[mov] = jit->js.compilerPC; jit->js.registersInUseAtLoc[jit->js.compilerPC] = registersInUse;
return; return;
} }

View File

@ -131,7 +131,4 @@ public:
void ConvertSingleToDouble(Gen::X64Reg dst, Gen::X64Reg src, bool src_is_gpr = false); void ConvertSingleToDouble(Gen::X64Reg dst, Gen::X64Reg src, bool src_is_gpr = false);
void ConvertDoubleToSingle(Gen::X64Reg dst, Gen::X64Reg src); void ConvertDoubleToSingle(Gen::X64Reg dst, Gen::X64Reg src);
void SetFPRF(Gen::X64Reg xmm); void SetFPRF(Gen::X64Reg xmm);
protected:
std::unordered_map<u8 *, u32> registersInUseAtLoc;
std::unordered_map<u8 *, u32> pcAtLoc;
}; };