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_GENERIC_FOR_SMALL_INPUTS 71 72 // ARM64 CRC32 instruction is only useful for CRC32. Currently, only 73 // little endian is supported since we were unable to test on a big 74 // endian machine. 75 // 76 // NOTE: Keep this and the next check in sync with the macro 77 // NO_CRC32_TABLE in crc32_table.c 78 #if defined(HAVE_ARM64_CRC32) && !defined(WORDS_BIGENDIAN) 79 // Allow ARM64 CRC32 instruction without a runtime check if 80 // __ARM_FEATURE_CRC32 is defined. GCC and Clang only define 81 // this if the proper compiler options are used. 82 # if defined(__ARM_FEATURE_CRC32) 83 # define CRC32_ARCH_OPTIMIZED 1 84 # define CRC32_ARM64 1 85 # elif defined(ARM64_RUNTIME_DETECTION) 86 # define CRC32_ARCH_OPTIMIZED 1 87 # define CRC32_ARM64 1 88 # define CRC32_GENERIC 1 89 # endif 90 #endif 91 92 #if defined(HAVE_USABLE_CLMUL) 93 // If CLMUL is allowed unconditionally in the compiler options then the 94 // generic version can be omitted. Note that this doesn't work with MSVC 95 // as I don't know how to detect the features here. 96 // 97 // NOTE: Keep this in sync with the NO_CRC32_TABLE macro in crc32_table.c 98 // and NO_CRC64_TABLE in crc64_table.c. 99 # if (defined(__SSSE3__) && defined(__SSE4_1__) && defined(__PCLMUL__)) \ 100 || (defined(__e2k__) && __iset__ >= 6) 101 # define CRC32_ARCH_OPTIMIZED 1 102 # define CRC64_ARCH_OPTIMIZED 1 103 # define CRC_X86_CLMUL 1 104 # else 105 # define CRC32_GENERIC 1 106 # define CRC64_GENERIC 1 107 # define CRC32_ARCH_OPTIMIZED 1 108 # define CRC64_ARCH_OPTIMIZED 1 109 # define CRC_X86_CLMUL 1 110 111 /* 112 // The generic code is much faster with 1-8-byte inputs and 113 // has similar performance up to 16 bytes at least in 114 // microbenchmarks (it depends on input buffer alignment 115 // too). If both versions are built, this #define will use 116 // the generic version for inputs up to 16 bytes and CLMUL 117 // for bigger inputs. It saves a little in code size since 118 // the special cases for 0-16-byte inputs will be omitted 119 // from the CLMUL code. 120 # define CRC_USE_GENERIC_FOR_SMALL_INPUTS 1 121 */ 122 # endif 123 #endif 124 125 // For CRC32 use the generic slice-by-eight implementation if no optimized 126 // version is available. 127 #if !defined(CRC32_ARCH_OPTIMIZED) && !defined(CRC32_GENERIC) 128 # define CRC32_GENERIC 1 129 #endif 130 131 // For CRC64 use the generic slice-by-four implementation if no optimized 132 // version is available. 133 #if !defined(CRC64_ARCH_OPTIMIZED) && !defined(CRC64_GENERIC) 134 # define CRC64_GENERIC 1 135 #endif 136 137 #endif 138