From 1d5ce4708f99a7b33ce901b0831f05f5ec4c69fe Mon Sep 17 00:00:00 2001 From: Lioncash Date: Mon, 2 Dec 2019 23:19:00 -0500 Subject: [PATCH 1/2] PPCCache: Make use of std::array where applicable Allows simplifying a bunch of initialization and filling code. --- Source/Core/Core/PowerPC/PPCCache.cpp | 41 ++++++++++++++++----------- Source/Core/Core/PowerPC/PPCCache.h | 30 +++++++++++--------- 2 files changed, 41 insertions(+), 30 deletions(-) diff --git a/Source/Core/Core/PowerPC/PPCCache.cpp b/Source/Core/Core/PowerPC/PPCCache.cpp index 551142e173..f914c0e36a 100644 --- a/Source/Core/Core/PowerPC/PPCCache.cpp +++ b/Source/Core/Core/PowerPC/PPCCache.cpp @@ -4,7 +4,7 @@ #include "Core/PowerPC/PPCCache.h" -#include +#include #include "Common/ChunkFile.h" #include "Common/Swap.h" @@ -15,8 +15,15 @@ namespace PowerPC { -static const u32 s_plru_mask[8] = {11, 11, 19, 19, 37, 37, 69, 69}; -static const u32 s_plru_value[8] = {11, 3, 17, 1, 36, 4, 64, 0}; +namespace +{ +constexpr std::array s_plru_mask{ + 11, 11, 19, 19, 37, 37, 69, 69, +}; +constexpr std::array s_plru_value{ + 11, 3, 17, 1, 36, 4, 64, 0, +}; +} // Anonymous namespace InstructionCache::InstructionCache() { @@ -59,19 +66,18 @@ InstructionCache::InstructionCache() void InstructionCache::Reset() { - memset(valid, 0, sizeof(valid)); - memset(plru, 0, sizeof(plru)); - memset(lookup_table, 0xff, sizeof(lookup_table)); - memset(lookup_table_ex, 0xff, sizeof(lookup_table_ex)); - memset(lookup_table_vmem, 0xff, sizeof(lookup_table_vmem)); + valid.fill(0); + plru.fill(0); + lookup_table.fill(0xFF); + lookup_table_ex.fill(0xFF); + lookup_table_vmem.fill(0xFF); JitInterface::ClearSafe(); } void InstructionCache::Init() { - memset(data, 0, sizeof(data)); - memset(tags, 0, sizeof(tags)); - + data.fill({}); + tags.fill({}); Reset(); } @@ -79,10 +85,12 @@ void InstructionCache::Invalidate(u32 addr) { if (!HID0.ICE) return; - // invalidates the whole set - u32 set = (addr >> 5) & 0x7f; - for (int i = 0; i < 8; i++) - if (valid[set] & (1 << i)) + + // Invalidates the whole set + const u32 set = (addr >> 5) & 0x7f; + for (size_t i = 0; i < 8; i++) + { + if (valid[set] & (1U << i)) { if (tags[set][i] & (ICACHE_VMEM_BIT >> 12)) lookup_table_vmem[((tags[set][i] << 7) | set) & 0xfffff] = 0xff; @@ -91,6 +99,7 @@ void InstructionCache::Invalidate(u32 addr) else lookup_table[((tags[set][i] << 7) | set) & 0xfffff] = 0xff; } + } valid[set] = 0; JitInterface::InvalidateICache(addr & ~0x1f, 32, false); } @@ -126,7 +135,7 @@ u32 InstructionCache::ReadInstruction(u32 addr) else t = way_from_plru[plru[set]]; // load - Memory::CopyFromEmu((u8*)data[set][t], (addr & ~0x1f), 32); + Memory::CopyFromEmu(reinterpret_cast(data[set][t].data()), (addr & ~0x1f), 32); if (valid[set] & (1 << t)) { if (tags[set][t] & (ICACHE_VMEM_BIT >> 12)) diff --git a/Source/Core/Core/PowerPC/PPCCache.h b/Source/Core/Core/PowerPC/PPCCache.h index b13dc15284..0298523131 100644 --- a/Source/Core/Core/PowerPC/PPCCache.h +++ b/Source/Core/Core/PowerPC/PPCCache.h @@ -4,33 +4,35 @@ #pragma once +#include + #include "Common/CommonTypes.h" class PointerWrap; namespace PowerPC { -const u32 ICACHE_SETS = 128; -const u32 ICACHE_WAYS = 8; +constexpr u32 ICACHE_SETS = 128; +constexpr u32 ICACHE_WAYS = 8; // size of an instruction cache block in words -const u32 ICACHE_BLOCK_SIZE = 8; +constexpr u32 ICACHE_BLOCK_SIZE = 8; -const u32 ICACHE_EXRAM_BIT = 0x10000000; -const u32 ICACHE_VMEM_BIT = 0x20000000; +constexpr u32 ICACHE_EXRAM_BIT = 0x10000000; +constexpr u32 ICACHE_VMEM_BIT = 0x20000000; struct InstructionCache { - u32 data[ICACHE_SETS][ICACHE_WAYS][ICACHE_BLOCK_SIZE]; - u32 tags[ICACHE_SETS][ICACHE_WAYS]; - u32 plru[ICACHE_SETS]; - u32 valid[ICACHE_SETS]; + std::array, ICACHE_WAYS>, ICACHE_SETS> data; + std::array, ICACHE_SETS> tags; + std::array plru; + std::array valid; - u32 way_from_valid[255]; - u32 way_from_plru[128]; + std::array way_from_valid; + std::array way_from_plru; - u8 lookup_table[1 << 20]; - u8 lookup_table_ex[1 << 21]; - u8 lookup_table_vmem[1 << 20]; + std::array lookup_table; + std::array lookup_table_ex; + std::array lookup_table_vmem; InstructionCache(); u32 ReadInstruction(u32 addr); From 474e210cd585cb40f8ff8f647f1e011329b584c6 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Mon, 2 Dec 2019 23:36:13 -0500 Subject: [PATCH 2/2] PPCCache: Make arrays constexpr where applicable Two of these arrays were stored within the save state when the exact same data is constructed all the time. We can just build this into the binary rather than the save state, shrinking a little bit of the save state's overall size. --- Source/Core/Core/PowerPC/PPCCache.cpp | 103 ++++++++++++++++---------- Source/Core/Core/PowerPC/PPCCache.h | 3 - Source/Core/Core/State.cpp | 2 +- 3 files changed, 65 insertions(+), 43 deletions(-) diff --git a/Source/Core/Core/PowerPC/PPCCache.cpp b/Source/Core/Core/PowerPC/PPCCache.cpp index f914c0e36a..80e74f5a5c 100644 --- a/Source/Core/Core/PowerPC/PPCCache.cpp +++ b/Source/Core/Core/PowerPC/PPCCache.cpp @@ -23,45 +23,72 @@ constexpr std::array s_plru_mask{ constexpr std::array s_plru_value{ 11, 3, 17, 1, 36, 4, 64, 0, }; + +constexpr std::array s_way_from_valid = [] { + std::array data{}; + for (size_t m = 0; m < data.size(); m++) + { + u32 w = 0; + while ((m & (size_t{1} << w)) != 0) + w++; + data[m] = w; + } + return data; +}(); + +constexpr std::array s_way_from_plru = [] { + std::array data{}; + + for (size_t m = 0; m < data.size(); m++) + { + std::array b{}; + for (size_t i = 0; i < b.size(); i++) + b[i] = u32(m & (size_t{1} << i)); + + u32 w = 0; + if (b[0] != 0) + { + if (b[2] != 0) + { + if (b[6] != 0) + w = 7; + else + w = 6; + } + else if (b[5] != 0) + { + w = 5; + } + else + { + w = 4; + } + } + else if (b[1] != 0) + { + if (b[4] != 0) + w = 3; + else + w = 2; + } + else if (b[3] != 0) + { + w = 1; + } + else + { + w = 0; + } + + data[m] = w; + } + + return data; +}(); } // Anonymous namespace InstructionCache::InstructionCache() { - for (u32 m = 0; m < 0xff; m++) - { - u32 w = 0; - while (m & (1 << w)) - w++; - way_from_valid[m] = w; - } - - for (u32 m = 0; m < 128; m++) - { - u32 b[7]; - for (int i = 0; i < 7; i++) - b[i] = m & (1 << i); - u32 w; - if (b[0]) - if (b[2]) - if (b[6]) - w = 7; - else - w = 6; - else if (b[5]) - w = 5; - else - w = 4; - else if (b[1]) - if (b[4]) - w = 3; - else - w = 2; - else if (b[3]) - w = 1; - else - w = 0; - way_from_plru[m] = w; - } } void InstructionCache::Reset() @@ -131,9 +158,9 @@ u32 InstructionCache::ReadInstruction(u32 addr) return Memory::Read_U32(addr); // select a way if (valid[set] != 0xff) - t = way_from_valid[valid[set]]; + t = s_way_from_valid[valid[set]]; else - t = way_from_plru[plru[set]]; + t = s_way_from_plru[plru[set]]; // load Memory::CopyFromEmu(reinterpret_cast(data[set][t].data()), (addr & ~0x1f), 32); if (valid[set] & (1 << t)) @@ -174,8 +201,6 @@ void InstructionCache::DoState(PointerWrap& p) p.DoArray(tags); p.DoArray(plru); p.DoArray(valid); - p.DoArray(way_from_valid); - p.DoArray(way_from_plru); p.DoArray(lookup_table); p.DoArray(lookup_table_ex); p.DoArray(lookup_table_vmem); diff --git a/Source/Core/Core/PowerPC/PPCCache.h b/Source/Core/Core/PowerPC/PPCCache.h index 0298523131..d5220dbde3 100644 --- a/Source/Core/Core/PowerPC/PPCCache.h +++ b/Source/Core/Core/PowerPC/PPCCache.h @@ -27,9 +27,6 @@ struct InstructionCache std::array plru; std::array valid; - std::array way_from_valid; - std::array way_from_plru; - 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 329c1052da..93f0b33318 100644 --- a/Source/Core/Core/State.cpp +++ b/Source/Core/Core/State.cpp @@ -73,7 +73,7 @@ static Common::Event g_compressAndDumpStateSyncEvent; static std::thread g_save_thread; // Don't forget to increase this after doing changes on the savestate system -static const u32 STATE_VERSION = 112; // Last changed in PR 8444 +constexpr u32 STATE_VERSION = 113; // Last changed in PR 8506 // Maps savestate versions to Dolphin versions. // Versions after 42 don't need to be added to this list,