Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
stenzek
GitHub Repository: stenzek/duckstation
Path: blob/master/dep/lzma/src/7zCrc.c
4253 views
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
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
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
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
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
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
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
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
422