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