aboutsummaryrefslogtreecommitdiff
path: root/src/liblzma/check/crc64.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/liblzma/check/crc64.c')
-rw-r--r--src/liblzma/check/crc64.c75
1 files changed, 75 insertions, 0 deletions
diff --git a/src/liblzma/check/crc64.c b/src/liblzma/check/crc64.c
new file mode 100644
index 00000000..e31bc7ff
--- /dev/null
+++ b/src/liblzma/check/crc64.c
@@ -0,0 +1,75 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file crc64.c
+/// \brief CRC64 calculation
+//
+// This code has been put into the public domain.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "check.h"
+#include "crc_macros.h"
+
+
+#ifdef WORDS_BIGENDIAN
+# define A1(x) ((x) >> 56)
+#else
+# define A1 A
+#endif
+
+
+// See comments in crc32.c.
+extern uint64_t
+lzma_crc64(const uint8_t *buf, size_t size, uint64_t crc)
+{
+ crc = ~crc;
+
+#ifdef WORDS_BIGENDIAN
+ crc = bswap_64(crc);
+#endif
+
+ if (size > 4) {
+ while ((uintptr_t)(buf) & 3) {
+ crc = lzma_crc64_table[0][*buf++ ^ A1(crc)] ^ S8(crc);
+ --size;
+ }
+
+ const uint8_t *const limit = buf + (size & ~(size_t)(3));
+ size &= (size_t)(3);
+
+ // Calculate the CRC64 using the slice-by-four algorithm.
+ //
+ // In contrast to CRC32 code, this one seems to be fastest
+ // with -O3 -fomit-frame-pointer.
+ while (buf < limit) {
+#ifdef WORDS_BIGENDIAN
+ const uint32_t tmp = (crc >> 32) ^ *(uint32_t *)(buf);
+#else
+ const uint32_t tmp = crc ^ *(uint32_t *)(buf);
+#endif
+ buf += 4;
+
+ // It is critical for performance, that
+ // the crc variable is XORed between the
+ // two table-lookup pairs.
+ crc = lzma_crc64_table[3][A(tmp)]
+ ^ lzma_crc64_table[2][B(tmp)]
+ ^ S32(crc)
+ ^ lzma_crc64_table[1][C(tmp)]
+ ^ lzma_crc64_table[0][D(tmp)];
+ }
+ }
+
+ while (size-- != 0)
+ crc = lzma_crc64_table[0][*buf++ ^ A1(crc)] ^ S8(crc);
+
+#ifdef WORDS_BIGENDIAN
+ crc = bswap_64(crc);
+#endif
+
+ return ~crc;
+}