Update.
[glibc/history.git] / sysdeps / i386 / i486 / strlen.S
blob4a2501101630977dae0a64f66fe3d1167bb74a06
1 /* strlen(str) -- determine the length of the string STR.
2    Optimized for Intel 80x86, x>=4.
3    Copyright (C) 1991, 92, 93, 94, 95, 96, 97 Free Software Foundation, Inc.
4    Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>.
5    This file is part of the GNU C Library.
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 not,
19    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20    Boston, MA 02111-1307, USA.  */
22 #include <sysdep.h>
23 #include "asm-syntax.h"
26    INPUT PARAMETERS:
27    str          (sp + 4)
30         .text
31 ENTRY (strlen)
32         movl 4(%esp), %ecx      /* get string pointer */
33         movl %ecx, %eax         /* duplicate it */
35         andl $3, %ecx           /* mask alignment bits */
36         jz L(1)                 /* aligned => start loop */
37         cmpb %ch, (%eax)        /* is byte NUL? */
38         je L(2)                 /* yes => return */
39         incl %eax               /* increment pointer */
41         xorl $3, %ecx           /* was alignment = 3? */
42         jz L(1)                 /* yes => now it is aligned and start loop */
43         cmpb %ch, (%eax)        /* is byte NUL? */
44         je L(2)                 /* yes => return */
45         addl $1, %eax           /* increment pointer */
47         subl $1, %ecx           /* was alignment = 2? */
48         jz L(1)                 /* yes => now it is aligned and start loop */
49         cmpb %ch, (%eax)        /* is byte NUL? */
50         je L(2)                 /* yes => return */
52 /* Don't change the above `addl $1,%eax' and `subl $1, %ecx' into `incl %eax'
53    and `decl %ecx' resp.  The additional two byte per instruction make the
54    label 4 to be aligned on a 16 byte boundary with nops.
56    The following `sub $15, %eax' is part of this trick, too.  Together with
57    the next instruction (`addl $16, %eax') it is in fact a `incl %eax', just
58    as expected from the algorithm.  But doing so has the advantage that
59    no jump to label 1 is necessary and so the pipeline is not flushed.  */
61         subl $15, %eax          /* effectively +1 */
64 L(4):   addl $16, %eax          /* adjust pointer for full loop */
66 L(1):   movl (%eax), %ecx       /* get word (= 4 bytes) in question */
67         movl $0xfefefeff, %edx  /* magic value */
68         addl %ecx, %edx         /* add the magic value to the word.  We get
69                                    carry bits reported for each byte which
70                                    is *not* 0 */
71         jnc L(3)                /* highest byte is NUL => return pointer */
72         xorl %ecx, %edx         /* (word+magic)^word */
73         orl $0xfefefeff, %edx   /* set all non-carry bits */
74         incl %edx               /* add 1: if one carry bit was *not* set
75                                    the addition will not result in 0.  */
76         jnz L(3)                /* found NUL => return pointer */
78         movl 4(%eax), %ecx      /* get word (= 4 bytes) in question */
79         movl $0xfefefeff, %edx  /* magic value */
80         addl %ecx, %edx         /* add the magic value to the word.  We get
81                                    carry bits reported for each byte which
82                                    is *not* 0 */
83         jnc L(5)                /* highest byte is NUL => return pointer */
84         xorl %ecx, %edx         /* (word+magic)^word */
85         orl $0xfefefeff, %edx   /* set all non-carry bits */
86         incl %edx               /* add 1: if one carry bit was *not* set
87                                    the addition will not result in 0.  */
88         jnz L(5)                /* found NUL => return pointer */
90         movl 8(%eax), %ecx      /* get word (= 4 bytes) in question */
91         movl $0xfefefeff, %edx  /* magic value */
92         addl %ecx, %edx         /* add the magic value to the word.  We get
93                                    carry bits reported for each byte which
94                                    is *not* 0 */
95         jnc L(6)                /* highest byte is NUL => return pointer */
96         xorl %ecx, %edx         /* (word+magic)^word */
97         orl $0xfefefeff, %edx   /* set all non-carry bits */
98         incl %edx               /* add 1: if one carry bit was *not* set
99                                    the addition will not result in 0.  */
100         jnz L(6)                /* found NUL => return pointer */
102         movl 12(%eax), %ecx     /* get word (= 4 bytes) in question */
103         movl $0xfefefeff, %edx  /* magic value */
104         addl %ecx, %edx         /* add the magic value to the word.  We get
105                                    carry bits reported for each byte which
106                                    is *not* 0 */
107         jnc L(7)                /* highest byte is NUL => return pointer */
108         xorl %ecx, %edx         /* (word+magic)^word */
109         orl $0xfefefeff, %edx   /* set all non-carry bits */
110         incl %edx               /* add 1: if one carry bit was *not* set
111                                    the addition will not result in 0.  */
112         jz L(4)                 /* no NUL found => continue loop */
114 L(7):   addl $4, %eax           /* adjust pointer */
115 L(6):   addl $4, %eax
116 L(5):   addl $4, %eax
118 L(3):   testb %cl, %cl          /* is first byte NUL? */
119         jz L(2)                 /* yes => return */
120         incl %eax               /* increment pointer */
122         testb %ch, %ch          /* is second byte NUL? */
123         jz L(2)                 /* yes => return */
124         incl %eax               /* increment pointer */
126         testl $0xff0000, %ecx   /* is third byte NUL? */
127         jz L(2)                 /* yes => return pointer */
128         incl %eax               /* increment pointer */
130 L(2):   subl 4(%esp), %eax      /* compute difference to string start */
132         ret
133 END (strlen)