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