improved solution for xgetbv() on windows and linux with all compilers

This commit is contained in:
Paul Davis 2015-08-11 17:45:41 -04:00
parent 53bc2ba2c1
commit bb5c969ac0

View file

@ -37,22 +37,6 @@
using namespace PBD; using namespace PBD;
using namespace std; 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 () FPU::FPU ()
{ {
unsigned long cpuflags = 0; unsigned long cpuflags = 0;
@ -126,8 +110,15 @@ FPU::FPU ()
* the 2nd and 3rd bits, indicating correct register save/restore. * 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) { if (xcrFeatureMask & 0x6) {
std::cerr << "Definitely AVX\n"; std::cerr << "Definitely AVX\n";
_flags = Flags (_flags | (HasAVX) ); _flags = Flags (_flags | (HasAVX) );