45#ifndef OJPH_DISABLE_SIMD
47 #if (defined(OJPH_ARCH_X86_64) || defined(OJPH_ARCH_I386))
53 bool run_cpuid(uint32_t eax, uint32_t ecx, uint32_t* abcd)
55 #ifdef OJPH_COMPILER_MSVC
56 __cpuidex((
int *)abcd, eax, ecx);
58 uint32_t ebx = 0, edx = 0;
59 #if defined( __i386__ ) && defined ( __PIC__ )
61 __asm__ (
"movl %%ebx, %%edi \n\t cpuid \n\t xchgl %%ebx, %%edi"
62 :
"=D" (ebx),
"+a" (eax),
"+c" (ecx),
"=d" (edx) );
64 __asm__ (
"cpuid" :
"+b" (ebx),
"+a" (eax),
"+c" (ecx),
"=d" (edx) );
66 abcd[0] = eax; abcd[1] = ebx; abcd[2] = ecx; abcd[3] = edx;
72 uint64_t read_xcr(uint32_t index)
74 #ifdef OJPH_COMPILER_MSVC
75 return _xgetbv(index);
77 uint32_t eax = 0, edx = 0;
78 __asm__ (
"xgetbv" :
"=a" (eax),
"=d" (edx) :
"c" (index) );
79 return ((uint64_t)edx << 32) | eax;
87 run_cpuid(1, 0, mmx_abcd);
88 bool mmx_avail = ((mmx_abcd[3] & 0x00800000) == 0x00800000);
94 bool sse_avail = ((mmx_abcd[3] & 0x02000000) == 0x02000000);
98 bool sse2_avail = ((mmx_abcd[3] & 0x04000000) == 0x04000000);
102 bool sse3_avail = ((mmx_abcd[2] & 0x00000001) == 0x00000001);
106 bool ssse3_avail = ((mmx_abcd[2] & 0x00000200) == 0x00000200);
110 bool sse41_avail = ((mmx_abcd[2] & 0x00080000) == 0x00080000);
113 bool sse42_avail = ((mmx_abcd[2] & 0x00100000) == 0x00100000);
118 uint64_t xcr_val = 0;
119 bool osxsave_avail, ymm_avail, avx_avail =
false;
120 osxsave_avail = ((mmx_abcd[2] & 0x08000000) == 0x08000000);
123 xcr_val = read_xcr(0);
124 ymm_avail = osxsave_avail && ((xcr_val & 0x6) == 0x6);
125 avx_avail = ymm_avail && (mmx_abcd[2] & 0x10000000);
131 uint32_t avx2_abcd[4];
132 run_cpuid(7, 0, avx2_abcd);
133 bool avx2_avail = (avx2_abcd[1] & 0x20) != 0;
138 avx2_avail && ((mmx_abcd[2] & 0x1000) == 0x1000);
144 osxsave_avail && ((xcr_val & 0xE0) == 0xE0);
145 bool avx512f_avail = (avx2_abcd[1] & 0x10000) != 0;
146 bool avx512cd_avail = (avx2_abcd[1] & 0x10000000) != 0;
147 bool avx512bw_avail = (avx2_abcd[1] & 0x40000000) != 0;
148 bool avx512vl_avail =
149 (avx2_abcd[1] & 0x80000000u) != 0;
150 bool avx512_avail = zmm_avail && avx512f_avail
151 && avx512cd_avail && avx512bw_avail
167 #elif defined(OJPH_ARCH_ARM)
169 #if !defined(OJPH_OS_LINUX) && !defined(OJPH_OS_FREEBSD) && !defined(OJPH_OS_OPENBSD)
178 #if defined(__aarch64__) || defined(_M_ARM64) || defined(_M_ARM64EC)
180 #include <sys/auxv.h>
182 #include <asm/hwcap.h>
187 unsigned long hwcaps = getauxval(AT_HWCAP);
188 unsigned long hwcaps2 = getauxval(AT_HWCAP2);
190 unsigned long hwcaps = 0;
191 unsigned long hwcaps2 = 0;
192 elf_aux_info(AT_HWCAP, &hwcaps,
sizeof(hwcaps));
193 elf_aux_info(AT_HWCAP2, &hwcaps2,
sizeof(hwcaps2));
197 if (hwcaps & HWCAP_ASIMD) {
199 if (hwcaps & HWCAP_SVE) {
201 if (hwcaps2 & HWCAP2_SVE2)
210 #include <sys/auxv.h>
212 #include <asm/hwcap.h>
217 unsigned long hwcaps = getauxval(AT_HWCAP);
219 unsigned long hwcaps = 0;
220 elf_aux_info(AT_HWCAP, &hwcaps,
sizeof(hwcaps));
223 if (hwcaps & HWCAP_NEON)
242#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
OJPH_EXPORT int get_cpu_ext_level()
static bool cpu_level_initialized
@ 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