44#ifndef OJPH_DISABLE_SIMD
46 #if (defined(OJPH_ARCH_X86_64) || defined(OJPH_ARCH_I386))
52 bool run_cpuid(uint32_t eax, uint32_t ecx, uint32_t* abcd)
54 #ifdef OJPH_COMPILER_MSVC
55 __cpuidex((
int *)abcd, eax, ecx);
57 uint32_t ebx = 0, edx = 0;
58 #if defined( __i386__ ) && defined ( __PIC__ )
60 __asm__ (
"movl %%ebx, %%edi \n\t cpuid \n\t xchgl %%ebx, %%edi"
61 :
"=D" (ebx),
"+a" (eax),
"+c" (ecx),
"=d" (edx) );
63 __asm__ (
"cpuid" :
"+b" (ebx),
"+a" (eax),
"+c" (ecx),
"=d" (edx) );
65 abcd[0] = eax; abcd[1] = ebx; abcd[2] = ecx; abcd[3] = edx;
71 uint64_t read_xcr(uint32_t index)
73 #ifdef OJPH_COMPILER_MSVC
74 return _xgetbv(index);
76 uint32_t eax = 0, edx = 0;
77 __asm__ (
"xgetbv" :
"=a" (eax),
"=d" (edx) :
"c" (index) );
78 return ((uint64_t)edx << 32) | eax;
86 run_cpuid(1, 0, mmx_abcd);
87 bool mmx_avail = ((mmx_abcd[3] & 0x00800000) == 0x00800000);
93 bool sse_avail = ((mmx_abcd[3] & 0x02000000) == 0x02000000);
97 bool sse2_avail = ((mmx_abcd[3] & 0x04000000) == 0x04000000);
101 bool sse3_avail = ((mmx_abcd[2] & 0x00000001) == 0x00000001);
105 bool ssse3_avail = ((mmx_abcd[2] & 0x00000200) == 0x00000200);
109 bool sse41_avail = ((mmx_abcd[2] & 0x00080000) == 0x00080000);
112 bool sse42_avail = ((mmx_abcd[2] & 0x00100000) == 0x00100000);
117 uint64_t xcr_val = 0;
118 bool osxsave_avail, ymm_avail, avx_avail =
false;
119 osxsave_avail = ((mmx_abcd[2] & 0x08000000) == 0x08000000);
122 xcr_val = read_xcr(0);
123 ymm_avail = osxsave_avail && ((xcr_val & 0x6) == 0x6);
124 avx_avail = ymm_avail && (mmx_abcd[2] & 0x10000000);
130 uint32_t avx2_abcd[4];
131 run_cpuid(7, 0, avx2_abcd);
132 bool avx2_avail = (avx2_abcd[1] & 0x20) != 0;
137 avx2_avail && ((mmx_abcd[2] & 0x1000) == 0x1000);
143 osxsave_avail && ((xcr_val & 0xE0) == 0xE0);
144 bool avx512f_avail = (avx2_abcd[1] & 0x10000) != 0;
145 bool avx512cd_avail = (avx2_abcd[1] & 0x10000000) != 0;
147 zmm_avail && avx512f_avail && avx512cd_avail;
162 #elif defined(OJPH_ARCH_ARM)
164 #ifndef OJPH_OS_LINUX
173 #if defined(__aarch64__) || defined(_M_ARM64)
175 #include <sys/auxv.h>
176 #include <asm/hwcap.h>
179 unsigned long hwcaps = getauxval(AT_HWCAP);
180 unsigned long hwcaps2 = getauxval(AT_HWCAP2);
183 if (hwcaps & HWCAP_ASIMD) {
185 if (hwcaps & HWCAP_SVE) {
187 if (hwcaps2 & HWCAP2_SVE2)
196 #include <sys/auxv.h>
197 #include <asm/hwcap.h>
200 unsigned long hwcaps = getauxval(AT_HWCAP);
202 if (hwcaps & HWCAP_NEON)
221#elif defined(OJPH_ENABLE_WASM_SIMD) && defined(OJPH_EMSCRIPTEN)
bool init_cpu_ext_level(int &level)
@ ARM_CPU_EXT_LEVEL_GENERIC
@ ARM_CPU_EXT_LEVEL_ASIMD
@ X86_CPU_EXT_LEVEL_AVX512
@ X86_CPU_EXT_LEVEL_SSE41
@ X86_CPU_EXT_LEVEL_SSE42
@ X86_CPU_EXT_LEVEL_SSSE3
@ X86_CPU_EXT_LEVEL_AVX2FMA
OJPH_EXPORT int get_cpu_ext_level()
static bool cpu_level_initialized