-
Notifications
You must be signed in to change notification settings - Fork 29
/
crc32.cpp
68 lines (57 loc) · 1.12 KB
/
crc32.cpp
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
62
63
64
65
66
67
68
#include <stdint.h>
#include <smmintrin.h>
#include <cpuid.h>
bool initialized(false);
uint32_t slowcrc_table[1<<8];
void slowcrc_init() {
uint32_t i, j, a;
for (i=0;i<(1<<8);i++) {
a=((uint32_t)i)<<24;
for (j=0;j<8;j++) {
if (a&0x80000000)
a=(a<<1)^0x11EDC6F41;
else
a=(a<<1);
}
slowcrc_table[i]=a;
}
initialized=true;
}
uint32_t slowcrc(char *str, uint32_t len) {
uint32_t lcrc=~0;
char *p, *e;
e=str+len;
for (p=str;p < e;++p)
lcrc=(lcrc>>8)^slowcrc_table[(lcrc^(*p))&0xff];
return ~lcrc;
}
uint32_t fastcrc(const char *str, uint32_t len) {
uint64_t q=len/sizeof(uint64_t),
r=len%sizeof(uint64_t),
*p=(uint64_t*)str,
crc64=0;
uint32_t crc=0;
while (q--) {
crc64 = _mm_crc32_u64(crc64,*p);
p++;
}
str=(char*)p;
crc=crc64;
while (r--) {
crc = _mm_crc32_u8(crc,*str);
str++;
}
return crc;
}
uint32_t crc32(char *str, uint32_t len) {
uint32_t eax, ebx, ecx, edx;
__get_cpuid(1, &eax, &ebx, &ecx, &edx);
if (ecx & bit_SSE4_2){
return fastcrc(str,len);
}else{
if (!initialized){
slowcrc_init();
}
return slowcrc(str,len);
}
}