diff options
author | Paul Davis <paul@linuxaudiosystems.com> | 2007-06-01 20:29:36 +0000 |
---|---|---|
committer | Paul Davis <paul@linuxaudiosystems.com> | 2007-06-01 20:29:36 +0000 |
commit | 01a780eb4d533465e94825b65a3f3d4216900832 (patch) | |
tree | 777e4cbf1c827d8fa29e676f33b06736e76ef2fb /libs/pbd/fpu.cc | |
parent | 38ed75ff979e72e73a759c350cd8b1e64e2ed18c (diff) |
round 2 of denormal handling changes - detect DAZ support at runtime, and use accordingly. move all FPU feature detection into PBD::FPU
git-svn-id: svn://localhost/ardour2/trunk@1939 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'libs/pbd/fpu.cc')
-rw-r--r-- | libs/pbd/fpu.cc | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/libs/pbd/fpu.cc b/libs/pbd/fpu.cc new file mode 100644 index 0000000000..ae69b62e8d --- /dev/null +++ b/libs/pbd/fpu.cc @@ -0,0 +1,92 @@ +#define _XOPEN_SOURCE 600 +#include <stdlib.h> +#include <stdint.h> + +#include <pbd/fpu.h> +#include <pbd/error.h> + +#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 () +{ +} |