]> code.bitgloo.com Git - clyne/funreg.git/commitdiff
Verify register and mask parameters error-checking
authorClyne <clyne@bitgloo.com>
Thu, 11 Aug 2022 12:10:34 +0000 (08:10 -0400)
committerClyne <clyne@bitgloo.com>
Thu, 11 Aug 2022 12:10:34 +0000 (08:10 -0400)
funreg.hpp

index accdb9d6a7bfca62f6e8676cea52712b233a06af..dc646aacf03aa4d6f6415658db6a35d5ee87c33a 100644 (file)
@@ -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), ...);
     }