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