1 /* Bytes swap functions, reverse order of bytes: 2 3 - _Py_bswap16(uint16_t) 4 - _Py_bswap32(uint32_t) 5 - _Py_bswap64(uint64_t) 6 */ 7 8 #ifndef Py_INTERNAL_BSWAP_H 9 #define Py_INTERNAL_BSWAP_H 10 #ifdef __cplusplus 11 extern "C" { 12 #endif 13 14 #ifndef Py_BUILD_CORE 15 # error "this header requires Py_BUILD_CORE define" 16 #endif 17 18 #if defined(__GNUC__) \ 19 && ((__GNUC__ >= 5) || (__GNUC__ == 4) && (__GNUC_MINOR__ >= 8)) 20 /* __builtin_bswap16() is available since GCC 4.8, 21 __builtin_bswap32() is available since GCC 4.3, 22 __builtin_bswap64() is available since GCC 4.3. */ 23 # define _PY_HAVE_BUILTIN_BSWAP 24 #endif 25 26 #ifdef _MSC_VER 27 /* Get _byteswap_ushort(), _byteswap_ulong(), _byteswap_uint64() */ 28 # include <intrin.h> 29 #endif 30 31 static inline uint16_t _Py_bswap16(uint16_t word)32_Py_bswap16(uint16_t word) 33 { 34 #if defined(_PY_HAVE_BUILTIN_BSWAP) || _Py__has_builtin(__builtin_bswap16) 35 return __builtin_bswap16(word); 36 #elif defined(_MSC_VER) 37 Py_BUILD_ASSERT(sizeof(word) == sizeof(unsigned short)); 38 return _byteswap_ushort(word); 39 #else 40 // Portable implementation which doesn't rely on circular bit shift 41 return ( ((word & UINT16_C(0x00FF)) << 8) 42 | ((word & UINT16_C(0xFF00)) >> 8)); 43 #endif 44 } 45 46 static inline uint32_t _Py_bswap32(uint32_t word)47_Py_bswap32(uint32_t word) 48 { 49 #if defined(_PY_HAVE_BUILTIN_BSWAP) || _Py__has_builtin(__builtin_bswap32) 50 return __builtin_bswap32(word); 51 #elif defined(_MSC_VER) 52 Py_BUILD_ASSERT(sizeof(word) == sizeof(unsigned long)); 53 return _byteswap_ulong(word); 54 #else 55 // Portable implementation which doesn't rely on circular bit shift 56 return ( ((word & UINT32_C(0x000000FF)) << 24) 57 | ((word & UINT32_C(0x0000FF00)) << 8) 58 | ((word & UINT32_C(0x00FF0000)) >> 8) 59 | ((word & UINT32_C(0xFF000000)) >> 24)); 60 #endif 61 } 62 63 static inline uint64_t _Py_bswap64(uint64_t word)64_Py_bswap64(uint64_t word) 65 { 66 #if defined(_PY_HAVE_BUILTIN_BSWAP) || _Py__has_builtin(__builtin_bswap64) 67 return __builtin_bswap64(word); 68 #elif defined(_MSC_VER) 69 return _byteswap_uint64(word); 70 #else 71 // Portable implementation which doesn't rely on circular bit shift 72 return ( ((word & UINT64_C(0x00000000000000FF)) << 56) 73 | ((word & UINT64_C(0x000000000000FF00)) << 40) 74 | ((word & UINT64_C(0x0000000000FF0000)) << 24) 75 | ((word & UINT64_C(0x00000000FF000000)) << 8) 76 | ((word & UINT64_C(0x000000FF00000000)) >> 8) 77 | ((word & UINT64_C(0x0000FF0000000000)) >> 24) 78 | ((word & UINT64_C(0x00FF000000000000)) >> 40) 79 | ((word & UINT64_C(0xFF00000000000000)) >> 56)); 80 #endif 81 } 82 83 84 #ifdef __cplusplus 85 } 86 #endif 87 #endif /* !Py_INTERNAL_BSWAP_H */ 88 89