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