]> git.ipfire.org Git - thirdparty/zlib-ng.git/commitdiff
Provide an inline asm fallback for the ARMv8 intrinsics
authorCameron Cawley <ccawley2011@gmail.com>
Thu, 29 Feb 2024 21:20:25 +0000 (21:20 +0000)
committerHans Kristian Rosbach <hk-github@circlestorm.org>
Wed, 12 Feb 2025 12:54:30 +0000 (13:54 +0100)
CMakeLists.txt
arch/arm/acle_intrins.h
cmake/detect-intrinsics.cmake
configure

index 64dd7ad46ed2c24c1ec2121e88049ec32999b893..35f75e44d1e442e2416d556cf26a227ee1e720f9 100644 (file)
@@ -713,12 +713,15 @@ if(WITH_OPTIM)
 
         if(WITH_ARMV8)
             check_armv8_compiler_flag()
-            if(HAVE_ARMV8_FLAG)
+            if(HAVE_ARMV8_INLINE_ASM OR HAVE_ARMV8_INTRIN)
                 add_definitions(-DARM_CRC32)
                 set(ARMV8_SRCS ${ARCHDIR}/crc32_armv8.c)
                 set_property(SOURCE ${ARMV8_SRCS} PROPERTY COMPILE_FLAGS "${ARMV8FLAG} ${NOLTOFLAG}")
                 list(APPEND ZLIB_ARCH_SRCS ${ARMV8_SRCS})
                 add_feature_info(ARMV8_CRC 1 "Support ARMv8 optimized CRC hash generation, using \"${ARMV8FLAG}\"")
+                if(HAVE_ARMV8_INTRIN)
+                    add_definitions(-DARM_CRC32_INTRIN)
+                endif()
             else()
                 set(WITH_ARMV8 OFF)
             endif()
index cc4faa9c26eb736104f750fb6fe5ee70559e4385..1545ef5757e49db474abf1cd3ac171a8cdaa33dd 100644 (file)
 #else
 #  define Z_TARGET_CRC
 #endif
+
+#if !defined(ARM_CRC32_INTRIN) && !defined(_MSC_VER)
+#ifdef __aarch64__
+static inline uint32_t __crc32b(uint32_t __a, uint8_t __b) {
+    uint32_t __c;
+    __asm__ __volatile__("crc32b %w0, %w1, %w2" : "=r" (__c) : "r"(__a), "r"(__b));
+    return __c;
+}
+
+static inline uint32_t __crc32h(uint32_t __a, uint16_t __b) {
+    uint32_t __c;
+    __asm__ __volatile__("crc32h %w0, %w1, %w2" : "=r" (__c) : "r"(__a), "r"(__b));
+    return __c;
+}
+
+static inline uint32_t __crc32w(uint32_t __a, uint32_t __b) {
+    uint32_t __c;
+    __asm__ __volatile__("crc32w %w0, %w1, %w2" : "=r" (__c) : "r"(__a), "r"(__b));
+    return __c;
+}
+
+static inline uint32_t __crc32d(uint32_t __a, uint64_t __b) {
+    uint32_t __c;
+    __asm__ __volatile__("crc32x %w0, %w1, %x2" : "=r" (__c) : "r"(__a), "r"(__b));
+    return __c;
+}
+#else
+static inline uint32_t __crc32b(uint32_t __a, uint8_t __b) {
+    uint32_t __c;
+    __asm__ __volatile__("crc32b %0, %1, %2" : "=r" (__c) : "r"(__a), "r"(__b));
+    return __c;
+}
+
+static inline uint32_t __crc32h(uint32_t __a, uint16_t __b) {
+    uint32_t __c;
+    __asm__ __volatile__("crc32h %0, %1, %2" : "=r" (__c) : "r"(__a), "r"(__b));
+    return __c;
+}
+
+static inline uint32_t __crc32w(uint32_t __a, uint32_t __b) {
+    uint32_t __c;
+    __asm__ __volatile__("crc32w %0, %1, %2" : "=r" (__c) : "r"(__a), "r"(__b));
+    return __c;
+}
+
+static inline uint32_t __crc32d(uint32_t __a, uint64_t __b) {
+    return __crc32w (__crc32w (__a, __b & 0xffffffffULL), __b >> 32);
+}
+#endif
+#endif
 #endif
 
 #ifdef ARM_SIMD
index e7498e27f4629dc788fb9ee47111a32fec524c8c..9ab351af23b3b0246ffba528e97a6434bef106bd 100644 (file)
@@ -15,8 +15,22 @@ macro(check_armv8_compiler_flag)
             endif()
         endif()
     endif()
-    # Check whether compiler supports ARMv8 CRC intrinsics
+    # Check whether compiler supports ARMv8 inline asm
     set(CMAKE_REQUIRED_FLAGS "${ARMV8FLAG} ${NATIVEFLAG} ${ZNOLTOFLAG}")
+    check_c_source_compiles(
+        "unsigned int f(unsigned int a, unsigned int b) {
+            unsigned int c;
+        #ifdef __aarch64__
+            __asm__ __volatile__ ( \"crc32w %w0, %w1, %w2\" : \"=r\" (c) : \"r\" (a), \"r\" (b));
+        #else
+            __asm__ __volatile__ ( \"crc32w %0, %1, %2\" : \"=r\" (c) : \"r\" (a), \"r\" (b));
+        #endif
+            return (int)c;
+        }
+        int main(void) { return f(1,2); }"
+        HAVE_ARMV8_INLINE_ASM
+    )
+    # Check whether compiler supports ARMv8 intrinsics
     check_c_source_compiles(
         "#if defined(_MSC_VER)
         #include <intrin.h>
@@ -27,7 +41,7 @@ macro(check_armv8_compiler_flag)
             return __crc32w(a, b);
         }
         int main(void) { return 0; }"
-        HAVE_ARMV8_FLAG
+        HAVE_ARMV8_INTRIN
     )
     set(CMAKE_REQUIRED_FLAGS)
 endmacro()
index a092e8eced6f9fce0717a29429e2589e7c444d92..c5b570d0289d63e0f83143df64f7d01ab22a42cd 100755 (executable)
--- a/configure
+++ b/configure
@@ -1121,7 +1121,7 @@ EOF
     fi
 }
 
-check_armv8_compiler_flag() {
+check_armv8_intrinsics() {
     # Check whether -march=armv8-a+crc works correctly
     cat > $test.c << EOF
 int main() { return 0; }
@@ -1139,7 +1139,28 @@ EOF
         fi
     fi
 
-    # Check whether compiler supports ARMv8 CRC intrinsics
+    # Check whether compiler supports ARMv8 inline asm
+    cat > $test.c << EOF
+unsigned int f(unsigned int a, unsigned int b) {
+    unsigned int c;
+#ifdef __aarch64__
+    __asm__ __volatile__("crc32w %w0, %w1, %w2" : "=r" (c) : "r"(a), "r"(b));
+#else
+    __asm__ __volatile__("crc32w %0, %1, %2" : "=r" (c) : "r"(a), "r"(b));
+#endif
+    return c;
+}
+int main(void) { return 0; }
+EOF
+    if try ${CC} ${CFLAGS} ${armv8flag} $test.c; then
+        echo "Checking for ARMv8 inline assembly ... Yes." | tee -a configure.log
+        HAVE_ARMV8_INLINE_ASM=1
+    else
+        echo "Checking for ARMv8 inline assembly ... No." | tee -a configure.log
+        HAVE_ARMV8_INLINE_ASM=0
+    fi
+
+    # Check whether compiler supports ARMv8 intrinsics
     cat > $test.c << EOF
 #include <arm_acle.h>
 unsigned int f(unsigned int a, unsigned int b) {
@@ -1147,12 +1168,12 @@ unsigned int f(unsigned int a, unsigned int b) {
 }
 int main(void) { return 0; }
 EOF
-    if try ${CC} ${CFLAGS} ${acleflag} $test.c; then
-        echo "Checking for ARMv8 CRC intrinsics ... Yes." | tee -a configure.log
-        ARMV8_AVAILABLE=1
+    if try ${CC} ${CFLAGS} ${armv8flag} $test.c; then
+        echo "Checking for ARMv8 intrinsics ... Yes." | tee -a configure.log
+        HAVE_ARMV8_INTRIN=1
     else
-        echo "Checking for ARMv8 CRC intrinsics ... No." | tee -a configure.log
-        ARMV8_AVAILABLE=0
+        echo "Checking for ARMv8 intrinsics ... No." | tee -a configure.log
+        HAVE_ARMV8_INTRIN=0
     fi
 }
 
@@ -1738,12 +1759,17 @@ EOF
             fi
 
             if test $buildarmv8 -eq 1; then
-                check_armv8_compiler_flag
+                check_armv8_intrinsics
 
-                if test $ARMV8_AVAILABLE -eq 1; then
+                if test $HAVE_ARMV8_INTRIN -eq 1 || test $HAVE_ARMV8_INLINE_ASM -eq 1; then
                     CFLAGS="${CFLAGS} -DARM_CRC32"
                     SFLAGS="${SFLAGS} -DARM_CRC32"
 
+                    if test $HAVE_ARMV8_INTRIN -eq 1; then
+                        CFLAGS="${CFLAGS} -DARM_CRC32_INTRIN"
+                        SFLAGS="${SFLAGS} -DARM_CRC32_INTRIN"
+                    fi
+
                     ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} crc32_armv8.o"
                     ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} crc32_armv8.lo"
                 fi