49 #define POLY 0x82f63b78
60 for (n = 0; n < 256; n++) {
62 crc = crc & 1 ? (crc >> 1) ^
POLY : crc >> 1;
63 crc = crc & 1 ? (crc >> 1) ^
POLY : crc >> 1;
64 crc = crc & 1 ? (crc >> 1) ^
POLY : crc >> 1;
65 crc = crc & 1 ? (crc >> 1) ^
POLY : crc >> 1;
66 crc = crc & 1 ? (crc >> 1) ^
POLY : crc >> 1;
67 crc = crc & 1 ? (crc >> 1) ^
POLY : crc >> 1;
68 crc = crc & 1 ? (crc >> 1) ^
POLY : crc >> 1;
69 crc = crc & 1 ? (crc >> 1) ^
POLY : crc >> 1;
72 for (n = 0; n < 256; n++) {
74 for (k = 1; k < 8; k++) {
84 static uint32_t
crc32c_sw(uint32_t crci,
const unsigned char *buf,
size_t len)
86 const unsigned char *
next = buf;
90 crc = crci ^ 0xffffffff;
91 while (len && ((uintptr_t)next & 7) != 0) {
92 crc =
crc32c_table[0][(crc ^ *next++) & 0xff] ^ (crc >> 8);
109 crc =
crc32c_table[0][(crc ^ *next++) & 0xff] ^ (crc >> 8);
112 return (uint32_t)crc ^ 0xffffffff;
115 #if defined(__x86_64__)
120 static inline uint32_t gf2_matrix_times(uint32_t *mat, uint32_t vec)
136 static inline void gf2_matrix_square(uint32_t *
square, uint32_t *mat)
140 for (n = 0; n < 32; n++)
141 square[n] = gf2_matrix_times(mat, mat[n]);
149 static void crc32c_zeros_op(uint32_t *even,
size_t len)
158 for (n = 1; n < 32; n++) {
164 gf2_matrix_square(even, odd);
167 gf2_matrix_square(odd, even);
173 gf2_matrix_square(even, odd);
177 gf2_matrix_square(odd, even);
182 for (n = 0; n < 32; n++)
188 static void crc32c_zeros(uint32_t zeros[][256],
size_t len)
193 crc32c_zeros_op(op, len);
194 for (n = 0; n < 256; n++) {
195 zeros[0][
n] = gf2_matrix_times(op, n);
196 zeros[1][
n] = gf2_matrix_times(op, n << 8);
197 zeros[2][
n] = gf2_matrix_times(op, n << 16);
198 zeros[3][
n] = gf2_matrix_times(op, n << 24);
203 static inline uint32_t crc32c_shift(uint32_t zeros[][256], uint32_t crc)
205 return zeros[0][crc & 0xff] ^ zeros[1][(crc >> 8) & 0xff] ^
206 zeros[2][(crc >> 16) & 0xff] ^ zeros[3][crc >> 24];
213 #define LONGx1 "8192"
214 #define LONGx2 "16384"
216 #define SHORTx1 "256"
217 #define SHORTx2 "512"
220 static pthread_once_t crc32c_once_hw = PTHREAD_ONCE_INIT;
221 static uint32_t crc32c_long[4][256];
222 static uint32_t crc32c_short[4][256];
225 static void crc32c_init_hw(
void)
227 crc32c_zeros(crc32c_long, LONG);
228 crc32c_zeros(crc32c_short, SHORT);
232 static uint32_t crc32c_hw(uint32_t crc,
const unsigned char *buf,
size_t len)
234 const unsigned char *
next = buf;
235 const unsigned char *
end;
239 pthread_once(&crc32c_once_hw, crc32c_init_hw);
242 crc0 = crc ^ 0xffffffff;
246 while (len && ((uintptr_t)next & 7) != 0) {
247 __asm__(
"crc32b\t" "(%1), %0"
249 :
"r"(next),
"0"(crc0));
258 while (len >= LONG*3) {
263 __asm__(
"crc32q\t" "(%3), %0\n\t"
264 "crc32q\t" LONGx1
"(%3), %1\n\t"
265 "crc32q\t" LONGx2
"(%3), %2"
266 :
"=r"(crc0),
"=r"(crc1),
"=r"(crc2)
267 :
"r"(next),
"0"(crc0),
"1"(crc1),
"2"(crc2));
269 }
while (next < end);
270 crc0 = crc32c_shift(crc32c_long, crc0) ^ crc1;
271 crc0 = crc32c_shift(crc32c_long, crc0) ^ crc2;
278 while (len >= SHORT*3) {
283 __asm__(
"crc32q\t" "(%3), %0\n\t"
284 "crc32q\t" SHORTx1
"(%3), %1\n\t"
285 "crc32q\t" SHORTx2
"(%3), %2"
286 :
"=r"(crc0),
"=r"(crc1),
"=r"(crc2)
287 :
"r"(next),
"0"(crc0),
"1"(crc1),
"2"(crc2));
289 }
while (next < end);
290 crc0 = crc32c_shift(crc32c_short, crc0) ^ crc1;
291 crc0 = crc32c_shift(crc32c_short, crc0) ^ crc2;
298 end = next + (len - (len & 7));
300 __asm__(
"crc32q\t" "(%1), %0"
302 :
"r"(next),
"0"(crc0));
309 __asm__(
"crc32b\t" "(%1), %0"
311 :
"r"(next),
"0"(crc0));
317 return (uint32_t)crc0 ^ 0xffffffff;
325 #define SSE42(have) \
333 (have) = (ecx >> 20) & 1; \
336 #endif //defined(__x86_64__)
340 uint32_t
crc32c(uint32_t crc,
const unsigned char *buf,
size_t len)
342 #if defined(__x86_64__)
346 return sse42 ? crc32c_hw(crc, buf, len) :
crc32c_sw(crc, buf, len);
357 #if defined(__x86_64__)
static pthread_once_t crc32c_once_sw
static uint32_t crc32c_table[8][256]
uint32_t crc32c(uint32_t crc, const unsigned char *buf, size_t len)
unsigned long long uint64_t
static void crc32c_init_sw(void)
double square(const double a)
static uint32_t crc32c_sw(uint32_t crci, const unsigned char *buf, size_t len)