Path: blob/master/Utilities/cmliblzma/liblzma/check/crc64_fast.c
3153 views
// SPDX-License-Identifier: 0BSD12///////////////////////////////////////////////////////////////////////////////3//4/// \file crc64.c5/// \brief CRC64 calculation6//7// Authors: Lasse Collin8// Ilya Kurdyukov9//10///////////////////////////////////////////////////////////////////////////////1112#include "check.h"13#include "crc_common.h"1415#if defined(CRC_X86_CLMUL)16# define BUILDING_CRC64_CLMUL17# include "crc_x86_clmul.h"18#endif192021#ifdef CRC64_GENERIC2223/////////////////////////////////24// Generic slice-by-four CRC64 //25/////////////////////////////////2627#ifdef WORDS_BIGENDIAN28# define A1(x) ((x) >> 56)29#else30# define A1 A31#endif323334// See the comments in crc32_fast.c. They aren't duplicated here.35static uint64_t36crc64_generic(const uint8_t *buf, size_t size, uint64_t crc)37{38crc = ~crc;3940#ifdef WORDS_BIGENDIAN41crc = byteswap64(crc);42#endif4344if (size > 4) {45while ((uintptr_t)(buf) & 3) {46crc = lzma_crc64_table[0][*buf++ ^ A1(crc)] ^ S8(crc);47--size;48}4950const uint8_t *const limit = buf + (size & ~(size_t)(3));51size &= (size_t)(3);5253while (buf < limit) {54#ifdef WORDS_BIGENDIAN55const uint32_t tmp = (uint32_t)(crc >> 32)56^ aligned_read32ne(buf);57#else58const uint32_t tmp = (uint32_t)crc59^ aligned_read32ne(buf);60#endif61buf += 4;6263crc = lzma_crc64_table[3][A(tmp)]64^ lzma_crc64_table[2][B(tmp)]65^ S32(crc)66^ lzma_crc64_table[1][C(tmp)]67^ lzma_crc64_table[0][D(tmp)];68}69}7071while (size-- != 0)72crc = lzma_crc64_table[0][*buf++ ^ A1(crc)] ^ S8(crc);7374#ifdef WORDS_BIGENDIAN75crc = byteswap64(crc);76#endif7778return ~crc;79}80#endif818283#if defined(CRC64_GENERIC) && defined(CRC64_ARCH_OPTIMIZED)8485//////////////////////////86// Function dispatching //87//////////////////////////8889// If both the generic and arch-optimized implementations are usable, then90// the function that is used is selected at runtime. See crc32_fast.c.9192typedef uint64_t (*crc64_func_type)(93const uint8_t *buf, size_t size, uint64_t crc);9495static crc64_func_type96crc64_resolve(void)97{98return is_arch_extension_supported()99? &crc64_arch_optimized : &crc64_generic;100}101102#ifdef HAVE_FUNC_ATTRIBUTE_CONSTRUCTOR103# define CRC64_SET_FUNC_ATTR __attribute__((__constructor__))104static crc64_func_type crc64_func;105#else106# define CRC64_SET_FUNC_ATTR107static uint64_t crc64_dispatch(const uint8_t *buf, size_t size, uint64_t crc);108static crc64_func_type crc64_func = &crc64_dispatch;109#endif110111112CRC64_SET_FUNC_ATTR113static void114crc64_set_func(void)115{116crc64_func = crc64_resolve();117return;118}119120121#ifndef HAVE_FUNC_ATTRIBUTE_CONSTRUCTOR122static uint64_t123crc64_dispatch(const uint8_t *buf, size_t size, uint64_t crc)124{125crc64_set_func();126return crc64_func(buf, size, crc);127}128#endif129#endif130131132extern LZMA_API(uint64_t)133lzma_crc64(const uint8_t *buf, size_t size, uint64_t crc)134{135#if defined(CRC64_GENERIC) && defined(CRC64_ARCH_OPTIMIZED)136137#ifdef CRC_USE_GENERIC_FOR_SMALL_INPUTS138if (size <= 16)139return crc64_generic(buf, size, crc);140#endif141return crc64_func(buf, size, crc);142143#elif defined(CRC64_ARCH_OPTIMIZED)144// If arch-optimized version is used unconditionally without runtime145// CPU detection then omitting the generic version and its 8 KiB146// lookup table makes the library smaller.147//148// FIXME: Lookup table isn't currently omitted on 32-bit x86,149// see crc64_table.c.150return crc64_arch_optimized(buf, size, crc);151152#else153return crc64_generic(buf, size, crc);154#endif155}156157158