Verify register and mask parameters

error-checking
Clyne 2 years ago
parent 922489447f
commit 2e6001946f

@ -86,20 +86,18 @@ requires IsAccess<Access>
struct Register; struct Register;
template<typename T> template<typename T>
concept IsRegister = requires { concept IsRegister =
requires IsAccess<typename T::access>; IsAccess<typename T::access> &&
requires std::same_as<T, Register<typename T::access>>; std::same_as<T, Register<typename T::access>>;
};
#else #else
template<typename T, uintptr_t Addr> template<typename T, uintptr_t Addr>
requires(std::unsigned_integral<T>) requires(std::unsigned_integral<T>)
class Register; class Register;
template<typename T> template<typename T>
concept IsRegister = requires { concept IsRegister =
requires std::unsigned_integral<typename T::type>; std::unsigned_integral<typename T::type> &&
requires IsAccess<typename T::Access>; IsAccess<typename T::Access>;
};
#endif #endif
template<typename Reg, typename Reg::type Mask> template<typename Reg, typename Reg::type Mask>
@ -107,10 +105,21 @@ requires IsRegister<Reg>
struct RegisterMask; struct RegisterMask;
template<typename T> template<typename T>
concept IsRegisterMask = requires { concept IsRegisterMask =
requires IsRegister<typename T::reg>; IsRegister<typename T::reg> &&
requires std::same_as<T, RegisterMask<typename T::reg, T::mask>>; std::same_as<T, RegisterMask<typename T::reg, T::mask>>;
};
template<typename M, typename R>
concept UsesRegister =
IsRegisterMask<M> &&
IsRegister<R> &&
std::same_as<typename M::reg, R>;
template<typename M, typename... Rs>
concept UsesSomeRegister =
IsRegisterMask<M> &&
(IsRegister<Rs>, ...) &&
(std::same_as<typename M::reg, Rs> || ...);
/** /**
* @struct Register * @struct Register
@ -156,7 +165,8 @@ public:
* Sets register bits to '1' according to the given RegisterMasks. * Sets register bits to '1' according to the given RegisterMasks.
*/ */
template<typename... Masks> template<typename... Masks>
requires(IsRegisterMask<Masks>, ...) requires((IsRegisterMask<Masks>, ...) &&
(UsesRegister<Masks, Register<Access>>, ...))
static void set() { static void set() {
apply<Masks...>([](auto r, auto m) { return r | m; }); apply<Masks...>([](auto r, auto m) { return r | m; });
} }
@ -172,7 +182,8 @@ public:
* Clears register bits to '0' according to the given RegisterMasks. * Clears register bits to '0' according to the given RegisterMasks.
*/ */
template<typename... Masks> template<typename... Masks>
requires(IsRegisterMask<Masks>, ...) requires((IsRegisterMask<Masks>, ...) &&
(UsesRegister<Masks, Register<Access>>, ...))
static void clear() { static void clear() {
apply<Masks...>([](auto r, auto m) { return r & ~m; }); apply<Masks...>([](auto r, auto m) { return r & ~m; });
} }
@ -188,7 +199,8 @@ public:
* Toggles bits in the register according to the given RegisterMasks. * Toggles bits in the register according to the given RegisterMasks.
*/ */
template<typename... Masks> template<typename... Masks>
requires(IsRegisterMask<Masks>, ...) requires((IsRegisterMask<Masks>, ...) &&
(UsesRegister<Masks, Register<Access>>, ...))
static void toggle() { static void toggle() {
apply<Masks...>([](auto r, auto m) { return r ^m; }); apply<Masks...>([](auto r, auto m) { return r ^m; });
} }
@ -206,7 +218,8 @@ public:
* If no masks are given, all register bits are returned. * If no masks are given, all register bits are returned.
*/ */
template<typename... Masks> template<typename... Masks>
requires(IsRegisterMask<Masks>, ...) requires((IsRegisterMask<Masks>, ...) &&
(UsesRegister<Masks, Register<Access>>, ...))
static auto read() { static auto read() {
if constexpr (sizeof...(Masks) > 0) if constexpr (sizeof...(Masks) > 0)
return read() & mergeMasks<Masks...>(); return read() & mergeMasks<Masks...>();
@ -219,7 +232,8 @@ public:
* If no masks are given, tests if the register has a non-zero value. * If no masks are given, tests if the register has a non-zero value.
*/ */
template<typename... Masks> template<typename... Masks>
requires(IsRegisterMask<Masks>, ...) requires((IsRegisterMask<Masks>, ...) &&
(UsesRegister<Masks, Register<Access>>, ...))
static bool test() { static bool test() {
if constexpr (sizeof...(Masks) > 0) { if constexpr (sizeof...(Masks) > 0) {
auto mask = mergeMasks<Masks...>(); auto mask = mergeMasks<Masks...>();
@ -248,16 +262,16 @@ public:
} }
} }
private: // Internal use only.
// Applies bit-masks to the register through the provided function. // Applies bit-masks to the register through the provided function.
// The provided function receives a pointer to the register's data and a // All masks meant for this register are merged together; then, `fn`
// bit-mask created by merging all provided bit-masks. // will receive the register's current value and the mask to carry out
// the operation. The result is written back to the register.
// If no masks are given, a mask selecting all bits is used. // If no masks are given, a mask selecting all bits is used.
template<typename... Masks> template<typename... Masks>
requires(IsRegisterMask<Masks>, ...) constexpr static void apply(auto fn) {
static void apply(auto fn) {
if constexpr (sizeof...(Masks) > 0) { if constexpr (sizeof...(Masks) > 0) {
auto mask = mergeMasks<Masks...>(); constexpr auto mask = mergeMasks<Masks...>();
if constexpr (mask) if constexpr (mask)
write(fn(read(), mask)); write(fn(read(), mask));
} else { } else {
@ -265,11 +279,11 @@ private:
} }
} }
private:
// Takes a list of bit-masks, and returns a merged mask of those which are // Takes a list of bit-masks, and returns a merged mask of those which are
// meant for this register. // meant for this register.
template<typename... Masks> template<typename... Masks>
requires(IsRegisterMask<Masks>, ...) constexpr static auto mergeMasks() {
static auto mergeMasks() {
if constexpr (sizeof...(Masks) > 0) { if constexpr (sizeof...(Masks) > 0) {
if constexpr ((isThis<typename Masks::reg> | ...)) { if constexpr ((isThis<typename Masks::reg> | ...)) {
auto mask = auto mask =
@ -482,7 +496,8 @@ public:
* only written once. * only written once.
*/ */
template<typename... Masks> template<typename... Masks>
requires(IsRegisterMask<Masks>, ...) requires((IsRegisterMask<Masks>, ...) &&
(UsesSomeRegister<Masks, Registers...>, ...))
static void set() { static void set() {
apply<Masks...>([](auto r, auto m) { return r | m; }); apply<Masks...>([](auto r, auto m) { return r | m; });
} }
@ -493,7 +508,8 @@ public:
* Only reads and writes each register once; see set(). * Only reads and writes each register once; see set().
*/ */
template<typename... Masks> template<typename... Masks>
requires(IsRegisterMask<Masks>, ...) requires((IsRegisterMask<Masks>, ...) &&
(UsesSomeRegister<Masks, Registers...>, ...))
static void clear() { static void clear() {
apply<Masks...>([](auto r, auto m) { return r & ~m; }); apply<Masks...>([](auto r, auto m) { return r & ~m; });
} }
@ -504,7 +520,8 @@ public:
* Only reads and writes each register once; see set(). * Only reads and writes each register once; see set().
*/ */
template<typename... Masks> template<typename... Masks>
requires(IsRegisterMask<Masks>, ...) requires((IsRegisterMask<Masks>, ...) &&
(UsesSomeRegister<Masks, Registers...>, ...))
static void toggle() { static void toggle() {
apply<Masks...>([](auto r, auto m) { return r ^ m; }); apply<Masks...>([](auto r, auto m) { return r ^ m; });
} }
@ -523,6 +540,8 @@ public:
private: private:
template<typename... Masks> template<typename... Masks>
requires((IsRegisterMask<Masks>, ...) &&
(UsesSomeRegister<Masks, Registers...>, ...))
static void apply(auto fn) { static void apply(auto fn) {
(Registers::template apply<Masks...>(fn), ...); (Registers::template apply<Masks...>(fn), ...);
} }

Loading…
Cancel
Save