improved solution for xgetbv() on windows and linux with all compilers
authorPaul Davis <paul@linuxaudiosystems.com>
Tue, 11 Aug 2015 21:45:41 +0000 (17:45 -0400)
committerPaul Davis <paul@linuxaudiosystems.com>
Tue, 11 Aug 2015 21:45:41 +0000 (17:45 -0400)
libs/pbd/fpu.cc

index 869c0b66fb54cc2fdac73b34fdbbfb33dfccf225..29d09f7aa947626459b69c8a2ad033241001e16e 100644 (file)
 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. This doesn't work on OS X because 
- * the compiler is different there. 
- */
-
-#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;
@@ -126,8 +110,15 @@ FPU::FPU ()
                 * the 2nd and 3rd bits, indicating correct register save/restore.
                 */
 
-               uint64_t xcrFeatureMask = _xgetbv (0);
+               uint64_t xcrFeatureMask = 0;
 
+#if __GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ >= 4
+               unsigned int eax, edx, index = 0;
+               asm volatile("xgetbv" : "=a"(eax), "=d"(edx) : "c"(index));
+               xcrFeatureMask = ((unsigned long long)edx << 32) | eax;
+#elif defined (COMPILER_MSVC)
+               xcrFeatureMask = _xgetbv(_XCR_XFEATURE_ENABLED_MASK);
+#endif
                if (xcrFeatureMask & 0x6) {
                        std::cerr << "Definitely AVX\n";
                        _flags = Flags (_flags | (HasAVX) );