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 = byteswap64(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 = byteswap64(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 static crc64_func_type 97 crc64_resolve(void) 98 { 99 return is_arch_extension_supported() 100 ? &crc64_arch_optimized : &crc64_generic; 101 } 102 103 #ifdef HAVE_FUNC_ATTRIBUTE_CONSTRUCTOR 104 # define CRC64_SET_FUNC_ATTR __attribute__((__constructor__)) 105 static crc64_func_type crc64_func; 106 #else 107 # define CRC64_SET_FUNC_ATTR 108 static uint64_t crc64_dispatch(const uint8_t *buf, size_t size, uint64_t crc); 109 static crc64_func_type crc64_func = &crc64_dispatch; 110 #endif 111 112 113 CRC64_SET_FUNC_ATTR 114 static void 115 crc64_set_func(void) 116 { 117 crc64_func = crc64_resolve(); 118 return; 119 } 120 121 122 #ifndef HAVE_FUNC_ATTRIBUTE_CONSTRUCTOR 123 static uint64_t 124 crc64_dispatch(const uint8_t *buf, size_t size, uint64_t crc) 125 { 126 crc64_set_func(); 127 return crc64_func(buf, size, crc); 128 } 129 #endif 130 #endif 131 132 133 extern LZMA_API(uint64_t) 134 lzma_crc64(const uint8_t *buf, size_t size, uint64_t crc) 135 { 136 #if defined(CRC64_GENERIC) && defined(CRC64_ARCH_OPTIMIZED) 137 138 #ifdef CRC_USE_GENERIC_FOR_SMALL_INPUTS 139 if (size <= 16) 140 return crc64_generic(buf, size, crc); 141 #endif 142 return crc64_func(buf, size, crc); 143 144 #elif defined(CRC64_ARCH_OPTIMIZED) 145 // If arch-optimized version is used unconditionally without runtime 146 // CPU detection then omitting the generic version and its 8 KiB 147 // lookup table makes the library smaller. 148 // 149 // FIXME: Lookup table isn't currently omitted on 32-bit x86, 150 // see crc64_table.c. 151 return crc64_arch_optimized(buf, size, crc); 152 153 #else 154 return crc64_generic(buf, size, crc); 155 #endif 156 } 157