Update copyright notices with scripts/update-copyrights.
[jlayton/glibc.git] / sysdeps / x86_64 / rtld-strlen.S
1 /* strlen(str) -- determine the length of the string STR.
2    Copyright (C) 2002-2013 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 <sysdep.h>
21 #include "asm-syntax.h"
22 #include "bp-sym.h"
23 #include "bp-asm.h"
24
25
26         .text
27 ENTRY (strlen)
28         movq %rdi, %rcx         /* Duplicate source pointer. */
29         andl $7, %ecx           /* mask alignment bits */
30         movq %rdi, %rax         /* duplicate destination.  */
31         jz 1f                   /* aligned => start loop */
32
33         neg %ecx                /* We need to align to 8 bytes.  */
34         addl $8,%ecx
35         /* Search the first bytes directly.  */
36 0:      cmpb $0x0,(%rax)        /* is byte NUL? */
37         je 2f                   /* yes => return */
38         incq %rax               /* increment pointer */
39         decl %ecx
40         jnz 0b
41
42 1:      movq $0xfefefefefefefeff,%r8 /* Save magic.  */
43
44         .p2align 4              /* Align loop.  */
45 4:      /* Main Loop is unrolled 4 times.  */
46         /* First unroll.  */
47         movq (%rax), %rcx       /* get double word (= 8 bytes) in question */
48         addq $8,%rax            /* adjust pointer for next word */
49         movq %r8, %rdx          /* magic value */
50         addq %rcx, %rdx         /* add the magic value to the word.  We get
51                                    carry bits reported for each byte which
52                                    is *not* 0 */
53         jnc 3f                  /* highest byte is NUL => return pointer */
54         xorq %rcx, %rdx         /* (word+magic)^word */
55         orq %r8, %rdx           /* set all non-carry bits */
56         incq %rdx               /* add 1: if one carry bit was *not* set
57                                    the addition will not result in 0.  */
58         jnz 3f                  /* found NUL => return pointer */
59
60         /* Second unroll.  */
61         movq (%rax), %rcx       /* get double word (= 8 bytes) in question */
62         addq $8,%rax            /* adjust pointer for next word */
63         movq %r8, %rdx          /* magic value */
64         addq %rcx, %rdx         /* add the magic value to the word.  We get
65                                    carry bits reported for each byte which
66                                    is *not* 0 */
67         jnc 3f                  /* highest byte is NUL => return pointer */
68         xorq %rcx, %rdx         /* (word+magic)^word */
69         orq %r8, %rdx           /* set all non-carry bits */
70         incq %rdx               /* add 1: if one carry bit was *not* set
71                                    the addition will not result in 0.  */
72         jnz 3f                  /* found NUL => return pointer */
73
74         /* Third unroll.  */
75         movq (%rax), %rcx       /* get double word (= 8 bytes) in question */
76         addq $8,%rax            /* adjust pointer for next word */
77         movq %r8, %rdx          /* magic value */
78         addq %rcx, %rdx         /* add the magic value to the word.  We get
79                                    carry bits reported for each byte which
80                                    is *not* 0 */
81         jnc 3f                  /* highest byte is NUL => return pointer */
82         xorq %rcx, %rdx         /* (word+magic)^word */
83         orq %r8, %rdx           /* set all non-carry bits */
84         incq %rdx               /* add 1: if one carry bit was *not* set
85                                    the addition will not result in 0.  */
86         jnz 3f                  /* found NUL => return pointer */
87
88         /* Fourth unroll.  */
89         movq (%rax), %rcx       /* get double word (= 8 bytes) in question */
90         addq $8,%rax            /* adjust pointer for next word */
91         movq %r8, %rdx          /* magic value */
92         addq %rcx, %rdx         /* add the magic value to the word.  We get
93                                    carry bits reported for each byte which
94                                    is *not* 0 */
95         jnc 3f                  /* highest byte is NUL => return pointer */
96         xorq %rcx, %rdx         /* (word+magic)^word */
97         orq %r8, %rdx           /* set all non-carry bits */
98         incq %rdx               /* add 1: if one carry bit was *not* set
99                                    the addition will not result in 0.  */
100         jz 4b                   /* no NUL found => continue loop */
101
102         .p2align 4              /* Align, it's a jump target.  */
103 3:      subq $8,%rax            /* correct pointer increment.  */
104
105         testb %cl, %cl          /* is first byte NUL? */
106         jz 2f                   /* yes => return */
107         incq %rax               /* increment pointer */
108
109         testb %ch, %ch          /* is second byte NUL? */
110         jz 2f                   /* yes => return */
111         incq %rax               /* increment pointer */
112
113         testl $0x00ff0000, %ecx /* is third byte NUL? */
114         jz 2f                   /* yes => return pointer */
115         incq %rax               /* increment pointer */
116
117         testl $0xff000000, %ecx /* is fourth byte NUL? */
118         jz 2f                   /* yes => return pointer */
119         incq %rax               /* increment pointer */
120
121         shrq $32, %rcx          /* look at other half.  */
122
123         testb %cl, %cl          /* is first byte NUL? */
124         jz 2f                   /* yes => return */
125         incq %rax               /* increment pointer */
126
127         testb %ch, %ch          /* is second byte NUL? */
128         jz 2f                   /* yes => return */
129         incq %rax               /* increment pointer */
130
131         testl $0xff0000, %ecx   /* is third byte NUL? */
132         jz 2f                   /* yes => return pointer */
133         incq %rax               /* increment pointer */
134 2:
135         subq %rdi, %rax         /* compute difference to string start */
136         ret
137 END (strlen)
138 libc_hidden_builtin_def (strlen)