1 #include <nil/crypto3/utilities/cpuid/cpuid.hpp>
2 #include <nil/crypto3/utilities/memory_operations.hpp>
3 #include <nil/crypto3/utilities/loadstore.hpp>
5 #if defined(BOOST_ARCH_X86)
7 #if defined(CRYPTO3_BUILD_COMPILER_IS_MSVC)
9 #elif defined(CRYPTO3_BUILD_COMPILER_IS_INTEL)
10 #include <ia32intrin.h>
11 #elif defined(CRYPTO3_BUILD_COMPILER_IS_GCC) || defined(CRYPTO3_BUILD_COMPILER_IS_CLANG)
20 #if defined(BOOST_ARCH_X86)
22 uint64_t cpuid::detect_cpu_features(
size_t *cache_line_size) {
23 #if defined(CRYPTO3_BUILD_COMPILER_IS_MSVC)
24 #define X86_CPUID(type, out) \
26 __cpuid((int *)out, type); \
28 #define X86_CPUID_SUBLEVEL(type, level, out) \
30 __cpuidex((int *)out, type, level); \
33 #elif defined(CRYPTO3_BUILD_COMPILER_IS_INTEL)
34 #define X86_CPUID(type, out) \
38 #define X86_CPUID_SUBLEVEL(type, level, out) \
40 __cpuidex((int *)out, type, level); \
43 #elif defined(CRYPTO3_TARGET_ARCHITECTURE_IS_X86_64) && defined(CRYPTO3_USE_GCC_INLINE_ASM)
44 #define X86_CPUID(type, out) asm("cpuid\n\t" : "=a"(out[0]), "=b"(out[1]), "=c"(out[2]), "=d"(out[3]) : "0"(type))
46 #define X86_CPUID_SUBLEVEL(type, level, out) \
47 asm("cpuid\n\t" : "=a"(out[0]), "=b"(out[1]), "=c"(out[2]), "=d"(out[3]) : "0"(type), "2"(level))
49 #elif defined(CRYPTO3_BUILD_COMPILER_IS_GCC) || defined(CRYPTO3_BUILD_COMPILER_IS_CLANG)
50 #define X86_CPUID(type, out) \
52 __get_cpuid(type, out, out + 1, out + 2, out + 3); \
55 #define X86_CPUID_SUBLEVEL(type, level, out) \
57 __cpuid_count(type, level, out[0], out[1], out[2], out[3]); \
60 #warning "No way of calling x86 cpuid instruction for this compiler"
61 #define X86_CPUID(type, out) \
65 #define X86_CPUID_SUBLEVEL(type, level, out) \
71 uint64_t features_detected = 0;
72 uint32_t cpuid[4] = {0};
77 const uint32_t max_supported_sublevel = cpuid[0];
79 const uint32_t INTEL_CPUID[3] = {0x756E6547, 0x6C65746E, 0x49656E69};
80 const uint32_t AMD_CPUID[3] = {0x68747541, 0x444D4163, 0x69746E65};
81 const bool is_intel =
same_mem(cpuid + 1, INTEL_CPUID, 3);
82 const bool is_amd =
same_mem(cpuid + 1, AMD_CPUID, 3);
84 if (max_supported_sublevel >= 1) {
87 const uint64_t flags0 = (
static_cast<uint64_t
>(cpuid[2]) << 32) | cpuid[3];
89 enum x86_CPUID_1_bits : uint64_t {
100 if (flags0 & x86_CPUID_1_bits::RDTSC)
101 features_detected |= cpuid::CPUID_RDTSC_BIT;
102 if (flags0 & x86_CPUID_1_bits::SSE2)
103 features_detected |= cpuid::CPUID_SSE2_BIT;
104 if (flags0 & x86_CPUID_1_bits::CLMUL)
105 features_detected |= cpuid::CPUID_CLMUL_BIT;
106 if (flags0 & x86_CPUID_1_bits::SSSE3)
107 features_detected |= cpuid::CPUID_SSSE3_BIT;
108 if (flags0 & x86_CPUID_1_bits::SSE41)
109 features_detected |= cpuid::CPUID_SSE41_BIT;
110 if (flags0 & x86_CPUID_1_bits::SSE42)
111 features_detected |= cpuid::CPUID_SSE42_BIT;
112 if (flags0 & x86_CPUID_1_bits::AESNI)
113 features_detected |= cpuid::CPUID_AESNI_BIT;
114 if (flags0 & x86_CPUID_1_bits::RDRAND)
115 features_detected |= cpuid::CPUID_RDRAND_BIT;
123 X86_CPUID(0x80000005, cpuid);
127 if (max_supported_sublevel >= 7) {
129 X86_CPUID_SUBLEVEL(7, 0, cpuid);
131 enum x86_CPUID_7_bits : uint64_t {
134 AVX512F = (1ULL << 16),
135 RDSEED = (1ULL << 18),
139 uint64_t flags7 = (
static_cast<uint64_t
>(cpuid[2]) << 32) | cpuid[1];
141 if (flags7 & x86_CPUID_7_bits::AVX2)
142 features_detected |= cpuid::CPUID_AVX2_BIT;
143 if (flags7 & x86_CPUID_7_bits::BMI2)
144 features_detected |= cpuid::CPUID_BMI2_BIT;
145 if (flags7 & x86_CPUID_7_bits::AVX512F)
146 features_detected |= cpuid::CPUID_AVX512F_BIT;
147 if (flags7 & x86_CPUID_7_bits::RDSEED)
148 features_detected |= cpuid::CPUID_RDSEED_BIT;
149 if (flags7 & x86_CPUID_7_bits::ADX)
150 features_detected |= cpuid::CPUID_ADX_BIT;
151 if (flags7 & x86_CPUID_7_bits::SHA)
152 features_detected |= cpuid::CPUID_SHA_BIT;
156 #undef X86_CPUID_SUBLEVEL
162 #if defined(CRYPTO3_TARGET_ARCHITECTURE_IS_X86_64)
163 if (features_detected == 0) {
164 features_detected |= cpuid::CPUID_SSE2_BIT;
165 features_detected |= cpuid::CPUID_RDTSC_BIT;
169 return features_detected;
static size_t cache_line_size()
Definition: cpuid.hpp:134
bool same_mem(const T *p1, const T *p2, size_t n)
Definition: memory_operations.hpp:229
void clear_mem(T *ptr, size_t n)
Definition: memory_operations.hpp:175