linux: Add FSCONFIG_CMD_CREATE_EXCL from Linux 6.6 to sys/mount.h
[glibc.git] / sysdeps / i386 / strlen.S
blob5d093d88b3adf76552088ce33b28af4cac0cad92
1 /* strlen(str) -- determine the length of the string STR.
2    Optimized for Intel 80x86, x>=4.
3    Copyright (C) 1991-2023 Free Software Foundation, Inc.
4    This file is part of the GNU C Library.
6    The GNU C Library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Lesser General Public
8    License as published by the Free Software Foundation; either
9    version 2.1 of the License, or (at your option) any later version.
11    The GNU C Library is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Lesser General Public License for more details.
16    You should have received a copy of the GNU Lesser General Public
17    License along with the GNU C Library; if not, see
18    <https://www.gnu.org/licenses/>.  */
20 #include <sysdep.h>
21 #include "asm-syntax.h"
23 #define PARMS   4               /* no space for saved regs */
24 #define STR     PARMS
26         .text
27 ENTRY (strlen)
29         movl STR(%esp), %ecx
30         movl %ecx, %eax         /* duplicate it */
32         andl $3, %ecx           /* mask alignment bits */
33         jz L(1)                 /* aligned => start loop */
34         cmpb %ch, (%eax)        /* is byte NUL? */
35         je L(2)                 /* yes => return */
36         incl %eax               /* increment pointer */
38         xorl $3, %ecx           /* was alignment = 3? */
39         jz L(1)                 /* yes => now it is aligned and start loop */
40         cmpb %ch, (%eax)        /* is byte NUL? */
41         je L(2)                 /* yes => return */
42         addl $1, %eax           /* increment pointer */
44         subl $1, %ecx           /* was alignment = 2? */
45         jz L(1)                 /* yes => now it is aligned and start loop */
46         cmpb %ch, (%eax)        /* is byte NUL? */
47         je L(2)                 /* yes => return */
49 /* Don't change the above `addl $1,%eax' and `subl $1, %ecx' into `incl %eax'
50    and `decl %ecx' resp.  The additional two byte per instruction make the
51    label 4 to be aligned on a 16 byte boundary with nops.
53    The following `sub $15, %eax' is part of this trick, too.  Together with
54    the next instruction (`addl $16, %eax') it is in fact a `incl %eax', just
55    as expected from the algorithm.  But doing so has the advantage that
56    no jump to label 1 is necessary and so the pipeline is not flushed.  */
58         subl $15, %eax          /* effectively +1 */
61 L(4):   addl $16, %eax          /* adjust pointer for full loop */
63 L(1):   movl (%eax), %ecx       /* get word (= 4 bytes) in question */
64         movl $0xfefefeff, %edx  /* magic value */
65         addl %ecx, %edx         /* add the magic value to the word.  We get
66                                    carry bits reported for each byte which
67                                    is *not* 0 */
68         jnc L(3)                /* highest byte is NUL => return pointer */
69         xorl %ecx, %edx         /* (word+magic)^word */
70         orl $0xfefefeff, %edx   /* set all non-carry bits */
71         incl %edx               /* add 1: if one carry bit was *not* set
72                                    the addition will not result in 0.  */
73         jnz L(3)                /* found NUL => return pointer */
75         movl 4(%eax), %ecx      /* get word (= 4 bytes) in question */
76         movl $0xfefefeff, %edx  /* magic value */
77         addl %ecx, %edx         /* add the magic value to the word.  We get
78                                    carry bits reported for each byte which
79                                    is *not* 0 */
80         jnc L(5)                /* highest byte is NUL => return pointer */
81         xorl %ecx, %edx         /* (word+magic)^word */
82         orl $0xfefefeff, %edx   /* set all non-carry bits */
83         incl %edx               /* add 1: if one carry bit was *not* set
84                                    the addition will not result in 0.  */
85         jnz L(5)                /* found NUL => return pointer */
87         movl 8(%eax), %ecx      /* get word (= 4 bytes) in question */
88         movl $0xfefefeff, %edx  /* magic value */
89         addl %ecx, %edx         /* add the magic value to the word.  We get
90                                    carry bits reported for each byte which
91                                    is *not* 0 */
92         jnc L(6)                /* highest byte is NUL => return pointer */
93         xorl %ecx, %edx         /* (word+magic)^word */
94         orl $0xfefefeff, %edx   /* set all non-carry bits */
95         incl %edx               /* add 1: if one carry bit was *not* set
96                                    the addition will not result in 0.  */
97         jnz L(6)                /* found NUL => return pointer */
99         movl 12(%eax), %ecx     /* get word (= 4 bytes) in question */
100         movl $0xfefefeff, %edx  /* magic value */
101         addl %ecx, %edx         /* add the magic value to the word.  We get
102                                    carry bits reported for each byte which
103                                    is *not* 0 */
104         jnc L(7)                /* highest byte is NUL => return pointer */
105         xorl %ecx, %edx         /* (word+magic)^word */
106         orl $0xfefefeff, %edx   /* set all non-carry bits */
107         incl %edx               /* add 1: if one carry bit was *not* set
108                                    the addition will not result in 0.  */
109         jz L(4)                 /* no NUL found => continue loop */
111 L(7):   addl $4, %eax           /* adjust pointer */
112 L(6):   addl $4, %eax
113 L(5):   addl $4, %eax
115 L(3):   testb %cl, %cl          /* is first byte NUL? */
116         jz L(2)                 /* yes => return */
117         incl %eax               /* increment pointer */
119         testb %ch, %ch          /* is second byte NUL? */
120         jz L(2)                 /* yes => return */
121         incl %eax               /* increment pointer */
123         testl $0xff0000, %ecx   /* is third byte NUL? */
124         jz L(2)                 /* yes => return pointer */
125         incl %eax               /* increment pointer */
127 L(2):   subl STR(%esp), %eax    /* compute difference to string start */
129         ret
130 END (strlen)
131 libc_hidden_builtin_def (strlen)