Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:42:14

0001 ///////////////////////////////////////////////////////////////
0002 //  Copyright 2020 Madhur Chauhan.
0003 //  Copyright 2020 John Maddock. 
0004 //  Distributed under the Boost
0005 //  Software License, Version 1.0. (See accompanying file
0006 //  LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt
0007 
0008 #ifndef BOOST_MP_INTEL_INTRINSICS_HPP
0009 #define BOOST_MP_INTEL_INTRINSICS_HPP
0010 //
0011 // Select which actual implementation header to use:
0012 //
0013 #ifdef __has_include
0014 #if __has_include(<immintrin.h>)
0015 #define BOOST_MP_HAS_IMMINTRIN_H
0016 #endif
0017 #endif
0018 //
0019 // If this is GCC/clang, then check that the actual intrinsic exists:
0020 //
0021 #if defined(__has_builtin) && defined(__GNUC__)
0022 #if !__has_builtin(__builtin_ia32_addcarryx_u64) && defined(BOOST_MP_HAS_IMMINTRIN_H) \
0023    && !(defined(BOOST_GCC) && (__GNUC__ >= 9) \
0024       && (defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64)\
0025           || defined(i386) || defined(__i386) || defined(__i386__) || defined(_M_AMD64) \
0026           || defined(_M_X64) || defined(__amd64__) || defined(_M_X64)))
0027 #undef BOOST_MP_HAS_IMMINTRIN_H
0028 #endif
0029 #elif defined(BOOST_MP_HAS_IMMINTRIN_H) && defined(__GNUC__) && !(defined(BOOST_GCC) && (__GNUC__ >= 9))
0030 #undef BOOST_MP_HAS_IMMINTRIN_H
0031 #endif
0032 
0033 #if defined(__clang_major__) && (__clang_major__ < 9)
0034 // We appear to crash the compiler if we try to use these intrinsics?
0035 #undef BOOST_MP_HAS_IMMINTRIN_H
0036 #endif
0037 
0038 #if defined(_WIN32) && (defined(_M_ARM64) || defined(_M_ARM))
0039 //
0040 // When targeting platforms such as ARM, msvc (and also clang when emulating msvc) still has the
0041 // Intel headers in its include path even though they're not usable.
0042 // See https://github.com/boostorg/multiprecision/issues/321
0043 // Also https://github.com/boostorg/multiprecision/issues/475
0044 //
0045 #undef BOOST_MP_HAS_IMMINTRIN_H
0046 #endif
0047 
0048 #if defined(__APPLE_CC__) && defined(__clang_major__) && (__clang_major__ < 11) && defined(BOOST_MP_HAS_IMMINTRIN_H)
0049 // Apple clang has it's own version numbers.
0050 #undef BOOST_MP_HAS_IMMINTRIN_H
0051 #endif
0052 
0053 
0054 //
0055 // If the compiler supports the intrinsics used by GCC internally
0056 // inside <immintrin.h> then we'll use them directly.
0057 // This is a bit of defensive programming, mostly for a modern clang
0058 // sitting on top of an older GCC header install.
0059 //
0060 #if defined(__has_builtin) && !defined(BOOST_INTEL)
0061 
0062 # if __has_builtin(__builtin_ia32_addcarryx_u64)
0063 #  define BOOST_MP_ADDC __builtin_ia32_addcarryx_u
0064 # endif
0065 
0066 # if __has_builtin(__builtin_ia32_subborrow_u64)
0067 #  define BOOST_MP_SUBB __builtin_ia32_subborrow_u
0068 # elif __has_builtin(__builtin_ia32_sbb_u64)
0069 #  define BOOST_MP_SUBB __builtin_ia32_sbb_u
0070 # endif
0071 
0072 #endif
0073 
0074 #ifndef BOOST_MP_ADDC
0075 #define BOOST_MP_ADDC _addcarry_u
0076 #endif
0077 #ifndef BOOST_MP_SUBB
0078 #define BOOST_MP_SUBB _subborrow_u
0079 #endif
0080 
0081 #ifdef BOOST_MP_HAS_IMMINTRIN_H
0082 
0083 #ifdef BOOST_MSVC
0084 //
0085 // This is a subset of the full <immintrin.h> :
0086 //
0087 #include <intrin.h>
0088 #else
0089 #include <immintrin.h>
0090 #endif
0091 
0092 #if defined(BOOST_HAS_INT128)
0093 
0094 namespace boost { namespace multiprecision { namespace detail {
0095 
0096 BOOST_MP_FORCEINLINE unsigned char addcarry_limb(unsigned char carry, limb_type a, limb_type b, limb_type* p_result)
0097 {
0098 #ifdef BOOST_INTEL
0099    using cast_type = unsigned __int64;
0100 #else
0101    using cast_type = unsigned long long;
0102 #endif
0103    return BOOST_JOIN(BOOST_MP_ADDC, 64)(carry, a, b, reinterpret_cast<cast_type*>(p_result));
0104 }
0105 
0106 BOOST_MP_FORCEINLINE unsigned char subborrow_limb(unsigned char carry, limb_type a, limb_type b, limb_type* p_result)
0107 {
0108 #ifdef BOOST_INTEL
0109    using cast_type = unsigned __int64;
0110 #else
0111    using cast_type = unsigned long long;
0112 #endif
0113    return BOOST_JOIN(BOOST_MP_SUBB, 64)(carry, a, b, reinterpret_cast<cast_type*>(p_result));
0114 }
0115 
0116 }}} // namespace boost::multiprecision::detail
0117 
0118 #else
0119 
0120 namespace boost { namespace multiprecision { namespace detail {
0121 
0122 BOOST_MP_FORCEINLINE unsigned char addcarry_limb(unsigned char carry, limb_type a, limb_type b, limb_type* p_result)
0123 {
0124    return BOOST_JOIN(BOOST_MP_ADDC, 32)(carry, a, b, reinterpret_cast<unsigned int*>(p_result));
0125 }
0126 
0127 BOOST_MP_FORCEINLINE unsigned char subborrow_limb(unsigned char carry, limb_type a, limb_type b, limb_type* p_result)
0128 {
0129    return BOOST_JOIN(BOOST_MP_SUBB, 32)(carry, a, b, reinterpret_cast<unsigned int*>(p_result));
0130 }
0131 
0132 }}} // namespace boost::multiprecision::detail
0133 
0134 #endif
0135 
0136 #endif
0137 
0138 #endif