]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - android-sdk/platform-bionic.git/blob - libc/arch-arm/cortex-a9/bionic/strcpy.S
Merge "Fixed int fast types for LP64"
[android-sdk/platform-bionic.git] / libc / arch-arm / cortex-a9 / bionic / strcpy.S
1 /*
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  */
56 #include <private/bionic_asm.h>
58     .syntax unified
60     .thumb
61     .thumb_func
63     .macro m_push
64     push    {r0, r4, r5, lr}
65     .endm // m_push
67     .macro m_ret inst
68     \inst   {r0, r4, r5, pc}
69     .endm // m_ret
71     .macro m_copy_byte reg, cmd, label
72     ldrb    \reg, [r1], #1
73     strb    \reg, [r0], #1
74     \cmd    \reg, \label
75     .endm // m_copy_byte
77 ENTRY(strcpy)
78     // Unroll the first 8 bytes that will be copied.
79     m_push
80     m_copy_byte reg=r2, cmd=cbz, label=strcpy_finish
81     m_copy_byte reg=r3, cmd=cbz, label=strcpy_finish
82     m_copy_byte reg=r4, cmd=cbz, label=strcpy_finish
83     m_copy_byte reg=r5, cmd=cbz, label=strcpy_finish
84     m_copy_byte reg=r2, cmd=cbz, label=strcpy_finish
85     m_copy_byte reg=r3, cmd=cbz, label=strcpy_finish
86     m_copy_byte reg=r4, cmd=cbz, label=strcpy_finish
87     m_copy_byte reg=r5, cmd=cbnz, label=strcpy_continue
89 strcpy_finish:
90     m_ret   inst=pop
92 strcpy_continue:
93     pld     [r1, #0]
94     ands    r3, r0, #7
95     bne     strcpy_align_dst
97 strcpy_check_src_align:
98     // At this point dst is aligned to a double word, check if src
99     // is also aligned to a double word.
100     ands    r3, r1, #7
101     bne     strcpy_unaligned_copy
103     .p2align 2
104 strcpy_mainloop:
105     ldmia   r1!, {r2, r3}
107     pld     [r1, #64]
109     sub     ip, r2, #0x01010101
110     bic     ip, ip, r2
111     ands    ip, ip, #0x80808080
112     bne     strcpy_zero_in_first_register
114     sub     ip, r3, #0x01010101
115     bic     ip, ip, r3
116     ands    ip, ip, #0x80808080
117     bne     strcpy_zero_in_second_register
119     stmia   r0!, {r2, r3}
120     b       strcpy_mainloop
122 strcpy_zero_in_first_register:
123     lsls    lr, ip, #17
124     itt     ne
125     strbne  r2, [r0]
126     m_ret   inst=popne
127     itt     cs
128     strhcs  r2, [r0]
129     m_ret   inst=popcs
130     lsls    ip, ip, #1
131     itt     eq
132     streq   r2, [r0]
133     m_ret   inst=popeq
134     strh    r2, [r0], #2
135     lsr     r3, r2, #16
136     strb    r3, [r0]
137     m_ret   inst=pop
139 strcpy_zero_in_second_register:
140     lsls    lr, ip, #17
141     ittt    ne
142     stmiane r0!, {r2}
143     strbne  r3, [r0]
144     m_ret   inst=popne
145     ittt    cs
146     strcs   r2, [r0], #4
147     strhcs  r3, [r0]
148     m_ret   inst=popcs
149     lsls    ip, ip, #1
150     itt     eq
151     stmiaeq r0, {r2, r3}
152     m_ret   inst=popeq
153     stmia   r0!, {r2}
154     strh    r3, [r0], #2
155     lsr     r4, r3, #16
156     strb    r4, [r0]
157     m_ret   inst=pop
159 strcpy_align_dst:
160     // Align to a double word (64 bits).
161     rsb     r3, r3, #8
162     lsls    ip, r3, #31
163     beq     strcpy_align_to_32
165     ldrb    r2, [r1], #1
166     strb    r2, [r0], #1
167     cbz     r2, strcpy_complete
169 strcpy_align_to_32:
170     bcc     strcpy_align_to_64
172     ldrb    r4, [r1], #1
173     strb    r4, [r0], #1
174     cmp     r4, #0
175     it      eq
176     m_ret   inst=popeq
177     ldrb    r5, [r1], #1
178     strb    r5, [r0], #1
179     cmp     r5, #0
180     it      eq
181     m_ret   inst=popeq
183 strcpy_align_to_64:
184     tst     r3, #4
185     beq     strcpy_check_src_align
186     ldr     r2, [r1], #4
188     sub     ip, r2, #0x01010101
189     bic     ip, ip, r2
190     ands    ip, ip, #0x80808080
191     bne     strcpy_zero_in_first_register
192     stmia   r0!, {r2}
193     b       strcpy_check_src_align
195 strcpy_complete:
196     m_ret   inst=pop
198 strcpy_unaligned_copy:
199     // Dst is aligned to a double word, while src is at an unknown alignment.
200     // There are 7 different versions of the unaligned copy code
201     // to prevent overreading the src. The mainloop of every single version
202     // will store 64 bits per loop. The difference is how much of src can
203     // be read without potentially crossing a page boundary.
204     tbb     [pc, r3]
205 strcpy_unaligned_branchtable:
206     .byte 0
207     .byte ((strcpy_unalign7 - strcpy_unaligned_branchtable)/2)
208     .byte ((strcpy_unalign6 - strcpy_unaligned_branchtable)/2)
209     .byte ((strcpy_unalign5 - strcpy_unaligned_branchtable)/2)
210     .byte ((strcpy_unalign4 - strcpy_unaligned_branchtable)/2)
211     .byte ((strcpy_unalign3 - strcpy_unaligned_branchtable)/2)
212     .byte ((strcpy_unalign2 - strcpy_unaligned_branchtable)/2)
213     .byte ((strcpy_unalign1 - strcpy_unaligned_branchtable)/2)
215     .p2align 2
216     // Can read 7 bytes before possibly crossing a page.
217 strcpy_unalign7:
218     ldr     r2, [r1], #4
220     sub     ip, r2, #0x01010101
221     bic     ip, ip, r2
222     ands    ip, ip, #0x80808080
223     bne     strcpy_zero_in_first_register
225     ldrb    r3, [r1]
226     cbz     r3, strcpy_unalign7_copy5bytes
227     ldrb    r4, [r1, #1]
228     cbz     r4, strcpy_unalign7_copy6bytes
229     ldrb    r5, [r1, #2]
230     cbz     r5, strcpy_unalign7_copy7bytes
232     ldr     r3, [r1], #4
233     pld     [r1, #64]
235     lsrs    ip, r3, #24
236     stmia   r0!, {r2, r3}
237     beq     strcpy_unalign_return
238     b       strcpy_unalign7
240 strcpy_unalign7_copy5bytes:
241     stmia   r0!, {r2}
242     strb    r3, [r0]
243 strcpy_unalign_return:
244     m_ret   inst=pop
246 strcpy_unalign7_copy6bytes:
247     stmia   r0!, {r2}
248     strb    r3, [r0], #1
249     strb    r4, [r0], #1
250     m_ret   inst=pop
252 strcpy_unalign7_copy7bytes:
253     stmia   r0!, {r2}
254     strb    r3, [r0], #1
255     strb    r4, [r0], #1
256     strb    r5, [r0], #1
257     m_ret   inst=pop
259     .p2align 2
260     // Can read 6 bytes before possibly crossing a page.
261 strcpy_unalign6:
262     ldr     r2, [r1], #4
264     sub     ip, r2, #0x01010101
265     bic     ip, ip, r2
266     ands    ip, ip, #0x80808080
267     bne     strcpy_zero_in_first_register
269     ldrb    r4, [r1]
270     cbz     r4, strcpy_unalign_copy5bytes
271     ldrb    r5, [r1, #1]
272     cbz     r5, strcpy_unalign_copy6bytes
274     ldr     r3, [r1], #4
275     pld     [r1, #64]
277     tst     r3, #0xff0000
278     beq     strcpy_unalign6_copy7bytes
279     lsrs    ip, r3, #24
280     stmia   r0!, {r2, r3}
281     beq     strcpy_unalign_return
282     b       strcpy_unalign6
284 strcpy_unalign6_copy7bytes:
285     stmia   r0!, {r2}
286     strh    r3, [r0], #2
287     lsr     r3, #16
288     strb    r3, [r0]
289     m_ret   inst=pop
291     .p2align 2
292     // Can read 5 bytes before possibly crossing a page.
293 strcpy_unalign5:
294     ldr     r2, [r1], #4
296     sub     ip, r2, #0x01010101
297     bic     ip, ip, r2
298     ands    ip, ip, #0x80808080
299     bne     strcpy_zero_in_first_register
301     ldrb    r4, [r1]
302     cbz     r4, strcpy_unalign_copy5bytes
304     ldr     r3, [r1], #4
306     pld     [r1, #64]
308     sub     ip, r3, #0x01010101
309     bic     ip, ip, r3
310     ands    ip, ip, #0x80808080
311     bne     strcpy_zero_in_second_register
313     stmia   r0!, {r2, r3}
314     b       strcpy_unalign5
316 strcpy_unalign_copy5bytes:
317     stmia   r0!, {r2}
318     strb    r4, [r0]
319     m_ret   inst=pop
321 strcpy_unalign_copy6bytes:
322     stmia   r0!, {r2}
323     strb    r4, [r0], #1
324     strb    r5, [r0]
325     m_ret   inst=pop
327     .p2align 2
328     // Can read 4 bytes before possibly crossing a page.
329 strcpy_unalign4:
330     ldmia   r1!, {r2}
332     sub     ip, r2, #0x01010101
333     bic     ip, ip, r2
334     ands    ip, ip, #0x80808080
335     bne     strcpy_zero_in_first_register
337     ldmia   r1!, {r3}
338     pld     [r1, #64]
340     sub     ip, r3, #0x01010101
341     bic     ip, ip, r3
342     ands    ip, ip, #0x80808080
343     bne     strcpy_zero_in_second_register
345     stmia   r0!, {r2, r3}
346     b       strcpy_unalign4
348     .p2align 2
349     // Can read 3 bytes before possibly crossing a page.
350 strcpy_unalign3:
351     ldrb    r2, [r1]
352     cbz     r2, strcpy_unalign3_copy1byte
353     ldrb    r3, [r1, #1]
354     cbz     r3, strcpy_unalign3_copy2bytes
355     ldrb    r4, [r1, #2]
356     cbz     r4, strcpy_unalign3_copy3bytes
358     ldr     r2, [r1], #4
359     ldr     r3, [r1], #4
361     pld     [r1, #64]
363     lsrs    lr, r2, #24
364     beq     strcpy_unalign_copy4bytes
366     sub     ip, r3, #0x01010101
367     bic     ip, ip, r3
368     ands    ip, ip, #0x80808080
369     bne     strcpy_zero_in_second_register
371     stmia   r0!, {r2, r3}
372     b       strcpy_unalign3
374 strcpy_unalign3_copy1byte:
375     strb    r2, [r0]
376     m_ret   inst=pop
378 strcpy_unalign3_copy2bytes:
379     strb    r2, [r0], #1
380     strb    r3, [r0]
381     m_ret   inst=pop
383 strcpy_unalign3_copy3bytes:
384     strb    r2, [r0], #1
385     strb    r3, [r0], #1
386     strb    r4, [r0]
387     m_ret   inst=pop
389     .p2align 2
390     // Can read 2 bytes before possibly crossing a page.
391 strcpy_unalign2:
392     ldrb    r2, [r1]
393     cbz     r2, strcpy_unalign_copy1byte
394     ldrb    r3, [r1, #1]
395     cbz     r3, strcpy_unalign_copy2bytes
397     ldr     r2, [r1], #4
398     ldr     r3, [r1], #4
399     pld     [r1, #64]
401     tst     r2, #0xff0000
402     beq     strcpy_unalign_copy3bytes
403     lsrs    ip, r2, #24
404     beq     strcpy_unalign_copy4bytes
406     sub     ip, r3, #0x01010101
407     bic     ip, ip, r3
408     ands    ip, ip, #0x80808080
409     bne     strcpy_zero_in_second_register
411     stmia   r0!, {r2, r3}
412     b       strcpy_unalign2
414     .p2align 2
415     // Can read 1 byte before possibly crossing a page.
416 strcpy_unalign1:
417     ldrb    r2, [r1]
418     cbz     r2, strcpy_unalign_copy1byte
420     ldr     r2, [r1], #4
421     ldr     r3, [r1], #4
423     pld     [r1, #64]
425     sub     ip, r2, #0x01010101
426     bic     ip, ip, r2
427     ands    ip, ip, #0x80808080
428     bne     strcpy_zero_in_first_register
430     sub     ip, r3, #0x01010101
431     bic     ip, ip, r3
432     ands    ip, ip, #0x80808080
433     bne     strcpy_zero_in_second_register
435     stmia   r0!, {r2, r3}
436     b       strcpy_unalign1
438 strcpy_unalign_copy1byte:
439     strb    r2, [r0]
440     m_ret   inst=pop
442 strcpy_unalign_copy2bytes:
443     strb    r2, [r0], #1
444     strb    r3, [r0]
445     m_ret   inst=pop
447 strcpy_unalign_copy3bytes:
448     strh    r2, [r0], #2
449     lsr     r2, #16
450     strb    r2, [r0]
451     m_ret   inst=pop
453 strcpy_unalign_copy4bytes:
454     stmia   r0, {r2}
455     m_ret   inst=pop
456 END(strcpy)