1 // SPDX-License-Identifier: 0BSD 2 3 /////////////////////////////////////////////////////////////////////////////// 4 // 5 /// \file crc64.c 6 /// \brief CRC64 calculation 7 // 8 // Authors: Lasse Collin 9 // Ilya Kurdyukov 10 // 11 /////////////////////////////////////////////////////////////////////////////// 12 13 #include "check.h" 14 #include "crc_common.h" 15 16 #if defined(CRC_X86_CLMUL) 17 # define BUILDING_CRC64_CLMUL 18 # include "crc_x86_clmul.h" 19 #endif 20 21 22 #ifdef CRC64_GENERIC 23 24 ///////////////////////////////// 25 // Generic slice-by-four CRC64 // 26 ///////////////////////////////// 27 28 #ifdef WORDS_BIGENDIAN 29 # define A1(x) ((x) >> 56) 30 #else 31 # define A1 A 32 #endif 33 34 35 // See the comments in crc32_fast.c. They aren't duplicated here. 36 static uint64_t 37 crc64_generic(const uint8_t *buf, size_t size, uint64_t crc) 38 { 39 crc = ~crc; 40 41 #ifdef WORDS_BIGENDIAN 42 crc = bswap64(crc); 43 #endif 44 45 if (size > 4) { 46 while ((uintptr_t)(buf) & 3) { 47 crc = lzma_crc64_table[0][*buf++ ^ A1(crc)] ^ S8(crc); 48 --size; 49 } 50 51 const uint8_t *const limit = buf + (size & ~(size_t)(3)); 52 size &= (size_t)(3); 53 54 while (buf < limit) { 55 #ifdef WORDS_BIGENDIAN 56 const uint32_t tmp = (uint32_t)(crc >> 32) 57 ^ aligned_read32ne(buf); 58 #else 59 const uint32_t tmp = (uint32_t)crc 60 ^ aligned_read32ne(buf); 61 #endif 62 buf += 4; 63 64 crc = lzma_crc64_table[3][A(tmp)] 65 ^ lzma_crc64_table[2][B(tmp)] 66 ^ S32(crc) 67 ^ lzma_crc64_table[1][C(tmp)] 68 ^ lzma_crc64_table[0][D(tmp)]; 69 } 70 } 71 72 while (size-- != 0) 73 crc = lzma_crc64_table[0][*buf++ ^ A1(crc)] ^ S8(crc); 74 75 #ifdef WORDS_BIGENDIAN 76 crc = bswap64(crc); 77 #endif 78 79 return ~crc; 80 } 81 #endif 82 83 84 #if defined(CRC64_GENERIC) && defined(CRC64_ARCH_OPTIMIZED) 85 86 ////////////////////////// 87 // Function dispatching // 88 ////////////////////////// 89 90 // If both the generic and arch-optimized implementations are usable, then 91 // the function that is used is selected at runtime. See crc32_fast.c. 92 93 typedef uint64_t (*crc64_func_type)( 94 const uint8_t *buf, size_t size, uint64_t crc); 95 96 #if defined(CRC_USE_IFUNC) && defined(__clang__) 97 # pragma GCC diagnostic push 98 # pragma GCC diagnostic ignored "-Wunused-function" 99 #endif 100 101 static crc64_func_type 102 crc64_resolve(void) 103 { 104 return is_arch_extension_supported() 105 ? &crc64_arch_optimized : &crc64_generic; 106 } 107 108 #if defined(CRC_USE_IFUNC) && defined(__clang__) 109 # pragma GCC diagnostic pop 110 #endif 111 112 #ifndef CRC_USE_IFUNC 113 114 #ifdef HAVE_FUNC_ATTRIBUTE_CONSTRUCTOR 115 # define CRC64_SET_FUNC_ATTR __attribute__((__constructor__)) 116 static crc64_func_type crc64_func; 117 #else 118 # define CRC64_SET_FUNC_ATTR 119 static uint64_t crc64_dispatch(const uint8_t *buf, size_t size, uint64_t crc); 120 static crc64_func_type crc64_func = &crc64_dispatch; 121 #endif 122 123 124 CRC64_SET_FUNC_ATTR 125 static void 126 crc64_set_func(void) 127 { 128 crc64_func = crc64_resolve(); 129 return; 130 } 131 132 133 #ifndef HAVE_FUNC_ATTRIBUTE_CONSTRUCTOR 134 static uint64_t 135 crc64_dispatch(const uint8_t *buf, size_t size, uint64_t crc) 136 { 137 crc64_set_func(); 138 return crc64_func(buf, size, crc); 139 } 140 #endif 141 #endif 142 #endif 143 144 145 #ifdef CRC_USE_IFUNC 146 extern LZMA_API(uint64_t) 147 lzma_crc64(const uint8_t *buf, size_t size, uint64_t crc) 148 __attribute__((__ifunc__("crc64_resolve"))); 149 #else 150 extern LZMA_API(uint64_t) 151 lzma_crc64(const uint8_t *buf, size_t size, uint64_t crc) 152 { 153 #if defined(CRC64_GENERIC) && defined(CRC64_ARCH_OPTIMIZED) 154 155 #ifdef CRC_USE_GENERIC_FOR_SMALL_INPUTS 156 if (size <= 16) 157 return crc64_generic(buf, size, crc); 158 #endif 159 return crc64_func(buf, size, crc); 160 161 #elif defined(CRC64_ARCH_OPTIMIZED) 162 // If arch-optimized version is used unconditionally without runtime 163 // CPU detection then omitting the generic version and its 8 KiB 164 // lookup table makes the library smaller. 165 // 166 // FIXME: Lookup table isn't currently omitted on 32-bit x86, 167 // see crc64_table.c. 168 return crc64_arch_optimized(buf, size, crc); 169 170 #else 171 return crc64_generic(buf, size, crc); 172 #endif 173 } 174 #endif 175