15#if defined(__SSE__) && defined(__x86_64__)
16#define HAVE_AMD64_CRC32C 1
19#ifdef __ARM_FEATURE_CRC32
21#define HAVE_ARM64_CRC32C 1
66#define POLY 0x82f63b78
77 for (
n = 0;
n < 256;
n++) {
79 crc = crc & 1 ? (crc >> 1) ^
POLY : crc >> 1;
80 crc = crc & 1 ? (crc >> 1) ^
POLY : crc >> 1;
81 crc = crc & 1 ? (crc >> 1) ^
POLY : crc >> 1;
82 crc = crc & 1 ? (crc >> 1) ^
POLY : crc >> 1;
83 crc = crc & 1 ? (crc >> 1) ^
POLY : crc >> 1;
84 crc = crc & 1 ? (crc >> 1) ^
POLY : crc >> 1;
85 crc = crc & 1 ? (crc >> 1) ^
POLY : crc >> 1;
86 crc = crc & 1 ? (crc >> 1) ^
POLY : crc >> 1;
89 for (
n = 0;
n < 256;
n++) {
91 for (
k = 1;
k < 8;
k++) {
101uint32_t
crc32c_sw(uint32_t crci,
const void *buf,
size_t len)
103 const unsigned char *next = (
const unsigned char*)buf;
109 crc = crci ^ 0xffffffff;
110 while (len && ((uintptr_t)next & 7) != 0) {
111 crc =
crc32c_table[0][(crc ^ *next++) & 0xff] ^ (crc >> 8);
115 crc ^= *(uint64_t *)next;
128 crc =
crc32c_table[0][(crc ^ *next++) & 0xff] ^ (crc >> 8);
131 return (uint32_t)crc ^ 0xffffffff;
158 for (
n = 0;
n < 32;
n++)
162#ifdef HAVE_AMD64_CRC32C
169static void crc32c_zeros_op(uint32_t *even,
size_t len)
178 for (
n = 1;
n < 32;
n++) {
202 for (
n = 0;
n < 32;
n++)
208static void crc32c_zeros(uint32_t zeros[][256],
size_t len)
213 crc32c_zeros_op(op, len);
214 for (
n = 0;
n < 256;
n++) {
225static inline uint32_t
crc32c_shift(uint32_t zeros[][256], uint32_t crc)
227 return zeros[0][crc & 0xff] ^ zeros[1][(crc >> 8) & 0xff] ^
228 zeros[2][(crc >> 16) & 0xff] ^ zeros[3][crc >> 24];
236#define LONGx2 "16384"
241#ifdef HAVE_AMD64_CRC32C
244static pthread_once_t crc32c_once_hw_amd64 = PTHREAD_ONCE_INIT;
245static uint32_t crc32c_long[4][256];
246static uint32_t crc32c_short[4][256];
249static void crc32c_init_hw_amd64(
void)
251 crc32c_zeros(crc32c_long,
LONG);
252 crc32c_zeros(crc32c_short,
SHORT);
256uint32_t crc32c_hw_amd64(uint32_t crc,
const void *buf,
size_t len)
258 const unsigned char *next = (
const unsigned char*)buf;
259 const unsigned char *
end;
260 uint64_t crc0, crc1, crc2;
265 pthread_once(&crc32c_once_hw_amd64, crc32c_init_hw_amd64);
268 crc0 = crc ^ 0xffffffff;
272 while (len && ((uintptr_t)next & 7) != 0) {
273 __asm__(
"crc32b\t" "(%1), %0"
275 :
"r"(next),
"0"(crc0));
284 while (len >=
LONG*3) {
289 __asm__(
"crc32q\t" "(%3), %0\n\t"
290 "crc32q\t" LONGx1 "(%3), %1\n\t"
291 "crc32q\t" LONGx2 "(%3), %2"
292 :
"=r"(crc0),
"=r"(crc1),
"=r"(crc2)
293 :
"r"(next),
"0"(crc0),
"1"(crc1),
"2"(crc2));
295 }
while (next <
end);
304 while (len >=
SHORT*3) {
309 __asm__(
"crc32q\t" "(%3), %0\n\t"
310 "crc32q\t" SHORTx1 "(%3), %1\n\t"
312 :
"=r"(crc0),
"=r"(crc1),
"=r"(crc2)
313 :
"r"(next),
"0"(crc0),
"1"(crc1),
"2"(crc2));
315 }
while (next <
end);
324 end = next + (len - (len & 7));
326 __asm__(
"crc32q\t" "(%1), %0"
328 :
"r"(next),
"0"(crc0));
335 __asm__(
"crc32b\t" "(%1), %0"
337 :
"r"(next),
"0"(crc0));
343 return (uint32_t)crc0 ^ 0xffffffff;
359 (have) = (ecx >> 20) & 1; \
364#ifdef HAVE_ARM64_CRC32C
366uint32_t crc32c_hw_arm64(uint32_t crc,
const void *buf,
size_t len)
369 uint8_t *pd = (uint8_t *)buf;
374 while (((uintptr_t)pd & 7) && len > 0) {
375 crc = __crc32cb(crc, *(uint8_t *)pd);
381 crc = __crc32cd(crc, *(uint64_t *)pd);
387 crc = __crc32cb(crc, *(uint8_t *)pd);
399uint32_t
crc32c(uint32_t crc,
const void *buf,
size_t len)
401#if defined(HAVE_AMD64_CRC32C)
404 return sse42 ? crc32c_hw_amd64(crc, buf, len) :
crc32c_sw(crc, buf, len);
405#elif defined(HAVE_ARM64_CRC32C)
406 return crc32c_hw_arm64(crc, buf, len);
408#warning Hardware accelerated CRC32C is not available.
413uint32_t
crc32c_hw(uint32_t crc,
const void *buf,
size_t len)
415#if defined(HAVE_AMD64_CRC32C)
416 return crc32c_hw_amd64(crc, buf, len);
417#elif defined(HAVE_ARM64_CRC32C)
418 return crc32c_hw_arm64(crc, buf, len);
420#warning Hardware accelerated CRC32C is not available.
427#define SIZE (262144*3)
430int main(
int argc,
char **argv)
439 buf = (
char*)malloc(
SIZE);
441 fputs(
"out of memory", stderr);
444 while ((got =
read(0, buf,
SIZE)) > 0) {
447 n = (size_t)got - off;
450 crc = argc > 1 ?
crc32c_sw(crc, buf + off,
n) :
453 }
while (off < (
size_t)got);
457 fputs(
"read error\n", stderr);
460 printf(
"%08x\n", crc);
static uint32_t gf2_matrix_times(uint32_t *mat, uint32_t vec)
uint32_t crc32c(uint32_t crc, const void *buf, size_t len)
static uint32_t crc32c_table[8][256]
static pthread_once_t crc32c_once_sw
static uint32_t crc32c_shift(uint32_t zeros[][256], uint32_t crc)
static void crc32c_init_sw(void)
static void gf2_matrix_square(uint32_t *square, uint32_t *mat)
uint32_t crc32c_hw(uint32_t crc, const void *buf, size_t len)
uint32_t crc32c_sw(uint32_t crci, const void *buf, size_t len)