2 * GF-Complete: A Comprehensive Open Source Library for Galois Field Arithmetic
3 * James S. Plank, Ethan L. Miller, Kevin M. Greenan,
4 * Benjamin A. Arnold, John A. Burnum, Adam W. Disney, Allen C. McBride.
8 * Identifies whether the CPU supports SIMD instructions at runtime.
14 int gf_cpu_identified = 0;
16 int gf_cpu_supports_intel_pclmul = 0;
17 int gf_cpu_supports_intel_sse4 = 0;
18 int gf_cpu_supports_intel_ssse3 = 0;
19 int gf_cpu_supports_intel_sse3 = 0;
20 int gf_cpu_supports_intel_sse2 = 0;
21 int gf_cpu_supports_arm_neon = 0;
23 #if defined(__x86_64__)
25 /* CPUID Feature Bits */
28 #define GF_CPU_SSE3 (1 << 0)
29 #define GF_CPU_PCLMUL (1 << 1)
30 #define GF_CPU_SSSE3 (1 << 9)
31 #define GF_CPU_SSE41 (1 << 19)
32 #define GF_CPU_SSE42 (1 << 20)
35 #define GF_CPU_SSE2 (1 << 26)
39 #define cpuid(info, x) __cpuidex(info, x, 0)
41 #elif defined(__GNUC__)
44 void cpuid(int info[4], int InfoType){
45 __cpuid_count(InfoType, 0, info[0], info[1], info[2], info[3]);
50 #error please add a way to detect CPU SIMD support at runtime
54 void gf_cpu_identify(void)
56 if (gf_cpu_identified) {
64 #if defined(INTEL_SSE4_PCLMUL)
65 if ((reg[2] & GF_CPU_PCLMUL) != 0 && !getenv("GF_COMPLETE_DISABLE_SSE4_PCLMUL")) {
66 gf_cpu_supports_intel_pclmul = 1;
67 #ifdef DEBUG_CPU_DETECTION
68 printf("#gf_cpu_supports_intel_pclmul\n");
73 #if defined(INTEL_SSE4)
74 if (((reg[2] & GF_CPU_SSE42) != 0 || (reg[2] & GF_CPU_SSE41) != 0) && !getenv("GF_COMPLETE_DISABLE_SSE4")) {
75 gf_cpu_supports_intel_sse4 = 1;
76 #ifdef DEBUG_CPU_DETECTION
77 printf("#gf_cpu_supports_intel_sse4\n");
82 #if defined(INTEL_SSSE3)
83 if ((reg[2] & GF_CPU_SSSE3) != 0 && !getenv("GF_COMPLETE_DISABLE_SSSE3")) {
84 gf_cpu_supports_intel_ssse3 = 1;
85 #ifdef DEBUG_CPU_DETECTION
86 printf("#gf_cpu_supports_intel_ssse3\n");
91 #if defined(INTEL_SSE3)
92 if ((reg[2] & GF_CPU_SSE3) != 0 && !getenv("GF_COMPLETE_DISABLE_SSE3")) {
93 gf_cpu_supports_intel_sse3 = 1;
94 #ifdef DEBUG_CPU_DETECTION
95 printf("#gf_cpu_supports_intel_sse3\n");
100 #if defined(INTEL_SSE2)
101 if ((reg[3] & GF_CPU_SSE2) != 0 && !getenv("GF_COMPLETE_DISABLE_SSE2")) {
102 gf_cpu_supports_intel_sse2 = 1;
103 #ifdef DEBUG_CPU_DETECTION
104 printf("#gf_cpu_supports_intel_sse2\n");
109 gf_cpu_identified = 1;
112 #elif defined(__arm__) || defined(__aarch64__)
119 #include <linux/auxvec.h>
120 #include <asm/hwcap.h>
123 unsigned long get_hwcap(unsigned long type) {
124 unsigned long hwcap = 0;
125 int fd = open("/proc/self/auxv", O_RDONLY);
128 while (read(fd, &auxv, sizeof(Elf32_auxv_t))) {
129 if (auxv.a_type == type) {
130 hwcap = auxv.a_un.a_val;
142 void gf_cpu_identify(void)
144 if (gf_cpu_identified) {
148 #if defined(ARM_NEON)
149 if (!getenv("GF_COMPLETE_DISABLE_NEON")) {
150 #if __linux__ && __arm__
151 gf_cpu_supports_arm_neon = (get_hwcap(AT_HWCAP) & HWCAP_NEON) > 0;
153 // ASIMD is supported on all aarch64 architectures
154 gf_cpu_supports_arm_neon = 1;
156 // we assume that NEON is supported if the compiler supports
157 // NEON and we dont have a reliable way to detect runtime support.
158 gf_cpu_supports_arm_neon = 1;
161 #ifdef DEBUG_CPU_DETECTION
162 if (gf_cpu_supports_arm_neon) {
163 printf("#gf_cpu_supports_arm_neon\n");
167 #endif // defined(ARM_NEON)
169 gf_cpu_identified = 1;
172 #else // defined(__arm__) || defined(__aarch64__)
174 int gf_cpu_identify(void)
176 gf_cpu_identified = 1;