aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMrPurple666 <antoniosacramento666usa@gmail.com>2025-04-02 02:11:32 -0300
committerMrPurple666 <antoniosacramento666usa@gmail.com>2025-04-11 17:05:06 -0300
commit3d43fecece99aef1a3008fb73933ab5418104d3c (patch)
tree9d0b777505db83b0793c4b20c6f9ab6d1f29bb91 /src
parent27ceda2c6cf01b165bc7517343f4e68a258db7a6 (diff)
WIP: DO-NOT-MERGE: NCE experiments: Initial LRU
Diffstat (limited to 'src')
-rw-r--r--src/core/arm/nce/lru_cache.h57
-rw-r--r--src/core/arm/nce/patcher.h15
2 files changed, 71 insertions, 1 deletions
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 <list>
+#include <unordered_map>
+
+template<typename KeyType, typename ValueType>
+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<KeyType> cache_list;
+ std::unordered_map<KeyType, std::pair<typename std::list<KeyType>::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<uintptr_t, PatchTextAddress> 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) {