25#if defined(__x86_64__) || defined(__amd64) || defined(_M_AMD64) || defined(_M_X64) || defined(__I386__) || \
26 defined(__i386__) || defined(__THW_INTEL) || defined(_M_IX86)
50static void cpuid(
int info,
unsigned *eax,
unsigned *ebx,
unsigned *ecx,
unsigned *edx)
52 TRACE(
"Entering cpuid(%d, %d, %d, %d, %d)", info, *eax, *ebx, *ecx, *edx);
55 unsigned int registers[4];
56 __cpuid(registers, info);
67 __cpuid(info, _eax, _ebx, _ecx, _edx);
74 TRACE(
"Exiting cpuid(%d, %d, %d, %d, %d)", info, *eax, *ebx, *ecx, *edx);
87static void cpuidex(
int info,
int count,
unsigned *eax,
unsigned *ebx,
unsigned *ecx,
unsigned *edx)
89 TRACE(
"Entering cpuidex(%d, %d, %d, %d, %d, %d)", info, count, *eax, *ebx, *ecx, *edx);
92 unsigned int registers[4];
93 __cpuidex(registers, info, count);
104 __cpuid_count(info, count, _eax, _ebx, _ecx, _edx);
111 TRACE(
"Exiting cpuidex(%d, %d, %d, %d, %d, %d)", info, count, *eax, *ebx, *ecx, *edx);
121 TRACE(
"Entering have_clmul()");
123 unsigned eax, ebx, ecx, edx;
124 cpuid(1 , &eax, &ebx, &ecx, &edx);
126 int has_pclmulqdq = ecx & 0x2;
127 int has_sse41 = ecx & 0x80000;
129 TRACE(
"Exiting have_clmul() = %d", has_pclmulqdq && has_sse41);
130 return has_pclmulqdq && has_sse41;
140 TRACE(
"Entering have_ssse3()");
141 unsigned eax, ebx, ecx, edx;
142 cpuid(1 , &eax, &ebx, &ecx, &edx);
144 TRACE(
"Exiting have_ssse3() = %d", ecx & 0x200);
155 TRACE(
"Entering have_avx2()");
156 unsigned eax, ebx, ecx, edx;
157 cpuidex(7 , 0, &eax, &ebx, &ecx, &edx);
159 TRACE(
"Exiting have_avx2() = %d", ebx & 0x20);
164#if defined(__aarch64__) || defined(_M_ARM64) || defined(__arm__) || defined(_M_ARM)
168#include <processthreadsapi.h>
169#elif defined(__APPLE__)
170#include <sys/sysctl.h>
176#if (defined(__aarch64__) || defined(_M_ARM64) || defined(__arm__) || defined(_M_ARM)) && defined(__APPLE__)
184 TRACE(
"Entering have_neon_apple()");
186 size_t len =
sizeof(int);
187 int ret = sysctlbyname(
"hw.optional.neon", &value, &len, NULL, 0);
191 TRACE(
"Exiting have_neon_apple() = 0");
195 TRACE(
"Exiting have_neon_apple() = %d", value == 1);
204int have_crc32_apple()
206 TRACE(
"Entering have_crc32_apple()");
208 size_t len =
sizeof(int);
209 int ret = sysctlbyname(
"hw.optional.crc32", &value, &len, NULL, 0);
213 TRACE(
"Exiting have_crc32_apple() = 0");
217 TRACE(
"Exiting have_crc32_apple() = %d", value == 1);
226int have_crypto_apple() {
return 0; }
229#if defined(__aarch64__) || defined(_M_ARM64)
238 return IsProcessorFeaturePresent(PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE) != 0;
239#elif defined(__APPLE__)
240 return have_crc32_apple();
242 return getauxval(AT_HWCAP) & HWCAP_CRC32;
249 return IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE) != 0;
250#elif defined(__APPLE__)
251 return have_crypto_apple();
253 return getauxval(AT_HWCAP) & HWCAP_AES;
258#if defined(__arm__) || defined(_M_ARM)
262 return IsProcessorFeaturePresent(PF_ARM_VFP_32_REGISTERS_AVAILABLE) != 0;
263#elif defined(__APPLE__)
264 return have_neon_apple();
266 return getauxval(AT_HWCAP) & HWCAP_NEON;
273 return IsProcessorFeaturePresent(PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE) != 0;
274#elif defined(__APPLE__)
275 return have_crc32_apple();
277 return getauxval(AT_HWCAP2) & HWCAP2_CRC32;
284 return IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE) != 0;
285#elif defined(__APPLE__)
286 return have_crypto_apple();
288 return getauxval(AT_HWCAP2) & HWCAP2_AES;