diff options
Diffstat (limited to 'src/common/multi_level_page_table.h')
-rw-r--r-- | src/common/multi_level_page_table.h | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/src/common/multi_level_page_table.h b/src/common/multi_level_page_table.h new file mode 100644 index 000000000..dde1cc962 --- /dev/null +++ b/src/common/multi_level_page_table.h @@ -0,0 +1,79 @@ +// Copyright 2021 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include <type_traits> +#include <utility> +#include <vector> + +#include "common/common_types.h" + +namespace Common { + +template <typename BaseAddr> +class MultiLevelPageTable final { +public: + constexpr MultiLevelPageTable() = default; + explicit MultiLevelPageTable(std::size_t address_space_bits, std::size_t first_level_bits, + std::size_t page_bits); + + ~MultiLevelPageTable() noexcept; + + MultiLevelPageTable(const MultiLevelPageTable&) = delete; + MultiLevelPageTable& operator=(const MultiLevelPageTable&) = delete; + + MultiLevelPageTable(MultiLevelPageTable&& other) noexcept + : address_space_bits{std::exchange(other.address_space_bits, 0)}, + first_level_bits{std::exchange(other.first_level_bits, 0)}, page_bits{std::exchange( + other.page_bits, 0)}, + first_level_shift{std::exchange(other.first_level_shift, 0)}, + first_level_chunk_size{std::exchange(other.first_level_chunk_size, 0)}, + first_level_map{std::move(other.first_level_map)}, base_ptr{std::exchange(other.base_ptr, + nullptr)} {} + + MultiLevelPageTable& operator=(MultiLevelPageTable&& other) noexcept { + address_space_bits = std::exchange(other.address_space_bits, 0); + first_level_bits = std::exchange(other.first_level_bits, 0); + page_bits = std::exchange(other.page_bits, 0); + first_level_shift = std::exchange(other.first_level_shift, 0); + first_level_chunk_size = std::exchange(other.first_level_chunk_size, 0); + alloc_size = std::exchange(other.alloc_size, 0); + first_level_map = std::move(other.first_level_map); + base_ptr = std::exchange(other.base_ptr, nullptr); + return *this; + } + + void ReserveRange(u64 start, std::size_t size); + + [[nodiscard]] constexpr const BaseAddr& operator[](std::size_t index) const { + return base_ptr[index]; + } + + [[nodiscard]] constexpr BaseAddr& operator[](std::size_t index) { + return base_ptr[index]; + } + + [[nodiscard]] constexpr BaseAddr* data() { + return base_ptr; + } + + [[nodiscard]] constexpr const BaseAddr* data() const { + return base_ptr; + } + +private: + void AllocateLevel(u64 level); + + std::size_t address_space_bits{}; + std::size_t first_level_bits{}; + std::size_t page_bits{}; + std::size_t first_level_shift{}; + std::size_t first_level_chunk_size{}; + std::size_t alloc_size{}; + std::vector<void*> first_level_map{}; + BaseAddr* base_ptr{}; +}; + +} // namespace Common |