#define _XOPEN_SOURCE 600 #include #include #include #include #include "i18n.h" using namespace PBD; using namespace std; FPU::FPU () { unsigned long cpuflags = 0; _flags = Flags (0); #ifndef ARCH_X86 return; #endif #ifndef USE_X86_64_ASM asm volatile ( "mov $1, %%eax\n" "pushl %%ebx\n" "cpuid\n" "movl %%edx, %0\n" "popl %%ebx\n" : "=r" (cpuflags) : : "%eax", "%ecx", "%edx", "memory" ); #else asm volatile ( "pushq %%rbx\n" "movq $1, %%rax\n" "cpuid\n" "movq %%rdx, %0\n" "popq %%rbx\n" : "=r" (cpuflags) : : "%rax", "%rcx", "%rdx", "memory" ); #endif /* USE_X86_64_ASM */ if (cpuflags & (1<<25)) { _flags = Flags (_flags | (HasSSE|HasFlushToZero)); } if (cpuflags & (1<<26)) { _flags = Flags (_flags | HasSSE2); } if (cpuflags & (1 << 24)) { char* fxbuf = 0; if (posix_memalign ((void**)&fxbuf, 16, 512)) { error << _("cannot allocate 16 byte aligned buffer for h/w feature detection") << endmsg; } else { asm volatile ( "fxsave (%0)" : : "r" (fxbuf) : "memory" ); uint32_t mxcsr_mask = *((uint32_t*) &fxbuf[28]); /* if the mask is zero, set its default value (from intel specs) */ if (mxcsr_mask == 0) { mxcsr_mask = 0xffbf; } if (mxcsr_mask & (1<<6)) { _flags = Flags (_flags | HasDenormalsAreZero); } free (fxbuf); } } } FPU::~FPU () { }