diff --git a/src/core/guest_memory.h b/src/core/guest_memory.h index e8bb798ec..994d70290 100644 --- a/src/core/guest_memory.h +++ b/src/core/guest_memory.h @@ -8,7 +8,6 @@ #include #include #include - #include "common/assert.h" #include "common/scratch_buffer.h" @@ -43,72 +42,33 @@ class GuestMemory { public: GuestMemory() = delete; explicit GuestMemory(M& memory, u64 addr, std::size_t size, - Common::ScratchBuffer* backup = nullptr) - : m_memory{&memory}, m_addr{addr}, m_size{size} { + Common::ScratchBuffer* backup = nullptr) noexcept + : m_memory{&memory}, m_addr{addr}, m_size{size}, m_is_data_copy{false}, m_addr_changed{false} { static_assert(FLAGS & GuestMemoryFlags::Read || FLAGS & GuestMemoryFlags::Write); if constexpr (!(FLAGS & GuestMemoryFlags::Read)) { if (!this->TrySetSpan()) { - if (backup) { - backup->resize_destructive(this->size()); - m_data_span = *backup; - m_span_valid = true; - m_is_data_copy = true; - } else { - m_data_copy.resize(this->size()); - m_data_span = std::span(m_data_copy); - m_span_valid = true; - m_is_data_copy = true; - } + allocateBackupOrCopy(backup); } - } else if constexpr (FLAGS & GuestMemoryFlags::Read) { + } else { Read(addr, size, backup); } } - ~GuestMemory() = default; + GuestMemory(GuestMemory&& rhs) noexcept = default; + GuestMemory& operator=(GuestMemory&& rhs) noexcept = default; - GuestMemory(GuestMemory&& rhs) = default; - GuestMemory& operator=(GuestMemory&& rhs) = default; + T* data() noexcept { return m_data_span.data(); } + const T* data() const noexcept { return m_data_span.data(); } + size_t size() const noexcept { return m_size; } + size_t size_bytes() const noexcept { return this->size() * sizeof(T); } - T* data() noexcept { - return m_data_span.data(); - } + T* begin() noexcept { return this->data(); } + const T* begin() const noexcept { return this->data(); } + T* end() noexcept { return this->data() + this->size(); } + const T* end() const noexcept { return this->data() + this->size(); } - const T* data() const noexcept { - return m_data_span.data(); - } - - size_t size() const noexcept { - return m_size; - } - - size_t size_bytes() const noexcept { - return this->size() * sizeof(T); - } - - [[nodiscard]] T* begin() noexcept { - return this->data(); - } - - [[nodiscard]] const T* begin() const noexcept { - return this->data(); - } - - [[nodiscard]] T* end() noexcept { - return this->data() + this->size(); - } - - [[nodiscard]] const T* end() const noexcept { - return this->data() + this->size(); - } - - T& operator[](size_t index) noexcept { - return m_data_span[index]; - } - - const T& operator[](size_t index) const noexcept { - return m_data_span[index]; - } + T& operator[](size_t index) noexcept { return m_data_span[index]; } + const T& operator[](size_t index) const noexcept { return m_data_span[index]; } void SetAddressAndSize(u64 addr, std::size_t size) noexcept { m_addr = addr; @@ -116,10 +76,10 @@ public: m_addr_changed = true; } - std::span Read(u64 addr, std::size_t size, - Common::ScratchBuffer* backup = nullptr) noexcept { + std::span Read(u64 addr, std::size_t size, Common::ScratchBuffer* backup = nullptr) noexcept { m_addr = addr; m_size = size; + if (m_size == 0) { m_is_data_copy = true; return {}; @@ -130,15 +90,7 @@ public: m_memory->FlushRegion(m_addr, this->size_bytes()); } } else { - if (backup) { - backup->resize_destructive(this->size()); - m_data_span = *backup; - } else { - m_data_copy.resize(this->size()); - m_data_span = std::span(m_data_copy); - } - m_is_data_copy = true; - m_span_valid = true; + allocateBackupOrCopy(backup); if constexpr (FLAGS & GuestMemoryFlags::Safe) { m_memory->ReadBlock(m_addr, this->data(), this->size_bytes()); } else { @@ -169,12 +121,19 @@ public: } protected: - bool IsDataCopy() const noexcept { - return m_is_data_copy; - } + bool IsDataCopy() const noexcept { return m_is_data_copy; } + bool AddressChanged() const noexcept { return m_addr_changed; } - bool AddressChanged() const noexcept { - return m_addr_changed; + void allocateBackupOrCopy(Common::ScratchBuffer* backup) { + if (backup) { + backup->resize_destructive(this->size()); + m_data_span = *backup; + } else { + m_data_copy.resize(this->size()); + m_data_span = std::span(m_data_copy); + } + m_is_data_copy = true; + m_span_valid = true; } M* m_memory; @@ -192,33 +151,34 @@ class GuestMemoryScoped : public GuestMemory { public: GuestMemoryScoped() = delete; explicit GuestMemoryScoped(M& memory, u64 addr, std::size_t size, - Common::ScratchBuffer* backup = nullptr) + Common::ScratchBuffer* backup = nullptr) noexcept : GuestMemory(memory, addr, size, backup) {} - ~GuestMemoryScoped() { + ~GuestMemoryScoped() noexcept { if constexpr (FLAGS & GuestMemoryFlags::Write) { - if (this->size() == 0) [[unlikely]] { + if (this->size() == 0 || !this->m_span_valid) [[unlikely]] { return; } if (this->AddressChanged() || this->IsDataCopy()) { - ASSERT(this->m_span_valid); - if constexpr (FLAGS & GuestMemoryFlags::Cached) { - this->m_memory->WriteBlockCached(this->m_addr, this->data(), - this->size_bytes()); - } else if constexpr (FLAGS & GuestMemoryFlags::Safe) { - this->m_memory->WriteBlock(this->m_addr, this->data(), this->size_bytes()); - } else { - this->m_memory->WriteBlockUnsafe(this->m_addr, this->data(), - this->size_bytes()); - } - } else if constexpr ((FLAGS & GuestMemoryFlags::Safe) || - (FLAGS & GuestMemoryFlags::Cached)) { + this->writeData(); + } else if constexpr ((FLAGS & GuestMemoryFlags::Safe) || (FLAGS & GuestMemoryFlags::Cached)) { this->m_memory->InvalidateRegion(this->m_addr, this->size_bytes()); } } } -}; -} // namespace -} // namespace Core::Memory +private: + void writeData() noexcept { + if constexpr (FLAGS & GuestMemoryFlags::Cached) { + this->m_memory->WriteBlockCached(this->m_addr, this->data(), this->size_bytes()); + } else if constexpr (FLAGS & GuestMemoryFlags::Safe) { + this->m_memory->WriteBlock(this->m_addr, this->data(), this->size_bytes()); + } else { + this->m_memory->WriteBlockUnsafe(this->m_addr, this->data(), this->size_bytes()); + } + } +}; +} // namespace + +} // namespace Core::Memory