1 /* compare258.c -- aligned and unaligned versions of compare258
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 "zutil.h"
8 
9 #include "fallback_builtins.h"
10 
11 /* ALIGNED, byte comparison */
compare256_c_static(const unsigned char * src0,const unsigned char * src1)12 static inline uint32_t compare256_c_static(const unsigned char *src0, const unsigned char *src1) {
13     uint32_t len = 0;
14 
15     do {
16         if (*src0 != *src1)
17             return len + (*src0 == *src1);
18         src0 += 1, src1 += 1, len += 1;
19         if (*src0 != *src1)
20             return len + (*src0 == *src1);
21         src0 += 1, src1 += 1, len += 1;
22         if (*src0 != *src1)
23             return len + (*src0 == *src1);
24         src0 += 1, src1 += 1, len += 1;
25         if (*src0 != *src1)
26             return len + (*src0 == *src1);
27         src0 += 1, src1 += 1, len += 1;
28         if (*src0 != *src1)
29             return len + (*src0 == *src1);
30         src0 += 1, src1 += 1, len += 1;
31         if (*src0 != *src1)
32             return len + (*src0 == *src1);
33         src0 += 1, src1 += 1, len += 1;
34         if (*src0 != *src1)
35             return len + (*src0 == *src1);
36         src0 += 1, src1 += 1, len += 1;
37         if (*src0 != *src1)
38             return len + (*src0 == *src1);
39         src0 += 1, src1 += 1, len += 1;
40     } while (len < 256);
41 
42     return 256;
43 }
44 
compare258_c_static(const unsigned char * src0,const unsigned char * src1)45 static inline uint32_t compare258_c_static(const unsigned char *src0, const unsigned char *src1) {
46     if (*src0 != *src1)
47         return 0;
48     src0 += 1, src1 += 1;
49     if (*src0 != *src1)
50         return 1;
51     src0 += 1, src1 += 1;
52 
53     return compare256_c_static(src0, src1) + 2;
54 }
55 
compare258_c(const unsigned char * src0,const unsigned char * src1)56 Z_INTERNAL uint32_t compare258_c(const unsigned char *src0, const unsigned char *src1) {
57     return compare258_c_static(src0, src1);
58 }
59 
60 #define LONGEST_MATCH   longest_match_c
61 #define COMPARE256      compare256_c_static
62 #define COMPARE258      compare258_c_static
63 
64 #include "match_tpl.h"
65 
66 #ifdef UNALIGNED_OK
67 /* UNALIGNED_OK, 16-bit integer comparison */
compare256_unaligned_16_static(const unsigned char * src0,const unsigned char * src1)68 static inline uint32_t compare256_unaligned_16_static(const unsigned char *src0, const unsigned char *src1) {
69     uint32_t len = 0;
70 
71     do {
72         if (*(uint16_t *)src0 != *(uint16_t *)src1)
73             return len + (*src0 == *src1);
74         src0 += 2, src1 += 2, len += 2;
75         if (*(uint16_t *)src0 != *(uint16_t *)src1)
76             return len + (*src0 == *src1);
77         src0 += 2, src1 += 2, len += 2;
78         if (*(uint16_t *)src0 != *(uint16_t *)src1)
79             return len + (*src0 == *src1);
80         src0 += 2, src1 += 2, len += 2;
81         if (*(uint16_t *)src0 != *(uint16_t *)src1)
82             return len + (*src0 == *src1);
83         src0 += 2, src1 += 2, len += 2;
84     } while (len < 256);
85 
86     return 256;
87 }
88 
compare258_unaligned_16_static(const unsigned char * src0,const unsigned char * src1)89 static inline uint32_t compare258_unaligned_16_static(const unsigned char *src0, const unsigned char *src1) {
90     if (*(uint16_t *)src0 != *(uint16_t *)src1)
91         return (*src0 == *src1);
92 
93     return compare256_unaligned_16_static(src0+2, src1+2) + 2;
94 }
95 
compare258_unaligned_16(const unsigned char * src0,const unsigned char * src1)96 Z_INTERNAL uint32_t compare258_unaligned_16(const unsigned char *src0, const unsigned char *src1) {
97     return compare258_unaligned_16_static(src0, src1);
98 }
99 
100 #define LONGEST_MATCH   longest_match_unaligned_16
101 #define COMPARE256      compare256_unaligned_16_static
102 #define COMPARE258      compare258_unaligned_16_static
103 
104 #include "match_tpl.h"
105 
106 #ifdef HAVE_BUILTIN_CTZ
107 /* UNALIGNED_OK, 32-bit integer comparison */
compare256_unaligned_32_static(const unsigned char * src0,const unsigned char * src1)108 static inline uint32_t compare256_unaligned_32_static(const unsigned char *src0, const unsigned char *src1) {
109     uint32_t len = 0;
110 
111     do {
112         uint32_t sv = *(uint32_t *)src0;
113         uint32_t mv = *(uint32_t *)src1;
114         uint32_t diff = sv ^ mv;
115 
116         if (diff) {
117             uint32_t match_byte = __builtin_ctz(diff) / 8;
118             return len + match_byte;
119         }
120 
121         src0 += 4, src1 += 4, len += 4;
122     } while (len < 256);
123 
124     return 256;
125 }
126 
compare258_unaligned_32_static(const unsigned char * src0,const unsigned char * src1)127 static inline uint32_t compare258_unaligned_32_static(const unsigned char *src0, const unsigned char *src1) {
128     if (*(uint16_t *)src0 != *(uint16_t *)src1)
129         return (*src0 == *src1);
130 
131     return compare256_unaligned_32_static(src0+2, src1+2) + 2;
132 }
133 
compare258_unaligned_32(const unsigned char * src0,const unsigned char * src1)134 Z_INTERNAL uint32_t compare258_unaligned_32(const unsigned char *src0, const unsigned char *src1) {
135     return compare258_unaligned_32_static(src0, src1);
136 }
137 
138 #define LONGEST_MATCH   longest_match_unaligned_32
139 #define COMPARE256      compare256_unaligned_32_static
140 #define COMPARE258      compare258_unaligned_32_static
141 
142 #include "match_tpl.h"
143 
144 #endif
145 
146 #if defined(UNALIGNED64_OK) && defined(HAVE_BUILTIN_CTZLL)
147 /* UNALIGNED64_OK, 64-bit integer comparison */
compare256_unaligned_64_static(const unsigned char * src0,const unsigned char * src1)148 static inline uint32_t compare256_unaligned_64_static(const unsigned char *src0, const unsigned char *src1) {
149     uint32_t len = 0;
150 
151     do {
152         uint64_t sv = *(uint64_t *)src0;
153         uint64_t mv = *(uint64_t *)src1;
154         uint64_t diff = sv ^ mv;
155 
156         if (diff) {
157             uint64_t match_byte = __builtin_ctzll(diff) / 8;
158             return len + (uint32_t)match_byte;
159         }
160 
161         src0 += 8, src1 += 8, len += 8;
162     } while (len < 256);
163 
164     return 256;
165 }
166 
compare258_unaligned_64_static(const unsigned char * src0,const unsigned char * src1)167 static inline uint32_t compare258_unaligned_64_static(const unsigned char *src0, const unsigned char *src1) {
168     if (*(uint16_t *)src0 != *(uint16_t *)src1)
169         return (*src0 == *src1);
170 
171     return compare256_unaligned_64_static(src0+2, src1+2) + 2;
172 }
173 
compare258_unaligned_64(const unsigned char * src0,const unsigned char * src1)174 Z_INTERNAL uint32_t compare258_unaligned_64(const unsigned char *src0, const unsigned char *src1) {
175     return compare258_unaligned_64_static(src0, src1);
176 }
177 
178 #define LONGEST_MATCH   longest_match_unaligned_64
179 #define COMPARE256      compare256_unaligned_64_static
180 #define COMPARE258      compare258_unaligned_64_static
181 
182 #include "match_tpl.h"
183 
184 #endif
185 
186 #endif
187