diff options
| author | lizzie <lizzie@eden-emu.dev> | 2026-02-12 02:14:50 +0100 |
|---|---|---|
| committer | crueter <crueter@eden-emu.dev> | 2026-02-12 02:14:50 +0100 |
| commit | c263b6af6fd6a164b859075366b8aaa697834146 (patch) | |
| tree | b06b8a19f9c67a219fe09a8b7450cd924200b49d /src/core | |
| parent | e46576b4c3059d74ce76c3449904c491ada692c9 (diff) | |
[dynarmic] add current code page cache (#3459)
should make JIT translation a bit faster - especially for non-fastmem
test if thumb still werks
previously:
we read 32-bits one by one, and do translation **for each u32 we read**
now:
one big read of 4096 bytes (aligned of course), only 1 VAddr translation
Signed-off-by: lizzie <lizzie@eden-emu.dev>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3459
Reviewed-by: DraVee <dravee@eden-emu.dev>
Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
Co-authored-by: lizzie <lizzie@eden-emu.dev>
Co-committed-by: lizzie <lizzie@eden-emu.dev>
Diffstat (limited to 'src/core')
| -rw-r--r-- | src/core/arm/dynarmic/arm_dynarmic_32.cpp | 10 | ||||
| -rw-r--r-- | src/core/arm/dynarmic/arm_dynarmic_32.h | 6 | ||||
| -rw-r--r-- | src/core/arm/dynarmic/arm_dynarmic_64.cpp | 11 | ||||
| -rw-r--r-- | src/core/arm/dynarmic/arm_dynarmic_64.h | 3 | ||||
| -rw-r--r-- | src/core/hle/service/jit/jit_context.cpp | 18 | ||||
| -rw-r--r-- | src/core/memory.cpp | 5 |
6 files changed, 42 insertions, 11 deletions
diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.cpp b/src/core/arm/dynarmic/arm_dynarmic_32.cpp index 0fa4ca6f06..2d8cfb6ed6 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_32.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_32.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project @@ -38,10 +38,16 @@ u64 DynarmicCallbacks32::MemoryRead64(u32 vaddr) { CheckMemoryAccess(vaddr, 8, Kernel::DebugWatchpointType::Read); return m_memory.Read64(vaddr); } + std::optional<u32> DynarmicCallbacks32::MemoryReadCode(u32 vaddr) { if (!m_memory.IsValidVirtualAddressRange(vaddr, sizeof(u32))) return std::nullopt; - return m_memory.Read32(vaddr); + auto const aligned_vaddr = vaddr & ~Core::Memory::YUZU_PAGEMASK; + if (last_code_addr != aligned_vaddr) { + m_memory.ReadBlock(aligned_vaddr, &cached_code_page, sizeof(cached_code_page)); + last_code_addr = aligned_vaddr; + } + return cached_code_page.inst[(vaddr & Core::Memory::YUZU_PAGEMASK) / sizeof(u32)]; } void DynarmicCallbacks32::MemoryWrite8(u32 vaddr, u8 value) { diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.h b/src/core/arm/dynarmic/arm_dynarmic_32.h index 1934934bd9..e19a2deee2 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_32.h +++ b/src/core/arm/dynarmic/arm_dynarmic_32.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project @@ -7,6 +7,7 @@ #pragma once #include <dynarmic/interface/A32/a32.h> +#include <dynarmic/interface/code_page.h> #include "core/arm/arm_interface.h" #include "core/arm/dynarmic/dynarmic_exclusive_monitor.h" @@ -49,6 +50,9 @@ public: u64 GetTicksRemaining() override; bool CheckMemoryAccess(u64 addr, u64 size, Kernel::DebugWatchpointType type); void ReturnException(u32 pc, Dynarmic::HaltReason hr); + // + Dynarmic::CodePage cached_code_page; + u64 last_code_addr = 0; ArmDynarmic32& m_parent; Core::Memory::Memory& m_memory; Kernel::KProcess* m_process{}; diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.cpp b/src/core/arm/dynarmic/arm_dynarmic_64.cpp index 92e1a70458..f13221be8f 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_64.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_64.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project @@ -41,10 +41,17 @@ Dynarmic::A64::Vector DynarmicCallbacks64::MemoryRead128(u64 vaddr) { CheckMemoryAccess(vaddr, 16, Kernel::DebugWatchpointType::Read); return {m_memory.Read64(vaddr), m_memory.Read64(vaddr + 8)}; } + std::optional<u32> DynarmicCallbacks64::MemoryReadCode(u64 vaddr) { if (!m_memory.IsValidVirtualAddressRange(vaddr, sizeof(u32))) return std::nullopt; - return m_memory.Read32(vaddr); +// return m_memory.Read32(vaddr); + auto const aligned_vaddr = vaddr & ~Core::Memory::YUZU_PAGEMASK; + if (last_code_addr != aligned_vaddr) { + m_memory.ReadBlock(aligned_vaddr, &cached_code_page, sizeof(cached_code_page)); + last_code_addr = aligned_vaddr; + } + return cached_code_page.inst[(vaddr & Core::Memory::YUZU_PAGEMASK) / sizeof(u32)]; } void DynarmicCallbacks64::MemoryWrite8(u64 vaddr, u8 value) { diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.h b/src/core/arm/dynarmic/arm_dynarmic_64.h index 07f6bb9449..c8406e544b 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_64.h +++ b/src/core/arm/dynarmic/arm_dynarmic_64.h @@ -11,6 +11,7 @@ #include <ankerl/unordered_dense.h> #include <dynarmic/interface/A64/a64.h> +#include <dynarmic/interface/code_page.h> #include "common/common_types.h" #include "common/hash.h" #include "core/arm/arm_interface.h" @@ -61,6 +62,8 @@ public: bool CheckMemoryAccess(u64 addr, u64 size, Kernel::DebugWatchpointType type); void ReturnException(u64 pc, Dynarmic::HaltReason hr); + Dynarmic::CodePage cached_code_page; + u64 last_code_addr = 0; ArmDynarmic64& m_parent; Core::Memory::Memory& m_memory; u64 m_tpidrro_el0{}; diff --git a/src/core/hle/service/jit/jit_context.cpp b/src/core/hle/service/jit/jit_context.cpp index 8fd7db17c2..447a28e9e7 100644 --- a/src/core/hle/service/jit/jit_context.cpp +++ b/src/core/hle/service/jit/jit_context.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project @@ -10,6 +10,7 @@ #include <boost/icl/interval_set.hpp> #include <dynarmic/interface/A64/a64.h> #include <dynarmic/interface/A64/config.h> +#include <dynarmic/interface/code_page.h> #include "common/alignment.h" #include "common/common_funcs.h" @@ -46,6 +47,15 @@ public: : memory{memory_}, local_memory{local_memory_}, mapped_ranges{mapped_ranges_}, parent{parent_} {} + std::optional<std::uint32_t> MemoryReadCode(VAddr vaddr) override { + static_assert(Core::Memory::YUZU_PAGESIZE == Dynarmic::CODE_PAGE_SIZE); + auto const aligned_vaddr = vaddr & ~Core::Memory::YUZU_PAGEMASK; + if (last_code_addr != aligned_vaddr) { + cached_code_page = ReadMemory<Dynarmic::CodePage>(aligned_vaddr); + last_code_addr = aligned_vaddr; + } + return cached_code_page.inst[(vaddr & Core::Memory::YUZU_PAGEMASK) / sizeof(u32)]; + } u8 MemoryRead8(u64 vaddr) override { return ReadMemory<u8>(vaddr); } @@ -116,8 +126,7 @@ public: return 0; } - template <class T> - T ReadMemory(u64 vaddr) { + template<typename T> T ReadMemory(u64 vaddr) { T ret{}; if (boost::icl::contains(mapped_ranges, vaddr)) { memory.ReadBlock(vaddr, &ret, sizeof(T)); @@ -146,6 +155,9 @@ private: std::vector<u8>& local_memory; IntervalSet& mapped_ranges; JITContextImpl& parent; + + Dynarmic::CodePage cached_code_page; + u64 last_code_addr = 0; }; class JITContextImpl { diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 672676cf12..0550a5bf81 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: 2015 Citra Emulator Project @@ -36,8 +36,7 @@ namespace Core::Memory { -static inline bool AddressSpaceContains(const Common::PageTable& table, const Common::ProcessAddress addr, - const std::size_t size) { +static inline bool AddressSpaceContains(const Common::PageTable& table, const Common::ProcessAddress addr, const std::size_t size) { const Common::ProcessAddress max_addr = 1ULL << table.GetAddressSpaceBits(); return addr + size >= addr && addr + size <= max_addr; } |
