[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>
This commit is contained in:
parent
e46576b4c3
commit
c263b6af6f
|
|
@ -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-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
|
||||||
|
|
@ -38,10 +38,16 @@ u64 DynarmicCallbacks32::MemoryRead64(u32 vaddr) {
|
||||||
CheckMemoryAccess(vaddr, 8, Kernel::DebugWatchpointType::Read);
|
CheckMemoryAccess(vaddr, 8, Kernel::DebugWatchpointType::Read);
|
||||||
return m_memory.Read64(vaddr);
|
return m_memory.Read64(vaddr);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<u32> DynarmicCallbacks32::MemoryReadCode(u32 vaddr) {
|
std::optional<u32> DynarmicCallbacks32::MemoryReadCode(u32 vaddr) {
|
||||||
if (!m_memory.IsValidVirtualAddressRange(vaddr, sizeof(u32)))
|
if (!m_memory.IsValidVirtualAddressRange(vaddr, sizeof(u32)))
|
||||||
return std::nullopt;
|
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) {
|
void DynarmicCallbacks32::MemoryWrite8(u32 vaddr, u8 value) {
|
||||||
|
|
|
||||||
|
|
@ -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-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <dynarmic/interface/A32/a32.h>
|
#include <dynarmic/interface/A32/a32.h>
|
||||||
|
#include <dynarmic/interface/code_page.h>
|
||||||
|
|
||||||
#include "core/arm/arm_interface.h"
|
#include "core/arm/arm_interface.h"
|
||||||
#include "core/arm/dynarmic/dynarmic_exclusive_monitor.h"
|
#include "core/arm/dynarmic/dynarmic_exclusive_monitor.h"
|
||||||
|
|
@ -49,6 +50,9 @@ public:
|
||||||
u64 GetTicksRemaining() override;
|
u64 GetTicksRemaining() override;
|
||||||
bool CheckMemoryAccess(u64 addr, u64 size, Kernel::DebugWatchpointType type);
|
bool CheckMemoryAccess(u64 addr, u64 size, Kernel::DebugWatchpointType type);
|
||||||
void ReturnException(u32 pc, Dynarmic::HaltReason hr);
|
void ReturnException(u32 pc, Dynarmic::HaltReason hr);
|
||||||
|
//
|
||||||
|
Dynarmic::CodePage cached_code_page;
|
||||||
|
u64 last_code_addr = 0;
|
||||||
ArmDynarmic32& m_parent;
|
ArmDynarmic32& m_parent;
|
||||||
Core::Memory::Memory& m_memory;
|
Core::Memory::Memory& m_memory;
|
||||||
Kernel::KProcess* m_process{};
|
Kernel::KProcess* m_process{};
|
||||||
|
|
|
||||||
|
|
@ -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-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
||||||
|
|
@ -41,10 +41,17 @@ Dynarmic::A64::Vector DynarmicCallbacks64::MemoryRead128(u64 vaddr) {
|
||||||
CheckMemoryAccess(vaddr, 16, Kernel::DebugWatchpointType::Read);
|
CheckMemoryAccess(vaddr, 16, Kernel::DebugWatchpointType::Read);
|
||||||
return {m_memory.Read64(vaddr), m_memory.Read64(vaddr + 8)};
|
return {m_memory.Read64(vaddr), m_memory.Read64(vaddr + 8)};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<u32> DynarmicCallbacks64::MemoryReadCode(u64 vaddr) {
|
std::optional<u32> DynarmicCallbacks64::MemoryReadCode(u64 vaddr) {
|
||||||
if (!m_memory.IsValidVirtualAddressRange(vaddr, sizeof(u32)))
|
if (!m_memory.IsValidVirtualAddressRange(vaddr, sizeof(u32)))
|
||||||
return std::nullopt;
|
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) {
|
void DynarmicCallbacks64::MemoryWrite8(u64 vaddr, u8 value) {
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@
|
||||||
#include <ankerl/unordered_dense.h>
|
#include <ankerl/unordered_dense.h>
|
||||||
|
|
||||||
#include <dynarmic/interface/A64/a64.h>
|
#include <dynarmic/interface/A64/a64.h>
|
||||||
|
#include <dynarmic/interface/code_page.h>
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "common/hash.h"
|
#include "common/hash.h"
|
||||||
#include "core/arm/arm_interface.h"
|
#include "core/arm/arm_interface.h"
|
||||||
|
|
@ -61,6 +62,8 @@ public:
|
||||||
bool CheckMemoryAccess(u64 addr, u64 size, Kernel::DebugWatchpointType type);
|
bool CheckMemoryAccess(u64 addr, u64 size, Kernel::DebugWatchpointType type);
|
||||||
void ReturnException(u64 pc, Dynarmic::HaltReason hr);
|
void ReturnException(u64 pc, Dynarmic::HaltReason hr);
|
||||||
|
|
||||||
|
Dynarmic::CodePage cached_code_page;
|
||||||
|
u64 last_code_addr = 0;
|
||||||
ArmDynarmic64& m_parent;
|
ArmDynarmic64& m_parent;
|
||||||
Core::Memory::Memory& m_memory;
|
Core::Memory::Memory& m_memory;
|
||||||
u64 m_tpidrro_el0{};
|
u64 m_tpidrro_el0{};
|
||||||
|
|
|
||||||
|
|
@ -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-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
#include <boost/icl/interval_set.hpp>
|
#include <boost/icl/interval_set.hpp>
|
||||||
#include <dynarmic/interface/A64/a64.h>
|
#include <dynarmic/interface/A64/a64.h>
|
||||||
#include <dynarmic/interface/A64/config.h>
|
#include <dynarmic/interface/A64/config.h>
|
||||||
|
#include <dynarmic/interface/code_page.h>
|
||||||
|
|
||||||
#include "common/alignment.h"
|
#include "common/alignment.h"
|
||||||
#include "common/common_funcs.h"
|
#include "common/common_funcs.h"
|
||||||
|
|
@ -46,6 +47,15 @@ public:
|
||||||
: memory{memory_}, local_memory{local_memory_},
|
: memory{memory_}, local_memory{local_memory_},
|
||||||
mapped_ranges{mapped_ranges_}, parent{parent_} {}
|
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 {
|
u8 MemoryRead8(u64 vaddr) override {
|
||||||
return ReadMemory<u8>(vaddr);
|
return ReadMemory<u8>(vaddr);
|
||||||
}
|
}
|
||||||
|
|
@ -116,8 +126,7 @@ public:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template<typename T> T ReadMemory(u64 vaddr) {
|
||||||
T ReadMemory(u64 vaddr) {
|
|
||||||
T ret{};
|
T ret{};
|
||||||
if (boost::icl::contains(mapped_ranges, vaddr)) {
|
if (boost::icl::contains(mapped_ranges, vaddr)) {
|
||||||
memory.ReadBlock(vaddr, &ret, sizeof(T));
|
memory.ReadBlock(vaddr, &ret, sizeof(T));
|
||||||
|
|
@ -146,6 +155,9 @@ private:
|
||||||
std::vector<u8>& local_memory;
|
std::vector<u8>& local_memory;
|
||||||
IntervalSet& mapped_ranges;
|
IntervalSet& mapped_ranges;
|
||||||
JITContextImpl& parent;
|
JITContextImpl& parent;
|
||||||
|
|
||||||
|
Dynarmic::CodePage cached_code_page;
|
||||||
|
u64 last_code_addr = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class JITContextImpl {
|
class JITContextImpl {
|
||||||
|
|
|
||||||
|
|
@ -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-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: 2015 Citra Emulator Project
|
// SPDX-FileCopyrightText: 2015 Citra Emulator Project
|
||||||
|
|
@ -36,8 +36,7 @@
|
||||||
|
|
||||||
namespace Core::Memory {
|
namespace Core::Memory {
|
||||||
|
|
||||||
static inline bool AddressSpaceContains(const Common::PageTable& table, const Common::ProcessAddress addr,
|
static inline bool AddressSpaceContains(const Common::PageTable& table, const Common::ProcessAddress addr, const std::size_t size) {
|
||||||
const std::size_t size) {
|
|
||||||
const Common::ProcessAddress max_addr = 1ULL << table.GetAddressSpaceBits();
|
const Common::ProcessAddress max_addr = 1ULL << table.GetAddressSpaceBits();
|
||||||
return addr + size >= addr && addr + size <= max_addr;
|
return addr + size >= addr && addr + size <= max_addr;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
namespace Dynarmic {
|
||||||
|
|
||||||
|
/// @brief Smallest valid page (may change for Apple?)
|
||||||
|
constexpr inline uint64_t CODE_PAGE_SIZE = 4096;
|
||||||
|
struct CodePage {
|
||||||
|
uint32_t inst[CODE_PAGE_SIZE / sizeof(uint32_t)];
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue