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