diff options
author | Paul Davis <paul@linuxaudiosystems.com> | 2007-06-01 22:26:12 +0000 |
---|---|---|
committer | Paul Davis <paul@linuxaudiosystems.com> | 2007-06-01 22:26:12 +0000 |
commit | 7777d54887d95a38cd0222233ca06d8a146e5a76 (patch) | |
tree | 4b2cf6be0c108ca86d8bb0d88eef0529b998555f /libs | |
parent | 2291d59bc813597c95f2f00b2e8ae697f1f284f9 (diff) |
2nd stage of denormal handling (from trunk); fix to avoid FLAC support when using a too-new FLAC library
git-svn-id: svn://localhost/ardour2/branches/2.0-ongoing@1940 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'libs')
-rw-r--r-- | libs/ardour/globals.cc | 62 | ||||
-rw-r--r-- | libs/ardour/session_state.cc | 2 | ||||
-rw-r--r-- | libs/pbd/SConscript | 1 | ||||
-rw-r--r-- | libs/pbd/fpu.cc | 92 | ||||
-rw-r--r-- | libs/pbd/pbd/fpu.h | 31 |
5 files changed, 145 insertions, 43 deletions
diff --git a/libs/ardour/globals.cc b/libs/ardour/globals.cc index eb5a2cc9f2..a6fb0fcf41 100644 --- a/libs/ardour/globals.cc +++ b/libs/ardour/globals.cc @@ -37,6 +37,7 @@ #include <pbd/error.h> #include <pbd/id.h> #include <pbd/strsplit.h> +#include <pbd/fpu.h> #include <midi++/port.h> #include <midi++/port_request.h> @@ -200,42 +201,14 @@ void setup_hardware_optimization (bool try_optimization) { bool generic_mix_functions = true; - + FPU fpu; if (try_optimization) { #if defined (ARCH_X86) && defined (BUILD_SSE_OPTIMIZATIONS) - - unsigned long use_sse = 0; - -#ifndef USE_X86_64_ASM - asm ( - "mov $1, %%eax\n" - "pushl %%ebx\n" - "cpuid\n" - "movl %%edx, %0\n" - "popl %%ebx\n" - : "=r" (use_sse) - : - : "%eax", "%ecx", "%edx", "memory"); - -#else - - asm ( - "pushq %%rbx\n" - "movq $1, %%rax\n" - "cpuid\n" - "movq %%rdx, %0\n" - "popq %%rbx\n" - : "=r" (use_sse) - : - : "%rax", "%rcx", "%rdx", "memory"); - -#endif /* USE_X86_64_ASM */ - - use_sse &= (1 << 25); // bit 25 = SSE support + + if (fpu.has_sse()) { - if (use_sse) { info << "Using SSE optimized routines" << endmsg; // SSE SET @@ -538,17 +511,16 @@ ARDOUR::LocaleGuard::~LocaleGuard () void ARDOUR::setup_fpu () { -#ifdef USE_XMMINTRIN +#if defined(ARCH_X86) && defined(USE_XMMINTRIN) + int MXCSR; + FPU fpu; /* XXX use real code to determine if the processor supports DenormalsAreZero and FlushToZero */ - bool has_daz = false; - bool can_ftz = true; - - if (!can_ftz && !has_daz) { + if (!fpu.has_flush_to_zero() && !fpu.has_denormals_are_zero()) { return; } @@ -556,25 +528,29 @@ ARDOUR::setup_fpu () switch (Config->get_denormal_model()) { case DenormalNone: - MXCSR &= ~_MM_FLUSH_ZERO_ON; + MXCSR &= ~(_MM_FLUSH_ZERO_ON|0x8000); break; case DenormalFTZ: - MXCSR |= _MM_FLUSH_ZERO_ON; + if (fpu.has_flush_to_zero()) { + MXCSR |= _MM_FLUSH_ZERO_ON; + } break; case DenormalDAZ: MXCSR &= ~_MM_FLUSH_ZERO_ON; - if (has_daz) { + if (fpu.has_denormals_are_zero()) { MXCSR |= 0x8000; } break; case DenormalFTZDAZ: - if (has_daz) { - MXCSR |= _MM_FLUSH_ZERO_ON | 0x8000; - } else { - MXCSR |= _MM_FLUSH_ZERO_ON; + if (fpu.has_flush_to_zero()) { + if (fpu.has_denormals_are_zero()) { + MXCSR |= _MM_FLUSH_ZERO_ON | 0x8000; + } else { + MXCSR |= _MM_FLUSH_ZERO_ON; + } } break; } diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc index 937fd78daf..37b717f491 100644 --- a/libs/ardour/session_state.cc +++ b/libs/ardour/session_state.cc @@ -3278,6 +3278,8 @@ Session::config_changed (const char* parameter_name) set_slave_source (Config->get_slave_source()); } else if (PARAM_IS ("remote-model")) { set_remote_control_ids (); + } else if (PARAM_IS ("denormal-model")) { + setup_fpu (); } set_dirty (); diff --git a/libs/pbd/SConscript b/libs/pbd/SConscript index 3aaeb1bf1b..a0065f09bd 100644 --- a/libs/pbd/SConscript +++ b/libs/pbd/SConscript @@ -27,6 +27,7 @@ controllable.cc enumwriter.cc dmalloc.cc error.cc +fpu.cc id.cc mountpoint.cc path.cc 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 () +{ +} diff --git a/libs/pbd/pbd/fpu.h b/libs/pbd/pbd/fpu.h new file mode 100644 index 0000000000..617dcdf3da --- /dev/null +++ b/libs/pbd/pbd/fpu.h @@ -0,0 +1,31 @@ +#ifndef __pbd_fpu_h__ +#define __pbd_fpu_h__ + +namespace PBD { + + +class FPU { + private: + enum Flags { + HasFlushToZero = 0x1, + HasDenormalsAreZero = 0x2, + HasSSE = 0x4, + HasSSE2 = 0x8 + }; + + public: + FPU (); + ~FPU (); + + bool has_flush_to_zero () const { return _flags & HasFlushToZero; } + bool has_denormals_are_zero () const { return _flags & HasDenormalsAreZero; } + bool has_sse () const { return _flags & HasSSE; } + bool has_sse2 () const { return _flags & HasSSE2; } + + private: + Flags _flags; +}; + +} + +#endif /* __pbd_fpu_h__ */ |