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 */
12static 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
45static 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
56Z_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 */
68static 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
89static 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: src0+2, src1: src1+2) + 2;
94}
95
96Z_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 */
108static 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
127static 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: src0+2, src1: src1+2) + 2;
132}
133
134Z_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 */
148static 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
167static 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: src0+2, src1: src1+2) + 2;
172}
173
174Z_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