Blame crc32c.c

Packit Service 584ef9
/* crc32c.c -- compute CRC-32C using the Intel crc32 instruction
Packit Service 584ef9
 * Copyright (C) 2013 Mark Adler
Packit Service 584ef9
 * Version 1.1  1 Aug 2013  Mark Adler
Packit Service 584ef9
 */
Packit Service 584ef9
Packit Service 584ef9
/*
Packit Service 584ef9
  This software is provided 'as-is', without any express or implied
Packit Service 584ef9
  warranty.  In no event will the author be held liable for any damages
Packit Service 584ef9
  arising from the use of this software.
Packit Service 584ef9
Packit Service 584ef9
  Permission is granted to anyone to use this software for any purpose,
Packit Service 584ef9
  including commercial applications, and to alter it and redistribute it
Packit Service 584ef9
  freely, subject to the following restrictions:
Packit Service 584ef9
Packit Service 584ef9
  1. The origin of this software must not be misrepresented; you must not
Packit Service 584ef9
     claim that you wrote the original software. If you use this software
Packit Service 584ef9
     in a product, an acknowledgment in the product documentation would be
Packit Service 584ef9
     appreciated but is not required.
Packit Service 584ef9
  2. Altered source versions must be plainly marked as such, and must not be
Packit Service 584ef9
     misrepresented as being the original software.
Packit Service 584ef9
  3. This notice may not be removed or altered from any source distribution.
Packit Service 584ef9
Packit Service 584ef9
  Mark Adler
Packit Service 584ef9
  madler@alumni.caltech.edu
Packit Service 584ef9
 */
Packit Service 584ef9
Packit Service 584ef9
/* Use hardware CRC instruction on Intel SSE 4.2 processors.  This computes a
Packit Service 584ef9
   CRC-32C, *not* the CRC-32 used by Ethernet and zip, gzip, etc.  A software
Packit Service 584ef9
   version is provided as a fall-back, as well as for speed comparisons. */
Packit Service 584ef9
Packit Service 584ef9
/* Version history:
Packit Service 584ef9
   1.0  10 Feb 2013  First version
Packit Service 584ef9
   1.1   1 Aug 2013  Correct comments on why three crc instructions in parallel
Packit Service 584ef9
 */
Packit Service 584ef9
Packit Service 584ef9
/* This version has been modified by dormando for inclusion in memcached */
Packit Service 584ef9
Packit Service 584ef9
#include <stdio.h>
Packit Service 584ef9
#include <stdlib.h>
Packit Service 584ef9
#include <stdint.h>
Packit Service 584ef9
#include <unistd.h>
Packit Service 584ef9
#include <pthread.h>
Packit Service 584ef9
#include "config.h"
Packit Service 584ef9
#if defined(__linux__) && defined(__aarch64__)
Packit Service 584ef9
#include <sys/auxv.h>
Packit Service 584ef9
#endif
Packit Service 584ef9
#include "crc32c.h"
Packit Service 584ef9
Packit Service 584ef9
/* CRC-32C (iSCSI) polynomial in reversed bit order. */
Packit Service 584ef9
#define POLY 0x82f63b78
Packit Service 584ef9
Packit Service 584ef9
/* Table for a quadword-at-a-time software crc. */
Packit Service 584ef9
static pthread_once_t crc32c_once_sw = PTHREAD_ONCE_INIT;
Packit Service 584ef9
static uint32_t crc32c_table[8][256];
Packit Service 584ef9
Packit Service 584ef9
/* Construct table for software CRC-32C calculation. */
Packit Service 584ef9
static void crc32c_init_sw(void)
Packit Service 584ef9
{
Packit Service 584ef9
    uint32_t n, crc, k;
Packit Service 584ef9
Packit Service 584ef9
    for (n = 0; n < 256; n++) {
Packit Service 584ef9
        crc = n;
Packit Service 584ef9
        crc = crc & 1 ? (crc >> 1) ^ POLY : crc >> 1;
Packit Service 584ef9
        crc = crc & 1 ? (crc >> 1) ^ POLY : crc >> 1;
Packit Service 584ef9
        crc = crc & 1 ? (crc >> 1) ^ POLY : crc >> 1;
Packit Service 584ef9
        crc = crc & 1 ? (crc >> 1) ^ POLY : crc >> 1;
Packit Service 584ef9
        crc = crc & 1 ? (crc >> 1) ^ POLY : crc >> 1;
Packit Service 584ef9
        crc = crc & 1 ? (crc >> 1) ^ POLY : crc >> 1;
Packit Service 584ef9
        crc = crc & 1 ? (crc >> 1) ^ POLY : crc >> 1;
Packit Service 584ef9
        crc = crc & 1 ? (crc >> 1) ^ POLY : crc >> 1;
Packit Service 584ef9
        crc32c_table[0][n] = crc;
Packit Service 584ef9
    }
Packit Service 584ef9
    for (n = 0; n < 256; n++) {
Packit Service 584ef9
        crc = crc32c_table[0][n];
Packit Service 584ef9
        for (k = 1; k < 8; k++) {
Packit Service 584ef9
            crc = crc32c_table[0][crc & 0xff] ^ (crc >> 8);
Packit Service 584ef9
            crc32c_table[k][n] = crc;
Packit Service 584ef9
        }
Packit Service 584ef9
    }
Packit Service 584ef9
}
Packit Service 584ef9
Packit Service 584ef9
/* Table-driven software version as a fall-back.  This is about 15 times slower
Packit Service 584ef9
   than using the hardware instructions.  This assumes little-endian integers,
Packit Service 584ef9
   as is the case on Intel processors that the assembler code here is for. */
Packit Service 584ef9
static uint32_t crc32c_sw(uint32_t crci, const void *buf, size_t len)
Packit Service 584ef9
{
Packit Service 584ef9
    const unsigned char *next = buf;
Packit Service 584ef9
    uint64_t crc;
Packit Service 584ef9
Packit Service 584ef9
    pthread_once(&crc32c_once_sw, crc32c_init_sw);
Packit Service 584ef9
    crc = crci ^ 0xffffffff;
Packit Service 584ef9
    while (len && ((uintptr_t)next & 7) != 0) {
Packit Service 584ef9
        crc = crc32c_table[0][(crc ^ *next++) & 0xff] ^ (crc >> 8);
Packit Service 584ef9
        len--;
Packit Service 584ef9
    }
Packit Service 584ef9
    while (len >= 8) {
Packit Service 584ef9
        crc ^= *(uint64_t *)next;
Packit Service 584ef9
        crc = crc32c_table[7][crc & 0xff] ^
Packit Service 584ef9
              crc32c_table[6][(crc >> 8) & 0xff] ^
Packit Service 584ef9
              crc32c_table[5][(crc >> 16) & 0xff] ^
Packit Service 584ef9
              crc32c_table[4][(crc >> 24) & 0xff] ^
Packit Service 584ef9
              crc32c_table[3][(crc >> 32) & 0xff] ^
Packit Service 584ef9
              crc32c_table[2][(crc >> 40) & 0xff] ^
Packit Service 584ef9
              crc32c_table[1][(crc >> 48) & 0xff] ^
Packit Service 584ef9
              crc32c_table[0][crc >> 56];
Packit Service 584ef9
        next += 8;
Packit Service 584ef9
        len -= 8;
Packit Service 584ef9
    }
Packit Service 584ef9
    while (len) {
Packit Service 584ef9
        crc = crc32c_table[0][(crc ^ *next++) & 0xff] ^ (crc >> 8);
Packit Service 584ef9
        len--;
Packit Service 584ef9
    }
Packit Service 584ef9
    return (uint32_t)crc ^ 0xffffffff;
Packit Service 584ef9
}
Packit Service 584ef9
Packit Service 584ef9
/* Hardware CRC support for aarch64 platform */
Packit Service 584ef9
#if defined(__linux__) && defined(__aarch64__) && defined(ARM_CRC32)
Packit Service 584ef9
Packit Service 584ef9
#define CRC32CX(crc, value) __asm__("crc32cx %w[c], %w[c], %x[v]":[c]"+r"(crc):[v]"r"(+value))
Packit Service 584ef9
#define CRC32CW(crc, value) __asm__("crc32cw %w[c], %w[c], %w[v]":[c]"+r"(crc):[v]"r"(+value))
Packit Service 584ef9
#define CRC32CH(crc, value) __asm__("crc32ch %w[c], %w[c], %w[v]":[c]"+r"(crc):[v]"r"(+value))
Packit Service 584ef9
#define CRC32CB(crc, value) __asm__("crc32cb %w[c], %w[c], %w[v]":[c]"+r"(crc):[v]"r"(+value))
Packit Service 584ef9
Packit Service 584ef9
#ifndef HWCAP_CRC32
Packit Service 584ef9
#define HWCAP_CRC32             (1 << 7)
Packit Service 584ef9
#endif /* HWCAP for crc32 */
Packit Service 584ef9
Packit Service 584ef9
static uint32_t crc32c_hw_aarch64(uint32_t crc, const void* buf, size_t len)
Packit Service 584ef9
{
Packit Service 584ef9
        const uint8_t* p_buf = buf;
Packit Service 584ef9
        uint64_t crc64bit = crc;
Packit Service 584ef9
        for (size_t i = 0; i < len / sizeof(uint64_t); i++) {
Packit Service 584ef9
                CRC32CX(crc64bit, *(uint64_t*) p_buf);
Packit Service 584ef9
                p_buf += sizeof(uint64_t);
Packit Service 584ef9
        }
Packit Service 584ef9
Packit Service 584ef9
        uint32_t crc32bit = (uint32_t) crc64bit;
Packit Service 584ef9
        len &= sizeof(uint64_t) - 1;
Packit Service 584ef9
        switch (len) {
Packit Service 584ef9
        case 7:
Packit Service 584ef9
                CRC32CB(crc32bit, *p_buf++);
Packit Service 584ef9
        case 6:
Packit Service 584ef9
                CRC32CH(crc32bit, *(uint16_t*) p_buf);
Packit Service 584ef9
                p_buf += 2;
Packit Service 584ef9
        case 4:
Packit Service 584ef9
                CRC32CW(crc32bit, *(uint32_t*) p_buf);
Packit Service 584ef9
                break;
Packit Service 584ef9
        case 3:
Packit Service 584ef9
                CRC32CB(crc32bit, *p_buf++);
Packit Service 584ef9
        case 2:
Packit Service 584ef9
                CRC32CH(crc32bit, *(uint16_t*) p_buf);
Packit Service 584ef9
                break;
Packit Service 584ef9
        case 5:
Packit Service 584ef9
                CRC32CW(crc32bit, *(uint32_t*) p_buf);
Packit Service 584ef9
                p_buf += 4;
Packit Service 584ef9
        case 1:
Packit Service 584ef9
                CRC32CB(crc32bit, *p_buf);
Packit Service 584ef9
                break;
Packit Service 584ef9
        case 0:
Packit Service 584ef9
                break;
Packit Service 584ef9
        }
Packit Service 584ef9
Packit Service 584ef9
        return crc32bit;
Packit Service 584ef9
}
Packit Service 584ef9
#endif
Packit Service 584ef9
Packit Service 584ef9
/* Apply if the platform is intel */
Packit Service 584ef9
#if defined(__X86_64__)||defined(__x86_64__)||defined(__ia64__)
Packit Service 584ef9
Packit Service 584ef9
/* Multiply a matrix times a vector over the Galois field of two elements,
Packit Service 584ef9
   GF(2).  Each element is a bit in an unsigned integer.  mat must have at
Packit Service 584ef9
   least as many entries as the power of two for most significant one bit in
Packit Service 584ef9
   vec. */
Packit Service 584ef9
static inline uint32_t gf2_matrix_times(uint32_t *mat, uint32_t vec)
Packit Service 584ef9
{
Packit Service 584ef9
    uint32_t sum;
Packit Service 584ef9
Packit Service 584ef9
    sum = 0;
Packit Service 584ef9
    while (vec) {
Packit Service 584ef9
        if (vec & 1)
Packit Service 584ef9
            sum ^= *mat;
Packit Service 584ef9
        vec >>= 1;
Packit Service 584ef9
        mat++;
Packit Service 584ef9
    }
Packit Service 584ef9
    return sum;
Packit Service 584ef9
}
Packit Service 584ef9
Packit Service 584ef9
/* Multiply a matrix by itself over GF(2).  Both mat and square must have 32
Packit Service 584ef9
   rows. */
Packit Service 584ef9
static inline void gf2_matrix_square(uint32_t *square, uint32_t *mat)
Packit Service 584ef9
{
Packit Service 584ef9
    int n;
Packit Service 584ef9
Packit Service 584ef9
    for (n = 0; n < 32; n++)
Packit Service 584ef9
        square[n] = gf2_matrix_times(mat, mat[n]);
Packit Service 584ef9
}
Packit Service 584ef9
Packit Service 584ef9
/* Construct an operator to apply len zeros to a crc.  len must be a power of
Packit Service 584ef9
   two.  If len is not a power of two, then the result is the same as for the
Packit Service 584ef9
   largest power of two less than len.  The result for len == 0 is the same as
Packit Service 584ef9
   for len == 1.  A version of this routine could be easily written for any
Packit Service 584ef9
   len, but that is not needed for this application. */
Packit Service 584ef9
static void crc32c_zeros_op(uint32_t *even, size_t len)
Packit Service 584ef9
{
Packit Service 584ef9
    int n;
Packit Service 584ef9
    uint32_t row;
Packit Service 584ef9
    uint32_t odd[32];       /* odd-power-of-two zeros operator */
Packit Service 584ef9
Packit Service 584ef9
    /* put operator for one zero bit in odd */
Packit Service 584ef9
    odd[0] = POLY;              /* CRC-32C polynomial */
Packit Service 584ef9
    row = 1;
Packit Service 584ef9
    for (n = 1; n < 32; n++) {
Packit Service 584ef9
        odd[n] = row;
Packit Service 584ef9
        row <<= 1;
Packit Service 584ef9
    }
Packit Service 584ef9
Packit Service 584ef9
    /* put operator for two zero bits in even */
Packit Service 584ef9
    gf2_matrix_square(even, odd);
Packit Service 584ef9
Packit Service 584ef9
    /* put operator for four zero bits in odd */
Packit Service 584ef9
    gf2_matrix_square(odd, even);
Packit Service 584ef9
Packit Service 584ef9
    /* first square will put the operator for one zero byte (eight zero bits),
Packit Service 584ef9
       in even -- next square puts operator for two zero bytes in odd, and so
Packit Service 584ef9
       on, until len has been rotated down to zero */
Packit Service 584ef9
    do {
Packit Service 584ef9
        gf2_matrix_square(even, odd);
Packit Service 584ef9
        len >>= 1;
Packit Service 584ef9
        if (len == 0)
Packit Service 584ef9
            return;
Packit Service 584ef9
        gf2_matrix_square(odd, even);
Packit Service 584ef9
        len >>= 1;
Packit Service 584ef9
    } while (len);
Packit Service 584ef9
Packit Service 584ef9
    /* answer ended up in odd -- copy to even */
Packit Service 584ef9
    for (n = 0; n < 32; n++)
Packit Service 584ef9
        even[n] = odd[n];
Packit Service 584ef9
}
Packit Service 584ef9
Packit Service 584ef9
/* Take a length and build four lookup tables for applying the zeros operator
Packit Service 584ef9
   for that length, byte-by-byte on the operand. */
Packit Service 584ef9
static void crc32c_zeros(uint32_t zeros[][256], size_t len)
Packit Service 584ef9
{
Packit Service 584ef9
    uint32_t n;
Packit Service 584ef9
    uint32_t op[32];
Packit Service 584ef9
Packit Service 584ef9
    crc32c_zeros_op(op, len);
Packit Service 584ef9
    for (n = 0; n < 256; n++) {
Packit Service 584ef9
        zeros[0][n] = gf2_matrix_times(op, n);
Packit Service 584ef9
        zeros[1][n] = gf2_matrix_times(op, n << 8);
Packit Service 584ef9
        zeros[2][n] = gf2_matrix_times(op, n << 16);
Packit Service 584ef9
        zeros[3][n] = gf2_matrix_times(op, n << 24);
Packit Service 584ef9
    }
Packit Service 584ef9
}
Packit Service 584ef9
Packit Service 584ef9
/* Apply the zeros operator table to crc. */
Packit Service 584ef9
static inline uint32_t crc32c_shift(uint32_t zeros[][256], uint32_t crc)
Packit Service 584ef9
{
Packit Service 584ef9
    return zeros[0][crc & 0xff] ^ zeros[1][(crc >> 8) & 0xff] ^
Packit Service 584ef9
           zeros[2][(crc >> 16) & 0xff] ^ zeros[3][crc >> 24];
Packit Service 584ef9
}
Packit Service 584ef9
Packit Service 584ef9
/* Block sizes for three-way parallel crc computation.  LONG and SHORT must
Packit Service 584ef9
   both be powers of two.  The associated string constants must be set
Packit Service 584ef9
   accordingly, for use in constructing the assembler instructions. */
Packit Service 584ef9
#define LONG 8192
Packit Service 584ef9
#define LONGx1 "8192"
Packit Service 584ef9
#define LONGx2 "16384"
Packit Service 584ef9
#define SHORT 256
Packit Service 584ef9
#define SHORTx1 "256"
Packit Service 584ef9
#define SHORTx2 "512"
Packit Service 584ef9
Packit Service 584ef9
/* Tables for hardware crc that shift a crc by LONG and SHORT zeros. */
Packit Service 584ef9
static pthread_once_t crc32c_once_hw = PTHREAD_ONCE_INIT;
Packit Service 584ef9
static uint32_t crc32c_long[4][256];
Packit Service 584ef9
static uint32_t crc32c_short[4][256];
Packit Service 584ef9
Packit Service 584ef9
/* Initialize tables for shifting crcs. */
Packit Service 584ef9
static void crc32c_init_hw(void)
Packit Service 584ef9
{
Packit Service 584ef9
    crc32c_zeros(crc32c_long, LONG);
Packit Service 584ef9
    crc32c_zeros(crc32c_short, SHORT);
Packit Service 584ef9
}
Packit Service 584ef9
Packit Service 584ef9
/* Compute CRC-32C using the Intel hardware instruction. */
Packit Service 584ef9
static uint32_t crc32c_hw(uint32_t crc, const void *buf, size_t len)
Packit Service 584ef9
{
Packit Service 584ef9
    const unsigned char *next = buf;
Packit Service 584ef9
    const unsigned char *end;
Packit Service 584ef9
    uint64_t crc0, crc1, crc2;      /* need to be 64 bits for crc32q */
Packit Service 584ef9
Packit Service 584ef9
    /* populate shift tables the first time through */
Packit Service 584ef9
    pthread_once(&crc32c_once_hw, crc32c_init_hw);
Packit Service 584ef9
Packit Service 584ef9
    /* pre-process the crc */
Packit Service 584ef9
    crc0 = crc ^ 0xffffffff;
Packit Service 584ef9
Packit Service 584ef9
    /* compute the crc for up to seven leading bytes to bring the data pointer
Packit Service 584ef9
       to an eight-byte boundary */
Packit Service 584ef9
    while (len && ((uintptr_t)next & 7) != 0) {
Packit Service 584ef9
        __asm__("crc32b\t" "(%1), %0"
Packit Service 584ef9
                : "=r"(crc0)
Packit Service 584ef9
                : "r"(next), "0"(crc0));
Packit Service 584ef9
        next++;
Packit Service 584ef9
        len--;
Packit Service 584ef9
    }
Packit Service 584ef9
Packit Service 584ef9
    /* compute the crc on sets of LONG*3 bytes, executing three independent crc
Packit Service 584ef9
       instructions, each on LONG bytes -- this is optimized for the Nehalem,
Packit Service 584ef9
       Westmere, Sandy Bridge, and Ivy Bridge architectures, which have a
Packit Service 584ef9
       throughput of one crc per cycle, but a latency of three cycles */
Packit Service 584ef9
    while (len >= LONG*3) {
Packit Service 584ef9
        crc1 = 0;
Packit Service 584ef9
        crc2 = 0;
Packit Service 584ef9
        end = next + LONG;
Packit Service 584ef9
        do {
Packit Service 584ef9
            __asm__("crc32q\t" "(%3), %0\n\t"
Packit Service 584ef9
                    "crc32q\t" LONGx1 "(%3), %1\n\t"
Packit Service 584ef9
                    "crc32q\t" LONGx2 "(%3), %2"
Packit Service 584ef9
                    : "=r"(crc0), "=r"(crc1), "=r"(crc2)
Packit Service 584ef9
                    : "r"(next), "0"(crc0), "1"(crc1), "2"(crc2));
Packit Service 584ef9
            next += 8;
Packit Service 584ef9
        } while (next < end);
Packit Service 584ef9
        crc0 = crc32c_shift(crc32c_long, crc0) ^ crc1;
Packit Service 584ef9
        crc0 = crc32c_shift(crc32c_long, crc0) ^ crc2;
Packit Service 584ef9
        next += LONG*2;
Packit Service 584ef9
        len -= LONG*3;
Packit Service 584ef9
    }
Packit Service 584ef9
Packit Service 584ef9
    /* do the same thing, but now on SHORT*3 blocks for the remaining data less
Packit Service 584ef9
       than a LONG*3 block */
Packit Service 584ef9
    while (len >= SHORT*3) {
Packit Service 584ef9
        crc1 = 0;
Packit Service 584ef9
        crc2 = 0;
Packit Service 584ef9
        end = next + SHORT;
Packit Service 584ef9
        do {
Packit Service 584ef9
            __asm__("crc32q\t" "(%3), %0\n\t"
Packit Service 584ef9
                    "crc32q\t" SHORTx1 "(%3), %1\n\t"
Packit Service 584ef9
                    "crc32q\t" SHORTx2 "(%3), %2"
Packit Service 584ef9
                    : "=r"(crc0), "=r"(crc1), "=r"(crc2)
Packit Service 584ef9
                    : "r"(next), "0"(crc0), "1"(crc1), "2"(crc2));
Packit Service 584ef9
            next += 8;
Packit Service 584ef9
        } while (next < end);
Packit Service 584ef9
        crc0 = crc32c_shift(crc32c_short, crc0) ^ crc1;
Packit Service 584ef9
        crc0 = crc32c_shift(crc32c_short, crc0) ^ crc2;
Packit Service 584ef9
        next += SHORT*2;
Packit Service 584ef9
        len -= SHORT*3;
Packit Service 584ef9
    }
Packit Service 584ef9
Packit Service 584ef9
    /* compute the crc on the remaining eight-byte units less than a SHORT*3
Packit Service 584ef9
       block */
Packit Service 584ef9
    end = next + (len - (len & 7));
Packit Service 584ef9
    while (next < end) {
Packit Service 584ef9
        __asm__("crc32q\t" "(%1), %0"
Packit Service 584ef9
                : "=r"(crc0)
Packit Service 584ef9
                : "r"(next), "0"(crc0));
Packit Service 584ef9
        next += 8;
Packit Service 584ef9
    }
Packit Service 584ef9
    len &= 7;
Packit Service 584ef9
Packit Service 584ef9
    /* compute the crc for up to seven trailing bytes */
Packit Service 584ef9
    while (len) {
Packit Service 584ef9
        __asm__("crc32b\t" "(%1), %0"
Packit Service 584ef9
                : "=r"(crc0)
Packit Service 584ef9
                : "r"(next), "0"(crc0));
Packit Service 584ef9
        next++;
Packit Service 584ef9
        len--;
Packit Service 584ef9
    }
Packit Service 584ef9
Packit Service 584ef9
    /* return a post-processed crc */
Packit Service 584ef9
    return (uint32_t)crc0 ^ 0xffffffff;
Packit Service 584ef9
}
Packit Service 584ef9
Packit Service 584ef9
/* Check for SSE 4.2.  SSE 4.2 was first supported in Nehalem processors
Packit Service 584ef9
   introduced in November, 2008.  This does not check for the existence of the
Packit Service 584ef9
   cpuid instruction itself, which was introduced on the 486SL in 1992, so this
Packit Service 584ef9
   will fail on earlier x86 processors.  cpuid works on all Pentium and later
Packit Service 584ef9
   processors. */
Packit Service 584ef9
#define SSE42(have) \
Packit Service 584ef9
    do { \
Packit Service 584ef9
        uint32_t eax, ecx; \
Packit Service 584ef9
        eax = 1; \
Packit Service 584ef9
        __asm__("cpuid" \
Packit Service 584ef9
                : "=c"(ecx) \
Packit Service 584ef9
                : "a"(eax) \
Packit Service 584ef9
                : "%ebx", "%edx"); \
Packit Service 584ef9
        (have) = (ecx >> 20) & 1; \
Packit Service 584ef9
    } while (0)
Packit Service 584ef9
Packit Service 584ef9
#endif
Packit Service 584ef9
/* Compute a CRC-32C.  If the crc32 instruction is available, use the hardware
Packit Service 584ef9
   version.  Otherwise, use the software version. */
Packit Service 584ef9
void crc32c_init(void) {
Packit Service 584ef9
    #if defined(__X86_64__)||defined(__x86_64__)||defined(__ia64__)
Packit Service 584ef9
    int sse42;
Packit Service 584ef9
    SSE42(sse42);
Packit Service 584ef9
Packit Service 584ef9
    if (sse42) {
Packit Service 584ef9
        crc32c = crc32c_hw;
Packit Service 584ef9
    } else
Packit Service 584ef9
    #endif
Packit Service 584ef9
    /* Check if CRC instructions supported by aarch64 */
Packit Service 584ef9
    #if defined(__linux__) && defined(__aarch64__) && defined(ARM_CRC32)
Packit Service 584ef9
    unsigned long hwcap = getauxval(AT_HWCAP);
Packit Service 584ef9
Packit Service 584ef9
    if (hwcap & HWCAP_CRC32) {
Packit Service 584ef9
        crc32c = crc32c_hw_aarch64;
Packit Service 584ef9
    } else
Packit Service 584ef9
    #endif
Packit Service 584ef9
    {
Packit Service 584ef9
        crc32c = crc32c_sw;
Packit Service 584ef9
    }
Packit Service 584ef9
}