├── README.md
├── crc32c-benchmarks.png
└── crc32c
├── LICENSE
├── Makefile
├── base
└── assert.h
├── crc32adler.cc
├── crc32c.cc
├── crc32c.kdev4
├── crc32c_test.cc
├── crc32cbench.cc
├── crc32ctables.cc
├── crc32intelasm.cc
├── crc32intelc.cc
├── crc32inteltable.cc
├── crc_iscsi_v_pcl.asm
├── logging
├── crc32c.h
├── crc32ctables.h
├── crc32intelc.h
└── cycletimer.h
├── stupidunit.cc
└── stupidunit
└── stupidunit.h
/README.md:
--------------------------------------------------------------------------------
1 | # Highly optimized CRC32C lib and benchmark
2 |
3 | This project implements various crc32c algorithmes and provides a benchmark routine for them. The main goal is to take the fastest routine and make it available on the Intel Edison platform. It would also be interesting to port to arm (Raspberry Pie) and possibly arm MCU's, but that hasn't been done yet.
4 |
5 | As it appears that the fastest algorithm available uses the CRC instruction available on Intel SSE 4.2 processors and where efficient uses 3 ```crc32q``` instructions 3 seperate parts of the buffer which a single core can execute in parallel. This compensates for the latency of a single crc32q instruction. Recombining the 3 CRC-32C bytes is done using the ```pclmulqdq``` instruction, which has overhead of its own, and makes this code path only efficient for buffer sizes above 216 bytes. The algorithem has been taken from Intels ```crc_iscsi_v_pcl.asm``` assembly code (which is available in a modified form in the linux kernel) and using a C wrapper (```crcintelasm.cc```) included into this project.
6 |
7 | To be able to run this code on 32 bit platforms first it has been ported to C (crc32intelc) where possible, a small amount of inline assembly is required. Certain parts of the code depend on the bitness, crc32q is not available on 32 bits and neither is movq, these are put in macro's (crc32intel.h) with alternative code for 32 bit platforms.
8 |
9 | Being written in C it is of course easier to maintain and hopfully some bright minds will come up with ideas to optimize the code further.
10 |
11 | ## Acknowledgements
12 |
13 | Much of the code is taken from the benchmarking code retrieved from
14 | http://www.evanjones.ca/crc32c.html.
15 |
16 | The already highly optimized code from Mark Adler (madler@alumni.caltech.edu) is taken from
17 | http://stackoverflow.com/questions/17645167/implementing-sse-4-2s-crc32c-in-software/17646775
18 |
19 | ```crc_iscsi_v_pcl.asm``` was dowloaded from Intel's web site, and is described in the white paper "Fast CRC
20 | Computation for iSCSI Polynomial Using CRC32 Instruction", Vinodh Gopal, Jim Guilford, Erdinc Ozturk,
21 | Gil Wolrich, Wajdi Feghali, Martin Dixon (IA Architects, Intel Corporation), Deniz Karakoyunlu (PhD Worcester, Polytechnic Institute), 2011.
22 |
23 | ## Building
24 |
25 | To build for your native platform just type:
26 | ```sh
27 | make all
28 | ```
29 |
30 | This will build the code with maximum optimizations on (which has a large effect on performance, a factor 3x with Adler, Hardware32, Hardware64, IntelC, SlicingBy8, 2.6x for SlicingBy4 and 1.7 for Sarwate) and no debug symbols.
31 |
32 | To force 32 bits code on a 64 bit platform type:
33 | ```sh
34 | CPU_TYPE=x32 make all
35 | ```
36 |
37 | To force 64 bits code on a 32 bit platform type:
38 | ```sh
39 | CPU_TYPE=amd64 make all
40 | ```
41 |
42 | To enable debug info and disable optimizations type:
43 | ```sh
44 | DEBUG=TRUE make all
45 | ```
46 |
47 | ## Tests
48 |
49 | `./crc32c_test` performs a series of tests on each algorithm to make sure they have the same results.
50 |
51 | ## Benchmarks
52 |
53 | Benchmarks can be run with the built-in benchmark program as follows:
54 |
55 | ```sh
56 | ./crc32cbench
57 | ```
58 |
59 | The following graph shows the results for a buffer size of 4096 bytes.
60 | 
61 |
62 | On i7 with Adler and IntelC using 64bits gives a factor 2x improvement as expected. On 64 bits, using SlicingBy8 (the best software based method) is 5.1x better than Sarwate. Using Hardware64 is 4.2x better that SlicingBy8. IntelC is 2.7x better than Hardware64.
63 |
64 | On 32-bit Edison IntelC is 8.8x better than SlicingBy8.
65 |
66 | On 64-bit Edison and NUC E3815 all optimized methods (Hardware64, Adler, Intel) are regressing and slower than Hardware64. The fastest 64-bit method on Edison (Hardware64) is slower than the fastest on 32-bits (IntelC).
67 |
68 | ## License
69 |
70 | This repository is licensed under the
71 | [BSD 2-clause License](http://opensource.org/licenses/BSD-2-Clause). See the
72 | LICENSE file.
73 |
--------------------------------------------------------------------------------
/crc32c-benchmarks.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/htot/crc32c/022db995990418e1b581b6bf5f843bb775348e34/crc32c-benchmarks.png
--------------------------------------------------------------------------------
/crc32c/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2008,2009,2010 Massachusetts Institute of Technology.
2 | All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions are
6 | met:
7 |
8 | * Redistributions of source code must retain the above copyright
9 | notice, this list of conditions and the following disclaimer.
10 | * Redistributions in binary form must reproduce the above copyright
11 | notice, this list of conditions and the following disclaimer in the
12 | documentation and/or other materials provided with the distribution.
13 | * Neither the name of the Massachusetts Institute of Technology nor
14 | the names of its contributors may be used to endorse or promote
15 | products derived from this software without specific prior written
16 | permission.
17 |
18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 |
30 | Code retrieved from:
31 | - Evan Jones, 16-03-2016, http://www.evanjones.ca/crc32c.html
32 | - Version 1.1 1 Aug 2013 Mark Adler
33 |
34 |
35 | Other portions are under the same license from Intel:
36 | http://sourceforge.net/projects/slicing-by-8/
37 | /*++
38 | *
39 | * Copyright (c) 2004-2006 Intel Corporation - All Rights Reserved
40 | *
41 | * This software program is licensed subject to the BSD License,
42 | * available at http://www.opensource.org/licenses/bsd-license.html
43 | *
44 | * Abstract: The main routine
45 | *
46 | --*/
47 |
--------------------------------------------------------------------------------
/crc32c/Makefile:
--------------------------------------------------------------------------------
1 | ifdef CPU_TYPE
2 | ifeq ($(CPU_TYPE),x32)
3 | LBITS := 32
4 | BITS=-m32
5 | endif
6 | ifeq ($(CPU_TYPE),amd64)
7 | LBITS := 64
8 | BITS=-m64
9 | endif
10 | else
11 | LBITS := $(shell getconf LONG_BIT)
12 | endif
13 |
14 | OBJECTS = crc32ctables.o crc32c.o stupidunit.o crc32intelc.o crc32inteltable.o crc32adler.o
15 |
16 | ifeq ($(LBITS),64)
17 | OBJECTS += crc32intelasm.o crc_iscsi_v_pcl.o
18 | else
19 | # do 32 bit stuff here
20 | endif
21 |
22 | ifdef DEBUG
23 | OPT_FLAGS= -g -O0
24 | else
25 | OPT_FLAGS=-O3 -DNDEBUG -flto
26 | endif
27 |
28 | WARNING_FLAGS=-Wall -Wextra -Wno-sign-compare
29 | CXXFLAGS+=-msse4.2 -mpclmul $(BITS) $(WARNING_FLAGS) $(OPT_FLAGS)
30 | CFLAGS+=-msse4.2 -mpclmul $(BITS) $(WARNING_FLAGS) $(OPT_FLAGS)
31 |
32 | BINARIES=crc32c_test crc32cbench
33 | all: $(BINARIES)
34 |
35 | crc32c_test: crc32c_test.o $(OBJECTS)
36 | $(CXX) -o $@ $^ $(CXXFLAGS)
37 |
38 | crc32cbench: crc32cbench.o $(OBJECTS)
39 | $(CXX) -o $@ $^ $(CXXFLAGS)
40 |
41 | clean:
42 | $(RM) $(BINARIES) *.o
43 |
44 | %.o: %.c
45 | $(CC) $(CFLAGS) -o $@ -c $<
46 |
47 | %.o: %.cc
48 | $(CXX) $(CXXFLAGS) -o $@ -c $<
49 |
50 | crc_iscsi_v_pcl.o: crc_iscsi_v_pcl.asm
51 | yasm -f x64 -f elf64 -X gnu -g dwarf2 -D LINUX -o crc_iscsi_v_pcl.o crc_iscsi_v_pcl.asm
52 |
--------------------------------------------------------------------------------
/crc32c/base/assert.h:
--------------------------------------------------------------------------------
1 | // Copyright 2008,2009,2010 Massachusetts Institute of Technology.
2 | // All rights reserved. Use of this source code is governed by a
3 | // BSD-style license that can be found in the LICENSE file.
4 |
5 | #ifndef ASSERT_H__
6 | #define ASSERT_H__
7 |
8 | #include
9 | #include
10 | #include
11 |
12 | // Wraps the standard assert macro to avoids "unused variable" warnings when compiled away.
13 | // Inspired by: http://cnicholson.net/2009/02/stupid-c-tricks-adventures-in-assert/
14 | // This is not the "default" because it does not conform to the requirements of the C standard,
15 | // which requires that the NDEBUG version be ((void) 0).
16 | #ifdef NDEBUG
17 | #define ASSERT(x) do { (void)sizeof(x); } while(0)
18 | #else
19 | #define ASSERT(x) assert(x)
20 | #endif
21 |
22 |
23 | // CHECK is always enabled. May only work with gcc because I stole this from assert.h
24 | // TODO: Add our own .cc implementation to avoid duplicating this all over?
25 | // TODO: Use a namespaced function to avoid namespace/class member conflicts?
26 | // TODO: Add unit tests.
27 | #define CHECK(x) do { \
28 | if (!(x)) { \
29 | ::fprintf(stderr, "CHECK failed: " #x " at %s:%d in function %s\n", \
30 | __FILE__, __LINE__, __PRETTY_FUNCTION__); \
31 | ::abort(); \
32 | } \
33 | } while (0)
34 |
35 | #define CHECK_M(x, message, args...) do { \
36 | if (!(x)) { \
37 | ::fprintf(stderr, "CHECK failed: " #x " at %s:%d in function %s\n" message "\n", \
38 | __FILE__, __LINE__, __PRETTY_FUNCTION__, ##args); \
39 | ::abort(); \
40 | } \
41 | } while (0)
42 |
43 |
44 | #endif
45 |
--------------------------------------------------------------------------------
/crc32c/crc32adler.cc:
--------------------------------------------------------------------------------
1 | /* crc32c.c -- compute CRC-32C using the Intel crc32 instruction
2 | * Copyright (C) 2013 Mark Adler
3 | * Version 1.1 1 Aug 2013 Mark Adler
4 | */
5 |
6 | /*
7 | This software is provided 'as-is', without any express or implied
8 | warranty. In no event will the author be held liable for any damages
9 | arising from the use of this software.
10 |
11 | Permission is granted to anyone to use this software for any purpose,
12 | including commercial applications, and to alter it and redistribute it
13 | freely, subject to the following restrictions:
14 |
15 | 1. The origin of this software must not be misrepresented; you must not
16 | claim that you wrote the original software. If you use this software
17 | in a product, an acknowledgment in the product documentation would be
18 | appreciated but is not required.
19 | 2. Altered source versions must be plainly marked as such, and must not be
20 | misrepresented as being the original software.
21 | 3. This notice may not be removed or altered from any source distribution.
22 |
23 | Mark Adler
24 | madler@alumni.caltech.edu
25 | */
26 |
27 | /* Use hardware CRC instruction on Intel SSE 4.2 processors. This computes a
28 | CRC-32C, *not* the CRC-32 used by Ethernet and zip, gzip, etc. A software
29 | version is provided as a fall-back, as well as for speed comparisons. */
30 |
31 | /* Version history:
32 | 1.0 10 Feb 2013 First version
33 | 1.1 1 Aug 2013 Correct comments on why three crc instructions in parallel
34 | */
35 |
36 | /* Altered version
37 | * This version modified to fit into the benchmarking code retrieved from
38 | * http://www.evanjones.ca/crc32c.html
39 | * 1.2 20 Mar 2016 Ferry Toth - Fit into benchmarking
40 | * 1.3 07 May 2016 Ferry Toth - Applied some speed ups by putting more CRC32 in the short and long loop
41 | * - Moved crc32q into macro's and put alternative code there for 32bit operation
42 | */
43 |
44 |
45 | #include "logging/crc32c.h"
46 | #include
47 | #include
48 | #include
49 | #include
50 |
51 | /* CRC-32C (iSCSI) polynomial in reversed bit order. */
52 | #define POLY 0x82f63b78
53 |
54 | namespace logging
55 | {
56 | /* Multiply a matrix times a vector over the Galois field of two elements,
57 | GF(2). Each element is a bit in an unsigned integer. mat must have at
58 | least as many entries as the power of two for most significant one bit in
59 | vec. */
60 | static inline uint32_t gf2_matrix_times ( uint32_t *mat, uint32_t vec )
61 | {
62 | uint32_t sum;
63 |
64 | sum = 0;
65 | while ( vec ) {
66 | if ( vec & 1 )
67 | sum ^= *mat;
68 | vec >>= 1;
69 | mat++;
70 | }
71 | return sum;
72 | }
73 |
74 | /* Multiply a matrix by itself over GF(2). Both mat and square must have 32
75 | rows. */
76 | static inline void gf2_matrix_square ( uint32_t *square, uint32_t *mat )
77 | {
78 | int n;
79 |
80 | for ( n = 0; n < 32; n++ )
81 | square[n] = gf2_matrix_times ( mat, mat[n] );
82 | }
83 |
84 | /* Construct an operator to apply len zeros to a crc. len must be a power of
85 | two. If len is not a power of two, then the result is the same as for the
86 | largest power of two less than len. The result for len == 0 is the same as
87 | for len == 1. A version of this routine could be easily written for any
88 | len, but that is not needed for this application. */
89 | static void crc32c_zeros_op ( uint32_t *even, size_t len )
90 | {
91 | int n;
92 | uint32_t row;
93 | uint32_t odd[32]; /* odd-power-of-two zeros operator */
94 |
95 | /* put operator for one zero bit in odd */
96 | odd[0] = POLY; /* CRC-32C polynomial */
97 | row = 1;
98 | for ( n = 1; n < 32; n++ ) {
99 | odd[n] = row;
100 | row <<= 1;
101 | }
102 |
103 | /* put operator for two zero bits in even */
104 | gf2_matrix_square ( even, odd );
105 |
106 | /* put operator for four zero bits in odd */
107 | gf2_matrix_square ( odd, even );
108 |
109 | /* first square will put the operator for one zero byte (eight zero bits),
110 | in even -- next square puts operator for two zero bytes in odd, and so
111 | on, until len has been rotated down to zero */
112 | do {
113 | gf2_matrix_square ( even, odd );
114 | len >>= 1;
115 | if ( len == 0 )
116 | return;
117 | gf2_matrix_square ( odd, even );
118 | len >>= 1;
119 | } while ( len );
120 |
121 | /* answer ended up in odd -- copy to even */
122 | for ( n = 0; n < 32; n++ )
123 | even[n] = odd[n];
124 | }
125 |
126 | /* Take a length and build four lookup tables for applying the zeros operator
127 | for that length, byte-by-byte on the operand. */
128 | static void crc32c_zeros ( uint32_t zeros[][256], size_t len )
129 | {
130 | uint32_t n;
131 | uint32_t op[32];
132 |
133 | crc32c_zeros_op ( op, len );
134 | for ( n = 0; n < 256; n++ ) {
135 | zeros[0][n] = gf2_matrix_times ( op, n );
136 | zeros[1][n] = gf2_matrix_times ( op, n << 8 );
137 | zeros[2][n] = gf2_matrix_times ( op, n << 16 );
138 | zeros[3][n] = gf2_matrix_times ( op, n << 24 );
139 | }
140 | }
141 |
142 |
143 | /* Apply the zeros operator table to crc. */
144 | static inline uint32_t crc32c_shift ( uint32_t zeros[][256], uint32_t crc )
145 | {
146 | return zeros[0][crc & 0xff] ^ zeros[1][ ( crc >> 8 ) & 0xff] ^
147 | zeros[2][ ( crc >> 16 ) & 0xff] ^ zeros[3][crc >> 24];
148 | }
149 |
150 | /* Block sizes for three-way parallel crc computation. LONG and SHORT must
151 | both be powers of two. The associated string constants must be set
152 | accordingly, for use in constructing the assembler instructions. */
153 | #define LONG 8192
154 | #define LONGx1 "8192"
155 | #define LONGx2 "16384"
156 | #define SHORT 256
157 | #define SHORTx1 "256"
158 | #define SHORTx2 "512"
159 |
160 | /* Tables for hardware crc that shift a crc by LONG and SHORT zeros. */
161 | static uint32_t crc32c_long[4][256];
162 | static uint32_t crc32c_short[4][256];
163 |
164 | /* Initialize tables for shifting crcs. */
165 | static void crc32c_init_hw ( void ) __attribute__ ( ( constructor ) );
166 | static void crc32c_init_hw ( void )
167 | {
168 | crc32c_zeros ( crc32c_long, LONG );
169 | crc32c_zeros ( crc32c_short, SHORT );
170 | }
171 |
172 | #ifndef __LP64__
173 | #define CRCtriplet(crc, buf, size, i) \
174 | crc ## 0 = __builtin_ia32_crc32si(crc ## 0, *(uint32_t*) (buf + i)); \
175 | crc ## 1 = __builtin_ia32_crc32si(crc ## 1, *(uint32_t*) (buf + i + size)); \
176 | crc ## 2 = __builtin_ia32_crc32si(crc ## 2, *(uint32_t*) (buf + i + 2 * size)); \
177 | crc ## 0 = __builtin_ia32_crc32si(crc ## 0, *(uint32_t*) (buf + sizeof(uint32_t) + i)); \
178 | crc ## 1 = __builtin_ia32_crc32si(crc ## 1, *(uint32_t*) (buf + sizeof(uint32_t) + i + size)); \
179 | crc ## 2 = __builtin_ia32_crc32si(crc ## 2, *(uint32_t*) (buf + sizeof(uint32_t) + i + 2 * size));
180 | #else
181 | #define CRCtriplet(crc, buf, size, i) \
182 | crc ## 0 = __builtin_ia32_crc32di(crc ## 0, *(uint64_t*) (buf + i)); \
183 | crc ## 1 = __builtin_ia32_crc32di(crc ## 1, *(uint64_t*) (buf + i + size)); \
184 | crc ## 2 = __builtin_ia32_crc32di(crc ## 2, *(uint64_t*) (buf + i + 2 * size));
185 | #endif
186 |
187 |
188 | #ifndef __LP64__
189 | #define CRCsinglet(crc, buf) \
190 | crc = __builtin_ia32_crc32si(crc, *(uint32_t*)buf); \
191 | crc = __builtin_ia32_crc32si(crc, *(uint32_t*)(buf + sizeof(uint32_t))); \
192 | buf+= 2 *sizeof(uint32_t);
193 | #else
194 | #define CRCsinglet(crc, buf) crc = __builtin_ia32_crc32di(crc, *(uint64_t*)buf); buf+= sizeof(uint64_t);
195 | #endif
196 |
197 | /* Compute CRC-32C using the Intel hardware instruction. */
198 | uint32_t crc32cAdler ( uint32_t crc, const void *buf, size_t len )
199 | {
200 | const unsigned char *next = ( const unsigned char * ) buf;
201 | const unsigned char *end;
202 | #ifndef __LP64__
203 | uint32_t crc0, crc1, crc2;
204 | #else
205 | uint64_t crc0, crc1, crc2; /* need to be 64 bits for crc32q */
206 | #endif
207 | uint32_t crc32bit;
208 |
209 | crc32bit = crc;
210 | // in len > 256 compute the crc for up to seven leading bytes to bring the data pointer to an eight-byte boundary
211 | if ( len > 128 ) {
212 | unsigned char align = ( 8 - ( uintptr_t ) next ) % 8; // byte to boundary
213 | len -= align;
214 | if ( ( align % 2 ) != 0 ) crc32bit = __builtin_ia32_crc32qi ( crc32bit, *next );
215 | next += align;
216 | switch ( align / 2 ) {
217 | case 3:
218 | crc32bit = __builtin_ia32_crc32hi ( crc32bit, * ( uint16_t* ) ( next - 6 ) ); // 6 char, remain 4
219 | case 2:
220 | crc32bit = __builtin_ia32_crc32si ( crc32bit, * ( uint32_t* ) ( next - 4 ) ); // 4 char, remain 0
221 | break;
222 | case 1:
223 | crc32bit = __builtin_ia32_crc32hi ( crc32bit, * ( uint16_t* ) ( next - 2 ) ); // 2 char, remain 0
224 | case 0:
225 | break;
226 | }
227 | };
228 |
229 | /* compute the crc on sets of LONG*3 bytes, executing three independent crc
230 | instructions, each on LONG bytes -- this is optimized for the Nehalem,
231 | Westmere, Sandy Bridge, and Ivy Bridge architectures, which have a
232 | throughput of one crc per cycle, but a latency of three cycles */
233 |
234 | crc0 = crc32bit;
235 | while ( len >= LONG*3 ) {
236 | crc1 = 0;
237 | crc2 = 0;
238 | end = next + LONG;
239 | do {
240 | CRCtriplet ( crc, next, LONG, 0 );
241 | CRCtriplet ( crc, next, LONG, 8 );
242 | CRCtriplet ( crc, next, LONG, 16 );
243 | CRCtriplet ( crc, next, LONG, 24 );
244 | next += 32;
245 | } while ( next < end );
246 | crc0 = crc32c_shift ( crc32c_long, crc0 ) ^ crc1;
247 | crc0 = crc32c_shift ( crc32c_long, crc0 ) ^ crc2;
248 | next += LONG*2;
249 | len -= LONG*3;
250 | }
251 |
252 | /* do the same thing, but now on SHORT*3 blocks for the remaining data less
253 | than a LONG*3 block */
254 | while ( len >= SHORT*3 ) {
255 | crc1 = 0;
256 | crc2 = 0;
257 | end = next + SHORT;
258 | do {
259 | CRCtriplet ( crc, next, SHORT, 0 );
260 | CRCtriplet ( crc, next, SHORT, 8 );
261 | CRCtriplet ( crc, next, SHORT, 16 );
262 | CRCtriplet ( crc, next, SHORT, 24 );
263 | next += 32;
264 | } while ( next < end );
265 | crc0 = crc32c_shift ( crc32c_short, crc0 ) ^ crc1;
266 | crc0 = crc32c_shift ( crc32c_short, crc0 ) ^ crc2;
267 | next += SHORT*2;
268 | len -= SHORT*3;
269 | }
270 |
271 | /* compute the crc on the remaining eight-byte units less than a SHORT*3
272 | block */
273 |
274 | // use Duff's device, a for() loop inside a switch() statement. This is Legal
275 | unsigned short count;
276 | if ( ( count = ( len - ( len & 7 ) ) ) >= 8 ) { // needs to execute crc at least once
277 | len -= count;
278 | count /= 8; // count number of crc32di
279 | unsigned short n = ( count + 15 ) / 16;
280 | switch ( count % 16 ) {
281 | case 0:
282 | do {
283 | CRCsinglet ( crc0, next );
284 | case 15:
285 | CRCsinglet ( crc0, next );
286 | case 14:
287 | CRCsinglet ( crc0, next );
288 | case 13:
289 | CRCsinglet ( crc0, next );
290 | case 12:
291 | CRCsinglet ( crc0, next );
292 | case 11:
293 | CRCsinglet ( crc0, next );
294 | case 10:
295 | CRCsinglet ( crc0, next );
296 | case 9:
297 | CRCsinglet ( crc0, next );
298 | case 8:
299 | CRCsinglet ( crc0, next );
300 | case 7:
301 | CRCsinglet ( crc0, next );
302 | case 6:
303 | CRCsinglet ( crc0, next );
304 | case 5:
305 | CRCsinglet ( crc0, next );
306 | case 4:
307 | CRCsinglet ( crc0, next );
308 | case 3:
309 | CRCsinglet ( crc0, next );
310 | case 2:
311 | CRCsinglet ( crc0, next );
312 | case 1:
313 | CRCsinglet ( crc0, next );
314 | } while ( --n > 0 );
315 | }
316 | };
317 |
318 | /* compute the crc for up to seven trailing bytes */
319 | crc32bit = crc0;
320 | if ( ( len % 2 ) != 0 ) crc32bit = __builtin_ia32_crc32qi ( crc32bit, * ( next ) ); // 1 char, remain even
321 | next += len;
322 | switch ( len / 2 ) {
323 | case 3:
324 | crc32bit = __builtin_ia32_crc32hi ( crc32bit, * ( uint16_t* ) ( next - 6 ) ); // 2 char, remain 4
325 | case 2:
326 | crc32bit = __builtin_ia32_crc32si ( crc32bit, * ( uint32_t* ) ( next - 4 ) ); // 4 char, remain 0
327 | break;
328 | case 1:
329 | crc32bit = __builtin_ia32_crc32hi ( crc32bit, * ( uint16_t* ) ( next - 2 ) ); // 2 char, remain 0
330 | break;
331 | case 0:
332 | break;
333 | }
334 | return ( uint32_t ) crc32bit;
335 | }
336 |
337 | } // namespace logging
338 | // kate: indent-mode cstyle; indent-width 8; replace-tabs on;
339 |
--------------------------------------------------------------------------------
/crc32c/crc32c.cc:
--------------------------------------------------------------------------------
1 | // Copyright 2008,2009,2010 Massachusetts Institute of Technology.
2 | // All rights reserved. Use of this source code is governed by a
3 | // BSD-style license that can be found in the LICENSE file.
4 |
5 | #include "logging/crc32c.h"
6 |
7 | #include
8 | #include
9 | #include
10 | #include
11 |
12 |
13 | #include "logging/crc32ctables.h"
14 |
15 | namespace logging {
16 |
17 | static uint32_t crc32c_CPUDetection(uint32_t crc, const void* data, size_t length) {
18 | // Avoid issues that could potentially be caused by multiple threads: use a local variable
19 | CRC32CFunctionPtr best = detectBestCRC32C();
20 | crc32c = best;
21 | return best(crc, data, length);
22 | }
23 |
24 | CRC32CFunctionPtr crc32c = crc32c_CPUDetection;
25 |
26 | CRC32CFunctionPtr detectBestCRC32C() {
27 | unsigned int eax, ebx = 0, ecx = 0, edx;
28 | unsigned int max_level;
29 |
30 | max_level = __get_cpuid_max(0, NULL);
31 | if (max_level >= 1) {
32 | __cpuid(1, eax, ebx, ecx, edx);
33 | };
34 | bool hasSSE42 = (ecx & bit_SSE4_2);
35 | if (hasSSE42) {
36 | #ifdef __LP64__
37 | return crc32cHardware64;
38 | #else
39 | return crc32cHardware32;
40 | #endif
41 | } else {
42 | return crc32cSlicingBy8;
43 | }
44 | }
45 |
46 | // Implementations adapted from Intel's Slicing By 8 Sourceforge Project
47 | // http://sourceforge.net/projects/slicing-by-8/
48 | /*++
49 | *
50 | * Copyright (c) 2004-2006 Intel Corporation - All Rights Reserved
51 | *
52 | * This software program is licensed subject to the BSD License,
53 | * available at http://www.opensource.org/licenses/bsd-license.html
54 | *
55 | * Abstract: The main routine
56 | *
57 | --*/
58 | uint32_t crc32cSarwate(uint32_t crc, const void* data, size_t length) {
59 | const char* p_buf = (const char*) data;
60 | const char* p_end = p_buf + length;
61 |
62 | while (p_buf < p_end) {
63 | crc = crc_tableil8_o32[(crc ^ *p_buf++) & 0x000000FF] ^ (crc >> 8);
64 | }
65 |
66 | return crc;
67 | }
68 |
69 | uint32_t crc32cSlicingBy4(uint32_t crc, const void* data, size_t length) {
70 | const char* p_buf = (const char*) data;
71 |
72 | // Handle leading misaligned bytes
73 | size_t initial_bytes = (sizeof(int32_t) - (intptr_t)p_buf) & (sizeof(int32_t) - 1);
74 | if (length < initial_bytes) initial_bytes = length;
75 | for (size_t li = 0; li < initial_bytes; li++) {
76 | crc = crc_tableil8_o32[(crc ^ *p_buf++) & 0x000000FF] ^ (crc >> 8);
77 | }
78 |
79 | length -= initial_bytes;
80 | size_t running_length = length & ~(sizeof(int32_t) - 1);
81 | size_t end_bytes = length - running_length;
82 |
83 | for (size_t li = 0; li < running_length/4; li++) {
84 | crc ^= *(uint32_t*) p_buf;
85 | p_buf += 4;
86 | uint32_t term1 = crc_tableil8_o56[crc & 0x000000FF] ^
87 | crc_tableil8_o48[(crc >> 8) & 0x000000FF];
88 | uint32_t term2 = crc >> 16;
89 | crc = term1 ^
90 | crc_tableil8_o40[term2 & 0x000000FF] ^
91 | crc_tableil8_o32[(term2 >> 8) & 0x000000FF];
92 | }
93 |
94 | for (size_t li=0; li < end_bytes; li++) {
95 | crc = crc_tableil8_o32[(crc ^ *p_buf++) & 0x000000FF] ^ (crc >> 8);
96 | }
97 |
98 | return crc;
99 | }
100 |
101 | uint32_t crc32cSlicingBy8(uint32_t crc, const void* data, size_t length) {
102 | const char* p_buf = (const char*) data;
103 |
104 | // Handle leading misaligned bytes
105 | size_t initial_bytes = (sizeof(int32_t) - (intptr_t)p_buf) & (sizeof(int32_t) - 1);
106 | if (length < initial_bytes) initial_bytes = length;
107 | for (size_t li = 0; li < initial_bytes; li++) {
108 | crc = crc_tableil8_o32[(crc ^ *p_buf++) & 0x000000FF] ^ (crc >> 8);
109 | }
110 |
111 | length -= initial_bytes;
112 | size_t running_length = length & ~(sizeof(uint64_t) - 1);
113 | size_t end_bytes = length - running_length;
114 |
115 | for (size_t li = 0; li < running_length/8; li++) {
116 | crc ^= *(uint32_t*) p_buf;
117 | p_buf += 4;
118 | uint32_t term1 = crc_tableil8_o88[crc & 0x000000FF] ^
119 | crc_tableil8_o80[(crc >> 8) & 0x000000FF];
120 | uint32_t term2 = crc >> 16;
121 | crc = term1 ^
122 | crc_tableil8_o72[term2 & 0x000000FF] ^
123 | crc_tableil8_o64[(term2 >> 8) & 0x000000FF];
124 | term1 = crc_tableil8_o56[(*(uint32_t *)p_buf) & 0x000000FF] ^
125 | crc_tableil8_o48[((*(uint32_t *)p_buf) >> 8) & 0x000000FF];
126 |
127 | term2 = (*(uint32_t *)p_buf) >> 16;
128 | crc = crc ^ term1 ^
129 | crc_tableil8_o40[term2 & 0x000000FF] ^
130 | crc_tableil8_o32[(term2 >> 8) & 0x000000FF];
131 | p_buf += 4;
132 | }
133 |
134 | for (size_t li=0; li < end_bytes; li++) {
135 | crc = crc_tableil8_o32[(crc ^ *p_buf++) & 0x000000FF] ^ (crc >> 8);
136 | }
137 |
138 | return crc;
139 | }
140 |
141 | // Hardware-accelerated CRC-32C (using CRC32 instruction)
142 | uint32_t crc32cHardware32(uint32_t crc, const void* data, size_t length) {
143 | const char* p_buf = (const char*) data;
144 | // alignment doesn't seem to help?
145 | for (size_t i = 0; i < length / sizeof(uint32_t); i++) {
146 | crc = __builtin_ia32_crc32si(crc, *(uint32_t*) p_buf);
147 | p_buf += sizeof(uint32_t);
148 | }
149 |
150 | // This ugly switch is slightly faster for short strings than the straightforward loop
151 | length &= sizeof(uint32_t) - 1;
152 | /*
153 | while (length > 0) {
154 | crc32bit = __builtin_ia32_crc32qi(crc32bit, *p_buf++);
155 | length--;
156 | }
157 | */
158 | switch (length) {
159 | case 3:
160 | crc = __builtin_ia32_crc32qi(crc, *p_buf++);
161 | case 2:
162 | crc = __builtin_ia32_crc32hi(crc, *(uint16_t*) p_buf);
163 | break;
164 | case 1:
165 | crc = __builtin_ia32_crc32qi(crc, *p_buf);
166 | break;
167 | case 0:
168 | break;
169 | default:
170 | // This should never happen; enable in debug code
171 | assert(false);
172 | }
173 |
174 | return crc;
175 | }
176 |
177 | // Hardware-accelerated CRC-32C (using CRC32 instruction)
178 | uint32_t crc32cHardware64(uint32_t crc, const void* data, size_t length) {
179 | #ifndef __LP64__
180 | return crc32cHardware32(crc, data, length);
181 | #else
182 | const char* p_buf = (const char*) data;
183 | // alignment doesn't seem to help?
184 | uint64_t crc64bit = crc;
185 | for (size_t i = 0; i < length / sizeof(uint64_t); i++) {
186 | crc64bit = __builtin_ia32_crc32di(crc64bit, *(uint64_t*) p_buf);
187 | p_buf += sizeof(uint64_t);
188 | }
189 |
190 | // This ugly switch is slightly faster for short strings than the straightforward loop
191 | uint32_t crc32bit = (uint32_t) crc64bit;
192 | length &= sizeof(uint64_t) - 1;
193 | /*
194 | while (length > 0) {
195 | crc32bit = __builtin_ia32_crc32qi(crc32bit, *p_buf++);
196 | length--;
197 | }
198 | */
199 | switch (length) {
200 | case 7:
201 | crc32bit = __builtin_ia32_crc32qi(crc32bit, *p_buf++);
202 | case 6:
203 | crc32bit = __builtin_ia32_crc32hi(crc32bit, *(uint16_t*) p_buf);
204 | p_buf += 2;
205 | // case 5 is below: 4 + 1
206 | case 4:
207 | crc32bit = __builtin_ia32_crc32si(crc32bit, *(uint32_t*) p_buf);
208 | break;
209 | case 3:
210 | crc32bit = __builtin_ia32_crc32qi(crc32bit, *p_buf++);
211 | case 2:
212 | crc32bit = __builtin_ia32_crc32hi(crc32bit, *(uint16_t*) p_buf);
213 | break;
214 | case 5:
215 | crc32bit = __builtin_ia32_crc32si(crc32bit, *(uint32_t*) p_buf);
216 | p_buf += 4;
217 | case 1:
218 | crc32bit = __builtin_ia32_crc32qi(crc32bit, *p_buf);
219 | break;
220 | case 0:
221 | break;
222 | default:
223 | // This should never happen; enable in debug code
224 | assert(false);
225 | }
226 |
227 | return crc32bit;
228 | #endif
229 | }
230 |
231 | } // namespace logging
232 |
--------------------------------------------------------------------------------
/crc32c/crc32c.kdev4:
--------------------------------------------------------------------------------
1 | [Project]
2 | Manager=KDevCustomMakeManager
3 | Name=crc32c
4 |
--------------------------------------------------------------------------------
/crc32c/crc32c_test.cc:
--------------------------------------------------------------------------------
1 | // Copyright 2008,2009,2010 Massachusetts Institute of Technology.
2 | // All rights reserved. Use of this source code is governed by a
3 | // BSD-style license that can be found in the LICENSE file.
4 |
5 | #include
6 | #include
7 |
8 | #include "logging/crc32c.h"
9 | #include "stupidunit/stupidunit.h"
10 |
11 | using namespace logging;
12 |
13 | TEST(CRC32C, CPUDetection) {
14 | CRC32CFunctionPtr initial = crc32c;
15 | /* uint32_t crc = */ crc32c(crc32cInit(), NULL, 0);
16 | // These should not be equal!
17 | CRC32CFunctionPtr final = crc32c;
18 | EXPECT_NE(initial, final);
19 |
20 | // Calling the function again does not change it
21 | /* crc = */ crc32c(crc32cInit(), NULL, 0);
22 | EXPECT_EQ(final, crc32c);
23 |
24 | EXPECT_EQ(final, detectBestCRC32C());
25 | }
26 |
27 | struct CRC32CFunctionInfo {
28 | CRC32CFunctionPtr crcfn;
29 | const char* name;
30 | };
31 |
32 | #define MAKE_FN_STRUCT(x) { x, # x }
33 | static const CRC32CFunctionInfo FNINFO[] = {
34 | MAKE_FN_STRUCT(crc32cSarwate),
35 | MAKE_FN_STRUCT(crc32cSlicingBy4),
36 | MAKE_FN_STRUCT(crc32cSlicingBy8),
37 | MAKE_FN_STRUCT(crc32cHardware32),
38 | #ifdef __LP64__
39 | MAKE_FN_STRUCT(crc32cHardware64),
40 | MAKE_FN_STRUCT(crc32cIntelAsm),
41 | #endif
42 | MAKE_FN_STRUCT(crc32cAdler),
43 | MAKE_FN_STRUCT(crc32cIntelC),
44 | };
45 | #undef MAKE_FN_STRUCT
46 |
47 | static size_t numValidFunctions() {
48 | size_t numFunctions = sizeof(FNINFO)/sizeof(*FNINFO);
49 | bool hasHardware = (detectBestCRC32C() != crc32cSlicingBy8);
50 | if (!hasHardware) {
51 | while (FNINFO[numFunctions-1].crcfn == crc32cHardware32 ||
52 | FNINFO[numFunctions-1].crcfn == crc32cHardware64 ||
53 | FNINFO[numFunctions-1].crcfn == crc32cIntelC) {
54 | numFunctions -= 1;
55 | }
56 | }
57 | return numFunctions;
58 | }
59 | static const size_t NUM_VALID_FUNCTIONS = numValidFunctions();
60 |
61 | static bool check(const CRC32CFunctionInfo& fninfo, const void* data, size_t length, uint32_t value) {
62 | uint32_t crc = fninfo.crcfn(crc32cInit(), data, length);
63 | crc = crc32cFinish(crc);
64 | if (crc != value) {
65 | printf("Function %s failed; expected: 0x%08x actual: 0x%08x. ", fninfo.name, value, crc);
66 | switch(*(char *)data) {
67 | case '1':
68 | printf("Test: NUMBERS len=%d\n", (int)length);
69 | break;
70 | case '2':
71 | printf("Test: NUMBERS not aligned len=%d\n", (int)length);
72 | break;
73 | case 'T':
74 | printf("Test: PHRASE len=%d\n", (int)length);
75 | break;
76 | case 'L':
77 | printf("Test: LONGPHRASE len=%d\n", (int)length);
78 | break;
79 | default:
80 | printf("Test: VARSIZE len=%d\n", (int)length);
81 | };
82 | return false;
83 | }
84 | return true;
85 | }
86 |
87 | #define CHECK_SIZE 10000
88 |
89 | TEST(CRC32C, KnownValues) {
90 | static const char NUMBERS[] = "1234567890";
91 | static const char PHRASE[] = "The quick brown fox jumps over the lazy dog";
92 | static const char LONGPHRASE[] = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc omni virtuti vitium contrario nomine opponitur. "
93 | "Conferam tecum, quam cuique verso rem subicias; Te ipsum, dignissimum maioribus tuis, voluptasne induxit, ut adolescentulus eriperes "
94 | "P. Conclusum est enim contra Cyrenaicos satis acute, nihil ad Epicurum. Duo Reges: constructio interrete. Tum Torquatus: Prorsus, inquit, assentior;\n"
95 | "Quando enim Socrates, qui parens philosophiae iure dici potest, quicquam tale fecit? Sed quid sentiat, non videtis. Haec quo modo conveniant, non "
96 | "sane intellego. Sed ille, ut dixi, vitiose. Dic in quovis conventu te omnia facere, ne doleas. Quod si ita se habeat, non possit beatam praestare "
97 | "vitam sapientia. Quis suae urbis conservatorem Codrum, quis Erechthei filias non maxime laudat? Primum divisit ineleganter; Huic mori optimum esse "
98 | "propter desperationem sapientiae, illi propter spem vivere.";
99 | char VARSIZE[CHECK_SIZE];
100 | uint32_t VAR_CRC[CHECK_SIZE];
101 |
102 | for (int i = 0; i < CHECK_SIZE; i++) {
103 | VARSIZE[i] = i;
104 | VAR_CRC[i] = crc32cFinish(crc32cSlicingBy8(crc32cInit(), VARSIZE, size_t(i)));
105 | };
106 |
107 |
108 | for (int i = 0; i < NUM_VALID_FUNCTIONS; ++i) {
109 | EXPECT_TRUE(check(FNINFO[i], NUMBERS, 9, 0xE3069283));
110 | EXPECT_TRUE(check(FNINFO[i], NUMBERS+1, 8, 0xBFE92A83));
111 | EXPECT_TRUE(check(FNINFO[i], NUMBERS, 10, 0xf3dbd4fe));
112 | EXPECT_TRUE(check(FNINFO[i], PHRASE, sizeof(PHRASE)-1, 0x22620404));
113 | EXPECT_TRUE(check(FNINFO[i], LONGPHRASE, sizeof(LONGPHRASE)-1, 0xfcb7575a));
114 | for(int j = 0; j < CHECK_SIZE; j++) {
115 | EXPECT_TRUE(check(FNINFO[i], VARSIZE, j, VAR_CRC[j]));
116 | };
117 | }
118 | }
119 |
120 | /*
121 | static size_t misalignedLeadingBytes(const void* pointer, int alignment) {
122 | size_t misalignedBytes = (alignment - (intptr_t)pointer) & (alignment - 1);
123 | return misalignedBytes;
124 | }
125 | */
126 |
127 | template
128 | static T* alignBlock(T* pointer, int alignment) {
129 | return (T*) (((intptr_t) pointer + (alignment - 1)) & ~(alignment - 1));
130 | }
131 |
132 | TEST(CRC32C, Alignment) {
133 | // The 64-bit algorithms use 8 byte alignment
134 | static const int ALIGNMENT_BITS = 3;
135 | static const int ALIGNMENT_SIZE = 1 << ALIGNMENT_BITS;
136 | // Allocate 4 aligned blocks. We will drop the first if the allocation is not aligned
137 | static char BUFFER[ALIGNMENT_SIZE * 4];
138 | // Get the first aligned block in BUFFER
139 | static char* const ALIGNED_BUFFER = alignBlock(BUFFER, ALIGNMENT_SIZE);
140 |
141 | // Fill the buffer with non-zero data
142 | for (char* p = ALIGNED_BUFFER; p < ALIGNED_BUFFER + ALIGNMENT_SIZE * 3; ++p) {
143 | *p = (char)(p - ALIGNED_BUFFER);
144 | }
145 |
146 | /* This test uses 3 blocks of variable sizes:
147 | (leading misaligned bytes 0-7)(aligned block 0 or 8)(trailing misaligned bytes 0-7)
148 |
149 | We increment an integer to iterate through all posibilities and cross check all CRC
150 | implementations. */
151 | static const int MAX_ITERATIONS = 1 << (ALIGNMENT_BITS * 2 + 1);
152 | static const int LEADING_MASK = (ALIGNMENT_SIZE - 1) << (ALIGNMENT_BITS + 1);
153 | static const int ALIGN_MASK = 1 << ALIGNMENT_BITS;
154 | static const int TRAILING_MASK = (ALIGNMENT_SIZE - 1);
155 | static char* const ALIGNED_BLOCK = ALIGNED_BUFFER + ALIGNMENT_SIZE;
156 | for (int i = 0; i < MAX_ITERATIONS; ++i) {
157 | int leading = (i & LEADING_MASK) >> (ALIGNMENT_BITS + 1);
158 | int aligned = i & ALIGN_MASK;
159 | int trailing = i & TRAILING_MASK;
160 | //~ printf("%d = %d %d %d\n", i, leading, aligned, trailing);
161 |
162 | char* start = ALIGNED_BLOCK - leading;
163 | char* end = ALIGNED_BLOCK;
164 | if (aligned) end += ALIGNMENT_SIZE;
165 | end += trailing;
166 | //~ printf("start: %p end: %p; %d bytes\n", start, end, end - start);
167 |
168 | uint32_t crc = 0;
169 | for (int j = 0; j < NUM_VALID_FUNCTIONS; ++j) {
170 | uint32_t crcTemp = FNINFO[j].crcfn(crc32cInit(), start, end - start);
171 | crcTemp = crc32cFinish(crcTemp);
172 | if (j == 0) {
173 | crc = crcTemp;
174 | } else {
175 | if (crc != crcTemp) {
176 | printf("Failed %s i = 0x%08x expected 0x%08x actual 0x%08x\n", FNINFO[j].name, i, crc, crcTemp);
177 | }
178 | EXPECT_EQ(crc, crcTemp);
179 | }
180 | }
181 | }
182 | }
183 |
184 | int main() {
185 | printf("Testing CRC32C functions\n");
186 | return TestSuite::globalInstance()->runAll();
187 | }
188 |
--------------------------------------------------------------------------------
/crc32c/crc32cbench.cc:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | // FT addition here
4 | #include
5 | #include
6 |
7 | #include "logging/crc32c.h"
8 | #include "logging/cycletimer.h"
9 |
10 | using namespace logging;
11 |
12 | static const int TRIALS = 5;
13 | static const int ITERATIONS = 10;
14 |
15 | static const int BUFFER_MAX = 128 * 1024 * 1024;
16 | static const int ALIGNMENT = 8;
17 |
18 | struct CRC32CFunctionInfo {
19 | CRC32CFunctionPtr crcfn;
20 | const char* name;
21 | };
22 |
23 | #define MAKE_FN_STRUCT(x) { x, # x }
24 | static const CRC32CFunctionInfo FNINFO[] = {
25 | MAKE_FN_STRUCT(crc32cSarwate),
26 | MAKE_FN_STRUCT(crc32cSlicingBy4),
27 | MAKE_FN_STRUCT(crc32cSlicingBy8),
28 | MAKE_FN_STRUCT(crc32cHardware32),
29 | #ifdef __LP64__
30 | MAKE_FN_STRUCT(crc32cHardware64),
31 | MAKE_FN_STRUCT(crc32cIntelAsm),
32 | #endif
33 | MAKE_FN_STRUCT(crc32cAdler),
34 | MAKE_FN_STRUCT(crc32cIntelC),
35 | };
36 | #undef MAKE_FN_STRUCT
37 |
38 | static size_t numValidFunctions() {
39 | size_t numFunctions = sizeof(FNINFO)/sizeof(*FNINFO);
40 | bool hasHardware = (detectBestCRC32C() != crc32cSlicingBy8);
41 | if (!hasHardware) {
42 | while (FNINFO[numFunctions-1].crcfn == crc32cHardware32 ||
43 | FNINFO[numFunctions-1].crcfn == crc32cHardware64) {
44 | numFunctions -= 1;
45 | }
46 | }
47 | return numFunctions;
48 | }
49 | static const size_t NUM_VALID_FUNCTIONS = numValidFunctions();
50 |
51 |
52 | static const int DATA_LENGTHS[] = {
53 | 16, 64, 128, 192, 256, 288, 512, 1024, 1032, 4096, 8192
54 | };
55 |
56 | // FT timing function copies from crc32
57 | static double seconds()
58 | {
59 | timespec now;
60 | clock_gettime(CLOCK_REALTIME, &now);
61 | return now.tv_sec + now.tv_nsec / 1000000000.0;
62 | }
63 |
64 | static int cmpDouble(const void *p1, const void *p2) {
65 | if(*(double *)p1 > *(double *)p2) return 1;
66 | if(*(double *)p1 == *(double *)p2) return 0;
67 | return -1;
68 | }
69 |
70 |
71 | void runTest(const CRC32CFunctionInfo& fninfo, const char* buffer, int length, bool aligned) {
72 | int iterations = BUFFER_MAX / length;
73 | double startTime, duration;
74 | double runTimes[TRIALS];
75 |
76 | printf("%-16s\t%s\t%d", fninfo.name, aligned ? "true" : "false", length);
77 |
78 | for (int j = 0; j < TRIALS; ++j) {
79 | uint32_t crc = 0;
80 | // FT removed the original timer and and retrieves the time
81 | // CycleTimer timer;
82 | // timer.start();
83 | startTime = seconds();
84 | // for (int i = 0; i < ITERATIONS; ++i) {
85 | for (int i = 0; i < iterations; ++i) {
86 | crc = fninfo.crcfn(crc32cInit(), buffer + length, length);
87 | crc = crc32cFinish(crc);
88 | }
89 | // timer.end();
90 |
91 | // uint32_t cycles = timer.getCycles();
92 | // printf(",%d", cycles);
93 | duration = seconds() - startTime;
94 | runTimes[j] = duration;
95 |
96 |
97 | }
98 | qsort(runTimes, TRIALS, sizeof(double), cmpDouble);
99 | // FT calculates the median value when TRIALS is an odd number
100 | printf("\t%.3f\n", 128.0 / runTimes[(TRIALS + 1) / 2 - 1]);
101 | }
102 |
103 | int main() {
104 | char* buffer = new char[BUFFER_MAX + ALIGNMENT];
105 | char* aligned_buffer = (char*) (((intptr_t) buffer + (ALIGNMENT-1)) & ~(ALIGNMENT-1));
106 | assert(aligned_buffer + BUFFER_MAX <= buffer + BUFFER_MAX + ALIGNMENT);
107 |
108 | // fill the buffer with non-zero data
109 | for (int i = 0; i < BUFFER_MAX; ++i) {
110 | aligned_buffer[i] = (char) i;
111 | }
112 |
113 | printf("function\t\taligned\tbytes\tMiB/sec\n");
114 | for (size_t fnIndex = 0; fnIndex < NUM_VALID_FUNCTIONS; ++fnIndex) {
115 | for (int aligned = 0; aligned < 2; ++aligned) {
116 | for (size_t lengthIndex = 0; lengthIndex < sizeof(DATA_LENGTHS)/sizeof(*DATA_LENGTHS);
117 | ++lengthIndex) {
118 | int length = DATA_LENGTHS[lengthIndex];
119 | const char* data = aligned_buffer;
120 | // For mis-alignment, add one to the front and remove one from the back
121 | if (!aligned) {
122 | data += 1;
123 | length -= 1;
124 | }
125 | runTest(FNINFO[fnIndex], data, length, aligned);
126 | }
127 | }
128 | }
129 |
130 | delete[] buffer;
131 | return 0;
132 | }
133 |
--------------------------------------------------------------------------------
/crc32c/crc32ctables.cc:
--------------------------------------------------------------------------------
1 | // Copyright 2008,2009,2010 Massachusetts Institute of Technology.
2 | // All rights reserved. Use of this source code is governed by a
3 | // BSD-style license that can be found in the LICENSE file.
4 |
5 | // Implementations adapted from Intel's Slicing By 8 Sourceforge Project
6 | // http://sourceforge.net/projects/slicing-by-8/
7 | /*
8 | * Copyright (c) 2004-2006 Intel Corporation - All Rights Reserved
9 | *
10 | *
11 | * This software program is licensed subject to the BSD License,
12 | * available at http://www.opensource.org/licenses/bsd-license.html.
13 | *
14 | * Abstract:
15 | *
16 | * Tables for software CRC generation
17 | */
18 |
19 | #include "logging/crc32ctables.h"
20 |
21 | namespace logging
22 | {
23 |
24 | /* Tables generated with code like the following:
25 |
26 | #define CRCPOLY 0x82f63b78 // reversed 0x1EDC6F41
27 | #define CRCINIT 0xFFFFFFFF
28 |
29 | void init() {
30 | for (uint32_t i = 0; i <= 0xFF; i++) {
31 | uint32_t x = i;
32 | for (uint32_t j = 0; j < 8; j++)
33 | x = (x>>1) ^ (CRCPOLY & (-(int32_t)(x & 1)));
34 | g_crc_slicing[0][i] = x;
35 | }
36 |
37 | for (uint32_t i = 0; i <= 0xFF; i++) {
38 | uint32_t c = g_crc_slicing[0][i];
39 | for (uint32_t j = 1; j < 8; j++) {
40 | c = g_crc_slicing[0][c & 0xFF] ^ (c >> 8);
41 | g_crc_slicing[j][i] = c;
42 | }
43 | }
44 | }
45 | */
46 |
47 | /*
48 | * The following CRC lookup table was generated automagically
49 | * using the following model parameters:
50 | *
51 | * Generator Polynomial = ................. 0x1EDC6F41
52 | * Generator Polynomial Length = .......... 32 bits
53 | * Reflected Bits = ....................... TRUE
54 | * Table Generation Offset = .............. 32 bits
55 | * Number of Slices = ..................... 8 slices
56 | * Slice Lengths = ........................ 8 8 8 8 8 8 8 8
57 | * Directory Name = ....................... .\
58 | * File Name = ............................ 8x256_tables.c
59 | */
60 |
61 | const uint32_t crc_tableil8_o32[256] = {
62 | 0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4, 0xC79A971F, 0x35F1141C, 0x26A1E7E8, 0xD4CA64EB,
63 | 0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B, 0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24,
64 | 0x105EC76F, 0xE235446C, 0xF165B798, 0x030E349B, 0xD7C45070, 0x25AFD373, 0x36FF2087, 0xC494A384,
65 | 0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57, 0x89D76C54, 0x5D1D08BF, 0xAF768BBC, 0xBC267848, 0x4E4DFB4B,
66 | 0x20BD8EDE, 0xD2D60DDD, 0xC186FE29, 0x33ED7D2A, 0xE72719C1, 0x154C9AC2, 0x061C6936, 0xF477EA35,
67 | 0xAA64D611, 0x580F5512, 0x4B5FA6E6, 0xB93425E5, 0x6DFE410E, 0x9F95C20D, 0x8CC531F9, 0x7EAEB2FA,
68 | 0x30E349B1, 0xC288CAB2, 0xD1D83946, 0x23B3BA45, 0xF779DEAE, 0x05125DAD, 0x1642AE59, 0xE4292D5A,
69 | 0xBA3A117E, 0x4851927D, 0x5B016189, 0xA96AE28A, 0x7DA08661, 0x8FCB0562, 0x9C9BF696, 0x6EF07595,
70 | 0x417B1DBC, 0xB3109EBF, 0xA0406D4B, 0x522BEE48, 0x86E18AA3, 0x748A09A0, 0x67DAFA54, 0x95B17957,
71 | 0xCBA24573, 0x39C9C670, 0x2A993584, 0xD8F2B687, 0x0C38D26C, 0xFE53516F, 0xED03A29B, 0x1F682198,
72 | 0x5125DAD3, 0xA34E59D0, 0xB01EAA24, 0x42752927, 0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38,
73 | 0xDBFC821C, 0x2997011F, 0x3AC7F2EB, 0xC8AC71E8, 0x1C661503, 0xEE0D9600, 0xFD5D65F4, 0x0F36E6F7,
74 | 0x61C69362, 0x93AD1061, 0x80FDE395, 0x72966096, 0xA65C047D, 0x5437877E, 0x4767748A, 0xB50CF789,
75 | 0xEB1FCBAD, 0x197448AE, 0x0A24BB5A, 0xF84F3859, 0x2C855CB2, 0xDEEEDFB1, 0xCDBE2C45, 0x3FD5AF46,
76 | 0x7198540D, 0x83F3D70E, 0x90A324FA, 0x62C8A7F9, 0xB602C312, 0x44694011, 0x5739B3E5, 0xA55230E6,
77 | 0xFB410CC2, 0x092A8FC1, 0x1A7A7C35, 0xE811FF36, 0x3CDB9BDD, 0xCEB018DE, 0xDDE0EB2A, 0x2F8B6829,
78 | 0x82F63B78, 0x709DB87B, 0x63CD4B8F, 0x91A6C88C, 0x456CAC67, 0xB7072F64, 0xA457DC90, 0x563C5F93,
79 | 0x082F63B7, 0xFA44E0B4, 0xE9141340, 0x1B7F9043, 0xCFB5F4A8, 0x3DDE77AB, 0x2E8E845F, 0xDCE5075C,
80 | 0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3, 0x55326B08, 0xA759E80B, 0xB4091BFF, 0x466298FC,
81 | 0x1871A4D8, 0xEA1A27DB, 0xF94AD42F, 0x0B21572C, 0xDFEB33C7, 0x2D80B0C4, 0x3ED04330, 0xCCBBC033,
82 | 0xA24BB5A6, 0x502036A5, 0x4370C551, 0xB11B4652, 0x65D122B9, 0x97BAA1BA, 0x84EA524E, 0x7681D14D,
83 | 0x2892ED69, 0xDAF96E6A, 0xC9A99D9E, 0x3BC21E9D, 0xEF087A76, 0x1D63F975, 0x0E330A81, 0xFC588982,
84 | 0xB21572C9, 0x407EF1CA, 0x532E023E, 0xA145813D, 0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622,
85 | 0x38CC2A06, 0xCAA7A905, 0xD9F75AF1, 0x2B9CD9F2, 0xFF56BD19, 0x0D3D3E1A, 0x1E6DCDEE, 0xEC064EED,
86 | 0xC38D26C4, 0x31E6A5C7, 0x22B65633, 0xD0DDD530, 0x0417B1DB, 0xF67C32D8, 0xE52CC12C, 0x1747422F,
87 | 0x49547E0B, 0xBB3FFD08, 0xA86F0EFC, 0x5A048DFF, 0x8ECEE914, 0x7CA56A17, 0x6FF599E3, 0x9D9E1AE0,
88 | 0xD3D3E1AB, 0x21B862A8, 0x32E8915C, 0xC083125F, 0x144976B4, 0xE622F5B7, 0xF5720643, 0x07198540,
89 | 0x590AB964, 0xAB613A67, 0xB831C993, 0x4A5A4A90, 0x9E902E7B, 0x6CFBAD78, 0x7FAB5E8C, 0x8DC0DD8F,
90 | 0xE330A81A, 0x115B2B19, 0x020BD8ED, 0xF0605BEE, 0x24AA3F05, 0xD6C1BC06, 0xC5914FF2, 0x37FACCF1,
91 | 0x69E9F0D5, 0x9B8273D6, 0x88D28022, 0x7AB90321, 0xAE7367CA, 0x5C18E4C9, 0x4F48173D, 0xBD23943E,
92 | 0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81, 0x34F4F86A, 0xC69F7B69, 0xD5CF889D, 0x27A40B9E,
93 | 0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E, 0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351
94 | };
95 |
96 | /*
97 | * end of the CRC lookup table crc_tableil8_o32
98 | */
99 |
100 |
101 |
102 | /*
103 | * The following CRC lookup table was generated automagically
104 | * using the following model parameters:
105 | *
106 | * Generator Polynomial = ................. 0x1EDC6F41
107 | * Generator Polynomial Length = .......... 32 bits
108 | * Reflected Bits = ....................... TRUE
109 | * Table Generation Offset = .............. 32 bits
110 | * Number of Slices = ..................... 8 slices
111 | * Slice Lengths = ........................ 8 8 8 8 8 8 8 8
112 | * Directory Name = ....................... .\
113 | * File Name = ............................ 8x256_tables.c
114 | */
115 |
116 | const uint32_t crc_tableil8_o40[256] = {
117 | 0x00000000, 0x13A29877, 0x274530EE, 0x34E7A899, 0x4E8A61DC, 0x5D28F9AB, 0x69CF5132, 0x7A6DC945,
118 | 0x9D14C3B8, 0x8EB65BCF, 0xBA51F356, 0xA9F36B21, 0xD39EA264, 0xC03C3A13, 0xF4DB928A, 0xE7790AFD,
119 | 0x3FC5F181, 0x2C6769F6, 0x1880C16F, 0x0B225918, 0x714F905D, 0x62ED082A, 0x560AA0B3, 0x45A838C4,
120 | 0xA2D13239, 0xB173AA4E, 0x859402D7, 0x96369AA0, 0xEC5B53E5, 0xFFF9CB92, 0xCB1E630B, 0xD8BCFB7C,
121 | 0x7F8BE302, 0x6C297B75, 0x58CED3EC, 0x4B6C4B9B, 0x310182DE, 0x22A31AA9, 0x1644B230, 0x05E62A47,
122 | 0xE29F20BA, 0xF13DB8CD, 0xC5DA1054, 0xD6788823, 0xAC154166, 0xBFB7D911, 0x8B507188, 0x98F2E9FF,
123 | 0x404E1283, 0x53EC8AF4, 0x670B226D, 0x74A9BA1A, 0x0EC4735F, 0x1D66EB28, 0x298143B1, 0x3A23DBC6,
124 | 0xDD5AD13B, 0xCEF8494C, 0xFA1FE1D5, 0xE9BD79A2, 0x93D0B0E7, 0x80722890, 0xB4958009, 0xA737187E,
125 | 0xFF17C604, 0xECB55E73, 0xD852F6EA, 0xCBF06E9D, 0xB19DA7D8, 0xA23F3FAF, 0x96D89736, 0x857A0F41,
126 | 0x620305BC, 0x71A19DCB, 0x45463552, 0x56E4AD25, 0x2C896460, 0x3F2BFC17, 0x0BCC548E, 0x186ECCF9,
127 | 0xC0D23785, 0xD370AFF2, 0xE797076B, 0xF4359F1C, 0x8E585659, 0x9DFACE2E, 0xA91D66B7, 0xBABFFEC0,
128 | 0x5DC6F43D, 0x4E646C4A, 0x7A83C4D3, 0x69215CA4, 0x134C95E1, 0x00EE0D96, 0x3409A50F, 0x27AB3D78,
129 | 0x809C2506, 0x933EBD71, 0xA7D915E8, 0xB47B8D9F, 0xCE1644DA, 0xDDB4DCAD, 0xE9537434, 0xFAF1EC43,
130 | 0x1D88E6BE, 0x0E2A7EC9, 0x3ACDD650, 0x296F4E27, 0x53028762, 0x40A01F15, 0x7447B78C, 0x67E52FFB,
131 | 0xBF59D487, 0xACFB4CF0, 0x981CE469, 0x8BBE7C1E, 0xF1D3B55B, 0xE2712D2C, 0xD69685B5, 0xC5341DC2,
132 | 0x224D173F, 0x31EF8F48, 0x050827D1, 0x16AABFA6, 0x6CC776E3, 0x7F65EE94, 0x4B82460D, 0x5820DE7A,
133 | 0xFBC3FAF9, 0xE861628E, 0xDC86CA17, 0xCF245260, 0xB5499B25, 0xA6EB0352, 0x920CABCB, 0x81AE33BC,
134 | 0x66D73941, 0x7575A136, 0x419209AF, 0x523091D8, 0x285D589D, 0x3BFFC0EA, 0x0F186873, 0x1CBAF004,
135 | 0xC4060B78, 0xD7A4930F, 0xE3433B96, 0xF0E1A3E1, 0x8A8C6AA4, 0x992EF2D3, 0xADC95A4A, 0xBE6BC23D,
136 | 0x5912C8C0, 0x4AB050B7, 0x7E57F82E, 0x6DF56059, 0x1798A91C, 0x043A316B, 0x30DD99F2, 0x237F0185,
137 | 0x844819FB, 0x97EA818C, 0xA30D2915, 0xB0AFB162, 0xCAC27827, 0xD960E050, 0xED8748C9, 0xFE25D0BE,
138 | 0x195CDA43, 0x0AFE4234, 0x3E19EAAD, 0x2DBB72DA, 0x57D6BB9F, 0x447423E8, 0x70938B71, 0x63311306,
139 | 0xBB8DE87A, 0xA82F700D, 0x9CC8D894, 0x8F6A40E3, 0xF50789A6, 0xE6A511D1, 0xD242B948, 0xC1E0213F,
140 | 0x26992BC2, 0x353BB3B5, 0x01DC1B2C, 0x127E835B, 0x68134A1E, 0x7BB1D269, 0x4F567AF0, 0x5CF4E287,
141 | 0x04D43CFD, 0x1776A48A, 0x23910C13, 0x30339464, 0x4A5E5D21, 0x59FCC556, 0x6D1B6DCF, 0x7EB9F5B8,
142 | 0x99C0FF45, 0x8A626732, 0xBE85CFAB, 0xAD2757DC, 0xD74A9E99, 0xC4E806EE, 0xF00FAE77, 0xE3AD3600,
143 | 0x3B11CD7C, 0x28B3550B, 0x1C54FD92, 0x0FF665E5, 0x759BACA0, 0x663934D7, 0x52DE9C4E, 0x417C0439,
144 | 0xA6050EC4, 0xB5A796B3, 0x81403E2A, 0x92E2A65D, 0xE88F6F18, 0xFB2DF76F, 0xCFCA5FF6, 0xDC68C781,
145 | 0x7B5FDFFF, 0x68FD4788, 0x5C1AEF11, 0x4FB87766, 0x35D5BE23, 0x26772654, 0x12908ECD, 0x013216BA,
146 | 0xE64B1C47, 0xF5E98430, 0xC10E2CA9, 0xD2ACB4DE, 0xA8C17D9B, 0xBB63E5EC, 0x8F844D75, 0x9C26D502,
147 | 0x449A2E7E, 0x5738B609, 0x63DF1E90, 0x707D86E7, 0x0A104FA2, 0x19B2D7D5, 0x2D557F4C, 0x3EF7E73B,
148 | 0xD98EEDC6, 0xCA2C75B1, 0xFECBDD28, 0xED69455F, 0x97048C1A, 0x84A6146D, 0xB041BCF4, 0xA3E32483
149 | };
150 |
151 | /*
152 | * end of the CRC lookup table crc_tableil8_o40
153 | */
154 |
155 |
156 |
157 | /*
158 | * The following CRC lookup table was generated automagically
159 | * using the following model parameters:
160 | *
161 | * Generator Polynomial = ................. 0x1EDC6F41
162 | * Generator Polynomial Length = .......... 32 bits
163 | * Reflected Bits = ....................... TRUE
164 | * Table Generation Offset = .............. 32 bits
165 | * Number of Slices = ..................... 8 slices
166 | * Slice Lengths = ........................ 8 8 8 8 8 8 8 8
167 | * Directory Name = ....................... .\
168 | * File Name = ............................ 8x256_tables.c
169 | */
170 |
171 | const uint32_t crc_tableil8_o48[256] = {
172 | 0x00000000, 0xA541927E, 0x4F6F520D, 0xEA2EC073, 0x9EDEA41A, 0x3B9F3664, 0xD1B1F617, 0x74F06469,
173 | 0x38513EC5, 0x9D10ACBB, 0x773E6CC8, 0xD27FFEB6, 0xA68F9ADF, 0x03CE08A1, 0xE9E0C8D2, 0x4CA15AAC,
174 | 0x70A27D8A, 0xD5E3EFF4, 0x3FCD2F87, 0x9A8CBDF9, 0xEE7CD990, 0x4B3D4BEE, 0xA1138B9D, 0x045219E3,
175 | 0x48F3434F, 0xEDB2D131, 0x079C1142, 0xA2DD833C, 0xD62DE755, 0x736C752B, 0x9942B558, 0x3C032726,
176 | 0xE144FB14, 0x4405696A, 0xAE2BA919, 0x0B6A3B67, 0x7F9A5F0E, 0xDADBCD70, 0x30F50D03, 0x95B49F7D,
177 | 0xD915C5D1, 0x7C5457AF, 0x967A97DC, 0x333B05A2, 0x47CB61CB, 0xE28AF3B5, 0x08A433C6, 0xADE5A1B8,
178 | 0x91E6869E, 0x34A714E0, 0xDE89D493, 0x7BC846ED, 0x0F382284, 0xAA79B0FA, 0x40577089, 0xE516E2F7,
179 | 0xA9B7B85B, 0x0CF62A25, 0xE6D8EA56, 0x43997828, 0x37691C41, 0x92288E3F, 0x78064E4C, 0xDD47DC32,
180 | 0xC76580D9, 0x622412A7, 0x880AD2D4, 0x2D4B40AA, 0x59BB24C3, 0xFCFAB6BD, 0x16D476CE, 0xB395E4B0,
181 | 0xFF34BE1C, 0x5A752C62, 0xB05BEC11, 0x151A7E6F, 0x61EA1A06, 0xC4AB8878, 0x2E85480B, 0x8BC4DA75,
182 | 0xB7C7FD53, 0x12866F2D, 0xF8A8AF5E, 0x5DE93D20, 0x29195949, 0x8C58CB37, 0x66760B44, 0xC337993A,
183 | 0x8F96C396, 0x2AD751E8, 0xC0F9919B, 0x65B803E5, 0x1148678C, 0xB409F5F2, 0x5E273581, 0xFB66A7FF,
184 | 0x26217BCD, 0x8360E9B3, 0x694E29C0, 0xCC0FBBBE, 0xB8FFDFD7, 0x1DBE4DA9, 0xF7908DDA, 0x52D11FA4,
185 | 0x1E704508, 0xBB31D776, 0x511F1705, 0xF45E857B, 0x80AEE112, 0x25EF736C, 0xCFC1B31F, 0x6A802161,
186 | 0x56830647, 0xF3C29439, 0x19EC544A, 0xBCADC634, 0xC85DA25D, 0x6D1C3023, 0x8732F050, 0x2273622E,
187 | 0x6ED23882, 0xCB93AAFC, 0x21BD6A8F, 0x84FCF8F1, 0xF00C9C98, 0x554D0EE6, 0xBF63CE95, 0x1A225CEB,
188 | 0x8B277743, 0x2E66E53D, 0xC448254E, 0x6109B730, 0x15F9D359, 0xB0B84127, 0x5A968154, 0xFFD7132A,
189 | 0xB3764986, 0x1637DBF8, 0xFC191B8B, 0x595889F5, 0x2DA8ED9C, 0x88E97FE2, 0x62C7BF91, 0xC7862DEF,
190 | 0xFB850AC9, 0x5EC498B7, 0xB4EA58C4, 0x11ABCABA, 0x655BAED3, 0xC01A3CAD, 0x2A34FCDE, 0x8F756EA0,
191 | 0xC3D4340C, 0x6695A672, 0x8CBB6601, 0x29FAF47F, 0x5D0A9016, 0xF84B0268, 0x1265C21B, 0xB7245065,
192 | 0x6A638C57, 0xCF221E29, 0x250CDE5A, 0x804D4C24, 0xF4BD284D, 0x51FCBA33, 0xBBD27A40, 0x1E93E83E,
193 | 0x5232B292, 0xF77320EC, 0x1D5DE09F, 0xB81C72E1, 0xCCEC1688, 0x69AD84F6, 0x83834485, 0x26C2D6FB,
194 | 0x1AC1F1DD, 0xBF8063A3, 0x55AEA3D0, 0xF0EF31AE, 0x841F55C7, 0x215EC7B9, 0xCB7007CA, 0x6E3195B4,
195 | 0x2290CF18, 0x87D15D66, 0x6DFF9D15, 0xC8BE0F6B, 0xBC4E6B02, 0x190FF97C, 0xF321390F, 0x5660AB71,
196 | 0x4C42F79A, 0xE90365E4, 0x032DA597, 0xA66C37E9, 0xD29C5380, 0x77DDC1FE, 0x9DF3018D, 0x38B293F3,
197 | 0x7413C95F, 0xD1525B21, 0x3B7C9B52, 0x9E3D092C, 0xEACD6D45, 0x4F8CFF3B, 0xA5A23F48, 0x00E3AD36,
198 | 0x3CE08A10, 0x99A1186E, 0x738FD81D, 0xD6CE4A63, 0xA23E2E0A, 0x077FBC74, 0xED517C07, 0x4810EE79,
199 | 0x04B1B4D5, 0xA1F026AB, 0x4BDEE6D8, 0xEE9F74A6, 0x9A6F10CF, 0x3F2E82B1, 0xD50042C2, 0x7041D0BC,
200 | 0xAD060C8E, 0x08479EF0, 0xE2695E83, 0x4728CCFD, 0x33D8A894, 0x96993AEA, 0x7CB7FA99, 0xD9F668E7,
201 | 0x9557324B, 0x3016A035, 0xDA386046, 0x7F79F238, 0x0B899651, 0xAEC8042F, 0x44E6C45C, 0xE1A75622,
202 | 0xDDA47104, 0x78E5E37A, 0x92CB2309, 0x378AB177, 0x437AD51E, 0xE63B4760, 0x0C158713, 0xA954156D,
203 | 0xE5F54FC1, 0x40B4DDBF, 0xAA9A1DCC, 0x0FDB8FB2, 0x7B2BEBDB, 0xDE6A79A5, 0x3444B9D6, 0x91052BA8
204 | };
205 |
206 | /*
207 | * end of the CRC lookup table crc_tableil8_o48
208 | */
209 |
210 |
211 |
212 | /*
213 | * The following CRC lookup table was generated automagically
214 | * using the following model parameters:
215 | *
216 | * Generator Polynomial = ................. 0x1EDC6F41
217 | * Generator Polynomial Length = .......... 32 bits
218 | * Reflected Bits = ....................... TRUE
219 | * Table Generation Offset = .............. 32 bits
220 | * Number of Slices = ..................... 8 slices
221 | * Slice Lengths = ........................ 8 8 8 8 8 8 8 8
222 | * Directory Name = ....................... .\
223 | * File Name = ............................ 8x256_tables.c
224 | */
225 |
226 | const uint32_t crc_tableil8_o56[256] = {
227 | 0x00000000, 0xDD45AAB8, 0xBF672381, 0x62228939, 0x7B2231F3, 0xA6679B4B, 0xC4451272, 0x1900B8CA,
228 | 0xF64463E6, 0x2B01C95E, 0x49234067, 0x9466EADF, 0x8D665215, 0x5023F8AD, 0x32017194, 0xEF44DB2C,
229 | 0xE964B13D, 0x34211B85, 0x560392BC, 0x8B463804, 0x924680CE, 0x4F032A76, 0x2D21A34F, 0xF06409F7,
230 | 0x1F20D2DB, 0xC2657863, 0xA047F15A, 0x7D025BE2, 0x6402E328, 0xB9474990, 0xDB65C0A9, 0x06206A11,
231 | 0xD725148B, 0x0A60BE33, 0x6842370A, 0xB5079DB2, 0xAC072578, 0x71428FC0, 0x136006F9, 0xCE25AC41,
232 | 0x2161776D, 0xFC24DDD5, 0x9E0654EC, 0x4343FE54, 0x5A43469E, 0x8706EC26, 0xE524651F, 0x3861CFA7,
233 | 0x3E41A5B6, 0xE3040F0E, 0x81268637, 0x5C632C8F, 0x45639445, 0x98263EFD, 0xFA04B7C4, 0x27411D7C,
234 | 0xC805C650, 0x15406CE8, 0x7762E5D1, 0xAA274F69, 0xB327F7A3, 0x6E625D1B, 0x0C40D422, 0xD1057E9A,
235 | 0xABA65FE7, 0x76E3F55F, 0x14C17C66, 0xC984D6DE, 0xD0846E14, 0x0DC1C4AC, 0x6FE34D95, 0xB2A6E72D,
236 | 0x5DE23C01, 0x80A796B9, 0xE2851F80, 0x3FC0B538, 0x26C00DF2, 0xFB85A74A, 0x99A72E73, 0x44E284CB,
237 | 0x42C2EEDA, 0x9F874462, 0xFDA5CD5B, 0x20E067E3, 0x39E0DF29, 0xE4A57591, 0x8687FCA8, 0x5BC25610,
238 | 0xB4868D3C, 0x69C32784, 0x0BE1AEBD, 0xD6A40405, 0xCFA4BCCF, 0x12E11677, 0x70C39F4E, 0xAD8635F6,
239 | 0x7C834B6C, 0xA1C6E1D4, 0xC3E468ED, 0x1EA1C255, 0x07A17A9F, 0xDAE4D027, 0xB8C6591E, 0x6583F3A6,
240 | 0x8AC7288A, 0x57828232, 0x35A00B0B, 0xE8E5A1B3, 0xF1E51979, 0x2CA0B3C1, 0x4E823AF8, 0x93C79040,
241 | 0x95E7FA51, 0x48A250E9, 0x2A80D9D0, 0xF7C57368, 0xEEC5CBA2, 0x3380611A, 0x51A2E823, 0x8CE7429B,
242 | 0x63A399B7, 0xBEE6330F, 0xDCC4BA36, 0x0181108E, 0x1881A844, 0xC5C402FC, 0xA7E68BC5, 0x7AA3217D,
243 | 0x52A0C93F, 0x8FE56387, 0xEDC7EABE, 0x30824006, 0x2982F8CC, 0xF4C75274, 0x96E5DB4D, 0x4BA071F5,
244 | 0xA4E4AAD9, 0x79A10061, 0x1B838958, 0xC6C623E0, 0xDFC69B2A, 0x02833192, 0x60A1B8AB, 0xBDE41213,
245 | 0xBBC47802, 0x6681D2BA, 0x04A35B83, 0xD9E6F13B, 0xC0E649F1, 0x1DA3E349, 0x7F816A70, 0xA2C4C0C8,
246 | 0x4D801BE4, 0x90C5B15C, 0xF2E73865, 0x2FA292DD, 0x36A22A17, 0xEBE780AF, 0x89C50996, 0x5480A32E,
247 | 0x8585DDB4, 0x58C0770C, 0x3AE2FE35, 0xE7A7548D, 0xFEA7EC47, 0x23E246FF, 0x41C0CFC6, 0x9C85657E,
248 | 0x73C1BE52, 0xAE8414EA, 0xCCA69DD3, 0x11E3376B, 0x08E38FA1, 0xD5A62519, 0xB784AC20, 0x6AC10698,
249 | 0x6CE16C89, 0xB1A4C631, 0xD3864F08, 0x0EC3E5B0, 0x17C35D7A, 0xCA86F7C2, 0xA8A47EFB, 0x75E1D443,
250 | 0x9AA50F6F, 0x47E0A5D7, 0x25C22CEE, 0xF8878656, 0xE1873E9C, 0x3CC29424, 0x5EE01D1D, 0x83A5B7A5,
251 | 0xF90696D8, 0x24433C60, 0x4661B559, 0x9B241FE1, 0x8224A72B, 0x5F610D93, 0x3D4384AA, 0xE0062E12,
252 | 0x0F42F53E, 0xD2075F86, 0xB025D6BF, 0x6D607C07, 0x7460C4CD, 0xA9256E75, 0xCB07E74C, 0x16424DF4,
253 | 0x106227E5, 0xCD278D5D, 0xAF050464, 0x7240AEDC, 0x6B401616, 0xB605BCAE, 0xD4273597, 0x09629F2F,
254 | 0xE6264403, 0x3B63EEBB, 0x59416782, 0x8404CD3A, 0x9D0475F0, 0x4041DF48, 0x22635671, 0xFF26FCC9,
255 | 0x2E238253, 0xF36628EB, 0x9144A1D2, 0x4C010B6A, 0x5501B3A0, 0x88441918, 0xEA669021, 0x37233A99,
256 | 0xD867E1B5, 0x05224B0D, 0x6700C234, 0xBA45688C, 0xA345D046, 0x7E007AFE, 0x1C22F3C7, 0xC167597F,
257 | 0xC747336E, 0x1A0299D6, 0x782010EF, 0xA565BA57, 0xBC65029D, 0x6120A825, 0x0302211C, 0xDE478BA4,
258 | 0x31035088, 0xEC46FA30, 0x8E647309, 0x5321D9B1, 0x4A21617B, 0x9764CBC3, 0xF54642FA, 0x2803E842
259 | };
260 |
261 | /*
262 | * end of the CRC lookup table crc_tableil8_o56
263 | */
264 |
265 |
266 |
267 | /*
268 | * The following CRC lookup table was generated automagically
269 | * using the following model parameters:
270 | *
271 | * Generator Polynomial = ................. 0x1EDC6F41
272 | * Generator Polynomial Length = .......... 32 bits
273 | * Reflected Bits = ....................... TRUE
274 | * Table Generation Offset = .............. 32 bits
275 | * Number of Slices = ..................... 8 slices
276 | * Slice Lengths = ........................ 8 8 8 8 8 8 8 8
277 | * Directory Name = ....................... .\
278 | * File Name = ............................ 8x256_tables.c
279 | */
280 |
281 | const uint32_t crc_tableil8_o64[256] = {
282 | 0x00000000, 0x38116FAC, 0x7022DF58, 0x4833B0F4, 0xE045BEB0, 0xD854D11C, 0x906761E8, 0xA8760E44,
283 | 0xC5670B91, 0xFD76643D, 0xB545D4C9, 0x8D54BB65, 0x2522B521, 0x1D33DA8D, 0x55006A79, 0x6D1105D5,
284 | 0x8F2261D3, 0xB7330E7F, 0xFF00BE8B, 0xC711D127, 0x6F67DF63, 0x5776B0CF, 0x1F45003B, 0x27546F97,
285 | 0x4A456A42, 0x725405EE, 0x3A67B51A, 0x0276DAB6, 0xAA00D4F2, 0x9211BB5E, 0xDA220BAA, 0xE2336406,
286 | 0x1BA8B557, 0x23B9DAFB, 0x6B8A6A0F, 0x539B05A3, 0xFBED0BE7, 0xC3FC644B, 0x8BCFD4BF, 0xB3DEBB13,
287 | 0xDECFBEC6, 0xE6DED16A, 0xAEED619E, 0x96FC0E32, 0x3E8A0076, 0x069B6FDA, 0x4EA8DF2E, 0x76B9B082,
288 | 0x948AD484, 0xAC9BBB28, 0xE4A80BDC, 0xDCB96470, 0x74CF6A34, 0x4CDE0598, 0x04EDB56C, 0x3CFCDAC0,
289 | 0x51EDDF15, 0x69FCB0B9, 0x21CF004D, 0x19DE6FE1, 0xB1A861A5, 0x89B90E09, 0xC18ABEFD, 0xF99BD151,
290 | 0x37516AAE, 0x0F400502, 0x4773B5F6, 0x7F62DA5A, 0xD714D41E, 0xEF05BBB2, 0xA7360B46, 0x9F2764EA,
291 | 0xF236613F, 0xCA270E93, 0x8214BE67, 0xBA05D1CB, 0x1273DF8F, 0x2A62B023, 0x625100D7, 0x5A406F7B,
292 | 0xB8730B7D, 0x806264D1, 0xC851D425, 0xF040BB89, 0x5836B5CD, 0x6027DA61, 0x28146A95, 0x10050539,
293 | 0x7D1400EC, 0x45056F40, 0x0D36DFB4, 0x3527B018, 0x9D51BE5C, 0xA540D1F0, 0xED736104, 0xD5620EA8,
294 | 0x2CF9DFF9, 0x14E8B055, 0x5CDB00A1, 0x64CA6F0D, 0xCCBC6149, 0xF4AD0EE5, 0xBC9EBE11, 0x848FD1BD,
295 | 0xE99ED468, 0xD18FBBC4, 0x99BC0B30, 0xA1AD649C, 0x09DB6AD8, 0x31CA0574, 0x79F9B580, 0x41E8DA2C,
296 | 0xA3DBBE2A, 0x9BCAD186, 0xD3F96172, 0xEBE80EDE, 0x439E009A, 0x7B8F6F36, 0x33BCDFC2, 0x0BADB06E,
297 | 0x66BCB5BB, 0x5EADDA17, 0x169E6AE3, 0x2E8F054F, 0x86F90B0B, 0xBEE864A7, 0xF6DBD453, 0xCECABBFF,
298 | 0x6EA2D55C, 0x56B3BAF0, 0x1E800A04, 0x269165A8, 0x8EE76BEC, 0xB6F60440, 0xFEC5B4B4, 0xC6D4DB18,
299 | 0xABC5DECD, 0x93D4B161, 0xDBE70195, 0xE3F66E39, 0x4B80607D, 0x73910FD1, 0x3BA2BF25, 0x03B3D089,
300 | 0xE180B48F, 0xD991DB23, 0x91A26BD7, 0xA9B3047B, 0x01C50A3F, 0x39D46593, 0x71E7D567, 0x49F6BACB,
301 | 0x24E7BF1E, 0x1CF6D0B2, 0x54C56046, 0x6CD40FEA, 0xC4A201AE, 0xFCB36E02, 0xB480DEF6, 0x8C91B15A,
302 | 0x750A600B, 0x4D1B0FA7, 0x0528BF53, 0x3D39D0FF, 0x954FDEBB, 0xAD5EB117, 0xE56D01E3, 0xDD7C6E4F,
303 | 0xB06D6B9A, 0x887C0436, 0xC04FB4C2, 0xF85EDB6E, 0x5028D52A, 0x6839BA86, 0x200A0A72, 0x181B65DE,
304 | 0xFA2801D8, 0xC2396E74, 0x8A0ADE80, 0xB21BB12C, 0x1A6DBF68, 0x227CD0C4, 0x6A4F6030, 0x525E0F9C,
305 | 0x3F4F0A49, 0x075E65E5, 0x4F6DD511, 0x777CBABD, 0xDF0AB4F9, 0xE71BDB55, 0xAF286BA1, 0x9739040D,
306 | 0x59F3BFF2, 0x61E2D05E, 0x29D160AA, 0x11C00F06, 0xB9B60142, 0x81A76EEE, 0xC994DE1A, 0xF185B1B6,
307 | 0x9C94B463, 0xA485DBCF, 0xECB66B3B, 0xD4A70497, 0x7CD10AD3, 0x44C0657F, 0x0CF3D58B, 0x34E2BA27,
308 | 0xD6D1DE21, 0xEEC0B18D, 0xA6F30179, 0x9EE26ED5, 0x36946091, 0x0E850F3D, 0x46B6BFC9, 0x7EA7D065,
309 | 0x13B6D5B0, 0x2BA7BA1C, 0x63940AE8, 0x5B856544, 0xF3F36B00, 0xCBE204AC, 0x83D1B458, 0xBBC0DBF4,
310 | 0x425B0AA5, 0x7A4A6509, 0x3279D5FD, 0x0A68BA51, 0xA21EB415, 0x9A0FDBB9, 0xD23C6B4D, 0xEA2D04E1,
311 | 0x873C0134, 0xBF2D6E98, 0xF71EDE6C, 0xCF0FB1C0, 0x6779BF84, 0x5F68D028, 0x175B60DC, 0x2F4A0F70,
312 | 0xCD796B76, 0xF56804DA, 0xBD5BB42E, 0x854ADB82, 0x2D3CD5C6, 0x152DBA6A, 0x5D1E0A9E, 0x650F6532,
313 | 0x081E60E7, 0x300F0F4B, 0x783CBFBF, 0x402DD013, 0xE85BDE57, 0xD04AB1FB, 0x9879010F, 0xA0686EA3
314 | };
315 |
316 | /*
317 | * end of the CRC lookup table crc_tableil8_o64
318 | */
319 |
320 |
321 |
322 | /*
323 | * The following CRC lookup table was generated automagically
324 | * using the following model parameters:
325 | *
326 | * Generator Polynomial = ................. 0x1EDC6F41
327 | * Generator Polynomial Length = .......... 32 bits
328 | * Reflected Bits = ....................... TRUE
329 | * Table Generation Offset = .............. 32 bits
330 | * Number of Slices = ..................... 8 slices
331 | * Slice Lengths = ........................ 8 8 8 8 8 8 8 8
332 | * Directory Name = ....................... .\
333 | * File Name = ............................ 8x256_tables.c
334 | */
335 |
336 | const uint32_t crc_tableil8_o72[256] = {
337 | 0x00000000, 0xEF306B19, 0xDB8CA0C3, 0x34BCCBDA, 0xB2F53777, 0x5DC55C6E, 0x697997B4, 0x8649FCAD,
338 | 0x6006181F, 0x8F367306, 0xBB8AB8DC, 0x54BAD3C5, 0xD2F32F68, 0x3DC34471, 0x097F8FAB, 0xE64FE4B2,
339 | 0xC00C303E, 0x2F3C5B27, 0x1B8090FD, 0xF4B0FBE4, 0x72F90749, 0x9DC96C50, 0xA975A78A, 0x4645CC93,
340 | 0xA00A2821, 0x4F3A4338, 0x7B8688E2, 0x94B6E3FB, 0x12FF1F56, 0xFDCF744F, 0xC973BF95, 0x2643D48C,
341 | 0x85F4168D, 0x6AC47D94, 0x5E78B64E, 0xB148DD57, 0x370121FA, 0xD8314AE3, 0xEC8D8139, 0x03BDEA20,
342 | 0xE5F20E92, 0x0AC2658B, 0x3E7EAE51, 0xD14EC548, 0x570739E5, 0xB83752FC, 0x8C8B9926, 0x63BBF23F,
343 | 0x45F826B3, 0xAAC84DAA, 0x9E748670, 0x7144ED69, 0xF70D11C4, 0x183D7ADD, 0x2C81B107, 0xC3B1DA1E,
344 | 0x25FE3EAC, 0xCACE55B5, 0xFE729E6F, 0x1142F576, 0x970B09DB, 0x783B62C2, 0x4C87A918, 0xA3B7C201,
345 | 0x0E045BEB, 0xE13430F2, 0xD588FB28, 0x3AB89031, 0xBCF16C9C, 0x53C10785, 0x677DCC5F, 0x884DA746,
346 | 0x6E0243F4, 0x813228ED, 0xB58EE337, 0x5ABE882E, 0xDCF77483, 0x33C71F9A, 0x077BD440, 0xE84BBF59,
347 | 0xCE086BD5, 0x213800CC, 0x1584CB16, 0xFAB4A00F, 0x7CFD5CA2, 0x93CD37BB, 0xA771FC61, 0x48419778,
348 | 0xAE0E73CA, 0x413E18D3, 0x7582D309, 0x9AB2B810, 0x1CFB44BD, 0xF3CB2FA4, 0xC777E47E, 0x28478F67,
349 | 0x8BF04D66, 0x64C0267F, 0x507CEDA5, 0xBF4C86BC, 0x39057A11, 0xD6351108, 0xE289DAD2, 0x0DB9B1CB,
350 | 0xEBF65579, 0x04C63E60, 0x307AF5BA, 0xDF4A9EA3, 0x5903620E, 0xB6330917, 0x828FC2CD, 0x6DBFA9D4,
351 | 0x4BFC7D58, 0xA4CC1641, 0x9070DD9B, 0x7F40B682, 0xF9094A2F, 0x16392136, 0x2285EAEC, 0xCDB581F5,
352 | 0x2BFA6547, 0xC4CA0E5E, 0xF076C584, 0x1F46AE9D, 0x990F5230, 0x763F3929, 0x4283F2F3, 0xADB399EA,
353 | 0x1C08B7D6, 0xF338DCCF, 0xC7841715, 0x28B47C0C, 0xAEFD80A1, 0x41CDEBB8, 0x75712062, 0x9A414B7B,
354 | 0x7C0EAFC9, 0x933EC4D0, 0xA7820F0A, 0x48B26413, 0xCEFB98BE, 0x21CBF3A7, 0x1577387D, 0xFA475364,
355 | 0xDC0487E8, 0x3334ECF1, 0x0788272B, 0xE8B84C32, 0x6EF1B09F, 0x81C1DB86, 0xB57D105C, 0x5A4D7B45,
356 | 0xBC029FF7, 0x5332F4EE, 0x678E3F34, 0x88BE542D, 0x0EF7A880, 0xE1C7C399, 0xD57B0843, 0x3A4B635A,
357 | 0x99FCA15B, 0x76CCCA42, 0x42700198, 0xAD406A81, 0x2B09962C, 0xC439FD35, 0xF08536EF, 0x1FB55DF6,
358 | 0xF9FAB944, 0x16CAD25D, 0x22761987, 0xCD46729E, 0x4B0F8E33, 0xA43FE52A, 0x90832EF0, 0x7FB345E9,
359 | 0x59F09165, 0xB6C0FA7C, 0x827C31A6, 0x6D4C5ABF, 0xEB05A612, 0x0435CD0B, 0x308906D1, 0xDFB96DC8,
360 | 0x39F6897A, 0xD6C6E263, 0xE27A29B9, 0x0D4A42A0, 0x8B03BE0D, 0x6433D514, 0x508F1ECE, 0xBFBF75D7,
361 | 0x120CEC3D, 0xFD3C8724, 0xC9804CFE, 0x26B027E7, 0xA0F9DB4A, 0x4FC9B053, 0x7B757B89, 0x94451090,
362 | 0x720AF422, 0x9D3A9F3B, 0xA98654E1, 0x46B63FF8, 0xC0FFC355, 0x2FCFA84C, 0x1B736396, 0xF443088F,
363 | 0xD200DC03, 0x3D30B71A, 0x098C7CC0, 0xE6BC17D9, 0x60F5EB74, 0x8FC5806D, 0xBB794BB7, 0x544920AE,
364 | 0xB206C41C, 0x5D36AF05, 0x698A64DF, 0x86BA0FC6, 0x00F3F36B, 0xEFC39872, 0xDB7F53A8, 0x344F38B1,
365 | 0x97F8FAB0, 0x78C891A9, 0x4C745A73, 0xA344316A, 0x250DCDC7, 0xCA3DA6DE, 0xFE816D04, 0x11B1061D,
366 | 0xF7FEE2AF, 0x18CE89B6, 0x2C72426C, 0xC3422975, 0x450BD5D8, 0xAA3BBEC1, 0x9E87751B, 0x71B71E02,
367 | 0x57F4CA8E, 0xB8C4A197, 0x8C786A4D, 0x63480154, 0xE501FDF9, 0x0A3196E0, 0x3E8D5D3A, 0xD1BD3623,
368 | 0x37F2D291, 0xD8C2B988, 0xEC7E7252, 0x034E194B, 0x8507E5E6, 0x6A378EFF, 0x5E8B4525, 0xB1BB2E3C
369 | };
370 |
371 | /*
372 | * end of the CRC lookup table crc_tableil8_o72
373 | */
374 |
375 |
376 |
377 | /*
378 | * The following CRC lookup table was generated automagically
379 | * using the following model parameters:
380 | *
381 | * Generator Polynomial = ................. 0x1EDC6F41
382 | * Generator Polynomial Length = .......... 32 bits
383 | * Reflected Bits = ....................... TRUE
384 | * Table Generation Offset = .............. 32 bits
385 | * Number of Slices = ..................... 8 slices
386 | * Slice Lengths = ........................ 8 8 8 8 8 8 8 8
387 | * Directory Name = ....................... .\
388 | * File Name = ............................ 8x256_tables.c
389 | */
390 |
391 | const uint32_t crc_tableil8_o80[256] = {
392 | 0x00000000, 0x68032CC8, 0xD0065990, 0xB8057558, 0xA5E0C5D1, 0xCDE3E919, 0x75E69C41, 0x1DE5B089,
393 | 0x4E2DFD53, 0x262ED19B, 0x9E2BA4C3, 0xF628880B, 0xEBCD3882, 0x83CE144A, 0x3BCB6112, 0x53C84DDA,
394 | 0x9C5BFAA6, 0xF458D66E, 0x4C5DA336, 0x245E8FFE, 0x39BB3F77, 0x51B813BF, 0xE9BD66E7, 0x81BE4A2F,
395 | 0xD27607F5, 0xBA752B3D, 0x02705E65, 0x6A7372AD, 0x7796C224, 0x1F95EEEC, 0xA7909BB4, 0xCF93B77C,
396 | 0x3D5B83BD, 0x5558AF75, 0xED5DDA2D, 0x855EF6E5, 0x98BB466C, 0xF0B86AA4, 0x48BD1FFC, 0x20BE3334,
397 | 0x73767EEE, 0x1B755226, 0xA370277E, 0xCB730BB6, 0xD696BB3F, 0xBE9597F7, 0x0690E2AF, 0x6E93CE67,
398 | 0xA100791B, 0xC90355D3, 0x7106208B, 0x19050C43, 0x04E0BCCA, 0x6CE39002, 0xD4E6E55A, 0xBCE5C992,
399 | 0xEF2D8448, 0x872EA880, 0x3F2BDDD8, 0x5728F110, 0x4ACD4199, 0x22CE6D51, 0x9ACB1809, 0xF2C834C1,
400 | 0x7AB7077A, 0x12B42BB2, 0xAAB15EEA, 0xC2B27222, 0xDF57C2AB, 0xB754EE63, 0x0F519B3B, 0x6752B7F3,
401 | 0x349AFA29, 0x5C99D6E1, 0xE49CA3B9, 0x8C9F8F71, 0x917A3FF8, 0xF9791330, 0x417C6668, 0x297F4AA0,
402 | 0xE6ECFDDC, 0x8EEFD114, 0x36EAA44C, 0x5EE98884, 0x430C380D, 0x2B0F14C5, 0x930A619D, 0xFB094D55,
403 | 0xA8C1008F, 0xC0C22C47, 0x78C7591F, 0x10C475D7, 0x0D21C55E, 0x6522E996, 0xDD279CCE, 0xB524B006,
404 | 0x47EC84C7, 0x2FEFA80F, 0x97EADD57, 0xFFE9F19F, 0xE20C4116, 0x8A0F6DDE, 0x320A1886, 0x5A09344E,
405 | 0x09C17994, 0x61C2555C, 0xD9C72004, 0xB1C40CCC, 0xAC21BC45, 0xC422908D, 0x7C27E5D5, 0x1424C91D,
406 | 0xDBB77E61, 0xB3B452A9, 0x0BB127F1, 0x63B20B39, 0x7E57BBB0, 0x16549778, 0xAE51E220, 0xC652CEE8,
407 | 0x959A8332, 0xFD99AFFA, 0x459CDAA2, 0x2D9FF66A, 0x307A46E3, 0x58796A2B, 0xE07C1F73, 0x887F33BB,
408 | 0xF56E0EF4, 0x9D6D223C, 0x25685764, 0x4D6B7BAC, 0x508ECB25, 0x388DE7ED, 0x808892B5, 0xE88BBE7D,
409 | 0xBB43F3A7, 0xD340DF6F, 0x6B45AA37, 0x034686FF, 0x1EA33676, 0x76A01ABE, 0xCEA56FE6, 0xA6A6432E,
410 | 0x6935F452, 0x0136D89A, 0xB933ADC2, 0xD130810A, 0xCCD53183, 0xA4D61D4B, 0x1CD36813, 0x74D044DB,
411 | 0x27180901, 0x4F1B25C9, 0xF71E5091, 0x9F1D7C59, 0x82F8CCD0, 0xEAFBE018, 0x52FE9540, 0x3AFDB988,
412 | 0xC8358D49, 0xA036A181, 0x1833D4D9, 0x7030F811, 0x6DD54898, 0x05D66450, 0xBDD31108, 0xD5D03DC0,
413 | 0x8618701A, 0xEE1B5CD2, 0x561E298A, 0x3E1D0542, 0x23F8B5CB, 0x4BFB9903, 0xF3FEEC5B, 0x9BFDC093,
414 | 0x546E77EF, 0x3C6D5B27, 0x84682E7F, 0xEC6B02B7, 0xF18EB23E, 0x998D9EF6, 0x2188EBAE, 0x498BC766,
415 | 0x1A438ABC, 0x7240A674, 0xCA45D32C, 0xA246FFE4, 0xBFA34F6D, 0xD7A063A5, 0x6FA516FD, 0x07A63A35,
416 | 0x8FD9098E, 0xE7DA2546, 0x5FDF501E, 0x37DC7CD6, 0x2A39CC5F, 0x423AE097, 0xFA3F95CF, 0x923CB907,
417 | 0xC1F4F4DD, 0xA9F7D815, 0x11F2AD4D, 0x79F18185, 0x6414310C, 0x0C171DC4, 0xB412689C, 0xDC114454,
418 | 0x1382F328, 0x7B81DFE0, 0xC384AAB8, 0xAB878670, 0xB66236F9, 0xDE611A31, 0x66646F69, 0x0E6743A1,
419 | 0x5DAF0E7B, 0x35AC22B3, 0x8DA957EB, 0xE5AA7B23, 0xF84FCBAA, 0x904CE762, 0x2849923A, 0x404ABEF2,
420 | 0xB2828A33, 0xDA81A6FB, 0x6284D3A3, 0x0A87FF6B, 0x17624FE2, 0x7F61632A, 0xC7641672, 0xAF673ABA,
421 | 0xFCAF7760, 0x94AC5BA8, 0x2CA92EF0, 0x44AA0238, 0x594FB2B1, 0x314C9E79, 0x8949EB21, 0xE14AC7E9,
422 | 0x2ED97095, 0x46DA5C5D, 0xFEDF2905, 0x96DC05CD, 0x8B39B544, 0xE33A998C, 0x5B3FECD4, 0x333CC01C,
423 | 0x60F48DC6, 0x08F7A10E, 0xB0F2D456, 0xD8F1F89E, 0xC5144817, 0xAD1764DF, 0x15121187, 0x7D113D4F
424 | };
425 |
426 | /*
427 | * end of the CRC lookup table crc_tableil8_o80
428 | */
429 |
430 |
431 |
432 | /*
433 | * The following CRC lookup table was generated automagically
434 | * using the following model parameters:
435 | *
436 | * Generator Polynomial = ................. 0x1EDC6F41
437 | * Generator Polynomial Length = .......... 32 bits
438 | * Reflected Bits = ....................... TRUE
439 | * Table Generation Offset = .............. 32 bits
440 | * Number of Slices = ..................... 8 slices
441 | * Slice Lengths = ........................ 8 8 8 8 8 8 8 8
442 | * Directory Name = ....................... .\
443 | * File Name = ............................ 8x256_tables.c
444 | */
445 |
446 | const uint32_t crc_tableil8_o88[256] = {
447 | 0x00000000, 0x493C7D27, 0x9278FA4E, 0xDB448769, 0x211D826D, 0x6821FF4A, 0xB3657823, 0xFA590504,
448 | 0x423B04DA, 0x0B0779FD, 0xD043FE94, 0x997F83B3, 0x632686B7, 0x2A1AFB90, 0xF15E7CF9, 0xB86201DE,
449 | 0x847609B4, 0xCD4A7493, 0x160EF3FA, 0x5F328EDD, 0xA56B8BD9, 0xEC57F6FE, 0x37137197, 0x7E2F0CB0,
450 | 0xC64D0D6E, 0x8F717049, 0x5435F720, 0x1D098A07, 0xE7508F03, 0xAE6CF224, 0x7528754D, 0x3C14086A,
451 | 0x0D006599, 0x443C18BE, 0x9F789FD7, 0xD644E2F0, 0x2C1DE7F4, 0x65219AD3, 0xBE651DBA, 0xF759609D,
452 | 0x4F3B6143, 0x06071C64, 0xDD439B0D, 0x947FE62A, 0x6E26E32E, 0x271A9E09, 0xFC5E1960, 0xB5626447,
453 | 0x89766C2D, 0xC04A110A, 0x1B0E9663, 0x5232EB44, 0xA86BEE40, 0xE1579367, 0x3A13140E, 0x732F6929,
454 | 0xCB4D68F7, 0x827115D0, 0x593592B9, 0x1009EF9E, 0xEA50EA9A, 0xA36C97BD, 0x782810D4, 0x31146DF3,
455 | 0x1A00CB32, 0x533CB615, 0x8878317C, 0xC1444C5B, 0x3B1D495F, 0x72213478, 0xA965B311, 0xE059CE36,
456 | 0x583BCFE8, 0x1107B2CF, 0xCA4335A6, 0x837F4881, 0x79264D85, 0x301A30A2, 0xEB5EB7CB, 0xA262CAEC,
457 | 0x9E76C286, 0xD74ABFA1, 0x0C0E38C8, 0x453245EF, 0xBF6B40EB, 0xF6573DCC, 0x2D13BAA5, 0x642FC782,
458 | 0xDC4DC65C, 0x9571BB7B, 0x4E353C12, 0x07094135, 0xFD504431, 0xB46C3916, 0x6F28BE7F, 0x2614C358,
459 | 0x1700AEAB, 0x5E3CD38C, 0x857854E5, 0xCC4429C2, 0x361D2CC6, 0x7F2151E1, 0xA465D688, 0xED59ABAF,
460 | 0x553BAA71, 0x1C07D756, 0xC743503F, 0x8E7F2D18, 0x7426281C, 0x3D1A553B, 0xE65ED252, 0xAF62AF75,
461 | 0x9376A71F, 0xDA4ADA38, 0x010E5D51, 0x48322076, 0xB26B2572, 0xFB575855, 0x2013DF3C, 0x692FA21B,
462 | 0xD14DA3C5, 0x9871DEE2, 0x4335598B, 0x0A0924AC, 0xF05021A8, 0xB96C5C8F, 0x6228DBE6, 0x2B14A6C1,
463 | 0x34019664, 0x7D3DEB43, 0xA6796C2A, 0xEF45110D, 0x151C1409, 0x5C20692E, 0x8764EE47, 0xCE589360,
464 | 0x763A92BE, 0x3F06EF99, 0xE44268F0, 0xAD7E15D7, 0x572710D3, 0x1E1B6DF4, 0xC55FEA9D, 0x8C6397BA,
465 | 0xB0779FD0, 0xF94BE2F7, 0x220F659E, 0x6B3318B9, 0x916A1DBD, 0xD856609A, 0x0312E7F3, 0x4A2E9AD4,
466 | 0xF24C9B0A, 0xBB70E62D, 0x60346144, 0x29081C63, 0xD3511967, 0x9A6D6440, 0x4129E329, 0x08159E0E,
467 | 0x3901F3FD, 0x703D8EDA, 0xAB7909B3, 0xE2457494, 0x181C7190, 0x51200CB7, 0x8A648BDE, 0xC358F6F9,
468 | 0x7B3AF727, 0x32068A00, 0xE9420D69, 0xA07E704E, 0x5A27754A, 0x131B086D, 0xC85F8F04, 0x8163F223,
469 | 0xBD77FA49, 0xF44B876E, 0x2F0F0007, 0x66337D20, 0x9C6A7824, 0xD5560503, 0x0E12826A, 0x472EFF4D,
470 | 0xFF4CFE93, 0xB67083B4, 0x6D3404DD, 0x240879FA, 0xDE517CFE, 0x976D01D9, 0x4C2986B0, 0x0515FB97,
471 | 0x2E015D56, 0x673D2071, 0xBC79A718, 0xF545DA3F, 0x0F1CDF3B, 0x4620A21C, 0x9D642575, 0xD4585852,
472 | 0x6C3A598C, 0x250624AB, 0xFE42A3C2, 0xB77EDEE5, 0x4D27DBE1, 0x041BA6C6, 0xDF5F21AF, 0x96635C88,
473 | 0xAA7754E2, 0xE34B29C5, 0x380FAEAC, 0x7133D38B, 0x8B6AD68F, 0xC256ABA8, 0x19122CC1, 0x502E51E6,
474 | 0xE84C5038, 0xA1702D1F, 0x7A34AA76, 0x3308D751, 0xC951D255, 0x806DAF72, 0x5B29281B, 0x1215553C,
475 | 0x230138CF, 0x6A3D45E8, 0xB179C281, 0xF845BFA6, 0x021CBAA2, 0x4B20C785, 0x906440EC, 0xD9583DCB,
476 | 0x613A3C15, 0x28064132, 0xF342C65B, 0xBA7EBB7C, 0x4027BE78, 0x091BC35F, 0xD25F4436, 0x9B633911,
477 | 0xA777317B, 0xEE4B4C5C, 0x350FCB35, 0x7C33B612, 0x866AB316, 0xCF56CE31, 0x14124958, 0x5D2E347F,
478 | 0xE54C35A1, 0xAC704886, 0x7734CFEF, 0x3E08B2C8, 0xC451B7CC, 0x8D6DCAEB, 0x56294D82, 0x1F1530A5
479 | };
480 |
481 | /*
482 | * end of the CRC lookup table crc_tableil8_o88
483 | */
484 |
485 | } // namespace logging
486 | // kate: indent-mode cstyle; indent-width 8; replace-tabs on;
487 |
--------------------------------------------------------------------------------
/crc32c/crc32intelasm.cc:
--------------------------------------------------------------------------------
1 | // All rights reserved. Use of this source code is governed by a
2 | // BSD-style license that can be found in the LICENSE file.
3 |
4 | // Implementations adapted from Intel's Slicing By 8 Sourceforge Project
5 | // http://sourceforge.net/projects/slicing-by-8/
6 | /*
7 | * Copyright 2016 Ferry Toth, Exalon Delft BV, The Netherlands
8 | *
9 | *
10 | * This software program is licensed subject to the BSD License,
11 | * available at http://www.opensource.org/licenses/bsd-license.html.
12 | *
13 | * Abstract:
14 | *
15 | * This file is just a C wrapper around Intels assembly optimized crc_pcl
16 | */
17 |
18 | #include "logging/crc32c.h"
19 |
20 | namespace logging
21 | {
22 | extern "C" unsigned int crc_pcl ( unsigned char * buffer, int len, unsigned int crc_init );
23 |
24 | uint32_t crc32cIntelAsm ( uint32_t crc, const void *buf, size_t len )
25 | {
26 | return ( unsigned int ) crc_pcl ( ( unsigned char * ) buf, ( int ) len, ( unsigned int ) crc );
27 | }
28 | }
29 | // kate: indent-mode cstyle; indent-width 8; replace-tabs on;
30 |
--------------------------------------------------------------------------------
/crc32c/crc32intelc.cc:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Ferry Toth, Exalon Delft BV, The Netherlands
2 | /*
3 | This software is provided 'as-is', without any express or implied
4 | warranty. In no event will the author be held liable for any damages
5 | arising from the use of this software.
6 |
7 | Permission is granted to anyone to use this software for any purpose,
8 | including commercial applications, and to alter it and redistribute it
9 | freely, subject to the following restrictions:
10 |
11 | 1. The origin of this software must not be misrepresented; you must not
12 | claim that you wrote the original software. If you use this software
13 | in a product, an acknowledgment in the product documentation would be
14 | appreciated but is not required.
15 | 2. Altered source versions must be plainly marked as such, and must not be
16 | misrepresented as being the original software.
17 | 3. This notice may not be removed or altered from any source distribution.
18 |
19 | Ferry Toth
20 | ftoth@exalondelft.nl
21 | */
22 |
23 | /* Use hardware CRC instruction on Intel SSE 4.2 processors. This computes a
24 | CRC-32C, *not* the CRC-32 used by Ethernet and zip, gzip, etc. Where efficient
25 | 3 crc32q instructions are used which a single core can execute in parallel.
26 | This compensates for the latency of a single crc32q instruction. Combining the
27 | 3 CRC-32C bytes is done using the pclmulqdq instruction, which has overhead of
28 | its own, and makes this code path only efficient for buffer sizes above 216 bytes.
29 | All code requiring a crc32q instruction is done inside a macro, for which alternative
30 | code is generated in case of a 32 bit platform.
31 |
32 | This code is a port of Intels crc_iscsi_v_pcl.asm assembly code (which is part of
33 | this project as well as in a modified form the linux kernel) and reaches the same
34 | throughput on 64bit platforms. The main advantage of this port is that it was
35 | relatively easy to port to 32bit platforms (like Intel Edison which currently has
36 | only 32bit support). Being written in C it is of course easier to maintain and possibly
37 | optimize further */
38 |
39 | /* Version history:
40 | 1.0 07 May 2016 Ferry Toth - First version
41 | */
42 |
43 | #include "logging/crc32c.h"
44 | #include "logging/crc32intelc.h"
45 | #include
46 |
47 | namespace logging
48 | {
49 |
50 | extern __v2di K[];
51 |
52 | /* Compute CRC-32C using the Intel hardware instruction. */
53 | uint32_t crc32cIntelC ( uint32_t crc, const void *buf, size_t len )
54 | {
55 | const unsigned char *next = ( const unsigned char * ) buf;
56 | unsigned long count;
57 | CRC_NATIVE crc0, crc1, crc2;
58 | crc0 = crc;
59 |
60 | if ( len >= 8 ) {
61 | // if len > 216 then align and use triplets
62 | if ( len > 216 ) {
63 | {
64 | uint32_t crc32bit = crc0; // create this block actually prevent 2 asignments
65 | unsigned long align = ( 8 - ( uintptr_t ) next ) % 8; // byte to boundary
66 | len -= align;
67 | if ( align & 0x04 ) {
68 | crc32bit = __builtin_ia32_crc32si ( crc32bit, * ( uint32_t* ) next );
69 | next += sizeof(uint32_t);
70 | };
71 | if ( align & 0x02 ) {
72 | crc32bit = __builtin_ia32_crc32hi ( crc32bit, * ( uint16_t* ) next );
73 | next += sizeof(uint16_t);
74 | };
75 |
76 | if ( align & 0x01 ) {
77 | crc32bit = __builtin_ia32_crc32qi ( crc32bit, * ( next ) );
78 | next++;
79 | };
80 | crc0 = crc32bit;
81 | };
82 |
83 | // use Duff's device, a for() loop inside a switch() statement. This is Legal
84 | // needs to execute at least once, round len down to nearast triplet multiple
85 | count = len / 24; // number of triplets
86 | len %= 24; // bytes remaining
87 | unsigned long n = count / 128; // #blocks = first block + full blocks
88 | unsigned long block_size = count % 128;
89 | if ( block_size == 0 ) {
90 | block_size = 128;
91 | } else {
92 | n++;
93 | };
94 | const uint64_t *next0 = ( uint64_t* ) next + block_size; // points to the first byte of the next block
95 | const uint64_t *next1 = next0 + block_size;
96 | const uint64_t *next2 = next1 + block_size;
97 |
98 | crc1 = crc2 = 0;
99 | switch ( block_size ) {
100 | case 128:
101 | do {
102 | CRCtriplet ( crc, next, -128 ); // jumps here for a full block of len 128
103 | case 127:
104 | CRCtriplet ( crc, next, -127 ); // jumps here or below for the first block smaller
105 | case 126:
106 | CRCtriplet ( crc, next, -126 ); // than 128
107 | case 125:
108 | CRCtriplet ( crc, next, -125 );
109 | case 124:
110 | CRCtriplet ( crc, next, -124 );
111 | case 123:
112 | CRCtriplet ( crc, next, -123 );
113 | case 122:
114 | CRCtriplet ( crc, next, -122 );
115 | case 121:
116 | CRCtriplet ( crc, next, -121 );
117 | case 120:
118 | CRCtriplet ( crc, next, -120 );
119 | case 119:
120 | CRCtriplet ( crc, next, -119 );
121 | case 118:
122 | CRCtriplet ( crc, next, -118 );
123 | case 117:
124 | CRCtriplet ( crc, next, -117 );
125 | case 116:
126 | CRCtriplet ( crc, next, -116 );
127 | case 115:
128 | CRCtriplet ( crc, next, -115 );
129 | case 114:
130 | CRCtriplet ( crc, next, -114 );
131 | case 113:
132 | CRCtriplet ( crc, next, -113 );
133 | case 112:
134 | CRCtriplet ( crc, next, -112 );
135 | case 111:
136 | CRCtriplet ( crc, next, -111 );
137 | case 110:
138 | CRCtriplet ( crc, next, -110 );
139 | case 109:
140 | CRCtriplet ( crc, next, -109 );
141 | case 108:
142 | CRCtriplet ( crc, next, -108 );
143 | case 107:
144 | CRCtriplet ( crc, next, -107 );
145 | case 106:
146 | CRCtriplet ( crc, next, -106 );
147 | case 105:
148 | CRCtriplet ( crc, next, -105 );
149 | case 104:
150 | CRCtriplet ( crc, next, -104 );
151 | case 103:
152 | CRCtriplet ( crc, next, -103 );
153 | case 102:
154 | CRCtriplet ( crc, next, -102 );
155 | case 101:
156 | CRCtriplet ( crc, next, -101 );
157 | case 100:
158 | CRCtriplet ( crc, next, -100 );
159 | case 99:
160 | CRCtriplet ( crc, next, -99 );
161 | case 98:
162 | CRCtriplet ( crc, next, -98 );
163 | case 97:
164 | CRCtriplet ( crc, next, -97 );
165 | case 96:
166 | CRCtriplet ( crc, next, -96 );
167 | case 95:
168 | CRCtriplet ( crc, next, -95 );
169 | case 94:
170 | CRCtriplet ( crc, next, -94 );
171 | case 93:
172 | CRCtriplet ( crc, next, -93 );
173 | case 92:
174 | CRCtriplet ( crc, next, -92 );
175 | case 91:
176 | CRCtriplet ( crc, next, -91 );
177 | case 90:
178 | CRCtriplet ( crc, next, -90 );
179 | case 89:
180 | CRCtriplet ( crc, next, -89 );
181 | case 88:
182 | CRCtriplet ( crc, next, -88 );
183 | case 87:
184 | CRCtriplet ( crc, next, -87 );
185 | case 86:
186 | CRCtriplet ( crc, next, -86 );
187 | case 85:
188 | CRCtriplet ( crc, next, -85 );
189 | case 84:
190 | CRCtriplet ( crc, next, -84 );
191 | case 83:
192 | CRCtriplet ( crc, next, -83 );
193 | case 82:
194 | CRCtriplet ( crc, next, -82 );
195 | case 81:
196 | CRCtriplet ( crc, next, -81 );
197 | case 80:
198 | CRCtriplet ( crc, next, -80 );
199 | case 79:
200 | CRCtriplet ( crc, next, -79 );
201 | case 78:
202 | CRCtriplet ( crc, next, -78 );
203 | case 77:
204 | CRCtriplet ( crc, next, -77 );
205 | case 76:
206 | CRCtriplet ( crc, next, -76 );
207 | case 75:
208 | CRCtriplet ( crc, next, -75 );
209 | case 74:
210 | CRCtriplet ( crc, next, -74 );
211 | case 73:
212 | CRCtriplet ( crc, next, -73 );
213 | case 72:
214 | CRCtriplet ( crc, next, -72 );
215 | case 71:
216 | CRCtriplet ( crc, next, -71 );
217 | case 70:
218 | CRCtriplet ( crc, next, -70 );
219 | case 69:
220 | CRCtriplet ( crc, next, -69 );
221 | case 68:
222 | CRCtriplet ( crc, next, -68 );
223 | case 67:
224 | CRCtriplet ( crc, next, -67 );
225 | case 66:
226 | CRCtriplet ( crc, next, -66 );
227 | case 65:
228 | CRCtriplet ( crc, next, -65 );
229 | case 64:
230 | CRCtriplet ( crc, next, -64 );
231 | case 63:
232 | CRCtriplet ( crc, next, -63 );
233 | case 62:
234 | CRCtriplet ( crc, next, -62 );
235 | case 61:
236 | CRCtriplet ( crc, next, -61 );
237 | case 60:
238 | CRCtriplet ( crc, next, -60 );
239 | case 59:
240 | CRCtriplet ( crc, next, -59 );
241 | case 58:
242 | CRCtriplet ( crc, next, -58 );
243 | case 57:
244 | CRCtriplet ( crc, next, -57 );
245 | case 56:
246 | CRCtriplet ( crc, next, -56 );
247 | case 55:
248 | CRCtriplet ( crc, next, -55 );
249 | case 54:
250 | CRCtriplet ( crc, next, -54 );
251 | case 53:
252 | CRCtriplet ( crc, next, -53 );
253 | case 52:
254 | CRCtriplet ( crc, next, -52 );
255 | case 51:
256 | CRCtriplet ( crc, next, -51 );
257 | case 50:
258 | CRCtriplet ( crc, next, -50 );
259 | case 49:
260 | CRCtriplet ( crc, next, -49 );
261 | case 48:
262 | CRCtriplet ( crc, next, -48 );
263 | case 47:
264 | CRCtriplet ( crc, next, -47 );
265 | case 46:
266 | CRCtriplet ( crc, next, -46 );
267 | case 45:
268 | CRCtriplet ( crc, next, -45 );
269 | case 44:
270 | CRCtriplet ( crc, next, -44 );
271 | case 43:
272 | CRCtriplet ( crc, next, -43 );
273 | case 42:
274 | CRCtriplet ( crc, next, -42 );
275 | case 41:
276 | CRCtriplet ( crc, next, -41 );
277 | case 40:
278 | CRCtriplet ( crc, next, -40 );
279 | case 39:
280 | CRCtriplet ( crc, next, -39 );
281 | case 38:
282 | CRCtriplet ( crc, next, -38 );
283 | case 37:
284 | CRCtriplet ( crc, next, -37 );
285 | case 36:
286 | CRCtriplet ( crc, next, -36 );
287 | case 35:
288 | CRCtriplet ( crc, next, -35 );
289 | case 34:
290 | CRCtriplet ( crc, next, -34 );
291 | case 33:
292 | CRCtriplet ( crc, next, -33 );
293 | case 32:
294 | CRCtriplet ( crc, next, -32 );
295 | case 31:
296 | CRCtriplet ( crc, next, -31 );
297 | case 30:
298 | CRCtriplet ( crc, next, -30 );
299 | case 29:
300 | CRCtriplet ( crc, next, -29 );
301 | case 28:
302 | CRCtriplet ( crc, next, -28 );
303 | case 27:
304 | CRCtriplet ( crc, next, -27 );
305 | case 26:
306 | CRCtriplet ( crc, next, -26 );
307 | case 25:
308 | CRCtriplet ( crc, next, -25 );
309 | case 24:
310 | CRCtriplet ( crc, next, -24 );
311 | case 23:
312 | CRCtriplet ( crc, next, -23 );
313 | case 22:
314 | CRCtriplet ( crc, next, -22 );
315 | case 21:
316 | CRCtriplet ( crc, next, -21 );
317 | case 20:
318 | CRCtriplet ( crc, next, -20 );
319 | case 19:
320 | CRCtriplet ( crc, next, -19 );
321 | case 18:
322 | CRCtriplet ( crc, next, -18 );
323 | case 17:
324 | CRCtriplet ( crc, next, -17 );
325 | case 16:
326 | CRCtriplet ( crc, next, -16 );
327 | case 15:
328 | CRCtriplet ( crc, next, -15 );
329 | case 14:
330 | CRCtriplet ( crc, next, -14 );
331 | case 13:
332 | CRCtriplet ( crc, next, -13 );
333 | case 12:
334 | CRCtriplet ( crc, next, -12 );
335 | case 11:
336 | CRCtriplet ( crc, next, -11 );
337 | case 10:
338 | CRCtriplet ( crc, next, -10 );
339 | case 9:
340 | CRCtriplet ( crc, next, -9 );
341 | case 8:
342 | CRCtriplet ( crc, next, -8 );
343 | case 7:
344 | CRCtriplet ( crc, next, -7 );
345 | case 6:
346 | CRCtriplet ( crc, next, -6 );
347 | case 5:
348 | CRCtriplet ( crc, next, -5 );
349 | case 4:
350 | CRCtriplet ( crc, next, -4 );
351 | case 3:
352 | CRCtriplet ( crc, next, -3 );
353 | case 2:
354 | CRCtriplet ( crc, next, -2 );
355 | case 1:
356 | CRCduplet ( crc, next, -1 ); // the final triplet is actually only 2
357 | CombineCRC();
358 | if ( --n > 0 ) {
359 | crc1 = crc2 = 0;
360 | block_size = 128;
361 | next0 = next2 + 128; // points to the first byte of the next block
362 | next1 = next0 + 128; // from here on all blocks are 128 long
363 | next2 = next1 + 128;
364 | };
365 | case 0:
366 | ;
367 | } while ( n > 0 );
368 | };
369 | next = ( const unsigned char* ) next2;
370 | };
371 | unsigned count = len / 8; // 216 of less bytes is 27 or less singlets
372 | len %= 8;
373 | next += ( count * 8 );
374 | switch ( count ) {
375 | case 27:
376 | CRCsinglet ( crc0, next, -27 * 8 );
377 | case 26:
378 | CRCsinglet ( crc0, next, -26 * 8 );
379 | case 25:
380 | CRCsinglet ( crc0, next, -25 * 8 );
381 | case 24:
382 | CRCsinglet ( crc0, next, -24 * 8 );
383 | case 23:
384 | CRCsinglet ( crc0, next, -23 * 8 );
385 | case 22:
386 | CRCsinglet ( crc0, next, -22 * 8 );
387 | case 21:
388 | CRCsinglet ( crc0, next, -21 * 8 );
389 | case 20:
390 | CRCsinglet ( crc0, next, -20 * 8 );
391 | case 19:
392 | CRCsinglet ( crc0, next, -19 * 8 );
393 | case 18:
394 | CRCsinglet ( crc0, next, -18 * 8 );
395 | case 17:
396 | CRCsinglet ( crc0, next, -17 * 8 );
397 | case 16:
398 | CRCsinglet ( crc0, next, -16 * 8 );
399 | case 15:
400 | CRCsinglet ( crc0, next, -15 * 8 );
401 | case 14:
402 | CRCsinglet ( crc0, next, -14 * 8 );
403 | case 13:
404 | CRCsinglet ( crc0, next, -13 * 8 );
405 | case 12:
406 | CRCsinglet ( crc0, next, -12 * 8 );
407 | case 11:
408 | CRCsinglet ( crc0, next, -11 * 8 );
409 | case 10:
410 | CRCsinglet ( crc0, next, -10 * 8 );
411 | case 9:
412 | CRCsinglet ( crc0, next, -9 * 8 );
413 | case 8:
414 | CRCsinglet ( crc0, next, -8 * 8 );
415 | case 7:
416 | CRCsinglet ( crc0, next, -7 * 8 );
417 | case 6:
418 | CRCsinglet ( crc0, next, -6 * 8 );
419 | case 5:
420 | CRCsinglet ( crc0, next, -5 * 8 );
421 | case 4:
422 | CRCsinglet ( crc0, next, -4 * 8 );
423 | case 3:
424 | CRCsinglet ( crc0, next, -3 * 8 );
425 | case 2:
426 | CRCsinglet ( crc0, next, -2 * 8 );
427 | case 1:
428 | CRCsinglet ( crc0, next, -1 * 8 );
429 | case 0:
430 | ;
431 | };
432 |
433 | };
434 | {
435 | uint32_t crc32bit = crc0;
436 | // less than 8 bytes remain
437 | /* compute the crc for up to seven trailing bytes */
438 | if ( len & 0x04 ) {
439 | crc32bit = __builtin_ia32_crc32si ( crc32bit, * ( uint32_t* ) next );
440 | next += 4;
441 | };
442 | if ( len & 0x02 ) {
443 | crc32bit = __builtin_ia32_crc32hi ( crc32bit, * ( uint16_t* ) next );
444 | next += 2;
445 | };
446 |
447 | if ( len & 0x01 ) {
448 | crc32bit = __builtin_ia32_crc32qi ( crc32bit, * ( next ) );
449 | };
450 | return ( uint32_t ) crc32bit;
451 | };
452 | };
453 |
454 | } // namespace logging
455 | // kate: indent-mode cstyle; indent-width 8; replace-tabs on;
456 |
--------------------------------------------------------------------------------
/crc32c/crc32inteltable.cc:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Ferry Toth, Exalon Delft BV, The Netherlands
2 |
3 | /*
4 | This software is provided 'as-is', without any express or implied
5 | warranty. In no event will the author be held liable for any damages
6 | arising from the use of this software.
7 |
8 | Permission is granted to anyone to use this software for any purpose,
9 | including commercial applications, and to alter it and redistribute it
10 | freely, subject to the following restrictions:
11 |
12 | 1. The origin of this software must not be misrepresented; you must not
13 | claim that you wrote the original software. If you use this software
14 | in a product, an acknowledgment in the product documentation would be
15 | appreciated but is not required.
16 | 2. Altered source versions must be plainly marked as such, and must not be
17 | misrepresented as being the original software.
18 | 3. This notice may not be removed or altered from any source distribution.
19 |
20 | Ferry Toth
21 | ftoth@exalondelft.nl
22 | */
23 |
24 | /* Use hardware CRC instruction on Intel SSE 4.2 processors. This computes a
25 | CRC-32C, *not* the CRC-32 used by Ethernet and zip, gzip, etc. Where efficient
26 | 3 crc32q instructions are used which a single core can execute in parallel.
27 | This compensates for the latency of a single crc32q instruction. Combining the
28 | 3 CRC-32C bytes is done using the pclmulqdq instruction, which has overhead of
29 | its own, and makes this code path only efficient for buffer sizes above 216 bytes.
30 | All code requiring a crc32q instruction is done inside a macro, for which alternative
31 | code is generated in case of a 32 bit platform.
32 |
33 | This code is a port of Intels crc_iscsi_v_pcl.asm assembly code (which is part of
34 | this project as well as in a modified form the linux kernel) and reaches the same
35 | throughput on 64bit platforms. The main advantage of this port is that it was
36 | relatively easy to port to 32bit platforms (like Intel Edison which currently has
37 | only 32bit support). Being written in C it is of course easier to maintain and possibly
38 | optimize further */
39 |
40 | /* Version history:
41 | 1.0 07 May 2016 Ferry Toth - This file just copies the data table from Intels assembly optimized crc_pcl
42 | */
43 |
44 | #include "logging/crc32c.h"
45 | #include
46 |
47 | namespace logging
48 | {
49 | __v2di K[] = {
50 | {0x14cd00bd6, 0x105ec76f0},
51 | {0x0ba4fc28e, 0x14cd00bd6},
52 | {0x1d82c63da, 0x0f20c0dfe},
53 | {0x09e4addf8, 0x0ba4fc28e},
54 | {0x039d3b296, 0x1384aa63a},
55 | {0x102f9b8a2, 0x1d82c63da},
56 | {0x14237f5e6, 0x01c291d04},
57 | {0x00d3b6092, 0x09e4addf8},
58 | {0x0c96cfdc0, 0x0740eef02},
59 | {0x18266e456, 0x039d3b296},
60 | {0x0daece73e, 0x0083a6eec},
61 | {0x0ab7aff2a, 0x102f9b8a2},
62 | {0x1248ea574, 0x1c1733996},
63 | {0x083348832, 0x14237f5e6},
64 | {0x12c743124, 0x02ad91c30},
65 | {0x0b9e02b86, 0x00d3b6092},
66 | {0x018b33a4e, 0x06992cea2},
67 | {0x1b331e26a, 0x0c96cfdc0},
68 | {0x17d35ba46, 0x07e908048},
69 | {0x1bf2e8b8a, 0x18266e456},
70 | {0x1a3e0968a, 0x11ed1f9d8},
71 | {0x0ce7f39f4, 0x0daece73e},
72 | {0x061d82e56, 0x0f1d0f55e},
73 | {0x0d270f1a2, 0x0ab7aff2a},
74 | {0x1c3f5f66c, 0x0a87ab8a8},
75 | {0x12ed0daac, 0x1248ea574},
76 | {0x065863b64, 0x08462d800},
77 | {0x11eef4f8e, 0x083348832},
78 | {0x1ee54f54c, 0x071d111a8},
79 | {0x0b3e32c28, 0x12c743124},
80 | {0x0064f7f26, 0x0ffd852c6},
81 | {0x0dd7e3b0c, 0x0b9e02b86},
82 | {0x0f285651c, 0x0dcb17aa4},
83 | {0x010746f3c, 0x018b33a4e},
84 | {0x1c24afea4, 0x0f37c5aee},
85 | {0x0271d9844, 0x1b331e26a},
86 | {0x08e766a0c, 0x06051d5a2},
87 | {0x093a5f730, 0x17d35ba46},
88 | {0x06cb08e5c, 0x11d5ca20e},
89 | {0x06b749fb2, 0x1bf2e8b8a},
90 | {0x1167f94f2, 0x021f3d99c},
91 | {0x0cec3662e, 0x1a3e0968a},
92 | {0x19329634a, 0x08f158014},
93 | {0x0e6fc4e6a, 0x0ce7f39f4},
94 | {0x08227bb8a, 0x1a5e82106},
95 | {0x0b0cd4768, 0x061d82e56},
96 | {0x13c2b89c4, 0x188815ab2},
97 | {0x0d7a4825c, 0x0d270f1a2},
98 | {0x10f5ff2ba, 0x105405f3e},
99 | {0x00167d312, 0x1c3f5f66c},
100 | {0x0f6076544, 0x0e9adf796},
101 | {0x026f6a60a, 0x12ed0daac},
102 | {0x1a2adb74e, 0x096638b34},
103 | {0x19d34af3a, 0x065863b64},
104 | {0x049c3cc9c, 0x1e50585a0},
105 | {0x068bce87a, 0x11eef4f8e},
106 | {0x1524fa6c6, 0x19f1c69dc},
107 | {0x16cba8aca, 0x1ee54f54c},
108 | {0x042d98888, 0x12913343e},
109 | {0x1329d9f7e, 0x0b3e32c28},
110 | {0x1b1c69528, 0x088f25a3a},
111 | {0x02178513a, 0x0064f7f26},
112 | {0x0e0ac139e, 0x04e36f0b0},
113 | {0x0170076fa, 0x0dd7e3b0c},
114 | {0x141a1a2e2, 0x0bd6f81f8},
115 | {0x16ad828b4, 0x0f285651c},
116 | {0x041d17b64, 0x19425cbba},
117 | {0x1fae1cc66, 0x010746f3c},
118 | {0x1a75b4b00, 0x18db37e8a},
119 | {0x0f872e54c, 0x1c24afea4},
120 | {0x01e41e9fc, 0x04c144932},
121 | {0x086d8e4d2, 0x0271d9844},
122 | {0x160f7af7a, 0x052148f02},
123 | {0x05bb8f1bc, 0x08e766a0c},
124 | {0x0a90fd27a, 0x0a3c6f37a},
125 | {0x0b3af077a, 0x093a5f730},
126 | {0x04984d782, 0x1d22c238e},
127 | {0x0ca6ef3ac, 0x06cb08e5c},
128 | {0x0234e0b26, 0x063ded06a},
129 | {0x1d88abd4a, 0x06b749fb2},
130 | {0x04597456a, 0x04d56973c},
131 | {0x0e9e28eb4, 0x1167f94f2},
132 | {0x07b3ff57a, 0x19385bf2e},
133 | {0x0c9c8b782, 0x0cec3662e},
134 | {0x13a9cba9e, 0x0e417f38a},
135 | {0x093e106a4, 0x19329634a},
136 | {0x167001a9c, 0x14e727980},
137 | {0x1ddffc5d4, 0x0e6fc4e6a},
138 | {0x00df04680, 0x0d104b8fc},
139 | {0x02342001e, 0x08227bb8a},
140 | {0x00a2a8d7e, 0x05b397730},
141 | {0x168763fa6, 0x0b0cd4768},
142 | {0x1ed5a407a, 0x0e78eb416},
143 | {0x0d2c3ed1a, 0x13c2b89c4},
144 | {0x0995a5724, 0x1641378f0},
145 | {0x19b1afbc4, 0x0d7a4825c},
146 | {0x109ffedc0, 0x08d96551c},
147 | {0x0f2271e60, 0x10f5ff2ba},
148 | {0x00b0bf8ca, 0x00bf80dd2},
149 | {0x123888b7a, 0x00167d312},
150 | {0x1e888f7dc, 0x18dcddd1c},
151 | {0x002ee03b2, 0x0f6076544},
152 | {0x183e8d8fe, 0x06a45d2b2},
153 | {0x133d7a042, 0x026f6a60a},
154 | {0x116b0f50c, 0x1dd3e10e8},
155 | {0x05fabe670, 0x1a2adb74e},
156 | {0x130004488, 0x0de87806c},
157 | {0x000bcf5f6, 0x19d34af3a},
158 | {0x18f0c7078, 0x014338754},
159 | {0x017f27698, 0x049c3cc9c},
160 | {0x058ca5f00, 0x15e3e77ee},
161 | {0x1af900c24, 0x068bce87a},
162 | {0x0b5cfca28, 0x0dd07448e},
163 | {0x0ded288f8, 0x1524fa6c6},
164 | {0x059f229bc, 0x1d8048348},
165 | {0x06d390dec, 0x16cba8aca},
166 | {0x037170390, 0x0a3e3e02c},
167 | {0x06353c1cc, 0x042d98888},
168 | {0x0c4584f5c, 0x0d73c7bea},
169 | {0x1f16a3418, 0x1329d9f7e},
170 | {0x0531377e2, 0x185137662},
171 | {0x1d8d9ca7c, 0x1b1c69528},
172 | {0x0b25b29f2, 0x18a08b5bc},
173 | {0x19fb2a8b0, 0x02178513a},
174 | {0x1a08fe6ac, 0x1da758ae0},
175 | {0x045cddf4e, 0x0e0ac139e},
176 | {0x1a91647f2, 0x169cf9eb0},
177 | {0x1a0f717c4, 0x0170076fa}
178 | };
179 |
180 | }
181 | // kate: indent-mode cstyle; indent-width 8; replace-tabs on;
182 |
--------------------------------------------------------------------------------
/crc32c/crc_iscsi_v_pcl.asm:
--------------------------------------------------------------------------------
1 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2 | ; Copyright (c) 2012, Intel Corporation
3 | ;
4 | ; All rights reserved.
5 | ;
6 | ; Redistribution and use in source and binary forms, with or without
7 | ; modification, are permitted provided that the following conditions are
8 | ; met:
9 | ;
10 | ; * Redistributions of source code must retain the above copyright
11 | ; notice, this list of conditions and the following disclaimer.
12 | ;
13 | ; * Redistributions in binary form must reproduce the above copyright
14 | ; notice, this list of conditions and the following disclaimer in the
15 | ; documentation and/or other materials provided with the
16 | ; distribution.
17 | ;
18 | ; * Neither the name of the Intel Corporation nor the names of its
19 | ; contributors may be used to endorse or promote products derived from
20 | ; this software without specific prior written permission.
21 | ;
22 | ;
23 | ; THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION "AS IS" AND ANY
24 | ; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 | ; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
26 | ; PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL CORPORATION OR
27 | ; CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
28 | ; EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
29 | ; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30 | ; PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31 | ; LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32 | ; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33 | ; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
35 | ;
36 | ; Example YASM command lines:
37 | ; Windows: yasm -Xvc -f x64 -rnasm -pnasm -o crc_iscsi_v_pcl.obj -g cv8 crc_iscsi_v_pcl.asm
38 | ; Linux: yasm -f x64 -f elf64 -X gnu -g dwarf2 -D LINUX -o crc_iscsi_v_pcl.o crc_iscsi_v_pcl.asm
39 | ;
40 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
41 | ;
42 | ; ISCSI CRC 32 Implementation with crc32 and pclmulqdq Instructions
43 |
44 | %ifdef LINUX
45 | %define bufp rdi
46 | %define bufp_dw edi
47 | %define bufp_w di
48 | %define bufp_b dil
49 | %define bufptmp rcx
50 | %define block_0 rcx
51 | %define block_1 rdx
52 | %define block_2 r11
53 | %define len rsi
54 | %define len_dw esi
55 | %define len_w si
56 | %define len_b sil
57 | %define crc_init_arg rdx
58 | %else
59 | %define bufp rcx
60 | %define bufp_dw ecx
61 | %define bufp_w cx
62 | %define bufp_b cl
63 | %define bufptmp rdi
64 | %define block_0 rdi
65 | %define block_1 rsi
66 | %define block_2 r11
67 | %define len rdx
68 | %define len_dw edx
69 | %define len_w dx
70 | %define len_b dl
71 | %endif
72 |
73 | %define tmp rbx
74 | %define crc_init r8
75 | %define crc_init_dw r8d
76 | %define crc1 r9
77 | %define crc2 r10
78 |
79 | %define CONCAT(a,b,c) a %+ b %+ c
80 |
81 | ; Define threshold where buffers are considered "small" and routed to more
82 | ; efficient "by-1" code. This "by-1" code only handles up to 255 bytes, so
83 | ; SMALL_SIZE can be no larger than 255.
84 | %define SMALL_SIZE 200
85 |
86 | %if (SMALL_SIZE > 255)
87 | %error SMALL_ SIZE must be < 256
88 | % error ; needed because '%error' actually generates only a warning
89 | %endif
90 |
91 | ; unsigned int crc_pcl(unsigned char * buffer, int len, unsigned int crc_init);
92 |
93 | global crc_pcl:function
94 | crc_pcl:
95 |
96 | push rbx
97 | %ifndef LINUX
98 | push rdi
99 | push rsi
100 | %endif
101 | %ifdef LINUX
102 | ; Move crc_init for Linux to r8
103 | ; 3rd argument is already r8 for Windows
104 | ; We can't just leave it in RDX because that gets clobbered by MUL
105 | mov crc_init, crc_init_arg
106 | %endif
107 |
108 |
109 | ;;;;;;;;;;;
110 | ; 1) ALIGN:
111 | ;;;;;;;;;;;
112 |
113 | mov bufptmp, bufp ; bufptmp = *buf
114 | neg bufp
115 | and bufp, 7 ; calculate the unalignment amount of
116 | ; the address
117 | je proc_block ; Skip if aligned
118 |
119 | ; If len is less than 8 and we're unaligned, we need to jump
120 | ; to special code to avoid reading beyond the end of the buffer
121 | cmp len, 8
122 | jae do_align
123 | ; less_than_8 expects length in upper 3 bits of len_dw
124 | ; less_than_8_post_shl1 expects length = carryflag * 8 + len_dw[31:30]
125 | shl len_dw, (32 - 3 + 1)
126 | jmp less_than_8_post_shl1
127 |
128 | do_align:
129 | ;;;; Calculate CRC of unaligned bytes of the buffer (if any) ;;;
130 | mov tmp, [bufptmp] ; load a quadword from the buffer
131 | add bufptmp, bufp ; align buffer pointer for quadword
132 | ; processing
133 | sub len, bufp ; update buffer length
134 | align_loop:
135 | crc32 crc_init_dw, bl ; compute crc32 of 1-byte
136 | shr tmp, 8 ; get next byte
137 | dec bufp
138 | jne align_loop
139 |
140 | proc_block:
141 |
142 | ;;;;;;;;;;;;;;;;;;;;;
143 | ; 2) PROCESS BLOCKS:
144 | ;;;;;;;;;;;;;;;;;;;;;
145 |
146 | ;; compute num of bytes to be processed
147 | mov tmp, len ; save num bytes in tmp
148 |
149 | cmp len, 128*24
150 | jae full_block
151 |
152 | continue_block:
153 | cmp len, SMALL_SIZE
154 | jb small
155 |
156 | ;; len < 128*24
157 | mov rax, 2731 ; 2731 = ceil(2^16 / 24)
158 | mul len_dw
159 | shr rax, 16
160 |
161 | ; eax contains floor(bytes / 24) = num 24-byte chunks to do
162 |
163 | ; process rax 24-byte chunks (128 >= rax >= 0)
164 |
165 | ; compute end address of each block
166 | ; block 0 (base addr + RAX * 8)
167 | ; block 1 (base addr + RAX * 16)
168 | ; block 2 (base addr + RAX * 24)
169 | lea block_0, [bufptmp + rax * 8]
170 | lea block_1, [block_0 + rax * 8]
171 | lea block_2, [block_1 + rax * 8]
172 |
173 | xor crc1,crc1
174 | xor crc2,crc2
175 |
176 | ; branch into array
177 | lea bufp, [jump_table wrt rip]
178 | movzx len, word [bufp + rax * 2] ; len is offset from crc_array
179 | lea bufp, [bufp + len + crc_array - jump_table]
180 | jmp bufp
181 |
182 |
183 | ;;;;;;;;;;;;;;;;;;;;;;;;;;
184 | ; 2a) PROCESS FULL BLOCKS:
185 | ;;;;;;;;;;;;;;;;;;;;;;;;;;
186 | full_block:
187 | mov rax, 128
188 | lea block_1, [block_0 + 128*8*2]
189 | lea block_2, [block_0 + 128*8*3]
190 | add block_0, 128*8*1
191 |
192 | xor crc1,crc1
193 | xor crc2,crc2
194 |
195 | ; Fall through into top of crc array (crc_128)
196 |
197 |
198 | ;;;;;;;;;;;;;;;
199 | ; 3) CRC Array:
200 | ;;;;;;;;;;;;;;;
201 |
202 | crc_array:
203 | %assign i 128
204 | %rep 128-1
205 | CONCAT(crc_,i,:)
206 | crc32 crc_init, [block_0 - i*8]
207 | crc32 crc1, [block_1 - i*8]
208 | crc32 crc2, [block_2 - i*8]
209 | %assign i (i-1)
210 | %endrep
211 |
212 | CONCAT(crc_,i,:)
213 | crc32 crc_init, [block_0 - i*8]
214 | crc32 crc1, [block_1 - i*8]
215 | ; SKIP ;crc32 crc2, [block_2 - i*8] ; Don't do this one yet
216 |
217 | mov block_0, block_2
218 |
219 |
220 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;
221 | ; 4) Combine three results:
222 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;
223 |
224 | lea bufp, [K_table - 16 wrt rip] ; first entry is for idx 1
225 | shl rax, 3 ; rax *= 8
226 | sub tmp, rax ; tmp -= rax*8
227 | shl rax, 1
228 | sub tmp, rax ; tmp -= rax*16 (total tmp -= rax*24)
229 | add bufp, rax
230 |
231 | movdqa xmm0, [bufp] ; 2 consts: K1:K2
232 |
233 | movq xmm1, crc_init ; CRC for block 1
234 | pclmulqdq xmm1, xmm0, 0x00 ; Multiply by K2
235 |
236 | movq xmm2, crc1 ; CRC for block 2
237 | pclmulqdq xmm2, xmm0, 0x10 ; Multiply by K1
238 |
239 | pxor xmm1, xmm2
240 | movq rax, xmm1
241 | xor rax, [block_2 - i*8]
242 | mov crc_init, crc2
243 | crc32 crc_init, rax
244 |
245 |
246 | ;;;;;;;;;;;;;;;;;;;
247 | ; 5) Check for end:
248 | ;;;;;;;;;;;;;;;;;;;
249 |
250 | CONCAT(crc_,0,:)
251 | mov len, tmp
252 | cmp tmp, 128*24
253 | jae full_block
254 | cmp tmp, 24
255 | jae continue_block
256 |
257 |
258 | less_than_24:
259 | shl len_dw, (32-4) ;; less_than_16 expects length in upper 4 bits of len_dw
260 | jnc less_than_16
261 | crc32 crc_init, [bufptmp]
262 | crc32 crc_init, [bufptmp+8]
263 | jz do_return
264 | add bufptmp, 16
265 |
266 | ; len is less than 8 if we got here
267 | ; less_than_8 expects length in upper 3 bits of len_dw
268 | ; less_than_8_post_shl1 expects length = carryflag * 8 + len_dw[31:30]
269 | shl len_dw, 2
270 | jmp less_than_8_post_shl1
271 |
272 |
273 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
274 | ; 6) LESS THAN 256-bytes REMAIN AT THIS POINT (8-bits of len are full):
275 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
276 |
277 | small:
278 | shl len_dw, (32-8) ; Prepare len_dw for less_than_256
279 |
280 | %assign j 256
281 | %rep 5 ; j = {256, 128, 64, 32, 16}
282 | CONCAT(less_than_,j,:) ; less_than_j: Length should be in upper log2(j) bits of len_dw
283 | %assign j (j/2)
284 | shl len_dw, 1 ; Get next MSB
285 | CONCAT(jnc less_than_,j,)
286 | %assign i 0
287 | %rep (j / 8)
288 | crc32 crc_init, [bufptmp+i] ; Compute crc32 of 8-byte data
289 | %assign i (i+8)
290 | %endrep
291 | jz do_return ; Return if remaining length is zero
292 | add bufptmp, j ; Advance buf
293 | %endrep
294 |
295 | less_than_8: ; Length should be stored in upper 3 bits of len_dw
296 | shl len_dw, 1
297 | less_than_8_post_shl1:
298 | jnc less_than_4
299 | crc32 crc_init_dw, dword[bufptmp] ; CRC of 4 bytes
300 | jz do_return ; return if remaining data is zero
301 | add bufptmp,4
302 | less_than_4: ; Length should be stored in upper 2 bits of len_dw
303 | shl len_dw, 1
304 | jnc less_than_2
305 | crc32 crc_init_dw, word[bufptmp] ; CRC of 2 bytes
306 | jz do_return ; return if remaining data is zero
307 | add bufptmp,2
308 | less_than_2: ; Length should be stored in the MSB of len_dw
309 | shl len_dw, 1
310 | jnc less_than_1
311 | crc32 crc_init_dw, byte[bufptmp] ; CRC of 1 byte
312 | less_than_1: ; Length should be zero
313 | do_return:
314 | mov rax, crc_init
315 | %ifndef LINUX
316 | pop rsi
317 | pop rdi
318 | %endif
319 | pop rbx
320 | ret
321 |
322 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
323 | ; jump table
324 | ; Table is 129 entries x 2 bytes each
325 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
326 |
327 | align 4
328 | jump_table:
329 | %assign i 0
330 | %rep 129
331 | dw CONCAT(crc_,i,) - crc_array
332 | %assign i (i+1)
333 | %endrep
334 |
335 |
336 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
337 | ; PCLMULQDQ tables
338 | ; Table is 128 entries x 2 quad words each
339 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
340 | section .data
341 | align 64
342 | K_table:
343 | dq 0x14cd00bd6, 0x105ec76f0
344 | dq 0x0ba4fc28e, 0x14cd00bd6
345 | dq 0x1d82c63da, 0x0f20c0dfe
346 | dq 0x09e4addf8, 0x0ba4fc28e
347 | dq 0x039d3b296, 0x1384aa63a
348 | dq 0x102f9b8a2, 0x1d82c63da
349 | dq 0x14237f5e6, 0x01c291d04
350 | dq 0x00d3b6092, 0x09e4addf8
351 | dq 0x0c96cfdc0, 0x0740eef02
352 | dq 0x18266e456, 0x039d3b296
353 | dq 0x0daece73e, 0x0083a6eec
354 | dq 0x0ab7aff2a, 0x102f9b8a2
355 | dq 0x1248ea574, 0x1c1733996
356 | dq 0x083348832, 0x14237f5e6
357 | dq 0x12c743124, 0x02ad91c30
358 | dq 0x0b9e02b86, 0x00d3b6092
359 | dq 0x018b33a4e, 0x06992cea2
360 | dq 0x1b331e26a, 0x0c96cfdc0
361 | dq 0x17d35ba46, 0x07e908048
362 | dq 0x1bf2e8b8a, 0x18266e456
363 | dq 0x1a3e0968a, 0x11ed1f9d8
364 | dq 0x0ce7f39f4, 0x0daece73e
365 | dq 0x061d82e56, 0x0f1d0f55e
366 | dq 0x0d270f1a2, 0x0ab7aff2a
367 | dq 0x1c3f5f66c, 0x0a87ab8a8
368 | dq 0x12ed0daac, 0x1248ea574
369 | dq 0x065863b64, 0x08462d800
370 | dq 0x11eef4f8e, 0x083348832
371 | dq 0x1ee54f54c, 0x071d111a8
372 | dq 0x0b3e32c28, 0x12c743124
373 | dq 0x0064f7f26, 0x0ffd852c6
374 | dq 0x0dd7e3b0c, 0x0b9e02b86
375 | dq 0x0f285651c, 0x0dcb17aa4
376 | dq 0x010746f3c, 0x018b33a4e
377 | dq 0x1c24afea4, 0x0f37c5aee
378 | dq 0x0271d9844, 0x1b331e26a
379 | dq 0x08e766a0c, 0x06051d5a2
380 | dq 0x093a5f730, 0x17d35ba46
381 | dq 0x06cb08e5c, 0x11d5ca20e
382 | dq 0x06b749fb2, 0x1bf2e8b8a
383 | dq 0x1167f94f2, 0x021f3d99c
384 | dq 0x0cec3662e, 0x1a3e0968a
385 | dq 0x19329634a, 0x08f158014
386 | dq 0x0e6fc4e6a, 0x0ce7f39f4
387 | dq 0x08227bb8a, 0x1a5e82106
388 | dq 0x0b0cd4768, 0x061d82e56
389 | dq 0x13c2b89c4, 0x188815ab2
390 | dq 0x0d7a4825c, 0x0d270f1a2
391 | dq 0x10f5ff2ba, 0x105405f3e
392 | dq 0x00167d312, 0x1c3f5f66c
393 | dq 0x0f6076544, 0x0e9adf796
394 | dq 0x026f6a60a, 0x12ed0daac
395 | dq 0x1a2adb74e, 0x096638b34
396 | dq 0x19d34af3a, 0x065863b64
397 | dq 0x049c3cc9c, 0x1e50585a0
398 | dq 0x068bce87a, 0x11eef4f8e
399 | dq 0x1524fa6c6, 0x19f1c69dc
400 | dq 0x16cba8aca, 0x1ee54f54c
401 | dq 0x042d98888, 0x12913343e
402 | dq 0x1329d9f7e, 0x0b3e32c28
403 | dq 0x1b1c69528, 0x088f25a3a
404 | dq 0x02178513a, 0x0064f7f26
405 | dq 0x0e0ac139e, 0x04e36f0b0
406 | dq 0x0170076fa, 0x0dd7e3b0c
407 | dq 0x141a1a2e2, 0x0bd6f81f8
408 | dq 0x16ad828b4, 0x0f285651c
409 | dq 0x041d17b64, 0x19425cbba
410 | dq 0x1fae1cc66, 0x010746f3c
411 | dq 0x1a75b4b00, 0x18db37e8a
412 | dq 0x0f872e54c, 0x1c24afea4
413 | dq 0x01e41e9fc, 0x04c144932
414 | dq 0x086d8e4d2, 0x0271d9844
415 | dq 0x160f7af7a, 0x052148f02
416 | dq 0x05bb8f1bc, 0x08e766a0c
417 | dq 0x0a90fd27a, 0x0a3c6f37a
418 | dq 0x0b3af077a, 0x093a5f730
419 | dq 0x04984d782, 0x1d22c238e
420 | dq 0x0ca6ef3ac, 0x06cb08e5c
421 | dq 0x0234e0b26, 0x063ded06a
422 | dq 0x1d88abd4a, 0x06b749fb2
423 | dq 0x04597456a, 0x04d56973c
424 | dq 0x0e9e28eb4, 0x1167f94f2
425 | dq 0x07b3ff57a, 0x19385bf2e
426 | dq 0x0c9c8b782, 0x0cec3662e
427 | dq 0x13a9cba9e, 0x0e417f38a
428 | dq 0x093e106a4, 0x19329634a
429 | dq 0x167001a9c, 0x14e727980
430 | dq 0x1ddffc5d4, 0x0e6fc4e6a
431 | dq 0x00df04680, 0x0d104b8fc
432 | dq 0x02342001e, 0x08227bb8a
433 | dq 0x00a2a8d7e, 0x05b397730
434 | dq 0x168763fa6, 0x0b0cd4768
435 | dq 0x1ed5a407a, 0x0e78eb416
436 | dq 0x0d2c3ed1a, 0x13c2b89c4
437 | dq 0x0995a5724, 0x1641378f0
438 | dq 0x19b1afbc4, 0x0d7a4825c
439 | dq 0x109ffedc0, 0x08d96551c
440 | dq 0x0f2271e60, 0x10f5ff2ba
441 | dq 0x00b0bf8ca, 0x00bf80dd2
442 | dq 0x123888b7a, 0x00167d312
443 | dq 0x1e888f7dc, 0x18dcddd1c
444 | dq 0x002ee03b2, 0x0f6076544
445 | dq 0x183e8d8fe, 0x06a45d2b2
446 | dq 0x133d7a042, 0x026f6a60a
447 | dq 0x116b0f50c, 0x1dd3e10e8
448 | dq 0x05fabe670, 0x1a2adb74e
449 | dq 0x130004488, 0x0de87806c
450 | dq 0x000bcf5f6, 0x19d34af3a
451 | dq 0x18f0c7078, 0x014338754
452 | dq 0x017f27698, 0x049c3cc9c
453 | dq 0x058ca5f00, 0x15e3e77ee
454 | dq 0x1af900c24, 0x068bce87a
455 | dq 0x0b5cfca28, 0x0dd07448e
456 | dq 0x0ded288f8, 0x1524fa6c6
457 | dq 0x059f229bc, 0x1d8048348
458 | dq 0x06d390dec, 0x16cba8aca
459 | dq 0x037170390, 0x0a3e3e02c
460 | dq 0x06353c1cc, 0x042d98888
461 | dq 0x0c4584f5c, 0x0d73c7bea
462 | dq 0x1f16a3418, 0x1329d9f7e
463 | dq 0x0531377e2, 0x185137662
464 | dq 0x1d8d9ca7c, 0x1b1c69528
465 | dq 0x0b25b29f2, 0x18a08b5bc
466 | dq 0x19fb2a8b0, 0x02178513a
467 | dq 0x1a08fe6ac, 0x1da758ae0
468 | dq 0x045cddf4e, 0x0e0ac139e
469 | dq 0x1a91647f2, 0x169cf9eb0
470 | dq 0x1a0f717c4, 0x0170076fa
471 |
--------------------------------------------------------------------------------
/crc32c/logging/crc32c.h:
--------------------------------------------------------------------------------
1 | // Copyright 2008,2009,2010 Massachusetts Institute of Technology.
2 | // All rights reserved. Use of this source code is governed by a
3 | // BSD-style license that can be found in the LICENSE file.
4 |
5 | #ifndef LOGGING_CRC32C_H__
6 | #define LOGGING_CRC32C_H__
7 |
8 | #include
9 | #include
10 |
11 | namespace logging {
12 |
13 | /** Returns the initial value for a CRC32-C computation. */
14 | static inline uint32_t crc32cInit() {
15 | return 0xFFFFFFFF;
16 | }
17 |
18 | /** Pointer to a function that computes a CRC32C checksum.
19 | @arg crc Previous CRC32C value, or crc32c_init().
20 | @arg data Pointer to the data to be checksummed.
21 | @arg length length of the data in bytes.
22 | */
23 | typedef uint32_t (*CRC32CFunctionPtr)(uint32_t crc, const void* data, size_t length);
24 |
25 | /** This will map automatically to the "best" CRC implementation. */
26 | extern CRC32CFunctionPtr crc32c;
27 |
28 | CRC32CFunctionPtr detectBestCRC32C();
29 |
30 | /** Converts a partial CRC32-C computation to the final value. */
31 | static inline uint32_t crc32cFinish(uint32_t crc) {
32 | return ~crc;
33 | }
34 |
35 | uint32_t crc32cSarwate(uint32_t crc, const void* data, size_t length);
36 | uint32_t crc32cSlicingBy4(uint32_t crc, const void* data, size_t length);
37 | uint32_t crc32cSlicingBy8(uint32_t crc, const void* data, size_t length);
38 | uint32_t crc32cHardware32(uint32_t crc, const void* data, size_t length);
39 | uint32_t crc32cHardware64(uint32_t crc, const void* data, size_t length);
40 | uint32_t crc32cAdler(uint32_t crc, const void* data, size_t length);
41 | uint32_t crc32cIntelC(uint32_t crc, const void* data, size_t length);
42 | uint32_t crc32cIntelAsm(uint32_t crc, const void *buf, size_t len);
43 |
44 | } // namespace logging
45 | #endif
46 |
--------------------------------------------------------------------------------
/crc32c/logging/crc32ctables.h:
--------------------------------------------------------------------------------
1 | // Copyright 2008,2009,2010 Massachusetts Institute of Technology.
2 | // All rights reserved. Use of this source code is governed by a
3 | // BSD-style license that can be found in the LICENSE file.
4 |
5 | #ifndef LOGGING_CRC32CTABLES_H__
6 | #define LOGGING_CRC32CTABLES_H__
7 |
8 | #include
9 |
10 | namespace logging {
11 |
12 | extern const uint32_t crc_tableil8_o32[256];
13 | extern const uint32_t crc_tableil8_o40[256];
14 | extern const uint32_t crc_tableil8_o48[256];
15 | extern const uint32_t crc_tableil8_o56[256];
16 | extern const uint32_t crc_tableil8_o64[256];
17 | extern const uint32_t crc_tableil8_o72[256];
18 | extern const uint32_t crc_tableil8_o80[256];
19 | extern const uint32_t crc_tableil8_o88[256];
20 |
21 | }
22 | #endif
23 |
--------------------------------------------------------------------------------
/crc32c/logging/crc32intelc.h:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Ferry Toth, Exalon Delft BV, The Netherlands
2 | /*
3 | This software is provided 'as-is', without any express or implied
4 | warranty. In no event will the author be held liable for any damages
5 | arising from the use of this software.
6 |
7 | Permission is granted to anyone to use this software for any purpose,
8 | including commercial applications, and to alter it and redistribute it
9 | freely, subject to the following restrictions:
10 |
11 | 1. The origin of this software must not be misrepresented; you must not
12 | claim that you wrote the original software. If you use this software
13 | in a product, an acknowledgment in the product documentation would be
14 | appreciated but is not required.
15 | 2. Altered source versions must be plainly marked as such, and must not be
16 | misrepresented as being the original software.
17 | 3. This notice may not be removed or altered from any source distribution.
18 |
19 | Ferry Toth
20 | ftoth@exalondelft.nl
21 | */
22 |
23 | /* Use hardware CRC instruction on Intel SSE 4.2 processors. This computes a
24 | CRC-32C, *not* the CRC-32 used by Ethernet and zip, gzip, etc. Where efficient
25 | 3 crc32q instructions are used which a single core can execute in parallel.
26 | This compensates for the latency of a single crc32q instruction. Combining the
27 | 3 CRC-32C bytes is done using the pclmulqdq instruction, which has overhead of
28 | its own, and makes this code path only efficient for buffer sizes above 216 bytes.
29 | All code requiring a crc32q instruction is done inside a macro, for which alternative
30 | code is generated in case of a 32 bit platform.
31 |
32 | This code is a port of Intels crc_iscsi_v_pcl.asm assembly code (which is part of
33 | this project as well as in a modified form the linux kernel) and reaches the same
34 | throughput on 64bit platforms. The main advantage of this port is that it was
35 | relatively easy to port to 32bit platforms (like Intel Edison which currently has
36 | only 32bit support). Being written in C it is of course easier to maintain and possibly
37 | optimize further */
38 |
39 | /* Version history:
40 | 1.0 07 May 2016 Ferry Toth - First version
41 | */
42 |
43 | #ifndef __LP64__
44 | #define CRC_NATIVE uint32_t
45 | #else
46 | #define CRC_NATIVE uint64_t
47 | #endif
48 |
49 | #ifndef __LP64__
50 | #define CRCtriplet(crc, buf, offset) \
51 | crc ## 0 = __builtin_ia32_crc32si(crc ## 0, *((uint32_t*) buf ## 0 + 2 * offset)); \
52 | crc ## 1 = __builtin_ia32_crc32si(crc ## 1, *((uint32_t*) buf ## 1 + 2 * offset)); \
53 | crc ## 2 = __builtin_ia32_crc32si(crc ## 2, *((uint32_t*) buf ## 2 + 2 * offset)); \
54 | crc ## 0 = __builtin_ia32_crc32si(crc ## 0, *((uint32_t*) buf ## 0 + 1 + 2 * offset)); \
55 | crc ## 1 = __builtin_ia32_crc32si(crc ## 1, *((uint32_t*) buf ## 1 + 1 + 2 * offset)); \
56 | crc ## 2 = __builtin_ia32_crc32si(crc ## 2, *((uint32_t*) buf ## 2 + 1 + 2 * offset));
57 | #else
58 | #define CRCtriplet(crc, buf, offset) \
59 | crc ## 0 = __builtin_ia32_crc32di(crc ## 0, *(buf ## 0 + offset)); \
60 | crc ## 1 = __builtin_ia32_crc32di(crc ## 1, *(buf ## 1 + offset)); \
61 | crc ## 2 = __builtin_ia32_crc32di(crc ## 2, *(buf ## 2 + offset));
62 | #endif
63 |
64 | #ifndef __LP64__
65 | #define CRCduplet(crc, buf, offset) \
66 | crc ## 0 = __builtin_ia32_crc32si(crc ## 0, *((uint32_t*) buf ## 0 + 2 * offset)); \
67 | crc ## 1 = __builtin_ia32_crc32si(crc ## 1, *((uint32_t*) buf ## 1 + 2 * offset)); \
68 | crc ## 0 = __builtin_ia32_crc32si(crc ## 0, *((uint32_t*) buf ## 0 + 1 + 2 * offset)); \
69 | crc ## 1 = __builtin_ia32_crc32si(crc ## 1, *((uint32_t*) buf ## 1 + 1 + 2 * offset));
70 | #else
71 | #define CRCduplet(crc, buf, offset) \
72 | crc ## 0 = __builtin_ia32_crc32di(crc ## 0, *(buf ## 0 + offset)); \
73 | crc ## 1 = __builtin_ia32_crc32di(crc ## 1, *(buf ## 1 + offset));
74 | #endif
75 |
76 |
77 | #ifndef __LP64__
78 | #define CRCsinglet(crc, buf, offset) \
79 | crc = __builtin_ia32_crc32si(crc, *(uint32_t*)(buf + offset)); \
80 | crc = __builtin_ia32_crc32si(crc, *(uint32_t*)(buf + offset + sizeof(uint32_t)));
81 | #else
82 | #define CRCsinglet(crc, buf, offset) crc = __builtin_ia32_crc32di(crc, *(uint64_t*)(buf + offset));
83 | #endif
84 |
85 |
86 | /*
87 | * CombineCRC performs pclmulqdq multiplication of 2 partial CRC's and a well chosen constant
88 | * and xor's these with the remaining CRC. I (Ferry Toth) could not find a way to implement this in
89 | * C, so the 64bit code following here is from Intel. As that code runs only on 64 bit (due to movq
90 | * instructions), I am providing a 32bit variant that does the same but using movd. The 32bit
91 | * version keeps intermediate results longer in the xmm registers to do the 2nd xor, then moves the
92 | * longs in 2 steps for the final crc32l
93 | *
94 | */
95 |
96 | #ifndef __LP64__
97 | #define CombineCRC()\
98 | asm volatile (\
99 | "movdqu (%3), %%xmm0\n\t"\
100 | "movd %0, %%xmm1\n\t"\
101 | "pclmullqlqdq %%xmm0, %%xmm1\n\t"\
102 | "movd %2, %%xmm2\n\t"\
103 | "pclmullqhqdq %%xmm0, %%xmm2\n\t"\
104 | "pxor %%xmm2, %%xmm1\n\t"\
105 | "movdqu (%4), %%xmm2\n\t"\
106 | "pxor %%xmm2, %%xmm1\n\t"\
107 | "movd %%xmm1, %0\n\t"\
108 | "crc32l %0, %5\n\t"\
109 | "pextrd $1, %%xmm1, %1\n\t"\
110 | "crc32l %1, %5\n\t"\
111 | "movl %5, %0"\
112 | : "=r" ( crc0 )\
113 | : "0" ( crc0 ), "r" ( crc1 ), "r" ( K + block_size - 1 ), "r" ( ( uint64_t* ) next2 - 1 ), "r" ( crc2 )\
114 | : "%xmm0", "%xmm1", "%xmm2"\
115 | );
116 | #else
117 | #define CombineCRC()\
118 | asm volatile (\
119 | "movdqa (%3), %%xmm0\n\t"\
120 | "movq %0, %%xmm1\n\t"\
121 | "pclmullqlqdq %%xmm0, %%xmm1\n\t"\
122 | "movq %2, %%xmm2\n\t"\
123 | "pclmullqhqdq %%xmm0, %%xmm2\n\t"\
124 | "pxor %%xmm2, %%xmm1\n\t"\
125 | "movq %%xmm1, %0"\
126 | : "=r" ( crc0 ) \
127 | : "0" ( crc0 ), "r" ( crc1 ), "r" ( K + block_size - 1 ) \
128 | : "%xmm0", "%xmm1", "%xmm2"\
129 | ); \
130 | crc0 = crc0 ^ * ( ( uint64_t* ) next2 - 1 );\
131 | crc2 = __builtin_ia32_crc32di ( crc2, crc0 );\
132 | crc0 = crc2;
133 | #endif
134 | // kate: indent-mode cstyle; indent-width 4; replace-tabs on;
135 |
--------------------------------------------------------------------------------
/crc32c/logging/cycletimer.h:
--------------------------------------------------------------------------------
1 | #ifndef LOGGING_CYCLETIMER_H__
2 | #define LOGGING_CYCLETIMER_H__
3 |
4 | #include
5 |
6 | namespace logging {
7 |
8 | class CycleTimer {
9 | public:
10 | void start() {
11 | cpuSync();
12 | start_ = rdtsc();
13 | }
14 |
15 | void end() {
16 | cpuSync();
17 | end_ = rdtsc();
18 | }
19 |
20 | uint32_t getCycles() {
21 | return end_ - start_;
22 | }
23 |
24 | private:
25 | uint32_t rdtsc() {
26 | #ifdef __x86_64__
27 | uint32_t low;
28 | uint32_t high;
29 | asm volatile("rdtsc" : "=a"(low), "=d" (high));
30 | return low;
31 | #elif defined(__i386__)
32 | uint64_t tsc;
33 | asm volatile("rdtsc" : "=A" (tsc));
34 | return (uint32_t) tsc;
35 | #else
36 | #error unsupported
37 | #endif
38 | }
39 |
40 | void cpuSync() {
41 | // Calls CPUID to force the pipeline to be flushed
42 | uint32_t eax;
43 | uint32_t ebx;
44 | uint32_t ecx;
45 | uint32_t edx;
46 | #ifdef __PIC__
47 | // PIC: Need to save and restore ebx See:
48 | // http://sam.zoy.org/blog/2007-04-13-shlib-with-non-pic-code-have-inline-assembly-and-pic-mix-well
49 | asm("pushl %%ebx\n\t" /* save %ebx */
50 | "cpuid\n\t"
51 | "movl %%ebx, %[ebx]\n\t" /* save what cpuid just put in %ebx */
52 | "popl %%ebx" : "=a"(eax), [ebx] "=r"(ebx), "=c"(ecx), "=d"(edx) : "a" (0)
53 | : "cc");
54 | #else
55 | asm("cpuid" : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) : "a" (0));
56 | #endif
57 | }
58 |
59 | uint32_t start_;
60 | uint32_t end_;
61 | };
62 |
63 | }
64 | #endif
65 |
--------------------------------------------------------------------------------
/crc32c/stupidunit.cc:
--------------------------------------------------------------------------------
1 | // Copyright 2008,2009,2010 Massachusetts Institute of Technology.
2 | // All rights reserved. Use of this source code is governed by a
3 | // BSD-style license that can be found in the LICENSE file.
4 |
5 | // A stupid and simple unit test framework for C++ code.
6 | // Evan Jones
7 |
8 | #include "stupidunit/stupidunit.h"
9 |
10 | #include
11 | #include
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include
17 |
18 | #include
19 | #include
20 | #include
21 | #include
22 |
23 | #include "base/assert.h"
24 |
25 | using std::string;
26 |
27 | // Contains and runs a collection of tests.
28 | void TestSuite::registerTest(Test* (*test_factory)()) {
29 | ASSERT(test_factory != NULL);
30 | test_factories_.push_back(test_factory);
31 | }
32 |
33 | // JSON requires the following characters to be escaped in strings:
34 | // quotation mark, revrse solidus, and U+0000 through U+001F.
35 | // http://www.ietf.org/rfc/rfc4627.txt
36 | // TODO: This should link against the version in strings/json.h
37 | static void jsonEscape(string* s) {
38 | static const char ESCAPES[] = { '"', '\\', '\b', '\f', '\n', '\r', '\t' };
39 | static const char REPLACEMENTS[] = { '"', '\\', 'b', 'f', 'n', 'r', 't' };
40 | ASSERT(sizeof(ESCAPES) == sizeof(REPLACEMENTS));
41 |
42 | for (size_t i = 0; i < s->size(); ++i) {
43 | char c = (*s)[i];
44 | if ((0 <= c && c <= 0x1f) || c == '"' || c =='\\') {
45 | // The character must be replaced with something: look in escapes
46 | bool replaced = false;
47 | for (int j = 0; j < sizeof(ESCAPES); ++j) {
48 | if (ESCAPES[j] == c) {
49 | replaced = true;
50 | (*s)[i] = '\\';
51 | i += 1;
52 | s->insert(i, 1, REPLACEMENTS[j]);
53 | break;
54 | }
55 | }
56 | if (!replaced) {
57 | // Use a hex escape sequence
58 | char hex[7];
59 | int bytes = snprintf(hex, sizeof(hex), "\\u%04x", (int) c);
60 | ASSERT(bytes == sizeof(hex)-1);
61 | s->replace(i, 1, hex, sizeof(hex)-1);
62 | // normally move forward 1 character, so move past the entire escape
63 | i += sizeof(hex) - 2;
64 | }
65 | }
66 | }
67 | }
68 |
69 | int TestSuite::runAll() {
70 | // Change to the root directory to avoid tests that depend on files, etc.
71 | int status = chdir("/");
72 | ASSERT(status == 0);
73 |
74 | // Look to see if we should produce machine readable output
75 | const char* machine_readable = getenv(stupidunit::OUT_FILE_ENVIRONMENT_VARIABLE);
76 | int json_output = -1;
77 | if (machine_readable != NULL && machine_readable[0] != '\0') {
78 | json_output = open(machine_readable, O_WRONLY | O_CREAT | O_EXCL, 0666);
79 | if (json_output == -1 && errno == EEXIST) {
80 | fprintf(stderr,
81 | "ERROR: %s file (%s) already exists: remove this file to run the tests",
82 | stupidunit::OUT_FILE_ENVIRONMENT_VARIABLE, machine_readable);
83 | abort();
84 | }
85 | ASSERT(json_output >= 0);
86 |
87 | ssize_t bytes = write(json_output, "[", 1);
88 | ASSERT(bytes == 1);
89 | }
90 |
91 | int failed_tests = 0;
92 | const char* last_suite = NULL;
93 | for (size_t i = 0; i < test_factories_.size(); ++i) {
94 | // Create the test
95 | Test* test = test_factories_[i]();
96 | ASSERT(test != NULL);
97 |
98 | // Print the suite name if it is new
99 | if (last_suite == NULL || strcmp(test->suiteName(), last_suite) != 0) {
100 | if (last_suite != NULL) printf("\n");
101 | last_suite = test->suiteName();
102 | printf("%s:\n", last_suite);
103 | }
104 |
105 | // Print the test name
106 | printf("\t%s: ", test->testName());
107 | fflush(stdout);
108 |
109 | // run the test and check the result
110 | test->run();
111 | if (test->testSuccess()) {
112 | printf("PASSED.\n");
113 | } else {
114 | printf("FAILED.\n");
115 | test->printErrors();
116 | printf("\n");
117 | failed_tests++;
118 | }
119 |
120 | if (json_output != -1) {
121 | // TODO: We probably should use the JSON builder code in strings
122 | string json = "{\"class_name\": \"";
123 | json += test->suiteName();
124 | json += "\", \"name\": \"";
125 | json += test->testName();
126 | json += "\"";
127 | if (!test->testSuccess()) {
128 | json += ", \"failure\": \"";
129 | for (int j = 0; j < test->stupidunitNumErrors(); ++j) {
130 | string message = test->stupidunitError(j);
131 | jsonEscape(&message);
132 | json += message;
133 | json += "\\n";
134 | }
135 | json += "\"";
136 | }
137 | json += "}";
138 |
139 | if (i != test_factories_.size() - 1) {
140 | json += ",\n";
141 | } else {
142 | json += "]\n";
143 | }
144 |
145 | ssize_t bytes = write(json_output, json.data(), json.size());
146 | ASSERT(bytes == json.size());
147 | }
148 |
149 | // Clean up the test
150 | delete test;
151 | }
152 |
153 | if (json_output != -1) {
154 | int error = close(json_output);
155 | ASSERT(error == 0);
156 | }
157 |
158 | if (failed_tests == 0) {
159 | printf("PASSED\n");
160 | } else {
161 | printf("%d FAILED\n", failed_tests);
162 | }
163 | return failed_tests;
164 | }
165 |
166 | TestSuite* TestSuite::globalInstance() {
167 | // Avoids static initialization order problems, although it could have destructor order
168 | // problems if the TestSuite destructor did anything. See:
169 | // http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.12
170 | static TestSuite global_suite;
171 | return &global_suite;
172 | }
173 |
174 | void Test::fail(const char* file, int line, const char* message) {
175 | std::ostringstream output;
176 | output << file << ":" << line << ": Test failed: " << message;
177 | errors_.push_back(output.str());
178 | }
179 |
180 | void Test::printErrors() const {
181 | for (size_t i = 0; i < errors_.size(); ++i) {
182 | printf("%s\n", errors_[i].c_str());
183 | }
184 | }
185 |
186 | const string& Test::stupidunitError(int i) const {
187 | ASSERT(0 <= i && i < errors_.size());
188 | return errors_[i];
189 | }
190 |
191 | namespace stupidunit {
192 |
193 | // P_tmpdir comes from stdio.h (see tempnam). TODO: Look at environment variables?
194 | ChTempDir::ChTempDir() : name_(P_tmpdir) {
195 | if (name_[name_.size()-1] != '/') {
196 | name_.push_back('/');
197 | }
198 | name_ += "test_XXXXXX";
199 | // Abuse the string to modify it in place
200 | #ifndef __sun
201 | char* result = mkdtemp(&*name_.begin());
202 | #else
203 | // Solaris doesn't seem to have mkdtemp?
204 | char* result = NULL;
205 | char* temp = &*name_.begin();
206 | if (mktemp(temp) && mkdir(temp, 0700) == 0) {
207 | result = temp;
208 | }
209 | #endif
210 | // TODO: Abort/throw on error
211 | ASSERT(result != NULL);
212 | ASSERT(result == name_.c_str());
213 |
214 | int status = chdir(name_.c_str());
215 | ASSERT(status == 0);
216 | }
217 |
218 | // Recursively deletes the file named path. If path is a file, it will be
219 | // removed. If it is a directory, everything in it will also be deleted.
220 | // Returns 0 on success, -1 on error, and sets errno appropriately.
221 | static int rmtree(const char* path) {
222 | // TODO: Handle errors in a more intelligent fashion?
223 | DIR* dir = opendir(path);
224 | if (dir == NULL) {
225 | if (errno == ENOTDIR) {
226 | // Not a directory: unlink it instead
227 | return unlink(path);
228 | }
229 |
230 | return -1;
231 | }
232 | ASSERT(dir != NULL);
233 |
234 | for (struct dirent* entry = readdir(dir); entry != NULL; entry = readdir(dir)) {
235 | // Skip special directories
236 | if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
237 | continue;
238 | }
239 |
240 | // Recursively delete the directory entry. This handles regular files
241 | // and directories.
242 | string fullpath(path);
243 | fullpath += "/";
244 | fullpath += entry->d_name;
245 | rmtree(fullpath.c_str());
246 | }
247 |
248 | int error = closedir(dir);
249 | ASSERT(error == 0);
250 |
251 | return rmdir(path);
252 | }
253 |
254 | ChTempDir::~ChTempDir() {
255 | // TODO: chdir back to the original directory?
256 | int status = chdir("/");
257 | ASSERT(status == 0);
258 |
259 | // Recursively delete everything in the temporary directory.
260 | status = rmtree(name_.c_str());
261 | ASSERT(status == 0);
262 | }
263 |
264 | // TODO: Capture and match client output
265 | ExpectDeathStatus expectDeath() {
266 | // Create a pipe for the child's output
267 | int pipe_descriptors[2];
268 | int error = pipe(pipe_descriptors);
269 | ASSERT(error == 0);
270 |
271 |
272 | pid_t expect_death_pid = fork();
273 | if (expect_death_pid == 0) {
274 | // Capture the child's output: replace stdout and stderr with the pipe
275 | error = dup2(pipe_descriptors[1], 1);
276 | ASSERT(error == 1);
277 | error = dup2(pipe_descriptors[1], 2);
278 | ASSERT(error == 2);
279 |
280 | // This is the child: tell the macro to run the block
281 | return EXECUTE_BLOCK;
282 | }
283 |
284 | // Parent: close the write end of the pipe
285 | error = close(pipe_descriptors[1]);
286 | ASSERT(error == 0);
287 |
288 | // Read the child's output
289 | string output;
290 | char buffer[4096];
291 | ssize_t bytes = 0;
292 | while ((bytes = read(pipe_descriptors[0], buffer, sizeof(buffer))) > 0
293 | || (bytes == -1 && errno == EINTR)) {
294 | if (bytes == -1) {
295 | // On Mac OS X under gdb, read returns EINTR when the child dies: ignore it
296 | assert(errno == EINTR);
297 | } else {
298 | output.append(buffer, bytes);
299 | }
300 | }
301 | ASSERT(bytes == 0);
302 | error = close(pipe_descriptors[0]);
303 | ASSERT(error == 0);
304 |
305 | // Collect the child's output status
306 | int expect_death_status = -1;
307 | waitpid(expect_death_pid, &expect_death_status, 0);
308 | if (WIFEXITED(expect_death_status)) {
309 | // The block exited: it was supposed to die!
310 | return FAILED;
311 | }
312 |
313 | // The client failed in some way: great
314 | return SUCCESS;
315 | }
316 |
317 | const char OUT_FILE_ENVIRONMENT_VARIABLE[] = "STUPIDUNIT_OUTPUT";
318 |
319 | } // namespace stupidunit
320 |
--------------------------------------------------------------------------------
/crc32c/stupidunit/stupidunit.h:
--------------------------------------------------------------------------------
1 | // Copyright 2008,2009,2010 Massachusetts Institute of Technology.
2 | // All rights reserved. Use of this source code is governed by a
3 | // BSD-style license that can be found in the LICENSE file.
4 |
5 | // A stupid and simple unit test framework for C++ code.
6 | // Evan Jones
7 |
8 | #ifndef STUPIDUNIT_H__
9 | #define STUPIDUNIT_H__
10 |
11 | #include
12 | #include
13 | #include
14 |
15 | class Test;
16 |
17 | // Contains and runs a collection of tests.
18 | class TestSuite {
19 | public:
20 | void registerTest(Test* (*test_factory)());
21 |
22 | // Returns the number of failed tests.
23 | int runAll();
24 |
25 | // Returns a properly initialized static global TestSuite. This is the "standard" test suite
26 | // used by the TEST and TEST_F macros.
27 | static TestSuite* globalInstance();
28 |
29 | private:
30 | std::vector test_factories_;
31 | };
32 |
33 | // Base class for a single test. Each test creates a subclass of this that
34 | // implements run(). Users create subclasses via the TEST_F helper macro.
35 | class Test {
36 | public:
37 | Test() {}
38 | virtual ~Test() {}
39 |
40 | // Run the actual test.
41 | virtual void run() = 0;
42 |
43 | virtual const char* suiteName() const = 0;
44 | virtual const char* testName() const = 0;
45 | bool testSuccess() const { return errors_.empty(); }
46 |
47 | // Fail the test with error.
48 | void fail(const char* file, int line, const char* message);
49 |
50 | // Output the errors for this test to standard output.
51 | void printErrors() const;
52 |
53 | int stupidunitNumErrors() const { return static_cast(errors_.size()); }
54 | const std::string& stupidunitError(int i) const;
55 |
56 | private:
57 | // Contains error messages if the test failed.
58 | std::vector errors_;
59 | };
60 |
61 | // A class used to statically register test instances with the global test suite.
62 | template
63 | class RegisterTest {
64 | public:
65 | RegisterTest(TestSuite* suite) {
66 | suite->registerTest(&RegisterTest::create);
67 | }
68 |
69 | static Test* create() {
70 | return new T();
71 | }
72 | };
73 |
74 | // Creates a test subclass.
75 | #define MAGIC_TEST_MACRO(parent_class, suite_name, test_name) \
76 | class suite_name ## _ ## test_name : public parent_class { \
77 | public: \
78 | virtual ~suite_name ## _ ## test_name() {} \
79 | virtual void run(); \
80 | virtual const char* suiteName() const { return suite_name_; } \
81 | virtual const char* testName() const { return test_name_; } \
82 | \
83 | private: \
84 | static const char suite_name_[]; \
85 | static const char test_name_[]; \
86 | }; \
87 | const char suite_name ## _ ## test_name::suite_name_[] = #suite_name; \
88 | const char suite_name ## _ ## test_name::test_name_[] = #test_name; \
89 | static RegisterTest suite_name ## _ ## test_name ## _register(TestSuite::globalInstance()); \
90 | void suite_name ## _ ## test_name::run()
91 |
92 | // A magic macro to make a test part of a user-defined test subclass.
93 | #define TEST_F(harness_name, test_name) MAGIC_TEST_MACRO(harness_name, harness_name, test_name)
94 |
95 | // A magic macro to make a test subclass for a block of code.
96 | #define TEST(suite_name, test_name) MAGIC_TEST_MACRO(Test, suite_name, test_name)
97 |
98 | // Abuse macros to easily define all the EXPECT and ASSERT variants
99 | #define STUPIDUNIT_MAKE_EXPECT_MACRO(operation, one, two) do { \
100 | if (!((one) operation (two))) fail(__FILE__, __LINE__, #one " " #operation " " #two); \
101 | } while (0)
102 |
103 | #define EXPECT_EQ(one, two) STUPIDUNIT_MAKE_EXPECT_MACRO(==, one, two)
104 | #define EXPECT_NE(one, two) STUPIDUNIT_MAKE_EXPECT_MACRO(!=, one, two)
105 | #define EXPECT_LT(one, two) STUPIDUNIT_MAKE_EXPECT_MACRO(<, one, two)
106 | #define EXPECT_LE(one, two) STUPIDUNIT_MAKE_EXPECT_MACRO(<=, one, two)
107 | #define EXPECT_GT(one, two) STUPIDUNIT_MAKE_EXPECT_MACRO(>, one, two)
108 | #define EXPECT_GE(one, two) STUPIDUNIT_MAKE_EXPECT_MACRO(>=, one, two)
109 |
110 | #define EXPECT_TRUE(value) do { \
111 | if (!(value)) fail(__FILE__, __LINE__, "Expected true; " #value " is false"); \
112 | } while (0)
113 | #define EXPECT_FALSE(value) do { \
114 | if ((value)) fail(__FILE__, __LINE__, "Expected false; " #value " is true"); \
115 | } while (0)
116 |
117 | // The only difference between EXPECT and ASSERT is that ASSERT returns from
118 | // the test method if the test fails
119 | #define STUPIDUNIT_MAKE_ASSERT_MACRO(operation, one, two) do { \
120 | if (!((one) operation (two))) { fail(__FILE__, __LINE__, #one " " #operation " " #two); return; } \
121 | } while (0)
122 |
123 | #define ASSERT_EQ(one, two) STUPIDUNIT_MAKE_ASSERT_MACRO(==, one, two)
124 | #define ASSERT_NE(one, two) STUPIDUNIT_MAKE_ASSERT_MACRO(!=, one, two)
125 | #define ASSERT_LT(one, two) STUPIDUNIT_MAKE_ASSERT_MACRO(<, one, two)
126 | #define ASSERT_LE(one, two) STUPIDUNIT_MAKE_ASSERT_MACRO(<=, one, two)
127 | #define ASSERT_GT(one, two) STUPIDUNIT_MAKE_ASSERT_MACRO(>, one, two)
128 | #define ASSERT_GE(one, two) STUPIDUNIT_MAKE_ASSERT_MACRO(>=, one, two)
129 |
130 | #define ASSERT_TRUE(value) do { \
131 | if (!(value)) { fail(__FILE__, __LINE__, "Expected true; " #value " is false"); return; } \
132 | } while (0)
133 | #define ASSERT_FALSE(value) do { \
134 | if ((value)) { fail(__FILE__, __LINE__, "Expected false; " #value " is true"); return; } \
135 | } while (0)
136 |
137 |
138 | namespace stupidunit {
139 |
140 | enum ExpectDeathStatus {
141 | // The caller is the child: run the block and exit.
142 | EXECUTE_BLOCK,
143 | SUCCESS,
144 | FAILED
145 | };
146 |
147 | // Implements EXPECT_DEATH.
148 | ExpectDeathStatus expectDeath();
149 |
150 | // Helper that creates a temporary directory then changes into it. The
151 | // directory will be automatically removed in the destructor.
152 | class ChTempDir {
153 | public:
154 | ChTempDir();
155 | ~ChTempDir();
156 |
157 | const std::string& name() const { return name_; }
158 |
159 | private:
160 | // The name of the temporary directory.
161 | std::string name_;
162 | };
163 |
164 | extern const char OUT_FILE_ENVIRONMENT_VARIABLE[];
165 |
166 | } // namespace stupidunit
167 |
168 | #define EXPECT_DEATH(block) do { \
169 | stupidunit::ExpectDeathStatus status = stupidunit::expectDeath(); \
170 | if (status == stupidunit::EXECUTE_BLOCK) { \
171 | block; \
172 | exit(0); \
173 | } else if (status == stupidunit::FAILED) { \
174 | fail(__FILE__, __LINE__, "EXPECT_DEATH(" #block "): did not die"); \
175 | } \
176 | } while (0)
177 |
178 | #endif // STUPIDUNIT_H__
179 |
--------------------------------------------------------------------------------