xref: /titanic_52/usr/src/contrib/zlib/crc32.c (revision 64c3d15931c5518f89221f1e36d3015dbb54b9bd)
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  */
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  */
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 *));
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. */
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 
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  */
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  */
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  */
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. */
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  */
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  */
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  */
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  */
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 
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  */
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 
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 /* ========================================================================= */
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 /* ========================================================================= */
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 /* ========================================================================= */
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 /* ========================================================================= */
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 /* ========================================================================= */
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 /* ========================================================================= */
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 /* ========================================================================= */
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