From 3d43fecece99aef1a3008fb73933ab5418104d3c Mon Sep 17 00:00:00 2001 From: MrPurple666 Date: Wed, 2 Apr 2025 02:11:32 -0300 Subject: [PATCH] WIP: DO-NOT-MERGE: NCE experiments: Initial LRU --- src/core/arm/nce/lru_cache.h | 57 ++++++++++++++++++++++++++++++++++++ src/core/arm/nce/patcher.h | 15 +++++++++- 2 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 src/core/arm/nce/lru_cache.h diff --git a/src/core/arm/nce/lru_cache.h b/src/core/arm/nce/lru_cache.h new file mode 100644 index 0000000000..47125922cb --- /dev/null +++ b/src/core/arm/nce/lru_cache.h @@ -0,0 +1,57 @@ +#pragma once + +#include +#include + +template +class LRUCache { +public: + explicit LRUCache(size_t capacity) : capacity(capacity) {} + + ValueType* get(const KeyType& key) { + auto it = cache_map.find(key); + if (it == cache_map.end()) { + return nullptr; + } + + // Move the accessed item to the front of the list (most recently used) + cache_list.splice(cache_list.begin(), cache_list, it->second.first); + return &(it->second.second); + } + + void put(const KeyType& key, const ValueType& value) { + auto it = cache_map.find(key); + + if (it != cache_map.end()) { + // Key exists, update value and move to front + it->second.second = value; + cache_list.splice(cache_list.begin(), cache_list, it->second.first); + return; + } + + // Remove the least recently used item if cache is full + if (cache_map.size() >= capacity) { + auto last = cache_list.back(); + cache_map.erase(last); + cache_list.pop_back(); + } + + // Insert new item at the front + cache_list.push_front(key); + cache_map[key] = {cache_list.begin(), value}; + } + + void clear() { + cache_map.clear(); + cache_list.clear(); + } + + size_t size() const { + return cache_map.size(); + } + +private: + size_t capacity; + std::list cache_list; + std::unordered_map::iterator, ValueType>> cache_map; +}; \ No newline at end of file diff --git a/src/core/arm/nce/patcher.h b/src/core/arm/nce/patcher.h index a44f385e2e..21ea7fd2a1 100644 --- a/src/core/arm/nce/patcher.h +++ b/src/core/arm/nce/patcher.h @@ -13,6 +13,7 @@ #include "core/hle/kernel/code_set.h" #include "core/hle/kernel/k_typed_address.h" #include "core/hle/kernel/physical_memory.h" +#include "lru_cache.h" namespace Core::NCE { @@ -60,8 +61,20 @@ private: void WriteCntpctHandler(ModuleDestLabel module_dest, oaknut::XReg dest_reg); private: + static constexpr size_t CACHE_SIZE = 1024; // Cache size for patch entries + LRUCache patch_cache{CACHE_SIZE}; + void BranchToPatch(uintptr_t module_dest) { - curr_patch->m_branch_to_patch_relocations.push_back({c.offset(), module_dest}); + // Try to get existing patch entry from cache + if (auto* cached_patch = patch_cache.get(module_dest)) { + curr_patch->m_branch_to_patch_relocations.push_back({c.offset(), *cached_patch}); + return; + } + + // If not in cache, create new entry and cache it + const auto patch_addr = c.offset(); + curr_patch->m_branch_to_patch_relocations.push_back({patch_addr, module_dest}); + patch_cache.put(module_dest, patch_addr); } void BranchToModule(uintptr_t module_dest) {