1 /* compare256.c -- 256 byte memory comparison with match length return
2 * Copyright (C) 2020 Nathan Moinvaziri
3 * For conditions of distribution and use, see copyright notice in zlib.h
4 */
5
6 #include "zbuild.h"
7 #include "fallback_builtins.h"
8
9 /* ALIGNED, byte comparison */
compare256_c_static(const uint8_t * src0,const uint8_t * src1)10 static inline uint32_t compare256_c_static(const uint8_t *src0, const uint8_t *src1) {
11 uint32_t len = 0;
12
13 do {
14 if (*src0 != *src1)
15 return len;
16 src0 += 1, src1 += 1, len += 1;
17 if (*src0 != *src1)
18 return len;
19 src0 += 1, src1 += 1, len += 1;
20 if (*src0 != *src1)
21 return len;
22 src0 += 1, src1 += 1, len += 1;
23 if (*src0 != *src1)
24 return len;
25 src0 += 1, src1 += 1, len += 1;
26 if (*src0 != *src1)
27 return len;
28 src0 += 1, src1 += 1, len += 1;
29 if (*src0 != *src1)
30 return len;
31 src0 += 1, src1 += 1, len += 1;
32 if (*src0 != *src1)
33 return len;
34 src0 += 1, src1 += 1, len += 1;
35 if (*src0 != *src1)
36 return len;
37 src0 += 1, src1 += 1, len += 1;
38 } while (len < 256);
39
40 return 256;
41 }
42
compare256_c(const uint8_t * src0,const uint8_t * src1)43 Z_INTERNAL uint32_t compare256_c(const uint8_t *src0, const uint8_t *src1) {
44 return compare256_c_static(src0, src1);
45 }
46
47 #define LONGEST_MATCH longest_match_c
48 #define COMPARE256 compare256_c_static
49
50 #include "match_tpl.h"
51
52 #define LONGEST_MATCH_SLOW
53 #define LONGEST_MATCH longest_match_slow_c
54 #define COMPARE256 compare256_c_static
55
56 #include "match_tpl.h"
57
58 #ifdef UNALIGNED_OK
59 /* 16-bit unaligned integer comparison */
compare256_unaligned_16_static(const uint8_t * src0,const uint8_t * src1)60 static inline uint32_t compare256_unaligned_16_static(const uint8_t *src0, const uint8_t *src1) {
61 uint32_t len = 0;
62
63 do {
64 if (zmemcmp_2(src0, src1) != 0)
65 return len + (*src0 == *src1);
66 src0 += 2, src1 += 2, len += 2;
67 if (zmemcmp_2(src0, src1) != 0)
68 return len + (*src0 == *src1);
69 src0 += 2, src1 += 2, len += 2;
70 if (zmemcmp_2(src0, src1) != 0)
71 return len + (*src0 == *src1);
72 src0 += 2, src1 += 2, len += 2;
73 if (zmemcmp_2(src0, src1) != 0)
74 return len + (*src0 == *src1);
75 src0 += 2, src1 += 2, len += 2;
76 } while (len < 256);
77
78 return 256;
79 }
80
compare256_unaligned_16(const uint8_t * src0,const uint8_t * src1)81 Z_INTERNAL uint32_t compare256_unaligned_16(const uint8_t *src0, const uint8_t *src1) {
82 return compare256_unaligned_16_static(src0, src1);
83 }
84
85 #define LONGEST_MATCH longest_match_unaligned_16
86 #define COMPARE256 compare256_unaligned_16_static
87
88 #include "match_tpl.h"
89
90 #define LONGEST_MATCH_SLOW
91 #define LONGEST_MATCH longest_match_slow_unaligned_16
92 #define COMPARE256 compare256_unaligned_16_static
93
94 #include "match_tpl.h"
95
96 #ifdef HAVE_BUILTIN_CTZ
97 /* 32-bit unaligned integer comparison */
compare256_unaligned_32_static(const uint8_t * src0,const uint8_t * src1)98 static inline uint32_t compare256_unaligned_32_static(const uint8_t *src0, const uint8_t *src1) {
99 uint32_t len = 0;
100
101 do {
102 uint32_t sv, mv, diff;
103
104 zmemcpy_4(&sv, src0);
105 zmemcpy_4(&mv, src1);
106
107 diff = sv ^ mv;
108 if (diff) {
109 uint32_t match_byte = __builtin_ctz(diff) / 8;
110 return len + match_byte;
111 }
112
113 src0 += 4, src1 += 4, len += 4;
114 } while (len < 256);
115
116 return 256;
117 }
118
compare256_unaligned_32(const uint8_t * src0,const uint8_t * src1)119 Z_INTERNAL uint32_t compare256_unaligned_32(const uint8_t *src0, const uint8_t *src1) {
120 return compare256_unaligned_32_static(src0, src1);
121 }
122
123 #define LONGEST_MATCH longest_match_unaligned_32
124 #define COMPARE256 compare256_unaligned_32_static
125
126 #include "match_tpl.h"
127
128 #define LONGEST_MATCH_SLOW
129 #define LONGEST_MATCH longest_match_slow_unaligned_32
130 #define COMPARE256 compare256_unaligned_32_static
131
132 #include "match_tpl.h"
133
134 #endif
135
136 #if defined(UNALIGNED64_OK) && defined(HAVE_BUILTIN_CTZLL)
137 /* UNALIGNED64_OK, 64-bit integer comparison */
compare256_unaligned_64_static(const uint8_t * src0,const uint8_t * src1)138 static inline uint32_t compare256_unaligned_64_static(const uint8_t *src0, const uint8_t *src1) {
139 uint32_t len = 0;
140
141 do {
142 uint64_t sv, mv, diff;
143
144 zmemcpy_8(&sv, src0);
145 zmemcpy_8(&mv, src1);
146
147 diff = sv ^ mv;
148 if (diff) {
149 uint64_t match_byte = __builtin_ctzll(diff) / 8;
150 return len + (uint32_t)match_byte;
151 }
152
153 src0 += 8, src1 += 8, len += 8;
154 } while (len < 256);
155
156 return 256;
157 }
158
compare256_unaligned_64(const uint8_t * src0,const uint8_t * src1)159 Z_INTERNAL uint32_t compare256_unaligned_64(const uint8_t *src0, const uint8_t *src1) {
160 return compare256_unaligned_64_static(src0, src1);
161 }
162
163 #define LONGEST_MATCH longest_match_unaligned_64
164 #define COMPARE256 compare256_unaligned_64_static
165
166 #include "match_tpl.h"
167
168 #define LONGEST_MATCH_SLOW
169 #define LONGEST_MATCH longest_match_slow_unaligned_64
170 #define COMPARE256 compare256_unaligned_64_static
171
172 #include "match_tpl.h"
173
174 #endif
175
176 #endif
177