From 74c8de6372bc84916551a6685f337e69017eb239 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 11 Aug 2014 14:19:15 -0700 Subject: [PATCH] Try the __cpuid intrinsic if GCC's __get_cpuid isn't available --- Alc/helpers.c | 52 ++++++++++++++++++++++++++++++++++++++++++---------- CMakeLists.txt | 11 +++++++++++ config.h.in | 6 ++++++ 3 files changed, 59 insertions(+), 10 deletions(-) diff --git a/Alc/helpers.c b/Alc/helpers.c index 22e99d7e..90419c17 100644 --- a/Alc/helpers.c +++ b/Alc/helpers.c @@ -66,6 +66,9 @@ DEFINE_DEVPROPKEY(DEVPKEY_Device_FriendlyName, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, #ifdef HAVE_DLFCN_H #include #endif +#ifdef HAVE_INTRIN_H +#include +#endif #ifdef HAVE_CPUID_H #include #endif @@ -147,19 +150,48 @@ void FillCPUCaps(ALuint capfilter) } } } -#elif defined(HAVE_WINDOWS_H) - HMODULE k32 = GetModuleHandleA("kernel32.dll"); - BOOL (WINAPI*IsProcessorFeaturePresent)(DWORD ProcessorFeature); - IsProcessorFeaturePresent = (BOOL(WINAPI*)(DWORD))GetProcAddress(k32, "IsProcessorFeaturePresent"); - if(!IsProcessorFeaturePresent) - ERR("IsProcessorFeaturePresent not available; CPU caps not detected\n"); +#elif defined(HAVE_CPUID_INTRINSIC) && (defined(__i386__) || defined(__x86_64__) || \ + defined(_M_IX86) || defined(_M_X64)) + union { + int regs[4]; + char str[sizeof(int[4])]; + } cpuinf[3]; + + (__cpuid)(cpuinf[0].regs, 0); + if(cpuinf[0].regs[0] == 0) + ERR("Failed to get CPUID\n"); else { - if(IsProcessorFeaturePresent(PF_XMMI_INSTRUCTIONS_AVAILABLE)) + unsigned int maxfunc = cpuinf[0].regs[0]; + unsigned int maxextfunc; + + (__cpuid)(cpuinf[0].regs, 0x80000000); + maxextfunc = cpuinf[0].regs[0]; + + TRACE("Detected max CPUID function: 0x%x (ext. 0x%x)\n", maxfunc, maxextfunc); + + TRACE("Vendor ID: \"%.4s%.4s%.4s\"\n", cpuinf[0].str+4, cpuinf[0].str+12, cpuinf[0].str+8); + if(maxextfunc >= 0x80000004) { - caps |= CPU_CAP_SSE; - if(IsProcessorFeaturePresent(PF_XMMI64_INSTRUCTIONS_AVAILABLE)) - caps |= CPU_CAP_SSE2; + (__cpuid)(cpuinf[0].regs, 0x80000002); + (__cpuid)(cpuinf[1].regs, 0x80000003); + (__cpuid)(cpuinf[2].regs, 0x80000004); + TRACE("Name: \"%.16s%.16s%.16s\"\n", cpuinf[0].str, cpuinf[1].str, cpuinf[2].str); + } + + if(maxfunc >= 1) + { + (__cpuid)(cpuinf[0].regs, 1); + if((cpuinf[0].regs[3]&(1<<25))) + { + caps |= CPU_CAP_SSE; + if((cpuinf[0].regs[3]&(1<<26))) + { + caps |= CPU_CAP_SSE2; + if((cpuinf[0].regs[2]&(1<<19))) + caps |= CPU_CAP_SSE4_1; + } + } } } #endif diff --git a/CMakeLists.txt b/CMakeLists.txt index cbb6844b..f1de92d6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -351,6 +351,7 @@ CHECK_INCLUDE_FILE(ftw.h HAVE_FTW_H) CHECK_INCLUDE_FILE(io.h HAVE_IO_H) CHECK_INCLUDE_FILE(strings.h HAVE_STRINGS_H) CHECK_INCLUDE_FILE(cpuid.h HAVE_CPUID_H) +CHECK_INCLUDE_FILE(intrin.h HAVE_INTRIN_H) CHECK_INCLUDE_FILE(sys/sysconf.h HAVE_SYS_SYSCONF_H) CHECK_INCLUDE_FILE(fenv.h HAVE_FENV_H) CHECK_INCLUDE_FILE(float.h HAVE_FLOAT_H) @@ -369,6 +370,16 @@ IF(HAVE_CPUID_H) }" HAVE_GCC_GET_CPUID) ENDIF() +IF(HAVE_INTRIN_H) + CHECK_C_SOURCE_COMPILES("#include + int main() + { + int regs[4]; + __cpuid(regs, 0); + return regs[0]; + }" HAVE_CPUID_INTRINSIC) +ENDIF() + # Some systems need libm for some of the following math functions to work CHECK_LIBRARY_EXISTS(m pow "" HAVE_LIBM) IF(HAVE_LIBM) diff --git a/config.h.in b/config.h.in index 27184824..af0d8bfd 100644 --- a/config.h.in +++ b/config.h.in @@ -148,6 +148,9 @@ /* Define if we have cpuid.h */ #cmakedefine HAVE_CPUID_H +/* Define if we have intrin.h */ +#cmakedefine HAVE_INTRIN_H + /* Define if we have sys/sysconf.h */ #cmakedefine HAVE_SYS_SYSCONF_H @@ -169,6 +172,9 @@ /* Define if we have GCC's __get_cpuid() */ #cmakedefine HAVE_GCC_GET_CPUID +/* Define if we have the __cpuid() intrinsic */ +#cmakedefine HAVE_CPUID_INTRINSIC + /* Define if we have _controlfp() */ #cmakedefine HAVE__CONTROLFP -- 2.11.4.GIT