diff options
| author | lizzie <lizzie@eden-emu.dev> | 2026-03-13 19:09:53 +0100 |
|---|---|---|
| committer | crueter <crueter@eden-emu.dev> | 2026-03-13 19:09:53 +0100 |
| commit | 59b0e667223823f57283b2c6fb1ecc2fd21d96f9 (patch) | |
| tree | 81fa8abd0a14fa6e7ffc291cffb0a833d2c396ba /src/core/memory.cpp | |
| parent | 8de1dd151ffa0549ffa18e5a94e31fb37d5b46f1 (diff) | |
Revert "[core/memory] remove indirection handling for unaligned access (#3584)" (#3725)
This reverts commit 2d273590747cec4716a2e3c293a5b8693abb0403.
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3725
Reviewed-by: DraVee <chimera@dravee.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/memory.cpp')
| -rw-r--r-- | src/core/memory.cpp | 184 |
1 files changed, 101 insertions, 83 deletions
diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 5c2c77e10a..5c57df424c 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -6,7 +6,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include <algorithm> -#include <bit> #include <cstring> #include <mutex> #include <span> @@ -128,14 +127,83 @@ struct Memory::Impl { } } - [[nodiscard]] inline u8* GetPointerFromRasterizerCachedMemory(u64 vaddr) const { - auto const paddr = current_page_table->entries[vaddr >> YUZU_PAGEBITS].addr; - return paddr ? system.DeviceMemory().GetPointer<u8>(paddr + vaddr) : nullptr; + [[nodiscard]] u8* GetPointerFromRasterizerCachedMemory(u64 vaddr) const { + Common::PhysicalAddress const paddr = current_page_table->entries[vaddr >> YUZU_PAGEBITS].addr; + if (paddr) + return system.DeviceMemory().GetPointer<u8>(paddr + vaddr); + return {}; } - [[nodiscard]] inline u8* GetPointerFromDebugMemory(u64 vaddr) const { - auto const paddr = current_page_table->entries[vaddr >> YUZU_PAGEBITS].addr; - return paddr ? system.DeviceMemory().GetPointer<u8>(paddr + vaddr) : nullptr; + [[nodiscard]] u8* GetPointerFromDebugMemory(u64 vaddr) const { + const Common::PhysicalAddress paddr = current_page_table->entries[vaddr >> YUZU_PAGEBITS].addr; + if (paddr != 0) + return system.DeviceMemory().GetPointer<u8>(paddr + vaddr); + return {}; + } + + u8 Read8(const Common::ProcessAddress addr) { + return Read<u8>(addr); + } + + u16 Read16(const Common::ProcessAddress addr) { + if ((addr & 1) == 0) { + return Read<u16_le>(addr); + } else { + const u32 a{Read<u8>(addr)}; + const u32 b{Read<u8>(addr + sizeof(u8))}; + return static_cast<u16>((b << 8) | a); + } + } + + u32 Read32(const Common::ProcessAddress addr) { + if ((addr & 3) == 0) { + return Read<u32_le>(addr); + } else { + const u32 a{Read16(addr)}; + const u32 b{Read16(addr + sizeof(u16))}; + return (b << 16) | a; + } + } + + u64 Read64(const Common::ProcessAddress addr) { + if ((addr & 7) == 0) { + return Read<u64_le>(addr); + } else { + const u32 a{Read32(addr)}; + const u32 b{Read32(addr + sizeof(u32))}; + return (static_cast<u64>(b) << 32) | a; + } + } + + void Write8(const Common::ProcessAddress addr, const u8 data) { + Write<u8>(addr, data); + } + + void Write16(const Common::ProcessAddress addr, const u16 data) { + if ((addr & 1) == 0) { + Write<u16_le>(addr, data); + } else { + Write<u8>(addr, static_cast<u8>(data)); + Write<u8>(addr + sizeof(u8), static_cast<u8>(data >> 8)); + } + } + + void Write32(const Common::ProcessAddress addr, const u32 data) { + if ((addr & 3) == 0) { + Write<u32_le>(addr, data); + } else { + Write16(addr, static_cast<u16>(data)); + Write16(addr + sizeof(u16), static_cast<u16>(data >> 16)); + } + } + + void Write64(const Common::ProcessAddress addr, const u64 data) { + if ((addr & 7) == 0) { + Write<u64_le>(addr, data); + } else { + Write32(addr, static_cast<u32>(data)); + Write32(addr + sizeof(u32), static_cast<u32>(data >> 32)); + } } bool WriteExclusive8(const Common::ProcessAddress addr, const u8 data, const u8 expected) { @@ -590,7 +658,7 @@ struct Memory::Impl { } template<typename F, typename G> - [[nodiscard]] inline u8* GetPointerImpl(u64 vaddr, F&& on_unmapped, G&& on_rasterizer) const { + [[nodiscard]] u8* GetPointerImpl(u64 vaddr, F&& on_unmapped, G&& on_rasterizer) const { // AARCH64 masks the upper 16 bit of all memory accesses vaddr &= 0xffffffffffffULL; if (AddressSpaceContains(*current_page_table, vaddr, 1)) [[likely]] { @@ -645,42 +713,18 @@ struct Memory::Impl { /// @returns The instance of T read from the specified virtual address. template <typename T> inline T Read(Common::ProcessAddress vaddr) noexcept requires(std::is_trivially_copyable_v<T>) { - auto const addr_c1 = GetInteger(vaddr); - if (!(sizeof(T) > 1 && (addr_c1 & 4095) + sizeof(T) > 4096)) { - if (auto const ptr_c1 = GetPointerImpl(addr_c1, [addr_c1] { - LOG_ERROR(HW_Memory, "Unmapped Read{} @ 0x{:016X}", sizeof(T) * 8, addr_c1); - }, [&] { - HandleRasterizerDownload(addr_c1, sizeof(T)); - }); ptr_c1) { - // It may be tempting to rewrite this particular section to use "reinterpret_cast"; - // afterall, it's trivially copyable so surely it can be copied ov- Alignment. - // Remember, alignment. memcpy() will deal with all the alignment extremely fast. - T result{}; - std::memcpy(&result, ptr_c1, sizeof(T)); - return result; - } - } else { - auto const addr_c2 = (addr_c1 & (~0xfff)) + 0x1000; - // page crossing: say if sizeof(T) = 2, vaddr = 4095 - // 4095 + 2 mod 4096 = 1 => 2 - 1 = 1, thus c1=1, c2=1 - auto const count_c2 = (addr_c1 + sizeof(T)) & 4095; - auto const count_c1 = sizeof(T) - count_c2; - if (auto const ptr_c1 = GetPointerImpl(addr_c1, [addr_c1] { - LOG_ERROR(HW_Memory, "Unmapped Read{} @ 0x{:016X}", sizeof(T) * 8, addr_c1); - }, [&] { - HandleRasterizerDownload(addr_c1, count_c1); - }); ptr_c1) { - if (auto const ptr_c2 = GetPointerImpl(addr_c2, [addr_c2] { - LOG_ERROR(HW_Memory, "Unmapped Read{} @ 0x{:016X}", sizeof(T) * 8, addr_c2); - }, [&] { - HandleRasterizerDownload(addr_c2, count_c2); - }); ptr_c2) { - std::array<char, sizeof(T)> result{}; - std::memcpy(result.data() + 0, ptr_c1, count_c1); - std::memcpy(result.data() + count_c1, ptr_c2, count_c2); - return std::bit_cast<T>(result); - } - } + const u64 addr = GetInteger(vaddr); + if (auto const ptr = GetPointerImpl(addr, [addr]() { + LOG_ERROR(HW_Memory, "Unmapped Read{} @ 0x{:016X}", sizeof(T) * 8, addr); + }, [&]() { + HandleRasterizerDownload(addr, sizeof(T)); + }); ptr) [[likely]] { + // It may be tempting to rewrite this particular section to use "reinterpret_cast"; + // afterall, it's trivially copyable so surely it can be copied ov- Alignment. + // Remember, alignment. memcpy() will deal with all the alignment extremely fast. + T result{}; + std::memcpy(&result, ptr, sizeof(T)); + return result; } return T{}; } @@ -690,37 +734,11 @@ struct Memory::Impl { /// @tparam T The data type to write to memory. template <typename T> inline void Write(Common::ProcessAddress vaddr, const T data) noexcept requires(std::is_trivially_copyable_v<T>) { - auto const addr_c1 = GetInteger(vaddr); - if (!(sizeof(T) > 1 && (addr_c1 & 4095) + sizeof(T) > 4096)) { - if (auto const ptr_c1 = GetPointerImpl(addr_c1, [addr_c1] { - LOG_ERROR(HW_Memory, "Unmapped Read{} @ 0x{:016X}", sizeof(T) * 8, addr_c1); - }, [&] { - HandleRasterizerWrite(addr_c1, sizeof(T)); - }); ptr_c1) { - std::memcpy(ptr_c1, &data, sizeof(T)); - } - } else { - auto const addr_c2 = (addr_c1 & (~0xfff)) + 0x1000; - // page crossing: say if sizeof(T) = 2, vaddr = 4095 - // 4095 + 2 mod 4096 = 1 => 2 - 1 = 1, thus c1=1, c2=1 - auto const count_c2 = (addr_c1 + sizeof(T)) & 4095; - auto const count_c1 = sizeof(T) - count_c2; - if (auto const ptr_c1 = GetPointerImpl(addr_c1, [addr_c1] { - LOG_ERROR(HW_Memory, "Unmapped Write{} @ 0x{:016X}", sizeof(T) * 8, addr_c1); - }, [&] { - HandleRasterizerWrite(addr_c1, count_c1); - }); ptr_c1) { - if (auto const ptr_c2 = GetPointerImpl(addr_c2, [addr_c2] { - LOG_ERROR(HW_Memory, "Unmapped Write{} @ 0x{:016X}", sizeof(T) * 8, addr_c2); - }, [&] { - HandleRasterizerWrite(addr_c2, count_c2); - }); ptr_c2) { - std::array<char, sizeof(T)> tmp = std::bit_cast<std::array<char, sizeof(T)>>(data); - std::memcpy(ptr_c1, tmp.data() + 0, count_c1); - std::memcpy(ptr_c2, tmp.data() + count_c1, count_c2); - } - } - } + const u64 addr = GetInteger(vaddr); + if (auto const ptr = GetPointerImpl(addr, [addr, data]() { + LOG_ERROR(HW_Memory, "Unmapped Write{} @ 0x{:016X} = 0x{:016X}", sizeof(T) * 8, addr, u64(data)); + }, [&]() { HandleRasterizerWrite(addr, sizeof(T)); }); ptr) [[likely]] + std::memcpy(ptr, &data, sizeof(T)); } template <typename T> @@ -924,35 +942,35 @@ const u8* Memory::GetPointer(Common::ProcessAddress vaddr) const { } u8 Memory::Read8(const Common::ProcessAddress addr) { - return impl->Read<u8>(addr); + return impl->Read8(addr); } u16 Memory::Read16(const Common::ProcessAddress addr) { - return impl->Read<u16_le>(addr); + return impl->Read16(addr); } u32 Memory::Read32(const Common::ProcessAddress addr) { - return impl->Read<u32_le>(addr); + return impl->Read32(addr); } u64 Memory::Read64(const Common::ProcessAddress addr) { - return impl->Read<u64_le>(addr); + return impl->Read64(addr); } void Memory::Write8(Common::ProcessAddress addr, u8 data) { - impl->Write<u8>(addr, data); + impl->Write8(addr, data); } void Memory::Write16(Common::ProcessAddress addr, u16 data) { - impl->Write<u16_le>(addr, data); + impl->Write16(addr, data); } void Memory::Write32(Common::ProcessAddress addr, u32 data) { - impl->Write<u32_le>(addr, data); + impl->Write32(addr, data); } void Memory::Write64(Common::ProcessAddress addr, u64 data) { - impl->Write<u64_le>(addr, data); + impl->Write64(addr, data); } bool Memory::WriteExclusive8(Common::ProcessAddress addr, u8 data, u8 expected) { |
