diff options
author | Paul Davis <paul@linuxaudiosystems.com> | 2008-06-02 21:41:35 +0000 |
---|---|---|
committer | Paul Davis <paul@linuxaudiosystems.com> | 2008-06-02 21:41:35 +0000 |
commit | 449aab3c465bbbf66d221fac3d7ea559f1720357 (patch) | |
tree | 6843cc40c88250a132acac701271f1504cd2df04 /libs/pbd/fpu.cc | |
parent | 9c0d7d72d70082a54f823cd44c0ccda5da64bb6f (diff) |
rollback to 3428, before the mysterious removal of libs/* at 3431/3432
git-svn-id: svn://localhost/ardour2/branches/3.0@3435 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'libs/pbd/fpu.cc')
-rw-r--r-- | libs/pbd/fpu.cc | 97 |
1 files changed, 97 insertions, 0 deletions
diff --git a/libs/pbd/fpu.cc b/libs/pbd/fpu.cc new file mode 100644 index 0000000000..f6850a57dc --- /dev/null +++ b/libs/pbd/fpu.cc @@ -0,0 +1,97 @@ +#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; + +#ifdef NO_POSIX_MEMALIGN + if ((fxbuf = (char *) malloc(512)) == 0) +#else + if (posix_memalign ((void**)&fxbuf, 16, 512)) +#endif + { + 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 () +{ +} |