xref: /third_party/lzma/C/7zCrc.c (revision 370b324c)
1370b324cSopenharmony_ci/* 7zCrc.c -- CRC32 calculation and init
2370b324cSopenharmony_ci2023-04-02 : Igor Pavlov : Public domain */
3370b324cSopenharmony_ci
4370b324cSopenharmony_ci#include "Precomp.h"
5370b324cSopenharmony_ci
6370b324cSopenharmony_ci#include "7zCrc.h"
7370b324cSopenharmony_ci#include "CpuArch.h"
8370b324cSopenharmony_ci
9370b324cSopenharmony_ci#define kCrcPoly 0xEDB88320
10370b324cSopenharmony_ci
11370b324cSopenharmony_ci#ifdef MY_CPU_LE
12370b324cSopenharmony_ci  #define CRC_NUM_TABLES 8
13370b324cSopenharmony_ci#else
14370b324cSopenharmony_ci  #define CRC_NUM_TABLES 9
15370b324cSopenharmony_ci
16370b324cSopenharmony_ci  UInt32 Z7_FASTCALL CrcUpdateT1_BeT4(UInt32 v, const void *data, size_t size, const UInt32 *table);
17370b324cSopenharmony_ci  UInt32 Z7_FASTCALL CrcUpdateT1_BeT8(UInt32 v, const void *data, size_t size, const UInt32 *table);
18370b324cSopenharmony_ci#endif
19370b324cSopenharmony_ci
20370b324cSopenharmony_ci#ifndef MY_CPU_BE
21370b324cSopenharmony_ci  UInt32 Z7_FASTCALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const UInt32 *table);
22370b324cSopenharmony_ci  UInt32 Z7_FASTCALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table);
23370b324cSopenharmony_ci#endif
24370b324cSopenharmony_ci
25370b324cSopenharmony_ci/*
26370b324cSopenharmony_ciextern
27370b324cSopenharmony_ciCRC_FUNC g_CrcUpdateT4;
28370b324cSopenharmony_ciCRC_FUNC g_CrcUpdateT4;
29370b324cSopenharmony_ci*/
30370b324cSopenharmony_ciextern
31370b324cSopenharmony_ciCRC_FUNC g_CrcUpdateT8;
32370b324cSopenharmony_ciCRC_FUNC g_CrcUpdateT8;
33370b324cSopenharmony_ciextern
34370b324cSopenharmony_ciCRC_FUNC g_CrcUpdateT0_32;
35370b324cSopenharmony_ciCRC_FUNC g_CrcUpdateT0_32;
36370b324cSopenharmony_ciextern
37370b324cSopenharmony_ciCRC_FUNC g_CrcUpdateT0_64;
38370b324cSopenharmony_ciCRC_FUNC g_CrcUpdateT0_64;
39370b324cSopenharmony_ciextern
40370b324cSopenharmony_ciCRC_FUNC g_CrcUpdate;
41370b324cSopenharmony_ciCRC_FUNC g_CrcUpdate;
42370b324cSopenharmony_ci
43370b324cSopenharmony_ciUInt32 g_CrcTable[256 * CRC_NUM_TABLES];
44370b324cSopenharmony_ci
45370b324cSopenharmony_ciUInt32 Z7_FASTCALL CrcUpdate(UInt32 v, const void *data, size_t size)
46370b324cSopenharmony_ci{
47370b324cSopenharmony_ci  return g_CrcUpdate(v, data, size, g_CrcTable);
48370b324cSopenharmony_ci}
49370b324cSopenharmony_ci
50370b324cSopenharmony_ciUInt32 Z7_FASTCALL CrcCalc(const void *data, size_t size)
51370b324cSopenharmony_ci{
52370b324cSopenharmony_ci  return g_CrcUpdate(CRC_INIT_VAL, data, size, g_CrcTable) ^ CRC_INIT_VAL;
53370b324cSopenharmony_ci}
54370b324cSopenharmony_ci
55370b324cSopenharmony_ci#if CRC_NUM_TABLES < 4 \
56370b324cSopenharmony_ci   || (CRC_NUM_TABLES == 4 && defined(MY_CPU_BE)) \
57370b324cSopenharmony_ci   || (!defined(MY_CPU_LE) && !defined(MY_CPU_BE))
58370b324cSopenharmony_ci#define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))
59370b324cSopenharmony_ciUInt32 Z7_FASTCALL CrcUpdateT1(UInt32 v, const void *data, size_t size, const UInt32 *table);
60370b324cSopenharmony_ciUInt32 Z7_FASTCALL CrcUpdateT1(UInt32 v, const void *data, size_t size, const UInt32 *table)
61370b324cSopenharmony_ci{
62370b324cSopenharmony_ci  const Byte *p = (const Byte *)data;
63370b324cSopenharmony_ci  const Byte *pEnd = p + size;
64370b324cSopenharmony_ci  for (; p != pEnd; p++)
65370b324cSopenharmony_ci    v = CRC_UPDATE_BYTE_2(v, *p);
66370b324cSopenharmony_ci  return v;
67370b324cSopenharmony_ci}
68370b324cSopenharmony_ci#endif
69370b324cSopenharmony_ci
70370b324cSopenharmony_ci/* ---------- hardware CRC ---------- */
71370b324cSopenharmony_ci
72370b324cSopenharmony_ci#ifdef MY_CPU_LE
73370b324cSopenharmony_ci
74370b324cSopenharmony_ci#if defined(MY_CPU_ARM_OR_ARM64)
75370b324cSopenharmony_ci
76370b324cSopenharmony_ci// #pragma message("ARM*")
77370b324cSopenharmony_ci
78370b324cSopenharmony_ci  #if defined(_MSC_VER)
79370b324cSopenharmony_ci    #if defined(MY_CPU_ARM64)
80370b324cSopenharmony_ci    #if (_MSC_VER >= 1910)
81370b324cSopenharmony_ci    #ifndef __clang__
82370b324cSopenharmony_ci        #define USE_ARM64_CRC
83370b324cSopenharmony_ci        #include <intrin.h>
84370b324cSopenharmony_ci    #endif
85370b324cSopenharmony_ci    #endif
86370b324cSopenharmony_ci    #endif
87370b324cSopenharmony_ci  #elif (defined(__clang__) && (__clang_major__ >= 3)) \
88370b324cSopenharmony_ci     || (defined(__GNUC__) && (__GNUC__ > 4))
89370b324cSopenharmony_ci      #if !defined(__ARM_FEATURE_CRC32)
90370b324cSopenharmony_ci        #define __ARM_FEATURE_CRC32 1
91370b324cSopenharmony_ci        #if defined(__clang__)
92370b324cSopenharmony_ci          #if defined(MY_CPU_ARM64)
93370b324cSopenharmony_ci            #define ATTRIB_CRC __attribute__((__target__("crc")))
94370b324cSopenharmony_ci          #else
95370b324cSopenharmony_ci            #define ATTRIB_CRC __attribute__((__target__("armv8-a,crc")))
96370b324cSopenharmony_ci          #endif
97370b324cSopenharmony_ci        #else
98370b324cSopenharmony_ci          #if defined(MY_CPU_ARM64)
99370b324cSopenharmony_ci            #define ATTRIB_CRC __attribute__((__target__("+crc")))
100370b324cSopenharmony_ci          #else
101370b324cSopenharmony_ci            #define ATTRIB_CRC __attribute__((__target__("arch=armv8-a+crc")))
102370b324cSopenharmony_ci          #endif
103370b324cSopenharmony_ci        #endif
104370b324cSopenharmony_ci      #endif
105370b324cSopenharmony_ci      #if defined(__ARM_FEATURE_CRC32)
106370b324cSopenharmony_ci        #define USE_ARM64_CRC
107370b324cSopenharmony_ci        #include <arm_acle.h>
108370b324cSopenharmony_ci      #endif
109370b324cSopenharmony_ci  #endif
110370b324cSopenharmony_ci
111370b324cSopenharmony_ci#else
112370b324cSopenharmony_ci
113370b324cSopenharmony_ci// no hardware CRC
114370b324cSopenharmony_ci
115370b324cSopenharmony_ci// #define USE_CRC_EMU
116370b324cSopenharmony_ci
117370b324cSopenharmony_ci#ifdef USE_CRC_EMU
118370b324cSopenharmony_ci
119370b324cSopenharmony_ci#pragma message("ARM64 CRC emulation")
120370b324cSopenharmony_ci
121370b324cSopenharmony_ciZ7_FORCE_INLINE
122370b324cSopenharmony_ciUInt32 __crc32b(UInt32 v, UInt32 data)
123370b324cSopenharmony_ci{
124370b324cSopenharmony_ci  const UInt32 *table = g_CrcTable;
125370b324cSopenharmony_ci  v = CRC_UPDATE_BYTE_2(v, (Byte)data);
126370b324cSopenharmony_ci  return v;
127370b324cSopenharmony_ci}
128370b324cSopenharmony_ci
129370b324cSopenharmony_ciZ7_FORCE_INLINE
130370b324cSopenharmony_ciUInt32 __crc32w(UInt32 v, UInt32 data)
131370b324cSopenharmony_ci{
132370b324cSopenharmony_ci  const UInt32 *table = g_CrcTable;
133370b324cSopenharmony_ci  v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8;
134370b324cSopenharmony_ci  v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8;
135370b324cSopenharmony_ci  v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8;
136370b324cSopenharmony_ci  v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8;
137370b324cSopenharmony_ci  return v;
138370b324cSopenharmony_ci}
139370b324cSopenharmony_ci
140370b324cSopenharmony_ciZ7_FORCE_INLINE
141370b324cSopenharmony_ciUInt32 __crc32d(UInt32 v, UInt64 data)
142370b324cSopenharmony_ci{
143370b324cSopenharmony_ci  const UInt32 *table = g_CrcTable;
144370b324cSopenharmony_ci  v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8;
145370b324cSopenharmony_ci  v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8;
146370b324cSopenharmony_ci  v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8;
147370b324cSopenharmony_ci  v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8;
148370b324cSopenharmony_ci  v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8;
149370b324cSopenharmony_ci  v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8;
150370b324cSopenharmony_ci  v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8;
151370b324cSopenharmony_ci  v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8;
152370b324cSopenharmony_ci  return v;
153370b324cSopenharmony_ci}
154370b324cSopenharmony_ci
155370b324cSopenharmony_ci#endif // USE_CRC_EMU
156370b324cSopenharmony_ci
157370b324cSopenharmony_ci#endif // defined(MY_CPU_ARM64) && defined(MY_CPU_LE)
158370b324cSopenharmony_ci
159370b324cSopenharmony_ci
160370b324cSopenharmony_ci
161370b324cSopenharmony_ci#if defined(USE_ARM64_CRC) || defined(USE_CRC_EMU)
162370b324cSopenharmony_ci
163370b324cSopenharmony_ci#define T0_32_UNROLL_BYTES (4 * 4)
164370b324cSopenharmony_ci#define T0_64_UNROLL_BYTES (4 * 8)
165370b324cSopenharmony_ci
166370b324cSopenharmony_ci#ifndef ATTRIB_CRC
167370b324cSopenharmony_ci#define ATTRIB_CRC
168370b324cSopenharmony_ci#endif
169370b324cSopenharmony_ci// #pragma message("USE ARM HW CRC")
170370b324cSopenharmony_ci
171370b324cSopenharmony_ciATTRIB_CRC
172370b324cSopenharmony_ciUInt32 Z7_FASTCALL CrcUpdateT0_32(UInt32 v, const void *data, size_t size, const UInt32 *table);
173370b324cSopenharmony_ciATTRIB_CRC
174370b324cSopenharmony_ciUInt32 Z7_FASTCALL CrcUpdateT0_32(UInt32 v, const void *data, size_t size, const UInt32 *table)
175370b324cSopenharmony_ci{
176370b324cSopenharmony_ci  const Byte *p = (const Byte *)data;
177370b324cSopenharmony_ci  UNUSED_VAR(table);
178370b324cSopenharmony_ci
179370b324cSopenharmony_ci  for (; size != 0 && ((unsigned)(ptrdiff_t)p & (T0_32_UNROLL_BYTES - 1)) != 0; size--)
180370b324cSopenharmony_ci    v = __crc32b(v, *p++);
181370b324cSopenharmony_ci
182370b324cSopenharmony_ci  if (size >= T0_32_UNROLL_BYTES)
183370b324cSopenharmony_ci  {
184370b324cSopenharmony_ci    const Byte *lim = p + size;
185370b324cSopenharmony_ci    size &= (T0_32_UNROLL_BYTES - 1);
186370b324cSopenharmony_ci    lim -= size;
187370b324cSopenharmony_ci    do
188370b324cSopenharmony_ci    {
189370b324cSopenharmony_ci      v = __crc32w(v, *(const UInt32 *)(const void *)(p));
190370b324cSopenharmony_ci      v = __crc32w(v, *(const UInt32 *)(const void *)(p + 4)); p += 2 * 4;
191370b324cSopenharmony_ci      v = __crc32w(v, *(const UInt32 *)(const void *)(p));
192370b324cSopenharmony_ci      v = __crc32w(v, *(const UInt32 *)(const void *)(p + 4)); p += 2 * 4;
193370b324cSopenharmony_ci    }
194370b324cSopenharmony_ci    while (p != lim);
195370b324cSopenharmony_ci  }
196370b324cSopenharmony_ci
197370b324cSopenharmony_ci  for (; size != 0; size--)
198370b324cSopenharmony_ci    v = __crc32b(v, *p++);
199370b324cSopenharmony_ci
200370b324cSopenharmony_ci  return v;
201370b324cSopenharmony_ci}
202370b324cSopenharmony_ci
203370b324cSopenharmony_ciATTRIB_CRC
204370b324cSopenharmony_ciUInt32 Z7_FASTCALL CrcUpdateT0_64(UInt32 v, const void *data, size_t size, const UInt32 *table);
205370b324cSopenharmony_ciATTRIB_CRC
206370b324cSopenharmony_ciUInt32 Z7_FASTCALL CrcUpdateT0_64(UInt32 v, const void *data, size_t size, const UInt32 *table)
207370b324cSopenharmony_ci{
208370b324cSopenharmony_ci  const Byte *p = (const Byte *)data;
209370b324cSopenharmony_ci  UNUSED_VAR(table);
210370b324cSopenharmony_ci
211370b324cSopenharmony_ci  for (; size != 0 && ((unsigned)(ptrdiff_t)p & (T0_64_UNROLL_BYTES - 1)) != 0; size--)
212370b324cSopenharmony_ci    v = __crc32b(v, *p++);
213370b324cSopenharmony_ci
214370b324cSopenharmony_ci  if (size >= T0_64_UNROLL_BYTES)
215370b324cSopenharmony_ci  {
216370b324cSopenharmony_ci    const Byte *lim = p + size;
217370b324cSopenharmony_ci    size &= (T0_64_UNROLL_BYTES - 1);
218370b324cSopenharmony_ci    lim -= size;
219370b324cSopenharmony_ci    do
220370b324cSopenharmony_ci    {
221370b324cSopenharmony_ci      v = __crc32d(v, *(const UInt64 *)(const void *)(p));
222370b324cSopenharmony_ci      v = __crc32d(v, *(const UInt64 *)(const void *)(p + 8)); p += 2 * 8;
223370b324cSopenharmony_ci      v = __crc32d(v, *(const UInt64 *)(const void *)(p));
224370b324cSopenharmony_ci      v = __crc32d(v, *(const UInt64 *)(const void *)(p + 8)); p += 2 * 8;
225370b324cSopenharmony_ci    }
226370b324cSopenharmony_ci    while (p != lim);
227370b324cSopenharmony_ci  }
228370b324cSopenharmony_ci
229370b324cSopenharmony_ci  for (; size != 0; size--)
230370b324cSopenharmony_ci    v = __crc32b(v, *p++);
231370b324cSopenharmony_ci
232370b324cSopenharmony_ci  return v;
233370b324cSopenharmony_ci}
234370b324cSopenharmony_ci
235370b324cSopenharmony_ci#undef T0_32_UNROLL_BYTES
236370b324cSopenharmony_ci#undef T0_64_UNROLL_BYTES
237370b324cSopenharmony_ci
238370b324cSopenharmony_ci#endif // defined(USE_ARM64_CRC) || defined(USE_CRC_EMU)
239370b324cSopenharmony_ci
240370b324cSopenharmony_ci#endif // MY_CPU_LE
241370b324cSopenharmony_ci
242370b324cSopenharmony_ci
243370b324cSopenharmony_ci
244370b324cSopenharmony_ci
245370b324cSopenharmony_civoid Z7_FASTCALL CrcGenerateTable(void)
246370b324cSopenharmony_ci{
247370b324cSopenharmony_ci  UInt32 i;
248370b324cSopenharmony_ci  for (i = 0; i < 256; i++)
249370b324cSopenharmony_ci  {
250370b324cSopenharmony_ci    UInt32 r = i;
251370b324cSopenharmony_ci    unsigned j;
252370b324cSopenharmony_ci    for (j = 0; j < 8; j++)
253370b324cSopenharmony_ci      r = (r >> 1) ^ (kCrcPoly & ((UInt32)0 - (r & 1)));
254370b324cSopenharmony_ci    g_CrcTable[i] = r;
255370b324cSopenharmony_ci  }
256370b324cSopenharmony_ci  for (i = 256; i < 256 * CRC_NUM_TABLES; i++)
257370b324cSopenharmony_ci  {
258370b324cSopenharmony_ci    const UInt32 r = g_CrcTable[(size_t)i - 256];
259370b324cSopenharmony_ci    g_CrcTable[i] = g_CrcTable[r & 0xFF] ^ (r >> 8);
260370b324cSopenharmony_ci  }
261370b324cSopenharmony_ci
262370b324cSopenharmony_ci  #if CRC_NUM_TABLES < 4
263370b324cSopenharmony_ci    g_CrcUpdate = CrcUpdateT1;
264370b324cSopenharmony_ci  #elif defined(MY_CPU_LE)
265370b324cSopenharmony_ci    // g_CrcUpdateT4 = CrcUpdateT4;
266370b324cSopenharmony_ci    #if CRC_NUM_TABLES < 8
267370b324cSopenharmony_ci      g_CrcUpdate = CrcUpdateT4;
268370b324cSopenharmony_ci    #else // CRC_NUM_TABLES >= 8
269370b324cSopenharmony_ci      g_CrcUpdateT8 = CrcUpdateT8;
270370b324cSopenharmony_ci      /*
271370b324cSopenharmony_ci      #ifdef MY_CPU_X86_OR_AMD64
272370b324cSopenharmony_ci      if (!CPU_Is_InOrder())
273370b324cSopenharmony_ci      #endif
274370b324cSopenharmony_ci      */
275370b324cSopenharmony_ci      g_CrcUpdate = CrcUpdateT8;
276370b324cSopenharmony_ci    #endif
277370b324cSopenharmony_ci  #else
278370b324cSopenharmony_ci  {
279370b324cSopenharmony_ci   #ifndef MY_CPU_BE
280370b324cSopenharmony_ci    UInt32 k = 0x01020304;
281370b324cSopenharmony_ci    const Byte *p = (const Byte *)&k;
282370b324cSopenharmony_ci    if (p[0] == 4 && p[1] == 3)
283370b324cSopenharmony_ci    {
284370b324cSopenharmony_ci      #if CRC_NUM_TABLES < 8
285370b324cSopenharmony_ci        // g_CrcUpdateT4 = CrcUpdateT4;
286370b324cSopenharmony_ci        g_CrcUpdate   = CrcUpdateT4;
287370b324cSopenharmony_ci      #else  // CRC_NUM_TABLES >= 8
288370b324cSopenharmony_ci        g_CrcUpdateT8 = CrcUpdateT8;
289370b324cSopenharmony_ci        g_CrcUpdate   = CrcUpdateT8;
290370b324cSopenharmony_ci      #endif
291370b324cSopenharmony_ci    }
292370b324cSopenharmony_ci    else if (p[0] != 1 || p[1] != 2)
293370b324cSopenharmony_ci      g_CrcUpdate = CrcUpdateT1;
294370b324cSopenharmony_ci    else
295370b324cSopenharmony_ci   #endif // MY_CPU_BE
296370b324cSopenharmony_ci    {
297370b324cSopenharmony_ci      for (i = 256 * CRC_NUM_TABLES - 1; i >= 256; i--)
298370b324cSopenharmony_ci      {
299370b324cSopenharmony_ci        const UInt32 x = g_CrcTable[(size_t)i - 256];
300370b324cSopenharmony_ci        g_CrcTable[i] = Z7_BSWAP32(x);
301370b324cSopenharmony_ci      }
302370b324cSopenharmony_ci      #if CRC_NUM_TABLES <= 4
303370b324cSopenharmony_ci        g_CrcUpdate = CrcUpdateT1;
304370b324cSopenharmony_ci      #elif CRC_NUM_TABLES <= 8
305370b324cSopenharmony_ci        // g_CrcUpdateT4 = CrcUpdateT1_BeT4;
306370b324cSopenharmony_ci        g_CrcUpdate   = CrcUpdateT1_BeT4;
307370b324cSopenharmony_ci      #else  // CRC_NUM_TABLES > 8
308370b324cSopenharmony_ci        g_CrcUpdateT8 = CrcUpdateT1_BeT8;
309370b324cSopenharmony_ci        g_CrcUpdate   = CrcUpdateT1_BeT8;
310370b324cSopenharmony_ci      #endif
311370b324cSopenharmony_ci    }
312370b324cSopenharmony_ci  }
313370b324cSopenharmony_ci  #endif // CRC_NUM_TABLES < 4
314370b324cSopenharmony_ci
315370b324cSopenharmony_ci  #ifdef MY_CPU_LE
316370b324cSopenharmony_ci    #ifdef USE_ARM64_CRC
317370b324cSopenharmony_ci      if (CPU_IsSupported_CRC32())
318370b324cSopenharmony_ci      {
319370b324cSopenharmony_ci        g_CrcUpdateT0_32 = CrcUpdateT0_32;
320370b324cSopenharmony_ci        g_CrcUpdateT0_64 = CrcUpdateT0_64;
321370b324cSopenharmony_ci        g_CrcUpdate =
322370b324cSopenharmony_ci          #if defined(MY_CPU_ARM)
323370b324cSopenharmony_ci            CrcUpdateT0_32;
324370b324cSopenharmony_ci          #else
325370b324cSopenharmony_ci            CrcUpdateT0_64;
326370b324cSopenharmony_ci          #endif
327370b324cSopenharmony_ci      }
328370b324cSopenharmony_ci    #endif
329370b324cSopenharmony_ci
330370b324cSopenharmony_ci    #ifdef USE_CRC_EMU
331370b324cSopenharmony_ci      g_CrcUpdateT0_32 = CrcUpdateT0_32;
332370b324cSopenharmony_ci      g_CrcUpdateT0_64 = CrcUpdateT0_64;
333370b324cSopenharmony_ci      g_CrcUpdate = CrcUpdateT0_64;
334370b324cSopenharmony_ci    #endif
335370b324cSopenharmony_ci  #endif
336370b324cSopenharmony_ci}
337370b324cSopenharmony_ci
338370b324cSopenharmony_ci#undef kCrcPoly
339370b324cSopenharmony_ci#undef CRC64_NUM_TABLES
340370b324cSopenharmony_ci#undef CRC_UPDATE_BYTE_2
341