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