1/* Compare two memory blocks for differences in the first COUNT bytes.
2 Copyright (C) 2004-2024 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
18
19#include <sysdep.h>
20#include "asm-syntax.h"
21
22#define PARMS 4+4 /* Preserve EBX. */
23#define BLK1 PARMS
24#define BLK2 BLK1+4
25#define LEN BLK2+4
26#define ENTRANCE pushl %ebx; cfi_adjust_cfa_offset (4); \
27 cfi_rel_offset (ebx, 0)
28#define RETURN popl %ebx; cfi_adjust_cfa_offset (-4); \
29 cfi_restore (ebx); ret
30
31/* Load an entry in a jump table into EBX. TABLE is a jump table
32 with relative offsets. INDEX is a register contains the index
33 into the jump table. */
34#define LOAD_JUMP_TABLE_ENTRY(TABLE, INDEX) \
35 /* We first load PC into EBX. */ \
36 SETUP_PIC_REG(bx); \
37 /* Get the address of the jump table. */ \
38 addl $(TABLE - .), %ebx; \
39 /* Get the entry and convert the relative offset to the \
40 absolute address. */ \
41 addl (%ebx,INDEX,4), %ebx
42
43 .text
44 ALIGN (4)
45ENTRY (memcmp)
46 ENTRANCE
47
48 movl BLK1(%esp), %eax
49 movl BLK2(%esp), %edx
50 movl LEN(%esp), %ecx
51
52 cmpl $1, %ecx
53 jne L(not_1)
54 movzbl (%eax), %ecx /* LEN == 1 */
55 cmpb (%edx), %cl
56 jne L(neq)
57L(bye):
58 xorl %eax, %eax
59 RETURN
60
61 cfi_adjust_cfa_offset (4)
62 cfi_rel_offset (ebx, 0)
63L(neq):
64 sbbl %eax, %eax
65 sbbl $-1, %eax
66 RETURN
67
68 cfi_adjust_cfa_offset (4)
69 cfi_rel_offset (ebx, 0)
70L(not_1):
71 jl L(bye) /* LEN == 0 */
72
73 pushl %esi
74 cfi_adjust_cfa_offset (4)
75 movl %eax, %esi
76 cfi_rel_offset (esi, 0)
77 cmpl $32, %ecx;
78 jge L(32bytesormore) /* LEN => 32 */
79
80 LOAD_JUMP_TABLE_ENTRY (L(table_32bytes), %ecx)
81 addl %ecx, %edx
82 addl %ecx, %esi
83 jmp *%ebx
84
85 ALIGN (4)
86L(28bytes):
87 movl -28(%esi), %eax
88 movl -28(%edx), %ecx
89 cmpl %ecx, %eax
90 jne L(find_diff)
91L(24bytes):
92 movl -24(%esi), %eax
93 movl -24(%edx), %ecx
94 cmpl %ecx, %eax
95 jne L(find_diff)
96L(20bytes):
97 movl -20(%esi), %eax
98 movl -20(%edx), %ecx
99 cmpl %ecx, %eax
100 jne L(find_diff)
101L(16bytes):
102 movl -16(%esi), %eax
103 movl -16(%edx), %ecx
104 cmpl %ecx, %eax
105 jne L(find_diff)
106L(12bytes):
107 movl -12(%esi), %eax
108 movl -12(%edx), %ecx
109 cmpl %ecx, %eax
110 jne L(find_diff)
111L(8bytes):
112 movl -8(%esi), %eax
113 movl -8(%edx), %ecx
114 cmpl %ecx, %eax
115 jne L(find_diff)
116L(4bytes):
117 movl -4(%esi), %eax
118 movl -4(%edx), %ecx
119 cmpl %ecx, %eax
120 jne L(find_diff)
121L(0bytes):
122 popl %esi
123 cfi_adjust_cfa_offset (-4)
124 cfi_restore (esi)
125 xorl %eax, %eax
126 RETURN
127
128 cfi_adjust_cfa_offset (8)
129 cfi_rel_offset (esi, 0)
130 cfi_rel_offset (ebx, 4)
131L(29bytes):
132 movl -29(%esi), %eax
133 movl -29(%edx), %ecx
134 cmpl %ecx, %eax
135 jne L(find_diff)
136L(25bytes):
137 movl -25(%esi), %eax
138 movl -25(%edx), %ecx
139 cmpl %ecx, %eax
140 jne L(find_diff)
141L(21bytes):
142 movl -21(%esi), %eax
143 movl -21(%edx), %ecx
144 cmpl %ecx, %eax
145 jne L(find_diff)
146L(17bytes):
147 movl -17(%esi), %eax
148 movl -17(%edx), %ecx
149 cmpl %ecx, %eax
150 jne L(find_diff)
151L(13bytes):
152 movl -13(%esi), %eax
153 movl -13(%edx), %ecx
154 cmpl %ecx, %eax
155 jne L(find_diff)
156L(9bytes):
157 movl -9(%esi), %eax
158 movl -9(%edx), %ecx
159 cmpl %ecx, %eax
160 jne L(find_diff)
161L(5bytes):
162 movl -5(%esi), %eax
163 movl -5(%edx), %ecx
164 cmpl %ecx, %eax
165 jne L(find_diff)
166L(1bytes):
167 movzbl -1(%esi), %eax
168 cmpb -1(%edx), %al
169 jne L(set)
170 popl %esi
171 cfi_adjust_cfa_offset (-4)
172 cfi_restore (esi)
173 xorl %eax, %eax
174 RETURN
175
176 cfi_adjust_cfa_offset (8)
177 cfi_rel_offset (esi, 0)
178 cfi_rel_offset (ebx, 4)
179L(30bytes):
180 movl -30(%esi), %eax
181 movl -30(%edx), %ecx
182 cmpl %ecx, %eax
183 jne L(find_diff)
184L(26bytes):
185 movl -26(%esi), %eax
186 movl -26(%edx), %ecx
187 cmpl %ecx, %eax
188 jne L(find_diff)
189L(22bytes):
190 movl -22(%esi), %eax
191 movl -22(%edx), %ecx
192 cmpl %ecx, %eax
193 jne L(find_diff)
194L(18bytes):
195 movl -18(%esi), %eax
196 movl -18(%edx), %ecx
197 cmpl %ecx, %eax
198 jne L(find_diff)
199L(14bytes):
200 movl -14(%esi), %eax
201 movl -14(%edx), %ecx
202 cmpl %ecx, %eax
203 jne L(find_diff)
204L(10bytes):
205 movl -10(%esi), %eax
206 movl -10(%edx), %ecx
207 cmpl %ecx, %eax
208 jne L(find_diff)
209L(6bytes):
210 movl -6(%esi), %eax
211 movl -6(%edx), %ecx
212 cmpl %ecx, %eax
213 jne L(find_diff)
214L(2bytes):
215 movzwl -2(%esi), %eax
216 movzwl -2(%edx), %ecx
217 cmpb %cl, %al
218 jne L(set)
219 cmpl %ecx, %eax
220 jne L(set)
221 popl %esi
222 cfi_adjust_cfa_offset (-4)
223 cfi_restore (esi)
224 xorl %eax, %eax
225 RETURN
226
227 cfi_adjust_cfa_offset (8)
228 cfi_rel_offset (esi, 0)
229 cfi_rel_offset (ebx, 4)
230L(31bytes):
231 movl -31(%esi), %eax
232 movl -31(%edx), %ecx
233 cmpl %ecx, %eax
234 jne L(find_diff)
235L(27bytes):
236 movl -27(%esi), %eax
237 movl -27(%edx), %ecx
238 cmpl %ecx, %eax
239 jne L(find_diff)
240L(23bytes):
241 movl -23(%esi), %eax
242 movl -23(%edx), %ecx
243 cmpl %ecx, %eax
244 jne L(find_diff)
245L(19bytes):
246 movl -19(%esi), %eax
247 movl -19(%edx), %ecx
248 cmpl %ecx, %eax
249 jne L(find_diff)
250L(15bytes):
251 movl -15(%esi), %eax
252 movl -15(%edx), %ecx
253 cmpl %ecx, %eax
254 jne L(find_diff)
255L(11bytes):
256 movl -11(%esi), %eax
257 movl -11(%edx), %ecx
258 cmpl %ecx, %eax
259 jne L(find_diff)
260L(7bytes):
261 movl -7(%esi), %eax
262 movl -7(%edx), %ecx
263 cmpl %ecx, %eax
264 jne L(find_diff)
265L(3bytes):
266 movzwl -3(%esi), %eax
267 movzwl -3(%edx), %ecx
268 cmpb %cl, %al
269 jne L(set)
270 cmpl %ecx, %eax
271 jne L(set)
272 movzbl -1(%esi), %eax
273 cmpb -1(%edx), %al
274 jne L(set)
275 popl %esi
276 cfi_adjust_cfa_offset (-4)
277 cfi_restore (esi)
278 xorl %eax, %eax
279 RETURN
280
281 cfi_adjust_cfa_offset (8)
282 cfi_rel_offset (esi, 0)
283 cfi_rel_offset (ebx, 4)
284 ALIGN (4)
285/* ECX >= 32. */
286L(32bytesormore):
287 subl $32, %ecx
288
289 movl (%esi), %eax
290 cmpl (%edx), %eax
291 jne L(load_ecx)
292
293 movl 4(%esi), %eax
294 cmpl 4(%edx), %eax
295 jne L(load_ecx_4)
296
297 movl 8(%esi), %eax
298 cmpl 8(%edx), %eax
299 jne L(load_ecx_8)
300
301 movl 12(%esi), %eax
302 cmpl 12(%edx), %eax
303 jne L(load_ecx_12)
304
305 movl 16(%esi), %eax
306 cmpl 16(%edx), %eax
307 jne L(load_ecx_16)
308
309 movl 20(%esi), %eax
310 cmpl 20(%edx), %eax
311 jne L(load_ecx_20)
312
313 movl 24(%esi), %eax
314 cmpl 24(%edx), %eax
315 jne L(load_ecx_24)
316
317 movl 28(%esi), %eax
318 cmpl 28(%edx), %eax
319 jne L(load_ecx_28)
320
321 addl $32, %esi
322 addl $32, %edx
323 cmpl $32, %ecx
324 jge L(32bytesormore)
325
326 LOAD_JUMP_TABLE_ENTRY (L(table_32bytes), %ecx)
327 addl %ecx, %edx
328 addl %ecx, %esi
329 jmp *%ebx
330
331L(load_ecx_28):
332 addl $0x4, %edx
333L(load_ecx_24):
334 addl $0x4, %edx
335L(load_ecx_20):
336 addl $0x4, %edx
337L(load_ecx_16):
338 addl $0x4, %edx
339L(load_ecx_12):
340 addl $0x4, %edx
341L(load_ecx_8):
342 addl $0x4, %edx
343L(load_ecx_4):
344 addl $0x4, %edx
345L(load_ecx):
346 movl (%edx), %ecx
347
348L(find_diff):
349 cmpb %cl, %al
350 jne L(set)
351 cmpb %ch, %ah
352 jne L(set)
353 shrl $16,%eax
354 shrl $16,%ecx
355 cmpb %cl, %al
356 jne L(set)
357 /* We get there only if we already know there is a
358 difference. */
359 cmpl %ecx, %eax
360L(set):
361 sbbl %eax, %eax
362 sbbl $-1, %eax
363 popl %esi
364 cfi_adjust_cfa_offset (-4)
365 cfi_restore (esi)
366 RETURN
367END (memcmp)
368
369 .section .rodata
370 ALIGN (2)
371L(table_32bytes) :
372 .long L(0bytes) - L(table_32bytes)
373 .long L(1bytes) - L(table_32bytes)
374 .long L(2bytes) - L(table_32bytes)
375 .long L(3bytes) - L(table_32bytes)
376 .long L(4bytes) - L(table_32bytes)
377 .long L(5bytes) - L(table_32bytes)
378 .long L(6bytes) - L(table_32bytes)
379 .long L(7bytes) - L(table_32bytes)
380 .long L(8bytes) - L(table_32bytes)
381 .long L(9bytes) - L(table_32bytes)
382 .long L(10bytes) - L(table_32bytes)
383 .long L(11bytes) - L(table_32bytes)
384 .long L(12bytes) - L(table_32bytes)
385 .long L(13bytes) - L(table_32bytes)
386 .long L(14bytes) - L(table_32bytes)
387 .long L(15bytes) - L(table_32bytes)
388 .long L(16bytes) - L(table_32bytes)
389 .long L(17bytes) - L(table_32bytes)
390 .long L(18bytes) - L(table_32bytes)
391 .long L(19bytes) - L(table_32bytes)
392 .long L(20bytes) - L(table_32bytes)
393 .long L(21bytes) - L(table_32bytes)
394 .long L(22bytes) - L(table_32bytes)
395 .long L(23bytes) - L(table_32bytes)
396 .long L(24bytes) - L(table_32bytes)
397 .long L(25bytes) - L(table_32bytes)
398 .long L(26bytes) - L(table_32bytes)
399 .long L(27bytes) - L(table_32bytes)
400 .long L(28bytes) - L(table_32bytes)
401 .long L(29bytes) - L(table_32bytes)
402 .long L(30bytes) - L(table_32bytes)
403 .long L(31bytes) - L(table_32bytes)
404
405
406#undef bcmp
407weak_alias (memcmp, bcmp)
408#undef __memcmpeq
409strong_alias (memcmp, __memcmpeq)
410libc_hidden_builtin_def (memcmp)
411libc_hidden_def (__memcmpeq)
412

source code of glibc/sysdeps/i386/i686/memcmp.S