• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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