Home | History | Annotate | Line # | Download | only in libkern
crc32.c revision 1.2
      1  1.2     tls /*	$NetBSD: crc32.c,v 1.2 2009/03/25 18:41:06 tls Exp $	*/
      2  1.1  darran 
      3  1.1  darran /* crc32.c -- compute the CRC-32 of a data stream
      4  1.1  darran  *
      5  1.1  darran  * Adapted from zlib's crc code.
      6  1.1  darran  *
      7  1.1  darran  * Copyright (C) 1995-2005 Mark Adler
      8  1.1  darran  * For conditions of distribution and use, see copyright notice in zlib.h
      9  1.1  darran  *
     10  1.1  darran  * Thanks to Rodney Brown <rbrown64 (at) csc.com.au> for his contribution of faster
     11  1.1  darran  * CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing
     12  1.1  darran  * tables for updating the shift register in one step with three exclusive-ors
     13  1.1  darran  * instead of four steps with four exclusive-ors.  This results in about a
     14  1.1  darran  * factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3.
     15  1.1  darran  */
     16  1.1  darran 
     17  1.1  darran /* @(#) Id */
     18  1.1  darran 
     19  1.1  darran #include <sys/param.h>
     20  1.1  darran #include <machine/endian.h>
     21  1.1  darran 
     22  1.1  darran #define z_ptrdiff_t int32_t
     23  1.1  darran 
     24  1.1  darran typedef uint32_t u4;
     25  1.1  darran 
     26  1.1  darran /* Definitions for doing the crc four data bytes at a time. */
     27  1.1  darran #define REV(w) (((w)>>24)+(((w)>>8)&0xff00)+ \
     28  1.1  darran                (((w)&0xff00)<<8)+(((w)&0xff)<<24))
     29  1.1  darran 
     30  1.1  darran /* ========================================================================
     31  1.1  darran  * Tables of CRC-32s of all single-byte values, made by make_crc_table().
     32  1.1  darran  */
     33  1.2     tls #include <lib/libkern/libkern.h>
     34  1.1  darran #include "crc32.h"
     35  1.1  darran 
     36  1.1  darran #if BYTE_ORDER == LITTLE_ENDIAN
     37  1.1  darran /* ========================================================================= */
     38  1.1  darran #define DOLIT4 c ^= *buf4++; \
     39  1.1  darran         c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \
     40  1.1  darran             crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24]
     41  1.1  darran #define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4
     42  1.1  darran 
     43  1.1  darran /* ========================================================================= */
     44  1.2     tls uint32_t crc32(uint32_t crc, const uint8_t *buf, size_t len)
     45  1.1  darran {
     46  1.1  darran     register u4 c;
     47  1.1  darran     register const u4 *buf4;
     48  1.1  darran 
     49  1.1  darran     if (buf == NULL) return 0UL;
     50  1.1  darran 
     51  1.1  darran     c = (u4)crc;
     52  1.1  darran     c = ~c;
     53  1.1  darran     while (len && ((z_ptrdiff_t)buf & 3)) {
     54  1.1  darran         c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8);
     55  1.1  darran         len--;
     56  1.1  darran     }
     57  1.1  darran 
     58  1.1  darran     buf4 = (const u4 *)(const void *)buf;
     59  1.1  darran     while (len >= 32) {
     60  1.1  darran         DOLIT32;
     61  1.1  darran         len -= 32;
     62  1.1  darran     }
     63  1.1  darran     while (len >= 4) {
     64  1.1  darran         DOLIT4;
     65  1.1  darran         len -= 4;
     66  1.1  darran     }
     67  1.1  darran     buf = (const unsigned char *)buf4;
     68  1.1  darran 
     69  1.1  darran     if (len) do {
     70  1.1  darran         c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8);
     71  1.1  darran     } while (--len);
     72  1.1  darran     c = ~c;
     73  1.1  darran     return (uint32_t)c;
     74  1.1  darran }
     75  1.1  darran 
     76  1.1  darran #else /* BIG_ENDIAN */
     77  1.1  darran 
     78  1.1  darran /* ========================================================================= */
     79  1.1  darran #define DOBIG4 c ^= *++buf4; \
     80  1.1  darran         c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \
     81  1.1  darran             crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24]
     82  1.1  darran #define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4
     83  1.1  darran 
     84  1.1  darran /* ========================================================================= */
     85  1.1  darran uint32_t crc32(
     86  1.1  darran     uint32_t crc,
     87  1.1  darran     const unsigned char *buf,
     88  1.1  darran     unsigned len)
     89  1.1  darran {
     90  1.1  darran     register u4 c;
     91  1.1  darran     register const u4 *buf4;
     92  1.1  darran 
     93  1.1  darran     if (buf == NULL) return 0UL;
     94  1.1  darran 
     95  1.1  darran     c = REV((u4)crc);
     96  1.1  darran     c = ~c;
     97  1.1  darran     while (len && ((z_ptrdiff_t)buf & 3)) {
     98  1.1  darran         c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
     99  1.1  darran         len--;
    100  1.1  darran     }
    101  1.1  darran 
    102  1.1  darran     buf4 = (const u4 *)(const void *)buf;
    103  1.1  darran     buf4--;
    104  1.1  darran     while (len >= 32) {
    105  1.1  darran         DOBIG32;
    106  1.1  darran         len -= 32;
    107  1.1  darran     }
    108  1.1  darran     while (len >= 4) {
    109  1.1  darran         DOBIG4;
    110  1.1  darran         len -= 4;
    111  1.1  darran     }
    112  1.1  darran     buf4++;
    113  1.1  darran     buf = (const unsigned char *)buf4;
    114  1.1  darran 
    115  1.1  darran     if (len) do {
    116  1.1  darran         c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
    117  1.1  darran     } while (--len);
    118  1.1  darran     c = ~c;
    119  1.1  darran     return (uint32_t)(REV(c));
    120  1.1  darran }
    121  1.1  darran #endif
    122