c9431fa1e59a88c2f0abf611f25b97af964449e5ahl/*
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl * Use is subject to license terms.
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl */
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl/* crc32.c -- compute the CRC-32 of a data stream
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl * Copyright (C) 1995-2005 Mark Adler
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl * For conditions of distribution and use, see copyright notice in zlib.h
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl *
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl * Thanks to Rodney Brown <rbrown64@csc.com.au> for his contribution of faster
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl * CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl * tables for updating the shift register in one step with three exclusive-ors
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl * instead of four steps with four exclusive-ors. This results in about a
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl * factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3.
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl */
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl#pragma ident "%Z%%M% %I% %E% SMI"
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl/*
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl protection on the static variables used to control the first-use generation
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl of the crc tables. Therefore, if you #define DYNAMIC_CRC_TABLE, you should
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl first call get_crc_table() to initialize the tables before allowing more than
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl one thread to use crc32().
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl */
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl#ifdef MAKECRCH
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl# include <stdio.h>
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl# ifndef DYNAMIC_CRC_TABLE
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl# define DYNAMIC_CRC_TABLE
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl# endif /* !DYNAMIC_CRC_TABLE */
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl#endif /* MAKECRCH */
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl#include "zutil.h" /* for STDC and FAR definitions */
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl#define local static
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl/* Find a four-byte integer type for crc32_little() and crc32_big(). */
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl#ifndef NOBYFOUR
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl# ifdef STDC /* need ANSI C limits.h to determine sizes */
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl# include <limits.h>
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl# define BYFOUR
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl# if (UINT_MAX == 0xffffffffUL)
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl typedef unsigned int u4;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl# else
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl# if (ULONG_MAX == 0xffffffffUL)
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl typedef unsigned long u4;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl# else
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl# if (USHRT_MAX == 0xffffffffUL)
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl typedef unsigned short u4;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl# else
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl# undef BYFOUR /* can't find a four-byte integer type! */
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl# endif
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl# endif
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl# endif
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl# endif /* STDC */
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl#endif /* !NOBYFOUR */
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl/* Definitions for doing the crc four data bytes at a time. */
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl#ifdef BYFOUR
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl# define REV(w) (((w)>>24)+(((w)>>8)&0xff00)+ \
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl (((w)&0xff00)<<8)+(((w)&0xff)<<24))
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl local unsigned long crc32_little OF((unsigned long,
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl const unsigned char FAR *, unsigned));
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl local unsigned long crc32_big OF((unsigned long,
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl const unsigned char FAR *, unsigned));
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl# define TBLS 8
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl#else
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl# define TBLS 1
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl#endif /* BYFOUR */
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl/* Local functions for crc concatenation */
c9431fa1e59a88c2f0abf611f25b97af964449e5ahllocal unsigned long gf2_matrix_times OF((unsigned long *mat,
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl unsigned long vec));
c9431fa1e59a88c2f0abf611f25b97af964449e5ahllocal void gf2_matrix_square OF((unsigned long *square, unsigned long *mat));
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl#ifdef DYNAMIC_CRC_TABLE
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl
c9431fa1e59a88c2f0abf611f25b97af964449e5ahllocal volatile int crc_table_empty = 1;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahllocal unsigned long FAR crc_table[TBLS][256];
c9431fa1e59a88c2f0abf611f25b97af964449e5ahllocal void make_crc_table OF((void));
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl#ifdef MAKECRCH
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl local void write_table OF((FILE *, const unsigned long FAR *));
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl#endif /* MAKECRCH */
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl/*
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl Generate tables for a byte-wise 32-bit CRC calculation on the polynomial:
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl 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.
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl Polynomials over GF(2) are represented in binary, one bit per coefficient,
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl with the lowest powers in the most significant bit. Then adding polynomials
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl is just exclusive-or, and multiplying a polynomial by x is a right shift by
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl one. If we call the above polynomial p, and represent a byte as the
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl polynomial q, also with the lowest power in the most significant bit (so the
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p,
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl where a mod b means the remainder after dividing a by b.
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl This calculation is done using the shift-register method of multiplying and
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl taking the remainder. The register is initialized to zero, and for each
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl incoming bit, x^32 is added mod p to the register if the bit is a one (where
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl x (which is shifting right by one and adding x^32 mod p if the bit shifted
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl out is a one). We start with the highest power (least significant bit) of
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl q and repeat for all eight bits of q.
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl The first table is simply the CRC of all possible eight bit values. This is
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl all the information needed to generate CRCs on data a byte at a time for all
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl combinations of CRC register values and incoming bytes. The remaining tables
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl allow for word-at-a-time CRC calculation for both big-endian and little-
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl endian machines, where a word is four bytes.
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl*/
c9431fa1e59a88c2f0abf611f25b97af964449e5ahllocal void make_crc_table()
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl{
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl unsigned long c;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl int n, k;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl unsigned long poly; /* polynomial exclusive-or pattern */
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl /* terms of polynomial defining this crc (except x^32): */
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl static volatile int first = 1; /* flag to limit concurrent making */
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26};
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl /* See if another task is already doing this (not thread-safe, but better
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl than nothing -- significantly reduces duration of vulnerability in
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl case the advice about DYNAMIC_CRC_TABLE is ignored) */
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl if (first) {
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl first = 0;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl /* make exclusive-or pattern from polynomial (0xedb88320UL) */
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl poly = 0UL;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl for (n = 0; n < sizeof(p)/sizeof(unsigned char); n++)
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl poly |= 1UL << (31 - p[n]);
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl /* generate a crc for every 8-bit value */
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl for (n = 0; n < 256; n++) {
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl c = (unsigned long)n;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl for (k = 0; k < 8; k++)
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl c = c & 1 ? poly ^ (c >> 1) : c >> 1;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl crc_table[0][n] = c;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl }
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl#ifdef BYFOUR
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl /* generate crc for each value followed by one, two, and three zeros,
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl and then the byte reversal of those as well as the first table */
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl for (n = 0; n < 256; n++) {
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl c = crc_table[0][n];
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl crc_table[4][n] = REV(c);
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl for (k = 1; k < 4; k++) {
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl c = crc_table[0][c & 0xff] ^ (c >> 8);
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl crc_table[k][n] = c;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl crc_table[k + 4][n] = REV(c);
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl }
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl }
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl#endif /* BYFOUR */
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl crc_table_empty = 0;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl }
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl else { /* not first */
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl /* wait for the other guy to finish (not efficient, but rare) */
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl while (crc_table_empty)
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl ;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl }
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl#ifdef MAKECRCH
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl /* write out CRC tables to crc32.h */
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl {
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl FILE *out;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl out = fopen("crc32.h", "w");
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl if (out == NULL) return;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n");
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl fprintf(out, " * Generated automatically by crc32.c\n */\n\n");
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl fprintf(out, "local const unsigned long FAR ");
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl fprintf(out, "crc_table[TBLS][256] =\n{\n {\n");
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl write_table(out, crc_table[0]);
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl# ifdef BYFOUR
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl fprintf(out, "#ifdef BYFOUR\n");
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl for (k = 1; k < 8; k++) {
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl fprintf(out, " },\n {\n");
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl write_table(out, crc_table[k]);
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl }
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl fprintf(out, "#endif\n");
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl# endif /* BYFOUR */
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl fprintf(out, " }\n};\n");
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl fclose(out);
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl }
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl#endif /* MAKECRCH */
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl}
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl#ifdef MAKECRCH
c9431fa1e59a88c2f0abf611f25b97af964449e5ahllocal void write_table(out, table)
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl FILE *out;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl const unsigned long FAR *table;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl{
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl int n;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl for (n = 0; n < 256; n++)
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : " ", table[n],
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", "));
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl}
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl#endif /* MAKECRCH */
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl#else /* !DYNAMIC_CRC_TABLE */
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl/* ========================================================================
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl * Tables of CRC-32s of all single-byte values, made by make_crc_table().
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl */
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl#include "crc32.h"
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl#endif /* DYNAMIC_CRC_TABLE */
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl/* =========================================================================
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl * This function can be used by asm versions of crc32()
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl */
c9431fa1e59a88c2f0abf611f25b97af964449e5ahlconst unsigned long FAR * ZEXPORT get_crc_table()
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl{
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl#ifdef DYNAMIC_CRC_TABLE
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl if (crc_table_empty)
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl make_crc_table();
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl#endif /* DYNAMIC_CRC_TABLE */
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl return (const unsigned long FAR *)crc_table;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl}
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl/* ========================================================================= */
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl#define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8)
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl/* ========================================================================= */
c9431fa1e59a88c2f0abf611f25b97af964449e5ahlunsigned long ZEXPORT crc32(crc, buf, len)
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl unsigned long crc;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl const unsigned char FAR *buf;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl unsigned len;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl{
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl if (buf == Z_NULL) return 0UL;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl#ifdef DYNAMIC_CRC_TABLE
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl if (crc_table_empty)
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl make_crc_table();
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl#endif /* DYNAMIC_CRC_TABLE */
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl#ifdef BYFOUR
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl if (sizeof(void *) == sizeof(ptrdiff_t)) {
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl u4 endian;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl endian = 1;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl if (*((unsigned char *)(&endian)))
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl return crc32_little(crc, buf, len);
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl else
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl return crc32_big(crc, buf, len);
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl }
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl#endif /* BYFOUR */
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl crc = crc ^ 0xffffffffUL;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl while (len >= 8) {
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl DO8;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl len -= 8;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl }
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl if (len) do {
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl DO1;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl } while (--len);
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl return crc ^ 0xffffffffUL;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl}
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl#ifdef BYFOUR
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl/* ========================================================================= */
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl#define DOLIT4 c ^= *buf4++; \
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24]
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl#define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl/* ========================================================================= */
c9431fa1e59a88c2f0abf611f25b97af964449e5ahllocal unsigned long crc32_little(crc, buf, len)
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl unsigned long crc;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl const unsigned char FAR *buf;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl unsigned len;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl{
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl register u4 c;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl register const u4 FAR *buf4;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl c = (u4)crc;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl c = ~c;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl while (len && ((ptrdiff_t)buf & 3)) {
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8);
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl len--;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl }
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl buf4 = (const u4 FAR *)(const void FAR *)buf;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl while (len >= 32) {
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl DOLIT32;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl len -= 32;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl }
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl while (len >= 4) {
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl DOLIT4;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl len -= 4;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl }
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl buf = (const unsigned char FAR *)buf4;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl if (len) do {
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8);
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl } while (--len);
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl c = ~c;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl return (unsigned long)c;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl}
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl/* ========================================================================= */
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl#define DOBIG4 c ^= *++buf4; \
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24]
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl#define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl/* ========================================================================= */
c9431fa1e59a88c2f0abf611f25b97af964449e5ahllocal unsigned long crc32_big(crc, buf, len)
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl unsigned long crc;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl const unsigned char FAR *buf;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl unsigned len;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl{
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl register u4 c;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl register const u4 FAR *buf4;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl c = REV((u4)crc);
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl c = ~c;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl while (len && ((ptrdiff_t)buf & 3)) {
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl len--;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl }
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl buf4 = (const u4 FAR *)(const void FAR *)buf;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl buf4--;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl while (len >= 32) {
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl DOBIG32;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl len -= 32;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl }
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl while (len >= 4) {
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl DOBIG4;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl len -= 4;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl }
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl buf4++;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl buf = (const unsigned char FAR *)buf4;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl if (len) do {
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl } while (--len);
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl c = ~c;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl return (unsigned long)(REV(c));
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl}
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl#endif /* BYFOUR */
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl#define GF2_DIM 32 /* dimension of GF(2) vectors (length of CRC) */
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl/* ========================================================================= */
c9431fa1e59a88c2f0abf611f25b97af964449e5ahllocal unsigned long gf2_matrix_times(mat, vec)
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl unsigned long *mat;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl unsigned long vec;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl{
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl unsigned long sum;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl sum = 0;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl while (vec) {
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl if (vec & 1)
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl sum ^= *mat;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl vec >>= 1;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl mat++;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl }
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl return sum;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl}
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl/* ========================================================================= */
c9431fa1e59a88c2f0abf611f25b97af964449e5ahllocal void gf2_matrix_square(square, mat)
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl unsigned long *square;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl unsigned long *mat;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl{
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl int n;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl for (n = 0; n < GF2_DIM; n++)
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl square[n] = gf2_matrix_times(mat, mat[n]);
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl}
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl/* ========================================================================= */
c9431fa1e59a88c2f0abf611f25b97af964449e5ahluLong ZEXPORT crc32_combine(crc1, crc2, len2)
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl uLong crc1;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl uLong crc2;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl z_off_t len2;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl{
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl int n;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl unsigned long row;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl unsigned long even[GF2_DIM]; /* even-power-of-two zeros operator */
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl unsigned long odd[GF2_DIM]; /* odd-power-of-two zeros operator */
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl /* degenerate case */
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl if (len2 == 0)
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl return crc1;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl /* put operator for one zero bit in odd */
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl odd[0] = 0xedb88320UL; /* CRC-32 polynomial */
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl row = 1;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl for (n = 1; n < GF2_DIM; n++) {
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl odd[n] = row;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl row <<= 1;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl }
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl /* put operator for two zero bits in even */
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl gf2_matrix_square(even, odd);
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl /* put operator for four zero bits in odd */
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl gf2_matrix_square(odd, even);
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl /* apply len2 zeros to crc1 (first square will put the operator for one
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl zero byte, eight zero bits, in even) */
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl do {
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl /* apply zeros operator for this bit of len2 */
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl gf2_matrix_square(even, odd);
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl if (len2 & 1)
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl crc1 = gf2_matrix_times(even, crc1);
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl len2 >>= 1;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl /* if no more bits set, then done */
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl if (len2 == 0)
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl break;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl /* another iteration of the loop with odd and even swapped */
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl gf2_matrix_square(odd, even);
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl if (len2 & 1)
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl crc1 = gf2_matrix_times(odd, crc1);
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl len2 >>= 1;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl /* if no more bits set, then done */
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl } while (len2 != 0);
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl /* return combined crc */
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl crc1 ^= crc2;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl return crc1;
c9431fa1e59a88c2f0abf611f25b97af964449e5ahl}