diff options
author | Nathan Moinvaziri <nathan@nathanm.com> | 2020-02-25 14:36:56 -0800 |
---|---|---|
committer | Hans Kristian Rosbach <hk-github@circlestorm.org> | 2020-05-24 13:53:25 +0200 |
commit | 9bd28d93813db93aa2fb1b14309cced1efe7d721 (patch) | |
tree | a1185fadcd53a5b8fe36e23ff748b7b118683dcb /compare258.c | |
parent | 641491adedec68079d728728a1e9b2c76c2fae1d (diff) |
Abstracted out architecture specific implementations of 258 byte comparison to compare258.
Diffstat (limited to 'compare258.c')
-rw-r--r-- | compare258.c | 122 |
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 |