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