Define VERSYMIDX/VALIDX/ADDRIDX in ldsodefs.h
[glibc.git] / sysdeps / x86_64 / strcpy.S
blob65216d26e14754897d0d72f111c5606b40e10a2f
1 /* strcpy/stpcpy implementation for x86-64.
2    Copyright (C) 2002 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4    Contributed by Andreas Jaeger <aj@suse.de>, 2002.
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"
22 #include "bp-sym.h"
23 #include "bp-asm.h"
25 #ifndef USE_AS_STPCPY
26 # define STRCPY strcpy
27 #endif
29         .text
30 ENTRY (BP_SYM (STRCPY))
31         movq %rsi, %rcx         /* Source register. */
32         andl $7, %ecx           /* mask alignment bits */
33         movq %rdi, %rdx         /* Duplicate destination pointer.  */
35         jz 5f                   /* aligned => start loop */
37         neg %ecx                /* We need to align to 8 bytes.  */
38         addl $8,%ecx
39         /* Search the first bytes directly.  */
41         movb    (%rsi), %al     /* Fetch a byte */
42         testb   %al, %al        /* Is it NUL? */
43         movb    %al, (%rdx)     /* Store it */
44         jz      4f              /* If it was NUL, done! */
45         incq    %rsi
46         incq    %rdx
47         decl    %ecx
48         jnz     0b
51         movq $0xfefefefefefefeff,%r8
53         /* Now the sources is aligned.  Unfortunatly we cannot force
54            to have both source and destination aligned, so ignore the
55            alignment of the destination.  */
56         .p2align 4
58         /* 1st unroll.  */
59         movq    (%rsi), %rax    /* Read double word (8 bytes).  */
60         addq    $8, %rsi        /* Adjust pointer for next word.  */
61         movq    %rax, %r9       /* Save a copy for NUL finding.  */
62         addq    %r8, %r9        /* 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    %rax, %r9       /* (word+magic)^word */
67         orq     %r8, %r9        /* set all non-carry bits */
68         incq    %r9             /* add 1: if one carry bit was *not* set
69                                    the addition will not result in 0.  */
71         jnz     3f              /* found NUL => return pointer */
73         movq    %rax, (%rdx)    /* Write value to destination.  */
74         addq    $8, %rdx        /* Adjust pointer.  */
76         /* 2nd unroll.  */
77         movq    (%rsi), %rax    /* Read double word (8 bytes).  */
78         addq    $8, %rsi        /* Adjust pointer for next word.  */
79         movq    %rax, %r9       /* Save a copy for NUL finding.  */
80         addq    %r8, %r9        /* add the magic value to the word.  We get
81                                    carry bits reported for each byte which
82                                    is *not* 0 */
83         jnc     3f              /* highest byte is NUL => return pointer */
84         xorq    %rax, %r9       /* (word+magic)^word */
85         orq     %r8, %r9        /* set all non-carry bits */
86         incq    %r9             /* add 1: if one carry bit was *not* set
87                                    the addition will not result in 0.  */
89         jnz     3f              /* found NUL => return pointer */
91         movq    %rax, (%rdx)    /* Write value to destination.  */
92         addq    $8, %rdx        /* Adjust pointer.  */
94         /* 3rd unroll.  */
95         movq    (%rsi), %rax    /* Read double word (8 bytes).  */
96         addq    $8, %rsi        /* Adjust pointer for next word.  */
97         movq    %rax, %r9       /* Save a copy for NUL finding.  */
98         addq    %r8, %r9        /* add the magic value to the word.  We get
99                                    carry bits reported for each byte which
100                                    is *not* 0 */
101         jnc     3f              /* highest byte is NUL => return pointer */
102         xorq    %rax, %r9       /* (word+magic)^word */
103         orq     %r8, %r9        /* set all non-carry bits */
104         incq    %r9             /* add 1: if one carry bit was *not* set
105                                    the addition will not result in 0.  */
107         jnz     3f              /* found NUL => return pointer */
109         movq    %rax, (%rdx)    /* Write value to destination.  */
110         addq    $8, %rdx        /* Adjust pointer.  */
112         /* 4th unroll.  */
113         movq    (%rsi), %rax    /* Read double word (8 bytes).  */
114         addq    $8, %rsi        /* Adjust pointer for next word.  */
115         movq    %rax, %r9       /* Save a copy for NUL finding.  */
116         addq    %r8, %r9        /* add the magic value to the word.  We get
117                                    carry bits reported for each byte which
118                                    is *not* 0 */
119         jnc     3f              /* highest byte is NUL => return pointer */
120         xorq    %rax, %r9       /* (word+magic)^word */
121         orq     %r8, %r9        /* set all non-carry bits */
122         incq    %r9             /* add 1: if one carry bit was *not* set
123                                    the addition will not result in 0.  */
125         jnz     3f              /* found NUL => return pointer */
127         movq    %rax, (%rdx)    /* Write value to destination.  */
128         addq    $8, %rdx        /* Adjust pointer.  */
129         jmp     1b              /* Next iteration.  */
131         /* Do the last few bytes. %rax contains the value to write.
132            The loop is unrolled twice.  */
133         .p2align 4
135         /* Note that stpcpy needs to return with the value of the NUL
136            byte.  */
137         movb    %al, (%rdx)     /* 1st byte.  */
138         testb   %al, %al        /* Is it NUL.  */
139         jz      4f              /* yes, finish.  */
140         incq    %rdx            /* Increment destination.  */
141         movb    %ah, (%rdx)     /* 2nd byte.  */
142         testb   %ah, %ah        /* Is it NUL?.  */
143         jz      4f              /* yes, finish.  */
144         incq    %rdx            /* Increment destination.  */
145         shrq    $16, %rax       /* Shift...  */
146         jmp     3b              /* and look at next two bytes in %rax.  */
149 #ifdef USE_AS_STPCPY
150         movq    %rdx, %rax      /* Destination is return value.  */
151 #else
152         movq    %rdi, %rax      /* Source is return value.  */
153 #endif
154         retq
155 END (BP_SYM (STRCPY))
156 #ifndef USE_AS_STPCPY
157 libc_hidden_builtin_def (strcpy)
158 #endif