xref: /third_party/lzma/C/7zCrc.c (revision 370b324c)
1/* 7zCrc.c -- CRC32 calculation and init
22023-04-02 : Igor Pavlov : Public domain */
3
4#include "Precomp.h"
5
6#include "7zCrc.h"
7#include "CpuArch.h"
8
9#define kCrcPoly 0xEDB88320
10
11#ifdef MY_CPU_LE
12  #define CRC_NUM_TABLES 8
13#else
14  #define CRC_NUM_TABLES 9
15
16  UInt32 Z7_FASTCALL CrcUpdateT1_BeT4(UInt32 v, const void *data, size_t size, const UInt32 *table);
17  UInt32 Z7_FASTCALL CrcUpdateT1_BeT8(UInt32 v, const void *data, size_t size, const UInt32 *table);
18#endif
19
20#ifndef MY_CPU_BE
21  UInt32 Z7_FASTCALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const UInt32 *table);
22  UInt32 Z7_FASTCALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table);
23#endif
24
25/*
26extern
27CRC_FUNC g_CrcUpdateT4;
28CRC_FUNC g_CrcUpdateT4;
29*/
30extern
31CRC_FUNC g_CrcUpdateT8;
32CRC_FUNC g_CrcUpdateT8;
33extern
34CRC_FUNC g_CrcUpdateT0_32;
35CRC_FUNC g_CrcUpdateT0_32;
36extern
37CRC_FUNC g_CrcUpdateT0_64;
38CRC_FUNC g_CrcUpdateT0_64;
39extern
40CRC_FUNC g_CrcUpdate;
41CRC_FUNC g_CrcUpdate;
42
43UInt32 g_CrcTable[256 * CRC_NUM_TABLES];
44
45UInt32 Z7_FASTCALL CrcUpdate(UInt32 v, const void *data, size_t size)
46{
47  return g_CrcUpdate(v, data, size, g_CrcTable);
48}
49
50UInt32 Z7_FASTCALL CrcCalc(const void *data, size_t size)
51{
52  return g_CrcUpdate(CRC_INIT_VAL, data, size, g_CrcTable) ^ CRC_INIT_VAL;
53}
54
55#if CRC_NUM_TABLES < 4 \
56   || (CRC_NUM_TABLES == 4 && defined(MY_CPU_BE)) \
57   || (!defined(MY_CPU_LE) && !defined(MY_CPU_BE))
58#define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))
59UInt32 Z7_FASTCALL CrcUpdateT1(UInt32 v, const void *data, size_t size, const UInt32 *table);
60UInt32 Z7_FASTCALL CrcUpdateT1(UInt32 v, const void *data, size_t size, const UInt32 *table)
61{
62  const Byte *p = (const Byte *)data;
63  const Byte *pEnd = p + size;
64  for (; p != pEnd; p++)
65    v = CRC_UPDATE_BYTE_2(v, *p);
66  return v;
67}
68#endif
69
70/* ---------- hardware CRC ---------- */
71
72#ifdef MY_CPU_LE
73
74#if defined(MY_CPU_ARM_OR_ARM64)
75
76// #pragma message("ARM*")
77
78  #if defined(_MSC_VER)
79    #if defined(MY_CPU_ARM64)
80    #if (_MSC_VER >= 1910)
81    #ifndef __clang__
82        #define USE_ARM64_CRC
83        #include <intrin.h>
84    #endif
85    #endif
86    #endif
87  #elif (defined(__clang__) && (__clang_major__ >= 3)) \
88     || (defined(__GNUC__) && (__GNUC__ > 4))
89      #if !defined(__ARM_FEATURE_CRC32)
90        #define __ARM_FEATURE_CRC32 1
91        #if defined(__clang__)
92          #if defined(MY_CPU_ARM64)
93            #define ATTRIB_CRC __attribute__((__target__("crc")))
94          #else
95            #define ATTRIB_CRC __attribute__((__target__("armv8-a,crc")))
96          #endif
97        #else
98          #if defined(MY_CPU_ARM64)
99            #define ATTRIB_CRC __attribute__((__target__("+crc")))
100          #else
101            #define ATTRIB_CRC __attribute__((__target__("arch=armv8-a+crc")))
102          #endif
103        #endif
104      #endif
105      #if defined(__ARM_FEATURE_CRC32)
106        #define USE_ARM64_CRC
107        #include <arm_acle.h>
108      #endif
109  #endif
110
111#else
112
113// no hardware CRC
114
115// #define USE_CRC_EMU
116
117#ifdef USE_CRC_EMU
118
119#pragma message("ARM64 CRC emulation")
120
121Z7_FORCE_INLINE
122UInt32 __crc32b(UInt32 v, UInt32 data)
123{
124  const UInt32 *table = g_CrcTable;
125  v = CRC_UPDATE_BYTE_2(v, (Byte)data);
126  return v;
127}
128
129Z7_FORCE_INLINE
130UInt32 __crc32w(UInt32 v, UInt32 data)
131{
132  const UInt32 *table = g_CrcTable;
133  v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8;
134  v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8;
135  v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8;
136  v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8;
137  return v;
138}
139
140Z7_FORCE_INLINE
141UInt32 __crc32d(UInt32 v, UInt64 data)
142{
143  const UInt32 *table = g_CrcTable;
144  v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8;
145  v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8;
146  v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8;
147  v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8;
148  v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8;
149  v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8;
150  v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8;
151  v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8;
152  return v;
153}
154
155#endif // USE_CRC_EMU
156
157#endif // defined(MY_CPU_ARM64) && defined(MY_CPU_LE)
158
159
160
161#if defined(USE_ARM64_CRC) || defined(USE_CRC_EMU)
162
163#define T0_32_UNROLL_BYTES (4 * 4)
164#define T0_64_UNROLL_BYTES (4 * 8)
165
166#ifndef ATTRIB_CRC
167#define ATTRIB_CRC
168#endif
169// #pragma message("USE ARM HW CRC")
170
171ATTRIB_CRC
172UInt32 Z7_FASTCALL CrcUpdateT0_32(UInt32 v, const void *data, size_t size, const UInt32 *table);
173ATTRIB_CRC
174UInt32 Z7_FASTCALL CrcUpdateT0_32(UInt32 v, const void *data, size_t size, const UInt32 *table)
175{
176  const Byte *p = (const Byte *)data;
177  UNUSED_VAR(table);
178
179  for (; size != 0 && ((unsigned)(ptrdiff_t)p & (T0_32_UNROLL_BYTES - 1)) != 0; size--)
180    v = __crc32b(v, *p++);
181
182  if (size >= T0_32_UNROLL_BYTES)
183  {
184    const Byte *lim = p + size;
185    size &= (T0_32_UNROLL_BYTES - 1);
186    lim -= size;
187    do
188    {
189      v = __crc32w(v, *(const UInt32 *)(const void *)(p));
190      v = __crc32w(v, *(const UInt32 *)(const void *)(p + 4)); p += 2 * 4;
191      v = __crc32w(v, *(const UInt32 *)(const void *)(p));
192      v = __crc32w(v, *(const UInt32 *)(const void *)(p + 4)); p += 2 * 4;
193    }
194    while (p != lim);
195  }
196
197  for (; size != 0; size--)
198    v = __crc32b(v, *p++);
199
200  return v;
201}
202
203ATTRIB_CRC
204UInt32 Z7_FASTCALL CrcUpdateT0_64(UInt32 v, const void *data, size_t size, const UInt32 *table);
205ATTRIB_CRC
206UInt32 Z7_FASTCALL CrcUpdateT0_64(UInt32 v, const void *data, size_t size, const UInt32 *table)
207{
208  const Byte *p = (const Byte *)data;
209  UNUSED_VAR(table);
210
211  for (; size != 0 && ((unsigned)(ptrdiff_t)p & (T0_64_UNROLL_BYTES - 1)) != 0; size--)
212    v = __crc32b(v, *p++);
213
214  if (size >= T0_64_UNROLL_BYTES)
215  {
216    const Byte *lim = p + size;
217    size &= (T0_64_UNROLL_BYTES - 1);
218    lim -= size;
219    do
220    {
221      v = __crc32d(v, *(const UInt64 *)(const void *)(p));
222      v = __crc32d(v, *(const UInt64 *)(const void *)(p + 8)); p += 2 * 8;
223      v = __crc32d(v, *(const UInt64 *)(const void *)(p));
224      v = __crc32d(v, *(const UInt64 *)(const void *)(p + 8)); p += 2 * 8;
225    }
226    while (p != lim);
227  }
228
229  for (; size != 0; size--)
230    v = __crc32b(v, *p++);
231
232  return v;
233}
234
235#undef T0_32_UNROLL_BYTES
236#undef T0_64_UNROLL_BYTES
237
238#endif // defined(USE_ARM64_CRC) || defined(USE_CRC_EMU)
239
240#endif // MY_CPU_LE
241
242
243
244
245void Z7_FASTCALL CrcGenerateTable(void)
246{
247  UInt32 i;
248  for (i = 0; i < 256; i++)
249  {
250    UInt32 r = i;
251    unsigned j;
252    for (j = 0; j < 8; j++)
253      r = (r >> 1) ^ (kCrcPoly & ((UInt32)0 - (r & 1)));
254    g_CrcTable[i] = r;
255  }
256  for (i = 256; i < 256 * CRC_NUM_TABLES; i++)
257  {
258    const UInt32 r = g_CrcTable[(size_t)i - 256];
259    g_CrcTable[i] = g_CrcTable[r & 0xFF] ^ (r >> 8);
260  }
261
262  #if CRC_NUM_TABLES < 4
263    g_CrcUpdate = CrcUpdateT1;
264  #elif defined(MY_CPU_LE)
265    // g_CrcUpdateT4 = CrcUpdateT4;
266    #if CRC_NUM_TABLES < 8
267      g_CrcUpdate = CrcUpdateT4;
268    #else // CRC_NUM_TABLES >= 8
269      g_CrcUpdateT8 = CrcUpdateT8;
270      /*
271      #ifdef MY_CPU_X86_OR_AMD64
272      if (!CPU_Is_InOrder())
273      #endif
274      */
275      g_CrcUpdate = CrcUpdateT8;
276    #endif
277  #else
278  {
279   #ifndef MY_CPU_BE
280    UInt32 k = 0x01020304;
281    const Byte *p = (const Byte *)&k;
282    if (p[0] == 4 && p[1] == 3)
283    {
284      #if CRC_NUM_TABLES < 8
285        // g_CrcUpdateT4 = CrcUpdateT4;
286        g_CrcUpdate   = CrcUpdateT4;
287      #else  // CRC_NUM_TABLES >= 8
288        g_CrcUpdateT8 = CrcUpdateT8;
289        g_CrcUpdate   = CrcUpdateT8;
290      #endif
291    }
292    else if (p[0] != 1 || p[1] != 2)
293      g_CrcUpdate = CrcUpdateT1;
294    else
295   #endif // MY_CPU_BE
296    {
297      for (i = 256 * CRC_NUM_TABLES - 1; i >= 256; i--)
298      {
299        const UInt32 x = g_CrcTable[(size_t)i - 256];
300        g_CrcTable[i] = Z7_BSWAP32(x);
301      }
302      #if CRC_NUM_TABLES <= 4
303        g_CrcUpdate = CrcUpdateT1;
304      #elif CRC_NUM_TABLES <= 8
305        // g_CrcUpdateT4 = CrcUpdateT1_BeT4;
306        g_CrcUpdate   = CrcUpdateT1_BeT4;
307      #else  // CRC_NUM_TABLES > 8
308        g_CrcUpdateT8 = CrcUpdateT1_BeT8;
309        g_CrcUpdate   = CrcUpdateT1_BeT8;
310      #endif
311    }
312  }
313  #endif // CRC_NUM_TABLES < 4
314
315  #ifdef MY_CPU_LE
316    #ifdef USE_ARM64_CRC
317      if (CPU_IsSupported_CRC32())
318      {
319        g_CrcUpdateT0_32 = CrcUpdateT0_32;
320        g_CrcUpdateT0_64 = CrcUpdateT0_64;
321        g_CrcUpdate =
322          #if defined(MY_CPU_ARM)
323            CrcUpdateT0_32;
324          #else
325            CrcUpdateT0_64;
326          #endif
327      }
328    #endif
329
330    #ifdef USE_CRC_EMU
331      g_CrcUpdateT0_32 = CrcUpdateT0_32;
332      g_CrcUpdateT0_64 = CrcUpdateT0_64;
333      g_CrcUpdate = CrcUpdateT0_64;
334    #endif
335  #endif
336}
337
338#undef kCrcPoly
339#undef CRC64_NUM_TABLES
340#undef CRC_UPDATE_BYTE_2
341