#pragma once #include "../../../Auxiliary/types.hpp" #include "../../../Auxiliary/bits.hpp" namespace JabyEngine { namespace IOAdress { constexpr uintptr_t patch_adr(uintptr_t adr) { constexpr uintptr_t Mask = 0xF0000000; constexpr uintptr_t Base = 0x10000000; // We might want to change this later to 0xB0000000 for caching and stuff (More research needed) return (Base + (adr & ~Mask)); } } namespace internal { template struct IOValue { typedef S UnderlyingType; UnderlyingType raw; template static constexpr T from(const ARGS&...args) { return T{0}.set(args...); } constexpr T& set(Bit bit) { this->raw = bit::set(this->raw, bit); return static_cast(*this); } constexpr T& set(ClearBit bit) { this->raw = bit::set(this->raw, bit); return static_cast(*this); } constexpr T& set_range(const BitRange& bits, UnderlyingType value) { this->raw = bit::value::set_normalized(this->raw, bits, value); return static_cast(*this); } template constexpr T& set(const BitRange::RangeValuePair& value) { this->raw = bit::value::set_normalized(this->raw, value); return static_cast(*this); } template constexpr T& set(const U& head, const ARGS&...tail) { return this->set(head).set(tail...); } constexpr IOValue::UnderlyingType get(BitRange bits) const { return bit::value::get_normalized(this->raw, bits.pos, bits.length); } constexpr T& clear(Bit bit) { this->raw = bit::clear(this->raw, bit); return static_cast(*this); } constexpr bool is_set(Bit bit) const { return bit::is_set(this->raw, bit); } }; } template struct IOPort { using Value = T; T value; T read() const { return {const_cast*>(this)->value.raw}; } void write(T value) { const_cast*>(this)->value.raw = value.raw; } }; template<> struct IOPort; template struct IOPort32 { union ValueHelper { struct { uint16_t low; uint16_t high; }; T value; }; using Value = T; T value; T read() const { const auto* cast_this = reinterpret_cast*>(this); const volatile auto* cv_this = const_cast(cast_this); return ValueHelper{.low = cv_this->value.low, .high = cv_this->value.high}.value; } void write(T value) { const auto new_value = ValueHelper{.value = value}; auto* cast_this = reinterpret_cast*>(this); volatile auto* v_this = const_cast(cast_this); v_this->value.low = new_value.low; v_this->value.high = new_value.high; } }; #define __declare_io_struct(name, type) struct name : public ::JabyEngine::internal::IOValue #define __declare_io_port(type, adr) *reinterpret_cast(adr) #define __declare_io_value(type, adr) __declare_io_port(type, adr) #define __declare_io_port_array(type, size, adr) reinterpret_cast(*reinterpret_cast(adr)) }