1/*
2 * strcpy
3 *
4 * Copyright (c) 2008-2020, Arm Limited.
5 * SPDX-License-Identifier: MIT
6 */
7
8/* For GLIBC:
9#include <string.h>
10#include <memcopy.h>
11
12#undef strcmp
13*/
14
15#ifdef __thumb2__
16#define magic1(REG) "#0x01010101"
17#define magic2(REG) "#0x80808080"
18#else
19#define magic1(REG) #REG
20#define magic2(REG) #REG ", lsl #7"
21#endif
22
23char* __attribute__((naked))
24__strcpy_arm (char* dst, const char* src)
25{
26  __asm__ (
27       "pld	[r1, #0]\n\t"
28       "eor	r2, r0, r1\n\t"
29       "mov	ip, r0\n\t"
30       "tst	r2, #3\n\t"
31       "bne	4f\n\t"
32       "tst	r1, #3\n\t"
33       "bne	3f\n"
34  "5:\n\t"
35# ifndef __thumb2__
36       "str	r5, [sp, #-4]!\n\t"
37       "mov	r5, #0x01\n\t"
38       "orr	r5, r5, r5, lsl #8\n\t"
39       "orr	r5, r5, r5, lsl #16\n\t"
40# endif
41
42       "str	r4, [sp, #-4]!\n\t"
43       "tst	r1, #4\n\t"
44       "ldr	r3, [r1], #4\n\t"
45       "beq	2f\n\t"
46       "sub	r2, r3, "magic1(r5)"\n\t"
47       "bics	r2, r2, r3\n\t"
48       "tst	r2, "magic2(r5)"\n\t"
49       "itt	eq\n\t"
50       "streq	r3, [ip], #4\n\t"
51       "ldreq	r3, [r1], #4\n"
52       "bne	1f\n\t"
53       /* Inner loop.  We now know that r1 is 64-bit aligned, so we
54	  can safely fetch up to two words.  This allows us to avoid
55	  load stalls.  */
56       ".p2align 2\n"
57  "2:\n\t"
58       "pld	[r1, #8]\n\t"
59       "ldr	r4, [r1], #4\n\t"
60       "sub	r2, r3, "magic1(r5)"\n\t"
61       "bics	r2, r2, r3\n\t"
62       "tst	r2, "magic2(r5)"\n\t"
63       "sub	r2, r4, "magic1(r5)"\n\t"
64       "bne	1f\n\t"
65       "str	r3, [ip], #4\n\t"
66       "bics	r2, r2, r4\n\t"
67       "tst	r2, "magic2(r5)"\n\t"
68       "itt	eq\n\t"
69       "ldreq	r3, [r1], #4\n\t"
70       "streq	r4, [ip], #4\n\t"
71       "beq	2b\n\t"
72       "mov	r3, r4\n"
73  "1:\n\t"
74# ifdef __ARMEB__
75       "rors	r3, r3, #24\n\t"
76# endif
77       "strb	r3, [ip], #1\n\t"
78       "tst	r3, #0xff\n\t"
79# ifdef __ARMEL__
80       "ror	r3, r3, #8\n\t"
81# endif
82       "bne	1b\n\t"
83       "ldr	r4, [sp], #4\n\t"
84# ifndef __thumb2__
85       "ldr	r5, [sp], #4\n\t"
86# endif
87       "BX LR\n"
88
89       /* Strings have the same offset from word alignment, but it's
90	  not zero.  */
91  "3:\n\t"
92       "tst	r1, #1\n\t"
93       "beq	1f\n\t"
94       "ldrb	r2, [r1], #1\n\t"
95       "strb	r2, [ip], #1\n\t"
96       "cmp	r2, #0\n\t"
97       "it	eq\n"
98       "BXEQ LR\n"
99  "1:\n\t"
100       "tst	r1, #2\n\t"
101       "beq	5b\n\t"
102       "ldrh	r2, [r1], #2\n\t"
103# ifdef __ARMEB__
104       "tst	r2, #0xff00\n\t"
105       "iteet	ne\n\t"
106       "strneh	r2, [ip], #2\n\t"
107       "lsreq	r2, r2, #8\n\t"
108       "streqb	r2, [ip]\n\t"
109       "tstne	r2, #0xff\n\t"
110# else
111       "tst	r2, #0xff\n\t"
112       "itet	ne\n\t"
113       "strneh	r2, [ip], #2\n\t"
114       "streqb	r2, [ip]\n\t"
115       "tstne	r2, #0xff00\n\t"
116# endif
117       "bne	5b\n\t"
118       "BX LR\n"
119
120       /* src and dst do not have a common word-alignement.  Fall back to
121	  byte copying.  */
122  "4:\n\t"
123       "ldrb	r2, [r1], #1\n\t"
124       "strb	r2, [ip], #1\n\t"
125       "cmp	r2, #0\n\t"
126       "bne	4b\n\t"
127       "BX LR");
128}
129/* For GLIBC: libc_hidden_builtin_def (strcpy) */
130