summaryrefslogtreecommitdiff
path: root/compare258.c
diff options
context:
space:
mode:
authorNathan Moinvaziri <nathan@nathanm.com>2020-02-25 14:36:56 -0800
committerHans Kristian Rosbach <hk-github@circlestorm.org>2020-05-24 13:53:25 +0200
commit9bd28d93813db93aa2fb1b14309cced1efe7d721 (patch)
treea1185fadcd53a5b8fe36e23ff748b7b118683dcb /compare258.c
parent641491adedec68079d728728a1e9b2c76c2fae1d (diff)
Abstracted out architecture specific implementations of 258 byte comparison to compare258.
Diffstat (limited to 'compare258.c')
-rw-r--r--compare258.c122
1 files changed, 122 insertions, 0 deletions
diff --git a/compare258.c b/compare258.c
new file mode 100644
index 0000000..b538277
--- /dev/null
+++ b/compare258.c
@@ -0,0 +1,122 @@
+/* compare258.c -- aligned and unaligned versions of compare258
+ * Copyright (C) 2020 Nathan Moinvaziri
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "zbuild.h"
+#include "zutil.h"
+
+#include "fallback_builtins.h"
+
+/* ALIGNED, byte comparison */
+int32_t compare258_c(const unsigned char *src0, const unsigned char *src1) {
+ const unsigned char *src0start = src0;
+ const unsigned char *src0end = src0 + 258;
+
+ do {
+ if (*src0 != *src1)
+ break;
+ src0 += 1, src1 += 1;
+ if (*src0 != *src1)
+ break;
+ src0 += 1, src1 += 1;
+ if (*src0 != *src1)
+ break;
+ src0 += 1, src1 += 1;
+ if (*src0 != *src1)
+ break;
+ src0 += 1, src1 += 1;
+ if (*src0 != *src1)
+ break;
+ src0 += 1, src1 += 1;
+ if (*src0 != *src1)
+ break;
+ src0 += 1, src1 += 1;
+ } while (src0 < src0end);
+
+ return (int32_t)(src0 - src0start);
+}
+
+#ifdef UNALIGNED_OK
+/* UNALIGNED_OK, 16-bit integer comparison */
+int32_t compare258_unaligned_16(const unsigned char *src0, const unsigned char *src1) {
+ const unsigned char *src0start = src0;
+ const unsigned char *src0end = src0 + 258;
+
+ do {
+ if (*(uint16_t *)src0 != *(uint16_t *)src1)
+ break;
+ src0 += 2, src1 += 2;
+ if (*(uint16_t *)src0 != *(uint16_t *)src1)
+ break;
+ src0 += 2, src1 += 2;
+ if (*(uint16_t *)src0 != *(uint16_t *)src1)
+ break;
+ src0 += 2, src1 += 2;
+ } while (src0 < src0end);
+
+ if (*src0 == *src1)
+ src0 += 1;
+
+ return (int32_t)(src0 - src0start);
+}
+
+#ifdef HAVE_BUILTIN_CTZ
+/* UNALIGNED_OK, 32-bit integer comparison */
+int32_t compare258_unaligned_32(const unsigned char *src0, const unsigned char *src1) {
+ const unsigned char *src0start = src0;
+ const unsigned char *src0end = src0 + 256;
+
+ do {
+ uint32_t sv = *(uint32_t *)src0;
+ uint32_t mv = *(uint32_t *)src1;
+ uint32_t xor = sv ^ mv;
+
+ if (xor) {
+ uint32_t match_byte = __builtin_ctz(xor) / 8;
+ return (int32_t)(src0 - src0start + match_byte);
+ }
+
+ src0 += 4, src1 += 4;
+ } while (src0 < src0end);
+
+ if (*(uint16_t *)src0 == *(uint16_t *)src1)
+ src0 += 2, src1 += 2;
+ else if (*src0 == *src1)
+ src0 += 1, src1 += 1;
+
+ return (int32_t)(src0 - src0start);
+}
+
+#endif
+
+#ifdef HAVE_BUILTIN_CTZLL
+/* UNALIGNED_OK, 64-bit integer comparison */
+int32_t compare258_unaligned_64(const unsigned char *src0, const unsigned char *src1) {
+ const unsigned char *src0start = src0;
+ const unsigned char *src0end = src0 + 256;
+
+ do {
+ uint64_t sv = *(uint64_t *)src0;
+ uint64_t mv = *(uint64_t *)src1;
+ uint64_t xor = sv ^ mv;
+
+ if (xor) {
+ uint64_t match_byte = __builtin_ctzll(xor) / 8;
+ return (int32_t)(src0 - src0start + match_byte);
+ }
+
+ src0 += 8, src1 += 8;
+ } while (src0 < src0end);
+
+ if (*(uint16_t *)src0 == *(uint16_t *)src1)
+ src0 += 2, src1 += 2;
+ else if (*src0 == *src1)
+ src0 += 1, src1 += 1;
+
+ return (int32_t)(src0 - src0start);
+}
+
+#endif
+
+#endif