1 /* strlen -- Compute length og NUL terminated string.
2 Highly optimized version for ix86, x>=5.
3 Copyright (C) 1995, 1996 Free Software Foundation, Inc.
4 This file is part of the GNU C Library.
5 Contributed by Ulrich Drepper, <drepper@gnu.ai.mit.edu>.
7 The GNU C Library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Library General Public License as
9 published by the Free Software Foundation; either version 2 of the
10 License, or (at your option) any later version.
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 Library General Public License for more details.
17 You should have received a copy of the GNU Library General Public
18 License along with the GNU C Library; see the file COPYING.LIB. If
19 not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
24 /* This version is especially optimized for the i586 (and following?)
25 processors. This is mainly done by using the two pipelines. The
26 version optimized for i486 is weak in this aspect because to get
27 as much parallelism we have to executs some *more* instructions.
29 The code below is structured to reflect the pairing of the instructions
30 as *I think* it is. I have no processor data book to verify this.
31 If you find something you think is incorrect let me know. */
34 /* The magic value which is used throughout in the whole code. */
35 #define magic 0xfefefeff
44 movl 4(%esp), %eax /* get string pointer */
45 movl $3, %edx /* load mask (= 3) */
47 andl %eax, %edx /* separate last two bits of address */
49 jz L1 /* aligned => start loop */
50 jp L0 /* exactly two bits set */
52 cmpb %dh, (%eax) /* is byte NUL? */
53 je L2 /* yes => return */
55 incl %eax /* increment pointer */
56 xorl $3, %edx /* was alignment = 3? */
58 jz L1 /* yes => now it is aligned and start loop */
60 L0: cmpb %dh, (%eax) /* is byte NUL? */
61 je L2 /* yes => return */
63 incl %eax /* increment pointer */
65 cmpb %dh, (%eax) /* is byte NUL? */
66 je L2 /* yes => return */
68 incl %eax /* increment pointer */
69 xorl %edx, %edx /* We need %edx == 0 for later */
71 /* We exit the loop if adding MAGIC_BITS to LONGWORD fails to
72 change any of the hole bits of LONGWORD.
74 1) Is this safe? Will it catch all the zero bytes?
75 Suppose there is a byte with all zeros. Any carry bits
76 propagating from its left will fall into the hole at its
77 least significant bit and stop. Since there will be no
78 carry from its most significant bit, the LSB of the
79 byte to the left will be unchanged, and the zero will be
82 2) Is this worthwhile? Will it ignore everything except
83 zero bytes? Suppose every byte of LONGWORD has a bit set
84 somewhere. There will be a carry into bit 8. If bit 8
85 is set, this will carry into bit 16. If bit 8 is clear,
86 one of bits 9-15 must be set, so there will be a carry
87 into bit 16. Similarly, there will be a carry into bit
88 24. If one of bits 24-31 is set, there will be a carry
89 into bit 32 (=carry flag), so all of the hole bits will
92 Note: %edx == 0 in any case here. */
95 movl (%eax), %ecx /* get word (= 4 bytes) in question */
96 addl $4, %eax /* adjust pointer for *next* word */
98 subl %ecx, %edx /* first step to negate word */
99 addl $magic, %ecx /* add magic word */
101 decl %edx /* complete negation of word */
102 jnc L3 /* previous addl caused overflow? */
104 xorl %ecx, %edx /* (word+magic)^word */
106 andl $~magic, %edx /* any of the carry flags set? */
108 jne L3 /* yes => determine byte */
111 movl (%eax), %ecx /* get word (= 4 bytes) in question */
112 addl $4, %eax /* adjust pointer for *next* word */
114 subl %ecx, %edx /* first step to negate word */
115 addl $magic, %ecx /* add magic word */
117 decl %edx /* complete negation of word */
118 jnc L3 /* previous addl caused overflow? */
120 xorl %ecx, %edx /* (word+magic)^word */
122 andl $~magic, %edx /* any of the carry flags set? */
124 jne L3 /* yes => determine byte */
127 movl (%eax), %ecx /* get word (= 4 bytes) in question */
128 addl $4, %eax /* adjust pointer for *next* word */
130 subl %ecx, %edx /* first step to negate word */
131 addl $magic, %ecx /* add magic word */
133 decl %edx /* complete negation of word */
134 jnc L3 /* previous addl caused overflow? */
136 xorl %ecx, %edx /* (word+magic)^word */
138 andl $~magic, %edx /* any of the carry flags set? */
140 jne L3 /* yes => determine byte */
143 movl (%eax), %ecx /* get word (= 4 bytes) in question */
144 addl $4, %eax /* adjust pointer for *next* word */
146 subl %ecx, %edx /* first step to negate word */
147 addl $magic, %ecx /* add magic word */
149 decl %edx /* complete negation of word */
150 jnc L3 /* previous addl caused overflow? */
152 xorl %ecx, %edx /* (word+magic)^word */
154 andl $~magic, %edx /* any of the carry flags set? */
156 je L1 /* no => start loop again */
159 L3: subl $4, %eax /* correct too early pointer increment */
162 cmpb $0, %cl /* lowest byte NUL? */
163 jz L2 /* yes => return */
165 inc %eax /* increment pointer */
166 testb %ch, %ch /* second byte NUL? */
168 jz L2 /* yes => return */
170 shrl $16, %ecx /* make upper bytes accessible */
171 incl %eax /* increment pointer */
173 cmpb $0, %cl /* is third byte NUL? */
174 jz L2 /* yes => return */
176 incl %eax /* increment pointer */
178 L2: subl 4(%esp), %eax /* now compute the length as difference
179 between start and terminating NUL