Sort sysdeps/powerpc/fpu/libm-test-ulps
[glibc.git] / sysdeps / x86_64 / strcpy_chk.S
blob1640e69235bf68082f05b3415ae5c954c31475ff
1 /* strcpy/stpcpy checking implementation for x86-64.
2    Copyright (C) 2002, 2004 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4    Contributed by Andreas Jaeger <aj@suse.de>, 2002.
5    Adopted into checking version by Jakub Jelinek <jakub@redhat.com>.
7    The GNU C Library is free software; you can redistribute it and/or
8    modify it under the terms of the GNU Lesser General Public
9    License as published by the Free Software Foundation; either
10    version 2.1 of the License, or (at your option) any later version.
12    The GNU C Library is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15    Lesser General Public License for more details.
17    You should have received a copy of the GNU Lesser General Public
18    License along with the GNU C Library; if not, see
19    <http://www.gnu.org/licenses/>.  */
21 #include <sysdep.h>
22 #include "asm-syntax.h"
23 #include "bp-sym.h"
24 #include "bp-asm.h"
26 #ifndef USE_AS_STPCPY_CHK
27 # define STRCPY_CHK __strcpy_chk
28 #endif
30         .text
31 ENTRY (STRCPY_CHK)
32         movq    %rsi, %rcx      /* Source register. */
33         andl    $7, %ecx        /* mask alignment bits */
34 #ifndef USE_AS_STPCPY_CHK
35         movq    %rdi, %r10      /* Duplicate destination pointer.  */
36 #endif
37         jz 5f                   /* aligned => start loop */
39         cmpq    $8, %rdx        /* Check if only few bytes left in
40                                    destination.  */
41         jb      50f
43         subq    $8, %rcx        /* We need to align to 8 bytes.  */
44         addq    %rcx, %rdx      /* Subtract count of stored bytes
45                                    in the cycle below from destlen.  */
47         /* Search the first bytes directly.  */
49         movb    (%rsi), %al     /* Fetch a byte */
50         testb   %al, %al        /* Is it NUL? */
51         movb    %al, (%rdi)     /* Store it */
52         jz      4f              /* If it was NUL, done! */
53         incq    %rsi
54         incq    %rdi
55         incl    %ecx
56         jnz     0b
59         movq $0xfefefefefefefeff,%r8
60         cmpq    $32, %rdx       /* Are there enough bytes in destination
61                                    for the next unrolled round?  */
62         jb      60f             /* If not, avoid the unrolled loop.  */
64         /* Now the sources is aligned.  Unfortunatly we cannot force
65            to have both source and destination aligned, so ignore the
66            alignment of the destination.  */
67         .p2align 4
69         /* 1st unroll.  */
70         movq    (%rsi), %rax    /* Read double word (8 bytes).  */
71         addq    $8, %rsi        /* Adjust pointer for next word.  */
72         movq    %rax, %r9       /* Save a copy for NUL finding.  */
73         addq    %r8, %r9        /* add the magic value to the word.  We get
74                                    carry bits reported for each byte which
75                                    is *not* 0 */
76         jnc     3f              /* highest byte is NUL => return pointer */
77         xorq    %rax, %r9       /* (word+magic)^word */
78         orq     %r8, %r9        /* set all non-carry bits */
79         incq    %r9             /* add 1: if one carry bit was *not* set
80                                    the addition will not result in 0.  */
82         jnz     3f              /* found NUL => return pointer */
84         movq    %rax, (%rdi)    /* Write value to destination.  */
85         addq    $8, %rdi        /* Adjust pointer.  */
87         /* 2nd unroll.  */
88         movq    (%rsi), %rax    /* Read double word (8 bytes).  */
89         addq    $8, %rsi        /* Adjust pointer for next word.  */
90         movq    %rax, %r9       /* Save a copy for NUL finding.  */
91         addq    %r8, %r9        /* add the magic value to the word.  We get
92                                    carry bits reported for each byte which
93                                    is *not* 0 */
94         jnc     3f              /* highest byte is NUL => return pointer */
95         xorq    %rax, %r9       /* (word+magic)^word */
96         orq     %r8, %r9        /* set all non-carry bits */
97         incq    %r9             /* add 1: if one carry bit was *not* set
98                                    the addition will not result in 0.  */
100         jnz     3f              /* found NUL => return pointer */
102         movq    %rax, (%rdi)    /* Write value to destination.  */
103         addq    $8, %rdi        /* Adjust pointer.  */
105         /* 3rd unroll.  */
106         movq    (%rsi), %rax    /* Read double word (8 bytes).  */
107         addq    $8, %rsi        /* Adjust pointer for next word.  */
108         movq    %rax, %r9       /* Save a copy for NUL finding.  */
109         addq    %r8, %r9        /* add the magic value to the word.  We get
110                                    carry bits reported for each byte which
111                                    is *not* 0 */
112         jnc     3f              /* highest byte is NUL => return pointer */
113         xorq    %rax, %r9       /* (word+magic)^word */
114         orq     %r8, %r9        /* set all non-carry bits */
115         incq    %r9             /* add 1: if one carry bit was *not* set
116                                    the addition will not result in 0.  */
118         jnz     3f              /* found NUL => return pointer */
120         movq    %rax, (%rdi)    /* Write value to destination.  */
121         addq    $8, %rdi        /* Adjust pointer.  */
123         /* 4th unroll.  */
124         movq    (%rsi), %rax    /* Read double word (8 bytes).  */
125         addq    $8, %rsi        /* Adjust pointer for next word.  */
126         movq    %rax, %r9       /* Save a copy for NUL finding.  */
127         addq    %r8, %r9        /* add the magic value to the word.  We get
128                                    carry bits reported for each byte which
129                                    is *not* 0 */
130         jnc     3f              /* highest byte is NUL => return pointer */
131         xorq    %rax, %r9       /* (word+magic)^word */
132         orq     %r8, %r9        /* set all non-carry bits */
133         incq    %r9             /* add 1: if one carry bit was *not* set
134                                    the addition will not result in 0.  */
136         jnz     3f              /* found NUL => return pointer */
138         subq    $32, %rdx       /* Adjust destlen.  */
139         movq    %rax, (%rdi)    /* Write value to destination.  */
140         addq    $8, %rdi        /* Adjust pointer.  */
141         cmpq    $32, %rdx       /* Are there enough bytes in destination
142                                    for the next unrolled round?  */
143         jae     1b              /* Next iteration.  */
146         cmpq    $8, %rdx        /* Are there enough bytes in destination
147                                    for the next unrolled round?  */
148         jb      50f             /* Now, copy and check byte by byte.  */
150         movq    (%rsi), %rax    /* Read double word (8 bytes).  */
151         addq    $8, %rsi        /* Adjust pointer for next word.  */
152         movq    %rax, %r9       /* Save a copy for NUL finding.  */
153         addq    %r8, %r9        /* add the magic value to the word.  We get
154                                    carry bits reported for each byte which
155                                    is *not* 0 */
156         jnc     3f              /* highest byte is NUL => return pointer */
157         xorq    %rax, %r9       /* (word+magic)^word */
158         orq     %r8, %r9        /* set all non-carry bits */
159         incq    %r9             /* add 1: if one carry bit was *not* set
160                                    the addition will not result in 0.  */
162         jnz     3f              /* found NUL => return pointer */
164         subq    $8, %rdx        /* Adjust destlen.  */
165         movq    %rax, (%rdi)    /* Write value to destination.  */
166         addq    $8, %rdi        /* Adjust pointer.  */
167         jmp     60b             /* Next iteration.  */
169         /* Do the last few bytes. %rax contains the value to write.
170            The loop is unrolled twice.  */
171         .p2align 4
173         /* Note that stpcpy needs to return with the value of the NUL
174            byte.  */
175         movb    %al, (%rdi)     /* 1st byte.  */
176         testb   %al, %al        /* Is it NUL.  */
177         jz      4f              /* yes, finish.  */
178         incq    %rdi            /* Increment destination.  */
179         movb    %ah, (%rdi)     /* 2nd byte.  */
180         testb   %ah, %ah        /* Is it NUL?.  */
181         jz      4f              /* yes, finish.  */
182         incq    %rdi            /* Increment destination.  */
183         shrq    $16, %rax       /* Shift...  */
184         jmp     3b              /* and look at next two bytes in %rax.  */
187         /* Search the bytes directly, checking for overflows.  */
188         incq    %rsi
189         incq    %rdi
190         decq    %rdx
191         jz      HIDDEN_JUMPTARGET (__chk_fail)
193         movb    (%rsi), %al     /* Fetch a byte */
194         testb   %al, %al        /* Is it NUL? */
195         movb    %al, (%rdi)     /* Store it */
196         jnz     51b             /* If it was NUL, done! */
198 #ifdef USE_AS_STPCPY_CHK
199         movq    %rdi, %rax      /* Destination is return value.  */
200 #else
201         movq    %r10, %rax      /* Source is return value.  */
202 #endif
203         retq
206         testq   %rdx, %rdx
207         jnz     52b
208         jmp     HIDDEN_JUMPTARGET (__chk_fail)
210 END (STRCPY_CHK)