1*f6dc9357SAndroid Build Coastguard Worker /* 7zCrcOpt.c -- CRC32 calculation (optimized functions)
2*f6dc9357SAndroid Build Coastguard Worker 2023-12-07 : Igor Pavlov : Public domain */
3*f6dc9357SAndroid Build Coastguard Worker
4*f6dc9357SAndroid Build Coastguard Worker #include "Precomp.h"
5*f6dc9357SAndroid Build Coastguard Worker
6*f6dc9357SAndroid Build Coastguard Worker #include "CpuArch.h"
7*f6dc9357SAndroid Build Coastguard Worker
8*f6dc9357SAndroid Build Coastguard Worker #if !defined(Z7_CRC_NUM_TABLES) || Z7_CRC_NUM_TABLES > 1
9*f6dc9357SAndroid Build Coastguard Worker
10*f6dc9357SAndroid Build Coastguard Worker // for debug only : define Z7_CRC_DEBUG_BE to test big-endian code in little-endian cpu
11*f6dc9357SAndroid Build Coastguard Worker // #define Z7_CRC_DEBUG_BE
12*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_CRC_DEBUG_BE
13*f6dc9357SAndroid Build Coastguard Worker #undef MY_CPU_LE
14*f6dc9357SAndroid Build Coastguard Worker #define MY_CPU_BE
15*f6dc9357SAndroid Build Coastguard Worker #endif
16*f6dc9357SAndroid Build Coastguard Worker
17*f6dc9357SAndroid Build Coastguard Worker // the value Z7_CRC_NUM_TABLES_USE must be defined to same value as in 7zCrc.c
18*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_CRC_NUM_TABLES
19*f6dc9357SAndroid Build Coastguard Worker #define Z7_CRC_NUM_TABLES_USE Z7_CRC_NUM_TABLES
20*f6dc9357SAndroid Build Coastguard Worker #else
21*f6dc9357SAndroid Build Coastguard Worker #define Z7_CRC_NUM_TABLES_USE 12
22*f6dc9357SAndroid Build Coastguard Worker #endif
23*f6dc9357SAndroid Build Coastguard Worker
24*f6dc9357SAndroid Build Coastguard Worker #if Z7_CRC_NUM_TABLES_USE % 4 || \
25*f6dc9357SAndroid Build Coastguard Worker Z7_CRC_NUM_TABLES_USE < 4 * 1 || \
26*f6dc9357SAndroid Build Coastguard Worker Z7_CRC_NUM_TABLES_USE > 4 * 6
27*f6dc9357SAndroid Build Coastguard Worker #error Stop_Compiling_Bad_Z7_CRC_NUM_TABLES
28*f6dc9357SAndroid Build Coastguard Worker #endif
29*f6dc9357SAndroid Build Coastguard Worker
30*f6dc9357SAndroid Build Coastguard Worker
31*f6dc9357SAndroid Build Coastguard Worker #ifndef MY_CPU_BE
32*f6dc9357SAndroid Build Coastguard Worker
33*f6dc9357SAndroid Build Coastguard Worker #define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))
34*f6dc9357SAndroid Build Coastguard Worker
35*f6dc9357SAndroid Build Coastguard Worker #define Q(n, d) \
36*f6dc9357SAndroid Build Coastguard Worker ( (table + ((n) * 4 + 3) * 0x100)[(Byte)(d)] \
37*f6dc9357SAndroid Build Coastguard Worker ^ (table + ((n) * 4 + 2) * 0x100)[((d) >> 1 * 8) & 0xFF] \
38*f6dc9357SAndroid Build Coastguard Worker ^ (table + ((n) * 4 + 1) * 0x100)[((d) >> 2 * 8) & 0xFF] \
39*f6dc9357SAndroid Build Coastguard Worker ^ (table + ((n) * 4 + 0) * 0x100)[((d) >> 3 * 8)] )
40*f6dc9357SAndroid Build Coastguard Worker
41*f6dc9357SAndroid Build Coastguard Worker #define R(a) *((const UInt32 *)(const void *)p + (a))
42*f6dc9357SAndroid Build Coastguard Worker
43*f6dc9357SAndroid Build Coastguard Worker #define CRC_FUNC_PRE_LE2(step) \
44*f6dc9357SAndroid Build Coastguard Worker UInt32 Z7_FASTCALL CrcUpdateT ## step (UInt32 v, const void *data, size_t size, const UInt32 *table)
45*f6dc9357SAndroid Build Coastguard Worker
46*f6dc9357SAndroid Build Coastguard Worker #define CRC_FUNC_PRE_LE(step) \
47*f6dc9357SAndroid Build Coastguard Worker CRC_FUNC_PRE_LE2(step); \
48*f6dc9357SAndroid Build Coastguard Worker CRC_FUNC_PRE_LE2(step)
49*f6dc9357SAndroid Build Coastguard Worker
CRC_FUNC_PRE_LE(Z7_CRC_NUM_TABLES_USE)50*f6dc9357SAndroid Build Coastguard Worker CRC_FUNC_PRE_LE(Z7_CRC_NUM_TABLES_USE)
51*f6dc9357SAndroid Build Coastguard Worker {
52*f6dc9357SAndroid Build Coastguard Worker const Byte *p = (const Byte *)data;
53*f6dc9357SAndroid Build Coastguard Worker const Byte *lim;
54*f6dc9357SAndroid Build Coastguard Worker for (; size && ((unsigned)(ptrdiff_t)p & (7 - (Z7_CRC_NUM_TABLES_USE & 4))) != 0; size--, p++)
55*f6dc9357SAndroid Build Coastguard Worker v = CRC_UPDATE_BYTE_2(v, *p);
56*f6dc9357SAndroid Build Coastguard Worker lim = p + size;
57*f6dc9357SAndroid Build Coastguard Worker if (size >= Z7_CRC_NUM_TABLES_USE)
58*f6dc9357SAndroid Build Coastguard Worker {
59*f6dc9357SAndroid Build Coastguard Worker lim -= Z7_CRC_NUM_TABLES_USE;
60*f6dc9357SAndroid Build Coastguard Worker do
61*f6dc9357SAndroid Build Coastguard Worker {
62*f6dc9357SAndroid Build Coastguard Worker v ^= R(0);
63*f6dc9357SAndroid Build Coastguard Worker {
64*f6dc9357SAndroid Build Coastguard Worker #if Z7_CRC_NUM_TABLES_USE == 1 * 4
65*f6dc9357SAndroid Build Coastguard Worker v = Q(0, v);
66*f6dc9357SAndroid Build Coastguard Worker #else
67*f6dc9357SAndroid Build Coastguard Worker #define U2(r, op) \
68*f6dc9357SAndroid Build Coastguard Worker { d = R(r); x op Q(Z7_CRC_NUM_TABLES_USE / 4 - 1 - (r), d); }
69*f6dc9357SAndroid Build Coastguard Worker UInt32 d, x;
70*f6dc9357SAndroid Build Coastguard Worker U2(1, =)
71*f6dc9357SAndroid Build Coastguard Worker #if Z7_CRC_NUM_TABLES_USE >= 3 * 4
72*f6dc9357SAndroid Build Coastguard Worker #define U(r) U2(r, ^=)
73*f6dc9357SAndroid Build Coastguard Worker U(2)
74*f6dc9357SAndroid Build Coastguard Worker #if Z7_CRC_NUM_TABLES_USE >= 4 * 4
75*f6dc9357SAndroid Build Coastguard Worker U(3)
76*f6dc9357SAndroid Build Coastguard Worker #if Z7_CRC_NUM_TABLES_USE >= 5 * 4
77*f6dc9357SAndroid Build Coastguard Worker U(4)
78*f6dc9357SAndroid Build Coastguard Worker #if Z7_CRC_NUM_TABLES_USE >= 6 * 4
79*f6dc9357SAndroid Build Coastguard Worker U(5)
80*f6dc9357SAndroid Build Coastguard Worker #if Z7_CRC_NUM_TABLES_USE >= 7 * 4
81*f6dc9357SAndroid Build Coastguard Worker #error Stop_Compiling_Bad_Z7_CRC_NUM_TABLES
82*f6dc9357SAndroid Build Coastguard Worker #endif
83*f6dc9357SAndroid Build Coastguard Worker #endif
84*f6dc9357SAndroid Build Coastguard Worker #endif
85*f6dc9357SAndroid Build Coastguard Worker #endif
86*f6dc9357SAndroid Build Coastguard Worker #endif
87*f6dc9357SAndroid Build Coastguard Worker #undef U
88*f6dc9357SAndroid Build Coastguard Worker #undef U2
89*f6dc9357SAndroid Build Coastguard Worker v = x ^ Q(Z7_CRC_NUM_TABLES_USE / 4 - 1, v);
90*f6dc9357SAndroid Build Coastguard Worker #endif
91*f6dc9357SAndroid Build Coastguard Worker }
92*f6dc9357SAndroid Build Coastguard Worker p += Z7_CRC_NUM_TABLES_USE;
93*f6dc9357SAndroid Build Coastguard Worker }
94*f6dc9357SAndroid Build Coastguard Worker while (p <= lim);
95*f6dc9357SAndroid Build Coastguard Worker lim += Z7_CRC_NUM_TABLES_USE;
96*f6dc9357SAndroid Build Coastguard Worker }
97*f6dc9357SAndroid Build Coastguard Worker for (; p < lim; p++)
98*f6dc9357SAndroid Build Coastguard Worker v = CRC_UPDATE_BYTE_2(v, *p);
99*f6dc9357SAndroid Build Coastguard Worker return v;
100*f6dc9357SAndroid Build Coastguard Worker }
101*f6dc9357SAndroid Build Coastguard Worker
102*f6dc9357SAndroid Build Coastguard Worker #undef CRC_UPDATE_BYTE_2
103*f6dc9357SAndroid Build Coastguard Worker #undef R
104*f6dc9357SAndroid Build Coastguard Worker #undef Q
105*f6dc9357SAndroid Build Coastguard Worker #undef CRC_FUNC_PRE_LE
106*f6dc9357SAndroid Build Coastguard Worker #undef CRC_FUNC_PRE_LE2
107*f6dc9357SAndroid Build Coastguard Worker
108*f6dc9357SAndroid Build Coastguard Worker #endif
109*f6dc9357SAndroid Build Coastguard Worker
110*f6dc9357SAndroid Build Coastguard Worker
111*f6dc9357SAndroid Build Coastguard Worker
112*f6dc9357SAndroid Build Coastguard Worker
113*f6dc9357SAndroid Build Coastguard Worker #ifndef MY_CPU_LE
114*f6dc9357SAndroid Build Coastguard Worker
115*f6dc9357SAndroid Build Coastguard Worker #define CRC_UPDATE_BYTE_2_BE(crc, b) (table[((crc) >> 24) ^ (b)] ^ ((crc) << 8))
116*f6dc9357SAndroid Build Coastguard Worker
117*f6dc9357SAndroid Build Coastguard Worker #define Q(n, d) \
118*f6dc9357SAndroid Build Coastguard Worker ( (table + ((n) * 4 + 0) * 0x100)[((d)) & 0xFF] \
119*f6dc9357SAndroid Build Coastguard Worker ^ (table + ((n) * 4 + 1) * 0x100)[((d) >> 1 * 8) & 0xFF] \
120*f6dc9357SAndroid Build Coastguard Worker ^ (table + ((n) * 4 + 2) * 0x100)[((d) >> 2 * 8) & 0xFF] \
121*f6dc9357SAndroid Build Coastguard Worker ^ (table + ((n) * 4 + 3) * 0x100)[((d) >> 3 * 8)] )
122*f6dc9357SAndroid Build Coastguard Worker
123*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_CRC_DEBUG_BE
124*f6dc9357SAndroid Build Coastguard Worker #define R(a) GetBe32a((const UInt32 *)(const void *)p + (a))
125*f6dc9357SAndroid Build Coastguard Worker #else
126*f6dc9357SAndroid Build Coastguard Worker #define R(a) *((const UInt32 *)(const void *)p + (a))
127*f6dc9357SAndroid Build Coastguard Worker #endif
128*f6dc9357SAndroid Build Coastguard Worker
129*f6dc9357SAndroid Build Coastguard Worker
130*f6dc9357SAndroid Build Coastguard Worker #define CRC_FUNC_PRE_BE2(step) \
131*f6dc9357SAndroid Build Coastguard Worker UInt32 Z7_FASTCALL CrcUpdateT1_BeT ## step (UInt32 v, const void *data, size_t size, const UInt32 *table)
132*f6dc9357SAndroid Build Coastguard Worker
133*f6dc9357SAndroid Build Coastguard Worker #define CRC_FUNC_PRE_BE(step) \
134*f6dc9357SAndroid Build Coastguard Worker CRC_FUNC_PRE_BE2(step); \
135*f6dc9357SAndroid Build Coastguard Worker CRC_FUNC_PRE_BE2(step)
136*f6dc9357SAndroid Build Coastguard Worker
CRC_FUNC_PRE_BE(Z7_CRC_NUM_TABLES_USE)137*f6dc9357SAndroid Build Coastguard Worker CRC_FUNC_PRE_BE(Z7_CRC_NUM_TABLES_USE)
138*f6dc9357SAndroid Build Coastguard Worker {
139*f6dc9357SAndroid Build Coastguard Worker const Byte *p = (const Byte *)data;
140*f6dc9357SAndroid Build Coastguard Worker const Byte *lim;
141*f6dc9357SAndroid Build Coastguard Worker table += 0x100;
142*f6dc9357SAndroid Build Coastguard Worker v = Z7_BSWAP32(v);
143*f6dc9357SAndroid Build Coastguard Worker for (; size && ((unsigned)(ptrdiff_t)p & (7 - (Z7_CRC_NUM_TABLES_USE & 4))) != 0; size--, p++)
144*f6dc9357SAndroid Build Coastguard Worker v = CRC_UPDATE_BYTE_2_BE(v, *p);
145*f6dc9357SAndroid Build Coastguard Worker lim = p + size;
146*f6dc9357SAndroid Build Coastguard Worker if (size >= Z7_CRC_NUM_TABLES_USE)
147*f6dc9357SAndroid Build Coastguard Worker {
148*f6dc9357SAndroid Build Coastguard Worker lim -= Z7_CRC_NUM_TABLES_USE;
149*f6dc9357SAndroid Build Coastguard Worker do
150*f6dc9357SAndroid Build Coastguard Worker {
151*f6dc9357SAndroid Build Coastguard Worker v ^= R(0);
152*f6dc9357SAndroid Build Coastguard Worker {
153*f6dc9357SAndroid Build Coastguard Worker #if Z7_CRC_NUM_TABLES_USE == 1 * 4
154*f6dc9357SAndroid Build Coastguard Worker v = Q(0, v);
155*f6dc9357SAndroid Build Coastguard Worker #else
156*f6dc9357SAndroid Build Coastguard Worker #define U2(r, op) \
157*f6dc9357SAndroid Build Coastguard Worker { d = R(r); x op Q(Z7_CRC_NUM_TABLES_USE / 4 - 1 - (r), d); }
158*f6dc9357SAndroid Build Coastguard Worker UInt32 d, x;
159*f6dc9357SAndroid Build Coastguard Worker U2(1, =)
160*f6dc9357SAndroid Build Coastguard Worker #if Z7_CRC_NUM_TABLES_USE >= 3 * 4
161*f6dc9357SAndroid Build Coastguard Worker #define U(r) U2(r, ^=)
162*f6dc9357SAndroid Build Coastguard Worker U(2)
163*f6dc9357SAndroid Build Coastguard Worker #if Z7_CRC_NUM_TABLES_USE >= 4 * 4
164*f6dc9357SAndroid Build Coastguard Worker U(3)
165*f6dc9357SAndroid Build Coastguard Worker #if Z7_CRC_NUM_TABLES_USE >= 5 * 4
166*f6dc9357SAndroid Build Coastguard Worker U(4)
167*f6dc9357SAndroid Build Coastguard Worker #if Z7_CRC_NUM_TABLES_USE >= 6 * 4
168*f6dc9357SAndroid Build Coastguard Worker U(5)
169*f6dc9357SAndroid Build Coastguard Worker #if Z7_CRC_NUM_TABLES_USE >= 7 * 4
170*f6dc9357SAndroid Build Coastguard Worker #error Stop_Compiling_Bad_Z7_CRC_NUM_TABLES
171*f6dc9357SAndroid Build Coastguard Worker #endif
172*f6dc9357SAndroid Build Coastguard Worker #endif
173*f6dc9357SAndroid Build Coastguard Worker #endif
174*f6dc9357SAndroid Build Coastguard Worker #endif
175*f6dc9357SAndroid Build Coastguard Worker #endif
176*f6dc9357SAndroid Build Coastguard Worker #undef U
177*f6dc9357SAndroid Build Coastguard Worker #undef U2
178*f6dc9357SAndroid Build Coastguard Worker v = x ^ Q(Z7_CRC_NUM_TABLES_USE / 4 - 1, v);
179*f6dc9357SAndroid Build Coastguard Worker #endif
180*f6dc9357SAndroid Build Coastguard Worker }
181*f6dc9357SAndroid Build Coastguard Worker p += Z7_CRC_NUM_TABLES_USE;
182*f6dc9357SAndroid Build Coastguard Worker }
183*f6dc9357SAndroid Build Coastguard Worker while (p <= lim);
184*f6dc9357SAndroid Build Coastguard Worker lim += Z7_CRC_NUM_TABLES_USE;
185*f6dc9357SAndroid Build Coastguard Worker }
186*f6dc9357SAndroid Build Coastguard Worker for (; p < lim; p++)
187*f6dc9357SAndroid Build Coastguard Worker v = CRC_UPDATE_BYTE_2_BE(v, *p);
188*f6dc9357SAndroid Build Coastguard Worker return Z7_BSWAP32(v);
189*f6dc9357SAndroid Build Coastguard Worker }
190*f6dc9357SAndroid Build Coastguard Worker
191*f6dc9357SAndroid Build Coastguard Worker #undef CRC_UPDATE_BYTE_2_BE
192*f6dc9357SAndroid Build Coastguard Worker #undef R
193*f6dc9357SAndroid Build Coastguard Worker #undef Q
194*f6dc9357SAndroid Build Coastguard Worker #undef CRC_FUNC_PRE_BE
195*f6dc9357SAndroid Build Coastguard Worker #undef CRC_FUNC_PRE_BE2
196*f6dc9357SAndroid Build Coastguard Worker
197*f6dc9357SAndroid Build Coastguard Worker #endif
198*f6dc9357SAndroid Build Coastguard Worker #undef Z7_CRC_NUM_TABLES_USE
199*f6dc9357SAndroid Build Coastguard Worker #endif
200