From f459ffe619d0b16dbd3333b226d8bc4e73fde915 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Tue, 20 Oct 2026 21:33:36 -0400 Subject: [PATCH] Clean up Storage.hpp and starship operators. --- Components/DiskII/IWM.cpp | 6 +- InstructionSets/x86/Flags.hpp | 5 +- Numeric/RegisterSizes.hpp | 81 ++++++++++++++++++++++++-- Storage/Storage.hpp | 106 +++++++++++++++++++--------------- 4 files changed, 143 insertions(+), 55 deletions(-) diff --git a/Components/DiskII/IWM.cpp b/Components/DiskII/IWM.cpp index 4aca34cef..31fc77a74 100644 --- a/Components/DiskII/IWM.cpp +++ b/Components/DiskII/IWM.cpp @@ -347,7 +347,11 @@ void IWM::select_shift_mode() { // If writing mode just began, set the drive into write mode and cue up the first output byte. if(old_shift_mode != ShiftMode::Writing && shift_mode_ == ShiftMode::Writing) { if(drives_[active_drive_]) { - drives_[active_drive_]->begin_writing(Storage::Time(1, clock_rate_ / bit_length_.get()), false, false); + drives_[active_drive_]->begin_writing( + Storage::Time(1, clock_rate_ / bit_length_.as()), + false, + false + ); } shift_register_ = next_output_; write_handshake_ |= 0x80 | 0x40; diff --git a/InstructionSets/x86/Flags.hpp b/InstructionSets/x86/Flags.hpp index 3d3630068..56b0ad846 100644 --- a/InstructionSets/x86/Flags.hpp +++ b/InstructionSets/x86/Flags.hpp @@ -222,7 +222,10 @@ public: return result; } - bool operator ==(const Flags &rhs) const { + auto operator <=> (const Flags &rhs) const { + return get() <=> rhs.get(); + } + auto operator == (const Flags &rhs) const { return get() == rhs.get(); } diff --git a/Numeric/RegisterSizes.hpp b/Numeric/RegisterSizes.hpp index 252097282..ae667de91 100644 --- a/Numeric/RegisterSizes.hpp +++ b/Numeric/RegisterSizes.hpp @@ -9,6 +9,7 @@ #pragma once #include +#include #include #pragma pack(push, 1) @@ -28,29 +29,61 @@ template struct Halves { /// Provides access to all intermediate parts of a larger int. template union alignas(Full) alignas(Half) RegisterPair { - RegisterPair(Full v) : full(v) {} + constexpr RegisterPair(const Full v) noexcept : full(v) {} RegisterPair() = default; Full full; - auto operator <=>(const RegisterPair &rhs) const { + Halves halves; + + auto operator <=>(const RegisterPair rhs) const { return full <=> rhs.full; } - auto operator ==(const RegisterPair &rhs) const { + auto operator ==(const RegisterPair rhs) const { return full == rhs.full; } - - Halves halves; }; using RegisterPair16 = RegisterPair; using RegisterPair32 = RegisterPair; +static_assert(sizeof(RegisterPair32) == 4); +static_assert( + ( + std::endian::native == std::endian::little && + offsetof(RegisterPair32, halves.low) == 0 && + offsetof(RegisterPair32, halves.high) == 2 + ) || + ( + std::endian::native == std::endian::big && + offsetof(RegisterPair32, halves.low) == 2 && + offsetof(RegisterPair32, halves.high) == 0 + ) +); + +static_assert(sizeof(RegisterPair16) == 2); +static_assert( + ( + std::endian::native == std::endian::little && + offsetof(RegisterPair16, halves.low) == 0 && + offsetof(RegisterPair16, halves.high) == 1 + ) || + ( + std::endian::native == std::endian::big && + offsetof(RegisterPair16, halves.low) == 1 && + offsetof(RegisterPair16, halves.high) == 0 + ) +); + /// Provides access to lower portions of a larger int. template union SlicedInt {}; template <> union SlicedInt { uint16_t w; uint8_t b; + + auto operator <=>(const SlicedInt rhs) const { + return w <=> rhs.w; + } }; template <> union SlicedInt { @@ -59,6 +92,10 @@ template <> union SlicedInt { uint8_t __padding[1]; uint8_t b; }; + + auto operator <=>(const SlicedInt rhs) const { + return w <=> rhs.w; + } }; template <> union SlicedInt { @@ -69,6 +106,10 @@ template <> union SlicedInt { struct { SlicedInt low, high; }; + + auto operator <=>(const SlicedInt &rhs) const { + return l <=> rhs.l; + } }; template <> union SlicedInt { @@ -84,11 +125,41 @@ template <> union SlicedInt { struct { SlicedInt high, low; }; + + auto operator <=>(const SlicedInt rhs) const { + return l <=> rhs.l; + } }; using SlicedInt16 = SlicedInt; using SlicedInt32 = SlicedInt; +static_assert(sizeof(SlicedInt16) == 2); +static_assert( + ( + std::endian::native == std::endian::little && + offsetof(SlicedInt16, b) == 0 + ) || + ( + std::endian::native == std::endian::big && + offsetof(SlicedInt16, b) == 1 + ) +); + +static_assert(sizeof(SlicedInt32) == 4); +static_assert( + ( + std::endian::native == std::endian::little && + offsetof(SlicedInt16, b) == 0 && + offsetof(SlicedInt16, w) == 0 + ) || + ( + std::endian::native == std::endian::big && + offsetof(SlicedInt16, b) == 3 && + offsetof(SlicedInt16, w) == 2 + ) +); + } #pragma pack(pop) diff --git a/Storage/Storage.hpp b/Storage/Storage.hpp index 329d8feec..4a38cde0e 100644 --- a/Storage/Storage.hpp +++ b/Storage/Storage.hpp @@ -21,18 +21,24 @@ namespace Storage { */ struct Time { unsigned int length, clock_rate; - constexpr Time() : length(0), clock_rate(1) {} - constexpr Time(unsigned int unsigned_int_value) : length(unsigned_int_value), clock_rate(1) {} - constexpr Time(int int_value) : Time(unsigned(int_value)) {} - constexpr Time(unsigned int length, unsigned int clock_rate) : length(length), clock_rate(clock_rate) {} - constexpr Time(int length, int clock_rate) : Time(unsigned(length), unsigned(clock_rate)) {} - Time(uint64_t length, uint64_t clock_rate) { + constexpr Time() noexcept : length(0), clock_rate(1) {} + + template + requires (sizeof(IntT) <= sizeof(int)) + constexpr Time(const IntT value) noexcept : length(unsigned(value)), clock_rate(1) {} + + template + requires (sizeof(IntT) <= sizeof(int)) + constexpr Time(const IntT length, const IntT clock_rate) noexcept : + length(unsigned(length)), clock_rate(unsigned(clock_rate)) {} + + Time(const uint64_t length, const uint64_t clock_rate) noexcept { install_result(length, clock_rate); } - Time(float value) { + Time(const float value) noexcept { install_float(value); } - static constexpr Time simplified(unsigned int _length, unsigned int _clock_rate) { + static constexpr Time simplified(const unsigned int _length, const unsigned int _clock_rate) { const auto gcd = std::gcd(_length, _clock_rate); return Time(_length / gcd, _clock_rate / gcd); } @@ -54,27 +60,15 @@ struct Time { return T(length) / T(clock_rate); } - inline bool operator < (const Time &other) const { - return uint64_t(other.clock_rate) * uint64_t(length) < uint64_t(clock_rate) * uint64_t(other.length); + auto operator <=> (const Time &rhs) const { + return uint64_t(rhs.clock_rate) * uint64_t(length) <=> uint64_t(clock_rate) * uint64_t(rhs.length); } - inline bool operator <= (const Time &other) const { - return uint64_t(other.clock_rate) * uint64_t(length) <= uint64_t(clock_rate) * uint64_t(other.length); + auto operator == (const Time &rhs) const { + return *this <=> rhs == std::strong_ordering::equal; } - inline bool operator > (const Time &other) const { - return uint64_t(other.clock_rate) * uint64_t(length) > uint64_t(clock_rate) * uint64_t(other.length); - } - - inline bool operator >= (const Time &other) const { - return uint64_t(other.clock_rate) * uint64_t(length) >= uint64_t(clock_rate) * uint64_t(other.length); - } - - inline bool operator == (const Time &other) const { - return uint64_t(other.clock_rate) * uint64_t(length) == uint64_t(clock_rate) * uint64_t(other.length); - } - - inline Time operator + (const Time &other) const { + Time operator + (const Time &other) const { if(!other.length) return *this; uint64_t result_length; @@ -83,13 +77,14 @@ struct Time { result_length = uint64_t(length) + uint64_t(other.length); result_clock_rate = clock_rate; } else { - result_length = uint64_t(length) * uint64_t(other.clock_rate) + uint64_t(other.length) * uint64_t(clock_rate); + result_length = + uint64_t(length) * uint64_t(other.clock_rate) + uint64_t(other.length) * uint64_t(clock_rate); result_clock_rate = uint64_t(clock_rate) * uint64_t(other.clock_rate); } return Time(result_length, result_clock_rate); } - inline Time &operator += (const Time &other) { + Time &operator += (const Time &other) { if(!other.length) return *this; if(!length) { *this = other; @@ -102,14 +97,15 @@ struct Time { result_length = uint64_t(length) + uint64_t(other.length); result_clock_rate = uint64_t(clock_rate); } else { - result_length = uint64_t(length) * uint64_t(other.clock_rate) + uint64_t(other.length) * uint64_t(clock_rate); + result_length = + uint64_t(length) * uint64_t(other.clock_rate) + uint64_t(other.length) * uint64_t(clock_rate); result_clock_rate = uint64_t(clock_rate) * uint64_t(other.clock_rate); } install_result(result_length, result_clock_rate); return *this; } - inline Time operator - (const Time &other) const { + Time operator - (const Time &other) const { if(!other.length) return *this; uint64_t result_length; @@ -118,13 +114,14 @@ struct Time { result_length = uint64_t(length) - uint64_t(other.length); result_clock_rate = clock_rate; } else { - result_length = uint64_t(length) * uint64_t(other.clock_rate) - uint64_t(other.length) * uint64_t(clock_rate); + result_length = + uint64_t(length) * uint64_t(other.clock_rate) - uint64_t(other.length) * uint64_t(clock_rate); result_clock_rate = uint64_t(clock_rate) * uint64_t(other.clock_rate); } return Time(result_length, result_clock_rate); } - inline Time operator -= (const Time &other) { + Time operator -= (const Time &other) { if(!other.length) return *this; uint64_t result_length; @@ -133,71 +130,72 @@ struct Time { result_length = uint64_t(length) - uint64_t(other.length); result_clock_rate = uint64_t(clock_rate); } else { - result_length = uint64_t(length) * uint64_t(other.clock_rate) - uint64_t(other.length) * uint64_t(clock_rate); + result_length = + uint64_t(length) * uint64_t(other.clock_rate) - uint64_t(other.length) * uint64_t(clock_rate); result_clock_rate = uint64_t(clock_rate) * uint64_t(other.clock_rate); } install_result(result_length, result_clock_rate); return *this; } - inline Time operator * (const Time &other) const { + Time operator * (const Time &other) const { uint64_t result_length = uint64_t(length) * uint64_t(other.length); uint64_t result_clock_rate = uint64_t(clock_rate) * uint64_t(other.clock_rate); return Time(result_length, result_clock_rate); } - inline Time &operator *= (const Time &other) { + Time &operator *= (const Time &other) { uint64_t result_length = uint64_t(length) * uint64_t(other.length); uint64_t result_clock_rate = uint64_t(clock_rate) * uint64_t(other.clock_rate); install_result(result_length, result_clock_rate); return *this; } - inline Time operator * (unsigned int multiplier) const { + Time operator * (unsigned int multiplier) const { uint64_t result_length = uint64_t(length) * uint64_t(multiplier); uint64_t result_clock_rate = uint64_t(clock_rate); return Time(result_length, result_clock_rate); } - inline Time &operator *= (unsigned int multiplier) { + Time &operator *= (unsigned int multiplier) { uint64_t result_length = uint64_t(length) * uint64_t(multiplier); uint64_t result_clock_rate = uint64_t(clock_rate); install_result(result_length, result_clock_rate); return *this; } - inline Time operator / (const Time &other) const { + Time operator / (const Time &other) const { uint64_t result_length = uint64_t(length) * uint64_t(other.clock_rate); uint64_t result_clock_rate = uint64_t(clock_rate) * uint64_t(other.length); return Time(result_length, result_clock_rate); } - inline Time &operator /= (const Time &other) { + Time &operator /= (const Time &other) { uint64_t result_length = uint64_t(length) * uint64_t(other.clock_rate); uint64_t result_clock_rate = uint64_t(clock_rate) * uint64_t(other.length); install_result(result_length, result_clock_rate); return *this; } - inline Time operator / (unsigned int divisor) const { + Time operator / (unsigned int divisor) const { uint64_t result_length = uint64_t(length); uint64_t result_clock_rate = uint64_t(clock_rate) * uint64_t(divisor); return Time(result_length, result_clock_rate); } - inline Time &operator /= (unsigned int divisor) { + Time &operator /= (unsigned int divisor) { uint64_t result_length = uint64_t(length); uint64_t result_clock_rate = uint64_t(clock_rate) * uint64_t(divisor); install_result(result_length, result_clock_rate); return *this; } - inline void set_zero() { + void set_zero() { length = 0; clock_rate = 1; } - inline void set_one() { + void set_one() { length = 1; clock_rate = 1; } @@ -207,8 +205,11 @@ struct Time { } private: - inline void install_result(uint64_t long_length, uint64_t long_clock_rate) { - if(long_length <= std::numeric_limits::max() && long_clock_rate <= std::numeric_limits::max()) { + void install_result(uint64_t long_length, uint64_t long_clock_rate) { + if( + long_length <= std::numeric_limits::max() && + long_clock_rate <= std::numeric_limits::max() + ) { length = unsigned(long_length); clock_rate = unsigned(long_clock_rate); return; @@ -231,21 +232,30 @@ private: long_clock_rate >>= 1; } - if(long_length > std::numeric_limits::max() || long_clock_rate > std::numeric_limits::max()) { + if( + long_length > std::numeric_limits::max() || + long_clock_rate > std::numeric_limits::max() + ) { uint64_t common_divisor = std::gcd(long_length, long_clock_rate); long_length /= common_divisor; long_clock_rate /= common_divisor; // Okay, in desperation accept a loss of accuracy. while( - (long_length > std::numeric_limits::max() || long_clock_rate > std::numeric_limits::max()) && + ( + long_length > std::numeric_limits::max() || + long_clock_rate > std::numeric_limits::max() + ) && (long_clock_rate > 1)) { long_length >>= 1; long_clock_rate >>= 1; } } - if(long_length <= std::numeric_limits::max() && long_clock_rate <= std::numeric_limits::max()) { + if( + long_length <= std::numeric_limits::max() && + long_clock_rate <= std::numeric_limits::max() + ) { length = unsigned(long_length); clock_rate = unsigned(long_clock_rate); } else { @@ -254,7 +264,7 @@ private: } } - inline void install_float(float value) { + void install_float(const float value) { // Grab the float's native mantissa and exponent. int exponent; const float mantissa = frexpf(value, &exponent);