diff options
Diffstat (limited to 'src/core/memory.h')
| -rw-r--r-- | src/core/memory.h | 125 |
1 files changed, 65 insertions, 60 deletions
diff --git a/src/core/memory.h b/src/core/memory.h index 2eb61ffd3..13047a545 100644 --- a/src/core/memory.h +++ b/src/core/memory.h | |||
| @@ -509,9 +509,9 @@ class GuestMemory { | |||
| 509 | 509 | ||
| 510 | public: | 510 | public: |
| 511 | GuestMemory() = delete; | 511 | GuestMemory() = delete; |
| 512 | explicit GuestMemory(M& memory_, u64 addr_, std::size_t size_, | 512 | explicit GuestMemory(M& memory, u64 addr, std::size_t size, |
| 513 | Common::ScratchBuffer<T>* backup = nullptr) | 513 | Common::ScratchBuffer<T>* backup = nullptr) |
| 514 | : memory{memory_}, addr{addr_}, size{size_} { | 514 | : m_memory{memory}, m_addr{addr}, m_size{size} { |
| 515 | static_assert(FLAGS & GuestMemoryFlags::Read || FLAGS & GuestMemoryFlags::Write); | 515 | static_assert(FLAGS & GuestMemoryFlags::Read || FLAGS & GuestMemoryFlags::Write); |
| 516 | if constexpr (FLAGS & GuestMemoryFlags::Read) { | 516 | if constexpr (FLAGS & GuestMemoryFlags::Read) { |
| 517 | Read(addr, size, backup); | 517 | Read(addr, size, backup); |
| @@ -521,89 +521,97 @@ public: | |||
| 521 | ~GuestMemory() = default; | 521 | ~GuestMemory() = default; |
| 522 | 522 | ||
| 523 | T* data() noexcept { | 523 | T* data() noexcept { |
| 524 | return data_span.data(); | 524 | return m_data_span.data(); |
| 525 | } | 525 | } |
| 526 | 526 | ||
| 527 | const T* data() const noexcept { | 527 | const T* data() const noexcept { |
| 528 | return data_span.data(); | 528 | return m_data_span.data(); |
| 529 | } | ||
| 530 | |||
| 531 | size_t size() const noexcept { | ||
| 532 | return m_size; | ||
| 533 | } | ||
| 534 | |||
| 535 | size_t size_bytes() const noexcept { | ||
| 536 | return this->size() * sizeof(T); | ||
| 529 | } | 537 | } |
| 530 | 538 | ||
| 531 | [[nodiscard]] T* begin() noexcept { | 539 | [[nodiscard]] T* begin() noexcept { |
| 532 | return data(); | 540 | return this->data(); |
| 533 | } | 541 | } |
| 534 | 542 | ||
| 535 | [[nodiscard]] const T* begin() const noexcept { | 543 | [[nodiscard]] const T* begin() const noexcept { |
| 536 | return data(); | 544 | return this->data(); |
| 537 | } | 545 | } |
| 538 | 546 | ||
| 539 | [[nodiscard]] T* end() noexcept { | 547 | [[nodiscard]] T* end() noexcept { |
| 540 | return data() + size; | 548 | return this->data() + this->size(); |
| 541 | } | 549 | } |
| 542 | 550 | ||
| 543 | [[nodiscard]] const T* end() const noexcept { | 551 | [[nodiscard]] const T* end() const noexcept { |
| 544 | return data() + size; | 552 | return this->data() + this->size(); |
| 545 | } | 553 | } |
| 546 | 554 | ||
| 547 | T& operator[](size_t index) noexcept { | 555 | T& operator[](size_t index) noexcept { |
| 548 | return data_span[index]; | 556 | return m_data_span[index]; |
| 549 | } | 557 | } |
| 550 | 558 | ||
| 551 | const T& operator[](size_t index) const noexcept { | 559 | const T& operator[](size_t index) const noexcept { |
| 552 | return data_span[index]; | 560 | return m_data_span[index]; |
| 553 | } | 561 | } |
| 554 | 562 | ||
| 555 | void SetAddressAndSize(u64 addr_, std::size_t size_) noexcept { | 563 | void SetAddressAndSize(u64 addr, std::size_t size) noexcept { |
| 556 | addr = addr_; | 564 | m_addr = addr; |
| 557 | size = size_; | 565 | m_size = size; |
| 558 | addr_changed = true; | 566 | m_addr_changed = true; |
| 559 | } | 567 | } |
| 560 | 568 | ||
| 561 | std::span<T> Read(u64 addr_, std::size_t size_, | 569 | std::span<T> Read(u64 addr, std::size_t size, |
| 562 | Common::ScratchBuffer<T>* backup = nullptr) noexcept { | 570 | Common::ScratchBuffer<T>* backup = nullptr) noexcept { |
| 563 | addr = addr_; | 571 | m_addr = addr; |
| 564 | size = size_; | 572 | m_size = size; |
| 565 | if (size == 0) { | 573 | if (m_size == 0) { |
| 566 | is_data_copy = true; | 574 | m_is_data_copy = true; |
| 567 | return {}; | 575 | return {}; |
| 568 | } | 576 | } |
| 569 | 577 | ||
| 570 | if (TrySetSpan()) { | 578 | if (this->TrySetSpan()) { |
| 571 | if constexpr (FLAGS & GuestMemoryFlags::Safe) { | 579 | if constexpr (FLAGS & GuestMemoryFlags::Safe) { |
| 572 | memory.FlushRegion(addr, size * sizeof(T)); | 580 | m_memory.FlushRegion(m_addr, this->size_bytes()); |
| 573 | } | 581 | } |
| 574 | } else { | 582 | } else { |
| 575 | if (backup) { | 583 | if (backup) { |
| 576 | backup->resize_destructive(size); | 584 | backup->resize_destructive(this->size()); |
| 577 | data_span = *backup; | 585 | m_data_span = *backup; |
| 578 | } else { | 586 | } else { |
| 579 | data_copy.resize(size); | 587 | m_data_copy.resize(this->size()); |
| 580 | data_span = std::span(data_copy); | 588 | m_data_span = std::span(m_data_copy); |
| 581 | } | 589 | } |
| 582 | is_data_copy = true; | 590 | m_is_data_copy = true; |
| 583 | span_valid = true; | 591 | m_span_valid = true; |
| 584 | if constexpr (FLAGS & GuestMemoryFlags::Safe) { | 592 | if constexpr (FLAGS & GuestMemoryFlags::Safe) { |
| 585 | memory.ReadBlock(addr, data_span.data(), size * sizeof(T)); | 593 | m_memory.ReadBlock(m_addr, this->data(), this->size_bytes()); |
| 586 | } else { | 594 | } else { |
| 587 | memory.ReadBlockUnsafe(addr, data_span.data(), size * sizeof(T)); | 595 | m_memory.ReadBlockUnsafe(m_addr, this->data(), this->size_bytes()); |
| 588 | } | 596 | } |
| 589 | } | 597 | } |
| 590 | return data_span; | 598 | return m_data_span; |
| 591 | } | 599 | } |
| 592 | 600 | ||
| 593 | void Write(std::span<T> write_data) noexcept { | 601 | void Write(std::span<T> write_data) noexcept { |
| 594 | if constexpr (FLAGS & GuestMemoryFlags::Cached) { | 602 | if constexpr (FLAGS & GuestMemoryFlags::Cached) { |
| 595 | memory.WriteBlockCached(addr, write_data.data(), size * sizeof(T)); | 603 | m_memory.WriteBlockCached(m_addr, write_data.data(), this->size_bytes()); |
| 596 | } else if constexpr (FLAGS & GuestMemoryFlags::Safe) { | 604 | } else if constexpr (FLAGS & GuestMemoryFlags::Safe) { |
| 597 | memory.WriteBlock(addr, write_data.data(), size * sizeof(T)); | 605 | m_memory.WriteBlock(m_addr, write_data.data(), this->size_bytes()); |
| 598 | } else { | 606 | } else { |
| 599 | memory.WriteBlockUnsafe(addr, write_data.data(), size * sizeof(T)); | 607 | m_memory.WriteBlockUnsafe(m_addr, write_data.data(), this->size_bytes()); |
| 600 | } | 608 | } |
| 601 | } | 609 | } |
| 602 | 610 | ||
| 603 | bool TrySetSpan() noexcept { | 611 | bool TrySetSpan() noexcept { |
| 604 | if (u8* ptr = memory.GetSpan(addr, size * sizeof(T)); ptr) { | 612 | if (u8* ptr = m_memory.GetSpan(m_addr, this->size_bytes()); ptr) { |
| 605 | data_span = {reinterpret_cast<T*>(ptr), size}; | 613 | m_data_span = {reinterpret_cast<T*>(ptr), this->size()}; |
| 606 | span_valid = true; | 614 | m_span_valid = true; |
| 607 | return true; | 615 | return true; |
| 608 | } | 616 | } |
| 609 | return false; | 617 | return false; |
| @@ -611,36 +619,36 @@ public: | |||
| 611 | 619 | ||
| 612 | protected: | 620 | protected: |
| 613 | bool IsDataCopy() const noexcept { | 621 | bool IsDataCopy() const noexcept { |
| 614 | return is_data_copy; | 622 | return m_is_data_copy; |
| 615 | } | 623 | } |
| 616 | 624 | ||
| 617 | bool AddressChanged() const noexcept { | 625 | bool AddressChanged() const noexcept { |
| 618 | return addr_changed; | 626 | return m_addr_changed; |
| 619 | } | 627 | } |
| 620 | 628 | ||
| 621 | M& memory; | 629 | M& m_memory; |
| 622 | u64 addr; | 630 | u64 m_addr{}; |
| 623 | size_t size; | 631 | size_t m_size{}; |
| 624 | std::span<T> data_span{}; | 632 | std::span<T> m_data_span{}; |
| 625 | std::vector<T> data_copy; | 633 | std::vector<T> m_data_copy{}; |
| 626 | bool span_valid{false}; | 634 | bool m_span_valid{false}; |
| 627 | bool is_data_copy{false}; | 635 | bool m_is_data_copy{false}; |
| 628 | bool addr_changed{false}; | 636 | bool m_addr_changed{false}; |
| 629 | }; | 637 | }; |
| 630 | 638 | ||
| 631 | template <typename M, typename T, GuestMemoryFlags FLAGS> | 639 | template <typename M, typename T, GuestMemoryFlags FLAGS> |
| 632 | class GuestMemoryScoped : public GuestMemory<M, T, FLAGS> { | 640 | class GuestMemoryScoped : public GuestMemory<M, T, FLAGS> { |
| 633 | public: | 641 | public: |
| 634 | GuestMemoryScoped() = delete; | 642 | GuestMemoryScoped() = delete; |
| 635 | explicit GuestMemoryScoped(M& memory_, u64 addr_, std::size_t size_, | 643 | explicit GuestMemoryScoped(M& memory, u64 addr, std::size_t size, |
| 636 | Common::ScratchBuffer<T>* backup = nullptr) | 644 | Common::ScratchBuffer<T>* backup = nullptr) |
| 637 | : GuestMemory<M, T, FLAGS>(memory_, addr_, size_, backup) { | 645 | : GuestMemory<M, T, FLAGS>(memory, addr, size, backup) { |
| 638 | if constexpr (!(FLAGS & GuestMemoryFlags::Read)) { | 646 | if constexpr (!(FLAGS & GuestMemoryFlags::Read)) { |
| 639 | if (!this->TrySetSpan()) { | 647 | if (!this->TrySetSpan()) { |
| 640 | if (backup) { | 648 | if (backup) { |
| 641 | this->data_span = *backup; | 649 | this->m_data_span = *backup; |
| 642 | this->span_valid = true; | 650 | this->m_span_valid = true; |
| 643 | this->is_data_copy = true; | 651 | this->m_is_data_copy = true; |
| 644 | } | 652 | } |
| 645 | } | 653 | } |
| 646 | } | 654 | } |
| @@ -648,24 +656,21 @@ public: | |||
| 648 | 656 | ||
| 649 | ~GuestMemoryScoped() { | 657 | ~GuestMemoryScoped() { |
| 650 | if constexpr (FLAGS & GuestMemoryFlags::Write) { | 658 | if constexpr (FLAGS & GuestMemoryFlags::Write) { |
| 651 | if (this->size == 0) [[unlikely]] { | 659 | if (this->size() == 0) [[unlikely]] { |
| 652 | return; | 660 | return; |
| 653 | } | 661 | } |
| 654 | 662 | ||
| 655 | if (this->AddressChanged() || this->IsDataCopy()) { | 663 | if (this->AddressChanged() || this->IsDataCopy()) { |
| 656 | ASSERT(this->span_valid); | 664 | ASSERT(this->m_span_valid); |
| 657 | if constexpr (FLAGS & GuestMemoryFlags::Cached) { | 665 | if constexpr (FLAGS & GuestMemoryFlags::Cached) { |
| 658 | this->memory.WriteBlockCached(this->addr, this->data_span.data(), | 666 | this->m_memory.WriteBlockCached(this->m_addr, this->data(), this->size_bytes()); |
| 659 | this->size * sizeof(T)); | ||
| 660 | } else if constexpr (FLAGS & GuestMemoryFlags::Safe) { | 667 | } else if constexpr (FLAGS & GuestMemoryFlags::Safe) { |
| 661 | this->memory.WriteBlock(this->addr, this->data_span.data(), | 668 | this->m_memory.WriteBlock(this->m_addr, this->data(), this->size_bytes()); |
| 662 | this->size * sizeof(T)); | ||
| 663 | } else { | 669 | } else { |
| 664 | this->memory.WriteBlockUnsafe(this->addr, this->data_span.data(), | 670 | this->m_memory.WriteBlockUnsafe(this->m_addr, this->data(), this->size_bytes()); |
| 665 | this->size * sizeof(T)); | ||
| 666 | } | 671 | } |
| 667 | } else if constexpr (FLAGS & GuestMemoryFlags::Safe) { | 672 | } else if constexpr (FLAGS & GuestMemoryFlags::Safe) { |
| 668 | this->memory.InvalidateRegion(this->addr, this->size * sizeof(T)); | 673 | this->m_memory.InvalidateRegion(this->m_addr, this->size_bytes()); |
| 669 | } | 674 | } |
| 670 | } | 675 | } |
| 671 | } | 676 | } |