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>
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
* 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; });
}
* 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; });
}
* 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; });
}
* 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...>();
* 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...>();
}
}
-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 {
}
}
+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 =
* 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; });
}
* 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; });
}
* 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; });
}
private:
template<typename... Masks>
+ requires((IsRegisterMask<Masks>, ...) &&
+ (UsesSomeRegister<Masks, Registers...>, ...))
static void apply(auto fn) {
(Registers::template apply<Masks...>(fn), ...);
}