From: Detlef Riekenberg Date: Mon, 14 Apr 2025 23:59:47 +0000 (+0200) Subject: port: Use __cpuid only, when available. X-Git-Url: http://git.ipfire.org/gitweb/gitweb.cgi?a=commitdiff_plain;h=5a232688e1bc5ce41bc1f0e11cedaa0c6c643c8b;p=thirdparty%2Fzlib-ng.git port: Use __cpuid only, when available. Add a fallback, when __cpuid is not available --- diff --git a/CMakeLists.txt b/CMakeLists.txt index 4a453ebe..df137738 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -496,6 +496,44 @@ if(HAVE__ALIGNED_MALLOC) endif() set(CMAKE_REQUIRED_DEFINITIONS) +# +# Check for x86 __cpuid / __cpuid_count support: GNU extensions +# gcc/clang and MSVC have __cpuid, so check __cpuid_count instead +check_symbol_exists(__cpuid_count cpuid.h HAVE_CPUID_GNU) +if(HAVE_CPUID_GNU) + add_definitions(-DHAVE_CPUID_GNU) +endif() +set(CMAKE_REQUIRED_DEFINITIONS) + +# +# Check for x86 __cpuid / __cpuidex support: MSVC extensions +# gcc/clang and MSVC have __cpuid, so check __cpuidex instead +# check_symbol_exists() does not work for intrinsics + +check_c_source_compiles( +" +#include +static inline void cpuid_ms(int info, unsigned int *eax, unsigned int *ebx, unsigned int *ecx, unsigned int *edx) { + unsigned int registers[4]; + __cpuid((int *)registers, info); + *eax = registers[0]; + *ebx = registers[1]; + *ecx = registers[2]; + *edx = registers[3]; +} + +int main(void) { + unsigned int eax, ebx, ecx, edx; + cpuid_ms(0, &eax, &ebx, &ecx, &edx); + return eax; +}" +HAVE_CPUID_MS) + +if(HAVE_CPUID_MS) + add_definitions(-DHAVE_CPUID_MS) +endif() +set(CMAKE_REQUIRED_DEFINITIONS) + # # Check whether a sanitizer was requested # diff --git a/arch/x86/x86_features.c b/arch/x86/x86_features.c index 9491a007..806e99a6 100644 --- a/arch/x86/x86_features.c +++ b/arch/x86/x86_features.c @@ -10,9 +10,10 @@ #include "zbuild.h" #include "x86_features.h" -#ifdef _MSC_VER -# include -#else + +#if defined(HAVE_CPUID_MS) +# include +#elif defined(HAVE_CPUID_GNU) // Newer versions of GCC and clang come with cpuid.h # include # ifdef X86_HAVE_XSAVE_INTRIN @@ -27,7 +28,7 @@ #include static inline void cpuid(int info, unsigned* eax, unsigned* ebx, unsigned* ecx, unsigned* edx) { -#ifdef _MSC_VER +#if defined(HAVE_CPUID_MS) unsigned int registers[4]; __cpuid((int *)registers, info); @@ -35,14 +36,17 @@ static inline void cpuid(int info, unsigned* eax, unsigned* ebx, unsigned* ecx, *ebx = registers[1]; *ecx = registers[2]; *edx = registers[3]; -#else +#elif defined(HAVE_CPUID_GNU) *eax = *ebx = *ecx = *edx = 0; __cpuid(info, *eax, *ebx, *ecx, *edx); +#else + /* When using this fallback, the faster SSE/AVX code is disabled */ + *eax = *ebx = *ecx = *edx = 0; #endif } static inline void cpuidex(int info, int subinfo, unsigned* eax, unsigned* ebx, unsigned* ecx, unsigned* edx) { -#ifdef _MSC_VER +#if defined(HAVE_CPUID_MS) unsigned int registers[4]; __cpuidex((int *)registers, info, subinfo); @@ -50,19 +54,25 @@ static inline void cpuidex(int info, int subinfo, unsigned* eax, unsigned* ebx, *ebx = registers[1]; *ecx = registers[2]; *edx = registers[3]; -#else +#elif defined(HAVE_CPUID_GNU) *eax = *ebx = *ecx = *edx = 0; __cpuid_count(info, subinfo, *eax, *ebx, *ecx, *edx); +#else + /* When using this fallback, the faster SSE/AVX code is disabled */ + *eax = *ebx = *ecx = *edx = 0; #endif } static inline uint64_t xgetbv(unsigned int xcr) { #if defined(_MSC_VER) || defined(X86_HAVE_XSAVE_INTRIN) return _xgetbv(xcr); -#else +#elif defined(__GNUC__) uint32_t eax, edx; __asm__ ( ".byte 0x0f, 0x01, 0xd0" : "=a"(eax), "=d"(edx) : "c"(xcr)); return (uint64_t)(edx) << 32 | eax; +#else + /* When using this fallback, some of the faster code is disabled */ + return 0; #endif } diff --git a/configure b/configure index 90f5c708..05b71858 100755 --- a/configure +++ b/configure @@ -809,6 +809,61 @@ fi echo >> configure.log +# check for cpuid support: GNU extensions +cat > $test.c < +#include +static inline void cpuid_gnu(int info, unsigned int *eax, unsigned int *ebx, unsigned int *ecx, unsigned int *edx) { + *eax = *ebx = *ecx = *edx = 0; + __cpuid(info, *eax, *ebx, *ecx, *edx); +} + +int main(void) { + unsigned int eax, ebx, ecx, edx; + cpuid_gnu(0, &eax, &ebx, &ecx, &edx); + printf("%d\n", eax); + return eax; +} +EOF +if try $CC $CFLAGS -o $test $test.c $LDSHAREDLIBC; then + echo "Checking for GNU style __cpuid... Yes." | tee -a configure.log + CFLAGS="${CFLAGS} -DHAVE_CPUID_GNU" + SFLAGS="${SFLAGS} -DHAVE_CPUID_GNU" +else + echo "Checking for GNU style __cpuid... No." | tee -a configure.log +fi +echo >> configure.log + +# check for cpuid support: MSVC extensions +cat > $test.c < +#include +static inline void cpuid_ms(int info, unsigned int *eax, unsigned int *ebx, unsigned int *ecx, unsigned int *edx) { + unsigned int registers[4]; + __cpuid((int *)registers, info); + *eax = registers[0]; + *ebx = registers[1]; + *ecx = registers[2]; + *edx = registers[3]; +} + +int main(void) { + unsigned int eax, ebx, ecx, edx; + cpuid_ms(0, &eax, &ebx, &ecx, &edx); + printf("%d\n", eax); + return 0; +} +EOF +if try $CC $CFLAGS -o $test $test.c $LDSHAREDLIBC; then + echo "Checking for MS style __cpuid... Yes." | tee -a configure.log + CFLAGS="${CFLAGS} -DHAVE_CPUID_MS" + SFLAGS="${SFLAGS} -DHAVE_CPUID_MS" +else + echo "Checking for MS style __cpuid... No." | tee -a configure.log +fi +echo >> configure.log + + # check for strerror() for use by gz* functions cat > $test.c <