1 #ifndef CRYPTO3_CPUID_HPP
2 #define CRYPTO3_CPUID_HPP
15 #if !defined(CRYPTO3_TARGET_CPU_DEFAULT_CACHE_LINE_SIZE)
16 #define CRYPTO3_TARGET_CPU_DEFAULT_CACHE_LINE_SIZE 32
45 g_processor_features = 0;
47 #if defined(BOOST_ARCH_PPC) || defined(BOOST_ARCH_ARM) || defined(BOOST_ARCH_X86)
49 g_processor_features = cpuid::detect_cpu_features(&g_cache_line_size);
53 g_endian_status = runtime_check_endian();
58 #if BOOST_HW_SIMD_X86 >= BOOST_HW_SIMD_X86_SSE2_VERSION
59 return cpuid::has_sse2();
60 #elif BOOST_HW_SIMD_ARM >= BOOST_HW_SIMD_ARM_NEON_VERSION
61 return cpuid::has_altivec();
62 #elif BOOST_HW_SIMD_PPC >= BOOST_HW_SIMD_PPC_VMX_VERSION
63 return cpuid::has_neon();
78 std::vector<std::string> flags;
80 #define CPUID_PRINT(flag) \
83 flags.push_back(#flag); \
87 #if defined(BOOST_ARCH_X86)
106 #if defined(BOOST_ARCH_PPC)
111 #if defined(BOOST_ARCH_ARM)
123 for (
const std::string &c : flags) {
125 out.insert(out.end(), c.begin(), c.end());
135 if (g_processor_features == 0) {
138 return g_cache_line_size;
142 return get_endian_status() == ENDIAN_LITTLE;
146 return get_endian_status() == ENDIAN_BIG;
150 #if defined(BOOST_ARCH_X86)
154 CPUID_SSE2_BIT = (1ULL << 0),
155 CPUID_SSSE3_BIT = (1ULL << 1),
156 CPUID_SSE41_BIT = (1ULL << 2),
157 CPUID_SSE42_BIT = (1ULL << 3),
158 CPUID_AVX2_BIT = (1ULL << 4),
159 CPUID_AVX512F_BIT = (1ULL << 5),
162 CPUID_RDTSC_BIT = (1ULL << 10),
163 CPUID_BMI2_BIT = (1ULL << 11),
164 CPUID_ADX_BIT = (1ULL << 12),
165 CPUID_BMI1_BIT = (1ULL << 13),
168 CPUID_AESNI_BIT = (1ULL << 16),
169 CPUID_CLMUL_BIT = (1ULL << 17),
170 CPUID_RDRAND_BIT = (1ULL << 18),
171 CPUID_RDSEED_BIT = (1ULL << 19),
172 CPUID_SHA_BIT = (1ULL << 20),
175 #
if defined(BOOST_ARCH_PPC)
176 CPUID_ALTIVEC_BIT = (1ULL << 0),
177 CPUID_PPC_CRYPTO3_BIT = (1ULL << 1),
180 #if defined(BOOST_ARCH_ARM)
181 CPUID_ARM_NEON_BIT = (1ULL << 0),
182 CPUID_ARM_RIJNDAEL_BIT = (1ULL << 16),
183 CPUID_ARM_PMULL_BIT = (1ULL << 17),
184 CPUID_ARM_SHA1_BIT = (1ULL << 18),
185 CPUID_ARM_SHA2_BIT = (1ULL << 19),
191 #if defined(BOOST_ARCH_PPC)
195 static bool has_altivec() {
202 static bool has_ppc_crypto() {
208 #if defined(BOOST_ARCH_ARM)
212 static bool has_neon() {
219 static bool has_arm_sha1() {
226 static bool has_arm_sha2() {
233 static bool has_arm_aes() {
240 static bool has_arm_pmull() {
245 #if defined(BOOST_ARCH_X86)
250 static bool has_rdtsc() {
257 static bool has_sse2() {
264 static bool has_ssse3() {
271 static bool has_sse41() {
278 static bool has_sse42() {
285 static bool has_avx2() {
292 static bool has_avx512f() {
299 static bool has_bmi1() {
306 static bool has_bmi2() {
313 static bool has_aes_ni() {
320 static bool has_clmul() {
327 static bool has_intel_sha() {
334 static bool has_adx() {
341 static bool has_rdrand() {
348 static bool has_rdseed() {
362 const uint64_t mask = ~(
static_cast<uint64_t
>(bit));
363 g_processor_features &= mask;
371 if (g_processor_features == 0) {
375 const uint64_t elem64 =
static_cast<uint64_t
>(elem);
376 return ((g_processor_features & elem64) == elem64);
380 #if defined(BOOST_ARCH_X86)
381 if (tok ==
"sse2" || tok ==
"simd") {
382 return {nil::crypto3::cpuid::CPUID_SSE2_BIT};
384 if (tok ==
"ssse3") {
385 return {nil::crypto3::cpuid::CPUID_SSSE3_BIT};
387 if (tok ==
"aesni") {
388 return {nil::crypto3::cpuid::CPUID_AESNI_BIT};
390 if (tok ==
"clmul") {
391 return {nil::crypto3::cpuid::CPUID_CLMUL_BIT};
394 return {nil::crypto3::cpuid::CPUID_AVX2_BIT};
397 return {nil::crypto3::cpuid::CPUID_SHA_BIT};
400 #elif defined(BOOST_ARCH_PPC)
401 if (tok ==
"altivec" || tok ==
"simd")
402 return {nil::crypto3::cpuid::CPUID_ALTIVEC_BIT};
404 #elif defined(BOOST_ARCH_ARM)
405 if (tok ==
"neon" || tok ==
"simd")
406 return {nil::crypto3::cpuid::CPUID_ARM_NEON_BIT};
407 if (tok ==
"armv8sha1")
408 return {nil::crypto3::cpuid::CPUID_ARM_SHA1_BIT};
409 if (tok ==
"armv8sha2")
410 return {nil::crypto3::cpuid::CPUID_ARM_SHA2_BIT};
411 if (tok ==
"armv8aes")
412 return {nil::crypto3::cpuid::CPUID_ARM_RIJNDAEL_BIT};
413 if (tok ==
"armv8pmull")
414 return {nil::crypto3::cpuid::CPUID_ARM_PMULL_BIT};
424 enum endian_status : uint32_t {
425 ENDIAN_UNKNOWN = 0x00000000,
426 ENDIAN_BIG = 0x01234567,
427 ENDIAN_LITTLE = 0x67452301,
430 #if defined(BOOST_ARCH_PPC) || defined(BOOST_ARCH_ARM) || defined(BOOST_ARCH_X86)
436 static endian_status runtime_check_endian() {
438 const uint32_t endian32 = 0x01234567;
439 const uint8_t *e8 =
reinterpret_cast<const uint8_t *
>(&endian32);
441 endian_status endian = ENDIAN_UNKNOWN;
443 if (e8[0] == 0x01 && e8[1] == 0x23 && e8[2] == 0x45 && e8[3] == 0x67) {
445 }
else if (e8[0] == 0x67 && e8[1] == 0x45 && e8[2] == 0x23 && e8[3] == 0x01) {
446 endian = ENDIAN_LITTLE;
448 throw std::exception();
452 #if defined(BOOST_ENDIAN_LITTLE_BYTE_AVAILABLE)
453 BOOST_ASSERT_MSG(endian == ENDIAN_LITTLE,
"Build and runtime endian match");
454 #elif defined(BOOST_ENDIAN_BIG_BYTE_AVAILABLE)
455 BOOST_ASSERT_MSG(endian == ENDIAN_BIG,
"Build and runtime endian match");
461 static endian_status get_endian_status() {
462 if (g_endian_status == ENDIAN_UNKNOWN) {
463 g_endian_status = runtime_check_endian();
465 return g_endian_status;
468 static uint64_t g_processor_features;
469 static size_t g_cache_line_size;
470 static enum endian_status g_endian_status;
473 uint64_t cpuid::g_processor_features = 0;
475 cpuid::endian_status cpuid::g_endian_status = ENDIAN_UNKNOWN;
static bool has_cpuid_bit(CPUID_bits elem)
Definition: cpuid.hpp:370
static std::string to_string()
Definition: cpuid.hpp:77
static bool is_big_endian()
Definition: cpuid.hpp:145
static size_t cache_line_size()
Definition: cpuid.hpp:134
static bool is_little_endian()
Definition: cpuid.hpp:141
static std::vector< cpuid::CPUID_bits > bit_from_string(const std::string &tok)
Definition: cpuid.hpp:379
static bool has_simd_32()
Definition: cpuid.hpp:57
static void clear_cpuid_bit(CPUID_bits bit)
Definition: cpuid.hpp:361
CPUID_bits
Definition: cpuid.hpp:149
@ CPUID_INITIALIZED_BIT
Definition: cpuid.hpp:188
static void initialize()
Definition: cpuid.hpp:44
#define CRYPTO3_TARGET_CPU_DEFAULT_CACHE_LINE_SIZE
Definition: cpuid.hpp:16
#define CPUID_PRINT(flag)