aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorClyne <clyne@bitgloo.com>2022-08-11 08:10:34 -0400
committerClyne <clyne@bitgloo.com>2022-08-11 08:10:34 -0400
commit2e6001946fd4b8b450e8023662e2192a94972f25 (patch)
tree1a345cd9cbdeca9debc4cd07a832d9394b75ed61
parent922489447fda4a0975aefcc1045cfaac744be598 (diff)
Verify register and mask parameterserror-checking
-rw-r--r--funreg.hpp75
1 files changed, 47 insertions, 28 deletions
diff --git a/funreg.hpp b/funreg.hpp
index accdb9d..dc646aa 100644
--- a/funreg.hpp
+++ b/funreg.hpp
@@ -86,20 +86,18 @@ requires IsAccess<Access>
struct Register;
template<typename T>
-concept IsRegister = requires {
- requires IsAccess<typename T::access>;
- requires std::same_as<T, Register<typename T::access>>;
-};
+concept IsRegister =
+ IsAccess<typename T::access> &&
+ std::same_as<T, Register<typename T::access>>;
#else
template<typename T, uintptr_t Addr>
requires(std::unsigned_integral<T>)
class Register;
template<typename T>
-concept IsRegister = requires {
- requires std::unsigned_integral<typename T::type>;
- requires IsAccess<typename T::Access>;
-};
+concept IsRegister =
+ std::unsigned_integral<typename T::type> &&
+ IsAccess<typename T::Access>;
#endif
template<typename Reg, typename Reg::type Mask>
@@ -107,10 +105,21 @@ requires IsRegister<Reg>
struct RegisterMask;
template<typename T>
-concept IsRegisterMask = requires {
- requires IsRegister<typename T::reg>;
- requires std::same_as<T, RegisterMask<typename T::reg, T::mask>>;
-};
+concept IsRegisterMask =
+ IsRegister<typename T::reg> &&
+ 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
@@ -156,7 +165,8 @@ public:
* Sets register bits to '1' according to the given RegisterMasks.
*/
template<typename... Masks>
- requires(IsRegisterMask<Masks>, ...)
+ requires((IsRegisterMask<Masks>, ...) &&
+ (UsesRegister<Masks, Register<Access>>, ...))
static void set() {
apply<Masks...>([](auto r, auto m) { return r | m; });
}
@@ -172,7 +182,8 @@ public:
* Clears register bits to '0' according to the given RegisterMasks.
*/
template<typename... Masks>
- requires(IsRegisterMask<Masks>, ...)
+ requires((IsRegisterMask<Masks>, ...) &&
+ (UsesRegister<Masks, Register<Access>>, ...))
static void clear() {
apply<Masks...>([](auto r, auto m) { return r & ~m; });
}
@@ -188,7 +199,8 @@ public:
* Toggles bits in the register according to the given RegisterMasks.
*/
template<typename... Masks>
- requires(IsRegisterMask<Masks>, ...)
+ requires((IsRegisterMask<Masks>, ...) &&
+ (UsesRegister<Masks, Register<Access>>, ...))
static void toggle() {
apply<Masks...>([](auto r, auto m) { return r ^m; });
}
@@ -206,7 +218,8 @@ public:
* If no masks are given, all register bits are returned.
*/
template<typename... Masks>
- requires(IsRegisterMask<Masks>, ...)
+ requires((IsRegisterMask<Masks>, ...) &&
+ (UsesRegister<Masks, Register<Access>>, ...))
static auto read() {
if constexpr (sizeof...(Masks) > 0)
return read() & mergeMasks<Masks...>();
@@ -219,7 +232,8 @@ public:
* If no masks are given, tests if the register has a non-zero value.
*/
template<typename... Masks>
- requires(IsRegisterMask<Masks>, ...)
+ requires((IsRegisterMask<Masks>, ...) &&
+ (UsesRegister<Masks, Register<Access>>, ...))
static bool test() {
if constexpr (sizeof...(Masks) > 0) {
auto mask = mergeMasks<Masks...>();
@@ -248,16 +262,16 @@ public:
}
}
-private:
+ // Internal use only.
// Applies bit-masks to the register through the provided function.
- // The provided function receives a pointer to the register's data and a
- // bit-mask created by merging all provided bit-masks.
+ // All masks meant for this register are merged together; then, `fn`
+ // 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.
template<typename... Masks>
- requires(IsRegisterMask<Masks>, ...)
- static void apply(auto fn) {
+ constexpr static void apply(auto fn) {
if constexpr (sizeof...(Masks) > 0) {
- auto mask = mergeMasks<Masks...>();
+ constexpr auto mask = mergeMasks<Masks...>();
if constexpr (mask)
write(fn(read(), mask));
} else {
@@ -265,11 +279,11 @@ private:
}
}
+private:
// Takes a list of bit-masks, and returns a merged mask of those which are
// meant for this register.
template<typename... Masks>
- requires(IsRegisterMask<Masks>, ...)
- static auto mergeMasks() {
+ constexpr static auto mergeMasks() {
if constexpr (sizeof...(Masks) > 0) {
if constexpr ((isThis<typename Masks::reg> | ...)) {
auto mask =
@@ -482,7 +496,8 @@ public:
* only written once.
*/
template<typename... Masks>
- requires(IsRegisterMask<Masks>, ...)
+ requires((IsRegisterMask<Masks>, ...) &&
+ (UsesSomeRegister<Masks, Registers...>, ...))
static void set() {
apply<Masks...>([](auto r, auto m) { return r | m; });
}
@@ -493,7 +508,8 @@ public:
* Only reads and writes each register once; see set().
*/
template<typename... Masks>
- requires(IsRegisterMask<Masks>, ...)
+ requires((IsRegisterMask<Masks>, ...) &&
+ (UsesSomeRegister<Masks, Registers...>, ...))
static void clear() {
apply<Masks...>([](auto r, auto m) { return r & ~m; });
}
@@ -504,7 +520,8 @@ public:
* Only reads and writes each register once; see set().
*/
template<typename... Masks>
- requires(IsRegisterMask<Masks>, ...)
+ requires((IsRegisterMask<Masks>, ...) &&
+ (UsesSomeRegister<Masks, Registers...>, ...))
static void toggle() {
apply<Masks...>([](auto r, auto m) { return r ^ m; });
}
@@ -523,6 +540,8 @@ public:
private:
template<typename... Masks>
+ requires((IsRegisterMask<Masks>, ...) &&
+ (UsesSomeRegister<Masks, Registers...>, ...))
static void apply(auto fn) {
(Registers::template apply<Masks...>(fn), ...);
}