]> git.ipfire.org Git - thirdparty/zlib-ng.git/commitdiff
port: Use __cpuid only, when available.
authorDetlef Riekenberg <wine.dev@web.de>
Mon, 14 Apr 2025 23:59:47 +0000 (01:59 +0200)
committerHans Kristian Rosbach <hk-github@circlestorm.org>
Tue, 15 Apr 2025 12:08:46 +0000 (14:08 +0200)
Add a fallback, when __cpuid is not available

CMakeLists.txt
arch/x86/x86_features.c
configure

index 4a453ebec7880d2360f00d633381233e7078cc0a..df137738a764c989b63636ccb48c78ae4fe6ba6e 100644 (file)
@@ -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 <intrin.h>
+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
 #
index 9491a00730831fc8658cfb1afe5bde254c631398..806e99a6f62b02f5d07e3da853a083597662633b 100644 (file)
 #include "zbuild.h"
 #include "x86_features.h"
 
-#ifdef _MSC_VER
-#  include <intrin.h>
-#else
+
+#if defined(HAVE_CPUID_MS)
+#   include <intrin.h>
+#elif defined(HAVE_CPUID_GNU)
 // Newer versions of GCC and clang come with cpuid.h
 #  include <cpuid.h>
 #  ifdef X86_HAVE_XSAVE_INTRIN
@@ -27,7 +28,7 @@
 #include <string.h>
 
 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
 }
 
index 90f5c7086edacd3a05a28ad70e4b1619d94098c5..05b7185811b89b4076b905fc16c056f02501172f 100755 (executable)
--- a/configure
+++ b/configure
@@ -809,6 +809,61 @@ fi
 echo >> configure.log
 
 
+# check for cpuid support: GNU extensions
+cat > $test.c <<EOF
+#include <cpuid.h>
+#include <stdio.h>
+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 <<EOF
+#include <intrin.h>
+#include <stdio.h>
+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 <<EOF
 #include <string.h>