1ab9e68a2SToomas Soome /* crc32.c -- compute the CRC-32 of a data stream 2*64c3d159SToomas Soome * Copyright (C) 1995-2022 Mark Adler 3ab9e68a2SToomas Soome * For conditions of distribution and use, see copyright notice in zlib.h 4ab9e68a2SToomas Soome * 5*64c3d159SToomas Soome * This interleaved implementation of a CRC makes use of pipelined multiple 6*64c3d159SToomas Soome * arithmetic-logic units, commonly found in modern CPU cores. It is due to 7*64c3d159SToomas Soome * Kadatch and Jenkins (2010). See doc/crc-doc.1.0.pdf in this distribution. 8ab9e68a2SToomas Soome */ 9ab9e68a2SToomas Soome 10ab9e68a2SToomas Soome /* 11ab9e68a2SToomas Soome Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore 12ab9e68a2SToomas Soome protection on the static variables used to control the first-use generation 13ab9e68a2SToomas Soome of the crc tables. Therefore, if you #define DYNAMIC_CRC_TABLE, you should 14ab9e68a2SToomas Soome first call get_crc_table() to initialize the tables before allowing more than 15ab9e68a2SToomas Soome one thread to use crc32(). 16ab9e68a2SToomas Soome 17*64c3d159SToomas Soome MAKECRCH can be #defined to write out crc32.h. A main() routine is also 18*64c3d159SToomas Soome produced, so that this one source file can be compiled to an executable. 19ab9e68a2SToomas Soome */ 20ab9e68a2SToomas Soome 21ab9e68a2SToomas Soome #ifdef MAKECRCH 22ab9e68a2SToomas Soome # include <stdio.h> 23ab9e68a2SToomas Soome # ifndef DYNAMIC_CRC_TABLE 24ab9e68a2SToomas Soome # define DYNAMIC_CRC_TABLE 25ab9e68a2SToomas Soome # endif /* !DYNAMIC_CRC_TABLE */ 26ab9e68a2SToomas Soome #endif /* MAKECRCH */ 27ab9e68a2SToomas Soome 28*64c3d159SToomas Soome #include "zutil.h" /* for Z_U4, Z_U8, z_crc_t, and FAR definitions */ 29ab9e68a2SToomas Soome 30*64c3d159SToomas Soome /* 31*64c3d159SToomas Soome A CRC of a message is computed on N braids of words in the message, where 32*64c3d159SToomas Soome each word consists of W bytes (4 or 8). If N is 3, for example, then three 33*64c3d159SToomas Soome running sparse CRCs are calculated respectively on each braid, at these 34*64c3d159SToomas Soome indices in the array of words: 0, 3, 6, ..., 1, 4, 7, ..., and 2, 5, 8, ... 35*64c3d159SToomas Soome This is done starting at a word boundary, and continues until as many blocks 36*64c3d159SToomas Soome of N * W bytes as are available have been processed. The results are combined 37*64c3d159SToomas Soome into a single CRC at the end. For this code, N must be in the range 1..6 and 38*64c3d159SToomas Soome W must be 4 or 8. The upper limit on N can be increased if desired by adding 39*64c3d159SToomas Soome more #if blocks, extending the patterns apparent in the code. In addition, 40*64c3d159SToomas Soome crc32.h would need to be regenerated, if the maximum N value is increased. 41*64c3d159SToomas Soome 42*64c3d159SToomas Soome N and W are chosen empirically by benchmarking the execution time on a given 43*64c3d159SToomas Soome processor. The choices for N and W below were based on testing on Intel Kaby 44*64c3d159SToomas Soome Lake i7, AMD Ryzen 7, ARM Cortex-A57, Sparc64-VII, PowerPC POWER9, and MIPS64 45*64c3d159SToomas Soome Octeon II processors. The Intel, AMD, and ARM processors were all fastest 46*64c3d159SToomas Soome with N=5, W=8. The Sparc, PowerPC, and MIPS64 were all fastest at N=5, W=4. 47*64c3d159SToomas Soome They were all tested with either gcc or clang, all using the -O3 optimization 48*64c3d159SToomas Soome level. Your mileage may vary. 49*64c3d159SToomas Soome */ 50*64c3d159SToomas Soome 51*64c3d159SToomas Soome /* Define N */ 52*64c3d159SToomas Soome #ifdef Z_TESTN 53*64c3d159SToomas Soome # define N Z_TESTN 54ab9e68a2SToomas Soome #else 55*64c3d159SToomas Soome # define N 5 56*64c3d159SToomas Soome #endif 57*64c3d159SToomas Soome #if N < 1 || N > 6 58*64c3d159SToomas Soome # error N must be in 1..6 59*64c3d159SToomas Soome #endif 60ab9e68a2SToomas Soome 61*64c3d159SToomas Soome /* 62*64c3d159SToomas Soome z_crc_t must be at least 32 bits. z_word_t must be at least as long as 63*64c3d159SToomas Soome z_crc_t. It is assumed here that z_word_t is either 32 bits or 64 bits, and 64*64c3d159SToomas Soome that bytes are eight bits. 65*64c3d159SToomas Soome */ 66ab9e68a2SToomas Soome 67*64c3d159SToomas Soome /* 68*64c3d159SToomas Soome Define W and the associated z_word_t type. If W is not defined, then a 69*64c3d159SToomas Soome braided calculation is not used, and the associated tables and code are not 70*64c3d159SToomas Soome compiled. 71*64c3d159SToomas Soome */ 72*64c3d159SToomas Soome #ifdef Z_TESTW 73*64c3d159SToomas Soome # if Z_TESTW-1 != -1 74*64c3d159SToomas Soome # define W Z_TESTW 75*64c3d159SToomas Soome # endif 76*64c3d159SToomas Soome #else 77*64c3d159SToomas Soome # ifdef MAKECRCH 78*64c3d159SToomas Soome # define W 8 /* required for MAKECRCH */ 79*64c3d159SToomas Soome # else 80*64c3d159SToomas Soome # if defined(__x86_64__) || defined(__aarch64__) 81*64c3d159SToomas Soome # define W 8 82*64c3d159SToomas Soome # else 83*64c3d159SToomas Soome # define W 4 84*64c3d159SToomas Soome # endif 85*64c3d159SToomas Soome # endif 86*64c3d159SToomas Soome #endif 87*64c3d159SToomas Soome #ifdef W 88*64c3d159SToomas Soome # if W == 8 && defined(Z_U8) 89*64c3d159SToomas Soome typedef Z_U8 z_word_t; 90*64c3d159SToomas Soome # elif defined(Z_U4) 91*64c3d159SToomas Soome # undef W 92*64c3d159SToomas Soome # define W 4 93*64c3d159SToomas Soome typedef Z_U4 z_word_t; 94*64c3d159SToomas Soome # else 95*64c3d159SToomas Soome # undef W 96*64c3d159SToomas Soome # endif 97*64c3d159SToomas Soome #endif 98*64c3d159SToomas Soome 99*64c3d159SToomas Soome /* Local functions. */ 100*64c3d159SToomas Soome local z_crc_t multmodp OF((z_crc_t a, z_crc_t b)); 101*64c3d159SToomas Soome local z_crc_t x2nmodp OF((z_off64_t n, unsigned k)); 102*64c3d159SToomas Soome 103*64c3d159SToomas Soome /* If available, use the ARM processor CRC32 instruction. */ 104*64c3d159SToomas Soome #if defined(__aarch64__) && defined(__ARM_FEATURE_CRC32) && W == 8 105*64c3d159SToomas Soome # define ARMCRC32 106*64c3d159SToomas Soome #endif 107*64c3d159SToomas Soome 108*64c3d159SToomas Soome #if defined(W) && (!defined(ARMCRC32) || defined(DYNAMIC_CRC_TABLE)) 109*64c3d159SToomas Soome /* 110*64c3d159SToomas Soome Swap the bytes in a z_word_t to convert between little and big endian. Any 111*64c3d159SToomas Soome self-respecting compiler will optimize this to a single machine byte-swap 112*64c3d159SToomas Soome instruction, if one is available. This assumes that word_t is either 32 bits 113*64c3d159SToomas Soome or 64 bits. 114*64c3d159SToomas Soome */ 115*64c3d159SToomas Soome local z_word_t byte_swap(z_word_t word) 116*64c3d159SToomas Soome { 117*64c3d159SToomas Soome # if W == 8 118*64c3d159SToomas Soome return 119*64c3d159SToomas Soome (word & 0xff00000000000000) >> 56 | 120*64c3d159SToomas Soome (word & 0xff000000000000) >> 40 | 121*64c3d159SToomas Soome (word & 0xff0000000000) >> 24 | 122*64c3d159SToomas Soome (word & 0xff00000000) >> 8 | 123*64c3d159SToomas Soome (word & 0xff000000) << 8 | 124*64c3d159SToomas Soome (word & 0xff0000) << 24 | 125*64c3d159SToomas Soome (word & 0xff00) << 40 | 126*64c3d159SToomas Soome (word & 0xff) << 56; 127*64c3d159SToomas Soome # else /* W == 4 */ 128*64c3d159SToomas Soome return 129*64c3d159SToomas Soome (word & 0xff000000) >> 24 | 130*64c3d159SToomas Soome (word & 0xff0000) >> 8 | 131*64c3d159SToomas Soome (word & 0xff00) << 8 | 132*64c3d159SToomas Soome (word & 0xff) << 24; 133*64c3d159SToomas Soome # endif 134*64c3d159SToomas Soome } 135*64c3d159SToomas Soome #endif 136*64c3d159SToomas Soome 137*64c3d159SToomas Soome /* CRC polynomial. */ 138*64c3d159SToomas Soome #define POLY 0xedb88320 /* p(x) reflected, with x^32 implied */ 139ab9e68a2SToomas Soome 140ab9e68a2SToomas Soome #ifdef DYNAMIC_CRC_TABLE 141ab9e68a2SToomas Soome 142*64c3d159SToomas Soome local z_crc_t FAR crc_table[256]; 143*64c3d159SToomas Soome local z_crc_t FAR x2n_table[32]; 144ab9e68a2SToomas Soome local void make_crc_table OF((void)); 145*64c3d159SToomas Soome #ifdef W 146*64c3d159SToomas Soome local z_word_t FAR crc_big_table[256]; 147*64c3d159SToomas Soome local z_crc_t FAR crc_braid_table[W][256]; 148*64c3d159SToomas Soome local z_word_t FAR crc_braid_big_table[W][256]; 149*64c3d159SToomas Soome local void braid OF((z_crc_t [][256], z_word_t [][256], int, int)); 150*64c3d159SToomas Soome #endif 151ab9e68a2SToomas Soome #ifdef MAKECRCH 152*64c3d159SToomas Soome local void write_table OF((FILE *, const z_crc_t FAR *, int)); 153*64c3d159SToomas Soome local void write_table32hi OF((FILE *, const z_word_t FAR *, int)); 154*64c3d159SToomas Soome local void write_table64 OF((FILE *, const z_word_t FAR *, int)); 155ab9e68a2SToomas Soome #endif /* MAKECRCH */ 156*64c3d159SToomas Soome 157*64c3d159SToomas Soome /* 158*64c3d159SToomas Soome Define a once() function depending on the availability of atomics. If this is 159*64c3d159SToomas Soome compiled with DYNAMIC_CRC_TABLE defined, and if CRCs will be computed in 160*64c3d159SToomas Soome multiple threads, and if atomics are not available, then get_crc_table() must 161*64c3d159SToomas Soome be called to initialize the tables and must return before any threads are 162*64c3d159SToomas Soome allowed to compute or combine CRCs. 163*64c3d159SToomas Soome */ 164*64c3d159SToomas Soome 165*64c3d159SToomas Soome /* Definition of once functionality. */ 166*64c3d159SToomas Soome typedef struct once_s once_t; 167*64c3d159SToomas Soome local void once OF((once_t *, void (*)(void))); 168*64c3d159SToomas Soome 169*64c3d159SToomas Soome /* Check for the availability of atomics. */ 170*64c3d159SToomas Soome #if defined(__STDC__) && __STDC_VERSION__ >= 201112L && \ 171*64c3d159SToomas Soome !defined(__STDC_NO_ATOMICS__) 172*64c3d159SToomas Soome 173*64c3d159SToomas Soome #include <stdatomic.h> 174*64c3d159SToomas Soome 175*64c3d159SToomas Soome /* Structure for once(), which must be initialized with ONCE_INIT. */ 176*64c3d159SToomas Soome struct once_s { 177*64c3d159SToomas Soome atomic_flag begun; 178*64c3d159SToomas Soome atomic_int done; 179*64c3d159SToomas Soome }; 180*64c3d159SToomas Soome #define ONCE_INIT {ATOMIC_FLAG_INIT, 0} 181*64c3d159SToomas Soome 182*64c3d159SToomas Soome /* 183*64c3d159SToomas Soome Run the provided init() function exactly once, even if multiple threads 184*64c3d159SToomas Soome invoke once() at the same time. The state must be a once_t initialized with 185*64c3d159SToomas Soome ONCE_INIT. 186*64c3d159SToomas Soome */ 187*64c3d159SToomas Soome local void once(state, init) 188*64c3d159SToomas Soome once_t *state; 189*64c3d159SToomas Soome void (*init)(void); 190*64c3d159SToomas Soome { 191*64c3d159SToomas Soome if (!atomic_load(&state->done)) { 192*64c3d159SToomas Soome if (atomic_flag_test_and_set(&state->begun)) 193*64c3d159SToomas Soome while (!atomic_load(&state->done)) 194*64c3d159SToomas Soome ; 195*64c3d159SToomas Soome else { 196*64c3d159SToomas Soome init(); 197*64c3d159SToomas Soome atomic_store(&state->done, 1); 198*64c3d159SToomas Soome } 199*64c3d159SToomas Soome } 200*64c3d159SToomas Soome } 201*64c3d159SToomas Soome 202*64c3d159SToomas Soome #else /* no atomics */ 203*64c3d159SToomas Soome 204*64c3d159SToomas Soome /* Structure for once(), which must be initialized with ONCE_INIT. */ 205*64c3d159SToomas Soome struct once_s { 206*64c3d159SToomas Soome volatile int begun; 207*64c3d159SToomas Soome volatile int done; 208*64c3d159SToomas Soome }; 209*64c3d159SToomas Soome #define ONCE_INIT {0, 0} 210*64c3d159SToomas Soome 211*64c3d159SToomas Soome /* Test and set. Alas, not atomic, but tries to minimize the period of 212*64c3d159SToomas Soome vulnerability. */ 213*64c3d159SToomas Soome local int test_and_set OF((int volatile *)); 214*64c3d159SToomas Soome local int test_and_set(flag) 215*64c3d159SToomas Soome int volatile *flag; 216*64c3d159SToomas Soome { 217*64c3d159SToomas Soome int was; 218*64c3d159SToomas Soome 219*64c3d159SToomas Soome was = *flag; 220*64c3d159SToomas Soome *flag = 1; 221*64c3d159SToomas Soome return was; 222*64c3d159SToomas Soome } 223*64c3d159SToomas Soome 224*64c3d159SToomas Soome /* Run the provided init() function once. This is not thread-safe. */ 225*64c3d159SToomas Soome local void once(state, init) 226*64c3d159SToomas Soome once_t *state; 227*64c3d159SToomas Soome void (*init)(void); 228*64c3d159SToomas Soome { 229*64c3d159SToomas Soome if (!state->done) { 230*64c3d159SToomas Soome if (test_and_set(&state->begun)) 231*64c3d159SToomas Soome while (!state->done) 232*64c3d159SToomas Soome ; 233*64c3d159SToomas Soome else { 234*64c3d159SToomas Soome init(); 235*64c3d159SToomas Soome state->done = 1; 236*64c3d159SToomas Soome } 237*64c3d159SToomas Soome } 238*64c3d159SToomas Soome } 239*64c3d159SToomas Soome 240*64c3d159SToomas Soome #endif 241*64c3d159SToomas Soome 242*64c3d159SToomas Soome /* State for once(). */ 243*64c3d159SToomas Soome local once_t made = ONCE_INIT; 244*64c3d159SToomas Soome 245ab9e68a2SToomas Soome /* 246ab9e68a2SToomas Soome Generate tables for a byte-wise 32-bit CRC calculation on the polynomial: 247ab9e68a2SToomas Soome x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. 248ab9e68a2SToomas Soome 249ab9e68a2SToomas Soome Polynomials over GF(2) are represented in binary, one bit per coefficient, 250ab9e68a2SToomas Soome with the lowest powers in the most significant bit. Then adding polynomials 251ab9e68a2SToomas Soome is just exclusive-or, and multiplying a polynomial by x is a right shift by 252ab9e68a2SToomas Soome one. If we call the above polynomial p, and represent a byte as the 253ab9e68a2SToomas Soome polynomial q, also with the lowest power in the most significant bit (so the 254*64c3d159SToomas Soome byte 0xb1 is the polynomial x^7+x^3+x^2+1), then the CRC is (q*x^32) mod p, 255ab9e68a2SToomas Soome where a mod b means the remainder after dividing a by b. 256ab9e68a2SToomas Soome 257ab9e68a2SToomas Soome This calculation is done using the shift-register method of multiplying and 258ab9e68a2SToomas Soome taking the remainder. The register is initialized to zero, and for each 259ab9e68a2SToomas Soome incoming bit, x^32 is added mod p to the register if the bit is a one (where 260*64c3d159SToomas Soome x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by x 261*64c3d159SToomas Soome (which is shifting right by one and adding x^32 mod p if the bit shifted out 262*64c3d159SToomas Soome is a one). We start with the highest power (least significant bit) of q and 263*64c3d159SToomas Soome repeat for all eight bits of q. 264ab9e68a2SToomas Soome 265*64c3d159SToomas Soome The table is simply the CRC of all possible eight bit values. This is all the 266*64c3d159SToomas Soome information needed to generate CRCs on data a byte at a time for all 267*64c3d159SToomas Soome combinations of CRC register values and incoming bytes. 268ab9e68a2SToomas Soome */ 269*64c3d159SToomas Soome 270ab9e68a2SToomas Soome local void make_crc_table() 271ab9e68a2SToomas Soome { 272*64c3d159SToomas Soome unsigned i, j, n; 273*64c3d159SToomas Soome z_crc_t p; 274ab9e68a2SToomas Soome 275*64c3d159SToomas Soome /* initialize the CRC of bytes tables */ 276*64c3d159SToomas Soome for (i = 0; i < 256; i++) { 277*64c3d159SToomas Soome p = i; 278*64c3d159SToomas Soome for (j = 0; j < 8; j++) 279*64c3d159SToomas Soome p = p & 1 ? (p >> 1) ^ POLY : p >> 1; 280*64c3d159SToomas Soome crc_table[i] = p; 281*64c3d159SToomas Soome #ifdef W 282*64c3d159SToomas Soome crc_big_table[i] = byte_swap(p); 283*64c3d159SToomas Soome #endif 284ab9e68a2SToomas Soome } 285ab9e68a2SToomas Soome 286*64c3d159SToomas Soome /* initialize the x^2^n mod p(x) table */ 287*64c3d159SToomas Soome p = (z_crc_t)1 << 30; /* x^1 */ 288*64c3d159SToomas Soome x2n_table[0] = p; 289*64c3d159SToomas Soome for (n = 1; n < 32; n++) 290*64c3d159SToomas Soome x2n_table[n] = p = multmodp(p, p); 291ab9e68a2SToomas Soome 292*64c3d159SToomas Soome #ifdef W 293*64c3d159SToomas Soome /* initialize the braiding tables -- needs x2n_table[] */ 294*64c3d159SToomas Soome braid(crc_braid_table, crc_braid_big_table, N, W); 295*64c3d159SToomas Soome #endif 296ab9e68a2SToomas Soome 297ab9e68a2SToomas Soome #ifdef MAKECRCH 298ab9e68a2SToomas Soome { 299*64c3d159SToomas Soome /* 300*64c3d159SToomas Soome The crc32.h header file contains tables for both 32-bit and 64-bit 301*64c3d159SToomas Soome z_word_t's, and so requires a 64-bit type be available. In that case, 302*64c3d159SToomas Soome z_word_t must be defined to be 64-bits. This code then also generates 303*64c3d159SToomas Soome and writes out the tables for the case that z_word_t is 32 bits. 304*64c3d159SToomas Soome */ 305*64c3d159SToomas Soome #if !defined(W) || W != 8 306*64c3d159SToomas Soome # error Need a 64-bit integer type in order to generate crc32.h. 307*64c3d159SToomas Soome #endif 308ab9e68a2SToomas Soome FILE *out; 309*64c3d159SToomas Soome int k, n; 310*64c3d159SToomas Soome z_crc_t ltl[8][256]; 311*64c3d159SToomas Soome z_word_t big[8][256]; 312ab9e68a2SToomas Soome 313ab9e68a2SToomas Soome out = fopen("crc32.h", "w"); 314ab9e68a2SToomas Soome if (out == NULL) return; 315*64c3d159SToomas Soome 316*64c3d159SToomas Soome /* write out little-endian CRC table to crc32.h */ 317*64c3d159SToomas Soome fprintf(out, 318*64c3d159SToomas Soome "/* crc32.h -- tables for rapid CRC calculation\n" 319*64c3d159SToomas Soome " * Generated automatically by crc32.c\n */\n" 320*64c3d159SToomas Soome "\n" 321*64c3d159SToomas Soome "local const z_crc_t FAR crc_table[] = {\n" 322*64c3d159SToomas Soome " "); 323*64c3d159SToomas Soome write_table(out, crc_table, 256); 324*64c3d159SToomas Soome fprintf(out, 325*64c3d159SToomas Soome "};\n"); 326*64c3d159SToomas Soome 327*64c3d159SToomas Soome /* write out big-endian CRC table for 64-bit z_word_t to crc32.h */ 328*64c3d159SToomas Soome fprintf(out, 329*64c3d159SToomas Soome "\n" 330*64c3d159SToomas Soome "#ifdef W\n" 331*64c3d159SToomas Soome "\n" 332*64c3d159SToomas Soome "#if W == 8\n" 333*64c3d159SToomas Soome "\n" 334*64c3d159SToomas Soome "local const z_word_t FAR crc_big_table[] = {\n" 335*64c3d159SToomas Soome " "); 336*64c3d159SToomas Soome write_table64(out, crc_big_table, 256); 337*64c3d159SToomas Soome fprintf(out, 338*64c3d159SToomas Soome "};\n"); 339*64c3d159SToomas Soome 340*64c3d159SToomas Soome /* write out big-endian CRC table for 32-bit z_word_t to crc32.h */ 341*64c3d159SToomas Soome fprintf(out, 342*64c3d159SToomas Soome "\n" 343*64c3d159SToomas Soome "#else /* W == 4 */\n" 344*64c3d159SToomas Soome "\n" 345*64c3d159SToomas Soome "local const z_word_t FAR crc_big_table[] = {\n" 346*64c3d159SToomas Soome " "); 347*64c3d159SToomas Soome write_table32hi(out, crc_big_table, 256); 348*64c3d159SToomas Soome fprintf(out, 349*64c3d159SToomas Soome "};\n" 350*64c3d159SToomas Soome "\n" 351*64c3d159SToomas Soome "#endif\n"); 352*64c3d159SToomas Soome 353*64c3d159SToomas Soome /* write out braid tables for each value of N */ 354*64c3d159SToomas Soome for (n = 1; n <= 6; n++) { 355*64c3d159SToomas Soome fprintf(out, 356*64c3d159SToomas Soome "\n" 357*64c3d159SToomas Soome "#if N == %d\n", n); 358*64c3d159SToomas Soome 359*64c3d159SToomas Soome /* compute braid tables for this N and 64-bit word_t */ 360*64c3d159SToomas Soome braid(ltl, big, n, 8); 361*64c3d159SToomas Soome 362*64c3d159SToomas Soome /* write out braid tables for 64-bit z_word_t to crc32.h */ 363*64c3d159SToomas Soome fprintf(out, 364*64c3d159SToomas Soome "\n" 365*64c3d159SToomas Soome "#if W == 8\n" 366*64c3d159SToomas Soome "\n" 367*64c3d159SToomas Soome "local const z_crc_t FAR crc_braid_table[][256] = {\n"); 368*64c3d159SToomas Soome for (k = 0; k < 8; k++) { 369*64c3d159SToomas Soome fprintf(out, " {"); 370*64c3d159SToomas Soome write_table(out, ltl[k], 256); 371*64c3d159SToomas Soome fprintf(out, "}%s", k < 7 ? ",\n" : ""); 372ab9e68a2SToomas Soome } 373*64c3d159SToomas Soome fprintf(out, 374*64c3d159SToomas Soome "};\n" 375*64c3d159SToomas Soome "\n" 376*64c3d159SToomas Soome "local const z_word_t FAR crc_braid_big_table[][256] = {\n"); 377*64c3d159SToomas Soome for (k = 0; k < 8; k++) { 378*64c3d159SToomas Soome fprintf(out, " {"); 379*64c3d159SToomas Soome write_table64(out, big[k], 256); 380*64c3d159SToomas Soome fprintf(out, "}%s", k < 7 ? ",\n" : ""); 381*64c3d159SToomas Soome } 382*64c3d159SToomas Soome fprintf(out, 383*64c3d159SToomas Soome "};\n"); 384*64c3d159SToomas Soome 385*64c3d159SToomas Soome /* compute braid tables for this N and 32-bit word_t */ 386*64c3d159SToomas Soome braid(ltl, big, n, 4); 387*64c3d159SToomas Soome 388*64c3d159SToomas Soome /* write out braid tables for 32-bit z_word_t to crc32.h */ 389*64c3d159SToomas Soome fprintf(out, 390*64c3d159SToomas Soome "\n" 391*64c3d159SToomas Soome "#else /* W == 4 */\n" 392*64c3d159SToomas Soome "\n" 393*64c3d159SToomas Soome "local const z_crc_t FAR crc_braid_table[][256] = {\n"); 394*64c3d159SToomas Soome for (k = 0; k < 4; k++) { 395*64c3d159SToomas Soome fprintf(out, " {"); 396*64c3d159SToomas Soome write_table(out, ltl[k], 256); 397*64c3d159SToomas Soome fprintf(out, "}%s", k < 3 ? ",\n" : ""); 398*64c3d159SToomas Soome } 399*64c3d159SToomas Soome fprintf(out, 400*64c3d159SToomas Soome "};\n" 401*64c3d159SToomas Soome "\n" 402*64c3d159SToomas Soome "local const z_word_t FAR crc_braid_big_table[][256] = {\n"); 403*64c3d159SToomas Soome for (k = 0; k < 4; k++) { 404*64c3d159SToomas Soome fprintf(out, " {"); 405*64c3d159SToomas Soome write_table32hi(out, big[k], 256); 406*64c3d159SToomas Soome fprintf(out, "}%s", k < 3 ? ",\n" : ""); 407*64c3d159SToomas Soome } 408*64c3d159SToomas Soome fprintf(out, 409*64c3d159SToomas Soome "};\n" 410*64c3d159SToomas Soome "\n" 411*64c3d159SToomas Soome "#endif\n" 412*64c3d159SToomas Soome "\n" 413*64c3d159SToomas Soome "#endif\n"); 414*64c3d159SToomas Soome } 415*64c3d159SToomas Soome fprintf(out, 416*64c3d159SToomas Soome "\n" 417*64c3d159SToomas Soome "#endif\n"); 418*64c3d159SToomas Soome 419*64c3d159SToomas Soome /* write out zeros operator table to crc32.h */ 420*64c3d159SToomas Soome fprintf(out, 421*64c3d159SToomas Soome "\n" 422*64c3d159SToomas Soome "local const z_crc_t FAR x2n_table[] = {\n" 423*64c3d159SToomas Soome " "); 424*64c3d159SToomas Soome write_table(out, x2n_table, 32); 425*64c3d159SToomas Soome fprintf(out, 426*64c3d159SToomas Soome "};\n"); 427ab9e68a2SToomas Soome fclose(out); 428ab9e68a2SToomas Soome } 429ab9e68a2SToomas Soome #endif /* MAKECRCH */ 430ab9e68a2SToomas Soome } 431ab9e68a2SToomas Soome 432ab9e68a2SToomas Soome #ifdef MAKECRCH 433*64c3d159SToomas Soome 434*64c3d159SToomas Soome /* 435*64c3d159SToomas Soome Write the 32-bit values in table[0..k-1] to out, five per line in 436*64c3d159SToomas Soome hexadecimal separated by commas. 437*64c3d159SToomas Soome */ 438*64c3d159SToomas Soome local void write_table(out, table, k) 439ab9e68a2SToomas Soome FILE *out; 440ab9e68a2SToomas Soome const z_crc_t FAR *table; 441*64c3d159SToomas Soome int k; 442ab9e68a2SToomas Soome { 443ab9e68a2SToomas Soome int n; 444ab9e68a2SToomas Soome 445*64c3d159SToomas Soome for (n = 0; n < k; n++) 446*64c3d159SToomas Soome fprintf(out, "%s0x%08lx%s", n == 0 || n % 5 ? "" : " ", 447ab9e68a2SToomas Soome (unsigned long)(table[n]), 448*64c3d159SToomas Soome n == k - 1 ? "" : (n % 5 == 4 ? ",\n" : ", ")); 449ab9e68a2SToomas Soome } 450*64c3d159SToomas Soome 451*64c3d159SToomas Soome /* 452*64c3d159SToomas Soome Write the high 32-bits of each value in table[0..k-1] to out, five per line 453*64c3d159SToomas Soome in hexadecimal separated by commas. 454*64c3d159SToomas Soome */ 455*64c3d159SToomas Soome local void write_table32hi(out, table, k) 456*64c3d159SToomas Soome FILE *out; 457*64c3d159SToomas Soome const z_word_t FAR *table; 458*64c3d159SToomas Soome int k; 459*64c3d159SToomas Soome { 460*64c3d159SToomas Soome int n; 461*64c3d159SToomas Soome 462*64c3d159SToomas Soome for (n = 0; n < k; n++) 463*64c3d159SToomas Soome fprintf(out, "%s0x%08lx%s", n == 0 || n % 5 ? "" : " ", 464*64c3d159SToomas Soome (unsigned long)(table[n] >> 32), 465*64c3d159SToomas Soome n == k - 1 ? "" : (n % 5 == 4 ? ",\n" : ", ")); 466*64c3d159SToomas Soome } 467*64c3d159SToomas Soome 468*64c3d159SToomas Soome /* 469*64c3d159SToomas Soome Write the 64-bit values in table[0..k-1] to out, three per line in 470*64c3d159SToomas Soome hexadecimal separated by commas. This assumes that if there is a 64-bit 471*64c3d159SToomas Soome type, then there is also a long long integer type, and it is at least 64 472*64c3d159SToomas Soome bits. If not, then the type cast and format string can be adjusted 473*64c3d159SToomas Soome accordingly. 474*64c3d159SToomas Soome */ 475*64c3d159SToomas Soome local void write_table64(out, table, k) 476*64c3d159SToomas Soome FILE *out; 477*64c3d159SToomas Soome const z_word_t FAR *table; 478*64c3d159SToomas Soome int k; 479*64c3d159SToomas Soome { 480*64c3d159SToomas Soome int n; 481*64c3d159SToomas Soome 482*64c3d159SToomas Soome for (n = 0; n < k; n++) 483*64c3d159SToomas Soome fprintf(out, "%s0x%016llx%s", n == 0 || n % 3 ? "" : " ", 484*64c3d159SToomas Soome (unsigned long long)(table[n]), 485*64c3d159SToomas Soome n == k - 1 ? "" : (n % 3 == 2 ? ",\n" : ", ")); 486*64c3d159SToomas Soome } 487*64c3d159SToomas Soome 488*64c3d159SToomas Soome /* Actually do the deed. */ 489*64c3d159SToomas Soome int main() 490*64c3d159SToomas Soome { 491*64c3d159SToomas Soome make_crc_table(); 492*64c3d159SToomas Soome return 0; 493*64c3d159SToomas Soome } 494*64c3d159SToomas Soome 495ab9e68a2SToomas Soome #endif /* MAKECRCH */ 496ab9e68a2SToomas Soome 497*64c3d159SToomas Soome #ifdef W 498*64c3d159SToomas Soome /* 499*64c3d159SToomas Soome Generate the little and big-endian braid tables for the given n and z_word_t 500*64c3d159SToomas Soome size w. Each array must have room for w blocks of 256 elements. 501*64c3d159SToomas Soome */ 502*64c3d159SToomas Soome local void braid(ltl, big, n, w) 503*64c3d159SToomas Soome z_crc_t ltl[][256]; 504*64c3d159SToomas Soome z_word_t big[][256]; 505*64c3d159SToomas Soome int n; 506*64c3d159SToomas Soome int w; 507*64c3d159SToomas Soome { 508*64c3d159SToomas Soome int k; 509*64c3d159SToomas Soome z_crc_t i, p, q; 510*64c3d159SToomas Soome for (k = 0; k < w; k++) { 511*64c3d159SToomas Soome p = x2nmodp((n * w + 3 - k) << 3, 0); 512*64c3d159SToomas Soome ltl[k][0] = 0; 513*64c3d159SToomas Soome big[w - 1 - k][0] = 0; 514*64c3d159SToomas Soome for (i = 1; i < 256; i++) { 515*64c3d159SToomas Soome ltl[k][i] = q = multmodp(i << 24, p); 516*64c3d159SToomas Soome big[w - 1 - k][i] = byte_swap(q); 517*64c3d159SToomas Soome } 518*64c3d159SToomas Soome } 519*64c3d159SToomas Soome } 520*64c3d159SToomas Soome #endif 521*64c3d159SToomas Soome 522ab9e68a2SToomas Soome #else /* !DYNAMIC_CRC_TABLE */ 523ab9e68a2SToomas Soome /* ======================================================================== 524*64c3d159SToomas Soome * Tables for byte-wise and braided CRC-32 calculations, and a table of powers 525*64c3d159SToomas Soome * of x for combining CRC-32s, all made by make_crc_table(). 526ab9e68a2SToomas Soome */ 527ab9e68a2SToomas Soome #include "crc32.h" 528ab9e68a2SToomas Soome #endif /* DYNAMIC_CRC_TABLE */ 529ab9e68a2SToomas Soome 530*64c3d159SToomas Soome /* ======================================================================== 531*64c3d159SToomas Soome * Routines used for CRC calculation. Some are also required for the table 532*64c3d159SToomas Soome * generation above. 533*64c3d159SToomas Soome */ 534*64c3d159SToomas Soome 535*64c3d159SToomas Soome /* 536*64c3d159SToomas Soome Return a(x) multiplied by b(x) modulo p(x), where p(x) is the CRC polynomial, 537*64c3d159SToomas Soome reflected. For speed, this requires that a not be zero. 538*64c3d159SToomas Soome */ 539*64c3d159SToomas Soome local z_crc_t multmodp(z_crc_t a, z_crc_t b) 540*64c3d159SToomas Soome { 541*64c3d159SToomas Soome z_crc_t m, p; 542*64c3d159SToomas Soome 543*64c3d159SToomas Soome m = (z_crc_t)1 << 31; 544*64c3d159SToomas Soome p = 0; 545*64c3d159SToomas Soome for (;;) { 546*64c3d159SToomas Soome if (a & m) { 547*64c3d159SToomas Soome p ^= b; 548*64c3d159SToomas Soome if ((a & (m - 1)) == 0) 549*64c3d159SToomas Soome break; 550*64c3d159SToomas Soome } 551*64c3d159SToomas Soome m >>= 1; 552*64c3d159SToomas Soome b = b & 1 ? (b >> 1) ^ POLY : b >> 1; 553*64c3d159SToomas Soome } 554*64c3d159SToomas Soome return p; 555*64c3d159SToomas Soome } 556*64c3d159SToomas Soome 557*64c3d159SToomas Soome /* 558*64c3d159SToomas Soome Return x^(n * 2^k) modulo p(x). Requires that x2n_table[] has been 559*64c3d159SToomas Soome initialized. 560*64c3d159SToomas Soome */ 561*64c3d159SToomas Soome local z_crc_t x2nmodp(z_off64_t n, unsigned k) 562*64c3d159SToomas Soome { 563*64c3d159SToomas Soome z_crc_t p; 564*64c3d159SToomas Soome 565*64c3d159SToomas Soome p = (z_crc_t)1 << 31; /* x^0 == 1 */ 566*64c3d159SToomas Soome while (n) { 567*64c3d159SToomas Soome if (n & 1) 568*64c3d159SToomas Soome p = multmodp(x2n_table[k & 31], p); 569*64c3d159SToomas Soome n >>= 1; 570*64c3d159SToomas Soome k++; 571*64c3d159SToomas Soome } 572*64c3d159SToomas Soome return p; 573*64c3d159SToomas Soome } 574*64c3d159SToomas Soome 575ab9e68a2SToomas Soome /* ========================================================================= 576*64c3d159SToomas Soome * This function can be used by asm versions of crc32(), and to force the 577*64c3d159SToomas Soome * generation of the CRC tables in a threaded application. 578ab9e68a2SToomas Soome */ 579ab9e68a2SToomas Soome const z_crc_t FAR * ZEXPORT get_crc_table(void) 580ab9e68a2SToomas Soome { 581ab9e68a2SToomas Soome #ifdef DYNAMIC_CRC_TABLE 582*64c3d159SToomas Soome once(&made, make_crc_table); 583ab9e68a2SToomas Soome #endif /* DYNAMIC_CRC_TABLE */ 584ab9e68a2SToomas Soome return (const z_crc_t FAR *)crc_table; 585ab9e68a2SToomas Soome } 586ab9e68a2SToomas Soome 587*64c3d159SToomas Soome /* ========================================================================= 588*64c3d159SToomas Soome * Use ARM machine instructions if available. This will compute the CRC about 589*64c3d159SToomas Soome * ten times faster than the braided calculation. This code does not check for 590*64c3d159SToomas Soome * the presence of the CRC instruction at run time. __ARM_FEATURE_CRC32 will 591*64c3d159SToomas Soome * only be defined if the compilation specifies an ARM processor architecture 592*64c3d159SToomas Soome * that has the instructions. For example, compiling with -march=armv8.1-a or 593*64c3d159SToomas Soome * -march=armv8-a+crc, or -march=native if the compile machine has the crc32 594*64c3d159SToomas Soome * instructions. 595*64c3d159SToomas Soome */ 596*64c3d159SToomas Soome #ifdef ARMCRC32 597*64c3d159SToomas Soome 598*64c3d159SToomas Soome /* 599*64c3d159SToomas Soome Constants empirically determined to maximize speed. These values are from 600*64c3d159SToomas Soome measurements on a Cortex-A57. Your mileage may vary. 601*64c3d159SToomas Soome */ 602*64c3d159SToomas Soome #define Z_BATCH 3990 /* number of words in a batch */ 603*64c3d159SToomas Soome #define Z_BATCH_ZEROS 0xa10d3d0c /* computed from Z_BATCH = 3990 */ 604*64c3d159SToomas Soome #define Z_BATCH_MIN 800 /* fewest words in a final batch */ 605*64c3d159SToomas Soome 606*64c3d159SToomas Soome unsigned long ZEXPORT crc32_z(crc, buf, len) 607*64c3d159SToomas Soome unsigned long crc; 608*64c3d159SToomas Soome const unsigned char FAR *buf; 609*64c3d159SToomas Soome z_size_t len; 610*64c3d159SToomas Soome { 611*64c3d159SToomas Soome z_crc_t val; 612*64c3d159SToomas Soome z_word_t crc1, crc2; 613*64c3d159SToomas Soome const z_word_t *word; 614*64c3d159SToomas Soome z_word_t val0, val1, val2; 615*64c3d159SToomas Soome z_size_t last, last2, i; 616*64c3d159SToomas Soome z_size_t num; 617*64c3d159SToomas Soome 618*64c3d159SToomas Soome /* Return initial CRC, if requested. */ 619*64c3d159SToomas Soome if (buf == Z_NULL) return 0; 620*64c3d159SToomas Soome 621*64c3d159SToomas Soome #ifdef DYNAMIC_CRC_TABLE 622*64c3d159SToomas Soome once(&made, make_crc_table); 623*64c3d159SToomas Soome #endif /* DYNAMIC_CRC_TABLE */ 624*64c3d159SToomas Soome 625*64c3d159SToomas Soome /* Pre-condition the CRC */ 626*64c3d159SToomas Soome crc = (~crc) & 0xffffffff; 627*64c3d159SToomas Soome 628*64c3d159SToomas Soome /* Compute the CRC up to a word boundary. */ 629*64c3d159SToomas Soome while (len && ((z_size_t)buf & 7) != 0) { 630*64c3d159SToomas Soome len--; 631*64c3d159SToomas Soome val = *buf++; 632*64c3d159SToomas Soome __asm__ volatile("crc32b %w0, %w0, %w1" : "+r"(crc) : "r"(val)); 633*64c3d159SToomas Soome } 634*64c3d159SToomas Soome 635*64c3d159SToomas Soome /* Prepare to compute the CRC on full 64-bit words word[0..num-1]. */ 636*64c3d159SToomas Soome word = (z_word_t const *)buf; 637*64c3d159SToomas Soome num = len >> 3; 638*64c3d159SToomas Soome len &= 7; 639*64c3d159SToomas Soome 640*64c3d159SToomas Soome /* Do three interleaved CRCs to realize the throughput of one crc32x 641*64c3d159SToomas Soome instruction per cycle. Each CRC is calcuated on Z_BATCH words. The three 642*64c3d159SToomas Soome CRCs are combined into a single CRC after each set of batches. */ 643*64c3d159SToomas Soome while (num >= 3 * Z_BATCH) { 644*64c3d159SToomas Soome crc1 = 0; 645*64c3d159SToomas Soome crc2 = 0; 646*64c3d159SToomas Soome for (i = 0; i < Z_BATCH; i++) { 647*64c3d159SToomas Soome val0 = word[i]; 648*64c3d159SToomas Soome val1 = word[i + Z_BATCH]; 649*64c3d159SToomas Soome val2 = word[i + 2 * Z_BATCH]; 650*64c3d159SToomas Soome __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc) : "r"(val0)); 651*64c3d159SToomas Soome __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc1) : "r"(val1)); 652*64c3d159SToomas Soome __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc2) : "r"(val2)); 653*64c3d159SToomas Soome } 654*64c3d159SToomas Soome word += 3 * Z_BATCH; 655*64c3d159SToomas Soome num -= 3 * Z_BATCH; 656*64c3d159SToomas Soome crc = multmodp(Z_BATCH_ZEROS, crc) ^ crc1; 657*64c3d159SToomas Soome crc = multmodp(Z_BATCH_ZEROS, crc) ^ crc2; 658*64c3d159SToomas Soome } 659*64c3d159SToomas Soome 660*64c3d159SToomas Soome /* Do one last smaller batch with the remaining words, if there are enough 661*64c3d159SToomas Soome to pay for the combination of CRCs. */ 662*64c3d159SToomas Soome last = num / 3; 663*64c3d159SToomas Soome if (last >= Z_BATCH_MIN) { 664*64c3d159SToomas Soome last2 = last << 1; 665*64c3d159SToomas Soome crc1 = 0; 666*64c3d159SToomas Soome crc2 = 0; 667*64c3d159SToomas Soome for (i = 0; i < last; i++) { 668*64c3d159SToomas Soome val0 = word[i]; 669*64c3d159SToomas Soome val1 = word[i + last]; 670*64c3d159SToomas Soome val2 = word[i + last2]; 671*64c3d159SToomas Soome __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc) : "r"(val0)); 672*64c3d159SToomas Soome __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc1) : "r"(val1)); 673*64c3d159SToomas Soome __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc2) : "r"(val2)); 674*64c3d159SToomas Soome } 675*64c3d159SToomas Soome word += 3 * last; 676*64c3d159SToomas Soome num -= 3 * last; 677*64c3d159SToomas Soome val = x2nmodp(last, 6); 678*64c3d159SToomas Soome crc = multmodp(val, crc) ^ crc1; 679*64c3d159SToomas Soome crc = multmodp(val, crc) ^ crc2; 680*64c3d159SToomas Soome } 681*64c3d159SToomas Soome 682*64c3d159SToomas Soome /* Compute the CRC on any remaining words. */ 683*64c3d159SToomas Soome for (i = 0; i < num; i++) { 684*64c3d159SToomas Soome val0 = word[i]; 685*64c3d159SToomas Soome __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc) : "r"(val0)); 686*64c3d159SToomas Soome } 687*64c3d159SToomas Soome word += num; 688*64c3d159SToomas Soome 689*64c3d159SToomas Soome /* Complete the CRC on any remaining bytes. */ 690*64c3d159SToomas Soome buf = (const unsigned char FAR *)word; 691*64c3d159SToomas Soome while (len) { 692*64c3d159SToomas Soome len--; 693*64c3d159SToomas Soome val = *buf++; 694*64c3d159SToomas Soome __asm__ volatile("crc32b %w0, %w0, %w1" : "+r"(crc) : "r"(val)); 695*64c3d159SToomas Soome } 696*64c3d159SToomas Soome 697*64c3d159SToomas Soome /* Return the CRC, post-conditioned. */ 698*64c3d159SToomas Soome return crc ^ 0xffffffff; 699*64c3d159SToomas Soome } 700*64c3d159SToomas Soome 701*64c3d159SToomas Soome #else 702*64c3d159SToomas Soome 703*64c3d159SToomas Soome #ifdef W 704*64c3d159SToomas Soome 705*64c3d159SToomas Soome /* 706*64c3d159SToomas Soome Return the CRC of the W bytes in the word_t data, taking the 707*64c3d159SToomas Soome least-significant byte of the word as the first byte of data, without any pre 708*64c3d159SToomas Soome or post conditioning. This is used to combine the CRCs of each braid. 709*64c3d159SToomas Soome */ 710*64c3d159SToomas Soome local z_crc_t crc_word(z_word_t data) 711*64c3d159SToomas Soome { 712*64c3d159SToomas Soome int k; 713*64c3d159SToomas Soome for (k = 0; k < W; k++) 714*64c3d159SToomas Soome data = (data >> 8) ^ crc_table[data & 0xff]; 715*64c3d159SToomas Soome return (z_crc_t)data; 716*64c3d159SToomas Soome } 717*64c3d159SToomas Soome 718*64c3d159SToomas Soome local z_word_t crc_word_big(z_word_t data) 719*64c3d159SToomas Soome { 720*64c3d159SToomas Soome int k; 721*64c3d159SToomas Soome for (k = 0; k < W; k++) 722*64c3d159SToomas Soome data = (data << 8) ^ 723*64c3d159SToomas Soome crc_big_table[(data >> ((W - 1) << 3)) & 0xff]; 724*64c3d159SToomas Soome return data; 725*64c3d159SToomas Soome } 726*64c3d159SToomas Soome 727*64c3d159SToomas Soome #endif 728ab9e68a2SToomas Soome 729ab9e68a2SToomas Soome /* ========================================================================= */ 730ab9e68a2SToomas Soome unsigned long ZEXPORT crc32_z(unsigned long crc, const unsigned char FAR *buf, 731ab9e68a2SToomas Soome z_size_t len) 732ab9e68a2SToomas Soome { 733*64c3d159SToomas Soome /* Return initial CRC, if requested. */ 734*64c3d159SToomas Soome if (buf == Z_NULL) return 0; 735ab9e68a2SToomas Soome 736ab9e68a2SToomas Soome #ifdef DYNAMIC_CRC_TABLE 737*64c3d159SToomas Soome once(&made, make_crc_table); 738ab9e68a2SToomas Soome #endif /* DYNAMIC_CRC_TABLE */ 739ab9e68a2SToomas Soome 740*64c3d159SToomas Soome /* Pre-condition the CRC */ 741*64c3d159SToomas Soome crc = (~crc) & 0xffffffff; 742ab9e68a2SToomas Soome 743*64c3d159SToomas Soome #ifdef W 744*64c3d159SToomas Soome 745*64c3d159SToomas Soome /* If provided enough bytes, do a braided CRC calculation. */ 746*64c3d159SToomas Soome if (len >= N * W + W - 1) { 747*64c3d159SToomas Soome z_size_t blks; 748*64c3d159SToomas Soome z_word_t const *words; 749*64c3d159SToomas Soome unsigned endian; 750*64c3d159SToomas Soome int k; 751*64c3d159SToomas Soome 752*64c3d159SToomas Soome /* Compute the CRC up to a z_word_t boundary. */ 753*64c3d159SToomas Soome while (len && ((z_size_t)buf & (W - 1)) != 0) { 754*64c3d159SToomas Soome len--; 755*64c3d159SToomas Soome crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff]; 756*64c3d159SToomas Soome } 757*64c3d159SToomas Soome 758*64c3d159SToomas Soome /* Compute the CRC on as many N z_word_t blocks as are available. */ 759*64c3d159SToomas Soome blks = len / (N * W); 760*64c3d159SToomas Soome len -= blks * N * W; 761*64c3d159SToomas Soome words = (z_word_t const *)buf; 762*64c3d159SToomas Soome 763*64c3d159SToomas Soome /* Do endian check at execution time instead of compile time, since ARM 764*64c3d159SToomas Soome processors can change the endianess at execution time. If the 765*64c3d159SToomas Soome compiler knows what the endianess will be, it can optimize out the 766*64c3d159SToomas Soome check and the unused branch. */ 767ab9e68a2SToomas Soome endian = 1; 768*64c3d159SToomas Soome if (*(unsigned char *)&endian) { 769*64c3d159SToomas Soome /* Little endian. */ 770*64c3d159SToomas Soome 771*64c3d159SToomas Soome z_crc_t crc0; 772*64c3d159SToomas Soome z_word_t word0; 773*64c3d159SToomas Soome #if N > 1 774*64c3d159SToomas Soome z_crc_t crc1; 775*64c3d159SToomas Soome z_word_t word1; 776*64c3d159SToomas Soome #if N > 2 777*64c3d159SToomas Soome z_crc_t crc2; 778*64c3d159SToomas Soome z_word_t word2; 779*64c3d159SToomas Soome #if N > 3 780*64c3d159SToomas Soome z_crc_t crc3; 781*64c3d159SToomas Soome z_word_t word3; 782*64c3d159SToomas Soome #if N > 4 783*64c3d159SToomas Soome z_crc_t crc4; 784*64c3d159SToomas Soome z_word_t word4; 785*64c3d159SToomas Soome #if N > 5 786*64c3d159SToomas Soome z_crc_t crc5; 787*64c3d159SToomas Soome z_word_t word5; 788*64c3d159SToomas Soome #endif 789*64c3d159SToomas Soome #endif 790*64c3d159SToomas Soome #endif 791*64c3d159SToomas Soome #endif 792*64c3d159SToomas Soome #endif 793*64c3d159SToomas Soome 794*64c3d159SToomas Soome /* Initialize the CRC for each braid. */ 795*64c3d159SToomas Soome crc0 = crc; 796*64c3d159SToomas Soome #if N > 1 797*64c3d159SToomas Soome crc1 = 0; 798*64c3d159SToomas Soome #if N > 2 799*64c3d159SToomas Soome crc2 = 0; 800*64c3d159SToomas Soome #if N > 3 801*64c3d159SToomas Soome crc3 = 0; 802*64c3d159SToomas Soome #if N > 4 803*64c3d159SToomas Soome crc4 = 0; 804*64c3d159SToomas Soome #if N > 5 805*64c3d159SToomas Soome crc5 = 0; 806*64c3d159SToomas Soome #endif 807*64c3d159SToomas Soome #endif 808*64c3d159SToomas Soome #endif 809*64c3d159SToomas Soome #endif 810*64c3d159SToomas Soome #endif 811*64c3d159SToomas Soome 812*64c3d159SToomas Soome /* 813*64c3d159SToomas Soome Process the first blks-1 blocks, computing the CRCs on each braid 814*64c3d159SToomas Soome independently. 815*64c3d159SToomas Soome */ 816*64c3d159SToomas Soome while (--blks) { 817*64c3d159SToomas Soome /* Load the word for each braid into registers. */ 818*64c3d159SToomas Soome word0 = crc0 ^ words[0]; 819*64c3d159SToomas Soome #if N > 1 820*64c3d159SToomas Soome word1 = crc1 ^ words[1]; 821*64c3d159SToomas Soome #if N > 2 822*64c3d159SToomas Soome word2 = crc2 ^ words[2]; 823*64c3d159SToomas Soome #if N > 3 824*64c3d159SToomas Soome word3 = crc3 ^ words[3]; 825*64c3d159SToomas Soome #if N > 4 826*64c3d159SToomas Soome word4 = crc4 ^ words[4]; 827*64c3d159SToomas Soome #if N > 5 828*64c3d159SToomas Soome word5 = crc5 ^ words[5]; 829*64c3d159SToomas Soome #endif 830*64c3d159SToomas Soome #endif 831*64c3d159SToomas Soome #endif 832*64c3d159SToomas Soome #endif 833*64c3d159SToomas Soome #endif 834*64c3d159SToomas Soome words += N; 835*64c3d159SToomas Soome 836*64c3d159SToomas Soome /* Compute and update the CRC for each word. The loop should 837*64c3d159SToomas Soome get unrolled. */ 838*64c3d159SToomas Soome crc0 = crc_braid_table[0][word0 & 0xff]; 839*64c3d159SToomas Soome #if N > 1 840*64c3d159SToomas Soome crc1 = crc_braid_table[0][word1 & 0xff]; 841*64c3d159SToomas Soome #if N > 2 842*64c3d159SToomas Soome crc2 = crc_braid_table[0][word2 & 0xff]; 843*64c3d159SToomas Soome #if N > 3 844*64c3d159SToomas Soome crc3 = crc_braid_table[0][word3 & 0xff]; 845*64c3d159SToomas Soome #if N > 4 846*64c3d159SToomas Soome crc4 = crc_braid_table[0][word4 & 0xff]; 847*64c3d159SToomas Soome #if N > 5 848*64c3d159SToomas Soome crc5 = crc_braid_table[0][word5 & 0xff]; 849*64c3d159SToomas Soome #endif 850*64c3d159SToomas Soome #endif 851*64c3d159SToomas Soome #endif 852*64c3d159SToomas Soome #endif 853*64c3d159SToomas Soome #endif 854*64c3d159SToomas Soome for (k = 1; k < W; k++) { 855*64c3d159SToomas Soome crc0 ^= crc_braid_table[k][(word0 >> (k << 3)) & 0xff]; 856*64c3d159SToomas Soome #if N > 1 857*64c3d159SToomas Soome crc1 ^= crc_braid_table[k][(word1 >> (k << 3)) & 0xff]; 858*64c3d159SToomas Soome #if N > 2 859*64c3d159SToomas Soome crc2 ^= crc_braid_table[k][(word2 >> (k << 3)) & 0xff]; 860*64c3d159SToomas Soome #if N > 3 861*64c3d159SToomas Soome crc3 ^= crc_braid_table[k][(word3 >> (k << 3)) & 0xff]; 862*64c3d159SToomas Soome #if N > 4 863*64c3d159SToomas Soome crc4 ^= crc_braid_table[k][(word4 >> (k << 3)) & 0xff]; 864*64c3d159SToomas Soome #if N > 5 865*64c3d159SToomas Soome crc5 ^= crc_braid_table[k][(word5 >> (k << 3)) & 0xff]; 866*64c3d159SToomas Soome #endif 867*64c3d159SToomas Soome #endif 868*64c3d159SToomas Soome #endif 869*64c3d159SToomas Soome #endif 870*64c3d159SToomas Soome #endif 871ab9e68a2SToomas Soome } 872*64c3d159SToomas Soome } 873*64c3d159SToomas Soome 874*64c3d159SToomas Soome /* 875*64c3d159SToomas Soome Process the last block, combining the CRCs of the N braids at the 876*64c3d159SToomas Soome same time. 877*64c3d159SToomas Soome */ 878*64c3d159SToomas Soome crc = crc_word(crc0 ^ words[0]); 879*64c3d159SToomas Soome #if N > 1 880*64c3d159SToomas Soome crc = crc_word(crc1 ^ words[1] ^ crc); 881*64c3d159SToomas Soome #if N > 2 882*64c3d159SToomas Soome crc = crc_word(crc2 ^ words[2] ^ crc); 883*64c3d159SToomas Soome #if N > 3 884*64c3d159SToomas Soome crc = crc_word(crc3 ^ words[3] ^ crc); 885*64c3d159SToomas Soome #if N > 4 886*64c3d159SToomas Soome crc = crc_word(crc4 ^ words[4] ^ crc); 887*64c3d159SToomas Soome #if N > 5 888*64c3d159SToomas Soome crc = crc_word(crc5 ^ words[5] ^ crc); 889*64c3d159SToomas Soome #endif 890*64c3d159SToomas Soome #endif 891*64c3d159SToomas Soome #endif 892*64c3d159SToomas Soome #endif 893*64c3d159SToomas Soome #endif 894*64c3d159SToomas Soome words += N; 895*64c3d159SToomas Soome } 896*64c3d159SToomas Soome else { 897*64c3d159SToomas Soome /* Big endian. */ 898*64c3d159SToomas Soome 899*64c3d159SToomas Soome z_word_t crc0, word0, comb; 900*64c3d159SToomas Soome #if N > 1 901*64c3d159SToomas Soome z_word_t crc1, word1; 902*64c3d159SToomas Soome #if N > 2 903*64c3d159SToomas Soome z_word_t crc2, word2; 904*64c3d159SToomas Soome #if N > 3 905*64c3d159SToomas Soome z_word_t crc3, word3; 906*64c3d159SToomas Soome #if N > 4 907*64c3d159SToomas Soome z_word_t crc4, word4; 908*64c3d159SToomas Soome #if N > 5 909*64c3d159SToomas Soome z_word_t crc5, word5; 910*64c3d159SToomas Soome #endif 911*64c3d159SToomas Soome #endif 912*64c3d159SToomas Soome #endif 913*64c3d159SToomas Soome #endif 914*64c3d159SToomas Soome #endif 915*64c3d159SToomas Soome 916*64c3d159SToomas Soome /* Initialize the CRC for each braid. */ 917*64c3d159SToomas Soome crc0 = byte_swap(crc); 918*64c3d159SToomas Soome #if N > 1 919*64c3d159SToomas Soome crc1 = 0; 920*64c3d159SToomas Soome #if N > 2 921*64c3d159SToomas Soome crc2 = 0; 922*64c3d159SToomas Soome #if N > 3 923*64c3d159SToomas Soome crc3 = 0; 924*64c3d159SToomas Soome #if N > 4 925*64c3d159SToomas Soome crc4 = 0; 926*64c3d159SToomas Soome #if N > 5 927*64c3d159SToomas Soome crc5 = 0; 928*64c3d159SToomas Soome #endif 929*64c3d159SToomas Soome #endif 930*64c3d159SToomas Soome #endif 931*64c3d159SToomas Soome #endif 932*64c3d159SToomas Soome #endif 933*64c3d159SToomas Soome 934*64c3d159SToomas Soome /* 935*64c3d159SToomas Soome Process the first blks-1 blocks, computing the CRCs on each braid 936*64c3d159SToomas Soome independently. 937*64c3d159SToomas Soome */ 938*64c3d159SToomas Soome while (--blks) { 939*64c3d159SToomas Soome /* Load the word for each braid into registers. */ 940*64c3d159SToomas Soome word0 = crc0 ^ words[0]; 941*64c3d159SToomas Soome #if N > 1 942*64c3d159SToomas Soome word1 = crc1 ^ words[1]; 943*64c3d159SToomas Soome #if N > 2 944*64c3d159SToomas Soome word2 = crc2 ^ words[2]; 945*64c3d159SToomas Soome #if N > 3 946*64c3d159SToomas Soome word3 = crc3 ^ words[3]; 947*64c3d159SToomas Soome #if N > 4 948*64c3d159SToomas Soome word4 = crc4 ^ words[4]; 949*64c3d159SToomas Soome #if N > 5 950*64c3d159SToomas Soome word5 = crc5 ^ words[5]; 951*64c3d159SToomas Soome #endif 952*64c3d159SToomas Soome #endif 953*64c3d159SToomas Soome #endif 954*64c3d159SToomas Soome #endif 955*64c3d159SToomas Soome #endif 956*64c3d159SToomas Soome words += N; 957*64c3d159SToomas Soome 958*64c3d159SToomas Soome /* Compute and update the CRC for each word. The loop should 959*64c3d159SToomas Soome get unrolled. */ 960*64c3d159SToomas Soome crc0 = crc_braid_big_table[0][word0 & 0xff]; 961*64c3d159SToomas Soome #if N > 1 962*64c3d159SToomas Soome crc1 = crc_braid_big_table[0][word1 & 0xff]; 963*64c3d159SToomas Soome #if N > 2 964*64c3d159SToomas Soome crc2 = crc_braid_big_table[0][word2 & 0xff]; 965*64c3d159SToomas Soome #if N > 3 966*64c3d159SToomas Soome crc3 = crc_braid_big_table[0][word3 & 0xff]; 967*64c3d159SToomas Soome #if N > 4 968*64c3d159SToomas Soome crc4 = crc_braid_big_table[0][word4 & 0xff]; 969*64c3d159SToomas Soome #if N > 5 970*64c3d159SToomas Soome crc5 = crc_braid_big_table[0][word5 & 0xff]; 971*64c3d159SToomas Soome #endif 972*64c3d159SToomas Soome #endif 973*64c3d159SToomas Soome #endif 974*64c3d159SToomas Soome #endif 975*64c3d159SToomas Soome #endif 976*64c3d159SToomas Soome for (k = 1; k < W; k++) { 977*64c3d159SToomas Soome crc0 ^= crc_braid_big_table[k][(word0 >> (k << 3)) & 0xff]; 978*64c3d159SToomas Soome #if N > 1 979*64c3d159SToomas Soome crc1 ^= crc_braid_big_table[k][(word1 >> (k << 3)) & 0xff]; 980*64c3d159SToomas Soome #if N > 2 981*64c3d159SToomas Soome crc2 ^= crc_braid_big_table[k][(word2 >> (k << 3)) & 0xff]; 982*64c3d159SToomas Soome #if N > 3 983*64c3d159SToomas Soome crc3 ^= crc_braid_big_table[k][(word3 >> (k << 3)) & 0xff]; 984*64c3d159SToomas Soome #if N > 4 985*64c3d159SToomas Soome crc4 ^= crc_braid_big_table[k][(word4 >> (k << 3)) & 0xff]; 986*64c3d159SToomas Soome #if N > 5 987*64c3d159SToomas Soome crc5 ^= crc_braid_big_table[k][(word5 >> (k << 3)) & 0xff]; 988*64c3d159SToomas Soome #endif 989*64c3d159SToomas Soome #endif 990*64c3d159SToomas Soome #endif 991*64c3d159SToomas Soome #endif 992*64c3d159SToomas Soome #endif 993*64c3d159SToomas Soome } 994*64c3d159SToomas Soome } 995*64c3d159SToomas Soome 996*64c3d159SToomas Soome /* 997*64c3d159SToomas Soome Process the last block, combining the CRCs of the N braids at the 998*64c3d159SToomas Soome same time. 999*64c3d159SToomas Soome */ 1000*64c3d159SToomas Soome comb = crc_word_big(crc0 ^ words[0]); 1001*64c3d159SToomas Soome #if N > 1 1002*64c3d159SToomas Soome comb = crc_word_big(crc1 ^ words[1] ^ comb); 1003*64c3d159SToomas Soome #if N > 2 1004*64c3d159SToomas Soome comb = crc_word_big(crc2 ^ words[2] ^ comb); 1005*64c3d159SToomas Soome #if N > 3 1006*64c3d159SToomas Soome comb = crc_word_big(crc3 ^ words[3] ^ comb); 1007*64c3d159SToomas Soome #if N > 4 1008*64c3d159SToomas Soome comb = crc_word_big(crc4 ^ words[4] ^ comb); 1009*64c3d159SToomas Soome #if N > 5 1010*64c3d159SToomas Soome comb = crc_word_big(crc5 ^ words[5] ^ comb); 1011*64c3d159SToomas Soome #endif 1012*64c3d159SToomas Soome #endif 1013*64c3d159SToomas Soome #endif 1014*64c3d159SToomas Soome #endif 1015*64c3d159SToomas Soome #endif 1016*64c3d159SToomas Soome words += N; 1017*64c3d159SToomas Soome crc = byte_swap(comb); 1018*64c3d159SToomas Soome } 1019*64c3d159SToomas Soome 1020*64c3d159SToomas Soome /* 1021*64c3d159SToomas Soome Update the pointer to the remaining bytes to process. 1022*64c3d159SToomas Soome */ 1023*64c3d159SToomas Soome buf = (unsigned char const *)words; 1024*64c3d159SToomas Soome } 1025*64c3d159SToomas Soome 1026*64c3d159SToomas Soome #endif /* W */ 1027*64c3d159SToomas Soome 1028*64c3d159SToomas Soome /* Complete the computation of the CRC on any remaining bytes. */ 1029ab9e68a2SToomas Soome while (len >= 8) { 1030ab9e68a2SToomas Soome len -= 8; 1031*64c3d159SToomas Soome crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff]; 1032*64c3d159SToomas Soome crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff]; 1033*64c3d159SToomas Soome crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff]; 1034*64c3d159SToomas Soome crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff]; 1035*64c3d159SToomas Soome crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff]; 1036*64c3d159SToomas Soome crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff]; 1037*64c3d159SToomas Soome crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff]; 1038*64c3d159SToomas Soome crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff]; 1039ab9e68a2SToomas Soome } 1040*64c3d159SToomas Soome while (len) { 1041*64c3d159SToomas Soome len--; 1042*64c3d159SToomas Soome crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff]; 1043ab9e68a2SToomas Soome } 1044ab9e68a2SToomas Soome 1045*64c3d159SToomas Soome /* Return the CRC, post-conditioned. */ 1046*64c3d159SToomas Soome return crc ^ 0xffffffff; 1047*64c3d159SToomas Soome } 1048*64c3d159SToomas Soome 1049*64c3d159SToomas Soome #endif 1050*64c3d159SToomas Soome 1051ab9e68a2SToomas Soome /* ========================================================================= */ 1052ab9e68a2SToomas Soome unsigned long ZEXPORT crc32(unsigned long crc, const unsigned char FAR *buf, 1053ab9e68a2SToomas Soome uInt len) 1054ab9e68a2SToomas Soome { 1055ab9e68a2SToomas Soome return crc32_z(crc, buf, len); 1056ab9e68a2SToomas Soome } 1057ab9e68a2SToomas Soome 1058ab9e68a2SToomas Soome /* ========================================================================= */ 1059*64c3d159SToomas Soome uLong ZEXPORT crc32_combine64(uLong crc1, uLong crc2, z_off64_t len2) 1060ab9e68a2SToomas Soome { 1061*64c3d159SToomas Soome #ifdef DYNAMIC_CRC_TABLE 1062*64c3d159SToomas Soome once(&made, make_crc_table); 1063*64c3d159SToomas Soome #endif /* DYNAMIC_CRC_TABLE */ 1064*64c3d159SToomas Soome return multmodp(x2nmodp(len2, 3), crc1) ^ (crc2 & 0xffffffff); 1065ab9e68a2SToomas Soome } 1066ab9e68a2SToomas Soome 1067ab9e68a2SToomas Soome /* ========================================================================= */ 1068ab9e68a2SToomas Soome uLong ZEXPORT crc32_combine(uLong crc1, uLong crc2, z_off_t len2) 1069ab9e68a2SToomas Soome { 1070*64c3d159SToomas Soome return crc32_combine64(crc1, crc2, len2); 1071ab9e68a2SToomas Soome } 1072ab9e68a2SToomas Soome 1073*64c3d159SToomas Soome /* ========================================================================= */ 1074*64c3d159SToomas Soome uLong ZEXPORT crc32_combine_gen64(z_off64_t len2) 1075ab9e68a2SToomas Soome { 1076*64c3d159SToomas Soome #ifdef DYNAMIC_CRC_TABLE 1077*64c3d159SToomas Soome once(&made, make_crc_table); 1078*64c3d159SToomas Soome #endif /* DYNAMIC_CRC_TABLE */ 1079*64c3d159SToomas Soome return x2nmodp(len2, 3); 1080*64c3d159SToomas Soome } 1081*64c3d159SToomas Soome 1082*64c3d159SToomas Soome /* ========================================================================= */ 1083*64c3d159SToomas Soome uLong ZEXPORT crc32_combine_gen(z_off_t len2) 1084*64c3d159SToomas Soome { 1085*64c3d159SToomas Soome return crc32_combine_gen64(len2); 1086*64c3d159SToomas Soome } 1087*64c3d159SToomas Soome 1088*64c3d159SToomas Soome /* ========================================================================= */ 1089*64c3d159SToomas Soome uLong crc32_combine_op(uLong crc1, uLong crc2, uLong op) 1090*64c3d159SToomas Soome { 1091*64c3d159SToomas Soome return multmodp(op, crc1) ^ (crc2 & 0xffffffff); 1092ab9e68a2SToomas Soome } 1093