summaryrefslogtreecommitdiff
path: root/libs/pbd/fpu.cc
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2015-08-11 17:23:11 -0400
committerPaul Davis <paul@linuxaudiosystems.com>2015-08-11 17:23:11 -0400
commitc0ad97c179d6b7791fec1aaf6d49e63c20f6c817 (patch)
tree61a6edfead1d2ece7a53703d1febcb680e186ef2 /libs/pbd/fpu.cc
parent4079855507474dcaea3e6586f716a8873d6e821b (diff)
add required test of OS support for AVX register use
Diffstat (limited to 'libs/pbd/fpu.cc')
-rw-r--r--libs/pbd/fpu.cc37
1 files changed, 35 insertions, 2 deletions
diff --git a/libs/pbd/fpu.cc b/libs/pbd/fpu.cc
index 78fc5ba820..9fde6ab133 100644
--- a/libs/pbd/fpu.cc
+++ b/libs/pbd/fpu.cc
@@ -37,6 +37,22 @@
using namespace PBD;
using namespace std;
+/* This function is provided by MSVC are part of the compiler instrinsics. We
+ * don't care about this on OS X (though perhaps we should), but we need to
+ * test AVX support on Linux also. It doesn't hurt that this works on OS X
+ * also.
+ */
+
+#if __GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ >= 4
+static inline unsigned long long _xgetbv(unsigned int index){
+ unsigned int eax, edx;
+ __asm__ __volatile__("xgetbv" : "=a"(eax), "=d"(edx) : "c"(index));
+ return ((unsigned long long)edx << 32) | eax;
+}
+#else
+#define _xgetbv() 0
+#endif
+
FPU::FPU ()
{
unsigned long cpuflags = 0;
@@ -96,8 +112,25 @@ FPU::FPU ()
#endif /* _LP64 */
#endif /* PLATFORM_WINDOWS */
- if (cpuflags & ((1<<27)|(1<<28))) {
- _flags = Flags (_flags | HasAVX);
+ if (cpuflags & ((1<<27) /* AVX */ |(1<<28) /* XGETBV */)) {
+
+ std::cerr << "Looks like AVX\n";
+
+ /* now check if YMM resters state is saved: which means OS does
+ * know about new YMM registers and saves them during context
+ * switches it's true for most cases, but we must be sure
+ *
+ * giving 0 as the argument to _xgetbv() fetches the
+ * XCR_XFEATURE_ENABLED_MASK, which we need to check for
+ * the 2nd and 3rd bits, indicating correct register save/restore.
+ */
+
+ uint64_t xcrFeatureMask = _xgetbv (0);
+
+ if (xcrFeatureMask & 0x6) {
+ std::cerr << "Definitely AVX\n";
+ _flags = Flags (_flags | (HasAVX) );
+ }
}
if (cpuflags & (1<<25)) {