mirror of
https://github.com/OpenTTD/OpenTTD.git
synced 2025-03-06 14:27:16 +00:00
Codechange: introduce own std::byteswap implementation
This is only available from C++23, but the implementation is fairly trivial and the old variants of BSWAP32/BSWAP16 were not constexpr on MSVC. This was due to all kinds of intrinsics that were added to get better code. However, recent compilers with reasonable optimisation settings see the naive code and will inject the appropriate optimised code (bswap op on x86-64). For x86-64 recent is: Clang 6+ -O1, GCC 6+ -O2, MSVC 19.34+ /O1.
This commit is contained in:
parent
37a2d97c64
commit
2481f2e085
@ -344,42 +344,23 @@ private:
|
||||
Tbitset bitset;
|
||||
};
|
||||
|
||||
#if defined(__APPLE__)
|
||||
/* Make endian swapping use Apple's macros to increase speed
|
||||
* (since it will use hardware swapping if available).
|
||||
* Even though they should return uint16_t and uint32_t, we get
|
||||
* warnings if we don't cast those (why?) */
|
||||
# define BSWAP32(x) (static_cast<uint32_t>(CFSwapInt32(x)))
|
||||
# define BSWAP16(x) (static_cast<uint16_t>(CFSwapInt16(x)))
|
||||
#elif defined(_MSC_VER)
|
||||
/* MSVC has intrinsics for swapping, resulting in faster code */
|
||||
# define BSWAP32(x) (_byteswap_ulong(x))
|
||||
# define BSWAP16(x) (_byteswap_ushort(x))
|
||||
#else
|
||||
namespace std {
|
||||
/**
|
||||
* Perform a 32 bits endianness bitswap on x.
|
||||
* Custom implementation of std::byteswap; remove once we build with C++23.
|
||||
* Perform an endianness bitswap on x.
|
||||
* @param x the variable to bitswap
|
||||
* @return the bitswapped value.
|
||||
*/
|
||||
static inline uint32_t BSWAP32(uint32_t x)
|
||||
template <typename T>
|
||||
[[nodiscard]] constexpr enable_if_t<is_integral_v<T>, T> byteswap(T x) noexcept
|
||||
{
|
||||
#if !defined(__ICC) && defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && __GNUC_MINOR__ >= 3))
|
||||
/* GCC >= 4.3 provides a builtin, resulting in faster code */
|
||||
return static_cast<uint32_t>(__builtin_bswap32(static_cast<int32_t>(x)));
|
||||
#else
|
||||
return ((x >> 24) & 0xFF) | ((x >> 8) & 0xFF00) | ((x << 8) & 0xFF0000) | ((x << 24) & 0xFF000000);
|
||||
#endif /* defined(__GNUC__) */
|
||||
if constexpr (sizeof(T) == 1) return x;
|
||||
if constexpr (sizeof(T) == 2) return (x >> 8) | (x << 8);
|
||||
if constexpr (sizeof(T) == 4) return ((x >> 24) & 0xFF) | ((x >> 8) & 0xFF00) | ((x << 8) & 0xFF0000) | ((x << 24) & 0xFF000000);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a 16 bits endianness bitswap on x.
|
||||
* @param x the variable to bitswap
|
||||
* @return the bitswapped value.
|
||||
*/
|
||||
static inline uint16_t BSWAP16(uint16_t x)
|
||||
{
|
||||
return (x >> 8) | (x << 8);
|
||||
}
|
||||
#endif /* __APPLE__ */
|
||||
constexpr uint32_t BSWAP32(uint32_t x) { return std::byteswap(x); }
|
||||
constexpr uint16_t BSWAP16(uint16_t x) { return std::byteswap(x); }
|
||||
|
||||
#endif /* BITMATH_FUNC_HPP */
|
||||
|
Loading…
Reference in New Issue
Block a user