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) || defined(HAVE_GETAUXVAL) \ 93 || defined(HAVE_ELF_AUX_INFO) \ 94 || (defined(__APPLE__) && defined(HAVE_SYSCTLBYNAME)) 95 # define CRC_ARM64_RUNTIME_DETECTION 1 96 #endif 97 98 // ARM64 CRC32 instruction is only useful for CRC32. Currently, only 99 // little endian is supported since we were unable to test on a big 100 // endian machine. 101 #if defined(HAVE_ARM64_CRC32) && !defined(WORDS_BIGENDIAN) 102 // Allow ARM64 CRC32 instruction without a runtime check if 103 // __ARM_FEATURE_CRC32 is defined. GCC and Clang only define 104 // this if the proper compiler options are used. 105 # if defined(__ARM_FEATURE_CRC32) 106 # define CRC32_ARCH_OPTIMIZED 1 107 # define CRC32_ARM64 1 108 # elif defined(CRC_ARM64_RUNTIME_DETECTION) 109 # define CRC32_ARCH_OPTIMIZED 1 110 # define CRC32_ARM64 1 111 # define CRC32_GENERIC 1 112 # endif 113 #endif 114 115 116 // LoongArch 117 // 118 // Only 64-bit LoongArch is supported for now. No runtime detection 119 // is needed because the LoongArch specification says that the CRC32 120 // instructions are a part of the Basic Integer Instructions and 121 // they shall be implemented by 64-bit LoongArch implementations. 122 #ifdef HAVE_LOONGARCH_CRC32 123 # define CRC32_ARCH_OPTIMIZED 1 124 # define CRC32_LOONGARCH 1 125 #endif 126 127 128 // x86 and E2K 129 #if defined(HAVE_USABLE_CLMUL) 130 // If CLMUL is allowed unconditionally in the compiler options then 131 // the generic version and the tables can be omitted. Exceptions: 132 // 133 // - If 32-bit x86 assembly files are enabled then those are always 134 // built and runtime detection is used even if compiler flags 135 // were set to allow CLMUL unconditionally. 136 // 137 // - This doesn't work with MSVC as I don't know how to detect 138 // the features here. 139 // 140 # if (defined(__SSSE3__) && defined(__SSE4_1__) && defined(__PCLMUL__) \ 141 && !defined(HAVE_CRC_X86_ASM)) \ 142 || (defined(__e2k__) && __iset__ >= 6) 143 # define CRC32_ARCH_OPTIMIZED 1 144 # define CRC64_ARCH_OPTIMIZED 1 145 # define CRC_X86_CLMUL 1 146 # else 147 # define CRC32_GENERIC 1 148 # define CRC64_GENERIC 1 149 # define CRC32_ARCH_OPTIMIZED 1 150 # define CRC64_ARCH_OPTIMIZED 1 151 # define CRC_X86_CLMUL 1 152 # endif 153 #endif 154 155 156 // Fallback configuration 157 // 158 // For CRC32 use the generic slice-by-eight implementation if no optimized 159 // version is available. 160 #if !defined(CRC32_ARCH_OPTIMIZED) && !defined(CRC32_GENERIC) 161 # define CRC32_GENERIC 1 162 #endif 163 164 // For CRC64 use the generic slice-by-four implementation if no optimized 165 // version is available. 166 #if !defined(CRC64_ARCH_OPTIMIZED) && !defined(CRC64_GENERIC) 167 # define CRC64_GENERIC 1 168 #endif 169 170 #endif 171