Update contrib.texi
[glibc.git] / sysdeps / i386 / memcmp.S
blob88a9a9e416bbd5de5b78cb250d5f4de4fd1801e3
1 /* Compare two memory blocks for differences in the first COUNT bytes.
2    Copyright (C) 1995-2014 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, see
17    <http://www.gnu.org/licenses/>.  */
19 #include <sysdep.h>
20 #include "asm-syntax.h"
22 #define PARMS   4+4     /* space for 1 saved reg */
23 #define BLK1    PARMS
24 #define BLK2    BLK1+4
25 #define LEN     BLK2+4
27         .text
28 ENTRY (memcmp)
30         pushl %esi              /* Save callee-safe registers.  */
31         cfi_adjust_cfa_offset (4)
32         movl %edi, %edx         /* Note that %edx is not used and can
33                                    so be used to save %edi.  It's faster.  */
34         cfi_register (edi, edx)
36         movl BLK1(%esp), %esi
37         cfi_rel_offset (esi, 0)
38         movl BLK2(%esp), %edi
39         movl LEN(%esp), %ecx
41         cld                     /* Set direction of comparison.  */
43         xorl %eax, %eax         /* Default result.  */
45         repe                    /* Compare at most %ecx bytes.  */
46         cmpsb
47         jz L(1)                 /* If even last byte was equal we return 0.  */
49         /* The memory blocks are not equal.  So result of the last
50            subtraction is present in the carry flag.  It is set when
51            the byte in block #2 is bigger.  In this case we have to
52            return -1 (=0xffffffff), else 1.  */
53         sbbl %eax, %eax         /* This is tricky.  %eax == 0 and carry is set
54                                    or not depending on last subtraction.  */
56         /* At this point %eax == 0, if the byte of block #1 was bigger, and
57            0xffffffff if the last byte of block #2 was bigger.  The latter
58            case is already correct but the former needs a little adjustment.
59            Note that the following operation does not change 0xffffffff.  */
60         orb $1, %al             /* Change 0 to 1.  */
62 L(1):   popl %esi               /* Restore registers.  */
63         cfi_adjust_cfa_offset (-4)
64         cfi_restore (esi)
65         movl %edx, %edi
66         cfi_restore (edi)
68         ret
69 END (memcmp)
71 #undef bcmp
72 weak_alias (memcmp, bcmp)
73 libc_hidden_builtin_def (memcmp)