CLK/Numeric/RegisterSizes.hpp

90 lines
1.5 KiB
C++

//
// RegisterSizes.hpp
// Clock Signal
//
// Created by Thomas Harte on 14/05/2017.
// Copyright 2017 Thomas Harte. All rights reserved.
//
#pragma once
#include <cstdint>
#pragma pack(push, 1)
// Unions below assume a modern consumer architecture,
// and that this compiler offers C-style anonymous structs.
namespace CPU {
/// 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) {}
RegisterPair() = default;
Full full;
#if TARGET_RT_BIG_ENDIAN
struct {
Half high, low;
} halves;
#else
struct {
Half low, high;
} halves;
#endif
};
using RegisterPair16 = RegisterPair<uint16_t, uint8_t>;
using RegisterPair32 = RegisterPair<uint32_t, RegisterPair16>;
/// Provides access to lower portions of a larger int.
template <typename IntT> union SlicedInt {};
template <> union SlicedInt<uint16_t> {
struct {
uint16_t w;
};
struct {
#if TARGET_RT_BIG_ENDIAN
uint8_t __padding[1];
#endif
uint8_t b;
};
};
template <> union SlicedInt<uint32_t> {
struct {
uint32_t l;
};
struct {
#if TARGET_RT_BIG_ENDIAN
uint16_t __padding[1];
#endif
uint16_t w;
};
struct {
#if TARGET_RT_BIG_ENDIAN
uint8_t __padding[3];
#endif
uint8_t b;
};
struct {
#if TARGET_RT_BIG_ENDIAN
SlicedInt<uint16_t> high, low;
#else
SlicedInt<uint16_t> low, high;
#endif
};
};
using SlicedInt16 = SlicedInt<uint16_t>;
using SlicedInt32 = SlicedInt<uint32_t>;
}
#pragma pack(pop)