crc64_fast.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  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 = byteswap64(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 = byteswap64(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. static crc64_func_type
  74. crc64_resolve(void)
  75. {
  76. return is_arch_extension_supported()
  77. ? &crc64_arch_optimized : &crc64_generic;
  78. }
  79. #ifdef HAVE_FUNC_ATTRIBUTE_CONSTRUCTOR
  80. # define CRC64_SET_FUNC_ATTR __attribute__((__constructor__))
  81. static crc64_func_type crc64_func;
  82. #else
  83. # define CRC64_SET_FUNC_ATTR
  84. static uint64_t crc64_dispatch(const uint8_t *buf, size_t size, uint64_t crc);
  85. static crc64_func_type crc64_func = &crc64_dispatch;
  86. #endif
  87. CRC64_SET_FUNC_ATTR
  88. static void
  89. crc64_set_func(void)
  90. {
  91. crc64_func = crc64_resolve();
  92. return;
  93. }
  94. #ifndef HAVE_FUNC_ATTRIBUTE_CONSTRUCTOR
  95. static uint64_t
  96. crc64_dispatch(const uint8_t *buf, size_t size, uint64_t crc)
  97. {
  98. crc64_set_func();
  99. return crc64_func(buf, size, crc);
  100. }
  101. #endif
  102. #endif
  103. extern LZMA_API(uint64_t)
  104. lzma_crc64(const uint8_t *buf, size_t size, uint64_t crc)
  105. {
  106. #if defined(CRC64_GENERIC) && defined(CRC64_ARCH_OPTIMIZED)
  107. #ifdef CRC_USE_GENERIC_FOR_SMALL_INPUTS
  108. if (size <= 16)
  109. return crc64_generic(buf, size, crc);
  110. #endif
  111. return crc64_func(buf, size, crc);
  112. #elif defined(CRC64_ARCH_OPTIMIZED)
  113. // If arch-optimized version is used unconditionally without runtime
  114. // CPU detection then omitting the generic version and its 8 KiB
  115. // lookup table makes the library smaller.
  116. //
  117. // FIXME: Lookup table isn't currently omitted on 32-bit x86,
  118. // see crc64_table.c.
  119. return crc64_arch_optimized(buf, size, crc);
  120. #else
  121. return crc64_generic(buf, size, crc);
  122. #endif
  123. }