.
[glibc.git] / sysdeps / i386 / i686 / memcmp.S
blob4bd5394bec11b2dd611b33232cffd8ea75841ca2
1 /* Compare two memory blocks for differences in the first COUNT bytes.
2    Copyright (C) 2004, 2005 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 #ifdef HAVE_HIDDEN
48         .section        .gnu.linkonce.t.__i686.get_pc_thunk.bx,"ax",@progbits
49         .globl  __i686.get_pc_thunk.bx
50         .hidden __i686.get_pc_thunk.bx
51 #else
52         .text
53 #endif
54         ALIGN (4)
55         .type   __i686.get_pc_thunk.bx,@function
56 __i686.get_pc_thunk.bx:
57         movl    (%esp), %ebx
58         ret
60         .text
61         ALIGN (4)
62 ENTRY (BP_SYM (memcmp))
63         ENTRANCE
65         movl    BLK1(%esp), %eax
66         movl    BLK2(%esp), %edx
67         movl    LEN(%esp), %ecx
69         cmpl    $1, %ecx
70         jne     L(not_1)
71         movzbl  (%eax), %ecx            /* LEN == 1  */
72         cmpb    (%edx), %cl
73         jne     L(neq)
74 L(bye):
75         xorl    %eax, %eax
76         RETURN
78 L(neq):
79         sbbl    %eax, %eax
80         sbbl    $-1, %eax
81         RETURN
83         cfi_adjust_cfa_offset (4)
84         cfi_rel_offset (ebx, 0)
85 L(not_1):
86         jl      L(bye)                  /* LEN == 0  */
88         pushl   %esi
89         cfi_adjust_cfa_offset (4)
90         movl    %eax, %esi
91         cfi_rel_offset (esi, 0)
92         cmpl    $32, %ecx;
93         jge     L(32bytesormore)        /* LEN => 32  */
95         LOAD_JUMP_TABLE_ENTRY (L(table_32bytes), %ecx)
96         addl    %ecx, %edx
97         addl    %ecx, %esi
98         jmp     *%ebx
100         ALIGN (4)
101 L(28bytes):
102         movl    -28(%esi), %eax
103         movl    -28(%edx), %ecx
104         cmpl    %ecx, %eax
105         jne     L(find_diff)
106 L(24bytes):
107         movl    -24(%esi), %eax
108         movl    -24(%edx), %ecx
109         cmpl    %ecx, %eax
110         jne     L(find_diff)
111 L(20bytes):
112         movl    -20(%esi), %eax
113         movl    -20(%edx), %ecx
114         cmpl    %ecx, %eax
115         jne     L(find_diff)
116 L(16bytes):
117         movl    -16(%esi), %eax
118         movl    -16(%edx), %ecx
119         cmpl    %ecx, %eax
120         jne     L(find_diff)
121 L(12bytes):
122         movl    -12(%esi), %eax
123         movl    -12(%edx), %ecx
124         cmpl    %ecx, %eax
125         jne     L(find_diff)
126 L(8bytes):
127         movl    -8(%esi), %eax
128         movl    -8(%edx), %ecx
129         cmpl    %ecx, %eax
130         jne     L(find_diff)
131 L(4bytes):
132         movl    -4(%esi), %eax
133         movl    -4(%edx), %ecx
134         cmpl    %ecx, %eax
135         jne     L(find_diff)
136 L(0bytes):
137         popl    %esi
138         cfi_adjust_cfa_offset (-4)
139         cfi_restore (esi)
140         xorl    %eax, %eax
141         RETURN
143         cfi_adjust_cfa_offset (8)
144         cfi_rel_offset (esi, 0)
145         cfi_rel_offset (ebx, 4)
146 L(29bytes):
147         movl    -29(%esi), %eax
148         movl    -29(%edx), %ecx
149         cmpl    %ecx, %eax
150         jne     L(find_diff)
151 L(25bytes):
152         movl    -25(%esi), %eax
153         movl    -25(%edx), %ecx
154         cmpl    %ecx, %eax
155         jne     L(find_diff)
156 L(21bytes):
157         movl    -21(%esi), %eax
158         movl    -21(%edx), %ecx
159         cmpl    %ecx, %eax
160         jne     L(find_diff)
161 L(17bytes):
162         movl    -17(%esi), %eax
163         movl    -17(%edx), %ecx
164         cmpl    %ecx, %eax
165         jne     L(find_diff)
166 L(13bytes):
167         movl    -13(%esi), %eax
168         movl    -13(%edx), %ecx
169         cmpl    %ecx, %eax
170         jne     L(find_diff)
171 L(9bytes):
172         movl    -9(%esi), %eax
173         movl    -9(%edx), %ecx
174         cmpl    %ecx, %eax
175         jne     L(find_diff)
176 L(5bytes):
177         movl    -5(%esi), %eax
178         movl    -5(%edx), %ecx
179         cmpl    %ecx, %eax
180         jne     L(find_diff)
181 L(1bytes):
182         movzbl  -1(%esi), %eax
183         cmpb    -1(%edx), %al
184         jne     L(set)
185         popl    %esi
186         cfi_adjust_cfa_offset (-4)
187         cfi_restore (esi)
188         xorl    %eax, %eax
189         RETURN
191         cfi_adjust_cfa_offset (8)
192         cfi_rel_offset (esi, 0)
193         cfi_rel_offset (ebx, 4)
194 L(30bytes):
195         movl    -30(%esi), %eax
196         movl    -30(%edx), %ecx
197         cmpl    %ecx, %eax
198         jne     L(find_diff)
199 L(26bytes):
200         movl    -26(%esi), %eax
201         movl    -26(%edx), %ecx
202         cmpl    %ecx, %eax
203         jne     L(find_diff)
204 L(22bytes):
205         movl    -22(%esi), %eax
206         movl    -22(%edx), %ecx
207         cmpl    %ecx, %eax
208         jne     L(find_diff)
209 L(18bytes):
210         movl    -18(%esi), %eax
211         movl    -18(%edx), %ecx
212         cmpl    %ecx, %eax
213         jne     L(find_diff)
214 L(14bytes):
215         movl    -14(%esi), %eax
216         movl    -14(%edx), %ecx
217         cmpl    %ecx, %eax
218         jne     L(find_diff)
219 L(10bytes):
220         movl    -10(%esi), %eax
221         movl    -10(%edx), %ecx
222         cmpl    %ecx, %eax
223         jne     L(find_diff)
224 L(6bytes):
225         movl    -6(%esi), %eax
226         movl    -6(%edx), %ecx
227         cmpl    %ecx, %eax
228         jne     L(find_diff)
229 L(2bytes):
230         movzwl  -2(%esi), %eax
231         movzwl  -2(%edx), %ecx
232         cmpb    %cl, %al
233         jne     L(set)
234         cmpl    %ecx, %eax
235         jne     L(set)
236         popl    %esi
237         cfi_adjust_cfa_offset (-4)
238         cfi_restore (esi)
239         xorl    %eax, %eax
240         RETURN
242         cfi_adjust_cfa_offset (8)
243         cfi_rel_offset (esi, 0)
244         cfi_rel_offset (ebx, 4)
245 L(31bytes):
246         movl    -31(%esi), %eax
247         movl    -31(%edx), %ecx
248         cmpl    %ecx, %eax
249         jne     L(find_diff)
250 L(27bytes):
251         movl    -27(%esi), %eax
252         movl    -27(%edx), %ecx
253         cmpl    %ecx, %eax
254         jne     L(find_diff)
255 L(23bytes):
256         movl    -23(%esi), %eax
257         movl    -23(%edx), %ecx
258         cmpl    %ecx, %eax
259         jne     L(find_diff)
260 L(19bytes):
261         movl    -19(%esi), %eax
262         movl    -19(%edx), %ecx
263         cmpl    %ecx, %eax
264         jne     L(find_diff)
265 L(15bytes):
266         movl    -15(%esi), %eax
267         movl    -15(%edx), %ecx
268         cmpl    %ecx, %eax
269         jne     L(find_diff)
270 L(11bytes):
271         movl    -11(%esi), %eax
272         movl    -11(%edx), %ecx
273         cmpl    %ecx, %eax
274         jne     L(find_diff)
275 L(7bytes):
276         movl    -7(%esi), %eax
277         movl    -7(%edx), %ecx
278         cmpl    %ecx, %eax
279         jne     L(find_diff)
280 L(3bytes):
281         movzwl  -3(%esi), %eax
282         movzwl  -3(%edx), %ecx
283         cmpb    %cl, %al
284         jne     L(set)
285         cmpl    %ecx, %eax
286         jne     L(set)
287         movzbl  -1(%esi), %eax
288         cmpb    -1(%edx), %al
289         jne     L(set)
290         popl    %esi
291         cfi_adjust_cfa_offset (-4)
292         cfi_restore (esi)
293         xorl    %eax, %eax
294         RETURN
296         cfi_adjust_cfa_offset (8)
297         cfi_rel_offset (esi, 0)
298         cfi_rel_offset (ebx, 4)
299         ALIGN (4)
300 /* ECX >= 32.  */
301 L(32bytesormore):
302         subl    $32, %ecx
304         movl    (%esi), %eax
305         cmpl    (%edx), %eax
306         jne     L(load_ecx)
308         movl    4(%esi), %eax
309         cmpl    4(%edx), %eax
310         jne     L(load_ecx_4)
312         movl    8(%esi), %eax
313         cmpl    8(%edx), %eax
314         jne     L(load_ecx_8)
316         movl    12(%esi), %eax
317         cmpl    12(%edx), %eax
318         jne     L(load_ecx_12)
320         movl    16(%esi), %eax
321         cmpl    16(%edx), %eax
322         jne     L(load_ecx_16)
324         movl    20(%esi), %eax
325         cmpl    20(%edx), %eax
326         jne     L(load_ecx_20)
328         movl    24(%esi), %eax
329         cmpl    24(%edx), %eax
330         jne     L(load_ecx_24)
332         movl    28(%esi), %eax
333         cmpl    28(%edx), %eax
334         jne     L(load_ecx_28)
336         addl    $32, %esi
337         addl    $32, %edx
338         cmpl    $32, %ecx
339         jge     L(32bytesormore)
341         LOAD_JUMP_TABLE_ENTRY (L(table_32bytes), %ecx)
342         addl    %ecx, %edx
343         addl    %ecx, %esi
344         jmp     *%ebx
346 L(load_ecx_28):
347         addl    $0x4, %edx
348 L(load_ecx_24):
349         addl    $0x4, %edx
350 L(load_ecx_20):
351         addl    $0x4, %edx
352 L(load_ecx_16):
353         addl    $0x4, %edx
354 L(load_ecx_12):
355         addl    $0x4, %edx
356 L(load_ecx_8):
357         addl    $0x4, %edx
358 L(load_ecx_4):
359         addl    $0x4, %edx
360 L(load_ecx):
361         movl    (%edx), %ecx
363 L(find_diff):
364         cmpb    %cl, %al
365         jne     L(set)
366         cmpb    %ch, %ah
367         jne     L(set)
368         shrl    $16,%eax
369         shrl    $16,%ecx
370         cmpb    %cl, %al
371         jne     L(set)
372         /* We get there only if we already know there is a
373            difference.  */
374         cmpl    %ecx, %eax
375 L(set):
376         sbbl    %eax, %eax
377         sbbl    $-1, %eax
378         popl    %esi
379         cfi_adjust_cfa_offset (-4)
380         cfi_restore (esi)
381         RETURN
382 END (BP_SYM (memcmp))
384         .section        .rodata
385         ALIGN (2)
386 L(table_32bytes) :
387         .long   L(0bytes) - . + 0x0
388         .long   L(1bytes) - . + 0x4
389         .long   L(2bytes) - . + 0x8
390         .long   L(3bytes) - . + 0xc
391         .long   L(4bytes) - . + 0x10
392         .long   L(5bytes) - . + 0x14
393         .long   L(6bytes) - . + 0x18
394         .long   L(7bytes) - . + 0x1c
395         .long   L(8bytes) - . + 0x20
396         .long   L(9bytes) - . + 0x24
397         .long   L(10bytes) - . + 0x28
398         .long   L(11bytes) - . + 0x2c
399         .long   L(12bytes) - . + 0x30
400         .long   L(13bytes) - . + 0x34
401         .long   L(14bytes) - . + 0x38
402         .long   L(15bytes) - . + 0x3c
403         .long   L(16bytes) - . + 0x40
404         .long   L(17bytes) - . + 0x44
405         .long   L(18bytes) - . + 0x48
406         .long   L(19bytes) - . + 0x4c
407         .long   L(20bytes) - . + 0x50
408         .long   L(21bytes) - . + 0x54
409         .long   L(22bytes) - . + 0x58
410         .long   L(23bytes) - . + 0x5c
411         .long   L(24bytes) - . + 0x60
412         .long   L(25bytes) - . + 0x64
413         .long   L(26bytes) - . + 0x68
414         .long   L(27bytes) - . + 0x6c
415         .long   L(28bytes) - . + 0x70
416         .long   L(29bytes) - . + 0x74
417         .long   L(30bytes) - . + 0x78
418         .long   L(31bytes) - . + 0x7c
421 #undef bcmp
422 weak_alias (BP_SYM (memcmp), BP_SYM (bcmp))
423 libc_hidden_builtin_def (BP_SYM (memcmp))