11cb0ef41Sopenharmony_ci/* crc32.c -- compute the CRC-32 of a data stream 21cb0ef41Sopenharmony_ci * Copyright (C) 1995-2022 Mark Adler 31cb0ef41Sopenharmony_ci * For conditions of distribution and use, see copyright notice in zlib.h 41cb0ef41Sopenharmony_ci * 51cb0ef41Sopenharmony_ci * This interleaved implementation of a CRC makes use of pipelined multiple 61cb0ef41Sopenharmony_ci * arithmetic-logic units, commonly found in modern CPU cores. It is due to 71cb0ef41Sopenharmony_ci * Kadatch and Jenkins (2010). See doc/crc-doc.1.0.pdf in this distribution. 81cb0ef41Sopenharmony_ci */ 91cb0ef41Sopenharmony_ci 101cb0ef41Sopenharmony_ci/* @(#) $Id$ */ 111cb0ef41Sopenharmony_ci 121cb0ef41Sopenharmony_ci/* 131cb0ef41Sopenharmony_ci Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore 141cb0ef41Sopenharmony_ci protection on the static variables used to control the first-use generation 151cb0ef41Sopenharmony_ci of the crc tables. Therefore, if you #define DYNAMIC_CRC_TABLE, you should 161cb0ef41Sopenharmony_ci first call get_crc_table() to initialize the tables before allowing more than 171cb0ef41Sopenharmony_ci one thread to use crc32(). 181cb0ef41Sopenharmony_ci 191cb0ef41Sopenharmony_ci MAKECRCH can be #defined to write out crc32.h. A main() routine is also 201cb0ef41Sopenharmony_ci produced, so that this one source file can be compiled to an executable. 211cb0ef41Sopenharmony_ci */ 221cb0ef41Sopenharmony_ci 231cb0ef41Sopenharmony_ci#ifdef MAKECRCH 241cb0ef41Sopenharmony_ci# include <stdio.h> 251cb0ef41Sopenharmony_ci# ifndef DYNAMIC_CRC_TABLE 261cb0ef41Sopenharmony_ci# define DYNAMIC_CRC_TABLE 271cb0ef41Sopenharmony_ci# endif /* !DYNAMIC_CRC_TABLE */ 281cb0ef41Sopenharmony_ci#endif /* MAKECRCH */ 291cb0ef41Sopenharmony_ci 301cb0ef41Sopenharmony_ci#include "deflate.h" 311cb0ef41Sopenharmony_ci#include "cpu_features.h" 321cb0ef41Sopenharmony_ci#include "zutil.h" /* for Z_U4, Z_U8, z_crc_t, and FAR definitions */ 331cb0ef41Sopenharmony_ci 341cb0ef41Sopenharmony_ci#if defined(CRC32_SIMD_SSE42_PCLMUL) || defined(CRC32_ARMV8_CRC32) 351cb0ef41Sopenharmony_ci#include "crc32_simd.h" 361cb0ef41Sopenharmony_ci#endif 371cb0ef41Sopenharmony_ci 381cb0ef41Sopenharmony_ci /* 391cb0ef41Sopenharmony_ci A CRC of a message is computed on N braids of words in the message, where 401cb0ef41Sopenharmony_ci each word consists of W bytes (4 or 8). If N is 3, for example, then three 411cb0ef41Sopenharmony_ci running sparse CRCs are calculated respectively on each braid, at these 421cb0ef41Sopenharmony_ci indices in the array of words: 0, 3, 6, ..., 1, 4, 7, ..., and 2, 5, 8, ... 431cb0ef41Sopenharmony_ci This is done starting at a word boundary, and continues until as many blocks 441cb0ef41Sopenharmony_ci of N * W bytes as are available have been processed. The results are combined 451cb0ef41Sopenharmony_ci into a single CRC at the end. For this code, N must be in the range 1..6 and 461cb0ef41Sopenharmony_ci W must be 4 or 8. The upper limit on N can be increased if desired by adding 471cb0ef41Sopenharmony_ci more #if blocks, extending the patterns apparent in the code. In addition, 481cb0ef41Sopenharmony_ci crc32.h would need to be regenerated, if the maximum N value is increased. 491cb0ef41Sopenharmony_ci 501cb0ef41Sopenharmony_ci N and W are chosen empirically by benchmarking the execution time on a given 511cb0ef41Sopenharmony_ci processor. The choices for N and W below were based on testing on Intel Kaby 521cb0ef41Sopenharmony_ci Lake i7, AMD Ryzen 7, ARM Cortex-A57, Sparc64-VII, PowerPC POWER9, and MIPS64 531cb0ef41Sopenharmony_ci Octeon II processors. The Intel, AMD, and ARM processors were all fastest 541cb0ef41Sopenharmony_ci with N=5, W=8. The Sparc, PowerPC, and MIPS64 were all fastest at N=5, W=4. 551cb0ef41Sopenharmony_ci They were all tested with either gcc or clang, all using the -O3 optimization 561cb0ef41Sopenharmony_ci level. Your mileage may vary. 571cb0ef41Sopenharmony_ci */ 581cb0ef41Sopenharmony_ci 591cb0ef41Sopenharmony_ci/* Define N */ 601cb0ef41Sopenharmony_ci#ifdef Z_TESTN 611cb0ef41Sopenharmony_ci# define N Z_TESTN 621cb0ef41Sopenharmony_ci#else 631cb0ef41Sopenharmony_ci# define N 5 641cb0ef41Sopenharmony_ci#endif 651cb0ef41Sopenharmony_ci#if N < 1 || N > 6 661cb0ef41Sopenharmony_ci# error N must be in 1..6 671cb0ef41Sopenharmony_ci#endif 681cb0ef41Sopenharmony_ci 691cb0ef41Sopenharmony_ci/* 701cb0ef41Sopenharmony_ci z_crc_t must be at least 32 bits. z_word_t must be at least as long as 711cb0ef41Sopenharmony_ci z_crc_t. It is assumed here that z_word_t is either 32 bits or 64 bits, and 721cb0ef41Sopenharmony_ci that bytes are eight bits. 731cb0ef41Sopenharmony_ci */ 741cb0ef41Sopenharmony_ci 751cb0ef41Sopenharmony_ci/* 761cb0ef41Sopenharmony_ci Define W and the associated z_word_t type. If W is not defined, then a 771cb0ef41Sopenharmony_ci braided calculation is not used, and the associated tables and code are not 781cb0ef41Sopenharmony_ci compiled. 791cb0ef41Sopenharmony_ci */ 801cb0ef41Sopenharmony_ci#ifdef Z_TESTW 811cb0ef41Sopenharmony_ci# if Z_TESTW-1 != -1 821cb0ef41Sopenharmony_ci# define W Z_TESTW 831cb0ef41Sopenharmony_ci# endif 841cb0ef41Sopenharmony_ci#else 851cb0ef41Sopenharmony_ci# ifdef MAKECRCH 861cb0ef41Sopenharmony_ci# define W 8 /* required for MAKECRCH */ 871cb0ef41Sopenharmony_ci# else 881cb0ef41Sopenharmony_ci# if defined(__x86_64__) || defined(__aarch64__) 891cb0ef41Sopenharmony_ci# define W 8 901cb0ef41Sopenharmony_ci# else 911cb0ef41Sopenharmony_ci# define W 4 921cb0ef41Sopenharmony_ci# endif 931cb0ef41Sopenharmony_ci# endif 941cb0ef41Sopenharmony_ci#endif 951cb0ef41Sopenharmony_ci#ifdef W 961cb0ef41Sopenharmony_ci# if W == 8 && defined(Z_U8) 971cb0ef41Sopenharmony_ci typedef Z_U8 z_word_t; 981cb0ef41Sopenharmony_ci# elif defined(Z_U4) 991cb0ef41Sopenharmony_ci# undef W 1001cb0ef41Sopenharmony_ci# define W 4 1011cb0ef41Sopenharmony_ci typedef Z_U4 z_word_t; 1021cb0ef41Sopenharmony_ci# else 1031cb0ef41Sopenharmony_ci# undef W 1041cb0ef41Sopenharmony_ci# endif 1051cb0ef41Sopenharmony_ci#endif 1061cb0ef41Sopenharmony_ci 1071cb0ef41Sopenharmony_ci/* If available, use the ARM processor CRC32 instruction. */ 1081cb0ef41Sopenharmony_ci#if defined(__aarch64__) && defined(__ARM_FEATURE_CRC32) && W == 8 \ 1091cb0ef41Sopenharmony_ci && defined(USE_CANONICAL_ARMV8_CRC32) 1101cb0ef41Sopenharmony_ci# define ARMCRC32_CANONICAL_ZLIB 1111cb0ef41Sopenharmony_ci#endif 1121cb0ef41Sopenharmony_ci 1131cb0ef41Sopenharmony_ci#if defined(W) && (!defined(ARMCRC32_CANONICAL_ZLIB) || defined(DYNAMIC_CRC_TABLE)) 1141cb0ef41Sopenharmony_ci/* 1151cb0ef41Sopenharmony_ci Swap the bytes in a z_word_t to convert between little and big endian. Any 1161cb0ef41Sopenharmony_ci self-respecting compiler will optimize this to a single machine byte-swap 1171cb0ef41Sopenharmony_ci instruction, if one is available. This assumes that word_t is either 32 bits 1181cb0ef41Sopenharmony_ci or 64 bits. 1191cb0ef41Sopenharmony_ci */ 1201cb0ef41Sopenharmony_cilocal z_word_t byte_swap(z_word_t word) { 1211cb0ef41Sopenharmony_ci# if W == 8 1221cb0ef41Sopenharmony_ci return 1231cb0ef41Sopenharmony_ci (word & 0xff00000000000000) >> 56 | 1241cb0ef41Sopenharmony_ci (word & 0xff000000000000) >> 40 | 1251cb0ef41Sopenharmony_ci (word & 0xff0000000000) >> 24 | 1261cb0ef41Sopenharmony_ci (word & 0xff00000000) >> 8 | 1271cb0ef41Sopenharmony_ci (word & 0xff000000) << 8 | 1281cb0ef41Sopenharmony_ci (word & 0xff0000) << 24 | 1291cb0ef41Sopenharmony_ci (word & 0xff00) << 40 | 1301cb0ef41Sopenharmony_ci (word & 0xff) << 56; 1311cb0ef41Sopenharmony_ci# else /* W == 4 */ 1321cb0ef41Sopenharmony_ci return 1331cb0ef41Sopenharmony_ci (word & 0xff000000) >> 24 | 1341cb0ef41Sopenharmony_ci (word & 0xff0000) >> 8 | 1351cb0ef41Sopenharmony_ci (word & 0xff00) << 8 | 1361cb0ef41Sopenharmony_ci (word & 0xff) << 24; 1371cb0ef41Sopenharmony_ci# endif 1381cb0ef41Sopenharmony_ci} 1391cb0ef41Sopenharmony_ci#endif 1401cb0ef41Sopenharmony_ci 1411cb0ef41Sopenharmony_ci#ifdef DYNAMIC_CRC_TABLE 1421cb0ef41Sopenharmony_ci/* ========================================================================= 1431cb0ef41Sopenharmony_ci * Table of powers of x for combining CRC-32s, filled in by make_crc_table() 1441cb0ef41Sopenharmony_ci * below. 1451cb0ef41Sopenharmony_ci */ 1461cb0ef41Sopenharmony_ci local z_crc_t FAR x2n_table[32]; 1471cb0ef41Sopenharmony_ci#else 1481cb0ef41Sopenharmony_ci/* ========================================================================= 1491cb0ef41Sopenharmony_ci * Tables for byte-wise and braided CRC-32 calculations, and a table of powers 1501cb0ef41Sopenharmony_ci * of x for combining CRC-32s, all made by make_crc_table(). 1511cb0ef41Sopenharmony_ci */ 1521cb0ef41Sopenharmony_ci# include "crc32.h" 1531cb0ef41Sopenharmony_ci#endif 1541cb0ef41Sopenharmony_ci 1551cb0ef41Sopenharmony_ci/* CRC polynomial. */ 1561cb0ef41Sopenharmony_ci#define POLY 0xedb88320 /* p(x) reflected, with x^32 implied */ 1571cb0ef41Sopenharmony_ci 1581cb0ef41Sopenharmony_ci/* 1591cb0ef41Sopenharmony_ci Return a(x) multiplied by b(x) modulo p(x), where p(x) is the CRC polynomial, 1601cb0ef41Sopenharmony_ci reflected. For speed, this requires that a not be zero. 1611cb0ef41Sopenharmony_ci */ 1621cb0ef41Sopenharmony_cilocal z_crc_t multmodp(z_crc_t a, z_crc_t b) { 1631cb0ef41Sopenharmony_ci z_crc_t m, p; 1641cb0ef41Sopenharmony_ci 1651cb0ef41Sopenharmony_ci m = (z_crc_t)1 << 31; 1661cb0ef41Sopenharmony_ci p = 0; 1671cb0ef41Sopenharmony_ci for (;;) { 1681cb0ef41Sopenharmony_ci if (a & m) { 1691cb0ef41Sopenharmony_ci p ^= b; 1701cb0ef41Sopenharmony_ci if ((a & (m - 1)) == 0) 1711cb0ef41Sopenharmony_ci break; 1721cb0ef41Sopenharmony_ci } 1731cb0ef41Sopenharmony_ci m >>= 1; 1741cb0ef41Sopenharmony_ci b = b & 1 ? (b >> 1) ^ POLY : b >> 1; 1751cb0ef41Sopenharmony_ci } 1761cb0ef41Sopenharmony_ci return p; 1771cb0ef41Sopenharmony_ci} 1781cb0ef41Sopenharmony_ci 1791cb0ef41Sopenharmony_ci/* 1801cb0ef41Sopenharmony_ci Return x^(n * 2^k) modulo p(x). Requires that x2n_table[] has been 1811cb0ef41Sopenharmony_ci initialized. 1821cb0ef41Sopenharmony_ci */ 1831cb0ef41Sopenharmony_cilocal z_crc_t x2nmodp(z_off64_t n, unsigned k) { 1841cb0ef41Sopenharmony_ci z_crc_t p; 1851cb0ef41Sopenharmony_ci 1861cb0ef41Sopenharmony_ci p = (z_crc_t)1 << 31; /* x^0 == 1 */ 1871cb0ef41Sopenharmony_ci while (n) { 1881cb0ef41Sopenharmony_ci if (n & 1) 1891cb0ef41Sopenharmony_ci p = multmodp(x2n_table[k & 31], p); 1901cb0ef41Sopenharmony_ci n >>= 1; 1911cb0ef41Sopenharmony_ci k++; 1921cb0ef41Sopenharmony_ci } 1931cb0ef41Sopenharmony_ci return p; 1941cb0ef41Sopenharmony_ci} 1951cb0ef41Sopenharmony_ci 1961cb0ef41Sopenharmony_ci#ifdef DYNAMIC_CRC_TABLE 1971cb0ef41Sopenharmony_ci/* ========================================================================= 1981cb0ef41Sopenharmony_ci * Build the tables for byte-wise and braided CRC-32 calculations, and a table 1991cb0ef41Sopenharmony_ci * of powers of x for combining CRC-32s. 2001cb0ef41Sopenharmony_ci */ 2011cb0ef41Sopenharmony_cilocal z_crc_t FAR crc_table[256]; 2021cb0ef41Sopenharmony_ci#ifdef W 2031cb0ef41Sopenharmony_ci local z_word_t FAR crc_big_table[256]; 2041cb0ef41Sopenharmony_ci local z_crc_t FAR crc_braid_table[W][256]; 2051cb0ef41Sopenharmony_ci local z_word_t FAR crc_braid_big_table[W][256]; 2061cb0ef41Sopenharmony_ci local void braid(z_crc_t [][256], z_word_t [][256], int, int); 2071cb0ef41Sopenharmony_ci#endif 2081cb0ef41Sopenharmony_ci#ifdef MAKECRCH 2091cb0ef41Sopenharmony_ci local void write_table(FILE *, const z_crc_t FAR *, int); 2101cb0ef41Sopenharmony_ci local void write_table32hi(FILE *, const z_word_t FAR *, int); 2111cb0ef41Sopenharmony_ci local void write_table64(FILE *, const z_word_t FAR *, int); 2121cb0ef41Sopenharmony_ci#endif /* MAKECRCH */ 2131cb0ef41Sopenharmony_ci 2141cb0ef41Sopenharmony_ci/* 2151cb0ef41Sopenharmony_ci Define a once() function depending on the availability of atomics. If this is 2161cb0ef41Sopenharmony_ci compiled with DYNAMIC_CRC_TABLE defined, and if CRCs will be computed in 2171cb0ef41Sopenharmony_ci multiple threads, and if atomics are not available, then get_crc_table() must 2181cb0ef41Sopenharmony_ci be called to initialize the tables and must return before any threads are 2191cb0ef41Sopenharmony_ci allowed to compute or combine CRCs. 2201cb0ef41Sopenharmony_ci */ 2211cb0ef41Sopenharmony_ci 2221cb0ef41Sopenharmony_ci/* Definition of once functionality. */ 2231cb0ef41Sopenharmony_citypedef struct once_s once_t; 2241cb0ef41Sopenharmony_ci 2251cb0ef41Sopenharmony_ci/* Check for the availability of atomics. */ 2261cb0ef41Sopenharmony_ci#if defined(__STDC__) && __STDC_VERSION__ >= 201112L && \ 2271cb0ef41Sopenharmony_ci !defined(__STDC_NO_ATOMICS__) 2281cb0ef41Sopenharmony_ci 2291cb0ef41Sopenharmony_ci#include <stdatomic.h> 2301cb0ef41Sopenharmony_ci 2311cb0ef41Sopenharmony_ci/* Structure for once(), which must be initialized with ONCE_INIT. */ 2321cb0ef41Sopenharmony_cistruct once_s { 2331cb0ef41Sopenharmony_ci atomic_flag begun; 2341cb0ef41Sopenharmony_ci atomic_int done; 2351cb0ef41Sopenharmony_ci}; 2361cb0ef41Sopenharmony_ci#define ONCE_INIT {ATOMIC_FLAG_INIT, 0} 2371cb0ef41Sopenharmony_ci 2381cb0ef41Sopenharmony_ci/* 2391cb0ef41Sopenharmony_ci Run the provided init() function exactly once, even if multiple threads 2401cb0ef41Sopenharmony_ci invoke once() at the same time. The state must be a once_t initialized with 2411cb0ef41Sopenharmony_ci ONCE_INIT. 2421cb0ef41Sopenharmony_ci */ 2431cb0ef41Sopenharmony_cilocal void once(once_t *state, void (*init)(void)) { 2441cb0ef41Sopenharmony_ci if (!atomic_load(&state->done)) { 2451cb0ef41Sopenharmony_ci if (atomic_flag_test_and_set(&state->begun)) 2461cb0ef41Sopenharmony_ci while (!atomic_load(&state->done)) 2471cb0ef41Sopenharmony_ci ; 2481cb0ef41Sopenharmony_ci else { 2491cb0ef41Sopenharmony_ci init(); 2501cb0ef41Sopenharmony_ci atomic_store(&state->done, 1); 2511cb0ef41Sopenharmony_ci } 2521cb0ef41Sopenharmony_ci } 2531cb0ef41Sopenharmony_ci} 2541cb0ef41Sopenharmony_ci 2551cb0ef41Sopenharmony_ci#else /* no atomics */ 2561cb0ef41Sopenharmony_ci 2571cb0ef41Sopenharmony_ci/* Structure for once(), which must be initialized with ONCE_INIT. */ 2581cb0ef41Sopenharmony_cistruct once_s { 2591cb0ef41Sopenharmony_ci volatile int begun; 2601cb0ef41Sopenharmony_ci volatile int done; 2611cb0ef41Sopenharmony_ci}; 2621cb0ef41Sopenharmony_ci#define ONCE_INIT {0, 0} 2631cb0ef41Sopenharmony_ci 2641cb0ef41Sopenharmony_ci/* Test and set. Alas, not atomic, but tries to minimize the period of 2651cb0ef41Sopenharmony_ci vulnerability. */ 2661cb0ef41Sopenharmony_cilocal int test_and_set(int volatile *flag) { 2671cb0ef41Sopenharmony_ci int was; 2681cb0ef41Sopenharmony_ci 2691cb0ef41Sopenharmony_ci was = *flag; 2701cb0ef41Sopenharmony_ci *flag = 1; 2711cb0ef41Sopenharmony_ci return was; 2721cb0ef41Sopenharmony_ci} 2731cb0ef41Sopenharmony_ci 2741cb0ef41Sopenharmony_ci/* Run the provided init() function once. This is not thread-safe. */ 2751cb0ef41Sopenharmony_cilocal void once(once_t *state, void (*init)(void)) { 2761cb0ef41Sopenharmony_ci if (!state->done) { 2771cb0ef41Sopenharmony_ci if (test_and_set(&state->begun)) 2781cb0ef41Sopenharmony_ci while (!state->done) 2791cb0ef41Sopenharmony_ci ; 2801cb0ef41Sopenharmony_ci else { 2811cb0ef41Sopenharmony_ci init(); 2821cb0ef41Sopenharmony_ci state->done = 1; 2831cb0ef41Sopenharmony_ci } 2841cb0ef41Sopenharmony_ci } 2851cb0ef41Sopenharmony_ci} 2861cb0ef41Sopenharmony_ci 2871cb0ef41Sopenharmony_ci#endif 2881cb0ef41Sopenharmony_ci 2891cb0ef41Sopenharmony_ci/* State for once(). */ 2901cb0ef41Sopenharmony_cilocal once_t made = ONCE_INIT; 2911cb0ef41Sopenharmony_ci 2921cb0ef41Sopenharmony_ci/* 2931cb0ef41Sopenharmony_ci Generate tables for a byte-wise 32-bit CRC calculation on the polynomial: 2941cb0ef41Sopenharmony_ci 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. 2951cb0ef41Sopenharmony_ci 2961cb0ef41Sopenharmony_ci Polynomials over GF(2) are represented in binary, one bit per coefficient, 2971cb0ef41Sopenharmony_ci with the lowest powers in the most significant bit. Then adding polynomials 2981cb0ef41Sopenharmony_ci is just exclusive-or, and multiplying a polynomial by x is a right shift by 2991cb0ef41Sopenharmony_ci one. If we call the above polynomial p, and represent a byte as the 3001cb0ef41Sopenharmony_ci polynomial q, also with the lowest power in the most significant bit (so the 3011cb0ef41Sopenharmony_ci byte 0xb1 is the polynomial x^7+x^3+x^2+1), then the CRC is (q*x^32) mod p, 3021cb0ef41Sopenharmony_ci where a mod b means the remainder after dividing a by b. 3031cb0ef41Sopenharmony_ci 3041cb0ef41Sopenharmony_ci This calculation is done using the shift-register method of multiplying and 3051cb0ef41Sopenharmony_ci taking the remainder. The register is initialized to zero, and for each 3061cb0ef41Sopenharmony_ci incoming bit, x^32 is added mod p to the register if the bit is a one (where 3071cb0ef41Sopenharmony_ci x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by x 3081cb0ef41Sopenharmony_ci (which is shifting right by one and adding x^32 mod p if the bit shifted out 3091cb0ef41Sopenharmony_ci is a one). We start with the highest power (least significant bit) of q and 3101cb0ef41Sopenharmony_ci repeat for all eight bits of q. 3111cb0ef41Sopenharmony_ci 3121cb0ef41Sopenharmony_ci The table is simply the CRC of all possible eight bit values. This is all the 3131cb0ef41Sopenharmony_ci information needed to generate CRCs on data a byte at a time for all 3141cb0ef41Sopenharmony_ci combinations of CRC register values and incoming bytes. 3151cb0ef41Sopenharmony_ci */ 3161cb0ef41Sopenharmony_cilocal void make_crc_table(void) 3171cb0ef41Sopenharmony_ci{ 3181cb0ef41Sopenharmony_ci unsigned i, j, n; 3191cb0ef41Sopenharmony_ci z_crc_t p; 3201cb0ef41Sopenharmony_ci 3211cb0ef41Sopenharmony_ci /* initialize the CRC of bytes tables */ 3221cb0ef41Sopenharmony_ci for (i = 0; i < 256; i++) { 3231cb0ef41Sopenharmony_ci p = i; 3241cb0ef41Sopenharmony_ci for (j = 0; j < 8; j++) 3251cb0ef41Sopenharmony_ci p = p & 1 ? (p >> 1) ^ POLY : p >> 1; 3261cb0ef41Sopenharmony_ci crc_table[i] = p; 3271cb0ef41Sopenharmony_ci#ifdef W 3281cb0ef41Sopenharmony_ci crc_big_table[i] = byte_swap(p); 3291cb0ef41Sopenharmony_ci#endif 3301cb0ef41Sopenharmony_ci } 3311cb0ef41Sopenharmony_ci 3321cb0ef41Sopenharmony_ci /* initialize the x^2^n mod p(x) table */ 3331cb0ef41Sopenharmony_ci p = (z_crc_t)1 << 30; /* x^1 */ 3341cb0ef41Sopenharmony_ci x2n_table[0] = p; 3351cb0ef41Sopenharmony_ci for (n = 1; n < 32; n++) 3361cb0ef41Sopenharmony_ci x2n_table[n] = p = multmodp(p, p); 3371cb0ef41Sopenharmony_ci 3381cb0ef41Sopenharmony_ci#ifdef W 3391cb0ef41Sopenharmony_ci /* initialize the braiding tables -- needs x2n_table[] */ 3401cb0ef41Sopenharmony_ci braid(crc_braid_table, crc_braid_big_table, N, W); 3411cb0ef41Sopenharmony_ci#endif 3421cb0ef41Sopenharmony_ci 3431cb0ef41Sopenharmony_ci#ifdef MAKECRCH 3441cb0ef41Sopenharmony_ci { 3451cb0ef41Sopenharmony_ci /* 3461cb0ef41Sopenharmony_ci The crc32.h header file contains tables for both 32-bit and 64-bit 3471cb0ef41Sopenharmony_ci z_word_t's, and so requires a 64-bit type be available. In that case, 3481cb0ef41Sopenharmony_ci z_word_t must be defined to be 64-bits. This code then also generates 3491cb0ef41Sopenharmony_ci and writes out the tables for the case that z_word_t is 32 bits. 3501cb0ef41Sopenharmony_ci */ 3511cb0ef41Sopenharmony_ci#if !defined(W) || W != 8 3521cb0ef41Sopenharmony_ci# error Need a 64-bit integer type in order to generate crc32.h. 3531cb0ef41Sopenharmony_ci#endif 3541cb0ef41Sopenharmony_ci FILE *out; 3551cb0ef41Sopenharmony_ci int k, n; 3561cb0ef41Sopenharmony_ci z_crc_t ltl[8][256]; 3571cb0ef41Sopenharmony_ci z_word_t big[8][256]; 3581cb0ef41Sopenharmony_ci 3591cb0ef41Sopenharmony_ci out = fopen("crc32.h", "w"); 3601cb0ef41Sopenharmony_ci if (out == NULL) return; 3611cb0ef41Sopenharmony_ci 3621cb0ef41Sopenharmony_ci /* write out little-endian CRC table to crc32.h */ 3631cb0ef41Sopenharmony_ci fprintf(out, 3641cb0ef41Sopenharmony_ci "/* crc32.h -- tables for rapid CRC calculation\n" 3651cb0ef41Sopenharmony_ci " * Generated automatically by crc32.c\n */\n" 3661cb0ef41Sopenharmony_ci "\n" 3671cb0ef41Sopenharmony_ci "local const z_crc_t FAR crc_table[] = {\n" 3681cb0ef41Sopenharmony_ci " "); 3691cb0ef41Sopenharmony_ci write_table(out, crc_table, 256); 3701cb0ef41Sopenharmony_ci fprintf(out, 3711cb0ef41Sopenharmony_ci "};\n"); 3721cb0ef41Sopenharmony_ci 3731cb0ef41Sopenharmony_ci /* write out big-endian CRC table for 64-bit z_word_t to crc32.h */ 3741cb0ef41Sopenharmony_ci fprintf(out, 3751cb0ef41Sopenharmony_ci "\n" 3761cb0ef41Sopenharmony_ci "#ifdef W\n" 3771cb0ef41Sopenharmony_ci "\n" 3781cb0ef41Sopenharmony_ci "#if W == 8\n" 3791cb0ef41Sopenharmony_ci "\n" 3801cb0ef41Sopenharmony_ci "local const z_word_t FAR crc_big_table[] = {\n" 3811cb0ef41Sopenharmony_ci " "); 3821cb0ef41Sopenharmony_ci write_table64(out, crc_big_table, 256); 3831cb0ef41Sopenharmony_ci fprintf(out, 3841cb0ef41Sopenharmony_ci "};\n"); 3851cb0ef41Sopenharmony_ci 3861cb0ef41Sopenharmony_ci /* write out big-endian CRC table for 32-bit z_word_t to crc32.h */ 3871cb0ef41Sopenharmony_ci fprintf(out, 3881cb0ef41Sopenharmony_ci "\n" 3891cb0ef41Sopenharmony_ci "#else /* W == 4 */\n" 3901cb0ef41Sopenharmony_ci "\n" 3911cb0ef41Sopenharmony_ci "local const z_word_t FAR crc_big_table[] = {\n" 3921cb0ef41Sopenharmony_ci " "); 3931cb0ef41Sopenharmony_ci write_table32hi(out, crc_big_table, 256); 3941cb0ef41Sopenharmony_ci fprintf(out, 3951cb0ef41Sopenharmony_ci "};\n" 3961cb0ef41Sopenharmony_ci "\n" 3971cb0ef41Sopenharmony_ci "#endif\n"); 3981cb0ef41Sopenharmony_ci 3991cb0ef41Sopenharmony_ci /* write out braid tables for each value of N */ 4001cb0ef41Sopenharmony_ci for (n = 1; n <= 6; n++) { 4011cb0ef41Sopenharmony_ci fprintf(out, 4021cb0ef41Sopenharmony_ci "\n" 4031cb0ef41Sopenharmony_ci "#if N == %d\n", n); 4041cb0ef41Sopenharmony_ci 4051cb0ef41Sopenharmony_ci /* compute braid tables for this N and 64-bit word_t */ 4061cb0ef41Sopenharmony_ci braid(ltl, big, n, 8); 4071cb0ef41Sopenharmony_ci 4081cb0ef41Sopenharmony_ci /* write out braid tables for 64-bit z_word_t to crc32.h */ 4091cb0ef41Sopenharmony_ci fprintf(out, 4101cb0ef41Sopenharmony_ci "\n" 4111cb0ef41Sopenharmony_ci "#if W == 8\n" 4121cb0ef41Sopenharmony_ci "\n" 4131cb0ef41Sopenharmony_ci "local const z_crc_t FAR crc_braid_table[][256] = {\n"); 4141cb0ef41Sopenharmony_ci for (k = 0; k < 8; k++) { 4151cb0ef41Sopenharmony_ci fprintf(out, " {"); 4161cb0ef41Sopenharmony_ci write_table(out, ltl[k], 256); 4171cb0ef41Sopenharmony_ci fprintf(out, "}%s", k < 7 ? ",\n" : ""); 4181cb0ef41Sopenharmony_ci } 4191cb0ef41Sopenharmony_ci fprintf(out, 4201cb0ef41Sopenharmony_ci "};\n" 4211cb0ef41Sopenharmony_ci "\n" 4221cb0ef41Sopenharmony_ci "local const z_word_t FAR crc_braid_big_table[][256] = {\n"); 4231cb0ef41Sopenharmony_ci for (k = 0; k < 8; k++) { 4241cb0ef41Sopenharmony_ci fprintf(out, " {"); 4251cb0ef41Sopenharmony_ci write_table64(out, big[k], 256); 4261cb0ef41Sopenharmony_ci fprintf(out, "}%s", k < 7 ? ",\n" : ""); 4271cb0ef41Sopenharmony_ci } 4281cb0ef41Sopenharmony_ci fprintf(out, 4291cb0ef41Sopenharmony_ci "};\n"); 4301cb0ef41Sopenharmony_ci 4311cb0ef41Sopenharmony_ci /* compute braid tables for this N and 32-bit word_t */ 4321cb0ef41Sopenharmony_ci braid(ltl, big, n, 4); 4331cb0ef41Sopenharmony_ci 4341cb0ef41Sopenharmony_ci /* write out braid tables for 32-bit z_word_t to crc32.h */ 4351cb0ef41Sopenharmony_ci fprintf(out, 4361cb0ef41Sopenharmony_ci "\n" 4371cb0ef41Sopenharmony_ci "#else /* W == 4 */\n" 4381cb0ef41Sopenharmony_ci "\n" 4391cb0ef41Sopenharmony_ci "local const z_crc_t FAR crc_braid_table[][256] = {\n"); 4401cb0ef41Sopenharmony_ci for (k = 0; k < 4; k++) { 4411cb0ef41Sopenharmony_ci fprintf(out, " {"); 4421cb0ef41Sopenharmony_ci write_table(out, ltl[k], 256); 4431cb0ef41Sopenharmony_ci fprintf(out, "}%s", k < 3 ? ",\n" : ""); 4441cb0ef41Sopenharmony_ci } 4451cb0ef41Sopenharmony_ci fprintf(out, 4461cb0ef41Sopenharmony_ci "};\n" 4471cb0ef41Sopenharmony_ci "\n" 4481cb0ef41Sopenharmony_ci "local const z_word_t FAR crc_braid_big_table[][256] = {\n"); 4491cb0ef41Sopenharmony_ci for (k = 0; k < 4; k++) { 4501cb0ef41Sopenharmony_ci fprintf(out, " {"); 4511cb0ef41Sopenharmony_ci write_table32hi(out, big[k], 256); 4521cb0ef41Sopenharmony_ci fprintf(out, "}%s", k < 3 ? ",\n" : ""); 4531cb0ef41Sopenharmony_ci } 4541cb0ef41Sopenharmony_ci fprintf(out, 4551cb0ef41Sopenharmony_ci "};\n" 4561cb0ef41Sopenharmony_ci "\n" 4571cb0ef41Sopenharmony_ci "#endif\n" 4581cb0ef41Sopenharmony_ci "\n" 4591cb0ef41Sopenharmony_ci "#endif\n"); 4601cb0ef41Sopenharmony_ci } 4611cb0ef41Sopenharmony_ci fprintf(out, 4621cb0ef41Sopenharmony_ci "\n" 4631cb0ef41Sopenharmony_ci "#endif\n"); 4641cb0ef41Sopenharmony_ci 4651cb0ef41Sopenharmony_ci /* write out zeros operator table to crc32.h */ 4661cb0ef41Sopenharmony_ci fprintf(out, 4671cb0ef41Sopenharmony_ci "\n" 4681cb0ef41Sopenharmony_ci "local const z_crc_t FAR x2n_table[] = {\n" 4691cb0ef41Sopenharmony_ci " "); 4701cb0ef41Sopenharmony_ci write_table(out, x2n_table, 32); 4711cb0ef41Sopenharmony_ci fprintf(out, 4721cb0ef41Sopenharmony_ci "};\n"); 4731cb0ef41Sopenharmony_ci fclose(out); 4741cb0ef41Sopenharmony_ci } 4751cb0ef41Sopenharmony_ci#endif /* MAKECRCH */ 4761cb0ef41Sopenharmony_ci} 4771cb0ef41Sopenharmony_ci 4781cb0ef41Sopenharmony_ci#ifdef MAKECRCH 4791cb0ef41Sopenharmony_ci 4801cb0ef41Sopenharmony_ci/* 4811cb0ef41Sopenharmony_ci Write the 32-bit values in table[0..k-1] to out, five per line in 4821cb0ef41Sopenharmony_ci hexadecimal separated by commas. 4831cb0ef41Sopenharmony_ci */ 4841cb0ef41Sopenharmony_cilocal void write_table(FILE *out, const z_crc_t FAR *table, int k) { 4851cb0ef41Sopenharmony_ci int n; 4861cb0ef41Sopenharmony_ci 4871cb0ef41Sopenharmony_ci for (n = 0; n < k; n++) 4881cb0ef41Sopenharmony_ci fprintf(out, "%s0x%08lx%s", n == 0 || n % 5 ? "" : " ", 4891cb0ef41Sopenharmony_ci (unsigned long)(table[n]), 4901cb0ef41Sopenharmony_ci n == k - 1 ? "" : (n % 5 == 4 ? ",\n" : ", ")); 4911cb0ef41Sopenharmony_ci} 4921cb0ef41Sopenharmony_ci 4931cb0ef41Sopenharmony_ci/* 4941cb0ef41Sopenharmony_ci Write the high 32-bits of each value in table[0..k-1] to out, five per line 4951cb0ef41Sopenharmony_ci in hexadecimal separated by commas. 4961cb0ef41Sopenharmony_ci */ 4971cb0ef41Sopenharmony_cilocal void write_table32hi(FILE *out, const z_word_t FAR *table, int k) { 4981cb0ef41Sopenharmony_ci int n; 4991cb0ef41Sopenharmony_ci 5001cb0ef41Sopenharmony_ci for (n = 0; n < k; n++) 5011cb0ef41Sopenharmony_ci fprintf(out, "%s0x%08lx%s", n == 0 || n % 5 ? "" : " ", 5021cb0ef41Sopenharmony_ci (unsigned long)(table[n] >> 32), 5031cb0ef41Sopenharmony_ci n == k - 1 ? "" : (n % 5 == 4 ? ",\n" : ", ")); 5041cb0ef41Sopenharmony_ci} 5051cb0ef41Sopenharmony_ci 5061cb0ef41Sopenharmony_ci/* 5071cb0ef41Sopenharmony_ci Write the 64-bit values in table[0..k-1] to out, three per line in 5081cb0ef41Sopenharmony_ci hexadecimal separated by commas. This assumes that if there is a 64-bit 5091cb0ef41Sopenharmony_ci type, then there is also a long long integer type, and it is at least 64 5101cb0ef41Sopenharmony_ci bits. If not, then the type cast and format string can be adjusted 5111cb0ef41Sopenharmony_ci accordingly. 5121cb0ef41Sopenharmony_ci */ 5131cb0ef41Sopenharmony_cilocal void write_table64(FILE *out, const z_word_t FAR *table, int k) { 5141cb0ef41Sopenharmony_ci int n; 5151cb0ef41Sopenharmony_ci 5161cb0ef41Sopenharmony_ci for (n = 0; n < k; n++) 5171cb0ef41Sopenharmony_ci fprintf(out, "%s0x%016llx%s", n == 0 || n % 3 ? "" : " ", 5181cb0ef41Sopenharmony_ci (unsigned long long)(table[n]), 5191cb0ef41Sopenharmony_ci n == k - 1 ? "" : (n % 3 == 2 ? ",\n" : ", ")); 5201cb0ef41Sopenharmony_ci} 5211cb0ef41Sopenharmony_ci 5221cb0ef41Sopenharmony_ci/* Actually do the deed. */ 5231cb0ef41Sopenharmony_ciint main(void) { 5241cb0ef41Sopenharmony_ci make_crc_table(); 5251cb0ef41Sopenharmony_ci return 0; 5261cb0ef41Sopenharmony_ci} 5271cb0ef41Sopenharmony_ci 5281cb0ef41Sopenharmony_ci#endif /* MAKECRCH */ 5291cb0ef41Sopenharmony_ci 5301cb0ef41Sopenharmony_ci#ifdef W 5311cb0ef41Sopenharmony_ci/* 5321cb0ef41Sopenharmony_ci Generate the little and big-endian braid tables for the given n and z_word_t 5331cb0ef41Sopenharmony_ci size w. Each array must have room for w blocks of 256 elements. 5341cb0ef41Sopenharmony_ci */ 5351cb0ef41Sopenharmony_cilocal void braid(z_crc_t ltl[][256], z_word_t big[][256], int n, int w) { 5361cb0ef41Sopenharmony_ci int k; 5371cb0ef41Sopenharmony_ci z_crc_t i, p, q; 5381cb0ef41Sopenharmony_ci for (k = 0; k < w; k++) { 5391cb0ef41Sopenharmony_ci p = x2nmodp((n * w + 3 - k) << 3, 0); 5401cb0ef41Sopenharmony_ci ltl[k][0] = 0; 5411cb0ef41Sopenharmony_ci big[w - 1 - k][0] = 0; 5421cb0ef41Sopenharmony_ci for (i = 1; i < 256; i++) { 5431cb0ef41Sopenharmony_ci ltl[k][i] = q = multmodp(i << 24, p); 5441cb0ef41Sopenharmony_ci big[w - 1 - k][i] = byte_swap(q); 5451cb0ef41Sopenharmony_ci } 5461cb0ef41Sopenharmony_ci } 5471cb0ef41Sopenharmony_ci} 5481cb0ef41Sopenharmony_ci#endif 5491cb0ef41Sopenharmony_ci 5501cb0ef41Sopenharmony_ci#endif /* DYNAMIC_CRC_TABLE */ 5511cb0ef41Sopenharmony_ci 5521cb0ef41Sopenharmony_ci/* ========================================================================= 5531cb0ef41Sopenharmony_ci * This function can be used by asm versions of crc32(), and to force the 5541cb0ef41Sopenharmony_ci * generation of the CRC tables in a threaded application. 5551cb0ef41Sopenharmony_ci */ 5561cb0ef41Sopenharmony_ciconst z_crc_t FAR * ZEXPORT get_crc_table(void) { 5571cb0ef41Sopenharmony_ci#ifdef DYNAMIC_CRC_TABLE 5581cb0ef41Sopenharmony_ci once(&made, make_crc_table); 5591cb0ef41Sopenharmony_ci#endif /* DYNAMIC_CRC_TABLE */ 5601cb0ef41Sopenharmony_ci return (const z_crc_t FAR *)crc_table; 5611cb0ef41Sopenharmony_ci} 5621cb0ef41Sopenharmony_ci 5631cb0ef41Sopenharmony_ci/* ========================================================================= 5641cb0ef41Sopenharmony_ci * Use ARM machine instructions if available. This will compute the CRC about 5651cb0ef41Sopenharmony_ci * ten times faster than the braided calculation. This code does not check for 5661cb0ef41Sopenharmony_ci * the presence of the CRC instruction at run time. __ARM_FEATURE_CRC32 will 5671cb0ef41Sopenharmony_ci * only be defined if the compilation specifies an ARM processor architecture 5681cb0ef41Sopenharmony_ci * that has the instructions. For example, compiling with -march=armv8.1-a or 5691cb0ef41Sopenharmony_ci * -march=armv8-a+crc, or -march=native if the compile machine has the crc32 5701cb0ef41Sopenharmony_ci * instructions. 5711cb0ef41Sopenharmony_ci */ 5721cb0ef41Sopenharmony_ci#if ARMCRC32_CANONICAL_ZLIB 5731cb0ef41Sopenharmony_ci 5741cb0ef41Sopenharmony_ci/* 5751cb0ef41Sopenharmony_ci Constants empirically determined to maximize speed. These values are from 5761cb0ef41Sopenharmony_ci measurements on a Cortex-A57. Your mileage may vary. 5771cb0ef41Sopenharmony_ci */ 5781cb0ef41Sopenharmony_ci#define Z_BATCH 3990 /* number of words in a batch */ 5791cb0ef41Sopenharmony_ci#define Z_BATCH_ZEROS 0xa10d3d0c /* computed from Z_BATCH = 3990 */ 5801cb0ef41Sopenharmony_ci#define Z_BATCH_MIN 800 /* fewest words in a final batch */ 5811cb0ef41Sopenharmony_ci 5821cb0ef41Sopenharmony_ciunsigned long ZEXPORT crc32_z(unsigned long crc, const unsigned char FAR *buf, 5831cb0ef41Sopenharmony_ci z_size_t len) { 5841cb0ef41Sopenharmony_ci z_crc_t val; 5851cb0ef41Sopenharmony_ci z_word_t crc1, crc2; 5861cb0ef41Sopenharmony_ci const z_word_t *word; 5871cb0ef41Sopenharmony_ci z_word_t val0, val1, val2; 5881cb0ef41Sopenharmony_ci z_size_t last, last2, i; 5891cb0ef41Sopenharmony_ci z_size_t num; 5901cb0ef41Sopenharmony_ci 5911cb0ef41Sopenharmony_ci /* Return initial CRC, if requested. */ 5921cb0ef41Sopenharmony_ci if (buf == Z_NULL) return 0; 5931cb0ef41Sopenharmony_ci 5941cb0ef41Sopenharmony_ci#ifdef DYNAMIC_CRC_TABLE 5951cb0ef41Sopenharmony_ci once(&made, make_crc_table); 5961cb0ef41Sopenharmony_ci#endif /* DYNAMIC_CRC_TABLE */ 5971cb0ef41Sopenharmony_ci 5981cb0ef41Sopenharmony_ci /* Pre-condition the CRC */ 5991cb0ef41Sopenharmony_ci crc = (~crc) & 0xffffffff; 6001cb0ef41Sopenharmony_ci 6011cb0ef41Sopenharmony_ci /* Compute the CRC up to a word boundary. */ 6021cb0ef41Sopenharmony_ci while (len && ((z_size_t)buf & 7) != 0) { 6031cb0ef41Sopenharmony_ci len--; 6041cb0ef41Sopenharmony_ci val = *buf++; 6051cb0ef41Sopenharmony_ci __asm__ volatile("crc32b %w0, %w0, %w1" : "+r"(crc) : "r"(val)); 6061cb0ef41Sopenharmony_ci } 6071cb0ef41Sopenharmony_ci 6081cb0ef41Sopenharmony_ci /* Prepare to compute the CRC on full 64-bit words word[0..num-1]. */ 6091cb0ef41Sopenharmony_ci word = (z_word_t const *)buf; 6101cb0ef41Sopenharmony_ci num = len >> 3; 6111cb0ef41Sopenharmony_ci len &= 7; 6121cb0ef41Sopenharmony_ci 6131cb0ef41Sopenharmony_ci /* Do three interleaved CRCs to realize the throughput of one crc32x 6141cb0ef41Sopenharmony_ci instruction per cycle. Each CRC is calculated on Z_BATCH words. The 6151cb0ef41Sopenharmony_ci three CRCs are combined into a single CRC after each set of batches. */ 6161cb0ef41Sopenharmony_ci while (num >= 3 * Z_BATCH) { 6171cb0ef41Sopenharmony_ci crc1 = 0; 6181cb0ef41Sopenharmony_ci crc2 = 0; 6191cb0ef41Sopenharmony_ci for (i = 0; i < Z_BATCH; i++) { 6201cb0ef41Sopenharmony_ci val0 = word[i]; 6211cb0ef41Sopenharmony_ci val1 = word[i + Z_BATCH]; 6221cb0ef41Sopenharmony_ci val2 = word[i + 2 * Z_BATCH]; 6231cb0ef41Sopenharmony_ci __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc) : "r"(val0)); 6241cb0ef41Sopenharmony_ci __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc1) : "r"(val1)); 6251cb0ef41Sopenharmony_ci __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc2) : "r"(val2)); 6261cb0ef41Sopenharmony_ci } 6271cb0ef41Sopenharmony_ci word += 3 * Z_BATCH; 6281cb0ef41Sopenharmony_ci num -= 3 * Z_BATCH; 6291cb0ef41Sopenharmony_ci crc = multmodp(Z_BATCH_ZEROS, crc) ^ crc1; 6301cb0ef41Sopenharmony_ci crc = multmodp(Z_BATCH_ZEROS, crc) ^ crc2; 6311cb0ef41Sopenharmony_ci } 6321cb0ef41Sopenharmony_ci 6331cb0ef41Sopenharmony_ci /* Do one last smaller batch with the remaining words, if there are enough 6341cb0ef41Sopenharmony_ci to pay for the combination of CRCs. */ 6351cb0ef41Sopenharmony_ci last = num / 3; 6361cb0ef41Sopenharmony_ci if (last >= Z_BATCH_MIN) { 6371cb0ef41Sopenharmony_ci last2 = last << 1; 6381cb0ef41Sopenharmony_ci crc1 = 0; 6391cb0ef41Sopenharmony_ci crc2 = 0; 6401cb0ef41Sopenharmony_ci for (i = 0; i < last; i++) { 6411cb0ef41Sopenharmony_ci val0 = word[i]; 6421cb0ef41Sopenharmony_ci val1 = word[i + last]; 6431cb0ef41Sopenharmony_ci val2 = word[i + last2]; 6441cb0ef41Sopenharmony_ci __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc) : "r"(val0)); 6451cb0ef41Sopenharmony_ci __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc1) : "r"(val1)); 6461cb0ef41Sopenharmony_ci __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc2) : "r"(val2)); 6471cb0ef41Sopenharmony_ci } 6481cb0ef41Sopenharmony_ci word += 3 * last; 6491cb0ef41Sopenharmony_ci num -= 3 * last; 6501cb0ef41Sopenharmony_ci val = x2nmodp(last, 6); 6511cb0ef41Sopenharmony_ci crc = multmodp(val, crc) ^ crc1; 6521cb0ef41Sopenharmony_ci crc = multmodp(val, crc) ^ crc2; 6531cb0ef41Sopenharmony_ci } 6541cb0ef41Sopenharmony_ci 6551cb0ef41Sopenharmony_ci /* Compute the CRC on any remaining words. */ 6561cb0ef41Sopenharmony_ci for (i = 0; i < num; i++) { 6571cb0ef41Sopenharmony_ci val0 = word[i]; 6581cb0ef41Sopenharmony_ci __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc) : "r"(val0)); 6591cb0ef41Sopenharmony_ci } 6601cb0ef41Sopenharmony_ci word += num; 6611cb0ef41Sopenharmony_ci 6621cb0ef41Sopenharmony_ci /* Complete the CRC on any remaining bytes. */ 6631cb0ef41Sopenharmony_ci buf = (const unsigned char FAR *)word; 6641cb0ef41Sopenharmony_ci while (len) { 6651cb0ef41Sopenharmony_ci len--; 6661cb0ef41Sopenharmony_ci val = *buf++; 6671cb0ef41Sopenharmony_ci __asm__ volatile("crc32b %w0, %w0, %w1" : "+r"(crc) : "r"(val)); 6681cb0ef41Sopenharmony_ci } 6691cb0ef41Sopenharmony_ci 6701cb0ef41Sopenharmony_ci /* Return the CRC, post-conditioned. */ 6711cb0ef41Sopenharmony_ci return crc ^ 0xffffffff; 6721cb0ef41Sopenharmony_ci} 6731cb0ef41Sopenharmony_ci 6741cb0ef41Sopenharmony_ci#else 6751cb0ef41Sopenharmony_ci 6761cb0ef41Sopenharmony_ci#ifdef W 6771cb0ef41Sopenharmony_ci 6781cb0ef41Sopenharmony_ci/* 6791cb0ef41Sopenharmony_ci Return the CRC of the W bytes in the word_t data, taking the 6801cb0ef41Sopenharmony_ci least-significant byte of the word as the first byte of data, without any pre 6811cb0ef41Sopenharmony_ci or post conditioning. This is used to combine the CRCs of each braid. 6821cb0ef41Sopenharmony_ci */ 6831cb0ef41Sopenharmony_cilocal z_crc_t crc_word(z_word_t data) { 6841cb0ef41Sopenharmony_ci int k; 6851cb0ef41Sopenharmony_ci for (k = 0; k < W; k++) 6861cb0ef41Sopenharmony_ci data = (data >> 8) ^ crc_table[data & 0xff]; 6871cb0ef41Sopenharmony_ci return (z_crc_t)data; 6881cb0ef41Sopenharmony_ci} 6891cb0ef41Sopenharmony_ci 6901cb0ef41Sopenharmony_cilocal z_word_t crc_word_big(z_word_t data) { 6911cb0ef41Sopenharmony_ci int k; 6921cb0ef41Sopenharmony_ci for (k = 0; k < W; k++) 6931cb0ef41Sopenharmony_ci data = (data << 8) ^ 6941cb0ef41Sopenharmony_ci crc_big_table[(data >> ((W - 1) << 3)) & 0xff]; 6951cb0ef41Sopenharmony_ci return data; 6961cb0ef41Sopenharmony_ci} 6971cb0ef41Sopenharmony_ci 6981cb0ef41Sopenharmony_ci#endif 6991cb0ef41Sopenharmony_ci 7001cb0ef41Sopenharmony_ci/* ========================================================================= */ 7011cb0ef41Sopenharmony_ciunsigned long ZEXPORT crc32_z(unsigned long crc, const unsigned char FAR *buf, 7021cb0ef41Sopenharmony_ci z_size_t len) { 7031cb0ef41Sopenharmony_ci /* 7041cb0ef41Sopenharmony_ci * zlib convention is to call crc32(0, NULL, 0); before making 7051cb0ef41Sopenharmony_ci * calls to crc32(). So this is a good, early (and infrequent) 7061cb0ef41Sopenharmony_ci * place to cache CPU features if needed for those later, more 7071cb0ef41Sopenharmony_ci * interesting crc32() calls. 7081cb0ef41Sopenharmony_ci */ 7091cb0ef41Sopenharmony_ci#if defined(CRC32_SIMD_SSE42_PCLMUL) || defined(CRC32_ARMV8_CRC32) 7101cb0ef41Sopenharmony_ci /* 7111cb0ef41Sopenharmony_ci * Since this routine can be freely used, check CPU features here. 7121cb0ef41Sopenharmony_ci */ 7131cb0ef41Sopenharmony_ci if (buf == Z_NULL) { 7141cb0ef41Sopenharmony_ci if (!len) /* Assume user is calling crc32(0, NULL, 0); */ 7151cb0ef41Sopenharmony_ci cpu_check_features(); 7161cb0ef41Sopenharmony_ci return 0UL; 7171cb0ef41Sopenharmony_ci } 7181cb0ef41Sopenharmony_ci 7191cb0ef41Sopenharmony_ci#endif 7201cb0ef41Sopenharmony_ci#if defined(CRC32_SIMD_AVX512_PCLMUL) 7211cb0ef41Sopenharmony_ci if (x86_cpu_enable_avx512 && len >= Z_CRC32_AVX512_MINIMUM_LENGTH) { 7221cb0ef41Sopenharmony_ci /* crc32 64-byte chunks */ 7231cb0ef41Sopenharmony_ci z_size_t chunk_size = len & ~Z_CRC32_AVX512_CHUNKSIZE_MASK; 7241cb0ef41Sopenharmony_ci crc = ~crc32_avx512_simd_(buf, chunk_size, ~(uint32_t)crc); 7251cb0ef41Sopenharmony_ci /* check remaining data */ 7261cb0ef41Sopenharmony_ci len -= chunk_size; 7271cb0ef41Sopenharmony_ci if (!len) 7281cb0ef41Sopenharmony_ci return crc; 7291cb0ef41Sopenharmony_ci /* Fall into the default crc32 for the remaining data. */ 7301cb0ef41Sopenharmony_ci buf += chunk_size; 7311cb0ef41Sopenharmony_ci } 7321cb0ef41Sopenharmony_ci#elif defined(CRC32_SIMD_SSE42_PCLMUL) 7331cb0ef41Sopenharmony_ci if (x86_cpu_enable_simd && len >= Z_CRC32_SSE42_MINIMUM_LENGTH) { 7341cb0ef41Sopenharmony_ci /* crc32 16-byte chunks */ 7351cb0ef41Sopenharmony_ci z_size_t chunk_size = len & ~Z_CRC32_SSE42_CHUNKSIZE_MASK; 7361cb0ef41Sopenharmony_ci crc = ~crc32_sse42_simd_(buf, chunk_size, ~(uint32_t)crc); 7371cb0ef41Sopenharmony_ci /* check remaining data */ 7381cb0ef41Sopenharmony_ci len -= chunk_size; 7391cb0ef41Sopenharmony_ci if (!len) 7401cb0ef41Sopenharmony_ci return crc; 7411cb0ef41Sopenharmony_ci /* Fall into the default crc32 for the remaining data. */ 7421cb0ef41Sopenharmony_ci buf += chunk_size; 7431cb0ef41Sopenharmony_ci } 7441cb0ef41Sopenharmony_ci#elif defined(CRC32_ARMV8_CRC32) 7451cb0ef41Sopenharmony_ci if (arm_cpu_enable_crc32) { 7461cb0ef41Sopenharmony_ci#if defined(__aarch64__) 7471cb0ef41Sopenharmony_ci /* PMULL is 64bit only, plus code needs at least a 64 bytes buffer. */ 7481cb0ef41Sopenharmony_ci if (arm_cpu_enable_pmull && (len > Z_CRC32_PMULL_MINIMUM_LENGTH)) { 7491cb0ef41Sopenharmony_ci const size_t chunk_size = len & ~Z_CRC32_PMULL_CHUNKSIZE_MASK; 7501cb0ef41Sopenharmony_ci crc = ~armv8_crc32_pmull_little(buf, chunk_size, ~(uint32_t)crc); 7511cb0ef41Sopenharmony_ci /* Check remaining data. */ 7521cb0ef41Sopenharmony_ci len -= chunk_size; 7531cb0ef41Sopenharmony_ci if (!len) 7541cb0ef41Sopenharmony_ci return crc; 7551cb0ef41Sopenharmony_ci 7561cb0ef41Sopenharmony_ci /* Fall through for the remaining data. */ 7571cb0ef41Sopenharmony_ci buf += chunk_size; 7581cb0ef41Sopenharmony_ci } 7591cb0ef41Sopenharmony_ci#endif 7601cb0ef41Sopenharmony_ci return armv8_crc32_little(buf, len, crc); /* Armv8@32bit or tail. */ 7611cb0ef41Sopenharmony_ci } 7621cb0ef41Sopenharmony_ci#else 7631cb0ef41Sopenharmony_ci if (buf == Z_NULL) { 7641cb0ef41Sopenharmony_ci return 0UL; 7651cb0ef41Sopenharmony_ci } 7661cb0ef41Sopenharmony_ci#endif /* CRC32_SIMD */ 7671cb0ef41Sopenharmony_ci 7681cb0ef41Sopenharmony_ci#ifdef DYNAMIC_CRC_TABLE 7691cb0ef41Sopenharmony_ci once(&made, make_crc_table); 7701cb0ef41Sopenharmony_ci#endif /* DYNAMIC_CRC_TABLE */ 7711cb0ef41Sopenharmony_ci /* Pre-condition the CRC */ 7721cb0ef41Sopenharmony_ci crc = (~crc) & 0xffffffff; 7731cb0ef41Sopenharmony_ci 7741cb0ef41Sopenharmony_ci#ifdef W 7751cb0ef41Sopenharmony_ci 7761cb0ef41Sopenharmony_ci /* If provided enough bytes, do a braided CRC calculation. */ 7771cb0ef41Sopenharmony_ci if (len >= N * W + W - 1) { 7781cb0ef41Sopenharmony_ci z_size_t blks; 7791cb0ef41Sopenharmony_ci z_word_t const *words; 7801cb0ef41Sopenharmony_ci unsigned endian; 7811cb0ef41Sopenharmony_ci int k; 7821cb0ef41Sopenharmony_ci 7831cb0ef41Sopenharmony_ci /* Compute the CRC up to a z_word_t boundary. */ 7841cb0ef41Sopenharmony_ci while (len && ((z_size_t)buf & (W - 1)) != 0) { 7851cb0ef41Sopenharmony_ci len--; 7861cb0ef41Sopenharmony_ci crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff]; 7871cb0ef41Sopenharmony_ci } 7881cb0ef41Sopenharmony_ci 7891cb0ef41Sopenharmony_ci /* Compute the CRC on as many N z_word_t blocks as are available. */ 7901cb0ef41Sopenharmony_ci blks = len / (N * W); 7911cb0ef41Sopenharmony_ci len -= blks * N * W; 7921cb0ef41Sopenharmony_ci words = (z_word_t const *)buf; 7931cb0ef41Sopenharmony_ci 7941cb0ef41Sopenharmony_ci /* Do endian check at execution time instead of compile time, since ARM 7951cb0ef41Sopenharmony_ci processors can change the endianness at execution time. If the 7961cb0ef41Sopenharmony_ci compiler knows what the endianness will be, it can optimize out the 7971cb0ef41Sopenharmony_ci check and the unused branch. */ 7981cb0ef41Sopenharmony_ci endian = 1; 7991cb0ef41Sopenharmony_ci if (*(unsigned char *)&endian) { 8001cb0ef41Sopenharmony_ci /* Little endian. */ 8011cb0ef41Sopenharmony_ci 8021cb0ef41Sopenharmony_ci z_crc_t crc0; 8031cb0ef41Sopenharmony_ci z_word_t word0; 8041cb0ef41Sopenharmony_ci#if N > 1 8051cb0ef41Sopenharmony_ci z_crc_t crc1; 8061cb0ef41Sopenharmony_ci z_word_t word1; 8071cb0ef41Sopenharmony_ci#if N > 2 8081cb0ef41Sopenharmony_ci z_crc_t crc2; 8091cb0ef41Sopenharmony_ci z_word_t word2; 8101cb0ef41Sopenharmony_ci#if N > 3 8111cb0ef41Sopenharmony_ci z_crc_t crc3; 8121cb0ef41Sopenharmony_ci z_word_t word3; 8131cb0ef41Sopenharmony_ci#if N > 4 8141cb0ef41Sopenharmony_ci z_crc_t crc4; 8151cb0ef41Sopenharmony_ci z_word_t word4; 8161cb0ef41Sopenharmony_ci#if N > 5 8171cb0ef41Sopenharmony_ci z_crc_t crc5; 8181cb0ef41Sopenharmony_ci z_word_t word5; 8191cb0ef41Sopenharmony_ci#endif 8201cb0ef41Sopenharmony_ci#endif 8211cb0ef41Sopenharmony_ci#endif 8221cb0ef41Sopenharmony_ci#endif 8231cb0ef41Sopenharmony_ci#endif 8241cb0ef41Sopenharmony_ci 8251cb0ef41Sopenharmony_ci /* Initialize the CRC for each braid. */ 8261cb0ef41Sopenharmony_ci crc0 = crc; 8271cb0ef41Sopenharmony_ci#if N > 1 8281cb0ef41Sopenharmony_ci crc1 = 0; 8291cb0ef41Sopenharmony_ci#if N > 2 8301cb0ef41Sopenharmony_ci crc2 = 0; 8311cb0ef41Sopenharmony_ci#if N > 3 8321cb0ef41Sopenharmony_ci crc3 = 0; 8331cb0ef41Sopenharmony_ci#if N > 4 8341cb0ef41Sopenharmony_ci crc4 = 0; 8351cb0ef41Sopenharmony_ci#if N > 5 8361cb0ef41Sopenharmony_ci crc5 = 0; 8371cb0ef41Sopenharmony_ci#endif 8381cb0ef41Sopenharmony_ci#endif 8391cb0ef41Sopenharmony_ci#endif 8401cb0ef41Sopenharmony_ci#endif 8411cb0ef41Sopenharmony_ci#endif 8421cb0ef41Sopenharmony_ci 8431cb0ef41Sopenharmony_ci /* 8441cb0ef41Sopenharmony_ci Process the first blks-1 blocks, computing the CRCs on each braid 8451cb0ef41Sopenharmony_ci independently. 8461cb0ef41Sopenharmony_ci */ 8471cb0ef41Sopenharmony_ci while (--blks) { 8481cb0ef41Sopenharmony_ci /* Load the word for each braid into registers. */ 8491cb0ef41Sopenharmony_ci word0 = crc0 ^ words[0]; 8501cb0ef41Sopenharmony_ci#if N > 1 8511cb0ef41Sopenharmony_ci word1 = crc1 ^ words[1]; 8521cb0ef41Sopenharmony_ci#if N > 2 8531cb0ef41Sopenharmony_ci word2 = crc2 ^ words[2]; 8541cb0ef41Sopenharmony_ci#if N > 3 8551cb0ef41Sopenharmony_ci word3 = crc3 ^ words[3]; 8561cb0ef41Sopenharmony_ci#if N > 4 8571cb0ef41Sopenharmony_ci word4 = crc4 ^ words[4]; 8581cb0ef41Sopenharmony_ci#if N > 5 8591cb0ef41Sopenharmony_ci word5 = crc5 ^ words[5]; 8601cb0ef41Sopenharmony_ci#endif 8611cb0ef41Sopenharmony_ci#endif 8621cb0ef41Sopenharmony_ci#endif 8631cb0ef41Sopenharmony_ci#endif 8641cb0ef41Sopenharmony_ci#endif 8651cb0ef41Sopenharmony_ci words += N; 8661cb0ef41Sopenharmony_ci 8671cb0ef41Sopenharmony_ci /* Compute and update the CRC for each word. The loop should 8681cb0ef41Sopenharmony_ci get unrolled. */ 8691cb0ef41Sopenharmony_ci crc0 = crc_braid_table[0][word0 & 0xff]; 8701cb0ef41Sopenharmony_ci#if N > 1 8711cb0ef41Sopenharmony_ci crc1 = crc_braid_table[0][word1 & 0xff]; 8721cb0ef41Sopenharmony_ci#if N > 2 8731cb0ef41Sopenharmony_ci crc2 = crc_braid_table[0][word2 & 0xff]; 8741cb0ef41Sopenharmony_ci#if N > 3 8751cb0ef41Sopenharmony_ci crc3 = crc_braid_table[0][word3 & 0xff]; 8761cb0ef41Sopenharmony_ci#if N > 4 8771cb0ef41Sopenharmony_ci crc4 = crc_braid_table[0][word4 & 0xff]; 8781cb0ef41Sopenharmony_ci#if N > 5 8791cb0ef41Sopenharmony_ci crc5 = crc_braid_table[0][word5 & 0xff]; 8801cb0ef41Sopenharmony_ci#endif 8811cb0ef41Sopenharmony_ci#endif 8821cb0ef41Sopenharmony_ci#endif 8831cb0ef41Sopenharmony_ci#endif 8841cb0ef41Sopenharmony_ci#endif 8851cb0ef41Sopenharmony_ci for (k = 1; k < W; k++) { 8861cb0ef41Sopenharmony_ci crc0 ^= crc_braid_table[k][(word0 >> (k << 3)) & 0xff]; 8871cb0ef41Sopenharmony_ci#if N > 1 8881cb0ef41Sopenharmony_ci crc1 ^= crc_braid_table[k][(word1 >> (k << 3)) & 0xff]; 8891cb0ef41Sopenharmony_ci#if N > 2 8901cb0ef41Sopenharmony_ci crc2 ^= crc_braid_table[k][(word2 >> (k << 3)) & 0xff]; 8911cb0ef41Sopenharmony_ci#if N > 3 8921cb0ef41Sopenharmony_ci crc3 ^= crc_braid_table[k][(word3 >> (k << 3)) & 0xff]; 8931cb0ef41Sopenharmony_ci#if N > 4 8941cb0ef41Sopenharmony_ci crc4 ^= crc_braid_table[k][(word4 >> (k << 3)) & 0xff]; 8951cb0ef41Sopenharmony_ci#if N > 5 8961cb0ef41Sopenharmony_ci crc5 ^= crc_braid_table[k][(word5 >> (k << 3)) & 0xff]; 8971cb0ef41Sopenharmony_ci#endif 8981cb0ef41Sopenharmony_ci#endif 8991cb0ef41Sopenharmony_ci#endif 9001cb0ef41Sopenharmony_ci#endif 9011cb0ef41Sopenharmony_ci#endif 9021cb0ef41Sopenharmony_ci } 9031cb0ef41Sopenharmony_ci } 9041cb0ef41Sopenharmony_ci 9051cb0ef41Sopenharmony_ci /* 9061cb0ef41Sopenharmony_ci Process the last block, combining the CRCs of the N braids at the 9071cb0ef41Sopenharmony_ci same time. 9081cb0ef41Sopenharmony_ci */ 9091cb0ef41Sopenharmony_ci crc = crc_word(crc0 ^ words[0]); 9101cb0ef41Sopenharmony_ci#if N > 1 9111cb0ef41Sopenharmony_ci crc = crc_word(crc1 ^ words[1] ^ crc); 9121cb0ef41Sopenharmony_ci#if N > 2 9131cb0ef41Sopenharmony_ci crc = crc_word(crc2 ^ words[2] ^ crc); 9141cb0ef41Sopenharmony_ci#if N > 3 9151cb0ef41Sopenharmony_ci crc = crc_word(crc3 ^ words[3] ^ crc); 9161cb0ef41Sopenharmony_ci#if N > 4 9171cb0ef41Sopenharmony_ci crc = crc_word(crc4 ^ words[4] ^ crc); 9181cb0ef41Sopenharmony_ci#if N > 5 9191cb0ef41Sopenharmony_ci crc = crc_word(crc5 ^ words[5] ^ crc); 9201cb0ef41Sopenharmony_ci#endif 9211cb0ef41Sopenharmony_ci#endif 9221cb0ef41Sopenharmony_ci#endif 9231cb0ef41Sopenharmony_ci#endif 9241cb0ef41Sopenharmony_ci#endif 9251cb0ef41Sopenharmony_ci words += N; 9261cb0ef41Sopenharmony_ci } 9271cb0ef41Sopenharmony_ci else { 9281cb0ef41Sopenharmony_ci /* Big endian. */ 9291cb0ef41Sopenharmony_ci 9301cb0ef41Sopenharmony_ci z_word_t crc0, word0, comb; 9311cb0ef41Sopenharmony_ci#if N > 1 9321cb0ef41Sopenharmony_ci z_word_t crc1, word1; 9331cb0ef41Sopenharmony_ci#if N > 2 9341cb0ef41Sopenharmony_ci z_word_t crc2, word2; 9351cb0ef41Sopenharmony_ci#if N > 3 9361cb0ef41Sopenharmony_ci z_word_t crc3, word3; 9371cb0ef41Sopenharmony_ci#if N > 4 9381cb0ef41Sopenharmony_ci z_word_t crc4, word4; 9391cb0ef41Sopenharmony_ci#if N > 5 9401cb0ef41Sopenharmony_ci z_word_t crc5, word5; 9411cb0ef41Sopenharmony_ci#endif 9421cb0ef41Sopenharmony_ci#endif 9431cb0ef41Sopenharmony_ci#endif 9441cb0ef41Sopenharmony_ci#endif 9451cb0ef41Sopenharmony_ci#endif 9461cb0ef41Sopenharmony_ci 9471cb0ef41Sopenharmony_ci /* Initialize the CRC for each braid. */ 9481cb0ef41Sopenharmony_ci crc0 = byte_swap(crc); 9491cb0ef41Sopenharmony_ci#if N > 1 9501cb0ef41Sopenharmony_ci crc1 = 0; 9511cb0ef41Sopenharmony_ci#if N > 2 9521cb0ef41Sopenharmony_ci crc2 = 0; 9531cb0ef41Sopenharmony_ci#if N > 3 9541cb0ef41Sopenharmony_ci crc3 = 0; 9551cb0ef41Sopenharmony_ci#if N > 4 9561cb0ef41Sopenharmony_ci crc4 = 0; 9571cb0ef41Sopenharmony_ci#if N > 5 9581cb0ef41Sopenharmony_ci crc5 = 0; 9591cb0ef41Sopenharmony_ci#endif 9601cb0ef41Sopenharmony_ci#endif 9611cb0ef41Sopenharmony_ci#endif 9621cb0ef41Sopenharmony_ci#endif 9631cb0ef41Sopenharmony_ci#endif 9641cb0ef41Sopenharmony_ci 9651cb0ef41Sopenharmony_ci /* 9661cb0ef41Sopenharmony_ci Process the first blks-1 blocks, computing the CRCs on each braid 9671cb0ef41Sopenharmony_ci independently. 9681cb0ef41Sopenharmony_ci */ 9691cb0ef41Sopenharmony_ci while (--blks) { 9701cb0ef41Sopenharmony_ci /* Load the word for each braid into registers. */ 9711cb0ef41Sopenharmony_ci word0 = crc0 ^ words[0]; 9721cb0ef41Sopenharmony_ci#if N > 1 9731cb0ef41Sopenharmony_ci word1 = crc1 ^ words[1]; 9741cb0ef41Sopenharmony_ci#if N > 2 9751cb0ef41Sopenharmony_ci word2 = crc2 ^ words[2]; 9761cb0ef41Sopenharmony_ci#if N > 3 9771cb0ef41Sopenharmony_ci word3 = crc3 ^ words[3]; 9781cb0ef41Sopenharmony_ci#if N > 4 9791cb0ef41Sopenharmony_ci word4 = crc4 ^ words[4]; 9801cb0ef41Sopenharmony_ci#if N > 5 9811cb0ef41Sopenharmony_ci word5 = crc5 ^ words[5]; 9821cb0ef41Sopenharmony_ci#endif 9831cb0ef41Sopenharmony_ci#endif 9841cb0ef41Sopenharmony_ci#endif 9851cb0ef41Sopenharmony_ci#endif 9861cb0ef41Sopenharmony_ci#endif 9871cb0ef41Sopenharmony_ci words += N; 9881cb0ef41Sopenharmony_ci 9891cb0ef41Sopenharmony_ci /* Compute and update the CRC for each word. The loop should 9901cb0ef41Sopenharmony_ci get unrolled. */ 9911cb0ef41Sopenharmony_ci crc0 = crc_braid_big_table[0][word0 & 0xff]; 9921cb0ef41Sopenharmony_ci#if N > 1 9931cb0ef41Sopenharmony_ci crc1 = crc_braid_big_table[0][word1 & 0xff]; 9941cb0ef41Sopenharmony_ci#if N > 2 9951cb0ef41Sopenharmony_ci crc2 = crc_braid_big_table[0][word2 & 0xff]; 9961cb0ef41Sopenharmony_ci#if N > 3 9971cb0ef41Sopenharmony_ci crc3 = crc_braid_big_table[0][word3 & 0xff]; 9981cb0ef41Sopenharmony_ci#if N > 4 9991cb0ef41Sopenharmony_ci crc4 = crc_braid_big_table[0][word4 & 0xff]; 10001cb0ef41Sopenharmony_ci#if N > 5 10011cb0ef41Sopenharmony_ci crc5 = crc_braid_big_table[0][word5 & 0xff]; 10021cb0ef41Sopenharmony_ci#endif 10031cb0ef41Sopenharmony_ci#endif 10041cb0ef41Sopenharmony_ci#endif 10051cb0ef41Sopenharmony_ci#endif 10061cb0ef41Sopenharmony_ci#endif 10071cb0ef41Sopenharmony_ci for (k = 1; k < W; k++) { 10081cb0ef41Sopenharmony_ci crc0 ^= crc_braid_big_table[k][(word0 >> (k << 3)) & 0xff]; 10091cb0ef41Sopenharmony_ci#if N > 1 10101cb0ef41Sopenharmony_ci crc1 ^= crc_braid_big_table[k][(word1 >> (k << 3)) & 0xff]; 10111cb0ef41Sopenharmony_ci#if N > 2 10121cb0ef41Sopenharmony_ci crc2 ^= crc_braid_big_table[k][(word2 >> (k << 3)) & 0xff]; 10131cb0ef41Sopenharmony_ci#if N > 3 10141cb0ef41Sopenharmony_ci crc3 ^= crc_braid_big_table[k][(word3 >> (k << 3)) & 0xff]; 10151cb0ef41Sopenharmony_ci#if N > 4 10161cb0ef41Sopenharmony_ci crc4 ^= crc_braid_big_table[k][(word4 >> (k << 3)) & 0xff]; 10171cb0ef41Sopenharmony_ci#if N > 5 10181cb0ef41Sopenharmony_ci crc5 ^= crc_braid_big_table[k][(word5 >> (k << 3)) & 0xff]; 10191cb0ef41Sopenharmony_ci#endif 10201cb0ef41Sopenharmony_ci#endif 10211cb0ef41Sopenharmony_ci#endif 10221cb0ef41Sopenharmony_ci#endif 10231cb0ef41Sopenharmony_ci#endif 10241cb0ef41Sopenharmony_ci } 10251cb0ef41Sopenharmony_ci } 10261cb0ef41Sopenharmony_ci 10271cb0ef41Sopenharmony_ci /* 10281cb0ef41Sopenharmony_ci Process the last block, combining the CRCs of the N braids at the 10291cb0ef41Sopenharmony_ci same time. 10301cb0ef41Sopenharmony_ci */ 10311cb0ef41Sopenharmony_ci comb = crc_word_big(crc0 ^ words[0]); 10321cb0ef41Sopenharmony_ci#if N > 1 10331cb0ef41Sopenharmony_ci comb = crc_word_big(crc1 ^ words[1] ^ comb); 10341cb0ef41Sopenharmony_ci#if N > 2 10351cb0ef41Sopenharmony_ci comb = crc_word_big(crc2 ^ words[2] ^ comb); 10361cb0ef41Sopenharmony_ci#if N > 3 10371cb0ef41Sopenharmony_ci comb = crc_word_big(crc3 ^ words[3] ^ comb); 10381cb0ef41Sopenharmony_ci#if N > 4 10391cb0ef41Sopenharmony_ci comb = crc_word_big(crc4 ^ words[4] ^ comb); 10401cb0ef41Sopenharmony_ci#if N > 5 10411cb0ef41Sopenharmony_ci comb = crc_word_big(crc5 ^ words[5] ^ comb); 10421cb0ef41Sopenharmony_ci#endif 10431cb0ef41Sopenharmony_ci#endif 10441cb0ef41Sopenharmony_ci#endif 10451cb0ef41Sopenharmony_ci#endif 10461cb0ef41Sopenharmony_ci#endif 10471cb0ef41Sopenharmony_ci words += N; 10481cb0ef41Sopenharmony_ci crc = byte_swap(comb); 10491cb0ef41Sopenharmony_ci } 10501cb0ef41Sopenharmony_ci 10511cb0ef41Sopenharmony_ci /* 10521cb0ef41Sopenharmony_ci Update the pointer to the remaining bytes to process. 10531cb0ef41Sopenharmony_ci */ 10541cb0ef41Sopenharmony_ci buf = (unsigned char const *)words; 10551cb0ef41Sopenharmony_ci } 10561cb0ef41Sopenharmony_ci 10571cb0ef41Sopenharmony_ci#endif /* W */ 10581cb0ef41Sopenharmony_ci 10591cb0ef41Sopenharmony_ci /* Complete the computation of the CRC on any remaining bytes. */ 10601cb0ef41Sopenharmony_ci while (len >= 8) { 10611cb0ef41Sopenharmony_ci len -= 8; 10621cb0ef41Sopenharmony_ci crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff]; 10631cb0ef41Sopenharmony_ci crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff]; 10641cb0ef41Sopenharmony_ci crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff]; 10651cb0ef41Sopenharmony_ci crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff]; 10661cb0ef41Sopenharmony_ci crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff]; 10671cb0ef41Sopenharmony_ci crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff]; 10681cb0ef41Sopenharmony_ci crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff]; 10691cb0ef41Sopenharmony_ci crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff]; 10701cb0ef41Sopenharmony_ci } 10711cb0ef41Sopenharmony_ci while (len) { 10721cb0ef41Sopenharmony_ci len--; 10731cb0ef41Sopenharmony_ci crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff]; 10741cb0ef41Sopenharmony_ci } 10751cb0ef41Sopenharmony_ci 10761cb0ef41Sopenharmony_ci /* Return the CRC, post-conditioned. */ 10771cb0ef41Sopenharmony_ci return crc ^ 0xffffffff; 10781cb0ef41Sopenharmony_ci} 10791cb0ef41Sopenharmony_ci 10801cb0ef41Sopenharmony_ci#endif 10811cb0ef41Sopenharmony_ci 10821cb0ef41Sopenharmony_ci/* ========================================================================= */ 10831cb0ef41Sopenharmony_ciunsigned long ZEXPORT crc32(unsigned long crc, const unsigned char FAR *buf, 10841cb0ef41Sopenharmony_ci uInt len) { 10851cb0ef41Sopenharmony_ci /* Some bots compile with optimizations disabled, others will emulate 10861cb0ef41Sopenharmony_ci * ARM on x86 and other weird combinations. 10871cb0ef41Sopenharmony_ci */ 10881cb0ef41Sopenharmony_ci#if defined(CRC32_SIMD_SSE42_PCLMUL) || defined(CRC32_ARMV8_CRC32) 10891cb0ef41Sopenharmony_ci /* We got to verify CPU features, so exploit the common usage pattern 10901cb0ef41Sopenharmony_ci * of calling this function with Z_NULL for an initial valid crc value. 10911cb0ef41Sopenharmony_ci * This allows to cache the result of the feature check and avoid extraneous 10921cb0ef41Sopenharmony_ci * function calls. 10931cb0ef41Sopenharmony_ci */ 10941cb0ef41Sopenharmony_ci if (buf == Z_NULL) { 10951cb0ef41Sopenharmony_ci if (!len) /* Assume user is calling crc32(0, NULL, 0); */ 10961cb0ef41Sopenharmony_ci cpu_check_features(); 10971cb0ef41Sopenharmony_ci return 0UL; 10981cb0ef41Sopenharmony_ci } 10991cb0ef41Sopenharmony_ci#endif 11001cb0ef41Sopenharmony_ci 11011cb0ef41Sopenharmony_ci#if defined(CRC32_ARMV8_CRC32) 11021cb0ef41Sopenharmony_ci if (arm_cpu_enable_crc32) { 11031cb0ef41Sopenharmony_ci#if defined(__aarch64__) 11041cb0ef41Sopenharmony_ci /* PMULL is 64bit only, plus code needs at least a 64 bytes buffer. */ 11051cb0ef41Sopenharmony_ci if (arm_cpu_enable_pmull && (len > Z_CRC32_PMULL_MINIMUM_LENGTH)) { 11061cb0ef41Sopenharmony_ci const size_t chunk_size = len & ~Z_CRC32_PMULL_CHUNKSIZE_MASK; 11071cb0ef41Sopenharmony_ci crc = ~armv8_crc32_pmull_little(buf, chunk_size, ~(uint32_t)crc); 11081cb0ef41Sopenharmony_ci /* Check remaining data. */ 11091cb0ef41Sopenharmony_ci len -= chunk_size; 11101cb0ef41Sopenharmony_ci if (!len) 11111cb0ef41Sopenharmony_ci return crc; 11121cb0ef41Sopenharmony_ci 11131cb0ef41Sopenharmony_ci /* Fall through for the remaining data. */ 11141cb0ef41Sopenharmony_ci buf += chunk_size; 11151cb0ef41Sopenharmony_ci } 11161cb0ef41Sopenharmony_ci#endif 11171cb0ef41Sopenharmony_ci return armv8_crc32_little(buf, len, crc); /* Armv8@32bit or tail. */ 11181cb0ef41Sopenharmony_ci } 11191cb0ef41Sopenharmony_ci#endif 11201cb0ef41Sopenharmony_ci return crc32_z(crc, buf, len); /* Armv7 or Armv8 w/o crypto extensions. */ 11211cb0ef41Sopenharmony_ci} 11221cb0ef41Sopenharmony_ci 11231cb0ef41Sopenharmony_ci/* ========================================================================= */ 11241cb0ef41Sopenharmony_ciuLong ZEXPORT crc32_combine64(uLong crc1, uLong crc2, z_off64_t len2) { 11251cb0ef41Sopenharmony_ci#ifdef DYNAMIC_CRC_TABLE 11261cb0ef41Sopenharmony_ci once(&made, make_crc_table); 11271cb0ef41Sopenharmony_ci#endif /* DYNAMIC_CRC_TABLE */ 11281cb0ef41Sopenharmony_ci return multmodp(x2nmodp(len2, 3), crc1) ^ (crc2 & 0xffffffff); 11291cb0ef41Sopenharmony_ci} 11301cb0ef41Sopenharmony_ci 11311cb0ef41Sopenharmony_ci/* ========================================================================= */ 11321cb0ef41Sopenharmony_ciuLong ZEXPORT crc32_combine(uLong crc1, uLong crc2, z_off_t len2) { 11331cb0ef41Sopenharmony_ci return crc32_combine64(crc1, crc2, (z_off64_t)len2); 11341cb0ef41Sopenharmony_ci} 11351cb0ef41Sopenharmony_ci/* ========================================================================= */ 11361cb0ef41Sopenharmony_ciuLong ZEXPORT crc32_combine_gen64(z_off64_t len2) { 11371cb0ef41Sopenharmony_ci#ifdef DYNAMIC_CRC_TABLE 11381cb0ef41Sopenharmony_ci once(&made, make_crc_table); 11391cb0ef41Sopenharmony_ci#endif /* DYNAMIC_CRC_TABLE */ 11401cb0ef41Sopenharmony_ci return x2nmodp(len2, 3); 11411cb0ef41Sopenharmony_ci} 11421cb0ef41Sopenharmony_ci 11431cb0ef41Sopenharmony_ci/* ========================================================================= */ 11441cb0ef41Sopenharmony_ciuLong ZEXPORT crc32_combine_gen(z_off_t len2) { 11451cb0ef41Sopenharmony_ci return crc32_combine_gen64((z_off64_t)len2); 11461cb0ef41Sopenharmony_ci} 11471cb0ef41Sopenharmony_ci 11481cb0ef41Sopenharmony_ci/* ========================================================================= */ 11491cb0ef41Sopenharmony_ciuLong ZEXPORT crc32_combine_op(uLong crc1, uLong crc2, uLong op) { 11501cb0ef41Sopenharmony_ci return multmodp(op, crc1) ^ (crc2 & 0xffffffff); 11511cb0ef41Sopenharmony_ci} 11521cb0ef41Sopenharmony_ci 11531cb0ef41Sopenharmony_ciZLIB_INTERNAL void crc_reset(deflate_state *const s) 11541cb0ef41Sopenharmony_ci{ 11551cb0ef41Sopenharmony_ci#ifdef CRC32_SIMD_SSE42_PCLMUL 11561cb0ef41Sopenharmony_ci if (x86_cpu_enable_simd) { 11571cb0ef41Sopenharmony_ci crc_fold_init(s); 11581cb0ef41Sopenharmony_ci return; 11591cb0ef41Sopenharmony_ci } 11601cb0ef41Sopenharmony_ci#endif 11611cb0ef41Sopenharmony_ci s->strm->adler = crc32(0L, Z_NULL, 0); 11621cb0ef41Sopenharmony_ci} 11631cb0ef41Sopenharmony_ci 11641cb0ef41Sopenharmony_ciZLIB_INTERNAL void crc_finalize(deflate_state *const s) 11651cb0ef41Sopenharmony_ci{ 11661cb0ef41Sopenharmony_ci#ifdef CRC32_SIMD_SSE42_PCLMUL 11671cb0ef41Sopenharmony_ci if (x86_cpu_enable_simd) 11681cb0ef41Sopenharmony_ci s->strm->adler = crc_fold_512to32(s); 11691cb0ef41Sopenharmony_ci#endif 11701cb0ef41Sopenharmony_ci} 11711cb0ef41Sopenharmony_ci 11721cb0ef41Sopenharmony_ciZLIB_INTERNAL void copy_with_crc(z_streamp strm, Bytef *dst, long size) 11731cb0ef41Sopenharmony_ci{ 11741cb0ef41Sopenharmony_ci#ifdef CRC32_SIMD_SSE42_PCLMUL 11751cb0ef41Sopenharmony_ci if (x86_cpu_enable_simd) { 11761cb0ef41Sopenharmony_ci crc_fold_copy(strm->state, dst, strm->next_in, size); 11771cb0ef41Sopenharmony_ci return; 11781cb0ef41Sopenharmony_ci } 11791cb0ef41Sopenharmony_ci#endif 11801cb0ef41Sopenharmony_ci zmemcpy(dst, strm->next_in, size); 11811cb0ef41Sopenharmony_ci strm->adler = crc32(strm->adler, dst, size); 11821cb0ef41Sopenharmony_ci} 1183