c5a4ce75a21933c21b8aec626d200ab22fb4d5d6
[platform/upstream/glibc.git] / sysdeps / i386 / i586 / strcpy.S
1 /* strcpy/stpcpy implementation for i586.
2    Copyright (C) 1997-2013 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
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 #define PARMS   LINKAGE+12      /* space for 3 saved regs */
26 #define RTN     PARMS
27 #define DEST    RTN+RTN_SIZE
28 #define SRC     DEST+PTR_SIZE
29
30 #ifndef USE_AS_STPCPY
31 # define STRCPY strcpy
32 #endif
33
34 #define magic 0xfefefeff
35
36         .text
37 ENTRY (BP_SYM (STRCPY))
38
39         pushl   %edi
40         cfi_adjust_cfa_offset (4)
41         pushl   %esi
42         cfi_adjust_cfa_offset (4)
43         pushl   %ebx
44         cfi_adjust_cfa_offset (4)
45
46         movl    DEST(%esp), %edi
47         cfi_rel_offset (edi, 8)
48         movl    SRC(%esp), %esi
49         cfi_rel_offset (esi, 4)
50
51         xorl    %eax, %eax
52         leal    -1(%esi), %ecx
53
54         movl    $magic, %ebx
55         cfi_rel_offset (ebx, 0)
56         andl    $3, %ecx
57
58 #ifdef PIC
59         call    2f
60         cfi_adjust_cfa_offset (4)
61 2:      popl    %edx
62         cfi_adjust_cfa_offset (-4)
63         /* 0xb is the distance between 2: and 1: but we avoid writing
64            1f-2b because the assembler generates worse code.  */
65         leal    0xb(%edx,%ecx,8), %ecx
66 #else
67         leal    1f(,%ecx,8), %ecx
68 #endif
69
70         jmp     *%ecx
71
72         .align 8
73 1:
74         orb     (%esi), %al
75         jz      L(end)
76         stosb
77         xorl    %eax, %eax
78         incl    %esi
79
80         orb     (%esi), %al
81         jz      L(end)
82         stosb
83         xorl    %eax, %eax
84         incl    %esi
85
86         orb     (%esi), %al
87         jz      L(end)
88         stosb
89         xorl    %eax, %eax
90         incl    %esi
91
92 L(1):   movl    (%esi), %ecx
93         leal    4(%esi),%esi
94
95         subl    %ecx, %eax
96         addl    %ebx, %ecx
97
98         decl    %eax
99         jnc     L(3)
100
101         movl    %ecx, %edx
102         xorl    %ecx, %eax
103
104         subl    %ebx, %edx
105         andl    $~magic, %eax
106
107         jne     L(4)
108
109         movl    %edx, (%edi)
110         leal    4(%edi),%edi
111
112         jmp     L(1)
113
114 L(3):   movl    %ecx, %edx
115
116         subl    %ebx, %edx
117
118 L(4):   movb    %dl, (%edi)
119         testb   %dl, %dl
120
121         movl    %edx, %eax
122         jz      L(end2)
123
124         shrl    $16, %eax
125         movb    %dh, 1(%edi)
126 #ifdef USE_AS_STPCPY
127         addl    $1, %edi
128 #endif
129
130         cmpb    $0, %dh
131         jz      L(end2)
132
133 #ifdef USE_AS_STPCPY
134         movb    %al, 1(%edi)
135         addl    $1, %edi
136
137         cmpb    $0, %al
138         jz      L(end2)
139
140         addl    $1, %edi
141 #else
142         movb    %al, 2(%edi)
143         testb   %al, %al
144
145         leal    3(%edi), %edi
146         jz      L(end2)
147 #endif
148
149 L(end): movb    %ah, (%edi)
150
151 L(end2):
152         /* GKM FIXME: check high bounds  */
153 #ifdef USE_AS_STPCPY
154         movl    %edi, %eax
155 #else
156         movl    DEST(%esp), %eax
157 #endif
158         popl    %ebx
159         cfi_adjust_cfa_offset (-4)
160         cfi_restore (ebx)
161         popl    %esi
162         cfi_adjust_cfa_offset (-4)
163         cfi_restore (esi)
164         popl    %edi
165         cfi_adjust_cfa_offset (-4)
166         cfi_restore (edi)
167
168         RET_PTR
169 END (BP_SYM (STRCPY))
170 #ifndef USE_AS_STPCPY
171 libc_hidden_builtin_def (strcpy)
172 #endif