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