13b35e7eeSXin LI // SPDX-License-Identifier: 0BSD 23b35e7eeSXin LI 33b35e7eeSXin LI /////////////////////////////////////////////////////////////////////////////// 43b35e7eeSXin LI // 53b35e7eeSXin LI /// \file crc_common.h 6*128836d3SXin LI /// \brief Macros and declarations for CRC32 and CRC64 73b35e7eeSXin LI // 83b35e7eeSXin LI // Authors: Lasse Collin 93b35e7eeSXin LI // Ilya Kurdyukov 103b35e7eeSXin LI // Jia Tan 113b35e7eeSXin LI // 123b35e7eeSXin LI /////////////////////////////////////////////////////////////////////////////// 133b35e7eeSXin LI 143b35e7eeSXin LI #ifndef LZMA_CRC_COMMON_H 153b35e7eeSXin LI #define LZMA_CRC_COMMON_H 163b35e7eeSXin LI 173b35e7eeSXin LI #include "common.h" 183b35e7eeSXin LI 193b35e7eeSXin LI 20*128836d3SXin LI ///////////// 21*128836d3SXin LI // Generic // 22*128836d3SXin LI ///////////// 23*128836d3SXin LI 243b35e7eeSXin LI #ifdef WORDS_BIGENDIAN 253b35e7eeSXin LI # define A(x) ((x) >> 24) 263b35e7eeSXin LI # define B(x) (((x) >> 16) & 0xFF) 273b35e7eeSXin LI # define C(x) (((x) >> 8) & 0xFF) 283b35e7eeSXin LI # define D(x) ((x) & 0xFF) 293b35e7eeSXin LI 303b35e7eeSXin LI # define S8(x) ((x) << 8) 313b35e7eeSXin LI # define S32(x) ((x) << 32) 323b35e7eeSXin LI 333b35e7eeSXin LI #else 343b35e7eeSXin LI # define A(x) ((x) & 0xFF) 353b35e7eeSXin LI # define B(x) (((x) >> 8) & 0xFF) 363b35e7eeSXin LI # define C(x) (((x) >> 16) & 0xFF) 373b35e7eeSXin LI # define D(x) ((x) >> 24) 383b35e7eeSXin LI 393b35e7eeSXin LI # define S8(x) ((x) >> 8) 403b35e7eeSXin LI # define S32(x) ((x) >> 32) 413b35e7eeSXin LI #endif 423b35e7eeSXin LI 433b35e7eeSXin LI 44*128836d3SXin LI /// lzma_crc32_table[0] is needed by LZ encoder so we need to keep 45*128836d3SXin LI /// the array two-dimensional. 46*128836d3SXin LI #ifdef HAVE_SMALL 47*128836d3SXin LI lzma_attr_visibility_hidden 48*128836d3SXin LI extern uint32_t lzma_crc32_table[1][256]; 49*128836d3SXin LI 50*128836d3SXin LI extern void lzma_crc32_init(void); 51*128836d3SXin LI 523b35e7eeSXin LI #else 533b35e7eeSXin LI 54*128836d3SXin LI lzma_attr_visibility_hidden 55*128836d3SXin LI extern const uint32_t lzma_crc32_table[8][256]; 56*128836d3SXin LI 57*128836d3SXin LI lzma_attr_visibility_hidden 58*128836d3SXin LI extern const uint64_t lzma_crc64_table[4][256]; 593b35e7eeSXin LI #endif 603b35e7eeSXin LI 613b35e7eeSXin LI 62*128836d3SXin LI /////////////////// 63*128836d3SXin LI // Configuration // 64*128836d3SXin LI /////////////////// 65*128836d3SXin LI 66*128836d3SXin LI // NOTE: This config isn't used if HAVE_SMALL is defined! 67*128836d3SXin LI 68*128836d3SXin LI // These are defined if the generic slicing-by-n implementations and their 69*128836d3SXin LI // lookup tables are built. 703b35e7eeSXin LI #undef CRC32_GENERIC 713b35e7eeSXin LI #undef CRC64_GENERIC 723b35e7eeSXin LI 73*128836d3SXin LI // These are defined if an arch-specific version is built. If both this 74*128836d3SXin LI // and matching _GENERIC is defined then runtime detection must be used. 753b35e7eeSXin LI #undef CRC32_ARCH_OPTIMIZED 763b35e7eeSXin LI #undef CRC64_ARCH_OPTIMIZED 773b35e7eeSXin LI 783b35e7eeSXin LI // The x86 CLMUL is used for both CRC32 and CRC64. 793b35e7eeSXin LI #undef CRC_X86_CLMUL 803b35e7eeSXin LI 81*128836d3SXin LI // Many ARM64 processor have CRC32 instructions. 82*128836d3SXin LI // CRC64 could be done with CLMUL but it's not implemented yet. 833b35e7eeSXin LI #undef CRC32_ARM64 843b35e7eeSXin LI 85*128836d3SXin LI // 64-bit LoongArch has CRC32 instructions. 86*128836d3SXin LI #undef CRC32_LOONGARCH 87*128836d3SXin LI 88*128836d3SXin LI 89*128836d3SXin LI // ARM64 90*128836d3SXin LI // 91*128836d3SXin LI // Keep this in sync with changes to crc32_arm64.h 92*128836d3SXin LI #if defined(_WIN32) || defined(HAVE_GETAUXVAL) \ 93*128836d3SXin LI || defined(HAVE_ELF_AUX_INFO) \ 94*128836d3SXin LI || (defined(__APPLE__) && defined(HAVE_SYSCTLBYNAME)) 95*128836d3SXin LI # define CRC_ARM64_RUNTIME_DETECTION 1 96*128836d3SXin LI #endif 973b35e7eeSXin LI 983b35e7eeSXin LI // ARM64 CRC32 instruction is only useful for CRC32. Currently, only 993b35e7eeSXin LI // little endian is supported since we were unable to test on a big 1003b35e7eeSXin LI // endian machine. 1013b35e7eeSXin LI #if defined(HAVE_ARM64_CRC32) && !defined(WORDS_BIGENDIAN) 1023b35e7eeSXin LI // Allow ARM64 CRC32 instruction without a runtime check if 10326743408SXin LI // __ARM_FEATURE_CRC32 is defined. GCC and Clang only define 10426743408SXin LI // this if the proper compiler options are used. 1053b35e7eeSXin LI # if defined(__ARM_FEATURE_CRC32) 1063b35e7eeSXin LI # define CRC32_ARCH_OPTIMIZED 1 1073b35e7eeSXin LI # define CRC32_ARM64 1 108*128836d3SXin LI # elif defined(CRC_ARM64_RUNTIME_DETECTION) 1093b35e7eeSXin LI # define CRC32_ARCH_OPTIMIZED 1 1103b35e7eeSXin LI # define CRC32_ARM64 1 1113b35e7eeSXin LI # define CRC32_GENERIC 1 1123b35e7eeSXin LI # endif 1133b35e7eeSXin LI #endif 1143b35e7eeSXin LI 115*128836d3SXin LI 116*128836d3SXin LI // LoongArch 1173b35e7eeSXin LI // 118*128836d3SXin LI // Only 64-bit LoongArch is supported for now. No runtime detection 119*128836d3SXin LI // is needed because the LoongArch specification says that the CRC32 120*128836d3SXin LI // instructions are a part of the Basic Integer Instructions and 121*128836d3SXin LI // they shall be implemented by 64-bit LoongArch implementations. 122*128836d3SXin LI #ifdef HAVE_LOONGARCH_CRC32 123*128836d3SXin LI # define CRC32_ARCH_OPTIMIZED 1 124*128836d3SXin LI # define CRC32_LOONGARCH 1 125*128836d3SXin LI #endif 126*128836d3SXin LI 127*128836d3SXin LI 128*128836d3SXin LI // x86 and E2K 129*128836d3SXin LI #if defined(HAVE_USABLE_CLMUL) 130*128836d3SXin LI // If CLMUL is allowed unconditionally in the compiler options then 131*128836d3SXin LI // the generic version and the tables can be omitted. Exceptions: 132*128836d3SXin LI // 133*128836d3SXin LI // - If 32-bit x86 assembly files are enabled then those are always 134*128836d3SXin LI // built and runtime detection is used even if compiler flags 135*128836d3SXin LI // were set to allow CLMUL unconditionally. 136*128836d3SXin LI // 137*128836d3SXin LI // - This doesn't work with MSVC as I don't know how to detect 138*128836d3SXin LI // the features here. 139*128836d3SXin LI // 140*128836d3SXin LI # if (defined(__SSSE3__) && defined(__SSE4_1__) && defined(__PCLMUL__) \ 141*128836d3SXin LI && !defined(HAVE_CRC_X86_ASM)) \ 1423b35e7eeSXin LI || (defined(__e2k__) && __iset__ >= 6) 1433b35e7eeSXin LI # define CRC32_ARCH_OPTIMIZED 1 1443b35e7eeSXin LI # define CRC64_ARCH_OPTIMIZED 1 1453b35e7eeSXin LI # define CRC_X86_CLMUL 1 1463b35e7eeSXin LI # else 1473b35e7eeSXin LI # define CRC32_GENERIC 1 1483b35e7eeSXin LI # define CRC64_GENERIC 1 1493b35e7eeSXin LI # define CRC32_ARCH_OPTIMIZED 1 1503b35e7eeSXin LI # define CRC64_ARCH_OPTIMIZED 1 1513b35e7eeSXin LI # define CRC_X86_CLMUL 1 1523b35e7eeSXin LI # endif 1533b35e7eeSXin LI #endif 1543b35e7eeSXin LI 155*128836d3SXin LI 156*128836d3SXin LI // Fallback configuration 157*128836d3SXin LI // 1583b35e7eeSXin LI // For CRC32 use the generic slice-by-eight implementation if no optimized 1593b35e7eeSXin LI // version is available. 1603b35e7eeSXin LI #if !defined(CRC32_ARCH_OPTIMIZED) && !defined(CRC32_GENERIC) 1613b35e7eeSXin LI # define CRC32_GENERIC 1 1623b35e7eeSXin LI #endif 1633b35e7eeSXin LI 1643b35e7eeSXin LI // For CRC64 use the generic slice-by-four implementation if no optimized 1653b35e7eeSXin LI // version is available. 1663b35e7eeSXin LI #if !defined(CRC64_ARCH_OPTIMIZED) && !defined(CRC64_GENERIC) 1673b35e7eeSXin LI # define CRC64_GENERIC 1 1683b35e7eeSXin LI #endif 1693b35e7eeSXin LI 1703b35e7eeSXin LI #endif 171