diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.cpp b/src/core/arm/dynarmic/arm_dynarmic_32.cpp index 8be0abc4fa..a59aa3cac3 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_32.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_32.cpp @@ -22,21 +22,15 @@ DynarmicCallbacks32::DynarmicCallbacks32(ArmDynarmic32& parent, Kernel::KProcess , m_check_memory_access{m_debugger_enabled || !Settings::values.cpuopt_ignore_memory_aborts.GetValue()} {} -u8 DynarmicCallbacks32::MemoryRead8(u32 vaddr) { - CheckMemoryAccess(vaddr, 1, Kernel::DebugWatchpointType::Read); - return m_memory.Read8(vaddr); -} -u16 DynarmicCallbacks32::MemoryRead16(u32 vaddr) { - CheckMemoryAccess(vaddr, 2, Kernel::DebugWatchpointType::Read); - return m_memory.Read16(vaddr); -} -u32 DynarmicCallbacks32::MemoryRead32(u32 vaddr) { - CheckMemoryAccess(vaddr, 4, Kernel::DebugWatchpointType::Read); - return m_memory.Read32(vaddr); -} -u64 DynarmicCallbacks32::MemoryRead64(u32 vaddr) { - CheckMemoryAccess(vaddr, 8, Kernel::DebugWatchpointType::Read); - return m_memory.Read64(vaddr); +u64 DynarmicCallbacks32::MemoryRead(u32 vaddr, size_t size) { + CheckMemoryAccess(vaddr, size, Kernel::DebugWatchpointType::Read); + switch (size) { + case sizeof(u64): return m_memory.Read64(vaddr); + case sizeof(u32): return m_memory.Read32(vaddr); + case sizeof(u16): return m_memory.Read16(vaddr); + case sizeof(u8): return m_memory.Read8(vaddr); + default: UNREACHABLE(); + } } std::optional DynarmicCallbacks32::MemoryReadCode(u32 vaddr) { @@ -50,27 +44,17 @@ std::optional DynarmicCallbacks32::MemoryReadCode(u32 vaddr) { return cached_code_page.inst[(vaddr & Core::Memory::YUZU_PAGEMASK) / sizeof(u32)]; } -void DynarmicCallbacks32::MemoryWrite8(u32 vaddr, u8 value) { - if (CheckMemoryAccess(vaddr, 1, Kernel::DebugWatchpointType::Write)) { - m_memory.Write8(vaddr, value); - } -} -void DynarmicCallbacks32::MemoryWrite16(u32 vaddr, u16 value) { - if (CheckMemoryAccess(vaddr, 2, Kernel::DebugWatchpointType::Write)) { - m_memory.Write16(vaddr, value); - } -} -void DynarmicCallbacks32::MemoryWrite32(u32 vaddr, u32 value) { - if (CheckMemoryAccess(vaddr, 4, Kernel::DebugWatchpointType::Write)) { - m_memory.Write32(vaddr, value); - } -} -void DynarmicCallbacks32::MemoryWrite64(u32 vaddr, u64 value) { - if (CheckMemoryAccess(vaddr, 8, Kernel::DebugWatchpointType::Write)) { - m_memory.Write64(vaddr, value); +void DynarmicCallbacks32::MemoryWrite(Dynarmic::A32::VAddr vaddr, u64 value, size_t size) { + if (CheckMemoryAccess(vaddr, size, Kernel::DebugWatchpointType::Write)) { + switch (size) { + case sizeof(u64): return m_memory.Write64(vaddr, value); + case sizeof(u32): return m_memory.Write32(vaddr, u32(value)); + case sizeof(u16): return m_memory.Write16(vaddr, u16(value)); + case sizeof(u8): return m_memory.Write8(vaddr, u8(value)); + default: UNREACHABLE(); + } } } - bool DynarmicCallbacks32::MemoryWriteExclusive8(u32 vaddr, u8 value, u8 expected) { return CheckMemoryAccess(vaddr, 1, Kernel::DebugWatchpointType::Write) && m_memory.WriteExclusive8(vaddr, value, expected); diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.h b/src/core/arm/dynarmic/arm_dynarmic_32.h index 623597152f..22655dff47 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_32.h +++ b/src/core/arm/dynarmic/arm_dynarmic_32.h @@ -30,18 +30,12 @@ class System; class DynarmicCallbacks32 : public Dynarmic::A32::UserCallbacks { public: explicit DynarmicCallbacks32(ArmDynarmic32& parent, Kernel::KProcess* process); - u8 MemoryRead8(u32 vaddr) override; - u16 MemoryRead16(u32 vaddr) override; - u32 MemoryRead32(u32 vaddr) override; - u64 MemoryRead64(u32 vaddr) override; + u64 MemoryRead(u32 vaddr, size_t size) override; std::optional MemoryReadCode(u32 vaddr) override; void InstructionSynchronizationBarrierRaised() override { last_code_addr = u64(-1); //reset back, force refetch } - void MemoryWrite8(u32 vaddr, u8 value) override; - void MemoryWrite16(u32 vaddr, u16 value) override; - void MemoryWrite32(u32 vaddr, u32 value) override; - void MemoryWrite64(u32 vaddr, u64 value) override; + void MemoryWrite(Dynarmic::A32::VAddr vaddr, u64 value, size_t size) override; bool MemoryWriteExclusive8(u32 vaddr, u8 value, u8 expected) override; bool MemoryWriteExclusive16(u32 vaddr, u16 value, u16 expected) override; bool MemoryWriteExclusive32(u32 vaddr, u32 value, u32 expected) override; diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.cpp b/src/core/arm/dynarmic/arm_dynarmic_64.cpp index 9db40b9356..894857a86d 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_64.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_64.cpp @@ -10,6 +10,7 @@ #include "core/arm/dynarmic/dynarmic_exclusive_monitor.h" #include "core/core_timing.h" #include "core/hle/kernel/k_process.h" +#include "dynarmic/interface/A64/config.h" namespace Core { @@ -21,21 +22,15 @@ DynarmicCallbacks64::DynarmicCallbacks64(ArmDynarmic64& parent, Kernel::KProcess , m_check_memory_access{m_debugger_enabled || !Settings::values.cpuopt_ignore_memory_aborts.GetValue()} {} -u8 DynarmicCallbacks64::MemoryRead8(u64 vaddr) { - CheckMemoryAccess(vaddr, 1, Kernel::DebugWatchpointType::Read); - return m_memory.Read8(vaddr); -} -u16 DynarmicCallbacks64::MemoryRead16(u64 vaddr) { - CheckMemoryAccess(vaddr, 2, Kernel::DebugWatchpointType::Read); - return m_memory.Read16(vaddr); -} -u32 DynarmicCallbacks64::MemoryRead32(u64 vaddr) { - CheckMemoryAccess(vaddr, 4, Kernel::DebugWatchpointType::Read); - return m_memory.Read32(vaddr); -} -u64 DynarmicCallbacks64::MemoryRead64(u64 vaddr) { - CheckMemoryAccess(vaddr, 8, Kernel::DebugWatchpointType::Read); - return m_memory.Read64(vaddr); +u64 DynarmicCallbacks64::MemoryRead(u64 vaddr, size_t size) { + CheckMemoryAccess(vaddr, size, Kernel::DebugWatchpointType::Read); + switch (size) { + case sizeof(u64): return m_memory.Read64(vaddr); + case sizeof(u32): return m_memory.Read32(vaddr); + case sizeof(u16): return m_memory.Read16(vaddr); + case sizeof(u8): return m_memory.Read8(vaddr); + default: UNREACHABLE(); + } } Dynarmic::A64::Vector DynarmicCallbacks64::MemoryRead128(u64 vaddr) { CheckMemoryAccess(vaddr, 16, Kernel::DebugWatchpointType::Read); @@ -53,24 +48,15 @@ std::optional DynarmicCallbacks64::MemoryReadCode(u64 vaddr) { return cached_code_page.inst[(vaddr & Core::Memory::YUZU_PAGEMASK) / sizeof(u32)]; } -void DynarmicCallbacks64::MemoryWrite8(u64 vaddr, u8 value) { - if (CheckMemoryAccess(vaddr, 1, Kernel::DebugWatchpointType::Write)) { - m_memory.Write8(vaddr, value); - } -} -void DynarmicCallbacks64::MemoryWrite16(u64 vaddr, u16 value) { - if (CheckMemoryAccess(vaddr, 2, Kernel::DebugWatchpointType::Write)) { - m_memory.Write16(vaddr, value); - } -} -void DynarmicCallbacks64::MemoryWrite32(u64 vaddr, u32 value) { - if (CheckMemoryAccess(vaddr, 4, Kernel::DebugWatchpointType::Write)) { - m_memory.Write32(vaddr, value); - } -} -void DynarmicCallbacks64::MemoryWrite64(u64 vaddr, u64 value) { - if (CheckMemoryAccess(vaddr, 8, Kernel::DebugWatchpointType::Write)) { - m_memory.Write64(vaddr, value); +void DynarmicCallbacks64::MemoryWrite(Dynarmic::A64::VAddr vaddr, u64 value, std::size_t size) { + if (CheckMemoryAccess(vaddr, size, Kernel::DebugWatchpointType::Write)) { + switch (size) { + case sizeof(u64): return m_memory.Write64(vaddr, u64(value)); + case sizeof(u32): return m_memory.Write32(vaddr, u32(value)); + case sizeof(u16): return m_memory.Write16(vaddr, u16(value)); + case sizeof(u8): return m_memory.Write8(vaddr, u8(value)); + default: UNREACHABLE(); + } } } void DynarmicCallbacks64::MemoryWrite128(u64 vaddr, Dynarmic::A64::Vector value) { diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.h b/src/core/arm/dynarmic/arm_dynarmic_64.h index 4c8570913f..5ea5dde8a6 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_64.h +++ b/src/core/arm/dynarmic/arm_dynarmic_64.h @@ -16,6 +16,7 @@ #include "common/hash.h" #include "core/arm/arm_interface.h" #include "core/arm/dynarmic/dynarmic_exclusive_monitor.h" +#include "dynarmic/interface/A64/config.h" namespace Core::Memory { class Memory; @@ -36,19 +37,13 @@ class DynarmicCallbacks64 : public Dynarmic::A64::UserCallbacks { public: explicit DynarmicCallbacks64(ArmDynarmic64& parent, Kernel::KProcess* process); - u8 MemoryRead8(u64 vaddr) override; - u16 MemoryRead16(u64 vaddr) override; - u32 MemoryRead32(u64 vaddr) override; - u64 MemoryRead64(u64 vaddr) override; + u64 MemoryRead(u64 vaddr, size_t size) override; Dynarmic::A64::Vector MemoryRead128(u64 vaddr) override; std::optional MemoryReadCode(u64 vaddr) override; void InstructionSynchronizationBarrierRaised() override { last_code_addr = u64(-1); //reset back, force refetch } - void MemoryWrite8(u64 vaddr, u8 value) override; - void MemoryWrite16(u64 vaddr, u16 value) override; - void MemoryWrite32(u64 vaddr, u32 value) override; - void MemoryWrite64(u64 vaddr, u64 value) override; + void MemoryWrite(Dynarmic::A64::VAddr vaddr, u64 value, std::size_t size) override; void MemoryWrite128(u64 vaddr, Dynarmic::A64::Vector value) override; bool MemoryWriteExclusive8(u64 vaddr, std::uint8_t value, std::uint8_t expected) override; bool MemoryWriteExclusive16(u64 vaddr, std::uint16_t value, std::uint16_t expected) override; diff --git a/src/core/hle/service/jit/jit_context.cpp b/src/core/hle/service/jit/jit_context.cpp index 36bf5d6649..e1e8eeadbe 100644 --- a/src/core/hle/service/jit/jit_context.cpp +++ b/src/core/hle/service/jit/jit_context.cpp @@ -71,17 +71,14 @@ public: void InstructionSynchronizationBarrierRaised() override { last_code_addr = u64(-1); //reset back, force refetch } - u8 MemoryRead8(u64 vaddr) override { - return ReadMemory(vaddr); - } - u16 MemoryRead16(u64 vaddr) override { - return ReadMemory(vaddr); - } - u32 MemoryRead32(u64 vaddr) override { - return ReadMemory(vaddr); - } - u64 MemoryRead64(u64 vaddr) override { - return ReadMemory(vaddr); + u64 MemoryRead(u64 vaddr, size_t size) override { + switch (size) { + case sizeof(u64): return ReadMemory(vaddr); + case sizeof(u32): return ReadMemory(vaddr); + case sizeof(u16): return ReadMemory(vaddr); + case sizeof(u8): return ReadMemory(vaddr); + default: UNREACHABLE(); + } } u128 MemoryRead128(u64 vaddr) override { return ReadMemory(vaddr); @@ -89,22 +86,19 @@ public: std::string MemoryReadCString(u64 vaddr) { std::string result{}; u8 next; - while ((next = MemoryRead8(vaddr++)) != 0) + while ((next = u8(MemoryRead(vaddr++, sizeof(u8)))) != 0) result += char(next); return result; } - void MemoryWrite8(u64 vaddr, u8 value) override { - WriteMemory(vaddr, value); - } - void MemoryWrite16(u64 vaddr, u16 value) override { - WriteMemory(vaddr, value); - } - void MemoryWrite32(u64 vaddr, u32 value) override { - WriteMemory(vaddr, value); - } - void MemoryWrite64(u64 vaddr, u64 value) override { - WriteMemory(vaddr, value); + void MemoryWrite(u64 vaddr, u64 value, size_t size) override { + switch (size) { + case sizeof(u64): WriteMemory(vaddr, u64(value)); break; + case sizeof(u32): WriteMemory(vaddr, u32(value)); break; + case sizeof(u16): WriteMemory(vaddr, u16(value)); break; + case sizeof(u8): WriteMemory(vaddr, u8(value)); break; + default: UNREACHABLE(); + } } void MemoryWrite128(u64 vaddr, u128 value) override { WriteMemory(vaddr, value); @@ -193,14 +187,14 @@ public: // The loaded NRO file has ELF relocations that must be processed before it can run. // Normally this would be processed by RTLD, but in HLE context, we don't have // the linker available, so we have to do it ourselves. - const VAddr mod_offset{callbacks->MemoryRead32(4)}; - if (callbacks->MemoryRead32(mod_offset) != Common::MakeMagic('M', 'O', 'D', '0')) + const VAddr mod_offset{callbacks->MemoryRead(4, sizeof(u32))}; + if (callbacks->MemoryRead(mod_offset, sizeof(u32)) != Common::MakeMagic('M', 'O', 'D', '0')) return false; // For more info about dynamic entries, see the ELF ABI specification: // https://refspecs.linuxbase.org/elf/gabi4+/ch5.dynamic.html // https://refspecs.linuxbase.org/elf/gabi4+/ch4.reloc.html - VAddr dynamic_offset{mod_offset + callbacks->MemoryRead32(mod_offset + 4)}; + VAddr dynamic_offset{mod_offset + callbacks->MemoryRead(mod_offset + 4, sizeof(u32))}; VAddr rela_dyn = 0, relr_dyn = 0; size_t num_rela = 0, num_relr = 0; while (true) { @@ -222,8 +216,8 @@ public: for (size_t i = 0; i < num_rela; i++) { const auto rela{callbacks->ReadMemory(rela_dyn + i * sizeof(Elf64_Rela))}; if (Elf64RelType(rela.r_info) == ElfAArch64Relative) { - const VAddr contents{callbacks->MemoryRead64(rela.r_offset)}; - callbacks->MemoryWrite64(rela.r_offset, contents + rela.r_addend); + const VAddr contents{callbacks->MemoryRead(rela.r_offset, sizeof(u64))}; + callbacks->MemoryWrite(rela.r_offset, contents + rela.r_addend, sizeof(u64)); } } @@ -231,7 +225,7 @@ public: for (size_t i = 0; i < num_relr; i++) { const auto relr = callbacks->ReadMemory(relr_dyn + i * sizeof(Elf64_Relr)); const auto incr = [&](VAddr where) { - callbacks->MemoryWrite64(where, callbacks->MemoryRead64(where) + relocbase); + callbacks->MemoryWrite(where, callbacks->MemoryRead(where, sizeof(u64)) + relocbase, sizeof(u64)); }; if ((relr & 1) == 0) { // where pointer @@ -294,7 +288,7 @@ public: if (argument_stack.size() > 8) { const VAddr new_sp = Common::AlignDown(top_of_stack - (argument_stack.size() - 8) * sizeof(u64), STACK_ALIGN); for (size_t i = 8; i < argument_stack.size(); i++) - callbacks->MemoryWrite64(new_sp + (i - 8) * sizeof(u64), argument_stack[i]); + callbacks->MemoryWrite(new_sp + (i - 8) * sizeof(u64), argument_stack[i], sizeof(u64)); jit->SetSP(new_sp); } // Reset the call state for the next invocation @@ -385,17 +379,17 @@ void DynarmicCallbacks64::CallSVC(u32 swi) { if (dest < src) { for (size_t i = 0; i < n; i++) - MemoryWrite8(dest + i, MemoryRead8(src + i)); + MemoryWrite(dest + i, u8(MemoryRead(src + i, sizeof(u8))), sizeof(u8)); } else { for (size_t i = n; i > 0; i--) - MemoryWrite8(dest + i - 1, MemoryRead8(src + i - 1)); + MemoryWrite(dest + i - 1, u8(MemoryRead(src + i - 1, sizeof(u8))), sizeof(u8)); } } else if (pc == parent.helpers[size_t(HelperFn::Memset)]) { const VAddr dest{parent.jit->GetRegister(0)}; const u64 c{parent.jit->GetRegister(1)}; const size_t n{parent.jit->GetRegister(2)}; for (size_t i = 0; i < n; i++) - MemoryWrite8(dest + i, u8(c)); + MemoryWrite(dest + i, u8(c), sizeof(u8)); } else if (pc == parent.helpers[size_t(HelperFn::Resolve)]) { // X0 contains a char* for a symbol to resolve const auto name{MemoryReadCString(parent.jit->GetRegister(0))}; @@ -422,7 +416,7 @@ void DynarmicCallbacks64::CallSVC(u32 swi) { } void DynarmicCallbacks64::ExceptionRaised(u64 pc, Dynarmic::A64::Exception exception) { - auto const inst = MemoryRead32(pc); + auto const inst = MemoryRead(pc, sizeof(u32)); LOG_CRITICAL(Service_JIT, "{} PC @ {:08x}, data = {:08x}", exception, pc, inst); parent.jit->HaltExecution(); } diff --git a/src/core/tools/freezer.cpp b/src/core/tools/freezer.cpp index 73a86b3c8c..606ac2da42 100644 --- a/src/core/tools/freezer.cpp +++ b/src/core/tools/freezer.cpp @@ -33,18 +33,10 @@ u64 MemoryReadWidth(Core::Memory::Memory& memory, u32 width, VAddr addr) { void MemoryWriteWidth(Core::Memory::Memory& memory, u32 width, VAddr addr, u64 value) { switch (width) { - case 1: - memory.Write8(addr, static_cast(value)); - break; - case 2: - memory.Write16(addr, static_cast(value)); - break; - case 4: - memory.Write32(addr, static_cast(value)); - break; - case 8: - memory.Write64(addr, value); - break; + case sizeof(u64): return memory.Write64(addr, value); + case sizeof(u32): return memory.Write32(addr, u32(value)); + case sizeof(u16): return memory.Write16(addr, u16(value)); + case sizeof(u8): return memory.Write8(addr, u8(value)); default: UNREACHABLE(); } diff --git a/src/dynarmic/src/dynarmic/backend/arm64/a32_address_space.cpp b/src/dynarmic/src/dynarmic/backend/arm64/a32_address_space.cpp index 8b6ec2506e..dc14d16978 100644 --- a/src/dynarmic/src/dynarmic/backend/arm64/a32_address_space.cpp +++ b/src/dynarmic/src/dynarmic/backend/arm64/a32_address_space.cpp @@ -82,7 +82,7 @@ static void* EmitExclusiveReadCallTrampoline(oaknut::CodeGenerator& code, const auto fn = [](const A32::UserConfig& conf, A32::VAddr vaddr) -> T { return conf.global_monitor->ReadAndMark(conf.processor_id, vaddr, [&]() -> T { - return (conf.callbacks->*callback)(vaddr); + return (conf.callbacks->*callback)(vaddr, sizeof(T)); }); }; @@ -136,12 +136,9 @@ static void* EmitExclusiveWriteCallTrampoline(oaknut::CodeGenerator& code, const oaknut::Label l_addr, l_this; auto fn = [](const A32::UserConfig& conf, A32::VAddr vaddr, T value) -> u32 { - return conf.global_monitor->DoExclusiveOperation(conf.processor_id, vaddr, - [&](T expected) -> bool { - return (conf.callbacks->*callback)(vaddr, value, expected); - }) - ? 0 - : 1; + return conf.global_monitor->DoExclusiveOperation(conf.processor_id, vaddr, [&](T expected) -> bool { + return (conf.callbacks->*callback)(vaddr, value, expected); + }) ? 0 : 1; }; void* target = code.xptr(); @@ -179,26 +176,14 @@ void A32AddressSpace::EmitPrelude() { UnprotectCodeMemory(); - prelude_info.read_memory_8 = EmitCallTrampoline<&A32::UserCallbacks::MemoryRead8>(code, conf.callbacks); - prelude_info.read_memory_16 = EmitCallTrampoline<&A32::UserCallbacks::MemoryRead16>(code, conf.callbacks); - prelude_info.read_memory_32 = EmitCallTrampoline<&A32::UserCallbacks::MemoryRead32>(code, conf.callbacks); - prelude_info.read_memory_64 = EmitCallTrampoline<&A32::UserCallbacks::MemoryRead64>(code, conf.callbacks); - prelude_info.wrapped_read_memory_8 = EmitWrappedReadCallTrampoline<&A32::UserCallbacks::MemoryRead8>(code, conf.callbacks); - prelude_info.wrapped_read_memory_16 = EmitWrappedReadCallTrampoline<&A32::UserCallbacks::MemoryRead16>(code, conf.callbacks); - prelude_info.wrapped_read_memory_32 = EmitWrappedReadCallTrampoline<&A32::UserCallbacks::MemoryRead32>(code, conf.callbacks); - prelude_info.wrapped_read_memory_64 = EmitWrappedReadCallTrampoline<&A32::UserCallbacks::MemoryRead64>(code, conf.callbacks); - prelude_info.exclusive_read_memory_8 = EmitExclusiveReadCallTrampoline<&A32::UserCallbacks::MemoryRead8, u8>(code, conf); - prelude_info.exclusive_read_memory_16 = EmitExclusiveReadCallTrampoline<&A32::UserCallbacks::MemoryRead16, u16>(code, conf); - prelude_info.exclusive_read_memory_32 = EmitExclusiveReadCallTrampoline<&A32::UserCallbacks::MemoryRead32, u32>(code, conf); - prelude_info.exclusive_read_memory_64 = EmitExclusiveReadCallTrampoline<&A32::UserCallbacks::MemoryRead64, u64>(code, conf); - prelude_info.write_memory_8 = EmitCallTrampoline<&A32::UserCallbacks::MemoryWrite8>(code, conf.callbacks); - prelude_info.write_memory_16 = EmitCallTrampoline<&A32::UserCallbacks::MemoryWrite16>(code, conf.callbacks); - prelude_info.write_memory_32 = EmitCallTrampoline<&A32::UserCallbacks::MemoryWrite32>(code, conf.callbacks); - prelude_info.write_memory_64 = EmitCallTrampoline<&A32::UserCallbacks::MemoryWrite64>(code, conf.callbacks); - prelude_info.wrapped_write_memory_8 = EmitWrappedWriteCallTrampoline<&A32::UserCallbacks::MemoryWrite8>(code, conf.callbacks); - prelude_info.wrapped_write_memory_16 = EmitWrappedWriteCallTrampoline<&A32::UserCallbacks::MemoryWrite16>(code, conf.callbacks); - prelude_info.wrapped_write_memory_32 = EmitWrappedWriteCallTrampoline<&A32::UserCallbacks::MemoryWrite32>(code, conf.callbacks); - prelude_info.wrapped_write_memory_64 = EmitWrappedWriteCallTrampoline<&A32::UserCallbacks::MemoryWrite64>(code, conf.callbacks); + prelude_info.read_memory = EmitCallTrampoline<&A32::UserCallbacks::MemoryRead>(code, conf.callbacks); + prelude_info.wrapped_read_memory = EmitWrappedReadCallTrampoline<&A32::UserCallbacks::MemoryRead>(code, conf.callbacks); + prelude_info.exclusive_read_memory_8 = EmitExclusiveReadCallTrampoline<&A32::UserCallbacks::MemoryRead, u8>(code, conf); + prelude_info.exclusive_read_memory_16 = EmitExclusiveReadCallTrampoline<&A32::UserCallbacks::MemoryRead, u16>(code, conf); + prelude_info.exclusive_read_memory_32 = EmitExclusiveReadCallTrampoline<&A32::UserCallbacks::MemoryRead, u32>(code, conf); + prelude_info.exclusive_read_memory_64 = EmitExclusiveReadCallTrampoline<&A32::UserCallbacks::MemoryRead, u64>(code, conf); + prelude_info.write_memory = EmitCallTrampoline<&A32::UserCallbacks::MemoryWrite>(code, conf.callbacks); + prelude_info.wrapped_write_memory = EmitWrappedWriteCallTrampoline<&A32::UserCallbacks::MemoryWrite>(code, conf.callbacks); prelude_info.exclusive_write_memory_8 = EmitExclusiveWriteCallTrampoline<&A32::UserCallbacks::MemoryWriteExclusive8, u8>(code, conf); prelude_info.exclusive_write_memory_16 = EmitExclusiveWriteCallTrampoline<&A32::UserCallbacks::MemoryWriteExclusive16, u16>(code, conf); prelude_info.exclusive_write_memory_32 = EmitExclusiveWriteCallTrampoline<&A32::UserCallbacks::MemoryWriteExclusive32, u32>(code, conf); diff --git a/src/dynarmic/src/dynarmic/backend/arm64/a64_address_space.cpp b/src/dynarmic/src/dynarmic/backend/arm64/a64_address_space.cpp index 2dbb7d2e1d..efb9fc538c 100644 --- a/src/dynarmic/src/dynarmic/backend/arm64/a64_address_space.cpp +++ b/src/dynarmic/src/dynarmic/backend/arm64/a64_address_space.cpp @@ -81,7 +81,7 @@ static void* EmitExclusiveReadCallTrampoline(oaknut::CodeGenerator& code, const auto fn = [](const A64::UserConfig& conf, A64::VAddr vaddr) -> T { return conf.global_monitor->ReadAndMark(conf.processor_id, vaddr, [&]() -> T { - return (conf.callbacks->*callback)(vaddr); + return (conf.callbacks->*callback)(vaddr, sizeof(T)); }); }; @@ -133,14 +133,10 @@ static void* EmitExclusiveWriteCallTrampoline(oaknut::CodeGenerator& code, const using namespace oaknut::util; oaknut::Label l_addr, l_this; - auto fn = [](const A64::UserConfig& conf, A64::VAddr vaddr, T value) -> u32 { - return conf.global_monitor->DoExclusiveOperation(conf.processor_id, vaddr, - [&](T expected) -> bool { - return (conf.callbacks->*callback)(vaddr, value, expected); - }) - ? 0 - : 1; + return conf.global_monitor->DoExclusiveOperation(conf.processor_id, vaddr, [&](T expected) -> bool { + return (conf.callbacks->*callback)(vaddr, value, expected); + }) ? 0 : 1; }; void* target = code.xptr(); @@ -346,30 +342,18 @@ void A64AddressSpace::EmitPrelude() { UnprotectCodeMemory(); - prelude_info.read_memory_8 = EmitCallTrampoline<&A64::UserCallbacks::MemoryRead8>(code, conf.callbacks); - prelude_info.read_memory_16 = EmitCallTrampoline<&A64::UserCallbacks::MemoryRead16>(code, conf.callbacks); - prelude_info.read_memory_32 = EmitCallTrampoline<&A64::UserCallbacks::MemoryRead32>(code, conf.callbacks); - prelude_info.read_memory_64 = EmitCallTrampoline<&A64::UserCallbacks::MemoryRead64>(code, conf.callbacks); + prelude_info.read_memory = EmitCallTrampoline<&A64::UserCallbacks::MemoryRead>(code, conf.callbacks); prelude_info.read_memory_128 = EmitRead128CallTrampoline(code, conf.callbacks); - prelude_info.wrapped_read_memory_8 = EmitWrappedReadCallTrampoline<&A64::UserCallbacks::MemoryRead8>(code, conf.callbacks); - prelude_info.wrapped_read_memory_16 = EmitWrappedReadCallTrampoline<&A64::UserCallbacks::MemoryRead16>(code, conf.callbacks); - prelude_info.wrapped_read_memory_32 = EmitWrappedReadCallTrampoline<&A64::UserCallbacks::MemoryRead32>(code, conf.callbacks); - prelude_info.wrapped_read_memory_64 = EmitWrappedReadCallTrampoline<&A64::UserCallbacks::MemoryRead64>(code, conf.callbacks); + prelude_info.wrapped_read_memory = EmitWrappedReadCallTrampoline<&A64::UserCallbacks::MemoryRead>(code, conf.callbacks); prelude_info.wrapped_read_memory_128 = EmitWrappedRead128CallTrampoline(code, conf.callbacks); - prelude_info.exclusive_read_memory_8 = EmitExclusiveReadCallTrampoline<&A64::UserCallbacks::MemoryRead8, u8>(code, conf); - prelude_info.exclusive_read_memory_16 = EmitExclusiveReadCallTrampoline<&A64::UserCallbacks::MemoryRead16, u16>(code, conf); - prelude_info.exclusive_read_memory_32 = EmitExclusiveReadCallTrampoline<&A64::UserCallbacks::MemoryRead32, u32>(code, conf); - prelude_info.exclusive_read_memory_64 = EmitExclusiveReadCallTrampoline<&A64::UserCallbacks::MemoryRead64, u64>(code, conf); + prelude_info.exclusive_read_memory_8 = EmitExclusiveReadCallTrampoline<&A64::UserCallbacks::MemoryRead, u8>(code, conf); + prelude_info.exclusive_read_memory_16 = EmitExclusiveReadCallTrampoline<&A64::UserCallbacks::MemoryRead, u16>(code, conf); + prelude_info.exclusive_read_memory_32 = EmitExclusiveReadCallTrampoline<&A64::UserCallbacks::MemoryRead, u32>(code, conf); + prelude_info.exclusive_read_memory_64 = EmitExclusiveReadCallTrampoline<&A64::UserCallbacks::MemoryRead, u64>(code, conf); prelude_info.exclusive_read_memory_128 = EmitExclusiveRead128CallTrampoline(code, conf); - prelude_info.write_memory_8 = EmitCallTrampoline<&A64::UserCallbacks::MemoryWrite8>(code, conf.callbacks); - prelude_info.write_memory_16 = EmitCallTrampoline<&A64::UserCallbacks::MemoryWrite16>(code, conf.callbacks); - prelude_info.write_memory_32 = EmitCallTrampoline<&A64::UserCallbacks::MemoryWrite32>(code, conf.callbacks); - prelude_info.write_memory_64 = EmitCallTrampoline<&A64::UserCallbacks::MemoryWrite64>(code, conf.callbacks); + prelude_info.write_memory = EmitCallTrampoline<&A64::UserCallbacks::MemoryWrite>(code, conf.callbacks); prelude_info.write_memory_128 = EmitWrite128CallTrampoline(code, conf.callbacks); - prelude_info.wrapped_write_memory_8 = EmitWrappedWriteCallTrampoline<&A64::UserCallbacks::MemoryWrite8>(code, conf.callbacks); - prelude_info.wrapped_write_memory_16 = EmitWrappedWriteCallTrampoline<&A64::UserCallbacks::MemoryWrite16>(code, conf.callbacks); - prelude_info.wrapped_write_memory_32 = EmitWrappedWriteCallTrampoline<&A64::UserCallbacks::MemoryWrite32>(code, conf.callbacks); - prelude_info.wrapped_write_memory_64 = EmitWrappedWriteCallTrampoline<&A64::UserCallbacks::MemoryWrite64>(code, conf.callbacks); + prelude_info.wrapped_write_memory = EmitWrappedWriteCallTrampoline<&A64::UserCallbacks::MemoryWrite>(code, conf.callbacks); prelude_info.wrapped_write_memory_128 = EmitWrappedWrite128CallTrampoline(code, conf.callbacks); prelude_info.exclusive_write_memory_8 = EmitExclusiveWriteCallTrampoline<&A64::UserCallbacks::MemoryWriteExclusive8, u8>(code, conf); prelude_info.exclusive_write_memory_16 = EmitExclusiveWriteCallTrampoline<&A64::UserCallbacks::MemoryWriteExclusive16, u16>(code, conf); diff --git a/src/dynarmic/src/dynarmic/backend/arm64/address_space.cpp b/src/dynarmic/src/dynarmic/backend/arm64/address_space.cpp index 947c50f4c3..7b83e372e6 100644 --- a/src/dynarmic/src/dynarmic/backend/arm64/address_space.cpp +++ b/src/dynarmic/src/dynarmic/backend/arm64/address_space.cpp @@ -145,32 +145,42 @@ void AddressSpace::Link(EmittedBlockInfo& block_info) { case LinkTarget::ReturnFromRunCode: c.B(prelude_info.return_from_run_code); break; + // { this, vaddr, size } case LinkTarget::ReadMemory8: - c.BL(prelude_info.read_memory_8); + c.LDR(X2, 1); + c.BL(prelude_info.read_memory); break; case LinkTarget::ReadMemory16: - c.BL(prelude_info.read_memory_16); + c.LDR(X2, 2); + c.BL(prelude_info.read_memory); break; case LinkTarget::ReadMemory32: - c.BL(prelude_info.read_memory_32); + c.LDR(X2, 4); + c.BL(prelude_info.read_memory); break; case LinkTarget::ReadMemory64: - c.BL(prelude_info.read_memory_64); + c.LDR(X2, 8); + c.BL(prelude_info.read_memory); break; case LinkTarget::ReadMemory128: c.BL(prelude_info.read_memory_128); break; + // { this, vaddr, size } case LinkTarget::WrappedReadMemory8: - c.BL(prelude_info.wrapped_read_memory_8); + c.LDR(X2, 1); + c.BL(prelude_info.wrapped_read_memory); break; case LinkTarget::WrappedReadMemory16: - c.BL(prelude_info.wrapped_read_memory_16); + c.LDR(X2, 2); + c.BL(prelude_info.wrapped_read_memory); break; case LinkTarget::WrappedReadMemory32: - c.BL(prelude_info.wrapped_read_memory_32); + c.LDR(X2, 4); + c.BL(prelude_info.wrapped_read_memory); break; case LinkTarget::WrappedReadMemory64: - c.BL(prelude_info.wrapped_read_memory_64); + c.LDR(X2, 8); + c.BL(prelude_info.wrapped_read_memory); break; case LinkTarget::WrappedReadMemory128: c.BL(prelude_info.wrapped_read_memory_128); @@ -190,32 +200,41 @@ void AddressSpace::Link(EmittedBlockInfo& block_info) { case LinkTarget::ExclusiveReadMemory128: c.BL(prelude_info.exclusive_read_memory_128); break; + // { this, vaddr, value, size } case LinkTarget::WriteMemory8: - c.BL(prelude_info.write_memory_8); + c.LDR(X3, 1); + c.BL(prelude_info.write_memory); break; case LinkTarget::WriteMemory16: - c.BL(prelude_info.write_memory_16); + c.LDR(X3, 2); + c.BL(prelude_info.write_memory); break; case LinkTarget::WriteMemory32: - c.BL(prelude_info.write_memory_32); + c.LDR(X3, 4); + c.BL(prelude_info.write_memory); break; case LinkTarget::WriteMemory64: - c.BL(prelude_info.write_memory_64); + c.LDR(X3, 8); + c.BL(prelude_info.write_memory); break; case LinkTarget::WriteMemory128: c.BL(prelude_info.write_memory_128); break; case LinkTarget::WrappedWriteMemory8: - c.BL(prelude_info.wrapped_write_memory_8); + c.LDR(X3, 1); + c.BL(prelude_info.wrapped_write_memory); break; case LinkTarget::WrappedWriteMemory16: - c.BL(prelude_info.wrapped_write_memory_16); + c.LDR(X3, 2); + c.BL(prelude_info.wrapped_write_memory); break; case LinkTarget::WrappedWriteMemory32: - c.BL(prelude_info.wrapped_write_memory_32); + c.LDR(X3, 4); + c.BL(prelude_info.wrapped_write_memory); break; case LinkTarget::WrappedWriteMemory64: - c.BL(prelude_info.wrapped_write_memory_64); + c.LDR(X3, 8); + c.BL(prelude_info.wrapped_write_memory); break; case LinkTarget::WrappedWriteMemory128: c.BL(prelude_info.wrapped_write_memory_128); diff --git a/src/dynarmic/src/dynarmic/backend/arm64/address_space.h b/src/dynarmic/src/dynarmic/backend/arm64/address_space.h index 755b05bd02..73e2c94a19 100644 --- a/src/dynarmic/src/dynarmic/backend/arm64/address_space.h +++ b/src/dynarmic/src/dynarmic/backend/arm64/address_space.h @@ -93,30 +93,18 @@ protected: void* return_to_dispatcher; void* return_from_run_code; - void* read_memory_8; - void* read_memory_16; - void* read_memory_32; - void* read_memory_64; + void* read_memory; void* read_memory_128; - void* wrapped_read_memory_8; - void* wrapped_read_memory_16; - void* wrapped_read_memory_32; - void* wrapped_read_memory_64; + void* wrapped_read_memory; void* wrapped_read_memory_128; void* exclusive_read_memory_8; void* exclusive_read_memory_16; void* exclusive_read_memory_32; void* exclusive_read_memory_64; void* exclusive_read_memory_128; - void* write_memory_8; - void* write_memory_16; - void* write_memory_32; - void* write_memory_64; + void* write_memory; void* write_memory_128; - void* wrapped_write_memory_8; - void* wrapped_write_memory_16; - void* wrapped_write_memory_32; - void* wrapped_write_memory_64; + void* wrapped_write_memory; void* wrapped_write_memory_128; void* exclusive_write_memory_8; void* exclusive_write_memory_16; diff --git a/src/dynarmic/src/dynarmic/backend/x64/a32_emit_x64_memory.cpp b/src/dynarmic/src/dynarmic/backend/x64/a32_emit_x64_memory.cpp index f138b5f137..e866b2acd6 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/a32_emit_x64_memory.cpp +++ b/src/dynarmic/src/dynarmic/backend/x64/a32_emit_x64_memory.cpp @@ -31,16 +31,16 @@ using namespace Xbyak::util; void A32EmitX64::GenFastmemFallbacks() { const std::initializer_list idxes{0, 1, 2, 3, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}; const std::array, 4> read_callbacks{{ - {8, Devirtualize<&A32::UserCallbacks::MemoryRead8>(conf.callbacks)}, - {16, Devirtualize<&A32::UserCallbacks::MemoryRead16>(conf.callbacks)}, - {32, Devirtualize<&A32::UserCallbacks::MemoryRead32>(conf.callbacks)}, - {64, Devirtualize<&A32::UserCallbacks::MemoryRead64>(conf.callbacks)}, + {8, Devirtualize<&A32::UserCallbacks::MemoryRead>(conf.callbacks)}, + {16, Devirtualize<&A32::UserCallbacks::MemoryRead>(conf.callbacks)}, + {32, Devirtualize<&A32::UserCallbacks::MemoryRead>(conf.callbacks)}, + {64, Devirtualize<&A32::UserCallbacks::MemoryRead>(conf.callbacks)}, }}; const std::array, 4> write_callbacks{{ - {8, Devirtualize<&A32::UserCallbacks::MemoryWrite8>(conf.callbacks)}, - {16, Devirtualize<&A32::UserCallbacks::MemoryWrite16>(conf.callbacks)}, - {32, Devirtualize<&A32::UserCallbacks::MemoryWrite32>(conf.callbacks)}, - {64, Devirtualize<&A32::UserCallbacks::MemoryWrite64>(conf.callbacks)}, + {8, Devirtualize<&A32::UserCallbacks::MemoryWrite>(conf.callbacks)}, + {16, Devirtualize<&A32::UserCallbacks::MemoryWrite>(conf.callbacks)}, + {32, Devirtualize<&A32::UserCallbacks::MemoryWrite>(conf.callbacks)}, + {64, Devirtualize<&A32::UserCallbacks::MemoryWrite>(conf.callbacks)}, }}; const std::array, 4> exclusive_write_callbacks{{ {8, Devirtualize<&A32::UserCallbacks::MemoryWriteExclusive8>(conf.callbacks)}, @@ -56,12 +56,12 @@ void A32EmitX64::GenFastmemFallbacks() { code.align(); read_fallbacks[std::make_tuple(ordered, bitsize, vaddr_idx, value_idx)] = code.getCurr(); ABI_PushCallerSaveRegistersAndAdjustStackExcept(code, HostLocRegIdx(value_idx)); + // params = { this, vaddr, size } if (vaddr_idx != code.ABI_PARAM2.getIdx()) { code.mov(code.ABI_PARAM2, Xbyak::Reg64{vaddr_idx}); } - if (ordered) { - code.mfence(); - } + code.mov(code.ABI_PARAM3, bitsize / CHAR_BIT); + if (ordered) code.mfence(); callback.EmitCall(code); if (value_idx != code.ABI_RETURN.getIdx()) { code.mov(Xbyak::Reg64{value_idx}, code.ABI_RETURN); @@ -76,6 +76,7 @@ void A32EmitX64::GenFastmemFallbacks() { code.align(); write_fallbacks[std::make_tuple(ordered, bitsize, vaddr_idx, value_idx)] = code.getCurr(); ABI_PushCallerSaveRegistersAndAdjustStack(code); + // params = { this, vaddr, value, size } if (vaddr_idx == code.ABI_PARAM3.getIdx() && value_idx == code.ABI_PARAM2.getIdx()) { code.xchg(code.ABI_PARAM2, code.ABI_PARAM3); } else if (vaddr_idx == code.ABI_PARAM3.getIdx()) { @@ -92,10 +93,9 @@ void A32EmitX64::GenFastmemFallbacks() { } } code.ZeroExtendFrom(bitsize, code.ABI_PARAM3); + code.mov(code.ABI_PARAM4, bitsize / CHAR_BIT); callback.EmitCall(code); - if (ordered) { - code.mfence(); - } + if (ordered) code.mfence(); ABI_PopCallerSaveRegistersAndAdjustStack(code); code.ret(); PerfMapRegister(write_fallbacks[std::make_tuple(ordered, bitsize, vaddr_idx, value_idx)], code.getCurr(), fmt::format("a32_write_fallback_{}", bitsize)); @@ -138,35 +138,35 @@ void A32EmitX64::GenFastmemFallbacks() { #undef Axx void A32EmitX64::EmitA32ReadMemory8(A32EmitContext& ctx, IR::Inst* inst) { - EmitMemoryRead<8, &A32::UserCallbacks::MemoryRead8>(ctx, inst); + EmitMemoryRead<8, &A32::UserCallbacks::MemoryRead>(ctx, inst); } void A32EmitX64::EmitA32ReadMemory16(A32EmitContext& ctx, IR::Inst* inst) { - EmitMemoryRead<16, &A32::UserCallbacks::MemoryRead16>(ctx, inst); + EmitMemoryRead<16, &A32::UserCallbacks::MemoryRead>(ctx, inst); } void A32EmitX64::EmitA32ReadMemory32(A32EmitContext& ctx, IR::Inst* inst) { - EmitMemoryRead<32, &A32::UserCallbacks::MemoryRead32>(ctx, inst); + EmitMemoryRead<32, &A32::UserCallbacks::MemoryRead>(ctx, inst); } void A32EmitX64::EmitA32ReadMemory64(A32EmitContext& ctx, IR::Inst* inst) { - EmitMemoryRead<64, &A32::UserCallbacks::MemoryRead64>(ctx, inst); + EmitMemoryRead<64, &A32::UserCallbacks::MemoryRead>(ctx, inst); } void A32EmitX64::EmitA32WriteMemory8(A32EmitContext& ctx, IR::Inst* inst) { - EmitMemoryWrite<8, &A32::UserCallbacks::MemoryWrite8>(ctx, inst); + EmitMemoryWrite<8, &A32::UserCallbacks::MemoryWrite>(ctx, inst); } void A32EmitX64::EmitA32WriteMemory16(A32EmitContext& ctx, IR::Inst* inst) { - EmitMemoryWrite<16, &A32::UserCallbacks::MemoryWrite16>(ctx, inst); + EmitMemoryWrite<16, &A32::UserCallbacks::MemoryWrite>(ctx, inst); } void A32EmitX64::EmitA32WriteMemory32(A32EmitContext& ctx, IR::Inst* inst) { - EmitMemoryWrite<32, &A32::UserCallbacks::MemoryWrite32>(ctx, inst); + EmitMemoryWrite<32, &A32::UserCallbacks::MemoryWrite>(ctx, inst); } void A32EmitX64::EmitA32WriteMemory64(A32EmitContext& ctx, IR::Inst* inst) { - EmitMemoryWrite<64, &A32::UserCallbacks::MemoryWrite64>(ctx, inst); + EmitMemoryWrite<64, &A32::UserCallbacks::MemoryWrite>(ctx, inst); } void A32EmitX64::EmitA32ClearExclusive(A32EmitContext&, IR::Inst*) { @@ -175,33 +175,33 @@ void A32EmitX64::EmitA32ClearExclusive(A32EmitContext&, IR::Inst*) { void A32EmitX64::EmitA32ExclusiveReadMemory8(A32EmitContext& ctx, IR::Inst* inst) { if (conf.fastmem_exclusive_access) { - EmitExclusiveReadMemoryInline<8, &A32::UserCallbacks::MemoryRead8>(ctx, inst); + EmitExclusiveReadMemoryInline<8, &A32::UserCallbacks::MemoryRead>(ctx, inst); } else { - EmitExclusiveReadMemory<8, &A32::UserCallbacks::MemoryRead8>(ctx, inst); + EmitExclusiveReadMemory<8, &A32::UserCallbacks::MemoryRead>(ctx, inst); } } void A32EmitX64::EmitA32ExclusiveReadMemory16(A32EmitContext& ctx, IR::Inst* inst) { if (conf.fastmem_exclusive_access) { - EmitExclusiveReadMemoryInline<16, &A32::UserCallbacks::MemoryRead16>(ctx, inst); + EmitExclusiveReadMemoryInline<16, &A32::UserCallbacks::MemoryRead>(ctx, inst); } else { - EmitExclusiveReadMemory<16, &A32::UserCallbacks::MemoryRead16>(ctx, inst); + EmitExclusiveReadMemory<16, &A32::UserCallbacks::MemoryRead>(ctx, inst); } } void A32EmitX64::EmitA32ExclusiveReadMemory32(A32EmitContext& ctx, IR::Inst* inst) { if (conf.fastmem_exclusive_access) { - EmitExclusiveReadMemoryInline<32, &A32::UserCallbacks::MemoryRead32>(ctx, inst); + EmitExclusiveReadMemoryInline<32, &A32::UserCallbacks::MemoryRead>(ctx, inst); } else { - EmitExclusiveReadMemory<32, &A32::UserCallbacks::MemoryRead32>(ctx, inst); + EmitExclusiveReadMemory<32, &A32::UserCallbacks::MemoryRead>(ctx, inst); } } void A32EmitX64::EmitA32ExclusiveReadMemory64(A32EmitContext& ctx, IR::Inst* inst) { if (conf.fastmem_exclusive_access) { - EmitExclusiveReadMemoryInline<64, &A32::UserCallbacks::MemoryRead64>(ctx, inst); + EmitExclusiveReadMemoryInline<64, &A32::UserCallbacks::MemoryRead>(ctx, inst); } else { - EmitExclusiveReadMemory<64, &A32::UserCallbacks::MemoryRead64>(ctx, inst); + EmitExclusiveReadMemory<64, &A32::UserCallbacks::MemoryRead>(ctx, inst); } } diff --git a/src/dynarmic/src/dynarmic/backend/x64/a64_emit_x64_memory.cpp b/src/dynarmic/src/dynarmic/backend/x64/a64_emit_x64_memory.cpp index 4b7054b4b2..8bb2fcfa59 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/a64_emit_x64_memory.cpp +++ b/src/dynarmic/src/dynarmic/backend/x64/a64_emit_x64_memory.cpp @@ -115,16 +115,16 @@ void A64EmitX64::GenMemory128Accessors() { void A64EmitX64::GenFastmemFallbacks() { const std::initializer_list idxes{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; const std::array, 4> read_callbacks{{ - {8, Devirtualize<&A64::UserCallbacks::MemoryRead8>(conf.callbacks)}, - {16, Devirtualize<&A64::UserCallbacks::MemoryRead16>(conf.callbacks)}, - {32, Devirtualize<&A64::UserCallbacks::MemoryRead32>(conf.callbacks)}, - {64, Devirtualize<&A64::UserCallbacks::MemoryRead64>(conf.callbacks)}, + {8, Devirtualize<&A64::UserCallbacks::MemoryRead>(conf.callbacks)}, + {16, Devirtualize<&A64::UserCallbacks::MemoryRead>(conf.callbacks)}, + {32, Devirtualize<&A64::UserCallbacks::MemoryRead>(conf.callbacks)}, + {64, Devirtualize<&A64::UserCallbacks::MemoryRead>(conf.callbacks)}, }}; const std::array, 4> write_callbacks{{ - {8, Devirtualize<&A64::UserCallbacks::MemoryWrite8>(conf.callbacks)}, - {16, Devirtualize<&A64::UserCallbacks::MemoryWrite16>(conf.callbacks)}, - {32, Devirtualize<&A64::UserCallbacks::MemoryWrite32>(conf.callbacks)}, - {64, Devirtualize<&A64::UserCallbacks::MemoryWrite64>(conf.callbacks)}, + {8, Devirtualize<&A64::UserCallbacks::MemoryWrite>(conf.callbacks)}, + {16, Devirtualize<&A64::UserCallbacks::MemoryWrite>(conf.callbacks)}, + {32, Devirtualize<&A64::UserCallbacks::MemoryWrite>(conf.callbacks)}, + {64, Devirtualize<&A64::UserCallbacks::MemoryWrite>(conf.callbacks)}, }}; const std::array, 4> exclusive_write_callbacks{{ {8, Devirtualize<&A64::UserCallbacks::MemoryWriteExclusive8>(conf.callbacks)}, @@ -204,12 +204,12 @@ void A64EmitX64::GenFastmemFallbacks() { code.align(); read_fallbacks[std::make_tuple(ordered, bitsize, vaddr_idx, value_idx)] = code.getCurr(); ABI_PushCallerSaveRegistersAndAdjustStackExcept(code, HostLocRegIdx(value_idx)); + // params = { this, vaddr, size } if (vaddr_idx != code.ABI_PARAM2.getIdx()) { code.mov(code.ABI_PARAM2, Xbyak::Reg64{vaddr_idx}); } - if (ordered) { - code.mfence(); - } + code.mov(code.ABI_PARAM3, bitsize / CHAR_BIT); + if (ordered) code.mfence(); callback.EmitCall(code); if (value_idx != code.ABI_RETURN.getIdx()) { code.mov(Xbyak::Reg64{value_idx}, code.ABI_RETURN); @@ -224,6 +224,7 @@ void A64EmitX64::GenFastmemFallbacks() { code.align(); write_fallbacks[std::make_tuple(ordered, bitsize, vaddr_idx, value_idx)] = code.getCurr(); ABI_PushCallerSaveRegistersAndAdjustStack(code); + // params = { this, vaddr, value, size } if (vaddr_idx == code.ABI_PARAM3.getIdx() && value_idx == code.ABI_PARAM2.getIdx()) { code.xchg(code.ABI_PARAM2, code.ABI_PARAM3); } else if (vaddr_idx == code.ABI_PARAM3.getIdx()) { @@ -240,10 +241,9 @@ void A64EmitX64::GenFastmemFallbacks() { } } code.ZeroExtendFrom(bitsize, code.ABI_PARAM3); + code.mov(code.ABI_PARAM4, bitsize / CHAR_BIT); callback.EmitCall(code); - if (ordered) { - code.mfence(); - } + if (ordered) code.mfence(); ABI_PopCallerSaveRegistersAndAdjustStack(code); code.ret(); PerfMapRegister(write_fallbacks[std::make_tuple(ordered, bitsize, vaddr_idx, value_idx)], code.getCurr(), fmt::format("a64_write_fallback_{}", bitsize)); @@ -286,19 +286,19 @@ void A64EmitX64::GenFastmemFallbacks() { #undef Axx void A64EmitX64::EmitA64ReadMemory8(A64EmitContext& ctx, IR::Inst* inst) { - EmitMemoryRead<8, &A64::UserCallbacks::MemoryRead8>(ctx, inst); + EmitMemoryRead<8, &A64::UserCallbacks::MemoryRead>(ctx, inst); } void A64EmitX64::EmitA64ReadMemory16(A64EmitContext& ctx, IR::Inst* inst) { - EmitMemoryRead<16, &A64::UserCallbacks::MemoryRead16>(ctx, inst); + EmitMemoryRead<16, &A64::UserCallbacks::MemoryRead>(ctx, inst); } void A64EmitX64::EmitA64ReadMemory32(A64EmitContext& ctx, IR::Inst* inst) { - EmitMemoryRead<32, &A64::UserCallbacks::MemoryRead32>(ctx, inst); + EmitMemoryRead<32, &A64::UserCallbacks::MemoryRead>(ctx, inst); } void A64EmitX64::EmitA64ReadMemory64(A64EmitContext& ctx, IR::Inst* inst) { - EmitMemoryRead<64, &A64::UserCallbacks::MemoryRead64>(ctx, inst); + EmitMemoryRead<64, &A64::UserCallbacks::MemoryRead>(ctx, inst); } void A64EmitX64::EmitA64ReadMemory128(A64EmitContext& ctx, IR::Inst* inst) { @@ -306,23 +306,23 @@ void A64EmitX64::EmitA64ReadMemory128(A64EmitContext& ctx, IR::Inst* inst) { } void A64EmitX64::EmitA64WriteMemory8(A64EmitContext& ctx, IR::Inst* inst) { - EmitMemoryWrite<8, &A64::UserCallbacks::MemoryWrite8>(ctx, inst); + EmitMemoryWrite<8, &A64::UserCallbacks::MemoryWrite>(ctx, inst); } void A64EmitX64::EmitA64WriteMemory16(A64EmitContext& ctx, IR::Inst* inst) { - EmitMemoryWrite<16, &A64::UserCallbacks::MemoryWrite16>(ctx, inst); + EmitMemoryWrite<16, &A64::UserCallbacks::MemoryWrite>(ctx, inst); } void A64EmitX64::EmitA64WriteMemory32(A64EmitContext& ctx, IR::Inst* inst) { - EmitMemoryWrite<32, &A64::UserCallbacks::MemoryWrite32>(ctx, inst); + EmitMemoryWrite<32, &A64::UserCallbacks::MemoryWrite>(ctx, inst); } void A64EmitX64::EmitA64WriteMemory64(A64EmitContext& ctx, IR::Inst* inst) { - EmitMemoryWrite<64, &A64::UserCallbacks::MemoryWrite64>(ctx, inst); + EmitMemoryWrite<64, &A64::UserCallbacks::MemoryWrite>(ctx, inst); } void A64EmitX64::EmitA64WriteMemory128(A64EmitContext& ctx, IR::Inst* inst) { - EmitMemoryWrite<128, &A64::UserCallbacks::MemoryWrite64>(ctx, inst); + EmitMemoryWrite<128, &A64::UserCallbacks::MemoryWrite>(ctx, inst); } void A64EmitX64::EmitA64ClearExclusive(A64EmitContext&, IR::Inst*) { @@ -331,33 +331,33 @@ void A64EmitX64::EmitA64ClearExclusive(A64EmitContext&, IR::Inst*) { void A64EmitX64::EmitA64ExclusiveReadMemory8(A64EmitContext& ctx, IR::Inst* inst) { if (conf.fastmem_exclusive_access) { - EmitExclusiveReadMemoryInline<8, &A64::UserCallbacks::MemoryRead8>(ctx, inst); + EmitExclusiveReadMemoryInline<8, &A64::UserCallbacks::MemoryRead>(ctx, inst); } else { - EmitExclusiveReadMemory<8, &A64::UserCallbacks::MemoryRead8>(ctx, inst); + EmitExclusiveReadMemory<8, &A64::UserCallbacks::MemoryRead>(ctx, inst); } } void A64EmitX64::EmitA64ExclusiveReadMemory16(A64EmitContext& ctx, IR::Inst* inst) { if (conf.fastmem_exclusive_access) { - EmitExclusiveReadMemoryInline<16, &A64::UserCallbacks::MemoryRead16>(ctx, inst); + EmitExclusiveReadMemoryInline<16, &A64::UserCallbacks::MemoryRead>(ctx, inst); } else { - EmitExclusiveReadMemory<16, &A64::UserCallbacks::MemoryRead16>(ctx, inst); + EmitExclusiveReadMemory<16, &A64::UserCallbacks::MemoryRead>(ctx, inst); } } void A64EmitX64::EmitA64ExclusiveReadMemory32(A64EmitContext& ctx, IR::Inst* inst) { if (conf.fastmem_exclusive_access) { - EmitExclusiveReadMemoryInline<32, &A64::UserCallbacks::MemoryRead32>(ctx, inst); + EmitExclusiveReadMemoryInline<32, &A64::UserCallbacks::MemoryRead>(ctx, inst); } else { - EmitExclusiveReadMemory<32, &A64::UserCallbacks::MemoryRead32>(ctx, inst); + EmitExclusiveReadMemory<32, &A64::UserCallbacks::MemoryRead>(ctx, inst); } } void A64EmitX64::EmitA64ExclusiveReadMemory64(A64EmitContext& ctx, IR::Inst* inst) { if (conf.fastmem_exclusive_access) { - EmitExclusiveReadMemoryInline<64, &A64::UserCallbacks::MemoryRead64>(ctx, inst); + EmitExclusiveReadMemoryInline<64, &A64::UserCallbacks::MemoryRead>(ctx, inst); } else { - EmitExclusiveReadMemory<64, &A64::UserCallbacks::MemoryRead64>(ctx, inst); + EmitExclusiveReadMemory<64, &A64::UserCallbacks::MemoryRead>(ctx, inst); } } diff --git a/src/dynarmic/src/dynarmic/backend/x64/emit_x64_memory.cpp.inc b/src/dynarmic/src/dynarmic/backend/x64/emit_x64_memory.cpp.inc index 4fa14d504b..8bb8be3d5b 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/emit_x64_memory.cpp.inc +++ b/src/dynarmic/src/dynarmic/backend/x64/emit_x64_memory.cpp.inc @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + /* This file is part of the dynarmic project. * Copyright (c) 2022 MerryMage * SPDX-License-Identifier: 0BSD @@ -56,16 +59,13 @@ void AxxEmitX64::EmitMemoryRead(AxxEmitContext& ctx, IR::Inst* inst) { // Neither fastmem nor page table: Use callbacks if constexpr (bitsize == 128) { ctx.reg_alloc.HostCall(code, nullptr, {}, args[1]); - if (ordered) { - code.mfence(); - } + if (ordered) code.mfence(); code.CallFunction(memory_read_128); ctx.reg_alloc.DefineValue(code, inst, xmm1); } else { ctx.reg_alloc.HostCall(code, inst, {}, args[1]); - if (ordered) { - code.mfence(); - } + code.mov(code.ABI_PARAM3.cvt32(), bitsize / CHAR_BIT); + if (ordered) code.mfence(); Devirtualize(conf.callbacks).EmitCall(code); code.ZeroExtendFrom(bitsize, code.ABI_RETURN); } @@ -148,12 +148,12 @@ void AxxEmitX64::EmitMemoryWrite(AxxEmitContext& ctx, IR::Inst* inst) { ctx.reg_alloc.HostCall(code, nullptr); code.CallFunction(memory_write_128); } else { + // { this, vaddr, value, size } ctx.reg_alloc.HostCall(code, nullptr, {}, args[1], args[2]); + code.mov(code.ABI_PARAM4.cvt32(), bitsize / CHAR_BIT); Devirtualize(conf.callbacks).EmitCall(code); } - if (ordered) { - code.mfence(); - } + if (ordered) code.mfence(); EmitCheckMemoryAbort(ctx, inst); return; } @@ -230,12 +230,11 @@ void AxxEmitX64::EmitExclusiveReadMemory(AxxEmitContext& ctx, IR::Inst* inst) { if (ordered) { code.mfence(); } - code.CallLambda( - [](AxxUserConfig& conf, Axx::VAddr vaddr) -> T { - return conf.global_monitor->ReadAndMark(conf.processor_id, vaddr, [&]() -> T { - return (conf.callbacks->*callback)(vaddr); - }); + code.CallLambda([](AxxUserConfig& conf, Axx::VAddr vaddr) -> T { + return conf.global_monitor->ReadAndMark(conf.processor_id, vaddr, [&]() -> T { + return (conf.callbacks->*callback)(vaddr, bitsize / CHAR_BIT); }); + }); code.ZeroExtendFrom(bitsize, code.ABI_RETURN); } else { const Xbyak::Xmm result = ctx.reg_alloc.ScratchXmm(code); @@ -250,12 +249,11 @@ void AxxEmitX64::EmitExclusiveReadMemory(AxxEmitContext& ctx, IR::Inst* inst) { if (ordered) { code.mfence(); } - code.CallLambda( - [](AxxUserConfig& conf, Axx::VAddr vaddr, Vector& ret) { - ret = conf.global_monitor->ReadAndMark(conf.processor_id, vaddr, [&]() -> Vector { - return (conf.callbacks->*callback)(vaddr); - }); + code.CallLambda([](AxxUserConfig& conf, Axx::VAddr vaddr, Vector& ret) { + ret = conf.global_monitor->ReadAndMark(conf.processor_id, vaddr, [&]() -> Vector { + return (conf.callbacks->*callback)(vaddr); }); + }); code.movups(result, xword[rsp + ABI_SHADOW_SPACE]); ctx.reg_alloc.ReleaseStackSpace(code, 16 + ABI_SHADOW_SPACE); diff --git a/src/dynarmic/src/dynarmic/interface/A32/config.h b/src/dynarmic/src/dynarmic/interface/A32/config.h index b93b116164..49063ed619 100644 --- a/src/dynarmic/src/dynarmic/interface/A32/config.h +++ b/src/dynarmic/src/dynarmic/interface/A32/config.h @@ -66,7 +66,9 @@ struct UserCallbacks : public TranslateCallbacks { // All reads through this callback are 4-byte aligned. // Memory must be interpreted as little endian. - std::optional MemoryReadCode(VAddr vaddr) override { return MemoryRead32(vaddr); } + std::optional MemoryReadCode(VAddr vaddr) override { + return std::uint32_t(MemoryRead(vaddr, sizeof(std::uint32_t))); + } // This function is called before the instruction at pc is read. // IR code can be emitted by the callee prior to instruction handling. @@ -80,16 +82,10 @@ struct UserCallbacks : public TranslateCallbacks { // Reads through these callbacks may not be aligned. // Memory must be interpreted as if ENDIANSTATE == 0, endianness will be corrected by the JIT. - virtual std::uint8_t MemoryRead8(VAddr vaddr) = 0; - virtual std::uint16_t MemoryRead16(VAddr vaddr) = 0; - virtual std::uint32_t MemoryRead32(VAddr vaddr) = 0; - virtual std::uint64_t MemoryRead64(VAddr vaddr) = 0; + virtual std::uint64_t MemoryRead(VAddr vaddr, std::size_t size) = 0; // Writes through these callbacks may not be aligned. - virtual void MemoryWrite8(VAddr vaddr, std::uint8_t value) = 0; - virtual void MemoryWrite16(VAddr vaddr, std::uint16_t value) = 0; - virtual void MemoryWrite32(VAddr vaddr, std::uint32_t value) = 0; - virtual void MemoryWrite64(VAddr vaddr, std::uint64_t value) = 0; + virtual void MemoryWrite(VAddr vaddr, std::uint64_t value, std::size_t size) = 0; // Writes through these callbacks may not be aligned. virtual bool MemoryWriteExclusive8(VAddr /*vaddr*/, std::uint8_t /*value*/, std::uint8_t /*expected*/) { return false; } diff --git a/src/dynarmic/src/dynarmic/interface/A64/config.h b/src/dynarmic/src/dynarmic/interface/A64/config.h index 818aed73e7..859aeba709 100644 --- a/src/dynarmic/src/dynarmic/interface/A64/config.h +++ b/src/dynarmic/src/dynarmic/interface/A64/config.h @@ -89,20 +89,16 @@ struct UserCallbacks { // All reads through this callback are 4-byte aligned. // Memory must be interpreted as little endian. - virtual std::optional MemoryReadCode(VAddr vaddr) { return MemoryRead32(vaddr); } + virtual std::optional MemoryReadCode(VAddr vaddr) { + return std::uint32_t(MemoryRead(vaddr, sizeof(std::uint32_t))); + } // Reads through these callbacks may not be aligned. - virtual std::uint8_t MemoryRead8(VAddr vaddr) = 0; - virtual std::uint16_t MemoryRead16(VAddr vaddr) = 0; - virtual std::uint32_t MemoryRead32(VAddr vaddr) = 0; - virtual std::uint64_t MemoryRead64(VAddr vaddr) = 0; + virtual std::uint64_t MemoryRead(VAddr vaddr, std::size_t size) = 0; virtual Vector MemoryRead128(VAddr vaddr) = 0; // Writes through these callbacks may not be aligned. - virtual void MemoryWrite8(VAddr vaddr, std::uint8_t value) = 0; - virtual void MemoryWrite16(VAddr vaddr, std::uint16_t value) = 0; - virtual void MemoryWrite32(VAddr vaddr, std::uint32_t value) = 0; - virtual void MemoryWrite64(VAddr vaddr, std::uint64_t value) = 0; + virtual void MemoryWrite(VAddr vaddr, std::uint64_t value, std::size_t size) = 0; virtual void MemoryWrite128(VAddr vaddr, Vector value) = 0; // Writes through these callbacks may not be aligned. diff --git a/src/dynarmic/src/dynarmic/ir/opt_passes.cpp b/src/dynarmic/src/dynarmic/ir/opt_passes.cpp index 02b8e821da..b32bbd517a 100644 --- a/src/dynarmic/src/dynarmic/ir/opt_passes.cpp +++ b/src/dynarmic/src/dynarmic/ir/opt_passes.cpp @@ -40,7 +40,7 @@ static void ConstantMemoryReads(IR::Block& block, A32::UserCallbacks* cb) { if (inst.AreAllArgsImmediates()) { const u32 vaddr = inst.GetArg(1).GetU32(); if (cb->IsReadOnlyMemory(vaddr)) { - const u8 value_from_memory = cb->MemoryRead8(vaddr); + const u8 value_from_memory = u8(cb->MemoryRead(vaddr, sizeof(u8))); inst.ReplaceUsesWith(IR::Value{value_from_memory}); } } @@ -51,7 +51,7 @@ static void ConstantMemoryReads(IR::Block& block, A32::UserCallbacks* cb) { if (inst.AreAllArgsImmediates()) { const u32 vaddr = inst.GetArg(1).GetU32(); if (cb->IsReadOnlyMemory(vaddr)) { - const u16 value_from_memory = cb->MemoryRead16(vaddr); + const u16 value_from_memory = u16(cb->MemoryRead(vaddr, sizeof(u16))); inst.ReplaceUsesWith(IR::Value{value_from_memory}); } } @@ -62,7 +62,7 @@ static void ConstantMemoryReads(IR::Block& block, A32::UserCallbacks* cb) { if (inst.AreAllArgsImmediates()) { const u32 vaddr = inst.GetArg(1).GetU32(); if (cb->IsReadOnlyMemory(vaddr)) { - const u32 value_from_memory = cb->MemoryRead32(vaddr); + const u32 value_from_memory = u32(cb->MemoryRead(vaddr, sizeof(u32))); inst.ReplaceUsesWith(IR::Value{value_from_memory}); } } @@ -73,7 +73,7 @@ static void ConstantMemoryReads(IR::Block& block, A32::UserCallbacks* cb) { if (inst.AreAllArgsImmediates()) { const u32 vaddr = inst.GetArg(1).GetU32(); if (cb->IsReadOnlyMemory(vaddr)) { - const u64 value_from_memory = cb->MemoryRead64(vaddr); + const u64 value_from_memory = u64(cb->MemoryRead(vaddr, sizeof(u64))); inst.ReplaceUsesWith(IR::Value{value_from_memory}); } } diff --git a/src/dynarmic/tests/A32/fuzz_thumb.cpp b/src/dynarmic/tests/A32/fuzz_thumb.cpp index 67a01daf9c..a29b877f3e 100644 --- a/src/dynarmic/tests/A32/fuzz_thumb.cpp +++ b/src/dynarmic/tests/A32/fuzz_thumb.cpp @@ -503,7 +503,7 @@ TEST_CASE("Fuzz Thumb32 instructions set", "[JitX64][Thumb][Thumb32]") { } } -TEST_CASE("Verify fix for off by one error in MemoryRead32 worked", "[Thumb][Thumb16]") { +TEST_CASE("Verify fix for off by one error in MemoryRead<32> worked", "[Thumb][Thumb16]") { ThumbTestEnv test_env; // Prepare test subjects diff --git a/src/dynarmic/tests/A32/test_arm_instructions.cpp b/src/dynarmic/tests/A32/test_arm_instructions.cpp index 5a27cd499c..ee24131386 100644 --- a/src/dynarmic/tests/A32/test_arm_instructions.cpp +++ b/src/dynarmic/tests/A32/test_arm_instructions.cpp @@ -553,9 +553,9 @@ TEST_CASE("arm: Memory access (fastmem)", "[arm][A32]") { memset(backing_memory, 0, memory_size); memcpy(backing_memory + 0x100, "Lorem ipsum dolor sit amet, consectetur adipiscing elit.", 57); - env.MemoryWrite32(0, 0xE5904000); // LDR R4, [R0] - env.MemoryWrite32(4, 0xE5814000); // STR R4, [R1] - env.MemoryWrite32(8, 0xEAFFFFFE); // B . + env.MemoryWrite(0, 0xE5904000, sizeof(u32)); // LDR R4, [R0] + env.MemoryWrite(4, 0xE5814000, sizeof(u32)); // STR R4, [R1] + env.MemoryWrite(8, 0xEAFFFFFE, sizeof(u32)); // B . jit.Regs()[0] = 0x100; jit.Regs()[1] = 0x1F0; jit.Regs()[15] = 0; // PC = 0 diff --git a/src/dynarmic/tests/A32/testenv.h b/src/dynarmic/tests/A32/testenv.h index bebc2566da..a22cc7131e 100644 --- a/src/dynarmic/tests/A32/testenv.h +++ b/src/dynarmic/tests/A32/testenv.h @@ -16,6 +16,7 @@ #include "common/assert.h" #include "common/common_types.h" +#include "dynarmic/frontend/A32/translate/translate_callbacks.h" #include "dynarmic/interface/A32/a32.h" template @@ -59,42 +60,51 @@ public: return infinite_loop_u32; // B . } - std::uint8_t MemoryRead8(u32 vaddr) override { - if (IsInCodeMem(vaddr)) { - return reinterpret_cast(code_mem.data())[vaddr]; + u64 MemoryRead(u32 vaddr, size_t size) override { + switch (size) { + case sizeof(u64): + return MemoryRead(vaddr, sizeof(u32)) + | MemoryRead(vaddr + sizeof(u32), sizeof(u32)) << 32; + case sizeof(u32): + return MemoryRead(vaddr, sizeof(u16)) + | MemoryRead(vaddr + sizeof(u16), sizeof(u16)) << 16; + case sizeof(u16): + return MemoryRead(vaddr, sizeof(u8)) + | MemoryRead(vaddr + sizeof(u8), sizeof(u8)) << 8; + case sizeof(u8): { + if (IsInCodeMem(vaddr)) + return reinterpret_cast(code_mem.data())[vaddr]; + if (auto iter = modified_memory.find(vaddr); iter != modified_memory.end()) + return iter->second; + return u8(vaddr); } - if (auto iter = modified_memory.find(vaddr); iter != modified_memory.end()) { - return iter->second; + default: + std::abort(); } - return static_cast(vaddr); - } - std::uint16_t MemoryRead16(u32 vaddr) override { - return u16(MemoryRead8(vaddr)) | u16(MemoryRead8(vaddr + 1)) << 8; - } - std::uint32_t MemoryRead32(u32 vaddr) override { - return u32(MemoryRead16(vaddr)) | u32(MemoryRead16(vaddr + 2)) << 16; - } - std::uint64_t MemoryRead64(u32 vaddr) override { - return u64(MemoryRead32(vaddr)) | u64(MemoryRead32(vaddr + 4)) << 32; } - void MemoryWrite8(u32 vaddr, std::uint8_t value) override { - if (vaddr < code_mem.size() * sizeof(u32)) { - code_mem_modified_by_guest = true; + void MemoryWrite(Dynarmic::A32::VAddr vaddr, u64 value, size_t size) override { + switch (size) { + case sizeof(u64): + MemoryWrite(vaddr, u32(value), sizeof(u32)); + MemoryWrite(vaddr + 4, u32(value >> 32), sizeof(u32)); + break; + case sizeof(u32): + MemoryWrite(vaddr, u16(value), sizeof(u16)); + MemoryWrite(vaddr + 2, u16(value >> 16), sizeof(u16)); + break; + case sizeof(u16): + MemoryWrite(vaddr, u8(value), sizeof(u8)); + MemoryWrite(vaddr + 1, u8(value >> 8), sizeof(u8)); + break; + case sizeof(u8): + if (vaddr < code_mem.size() * sizeof(u32)) + code_mem_modified_by_guest = true; + modified_memory[vaddr] = value; + break; + default: + std::abort(); } - modified_memory[vaddr] = value; - } - void MemoryWrite16(u32 vaddr, std::uint16_t value) override { - MemoryWrite8(vaddr, static_cast(value)); - MemoryWrite8(vaddr + 1, static_cast(value >> 8)); - } - void MemoryWrite32(u32 vaddr, std::uint32_t value) override { - MemoryWrite16(vaddr, static_cast(value)); - MemoryWrite16(vaddr + 2, static_cast(value >> 16)); - } - void MemoryWrite64(u32 vaddr, std::uint64_t value) override { - MemoryWrite32(vaddr, static_cast(value)); - MemoryWrite32(vaddr + 4, static_cast(value >> 32)); } void CallSVC(std::uint32_t swi) override { @@ -143,46 +153,41 @@ public: return read(vaddr); } - std::uint8_t MemoryRead8(std::uint32_t vaddr) override { - return read(vaddr); - } - std::uint16_t MemoryRead16(std::uint32_t vaddr) override { - return read(vaddr); - } - std::uint32_t MemoryRead32(std::uint32_t vaddr) override { - return read(vaddr); - } - std::uint64_t MemoryRead64(std::uint32_t vaddr) override { - return read(vaddr); + u64 MemoryRead(u32 vaddr, size_t size) override { + switch (size) { + case sizeof(u64): return read(vaddr); + case sizeof(u32): return read(vaddr); + case sizeof(u16): return read(vaddr); + case sizeof(u8): return read(vaddr); + default: + std::abort(); + } } - void MemoryWrite8(std::uint32_t vaddr, std::uint8_t value) override { - write(vaddr, value); - } - void MemoryWrite16(std::uint32_t vaddr, std::uint16_t value) override { - write(vaddr, value); - } - void MemoryWrite32(std::uint32_t vaddr, std::uint32_t value) override { - write(vaddr, value); - } - void MemoryWrite64(std::uint32_t vaddr, std::uint64_t value) override { - write(vaddr, value); + void MemoryWrite(Dynarmic::A32::VAddr vaddr, std::uint64_t value, size_t size) override { + switch (size) { + case sizeof(u64): return write(vaddr, u64(value)); + case sizeof(u32): return write(vaddr, u32(value)); + case sizeof(u16): return write(vaddr, u16(value)); + case sizeof(u8): return write(vaddr, u8(value)); + default: std::abort(); + } } - bool MemoryWriteExclusive8(std::uint32_t vaddr, std::uint8_t value, [[maybe_unused]] std::uint8_t expected) override { - MemoryWrite8(vaddr, value); + bool MemoryWriteExclusive8(Dynarmic::A32::VAddr vaddr, std::uint8_t value, [[maybe_unused]] std::uint8_t expected) override { + MemoryWrite(vaddr, value, sizeof(u8)); return true; } - bool MemoryWriteExclusive16(std::uint32_t vaddr, std::uint16_t value, [[maybe_unused]] std::uint16_t expected) override { - MemoryWrite16(vaddr, value); + bool MemoryWriteExclusive16(Dynarmic::A32::VAddr vaddr, std::uint16_t value, [[maybe_unused]] std::uint16_t expected) override { + MemoryWrite(vaddr, value, sizeof(u16)); return true; } - bool MemoryWriteExclusive32(std::uint32_t vaddr, std::uint32_t value, [[maybe_unused]] std::uint32_t expected) override { - MemoryWrite32(vaddr, value); + bool MemoryWriteExclusive32(Dynarmic::A32::VAddr vaddr, std::uint32_t value, [[maybe_unused]] std::uint32_t expected) override { + MemoryWrite(vaddr, value, sizeof(u32)); return true; } - bool MemoryWriteExclusive64(std::uint32_t vaddr, std::uint64_t value, [[maybe_unused]] std::uint64_t expected) override { - MemoryWrite64(vaddr, value); + bool MemoryWriteExclusive64(Dynarmic::A32::VAddr vaddr, std::uint64_t value, [[maybe_unused]] std::uint64_t expected) override { + MemoryWrite(vaddr, value, sizeof(u64)); return true; } diff --git a/src/dynarmic/tests/A64/a64.cpp b/src/dynarmic/tests/A64/a64.cpp index 99cc9d3d4d..24ddfd4084 100644 --- a/src/dynarmic/tests/A64/a64.cpp +++ b/src/dynarmic/tests/A64/a64.cpp @@ -1006,8 +1006,8 @@ TEST_CASE("A64: 128-bit exclusive read/write", "[a64]") { REQUIRE(jit.GetRegister(1) == 0x7f7e7d7c7b7a7978); REQUIRE(jit.GetRegister(2) == 0x8786858483828180); REQUIRE(jit.GetRegister(4) == 0); - REQUIRE(env.MemoryRead64(0x1234567812345678) == 0xaf00d1e5badcafe0); - REQUIRE(env.MemoryRead64(0x1234567812345680) == 0xd0d0cacad0d0caca); + REQUIRE(env.MemoryRead(0x1234567812345678, sizeof(u64)) == 0xaf00d1e5badcafe0); + REQUIRE(env.MemoryRead(0x1234567812345680, sizeof(u64)) == 0xd0d0cacad0d0caca); } TEST_CASE("A64: CNTPCT_EL0", "[a64]") { @@ -1517,11 +1517,11 @@ TEST_CASE("A64: Memory access (fastmem)", "[a64]") { memset(backing_memory, 0, memory_size); memcpy(backing_memory + 0x100, "Lorem ipsum dolor sit amet, consectetur adipiscing elit.", 57); - env.MemoryWrite32(0, 0xA9401404); // LDP X4, X5, [X0] - env.MemoryWrite32(4, 0xF9400046); // LDR X6, [X2] - env.MemoryWrite32(8, 0xA9001424); // STP X4, X5, [X1] - env.MemoryWrite32(12, 0xF9000066); // STR X6, [X3] - env.MemoryWrite32(16, 0x14000000); // B . + env.MemoryWrite(0, 0xA9401404, sizeof(u32)); // LDP X4, X5, [X0] + env.MemoryWrite(4, 0xF9400046, sizeof(u32)); // LDR X6, [X2] + env.MemoryWrite(8, 0xA9001424, sizeof(u32)); // STP X4, X5, [X1] + env.MemoryWrite(12, 0xF9000066, sizeof(u32)); // STR X6, [X3] + env.MemoryWrite(16, 0x14000000, sizeof(u32)); // B . jit.SetRegister(0, 0x100); jit.SetRegister(1, 0x1F0); jit.SetRegister(2, 0x10F); @@ -1788,8 +1788,8 @@ TEST_CASE("A64: rand3", "[a64]") { memset(backing_memory, 0, memory_size); // cat rand2.txt | awk '{print "env.code_mem.emplace_back(0x"$2"); // "$0}' > rand2-out.tx - env.MemoryWrite32(100, 0x58028edd); // 0000000000000084 58028edd ldr x29, #20952 - env.MemoryWrite32(104, 0x14000000); // 0000000000000ea4 14000000 b #0 + env.MemoryWrite(100, 0x58028edd, sizeof(u32)); // 0000000000000084 58028edd ldr x29, #20952 + env.MemoryWrite(104, 0x14000000, sizeof(u32)); // 0000000000000ea4 14000000 b #0 jit.SetPC(100); jit.SetPstate(0xb0000000); @@ -1824,7 +1824,7 @@ TEST_CASE("A64: rand2", "[a64][.]") { // cat rand2.txt | awk '{print "env.code_mem.emplace_back(0x"$2"); // "$0}' > rand2-out.tx const std::array code32 = {0xea80f352, 0x6e65e59d, 0x1e20c343, 0x2e3a7192, 0x2e267249, 0xd500405f, 0x6f01f461, 0x6eb684fc, 0x58028edd, 0x0ea5f5b6, 0x0ea069fb, 0x2e769517, 0x5e066063, 0x1e65c3f5, 0x4f00ff52, 0x93401cf6, 0x1e274248, 0x6f67aaf5, 0x5e0c0782, 0x5ef43f3c, 0x2e6595b7, 0x4e20590f, 0xb35aa451, 0x6ee2c5ed, 0x4e32bf46, 0x2ea1ba8f, 0x2f68a85e, 0x9237d90a, 0x5e23dd10, 0x0e762e32, 0x4e31a8cf, 0xce1f3360, 0x781a4ac0, 0x13834066, 0x5fa8101c, 0x6f7c5594, 0x0e71bb68, 0xbc0b3e8f, 0x785dbbda, 0x6f51e794, 0xce50af75, 0x1ad728ec, 0x6ee0da4c, 0xb84efa14, 0x2eb3f613, 0x4e287ade, 0x4eb8c734, 0x2e83f4e8, 0x0e397c80, 0xd08f93f8, 0xce718e48, 0x0f672a0d, 0x2e9edd40, 0x0e14128b, 0x6f5942e6, 0x8b3a0f03, 0x3c5d16b9, 0x7f7e3743, 0x4f4c54e4, 0x0ea0a9e9, 0x9e59dbe6, 0x6e7ddcd3, 0xcec08377, 0x9ba759f8, 0x2ea5046e, 0x0e24c569, 0xb8979780, 0x4e31b98c, 0x4efe4f46, 0x4ea7c762, 0x7e61c9c6, 0x6e30c880, 0x1ada0c25, 0x4e603a2f, 0xda9d7218, 0x0d40c5d9, 0x5e214b05, 0x9ba9efc5, 0x5e61b81e, 0x6e7bc31c, 0x0e61a163, 0x9e5832d2, 0x4e772248, 0x4e3d17c8, 0x92624f60, 0x7a1a02dc, 0x79891f65, 0x6eb45036, 0x0e321ee8, 0x4e2566f0, 0x4ea02b9b, 0x0f9dcb3d, 0x2e21b9f9, 0x0e21a8c3, 0xda1700bd, 0x6ea0fb38, 0x7e607a0b, 0x72845817, 0x7f61068e, 0x0d60e529, 0x4ea0ca5c, 0x1a94b20f, 0x8b87419d, 0x7ea9ed71, 0x2ea1a86e, 0x4d40c4da, 0x5ea0eada, 0x784ba96e, 0x7eb6ee02, 0x3db1c710, 0x0e217836, 0x7ee0bb96, 0x4e786c08, 0x4e976a08, 0x489ffe86, 0x4e79fc9b, 0x0e21cbce, 0x5ef7fc65, 0x4ea1286d, 0xd29c771e, 0x6f5c2839, 0x0ea00a9d, 0x6ee44c06, 0x5ee1d858, 0x5ef2fda6, 0x7eb0c9fe, 0x7f762791, 0x2e212ae6, 0x4e61c9db, 0x13003c57, 0x5ee1b8f8, 0x0f2396d2, 0x6ea0db1e, 0x0e71ba82, 0xab29c807, 0x6ef8f8b3, 0x1f18d4a1, 0x0e261d15, 0x1e290081, 0x1b0c7d12, 0x4e7771c3, 0xf845f1e4, 0x4d40c9e8, 0xce778452, 0x6eb9879d, 0x6e21c93d, 0xcec0829f, 0x52a0969f, 0x1e772b4f, 0x7ee1da88, 0x5f52fe0a, 0x7f3387b1, 0x5e214850, 0x1e65c025, 0x0e2ca294, 0x2e614829, 0x1e640077, 0x9e240048, 0x4ebe9537, 0x9bb7925e, 0x38b669c5, 0x2840d089, 0x6f43e648, 0x2e662d28, 0x4eabaff3, 0x6e734cc7, 0x0e31baee, 0x7ee0d93c, 0x5e282bde, 0x7e21bba4, 0x4e6c75fa, 0x5ac01217, 0x7f4304af, 0x1e7878ed, 0x1ada2196, 0x7ee1aba3, 0x93407f3c, 0x4f6c34eb, 0x6e3447a9, 0x7e7ae545, 0x5e0802bb, 0x6eeae63a, 0x7ee1da62, 0x5e280bb3, 0xf81d4009, 0x1e603b21, 0x5e281a14, 0x6eb0a99b, 0x1e266a25, 0x0d60cafe, 0x0e0b6194, 0x7a4ed2c5, 0x92b762ec, 0x4e6b5749, 0x3c16a6e5, 0x4ea0a92b, 0x0fa58b6a, 0x5f76148c, 0x6e30c95f, 0x1e6540fd, 0x5e28e40f, 0x0d403fd4, 0x7e30da36, 0x7fda9b51, 0x2ea04bde, 0x1e25c3d2, 0x1ee0434c, 0x5e21d8e7, 0x5ee1ba51, 0x5e61aba9, 0x4e2849fb, 0x5ee098ea, 0x4e60f63d, 0x0f280443, 0x5ee0da27, 0x2e78a6ce, 0x78054afc, 0x4e14286b, 0x4e218bd8, 0x2a3d2551, 0x3a04017a, 0x5f4317cd, 0x0e604a37, 0x9a834614, 0x0e2edf4d, 0x7a51a0a0, 0x5f8e9043, 0x6ea06bb2, 0xaa2857dd, 0x7a1903fc, 0x301ba9ba, 0x9ac929cd, 0x4e061ff0, 0x2e38fcfc, 0x0e2f614a, 0x7ee0d8e4, 0x6e73afda, 0x7f4156f7, 0x0e6078bf, 0x4ee1d9ed, 0x93403fbe, 0xce6f8640, 0x4e3855e3, 0x6f76fe23, 0x112466e8, 0x1e358a90, 0x7f45272c, 0x6ea19a9d, 0x8a696350, 0x1e3900f6, 0x5e61c866, 0x0e3fbfd0, 0x5ee09ad0, 0x0e651d27, 0x4dffc35e, 0x2e20c6ce, 0x0fbe118d, 0x1e656a15, 0xd1357365, 0x0e20a847, 0xce4a835c, 0x4e203905, 0x2e60090d, 0x7f4a27bb, 0x1e64c316, 0xce7d86a4, 0x7ebded2d, 0x6e70a97e, 0x4eb9a42b, 0x0e209bef, 0x6f151730, 0x0e7e30f7, 0x4e724509, 0xd503375f, 0xce58b6ae, 0x5e21a9b8, 0xcb2ca538, 0x5ac01131, 0x6ea19a24, 0xeb40c8b3, 0xc8df7d65, 0x78108341, 0x3218ab9b, 0x0f3da7dd, 0x2e003089, 0x4e21cab5, 0x8aa5c924, 0x1a94950c, 0x123e506f, 0x13117e37, 0x1ee6005b, 0x5ac00647, 0x5eec8cd5, 0x7ef0fb3d, 0x9223272a, 0x5ee0cb02, 0x6e66071d, 0x6ea1dbbf, 0x5e61c903, 0x5ac015ea, 0x93db6206, 0x7e62b5e3, 0x6ea0c87b, 0xdac0090e, 0x48df7d90, 0x6e206ba5, 0x9e2503c2, 0x6e25fc89, 0x4d60e2db, 0x1e3e22a0, 0x2eb81c19, 0x7856ea00, 0x5fbfb22d, 0x1e630244, 0x4e202a83, 0x1f50a722, 0x7f7b55d2, 0x0fae89b9, 0x4e781d73, 0xce738c3a, 0x4f15a591, 0x6e21c7e1, 0x586ff77e, 0x8a5d3592, 0x93401c67, 0x5e61cb86, 0xce6bc2c1, 0x6e393f10, 0x9bb70ec3, 0xdac0098c, 0x4da84b95, 0x7f494476, 0x9ace5c11, 0x7e61ca14, 0x4f7a60ef, 0x1ad32b39, 0x0ea3777f, 0x5e61da7f, 0x4f1404e2, 0x4e3244e2, 0x6e1b1ceb, 0x0dee5aac, 0x4e2f9dc4, 0x5ea1b8c3, 0x1e59f863, 0xd500403f, 0x4e3ae7d0, 0x4ef5c6ea, 0x08dffe3b, 0x6e36f4f6, 0x2e764f29, 0x0e726f23, 0x5f42375b, 0x7f71fc40, 0x6e618aad, 0x93403e5b, 0x0e205976, 0x0e7250c4, 0x6eb0abc9, 0x2e2049f0, 0x5f14754d, 0x7f6ce468, 0x6f950bbe, 0x6e31aa47, 0x4eb83396, 0x0dccc952, 0x2ea1ca90, 0xce69c701, 0xb0bed69e, 0x7c5dec39, 0x4e2868a2, 0x0e591b08, 0x5f34e6dd, 0x3a449184, 0x5e3ce6de, 0x4ea149b7, 0x4e7ad29b, 0xba198503, 0x1f683e8f, 0xfa52f2a7, 0x6e30dffc, 0x4e6c3d17, 0x2eae3248, 0xd503349f, 0x1e60002c, 0x0f180680, 0x9e240049, 0x6f75774e, 0xa90d8678, 0x9ad924c4, 0x7eb0f85b, 0x0e205aaf, 0x7ee08899, 0x5f4bffd8, 0x1b0ff5f3, 0x4ee11dcd, 0x2e218948, 0x0dcb2733, 0x4eac107c, 0x4ea04a53, 0x4e287b44, 0x0e60b82a, 0x5ee0ebbc, 0xce454ff1, 0x5e1761e7, 0x5e09202f, 0x0e0c0754, 0x1e72e6b9, 0x7e21da70, 0x0fbdb20c, 0x5efb8c84, 0xd500401f, 0x3a47526e, 0x1e680acf, 0x7f7375fc, 0xf80522da, 0x4ee60c02, 0x4d40c2e7, 0x6f89096b, 0x7ee1bb6e, 0x5e280b4a, 0x1e3120c8, 0x7eb2ef96, 0x4fd012dd, 0x0f3027ef, 0x4e2078a8, 0xd503201f, 0x2e2312d9, 0x6ebf1c6e, 0x5ee1f8df, 0x4e607a46, 0x6e30c877, 0x6c09d2d1, 0x4e61abd8, 0x0e35267e, 0x6ac17728, 0x0e861aa0, 0x6f63fe26, 0x6f157628, 0x6f30a5f9, 0x4d60cc0c, 0x4e21cb59, 0x2e68a3fb, 0x7efae601, 0x6ea0f82c, 0x9b25ec12, 0x1a1a0305, 0x0e043fe1, 0x6e73c0ed, 0x6ea1b8c0, 0x7e20380b, 0x0f0534e8, 0x1f56bc7d, 0xba0c0128, 0x1e672160, 0x6e7b259b, 0x7ee07b5d, 0x9a820443, 0x4e040581, 0x2f1d87e8, 0x1acd2f5b, 0x6e20794f, 0x2e6a3c93, 0xc8dffe13, 0xce5ab1c6, 0x6eea55f6, 0x4ea039b3, 0x0d602fec, 0x2e246e2f, 0x7857be39, 0xb80608fb, 0x1e67c017, 0x9bcf7f63, 0x0f92d857, 0x5e0812f7, 0x1e210172, 0x7e6128e9, 0x7ea94d41, 0x981179e1, 0x1effb018, 0x2e600828, 0x0eb9c6b2, 0x6ee1baae, 0x4ea0db28, 0x2ea1487b, 0x4ea6c7f0, 0x2e2374c7, 0x7e30d8dd, 0xb9991fa7, 0x4e791e3e, 0x889f7c4b, 0x0e6c753c, 0x1e740ad1, 0x1e244324, 0x1ef33010, 0x5ac01102, 0x9bd97fba, 0x6e290143, 0x1e2220d8, 0x4d8d5aee, 0x6f28570b, 0xfa4ab0c1, 0xdac00b14, 0x7ea1a90e, 0x2e3027d8, 0x6f25a733, 0x4e61a96e, 0x4e1a2fcb, 0x0e22fe0a, 0xc8df7cd0, 0x5e280a55, 0x4e012b20, 0x7e70dbf4, 0x520c5a4e, 0x6ea6c57f, 0x0e861af8, 0xd503233f, 0x889ffe3c, 0x5e274ea9, 0x4e21a89a, 0x0e170c02, 0x6efd4c0b, 0xd5033ebf, 0x6e61a92c, 0x2e205b72, 0x789fb828, 0x0e626e94, 0x2ea6724c, 0x9a10028b, 0x2c6c51fc, 0x5a9de6b9, 0x6e6881f3, 0x5ee0ea6b, 0x0faec36e, 0x0e955bca, 0x1acf206d, 0x7f6f571b, 0x4e286930, 0x12b41ceb, 0x1e770b7a, 0x0ea18ac2, 0x5e282aaf, 0xf2b7fa1e, 0x1ac34311, 0x13167d11, 0x4ea63412, 0x6e758038, 0x2f1d85d6, 0x0f275480, 0x0ead6c71, 0x6e204b69, 0x1e6303f4, 0x5e0031ef, 0x13001e40, 0x7a16006f, 0x6e6ae4c0, 0x0f0f242f, 0x6e674f50, 0x4e606b7a, 0x7e6ee684, 0x1e6b5957, 0x7ea1bbab, 0x7ea0b6cb, 0xce4da241, 0x0ea1b953, 0x0eb2af4b, 0x9ac309d0, 0x6e61d8bd, 0x5ea0d890, 0x5f47d1e7, 0xfa5981ca, 0x1e7f7959, 0x6ef24dd8, 0x0e0a41d1, 0x5ee0e898, 0x4e6038e2, 0x13097d65, 0x6f839088, 0x9e290265, 0x0e208824, 0x2e65af79, 0x6f36a561, 0x9ad3204b, 0x0e21482e, 0x1e24431d, 0xd50330bf, 0x0df641aa, 0x6e602a83, 0xce30505f, 0x5e025238, 0xd503201f, 0x4e608880, 0x4de9c38d, 0x5e0f5348, 0x6eb48ca9, 0x50fda31b, 0x2e251eec, 0x7842ba50, 0xd8a1cd86, 0x2ea09862, 0x0ea09983, 0x2ea333b0, 0x0ea6032c, 0x4f94801b, 0x7e3ee57d, 0x38135e4f, 0xd8fdd9dd, 0x5ee0fcde, 0x9e64033d, 0x6e37f547, 0x6e3dd7ef, 0x13003f3d, 0x0e602f9f, 0x4e7ad014, 0x9b3b6857, 0x5ea0cb67, 0x0eb31c9f, 0x4e7c5372, 0x5e61b8c0, 0x0ea19b23, 0x0ee6e1df, 0x6e63a626, 0x2f139405, 0x7eb0f96d, 0x9e588c63, 0x2e714c3a, 0x6e8c941e, 0x0f61b331, 0x6f01f625, 0x4e78d4ea, 0x6f403709, 0x1a0300da, 0xda0102c8, 0x7e61d9fd, 0xb89469bb, 0x0c838780, 0x2e60a590, 0x4dfd29e1, 0x4e150f2e, 0xce2810bc, 0x5f541591, 0x9ee60259, 0x2eb40e56, 0x5e014027, 0x2ef71faf, 0x4e2d452f, 0x5ee0a813, 0x4eb03301, 0x38443acf, 0x6eabd502, 0x0e2ee71e, 0x5a960364, 0xce7ec596, 0x7efbed09, 0x4ef42ea2, 0x0eb30ea5, 0x5ee0d9f8, 0x6f513552, 0xf89eb3fa, 0x7ea2eca6, 0x9b00cc19, 0xf897409e, 0x1e73485f, 0x381afa77, 0x0f169f3b, 0x5ee1aa70, 0x5e1803ee, 0x0dbf5a4c, 0xce78c7a6, 0x9b0b260c, 0x2ef8fa19, 0x6e70aa4b, 0xce45b805, 0x2ea08e86, 0x4ee0bafd, 0x2ea09a1f, 0x4e218900, 0x6e744f13, 0xce518653, 0xf81b7a68, 0xce45ac5e, 0x7e62e416, 0x1a1b02b6, 0x7e21db48, 0x381daaaf, 0x6b2c0987, 0x0e2ec651, 0x4eae8502, 0x9bde7ca0, 0x6f47201f, 0x7e61a8a3, 0x6e60d5db, 0x4e2879de, 0xf81d194e, 0x4f1b8d05, 0x4d0048b2, 0x6e203be9, 0x4e3e7eb1, 0x0e260ef8, 0x2e688518, 0x7e3fec46, 0xdac00843, 0xf85c8917, 0x2e212a0f, 0x0e8196da, 0xd503359f, 0xce4c81f2, 0x6ee19992, 0x6e21ca79, 0x4d40c1d2, 0x4f5816ef, 0x4e34c3ea, 0x4df7c283, 0x7ef7eeb6, 0x18e276ce, 0xab0d21c0, 0xd5032f7f, 0x4ea00dbf, 0x5ac01251, 0xd0121955, 0x7f1495e4, 0x7ef0fa11, 0x5e24dd9c, 0x9add25b5, 0x0eb2bdef, 0x9e1977c7, 0x6f4b26bd, 0x0e200a9c, 0x9b4f7c00, 0x0ea0392e, 0x7e212a2c, 0x0b248b90, 0x1acc27a1, 0x2e701c90, 0x5ee1b870, 0x5e280aba, 0x5ea0780e, 0x1e264246, 0x4e052d04, 0x0e731dc4, 0xce461997, 0x9a9e9413, 0x3d462048, 0x5ea1fac5, 0x2ea0c8c4, 0x9a030280, 0x2ebda4b8, 0x5eef8614, 0x6eadc4e0, 0xbd035a8f, 0x4e606b84, 0x4eb1aba1, 0x4e286928, 0x4e2858cc, 0x9add0ce9, 0x4e070d65, 0x5fd399d5, 0x0f03fde7, 0x6ee90c74, 0x4ef8e31e, 0x381d986a, 0x5ea0ebf4, 0x5ea0d87e, 0x2e76ac9e, 0x6eb36cd4, 0x2e6e1c4c, 0x2e2feebc, 0x1ace4b03, 0x5ee0db12, 0x5ea0e9b1, 0x2e1c32d5, 0x5fa49a09, 0x0e258737, 0x7e21ca8e, 0xce4f9988, 0x5f7f56a6, 0x0e739766, 0x4e28586c, 0x6e619908, 0xd500401f, 0xf88b9252, 0x6e251c8e, 0x9e20015b, 0x7f1486b9, 0x717c339b, 0x1f31ff70, 0x4ea0eb62, 0x9acb0926, 0x489f7d85, 0x4e209b54, 0x2e84cf03, 0x2e65946c, 0x0e7d80cd, 0xc8dffecc, 0xce668bd8, 0x6e2188af, 0xeb4ada34, 0x2b25ec33, 0x0d40e6e7, 0x4eb2c757, 0x4ec82ad0, 0x7e21cb0a, 0x0e21a847, 0x4e0b1ec0, 0x381e6ac0, 0x6e61c8f5, 0x0f10071c, 0x2ee21daa, 0x5e61ab31, 0x6e218892, 0x2e7e7cb5, 0x6f2826aa, 0x7f6b54df, 0x4eaa2620, 0xdac00034, 0x4f6477be, 0x7e6148ea, 0x4eef1f57, 0x78459aeb, 0x2ebc3f10, 0x2e35f4eb, 0x4fbf19ce, 0xd8d0e58e, 0x2e21bbc7, 0x6ee0cab6, 0x9bc57e3f, 0x2f854037, 0x4e92181c, 0x6e6d1f89, 0x0f305545, 0x4ee19a57, 0x0e887bdf, 0x5e1a4185, 0x7ef0c821, 0x2eb6607c, 0x2ea0d9b8, 0x9e0380f4, 0x2ebf1c83, 0x1e62597d, 0x7f6e2548, 0x5ac00205, 0x4e616adb, 0xce638b8c, 0x5e1653cf, 0x2e6069be, 0x0e2ac641, 0x1e33c76f, 0xce44956d, 0x9bb90d31, 0x1e24c20a, 0x7ee038c1, 0x93407e5e, 0x4e280127, 0xc8df7f7d, 0xba42f263, 0x1e6f199c, 0x6e212889, 0x6e92f60e, 0x6ebdc499, 0x8b9acbf8, 0x4d40c581, 0x3a020250, 0x6e6a6716, 0x9248403b, 0x9081ffea, 0x4e603856, 0x9ad1242b, 0x6f270579, 0x1a070349, 0xcec08133, 0xd503305f, 0x5a1a00ca, 0x2e60b8a2, 0x0e5f28fd, 0x0e31a3da, 0x7e61cbc1, 0xd503399f, 0x5f5e54aa, 0x0eb8bdea, 0x4eba8f10, 0x4e2a2e60, 0x2f3da7d6, 0x1e58e297, 0x6e71aa3e, 0x6b86701a, 0xce4fa5e6, 0x4ee7c463, 0x8a79307f, 0x0ebea541, 0x2e218af4, 0x4e774f8a, 0xb9b95dc5, 0x6e61abd5, 0x4dd1e814, 0x4da72098, 0x98307582, 0x3a512101, 0x7ef95497, 0x1ace5535, 0x5a0c0349, 0x4e28581b, 0x6ebf1c02, 0x5ea1da23, 0x1e274314, 0x5e25dd29, 0x6e75f594, 0x6eaf6ed5, 0x4e214abe, 0x4e064172, 0x2e21c8f4, 0xf84c5b08, 0x1e244312, 0x14000000}; for (size_t i = 0; i < code32.size(); ++i) - env.MemoryWrite32(100 + i, code32[i]); + env.MemoryWrite(100 + i, code32[i], sizeof(u32)); env.ignore_invalid_insn = true; jit.SetRegister(0, 0x866524401a1d4e47); diff --git a/src/dynarmic/tests/A64/fibonacci.cpp b/src/dynarmic/tests/A64/fibonacci.cpp index f52a04e217..8816a89b1c 100644 --- a/src/dynarmic/tests/A64/fibonacci.cpp +++ b/src/dynarmic/tests/A64/fibonacci.cpp @@ -25,48 +25,55 @@ public: u64 ticks_left = 0; ::Common::unordered_map memory{}; - u8 MemoryRead8(u64 vaddr) override { - return memory[vaddr]; - } - - u16 MemoryRead16(u64 vaddr) override { - return u16(MemoryRead8(vaddr)) | u16(MemoryRead8(vaddr + 1)) << 8; - } - - u32 MemoryRead32(u64 vaddr) override { - return u32(MemoryRead16(vaddr)) | u32(MemoryRead16(vaddr + 2)) << 16; - } - - u64 MemoryRead64(u64 vaddr) override { - return u64(MemoryRead32(vaddr)) | u64(MemoryRead32(vaddr + 4)) << 32; + u64 MemoryRead(u64 vaddr, size_t size) override { + switch (size) { + case sizeof(u64): + return MemoryRead(vaddr, sizeof(u32)) + | MemoryRead(vaddr + sizeof(u32), sizeof(u32)) << 32; + case sizeof(u32): + return MemoryRead(vaddr, sizeof(u16)) + | MemoryRead(vaddr + sizeof(u16), sizeof(u16)) << 16; + case sizeof(u16): + return MemoryRead(vaddr, sizeof(u8)) + | MemoryRead(vaddr + sizeof(u8), sizeof(u8)) << 8; + case sizeof(u8): + return memory[vaddr]; + default: + std::abort(); + } } std::array MemoryRead128(u64 vaddr) override { - return {MemoryRead64(vaddr), MemoryRead64(vaddr + 8)}; - } - - void MemoryWrite8(u64 vaddr, u8 value) override { - memory[vaddr] = value; + return { + MemoryRead(vaddr, sizeof(u64)), + MemoryRead(vaddr + sizeof(u64), sizeof(u64)) + }; + } + + void MemoryWrite(Dynarmic::A64::VAddr vaddr, u64 value, size_t size) override { + switch (size) { + case sizeof(u64): + MemoryWrite(vaddr, u32(value), sizeof(u32)); + MemoryWrite(vaddr + 4, u32(value >> 32), sizeof(u32)); + break; + case sizeof(u32): + MemoryWrite(vaddr, u16(value), sizeof(u16)); + MemoryWrite(vaddr + 2, u16(value >> 16), sizeof(u16)); + break; + case sizeof(u16): + MemoryWrite(vaddr, u8(value), sizeof(u8)); + MemoryWrite(vaddr + 1, u8(value >> 8), sizeof(u8)); + break; + case sizeof(u8): + memory[vaddr] = value; + break; + default: + std::abort(); + } } - - void MemoryWrite16(u64 vaddr, u16 value) override { - MemoryWrite8(vaddr, u8(value)); - MemoryWrite8(vaddr + 1, u8(value >> 8)); - } - - void MemoryWrite32(u64 vaddr, u32 value) override { - MemoryWrite16(vaddr, u16(value)); - MemoryWrite16(vaddr + 2, u16(value >> 16)); - } - - void MemoryWrite64(u64 vaddr, u64 value) override { - MemoryWrite32(vaddr, u32(value)); - MemoryWrite32(vaddr + 4, u32(value >> 32)); - } - void MemoryWrite128(u64 vaddr, std::array value) override { - MemoryWrite64(vaddr, value[0]); - MemoryWrite64(vaddr + 8, value[1]); + MemoryWrite(vaddr, value[0], sizeof(u64)); + MemoryWrite(vaddr + 8, value[1], sizeof(u64)); } void CallSVC(u32) override { @@ -135,9 +142,9 @@ TEST_CASE("A64: fibonacci", "[a64]") { code.RET(); for (size_t i = 0; i < 1024; i++) { - env.MemoryWrite32(i * 4, instructions[i]); + env.MemoryWrite(i * 4, instructions[i], sizeof(u32)); } - env.MemoryWrite32(8888, 0xd4200000); + env.MemoryWrite(8888, 0xd4200000, sizeof(u32)); cpu.SetRegister(30, 8888); cpu.SetRegister(0, 10); diff --git a/src/dynarmic/tests/A64/testenv.h b/src/dynarmic/tests/A64/testenv.h index f4ddc63a6b..11aa6389f8 100644 --- a/src/dynarmic/tests/A64/testenv.h +++ b/src/dynarmic/tests/A64/testenv.h @@ -12,6 +12,7 @@ #include "common/assert.h" #include "common/common_types.h" #include "dynarmic/interface/A64/a64.h" +#include "dynarmic/interface/A64/config.h" using Vector = Dynarmic::A64::Vector; @@ -34,64 +35,79 @@ public: return code_mem[index]; } - std::uint8_t MemoryRead8(u64 vaddr) override { - if (IsInCodeMem(vaddr)) { - return reinterpret_cast(code_mem.data())[vaddr - code_mem_start_address]; + u64 MemoryRead(u64 vaddr, size_t size) override { + switch (size) { + case sizeof(u64): + return MemoryRead(vaddr, sizeof(u32)) + | MemoryRead(vaddr + sizeof(u32), sizeof(u32)) << 32; + case sizeof(u32): + return MemoryRead(vaddr, sizeof(u16)) + | MemoryRead(vaddr + sizeof(u16), sizeof(u16)) << 16; + case sizeof(u16): + return MemoryRead(vaddr, sizeof(u8)) + | MemoryRead(vaddr + sizeof(u8), sizeof(u8)) << 8; + case sizeof(u8): { + if (IsInCodeMem(vaddr)) + return reinterpret_cast(code_mem.data())[vaddr - code_mem_start_address]; + if (auto const it = modified_memory.find(vaddr); it != modified_memory.end()) + return it->second; + return u8(vaddr); + } + default: + std::abort(); } - if (auto const it = modified_memory.find(vaddr); it != modified_memory.end()) - return it->second; - return u8(vaddr); - } - std::uint16_t MemoryRead16(u64 vaddr) override { - return u16(MemoryRead8(vaddr)) | u16(MemoryRead8(vaddr + 1)) << 8; - } - std::uint32_t MemoryRead32(u64 vaddr) override { - return u32(MemoryRead16(vaddr)) | u32(MemoryRead16(vaddr + 2)) << 16; - } - std::uint64_t MemoryRead64(u64 vaddr) override { - return u64(MemoryRead32(vaddr)) | u64(MemoryRead32(vaddr + 4)) << 32; - } - Vector MemoryRead128(u64 vaddr) override { - return {MemoryRead64(vaddr), MemoryRead64(vaddr + 8)}; } - void MemoryWrite8(u64 vaddr, std::uint8_t value) override { - if (IsInCodeMem(vaddr)) { - code_mem_modified_by_guest = true; + Vector MemoryRead128(u64 vaddr) override { + return { + MemoryRead(vaddr, sizeof(u64)), + MemoryRead(vaddr + 8, sizeof(u64)) + }; + } + + void MemoryWrite(Dynarmic::A64::VAddr vaddr, u64 value, size_t size) override { + switch (size) { + case sizeof(u64): + MemoryWrite(vaddr, u32(value), sizeof(u32)); + MemoryWrite(vaddr + 4, u32(value >> 32), sizeof(u32)); + break; + case sizeof(u32): + MemoryWrite(vaddr, u16(value), sizeof(u16)); + MemoryWrite(vaddr + 2, u16(value >> 16), sizeof(u16)); + break; + case sizeof(u16): + MemoryWrite(vaddr, u8(value), sizeof(u8)); + MemoryWrite(vaddr + 1, u8(value >> 8), sizeof(u8)); + break; + case sizeof(u8): + if (IsInCodeMem(vaddr)) { + code_mem_modified_by_guest = true; + } + modified_memory[vaddr] = value; + break; + default: + std::abort(); } - modified_memory[vaddr] = value; - } - void MemoryWrite16(u64 vaddr, std::uint16_t value) override { - MemoryWrite8(vaddr, u8(value)); - MemoryWrite8(vaddr + 1, u8(value >> 8)); - } - void MemoryWrite32(u64 vaddr, std::uint32_t value) override { - MemoryWrite16(vaddr, u16(value)); - MemoryWrite16(vaddr + 2, u16(value >> 16)); - } - void MemoryWrite64(u64 vaddr, std::uint64_t value) override { - MemoryWrite32(vaddr, u32(value)); - MemoryWrite32(vaddr + 4, u32(value >> 32)); } void MemoryWrite128(u64 vaddr, Vector value) override { - MemoryWrite64(vaddr, value[0]); - MemoryWrite64(vaddr + 8, value[1]); + MemoryWrite(vaddr, value[0], sizeof(u64)); + MemoryWrite(vaddr + 8, value[1], sizeof(u64)); } bool MemoryWriteExclusive8(u64 vaddr, std::uint8_t value, [[maybe_unused]] std::uint8_t expected) override { - MemoryWrite8(vaddr, value); + MemoryWrite(vaddr, value, sizeof(u8)); return true; } bool MemoryWriteExclusive16(u64 vaddr, std::uint16_t value, [[maybe_unused]] std::uint16_t expected) override { - MemoryWrite16(vaddr, value); + MemoryWrite(vaddr, value, sizeof(u16)); return true; } bool MemoryWriteExclusive32(u64 vaddr, std::uint32_t value, [[maybe_unused]] std::uint32_t expected) override { - MemoryWrite32(vaddr, value); + MemoryWrite(vaddr, value, sizeof(u32)); return true; } bool MemoryWriteExclusive64(u64 vaddr, std::uint64_t value, [[maybe_unused]] std::uint64_t expected) override { - MemoryWrite64(vaddr, value); + MemoryWrite(vaddr, value, sizeof(u64)); return true; } bool MemoryWriteExclusive128(u64 vaddr, Vector value, [[maybe_unused]] Vector expected) override { @@ -145,52 +161,46 @@ public: return read(vaddr); } - std::uint8_t MemoryRead8(u64 vaddr) override { - return read(vaddr); - } - std::uint16_t MemoryRead16(u64 vaddr) override { - return read(vaddr); - } - std::uint32_t MemoryRead32(u64 vaddr) override { - return read(vaddr); - } - std::uint64_t MemoryRead64(u64 vaddr) override { - return read(vaddr); + u64 MemoryRead(u64 vaddr, size_t size) override { + switch (size) { + case sizeof(u64): return read(vaddr); + case sizeof(u32): return read(vaddr); + case sizeof(u16): return read(vaddr); + case sizeof(u8): return read(vaddr); + default: std::abort(); + } } Vector MemoryRead128(u64 vaddr) override { return read(vaddr); } - void MemoryWrite8(u64 vaddr, std::uint8_t value) override { - write(vaddr, value); - } - void MemoryWrite16(u64 vaddr, std::uint16_t value) override { - write(vaddr, value); - } - void MemoryWrite32(u64 vaddr, std::uint32_t value) override { - write(vaddr, value); - } - void MemoryWrite64(u64 vaddr, std::uint64_t value) override { - write(vaddr, value); + void MemoryWrite(u64 vaddr, std::uint64_t value, size_t size) override { + switch (size) { + case sizeof(u64): return write(vaddr, u64(value)); + case sizeof(u32): return write(vaddr, u32(value)); + case sizeof(u16): return write(vaddr, u16(value)); + case sizeof(u8): return write(vaddr, u8(value)); + default: std::abort(); + } } void MemoryWrite128(u64 vaddr, Vector value) override { write(vaddr, value); } bool MemoryWriteExclusive8(u64 vaddr, std::uint8_t value, [[maybe_unused]] std::uint8_t expected) override { - MemoryWrite8(vaddr, value); + MemoryWrite(vaddr, value, sizeof(u8)); return true; } bool MemoryWriteExclusive16(u64 vaddr, std::uint16_t value, [[maybe_unused]] std::uint16_t expected) override { - MemoryWrite16(vaddr, value); + MemoryWrite(vaddr, value, sizeof(u16)); return true; } bool MemoryWriteExclusive32(u64 vaddr, std::uint32_t value, [[maybe_unused]] std::uint32_t expected) override { - MemoryWrite32(vaddr, value); + MemoryWrite(vaddr, value, sizeof(u32)); return true; } bool MemoryWriteExclusive64(u64 vaddr, std::uint64_t value, [[maybe_unused]] std::uint64_t expected) override { - MemoryWrite64(vaddr, value); + MemoryWrite(vaddr, value, sizeof(u64)); return true; } bool MemoryWriteExclusive128(u64 vaddr, Vector value, [[maybe_unused]] Vector expected) override { diff --git a/src/dynarmic/tests/print_info.cpp b/src/dynarmic/tests/print_info.cpp index 5b1c5cfe63..87f4438ad4 100644 --- a/src/dynarmic/tests/print_info.cpp +++ b/src/dynarmic/tests/print_info.cpp @@ -18,6 +18,7 @@ #include #include #include +#include "dynarmic/frontend/A32/translate/translate_callbacks.h" #include "dynarmic/mcl/bit.hpp" #include "common/common_types.h" @@ -118,36 +119,47 @@ public: u64 ticks_left = 0; std::map memory; - std::uint8_t MemoryRead8(u32 vaddr) override { - if (auto iter = memory.find(vaddr); iter != memory.end()) { - return iter->second; + u64 MemoryRead(Dynarmic::A32::VAddr vaddr, size_t size) override { + switch (size) { + case sizeof(u64): + return MemoryRead(vaddr, sizeof(u32)) + | MemoryRead(vaddr + sizeof(u32), sizeof(u32)) << 32; + case sizeof(u32): + return MemoryRead(vaddr, sizeof(u16)) + | MemoryRead(vaddr + sizeof(u16), sizeof(u16)) << 16; + case sizeof(u16): + return MemoryRead(vaddr, sizeof(u8)) + | MemoryRead(vaddr + sizeof(u8), sizeof(u8)) << 8; + case sizeof(u8): { + if (auto const it = memory.find(vaddr); it != memory.end()) + return it->second; + return 0; + } + default: + std::abort(); } - return 0; - } - std::uint16_t MemoryRead16(u32 vaddr) override { - return u16(MemoryRead8(vaddr)) | u16(MemoryRead8(vaddr + 1)) << 8; - } - std::uint32_t MemoryRead32(u32 vaddr) override { - return u32(MemoryRead16(vaddr)) | u32(MemoryRead16(vaddr + 2)) << 16; - } - std::uint64_t MemoryRead64(u32 vaddr) override { - return u64(MemoryRead32(vaddr)) | u64(MemoryRead32(vaddr + 4)) << 32; } - void MemoryWrite8(u32 vaddr, std::uint8_t value) override { - memory[vaddr] = value; - } - void MemoryWrite16(u32 vaddr, std::uint16_t value) override { - MemoryWrite8(vaddr, static_cast(value)); - MemoryWrite8(vaddr + 1, static_cast(value >> 8)); - } - void MemoryWrite32(u32 vaddr, std::uint32_t value) override { - MemoryWrite16(vaddr, static_cast(value)); - MemoryWrite16(vaddr + 2, static_cast(value >> 16)); - } - void MemoryWrite64(u32 vaddr, std::uint64_t value) override { - MemoryWrite32(vaddr, static_cast(value)); - MemoryWrite32(vaddr + 4, static_cast(value >> 32)); + void MemoryWrite(Dynarmic::A32::VAddr vaddr, u64 value, size_t size) override { + switch (size) { + case sizeof(u64): + MemoryWrite(vaddr, u32(value), sizeof(u32)); + MemoryWrite(vaddr + 4, u32(value >> 32), sizeof(u32)); + break; + case sizeof(u32): + MemoryWrite(vaddr, u16(value), sizeof(u16)); + MemoryWrite(vaddr + 2, u16(value >> 16), sizeof(u16)); + break; + case sizeof(u16): + MemoryWrite(vaddr, u8(value), sizeof(u8)); + MemoryWrite(vaddr + 1, u8(value >> 8), sizeof(u8)); + break; + case sizeof(u8): + memory[vaddr] = value; + break; + default: + std::abort(); + } } void CallSVC(std::uint32_t swi) override { @@ -231,7 +243,7 @@ void ExecuteA32Instruction(u32 instruction) { if (const auto address = get_value()) { fmt::print("value: "); if (const auto value = get_value()) { - env.MemoryWrite32(*address, *value); + env.MemoryWrite(*address, *value, sizeof(u32)); fmt::print("> mem[{:#08x}] = {:#08x}\n", *address, *value); } } @@ -247,8 +259,8 @@ void ExecuteA32Instruction(u32 instruction) { cpu.SetFpscr(fpscr); const u32 initial_pc = regs[15]; - env.MemoryWrite32(initial_pc + 0, instruction); - env.MemoryWrite32(initial_pc + 4, 0xEAFFFFFE); // B +0 + env.MemoryWrite(initial_pc + 0, instruction, sizeof(u32)); + env.MemoryWrite(initial_pc + 4, 0xEAFFFFFE, sizeof(u32)); // B +0 cpu.Run(); fmt::print("{}", fmt::join(cpu.Disassemble(), "\n")); diff --git a/src/dynarmic/tests/unicorn_emu/a32_unicorn.cpp b/src/dynarmic/tests/unicorn_emu/a32_unicorn.cpp index c0e1e13d9b..1fe09cdef0 100644 --- a/src/dynarmic/tests/unicorn_emu/a32_unicorn.cpp +++ b/src/dynarmic/tests/unicorn_emu/a32_unicorn.cpp @@ -290,7 +290,7 @@ bool A32Unicorn::UnmappedMemoryHook(uc_engine* uc, uc_mem_type auto page = std::make_unique(); page->address = base_address; for (size_t i = 0; i < page->data.size(); ++i) - page->data[i] = this_->testenv.MemoryRead8(static_cast(base_address + i)); + page->data[i] = u8(this_->testenv.MemoryRead(u32(base_address + i), sizeof(u8))); uc_err err = uc_mem_map_ptr(uc, base_address, page->data.size(), permissions, page->data.data()); if (err == UC_ERR_MAP) @@ -321,24 +321,7 @@ bool A32Unicorn::UnmappedMemoryHook(uc_engine* uc, uc_mem_type template bool A32Unicorn::MemoryWriteHook(uc_engine* /*uc*/, uc_mem_type /*type*/, u32 start_address, int size, u64 value, void* user_data) { auto* this_ = static_cast(user_data); - - switch (size) { - case 1: - this_->testenv.MemoryWrite8(start_address, static_cast(value)); - break; - case 2: - this_->testenv.MemoryWrite16(start_address, static_cast(value)); - break; - case 4: - this_->testenv.MemoryWrite32(start_address, static_cast(value)); - break; - case 8: - this_->testenv.MemoryWrite64(start_address, value); - break; - default: - UNREACHABLE(); - } - + this_->testenv.MemoryWrite(start_address, value, size); return true; } diff --git a/src/dynarmic/tests/unicorn_emu/a64_unicorn.cpp b/src/dynarmic/tests/unicorn_emu/a64_unicorn.cpp index c9a194d50a..4afb6a6859 100644 --- a/src/dynarmic/tests/unicorn_emu/a64_unicorn.cpp +++ b/src/dynarmic/tests/unicorn_emu/a64_unicorn.cpp @@ -197,7 +197,7 @@ bool A64Unicorn::UnmappedMemoryHook(uc_engine* uc, uc_mem_type /*type*/, u64 sta auto page = std::make_unique(); page->address = base_address; for (size_t i = 0; i < page->data.size(); ++i) - page->data[i] = this_->testenv.MemoryRead8(base_address + i); + page->data[i] = u8(this_->testenv.MemoryRead(base_address + i, sizeof(u8))); uc_err err = uc_mem_map_ptr(uc, base_address, page->data.size(), permissions, page->data.data()); if (err == UC_ERR_MAP) @@ -227,23 +227,6 @@ bool A64Unicorn::UnmappedMemoryHook(uc_engine* uc, uc_mem_type /*type*/, u64 sta bool A64Unicorn::MemoryWriteHook(uc_engine* /*uc*/, uc_mem_type /*type*/, u64 start_address, int size, u64 value, void* user_data) { auto* this_ = static_cast(user_data); - - switch (size) { - case 1: - this_->testenv.MemoryWrite8(start_address, static_cast(value)); - break; - case 2: - this_->testenv.MemoryWrite16(start_address, static_cast(value)); - break; - case 4: - this_->testenv.MemoryWrite32(start_address, static_cast(value)); - break; - case 8: - this_->testenv.MemoryWrite64(start_address, value); - break; - default: - UNREACHABLE(); - } - + this_->testenv.MemoryWrite(start_address, value, size); return true; }