1*3b35e7eeSXin LI // SPDX-License-Identifier: 0BSD 2*3b35e7eeSXin LI 3*3b35e7eeSXin LI /////////////////////////////////////////////////////////////////////////////// 4*3b35e7eeSXin LI // 5*3b35e7eeSXin LI /// \file crc_common.h 6*3b35e7eeSXin LI /// \brief Some functions and macros for CRC32 and CRC64 7*3b35e7eeSXin LI // 8*3b35e7eeSXin LI // Authors: Lasse Collin 9*3b35e7eeSXin LI // Ilya Kurdyukov 10*3b35e7eeSXin LI // Hans Jansen 11*3b35e7eeSXin LI // Jia Tan 12*3b35e7eeSXin LI // 13*3b35e7eeSXin LI /////////////////////////////////////////////////////////////////////////////// 14*3b35e7eeSXin LI 15*3b35e7eeSXin LI #ifndef LZMA_CRC_COMMON_H 16*3b35e7eeSXin LI #define LZMA_CRC_COMMON_H 17*3b35e7eeSXin LI 18*3b35e7eeSXin LI #include "common.h" 19*3b35e7eeSXin LI 20*3b35e7eeSXin LI 21*3b35e7eeSXin LI #ifdef WORDS_BIGENDIAN 22*3b35e7eeSXin LI # define A(x) ((x) >> 24) 23*3b35e7eeSXin LI # define B(x) (((x) >> 16) & 0xFF) 24*3b35e7eeSXin LI # define C(x) (((x) >> 8) & 0xFF) 25*3b35e7eeSXin LI # define D(x) ((x) & 0xFF) 26*3b35e7eeSXin LI 27*3b35e7eeSXin LI # define S8(x) ((x) << 8) 28*3b35e7eeSXin LI # define S32(x) ((x) << 32) 29*3b35e7eeSXin LI 30*3b35e7eeSXin LI #else 31*3b35e7eeSXin LI # define A(x) ((x) & 0xFF) 32*3b35e7eeSXin LI # define B(x) (((x) >> 8) & 0xFF) 33*3b35e7eeSXin LI # define C(x) (((x) >> 16) & 0xFF) 34*3b35e7eeSXin LI # define D(x) ((x) >> 24) 35*3b35e7eeSXin LI 36*3b35e7eeSXin LI # define S8(x) ((x) >> 8) 37*3b35e7eeSXin LI # define S32(x) ((x) >> 32) 38*3b35e7eeSXin LI #endif 39*3b35e7eeSXin LI 40*3b35e7eeSXin LI 41*3b35e7eeSXin LI // CRC CLMUL code needs this because accessing input buffers that aren't 42*3b35e7eeSXin LI // aligned to the vector size will inherently trip the address sanitizer. 43*3b35e7eeSXin LI #if lzma_has_attribute(__no_sanitize_address__) 44*3b35e7eeSXin LI # define crc_attr_no_sanitize_address \ 45*3b35e7eeSXin LI __attribute__((__no_sanitize_address__)) 46*3b35e7eeSXin LI #else 47*3b35e7eeSXin LI # define crc_attr_no_sanitize_address 48*3b35e7eeSXin LI #endif 49*3b35e7eeSXin LI 50*3b35e7eeSXin LI // Keep this in sync with changes to crc32_arm64.h 51*3b35e7eeSXin LI #if defined(_WIN32) || defined(HAVE_GETAUXVAL) \ 52*3b35e7eeSXin LI || defined(HAVE_ELF_AUX_INFO) \ 53*3b35e7eeSXin LI || (defined(__APPLE__) && defined(HAVE_SYSCTLBYNAME)) 54*3b35e7eeSXin LI # define ARM64_RUNTIME_DETECTION 1 55*3b35e7eeSXin LI #endif 56*3b35e7eeSXin LI 57*3b35e7eeSXin LI 58*3b35e7eeSXin LI #undef CRC32_GENERIC 59*3b35e7eeSXin LI #undef CRC64_GENERIC 60*3b35e7eeSXin LI 61*3b35e7eeSXin LI #undef CRC32_ARCH_OPTIMIZED 62*3b35e7eeSXin LI #undef CRC64_ARCH_OPTIMIZED 63*3b35e7eeSXin LI 64*3b35e7eeSXin LI // The x86 CLMUL is used for both CRC32 and CRC64. 65*3b35e7eeSXin LI #undef CRC_X86_CLMUL 66*3b35e7eeSXin LI 67*3b35e7eeSXin LI #undef CRC32_ARM64 68*3b35e7eeSXin LI #undef CRC64_ARM64_CLMUL 69*3b35e7eeSXin LI 70*3b35e7eeSXin LI #undef CRC_USE_GENERIC_FOR_SMALL_INPUTS 71*3b35e7eeSXin LI 72*3b35e7eeSXin LI // ARM64 CRC32 instruction is only useful for CRC32. Currently, only 73*3b35e7eeSXin LI // little endian is supported since we were unable to test on a big 74*3b35e7eeSXin LI // endian machine. 75*3b35e7eeSXin LI // 76*3b35e7eeSXin LI // NOTE: Keep this and the next check in sync with the macro 77*3b35e7eeSXin LI // NO_CRC32_TABLE in crc32_table.c 78*3b35e7eeSXin LI #if defined(HAVE_ARM64_CRC32) && !defined(WORDS_BIGENDIAN) 79*3b35e7eeSXin LI // Allow ARM64 CRC32 instruction without a runtime check if 80*3b35e7eeSXin LI // __ARM_FEATURE_CRC32 is defined. GCC and Clang only define this if the 81*3b35e7eeSXin LI // proper compiler options are used. 82*3b35e7eeSXin LI # if defined(__ARM_FEATURE_CRC32) 83*3b35e7eeSXin LI # define CRC32_ARCH_OPTIMIZED 1 84*3b35e7eeSXin LI # define CRC32_ARM64 1 85*3b35e7eeSXin LI # elif defined(ARM64_RUNTIME_DETECTION) 86*3b35e7eeSXin LI # define CRC32_ARCH_OPTIMIZED 1 87*3b35e7eeSXin LI # define CRC32_ARM64 1 88*3b35e7eeSXin LI # define CRC32_GENERIC 1 89*3b35e7eeSXin LI # endif 90*3b35e7eeSXin LI #endif 91*3b35e7eeSXin LI 92*3b35e7eeSXin LI #if defined(HAVE_USABLE_CLMUL) 93*3b35e7eeSXin LI // If CLMUL is allowed unconditionally in the compiler options then the 94*3b35e7eeSXin LI // generic version can be omitted. Note that this doesn't work with MSVC 95*3b35e7eeSXin LI // as I don't know how to detect the features here. 96*3b35e7eeSXin LI // 97*3b35e7eeSXin LI // NOTE: Keep this in sync with the NO_CRC32_TABLE macro in crc32_table.c 98*3b35e7eeSXin LI // and NO_CRC64_TABLE in crc64_table.c. 99*3b35e7eeSXin LI # if (defined(__SSSE3__) && defined(__SSE4_1__) && defined(__PCLMUL__)) \ 100*3b35e7eeSXin LI || (defined(__e2k__) && __iset__ >= 6) 101*3b35e7eeSXin LI # define CRC32_ARCH_OPTIMIZED 1 102*3b35e7eeSXin LI # define CRC64_ARCH_OPTIMIZED 1 103*3b35e7eeSXin LI # define CRC_X86_CLMUL 1 104*3b35e7eeSXin LI # else 105*3b35e7eeSXin LI # define CRC32_GENERIC 1 106*3b35e7eeSXin LI # define CRC64_GENERIC 1 107*3b35e7eeSXin LI # define CRC32_ARCH_OPTIMIZED 1 108*3b35e7eeSXin LI # define CRC64_ARCH_OPTIMIZED 1 109*3b35e7eeSXin LI # define CRC_X86_CLMUL 1 110*3b35e7eeSXin LI 111*3b35e7eeSXin LI /* 112*3b35e7eeSXin LI // The generic code is much faster with 1-8-byte inputs and 113*3b35e7eeSXin LI // has similar performance up to 16 bytes at least in 114*3b35e7eeSXin LI // microbenchmarks (it depends on input buffer alignment 115*3b35e7eeSXin LI // too). If both versions are built, this #define will use 116*3b35e7eeSXin LI // the generic version for inputs up to 16 bytes and CLMUL 117*3b35e7eeSXin LI // for bigger inputs. It saves a little in code size since 118*3b35e7eeSXin LI // the special cases for 0-16-byte inputs will be omitted 119*3b35e7eeSXin LI // from the CLMUL code. 120*3b35e7eeSXin LI # define CRC_USE_GENERIC_FOR_SMALL_INPUTS 1 121*3b35e7eeSXin LI */ 122*3b35e7eeSXin LI # endif 123*3b35e7eeSXin LI #endif 124*3b35e7eeSXin LI 125*3b35e7eeSXin LI // For CRC32 use the generic slice-by-eight implementation if no optimized 126*3b35e7eeSXin LI // version is available. 127*3b35e7eeSXin LI #if !defined(CRC32_ARCH_OPTIMIZED) && !defined(CRC32_GENERIC) 128*3b35e7eeSXin LI # define CRC32_GENERIC 1 129*3b35e7eeSXin LI #endif 130*3b35e7eeSXin LI 131*3b35e7eeSXin LI // For CRC64 use the generic slice-by-four implementation if no optimized 132*3b35e7eeSXin LI // version is available. 133*3b35e7eeSXin LI #if !defined(CRC64_ARCH_OPTIMIZED) && !defined(CRC64_GENERIC) 134*3b35e7eeSXin LI # define CRC64_GENERIC 1 135*3b35e7eeSXin LI #endif 136*3b35e7eeSXin LI 137*3b35e7eeSXin LI #endif 138