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