xref: /freebsd/contrib/xz/src/liblzma/check/crc_common.h (revision 128836d304d93f2d00eb14069c27089ab46c38d4)
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) || defined(HAVE_GETAUXVAL) \
93 		|| defined(HAVE_ELF_AUX_INFO) \
94 		|| (defined(__APPLE__) && defined(HAVE_SYSCTLBYNAME))
95 #	define CRC_ARM64_RUNTIME_DETECTION 1
96 #endif
97 
98 // ARM64 CRC32 instruction is only useful for CRC32. Currently, only
99 // little endian is supported since we were unable to test on a big
100 // endian machine.
101 #if defined(HAVE_ARM64_CRC32) && !defined(WORDS_BIGENDIAN)
102 	// Allow ARM64 CRC32 instruction without a runtime check if
103 	// __ARM_FEATURE_CRC32 is defined. GCC and Clang only define
104 	// this if the proper compiler options are used.
105 #	if defined(__ARM_FEATURE_CRC32)
106 #		define CRC32_ARCH_OPTIMIZED 1
107 #		define CRC32_ARM64 1
108 #	elif defined(CRC_ARM64_RUNTIME_DETECTION)
109 #		define CRC32_ARCH_OPTIMIZED 1
110 #		define CRC32_ARM64 1
111 #		define CRC32_GENERIC 1
112 #	endif
113 #endif
114 
115 
116 // LoongArch
117 //
118 // Only 64-bit LoongArch is supported for now. No runtime detection
119 // is needed because the LoongArch specification says that the CRC32
120 // instructions are a part of the Basic Integer Instructions and
121 // they shall be implemented by 64-bit LoongArch implementations.
122 #ifdef HAVE_LOONGARCH_CRC32
123 #	define CRC32_ARCH_OPTIMIZED 1
124 #	define CRC32_LOONGARCH 1
125 #endif
126 
127 
128 // x86 and E2K
129 #if defined(HAVE_USABLE_CLMUL)
130 	// If CLMUL is allowed unconditionally in the compiler options then
131 	// the generic version and the tables can be omitted. Exceptions:
132 	//
133 	//   - If 32-bit x86 assembly files are enabled then those are always
134 	//     built and runtime detection is used even if compiler flags
135 	//     were set to allow CLMUL unconditionally.
136 	//
137 	//   - This doesn't work with MSVC as I don't know how to detect
138 	//     the features here.
139 	//
140 #	if (defined(__SSSE3__) && defined(__SSE4_1__) && defined(__PCLMUL__) \
141 			&& !defined(HAVE_CRC_X86_ASM)) \
142 		|| (defined(__e2k__) && __iset__ >= 6)
143 #		define CRC32_ARCH_OPTIMIZED 1
144 #		define CRC64_ARCH_OPTIMIZED 1
145 #		define CRC_X86_CLMUL 1
146 #	else
147 #		define CRC32_GENERIC 1
148 #		define CRC64_GENERIC 1
149 #		define CRC32_ARCH_OPTIMIZED 1
150 #		define CRC64_ARCH_OPTIMIZED 1
151 #		define CRC_X86_CLMUL 1
152 #	endif
153 #endif
154 
155 
156 // Fallback configuration
157 //
158 // For CRC32 use the generic slice-by-eight implementation if no optimized
159 // version is available.
160 #if !defined(CRC32_ARCH_OPTIMIZED) && !defined(CRC32_GENERIC)
161 #	define CRC32_GENERIC 1
162 #endif
163 
164 // For CRC64 use the generic slice-by-four implementation if no optimized
165 // version is available.
166 #if !defined(CRC64_ARCH_OPTIMIZED) && !defined(CRC64_GENERIC)
167 #	define CRC64_GENERIC 1
168 #endif
169 
170 #endif
171