12 [[nodiscard]]
static inline uint16_t byteswap16(uint16_t
x)
19 return ((
x & 0x00FF) << 8) | ((
x & 0xFF00) >> 8);
24 [[nodiscard]]
static inline uint32_t byteswap32(uint32_t
x)
26 #if (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3))
29 return __builtin_bswap32(
x);
32 ((
x << 8) & 0x00ff0000) |
33 ((
x >> 8) & 0x0000ff00) |
39 [[nodiscard]]
static inline uint64_t byteswap64(uint64_t
x)
41 #if (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3))
44 return __builtin_bswap64(
x);
46 return (uint64_t(byteswap32(
x >> 0)) << 32) |
47 (uint64_t(byteswap32(
x >> 32)) << 0);
52 [[nodiscard]]
static inline uint16_t byteswap(uint16_t
x) {
return byteswap16(
x); }
53 [[nodiscard]]
static inline uint32_t byteswap(uint32_t
x) {
return byteswap32(
x); }
54 [[nodiscard]]
static inline uint64_t byteswap(uint64_t
x) {
return byteswap64(
x); }
59 template<
typename T> [[nodiscard]]
inline T
operator()(T
t)
const {
return t; }
64 template<
typename T> [[nodiscard]]
inline T
operator()(T
t)
const {
return byteswap(
t); }
71 template<
typename T,
typename Op>
class EndianT {
75 [[nodiscard]]
inline operator T()
const { Op op;
return op(t); }
116 static_assert(
sizeof(
B16) == 2,
"must have size 2");
117 static_assert(
sizeof(
L16) == 2,
"must have size 2");
118 static_assert(
sizeof(
B32) == 4,
"must have size 4");
119 static_assert(
sizeof(
L32) == 4,
"must have size 4");
120 static_assert(
sizeof(
B64) == 8,
"must have size 8");
121 static_assert(
sizeof(
L64) == 8,
"must have size 8");
122 static_assert(
alignof(
B16) <= 2,
"may have alignment 2");
123 static_assert(
alignof(
L16) <= 2,
"may have alignment 2");
124 static_assert(
alignof(
B32) <= 4,
"may have alignment 4");
125 static_assert(
alignof(
L32) <= 4,
"may have alignment 4");
126 static_assert(
alignof(
B64) <= 8,
"may have alignment 8");
127 static_assert(
alignof(
L64) <= 8,
"may have alignment 8");
133 *
reinterpret_cast<B16*
>(p) =
x;
137 *
reinterpret_cast<L16*
>(p) =
x;
141 *
reinterpret_cast<B32*
>(p) =
x;
145 *
reinterpret_cast<L32*
>(p) =
x;
148 [[nodiscard]]
inline uint16_t
readB16(
const void* p)
150 return *
reinterpret_cast<const B16*
>(p);
152 [[nodiscard]]
inline uint16_t
readL16(
const void* p)
154 return *
reinterpret_cast<const L16*
>(p);
156 [[nodiscard]]
inline uint32_t
readB32(
const void* p)
158 return *
reinterpret_cast<const B32*
>(p);
160 [[nodiscard]]
inline uint32_t
readL32(
const void* p)
162 return *
reinterpret_cast<const L32*
>(p);
172 template<
bool SWAP,
typename T>
static ALWAYS_INLINE void write_UA(
void* p, T
x)
174 if (SWAP)
x = byteswap(
x);
175 memcpy(p, &
x,
sizeof(
x));
179 write_UA<!openmsx::OPENMSX_BIGENDIAN>(p,
x);
183 write_UA< openmsx::OPENMSX_BIGENDIAN>(p,
x);
187 write_UA<!openmsx::OPENMSX_BIGENDIAN>(p,
x);
191 write_UA< openmsx::OPENMSX_BIGENDIAN>(p,
x);
195 write_UA<!openmsx::OPENMSX_BIGENDIAN>(p,
x);
199 write_UA< openmsx::OPENMSX_BIGENDIAN>(p,
x);
202 template<
bool SWAP,
typename T> [[nodiscard]]
static ALWAYS_INLINE T read_UA(
const void* p)
205 memcpy(&
x, p,
sizeof(
x));
206 if (SWAP)
x = byteswap(
x);
211 return read_UA<!openmsx::OPENMSX_BIGENDIAN, uint16_t>(p);
215 return read_UA< openmsx::OPENMSX_BIGENDIAN, uint16_t>(p);
219 return read_UA<!openmsx::OPENMSX_BIGENDIAN, uint32_t>(p);
223 return read_UA< openmsx::OPENMSX_BIGENDIAN, uint32_t>(p);
227 return read_UA<!openmsx::OPENMSX_BIGENDIAN, uint64_t>(p);
231 return read_UA< openmsx::OPENMSX_BIGENDIAN, uint64_t>(p);
239 [[nodiscard]]
inline operator uint16_t()
const {
return read_UA_B16(x); }
247 [[nodiscard]]
inline operator uint16_t()
const {
return read_UA_L16(x); }
255 [[nodiscard]]
inline operator uint32_t()
const {
return read_UA_B32(x); }
263 [[nodiscard]]
inline operator uint32_t()
const {
return read_UA_L32(x); }
269 static_assert(
sizeof(UA_B16) == 2,
"must have size 2");
270 static_assert(
sizeof(UA_L16) == 2,
"must have size 2");
271 static_assert(
sizeof(UA_B32) == 4,
"must have size 4");
272 static_assert(
sizeof(UA_L32) == 4,
"must have size 4");
273 static_assert(
alignof(UA_B16) == 1,
"must have alignment 1");
274 static_assert(
alignof(UA_L16) == 1,
"must have alignment 1");
275 static_assert(
alignof(UA_B32) == 1,
"must have alignment 1");
276 static_assert(
alignof(UA_L32) == 1,
"must have alignment 1");
287 template<>
struct Little<uint8_t > {
using type = uint8_t; };
290 template<
typename>
struct Big;
291 template<>
struct Big<uint8_t > {
using type = uint8_t; };
UA_B16 & operator=(uint16_t a)
UA_B32 & operator=(uint32_t a)
UA_L16 & operator=(uint16_t a)
UA_L32 & operator=(uint32_t a)
uint16_t readB16(const void *p)
ALWAYS_INLINE uint16_t read_UA_B16(const void *p)
void writeB16(void *p, uint16_t x)
ALWAYS_INLINE void write_UA_B32(void *p, uint32_t x)
ALWAYS_INLINE void write_UA_B64(void *p, uint64_t x)
EndianT< uint16_t, ConvBig< openmsx::OPENMSX_BIGENDIAN > > B16
uint32_t readL32(const void *p)
ALWAYS_INLINE void write_UA_B16(void *p, uint16_t x)
void writeL32(void *p, uint32_t x)
ALWAYS_INLINE uint64_t read_UA_L64(const void *p)
ALWAYS_INLINE uint32_t read_UA_B32(const void *p)
void writeB32(void *p, uint32_t x)
EndianT< uint32_t, ConvBig< openmsx::OPENMSX_BIGENDIAN > > B32
ALWAYS_INLINE void write_UA_L64(void *p, uint64_t x)
ALWAYS_INLINE uint16_t read_UA_L16(const void *p)
ALWAYS_INLINE uint64_t read_UA_B64(const void *p)
ALWAYS_INLINE void write_UA_L32(void *p, uint32_t x)
EndianT< uint16_t, ConvLittle< openmsx::OPENMSX_BIGENDIAN > > L16
ALWAYS_INLINE void write_UA_L16(void *p, uint16_t x)
uint16_t readL16(const void *p)
uint32_t readB32(const void *p)
ALWAYS_INLINE uint32_t read_UA_L32(const void *p)
EndianT< uint32_t, ConvLittle< openmsx::OPENMSX_BIGENDIAN > > L32
void writeL16(void *p, uint16_t x)
constexpr KeyMatrixPosition x
Keyboard bindings.