xref: /aosp_15_r20/external/lzma/C/7zCrc.c (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
1 /* 7zCrc.c -- CRC32 calculation and init
2 2024-03-01 : Igor Pavlov : Public domain */
3 
4 #include "Precomp.h"
5 
6 #include "7zCrc.h"
7 #include "CpuArch.h"
8 
9 // for debug:
10 // #define __ARM_FEATURE_CRC32 1
11 
12 #ifdef __ARM_FEATURE_CRC32
13 // #pragma message("__ARM_FEATURE_CRC32")
14 #define Z7_CRC_HW_FORCE
15 #endif
16 
17 // #define Z7_CRC_DEBUG_BE
18 #ifdef Z7_CRC_DEBUG_BE
19 #undef MY_CPU_LE
20 #define MY_CPU_BE
21 #endif
22 
23 #ifdef Z7_CRC_HW_FORCE
24   #define Z7_CRC_NUM_TABLES_USE  1
25 #else
26 #ifdef Z7_CRC_NUM_TABLES
27   #define Z7_CRC_NUM_TABLES_USE  Z7_CRC_NUM_TABLES
28 #else
29   #define Z7_CRC_NUM_TABLES_USE  12
30 #endif
31 #endif
32 
33 #if Z7_CRC_NUM_TABLES_USE < 1
34   #error Stop_Compiling_Bad_Z7_CRC_NUM_TABLES
35 #endif
36 
37 #if defined(MY_CPU_LE) || (Z7_CRC_NUM_TABLES_USE == 1)
38   #define Z7_CRC_NUM_TABLES_TOTAL  Z7_CRC_NUM_TABLES_USE
39 #else
40   #define Z7_CRC_NUM_TABLES_TOTAL  (Z7_CRC_NUM_TABLES_USE + 1)
41 #endif
42 
43 #ifndef Z7_CRC_HW_FORCE
44 
45 #if Z7_CRC_NUM_TABLES_USE == 1 \
46    || (!defined(MY_CPU_LE) && !defined(MY_CPU_BE))
47 #define CRC_UPDATE_BYTE_2(crc, b)   (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))
48 #define Z7_CRC_UPDATE_T1_FUNC_NAME  CrcUpdateGT1
Z7_CRC_UPDATE_T1_FUNC_NAME(UInt32 v,const void * data,size_t size)49 static UInt32 Z7_FASTCALL Z7_CRC_UPDATE_T1_FUNC_NAME(UInt32 v, const void *data, size_t size)
50 {
51   const UInt32 *table = g_CrcTable;
52   const Byte *p = (const Byte *)data;
53   const Byte *lim = p + size;
54   for (; p != lim; p++)
55     v = CRC_UPDATE_BYTE_2(v, *p);
56   return v;
57 }
58 #endif
59 
60 
61 #if Z7_CRC_NUM_TABLES_USE != 1
62 #ifndef MY_CPU_BE
63   #define FUNC_NAME_LE_2(s)   CrcUpdateT ## s
64   #define FUNC_NAME_LE_1(s)   FUNC_NAME_LE_2(s)
65   #define FUNC_NAME_LE        FUNC_NAME_LE_1(Z7_CRC_NUM_TABLES_USE)
66   UInt32 Z7_FASTCALL FUNC_NAME_LE (UInt32 v, const void *data, size_t size, const UInt32 *table);
67 #endif
68 #ifndef MY_CPU_LE
69   #define FUNC_NAME_BE_2(s)   CrcUpdateT1_BeT ## s
70   #define FUNC_NAME_BE_1(s)   FUNC_NAME_BE_2(s)
71   #define FUNC_NAME_BE        FUNC_NAME_BE_1(Z7_CRC_NUM_TABLES_USE)
72   UInt32 Z7_FASTCALL FUNC_NAME_BE (UInt32 v, const void *data, size_t size, const UInt32 *table);
73 #endif
74 #endif
75 
76 #endif // Z7_CRC_HW_FORCE
77 
78 /* ---------- hardware CRC ---------- */
79 
80 #ifdef MY_CPU_LE
81 
82 #if defined(MY_CPU_ARM_OR_ARM64)
83 // #pragma message("ARM*")
84 
85   #if (defined(__clang__) && (__clang_major__ >= 3)) \
86      || defined(__GNUC__) && (__GNUC__ >= 6) && defined(MY_CPU_ARM64) \
87      || defined(__GNUC__) && (__GNUC__ >= 8)
88       #if !defined(__ARM_FEATURE_CRC32)
89 //        #pragma message("!defined(__ARM_FEATURE_CRC32)")
90 Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER
91         #define __ARM_FEATURE_CRC32 1
92 Z7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER
93         #define Z7_ARM_FEATURE_CRC32_WAS_SET
94         #if defined(__clang__)
95           #if defined(MY_CPU_ARM64)
96             #define ATTRIB_CRC __attribute__((__target__("crc")))
97           #else
98             #define ATTRIB_CRC __attribute__((__target__("armv8-a,crc")))
99           #endif
100         #else
101           #if defined(MY_CPU_ARM64)
102 #if !defined(Z7_GCC_VERSION) || (Z7_GCC_VERSION >= 60000)
103             #define ATTRIB_CRC __attribute__((__target__("+crc")))
104 #endif
105           #else
106 #if !defined(Z7_GCC_VERSION) || (__GNUC__  >= 8)
107 #if defined(__ARM_FP) && __GNUC__ >= 8
108 // for -mfloat-abi=hard: similar to <arm_acle.h>
109             #define ATTRIB_CRC __attribute__((__target__("arch=armv8-a+crc+simd")))
110 #else
111             #define ATTRIB_CRC __attribute__((__target__("arch=armv8-a+crc")))
112 #endif
113 #endif
114           #endif
115         #endif
116       #endif
117       #if defined(__ARM_FEATURE_CRC32)
118       // #pragma message("<arm_acle.h>")
119 /*
120 arm_acle.h (GGC):
121     before Nov 17, 2017:
122 #ifdef __ARM_FEATURE_CRC32
123 
124     Nov 17, 2017: gcc10.0  (gcc 9.2.0) checked"
125 #if __ARM_ARCH >= 8
126 #pragma GCC target ("arch=armv8-a+crc")
127 
128     Aug 22, 2019: GCC 8.4?, 9.2.1, 10.1:
129 #ifdef __ARM_FEATURE_CRC32
130 #ifdef __ARM_FP
131 #pragma GCC target ("arch=armv8-a+crc+simd")
132 #else
133 #pragma GCC target ("arch=armv8-a+crc")
134 #endif
135 */
136 #if defined(__ARM_ARCH) && __ARM_ARCH < 8
137 #if defined(Z7_GCC_VERSION) && (__GNUC__ ==   8) && (Z7_GCC_VERSION <  80400) \
138  || defined(Z7_GCC_VERSION) && (__GNUC__ ==   9) && (Z7_GCC_VERSION <  90201) \
139  || defined(Z7_GCC_VERSION) && (__GNUC__ ==  10) && (Z7_GCC_VERSION < 100100)
140 Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER
141 // #pragma message("#define __ARM_ARCH 8")
142 #undef  __ARM_ARCH
143 #define __ARM_ARCH 8
144 Z7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER
145 #endif
146 #endif
147         #define Z7_CRC_HW_USE
148         #include <arm_acle.h>
149       #endif
150   #elif defined(_MSC_VER)
151     #if defined(MY_CPU_ARM64)
152     #if (_MSC_VER >= 1910)
153     #ifdef __clang__
154        // #define Z7_CRC_HW_USE
155        // #include <arm_acle.h>
156     #else
157        #define Z7_CRC_HW_USE
158        #include <intrin.h>
159     #endif
160     #endif
161     #endif
162   #endif
163 
164 #else // non-ARM*
165 
166 // #define Z7_CRC_HW_USE // for debug : we can test HW-branch of code
167 #ifdef Z7_CRC_HW_USE
168 #include "7zCrcEmu.h"
169 #endif
170 
171 #endif // non-ARM*
172 
173 
174 
175 #if defined(Z7_CRC_HW_USE)
176 
177 // #pragma message("USE ARM HW CRC")
178 
179 #ifdef MY_CPU_64BIT
180   #define CRC_HW_WORD_TYPE  UInt64
181   #define CRC_HW_WORD_FUNC  __crc32d
182 #else
183   #define CRC_HW_WORD_TYPE  UInt32
184   #define CRC_HW_WORD_FUNC  __crc32w
185 #endif
186 
187 #define CRC_HW_UNROLL_BYTES (sizeof(CRC_HW_WORD_TYPE) * 4)
188 
189 #ifdef ATTRIB_CRC
190   ATTRIB_CRC
191 #endif
192 Z7_NO_INLINE
193 #ifdef Z7_CRC_HW_FORCE
CrcUpdate(UInt32 v,const void * data,size_t size)194          UInt32 Z7_FASTCALL CrcUpdate
195 #else
196   static UInt32 Z7_FASTCALL CrcUpdate_HW
197 #endif
198     (UInt32 v, const void *data, size_t size)
199 {
200   const Byte *p = (const Byte *)data;
201   for (; size != 0 && ((unsigned)(ptrdiff_t)p & (CRC_HW_UNROLL_BYTES - 1)) != 0; size--)
202     v = __crc32b(v, *p++);
203   if (size >= CRC_HW_UNROLL_BYTES)
204   {
205     const Byte *lim = p + size;
206     size &= CRC_HW_UNROLL_BYTES - 1;
207     lim -= size;
208     do
209     {
210       v = CRC_HW_WORD_FUNC(v, *(const CRC_HW_WORD_TYPE *)(const void *)(p));
211       v = CRC_HW_WORD_FUNC(v, *(const CRC_HW_WORD_TYPE *)(const void *)(p + sizeof(CRC_HW_WORD_TYPE)));
212       p += 2 * sizeof(CRC_HW_WORD_TYPE);
213       v = CRC_HW_WORD_FUNC(v, *(const CRC_HW_WORD_TYPE *)(const void *)(p));
214       v = CRC_HW_WORD_FUNC(v, *(const CRC_HW_WORD_TYPE *)(const void *)(p + sizeof(CRC_HW_WORD_TYPE)));
215       p += 2 * sizeof(CRC_HW_WORD_TYPE);
216     }
217     while (p != lim);
218   }
219 
220   for (; size != 0; size--)
221     v = __crc32b(v, *p++);
222 
223   return v;
224 }
225 
226 #ifdef Z7_ARM_FEATURE_CRC32_WAS_SET
227 Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER
228 #undef __ARM_FEATURE_CRC32
229 Z7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER
230 #undef Z7_ARM_FEATURE_CRC32_WAS_SET
231 #endif
232 
233 #endif // defined(Z7_CRC_HW_USE)
234 #endif // MY_CPU_LE
235 
236 
237 
238 #ifndef Z7_CRC_HW_FORCE
239 
240 #if defined(Z7_CRC_HW_USE) || defined(Z7_CRC_UPDATE_T1_FUNC_NAME)
241 /*
242 typedef UInt32 (Z7_FASTCALL *Z7_CRC_UPDATE_WITH_TABLE_FUNC)
243     (UInt32 v, const void *data, size_t size, const UInt32 *table);
244 Z7_CRC_UPDATE_WITH_TABLE_FUNC g_CrcUpdate;
245 */
246 static unsigned g_Crc_Algo;
247 #if (!defined(MY_CPU_LE) && !defined(MY_CPU_BE))
248 static unsigned g_Crc_Be;
249 #endif
250 #endif // defined(Z7_CRC_HW_USE) || defined(Z7_CRC_UPDATE_T1_FUNC_NAME)
251 
252 
253 
254 Z7_NO_INLINE
255 #ifdef Z7_CRC_HW_USE
CrcUpdate_Base(UInt32 crc,const void * data,size_t size)256   static UInt32 Z7_FASTCALL CrcUpdate_Base
257 #else
258          UInt32 Z7_FASTCALL CrcUpdate
259 #endif
260     (UInt32 crc, const void *data, size_t size)
261 {
262 #if Z7_CRC_NUM_TABLES_USE == 1
263     return Z7_CRC_UPDATE_T1_FUNC_NAME(crc, data, size);
264 #else // Z7_CRC_NUM_TABLES_USE != 1
265 #ifdef Z7_CRC_UPDATE_T1_FUNC_NAME
266   if (g_Crc_Algo == 1)
267     return Z7_CRC_UPDATE_T1_FUNC_NAME(crc, data, size);
268 #endif
269 
270 #ifdef MY_CPU_LE
271     return FUNC_NAME_LE(crc, data, size, g_CrcTable);
272 #elif defined(MY_CPU_BE)
273     return FUNC_NAME_BE(crc, data, size, g_CrcTable);
274 #else
275   if (g_Crc_Be)
276     return FUNC_NAME_BE(crc, data, size, g_CrcTable);
277   else
278     return FUNC_NAME_LE(crc, data, size, g_CrcTable);
279 #endif
280 #endif // Z7_CRC_NUM_TABLES_USE != 1
281 }
282 
283 
284 #ifdef Z7_CRC_HW_USE
285 Z7_NO_INLINE
CrcUpdate(UInt32 crc,const void * data,size_t size)286 UInt32 Z7_FASTCALL CrcUpdate(UInt32 crc, const void *data, size_t size)
287 {
288   if (g_Crc_Algo == 0)
289     return CrcUpdate_HW(crc, data, size);
290   return CrcUpdate_Base(crc, data, size);
291 }
292 #endif
293 
294 #endif // !defined(Z7_CRC_HW_FORCE)
295 
296 
297 
CrcCalc(const void * data,size_t size)298 UInt32 Z7_FASTCALL CrcCalc(const void *data, size_t size)
299 {
300   return CrcUpdate(CRC_INIT_VAL, data, size) ^ CRC_INIT_VAL;
301 }
302 
303 
304 MY_ALIGN(64)
305 UInt32 g_CrcTable[256 * Z7_CRC_NUM_TABLES_TOTAL];
306 
307 
CrcGenerateTable(void)308 void Z7_FASTCALL CrcGenerateTable(void)
309 {
310   UInt32 i;
311   for (i = 0; i < 256; i++)
312   {
313 #if defined(Z7_CRC_HW_FORCE)
314     g_CrcTable[i] = __crc32b(i, 0);
315 #else
316     #define kCrcPoly 0xEDB88320
317     UInt32 r = i;
318     unsigned j;
319     for (j = 0; j < 8; j++)
320       r = (r >> 1) ^ (kCrcPoly & ((UInt32)0 - (r & 1)));
321     g_CrcTable[i] = r;
322 #endif
323   }
324   for (i = 256; i < 256 * Z7_CRC_NUM_TABLES_USE; i++)
325   {
326     const UInt32 r = g_CrcTable[(size_t)i - 256];
327     g_CrcTable[i] = g_CrcTable[r & 0xFF] ^ (r >> 8);
328   }
329 
330 #if !defined(Z7_CRC_HW_FORCE) && \
331     (defined(Z7_CRC_HW_USE) || defined(Z7_CRC_UPDATE_T1_FUNC_NAME) || defined(MY_CPU_BE))
332 
333 #if Z7_CRC_NUM_TABLES_USE <= 1
334     g_Crc_Algo = 1;
335 #else // Z7_CRC_NUM_TABLES_USE <= 1
336 
337 #if defined(MY_CPU_LE)
338     g_Crc_Algo = Z7_CRC_NUM_TABLES_USE;
339 #else // !defined(MY_CPU_LE)
340   {
341 #ifndef MY_CPU_BE
342     UInt32 k = 0x01020304;
343     const Byte *p = (const Byte *)&k;
344     if (p[0] == 4 && p[1] == 3)
345       g_Crc_Algo = Z7_CRC_NUM_TABLES_USE;
346     else if (p[0] != 1 || p[1] != 2)
347       g_Crc_Algo = 1;
348     else
349 #endif // MY_CPU_BE
350     {
351       for (i = 256 * Z7_CRC_NUM_TABLES_TOTAL - 1; i >= 256; i--)
352       {
353         const UInt32 x = g_CrcTable[(size_t)i - 256];
354         g_CrcTable[i] = Z7_BSWAP32(x);
355       }
356 #if defined(Z7_CRC_UPDATE_T1_FUNC_NAME)
357       g_Crc_Algo = Z7_CRC_NUM_TABLES_USE;
358 #endif
359 #if (!defined(MY_CPU_LE) && !defined(MY_CPU_BE))
360       g_Crc_Be = 1;
361 #endif
362     }
363   }
364 #endif  // !defined(MY_CPU_LE)
365 
366 #ifdef MY_CPU_LE
367 #ifdef Z7_CRC_HW_USE
368   if (CPU_IsSupported_CRC32())
369     g_Crc_Algo = 0;
370 #endif // Z7_CRC_HW_USE
371 #endif // MY_CPU_LE
372 
373 #endif // Z7_CRC_NUM_TABLES_USE <= 1
374 #endif // g_Crc_Algo was declared
375 }
376 
z7_GetFunc_CrcUpdate(unsigned algo)377 Z7_CRC_UPDATE_FUNC z7_GetFunc_CrcUpdate(unsigned algo)
378 {
379   if (algo == 0)
380     return &CrcUpdate;
381 
382 #if defined(Z7_CRC_HW_USE)
383   if (algo == sizeof(CRC_HW_WORD_TYPE) * 8)
384   {
385 #ifdef Z7_CRC_HW_FORCE
386     return &CrcUpdate;
387 #else
388     if (g_Crc_Algo == 0)
389       return &CrcUpdate_HW;
390 #endif
391   }
392 #endif
393 
394 #ifndef Z7_CRC_HW_FORCE
395   if (algo == Z7_CRC_NUM_TABLES_USE)
396     return
397   #ifdef Z7_CRC_HW_USE
398       &CrcUpdate_Base;
399   #else
400       &CrcUpdate;
401   #endif
402 #endif
403 
404   return NULL;
405 }
406 
407 #undef kCrcPoly
408 #undef Z7_CRC_NUM_TABLES_USE
409 #undef Z7_CRC_NUM_TABLES_TOTAL
410 #undef CRC_UPDATE_BYTE_2
411 #undef FUNC_NAME_LE_2
412 #undef FUNC_NAME_LE_1
413 #undef FUNC_NAME_LE
414 #undef FUNC_NAME_BE_2
415 #undef FUNC_NAME_BE_1
416 #undef FUNC_NAME_BE
417 
418 #undef CRC_HW_UNROLL_BYTES
419 #undef CRC_HW_WORD_FUNC
420 #undef CRC_HW_WORD_TYPE
421