├── 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 | ![Benchmarks](crc32c-benchmarks.png) 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 | --------------------------------------------------------------------------------