xref: /freebsd/contrib/xz/src/liblzma/check/crc_common.h (revision 128836d304d93f2d00eb14069c27089ab46c38d4)
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