crc64_fast.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. // SPDX-License-Identifier: 0BSD
  2. ///////////////////////////////////////////////////////////////////////////////
  3. //
  4. /// \file crc64.c
  5. /// \brief CRC64 calculation
  6. //
  7. // Authors: Lasse Collin
  8. // Ilya Kurdyukov
  9. //
  10. ///////////////////////////////////////////////////////////////////////////////
  11. #include "check.h"
  12. #include "crc_common.h"
  13. #if defined(CRC_X86_CLMUL)
  14. # define BUILDING_CRC64_CLMUL
  15. # include "crc_x86_clmul.h"
  16. #endif
  17. #ifdef CRC64_GENERIC
  18. /////////////////////////////////
  19. // Generic slice-by-four CRC64 //
  20. /////////////////////////////////
  21. #ifdef WORDS_BIGENDIAN
  22. # define A1(x) ((x) >> 56)
  23. #else
  24. # define A1 A
  25. #endif
  26. // See the comments in crc32_fast.c. They aren't duplicated here.
  27. static uint64_t
  28. crc64_generic(const uint8_t *buf, size_t size, uint64_t crc)
  29. {
  30. crc = ~crc;
  31. #ifdef WORDS_BIGENDIAN
  32. crc = bswap64(crc);
  33. #endif
  34. if (size > 4) {
  35. while ((uintptr_t)(buf) & 3) {
  36. crc = lzma_crc64_table[0][*buf++ ^ A1(crc)] ^ S8(crc);
  37. --size;
  38. }
  39. const uint8_t *const limit = buf + (size & ~(size_t)(3));
  40. size &= (size_t)(3);
  41. while (buf < limit) {
  42. #ifdef WORDS_BIGENDIAN
  43. const uint32_t tmp = (uint32_t)(crc >> 32)
  44. ^ aligned_read32ne(buf);
  45. #else
  46. const uint32_t tmp = (uint32_t)crc
  47. ^ aligned_read32ne(buf);
  48. #endif
  49. buf += 4;
  50. crc = lzma_crc64_table[3][A(tmp)]
  51. ^ lzma_crc64_table[2][B(tmp)]
  52. ^ S32(crc)
  53. ^ lzma_crc64_table[1][C(tmp)]
  54. ^ lzma_crc64_table[0][D(tmp)];
  55. }
  56. }
  57. while (size-- != 0)
  58. crc = lzma_crc64_table[0][*buf++ ^ A1(crc)] ^ S8(crc);
  59. #ifdef WORDS_BIGENDIAN
  60. crc = bswap64(crc);
  61. #endif
  62. return ~crc;
  63. }
  64. #endif
  65. #if defined(CRC64_GENERIC) && defined(CRC64_ARCH_OPTIMIZED)
  66. //////////////////////////
  67. // Function dispatching //
  68. //////////////////////////
  69. // If both the generic and arch-optimized implementations are usable, then
  70. // the function that is used is selected at runtime. See crc32_fast.c.
  71. typedef uint64_t (*crc64_func_type)(
  72. const uint8_t *buf, size_t size, uint64_t crc);
  73. #if defined(CRC_USE_IFUNC) && defined(__clang__)
  74. # pragma GCC diagnostic push
  75. # pragma GCC diagnostic ignored "-Wunused-function"
  76. #endif
  77. lzma_resolver_attributes
  78. static crc64_func_type
  79. crc64_resolve(void)
  80. {
  81. return is_arch_extension_supported()
  82. ? &crc64_arch_optimized : &crc64_generic;
  83. }
  84. #if defined(CRC_USE_IFUNC) && defined(__clang__)
  85. # pragma GCC diagnostic pop
  86. #endif
  87. #ifndef CRC_USE_IFUNC
  88. #ifdef HAVE_FUNC_ATTRIBUTE_CONSTRUCTOR
  89. # define CRC64_SET_FUNC_ATTR __attribute__((__constructor__))
  90. static crc64_func_type crc64_func;
  91. #else
  92. # define CRC64_SET_FUNC_ATTR
  93. static uint64_t crc64_dispatch(const uint8_t *buf, size_t size, uint64_t crc);
  94. static crc64_func_type crc64_func = &crc64_dispatch;
  95. #endif
  96. CRC64_SET_FUNC_ATTR
  97. static void
  98. crc64_set_func(void)
  99. {
  100. crc64_func = crc64_resolve();
  101. return;
  102. }
  103. #ifndef HAVE_FUNC_ATTRIBUTE_CONSTRUCTOR
  104. static uint64_t
  105. crc64_dispatch(const uint8_t *buf, size_t size, uint64_t crc)
  106. {
  107. crc64_set_func();
  108. return crc64_func(buf, size, crc);
  109. }
  110. #endif
  111. #endif
  112. #endif
  113. #ifdef CRC_USE_IFUNC
  114. extern LZMA_API(uint64_t)
  115. lzma_crc64(const uint8_t *buf, size_t size, uint64_t crc)
  116. __attribute__((__ifunc__("crc64_resolve")));
  117. #else
  118. extern LZMA_API(uint64_t)
  119. lzma_crc64(const uint8_t *buf, size_t size, uint64_t crc)
  120. {
  121. #if defined(CRC64_GENERIC) && defined(CRC64_ARCH_OPTIMIZED)
  122. #ifdef CRC_USE_GENERIC_FOR_SMALL_INPUTS
  123. if (size <= 16)
  124. return crc64_generic(buf, size, crc);
  125. #endif
  126. return crc64_func(buf, size, crc);
  127. #elif defined(CRC64_ARCH_OPTIMIZED)
  128. // If arch-optimized version is used unconditionally without runtime
  129. // CPU detection then omitting the generic version and its 8 KiB
  130. // lookup table makes the library smaller.
  131. //
  132. // FIXME: Lookup table isn't currently omitted on 32-bit x86,
  133. // see crc64_table.c.
  134. return crc64_arch_optimized(buf, size, crc);
  135. #else
  136. return crc64_generic(buf, size, crc);
  137. #endif
  138. }
  139. #endif