xref: /freebsd/contrib/xz/src/liblzma/check/crc_common.h (revision 3b35e7ee8de9b0260149a2b77e87a2b9c7a36244)
1*3b35e7eeSXin LI // SPDX-License-Identifier: 0BSD
2*3b35e7eeSXin LI 
3*3b35e7eeSXin LI ///////////////////////////////////////////////////////////////////////////////
4*3b35e7eeSXin LI //
5*3b35e7eeSXin LI /// \file       crc_common.h
6*3b35e7eeSXin LI /// \brief      Some functions and macros for CRC32 and CRC64
7*3b35e7eeSXin LI //
8*3b35e7eeSXin LI //  Authors:    Lasse Collin
9*3b35e7eeSXin LI //              Ilya Kurdyukov
10*3b35e7eeSXin LI //              Hans Jansen
11*3b35e7eeSXin LI //              Jia Tan
12*3b35e7eeSXin LI //
13*3b35e7eeSXin LI ///////////////////////////////////////////////////////////////////////////////
14*3b35e7eeSXin LI 
15*3b35e7eeSXin LI #ifndef LZMA_CRC_COMMON_H
16*3b35e7eeSXin LI #define LZMA_CRC_COMMON_H
17*3b35e7eeSXin LI 
18*3b35e7eeSXin LI #include "common.h"
19*3b35e7eeSXin LI 
20*3b35e7eeSXin LI 
21*3b35e7eeSXin LI #ifdef WORDS_BIGENDIAN
22*3b35e7eeSXin LI #	define A(x) ((x) >> 24)
23*3b35e7eeSXin LI #	define B(x) (((x) >> 16) & 0xFF)
24*3b35e7eeSXin LI #	define C(x) (((x) >> 8) & 0xFF)
25*3b35e7eeSXin LI #	define D(x) ((x) & 0xFF)
26*3b35e7eeSXin LI 
27*3b35e7eeSXin LI #	define S8(x) ((x) << 8)
28*3b35e7eeSXin LI #	define S32(x) ((x) << 32)
29*3b35e7eeSXin LI 
30*3b35e7eeSXin LI #else
31*3b35e7eeSXin LI #	define A(x) ((x) & 0xFF)
32*3b35e7eeSXin LI #	define B(x) (((x) >> 8) & 0xFF)
33*3b35e7eeSXin LI #	define C(x) (((x) >> 16) & 0xFF)
34*3b35e7eeSXin LI #	define D(x) ((x) >> 24)
35*3b35e7eeSXin LI 
36*3b35e7eeSXin LI #	define S8(x) ((x) >> 8)
37*3b35e7eeSXin LI #	define S32(x) ((x) >> 32)
38*3b35e7eeSXin LI #endif
39*3b35e7eeSXin LI 
40*3b35e7eeSXin LI 
41*3b35e7eeSXin LI // CRC CLMUL code needs this because accessing input buffers that aren't
42*3b35e7eeSXin LI // aligned to the vector size will inherently trip the address sanitizer.
43*3b35e7eeSXin LI #if lzma_has_attribute(__no_sanitize_address__)
44*3b35e7eeSXin LI #	define crc_attr_no_sanitize_address \
45*3b35e7eeSXin LI 			__attribute__((__no_sanitize_address__))
46*3b35e7eeSXin LI #else
47*3b35e7eeSXin LI #	define crc_attr_no_sanitize_address
48*3b35e7eeSXin LI #endif
49*3b35e7eeSXin LI 
50*3b35e7eeSXin LI // Keep this in sync with changes to crc32_arm64.h
51*3b35e7eeSXin LI #if defined(_WIN32) || defined(HAVE_GETAUXVAL) \
52*3b35e7eeSXin LI 		|| defined(HAVE_ELF_AUX_INFO) \
53*3b35e7eeSXin LI 		|| (defined(__APPLE__) && defined(HAVE_SYSCTLBYNAME))
54*3b35e7eeSXin LI #	define ARM64_RUNTIME_DETECTION 1
55*3b35e7eeSXin LI #endif
56*3b35e7eeSXin LI 
57*3b35e7eeSXin LI 
58*3b35e7eeSXin LI #undef CRC32_GENERIC
59*3b35e7eeSXin LI #undef CRC64_GENERIC
60*3b35e7eeSXin LI 
61*3b35e7eeSXin LI #undef CRC32_ARCH_OPTIMIZED
62*3b35e7eeSXin LI #undef CRC64_ARCH_OPTIMIZED
63*3b35e7eeSXin LI 
64*3b35e7eeSXin LI // The x86 CLMUL is used for both CRC32 and CRC64.
65*3b35e7eeSXin LI #undef CRC_X86_CLMUL
66*3b35e7eeSXin LI 
67*3b35e7eeSXin LI #undef CRC32_ARM64
68*3b35e7eeSXin LI #undef CRC64_ARM64_CLMUL
69*3b35e7eeSXin LI 
70*3b35e7eeSXin LI #undef CRC_USE_GENERIC_FOR_SMALL_INPUTS
71*3b35e7eeSXin LI 
72*3b35e7eeSXin LI // ARM64 CRC32 instruction is only useful for CRC32. Currently, only
73*3b35e7eeSXin LI // little endian is supported since we were unable to test on a big
74*3b35e7eeSXin LI // endian machine.
75*3b35e7eeSXin LI //
76*3b35e7eeSXin LI // NOTE: Keep this and the next check in sync with the macro
77*3b35e7eeSXin LI //       NO_CRC32_TABLE in crc32_table.c
78*3b35e7eeSXin LI #if defined(HAVE_ARM64_CRC32) && !defined(WORDS_BIGENDIAN)
79*3b35e7eeSXin LI // Allow ARM64 CRC32 instruction without a runtime check if
80*3b35e7eeSXin LI // __ARM_FEATURE_CRC32 is defined. GCC and Clang only define this if the
81*3b35e7eeSXin LI // proper compiler options are used.
82*3b35e7eeSXin LI #	if defined(__ARM_FEATURE_CRC32)
83*3b35e7eeSXin LI #		define CRC32_ARCH_OPTIMIZED 1
84*3b35e7eeSXin LI #		define CRC32_ARM64 1
85*3b35e7eeSXin LI #	elif defined(ARM64_RUNTIME_DETECTION)
86*3b35e7eeSXin LI #		define CRC32_ARCH_OPTIMIZED 1
87*3b35e7eeSXin LI #		define CRC32_ARM64 1
88*3b35e7eeSXin LI #		define CRC32_GENERIC 1
89*3b35e7eeSXin LI #	endif
90*3b35e7eeSXin LI #endif
91*3b35e7eeSXin LI 
92*3b35e7eeSXin LI #if defined(HAVE_USABLE_CLMUL)
93*3b35e7eeSXin LI // If CLMUL is allowed unconditionally in the compiler options then the
94*3b35e7eeSXin LI // generic version can be omitted. Note that this doesn't work with MSVC
95*3b35e7eeSXin LI // as I don't know how to detect the features here.
96*3b35e7eeSXin LI //
97*3b35e7eeSXin LI // NOTE: Keep this in sync with the NO_CRC32_TABLE macro in crc32_table.c
98*3b35e7eeSXin LI // and NO_CRC64_TABLE in crc64_table.c.
99*3b35e7eeSXin LI #	if (defined(__SSSE3__) && defined(__SSE4_1__) && defined(__PCLMUL__)) \
100*3b35e7eeSXin LI 		|| (defined(__e2k__) && __iset__ >= 6)
101*3b35e7eeSXin LI #		define CRC32_ARCH_OPTIMIZED 1
102*3b35e7eeSXin LI #		define CRC64_ARCH_OPTIMIZED 1
103*3b35e7eeSXin LI #		define CRC_X86_CLMUL 1
104*3b35e7eeSXin LI #	else
105*3b35e7eeSXin LI #		define CRC32_GENERIC 1
106*3b35e7eeSXin LI #		define CRC64_GENERIC 1
107*3b35e7eeSXin LI #		define CRC32_ARCH_OPTIMIZED 1
108*3b35e7eeSXin LI #		define CRC64_ARCH_OPTIMIZED 1
109*3b35e7eeSXin LI #		define CRC_X86_CLMUL 1
110*3b35e7eeSXin LI 
111*3b35e7eeSXin LI /*
112*3b35e7eeSXin LI 		// The generic code is much faster with 1-8-byte inputs and
113*3b35e7eeSXin LI 		// has similar performance up to 16 bytes  at least in
114*3b35e7eeSXin LI 		// microbenchmarks (it depends on input buffer alignment
115*3b35e7eeSXin LI 		// too). If both versions are built, this #define will use
116*3b35e7eeSXin LI 		// the generic version for inputs up to 16 bytes and CLMUL
117*3b35e7eeSXin LI 		// for bigger inputs. It saves a little in code size since
118*3b35e7eeSXin LI 		// the special cases for 0-16-byte inputs will be omitted
119*3b35e7eeSXin LI 		// from the CLMUL code.
120*3b35e7eeSXin LI #		define CRC_USE_GENERIC_FOR_SMALL_INPUTS 1
121*3b35e7eeSXin LI */
122*3b35e7eeSXin LI #	endif
123*3b35e7eeSXin LI #endif
124*3b35e7eeSXin LI 
125*3b35e7eeSXin LI // For CRC32 use the generic slice-by-eight implementation if no optimized
126*3b35e7eeSXin LI // version is available.
127*3b35e7eeSXin LI #if !defined(CRC32_ARCH_OPTIMIZED) && !defined(CRC32_GENERIC)
128*3b35e7eeSXin LI #	define CRC32_GENERIC 1
129*3b35e7eeSXin LI #endif
130*3b35e7eeSXin LI 
131*3b35e7eeSXin LI // For CRC64 use the generic slice-by-four implementation if no optimized
132*3b35e7eeSXin LI // version is available.
133*3b35e7eeSXin LI #if !defined(CRC64_ARCH_OPTIMIZED) && !defined(CRC64_GENERIC)
134*3b35e7eeSXin LI #	define CRC64_GENERIC 1
135*3b35e7eeSXin LI #endif
136*3b35e7eeSXin LI 
137*3b35e7eeSXin LI #endif
138