From 0abd16d62c3f84524efa372b0c9650e786852ed6 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Wed, 22 Jun 2016 14:14:46 +0200 Subject: [PATCH] lib: try GCC builtins for endian byteswap --- lib/capnp_c.h | 61 +++++++++++++++++++++++++++++---------------------- 1 file changed, 35 insertions(+), 26 deletions(-) diff --git a/lib/capnp_c.h b/lib/capnp_c.h index f2dbdb8..f1baa7a 100644 --- a/lib/capnp_c.h +++ b/lib/capnp_c.h @@ -310,41 +310,50 @@ CAPN_INLINE uint8_t capn_flip8(uint8_t v) { return v; } CAPN_INLINE uint16_t capn_flip16(uint16_t v) { -#if !defined(__BYTE_ORDER) || (__BYTE_ORDER != __LITTLE_ENDIAN) - union { uint16_t u; uint8_t v[2]; } s; - s.v[0] = (uint8_t)v; - s.v[1] = (uint8_t)(v>>8); - return s.u; +#if defined(__BYTE_ORDER) && (__BYTE_ORDER == __LITTLE_ENDIAN) + return v; +#elif defined(__BYTE_ORDER) && (__BYTE_ORDER == __BIG_ENDIAN) && \ + defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 8 + return __builtin_bswap16(v); #else - return v; + union { uint16_t u; uint8_t v[2]; } s; + s.v[0] = (uint8_t)v; + s.v[1] = (uint8_t)(v>>8); + return s.u; #endif } CAPN_INLINE uint32_t capn_flip32(uint32_t v) { -#if !defined(__BYTE_ORDER) || (__BYTE_ORDER != __LITTLE_ENDIAN) - union { uint32_t u; uint8_t v[4]; } s; - s.v[0] = (uint8_t)v; - s.v[1] = (uint8_t)(v>>8); - s.v[2] = (uint8_t)(v>>16); - s.v[3] = (uint8_t)(v>>24); - return s.u; +#if defined(__BYTE_ORDER) && (__BYTE_ORDER == __LITTLE_ENDIAN) + return v; +#elif defined(__BYTE_ORDER) && (__BYTE_ORDER == __BIG_ENDIAN) && \ + defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 8 + return __builtin_bswap32(v); #else - return v; + union { uint32_t u; uint8_t v[4]; } s; + s.v[0] = (uint8_t)v; + s.v[1] = (uint8_t)(v>>8); + s.v[2] = (uint8_t)(v>>16); + s.v[3] = (uint8_t)(v>>24); + return s.u; #endif } CAPN_INLINE uint64_t capn_flip64(uint64_t v) { -#if !defined(__BYTE_ORDER) || (__BYTE_ORDER != __LITTLE_ENDIAN) - union { uint64_t u; uint8_t v[8]; } s; - s.v[0] = (uint8_t)v; - s.v[1] = (uint8_t)(v>>8); - s.v[2] = (uint8_t)(v>>16); - s.v[3] = (uint8_t)(v>>24); - s.v[4] = (uint8_t)(v>>32); - s.v[5] = (uint8_t)(v>>40); - s.v[6] = (uint8_t)(v>>48); - s.v[7] = (uint8_t)(v>>56); - return s.u; +#if defined(__BYTE_ORDER) && (__BYTE_ORDER == __LITTLE_ENDIAN) + return v; +#elif defined(__BYTE_ORDER) && (__BYTE_ORDER == __BIG_ENDIAN) && \ + defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 8 + return __builtin_bswap64(v); #else - return v; + union { uint64_t u; uint8_t v[8]; } s; + s.v[0] = (uint8_t)v; + s.v[1] = (uint8_t)(v>>8); + s.v[2] = (uint8_t)(v>>16); + s.v[3] = (uint8_t)(v>>24); + s.v[4] = (uint8_t)(v>>32); + s.v[5] = (uint8_t)(v>>40); + s.v[6] = (uint8_t)(v>>48); + s.v[7] = (uint8_t)(v>>56); + return s.u; #endif }