1 module pfft.detect_avx; 2 3 nothrow: 4 @nogc: 5 6 private __gshared int avx_state; 7 8 private void set_avx_state() 9 { 10 enum xcr0_avx_shift = 2; // AVX enabled by OS 11 enum cpuid_avx = 1 << 28; // processor supports AVX 12 enum cpuid_xsave = 1 << 26; // processor supports xgetbv 13 enum mask = cpuid_avx | cpuid_xsave; 14 15 int r = void; 16 version(GNU) 17 asm nothrow @nogc 18 { 19 "mov $1, %%eax 20 cpuid 21 mov $0, %%eax 22 and $0x14000000, %%ecx 23 cmp $0x14000000, %%ecx 24 jne exit_label%= 25 xor %%ecx, %%ecx 26 xgetbv 27 shr $2, %%eax 28 and $1, %%eax 29 exit_label%=: 30 mov %%eax, %0" 31 : "=r" r 32 : 33 : "eax", "ebx", "ecx", "edx" ; 34 } 35 else 36 asm nothrow @nogc 37 { 38 mov EAX, 1; 39 cpuid; 40 mov EAX, 0; 41 and ECX, mask; 42 cmp ECX, mask; 43 jne exit_label; 44 xor ECX, ECX; 45 xgetbv; 46 shr EAX, xcr0_avx_shift; 47 and EAX, 1; 48 exit_label: 49 mov r, EAX; 50 } 51 52 avx_state = r | 2; 53 } 54 55 // TODO: use atomics there to protect avx_state 56 @property get()() 57 { 58 if(!avx_state) 59 set_avx_state(); 60 61 return avx_state & 1; 62 } 63