1 /*
2  * Use SSE4.2 to calculate crc32c.
3  *
4  * Copyright 2015 Kubo Takehiro <kubo@jiubao.org>
5  *
6  * Redistribution and use in source and binary forms, with or without modification, are
7  * permitted provided that the following conditions are met:
8  *
9  *    1. Redistributions of source code must retain the above copyright notice, this list of
10  *       conditions and the following disclaimer.
11  *
12  *    2. Redistributions in binary form must reproduce the above copyright notice, this list
13  *       of conditions and the following disclaimer in the documentation and/or other materials
14  *       provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS OR IMPLIED
17  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
18  * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> OR
19  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
22  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
23  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
24  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  *
26  * The views and conclusions contained in the software and documentation are those of the
27  * authors and should not be interpreted as representing official policies, either expressed
28  * or implied, of the authors.
29  */
30 #include <stdlib.h>
31 #include "config.h"
32 #include "crc32.h"
33 #include <nmmintrin.h>
34 
35 uint32_t
calculate_crc32c_sse4_2(uint32_t crc32c,const unsigned char * buffer,unsigned int length)36 calculate_crc32c_sse4_2(uint32_t crc32c,
37     const unsigned char *buffer,
38     unsigned int length)
39 {
40 	size_t quotient;
41 
42 #if defined(__x86_64) || defined(__x86_64__) || defined(_M_X64)
43 	quotient = length / 8;
44 	while (quotient--) {
45 		crc32c = _mm_crc32_u64(crc32c, *(uint64_t*)buffer);
46 		buffer += 8;
47 	}
48 	if (length & 4) {
49 		crc32c = _mm_crc32_u32(crc32c, *(uint32_t*)buffer);
50 		buffer += 4;
51 	}
52 #else
53 	quotient = length / 4;
54 	while (quotient--) {
55 		crc32c = _mm_crc32_u32(crc32c, *(uint32_t*)buffer);
56 		buffer += 4;
57 	}
58 #endif
59 	if (length & 2) {
60 		crc32c = _mm_crc32_u16(crc32c, *(uint16_t*)buffer);
61 		buffer += 2;
62 	}
63 	if (length & 1) {
64 		crc32c = _mm_crc32_u8(crc32c, *(uint8_t*)buffer);
65 	}
66 	return crc32c;
67 }
68