| 1 | // endian/detail/intrinsic.hpp -------------------------------------------------------// |
| 2 | |
| 3 | // Copyright (C) 2012 David Stone |
| 4 | // Copyright Beman Dawes 2013 |
| 5 | |
| 6 | // Distributed under the Boost Software License, Version 1.0. |
| 7 | // http://www.boost.org/LICENSE_1_0.txt |
| 8 | |
| 9 | #ifndef BOOST_ENDIAN_INTRINSIC_HPP |
| 10 | #define BOOST_ENDIAN_INTRINSIC_HPP |
| 11 | |
| 12 | // Allow user to force BOOST_ENDIAN_NO_INTRINSICS in case they aren't available for a |
| 13 | // particular platform/compiler combination. Please report such platform/compiler |
| 14 | // combinations to the Boost mailing list. |
| 15 | #ifndef BOOST_ENDIAN_NO_INTRINSICS |
| 16 | |
| 17 | #ifndef __has_builtin // Optional of course |
| 18 | #define __has_builtin(x) 0 // Compatibility with non-clang compilers |
| 19 | #endif |
| 20 | |
| 21 | #if defined(_MSC_VER) && ( !defined(__clang__) || defined(__c2__) ) |
| 22 | // Microsoft documents these as being compatible since Windows 95 and specifically |
| 23 | // lists runtime library support since Visual Studio 2003 (aka 7.1). |
| 24 | // Clang/c2 uses the Microsoft rather than GCC intrinsics, so we check for |
| 25 | // defined(_MSC_VER) before defined(__clang__) |
| 26 | # define BOOST_ENDIAN_INTRINSIC_MSG "cstdlib _byteswap_ushort, etc." |
| 27 | # include <cstdlib> |
| 28 | # define BOOST_ENDIAN_INTRINSIC_BYTE_SWAP_2(x) _byteswap_ushort(x) |
| 29 | # define BOOST_ENDIAN_INTRINSIC_BYTE_SWAP_4(x) _byteswap_ulong(x) |
| 30 | # define BOOST_ENDIAN_INTRINSIC_BYTE_SWAP_8(x) _byteswap_uint64(x) |
| 31 | |
| 32 | // GCC and Clang recent versions provide intrinsic byte swaps via builtins |
| 33 | #elif (defined(__clang__) && __has_builtin(__builtin_bswap32) && __has_builtin(__builtin_bswap64)) \ |
| 34 | || (defined(__GNUC__ ) && \ |
| 35 | (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))) |
| 36 | # define BOOST_ENDIAN_INTRINSIC_MSG "__builtin_bswap16, etc." |
| 37 | // prior to 4.8, gcc did not provide __builtin_bswap16 on some platforms so we emulate it |
| 38 | // see http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52624 |
| 39 | // Clang has a similar problem, but their feature test macros make it easier to detect |
| 40 | # if (defined(__clang__) && __has_builtin(__builtin_bswap16)) \ |
| 41 | || (defined(__GNUC__) &&(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))) |
| 42 | # define BOOST_ENDIAN_INTRINSIC_BYTE_SWAP_2(x) __builtin_bswap16(x) |
| 43 | # else |
| 44 | # define BOOST_ENDIAN_INTRINSIC_BYTE_SWAP_2(x) __builtin_bswap32((x) << 16) |
| 45 | # endif |
| 46 | # define BOOST_ENDIAN_INTRINSIC_BYTE_SWAP_4(x) __builtin_bswap32(x) |
| 47 | # define BOOST_ENDIAN_INTRINSIC_BYTE_SWAP_8(x) __builtin_bswap64(x) |
| 48 | |
| 49 | # define BOOST_ENDIAN_CONSTEXPR_INTRINSICS |
| 50 | |
| 51 | // Linux systems provide the byteswap.h header, with |
| 52 | #elif defined(__linux__) |
| 53 | // don't check for obsolete forms defined(linux) and defined(__linux) on the theory that |
| 54 | // compilers that predefine only these are so old that byteswap.h probably isn't present. |
| 55 | # define BOOST_ENDIAN_INTRINSIC_MSG "byteswap.h bswap_16, etc." |
| 56 | # include <byteswap.h> |
| 57 | # define BOOST_ENDIAN_INTRINSIC_BYTE_SWAP_2(x) bswap_16(x) |
| 58 | # define BOOST_ENDIAN_INTRINSIC_BYTE_SWAP_4(x) bswap_32(x) |
| 59 | # define BOOST_ENDIAN_INTRINSIC_BYTE_SWAP_8(x) bswap_64(x) |
| 60 | |
| 61 | #else |
| 62 | # define BOOST_ENDIAN_NO_INTRINSICS |
| 63 | # define BOOST_ENDIAN_INTRINSIC_MSG "no byte swap intrinsics" |
| 64 | #endif |
| 65 | |
| 66 | #elif !defined(BOOST_ENDIAN_INTRINSIC_MSG) |
| 67 | # define BOOST_ENDIAN_INTRINSIC_MSG "no byte swap intrinsics" |
| 68 | #endif // BOOST_ENDIAN_NO_INTRINSICS |
| 69 | #endif // BOOST_ENDIAN_INTRINSIC_HPP |
| 70 | |