]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/uclibc/lib/contrib/uclibc/libc/string/x86_64/strlen.S
update
[l4.git] / l4 / pkg / uclibc / lib / contrib / uclibc / libc / string / x86_64 / strlen.S
1 /* strlen(str) -- determine the length of the string STR.
2    Copyright (C) 2002, 2003 Free Software Foundation, Inc.
3    Based on i486 version contributed by Ulrich Drepper <drepper@redhat.com>.
4    This file is part of the GNU C Library.
5
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.
10
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.
15
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    <http://www.gnu.org/licenses/>.  */
19
20 #include "_glibc_inc.h"
21
22 /* Seems to be unrolled too much */
23
24         .text
25 ENTRY (strlen)
26         movq %rdi, %rcx         /* Duplicate source pointer. */
27         andl $7, %ecx           /* mask alignment bits */
28         movq %rdi, %rax         /* duplicate destination.  */
29         jz 1f                   /* aligned => start loop */
30
31         neg %ecx                /* We need to align to 8 bytes.  */
32         addl $8,%ecx
33         /* Search the first bytes directly.  */
34 0:      cmpb $0x0,(%rax)        /* is byte NUL? */
35         je 2f                   /* yes => return */
36         incq %rax               /* increment pointer */
37         decl %ecx
38         jnz 0b
39
40 1:      movq $0xfefefefefefefeff,%r8 /* Save magic.  */
41
42         /* Align loop.  */
43         /* Next 3 insns are 10 bytes total, make sure we decode them in one go */
44         .p2align 4,,10
45 4:
46         /* Main Loop is unrolled 4 times.  */
47         /* First unroll.  */
48         movq (%rax), %rcx       /* get double word (= 8 bytes) in question */
49         addq $8,%rax            /* adjust pointer for next word */
50         movq %r8, %rdx          /* magic value */
51         addq %rcx, %rdx         /* add the magic value to the word.  We get
52                                    carry bits reported for each byte which
53                                    is *not* 0 */
54         jnc 3f                  /* highest byte is NUL => return pointer */
55         xorq %rcx, %rdx         /* (word+magic)^word */
56         orq %r8, %rdx           /* set all non-carry bits */
57         incq %rdx               /* add 1: if one carry bit was *not* set
58                                    the addition will not result in 0.  */
59         jnz 3f                  /* found NUL => return pointer */
60
61         /* Second unroll.  */
62         movq (%rax), %rcx       /* get double word (= 8 bytes) in question */
63         addq $8,%rax            /* adjust pointer for next word */
64         movq %r8, %rdx          /* magic value */
65         addq %rcx, %rdx         /* add the magic value to the word.  We get
66                                    carry bits reported for each byte which
67                                    is *not* 0 */
68         jnc 3f                  /* highest byte is NUL => return pointer */
69         xorq %rcx, %rdx         /* (word+magic)^word */
70         orq %r8, %rdx           /* set all non-carry bits */
71         incq %rdx               /* add 1: if one carry bit was *not* set
72                                    the addition will not result in 0.  */
73         jnz 3f                  /* found NUL => return pointer */
74
75         /* Third unroll.  */
76         movq (%rax), %rcx       /* get double word (= 8 bytes) in question */
77         addq $8,%rax            /* adjust pointer for next word */
78         movq %r8, %rdx          /* magic value */
79         addq %rcx, %rdx         /* add the magic value to the word.  We get
80                                    carry bits reported for each byte which
81                                    is *not* 0 */
82         jnc 3f                  /* highest byte is NUL => return pointer */
83         xorq %rcx, %rdx         /* (word+magic)^word */
84         orq %r8, %rdx           /* set all non-carry bits */
85         incq %rdx               /* add 1: if one carry bit was *not* set
86                                    the addition will not result in 0.  */
87         jnz 3f                  /* found NUL => return pointer */
88
89         /* Fourth unroll.  */
90         movq (%rax), %rcx       /* get double word (= 8 bytes) in question */
91         addq $8,%rax            /* adjust pointer for next word */
92         movq %r8, %rdx          /* magic value */
93         addq %rcx, %rdx         /* add the magic value to the word.  We get
94                                    carry bits reported for each byte which
95                                    is *not* 0 */
96         jnc 3f                  /* highest byte is NUL => return pointer */
97         xorq %rcx, %rdx         /* (word+magic)^word */
98         orq %r8, %rdx           /* set all non-carry bits */
99         incq %rdx               /* add 1: if one carry bit was *not* set
100                                    the addition will not result in 0.  */
101         jz 4b                   /* no NUL found => continue loop */
102
103         /* Align, it is a jump target.  */
104         /* Next 3 insns are 8 bytes total, make sure we decode them in one go */
105         .p2align 3,,8
106 3:
107         subq $8,%rax            /* correct pointer increment.  */
108
109         testb %cl, %cl          /* is first byte NUL? */
110         jz 2f                   /* yes => return */
111         incq %rax               /* increment pointer */
112
113         testb %ch, %ch          /* is second byte NUL? */
114         jz 2f                   /* yes => return */
115         incq %rax               /* increment pointer */
116
117         testl $0x00ff0000, %ecx /* is third byte NUL? */
118         jz 2f                   /* yes => return pointer */
119         incq %rax               /* increment pointer */
120
121         testl $0xff000000, %ecx /* is fourth byte NUL? */
122         jz 2f                   /* yes => return pointer */
123         incq %rax               /* increment pointer */
124
125         shrq $32, %rcx          /* look at other half.  */
126
127         testb %cl, %cl          /* is first byte NUL? */
128         jz 2f                   /* yes => return */
129         incq %rax               /* increment pointer */
130
131         testb %ch, %ch          /* is second byte NUL? */
132         jz 2f                   /* yes => return */
133         incq %rax               /* increment pointer */
134
135         testl $0xff0000, %ecx   /* is third byte NUL? */
136         jz 2f                   /* yes => return pointer */
137         incq %rax               /* increment pointer */
138 2:
139         subq %rdi, %rax         /* compute difference to string start */
140         ret
141 END (strlen)
142
143 libc_hidden_def(strlen)