13b35e7eeSXin LI // SPDX-License-Identifier: 0BSD 23b35e7eeSXin LI 33b35e7eeSXin LI /////////////////////////////////////////////////////////////////////////////// 43b35e7eeSXin LI // 53b35e7eeSXin LI /// \file crc_common.h 63b35e7eeSXin LI /// \brief Some functions and macros for CRC32 and CRC64 73b35e7eeSXin LI // 83b35e7eeSXin LI // Authors: Lasse Collin 93b35e7eeSXin LI // Ilya Kurdyukov 103b35e7eeSXin LI // Hans Jansen 113b35e7eeSXin LI // Jia Tan 123b35e7eeSXin LI // 133b35e7eeSXin LI /////////////////////////////////////////////////////////////////////////////// 143b35e7eeSXin LI 153b35e7eeSXin LI #ifndef LZMA_CRC_COMMON_H 163b35e7eeSXin LI #define LZMA_CRC_COMMON_H 173b35e7eeSXin LI 183b35e7eeSXin LI #include "common.h" 193b35e7eeSXin LI 203b35e7eeSXin LI 213b35e7eeSXin LI #ifdef WORDS_BIGENDIAN 223b35e7eeSXin LI # define A(x) ((x) >> 24) 233b35e7eeSXin LI # define B(x) (((x) >> 16) & 0xFF) 243b35e7eeSXin LI # define C(x) (((x) >> 8) & 0xFF) 253b35e7eeSXin LI # define D(x) ((x) & 0xFF) 263b35e7eeSXin LI 273b35e7eeSXin LI # define S8(x) ((x) << 8) 283b35e7eeSXin LI # define S32(x) ((x) << 32) 293b35e7eeSXin LI 303b35e7eeSXin LI #else 313b35e7eeSXin LI # define A(x) ((x) & 0xFF) 323b35e7eeSXin LI # define B(x) (((x) >> 8) & 0xFF) 333b35e7eeSXin LI # define C(x) (((x) >> 16) & 0xFF) 343b35e7eeSXin LI # define D(x) ((x) >> 24) 353b35e7eeSXin LI 363b35e7eeSXin LI # define S8(x) ((x) >> 8) 373b35e7eeSXin LI # define S32(x) ((x) >> 32) 383b35e7eeSXin LI #endif 393b35e7eeSXin LI 403b35e7eeSXin LI 413b35e7eeSXin LI // CRC CLMUL code needs this because accessing input buffers that aren't 423b35e7eeSXin LI // aligned to the vector size will inherently trip the address sanitizer. 433b35e7eeSXin LI #if lzma_has_attribute(__no_sanitize_address__) 443b35e7eeSXin LI # define crc_attr_no_sanitize_address \ 453b35e7eeSXin LI __attribute__((__no_sanitize_address__)) 463b35e7eeSXin LI #else 473b35e7eeSXin LI # define crc_attr_no_sanitize_address 483b35e7eeSXin LI #endif 493b35e7eeSXin LI 503b35e7eeSXin LI // Keep this in sync with changes to crc32_arm64.h 513b35e7eeSXin LI #if defined(_WIN32) || defined(HAVE_GETAUXVAL) \ 523b35e7eeSXin LI || defined(HAVE_ELF_AUX_INFO) \ 533b35e7eeSXin LI || (defined(__APPLE__) && defined(HAVE_SYSCTLBYNAME)) 543b35e7eeSXin LI # define ARM64_RUNTIME_DETECTION 1 553b35e7eeSXin LI #endif 563b35e7eeSXin LI 573b35e7eeSXin LI 583b35e7eeSXin LI #undef CRC32_GENERIC 593b35e7eeSXin LI #undef CRC64_GENERIC 603b35e7eeSXin LI 613b35e7eeSXin LI #undef CRC32_ARCH_OPTIMIZED 623b35e7eeSXin LI #undef CRC64_ARCH_OPTIMIZED 633b35e7eeSXin LI 643b35e7eeSXin LI // The x86 CLMUL is used for both CRC32 and CRC64. 653b35e7eeSXin LI #undef CRC_X86_CLMUL 663b35e7eeSXin LI 673b35e7eeSXin LI #undef CRC32_ARM64 683b35e7eeSXin LI #undef CRC64_ARM64_CLMUL 693b35e7eeSXin LI 703b35e7eeSXin LI #undef CRC_USE_GENERIC_FOR_SMALL_INPUTS 713b35e7eeSXin LI 723b35e7eeSXin LI // ARM64 CRC32 instruction is only useful for CRC32. Currently, only 733b35e7eeSXin LI // little endian is supported since we were unable to test on a big 743b35e7eeSXin LI // endian machine. 753b35e7eeSXin LI // 763b35e7eeSXin LI // NOTE: Keep this and the next check in sync with the macro 773b35e7eeSXin LI // NO_CRC32_TABLE in crc32_table.c 783b35e7eeSXin LI #if defined(HAVE_ARM64_CRC32) && !defined(WORDS_BIGENDIAN) 793b35e7eeSXin LI // Allow ARM64 CRC32 instruction without a runtime check if 80*26743408SXin LI // __ARM_FEATURE_CRC32 is defined. GCC and Clang only define 81*26743408SXin LI // this if the proper compiler options are used. 823b35e7eeSXin LI # if defined(__ARM_FEATURE_CRC32) 833b35e7eeSXin LI # define CRC32_ARCH_OPTIMIZED 1 843b35e7eeSXin LI # define CRC32_ARM64 1 853b35e7eeSXin LI # elif defined(ARM64_RUNTIME_DETECTION) 863b35e7eeSXin LI # define CRC32_ARCH_OPTIMIZED 1 873b35e7eeSXin LI # define CRC32_ARM64 1 883b35e7eeSXin LI # define CRC32_GENERIC 1 893b35e7eeSXin LI # endif 903b35e7eeSXin LI #endif 913b35e7eeSXin LI 923b35e7eeSXin LI #if defined(HAVE_USABLE_CLMUL) 933b35e7eeSXin LI // If CLMUL is allowed unconditionally in the compiler options then the 943b35e7eeSXin LI // generic version can be omitted. Note that this doesn't work with MSVC 953b35e7eeSXin LI // as I don't know how to detect the features here. 963b35e7eeSXin LI // 973b35e7eeSXin LI // NOTE: Keep this in sync with the NO_CRC32_TABLE macro in crc32_table.c 983b35e7eeSXin LI // and NO_CRC64_TABLE in crc64_table.c. 993b35e7eeSXin LI # if (defined(__SSSE3__) && defined(__SSE4_1__) && defined(__PCLMUL__)) \ 1003b35e7eeSXin LI || (defined(__e2k__) && __iset__ >= 6) 1013b35e7eeSXin LI # define CRC32_ARCH_OPTIMIZED 1 1023b35e7eeSXin LI # define CRC64_ARCH_OPTIMIZED 1 1033b35e7eeSXin LI # define CRC_X86_CLMUL 1 1043b35e7eeSXin LI # else 1053b35e7eeSXin LI # define CRC32_GENERIC 1 1063b35e7eeSXin LI # define CRC64_GENERIC 1 1073b35e7eeSXin LI # define CRC32_ARCH_OPTIMIZED 1 1083b35e7eeSXin LI # define CRC64_ARCH_OPTIMIZED 1 1093b35e7eeSXin LI # define CRC_X86_CLMUL 1 1103b35e7eeSXin LI 1113b35e7eeSXin LI /* 1123b35e7eeSXin LI // The generic code is much faster with 1-8-byte inputs and 1133b35e7eeSXin LI // has similar performance up to 16 bytes at least in 1143b35e7eeSXin LI // microbenchmarks (it depends on input buffer alignment 1153b35e7eeSXin LI // too). If both versions are built, this #define will use 1163b35e7eeSXin LI // the generic version for inputs up to 16 bytes and CLMUL 1173b35e7eeSXin LI // for bigger inputs. It saves a little in code size since 1183b35e7eeSXin LI // the special cases for 0-16-byte inputs will be omitted 1193b35e7eeSXin LI // from the CLMUL code. 1203b35e7eeSXin LI # define CRC_USE_GENERIC_FOR_SMALL_INPUTS 1 1213b35e7eeSXin LI */ 1223b35e7eeSXin LI # endif 1233b35e7eeSXin LI #endif 1243b35e7eeSXin LI 1253b35e7eeSXin LI // For CRC32 use the generic slice-by-eight implementation if no optimized 1263b35e7eeSXin LI // version is available. 1273b35e7eeSXin LI #if !defined(CRC32_ARCH_OPTIMIZED) && !defined(CRC32_GENERIC) 1283b35e7eeSXin LI # define CRC32_GENERIC 1 1293b35e7eeSXin LI #endif 1303b35e7eeSXin LI 1313b35e7eeSXin LI // For CRC64 use the generic slice-by-four implementation if no optimized 1323b35e7eeSXin LI // version is available. 1333b35e7eeSXin LI #if !defined(CRC64_ARCH_OPTIMIZED) && !defined(CRC64_GENERIC) 1343b35e7eeSXin LI # define CRC64_GENERIC 1 1353b35e7eeSXin LI #endif 1363b35e7eeSXin LI 1373b35e7eeSXin LI #endif 138