Merge pull request #4961 from aldelaro5/fast-memchecks

Make memory breakpoint faster
This commit is contained in:
Markus Wick 2017-03-02 11:13:18 +01:00 committed by GitHub
commit 521a777ade
8 changed files with 43 additions and 25 deletions

View File

@ -11,8 +11,10 @@
#include "Common/CommonTypes.h"
#include "Common/DebugInterface.h"
#include "Core/Core.h"
#include "Core/PowerPC/JitCommon/JitBase.h"
#include "Core/PowerPC/JitCommon/JitCache.h"
#include "Core/PowerPC/PowerPC.h"
bool BreakPoints::IsAddressBreakPoint(u32 address) const
{
@ -168,13 +170,18 @@ void MemChecks::AddFromStrings(const TMemChecksStr& mc_strings)
void MemChecks::Add(const TMemCheck& memory_check)
{
bool had_any = HasAny();
if (GetMemCheck(memory_check.start_address) == nullptr)
{
bool had_any = HasAny();
bool lock = Core::PauseAndLock(true);
m_mem_checks.push_back(memory_check);
// If this is the first one, clear the JIT cache so it can switch to
// watchpoint-compatible code.
if (!had_any && g_jit)
g_jit->GetBlockCache()->SchedulateClearCacheThreadSafe();
// If this is the first one, clear the JIT cache so it can switch to
// watchpoint-compatible code.
if (!had_any && g_jit)
g_jit->ClearCache();
PowerPC::DBATUpdated();
Core::PauseAndLock(false, lock);
}
}
void MemChecks::Remove(u32 address)
@ -183,9 +190,12 @@ void MemChecks::Remove(u32 address)
{
if (i->start_address == address)
{
bool lock = Core::PauseAndLock(true);
m_mem_checks.erase(i);
if (!HasAny() && g_jit)
g_jit->GetBlockCache()->SchedulateClearCacheThreadSafe();
g_jit->ClearCache();
PowerPC::DBATUpdated();
Core::PauseAndLock(false, lock);
return;
}
}
@ -210,6 +220,25 @@ TMemCheck* MemChecks::GetMemCheck(u32 address)
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,
u32 pc)
{

View File

@ -87,6 +87,7 @@ public:
// memory breakpoint
TMemCheck* GetMemCheck(u32 address);
bool OverlapsMemcheck(u32 address, u32 length);
void Remove(u32 address);
void Clear() { m_mem_checks.clear(); }

View File

@ -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,
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;
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)
{
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
reg_value = FixImmediate(accessSize, reg_value);

View File

@ -46,7 +46,6 @@ bool JitBase::MergeAllowedNextInstructions(int count)
void JitBase::UpdateMemoryOptions()
{
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.alwaysUseMemFuncs = any_watchpoints;
}

View File

@ -52,7 +52,6 @@ protected:
bool accurateSinglePrecision;
bool fastmem;
bool memcheck;
bool alwaysUseMemFuncs;
};
struct JitState
{

View File

@ -29,13 +29,6 @@
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
{
return physical_addresses.lower_bound(address) !=
@ -50,7 +43,6 @@ JitBaseBlockCache::~JitBaseBlockCache() = default;
void JitBaseBlockCache::Init()
{
s_clear_jit_cache_thread_safe = CoreTiming::RegisterEvent("clearJitCache", ClearCacheThreadSafe);
JitRegister::Init(SConfig::GetInstance().m_perfDir);
Clear();
@ -89,11 +81,6 @@ void JitBaseBlockCache::Reset()
Init();
}
void JitBaseBlockCache::SchedulateClearCacheThreadSafe()
{
CoreTiming::ScheduleEvent(0, s_clear_jit_cache_thread_safe, 0, CoreTiming::FromThread::NON_CPU);
}
JitBlock** JitBaseBlockCache::GetFastBlockMap()
{
return fast_block_map.data();

View File

@ -125,7 +125,6 @@ public:
void Shutdown();
void Clear();
void Reset();
void SchedulateClearCacheThreadSafe();
// Code Cache
JitBlock** GetFastBlockMap();

View File

@ -1191,6 +1191,10 @@ static void UpdateBATs(BatTable& bat_table, u32 base_spr)
valid_bit = 0x3;
else if ((address >> 28) == 0xE && (address < (0xE0000000 + Memory::L1_CACHE_SIZE)))
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).
bat_table[batu.BEPI | j] = address | valid_bit;