1 // SPDX-License-Identifier: 0BSD 2 3 /////////////////////////////////////////////////////////////////////////////// 4 // 5 /// \file crc_common.h 6 /// \brief Macros and declarations for CRC32 and CRC64 7 // 8 // Authors: Lasse Collin 9 // Ilya Kurdyukov 10 // Jia Tan 11 // 12 /////////////////////////////////////////////////////////////////////////////// 13 14 #ifndef LZMA_CRC_COMMON_H 15 #define LZMA_CRC_COMMON_H 16 17 #include "common.h" 18 19 20 ///////////// 21 // Generic // 22 ///////////// 23 24 #ifdef WORDS_BIGENDIAN 25 # define A(x) ((x) >> 24) 26 # define B(x) (((x) >> 16) & 0xFF) 27 # define C(x) (((x) >> 8) & 0xFF) 28 # define D(x) ((x) & 0xFF) 29 30 # define S8(x) ((x) << 8) 31 # define S32(x) ((x) << 32) 32 33 #else 34 # define A(x) ((x) & 0xFF) 35 # define B(x) (((x) >> 8) & 0xFF) 36 # define C(x) (((x) >> 16) & 0xFF) 37 # define D(x) ((x) >> 24) 38 39 # define S8(x) ((x) >> 8) 40 # define S32(x) ((x) >> 32) 41 #endif 42 43 44 /// lzma_crc32_table[0] is needed by LZ encoder so we need to keep 45 /// the array two-dimensional. 46 #ifdef HAVE_SMALL 47 lzma_attr_visibility_hidden 48 extern uint32_t lzma_crc32_table[1][256]; 49 50 extern void lzma_crc32_init(void); 51 52 #else 53 54 lzma_attr_visibility_hidden 55 extern const uint32_t lzma_crc32_table[8][256]; 56 57 lzma_attr_visibility_hidden 58 extern const uint64_t lzma_crc64_table[4][256]; 59 #endif 60 61 62 /////////////////// 63 // Configuration // 64 /////////////////// 65 66 // NOTE: This config isn't used if HAVE_SMALL is defined! 67 68 // These are defined if the generic slicing-by-n implementations and their 69 // lookup tables are built. 70 #undef CRC32_GENERIC 71 #undef CRC64_GENERIC 72 73 // These are defined if an arch-specific version is built. If both this 74 // and matching _GENERIC is defined then runtime detection must be used. 75 #undef CRC32_ARCH_OPTIMIZED 76 #undef CRC64_ARCH_OPTIMIZED 77 78 // The x86 CLMUL is used for both CRC32 and CRC64. 79 #undef CRC_X86_CLMUL 80 81 // Many ARM64 processor have CRC32 instructions. 82 // CRC64 could be done with CLMUL but it's not implemented yet. 83 #undef CRC32_ARM64 84 85 // 64-bit LoongArch has CRC32 instructions. 86 #undef CRC32_LOONGARCH 87 88 89 // ARM64 90 // 91 // Keep this in sync with changes to crc32_arm64.h 92 #if defined(_WIN32) \ 93 || (defined(HAVE_GETAUXVAL) && defined(HAVE_HWCAP_CRC32)) \ 94 || defined(HAVE_ELF_AUX_INFO) \ 95 || (defined(__APPLE__) && defined(HAVE_SYSCTLBYNAME)) 96 # define CRC_ARM64_RUNTIME_DETECTION 1 97 #endif 98 99 // ARM64 CRC32 instruction is only useful for CRC32. Currently, only 100 // little endian is supported since we were unable to test on a big 101 // endian machine. 102 #if defined(HAVE_ARM64_CRC32) && !defined(WORDS_BIGENDIAN) 103 // Allow ARM64 CRC32 instruction without a runtime check if 104 // __ARM_FEATURE_CRC32 is defined. GCC and Clang only define 105 // this if the proper compiler options are used. 106 # if defined(__ARM_FEATURE_CRC32) 107 # define CRC32_ARCH_OPTIMIZED 1 108 # define CRC32_ARM64 1 109 # elif defined(CRC_ARM64_RUNTIME_DETECTION) 110 # define CRC32_ARCH_OPTIMIZED 1 111 # define CRC32_ARM64 1 112 # define CRC32_GENERIC 1 113 # endif 114 #endif 115 116 117 // LoongArch 118 // 119 // Only 64-bit LoongArch is supported for now. No runtime detection 120 // is needed because the LoongArch specification says that the CRC32 121 // instructions are a part of the Basic Integer Instructions and 122 // they shall be implemented by 64-bit LoongArch implementations. 123 #ifdef HAVE_LOONGARCH_CRC32 124 # define CRC32_ARCH_OPTIMIZED 1 125 # define CRC32_LOONGARCH 1 126 #endif 127 128 129 // x86 and E2K 130 #if defined(HAVE_USABLE_CLMUL) 131 // If CLMUL is allowed unconditionally in the compiler options then 132 // the generic version and the tables can be omitted. Exceptions: 133 // 134 // - If 32-bit x86 assembly files are enabled then those are always 135 // built and runtime detection is used even if compiler flags 136 // were set to allow CLMUL unconditionally. 137 // 138 // - The unconditional use doesn't work with MSVC as I don't know 139 // how to detect the features here. 140 // 141 // Don't enable CLMUL at all on old MSVC that targets 32-bit x86. 142 // There seems to be a compiler bug that produces broken code 143 // in optimized (Release) builds. It results in crashing tests. 144 // It is known that VS 2019 16.11 (MSVC 19.29.30158) is broken 145 // and that VS 2022 17.13 (MSVC 19.43.34808) works. 146 # if defined(_MSC_FULL_VER) && _MSC_FULL_VER < 194334808 \ 147 && !defined(__INTEL_COMPILER) && !defined(__clang__) \ 148 && defined(_M_IX86) 149 // Old MSVC targeting 32-bit x86: Don't enable CLMUL at all. 150 # elif (defined(__SSSE3__) && defined(__SSE4_1__) \ 151 && defined(__PCLMUL__) \ 152 && !defined(HAVE_CRC_X86_ASM)) \ 153 || (defined(__e2k__) && __iset__ >= 6) 154 # define CRC32_ARCH_OPTIMIZED 1 155 # define CRC64_ARCH_OPTIMIZED 1 156 # define CRC_X86_CLMUL 1 157 # else 158 # define CRC32_GENERIC 1 159 # define CRC64_GENERIC 1 160 # define CRC32_ARCH_OPTIMIZED 1 161 # define CRC64_ARCH_OPTIMIZED 1 162 # define CRC_X86_CLMUL 1 163 # endif 164 #endif 165 166 167 // Fallback configuration 168 // 169 // For CRC32 use the generic slice-by-eight implementation if no optimized 170 // version is available. 171 #if !defined(CRC32_ARCH_OPTIMIZED) && !defined(CRC32_GENERIC) 172 # define CRC32_GENERIC 1 173 #endif 174 175 // For CRC64 use the generic slice-by-four implementation if no optimized 176 // version is available. 177 #if !defined(CRC64_ARCH_OPTIMIZED) && !defined(CRC64_GENERIC) 178 # define CRC64_GENERIC 1 179 #endif 180 181 #endif 182