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