xref: /titanic_52/usr/src/contrib/zlib/crc32.c (revision ab9e68a238043b4ee046d74742fe13407f00e542)
1*ab9e68a2SToomas Soome /* crc32.c -- compute the CRC-32 of a data stream
2*ab9e68a2SToomas Soome  * Copyright (C) 1995-2006, 2010, 2011, 2012, 2016 Mark Adler
3*ab9e68a2SToomas Soome  * For conditions of distribution and use, see copyright notice in zlib.h
4*ab9e68a2SToomas Soome  *
5*ab9e68a2SToomas Soome  * Thanks to Rodney Brown <rbrown64@csc.com.au> for his contribution of faster
6*ab9e68a2SToomas Soome  * CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing
7*ab9e68a2SToomas Soome  * tables for updating the shift register in one step with three exclusive-ors
8*ab9e68a2SToomas Soome  * instead of four steps with four exclusive-ors.  This results in about a
9*ab9e68a2SToomas Soome  * factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3.
10*ab9e68a2SToomas Soome  */
11*ab9e68a2SToomas Soome 
12*ab9e68a2SToomas Soome /*
13*ab9e68a2SToomas Soome   Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore
14*ab9e68a2SToomas Soome   protection on the static variables used to control the first-use generation
15*ab9e68a2SToomas Soome   of the crc tables.  Therefore, if you #define DYNAMIC_CRC_TABLE, you should
16*ab9e68a2SToomas Soome   first call get_crc_table() to initialize the tables before allowing more than
17*ab9e68a2SToomas Soome   one thread to use crc32().
18*ab9e68a2SToomas Soome 
19*ab9e68a2SToomas Soome   DYNAMIC_CRC_TABLE and MAKECRCH can be #defined to write out crc32.h.
20*ab9e68a2SToomas Soome  */
21*ab9e68a2SToomas Soome 
22*ab9e68a2SToomas Soome #ifdef MAKECRCH
23*ab9e68a2SToomas Soome #  include <stdio.h>
24*ab9e68a2SToomas Soome #  ifndef DYNAMIC_CRC_TABLE
25*ab9e68a2SToomas Soome #    define DYNAMIC_CRC_TABLE
26*ab9e68a2SToomas Soome #  endif /* !DYNAMIC_CRC_TABLE */
27*ab9e68a2SToomas Soome #endif /* MAKECRCH */
28*ab9e68a2SToomas Soome 
29*ab9e68a2SToomas Soome #include "zutil.h"      /* for STDC and FAR definitions */
30*ab9e68a2SToomas Soome 
31*ab9e68a2SToomas Soome /* Definitions for doing the crc four data bytes at a time. */
32*ab9e68a2SToomas Soome #if !defined(NOBYFOUR) && defined(Z_U4)
33*ab9e68a2SToomas Soome #  define BYFOUR
34*ab9e68a2SToomas Soome #endif
35*ab9e68a2SToomas Soome #ifdef BYFOUR
36*ab9e68a2SToomas Soome    local unsigned long crc32_little OF((unsigned long,
37*ab9e68a2SToomas Soome                         const unsigned char FAR *, z_size_t));
38*ab9e68a2SToomas Soome    local unsigned long crc32_big OF((unsigned long,
39*ab9e68a2SToomas Soome                         const unsigned char FAR *, z_size_t));
40*ab9e68a2SToomas Soome #  define TBLS 8
41*ab9e68a2SToomas Soome #else
42*ab9e68a2SToomas Soome #  define TBLS 1
43*ab9e68a2SToomas Soome #endif /* BYFOUR */
44*ab9e68a2SToomas Soome 
45*ab9e68a2SToomas Soome /* Local functions for crc concatenation */
46*ab9e68a2SToomas Soome local unsigned long gf2_matrix_times OF((unsigned long *mat,
47*ab9e68a2SToomas Soome                                          unsigned long vec));
48*ab9e68a2SToomas Soome local void gf2_matrix_square OF((unsigned long *square, unsigned long *mat));
49*ab9e68a2SToomas Soome local uLong crc32_combine_ OF((uLong crc1, uLong crc2, z_off64_t len2));
50*ab9e68a2SToomas Soome 
51*ab9e68a2SToomas Soome 
52*ab9e68a2SToomas Soome #ifdef DYNAMIC_CRC_TABLE
53*ab9e68a2SToomas Soome 
54*ab9e68a2SToomas Soome local volatile int crc_table_empty = 1;
55*ab9e68a2SToomas Soome local z_crc_t FAR crc_table[TBLS][256];
56*ab9e68a2SToomas Soome local void make_crc_table OF((void));
57*ab9e68a2SToomas Soome #ifdef MAKECRCH
58*ab9e68a2SToomas Soome    local void write_table OF((FILE *, const z_crc_t FAR *));
59*ab9e68a2SToomas Soome #endif /* MAKECRCH */
60*ab9e68a2SToomas Soome /*
61*ab9e68a2SToomas Soome   Generate tables for a byte-wise 32-bit CRC calculation on the polynomial:
62*ab9e68a2SToomas 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.
63*ab9e68a2SToomas Soome 
64*ab9e68a2SToomas Soome   Polynomials over GF(2) are represented in binary, one bit per coefficient,
65*ab9e68a2SToomas Soome   with the lowest powers in the most significant bit.  Then adding polynomials
66*ab9e68a2SToomas Soome   is just exclusive-or, and multiplying a polynomial by x is a right shift by
67*ab9e68a2SToomas Soome   one.  If we call the above polynomial p, and represent a byte as the
68*ab9e68a2SToomas Soome   polynomial q, also with the lowest power in the most significant bit (so the
69*ab9e68a2SToomas Soome   byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p,
70*ab9e68a2SToomas Soome   where a mod b means the remainder after dividing a by b.
71*ab9e68a2SToomas Soome 
72*ab9e68a2SToomas Soome   This calculation is done using the shift-register method of multiplying and
73*ab9e68a2SToomas Soome   taking the remainder.  The register is initialized to zero, and for each
74*ab9e68a2SToomas Soome   incoming bit, x^32 is added mod p to the register if the bit is a one (where
75*ab9e68a2SToomas Soome   x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by
76*ab9e68a2SToomas Soome   x (which is shifting right by one and adding x^32 mod p if the bit shifted
77*ab9e68a2SToomas Soome   out is a one).  We start with the highest power (least significant bit) of
78*ab9e68a2SToomas Soome   q and repeat for all eight bits of q.
79*ab9e68a2SToomas Soome 
80*ab9e68a2SToomas Soome   The first table is simply the CRC of all possible eight bit values.  This is
81*ab9e68a2SToomas Soome   all the information needed to generate CRCs on data a byte at a time for all
82*ab9e68a2SToomas Soome   combinations of CRC register values and incoming bytes.  The remaining tables
83*ab9e68a2SToomas Soome   allow for word-at-a-time CRC calculation for both big-endian and little-
84*ab9e68a2SToomas Soome   endian machines, where a word is four bytes.
85*ab9e68a2SToomas Soome */
86*ab9e68a2SToomas Soome local void make_crc_table()
87*ab9e68a2SToomas Soome {
88*ab9e68a2SToomas Soome     z_crc_t c;
89*ab9e68a2SToomas Soome     int n, k;
90*ab9e68a2SToomas Soome     z_crc_t poly;                       /* polynomial exclusive-or pattern */
91*ab9e68a2SToomas Soome     /* terms of polynomial defining this crc (except x^32): */
92*ab9e68a2SToomas Soome     static volatile int first = 1;      /* flag to limit concurrent making */
93*ab9e68a2SToomas Soome     static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26};
94*ab9e68a2SToomas Soome 
95*ab9e68a2SToomas Soome     /* See if another task is already doing this (not thread-safe, but better
96*ab9e68a2SToomas Soome        than nothing -- significantly reduces duration of vulnerability in
97*ab9e68a2SToomas Soome        case the advice about DYNAMIC_CRC_TABLE is ignored) */
98*ab9e68a2SToomas Soome     if (first) {
99*ab9e68a2SToomas Soome         first = 0;
100*ab9e68a2SToomas Soome 
101*ab9e68a2SToomas Soome         /* make exclusive-or pattern from polynomial (0xedb88320UL) */
102*ab9e68a2SToomas Soome         poly = 0;
103*ab9e68a2SToomas Soome         for (n = 0; n < (int)(sizeof(p)/sizeof(unsigned char)); n++)
104*ab9e68a2SToomas Soome             poly |= (z_crc_t)1 << (31 - p[n]);
105*ab9e68a2SToomas Soome 
106*ab9e68a2SToomas Soome         /* generate a crc for every 8-bit value */
107*ab9e68a2SToomas Soome         for (n = 0; n < 256; n++) {
108*ab9e68a2SToomas Soome             c = (z_crc_t)n;
109*ab9e68a2SToomas Soome             for (k = 0; k < 8; k++)
110*ab9e68a2SToomas Soome                 c = c & 1 ? poly ^ (c >> 1) : c >> 1;
111*ab9e68a2SToomas Soome             crc_table[0][n] = c;
112*ab9e68a2SToomas Soome         }
113*ab9e68a2SToomas Soome 
114*ab9e68a2SToomas Soome #ifdef BYFOUR
115*ab9e68a2SToomas Soome         /* generate crc for each value followed by one, two, and three zeros,
116*ab9e68a2SToomas Soome            and then the byte reversal of those as well as the first table */
117*ab9e68a2SToomas Soome         for (n = 0; n < 256; n++) {
118*ab9e68a2SToomas Soome             c = crc_table[0][n];
119*ab9e68a2SToomas Soome             crc_table[4][n] = ZSWAP32(c);
120*ab9e68a2SToomas Soome             for (k = 1; k < 4; k++) {
121*ab9e68a2SToomas Soome                 c = crc_table[0][c & 0xff] ^ (c >> 8);
122*ab9e68a2SToomas Soome                 crc_table[k][n] = c;
123*ab9e68a2SToomas Soome                 crc_table[k + 4][n] = ZSWAP32(c);
124*ab9e68a2SToomas Soome             }
125*ab9e68a2SToomas Soome         }
126*ab9e68a2SToomas Soome #endif /* BYFOUR */
127*ab9e68a2SToomas Soome 
128*ab9e68a2SToomas Soome         crc_table_empty = 0;
129*ab9e68a2SToomas Soome     }
130*ab9e68a2SToomas Soome     else {      /* not first */
131*ab9e68a2SToomas Soome         /* wait for the other guy to finish (not efficient, but rare) */
132*ab9e68a2SToomas Soome         while (crc_table_empty)
133*ab9e68a2SToomas Soome             ;
134*ab9e68a2SToomas Soome     }
135*ab9e68a2SToomas Soome 
136*ab9e68a2SToomas Soome #ifdef MAKECRCH
137*ab9e68a2SToomas Soome     /* write out CRC tables to crc32.h */
138*ab9e68a2SToomas Soome     {
139*ab9e68a2SToomas Soome         FILE *out;
140*ab9e68a2SToomas Soome 
141*ab9e68a2SToomas Soome         out = fopen("crc32.h", "w");
142*ab9e68a2SToomas Soome         if (out == NULL) return;
143*ab9e68a2SToomas Soome         fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n");
144*ab9e68a2SToomas Soome         fprintf(out, " * Generated automatically by crc32.c\n */\n\n");
145*ab9e68a2SToomas Soome         fprintf(out, "local const z_crc_t FAR ");
146*ab9e68a2SToomas Soome         fprintf(out, "crc_table[TBLS][256] =\n{\n  {\n");
147*ab9e68a2SToomas Soome         write_table(out, crc_table[0]);
148*ab9e68a2SToomas Soome #  ifdef BYFOUR
149*ab9e68a2SToomas Soome         fprintf(out, "#ifdef BYFOUR\n");
150*ab9e68a2SToomas Soome         for (k = 1; k < 8; k++) {
151*ab9e68a2SToomas Soome             fprintf(out, "  },\n  {\n");
152*ab9e68a2SToomas Soome             write_table(out, crc_table[k]);
153*ab9e68a2SToomas Soome         }
154*ab9e68a2SToomas Soome         fprintf(out, "#endif\n");
155*ab9e68a2SToomas Soome #  endif /* BYFOUR */
156*ab9e68a2SToomas Soome         fprintf(out, "  }\n};\n");
157*ab9e68a2SToomas Soome         fclose(out);
158*ab9e68a2SToomas Soome     }
159*ab9e68a2SToomas Soome #endif /* MAKECRCH */
160*ab9e68a2SToomas Soome }
161*ab9e68a2SToomas Soome 
162*ab9e68a2SToomas Soome #ifdef MAKECRCH
163*ab9e68a2SToomas Soome local void write_table(out, table)
164*ab9e68a2SToomas Soome     FILE *out;
165*ab9e68a2SToomas Soome     const z_crc_t FAR *table;
166*ab9e68a2SToomas Soome {
167*ab9e68a2SToomas Soome     int n;
168*ab9e68a2SToomas Soome 
169*ab9e68a2SToomas Soome     for (n = 0; n < 256; n++)
170*ab9e68a2SToomas Soome         fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : "    ",
171*ab9e68a2SToomas Soome                 (unsigned long)(table[n]),
172*ab9e68a2SToomas Soome                 n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", "));
173*ab9e68a2SToomas Soome }
174*ab9e68a2SToomas Soome #endif /* MAKECRCH */
175*ab9e68a2SToomas Soome 
176*ab9e68a2SToomas Soome #else /* !DYNAMIC_CRC_TABLE */
177*ab9e68a2SToomas Soome /* ========================================================================
178*ab9e68a2SToomas Soome  * Tables of CRC-32s of all single-byte values, made by make_crc_table().
179*ab9e68a2SToomas Soome  */
180*ab9e68a2SToomas Soome #include "crc32.h"
181*ab9e68a2SToomas Soome #endif /* DYNAMIC_CRC_TABLE */
182*ab9e68a2SToomas Soome 
183*ab9e68a2SToomas Soome /* =========================================================================
184*ab9e68a2SToomas Soome  * This function can be used by asm versions of crc32()
185*ab9e68a2SToomas Soome  */
186*ab9e68a2SToomas Soome const z_crc_t FAR * ZEXPORT get_crc_table(void)
187*ab9e68a2SToomas Soome {
188*ab9e68a2SToomas Soome #ifdef DYNAMIC_CRC_TABLE
189*ab9e68a2SToomas Soome     if (crc_table_empty)
190*ab9e68a2SToomas Soome         make_crc_table();
191*ab9e68a2SToomas Soome #endif /* DYNAMIC_CRC_TABLE */
192*ab9e68a2SToomas Soome     return (const z_crc_t FAR *)crc_table;
193*ab9e68a2SToomas Soome }
194*ab9e68a2SToomas Soome 
195*ab9e68a2SToomas Soome /* ========================================================================= */
196*ab9e68a2SToomas Soome #define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8)
197*ab9e68a2SToomas Soome #define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1
198*ab9e68a2SToomas Soome 
199*ab9e68a2SToomas Soome /* ========================================================================= */
200*ab9e68a2SToomas Soome unsigned long ZEXPORT crc32_z(unsigned long crc, const unsigned char FAR *buf,
201*ab9e68a2SToomas Soome     z_size_t len)
202*ab9e68a2SToomas Soome {
203*ab9e68a2SToomas Soome     if (buf == Z_NULL) return 0UL;
204*ab9e68a2SToomas Soome 
205*ab9e68a2SToomas Soome #ifdef DYNAMIC_CRC_TABLE
206*ab9e68a2SToomas Soome     if (crc_table_empty)
207*ab9e68a2SToomas Soome         make_crc_table();
208*ab9e68a2SToomas Soome #endif /* DYNAMIC_CRC_TABLE */
209*ab9e68a2SToomas Soome 
210*ab9e68a2SToomas Soome #ifdef BYFOUR
211*ab9e68a2SToomas Soome     if (sizeof(void *) == sizeof(ptrdiff_t)) {
212*ab9e68a2SToomas Soome         z_crc_t endian;
213*ab9e68a2SToomas Soome 
214*ab9e68a2SToomas Soome         endian = 1;
215*ab9e68a2SToomas Soome         if (*((unsigned char *)(&endian)))
216*ab9e68a2SToomas Soome             return crc32_little(crc, buf, len);
217*ab9e68a2SToomas Soome         else
218*ab9e68a2SToomas Soome             return crc32_big(crc, buf, len);
219*ab9e68a2SToomas Soome     }
220*ab9e68a2SToomas Soome #endif /* BYFOUR */
221*ab9e68a2SToomas Soome     crc = crc ^ 0xffffffffUL;
222*ab9e68a2SToomas Soome     while (len >= 8) {
223*ab9e68a2SToomas Soome         DO8;
224*ab9e68a2SToomas Soome         len -= 8;
225*ab9e68a2SToomas Soome     }
226*ab9e68a2SToomas Soome     if (len) do {
227*ab9e68a2SToomas Soome         DO1;
228*ab9e68a2SToomas Soome     } while (--len);
229*ab9e68a2SToomas Soome     return crc ^ 0xffffffffUL;
230*ab9e68a2SToomas Soome }
231*ab9e68a2SToomas Soome 
232*ab9e68a2SToomas Soome /* ========================================================================= */
233*ab9e68a2SToomas Soome unsigned long ZEXPORT crc32(unsigned long crc, const unsigned char FAR *buf,
234*ab9e68a2SToomas Soome     uInt len)
235*ab9e68a2SToomas Soome {
236*ab9e68a2SToomas Soome     return crc32_z(crc, buf, len);
237*ab9e68a2SToomas Soome }
238*ab9e68a2SToomas Soome 
239*ab9e68a2SToomas Soome #ifdef BYFOUR
240*ab9e68a2SToomas Soome 
241*ab9e68a2SToomas Soome /*
242*ab9e68a2SToomas Soome    This BYFOUR code accesses the passed unsigned char * buffer with a 32-bit
243*ab9e68a2SToomas Soome    integer pointer type. This violates the strict aliasing rule, where a
244*ab9e68a2SToomas Soome    compiler can assume, for optimization purposes, that two pointers to
245*ab9e68a2SToomas Soome    fundamentally different types won't ever point to the same memory. This can
246*ab9e68a2SToomas Soome    manifest as a problem only if one of the pointers is written to. This code
247*ab9e68a2SToomas Soome    only reads from those pointers. So long as this code remains isolated in
248*ab9e68a2SToomas Soome    this compilation unit, there won't be a problem. For this reason, this code
249*ab9e68a2SToomas Soome    should not be copied and pasted into a compilation unit in which other code
250*ab9e68a2SToomas Soome    writes to the buffer that is passed to these routines.
251*ab9e68a2SToomas Soome  */
252*ab9e68a2SToomas Soome 
253*ab9e68a2SToomas Soome /* ========================================================================= */
254*ab9e68a2SToomas Soome #define DOLIT4 c ^= *buf4++; \
255*ab9e68a2SToomas Soome         c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \
256*ab9e68a2SToomas Soome             crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24]
257*ab9e68a2SToomas Soome #define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4
258*ab9e68a2SToomas Soome 
259*ab9e68a2SToomas Soome /* ========================================================================= */
260*ab9e68a2SToomas Soome local unsigned long crc32_little(unsigned long crc,
261*ab9e68a2SToomas Soome     const unsigned char FAR *buf, z_size_t len)
262*ab9e68a2SToomas Soome {
263*ab9e68a2SToomas Soome     register z_crc_t c;
264*ab9e68a2SToomas Soome     register const z_crc_t FAR *buf4;
265*ab9e68a2SToomas Soome 
266*ab9e68a2SToomas Soome     c = (z_crc_t)crc;
267*ab9e68a2SToomas Soome     c = ~c;
268*ab9e68a2SToomas Soome     while (len && ((ptrdiff_t)buf & 3)) {
269*ab9e68a2SToomas Soome         c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8);
270*ab9e68a2SToomas Soome         len--;
271*ab9e68a2SToomas Soome     }
272*ab9e68a2SToomas Soome 
273*ab9e68a2SToomas Soome     buf4 = (const z_crc_t FAR *)(const void FAR *)buf;
274*ab9e68a2SToomas Soome     while (len >= 32) {
275*ab9e68a2SToomas Soome         DOLIT32;
276*ab9e68a2SToomas Soome         len -= 32;
277*ab9e68a2SToomas Soome     }
278*ab9e68a2SToomas Soome     while (len >= 4) {
279*ab9e68a2SToomas Soome         DOLIT4;
280*ab9e68a2SToomas Soome         len -= 4;
281*ab9e68a2SToomas Soome     }
282*ab9e68a2SToomas Soome     buf = (const unsigned char FAR *)buf4;
283*ab9e68a2SToomas Soome 
284*ab9e68a2SToomas Soome     if (len) do {
285*ab9e68a2SToomas Soome         c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8);
286*ab9e68a2SToomas Soome     } while (--len);
287*ab9e68a2SToomas Soome     c = ~c;
288*ab9e68a2SToomas Soome     return (unsigned long)c;
289*ab9e68a2SToomas Soome }
290*ab9e68a2SToomas Soome 
291*ab9e68a2SToomas Soome /* ========================================================================= */
292*ab9e68a2SToomas Soome #define DOBIG4 c ^= *buf4++; \
293*ab9e68a2SToomas Soome         c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \
294*ab9e68a2SToomas Soome             crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24]
295*ab9e68a2SToomas Soome #define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4
296*ab9e68a2SToomas Soome 
297*ab9e68a2SToomas Soome /* ========================================================================= */
298*ab9e68a2SToomas Soome local unsigned long crc32_big(unsigned long crc, const unsigned char FAR *buf,
299*ab9e68a2SToomas Soome     z_size_t len)
300*ab9e68a2SToomas Soome {
301*ab9e68a2SToomas Soome     register z_crc_t c;
302*ab9e68a2SToomas Soome     register const z_crc_t FAR *buf4;
303*ab9e68a2SToomas Soome 
304*ab9e68a2SToomas Soome     c = ZSWAP32((z_crc_t)crc);
305*ab9e68a2SToomas Soome     c = ~c;
306*ab9e68a2SToomas Soome     while (len && ((ptrdiff_t)buf & 3)) {
307*ab9e68a2SToomas Soome         c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
308*ab9e68a2SToomas Soome         len--;
309*ab9e68a2SToomas Soome     }
310*ab9e68a2SToomas Soome 
311*ab9e68a2SToomas Soome     buf4 = (const z_crc_t FAR *)(const void FAR *)buf;
312*ab9e68a2SToomas Soome     while (len >= 32) {
313*ab9e68a2SToomas Soome         DOBIG32;
314*ab9e68a2SToomas Soome         len -= 32;
315*ab9e68a2SToomas Soome     }
316*ab9e68a2SToomas Soome     while (len >= 4) {
317*ab9e68a2SToomas Soome         DOBIG4;
318*ab9e68a2SToomas Soome         len -= 4;
319*ab9e68a2SToomas Soome     }
320*ab9e68a2SToomas Soome     buf = (const unsigned char FAR *)buf4;
321*ab9e68a2SToomas Soome 
322*ab9e68a2SToomas Soome     if (len) do {
323*ab9e68a2SToomas Soome         c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
324*ab9e68a2SToomas Soome     } while (--len);
325*ab9e68a2SToomas Soome     c = ~c;
326*ab9e68a2SToomas Soome     return (unsigned long)(ZSWAP32(c));
327*ab9e68a2SToomas Soome }
328*ab9e68a2SToomas Soome 
329*ab9e68a2SToomas Soome #endif /* BYFOUR */
330*ab9e68a2SToomas Soome 
331*ab9e68a2SToomas Soome #define GF2_DIM 32      /* dimension of GF(2) vectors (length of CRC) */
332*ab9e68a2SToomas Soome 
333*ab9e68a2SToomas Soome /* ========================================================================= */
334*ab9e68a2SToomas Soome local unsigned long gf2_matrix_times(unsigned long *mat, unsigned long vec)
335*ab9e68a2SToomas Soome {
336*ab9e68a2SToomas Soome     unsigned long sum;
337*ab9e68a2SToomas Soome 
338*ab9e68a2SToomas Soome     sum = 0;
339*ab9e68a2SToomas Soome     while (vec) {
340*ab9e68a2SToomas Soome         if (vec & 1)
341*ab9e68a2SToomas Soome             sum ^= *mat;
342*ab9e68a2SToomas Soome         vec >>= 1;
343*ab9e68a2SToomas Soome         mat++;
344*ab9e68a2SToomas Soome     }
345*ab9e68a2SToomas Soome     return sum;
346*ab9e68a2SToomas Soome }
347*ab9e68a2SToomas Soome 
348*ab9e68a2SToomas Soome /* ========================================================================= */
349*ab9e68a2SToomas Soome local void gf2_matrix_square(unsigned long *square, unsigned long *mat)
350*ab9e68a2SToomas Soome {
351*ab9e68a2SToomas Soome     int n;
352*ab9e68a2SToomas Soome 
353*ab9e68a2SToomas Soome     for (n = 0; n < GF2_DIM; n++)
354*ab9e68a2SToomas Soome         square[n] = gf2_matrix_times(mat, mat[n]);
355*ab9e68a2SToomas Soome }
356*ab9e68a2SToomas Soome 
357*ab9e68a2SToomas Soome /* ========================================================================= */
358*ab9e68a2SToomas Soome local uLong crc32_combine_(uLong crc1, uLong crc2, z_off64_t len2)
359*ab9e68a2SToomas Soome {
360*ab9e68a2SToomas Soome     int n;
361*ab9e68a2SToomas Soome     unsigned long row;
362*ab9e68a2SToomas Soome     unsigned long even[GF2_DIM];    /* even-power-of-two zeros operator */
363*ab9e68a2SToomas Soome     unsigned long odd[GF2_DIM];     /* odd-power-of-two zeros operator */
364*ab9e68a2SToomas Soome 
365*ab9e68a2SToomas Soome     /* degenerate case (also disallow negative lengths) */
366*ab9e68a2SToomas Soome     if (len2 <= 0)
367*ab9e68a2SToomas Soome         return crc1;
368*ab9e68a2SToomas Soome 
369*ab9e68a2SToomas Soome     /* put operator for one zero bit in odd */
370*ab9e68a2SToomas Soome     odd[0] = 0xedb88320UL;          /* CRC-32 polynomial */
371*ab9e68a2SToomas Soome     row = 1;
372*ab9e68a2SToomas Soome     for (n = 1; n < GF2_DIM; n++) {
373*ab9e68a2SToomas Soome         odd[n] = row;
374*ab9e68a2SToomas Soome         row <<= 1;
375*ab9e68a2SToomas Soome     }
376*ab9e68a2SToomas Soome 
377*ab9e68a2SToomas Soome     /* put operator for two zero bits in even */
378*ab9e68a2SToomas Soome     gf2_matrix_square(even, odd);
379*ab9e68a2SToomas Soome 
380*ab9e68a2SToomas Soome     /* put operator for four zero bits in odd */
381*ab9e68a2SToomas Soome     gf2_matrix_square(odd, even);
382*ab9e68a2SToomas Soome 
383*ab9e68a2SToomas Soome     /* apply len2 zeros to crc1 (first square will put the operator for one
384*ab9e68a2SToomas Soome        zero byte, eight zero bits, in even) */
385*ab9e68a2SToomas Soome     do {
386*ab9e68a2SToomas Soome         /* apply zeros operator for this bit of len2 */
387*ab9e68a2SToomas Soome         gf2_matrix_square(even, odd);
388*ab9e68a2SToomas Soome         if (len2 & 1)
389*ab9e68a2SToomas Soome             crc1 = gf2_matrix_times(even, crc1);
390*ab9e68a2SToomas Soome         len2 >>= 1;
391*ab9e68a2SToomas Soome 
392*ab9e68a2SToomas Soome         /* if no more bits set, then done */
393*ab9e68a2SToomas Soome         if (len2 == 0)
394*ab9e68a2SToomas Soome             break;
395*ab9e68a2SToomas Soome 
396*ab9e68a2SToomas Soome         /* another iteration of the loop with odd and even swapped */
397*ab9e68a2SToomas Soome         gf2_matrix_square(odd, even);
398*ab9e68a2SToomas Soome         if (len2 & 1)
399*ab9e68a2SToomas Soome             crc1 = gf2_matrix_times(odd, crc1);
400*ab9e68a2SToomas Soome         len2 >>= 1;
401*ab9e68a2SToomas Soome 
402*ab9e68a2SToomas Soome         /* if no more bits set, then done */
403*ab9e68a2SToomas Soome     } while (len2 != 0);
404*ab9e68a2SToomas Soome 
405*ab9e68a2SToomas Soome     /* return combined crc */
406*ab9e68a2SToomas Soome     crc1 ^= crc2;
407*ab9e68a2SToomas Soome     return crc1;
408*ab9e68a2SToomas Soome }
409*ab9e68a2SToomas Soome 
410*ab9e68a2SToomas Soome /* ========================================================================= */
411*ab9e68a2SToomas Soome uLong ZEXPORT crc32_combine(uLong crc1, uLong crc2, z_off_t len2)
412*ab9e68a2SToomas Soome {
413*ab9e68a2SToomas Soome     return crc32_combine_(crc1, crc2, len2);
414*ab9e68a2SToomas Soome }
415*ab9e68a2SToomas Soome 
416*ab9e68a2SToomas Soome uLong ZEXPORT crc32_combine64(uLong crc1, uLong crc2, z_off64_t len2)
417*ab9e68a2SToomas Soome {
418*ab9e68a2SToomas Soome     return crc32_combine_(crc1, crc2, len2);
419*ab9e68a2SToomas Soome }
420