-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathcrc32c.c
61 lines (55 loc) · 1.21 KB
/
crc32c.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#include "crc32c.h"
#ifdef __SSE4_2__
#include <x86intrin.h>
/* x86 version based using instrinsics */
uint32_t crc32c_hw(const char *src, size_t len) {
const unsigned char *s = (unsigned char *)src;
uint64_t hh = ~0;
#ifdef __x86_64__
while (len > 7) {
uint64_t v = *(uint64_t *)s;
hh = _mm_crc32_u64(hh, v);
s += 8;
len -= 8;
}
#endif /* __x86_64__ */
uint32_t h = (uint32_t)hh;
if (len > 3) {
uint32_t v = *(uint32_t *)s;
h = _mm_crc32_u32(h, v);
s += 4;
len -= 4;
}
if (len > 1) {
uint16_t v = *(uint16_t *)s;
h = _mm_crc32_u16(h, v);
s += 2;
len -= 2;
}
if (len > 0) {
uint8_t v = *(uint8_t *)s;
h = _mm_crc32_u8(h, v);
s += 1;
len -= 1;
}
return ~h;
}
#endif /* __SSE4_2__ */
/* CRC-32C (iSCSI) polynomial in reversed bit order. */
#define POLY 0x82f63b78
uint32_t crc32c_sw(const char *src, size_t len) {
const unsigned char *s = (unsigned char *)src;
uint32_t h = ~0;
while (len--) {
h ^= *s++;
for (int k = 0; k < 8; k++) h = h & 1 ? (h >> 1) ^ POLY : h >> 1;
}
return ~h;
}
uint32_t crc32c(const char *src, size_t len) {
#ifdef __SSE4_2__
return crc32c_hw(src, len);
#else
return crc32c_sw(src, len);
#endif
}