diff --git a/libs/pbd/fpu.cc b/libs/pbd/fpu.cc index 2c0d70df25..a0013fee57 100644 --- a/libs/pbd/fpu.cc +++ b/libs/pbd/fpu.cc @@ -27,16 +27,20 @@ #include #include -#ifdef PLATFORM_WINDOWS -#include -#endif - #ifdef ARM_NEON_SUPPORT /* Needed for ARM NEON detection */ #include #include #endif +#ifdef PLATFORM_WINDOWS +#include +#elif defined(__GNUC__) || defined(__clang__) +#include +#else +#error "Unsupported compiler: need __cpuid and __cpuidex for CPU detection" +#endif + #include "pbd/compose.h" #include "pbd/fpu.h" #include "pbd/error.h" @@ -49,35 +53,30 @@ using namespace std; FPU* FPU::_instance (0); #if ( (defined __x86_64__) || (defined __i386__) || (defined _M_X64) || (defined _M_IX86) ) // ARCH_X86 -#ifndef PLATFORM_WINDOWS -/* use __cpuid() as the name to match the MSVC/mingw intrinsic */ - -static void -__cpuid(int regs[4], int cpuid_leaf) +#ifdef PLATFORM_WINDOWS +/* Use MSVC/mingw intrinsic to get CPUID */ +static void cpuid(int reg[4], int cpuid_leaf) { - asm volatile ( -#if defined(__i386__) - "pushl %%ebx;\n\t" -#endif - "cpuid;\n\t" - "movl %%eax, (%1);\n\t" - "movl %%ebx, 4(%1);\n\t" - "movl %%ecx, 8(%1);\n\t" - "movl %%edx, 12(%1);\n\t" -#if defined(__i386__) - "popl %%ebx;\n\t" -#endif - :"=a" (cpuid_leaf) /* %eax clobbered by CPUID */ - :"S" (regs), "a" (cpuid_leaf) - : -#if !defined(__i386__) - "%ebx", -#endif - "%ecx", "%edx", "memory"); + __cpuid(reg, cpuid_leaf); } - -#endif /* !PLATFORM_WINDOWS */ +/* Get extended features of CPUID */ +static void cpuidex(int reg[4], int cpuid_leaf, int cpuid_level) +{ + __cpuidex(reg, cpuid_leaf, cpuid_level); +} +#else +/* use __cpuid() with the same API to match the MSVC/mingw intrinsic */ +static void cpuid(int reg[4], int cpuid_leaf) +{ + __cpuid_count(cpuid_leaf, 0, reg[0], reg[1], reg[2], reg[3]); +} +/* Get extended features of CPUID */ +static void cpuidex(int reg[4], int cpuid_leaf, int cpuid_level) +{ + __cpuid_count(cpuid_leaf, cpuid_level, reg[0], reg[1], reg[2], reg[3]); +} +#endif // PLATFORM_WINDOWS #ifndef HAVE_XGETBV // Allow definition by build system #if defined(__MINGW32__) && defined(__MINGW64_VERSION_MAJOR) && __MINGW64_VERSION_MAJOR >= 5 @@ -192,7 +191,7 @@ FPU::FPU () char cpu_string[48]; string cpu_vendor; - __cpuid (cpu_info, 0); + cpuid(cpu_info, 0); int num_ids = cpu_info[0]; std::swap(cpu_info[2], cpu_info[3]); @@ -203,9 +202,13 @@ FPU::FPU () if (num_ids > 0) { - /* Now get CPU/FPU flags */ + int cpu_info_ex[4]; - __cpuid (cpu_info, 1); + /* Now get CPU/FPU flags */ + cpuid(cpu_info, 1); + + /* Get CPU extended features: Like AVX512F */ + cpuidex(cpu_info_ex, 7, 0); if ((cpu_info[2] & (1<<27)) /* OSXSAVE */ && (cpu_info[2] & (1<<28) /* AVX */) && @@ -219,7 +222,7 @@ FPU::FPU () _flags = Flags (_flags | (HasFMA)); } - if (cpu_info[2] & (1<<16) /* AVX512F */) { + if (cpu_info_ex[1] & (1<<16) /* AVX512F */) { info << _("AVX512F capable processor") << endmsg; _flags = Flags (_flags | (HasAVX512F)); } @@ -317,8 +320,7 @@ FPU::FPU () } /* finally get the CPU brand */ - - __cpuid (cpu_info, 0x80000000); + cpuid(cpu_info, 0x80000000); const int parameter_end = 0x80000004; string cpu_brand; @@ -328,7 +330,7 @@ FPU::FPU () for (int parameter = 0x80000002; parameter <= parameter_end && cpu_string_ptr < &cpu_string[sizeof(cpu_string)]; parameter++) { - __cpuid(cpu_info, parameter); + cpuid(cpu_info, parameter); memcpy(cpu_string_ptr, cpu_info, sizeof(cpu_info)); cpu_string_ptr += sizeof(cpu_info); }