From 9ad6c8f334b07f28633734eb8a240a85c48238a9 Mon Sep 17 00:00:00 2001 From: aldelaro5 Date: Tue, 28 Feb 2017 17:32:17 -0500 Subject: [PATCH] Make memory breakpoint faster Currently, slowmem is used at any time that memory breakpoints are in use. This commit makes it so that whenever the DBAT gets updated, if the address is overllaping any memchecks, it forces the use of slowmem. This allows to keep fastmem for any other cases and noticably increases performance when using memory breakpoints. --- Source/Core/Core/PowerPC/BreakPoints.cpp | 23 +++++++++++++++++-- Source/Core/Core/PowerPC/BreakPoints.h | 1 + .../Core/Core/PowerPC/JitCommon/JitBase.cpp | 2 +- Source/Core/Core/PowerPC/MMU.cpp | 22 +++--------------- 4 files changed, 26 insertions(+), 22 deletions(-) diff --git a/Source/Core/Core/PowerPC/BreakPoints.cpp b/Source/Core/Core/PowerPC/BreakPoints.cpp index 6bca42b4b3..8714efda87 100644 --- a/Source/Core/Core/PowerPC/BreakPoints.cpp +++ b/Source/Core/Core/PowerPC/BreakPoints.cpp @@ -173,8 +173,8 @@ void MemChecks::Add(const TMemCheck& memory_check) if (GetMemCheck(memory_check.start_address) == nullptr) { bool had_any = HasAny(); - m_mem_checks.push_back(memory_check); 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) @@ -190,8 +190,8 @@ void MemChecks::Remove(u32 address) { if (i->start_address == address) { - m_mem_checks.erase(i); bool lock = Core::PauseAndLock(true); + m_mem_checks.erase(i); if (!HasAny() && g_jit) g_jit->ClearCache(); PowerPC::DBATUpdated(); @@ -220,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) { diff --git a/Source/Core/Core/PowerPC/BreakPoints.h b/Source/Core/Core/PowerPC/BreakPoints.h index b9481b5d18..cce1756513 100644 --- a/Source/Core/Core/PowerPC/BreakPoints.h +++ b/Source/Core/Core/PowerPC/BreakPoints.h @@ -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(); } diff --git a/Source/Core/Core/PowerPC/JitCommon/JitBase.cpp b/Source/Core/Core/PowerPC/JitCommon/JitBase.cpp index 0b047fca97..9b0c837610 100644 --- a/Source/Core/Core/PowerPC/JitCommon/JitBase.cpp +++ b/Source/Core/Core/PowerPC/JitCommon/JitBase.cpp @@ -46,6 +46,6 @@ bool JitBase::MergeAllowedNextInstructions(int count) void JitBase::UpdateMemoryOptions() { bool any_watchpoints = PowerPC::memchecks.HasAny(); - jo.fastmem = SConfig::GetInstance().bFastmem; + jo.fastmem = SConfig::GetInstance().bFastmem && (UReg_MSR(MSR).DR || !any_watchpoints); jo.memcheck = SConfig::GetInstance().bMMU || any_watchpoints; } diff --git a/Source/Core/Core/PowerPC/MMU.cpp b/Source/Core/Core/PowerPC/MMU.cpp index 992af28ac7..583d170f43 100644 --- a/Source/Core/Core/PowerPC/MMU.cpp +++ b/Source/Core/Core/PowerPC/MMU.cpp @@ -1132,24 +1132,6 @@ static TranslateAddressResult TranslatePageAddress(const u32 address, const XChe return TranslateAddressResult{TranslateAddressResult::PAGE_FAULT, 0}; } -static bool overlaps_memcheck(u32 pageEndAddress) -{ - if (!memchecks.HasAny()) - return false; - u32 page_end_suffix = ((1 << BAT_INDEX_SHIFT)) - 1; - for (TMemCheck memcheck : memchecks.GetMemChecks()) - { - if (((memcheck.start_address | page_end_suffix) == pageEndAddress || - (memcheck.end_address | page_end_suffix) == pageEndAddress) || - ((memcheck.start_address | page_end_suffix) < pageEndAddress && - (memcheck.end_address | page_end_suffix) > pageEndAddress)) - { - return true; - } - } - return false; -} - static void UpdateBATs(BatTable& bat_table, u32 base_spr) { // TODO: Separate BATs for MSR.PR==0 and MSR.PR==1 @@ -1209,7 +1191,9 @@ 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; - if (overlaps_memcheck(((batu.BEPI | j) << BAT_INDEX_SHIFT) | ((1 << BAT_INDEX_SHIFT) - 1))) + // 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).