summaryrefslogtreecommitdiffstats
path: root/src/core/hle/kernel/k_address_space_info.cpp
blob: eb8af660c65aa10003283f039f3ae10b64e71138 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
// Copyright 2020 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.

#include <array>

#include "common/assert.h"
#include "common/common_sizes.h"
#include "core/hle/kernel/k_address_space_info.h"

namespace Kernel {

namespace {

// clang-format off
constexpr std::array<KAddressSpaceInfo, 13> AddressSpaceInfos{{
   { .bit_width = 32, .address = Size_2_MB  , .size = Size_1_GB   - Size_2_MB  , .type = KAddressSpaceInfo::Type::MapSmall,    },
   { .bit_width = 32, .address = Size_1_GB  , .size = Size_4_GB   - Size_1_GB  , .type = KAddressSpaceInfo::Type::MapLarge, },
   { .bit_width = 32, .address = Invalid    , .size = Size_1_GB                , .type = KAddressSpaceInfo::Type::Heap,       },
   { .bit_width = 32, .address = Invalid    , .size = Size_1_GB                , .type = KAddressSpaceInfo::Type::Alias,      },
   { .bit_width = 36, .address = Size_128_MB, .size = Size_2_GB   - Size_128_MB, .type = KAddressSpaceInfo::Type::MapSmall,    },
   { .bit_width = 36, .address = Size_2_GB  , .size = Size_64_GB  - Size_2_GB  , .type = KAddressSpaceInfo::Type::MapLarge, },
   { .bit_width = 36, .address = Invalid    , .size = Size_6_GB                , .type = KAddressSpaceInfo::Type::Heap,       },
   { .bit_width = 36, .address = Invalid    , .size = Size_6_GB                , .type = KAddressSpaceInfo::Type::Alias,      },
   { .bit_width = 39, .address = Size_128_MB, .size = Size_512_GB - Size_128_MB, .type = KAddressSpaceInfo::Type::Map39Bit, },
   { .bit_width = 39, .address = Invalid    , .size = Size_64_GB               , .type = KAddressSpaceInfo::Type::MapSmall     },
   { .bit_width = 39, .address = Invalid    , .size = Size_6_GB                , .type = KAddressSpaceInfo::Type::Heap,       },
   { .bit_width = 39, .address = Invalid    , .size = Size_64_GB               , .type = KAddressSpaceInfo::Type::Alias,      },
   { .bit_width = 39, .address = Invalid    , .size = Size_2_GB                , .type = KAddressSpaceInfo::Type::Stack,      },
}};
// clang-format on

constexpr bool IsAllowedIndexForAddress(std::size_t index) {
    return index < AddressSpaceInfos.size() && AddressSpaceInfos[index].address != Invalid;
}

using IndexArray =
    std::array<std::size_t, static_cast<std::size_t>(KAddressSpaceInfo::Type::Count)>;

constexpr IndexArray AddressSpaceIndices32Bit{
    0, 1, 0, 2, 0, 3,
};

constexpr IndexArray AddressSpaceIndices36Bit{
    4, 5, 4, 6, 4, 7,
};

constexpr IndexArray AddressSpaceIndices39Bit{
    9, 8, 8, 10, 12, 11,
};

constexpr bool IsAllowed32BitType(KAddressSpaceInfo::Type type) {
    return type < KAddressSpaceInfo::Type::Count && type != KAddressSpaceInfo::Type::Map39Bit &&
           type != KAddressSpaceInfo::Type::Stack;
}

constexpr bool IsAllowed36BitType(KAddressSpaceInfo::Type type) {
    return type < KAddressSpaceInfo::Type::Count && type != KAddressSpaceInfo::Type::Map39Bit &&
           type != KAddressSpaceInfo::Type::Stack;
}

constexpr bool IsAllowed39BitType(KAddressSpaceInfo::Type type) {
    return type < KAddressSpaceInfo::Type::Count && type != KAddressSpaceInfo::Type::MapLarge;
}

} // namespace

u64 KAddressSpaceInfo::GetAddressSpaceStart(std::size_t width, Type type) {
    const std::size_t index{static_cast<std::size_t>(type)};
    switch (width) {
    case 32:
        ASSERT(IsAllowed32BitType(type));
        ASSERT(IsAllowedIndexForAddress(AddressSpaceIndices32Bit[index]));
        return AddressSpaceInfos[AddressSpaceIndices32Bit[index]].address;
    case 36:
        ASSERT(IsAllowed36BitType(type));
        ASSERT(IsAllowedIndexForAddress(AddressSpaceIndices36Bit[index]));
        return AddressSpaceInfos[AddressSpaceIndices36Bit[index]].address;
    case 39:
        ASSERT(IsAllowed39BitType(type));
        ASSERT(IsAllowedIndexForAddress(AddressSpaceIndices39Bit[index]));
        return AddressSpaceInfos[AddressSpaceIndices39Bit[index]].address;
    }
    UNREACHABLE();
    return 0;
}

std::size_t KAddressSpaceInfo::GetAddressSpaceSize(std::size_t width, Type type) {
    const std::size_t index{static_cast<std::size_t>(type)};
    switch (width) {
    case 32:
        ASSERT(IsAllowed32BitType(type));
        return AddressSpaceInfos[AddressSpaceIndices32Bit[index]].size;
    case 36:
        ASSERT(IsAllowed36BitType(type));
        return AddressSpaceInfos[AddressSpaceIndices36Bit[index]].size;
    case 39:
        ASSERT(IsAllowed39BitType(type));
        return AddressSpaceInfos[AddressSpaceIndices39Bit[index]].size;
    }
    UNREACHABLE();
    return 0;
}

} // namespace Kernel