summaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2007-06-01 22:26:12 +0000
committerPaul Davis <paul@linuxaudiosystems.com>2007-06-01 22:26:12 +0000
commit7777d54887d95a38cd0222233ca06d8a146e5a76 (patch)
tree4b2cf6be0c108ca86d8bb0d88eef0529b998555f /libs
parent2291d59bc813597c95f2f00b2e8ae697f1f284f9 (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.cc62
-rw-r--r--libs/ardour/session_state.cc2
-rw-r--r--libs/pbd/SConscript1
-rw-r--r--libs/pbd/fpu.cc92
-rw-r--r--libs/pbd/pbd/fpu.h31
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__ */