Merge pull request #4961 from aldelaro5/fast-memchecks
Make memory breakpoint faster
This commit is contained in:
commit
521a777ade
|
@ -11,8 +11,10 @@
|
||||||
|
|
||||||
#include "Common/CommonTypes.h"
|
#include "Common/CommonTypes.h"
|
||||||
#include "Common/DebugInterface.h"
|
#include "Common/DebugInterface.h"
|
||||||
|
#include "Core/Core.h"
|
||||||
#include "Core/PowerPC/JitCommon/JitBase.h"
|
#include "Core/PowerPC/JitCommon/JitBase.h"
|
||||||
#include "Core/PowerPC/JitCommon/JitCache.h"
|
#include "Core/PowerPC/JitCommon/JitCache.h"
|
||||||
|
#include "Core/PowerPC/PowerPC.h"
|
||||||
|
|
||||||
bool BreakPoints::IsAddressBreakPoint(u32 address) const
|
bool BreakPoints::IsAddressBreakPoint(u32 address) const
|
||||||
{
|
{
|
||||||
|
@ -168,13 +170,18 @@ void MemChecks::AddFromStrings(const TMemChecksStr& mc_strings)
|
||||||
|
|
||||||
void MemChecks::Add(const TMemCheck& memory_check)
|
void MemChecks::Add(const TMemCheck& memory_check)
|
||||||
{
|
{
|
||||||
bool had_any = HasAny();
|
|
||||||
if (GetMemCheck(memory_check.start_address) == nullptr)
|
if (GetMemCheck(memory_check.start_address) == nullptr)
|
||||||
|
{
|
||||||
|
bool had_any = HasAny();
|
||||||
|
bool lock = Core::PauseAndLock(true);
|
||||||
m_mem_checks.push_back(memory_check);
|
m_mem_checks.push_back(memory_check);
|
||||||
// If this is the first one, clear the JIT cache so it can switch to
|
// If this is the first one, clear the JIT cache so it can switch to
|
||||||
// watchpoint-compatible code.
|
// watchpoint-compatible code.
|
||||||
if (!had_any && g_jit)
|
if (!had_any && g_jit)
|
||||||
g_jit->GetBlockCache()->SchedulateClearCacheThreadSafe();
|
g_jit->ClearCache();
|
||||||
|
PowerPC::DBATUpdated();
|
||||||
|
Core::PauseAndLock(false, lock);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MemChecks::Remove(u32 address)
|
void MemChecks::Remove(u32 address)
|
||||||
|
@ -183,9 +190,12 @@ void MemChecks::Remove(u32 address)
|
||||||
{
|
{
|
||||||
if (i->start_address == address)
|
if (i->start_address == address)
|
||||||
{
|
{
|
||||||
|
bool lock = Core::PauseAndLock(true);
|
||||||
m_mem_checks.erase(i);
|
m_mem_checks.erase(i);
|
||||||
if (!HasAny() && g_jit)
|
if (!HasAny() && g_jit)
|
||||||
g_jit->GetBlockCache()->SchedulateClearCacheThreadSafe();
|
g_jit->ClearCache();
|
||||||
|
PowerPC::DBATUpdated();
|
||||||
|
Core::PauseAndLock(false, lock);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -210,6 +220,25 @@ TMemCheck* MemChecks::GetMemCheck(u32 address)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MemChecks::OverlapsMemcheck(u32 address, u32 length)
|
||||||
|
{
|
||||||
|
if (!HasAny())
|
||||||
|
return false;
|
||||||
|
u32 page_end_suffix = length - 1;
|
||||||
|
u32 page_end_address = address | page_end_suffix;
|
||||||
|
for (TMemCheck memcheck : m_mem_checks)
|
||||||
|
{
|
||||||
|
if (((memcheck.start_address | page_end_suffix) == page_end_address ||
|
||||||
|
(memcheck.end_address | page_end_suffix) == page_end_address) ||
|
||||||
|
((memcheck.start_address | page_end_suffix) < page_end_address &&
|
||||||
|
(memcheck.end_address | page_end_suffix) > page_end_address))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool TMemCheck::Action(DebugInterface* debug_interface, u32 value, u32 addr, bool write, int size,
|
bool TMemCheck::Action(DebugInterface* debug_interface, u32 value, u32 addr, bool write, int size,
|
||||||
u32 pc)
|
u32 pc)
|
||||||
{
|
{
|
||||||
|
|
|
@ -87,6 +87,7 @@ public:
|
||||||
|
|
||||||
// memory breakpoint
|
// memory breakpoint
|
||||||
TMemCheck* GetMemCheck(u32 address);
|
TMemCheck* GetMemCheck(u32 address);
|
||||||
|
bool OverlapsMemcheck(u32 address, u32 length);
|
||||||
void Remove(u32 address);
|
void Remove(u32 address);
|
||||||
|
|
||||||
void Clear() { m_mem_checks.clear(); }
|
void Clear() { m_mem_checks.clear(); }
|
||||||
|
|
|
@ -335,7 +335,7 @@ void EmuCodeBlock::MMIOLoadToReg(MMIO::Mapping* mmio, Gen::X64Reg reg_value,
|
||||||
void EmuCodeBlock::SafeLoadToReg(X64Reg reg_value, const Gen::OpArg& opAddress, int accessSize,
|
void EmuCodeBlock::SafeLoadToReg(X64Reg reg_value, const Gen::OpArg& opAddress, int accessSize,
|
||||||
s32 offset, BitSet32 registersInUse, bool signExtend, int flags)
|
s32 offset, BitSet32 registersInUse, bool signExtend, int flags)
|
||||||
{
|
{
|
||||||
bool slowmem = (flags & SAFE_LOADSTORE_FORCE_SLOWMEM) != 0 || g_jit->jo.alwaysUseMemFuncs;
|
bool slowmem = (flags & SAFE_LOADSTORE_FORCE_SLOWMEM) != 0;
|
||||||
|
|
||||||
registersInUse[reg_value] = false;
|
registersInUse[reg_value] = false;
|
||||||
if (g_jit->jo.fastmem && !(flags & SAFE_LOADSTORE_NO_FASTMEM) && !slowmem)
|
if (g_jit->jo.fastmem && !(flags & SAFE_LOADSTORE_NO_FASTMEM) && !slowmem)
|
||||||
|
@ -492,7 +492,7 @@ void EmuCodeBlock::SafeWriteRegToReg(OpArg reg_value, X64Reg reg_addr, int acces
|
||||||
BitSet32 registersInUse, int flags)
|
BitSet32 registersInUse, int flags)
|
||||||
{
|
{
|
||||||
bool swap = !(flags & SAFE_LOADSTORE_NO_SWAP);
|
bool swap = !(flags & SAFE_LOADSTORE_NO_SWAP);
|
||||||
bool slowmem = (flags & SAFE_LOADSTORE_FORCE_SLOWMEM) != 0 || g_jit->jo.alwaysUseMemFuncs;
|
bool slowmem = (flags & SAFE_LOADSTORE_FORCE_SLOWMEM) != 0;
|
||||||
|
|
||||||
// set the correct immediate format
|
// set the correct immediate format
|
||||||
reg_value = FixImmediate(accessSize, reg_value);
|
reg_value = FixImmediate(accessSize, reg_value);
|
||||||
|
|
|
@ -46,7 +46,6 @@ bool JitBase::MergeAllowedNextInstructions(int count)
|
||||||
void JitBase::UpdateMemoryOptions()
|
void JitBase::UpdateMemoryOptions()
|
||||||
{
|
{
|
||||||
bool any_watchpoints = PowerPC::memchecks.HasAny();
|
bool any_watchpoints = PowerPC::memchecks.HasAny();
|
||||||
jo.fastmem = SConfig::GetInstance().bFastmem && !any_watchpoints;
|
jo.fastmem = SConfig::GetInstance().bFastmem && (UReg_MSR(MSR).DR || !any_watchpoints);
|
||||||
jo.memcheck = SConfig::GetInstance().bMMU || any_watchpoints;
|
jo.memcheck = SConfig::GetInstance().bMMU || any_watchpoints;
|
||||||
jo.alwaysUseMemFuncs = any_watchpoints;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,7 +52,6 @@ protected:
|
||||||
bool accurateSinglePrecision;
|
bool accurateSinglePrecision;
|
||||||
bool fastmem;
|
bool fastmem;
|
||||||
bool memcheck;
|
bool memcheck;
|
||||||
bool alwaysUseMemFuncs;
|
|
||||||
};
|
};
|
||||||
struct JitState
|
struct JitState
|
||||||
{
|
{
|
||||||
|
|
|
@ -29,13 +29,6 @@
|
||||||
|
|
||||||
using namespace Gen;
|
using namespace Gen;
|
||||||
|
|
||||||
static CoreTiming::EventType* s_clear_jit_cache_thread_safe;
|
|
||||||
|
|
||||||
static void ClearCacheThreadSafe(u64 userdata, s64 cyclesdata)
|
|
||||||
{
|
|
||||||
JitInterface::ClearCache();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool JitBlock::OverlapsPhysicalRange(u32 address, u32 length) const
|
bool JitBlock::OverlapsPhysicalRange(u32 address, u32 length) const
|
||||||
{
|
{
|
||||||
return physical_addresses.lower_bound(address) !=
|
return physical_addresses.lower_bound(address) !=
|
||||||
|
@ -50,7 +43,6 @@ JitBaseBlockCache::~JitBaseBlockCache() = default;
|
||||||
|
|
||||||
void JitBaseBlockCache::Init()
|
void JitBaseBlockCache::Init()
|
||||||
{
|
{
|
||||||
s_clear_jit_cache_thread_safe = CoreTiming::RegisterEvent("clearJitCache", ClearCacheThreadSafe);
|
|
||||||
JitRegister::Init(SConfig::GetInstance().m_perfDir);
|
JitRegister::Init(SConfig::GetInstance().m_perfDir);
|
||||||
|
|
||||||
Clear();
|
Clear();
|
||||||
|
@ -89,11 +81,6 @@ void JitBaseBlockCache::Reset()
|
||||||
Init();
|
Init();
|
||||||
}
|
}
|
||||||
|
|
||||||
void JitBaseBlockCache::SchedulateClearCacheThreadSafe()
|
|
||||||
{
|
|
||||||
CoreTiming::ScheduleEvent(0, s_clear_jit_cache_thread_safe, 0, CoreTiming::FromThread::NON_CPU);
|
|
||||||
}
|
|
||||||
|
|
||||||
JitBlock** JitBaseBlockCache::GetFastBlockMap()
|
JitBlock** JitBaseBlockCache::GetFastBlockMap()
|
||||||
{
|
{
|
||||||
return fast_block_map.data();
|
return fast_block_map.data();
|
||||||
|
|
|
@ -125,7 +125,6 @@ public:
|
||||||
void Shutdown();
|
void Shutdown();
|
||||||
void Clear();
|
void Clear();
|
||||||
void Reset();
|
void Reset();
|
||||||
void SchedulateClearCacheThreadSafe();
|
|
||||||
|
|
||||||
// Code Cache
|
// Code Cache
|
||||||
JitBlock** GetFastBlockMap();
|
JitBlock** GetFastBlockMap();
|
||||||
|
|
|
@ -1191,6 +1191,10 @@ static void UpdateBATs(BatTable& bat_table, u32 base_spr)
|
||||||
valid_bit = 0x3;
|
valid_bit = 0x3;
|
||||||
else if ((address >> 28) == 0xE && (address < (0xE0000000 + Memory::L1_CACHE_SIZE)))
|
else if ((address >> 28) == 0xE && (address < (0xE0000000 + Memory::L1_CACHE_SIZE)))
|
||||||
valid_bit = 0x3;
|
valid_bit = 0x3;
|
||||||
|
// Fastmem doesn't support memchecks, so disable it for all overlapping virtual pages.
|
||||||
|
if (PowerPC::memchecks.OverlapsMemcheck(((batu.BEPI | j) << BAT_INDEX_SHIFT),
|
||||||
|
1 << BAT_INDEX_SHIFT))
|
||||||
|
valid_bit &= ~0x2;
|
||||||
|
|
||||||
// (BEPI | j) == (BEPI & ~BL) | (j & BL).
|
// (BEPI | j) == (BEPI & ~BL) | (j & BL).
|
||||||
bat_table[batu.BEPI | j] = address | valid_bit;
|
bat_table[batu.BEPI | j] = address | valid_bit;
|
||||||
|
|
Loading…
Reference in New Issue