Home | History | Annotate | Line # | Download | only in check
      1 // SPDX-License-Identifier: 0BSD
      2 
      3 ///////////////////////////////////////////////////////////////////////////////
      4 //
      5 /// \file       crc_common.h
      6 /// \brief      Macros and declarations for CRC32 and CRC64
      7 //
      8 //  Authors:    Lasse Collin
      9 //              Ilya Kurdyukov
     10 //              Jia Tan
     11 //
     12 ///////////////////////////////////////////////////////////////////////////////
     13 
     14 #ifndef LZMA_CRC_COMMON_H
     15 #define LZMA_CRC_COMMON_H
     16 
     17 #include "common.h"
     18 
     19 
     20 /////////////
     21 // Generic //
     22 /////////////
     23 
     24 #ifdef WORDS_BIGENDIAN
     25 #	define A(x) ((x) >> 24)
     26 #	define B(x) (((x) >> 16) & 0xFF)
     27 #	define C(x) (((x) >> 8) & 0xFF)
     28 #	define D(x) ((x) & 0xFF)
     29 
     30 #	define S8(x) ((x) << 8)
     31 #	define S32(x) ((x) << 32)
     32 
     33 #else
     34 #	define A(x) ((x) & 0xFF)
     35 #	define B(x) (((x) >> 8) & 0xFF)
     36 #	define C(x) (((x) >> 16) & 0xFF)
     37 #	define D(x) ((x) >> 24)
     38 
     39 #	define S8(x) ((x) >> 8)
     40 #	define S32(x) ((x) >> 32)
     41 #endif
     42 
     43 
     44 /// lzma_crc32_table[0] is needed by LZ encoder so we need to keep
     45 /// the array two-dimensional.
     46 #ifdef HAVE_SMALL
     47 lzma_attr_visibility_hidden
     48 extern uint32_t lzma_crc32_table[1][256];
     49 
     50 extern void lzma_crc32_init(void);
     51 
     52 #else
     53 
     54 lzma_attr_visibility_hidden
     55 extern const uint32_t lzma_crc32_table[8][256];
     56 
     57 lzma_attr_visibility_hidden
     58 extern const uint64_t lzma_crc64_table[4][256];
     59 #endif
     60 
     61 
     62 ///////////////////
     63 // Configuration //
     64 ///////////////////
     65 
     66 // NOTE: This config isn't used if HAVE_SMALL is defined!
     67 
     68 // These are defined if the generic slicing-by-n implementations and their
     69 // lookup tables are built.
     70 #undef CRC32_GENERIC
     71 #undef CRC64_GENERIC
     72 
     73 // These are defined if an arch-specific version is built. If both this
     74 // and matching _GENERIC is defined then runtime detection must be used.
     75 #undef CRC32_ARCH_OPTIMIZED
     76 #undef CRC64_ARCH_OPTIMIZED
     77 
     78 // The x86 CLMUL is used for both CRC32 and CRC64.
     79 #undef CRC_X86_CLMUL
     80 
     81 // Many ARM64 processor have CRC32 instructions.
     82 // CRC64 could be done with CLMUL but it's not implemented yet.
     83 #undef CRC32_ARM64
     84 
     85 // 64-bit LoongArch has CRC32 instructions.
     86 #undef CRC32_LOONGARCH
     87 
     88 
     89 // ARM64
     90 //
     91 // Keep this in sync with changes to crc32_arm64.h
     92 #if defined(_WIN32) \
     93 		|| (defined(HAVE_GETAUXVAL) && defined(HAVE_HWCAP_CRC32)) \
     94 		|| defined(HAVE_ELF_AUX_INFO) \
     95 		|| (defined(__APPLE__) && defined(HAVE_SYSCTLBYNAME))
     96 #	define CRC_ARM64_RUNTIME_DETECTION 1
     97 #endif
     98 
     99 // ARM64 CRC32 instruction is only useful for CRC32. Currently, only
    100 // little endian is supported since we were unable to test on a big
    101 // endian machine.
    102 #if defined(HAVE_ARM64_CRC32) && !defined(WORDS_BIGENDIAN)
    103 	// Allow ARM64 CRC32 instruction without a runtime check if
    104 	// __ARM_FEATURE_CRC32 is defined. GCC and Clang only define
    105 	// this if the proper compiler options are used.
    106 #	if defined(__ARM_FEATURE_CRC32)
    107 #		define CRC32_ARCH_OPTIMIZED 1
    108 #		define CRC32_ARM64 1
    109 #	elif defined(CRC_ARM64_RUNTIME_DETECTION)
    110 #		define CRC32_ARCH_OPTIMIZED 1
    111 #		define CRC32_ARM64 1
    112 #		define CRC32_GENERIC 1
    113 #	endif
    114 #endif
    115 
    116 
    117 // LoongArch
    118 //
    119 // Only 64-bit LoongArch is supported for now. No runtime detection
    120 // is needed because the LoongArch specification says that the CRC32
    121 // instructions are a part of the Basic Integer Instructions and
    122 // they shall be implemented by 64-bit LoongArch implementations.
    123 #ifdef HAVE_LOONGARCH_CRC32
    124 #	define CRC32_ARCH_OPTIMIZED 1
    125 #	define CRC32_LOONGARCH 1
    126 #endif
    127 
    128 
    129 // x86 and E2K
    130 #if defined(HAVE_USABLE_CLMUL)
    131 	// If CLMUL is allowed unconditionally in the compiler options then
    132 	// the generic version and the tables can be omitted. Exceptions:
    133 	//
    134 	//   - If 32-bit x86 assembly files are enabled then those are always
    135 	//     built and runtime detection is used even if compiler flags
    136 	//     were set to allow CLMUL unconditionally.
    137 	//
    138 	//   - The unconditional use doesn't work with MSVC as I don't know
    139 	//     how to detect the features here.
    140 	//
    141 	// Don't enable CLMUL at all on old MSVC that targets 32-bit x86.
    142 	// There seems to be a compiler bug that produces broken code
    143 	// in optimized (Release) builds. It results in crashing tests.
    144 	// It is known that VS 2019 16.11 (MSVC 19.29.30158) is broken
    145 	// and that VS 2022 17.13 (MSVC 19.43.34808) works.
    146 #	if defined(_MSC_FULL_VER) && _MSC_FULL_VER < 194334808 \
    147 			&& !defined(__INTEL_COMPILER) && !defined(__clang__) \
    148 			&& defined(_M_IX86)
    149 		// Old MSVC targeting 32-bit x86: Don't enable CLMUL at all.
    150 #	elif (defined(__SSSE3__) && defined(__SSE4_1__) \
    151 			&& defined(__PCLMUL__) \
    152 			&& !defined(HAVE_CRC_X86_ASM)) \
    153 		|| (defined(__e2k__) && __iset__ >= 6)
    154 #		define CRC32_ARCH_OPTIMIZED 1
    155 #		define CRC64_ARCH_OPTIMIZED 1
    156 #		define CRC_X86_CLMUL 1
    157 #	else
    158 #		define CRC32_GENERIC 1
    159 #		define CRC64_GENERIC 1
    160 #		define CRC32_ARCH_OPTIMIZED 1
    161 #		define CRC64_ARCH_OPTIMIZED 1
    162 #		define CRC_X86_CLMUL 1
    163 #	endif
    164 #endif
    165 
    166 
    167 // Fallback configuration
    168 //
    169 // For CRC32 use the generic slice-by-eight implementation if no optimized
    170 // version is available.
    171 #if !defined(CRC32_ARCH_OPTIMIZED) && !defined(CRC32_GENERIC)
    172 #	define CRC32_GENERIC 1
    173 #endif
    174 
    175 // For CRC64 use the generic slice-by-four implementation if no optimized
    176 // version is available.
    177 #if !defined(CRC64_ARCH_OPTIMIZED) && !defined(CRC64_GENERIC)
    178 #	define CRC64_GENERIC 1
    179 #endif
    180 
    181 #endif
    182