1ab9e68a2SToomas Soome /* crc32.c -- compute the CRC-32 of a data stream
2*64c3d159SToomas Soome * Copyright (C) 1995-2022 Mark Adler
3ab9e68a2SToomas Soome * For conditions of distribution and use, see copyright notice in zlib.h
4ab9e68a2SToomas Soome *
5*64c3d159SToomas Soome * This interleaved implementation of a CRC makes use of pipelined multiple
6*64c3d159SToomas Soome * arithmetic-logic units, commonly found in modern CPU cores. It is due to
7*64c3d159SToomas Soome * Kadatch and Jenkins (2010). See doc/crc-doc.1.0.pdf in this distribution.
8ab9e68a2SToomas Soome */
9ab9e68a2SToomas Soome
10ab9e68a2SToomas Soome /*
11ab9e68a2SToomas Soome Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore
12ab9e68a2SToomas Soome protection on the static variables used to control the first-use generation
13ab9e68a2SToomas Soome of the crc tables. Therefore, if you #define DYNAMIC_CRC_TABLE, you should
14ab9e68a2SToomas Soome first call get_crc_table() to initialize the tables before allowing more than
15ab9e68a2SToomas Soome one thread to use crc32().
16ab9e68a2SToomas Soome
17*64c3d159SToomas Soome MAKECRCH can be #defined to write out crc32.h. A main() routine is also
18*64c3d159SToomas Soome produced, so that this one source file can be compiled to an executable.
19ab9e68a2SToomas Soome */
20ab9e68a2SToomas Soome
21ab9e68a2SToomas Soome #ifdef MAKECRCH
22ab9e68a2SToomas Soome # include <stdio.h>
23ab9e68a2SToomas Soome # ifndef DYNAMIC_CRC_TABLE
24ab9e68a2SToomas Soome # define DYNAMIC_CRC_TABLE
25ab9e68a2SToomas Soome # endif /* !DYNAMIC_CRC_TABLE */
26ab9e68a2SToomas Soome #endif /* MAKECRCH */
27ab9e68a2SToomas Soome
28*64c3d159SToomas Soome #include "zutil.h" /* for Z_U4, Z_U8, z_crc_t, and FAR definitions */
29ab9e68a2SToomas Soome
30*64c3d159SToomas Soome /*
31*64c3d159SToomas Soome A CRC of a message is computed on N braids of words in the message, where
32*64c3d159SToomas Soome each word consists of W bytes (4 or 8). If N is 3, for example, then three
33*64c3d159SToomas Soome running sparse CRCs are calculated respectively on each braid, at these
34*64c3d159SToomas Soome indices in the array of words: 0, 3, 6, ..., 1, 4, 7, ..., and 2, 5, 8, ...
35*64c3d159SToomas Soome This is done starting at a word boundary, and continues until as many blocks
36*64c3d159SToomas Soome of N * W bytes as are available have been processed. The results are combined
37*64c3d159SToomas Soome into a single CRC at the end. For this code, N must be in the range 1..6 and
38*64c3d159SToomas Soome W must be 4 or 8. The upper limit on N can be increased if desired by adding
39*64c3d159SToomas Soome more #if blocks, extending the patterns apparent in the code. In addition,
40*64c3d159SToomas Soome crc32.h would need to be regenerated, if the maximum N value is increased.
41*64c3d159SToomas Soome
42*64c3d159SToomas Soome N and W are chosen empirically by benchmarking the execution time on a given
43*64c3d159SToomas Soome processor. The choices for N and W below were based on testing on Intel Kaby
44*64c3d159SToomas Soome Lake i7, AMD Ryzen 7, ARM Cortex-A57, Sparc64-VII, PowerPC POWER9, and MIPS64
45*64c3d159SToomas Soome Octeon II processors. The Intel, AMD, and ARM processors were all fastest
46*64c3d159SToomas Soome with N=5, W=8. The Sparc, PowerPC, and MIPS64 were all fastest at N=5, W=4.
47*64c3d159SToomas Soome They were all tested with either gcc or clang, all using the -O3 optimization
48*64c3d159SToomas Soome level. Your mileage may vary.
49*64c3d159SToomas Soome */
50*64c3d159SToomas Soome
51*64c3d159SToomas Soome /* Define N */
52*64c3d159SToomas Soome #ifdef Z_TESTN
53*64c3d159SToomas Soome # define N Z_TESTN
54ab9e68a2SToomas Soome #else
55*64c3d159SToomas Soome # define N 5
56*64c3d159SToomas Soome #endif
57*64c3d159SToomas Soome #if N < 1 || N > 6
58*64c3d159SToomas Soome # error N must be in 1..6
59*64c3d159SToomas Soome #endif
60ab9e68a2SToomas Soome
61*64c3d159SToomas Soome /*
62*64c3d159SToomas Soome z_crc_t must be at least 32 bits. z_word_t must be at least as long as
63*64c3d159SToomas Soome z_crc_t. It is assumed here that z_word_t is either 32 bits or 64 bits, and
64*64c3d159SToomas Soome that bytes are eight bits.
65*64c3d159SToomas Soome */
66ab9e68a2SToomas Soome
67*64c3d159SToomas Soome /*
68*64c3d159SToomas Soome Define W and the associated z_word_t type. If W is not defined, then a
69*64c3d159SToomas Soome braided calculation is not used, and the associated tables and code are not
70*64c3d159SToomas Soome compiled.
71*64c3d159SToomas Soome */
72*64c3d159SToomas Soome #ifdef Z_TESTW
73*64c3d159SToomas Soome # if Z_TESTW-1 != -1
74*64c3d159SToomas Soome # define W Z_TESTW
75*64c3d159SToomas Soome # endif
76*64c3d159SToomas Soome #else
77*64c3d159SToomas Soome # ifdef MAKECRCH
78*64c3d159SToomas Soome # define W 8 /* required for MAKECRCH */
79*64c3d159SToomas Soome # else
80*64c3d159SToomas Soome # if defined(__x86_64__) || defined(__aarch64__)
81*64c3d159SToomas Soome # define W 8
82*64c3d159SToomas Soome # else
83*64c3d159SToomas Soome # define W 4
84*64c3d159SToomas Soome # endif
85*64c3d159SToomas Soome # endif
86*64c3d159SToomas Soome #endif
87*64c3d159SToomas Soome #ifdef W
88*64c3d159SToomas Soome # if W == 8 && defined(Z_U8)
89*64c3d159SToomas Soome typedef Z_U8 z_word_t;
90*64c3d159SToomas Soome # elif defined(Z_U4)
91*64c3d159SToomas Soome # undef W
92*64c3d159SToomas Soome # define W 4
93*64c3d159SToomas Soome typedef Z_U4 z_word_t;
94*64c3d159SToomas Soome # else
95*64c3d159SToomas Soome # undef W
96*64c3d159SToomas Soome # endif
97*64c3d159SToomas Soome #endif
98*64c3d159SToomas Soome
99*64c3d159SToomas Soome /* Local functions. */
100*64c3d159SToomas Soome local z_crc_t multmodp OF((z_crc_t a, z_crc_t b));
101*64c3d159SToomas Soome local z_crc_t x2nmodp OF((z_off64_t n, unsigned k));
102*64c3d159SToomas Soome
103*64c3d159SToomas Soome /* If available, use the ARM processor CRC32 instruction. */
104*64c3d159SToomas Soome #if defined(__aarch64__) && defined(__ARM_FEATURE_CRC32) && W == 8
105*64c3d159SToomas Soome # define ARMCRC32
106*64c3d159SToomas Soome #endif
107*64c3d159SToomas Soome
108*64c3d159SToomas Soome #if defined(W) && (!defined(ARMCRC32) || defined(DYNAMIC_CRC_TABLE))
109*64c3d159SToomas Soome /*
110*64c3d159SToomas Soome Swap the bytes in a z_word_t to convert between little and big endian. Any
111*64c3d159SToomas Soome self-respecting compiler will optimize this to a single machine byte-swap
112*64c3d159SToomas Soome instruction, if one is available. This assumes that word_t is either 32 bits
113*64c3d159SToomas Soome or 64 bits.
114*64c3d159SToomas Soome */
byte_swap(z_word_t word)115*64c3d159SToomas Soome local z_word_t byte_swap(z_word_t word)
116*64c3d159SToomas Soome {
117*64c3d159SToomas Soome # if W == 8
118*64c3d159SToomas Soome return
119*64c3d159SToomas Soome (word & 0xff00000000000000) >> 56 |
120*64c3d159SToomas Soome (word & 0xff000000000000) >> 40 |
121*64c3d159SToomas Soome (word & 0xff0000000000) >> 24 |
122*64c3d159SToomas Soome (word & 0xff00000000) >> 8 |
123*64c3d159SToomas Soome (word & 0xff000000) << 8 |
124*64c3d159SToomas Soome (word & 0xff0000) << 24 |
125*64c3d159SToomas Soome (word & 0xff00) << 40 |
126*64c3d159SToomas Soome (word & 0xff) << 56;
127*64c3d159SToomas Soome # else /* W == 4 */
128*64c3d159SToomas Soome return
129*64c3d159SToomas Soome (word & 0xff000000) >> 24 |
130*64c3d159SToomas Soome (word & 0xff0000) >> 8 |
131*64c3d159SToomas Soome (word & 0xff00) << 8 |
132*64c3d159SToomas Soome (word & 0xff) << 24;
133*64c3d159SToomas Soome # endif
134*64c3d159SToomas Soome }
135*64c3d159SToomas Soome #endif
136*64c3d159SToomas Soome
137*64c3d159SToomas Soome /* CRC polynomial. */
138*64c3d159SToomas Soome #define POLY 0xedb88320 /* p(x) reflected, with x^32 implied */
139ab9e68a2SToomas Soome
140ab9e68a2SToomas Soome #ifdef DYNAMIC_CRC_TABLE
141ab9e68a2SToomas Soome
142*64c3d159SToomas Soome local z_crc_t FAR crc_table[256];
143*64c3d159SToomas Soome local z_crc_t FAR x2n_table[32];
144ab9e68a2SToomas Soome local void make_crc_table OF((void));
145*64c3d159SToomas Soome #ifdef W
146*64c3d159SToomas Soome local z_word_t FAR crc_big_table[256];
147*64c3d159SToomas Soome local z_crc_t FAR crc_braid_table[W][256];
148*64c3d159SToomas Soome local z_word_t FAR crc_braid_big_table[W][256];
149*64c3d159SToomas Soome local void braid OF((z_crc_t [][256], z_word_t [][256], int, int));
150*64c3d159SToomas Soome #endif
151ab9e68a2SToomas Soome #ifdef MAKECRCH
152*64c3d159SToomas Soome local void write_table OF((FILE *, const z_crc_t FAR *, int));
153*64c3d159SToomas Soome local void write_table32hi OF((FILE *, const z_word_t FAR *, int));
154*64c3d159SToomas Soome local void write_table64 OF((FILE *, const z_word_t FAR *, int));
155ab9e68a2SToomas Soome #endif /* MAKECRCH */
156*64c3d159SToomas Soome
157*64c3d159SToomas Soome /*
158*64c3d159SToomas Soome Define a once() function depending on the availability of atomics. If this is
159*64c3d159SToomas Soome compiled with DYNAMIC_CRC_TABLE defined, and if CRCs will be computed in
160*64c3d159SToomas Soome multiple threads, and if atomics are not available, then get_crc_table() must
161*64c3d159SToomas Soome be called to initialize the tables and must return before any threads are
162*64c3d159SToomas Soome allowed to compute or combine CRCs.
163*64c3d159SToomas Soome */
164*64c3d159SToomas Soome
165*64c3d159SToomas Soome /* Definition of once functionality. */
166*64c3d159SToomas Soome typedef struct once_s once_t;
167*64c3d159SToomas Soome local void once OF((once_t *, void (*)(void)));
168*64c3d159SToomas Soome
169*64c3d159SToomas Soome /* Check for the availability of atomics. */
170*64c3d159SToomas Soome #if defined(__STDC__) && __STDC_VERSION__ >= 201112L && \
171*64c3d159SToomas Soome !defined(__STDC_NO_ATOMICS__)
172*64c3d159SToomas Soome
173*64c3d159SToomas Soome #include <stdatomic.h>
174*64c3d159SToomas Soome
175*64c3d159SToomas Soome /* Structure for once(), which must be initialized with ONCE_INIT. */
176*64c3d159SToomas Soome struct once_s {
177*64c3d159SToomas Soome atomic_flag begun;
178*64c3d159SToomas Soome atomic_int done;
179*64c3d159SToomas Soome };
180*64c3d159SToomas Soome #define ONCE_INIT {ATOMIC_FLAG_INIT, 0}
181*64c3d159SToomas Soome
182*64c3d159SToomas Soome /*
183*64c3d159SToomas Soome Run the provided init() function exactly once, even if multiple threads
184*64c3d159SToomas Soome invoke once() at the same time. The state must be a once_t initialized with
185*64c3d159SToomas Soome ONCE_INIT.
186*64c3d159SToomas Soome */
once(state,init)187*64c3d159SToomas Soome local void once(state, init)
188*64c3d159SToomas Soome once_t *state;
189*64c3d159SToomas Soome void (*init)(void);
190*64c3d159SToomas Soome {
191*64c3d159SToomas Soome if (!atomic_load(&state->done)) {
192*64c3d159SToomas Soome if (atomic_flag_test_and_set(&state->begun))
193*64c3d159SToomas Soome while (!atomic_load(&state->done))
194*64c3d159SToomas Soome ;
195*64c3d159SToomas Soome else {
196*64c3d159SToomas Soome init();
197*64c3d159SToomas Soome atomic_store(&state->done, 1);
198*64c3d159SToomas Soome }
199*64c3d159SToomas Soome }
200*64c3d159SToomas Soome }
201*64c3d159SToomas Soome
202*64c3d159SToomas Soome #else /* no atomics */
203*64c3d159SToomas Soome
204*64c3d159SToomas Soome /* Structure for once(), which must be initialized with ONCE_INIT. */
205*64c3d159SToomas Soome struct once_s {
206*64c3d159SToomas Soome volatile int begun;
207*64c3d159SToomas Soome volatile int done;
208*64c3d159SToomas Soome };
209*64c3d159SToomas Soome #define ONCE_INIT {0, 0}
210*64c3d159SToomas Soome
211*64c3d159SToomas Soome /* Test and set. Alas, not atomic, but tries to minimize the period of
212*64c3d159SToomas Soome vulnerability. */
213*64c3d159SToomas Soome local int test_and_set OF((int volatile *));
test_and_set(flag)214*64c3d159SToomas Soome local int test_and_set(flag)
215*64c3d159SToomas Soome int volatile *flag;
216*64c3d159SToomas Soome {
217*64c3d159SToomas Soome int was;
218*64c3d159SToomas Soome
219*64c3d159SToomas Soome was = *flag;
220*64c3d159SToomas Soome *flag = 1;
221*64c3d159SToomas Soome return was;
222*64c3d159SToomas Soome }
223*64c3d159SToomas Soome
224*64c3d159SToomas Soome /* Run the provided init() function once. This is not thread-safe. */
once(state,init)225*64c3d159SToomas Soome local void once(state, init)
226*64c3d159SToomas Soome once_t *state;
227*64c3d159SToomas Soome void (*init)(void);
228*64c3d159SToomas Soome {
229*64c3d159SToomas Soome if (!state->done) {
230*64c3d159SToomas Soome if (test_and_set(&state->begun))
231*64c3d159SToomas Soome while (!state->done)
232*64c3d159SToomas Soome ;
233*64c3d159SToomas Soome else {
234*64c3d159SToomas Soome init();
235*64c3d159SToomas Soome state->done = 1;
236*64c3d159SToomas Soome }
237*64c3d159SToomas Soome }
238*64c3d159SToomas Soome }
239*64c3d159SToomas Soome
240*64c3d159SToomas Soome #endif
241*64c3d159SToomas Soome
242*64c3d159SToomas Soome /* State for once(). */
243*64c3d159SToomas Soome local once_t made = ONCE_INIT;
244*64c3d159SToomas Soome
245ab9e68a2SToomas Soome /*
246ab9e68a2SToomas Soome Generate tables for a byte-wise 32-bit CRC calculation on the polynomial:
247ab9e68a2SToomas Soome x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1.
248ab9e68a2SToomas Soome
249ab9e68a2SToomas Soome Polynomials over GF(2) are represented in binary, one bit per coefficient,
250ab9e68a2SToomas Soome with the lowest powers in the most significant bit. Then adding polynomials
251ab9e68a2SToomas Soome is just exclusive-or, and multiplying a polynomial by x is a right shift by
252ab9e68a2SToomas Soome one. If we call the above polynomial p, and represent a byte as the
253ab9e68a2SToomas Soome polynomial q, also with the lowest power in the most significant bit (so the
254*64c3d159SToomas Soome byte 0xb1 is the polynomial x^7+x^3+x^2+1), then the CRC is (q*x^32) mod p,
255ab9e68a2SToomas Soome where a mod b means the remainder after dividing a by b.
256ab9e68a2SToomas Soome
257ab9e68a2SToomas Soome This calculation is done using the shift-register method of multiplying and
258ab9e68a2SToomas Soome taking the remainder. The register is initialized to zero, and for each
259ab9e68a2SToomas Soome incoming bit, x^32 is added mod p to the register if the bit is a one (where
260*64c3d159SToomas Soome x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by x
261*64c3d159SToomas Soome (which is shifting right by one and adding x^32 mod p if the bit shifted out
262*64c3d159SToomas Soome is a one). We start with the highest power (least significant bit) of q and
263*64c3d159SToomas Soome repeat for all eight bits of q.
264ab9e68a2SToomas Soome
265*64c3d159SToomas Soome The table is simply the CRC of all possible eight bit values. This is all the
266*64c3d159SToomas Soome information needed to generate CRCs on data a byte at a time for all
267*64c3d159SToomas Soome combinations of CRC register values and incoming bytes.
268ab9e68a2SToomas Soome */
269*64c3d159SToomas Soome
make_crc_table()270ab9e68a2SToomas Soome local void make_crc_table()
271ab9e68a2SToomas Soome {
272*64c3d159SToomas Soome unsigned i, j, n;
273*64c3d159SToomas Soome z_crc_t p;
274ab9e68a2SToomas Soome
275*64c3d159SToomas Soome /* initialize the CRC of bytes tables */
276*64c3d159SToomas Soome for (i = 0; i < 256; i++) {
277*64c3d159SToomas Soome p = i;
278*64c3d159SToomas Soome for (j = 0; j < 8; j++)
279*64c3d159SToomas Soome p = p & 1 ? (p >> 1) ^ POLY : p >> 1;
280*64c3d159SToomas Soome crc_table[i] = p;
281*64c3d159SToomas Soome #ifdef W
282*64c3d159SToomas Soome crc_big_table[i] = byte_swap(p);
283*64c3d159SToomas Soome #endif
284ab9e68a2SToomas Soome }
285ab9e68a2SToomas Soome
286*64c3d159SToomas Soome /* initialize the x^2^n mod p(x) table */
287*64c3d159SToomas Soome p = (z_crc_t)1 << 30; /* x^1 */
288*64c3d159SToomas Soome x2n_table[0] = p;
289*64c3d159SToomas Soome for (n = 1; n < 32; n++)
290*64c3d159SToomas Soome x2n_table[n] = p = multmodp(p, p);
291ab9e68a2SToomas Soome
292*64c3d159SToomas Soome #ifdef W
293*64c3d159SToomas Soome /* initialize the braiding tables -- needs x2n_table[] */
294*64c3d159SToomas Soome braid(crc_braid_table, crc_braid_big_table, N, W);
295*64c3d159SToomas Soome #endif
296ab9e68a2SToomas Soome
297ab9e68a2SToomas Soome #ifdef MAKECRCH
298ab9e68a2SToomas Soome {
299*64c3d159SToomas Soome /*
300*64c3d159SToomas Soome The crc32.h header file contains tables for both 32-bit and 64-bit
301*64c3d159SToomas Soome z_word_t's, and so requires a 64-bit type be available. In that case,
302*64c3d159SToomas Soome z_word_t must be defined to be 64-bits. This code then also generates
303*64c3d159SToomas Soome and writes out the tables for the case that z_word_t is 32 bits.
304*64c3d159SToomas Soome */
305*64c3d159SToomas Soome #if !defined(W) || W != 8
306*64c3d159SToomas Soome # error Need a 64-bit integer type in order to generate crc32.h.
307*64c3d159SToomas Soome #endif
308ab9e68a2SToomas Soome FILE *out;
309*64c3d159SToomas Soome int k, n;
310*64c3d159SToomas Soome z_crc_t ltl[8][256];
311*64c3d159SToomas Soome z_word_t big[8][256];
312ab9e68a2SToomas Soome
313ab9e68a2SToomas Soome out = fopen("crc32.h", "w");
314ab9e68a2SToomas Soome if (out == NULL) return;
315*64c3d159SToomas Soome
316*64c3d159SToomas Soome /* write out little-endian CRC table to crc32.h */
317*64c3d159SToomas Soome fprintf(out,
318*64c3d159SToomas Soome "/* crc32.h -- tables for rapid CRC calculation\n"
319*64c3d159SToomas Soome " * Generated automatically by crc32.c\n */\n"
320*64c3d159SToomas Soome "\n"
321*64c3d159SToomas Soome "local const z_crc_t FAR crc_table[] = {\n"
322*64c3d159SToomas Soome " ");
323*64c3d159SToomas Soome write_table(out, crc_table, 256);
324*64c3d159SToomas Soome fprintf(out,
325*64c3d159SToomas Soome "};\n");
326*64c3d159SToomas Soome
327*64c3d159SToomas Soome /* write out big-endian CRC table for 64-bit z_word_t to crc32.h */
328*64c3d159SToomas Soome fprintf(out,
329*64c3d159SToomas Soome "\n"
330*64c3d159SToomas Soome "#ifdef W\n"
331*64c3d159SToomas Soome "\n"
332*64c3d159SToomas Soome "#if W == 8\n"
333*64c3d159SToomas Soome "\n"
334*64c3d159SToomas Soome "local const z_word_t FAR crc_big_table[] = {\n"
335*64c3d159SToomas Soome " ");
336*64c3d159SToomas Soome write_table64(out, crc_big_table, 256);
337*64c3d159SToomas Soome fprintf(out,
338*64c3d159SToomas Soome "};\n");
339*64c3d159SToomas Soome
340*64c3d159SToomas Soome /* write out big-endian CRC table for 32-bit z_word_t to crc32.h */
341*64c3d159SToomas Soome fprintf(out,
342*64c3d159SToomas Soome "\n"
343*64c3d159SToomas Soome "#else /* W == 4 */\n"
344*64c3d159SToomas Soome "\n"
345*64c3d159SToomas Soome "local const z_word_t FAR crc_big_table[] = {\n"
346*64c3d159SToomas Soome " ");
347*64c3d159SToomas Soome write_table32hi(out, crc_big_table, 256);
348*64c3d159SToomas Soome fprintf(out,
349*64c3d159SToomas Soome "};\n"
350*64c3d159SToomas Soome "\n"
351*64c3d159SToomas Soome "#endif\n");
352*64c3d159SToomas Soome
353*64c3d159SToomas Soome /* write out braid tables for each value of N */
354*64c3d159SToomas Soome for (n = 1; n <= 6; n++) {
355*64c3d159SToomas Soome fprintf(out,
356*64c3d159SToomas Soome "\n"
357*64c3d159SToomas Soome "#if N == %d\n", n);
358*64c3d159SToomas Soome
359*64c3d159SToomas Soome /* compute braid tables for this N and 64-bit word_t */
360*64c3d159SToomas Soome braid(ltl, big, n, 8);
361*64c3d159SToomas Soome
362*64c3d159SToomas Soome /* write out braid tables for 64-bit z_word_t to crc32.h */
363*64c3d159SToomas Soome fprintf(out,
364*64c3d159SToomas Soome "\n"
365*64c3d159SToomas Soome "#if W == 8\n"
366*64c3d159SToomas Soome "\n"
367*64c3d159SToomas Soome "local const z_crc_t FAR crc_braid_table[][256] = {\n");
368*64c3d159SToomas Soome for (k = 0; k < 8; k++) {
369*64c3d159SToomas Soome fprintf(out, " {");
370*64c3d159SToomas Soome write_table(out, ltl[k], 256);
371*64c3d159SToomas Soome fprintf(out, "}%s", k < 7 ? ",\n" : "");
372ab9e68a2SToomas Soome }
373*64c3d159SToomas Soome fprintf(out,
374*64c3d159SToomas Soome "};\n"
375*64c3d159SToomas Soome "\n"
376*64c3d159SToomas Soome "local const z_word_t FAR crc_braid_big_table[][256] = {\n");
377*64c3d159SToomas Soome for (k = 0; k < 8; k++) {
378*64c3d159SToomas Soome fprintf(out, " {");
379*64c3d159SToomas Soome write_table64(out, big[k], 256);
380*64c3d159SToomas Soome fprintf(out, "}%s", k < 7 ? ",\n" : "");
381*64c3d159SToomas Soome }
382*64c3d159SToomas Soome fprintf(out,
383*64c3d159SToomas Soome "};\n");
384*64c3d159SToomas Soome
385*64c3d159SToomas Soome /* compute braid tables for this N and 32-bit word_t */
386*64c3d159SToomas Soome braid(ltl, big, n, 4);
387*64c3d159SToomas Soome
388*64c3d159SToomas Soome /* write out braid tables for 32-bit z_word_t to crc32.h */
389*64c3d159SToomas Soome fprintf(out,
390*64c3d159SToomas Soome "\n"
391*64c3d159SToomas Soome "#else /* W == 4 */\n"
392*64c3d159SToomas Soome "\n"
393*64c3d159SToomas Soome "local const z_crc_t FAR crc_braid_table[][256] = {\n");
394*64c3d159SToomas Soome for (k = 0; k < 4; k++) {
395*64c3d159SToomas Soome fprintf(out, " {");
396*64c3d159SToomas Soome write_table(out, ltl[k], 256);
397*64c3d159SToomas Soome fprintf(out, "}%s", k < 3 ? ",\n" : "");
398*64c3d159SToomas Soome }
399*64c3d159SToomas Soome fprintf(out,
400*64c3d159SToomas Soome "};\n"
401*64c3d159SToomas Soome "\n"
402*64c3d159SToomas Soome "local const z_word_t FAR crc_braid_big_table[][256] = {\n");
403*64c3d159SToomas Soome for (k = 0; k < 4; k++) {
404*64c3d159SToomas Soome fprintf(out, " {");
405*64c3d159SToomas Soome write_table32hi(out, big[k], 256);
406*64c3d159SToomas Soome fprintf(out, "}%s", k < 3 ? ",\n" : "");
407*64c3d159SToomas Soome }
408*64c3d159SToomas Soome fprintf(out,
409*64c3d159SToomas Soome "};\n"
410*64c3d159SToomas Soome "\n"
411*64c3d159SToomas Soome "#endif\n"
412*64c3d159SToomas Soome "\n"
413*64c3d159SToomas Soome "#endif\n");
414*64c3d159SToomas Soome }
415*64c3d159SToomas Soome fprintf(out,
416*64c3d159SToomas Soome "\n"
417*64c3d159SToomas Soome "#endif\n");
418*64c3d159SToomas Soome
419*64c3d159SToomas Soome /* write out zeros operator table to crc32.h */
420*64c3d159SToomas Soome fprintf(out,
421*64c3d159SToomas Soome "\n"
422*64c3d159SToomas Soome "local const z_crc_t FAR x2n_table[] = {\n"
423*64c3d159SToomas Soome " ");
424*64c3d159SToomas Soome write_table(out, x2n_table, 32);
425*64c3d159SToomas Soome fprintf(out,
426*64c3d159SToomas Soome "};\n");
427ab9e68a2SToomas Soome fclose(out);
428ab9e68a2SToomas Soome }
429ab9e68a2SToomas Soome #endif /* MAKECRCH */
430ab9e68a2SToomas Soome }
431ab9e68a2SToomas Soome
432ab9e68a2SToomas Soome #ifdef MAKECRCH
433*64c3d159SToomas Soome
434*64c3d159SToomas Soome /*
435*64c3d159SToomas Soome Write the 32-bit values in table[0..k-1] to out, five per line in
436*64c3d159SToomas Soome hexadecimal separated by commas.
437*64c3d159SToomas Soome */
write_table(out,table,k)438*64c3d159SToomas Soome local void write_table(out, table, k)
439ab9e68a2SToomas Soome FILE *out;
440ab9e68a2SToomas Soome const z_crc_t FAR *table;
441*64c3d159SToomas Soome int k;
442ab9e68a2SToomas Soome {
443ab9e68a2SToomas Soome int n;
444ab9e68a2SToomas Soome
445*64c3d159SToomas Soome for (n = 0; n < k; n++)
446*64c3d159SToomas Soome fprintf(out, "%s0x%08lx%s", n == 0 || n % 5 ? "" : " ",
447ab9e68a2SToomas Soome (unsigned long)(table[n]),
448*64c3d159SToomas Soome n == k - 1 ? "" : (n % 5 == 4 ? ",\n" : ", "));
449ab9e68a2SToomas Soome }
450*64c3d159SToomas Soome
451*64c3d159SToomas Soome /*
452*64c3d159SToomas Soome Write the high 32-bits of each value in table[0..k-1] to out, five per line
453*64c3d159SToomas Soome in hexadecimal separated by commas.
454*64c3d159SToomas Soome */
write_table32hi(out,table,k)455*64c3d159SToomas Soome local void write_table32hi(out, table, k)
456*64c3d159SToomas Soome FILE *out;
457*64c3d159SToomas Soome const z_word_t FAR *table;
458*64c3d159SToomas Soome int k;
459*64c3d159SToomas Soome {
460*64c3d159SToomas Soome int n;
461*64c3d159SToomas Soome
462*64c3d159SToomas Soome for (n = 0; n < k; n++)
463*64c3d159SToomas Soome fprintf(out, "%s0x%08lx%s", n == 0 || n % 5 ? "" : " ",
464*64c3d159SToomas Soome (unsigned long)(table[n] >> 32),
465*64c3d159SToomas Soome n == k - 1 ? "" : (n % 5 == 4 ? ",\n" : ", "));
466*64c3d159SToomas Soome }
467*64c3d159SToomas Soome
468*64c3d159SToomas Soome /*
469*64c3d159SToomas Soome Write the 64-bit values in table[0..k-1] to out, three per line in
470*64c3d159SToomas Soome hexadecimal separated by commas. This assumes that if there is a 64-bit
471*64c3d159SToomas Soome type, then there is also a long long integer type, and it is at least 64
472*64c3d159SToomas Soome bits. If not, then the type cast and format string can be adjusted
473*64c3d159SToomas Soome accordingly.
474*64c3d159SToomas Soome */
write_table64(out,table,k)475*64c3d159SToomas Soome local void write_table64(out, table, k)
476*64c3d159SToomas Soome FILE *out;
477*64c3d159SToomas Soome const z_word_t FAR *table;
478*64c3d159SToomas Soome int k;
479*64c3d159SToomas Soome {
480*64c3d159SToomas Soome int n;
481*64c3d159SToomas Soome
482*64c3d159SToomas Soome for (n = 0; n < k; n++)
483*64c3d159SToomas Soome fprintf(out, "%s0x%016llx%s", n == 0 || n % 3 ? "" : " ",
484*64c3d159SToomas Soome (unsigned long long)(table[n]),
485*64c3d159SToomas Soome n == k - 1 ? "" : (n % 3 == 2 ? ",\n" : ", "));
486*64c3d159SToomas Soome }
487*64c3d159SToomas Soome
488*64c3d159SToomas Soome /* Actually do the deed. */
main()489*64c3d159SToomas Soome int main()
490*64c3d159SToomas Soome {
491*64c3d159SToomas Soome make_crc_table();
492*64c3d159SToomas Soome return 0;
493*64c3d159SToomas Soome }
494*64c3d159SToomas Soome
495ab9e68a2SToomas Soome #endif /* MAKECRCH */
496ab9e68a2SToomas Soome
497*64c3d159SToomas Soome #ifdef W
498*64c3d159SToomas Soome /*
499*64c3d159SToomas Soome Generate the little and big-endian braid tables for the given n and z_word_t
500*64c3d159SToomas Soome size w. Each array must have room for w blocks of 256 elements.
501*64c3d159SToomas Soome */
braid(ltl,big,n,w)502*64c3d159SToomas Soome local void braid(ltl, big, n, w)
503*64c3d159SToomas Soome z_crc_t ltl[][256];
504*64c3d159SToomas Soome z_word_t big[][256];
505*64c3d159SToomas Soome int n;
506*64c3d159SToomas Soome int w;
507*64c3d159SToomas Soome {
508*64c3d159SToomas Soome int k;
509*64c3d159SToomas Soome z_crc_t i, p, q;
510*64c3d159SToomas Soome for (k = 0; k < w; k++) {
511*64c3d159SToomas Soome p = x2nmodp((n * w + 3 - k) << 3, 0);
512*64c3d159SToomas Soome ltl[k][0] = 0;
513*64c3d159SToomas Soome big[w - 1 - k][0] = 0;
514*64c3d159SToomas Soome for (i = 1; i < 256; i++) {
515*64c3d159SToomas Soome ltl[k][i] = q = multmodp(i << 24, p);
516*64c3d159SToomas Soome big[w - 1 - k][i] = byte_swap(q);
517*64c3d159SToomas Soome }
518*64c3d159SToomas Soome }
519*64c3d159SToomas Soome }
520*64c3d159SToomas Soome #endif
521*64c3d159SToomas Soome
522ab9e68a2SToomas Soome #else /* !DYNAMIC_CRC_TABLE */
523ab9e68a2SToomas Soome /* ========================================================================
524*64c3d159SToomas Soome * Tables for byte-wise and braided CRC-32 calculations, and a table of powers
525*64c3d159SToomas Soome * of x for combining CRC-32s, all made by make_crc_table().
526ab9e68a2SToomas Soome */
527ab9e68a2SToomas Soome #include "crc32.h"
528ab9e68a2SToomas Soome #endif /* DYNAMIC_CRC_TABLE */
529ab9e68a2SToomas Soome
530*64c3d159SToomas Soome /* ========================================================================
531*64c3d159SToomas Soome * Routines used for CRC calculation. Some are also required for the table
532*64c3d159SToomas Soome * generation above.
533*64c3d159SToomas Soome */
534*64c3d159SToomas Soome
535*64c3d159SToomas Soome /*
536*64c3d159SToomas Soome Return a(x) multiplied by b(x) modulo p(x), where p(x) is the CRC polynomial,
537*64c3d159SToomas Soome reflected. For speed, this requires that a not be zero.
538*64c3d159SToomas Soome */
multmodp(z_crc_t a,z_crc_t b)539*64c3d159SToomas Soome local z_crc_t multmodp(z_crc_t a, z_crc_t b)
540*64c3d159SToomas Soome {
541*64c3d159SToomas Soome z_crc_t m, p;
542*64c3d159SToomas Soome
543*64c3d159SToomas Soome m = (z_crc_t)1 << 31;
544*64c3d159SToomas Soome p = 0;
545*64c3d159SToomas Soome for (;;) {
546*64c3d159SToomas Soome if (a & m) {
547*64c3d159SToomas Soome p ^= b;
548*64c3d159SToomas Soome if ((a & (m - 1)) == 0)
549*64c3d159SToomas Soome break;
550*64c3d159SToomas Soome }
551*64c3d159SToomas Soome m >>= 1;
552*64c3d159SToomas Soome b = b & 1 ? (b >> 1) ^ POLY : b >> 1;
553*64c3d159SToomas Soome }
554*64c3d159SToomas Soome return p;
555*64c3d159SToomas Soome }
556*64c3d159SToomas Soome
557*64c3d159SToomas Soome /*
558*64c3d159SToomas Soome Return x^(n * 2^k) modulo p(x). Requires that x2n_table[] has been
559*64c3d159SToomas Soome initialized.
560*64c3d159SToomas Soome */
x2nmodp(z_off64_t n,unsigned k)561*64c3d159SToomas Soome local z_crc_t x2nmodp(z_off64_t n, unsigned k)
562*64c3d159SToomas Soome {
563*64c3d159SToomas Soome z_crc_t p;
564*64c3d159SToomas Soome
565*64c3d159SToomas Soome p = (z_crc_t)1 << 31; /* x^0 == 1 */
566*64c3d159SToomas Soome while (n) {
567*64c3d159SToomas Soome if (n & 1)
568*64c3d159SToomas Soome p = multmodp(x2n_table[k & 31], p);
569*64c3d159SToomas Soome n >>= 1;
570*64c3d159SToomas Soome k++;
571*64c3d159SToomas Soome }
572*64c3d159SToomas Soome return p;
573*64c3d159SToomas Soome }
574*64c3d159SToomas Soome
575ab9e68a2SToomas Soome /* =========================================================================
576*64c3d159SToomas Soome * This function can be used by asm versions of crc32(), and to force the
577*64c3d159SToomas Soome * generation of the CRC tables in a threaded application.
578ab9e68a2SToomas Soome */
get_crc_table(void)579ab9e68a2SToomas Soome const z_crc_t FAR * ZEXPORT get_crc_table(void)
580ab9e68a2SToomas Soome {
581ab9e68a2SToomas Soome #ifdef DYNAMIC_CRC_TABLE
582*64c3d159SToomas Soome once(&made, make_crc_table);
583ab9e68a2SToomas Soome #endif /* DYNAMIC_CRC_TABLE */
584ab9e68a2SToomas Soome return (const z_crc_t FAR *)crc_table;
585ab9e68a2SToomas Soome }
586ab9e68a2SToomas Soome
587*64c3d159SToomas Soome /* =========================================================================
588*64c3d159SToomas Soome * Use ARM machine instructions if available. This will compute the CRC about
589*64c3d159SToomas Soome * ten times faster than the braided calculation. This code does not check for
590*64c3d159SToomas Soome * the presence of the CRC instruction at run time. __ARM_FEATURE_CRC32 will
591*64c3d159SToomas Soome * only be defined if the compilation specifies an ARM processor architecture
592*64c3d159SToomas Soome * that has the instructions. For example, compiling with -march=armv8.1-a or
593*64c3d159SToomas Soome * -march=armv8-a+crc, or -march=native if the compile machine has the crc32
594*64c3d159SToomas Soome * instructions.
595*64c3d159SToomas Soome */
596*64c3d159SToomas Soome #ifdef ARMCRC32
597*64c3d159SToomas Soome
598*64c3d159SToomas Soome /*
599*64c3d159SToomas Soome Constants empirically determined to maximize speed. These values are from
600*64c3d159SToomas Soome measurements on a Cortex-A57. Your mileage may vary.
601*64c3d159SToomas Soome */
602*64c3d159SToomas Soome #define Z_BATCH 3990 /* number of words in a batch */
603*64c3d159SToomas Soome #define Z_BATCH_ZEROS 0xa10d3d0c /* computed from Z_BATCH = 3990 */
604*64c3d159SToomas Soome #define Z_BATCH_MIN 800 /* fewest words in a final batch */
605*64c3d159SToomas Soome
crc32_z(crc,buf,len)606*64c3d159SToomas Soome unsigned long ZEXPORT crc32_z(crc, buf, len)
607*64c3d159SToomas Soome unsigned long crc;
608*64c3d159SToomas Soome const unsigned char FAR *buf;
609*64c3d159SToomas Soome z_size_t len;
610*64c3d159SToomas Soome {
611*64c3d159SToomas Soome z_crc_t val;
612*64c3d159SToomas Soome z_word_t crc1, crc2;
613*64c3d159SToomas Soome const z_word_t *word;
614*64c3d159SToomas Soome z_word_t val0, val1, val2;
615*64c3d159SToomas Soome z_size_t last, last2, i;
616*64c3d159SToomas Soome z_size_t num;
617*64c3d159SToomas Soome
618*64c3d159SToomas Soome /* Return initial CRC, if requested. */
619*64c3d159SToomas Soome if (buf == Z_NULL) return 0;
620*64c3d159SToomas Soome
621*64c3d159SToomas Soome #ifdef DYNAMIC_CRC_TABLE
622*64c3d159SToomas Soome once(&made, make_crc_table);
623*64c3d159SToomas Soome #endif /* DYNAMIC_CRC_TABLE */
624*64c3d159SToomas Soome
625*64c3d159SToomas Soome /* Pre-condition the CRC */
626*64c3d159SToomas Soome crc = (~crc) & 0xffffffff;
627*64c3d159SToomas Soome
628*64c3d159SToomas Soome /* Compute the CRC up to a word boundary. */
629*64c3d159SToomas Soome while (len && ((z_size_t)buf & 7) != 0) {
630*64c3d159SToomas Soome len--;
631*64c3d159SToomas Soome val = *buf++;
632*64c3d159SToomas Soome __asm__ volatile("crc32b %w0, %w0, %w1" : "+r"(crc) : "r"(val));
633*64c3d159SToomas Soome }
634*64c3d159SToomas Soome
635*64c3d159SToomas Soome /* Prepare to compute the CRC on full 64-bit words word[0..num-1]. */
636*64c3d159SToomas Soome word = (z_word_t const *)buf;
637*64c3d159SToomas Soome num = len >> 3;
638*64c3d159SToomas Soome len &= 7;
639*64c3d159SToomas Soome
640*64c3d159SToomas Soome /* Do three interleaved CRCs to realize the throughput of one crc32x
641*64c3d159SToomas Soome instruction per cycle. Each CRC is calcuated on Z_BATCH words. The three
642*64c3d159SToomas Soome CRCs are combined into a single CRC after each set of batches. */
643*64c3d159SToomas Soome while (num >= 3 * Z_BATCH) {
644*64c3d159SToomas Soome crc1 = 0;
645*64c3d159SToomas Soome crc2 = 0;
646*64c3d159SToomas Soome for (i = 0; i < Z_BATCH; i++) {
647*64c3d159SToomas Soome val0 = word[i];
648*64c3d159SToomas Soome val1 = word[i + Z_BATCH];
649*64c3d159SToomas Soome val2 = word[i + 2 * Z_BATCH];
650*64c3d159SToomas Soome __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc) : "r"(val0));
651*64c3d159SToomas Soome __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc1) : "r"(val1));
652*64c3d159SToomas Soome __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc2) : "r"(val2));
653*64c3d159SToomas Soome }
654*64c3d159SToomas Soome word += 3 * Z_BATCH;
655*64c3d159SToomas Soome num -= 3 * Z_BATCH;
656*64c3d159SToomas Soome crc = multmodp(Z_BATCH_ZEROS, crc) ^ crc1;
657*64c3d159SToomas Soome crc = multmodp(Z_BATCH_ZEROS, crc) ^ crc2;
658*64c3d159SToomas Soome }
659*64c3d159SToomas Soome
660*64c3d159SToomas Soome /* Do one last smaller batch with the remaining words, if there are enough
661*64c3d159SToomas Soome to pay for the combination of CRCs. */
662*64c3d159SToomas Soome last = num / 3;
663*64c3d159SToomas Soome if (last >= Z_BATCH_MIN) {
664*64c3d159SToomas Soome last2 = last << 1;
665*64c3d159SToomas Soome crc1 = 0;
666*64c3d159SToomas Soome crc2 = 0;
667*64c3d159SToomas Soome for (i = 0; i < last; i++) {
668*64c3d159SToomas Soome val0 = word[i];
669*64c3d159SToomas Soome val1 = word[i + last];
670*64c3d159SToomas Soome val2 = word[i + last2];
671*64c3d159SToomas Soome __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc) : "r"(val0));
672*64c3d159SToomas Soome __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc1) : "r"(val1));
673*64c3d159SToomas Soome __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc2) : "r"(val2));
674*64c3d159SToomas Soome }
675*64c3d159SToomas Soome word += 3 * last;
676*64c3d159SToomas Soome num -= 3 * last;
677*64c3d159SToomas Soome val = x2nmodp(last, 6);
678*64c3d159SToomas Soome crc = multmodp(val, crc) ^ crc1;
679*64c3d159SToomas Soome crc = multmodp(val, crc) ^ crc2;
680*64c3d159SToomas Soome }
681*64c3d159SToomas Soome
682*64c3d159SToomas Soome /* Compute the CRC on any remaining words. */
683*64c3d159SToomas Soome for (i = 0; i < num; i++) {
684*64c3d159SToomas Soome val0 = word[i];
685*64c3d159SToomas Soome __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc) : "r"(val0));
686*64c3d159SToomas Soome }
687*64c3d159SToomas Soome word += num;
688*64c3d159SToomas Soome
689*64c3d159SToomas Soome /* Complete the CRC on any remaining bytes. */
690*64c3d159SToomas Soome buf = (const unsigned char FAR *)word;
691*64c3d159SToomas Soome while (len) {
692*64c3d159SToomas Soome len--;
693*64c3d159SToomas Soome val = *buf++;
694*64c3d159SToomas Soome __asm__ volatile("crc32b %w0, %w0, %w1" : "+r"(crc) : "r"(val));
695*64c3d159SToomas Soome }
696*64c3d159SToomas Soome
697*64c3d159SToomas Soome /* Return the CRC, post-conditioned. */
698*64c3d159SToomas Soome return crc ^ 0xffffffff;
699*64c3d159SToomas Soome }
700*64c3d159SToomas Soome
701*64c3d159SToomas Soome #else
702*64c3d159SToomas Soome
703*64c3d159SToomas Soome #ifdef W
704*64c3d159SToomas Soome
705*64c3d159SToomas Soome /*
706*64c3d159SToomas Soome Return the CRC of the W bytes in the word_t data, taking the
707*64c3d159SToomas Soome least-significant byte of the word as the first byte of data, without any pre
708*64c3d159SToomas Soome or post conditioning. This is used to combine the CRCs of each braid.
709*64c3d159SToomas Soome */
crc_word(z_word_t data)710*64c3d159SToomas Soome local z_crc_t crc_word(z_word_t data)
711*64c3d159SToomas Soome {
712*64c3d159SToomas Soome int k;
713*64c3d159SToomas Soome for (k = 0; k < W; k++)
714*64c3d159SToomas Soome data = (data >> 8) ^ crc_table[data & 0xff];
715*64c3d159SToomas Soome return (z_crc_t)data;
716*64c3d159SToomas Soome }
717*64c3d159SToomas Soome
crc_word_big(z_word_t data)718*64c3d159SToomas Soome local z_word_t crc_word_big(z_word_t data)
719*64c3d159SToomas Soome {
720*64c3d159SToomas Soome int k;
721*64c3d159SToomas Soome for (k = 0; k < W; k++)
722*64c3d159SToomas Soome data = (data << 8) ^
723*64c3d159SToomas Soome crc_big_table[(data >> ((W - 1) << 3)) & 0xff];
724*64c3d159SToomas Soome return data;
725*64c3d159SToomas Soome }
726*64c3d159SToomas Soome
727*64c3d159SToomas Soome #endif
728ab9e68a2SToomas Soome
729ab9e68a2SToomas Soome /* ========================================================================= */
crc32_z(unsigned long crc,const unsigned char FAR * buf,z_size_t len)730ab9e68a2SToomas Soome unsigned long ZEXPORT crc32_z(unsigned long crc, const unsigned char FAR *buf,
731ab9e68a2SToomas Soome z_size_t len)
732ab9e68a2SToomas Soome {
733*64c3d159SToomas Soome /* Return initial CRC, if requested. */
734*64c3d159SToomas Soome if (buf == Z_NULL) return 0;
735ab9e68a2SToomas Soome
736ab9e68a2SToomas Soome #ifdef DYNAMIC_CRC_TABLE
737*64c3d159SToomas Soome once(&made, make_crc_table);
738ab9e68a2SToomas Soome #endif /* DYNAMIC_CRC_TABLE */
739ab9e68a2SToomas Soome
740*64c3d159SToomas Soome /* Pre-condition the CRC */
741*64c3d159SToomas Soome crc = (~crc) & 0xffffffff;
742ab9e68a2SToomas Soome
743*64c3d159SToomas Soome #ifdef W
744*64c3d159SToomas Soome
745*64c3d159SToomas Soome /* If provided enough bytes, do a braided CRC calculation. */
746*64c3d159SToomas Soome if (len >= N * W + W - 1) {
747*64c3d159SToomas Soome z_size_t blks;
748*64c3d159SToomas Soome z_word_t const *words;
749*64c3d159SToomas Soome unsigned endian;
750*64c3d159SToomas Soome int k;
751*64c3d159SToomas Soome
752*64c3d159SToomas Soome /* Compute the CRC up to a z_word_t boundary. */
753*64c3d159SToomas Soome while (len && ((z_size_t)buf & (W - 1)) != 0) {
754*64c3d159SToomas Soome len--;
755*64c3d159SToomas Soome crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
756*64c3d159SToomas Soome }
757*64c3d159SToomas Soome
758*64c3d159SToomas Soome /* Compute the CRC on as many N z_word_t blocks as are available. */
759*64c3d159SToomas Soome blks = len / (N * W);
760*64c3d159SToomas Soome len -= blks * N * W;
761*64c3d159SToomas Soome words = (z_word_t const *)buf;
762*64c3d159SToomas Soome
763*64c3d159SToomas Soome /* Do endian check at execution time instead of compile time, since ARM
764*64c3d159SToomas Soome processors can change the endianess at execution time. If the
765*64c3d159SToomas Soome compiler knows what the endianess will be, it can optimize out the
766*64c3d159SToomas Soome check and the unused branch. */
767ab9e68a2SToomas Soome endian = 1;
768*64c3d159SToomas Soome if (*(unsigned char *)&endian) {
769*64c3d159SToomas Soome /* Little endian. */
770*64c3d159SToomas Soome
771*64c3d159SToomas Soome z_crc_t crc0;
772*64c3d159SToomas Soome z_word_t word0;
773*64c3d159SToomas Soome #if N > 1
774*64c3d159SToomas Soome z_crc_t crc1;
775*64c3d159SToomas Soome z_word_t word1;
776*64c3d159SToomas Soome #if N > 2
777*64c3d159SToomas Soome z_crc_t crc2;
778*64c3d159SToomas Soome z_word_t word2;
779*64c3d159SToomas Soome #if N > 3
780*64c3d159SToomas Soome z_crc_t crc3;
781*64c3d159SToomas Soome z_word_t word3;
782*64c3d159SToomas Soome #if N > 4
783*64c3d159SToomas Soome z_crc_t crc4;
784*64c3d159SToomas Soome z_word_t word4;
785*64c3d159SToomas Soome #if N > 5
786*64c3d159SToomas Soome z_crc_t crc5;
787*64c3d159SToomas Soome z_word_t word5;
788*64c3d159SToomas Soome #endif
789*64c3d159SToomas Soome #endif
790*64c3d159SToomas Soome #endif
791*64c3d159SToomas Soome #endif
792*64c3d159SToomas Soome #endif
793*64c3d159SToomas Soome
794*64c3d159SToomas Soome /* Initialize the CRC for each braid. */
795*64c3d159SToomas Soome crc0 = crc;
796*64c3d159SToomas Soome #if N > 1
797*64c3d159SToomas Soome crc1 = 0;
798*64c3d159SToomas Soome #if N > 2
799*64c3d159SToomas Soome crc2 = 0;
800*64c3d159SToomas Soome #if N > 3
801*64c3d159SToomas Soome crc3 = 0;
802*64c3d159SToomas Soome #if N > 4
803*64c3d159SToomas Soome crc4 = 0;
804*64c3d159SToomas Soome #if N > 5
805*64c3d159SToomas Soome crc5 = 0;
806*64c3d159SToomas Soome #endif
807*64c3d159SToomas Soome #endif
808*64c3d159SToomas Soome #endif
809*64c3d159SToomas Soome #endif
810*64c3d159SToomas Soome #endif
811*64c3d159SToomas Soome
812*64c3d159SToomas Soome /*
813*64c3d159SToomas Soome Process the first blks-1 blocks, computing the CRCs on each braid
814*64c3d159SToomas Soome independently.
815*64c3d159SToomas Soome */
816*64c3d159SToomas Soome while (--blks) {
817*64c3d159SToomas Soome /* Load the word for each braid into registers. */
818*64c3d159SToomas Soome word0 = crc0 ^ words[0];
819*64c3d159SToomas Soome #if N > 1
820*64c3d159SToomas Soome word1 = crc1 ^ words[1];
821*64c3d159SToomas Soome #if N > 2
822*64c3d159SToomas Soome word2 = crc2 ^ words[2];
823*64c3d159SToomas Soome #if N > 3
824*64c3d159SToomas Soome word3 = crc3 ^ words[3];
825*64c3d159SToomas Soome #if N > 4
826*64c3d159SToomas Soome word4 = crc4 ^ words[4];
827*64c3d159SToomas Soome #if N > 5
828*64c3d159SToomas Soome word5 = crc5 ^ words[5];
829*64c3d159SToomas Soome #endif
830*64c3d159SToomas Soome #endif
831*64c3d159SToomas Soome #endif
832*64c3d159SToomas Soome #endif
833*64c3d159SToomas Soome #endif
834*64c3d159SToomas Soome words += N;
835*64c3d159SToomas Soome
836*64c3d159SToomas Soome /* Compute and update the CRC for each word. The loop should
837*64c3d159SToomas Soome get unrolled. */
838*64c3d159SToomas Soome crc0 = crc_braid_table[0][word0 & 0xff];
839*64c3d159SToomas Soome #if N > 1
840*64c3d159SToomas Soome crc1 = crc_braid_table[0][word1 & 0xff];
841*64c3d159SToomas Soome #if N > 2
842*64c3d159SToomas Soome crc2 = crc_braid_table[0][word2 & 0xff];
843*64c3d159SToomas Soome #if N > 3
844*64c3d159SToomas Soome crc3 = crc_braid_table[0][word3 & 0xff];
845*64c3d159SToomas Soome #if N > 4
846*64c3d159SToomas Soome crc4 = crc_braid_table[0][word4 & 0xff];
847*64c3d159SToomas Soome #if N > 5
848*64c3d159SToomas Soome crc5 = crc_braid_table[0][word5 & 0xff];
849*64c3d159SToomas Soome #endif
850*64c3d159SToomas Soome #endif
851*64c3d159SToomas Soome #endif
852*64c3d159SToomas Soome #endif
853*64c3d159SToomas Soome #endif
854*64c3d159SToomas Soome for (k = 1; k < W; k++) {
855*64c3d159SToomas Soome crc0 ^= crc_braid_table[k][(word0 >> (k << 3)) & 0xff];
856*64c3d159SToomas Soome #if N > 1
857*64c3d159SToomas Soome crc1 ^= crc_braid_table[k][(word1 >> (k << 3)) & 0xff];
858*64c3d159SToomas Soome #if N > 2
859*64c3d159SToomas Soome crc2 ^= crc_braid_table[k][(word2 >> (k << 3)) & 0xff];
860*64c3d159SToomas Soome #if N > 3
861*64c3d159SToomas Soome crc3 ^= crc_braid_table[k][(word3 >> (k << 3)) & 0xff];
862*64c3d159SToomas Soome #if N > 4
863*64c3d159SToomas Soome crc4 ^= crc_braid_table[k][(word4 >> (k << 3)) & 0xff];
864*64c3d159SToomas Soome #if N > 5
865*64c3d159SToomas Soome crc5 ^= crc_braid_table[k][(word5 >> (k << 3)) & 0xff];
866*64c3d159SToomas Soome #endif
867*64c3d159SToomas Soome #endif
868*64c3d159SToomas Soome #endif
869*64c3d159SToomas Soome #endif
870*64c3d159SToomas Soome #endif
871ab9e68a2SToomas Soome }
872*64c3d159SToomas Soome }
873*64c3d159SToomas Soome
874*64c3d159SToomas Soome /*
875*64c3d159SToomas Soome Process the last block, combining the CRCs of the N braids at the
876*64c3d159SToomas Soome same time.
877*64c3d159SToomas Soome */
878*64c3d159SToomas Soome crc = crc_word(crc0 ^ words[0]);
879*64c3d159SToomas Soome #if N > 1
880*64c3d159SToomas Soome crc = crc_word(crc1 ^ words[1] ^ crc);
881*64c3d159SToomas Soome #if N > 2
882*64c3d159SToomas Soome crc = crc_word(crc2 ^ words[2] ^ crc);
883*64c3d159SToomas Soome #if N > 3
884*64c3d159SToomas Soome crc = crc_word(crc3 ^ words[3] ^ crc);
885*64c3d159SToomas Soome #if N > 4
886*64c3d159SToomas Soome crc = crc_word(crc4 ^ words[4] ^ crc);
887*64c3d159SToomas Soome #if N > 5
888*64c3d159SToomas Soome crc = crc_word(crc5 ^ words[5] ^ crc);
889*64c3d159SToomas Soome #endif
890*64c3d159SToomas Soome #endif
891*64c3d159SToomas Soome #endif
892*64c3d159SToomas Soome #endif
893*64c3d159SToomas Soome #endif
894*64c3d159SToomas Soome words += N;
895*64c3d159SToomas Soome }
896*64c3d159SToomas Soome else {
897*64c3d159SToomas Soome /* Big endian. */
898*64c3d159SToomas Soome
899*64c3d159SToomas Soome z_word_t crc0, word0, comb;
900*64c3d159SToomas Soome #if N > 1
901*64c3d159SToomas Soome z_word_t crc1, word1;
902*64c3d159SToomas Soome #if N > 2
903*64c3d159SToomas Soome z_word_t crc2, word2;
904*64c3d159SToomas Soome #if N > 3
905*64c3d159SToomas Soome z_word_t crc3, word3;
906*64c3d159SToomas Soome #if N > 4
907*64c3d159SToomas Soome z_word_t crc4, word4;
908*64c3d159SToomas Soome #if N > 5
909*64c3d159SToomas Soome z_word_t crc5, word5;
910*64c3d159SToomas Soome #endif
911*64c3d159SToomas Soome #endif
912*64c3d159SToomas Soome #endif
913*64c3d159SToomas Soome #endif
914*64c3d159SToomas Soome #endif
915*64c3d159SToomas Soome
916*64c3d159SToomas Soome /* Initialize the CRC for each braid. */
917*64c3d159SToomas Soome crc0 = byte_swap(crc);
918*64c3d159SToomas Soome #if N > 1
919*64c3d159SToomas Soome crc1 = 0;
920*64c3d159SToomas Soome #if N > 2
921*64c3d159SToomas Soome crc2 = 0;
922*64c3d159SToomas Soome #if N > 3
923*64c3d159SToomas Soome crc3 = 0;
924*64c3d159SToomas Soome #if N > 4
925*64c3d159SToomas Soome crc4 = 0;
926*64c3d159SToomas Soome #if N > 5
927*64c3d159SToomas Soome crc5 = 0;
928*64c3d159SToomas Soome #endif
929*64c3d159SToomas Soome #endif
930*64c3d159SToomas Soome #endif
931*64c3d159SToomas Soome #endif
932*64c3d159SToomas Soome #endif
933*64c3d159SToomas Soome
934*64c3d159SToomas Soome /*
935*64c3d159SToomas Soome Process the first blks-1 blocks, computing the CRCs on each braid
936*64c3d159SToomas Soome independently.
937*64c3d159SToomas Soome */
938*64c3d159SToomas Soome while (--blks) {
939*64c3d159SToomas Soome /* Load the word for each braid into registers. */
940*64c3d159SToomas Soome word0 = crc0 ^ words[0];
941*64c3d159SToomas Soome #if N > 1
942*64c3d159SToomas Soome word1 = crc1 ^ words[1];
943*64c3d159SToomas Soome #if N > 2
944*64c3d159SToomas Soome word2 = crc2 ^ words[2];
945*64c3d159SToomas Soome #if N > 3
946*64c3d159SToomas Soome word3 = crc3 ^ words[3];
947*64c3d159SToomas Soome #if N > 4
948*64c3d159SToomas Soome word4 = crc4 ^ words[4];
949*64c3d159SToomas Soome #if N > 5
950*64c3d159SToomas Soome word5 = crc5 ^ words[5];
951*64c3d159SToomas Soome #endif
952*64c3d159SToomas Soome #endif
953*64c3d159SToomas Soome #endif
954*64c3d159SToomas Soome #endif
955*64c3d159SToomas Soome #endif
956*64c3d159SToomas Soome words += N;
957*64c3d159SToomas Soome
958*64c3d159SToomas Soome /* Compute and update the CRC for each word. The loop should
959*64c3d159SToomas Soome get unrolled. */
960*64c3d159SToomas Soome crc0 = crc_braid_big_table[0][word0 & 0xff];
961*64c3d159SToomas Soome #if N > 1
962*64c3d159SToomas Soome crc1 = crc_braid_big_table[0][word1 & 0xff];
963*64c3d159SToomas Soome #if N > 2
964*64c3d159SToomas Soome crc2 = crc_braid_big_table[0][word2 & 0xff];
965*64c3d159SToomas Soome #if N > 3
966*64c3d159SToomas Soome crc3 = crc_braid_big_table[0][word3 & 0xff];
967*64c3d159SToomas Soome #if N > 4
968*64c3d159SToomas Soome crc4 = crc_braid_big_table[0][word4 & 0xff];
969*64c3d159SToomas Soome #if N > 5
970*64c3d159SToomas Soome crc5 = crc_braid_big_table[0][word5 & 0xff];
971*64c3d159SToomas Soome #endif
972*64c3d159SToomas Soome #endif
973*64c3d159SToomas Soome #endif
974*64c3d159SToomas Soome #endif
975*64c3d159SToomas Soome #endif
976*64c3d159SToomas Soome for (k = 1; k < W; k++) {
977*64c3d159SToomas Soome crc0 ^= crc_braid_big_table[k][(word0 >> (k << 3)) & 0xff];
978*64c3d159SToomas Soome #if N > 1
979*64c3d159SToomas Soome crc1 ^= crc_braid_big_table[k][(word1 >> (k << 3)) & 0xff];
980*64c3d159SToomas Soome #if N > 2
981*64c3d159SToomas Soome crc2 ^= crc_braid_big_table[k][(word2 >> (k << 3)) & 0xff];
982*64c3d159SToomas Soome #if N > 3
983*64c3d159SToomas Soome crc3 ^= crc_braid_big_table[k][(word3 >> (k << 3)) & 0xff];
984*64c3d159SToomas Soome #if N > 4
985*64c3d159SToomas Soome crc4 ^= crc_braid_big_table[k][(word4 >> (k << 3)) & 0xff];
986*64c3d159SToomas Soome #if N > 5
987*64c3d159SToomas Soome crc5 ^= crc_braid_big_table[k][(word5 >> (k << 3)) & 0xff];
988*64c3d159SToomas Soome #endif
989*64c3d159SToomas Soome #endif
990*64c3d159SToomas Soome #endif
991*64c3d159SToomas Soome #endif
992*64c3d159SToomas Soome #endif
993*64c3d159SToomas Soome }
994*64c3d159SToomas Soome }
995*64c3d159SToomas Soome
996*64c3d159SToomas Soome /*
997*64c3d159SToomas Soome Process the last block, combining the CRCs of the N braids at the
998*64c3d159SToomas Soome same time.
999*64c3d159SToomas Soome */
1000*64c3d159SToomas Soome comb = crc_word_big(crc0 ^ words[0]);
1001*64c3d159SToomas Soome #if N > 1
1002*64c3d159SToomas Soome comb = crc_word_big(crc1 ^ words[1] ^ comb);
1003*64c3d159SToomas Soome #if N > 2
1004*64c3d159SToomas Soome comb = crc_word_big(crc2 ^ words[2] ^ comb);
1005*64c3d159SToomas Soome #if N > 3
1006*64c3d159SToomas Soome comb = crc_word_big(crc3 ^ words[3] ^ comb);
1007*64c3d159SToomas Soome #if N > 4
1008*64c3d159SToomas Soome comb = crc_word_big(crc4 ^ words[4] ^ comb);
1009*64c3d159SToomas Soome #if N > 5
1010*64c3d159SToomas Soome comb = crc_word_big(crc5 ^ words[5] ^ comb);
1011*64c3d159SToomas Soome #endif
1012*64c3d159SToomas Soome #endif
1013*64c3d159SToomas Soome #endif
1014*64c3d159SToomas Soome #endif
1015*64c3d159SToomas Soome #endif
1016*64c3d159SToomas Soome words += N;
1017*64c3d159SToomas Soome crc = byte_swap(comb);
1018*64c3d159SToomas Soome }
1019*64c3d159SToomas Soome
1020*64c3d159SToomas Soome /*
1021*64c3d159SToomas Soome Update the pointer to the remaining bytes to process.
1022*64c3d159SToomas Soome */
1023*64c3d159SToomas Soome buf = (unsigned char const *)words;
1024*64c3d159SToomas Soome }
1025*64c3d159SToomas Soome
1026*64c3d159SToomas Soome #endif /* W */
1027*64c3d159SToomas Soome
1028*64c3d159SToomas Soome /* Complete the computation of the CRC on any remaining bytes. */
1029ab9e68a2SToomas Soome while (len >= 8) {
1030ab9e68a2SToomas Soome len -= 8;
1031*64c3d159SToomas Soome crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
1032*64c3d159SToomas Soome crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
1033*64c3d159SToomas Soome crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
1034*64c3d159SToomas Soome crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
1035*64c3d159SToomas Soome crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
1036*64c3d159SToomas Soome crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
1037*64c3d159SToomas Soome crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
1038*64c3d159SToomas Soome crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
1039ab9e68a2SToomas Soome }
1040*64c3d159SToomas Soome while (len) {
1041*64c3d159SToomas Soome len--;
1042*64c3d159SToomas Soome crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
1043ab9e68a2SToomas Soome }
1044ab9e68a2SToomas Soome
1045*64c3d159SToomas Soome /* Return the CRC, post-conditioned. */
1046*64c3d159SToomas Soome return crc ^ 0xffffffff;
1047*64c3d159SToomas Soome }
1048*64c3d159SToomas Soome
1049*64c3d159SToomas Soome #endif
1050*64c3d159SToomas Soome
1051ab9e68a2SToomas Soome /* ========================================================================= */
crc32(unsigned long crc,const unsigned char FAR * buf,uInt len)1052ab9e68a2SToomas Soome unsigned long ZEXPORT crc32(unsigned long crc, const unsigned char FAR *buf,
1053ab9e68a2SToomas Soome uInt len)
1054ab9e68a2SToomas Soome {
1055ab9e68a2SToomas Soome return crc32_z(crc, buf, len);
1056ab9e68a2SToomas Soome }
1057ab9e68a2SToomas Soome
1058ab9e68a2SToomas Soome /* ========================================================================= */
crc32_combine64(uLong crc1,uLong crc2,z_off64_t len2)1059*64c3d159SToomas Soome uLong ZEXPORT crc32_combine64(uLong crc1, uLong crc2, z_off64_t len2)
1060ab9e68a2SToomas Soome {
1061*64c3d159SToomas Soome #ifdef DYNAMIC_CRC_TABLE
1062*64c3d159SToomas Soome once(&made, make_crc_table);
1063*64c3d159SToomas Soome #endif /* DYNAMIC_CRC_TABLE */
1064*64c3d159SToomas Soome return multmodp(x2nmodp(len2, 3), crc1) ^ (crc2 & 0xffffffff);
1065ab9e68a2SToomas Soome }
1066ab9e68a2SToomas Soome
1067ab9e68a2SToomas Soome /* ========================================================================= */
crc32_combine(uLong crc1,uLong crc2,z_off_t len2)1068ab9e68a2SToomas Soome uLong ZEXPORT crc32_combine(uLong crc1, uLong crc2, z_off_t len2)
1069ab9e68a2SToomas Soome {
1070*64c3d159SToomas Soome return crc32_combine64(crc1, crc2, len2);
1071ab9e68a2SToomas Soome }
1072ab9e68a2SToomas Soome
1073*64c3d159SToomas Soome /* ========================================================================= */
crc32_combine_gen64(z_off64_t len2)1074*64c3d159SToomas Soome uLong ZEXPORT crc32_combine_gen64(z_off64_t len2)
1075ab9e68a2SToomas Soome {
1076*64c3d159SToomas Soome #ifdef DYNAMIC_CRC_TABLE
1077*64c3d159SToomas Soome once(&made, make_crc_table);
1078*64c3d159SToomas Soome #endif /* DYNAMIC_CRC_TABLE */
1079*64c3d159SToomas Soome return x2nmodp(len2, 3);
1080*64c3d159SToomas Soome }
1081*64c3d159SToomas Soome
1082*64c3d159SToomas Soome /* ========================================================================= */
crc32_combine_gen(z_off_t len2)1083*64c3d159SToomas Soome uLong ZEXPORT crc32_combine_gen(z_off_t len2)
1084*64c3d159SToomas Soome {
1085*64c3d159SToomas Soome return crc32_combine_gen64(len2);
1086*64c3d159SToomas Soome }
1087*64c3d159SToomas Soome
1088*64c3d159SToomas Soome /* ========================================================================= */
crc32_combine_op(uLong crc1,uLong crc2,uLong op)1089*64c3d159SToomas Soome uLong crc32_combine_op(uLong crc1, uLong crc2, uLong op)
1090*64c3d159SToomas Soome {
1091*64c3d159SToomas Soome return multmodp(op, crc1) ^ (crc2 & 0xffffffff);
1092ab9e68a2SToomas Soome }
1093