1/* Copyright (C) 1999-2021 Free Software Foundation, Inc.
2   This file is part of the GNU C Library.
3
4   The GNU C Library is free software; you can redistribute it and/or
5   modify it under the terms of the GNU Lesser General Public
6   License as published by the Free Software Foundation; either
7   version 2.1 of the License, or (at your option) any later version.
8
9   The GNU C Library is distributed in the hope that it will be useful,
10   but WITHOUT ANY WARRANTY; without even the implied warranty of
11   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12   Lesser General Public License for more details.
13
14   You should have received a copy of the GNU Lesser General Public
15   License along with the GNU C Library; if not, see
16   <https://www.gnu.org/licenses/>.  */
17
18#include <sysdep.h>
19
20/* void *memcpy(void *dst, const void *src, size_t n);
21    No overlap between the memory of DST and of SRC are assumed.  */
22
23ENTRY(memcpy)
24	mov	r4,r3		/* Save destination.  */
25
26	/* If less than 11 bytes, just do a byte copy.  */
27	mov	#11,r0
28	cmp/gt	r6,r0
29	bt	L_byteloop_init
30
31	/* Check if we need to word-align source.  */
32	mov	r5,r0
33	tst	#1,r0
34	bt	L_wordalign
35
36	mov.b	@r0+,r1		/* Copy one byte.  */
37	add	#-1,r6
38	mov.b	r1,@r4
39	add	#1,r4
40
41	.balignw 4,0x0009
42L_wordalign:
43	/* Check if we need to longword-align source.  */
44	tst	#2,r0
45	bt	L_copy
46
47	mov.w	@r0+,r1		/* Copy one word.  */
48	add	#-2,r6
49#ifdef __BIG_ENDIAN__
50	add	#1,r4
51	mov.b	r1,@r4
52	shlr8	r1
53	mov.b	r1,@-r4
54	add	#2,r4
55#else
56	mov.b	r1,@r4
57	add	#1,r4
58	shlr8	r1
59	mov.b	r1,@r4
60	add	#1,r4
61#endif
62L_copy:
63	mov	r0,r5
64
65	/* Calculate the correct routine to handle the destination
66	   alignment and simultaneously calculate the loop counts for
67	   both the 2 word copy loop and byte copy loop.  */
68	mova	L_jumptable,r0
69	mov	r0,r1
70	mov	r4,r0
71	mov	r6,r7
72	and	#3,r0
73	shlr2	r7
74	shll	r0
75	shlr	r7
76	mov.w	@(r0,r1),r2
77	mov	#7,r0
78	braf	r2
79	and	r0,r6
80L_base:
81
82	.balign	4
83L_jumptable:
84	.word	L_copydest0 - L_base
85	.word	L_copydest1_or_3 - L_base
86	.word	L_copydest2 - L_base
87	.word	L_copydest1_or_3 - L_base
88
89	.balign	4
90	/* Copy routine for (dest mod 4) == 1 or == 3.  */
91L_copydest1_or_3:
92	add	#-1,r4
93	.balignw 4,0x0009
94L_copydest1_or_3_loop:
95	mov.l	@r5+,r0		/* Read first longword.  */
96	dt	r7
97	mov.l	@r5+,r1		/* Read second longword.  */
98#ifdef __BIG_ENDIAN__
99	/* Write first longword as byte, word, byte.  */
100	mov.b	r0,@(4,r4)
101	shlr8	r0
102	mov.w	r0,@(2,r4)
103	shlr16	r0
104	mov.b	r0,@(1,r4)
105	mov	r1,r0
106	/* Write second longword as byte, word, byte.  */
107	mov.b	r0,@(8,r4)
108	shlr8	r0
109	mov.w	r0,@(6,r4)
110	shlr16	r0
111	mov.b	r0,@(5,r4)
112#else
113	/* Write first longword as byte, word, byte.  */
114	mov.b	r0,@(1,r4)
115	shlr8	r0
116	mov.w	r0,@(2,r4)
117	shlr16	r0
118	mov.b	r0,@(4,r4)
119	mov	r1,r0
120	/* Write second longword as byte, word, byte.  */
121	mov.b	r0,@(5,r4)
122	shlr8	r0
123	mov.w	r0,@(6,r4)
124	shlr16	r0
125	mov.b	r0,@(8,r4)
126#endif
127	bf/s	L_copydest1_or_3_loop
128	add	#8,r4
129
130	bra	L_byteloop_init
131	add	#1,r4
132
133	.balign 4
134	/* Copy routine for (dest mod 4) == 2.  */
135L_copydest2:
136L_copydest2_loop:
137	mov.l	@r5+,r0
138	dt	r7
139	mov.l	@r5+,r1
140#ifdef __BIG_ENDIAN__
141	mov.w	r0,@(2,r4)
142	shlr16	r0
143	mov.w	r0,@r4
144	mov	r1,r0
145	mov.w	r0,@(6,r4)
146	shlr16	r0
147	mov.w	r0,@(4,r4)
148#else
149	mov.w	r0,@r4
150	shlr16	r0
151	mov.w	r0,@(2,r4)
152	mov	r1,r0
153	mov.w	r0,@(4,r4)
154	shlr16	r0
155	mov.w	r0,@(6,r4)
156#endif
157	bf/s	L_copydest2_loop
158	add	#8,r4
159
160	bra	L_byteloop_init
161	nop
162
163	.balign 4
164	/* Copy routine for (dest mod 4) == 0.  */
165L_copydest0:
166	add	#-8,r4
167	.balignw 4,0x0009
168L_copydest0_loop:
169	mov.l	@r5+,r0
170	dt	r7
171	mov.l	@r5+,r1
172	add	#8,r4
173	mov.l	r0,@r4
174	bf/s	L_copydest0_loop
175	mov.l	r1,@(4,r4)
176
177	add	#8,r4		/* Fall through.  */
178
179L_byteloop_init:
180	tst	r6,r6
181	bt	L_exit
182
183	.balignw 4,0x0009
184	/* Copy remaining bytes.  */
185L_byteloop:
186	mov.b	@r5+,r0
187	dt	r6
188	mov.b	r0,@r4
189	bf/s	L_byteloop
190	add	#1,r4
191
192L_exit:
193	rts
194	mov	r3,r0		/* Return destination.  */
195END(memcpy)
196libc_hidden_builtin_def (memcpy)
197