]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/uclibc/lib/contrib/uclibc/libc/string/x86_64/strcpy.S
update
[l4.git] / l4 / pkg / uclibc / lib / contrib / uclibc / libc / string / x86_64 / strcpy.S
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.
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 #ifndef USE_AS_STPCPY
25 # define STRCPY strcpy
26 #endif
27
28         .text
29 ENTRY (BP_SYM (STRCPY))
30         movq %rsi, %rcx         /* Source register. */
31         andl $7, %ecx           /* mask alignment bits */
32         movq %rdi, %rdx         /* Duplicate destination pointer.  */
33
34         jz 5f                   /* aligned => start loop */
35
36         neg %ecx                /* We need to align to 8 bytes.  */
37         addl $8,%ecx
38         /* Search the first bytes directly.  */
39 0:
40         movb    (%rsi), %al     /* Fetch a byte */
41         testb   %al, %al        /* Is it NUL? */
42         movb    %al, (%rdx)     /* Store it */
43         jz      4f              /* If it was NUL, done! */
44         incq    %rsi
45         incq    %rdx
46         decl    %ecx
47         jnz     0b
48
49 5:
50         movq $0xfefefefefefefeff,%r8
51
52         /* Now the sources is aligned.  Unfortunatly we cannot force
53            to have both source and destination aligned, so ignore the
54            alignment of the destination.  */
55
56         /* Next 3 insns are 10 bytes total, make sure we decode them in one go */
57         .p2align 4,,10
58 1:
59         /* 1st unroll.  */
60         movq    (%rsi), %rax    /* Read double word (8 bytes).  */
61         addq    $8, %rsi        /* Adjust pointer for next word.  */
62         movq    %rax, %r9       /* Save a copy for NUL finding.  */
63         addq    %r8, %r9        /* add the magic value to the word.  We get
64                                    carry bits reported for each byte which
65                                    is *not* 0 */
66         jnc     3f              /* highest byte is NUL => return pointer */
67         xorq    %rax, %r9       /* (word+magic)^word */
68         orq     %r8, %r9        /* set all non-carry bits */
69         incq    %r9             /* add 1: if one carry bit was *not* set
70                                    the addition will not result in 0.  */
71
72         jnz     3f              /* found NUL => return pointer */
73
74         movq    %rax, (%rdx)    /* Write value to destination.  */
75         addq    $8, %rdx        /* Adjust pointer.  */
76
77         /* 2nd unroll.  */
78         movq    (%rsi), %rax    /* Read double word (8 bytes).  */
79         addq    $8, %rsi        /* Adjust pointer for next word.  */
80         movq    %rax, %r9       /* Save a copy for NUL finding.  */
81         addq    %r8, %r9        /* add the magic value to the word.  We get
82                                    carry bits reported for each byte which
83                                    is *not* 0 */
84         jnc     3f              /* highest byte is NUL => return pointer */
85         xorq    %rax, %r9       /* (word+magic)^word */
86         orq     %r8, %r9        /* set all non-carry bits */
87         incq    %r9             /* add 1: if one carry bit was *not* set
88                                    the addition will not result in 0.  */
89
90         jnz     3f              /* found NUL => return pointer */
91
92         movq    %rax, (%rdx)    /* Write value to destination.  */
93         addq    $8, %rdx        /* Adjust pointer.  */
94
95         /* 3rd unroll.  */
96         movq    (%rsi), %rax    /* Read double word (8 bytes).  */
97         addq    $8, %rsi        /* Adjust pointer for next word.  */
98         movq    %rax, %r9       /* Save a copy for NUL finding.  */
99         addq    %r8, %r9        /* add the magic value to the word.  We get
100                                    carry bits reported for each byte which
101                                    is *not* 0 */
102         jnc     3f              /* highest byte is NUL => return pointer */
103         xorq    %rax, %r9       /* (word+magic)^word */
104         orq     %r8, %r9        /* set all non-carry bits */
105         incq    %r9             /* add 1: if one carry bit was *not* set
106                                    the addition will not result in 0.  */
107
108         jnz     3f              /* found NUL => return pointer */
109
110         movq    %rax, (%rdx)    /* Write value to destination.  */
111         addq    $8, %rdx        /* Adjust pointer.  */
112
113         /* 4th unroll.  */
114         movq    (%rsi), %rax    /* Read double word (8 bytes).  */
115         addq    $8, %rsi        /* Adjust pointer for next word.  */
116         movq    %rax, %r9       /* Save a copy for NUL finding.  */
117         addq    %r8, %r9        /* add the magic value to the word.  We get
118                                    carry bits reported for each byte which
119                                    is *not* 0 */
120         jnc     3f              /* highest byte is NUL => return pointer */
121         xorq    %rax, %r9       /* (word+magic)^word */
122         orq     %r8, %r9        /* set all non-carry bits */
123         incq    %r9             /* add 1: if one carry bit was *not* set
124                                    the addition will not result in 0.  */
125
126         jnz     3f              /* found NUL => return pointer */
127
128         movq    %rax, (%rdx)    /* Write value to destination.  */
129         addq    $8, %rdx        /* Adjust pointer.  */
130         jmp     1b              /* Next iteration.  */
131
132         /* Do the last few bytes. %rax contains the value to write.
133            The loop is unrolled twice.  */
134
135         /* Next 3 insns are 6 bytes total, make sure we decode them in one go */
136         .p2align 3,,6
137 3:
138         /* Note that stpcpy needs to return with the value of the NUL
139            byte.  */
140         movb    %al, (%rdx)     /* 1st byte.  */
141         testb   %al, %al        /* Is it NUL.  */
142         jz      4f              /* yes, finish.  */
143         incq    %rdx            /* Increment destination.  */
144         movb    %ah, (%rdx)     /* 2nd byte.  */
145         testb   %ah, %ah        /* Is it NUL?.  */
146         jz      4f              /* yes, finish.  */
147         incq    %rdx            /* Increment destination.  */
148         shrq    $16, %rax       /* Shift...  */
149         jmp     3b              /* and look at next two bytes in %rax.  */
150
151 4:
152 #ifdef USE_AS_STPCPY
153         movq    %rdx, %rax      /* Destination is return value.  */
154 #else
155         movq    %rdi, %rax      /* Source is return value.  */
156 #endif
157         retq
158 END (BP_SYM (STRCPY))
159 #ifndef USE_AS_STPCPY
160 libc_hidden_def(strcpy)
161 #endif