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).