summaryrefslogtreecommitdiff
path: root/src/common/multi_level_page_table.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/multi_level_page_table.h')
-rw-r--r--src/common/multi_level_page_table.h79
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 @@
1// Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <type_traits>
8#include <utility>
9#include <vector>
10
11#include "common/common_types.h"
12
13namespace Common {
14
15template <typename BaseAddr>
16class MultiLevelPageTable final {
17public:
18 constexpr MultiLevelPageTable() = default;
19 explicit MultiLevelPageTable(std::size_t address_space_bits, std::size_t first_level_bits,
20 std::size_t page_bits);
21
22 ~MultiLevelPageTable() noexcept;
23
24 MultiLevelPageTable(const MultiLevelPageTable&) = delete;
25 MultiLevelPageTable& operator=(const MultiLevelPageTable&) = delete;
26
27 MultiLevelPageTable(MultiLevelPageTable&& other) noexcept
28 : address_space_bits{std::exchange(other.address_space_bits, 0)},
29 first_level_bits{std::exchange(other.first_level_bits, 0)}, page_bits{std::exchange(
30 other.page_bits, 0)},
31 first_level_shift{std::exchange(other.first_level_shift, 0)},
32 first_level_chunk_size{std::exchange(other.first_level_chunk_size, 0)},
33 first_level_map{std::move(other.first_level_map)}, base_ptr{std::exchange(other.base_ptr,
34 nullptr)} {}
35
36 MultiLevelPageTable& operator=(MultiLevelPageTable&& other) noexcept {
37 address_space_bits = std::exchange(other.address_space_bits, 0);
38 first_level_bits = std::exchange(other.first_level_bits, 0);
39 page_bits = std::exchange(other.page_bits, 0);
40 first_level_shift = std::exchange(other.first_level_shift, 0);
41 first_level_chunk_size = std::exchange(other.first_level_chunk_size, 0);
42 alloc_size = std::exchange(other.alloc_size, 0);
43 first_level_map = std::move(other.first_level_map);
44 base_ptr = std::exchange(other.base_ptr, nullptr);
45 return *this;
46 }
47
48 void ReserveRange(u64 start, std::size_t size);
49
50 [[nodiscard]] constexpr const BaseAddr& operator[](std::size_t index) const {
51 return base_ptr[index];
52 }
53
54 [[nodiscard]] constexpr BaseAddr& operator[](std::size_t index) {
55 return base_ptr[index];
56 }
57
58 [[nodiscard]] constexpr BaseAddr* data() {
59 return base_ptr;
60 }
61
62 [[nodiscard]] constexpr const BaseAddr* data() const {
63 return base_ptr;
64 }
65
66private:
67 void AllocateLevel(u64 level);
68
69 std::size_t address_space_bits{};
70 std::size_t first_level_bits{};
71 std::size_t page_bits{};
72 std::size_t first_level_shift{};
73 std::size_t first_level_chunk_size{};
74 std::size_t alloc_size{};
75 std::vector<void*> first_level_map{};
76 BaseAddr* base_ptr{};
77};
78
79} // namespace Common