1 /* crc32.c -- compute the CRC-32 of a data stream
2  * Copyright (C) 1995-2006, 2010, 2011, 2012, 2016, 2018 Mark Adler
3  * For conditions of distribution and use, see copyright notice in zlib.h
4  *
5  * Thanks to Rodney Brown <rbrown64@csc.com.au> for his contribution of faster
6  * CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing
7  * tables for updating the shift register in one step with three exclusive-ors
8  * instead of four steps with four exclusive-ors.  This results in about a
9  * factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3.
10  */
11 
12 #include "zbuild.h"
13 #include "zendian.h"
14 #include <inttypes.h>
15 #include "deflate.h"
16 #include "functable.h"
17 #include "crc32_tbl.h"
18 
19 /* =========================================================================
20  * This function can be used by asm versions of crc32()
21  */
PREFIX(get_crc_table)22 const uint32_t * Z_EXPORT PREFIX(get_crc_table)(void) {
23     return (const uint32_t *)crc_table;
24 }
25 
26 #ifdef ZLIB_COMPAT
PREFIX(crc32_z)27 unsigned long Z_EXPORT PREFIX(crc32_z)(unsigned long crc, const unsigned char *buf, size_t len) {
28     if (buf == NULL) return 0;
29 
30     return (unsigned long)functable.crc32((uint32_t)crc, buf, len);
31 }
32 #else
PREFIX(crc32_z)33 uint32_t Z_EXPORT PREFIX(crc32_z)(uint32_t crc, const unsigned char *buf, size_t len) {
34     if (buf == NULL) return 0;
35 
36     return functable.crc32(crc, buf, len);
37 }
38 #endif
39 /* ========================================================================= */
40 #define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8)
41 #define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1
42 #define DO4 DO1; DO1; DO1; DO1
43 
44 /* ========================================================================= */
crc32_generic(uint32_t crc,const unsigned char * buf,uint64_t len)45 Z_INTERNAL uint32_t crc32_generic(uint32_t crc, const unsigned char *buf, uint64_t len) {
46     crc = crc ^ 0xffffffff;
47 
48 #ifdef UNROLL_MORE
49     while (len >= 8) {
50         DO8;
51         len -= 8;
52     }
53 #else
54     while (len >= 4) {
55         DO4;
56         len -= 4;
57     }
58 #endif
59 
60     if (len) do {
61         DO1;
62     } while (--len);
63     return crc ^ 0xffffffff;
64 }
65 
66 #ifdef ZLIB_COMPAT
PREFIX(crc32)67 unsigned long Z_EXPORT PREFIX(crc32)(unsigned long crc, const unsigned char *buf, unsigned int len) {
68     return (unsigned long)PREFIX(crc32_z)((uint32_t)crc, buf, len);
69 }
70 #else
PREFIX(crc32)71 uint32_t Z_EXPORT PREFIX(crc32)(uint32_t crc, const unsigned char *buf, uint32_t len) {
72     return PREFIX(crc32_z)(crc, buf, len);
73 }
74 #endif
75 
76 /*
77    This BYFOUR code accesses the passed unsigned char * buffer with a 32-bit
78    integer pointer type. This violates the strict aliasing rule, where a
79    compiler can assume, for optimization purposes, that two pointers to
80    fundamentally different types won't ever point to the same memory. This can
81    manifest as a problem only if one of the pointers is written to. This code
82    only reads from those pointers. So long as this code remains isolated in
83    this compilation unit, there won't be a problem. For this reason, this code
84    should not be copied and pasted into a compilation unit in which other code
85    writes to the buffer that is passed to these routines.
86  */
87 
88 /* ========================================================================= */
89 #if BYTE_ORDER == LITTLE_ENDIAN
90 #define DOLIT4 c ^= *buf4++; \
91         c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \
92             crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24]
93 #define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4
94 
95 /* ========================================================================= */
crc32_little(uint32_t crc,const unsigned char * buf,uint64_t len)96 Z_INTERNAL uint32_t crc32_little(uint32_t crc, const unsigned char *buf, uint64_t len) {
97     Z_REGISTER uint32_t c;
98     Z_REGISTER const uint32_t *buf4;
99 
100     c = crc;
101     c = ~c;
102     while (len && ((ptrdiff_t)buf & 3)) {
103         c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8);
104         len--;
105     }
106 
107     buf4 = (const uint32_t *)(const void *)buf;
108 
109 #ifdef UNROLL_MORE
110     while (len >= 32) {
111         DOLIT32;
112         len -= 32;
113     }
114 #endif
115 
116     while (len >= 4) {
117         DOLIT4;
118         len -= 4;
119     }
120     buf = (const unsigned char *)buf4;
121 
122     if (len) do {
123         c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8);
124     } while (--len);
125     c = ~c;
126     return c;
127 }
128 #endif /* BYTE_ORDER == LITTLE_ENDIAN */
129 
130 /* ========================================================================= */
131 #if BYTE_ORDER == BIG_ENDIAN
132 #define DOBIG4 c ^= *buf4++; \
133         c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \
134             crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24]
135 #define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4
136 
137 /* ========================================================================= */
crc32_big(uint32_t crc,const unsigned char * buf,uint64_t len)138 Z_INTERNAL uint32_t crc32_big(uint32_t crc, const unsigned char *buf, uint64_t len) {
139     Z_REGISTER uint32_t c;
140     Z_REGISTER const uint32_t *buf4;
141 
142     c = ZSWAP32(crc);
143     c = ~c;
144     while (len && ((ptrdiff_t)buf & 3)) {
145         c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
146         len--;
147     }
148 
149     buf4 = (const uint32_t *)(const void *)buf;
150 
151 #ifdef UNROLL_MORE
152     while (len >= 32) {
153         DOBIG32;
154         len -= 32;
155     }
156 #endif
157 
158     while (len >= 4) {
159         DOBIG4;
160         len -= 4;
161     }
162     buf = (const unsigned char *)buf4;
163 
164     if (len) do {
165         c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
166     } while (--len);
167     c = ~c;
168     return ZSWAP32(c);
169 }
170 #endif /* BYTE_ORDER == BIG_ENDIAN */
171 
172 #ifdef X86_PCLMULQDQ_CRC
173 #include "arch/x86/x86.h"
174 #include "arch/x86/crc_folding.h"
175 
crc_finalize(deflate_state * const s)176 Z_INTERNAL void crc_finalize(deflate_state *const s) {
177     if (x86_cpu_has_pclmulqdq)
178         s->strm->adler = crc_fold_512to32(s);
179 }
180 #endif
181 
crc_reset(deflate_state * const s)182 Z_INTERNAL void crc_reset(deflate_state *const s) {
183 #ifdef X86_PCLMULQDQ_CRC
184     x86_check_features();
185     if (x86_cpu_has_pclmulqdq) {
186         crc_fold_init(s);
187         return;
188     }
189 #endif
190     s->strm->adler = PREFIX(crc32)(0L, NULL, 0);
191 }
192 
copy_with_crc(PREFIX3 (stream)* strm,unsigned char * dst,unsigned long size)193 Z_INTERNAL void copy_with_crc(PREFIX3(stream) *strm, unsigned char *dst, unsigned long size) {
194 #ifdef X86_PCLMULQDQ_CRC
195     if (x86_cpu_has_pclmulqdq) {
196         crc_fold_copy(strm->state, dst, strm->next_in, size);
197         return;
198     }
199 #endif
200     memcpy(dst, strm->next_in, size);
201     strm->adler = PREFIX(crc32)(strm->adler, dst, size);
202 }
203