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