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()
#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
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>
return __crc32w(a, b);
}
int main(void) { return 0; }"
- HAVE_ARMV8_FLAG
+ HAVE_ARMV8_INTRIN
)
set(CMAKE_REQUIRED_FLAGS)
endmacro()
fi
}
-check_armv8_compiler_flag() {
+check_armv8_intrinsics() {
# Check whether -march=armv8-a+crc works correctly
cat > $test.c << EOF
int main() { return 0; }
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) {
}
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
}
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