Merge pull request #1222 from FioraAeterna/backpatchchanges
FastMem: don't let the backpatcher hit the same location twice
This commit is contained in:
commit
002b9f7acd
|
@ -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;
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -99,6 +99,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;
|
||||||
|
|
|
@ -339,14 +339,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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
{
|
{
|
||||||
|
@ -482,7 +484,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
|
||||||
|
@ -496,8 +499,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -136,7 +136,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;
|
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue