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