M tests/memory/address.cpp => tests/memory/address.cpp +4 -2
@@ 2,12 2,13 @@
#include <catch2/catch.hpp>
-#include "vmm/memory.hpp"
+#include "vmm/memory/memory.hpp"
class TestAddress : public vmm::memory::Address<TestAddress, uint64_t>
{
using value_type = TestAddress;
using size_type = uint64_t;
+ using reference = value_type&;
using const_reference = const value_type&;
private:
@@ 27,10 28,11 @@ class TestAddress : public vmm::memory::Address<TestAddress, uint64_t>
auto operator==(const_reference addr) const noexcept -> bool { return m_addr == addr.data(); }
auto operator!=(const_reference addr) const noexcept -> bool { return m_addr != addr.data(); }
- auto align(const size_type alignment) noexcept -> void override
+ auto align(const size_type alignment) noexcept -> reference override
{
const auto mask = alignment - 1;
m_addr = (*this + mask) & ~mask;
+ return *this;
}
};
M vmm/memory/detail/address.hpp => vmm/memory/detail/address.hpp +1 -1
@@ 41,7 41,7 @@ class Address
virtual auto operator-(const Concrete&) const noexcept -> Concrete = 0;
// Aligns the address to a power of 2.
- virtual auto align(const Size) noexcept -> void = 0;
+ virtual auto align(const Size) noexcept -> Concrete& = 0;
};
//template<typename Derived>
M vmm/memory/detail/guest.cpp => vmm/memory/detail/guest.cpp +44 -1
@@ 38,10 38,53 @@ auto GuestAddress::operator-(const_reference addr) const noexcept -> value_type
return *this - addr.data();
}
-auto GuestAddress::align(const size_type alignment) noexcept -> void
+auto GuestAddress::align(const size_type alignment) noexcept -> reference
{
const auto mask = alignment - 1;
m_addr = (*this + mask) & ~mask;
+ return *this;
+}
+
+auto MemoryRegionAddress::data() const noexcept -> size_type
+{
+ return m_addr;
+}
+
+auto MemoryRegionAddress::operator&(const size_type mask) const noexcept -> size_type
+{
+ return m_addr & mask;
+}
+
+auto MemoryRegionAddress::operator|(const size_type mask) const noexcept -> size_type
+{
+ return m_addr | mask;
+}
+
+auto MemoryRegionAddress::operator+(const size_type val) const noexcept -> value_type
+{
+ return MemoryRegionAddress{m_addr + val};
+}
+
+auto MemoryRegionAddress::operator+(const_reference addr) const noexcept -> value_type
+{
+ return *this + addr.data();
+}
+
+auto MemoryRegionAddress::operator-(const size_type val) const noexcept -> value_type
+{
+ return MemoryRegionAddress{m_addr - val};
+}
+
+auto MemoryRegionAddress::operator-(const_reference addr) const noexcept -> value_type
+{
+ return *this - addr.data();
+}
+
+auto MemoryRegionAddress::align(const size_type alignment) noexcept -> reference
+{
+ const auto mask = alignment - 1;
+ m_addr = (*this + mask) & ~mask;
+ return *this;
}
} // vmm::memory::detail
M vmm/memory/detail/guest.hpp => vmm/memory/detail/guest.hpp +40 -1
@@ 22,6 22,7 @@ class GuestAddress : public Address<GuestAddress, uint64_t>
{
using value_type = GuestAddress;
using size_type = uint64_t;
+ using reference = value_type&;
using const_reference = const value_type&;
private:
@@ 51,7 52,45 @@ class GuestAddress : public Address<GuestAddress, uint64_t>
auto operator-(const_reference addr) const noexcept -> value_type override;
// Aligns the address to a power of 2.
- auto align(const size_type alignment) noexcept -> void override;
+ auto align(const size_type alignment) noexcept -> reference override;
+};
+
+// An offset into a memory region.
+class MemoryRegionAddress : public Address<MemoryRegionAddress, uint64_t>
+{
+ using value_type = MemoryRegionAddress;
+ using size_type = uint64_t;
+ using reference = value_type&;
+ using const_reference = const value_type&;
+
+ private:
+ size_type m_addr{};
+ public:
+ explicit MemoryRegionAddress(size_type addr=0) noexcept : m_addr{addr} {}
+
+ auto data() const noexcept -> size_type override;
+
+ // Returns the bitwise AND of the address and a mask.
+ auto operator&(const size_type mask) const noexcept -> size_type override;
+
+ // Returns the bitwise OR of the address and a mask.
+ auto operator|(const size_type mask) const noexcept -> size_type override;
+
+ // Returns the address plus some value (sum is wrapped).
+ auto operator+(const size_type val) const noexcept -> value_type override;
+
+ // Returns the sum of the address and another address (sum is wrapped).
+ auto operator+(const_reference addr) const noexcept -> value_type override;
+
+ // Returns the address minus some value (difference is wrapped).
+ auto operator-(const size_type val) const noexcept -> value_type override;
+
+ // Returns the difference between the address and another address
+ // (difference is wrapped).
+ auto operator-(const_reference addr) const noexcept -> value_type override;
+
+ // Aligns the address to a power of 2.
+ auto align(const size_type alignment) noexcept -> reference override;
};
} // vmm::memory::detail
M vmm/memory/memory.hpp => vmm/memory/memory.hpp +1 -0
@@ 16,5 16,6 @@ template<typename T, typename S>
using Address = vmm::memory::detail::Address<T, S>;
using GuestAddress = vmm::memory::detail::GuestAddress;
+using MemoryRegionAddress = vmm::memory::detail::MemoryRegionAddress;
} // vmm::memory