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