Clean up Storage.hpp and starship operators.

This commit is contained in:
Thomas Harte committed 2026-10-20 21:33:36 -04:00
1 parent 8ff5129704
commit f459ffe619
4 files changed
+143 -55

No files matched your search

+5 -1
View File
@@ -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<int>()),
false,
false
);
}
shift_register_ = next_output_;
write_handshake_ |= 0x80 | 0x40;
+4 -1
View File
@@ -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();
}
+76 -5
View File
@@ -9,6 +9,7 @@
#pragma once
#include <bit>
#include <compare>
#include <cstdint>
#pragma pack(push, 1)
@@ -28,29 +29,61 @@ template <typename ValueT> struct Halves<ValueT, std::endian::big> {
/// Provides access to all intermediate parts of a larger int.
template <typename Full, typename Half> 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<Half> 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<Half> halves;
};
using RegisterPair16 = RegisterPair<uint16_t, uint8_t>;
using RegisterPair32 = RegisterPair<uint32_t, RegisterPair16>;
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 <typename IntT, std::endian = std::endian::native> union SlicedInt {};
template <> union SlicedInt<uint16_t, std::endian::little> {
uint16_t w;
uint8_t b;
auto operator <=>(const SlicedInt rhs) const {
return w <=> rhs.w;
}
};
template <> union SlicedInt<uint16_t, std::endian::big> {
@@ -59,6 +92,10 @@ template <> union SlicedInt<uint16_t, std::endian::big> {
uint8_t __padding[1];
uint8_t b;
};
auto operator <=>(const SlicedInt rhs) const {
return w <=> rhs.w;
}
};
template <> union SlicedInt<uint32_t, std::endian::little> {
@@ -69,6 +106,10 @@ template <> union SlicedInt<uint32_t, std::endian::little> {
struct {
SlicedInt<uint16_t> low, high;
};
auto operator <=>(const SlicedInt &rhs) const {
return l <=> rhs.l;
}
};
template <> union SlicedInt<uint32_t, std::endian::big> {
@@ -84,11 +125,41 @@ template <> union SlicedInt<uint32_t, std::endian::big> {
struct {
SlicedInt<uint16_t> high, low;
};
auto operator <=>(const SlicedInt rhs) const {
return l <=> rhs.l;
}
};
using SlicedInt16 = SlicedInt<uint16_t>;
using SlicedInt32 = SlicedInt<uint32_t>;
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)
+58 -48
View File
@@ -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 <std::integral IntT>
requires (sizeof(IntT) <= sizeof(int))
constexpr Time(const IntT value) noexcept : length(unsigned(value)), clock_rate(1) {}
template <std::integral IntT>
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<unsigned int>::max() && long_clock_rate <= std::numeric_limits<unsigned int>::max()) {
void install_result(uint64_t long_length, uint64_t long_clock_rate) {
if(
long_length <= std::numeric_limits<unsigned int>::max() &&
long_clock_rate <= std::numeric_limits<unsigned int>::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<unsigned int>::max() || long_clock_rate > std::numeric_limits<unsigned int>::max()) {
if(
long_length > std::numeric_limits<unsigned int>::max() ||
long_clock_rate > std::numeric_limits<unsigned int>::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<unsigned int>::max() || long_clock_rate > std::numeric_limits<unsigned int>::max()) &&
(
long_length > std::numeric_limits<unsigned int>::max() ||
long_clock_rate > std::numeric_limits<unsigned int>::max()
) &&
(long_clock_rate > 1)) {
long_length >>= 1;
long_clock_rate >>= 1;
}
}
if(long_length <= std::numeric_limits<unsigned int>::max() && long_clock_rate <= std::numeric_limits<unsigned int>::max()) {
if(
long_length <= std::numeric_limits<unsigned int>::max() &&
long_clock_rate <= std::numeric_limits<unsigned int>::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);