From c292351faafa76ff457db1d96d241a14176c9535 Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Sat, 27 Feb 2021 16:07:41 +0100 Subject: [PATCH] Core/MMU: Add HostTryWrite*() functions. --- Source/Core/Core/PowerPC/MMU.cpp | 57 ++++++++++++++++++++++++++++++++ Source/Core/Core/PowerPC/MMU.h | 34 +++++++++++++++++++ 2 files changed, 91 insertions(+) diff --git a/Source/Core/Core/PowerPC/MMU.cpp b/Source/Core/Core/PowerPC/MMU.cpp index ac0cea0cf3..e5d4bebdb8 100644 --- a/Source/Core/Core/PowerPC/MMU.cpp +++ b/Source/Core/Core/PowerPC/MMU.cpp @@ -721,6 +721,63 @@ void HostWrite_F64(const double var, const u32 address) HostWrite_U64(integral, address); } +template +static TryWriteResult HostTryWriteUX(const T var, const u32 address, RequestedAddressSpace space) +{ + if (!HostIsRAMAddress(address, space)) + return TryWriteResult(); + + switch (space) + { + case RequestedAddressSpace::Effective: + WriteToHardware(address, var); + return TryWriteResult(!!MSR.DR); + case RequestedAddressSpace::Physical: + WriteToHardware(address, var); + return TryWriteResult(false); + case RequestedAddressSpace::Virtual: + if (!MSR.DR) + return TryWriteResult(); + WriteToHardware(address, var); + return TryWriteResult(true); + } + + assert(0); + return TryWriteResult(); +} + +TryWriteResult HostTryWriteU8(const u8 var, const u32 address, RequestedAddressSpace space) +{ + return HostTryWriteUX(var, address, space); +} + +TryWriteResult HostTryWriteU16(const u16 var, const u32 address, RequestedAddressSpace space) +{ + return HostTryWriteUX(var, address, space); +} + +TryWriteResult HostTryWriteU32(const u32 var, const u32 address, RequestedAddressSpace space) +{ + return HostTryWriteUX(var, address, space); +} + +TryWriteResult HostTryWriteU64(const u64 var, const u32 address, RequestedAddressSpace space) +{ + return HostTryWriteUX(var, address, space); +} + +TryWriteResult HostTryWriteF32(const float var, const u32 address, RequestedAddressSpace space) +{ + const u32 integral = Common::BitCast(var); + return HostTryWriteU32(integral, address, space); +} + +TryWriteResult HostTryWriteF64(const double var, const u32 address, RequestedAddressSpace space) +{ + const u64 integral = Common::BitCast(var); + return HostTryWriteU64(integral, address, space); +} + std::string HostGetString(u32 address, size_t size) { std::string s; diff --git a/Source/Core/Core/PowerPC/MMU.h b/Source/Core/Core/PowerPC/MMU.h index 591aec44fd..9191cea2ab 100644 --- a/Source/Core/Core/PowerPC/MMU.h +++ b/Source/Core/Core/PowerPC/MMU.h @@ -83,6 +83,9 @@ TryReadResult HostTryReadString(u32 address, size_t size = 0, RequestedAddressSpace space = RequestedAddressSpace::Effective); +// Writes a value to emulated memory using the currently active MMU settings. +// If the write fails (eg. address does not correspond to a mapped address in the current address +// space), a PanicAlert will be shown to the user. void HostWrite_U8(u8 var, u32 address); void HostWrite_U16(u16 var, u32 address); void HostWrite_U32(u32 var, u32 address); @@ -90,6 +93,37 @@ void HostWrite_U64(u64 var, u32 address); void HostWrite_F32(float var, u32 address); void HostWrite_F64(double var, u32 address); +struct TryWriteResult +{ + // whether the write succeeded; if false, the other fields should not be touched + bool success; + + // whether the address had to be translated (given address was treated as virtual) or not (given + // address was treated as physical) + bool translated; + + TryWriteResult() : success(false) {} + TryWriteResult(bool translated_) : success(true), translated(translated_) {} + explicit operator bool() const { return success; } +}; + +// Try to a write a value to memory at the given address in the given memory space. +// If the write succeeds, the returned TryWriteResult contains information on whether the given +// address had to be translated or not. Unlike the HostWrite functions, this does not raise a +// user-visible alert on failure. +TryWriteResult HostTryWriteU8(u8 var, const u32 address, + RequestedAddressSpace space = RequestedAddressSpace::Effective); +TryWriteResult HostTryWriteU16(u16 var, const u32 address, + RequestedAddressSpace space = RequestedAddressSpace::Effective); +TryWriteResult HostTryWriteU32(u32 var, const u32 address, + RequestedAddressSpace space = RequestedAddressSpace::Effective); +TryWriteResult HostTryWriteU64(u64 var, const u32 address, + RequestedAddressSpace space = RequestedAddressSpace::Effective); +TryWriteResult HostTryWriteF32(float var, const u32 address, + RequestedAddressSpace space = RequestedAddressSpace::Effective); +TryWriteResult HostTryWriteF64(double var, const u32 address, + RequestedAddressSpace space = RequestedAddressSpace::Effective); + // Returns whether a read or write to the given address will resolve to a RAM access in the given // address space. bool HostIsRAMAddress(u32 address, RequestedAddressSpace space = RequestedAddressSpace::Effective);