blob: d705aa354a03be79646121c8ce43ec734351a959 [file] [log] [blame]
Christopher Ferris4e24dcc2013-07-15 12:49:26 -07001/*
2 * Copyright (C) 2013 The Android Open Source Project
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in
12 * the documentation and/or other materials provided with the
13 * distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28/*
29 * Copyright (c) 2013 ARM Ltd
30 * All rights reserved.
31 *
32 * Redistribution and use in source and binary forms, with or without
33 * modification, are permitted provided that the following conditions
34 * are met:
35 * 1. Redistributions of source code must retain the above copyright
36 * notice, this list of conditions and the following disclaimer.
37 * 2. Redistributions in binary form must reproduce the above copyright
38 * notice, this list of conditions and the following disclaimer in the
39 * documentation and/or other materials provided with the distribution.
40 * 3. The name of the company may not be used to endorse or promote
41 * products derived from this software without specific prior written
42 * permission.
43 *
44 * THIS SOFTWARE IS PROVIDED BY ARM LTD ``AS IS'' AND ANY EXPRESS OR IMPLIED
45 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
46 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
47 * IN NO EVENT SHALL ARM LTD BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
48 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
49 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
50 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
51 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
52 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
53 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
54 */
55
Elliott Hughes851e68a2014-02-19 16:53:20 -080056#include <private/bionic_asm.h>
Christopher Ferris4e24dcc2013-07-15 12:49:26 -070057
58 .syntax unified
59
60 .thumb
61 .thumb_func
62
63 .macro m_push
64 push {r0, r4, r5, lr}
Christopher Ferris1c8ea802014-09-29 15:34:20 -070065 .cfi_def_cfa_offset 16
66 .cfi_rel_offset r0, 0
67 .cfi_rel_offset r4, 4
68 .cfi_rel_offset r5, 8
69 .cfi_rel_offset lr, 12
Christopher Ferris4e24dcc2013-07-15 12:49:26 -070070 .endm // m_push
71
72 .macro m_ret inst
73 \inst {r0, r4, r5, pc}
74 .endm // m_ret
75
76 .macro m_copy_byte reg, cmd, label
77 ldrb \reg, [r1], #1
78 strb \reg, [r0], #1
79 \cmd \reg, \label
80 .endm // m_copy_byte
81
82ENTRY(strcpy)
83 // Unroll the first 8 bytes that will be copied.
84 m_push
Christopher Ferris1c8ea802014-09-29 15:34:20 -070085 m_copy_byte reg=r2, cmd=cbz, label=.Lstrcpy_finish
86 m_copy_byte reg=r3, cmd=cbz, label=.Lstrcpy_finish
87 m_copy_byte reg=r4, cmd=cbz, label=.Lstrcpy_finish
88 m_copy_byte reg=r5, cmd=cbz, label=.Lstrcpy_finish
89 m_copy_byte reg=r2, cmd=cbz, label=.Lstrcpy_finish
90 m_copy_byte reg=r3, cmd=cbz, label=.Lstrcpy_finish
91 m_copy_byte reg=r4, cmd=cbz, label=.Lstrcpy_finish
92 m_copy_byte reg=r5, cmd=cbnz, label=.Lstrcpy_continue
Christopher Ferris4e24dcc2013-07-15 12:49:26 -070093
Christopher Ferris1c8ea802014-09-29 15:34:20 -070094.Lstrcpy_finish:
Christopher Ferris4e24dcc2013-07-15 12:49:26 -070095 m_ret inst=pop
96
Christopher Ferris1c8ea802014-09-29 15:34:20 -070097.Lstrcpy_continue:
Christopher Ferris4e24dcc2013-07-15 12:49:26 -070098 pld [r1, #0]
99 ands r3, r0, #7
Christopher Ferris1c8ea802014-09-29 15:34:20 -0700100 bne .Lstrcpy_align_dst
Christopher Ferris4e24dcc2013-07-15 12:49:26 -0700101
Christopher Ferris1c8ea802014-09-29 15:34:20 -0700102.Lstrcpy_check_src_align:
Christopher Ferris4e24dcc2013-07-15 12:49:26 -0700103 // At this point dst is aligned to a double word, check if src
104 // is also aligned to a double word.
105 ands r3, r1, #7
Christopher Ferris1c8ea802014-09-29 15:34:20 -0700106 bne .Lstrcpy_unaligned_copy
Christopher Ferris4e24dcc2013-07-15 12:49:26 -0700107
108 .p2align 2
Christopher Ferris1c8ea802014-09-29 15:34:20 -0700109.Lstrcpy_mainloop:
Christopher Ferris4e24dcc2013-07-15 12:49:26 -0700110 ldmia r1!, {r2, r3}
111
112 pld [r1, #64]
113
114 sub ip, r2, #0x01010101
115 bic ip, ip, r2
116 ands ip, ip, #0x80808080
Christopher Ferris1c8ea802014-09-29 15:34:20 -0700117 bne .Lstrcpy_zero_in_first_register
Christopher Ferris4e24dcc2013-07-15 12:49:26 -0700118
119 sub ip, r3, #0x01010101
120 bic ip, ip, r3
121 ands ip, ip, #0x80808080
Christopher Ferris1c8ea802014-09-29 15:34:20 -0700122 bne .Lstrcpy_zero_in_second_register
Christopher Ferris4e24dcc2013-07-15 12:49:26 -0700123
124 stmia r0!, {r2, r3}
Christopher Ferris1c8ea802014-09-29 15:34:20 -0700125 b .Lstrcpy_mainloop
Christopher Ferris4e24dcc2013-07-15 12:49:26 -0700126
Christopher Ferris1c8ea802014-09-29 15:34:20 -0700127.Lstrcpy_zero_in_first_register:
Christopher Ferris4e24dcc2013-07-15 12:49:26 -0700128 lsls lr, ip, #17
129 itt ne
130 strbne r2, [r0]
131 m_ret inst=popne
132 itt cs
133 strhcs r2, [r0]
134 m_ret inst=popcs
135 lsls ip, ip, #1
136 itt eq
137 streq r2, [r0]
138 m_ret inst=popeq
139 strh r2, [r0], #2
140 lsr r3, r2, #16
141 strb r3, [r0]
142 m_ret inst=pop
143
Christopher Ferris1c8ea802014-09-29 15:34:20 -0700144.Lstrcpy_zero_in_second_register:
Christopher Ferris4e24dcc2013-07-15 12:49:26 -0700145 lsls lr, ip, #17
146 ittt ne
147 stmiane r0!, {r2}
148 strbne r3, [r0]
149 m_ret inst=popne
150 ittt cs
151 strcs r2, [r0], #4
152 strhcs r3, [r0]
153 m_ret inst=popcs
154 lsls ip, ip, #1
155 itt eq
156 stmiaeq r0, {r2, r3}
157 m_ret inst=popeq
158 stmia r0!, {r2}
159 strh r3, [r0], #2
160 lsr r4, r3, #16
161 strb r4, [r0]
162 m_ret inst=pop
163
Christopher Ferris1c8ea802014-09-29 15:34:20 -0700164.Lstrcpy_align_dst:
Christopher Ferris4e24dcc2013-07-15 12:49:26 -0700165 // Align to a double word (64 bits).
166 rsb r3, r3, #8
167 lsls ip, r3, #31
Christopher Ferris1c8ea802014-09-29 15:34:20 -0700168 beq .Lstrcpy_align_to_32
Christopher Ferris4e24dcc2013-07-15 12:49:26 -0700169
170 ldrb r2, [r1], #1
171 strb r2, [r0], #1
Christopher Ferris1c8ea802014-09-29 15:34:20 -0700172 cbz r2, .Lstrcpy_complete
Christopher Ferris4e24dcc2013-07-15 12:49:26 -0700173
Christopher Ferris1c8ea802014-09-29 15:34:20 -0700174.Lstrcpy_align_to_32:
175 bcc .Lstrcpy_align_to_64
Christopher Ferris4e24dcc2013-07-15 12:49:26 -0700176
177 ldrb r4, [r1], #1
178 strb r4, [r0], #1
179 cmp r4, #0
180 it eq
181 m_ret inst=popeq
182 ldrb r5, [r1], #1
183 strb r5, [r0], #1
184 cmp r5, #0
185 it eq
186 m_ret inst=popeq
187
Christopher Ferris1c8ea802014-09-29 15:34:20 -0700188.Lstrcpy_align_to_64:
Christopher Ferris4e24dcc2013-07-15 12:49:26 -0700189 tst r3, #4
Christopher Ferris1c8ea802014-09-29 15:34:20 -0700190 beq .Lstrcpy_check_src_align
Christopher Ferris4e24dcc2013-07-15 12:49:26 -0700191 ldr r2, [r1], #4
192
193 sub ip, r2, #0x01010101
194 bic ip, ip, r2
195 ands ip, ip, #0x80808080
Christopher Ferris1c8ea802014-09-29 15:34:20 -0700196 bne .Lstrcpy_zero_in_first_register
Christopher Ferris4e24dcc2013-07-15 12:49:26 -0700197 stmia r0!, {r2}
Christopher Ferris1c8ea802014-09-29 15:34:20 -0700198 b .Lstrcpy_check_src_align
Christopher Ferris4e24dcc2013-07-15 12:49:26 -0700199
Christopher Ferris1c8ea802014-09-29 15:34:20 -0700200.Lstrcpy_complete:
Christopher Ferris4e24dcc2013-07-15 12:49:26 -0700201 m_ret inst=pop
202
Christopher Ferris1c8ea802014-09-29 15:34:20 -0700203.Lstrcpy_unaligned_copy:
Christopher Ferris4e24dcc2013-07-15 12:49:26 -0700204 // Dst is aligned to a double word, while src is at an unknown alignment.
205 // There are 7 different versions of the unaligned copy code
206 // to prevent overreading the src. The mainloop of every single version
207 // will store 64 bits per loop. The difference is how much of src can
208 // be read without potentially crossing a page boundary.
209 tbb [pc, r3]
Christopher Ferris1c8ea802014-09-29 15:34:20 -0700210.Lstrcpy_unaligned_branchtable:
Christopher Ferris4e24dcc2013-07-15 12:49:26 -0700211 .byte 0
Christopher Ferris1c8ea802014-09-29 15:34:20 -0700212 .byte ((.Lstrcpy_unalign7 - .Lstrcpy_unaligned_branchtable)/2)
213 .byte ((.Lstrcpy_unalign6 - .Lstrcpy_unaligned_branchtable)/2)
214 .byte ((.Lstrcpy_unalign5 - .Lstrcpy_unaligned_branchtable)/2)
215 .byte ((.Lstrcpy_unalign4 - .Lstrcpy_unaligned_branchtable)/2)
216 .byte ((.Lstrcpy_unalign3 - .Lstrcpy_unaligned_branchtable)/2)
217 .byte ((.Lstrcpy_unalign2 - .Lstrcpy_unaligned_branchtable)/2)
218 .byte ((.Lstrcpy_unalign1 - .Lstrcpy_unaligned_branchtable)/2)
Christopher Ferris4e24dcc2013-07-15 12:49:26 -0700219
220 .p2align 2
221 // Can read 7 bytes before possibly crossing a page.
Christopher Ferris1c8ea802014-09-29 15:34:20 -0700222.Lstrcpy_unalign7:
Christopher Ferris4e24dcc2013-07-15 12:49:26 -0700223 ldr r2, [r1], #4
224
225 sub ip, r2, #0x01010101
226 bic ip, ip, r2
227 ands ip, ip, #0x80808080
Christopher Ferris1c8ea802014-09-29 15:34:20 -0700228 bne .Lstrcpy_zero_in_first_register
Christopher Ferris4e24dcc2013-07-15 12:49:26 -0700229
230 ldrb r3, [r1]
Christopher Ferris1c8ea802014-09-29 15:34:20 -0700231 cbz r3, .Lstrcpy_unalign7_copy5bytes
Christopher Ferris4e24dcc2013-07-15 12:49:26 -0700232 ldrb r4, [r1, #1]
Christopher Ferris1c8ea802014-09-29 15:34:20 -0700233 cbz r4, .Lstrcpy_unalign7_copy6bytes
Christopher Ferris4e24dcc2013-07-15 12:49:26 -0700234 ldrb r5, [r1, #2]
Christopher Ferris1c8ea802014-09-29 15:34:20 -0700235 cbz r5, .Lstrcpy_unalign7_copy7bytes
Christopher Ferris4e24dcc2013-07-15 12:49:26 -0700236
237 ldr r3, [r1], #4
238 pld [r1, #64]
239
240 lsrs ip, r3, #24
241 stmia r0!, {r2, r3}
Christopher Ferris1c8ea802014-09-29 15:34:20 -0700242 beq .Lstrcpy_unalign_return
243 b .Lstrcpy_unalign7
Christopher Ferris4e24dcc2013-07-15 12:49:26 -0700244
Christopher Ferris1c8ea802014-09-29 15:34:20 -0700245.Lstrcpy_unalign7_copy5bytes:
Christopher Ferris4e24dcc2013-07-15 12:49:26 -0700246 stmia r0!, {r2}
247 strb r3, [r0]
Christopher Ferris1c8ea802014-09-29 15:34:20 -0700248.Lstrcpy_unalign_return:
Christopher Ferris4e24dcc2013-07-15 12:49:26 -0700249 m_ret inst=pop
250
Christopher Ferris1c8ea802014-09-29 15:34:20 -0700251.Lstrcpy_unalign7_copy6bytes:
Christopher Ferris4e24dcc2013-07-15 12:49:26 -0700252 stmia r0!, {r2}
253 strb r3, [r0], #1
254 strb r4, [r0], #1
255 m_ret inst=pop
256
Christopher Ferris1c8ea802014-09-29 15:34:20 -0700257.Lstrcpy_unalign7_copy7bytes:
Christopher Ferris4e24dcc2013-07-15 12:49:26 -0700258 stmia r0!, {r2}
259 strb r3, [r0], #1
260 strb r4, [r0], #1
261 strb r5, [r0], #1
262 m_ret inst=pop
263
264 .p2align 2
265 // Can read 6 bytes before possibly crossing a page.
Christopher Ferris1c8ea802014-09-29 15:34:20 -0700266.Lstrcpy_unalign6:
Christopher Ferris4e24dcc2013-07-15 12:49:26 -0700267 ldr r2, [r1], #4
268
269 sub ip, r2, #0x01010101
270 bic ip, ip, r2
271 ands ip, ip, #0x80808080
Christopher Ferris1c8ea802014-09-29 15:34:20 -0700272 bne .Lstrcpy_zero_in_first_register
Christopher Ferris4e24dcc2013-07-15 12:49:26 -0700273
274 ldrb r4, [r1]
Christopher Ferris1c8ea802014-09-29 15:34:20 -0700275 cbz r4, .Lstrcpy_unalign_copy5bytes
Christopher Ferris4e24dcc2013-07-15 12:49:26 -0700276 ldrb r5, [r1, #1]
Christopher Ferris1c8ea802014-09-29 15:34:20 -0700277 cbz r5, .Lstrcpy_unalign_copy6bytes
Christopher Ferris4e24dcc2013-07-15 12:49:26 -0700278
279 ldr r3, [r1], #4
280 pld [r1, #64]
281
282 tst r3, #0xff0000
Christopher Ferris1c8ea802014-09-29 15:34:20 -0700283 beq .Lstrcpy_unalign6_copy7bytes
Christopher Ferris4e24dcc2013-07-15 12:49:26 -0700284 lsrs ip, r3, #24
285 stmia r0!, {r2, r3}
Christopher Ferris1c8ea802014-09-29 15:34:20 -0700286 beq .Lstrcpy_unalign_return
287 b .Lstrcpy_unalign6
Christopher Ferris4e24dcc2013-07-15 12:49:26 -0700288
Christopher Ferris1c8ea802014-09-29 15:34:20 -0700289.Lstrcpy_unalign6_copy7bytes:
Christopher Ferris4e24dcc2013-07-15 12:49:26 -0700290 stmia r0!, {r2}
291 strh r3, [r0], #2
292 lsr r3, #16
293 strb r3, [r0]
294 m_ret inst=pop
295
296 .p2align 2
297 // Can read 5 bytes before possibly crossing a page.
Christopher Ferris1c8ea802014-09-29 15:34:20 -0700298.Lstrcpy_unalign5:
Christopher Ferris4e24dcc2013-07-15 12:49:26 -0700299 ldr r2, [r1], #4
300
301 sub ip, r2, #0x01010101
302 bic ip, ip, r2
303 ands ip, ip, #0x80808080
Christopher Ferris1c8ea802014-09-29 15:34:20 -0700304 bne .Lstrcpy_zero_in_first_register
Christopher Ferris4e24dcc2013-07-15 12:49:26 -0700305
306 ldrb r4, [r1]
Christopher Ferris1c8ea802014-09-29 15:34:20 -0700307 cbz r4, .Lstrcpy_unalign_copy5bytes
Christopher Ferris4e24dcc2013-07-15 12:49:26 -0700308
309 ldr r3, [r1], #4
310
311 pld [r1, #64]
312
313 sub ip, r3, #0x01010101
314 bic ip, ip, r3
315 ands ip, ip, #0x80808080
Christopher Ferris1c8ea802014-09-29 15:34:20 -0700316 bne .Lstrcpy_zero_in_second_register
Christopher Ferris4e24dcc2013-07-15 12:49:26 -0700317
318 stmia r0!, {r2, r3}
Christopher Ferris1c8ea802014-09-29 15:34:20 -0700319 b .Lstrcpy_unalign5
Christopher Ferris4e24dcc2013-07-15 12:49:26 -0700320
Christopher Ferris1c8ea802014-09-29 15:34:20 -0700321.Lstrcpy_unalign_copy5bytes:
Christopher Ferris4e24dcc2013-07-15 12:49:26 -0700322 stmia r0!, {r2}
323 strb r4, [r0]
324 m_ret inst=pop
325
Christopher Ferris1c8ea802014-09-29 15:34:20 -0700326.Lstrcpy_unalign_copy6bytes:
Christopher Ferris4e24dcc2013-07-15 12:49:26 -0700327 stmia r0!, {r2}
328 strb r4, [r0], #1
329 strb r5, [r0]
330 m_ret inst=pop
331
332 .p2align 2
333 // Can read 4 bytes before possibly crossing a page.
Christopher Ferris1c8ea802014-09-29 15:34:20 -0700334.Lstrcpy_unalign4:
Christopher Ferris4e24dcc2013-07-15 12:49:26 -0700335 ldmia r1!, {r2}
336
337 sub ip, r2, #0x01010101
338 bic ip, ip, r2
339 ands ip, ip, #0x80808080
Christopher Ferris1c8ea802014-09-29 15:34:20 -0700340 bne .Lstrcpy_zero_in_first_register
Christopher Ferris4e24dcc2013-07-15 12:49:26 -0700341
342 ldmia r1!, {r3}
343 pld [r1, #64]
344
345 sub ip, r3, #0x01010101
346 bic ip, ip, r3
347 ands ip, ip, #0x80808080
Christopher Ferris1c8ea802014-09-29 15:34:20 -0700348 bne .Lstrcpy_zero_in_second_register
Christopher Ferris4e24dcc2013-07-15 12:49:26 -0700349
350 stmia r0!, {r2, r3}
Christopher Ferris1c8ea802014-09-29 15:34:20 -0700351 b .Lstrcpy_unalign4
Christopher Ferris4e24dcc2013-07-15 12:49:26 -0700352
353 .p2align 2
354 // Can read 3 bytes before possibly crossing a page.
Christopher Ferris1c8ea802014-09-29 15:34:20 -0700355.Lstrcpy_unalign3:
Christopher Ferris4e24dcc2013-07-15 12:49:26 -0700356 ldrb r2, [r1]
Christopher Ferris1c8ea802014-09-29 15:34:20 -0700357 cbz r2, .Lstrcpy_unalign3_copy1byte
Christopher Ferris4e24dcc2013-07-15 12:49:26 -0700358 ldrb r3, [r1, #1]
Christopher Ferris1c8ea802014-09-29 15:34:20 -0700359 cbz r3, .Lstrcpy_unalign3_copy2bytes
Christopher Ferris4e24dcc2013-07-15 12:49:26 -0700360 ldrb r4, [r1, #2]
Christopher Ferris1c8ea802014-09-29 15:34:20 -0700361 cbz r4, .Lstrcpy_unalign3_copy3bytes
Christopher Ferris4e24dcc2013-07-15 12:49:26 -0700362
363 ldr r2, [r1], #4
364 ldr r3, [r1], #4
365
366 pld [r1, #64]
367
368 lsrs lr, r2, #24
Christopher Ferris1c8ea802014-09-29 15:34:20 -0700369 beq .Lstrcpy_unalign_copy4bytes
Christopher Ferris4e24dcc2013-07-15 12:49:26 -0700370
371 sub ip, r3, #0x01010101
372 bic ip, ip, r3
373 ands ip, ip, #0x80808080
Christopher Ferris1c8ea802014-09-29 15:34:20 -0700374 bne .Lstrcpy_zero_in_second_register
Christopher Ferris4e24dcc2013-07-15 12:49:26 -0700375
376 stmia r0!, {r2, r3}
Christopher Ferris1c8ea802014-09-29 15:34:20 -0700377 b .Lstrcpy_unalign3
Christopher Ferris4e24dcc2013-07-15 12:49:26 -0700378
Christopher Ferris1c8ea802014-09-29 15:34:20 -0700379.Lstrcpy_unalign3_copy1byte:
Christopher Ferris4e24dcc2013-07-15 12:49:26 -0700380 strb r2, [r0]
381 m_ret inst=pop
382
Christopher Ferris1c8ea802014-09-29 15:34:20 -0700383.Lstrcpy_unalign3_copy2bytes:
Christopher Ferris4e24dcc2013-07-15 12:49:26 -0700384 strb r2, [r0], #1
385 strb r3, [r0]
386 m_ret inst=pop
387
Christopher Ferris1c8ea802014-09-29 15:34:20 -0700388.Lstrcpy_unalign3_copy3bytes:
Christopher Ferris4e24dcc2013-07-15 12:49:26 -0700389 strb r2, [r0], #1
390 strb r3, [r0], #1
391 strb r4, [r0]
392 m_ret inst=pop
393
394 .p2align 2
395 // Can read 2 bytes before possibly crossing a page.
Christopher Ferris1c8ea802014-09-29 15:34:20 -0700396.Lstrcpy_unalign2:
Christopher Ferris4e24dcc2013-07-15 12:49:26 -0700397 ldrb r2, [r1]
Christopher Ferris1c8ea802014-09-29 15:34:20 -0700398 cbz r2, .Lstrcpy_unalign_copy1byte
Christopher Ferris4e24dcc2013-07-15 12:49:26 -0700399 ldrb r3, [r1, #1]
Christopher Ferris1c8ea802014-09-29 15:34:20 -0700400 cbz r3, .Lstrcpy_unalign_copy2bytes
Christopher Ferris4e24dcc2013-07-15 12:49:26 -0700401
402 ldr r2, [r1], #4
403 ldr r3, [r1], #4
404 pld [r1, #64]
405
406 tst r2, #0xff0000
Christopher Ferris1c8ea802014-09-29 15:34:20 -0700407 beq .Lstrcpy_unalign_copy3bytes
Christopher Ferris4e24dcc2013-07-15 12:49:26 -0700408 lsrs ip, r2, #24
Christopher Ferris1c8ea802014-09-29 15:34:20 -0700409 beq .Lstrcpy_unalign_copy4bytes
Christopher Ferris4e24dcc2013-07-15 12:49:26 -0700410
411 sub ip, r3, #0x01010101
412 bic ip, ip, r3
413 ands ip, ip, #0x80808080
Christopher Ferris1c8ea802014-09-29 15:34:20 -0700414 bne .Lstrcpy_zero_in_second_register
Christopher Ferris4e24dcc2013-07-15 12:49:26 -0700415
416 stmia r0!, {r2, r3}
Christopher Ferris1c8ea802014-09-29 15:34:20 -0700417 b .Lstrcpy_unalign2
Christopher Ferris4e24dcc2013-07-15 12:49:26 -0700418
419 .p2align 2
420 // Can read 1 byte before possibly crossing a page.
Christopher Ferris1c8ea802014-09-29 15:34:20 -0700421.Lstrcpy_unalign1:
Christopher Ferris4e24dcc2013-07-15 12:49:26 -0700422 ldrb r2, [r1]
Christopher Ferris1c8ea802014-09-29 15:34:20 -0700423 cbz r2, .Lstrcpy_unalign_copy1byte
Christopher Ferris4e24dcc2013-07-15 12:49:26 -0700424
425 ldr r2, [r1], #4
426 ldr r3, [r1], #4
427
428 pld [r1, #64]
429
430 sub ip, r2, #0x01010101
431 bic ip, ip, r2
432 ands ip, ip, #0x80808080
Christopher Ferris1c8ea802014-09-29 15:34:20 -0700433 bne .Lstrcpy_zero_in_first_register
Christopher Ferris4e24dcc2013-07-15 12:49:26 -0700434
435 sub ip, r3, #0x01010101
436 bic ip, ip, r3
437 ands ip, ip, #0x80808080
Christopher Ferris1c8ea802014-09-29 15:34:20 -0700438 bne .Lstrcpy_zero_in_second_register
Christopher Ferris4e24dcc2013-07-15 12:49:26 -0700439
440 stmia r0!, {r2, r3}
Christopher Ferris1c8ea802014-09-29 15:34:20 -0700441 b .Lstrcpy_unalign1
Christopher Ferris4e24dcc2013-07-15 12:49:26 -0700442
Christopher Ferris1c8ea802014-09-29 15:34:20 -0700443.Lstrcpy_unalign_copy1byte:
Christopher Ferris4e24dcc2013-07-15 12:49:26 -0700444 strb r2, [r0]
445 m_ret inst=pop
446
Christopher Ferris1c8ea802014-09-29 15:34:20 -0700447.Lstrcpy_unalign_copy2bytes:
Christopher Ferris4e24dcc2013-07-15 12:49:26 -0700448 strb r2, [r0], #1
449 strb r3, [r0]
450 m_ret inst=pop
451
Christopher Ferris1c8ea802014-09-29 15:34:20 -0700452.Lstrcpy_unalign_copy3bytes:
Christopher Ferris4e24dcc2013-07-15 12:49:26 -0700453 strh r2, [r0], #2
454 lsr r2, #16
455 strb r2, [r0]
456 m_ret inst=pop
457
Christopher Ferris1c8ea802014-09-29 15:34:20 -0700458.Lstrcpy_unalign_copy4bytes:
Christopher Ferris4e24dcc2013-07-15 12:49:26 -0700459 stmia r0, {r2}
460 m_ret inst=pop
461END(strcpy)