aboutsummaryrefslogtreecommitdiff
path: root/src/core/device_memory_manager.inc
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/device_memory_manager.inc')
-rw-r--r--src/core/device_memory_manager.inc44
1 files changed, 43 insertions, 1 deletions
diff --git a/src/core/device_memory_manager.inc b/src/core/device_memory_manager.inc
index 4be26d9631..08fe799174 100644
--- a/src/core/device_memory_manager.inc
+++ b/src/core/device_memory_manager.inc
@@ -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 2023 yuzu Emulator Project
@@ -247,6 +247,7 @@ void DeviceMemoryManager<Traits>::Map(DAddr address, VAddr virtual_address, size
}
impl->multi_dev_address.Register(new_dev, start_id);
}
+ t_slot = {};
if (track) {
TrackContinuityImpl(address, virtual_address, size, asid);
}
@@ -278,6 +279,7 @@ void DeviceMemoryManager<Traits>::Unmap(DAddr address, size_t size) {
compressed_device_addr[phys_addr - 1] = new_start | MULTI_FLAG;
}
}
+ t_slot = {};
}
template <typename Traits>
void DeviceMemoryManager<Traits>::TrackContinuityImpl(DAddr address, VAddr virtual_address,
@@ -417,6 +419,26 @@ void DeviceMemoryManager<Traits>::WalkBlock(DAddr addr, std::size_t size, auto o
template <typename Traits>
void DeviceMemoryManager<Traits>::ReadBlock(DAddr address, void* dest_pointer, size_t size) {
device_inter->FlushRegion(address, size);
+ const std::size_t page_offset = address & Memory::YUZU_PAGEMASK;
+ if (size <= Memory::YUZU_PAGESIZE - page_offset) {
+ const DAddr guest_page = address & ~static_cast<DAddr>(Memory::YUZU_PAGEMASK);
+ for (size_t i = 0; i < 4; ++i) {
+ if (t_slot[i].guest_page == guest_page && t_slot[i].host_ptr != nullptr) {
+ std::memcpy(dest_pointer, t_slot[i].host_ptr + page_offset, size);
+ return;
+ }
+ }
+
+ const std::size_t page_index = address >> Memory::YUZU_PAGEBITS;
+ const auto phys_addr = compressed_physical_ptr[page_index];
+ if (phys_addr != 0) {
+ auto* const mem_ptr = GetPointerFromRaw<u8>((PAddr(phys_addr - 1) << Memory::YUZU_PAGEBITS));
+ t_slot[cache_cursor % t_slot.size()] = TranslationEntry{.guest_page = guest_page, .host_ptr = mem_ptr};
+ cache_cursor = (cache_cursor + 1) & 3U;
+ std::memcpy(dest_pointer, mem_ptr + page_offset, size);
+ return;
+ }
+ }
WalkBlock(
address, size,
[&](size_t copy_amount, DAddr current_vaddr) {
@@ -455,6 +477,26 @@ void DeviceMemoryManager<Traits>::WriteBlock(DAddr address, const void* src_poin
template <typename Traits>
void DeviceMemoryManager<Traits>::ReadBlockUnsafe(DAddr address, void* dest_pointer, size_t size) {
+ const std::size_t page_offset = address & Memory::YUZU_PAGEMASK;
+ if (size <= Memory::YUZU_PAGESIZE - page_offset) {
+ const DAddr guest_page = address & ~static_cast<DAddr>(Memory::YUZU_PAGEMASK);
+ for (size_t i = 0; i < 4; ++i) {
+ if (t_slot[i].guest_page == guest_page && t_slot[i].host_ptr != nullptr) {
+ std::memcpy(dest_pointer, t_slot[i].host_ptr + page_offset, size);
+ return;
+ }
+ }
+
+ const std::size_t page_index = address >> Memory::YUZU_PAGEBITS;
+ const auto phys_addr = compressed_physical_ptr[page_index];
+ if (phys_addr != 0) {
+ auto* const mem_ptr = GetPointerFromRaw<u8>((PAddr(phys_addr - 1) << Memory::YUZU_PAGEBITS));
+ t_slot[cache_cursor % t_slot.size()] = TranslationEntry{.guest_page = guest_page, .host_ptr = mem_ptr};
+ cache_cursor = (cache_cursor + 1) & 3U;
+ std::memcpy(dest_pointer, mem_ptr + page_offset, size);
+ return;
+ }
+ }
WalkBlock(
address, size,
[&](size_t copy_amount, DAddr current_vaddr) {