diff --git a/src/util/compat/bswap.h b/src/util/compat/bswap.h new file mode 100644 index 0000000..a8acdcf --- /dev/null +++ b/src/util/compat/bswap.h @@ -0,0 +1,44 @@ +#pragma once + +#include + +#if defined(__GNUC__) || defined(__clang__) +#define bswap16 __builtin_bswap16 +#define bswap32 __builtin_bswap32 +#define bswap64 __builtin_bswap64 +#elif __has_include() +#include +#define bswap16 bswap_16 +#define bswap32 bswap_32 +#define bswap64 bswap_64 +#else +#define bswap16 bswap16_impl +#define bswap32 bswap32_impl +#define bswap64 bswap64_impl +#define IMPL_BSWAP +#endif + +#if defined(IMPL_BSWAP) || !defined(NDEBUG) +static inline uint16_t bswap16_impl(uint16_t x) { + return (x << 8) | (x >> 8); +} + +static inline uint32_t bswap32_impl(uint32_t x) { + return (x << 24) | + ((0x0000FF00U & x) << 8) | + ((0x00FF0000U & x) >> 8) | + (x >> 24); +} + +static inline uint64_t bswap64_impl(uint64_t x) { + return (x << 56) | + ((0x000000000000FF00ULL & x) << 40) | + ((0x0000000000FF0000ULL & x) << 24) | + ((0x00000000FF000000ULL & x) << 8) | + ((0x000000FF00000000ULL & x) >> 8) | + ((0x0000FF0000000000ULL & x) >> 24) | + ((0x00FF000000000000ULL & x) >> 40) | + (x >> 56); +} +#endif +#undef IMPL_BSWAP diff --git a/src/util/compat/endian.h b/src/util/compat/endian.h index f326815..a3f6d9e 100644 --- a/src/util/compat/endian.h +++ b/src/util/compat/endian.h @@ -5,18 +5,7 @@ #include #include "../atrb.h" - -#if __has_include() -#include -#elif defined(__GNUC__) || defined(__clang__) -#define bswap_16 __builtin_bswap16 -#define bswap_32 __builtin_bswap32 -#define bswap_64 __builtin_bswap64 -#else -// TODO: use custom bswap bacros -#error WIP, no support -#endif - +#include "bswap.h" /* little endian */ atrb_const static inline uint16_t le16ton(uint16_t); // converts little-endian (LE) encoding to native for a 16 bit integer. (NOOP if native is LE) @@ -41,12 +30,12 @@ uint64_t le64ton(uint64_t x) { return x; } uint16_t ntole16(uint16_t x) { return x; } uint32_t ntole32(uint32_t x) { return x; } uint64_t ntole64(uint64_t x) { return x; } -uint16_t be16ton(uint16_t x) { return bswap_16(x); } -uint32_t be32ton(uint32_t x) { return bswap_32(x); } -uint64_t be64ton(uint64_t x) { return bswap_64(x); } -uint16_t ntobe16(uint16_t x) { return bswap_16(x); } -uint32_t ntobe32(uint32_t x) { return bswap_32(x); } -uint64_t ntobe64(uint64_t x) { return bswap_64(x); } +uint16_t be16ton(uint16_t x) { return bswap16(x); } +uint32_t be32ton(uint32_t x) { return bswap32(x); } +uint64_t be64ton(uint64_t x) { return bswap64(x); } +uint16_t ntobe16(uint16_t x) { return bswap16(x); } +uint32_t ntobe32(uint32_t x) { return bswap32(x); } +uint64_t ntobe64(uint64_t x) { return bswap64(x); } #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ uint16_t le16ton(uint16_t x) { bswap_16(x); } uint32_t le32ton(uint32_t x) { bswap_32(x); }