xref: /third_party/node/deps/zlib/crc32.c (revision 1cb0ef41)
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