17dd7cddfSDavid du Colombier /* crc32.c -- compute the CRC-32 of a data stream
2*593dc095SDavid du Colombier * Copyright (C) 1995-2003 Mark Adler
37dd7cddfSDavid du Colombier * For conditions of distribution and use, see copyright notice in zlib.h
4*593dc095SDavid du Colombier *
5*593dc095SDavid du Colombier * Thanks to Rodney Brown <rbrown64@csc.com.au> for his contribution of faster
6*593dc095SDavid du Colombier * CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing
7*593dc095SDavid du Colombier * tables for updating the shift register in one step with three exclusive-ors
8*593dc095SDavid du Colombier * instead of four steps with four exclusive-ors. This results about a factor
9*593dc095SDavid du Colombier * of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3.
107dd7cddfSDavid du Colombier */
117dd7cddfSDavid du Colombier
12*593dc095SDavid du Colombier /* @(#) $Id: crc32.c,v 1.1.1.1 2005/04/24 21:39:37 giles Exp $ */
137dd7cddfSDavid du Colombier
14*593dc095SDavid du Colombier /*
15*593dc095SDavid du Colombier Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore
16*593dc095SDavid du Colombier protection on the static variables used to control the first-use generation
17*593dc095SDavid du Colombier of the crc tables. Therefore, if you #define DYNAMIC_CRC_TABLE, you should
18*593dc095SDavid du Colombier first call get_crc_table() to initialize the tables before allowing more than
19*593dc095SDavid du Colombier one thread to use crc32().
20*593dc095SDavid du Colombier */
21*593dc095SDavid du Colombier
22*593dc095SDavid du Colombier #ifdef MAKECRCH
23*593dc095SDavid du Colombier # include <stdio.h>
24*593dc095SDavid du Colombier # ifndef DYNAMIC_CRC_TABLE
25*593dc095SDavid du Colombier # define DYNAMIC_CRC_TABLE
26*593dc095SDavid du Colombier # endif /* !DYNAMIC_CRC_TABLE */
27*593dc095SDavid du Colombier #endif /* MAKECRCH */
28*593dc095SDavid du Colombier
29*593dc095SDavid du Colombier #include "zutil.h" /* for STDC and FAR definitions */
307dd7cddfSDavid du Colombier
317dd7cddfSDavid du Colombier #define local static
327dd7cddfSDavid du Colombier
33*593dc095SDavid du Colombier /* Find a four-byte integer type for crc32_little() and crc32_big(). */
34*593dc095SDavid du Colombier #ifndef NOBYFOUR
35*593dc095SDavid du Colombier # ifdef STDC /* need ANSI C limits.h to determine sizes */
36*593dc095SDavid du Colombier # include <limits.h>
37*593dc095SDavid du Colombier # define BYFOUR
38*593dc095SDavid du Colombier # if (UINT_MAX == 0xffffffffUL)
39*593dc095SDavid du Colombier typedef unsigned int u4;
40*593dc095SDavid du Colombier # else
41*593dc095SDavid du Colombier # if (ULONG_MAX == 0xffffffffUL)
42*593dc095SDavid du Colombier typedef unsigned long u4;
43*593dc095SDavid du Colombier # else
44*593dc095SDavid du Colombier # if (USHRT_MAX == 0xffffffffUL)
45*593dc095SDavid du Colombier typedef unsigned short u4;
46*593dc095SDavid du Colombier # else
47*593dc095SDavid du Colombier # undef BYFOUR /* can't find a four-byte integer type! */
48*593dc095SDavid du Colombier # endif
49*593dc095SDavid du Colombier # endif
50*593dc095SDavid du Colombier # endif
51*593dc095SDavid du Colombier # endif /* STDC */
52*593dc095SDavid du Colombier #endif /* !NOBYFOUR */
53*593dc095SDavid du Colombier
54*593dc095SDavid du Colombier /* Definitions for doing the crc four data bytes at a time. */
55*593dc095SDavid du Colombier #ifdef BYFOUR
56*593dc095SDavid du Colombier # define REV(w) (((w)>>24)+(((w)>>8)&0xff00)+ \
57*593dc095SDavid du Colombier (((w)&0xff00)<<8)+(((w)&0xff)<<24))
58*593dc095SDavid du Colombier local unsigned long crc32_little OF((unsigned long,
59*593dc095SDavid du Colombier const unsigned char FAR *, unsigned));
60*593dc095SDavid du Colombier local unsigned long crc32_big OF((unsigned long,
61*593dc095SDavid du Colombier const unsigned char FAR *, unsigned));
62*593dc095SDavid du Colombier # define TBLS 8
63*593dc095SDavid du Colombier #else
64*593dc095SDavid du Colombier # define TBLS 1
65*593dc095SDavid du Colombier #endif /* BYFOUR */
66*593dc095SDavid du Colombier
677dd7cddfSDavid du Colombier #ifdef DYNAMIC_CRC_TABLE
687dd7cddfSDavid du Colombier
69*593dc095SDavid du Colombier local volatile int crc_table_empty = 1;
70*593dc095SDavid du Colombier local unsigned long FAR crc_table[TBLS][256];
717dd7cddfSDavid du Colombier local void make_crc_table OF((void));
72*593dc095SDavid du Colombier #ifdef MAKECRCH
73*593dc095SDavid du Colombier local void write_table OF((FILE *, const unsigned long FAR *));
74*593dc095SDavid du Colombier #endif /* MAKECRCH */
757dd7cddfSDavid du Colombier
767dd7cddfSDavid du Colombier /*
77*593dc095SDavid du Colombier Generate tables for a byte-wise 32-bit CRC calculation on the polynomial:
787dd7cddfSDavid du Colombier 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.
797dd7cddfSDavid du Colombier
807dd7cddfSDavid du Colombier Polynomials over GF(2) are represented in binary, one bit per coefficient,
817dd7cddfSDavid du Colombier with the lowest powers in the most significant bit. Then adding polynomials
827dd7cddfSDavid du Colombier is just exclusive-or, and multiplying a polynomial by x is a right shift by
837dd7cddfSDavid du Colombier one. If we call the above polynomial p, and represent a byte as the
847dd7cddfSDavid du Colombier polynomial q, also with the lowest power in the most significant bit (so the
857dd7cddfSDavid du Colombier byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p,
867dd7cddfSDavid du Colombier where a mod b means the remainder after dividing a by b.
877dd7cddfSDavid du Colombier
887dd7cddfSDavid du Colombier This calculation is done using the shift-register method of multiplying and
897dd7cddfSDavid du Colombier taking the remainder. The register is initialized to zero, and for each
907dd7cddfSDavid du Colombier incoming bit, x^32 is added mod p to the register if the bit is a one (where
917dd7cddfSDavid du Colombier x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by
927dd7cddfSDavid du Colombier x (which is shifting right by one and adding x^32 mod p if the bit shifted
937dd7cddfSDavid du Colombier out is a one). We start with the highest power (least significant bit) of
947dd7cddfSDavid du Colombier q and repeat for all eight bits of q.
957dd7cddfSDavid du Colombier
96*593dc095SDavid du Colombier The first table is simply the CRC of all possible eight bit values. This is
97*593dc095SDavid du Colombier all the information needed to generate CRCs on data a byte at a time for all
98*593dc095SDavid du Colombier combinations of CRC register values and incoming bytes. The remaining tables
99*593dc095SDavid du Colombier allow for word-at-a-time CRC calculation for both big-endian and little-
100*593dc095SDavid du Colombier endian machines, where a word is four bytes.
1017dd7cddfSDavid du Colombier */
make_crc_table()1027dd7cddfSDavid du Colombier local void make_crc_table()
1037dd7cddfSDavid du Colombier {
104*593dc095SDavid du Colombier unsigned long c;
1057dd7cddfSDavid du Colombier int n, k;
106*593dc095SDavid du Colombier unsigned long poly; /* polynomial exclusive-or pattern */
1077dd7cddfSDavid du Colombier /* terms of polynomial defining this crc (except x^32): */
108*593dc095SDavid du Colombier static volatile int first = 1; /* flag to limit concurrent making */
109*593dc095SDavid du Colombier static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26};
1107dd7cddfSDavid du Colombier
111*593dc095SDavid du Colombier /* See if another task is already doing this (not thread-safe, but better
112*593dc095SDavid du Colombier than nothing -- significantly reduces duration of vulnerability in
113*593dc095SDavid du Colombier case the advice about DYNAMIC_CRC_TABLE is ignored) */
114*593dc095SDavid du Colombier if (first) {
115*593dc095SDavid du Colombier first = 0;
1167dd7cddfSDavid du Colombier
117*593dc095SDavid du Colombier /* make exclusive-or pattern from polynomial (0xedb88320UL) */
118*593dc095SDavid du Colombier poly = 0UL;
119*593dc095SDavid du Colombier for (n = 0; n < sizeof(p)/sizeof(unsigned char); n++)
120*593dc095SDavid du Colombier poly |= 1UL << (31 - p[n]);
121*593dc095SDavid du Colombier
122*593dc095SDavid du Colombier /* generate a crc for every 8-bit value */
123*593dc095SDavid du Colombier for (n = 0; n < 256; n++) {
124*593dc095SDavid du Colombier c = (unsigned long)n;
1257dd7cddfSDavid du Colombier for (k = 0; k < 8; k++)
1267dd7cddfSDavid du Colombier c = c & 1 ? poly ^ (c >> 1) : c >> 1;
127*593dc095SDavid du Colombier crc_table[0][n] = c;
1287dd7cddfSDavid du Colombier }
129*593dc095SDavid du Colombier
130*593dc095SDavid du Colombier #ifdef BYFOUR
131*593dc095SDavid du Colombier /* generate crc for each value followed by one, two, and three zeros,
132*593dc095SDavid du Colombier and then the byte reversal of those as well as the first table */
133*593dc095SDavid du Colombier for (n = 0; n < 256; n++) {
134*593dc095SDavid du Colombier c = crc_table[0][n];
135*593dc095SDavid du Colombier crc_table[4][n] = REV(c);
136*593dc095SDavid du Colombier for (k = 1; k < 4; k++) {
137*593dc095SDavid du Colombier c = crc_table[0][c & 0xff] ^ (c >> 8);
138*593dc095SDavid du Colombier crc_table[k][n] = c;
139*593dc095SDavid du Colombier crc_table[k + 4][n] = REV(c);
140*593dc095SDavid du Colombier }
141*593dc095SDavid du Colombier }
142*593dc095SDavid du Colombier #endif /* BYFOUR */
143*593dc095SDavid du Colombier
1447dd7cddfSDavid du Colombier crc_table_empty = 0;
1457dd7cddfSDavid du Colombier }
146*593dc095SDavid du Colombier else { /* not first */
147*593dc095SDavid du Colombier /* wait for the other guy to finish (not efficient, but rare) */
148*593dc095SDavid du Colombier while (crc_table_empty)
149*593dc095SDavid du Colombier ;
150*593dc095SDavid du Colombier }
151*593dc095SDavid du Colombier
152*593dc095SDavid du Colombier #ifdef MAKECRCH
153*593dc095SDavid du Colombier /* write out CRC tables to crc32.h */
154*593dc095SDavid du Colombier {
155*593dc095SDavid du Colombier FILE *out;
156*593dc095SDavid du Colombier
157*593dc095SDavid du Colombier out = fopen("crc32.h", "w");
158*593dc095SDavid du Colombier if (out == NULL) return;
159*593dc095SDavid du Colombier fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n");
160*593dc095SDavid du Colombier fprintf(out, " * Generated automatically by crc32.c\n */\n\n");
161*593dc095SDavid du Colombier fprintf(out, "local const unsigned long FAR ");
162*593dc095SDavid du Colombier fprintf(out, "crc_table[TBLS][256] =\n{\n {\n");
163*593dc095SDavid du Colombier write_table(out, crc_table[0]);
164*593dc095SDavid du Colombier # ifdef BYFOUR
165*593dc095SDavid du Colombier fprintf(out, "#ifdef BYFOUR\n");
166*593dc095SDavid du Colombier for (k = 1; k < 8; k++) {
167*593dc095SDavid du Colombier fprintf(out, " },\n {\n");
168*593dc095SDavid du Colombier write_table(out, crc_table[k]);
169*593dc095SDavid du Colombier }
170*593dc095SDavid du Colombier fprintf(out, "#endif\n");
171*593dc095SDavid du Colombier # endif /* BYFOUR */
172*593dc095SDavid du Colombier fprintf(out, " }\n};\n");
173*593dc095SDavid du Colombier fclose(out);
174*593dc095SDavid du Colombier }
175*593dc095SDavid du Colombier #endif /* MAKECRCH */
176*593dc095SDavid du Colombier }
177*593dc095SDavid du Colombier
178*593dc095SDavid du Colombier #ifdef MAKECRCH
write_table(out,table)179*593dc095SDavid du Colombier local void write_table(out, table)
180*593dc095SDavid du Colombier FILE *out;
181*593dc095SDavid du Colombier const unsigned long FAR *table;
182*593dc095SDavid du Colombier {
183*593dc095SDavid du Colombier int n;
184*593dc095SDavid du Colombier
185*593dc095SDavid du Colombier for (n = 0; n < 256; n++)
186*593dc095SDavid du Colombier fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : " ", table[n],
187*593dc095SDavid du Colombier n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", "));
188*593dc095SDavid du Colombier }
189*593dc095SDavid du Colombier #endif /* MAKECRCH */
190*593dc095SDavid du Colombier
191*593dc095SDavid du Colombier #else /* !DYNAMIC_CRC_TABLE */
1927dd7cddfSDavid du Colombier /* ========================================================================
193*593dc095SDavid du Colombier * Tables of CRC-32s of all single-byte values, made by make_crc_table().
1947dd7cddfSDavid du Colombier */
195*593dc095SDavid du Colombier #include "crc32.h"
196*593dc095SDavid du Colombier #endif /* DYNAMIC_CRC_TABLE */
1977dd7cddfSDavid du Colombier
1987dd7cddfSDavid du Colombier /* =========================================================================
1997dd7cddfSDavid du Colombier * This function can be used by asm versions of crc32()
2007dd7cddfSDavid du Colombier */
get_crc_table()201*593dc095SDavid du Colombier const unsigned long FAR * ZEXPORT get_crc_table()
2027dd7cddfSDavid du Colombier {
2037dd7cddfSDavid du Colombier #ifdef DYNAMIC_CRC_TABLE
2047dd7cddfSDavid du Colombier if (crc_table_empty)
2057dd7cddfSDavid du Colombier make_crc_table();
206*593dc095SDavid du Colombier #endif /* DYNAMIC_CRC_TABLE */
207*593dc095SDavid du Colombier return (const unsigned long FAR *)crc_table;
208*593dc095SDavid du Colombier }
209*593dc095SDavid du Colombier
210*593dc095SDavid du Colombier /* ========================================================================= */
211*593dc095SDavid du Colombier #define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8)
212*593dc095SDavid du Colombier #define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1
213*593dc095SDavid du Colombier
214*593dc095SDavid du Colombier /* ========================================================================= */
crc32(crc,buf,len)215*593dc095SDavid du Colombier unsigned long ZEXPORT crc32(crc, buf, len)
216*593dc095SDavid du Colombier unsigned long crc;
217*593dc095SDavid du Colombier const unsigned char FAR *buf;
218*593dc095SDavid du Colombier unsigned len;
2197dd7cddfSDavid du Colombier {
220*593dc095SDavid du Colombier if (buf == Z_NULL) return 0UL;
221*593dc095SDavid du Colombier
222*593dc095SDavid du Colombier #ifdef DYNAMIC_CRC_TABLE
223*593dc095SDavid du Colombier if (crc_table_empty)
224*593dc095SDavid du Colombier make_crc_table();
225*593dc095SDavid du Colombier #endif /* DYNAMIC_CRC_TABLE */
226*593dc095SDavid du Colombier
227*593dc095SDavid du Colombier #ifdef BYFOUR
228*593dc095SDavid du Colombier if (sizeof(void *) == sizeof(ptrdiff_t)) {
229*593dc095SDavid du Colombier u4 endian;
230*593dc095SDavid du Colombier
231*593dc095SDavid du Colombier endian = 1;
232*593dc095SDavid du Colombier if (*((unsigned char *)(&endian)))
233*593dc095SDavid du Colombier return crc32_little(crc, buf, len);
234*593dc095SDavid du Colombier else
235*593dc095SDavid du Colombier return crc32_big(crc, buf, len);
236*593dc095SDavid du Colombier }
237*593dc095SDavid du Colombier #endif /* BYFOUR */
238*593dc095SDavid du Colombier crc = crc ^ 0xffffffffUL;
239*593dc095SDavid du Colombier while (len >= 8) {
240*593dc095SDavid du Colombier DO8;
2417dd7cddfSDavid du Colombier len -= 8;
2427dd7cddfSDavid du Colombier }
2437dd7cddfSDavid du Colombier if (len) do {
244*593dc095SDavid du Colombier DO1;
2457dd7cddfSDavid du Colombier } while (--len);
246*593dc095SDavid du Colombier return crc ^ 0xffffffffUL;
2477dd7cddfSDavid du Colombier }
248*593dc095SDavid du Colombier
249*593dc095SDavid du Colombier #ifdef BYFOUR
250*593dc095SDavid du Colombier
251*593dc095SDavid du Colombier /* ========================================================================= */
252*593dc095SDavid du Colombier #define DOLIT4 c ^= *buf4++; \
253*593dc095SDavid du Colombier c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \
254*593dc095SDavid du Colombier crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24]
255*593dc095SDavid du Colombier #define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4
256*593dc095SDavid du Colombier
257*593dc095SDavid du Colombier /* ========================================================================= */
crc32_little(crc,buf,len)258*593dc095SDavid du Colombier local unsigned long crc32_little(crc, buf, len)
259*593dc095SDavid du Colombier unsigned long crc;
260*593dc095SDavid du Colombier const unsigned char FAR *buf;
261*593dc095SDavid du Colombier unsigned len;
262*593dc095SDavid du Colombier {
263*593dc095SDavid du Colombier register u4 c;
264*593dc095SDavid du Colombier register const u4 FAR *buf4;
265*593dc095SDavid du Colombier
266*593dc095SDavid du Colombier c = (u4)crc;
267*593dc095SDavid du Colombier c = ~c;
268*593dc095SDavid du Colombier while (len && ((ptrdiff_t)buf & 3)) {
269*593dc095SDavid du Colombier c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8);
270*593dc095SDavid du Colombier len--;
271*593dc095SDavid du Colombier }
272*593dc095SDavid du Colombier
273*593dc095SDavid du Colombier buf4 = (const u4 FAR *)buf;
274*593dc095SDavid du Colombier while (len >= 32) {
275*593dc095SDavid du Colombier DOLIT32;
276*593dc095SDavid du Colombier len -= 32;
277*593dc095SDavid du Colombier }
278*593dc095SDavid du Colombier while (len >= 4) {
279*593dc095SDavid du Colombier DOLIT4;
280*593dc095SDavid du Colombier len -= 4;
281*593dc095SDavid du Colombier }
282*593dc095SDavid du Colombier buf = (const unsigned char FAR *)buf4;
283*593dc095SDavid du Colombier
284*593dc095SDavid du Colombier if (len) do {
285*593dc095SDavid du Colombier c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8);
286*593dc095SDavid du Colombier } while (--len);
287*593dc095SDavid du Colombier c = ~c;
288*593dc095SDavid du Colombier return (unsigned long)c;
289*593dc095SDavid du Colombier }
290*593dc095SDavid du Colombier
291*593dc095SDavid du Colombier /* ========================================================================= */
292*593dc095SDavid du Colombier #define DOBIG4 c ^= *++buf4; \
293*593dc095SDavid du Colombier c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \
294*593dc095SDavid du Colombier crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24]
295*593dc095SDavid du Colombier #define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4
296*593dc095SDavid du Colombier
297*593dc095SDavid du Colombier /* ========================================================================= */
crc32_big(crc,buf,len)298*593dc095SDavid du Colombier local unsigned long crc32_big(crc, buf, len)
299*593dc095SDavid du Colombier unsigned long crc;
300*593dc095SDavid du Colombier const unsigned char FAR *buf;
301*593dc095SDavid du Colombier unsigned len;
302*593dc095SDavid du Colombier {
303*593dc095SDavid du Colombier register u4 c;
304*593dc095SDavid du Colombier register const u4 FAR *buf4;
305*593dc095SDavid du Colombier
306*593dc095SDavid du Colombier c = REV((u4)crc);
307*593dc095SDavid du Colombier c = ~c;
308*593dc095SDavid du Colombier while (len && ((ptrdiff_t)buf & 3)) {
309*593dc095SDavid du Colombier c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
310*593dc095SDavid du Colombier len--;
311*593dc095SDavid du Colombier }
312*593dc095SDavid du Colombier
313*593dc095SDavid du Colombier buf4 = (const u4 FAR *)buf;
314*593dc095SDavid du Colombier buf4--;
315*593dc095SDavid du Colombier while (len >= 32) {
316*593dc095SDavid du Colombier DOBIG32;
317*593dc095SDavid du Colombier len -= 32;
318*593dc095SDavid du Colombier }
319*593dc095SDavid du Colombier while (len >= 4) {
320*593dc095SDavid du Colombier DOBIG4;
321*593dc095SDavid du Colombier len -= 4;
322*593dc095SDavid du Colombier }
323*593dc095SDavid du Colombier buf4++;
324*593dc095SDavid du Colombier buf = (const unsigned char FAR *)buf4;
325*593dc095SDavid du Colombier
326*593dc095SDavid du Colombier if (len) do {
327*593dc095SDavid du Colombier c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
328*593dc095SDavid du Colombier } while (--len);
329*593dc095SDavid du Colombier c = ~c;
330*593dc095SDavid du Colombier return (unsigned long)(REV(c));
331*593dc095SDavid du Colombier }
332*593dc095SDavid du Colombier
333*593dc095SDavid du Colombier #endif /* BYFOUR */
334