1/*
2 * Copyright (c) 2008 ARM Ltd
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 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. The name of the company may not be used to endorse or promote
14 *    products derived from this software without specific prior written
15 *    permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY ARM LTD ``AS IS'' AND ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL ARM LTD BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
22 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
25 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <picolibc.h>
30
31#include "arm_asm.h"
32
33#ifdef __thumb2__
34#define magic1(REG) #0x01010101
35#define magic2(REG) #0x80808080
36#else
37#define magic1(REG) REG
38#define magic2(REG) REG , lsl #7
39#endif
40
41        .syntax unified
42#ifdef __thumb__
43	.thumb
44#endif
45	.text
46	.global strcpy
47	.type strcpy, %function
48strcpy:
49	.fnstart
50	.cfi_sections .debug_frame
51	.cfi_startproc
52	prologue push_ip=HAVE_PAC_LEAF
53
54#if !(defined(__OPTIMIZE_SIZE__) || defined (PREFER_SIZE_OVER_SPEED) || \
55      (defined (__thumb__) && !defined (__thumb2__)))
56
57#ifdef _ISA_ARM_7
58        pld	[r1]
59#endif
60        eor	r2, r0, r1
61        mov	ip, r0
62        tst	r2, #3
63        bne	4f
64        tst	r1, #3
65        bne	3f
665:
67#ifndef __thumb2__
68        str	r5, [sp, #-4]!
69        mov	r5, #0x01
70        orr	r5, r5, r5, lsl #8
71        orr	r5, r5, r5, lsl #16
72#endif
73
74        str	r4, [sp, #-4]!
75        tst	r1, #4
76        ldr	r3, [r1], #4
77        beq	2f
78        sub	r2, r3, magic1(r5)
79        bics	r2, r2, r3
80        tst	r2, magic2(r5)
81        itt	eq
82        streq	r3, [ip], #4
83        ldreq	r3, [r1], #4
84        bne	1f
85       /* Inner loop.  We now know that r1 is 64-bit aligned, so we
86	  can safely fetch up to two words.  This allows us to avoid
87	  load stalls.  */
88        .p2align 2
892:
90#ifdef _ISA_ARM_7
91        pld	[r1, #8]
92#endif
93        ldr	r4, [r1], #4
94        sub	r2, r3, magic1(r5)
95        bics	r2, r2, r3
96        tst	r2, magic2(r5)
97        sub	r2, r4, magic1(r5)
98        bne	1f
99        str	r3, [ip], #4
100        bics	r2, r2, r4
101        tst	r2, magic2(r5)
102        itt	eq
103        ldreq	r3, [r1], #4
104        streq	r4, [ip], #4
105        beq	2b
106        mov	r3, r4
1071:
108#ifdef __ARMEB__
109        rors	r3, r3, #24
110#endif
111        strb	r3, [ip], #1
112        tst	r3, #0xff
113#ifdef __ARMEL__
114        ror	r3, r3, #8
115#endif
116        bne	1b
117        ldr	r4, [sp], #4
118#ifndef __thumb2__
119        ldr	r5, [sp], #4
120#endif
121        bx	lr
122
123       /* Strings have the same offset from word alignment, but it's
124	  not zero.  */
1253:
126        tst	r1, #1
127        beq	1f
128        ldrb	r2, [r1], #1
129        strb	r2, [ip], #1
130        cmp	r2, #0
131        it	eq
132        bxeq	lr
1331:
134        tst	r1, #2
135        beq	5b
136        ldrh	r2, [r1], #2
137#ifdef __ARMEB__
138        tst	r2, #0xff00
139        iteet	ne
140        strhne	r2, [ip], #2
141        lsreq	r2, r2, #8
142        strbeq	r2, [ip]
143        tstne	r2, #0xff
144#else
145        tst	r2, #0xff
146        itet	ne
147        strhne	r2, [ip], #2
148        strbeq	r2, [ip]
149        tstne	r2, #0xff00
150#endif
151        bne	5b
152	.cfi_remember_state
153	epilogue push_ip=HAVE_PAC_LEAF
154	.cfi_restore_state
155
156       /* src and dst do not have a common word-alignement.  Fall back to
157	  byte copying.  */
1584:
159        ldrb	r2, [r1], #1
160        strb	r2, [ip], #1
161        cmp	r2, #0
162        bne	4b
163
164#elif !defined (__thumb__) || defined (__thumb2__)
165        mov	r3, r0
166        1:
167        ldrb	r2, [r1], #1
168        strb	r2, [r3], #1
169        cmp	r2, #0
170        bne	1b
171#else
172        movs	r3, r0
1731:
174        ldrb	r2, [r1]
175        adds	r1, #1
176        strb	r2, [r3]
177        adds	r3, #1
178        cmp	r2, #0
179        bne	1b
180#endif
181	epilogue push_ip=HAVE_PAC_LEAF
182	.cfi_endproc
183	.cantunwind
184	.fnend
185	.size strcpy, . - strcpy
186
187#if defined(__linux__) && defined(__ELF__)
188.section .note.GNU-stack,"",%progbits
189#endif
190