1#pragma once
2
3#include <nn/os.h>
4
5#include <basis/seadTypes.h>
6#include <prim/seadBitFlag.h>
7#include <prim/seadEnum.h>
8
9namespace sead
10{
11#line 46
12SEAD_ENUM(CoreId, cMain, cSub1, cSub2, cSub3, cSub4, cSub5, cSub6, cSub7, cSub8, cSub9, cSub10,
13 cSub11, cSub12, cSub13, cSub14, cSub15, cSub16, cSub17, cSub18, cSub19, cSub20, cSub21,
14 cSub22, cSub23, cSub24, cSub25, cSub26, cSub27, cSub28, cSub29, cSub30, cSub31, cSub32,
15 cUndef)
16
17class CoreIdMask
18{
19public:
20 CoreIdMask() = default;
21 explicit CoreIdMask(CoreId id) { mMask = makeCoreMask_(id); }
22 explicit CoreIdMask(CoreId id1, CoreId id2)
23 {
24 mMask |= makeCoreMask_(id: id1);
25 mMask |= makeCoreMask_(id: id2);
26 }
27 explicit CoreIdMask(CoreId id1, CoreId id2, CoreId id3)
28 {
29 mMask |= makeCoreMask_(id: id1);
30 mMask |= makeCoreMask_(id: id2);
31 mMask |= makeCoreMask_(id: id3);
32 }
33
34 void set(u32 mask) volatile { mMask = mask; }
35 operator u32() const volatile { return mMask; }
36
37 volatile CoreIdMask& OR(CoreId id) volatile
38 {
39 setOn(id);
40 return *this;
41 }
42
43 bool isOn(const CoreId& id) const volatile { return (mMask & makeCoreMask_(id)) != 0; }
44 void setOff(CoreId id) volatile { mMask &= ~makeCoreMask_(id); }
45 void setOn(CoreId id) volatile { mMask |= makeCoreMask_(id); }
46 void clear() volatile { mMask = 0; }
47 u32 countOnBits() const;
48
49protected:
50 static u32 makeCoreMask_(CoreId id) { return 1u << u32(int(id)); }
51
52 // It seems that mMask is a u32 and not a BitFlag32 because this class is intended to be
53 // volatile, and BitFlag isn't compatible with volatile...
54 u32 mMask = 0;
55};
56
57class CoreInfo
58{
59public:
60 static void configure();
61 static void dump();
62
63 static u32 getNumCores() { return sNumCores; }
64 static u32 getPlatformMainCoreId() { return sPlatformCoreId[0]; }
65 static u32 getPlatformCoreId(CoreId id) { return sPlatformCoreId[id]; }
66
67 static CoreId getCurrentCoreId()
68 {
69#ifdef NNSDK
70 // Based on the BotW implementation
71 const auto number = nn::os::GetTlsValue(slot: sCoreNumberTlsSlot);
72 if (number)
73 return number - 1;
74 return nn::os::GetCurrentCoreNumber();
75#else
76#error "Unknown platform"
77#endif
78 }
79
80 static u32 getPlatformMask(CoreId id);
81
82 static CoreId getCoreIdFromPlatformCoreId(u32 idx)
83 {
84 // XXX: Is this correct?
85 return sCoreIdFromPlatformCoreIdTable[idx];
86 }
87
88 static CoreIdMask getMaskAll()
89 {
90 // Based on the implementation of CoreInfo::dump
91 CoreIdMask mask;
92 mask.set((1u << sNumCores) - 1);
93 return mask;
94 }
95
96 static CoreIdMask getMaskSubAll()
97 {
98 // Based on the implementation of CoreInfo::dump
99 CoreIdMask mask;
100 mask.set(u32(getMaskAll()) - 1);
101 return mask;
102 }
103
104#ifdef NNSDK
105 static nn::os::TlsSlot getCoreNumberTlsSlot() { return sCoreNumberTlsSlot; }
106#endif
107
108protected:
109 static u32 sNumCores;
110 static u32 sPlatformCoreId[32];
111 static CoreId sCoreIdFromPlatformCoreIdTable[32];
112#ifdef NNSDK
113 static nn::os::TlsSlot sCoreNumberTlsSlot;
114#endif
115};
116
117} // namespace sead
118