/* * Byte Swapping Operations * (C) 1999-2011,2018 Jack Lloyd * (C) 2007 Yves Jerschow * * Botan is released under the Simplified BSD License (see license.txt) */ #ifndef BOTAN_BYTE_SWAP_H_ #define BOTAN_BYTE_SWAP_H_ #include #if defined(BOTAN_BUILD_COMPILER_IS_MSVC) #include #endif namespace Botan { /** * Swap a 16 bit integer */ inline uint16_t reverse_bytes(uint16_t val) { #if defined(BOTAN_BUILD_COMPILER_IS_GCC) || defined(BOTAN_BUILD_COMPILER_IS_CLANG) || defined(BOTAN_BUILD_COMPILER_IS_XLC) return __builtin_bswap16(val); #else return static_cast((val << 8) | (val >> 8)); #endif } /** * Swap a 32 bit integer */ inline uint32_t reverse_bytes(uint32_t val) { #if defined(BOTAN_BUILD_COMPILER_IS_GCC) || defined(BOTAN_BUILD_COMPILER_IS_CLANG) || defined(BOTAN_BUILD_COMPILER_IS_XLC) return __builtin_bswap32(val); #elif defined(BOTAN_BUILD_COMPILER_IS_MSVC) return _byteswap_ulong(val); #elif defined(BOTAN_USE_GCC_INLINE_ASM) && defined(BOTAN_TARGET_CPU_IS_X86_FAMILY) // GCC-style inline assembly for x86 or x86-64 asm("bswapl %0" : "=r" (val) : "0" (val)); return val; #else // Generic implementation uint16_t hi = static_cast(val >> 16); uint16_t lo = static_cast(val); hi = reverse_bytes(hi); lo = reverse_bytes(lo); return (static_cast(lo) << 16) | hi; #endif } /** * Swap a 64 bit integer */ inline uint64_t reverse_bytes(uint64_t val) { #if defined(BOTAN_BUILD_COMPILER_IS_GCC) || defined(BOTAN_BUILD_COMPILER_IS_CLANG) || defined(BOTAN_BUILD_COMPILER_IS_XLC) return __builtin_bswap64(val); #elif defined(BOTAN_BUILD_COMPILER_IS_MSVC) return _byteswap_uint64(val); #elif defined(BOTAN_USE_GCC_INLINE_ASM) && defined(BOTAN_TARGET_ARCH_IS_X86_64) // GCC-style inline assembly for x86-64 asm("bswapq %0" : "=r" (val) : "0" (val)); return val; #else /* Generic implementation. Defined in terms of 32-bit bswap so any * optimizations in that version can help. */ uint32_t hi = static_cast(val >> 32); uint32_t lo = static_cast(val); hi = reverse_bytes(hi); lo = reverse_bytes(lo); return (static_cast(lo) << 32) | hi; #endif } /** * Swap 4 Ts in an array */ template inline void bswap_4(T x[4]) { x[0] = reverse_bytes(x[0]); x[1] = reverse_bytes(x[1]); x[2] = reverse_bytes(x[2]); x[3] = reverse_bytes(x[3]); } } #endif