(CFLAGS-tst-align.c): Add -mpreferred-stack-boundary=4.
[glibc.git] / sysdeps / i386 / i686 / memcmp.S
blobef57acdee8ceadc498b0fd22351f7ef34e57deb2
1 /* Compare two memory blocks for differences in the first COUNT bytes.
2    Copyright (C) 2004 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; ENTER
30 #define RETURN          popl %ebx; LEAVE; ret
32 /* Load an entry in a jump table into EBX.  TABLE is a jump table
33    with relative offsets.  INDEX is a register contains the index
34    into the jump table.  */
35 #define LOAD_JUMP_TABLE_ENTRY(TABLE, INDEX) \
36   /* We first load PC into EBX.  */                                           \
37   call  __i686.get_pc_thunk.bx;                                               \
38   /* Get the address of the jump table.  */                                   \
39   addl  $(TABLE - .), %ebx;                                                   \
40   /* Get the entry and convert the relative offset to the                     \
41      absolute address.  */                                                    \
42   addl  (%ebx,INDEX,4), %ebx
44 #ifdef HAVE_HIDDEN
45         .section        .gnu.linkonce.t.__i686.get_pc_thunk.bx,"ax",@progbits
46         .globl  __i686.get_pc_thunk.bx
47         .hidden __i686.get_pc_thunk.bx
48 #else
49         .text
50 #endif
51         ALIGN (4)
52         .type   __i686.get_pc_thunk.bx,@function
53 __i686.get_pc_thunk.bx:
54         movl    (%esp), %ebx
55         ret
57         .text
58         ALIGN (4)
59 ENTRY (BP_SYM (memcmp))
60         ENTRANCE
62         movl    BLK1(%esp), %eax
63         movl    BLK2(%esp), %edx
64         movl    LEN(%esp), %ecx
66         cmpl    $1, %ecx
67         jne     L(not_1)
68         movzbl  (%eax), %ecx            /* LEN == 1  */
69         cmpb    (%edx), %cl
70         jne     L(neq)
71 L(bye):
72         xorl    %eax, %eax
73         RETURN
75 L(neq):
76         sbbl    %eax, %eax
77         sbbl    $-1, %eax
78         RETURN
80 L(not_1):
81         jl      L(bye)                  /* LEN == 0  */
83         pushl   %esi
84         movl    %eax, %esi
85         cmpl    $32, %ecx;
86         jge     L(32bytesormore)        /* LEN => 32  */
88         LOAD_JUMP_TABLE_ENTRY (L(table_32bytes), %ecx)
89         addl    %ecx, %edx
90         addl    %ecx, %esi
91         jmp     *%ebx
93         ALIGN (4)
94 L(28bytes):
95         movl    -28(%esi), %eax
96         movl    -28(%edx), %ecx
97         cmpl    %ecx, %eax
98         jne     L(find_diff)
99 L(24bytes):
100         movl    -24(%esi), %eax
101         movl    -24(%edx), %ecx
102         cmpl    %ecx, %eax
103         jne     L(find_diff)
104 L(20bytes):
105         movl    -20(%esi), %eax
106         movl    -20(%edx), %ecx
107         cmpl    %ecx, %eax
108         jne     L(find_diff)
109 L(16bytes):
110         movl    -16(%esi), %eax
111         movl    -16(%edx), %ecx
112         cmpl    %ecx, %eax
113         jne     L(find_diff)
114 L(12bytes):
115         movl    -12(%esi), %eax
116         movl    -12(%edx), %ecx
117         cmpl    %ecx, %eax
118         jne     L(find_diff)
119 L(8bytes):
120         movl    -8(%esi), %eax
121         movl    -8(%edx), %ecx
122         cmpl    %ecx, %eax
123         jne     L(find_diff)
124 L(4bytes):
125         movl    -4(%esi), %eax
126         movl    -4(%edx), %ecx
127         cmpl    %ecx, %eax
128         jne     L(find_diff)
129 L(0bytes):
130         popl    %esi
131         xorl    %eax, %eax
132         RETURN
134 L(29bytes):
135         movl    -29(%esi), %eax
136         movl    -29(%edx), %ecx
137         cmpl    %ecx, %eax
138         jne     L(find_diff)
139 L(25bytes):
140         movl    -25(%esi), %eax
141         movl    -25(%edx), %ecx
142         cmpl    %ecx, %eax
143         jne     L(find_diff)
144 L(21bytes):
145         movl    -21(%esi), %eax
146         movl    -21(%edx), %ecx
147         cmpl    %ecx, %eax
148         jne     L(find_diff)
149 L(17bytes):
150         movl    -17(%esi), %eax
151         movl    -17(%edx), %ecx
152         cmpl    %ecx, %eax
153         jne     L(find_diff)
154 L(13bytes):
155         movl    -13(%esi), %eax
156         movl    -13(%edx), %ecx
157         cmpl    %ecx, %eax
158         jne     L(find_diff)
159 L(9bytes):
160         movl    -9(%esi), %eax
161         movl    -9(%edx), %ecx
162         cmpl    %ecx, %eax
163         jne     L(find_diff)
164 L(5bytes):
165         movl    -5(%esi), %eax
166         movl    -5(%edx), %ecx
167         cmpl    %ecx, %eax
168         jne     L(find_diff)
169 L(1bytes):
170         movzbl  -1(%esi), %eax
171         cmpb    -1(%edx), %al
172         jne     L(set)
173         popl    %esi
174         xorl    %eax, %eax
175         RETURN
177 L(30bytes):
178         movl    -30(%esi), %eax
179         movl    -30(%edx), %ecx
180         cmpl    %ecx, %eax
181         jne     L(find_diff)
182 L(26bytes):
183         movl    -26(%esi), %eax
184         movl    -26(%edx), %ecx
185         cmpl    %ecx, %eax
186         jne     L(find_diff)
187 L(22bytes):
188         movl    -22(%esi), %eax
189         movl    -22(%edx), %ecx
190         cmpl    %ecx, %eax
191         jne     L(find_diff)
192 L(18bytes):
193         movl    -18(%esi), %eax
194         movl    -18(%edx), %ecx
195         cmpl    %ecx, %eax
196         jne     L(find_diff)
197 L(14bytes):
198         movl    -14(%esi), %eax
199         movl    -14(%edx), %ecx
200         cmpl    %ecx, %eax
201         jne     L(find_diff)
202 L(10bytes):
203         movl    -10(%esi), %eax
204         movl    -10(%edx), %ecx
205         cmpl    %ecx, %eax
206         jne     L(find_diff)
207 L(6bytes):
208         movl    -6(%esi), %eax
209         movl    -6(%edx), %ecx
210         cmpl    %ecx, %eax
211         jne     L(find_diff)
212 L(2bytes):
213         movzwl  -2(%esi), %eax
214         movzwl  -2(%edx), %ecx
215         cmpb    %cl, %al
216         jne     L(set)
217         cmpl    %ecx, %eax
218         jne     L(set)
219         popl    %esi
220         xorl    %eax, %eax
221         RETURN
223 L(31bytes):
224         movl    -31(%esi), %eax
225         movl    -31(%edx), %ecx
226         cmpl    %ecx, %eax
227         jne     L(find_diff)
228 L(27bytes):
229         movl    -27(%esi), %eax
230         movl    -27(%edx), %ecx
231         cmpl    %ecx, %eax
232         jne     L(find_diff)
233 L(23bytes):
234         movl    -23(%esi), %eax
235         movl    -23(%edx), %ecx
236         cmpl    %ecx, %eax
237         jne     L(find_diff)
238 L(19bytes):
239         movl    -19(%esi), %eax
240         movl    -19(%edx), %ecx
241         cmpl    %ecx, %eax
242         jne     L(find_diff)
243 L(15bytes):
244         movl    -15(%esi), %eax
245         movl    -15(%edx), %ecx
246         cmpl    %ecx, %eax
247         jne     L(find_diff)
248 L(11bytes):
249         movl    -11(%esi), %eax
250         movl    -11(%edx), %ecx
251         cmpl    %ecx, %eax
252         jne     L(find_diff)
253 L(7bytes):
254         movl    -7(%esi), %eax
255         movl    -7(%edx), %ecx
256         cmpl    %ecx, %eax
257         jne     L(find_diff)
258 L(3bytes):
259         movzwl  -3(%esi), %eax
260         movzwl  -3(%edx), %ecx
261         cmpb    %cl, %al
262         jne     L(set)
263         cmpl    %ecx, %eax
264         jne     L(set)
265         movzbl  -1(%esi), %eax
266         cmpb    -1(%edx), %al
267         jne     L(set)
268         popl    %esi
269         xorl    %eax, %eax
270         RETURN
272         ALIGN (4)
273 /* ECX >= 32.  */
274 L(32bytesormore):
275         subl    $32, %ecx
277         movl    (%esi), %eax
278         cmpl    (%edx), %eax
279         jne     L(load_ecx)
281         movl    4(%esi), %eax
282         cmpl    4(%edx), %eax
283         jne     L(load_ecx_4)
285         movl    8(%esi), %eax
286         cmpl    8(%edx), %eax
287         jne     L(load_ecx_8)
289         movl    12(%esi), %eax
290         cmpl    12(%edx), %eax
291         jne     L(load_ecx_12)
293         movl    16(%esi), %eax
294         cmpl    16(%edx), %eax
295         jne     L(load_ecx_16)
297         movl    20(%esi), %eax
298         cmpl    20(%edx), %eax
299         jne     L(load_ecx_20)
301         movl    24(%esi), %eax
302         cmpl    24(%edx), %eax
303         jne     L(load_ecx_24)
305         movl    28(%esi), %eax
306         cmpl    28(%edx), %eax
307         jne     L(load_ecx_28)
309         addl    $32, %esi
310         addl    $32, %edx
311         cmpl    $32, %ecx
312         jge     L(32bytesormore)
314         LOAD_JUMP_TABLE_ENTRY (L(table_32bytes), %ecx)
315         addl    %ecx, %edx
316         addl    %ecx, %esi
317         jmp     *%ebx
319 L(load_ecx_28):
320         addl    $0x4, %edx
321 L(load_ecx_24):
322         addl    $0x4, %edx
323 L(load_ecx_20):
324         addl    $0x4, %edx
325 L(load_ecx_16):
326         addl    $0x4, %edx
327 L(load_ecx_12):
328         addl    $0x4, %edx
329 L(load_ecx_8):
330         addl    $0x4, %edx
331 L(load_ecx_4):
332         addl    $0x4, %edx
333 L(load_ecx):
334         movl    (%edx), %ecx
336 L(find_diff):
337         cmpb    %cl, %al
338         jne     L(set)
339         cmpb    %ch, %ah
340         jne     L(set)
341         shrl    $16,%eax
342         shrl    $16,%ecx
343         cmpb    %cl, %al
344         jne     L(set)
345         /* We get there only if we already know there is a
346            difference.  */
347         cmpl    %ecx, %eax
348 L(set):
349         sbbl    %eax, %eax
350         sbbl    $-1, %eax
351         popl    %esi
352         RETURN
354         .section        .rodata
355         ALIGN (2)
356 L(table_32bytes) :
357         .long   L(0bytes) - . + 0x0
358         .long   L(1bytes) - . + 0x4
359         .long   L(2bytes) - . + 0x8
360         .long   L(3bytes) - . + 0xc
361         .long   L(4bytes) - . + 0x10
362         .long   L(5bytes) - . + 0x14
363         .long   L(6bytes) - . + 0x18
364         .long   L(7bytes) - . + 0x1c
365         .long   L(8bytes) - . + 0x20
366         .long   L(9bytes) - . + 0x24
367         .long   L(10bytes) - . + 0x28
368         .long   L(11bytes) - . + 0x2c
369         .long   L(12bytes) - . + 0x30
370         .long   L(13bytes) - . + 0x34
371         .long   L(14bytes) - . + 0x38
372         .long   L(15bytes) - . + 0x3c
373         .long   L(16bytes) - . + 0x40
374         .long   L(17bytes) - . + 0x44
375         .long   L(18bytes) - . + 0x48
376         .long   L(19bytes) - . + 0x4c
377         .long   L(20bytes) - . + 0x50
378         .long   L(21bytes) - . + 0x54
379         .long   L(22bytes) - . + 0x58
380         .long   L(23bytes) - . + 0x5c
381         .long   L(24bytes) - . + 0x60
382         .long   L(25bytes) - . + 0x64
383         .long   L(26bytes) - . + 0x68
384         .long   L(27bytes) - . + 0x6c
385         .long   L(28bytes) - . + 0x70
386         .long   L(29bytes) - . + 0x74
387         .long   L(30bytes) - . + 0x78
388         .long   L(31bytes) - . + 0x7c
390 END (BP_SYM (memcmp))
392 #undef bcmp
393 weak_alias (BP_SYM (memcmp), BP_SYM (bcmp))
394 libc_hidden_builtin_def (BP_SYM (memcmp))