crc_common.h 5.0 KB

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