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