summaryrefslogtreecommitdiff
path: root/neozip/arch/generic/slide_hash_c.c
diff options
context:
space:
mode:
Diffstat (limited to 'neozip/arch/generic/slide_hash_c.c')
-rw-r--r--neozip/arch/generic/slide_hash_c.c52
1 files changed, 52 insertions, 0 deletions
diff --git a/neozip/arch/generic/slide_hash_c.c b/neozip/arch/generic/slide_hash_c.c
new file mode 100644
index 0000000000..8345b9e36b
--- /dev/null
+++ b/neozip/arch/generic/slide_hash_c.c
@@ -0,0 +1,52 @@
+/* slide_hash.c -- slide hash table C implementation
+ *
+ * Copyright (C) 1995-2024 Jean-loup Gailly and Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "zbuild.h"
+#include "deflate.h"
+
+/* ===========================================================================
+ * Slide the hash table when sliding the window down (could be avoided with 32
+ * bit values at the expense of memory usage). We slide even when level == 0 to
+ * keep the hash table consistent if we switch back to level > 0 later.
+ */
+static inline void slide_hash_c_chain(Pos *table, uint32_t entries, uint16_t wsize) {
+#ifdef NOT_TWEAK_COMPILER
+ table += entries;
+ do {
+ unsigned m;
+ m = *--table;
+ *table = (Pos)(m >= wsize ? m-wsize : 0);
+ /* If entries is not on any hash chain, prev[entries] is garbage but
+ * its value will never be used.
+ */
+ } while (--entries);
+#else
+ {
+ /* As of I make this change, gcc (4.8.*) isn't able to vectorize
+ * this hot loop using saturated-subtraction on x86-64 architecture.
+ * To avoid this defect, we can change the loop such that
+ * o. the pointer advance forward, and
+ * o. demote the variable 'm' to be local to the loop, and
+ * choose type "Pos" (instead of 'unsigned int') for the
+ * variable to avoid unnecessary zero-extension.
+ */
+ unsigned int i;
+ Pos *q = table;
+ for (i = 0; i < entries; i++) {
+ Pos m = *q;
+ Pos t = (Pos)wsize;
+ *q++ = (Pos)(m >= t ? m-t: 0);
+ }
+ }
+#endif /* NOT_TWEAK_COMPILER */
+}
+
+Z_INTERNAL void slide_hash_c(deflate_state *s) {
+ uint16_t wsize = (uint16_t)s->w_size;
+
+ slide_hash_c_chain(s->head, HASH_SIZE, wsize);
+ slide_hash_c_chain(s->prev, wsize, wsize);
+}