From 134397754ecdd1e5d1f4d3404be32af3467622cf Mon Sep 17 00:00:00 2001 From: Pokechu22 Date: Mon, 1 Aug 2022 16:16:11 -0700 Subject: [PATCH] PPCCache: Stop storing lookup table in savestates These lookup tables total 4 megabytes, and contain data that's entirely redundant to the actual cache state (as part of an optimization, though I'm not sure whether the optimization actually is useful). This change instead recomputes these lookup tables when loading the state (which involves filling the lookup table with a marker (0xff), and then setting the 128 * 8 valid entries (1 kilobyte)). --- Source/Core/Core/PowerPC/PPCCache.cpp | 46 +++++++++++++++++++++++++-- Source/Core/Core/PowerPC/PPCCache.h | 2 ++ Source/Core/Core/State.cpp | 2 +- 3 files changed, 46 insertions(+), 4 deletions(-) diff --git a/Source/Core/Core/PowerPC/PPCCache.cpp b/Source/Core/Core/PowerPC/PPCCache.cpp index 9207ea5f72..b70575c04a 100644 --- a/Source/Core/Core/PowerPC/PPCCache.cpp +++ b/Source/Core/Core/PowerPC/PPCCache.cpp @@ -204,13 +204,53 @@ u32 InstructionCache::ReadInstruction(u32 addr) void InstructionCache::DoState(PointerWrap& p) { + if (p.IsReadMode()) + { + // Clear valid parts of the lookup tables (this is done instead of using fill(0xff) to avoid + // loading the entire 4MB of tables into cache) + for (u32 set = 0; set < ICACHE_SETS; set++) + { + for (u32 way = 0; way < ICACHE_WAYS; way++) + { + if ((valid[set] & (1 << way)) != 0) + { + const u32 addr = (tags[set][way] << 12) | (set << 5); + if (addr & ICACHE_VMEM_BIT) + lookup_table_vmem[(addr >> 5) & 0xfffff] = 0xff; + else if (addr & ICACHE_EXRAM_BIT) + lookup_table_ex[(addr >> 5) & 0x1fffff] = 0xff; + else + lookup_table[(addr >> 5) & 0xfffff] = 0xff; + } + } + } + } + p.DoArray(data); p.DoArray(tags); p.DoArray(plru); p.DoArray(valid); - p.DoArray(lookup_table); - p.DoArray(lookup_table_ex); - p.DoArray(lookup_table_vmem); + + if (p.IsReadMode()) + { + // Recompute lookup tables + for (u32 set = 0; set < ICACHE_SETS; set++) + { + for (u32 way = 0; way < ICACHE_WAYS; way++) + { + if ((valid[set] & (1 << way)) != 0) + { + const u32 addr = (tags[set][way] << 12) | (set << 5); + if (addr & ICACHE_VMEM_BIT) + lookup_table_vmem[(addr >> 5) & 0xfffff] = way; + else if (addr & ICACHE_EXRAM_BIT) + lookup_table_ex[(addr >> 5) & 0x1fffff] = way; + else + lookup_table[(addr >> 5) & 0xfffff] = way; + } + } + } + } } void InstructionCache::RefreshConfig() diff --git a/Source/Core/Core/PowerPC/PPCCache.h b/Source/Core/Core/PowerPC/PPCCache.h index 431bc10c41..4b9906ea42 100644 --- a/Source/Core/Core/PowerPC/PPCCache.h +++ b/Source/Core/Core/PowerPC/PPCCache.h @@ -27,6 +27,8 @@ struct InstructionCache std::array plru{}; std::array valid{}; + // Note: This is only for performance purposes; this same data could be computed at runtime + // from the tags and valid fields (and that's how it's done on the actual cache) std::array lookup_table{}; std::array lookup_table_ex{}; std::array lookup_table_vmem{}; diff --git a/Source/Core/Core/State.cpp b/Source/Core/Core/State.cpp index c0ab42a64b..9457ea259a 100644 --- a/Source/Core/Core/State.cpp +++ b/Source/Core/Core/State.cpp @@ -74,7 +74,7 @@ static std::recursive_mutex g_save_thread_mutex; static std::thread g_save_thread; // Don't forget to increase this after doing changes on the savestate system -constexpr u32 STATE_VERSION = 146; // Last changed in PR 10883 +constexpr u32 STATE_VERSION = 147; // Last changed in PR 10935 // Maps savestate versions to Dolphin versions. // Versions after 42 don't need to be added to this list,