1 /* strcpy -- copy a nul-terminated string.
2 Copyright (C) 2013-2014 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library. If not, see
17 <http://www.gnu.org/licenses/>. */
21 /* Endian independent macros for shifting bytes within registers. */
34 @ Signal stpcpy with NULL in IP.
39 weak_alias (__stpcpy, stpcpy)
40 libc_hidden_def (__stpcpy)
41 libc_hidden_builtin_def (stpcpy)
44 @ Signal strcpy with DEST in IP.
50 @ To cater to long strings, we want 8 byte alignment in the source.
51 @ To cater to small strings, we don't want to start that right away.
52 @ Loop up to 16 times, less whatever it takes to reach alignment.
56 @ Loop until we find ...
59 subs r3, r3, #1 @ ... the alignment point
63 cmpne r2, #0 @ ... or EOS
66 @ Disambiguate the exit possibilites above
67 cmp r2, #0 @ Found EOS
70 @ Load the next two words asap
76 @ For longer strings, we actaully need a stack frame.
77 push { r4, r5, r6, r7 }
78 cfi_adjust_cfa_offset (16)
79 cfi_rel_offset (r4, 0)
80 cfi_rel_offset (r5, 4)
81 cfi_rel_offset (r6, 8)
82 cfi_rel_offset (r7, 12)
84 @ Subtracting (unsigned saturating) from 1 for any byte means result
85 @ of 1 for any byte that was originally zero and 0 otherwise.
86 @ Therefore we consider the lsb of each byte the "found" bit.
89 tst r0, #3 @ Test alignment of DEST
97 @ So now source (r1) is aligned to 8, and dest (r0) is aligned to 4.
98 @ Loop, reading 8 bytes at a time, searching for EOS.
100 2: uqsub8 r4, r7, r2 @ Find EOS
103 cmp r4, #0 @ EOS in first word?
108 cmp r5, #0 @ EOS in second word?
113 ldrd r2, r3, [\B], #8
116 3: sub r1, r1, #4 @ backup to first word
117 4: sub r1, r1, #4 @ backup to second word
119 @ ... then finish up any tail a byte at a time.
120 @ Note that we generally back up and re-read source bytes,
121 @ but we'll not re-write dest bytes.
130 pop { r4, r5, r6, r7 }
132 cfi_adjust_cfa_offset (-16)
139 cmp ip, #0 @ Was this strcpy or stpcpy?
141 subeq r0, r0, #1 @ stpcpy: undo post-inc from store
142 movne r0, ip @ strcpy: return original dest
147 @ Here, source is aligned to 8, but the destination is not word
148 @ aligned. Therefore we have to shift the data in order to be
149 @ able to perform aligned word stores.
151 @ Find out which misalignment we're dealing with.
156 @ Fallthru to .Lunaligned1.
158 .macro unaligned_copy unalign
159 @ Prologue to unaligned loop. Seed shifted non-zero bytes.
160 uqsub8 r4, r7, r2 @ Find EOS
162 mvns r4, r4 @ EOS in first word?
167 rev r2, r2 @ Byte stores below need LE data
169 @ Store a few bytes from the first word.
170 @ At the same time we align r0 and shift out bytes from r2.
177 rev r2, r2 @ Undo previous rev
179 @ Rotated unaligned copy loop. The tail of the prologue is
180 @ shared with the loop itself.
182 1: mvns r5, r5 @ EOS in second word?
184 @ Combine first and second words
185 orr r2, r2, r3, lsh_gt #(\unalign*8)
186 @ Save leftover bytes from the two words
187 lsh_ls r6, r3, #((4-\unalign)*8)
190 @ The "real" start of the unaligned copy loop.
192 ldrd r2, r3, [\B], #8 @ Load 8 more bytes
193 uqsub8 r4, r7, r2 @ Find EOS
197 mvns r4, r4 @ EOS in first word?
199 @ Combine the leftover and the first word
200 orr r6, r6, r2, lsh_gt #(\unalign*8)
201 @ Discard used bytes from the first word.
202 lsh_ls r2, r2, #((4-\unalign)*8)
206 @ Found EOS in one of the words; adjust backward
210 @ And store the remaining bytes from the leftover
231 libc_hidden_builtin_def (strcpy)