1/* The assembly function for memcpy.  C-SKY ABIV2 version.
2   Copyright (C) 2018-2022 Free Software Foundation, Inc.
3   This file is part of the GNU C Library.
4
5   The GNU C Library is free software; you can redistribute it and/or
6   modify it under the terms of the GNU Lesser General Public
7   License as published by the Free Software Foundation; either
8   version 2.1 of the License, or (at your option) any later version.
9
10   The GNU C Library is distributed in the hope that it will be useful,
11   but WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13   Lesser General Public License for more details.
14
15   You should have received a copy of the GNU Lesser General Public
16   License along with the GNU C Library.  If not, see
17   <https://www.gnu.org/licenses/>.  */
18
19#include <sysdep.h>
20
21ENTRY (memcpy)
22	/* Test if len less than 4 bytes.  */
23	mov	r12, r0
24	cmplti	r2, 4
25	bt	.L_copy_by_byte
26
27	andi	r13, r0, 3
28	movi	r19, 4
29	/* Test if dest is not 4 bytes aligned.  */
30	bnez	r13, .L_dest_not_aligned
31.L_dest_aligned:
32	/* If dest is aligned, then copy.  */
33	zext	r18, r2, 31, 4
34	/* Test if len less than 16 bytes.  */
35	bez	r18, .L_len_less_16bytes
36	movi	r19, 0
37
38	LABLE_ALIGN
39.L_len_larger_16bytes:
40#if defined (__CSKY_VDSPV2__)
41	vldx.8	vr0, (r1), r19
42	PRE_BNEZAD (r18)
43	addi	r1, 16
44	vstx.8	vr0, (r0), r19
45	addi	r0, 16
46#elif defined (__csky_fpuv2__) && defined(__CK810__)
47	fldd	fr4, (r1, 0)
48	PRE_BNEZAD (r18)
49	fstd	fr4, (r0, 0)
50	fldd	fr4, (r1, 8)
51	addi	r1, 16
52	fstd	fr4, (r0, 8)
53	addi	r0, 16
54#elif defined (__CK860__)
55	ldw	r3, (r1, 0)
56	stw	r3, (r0, 0)
57	ldw	r3, (r1, 4)
58	stw	r3, (r0, 4)
59	ldw	r3, (r1, 8)
60	stw	r3, (r0, 8)
61	ldw	r3, (r1, 12)
62	addi	r1, 16
63	stw	r3, (r0, 12)
64	addi	r0, 16
65#else
66	ldw	r20, (r1, 0)
67	ldw	r21, (r1, 4)
68	ldw	r22, (r1, 8)
69	ldw	r23, (r1, 12)
70	stw	r20, (r0, 0)
71	stw	r21, (r0, 4)
72	stw	r22, (r0, 8)
73	stw	r23, (r0, 12)
74	PRE_BNEZAD (r18)
75	addi	r1, 16
76	addi	r0, 16
77#endif
78	BNEZAD (r18, .L_len_larger_16bytes)
79
80.L_len_less_16bytes:
81	zext	r18, r2, 3, 2
82	bez	r18, .L_copy_by_byte
83.L_len_less_16bytes_loop:
84	ldw	r3, (r1, 0)
85	PRE_BNEZAD (r18)
86	addi	r1, 4
87	stw	r3, (r0, 0)
88	addi	r0, 4
89	BNEZAD (r18, .L_len_less_16bytes_loop)
90
91	/* Test if len less than 4 bytes.  */
92.L_copy_by_byte:
93	zext	r18, r2, 1, 0
94	bez	r18, .L_return
95.L_copy_by_byte_loop:
96	ldb	r3, (r1, 0)
97	PRE_BNEZAD (r18)
98	addi	r1, 1
99	stb	r3, (r0, 0)
100	addi	r0, 1
101	BNEZAD (r18, .L_copy_by_byte_loop)
102
103.L_return:
104	mov	r0, r12
105	rts
106
107	/* If dest is not aligned, just copying some bytes makes the dest
108	   align.  */
109
110.L_dest_not_aligned:
111	sub	r13, r19, r13
112	mov	r19, r13
113.L_dest_not_aligned_loop:
114	/* Makes the dest align.  */
115	ldb	r3, (r1, 0)
116	PRE_BNEZAD (r13)
117	addi	r1, 1
118	stb	r3, (r0, 0)
119	addi	r0, 1
120	BNEZAD (r13, .L_dest_not_aligned_loop)
121	sub	r2, r19
122	cmplti	r2, 4
123	bt	.L_copy_by_byte
124	/* Check whether the src is aligned.  */
125	br	.L_dest_aligned
126END (memcpy)
127
128libc_hidden_builtin_def (memcpy)
129.weak memcpy
130
131
132ENTRY (memmove)
133	subu	r3, r0, r1
134	cmphs	r3, r2
135	bt	memcpy
136
137	mov	r12, r0
138	addu	r0, r0, r2
139	addu	r1, r1, r2
140
141	/* Test if len less than 4 bytes.  */
142	cmplti	r2, 4
143	bt	.L_copy_by_byte_m
144
145	andi	r13, r0, 3
146	/* Test if dest is not 4 bytes aligned.  */
147	bnez	r13, .L_dest_not_aligned_m
148.L_dest_aligned_m:
149	/* If dest is aligned, then copy.  */
150	zext	r18, r2, 31, 4
151	/* Test if len less than 16 bytes.  */
152	bez	r18, .L_len_less_16bytes_m
153	movi	r19, 0
154
155	/* len > 16 bytes */
156	LABLE_ALIGN
157.L_len_larger_16bytes_m:
158	subi	r1, 16
159	subi	r0, 16
160#if defined (__CSKY_VDSPV2__)
161	vldx.8	vr0, (r1), r19
162	PRE_BNEZAD (r18)
163	vstx.8	vr0, (r0), r19
164#elif defined (__csky_fpuv2__) && defined(__CK810__)
165	fldd	fr4, (r1, 8)
166	PRE_BNEZAD (r18)
167	fstd	fr4, (r0, 8)
168	fldd	fr4, (r1, 0)
169	fstd	fr4, (r0, 0)
170#elif defined (__CK860__)
171	ldw	r3, (r1, 12)
172	stw	r3, (r0, 12)
173	ldw	r3, (r1, 8)
174	stw	r3, (r0, 8)
175	ldw	r3, (r1, 4)
176	stw	r3, (r0, 4)
177	ldw	r3, (r1, 0)
178	stw	r3, (r0, 0)
179#else
180	ldw	r20, (r1, 0)
181	ldw	r21, (r1, 4)
182	ldw	r22, (r1, 8)
183	ldw	r23, (r1, 12)
184	stw	r20, (r0, 0)
185	stw	r21, (r0, 4)
186	stw	r22, (r0, 8)
187	stw	r23, (r0, 12)
188	PRE_BNEZAD (r18)
189#endif
190	BNEZAD (r18, .L_len_larger_16bytes_m)
191
192.L_len_less_16bytes_m:
193	zext	r18, r2, 3, 2
194	bez	r18, .L_copy_by_byte_m
195.L_len_less_16bytes_loop_m:
196	subi	r1, 4
197	subi	r0, 4
198	ldw	r3, (r1, 0)
199	PRE_BNEZAD (r18)
200	stw	r3, (r0, 0)
201	BNEZAD (r18, .L_len_less_16bytes_loop_m)
202
203	/* Test if len less than 4 bytes.  */
204.L_copy_by_byte_m:
205	zext	r18, r2, 1, 0
206	bez	r18, .L_return_m
207.L_copy_by_byte_loop_m:
208	subi	r1, 1
209	subi	r0, 1
210	ldb	r3, (r1, 0)
211	PRE_BNEZAD (r18)
212	stb	r3, (r0, 0)
213	BNEZAD (r18, .L_copy_by_byte_loop_m)
214
215.L_return_m:
216	mov	r0, r12
217	rts
218
219	/* If dest is not aligned, just copying some bytes makes the dest
220	   align.  */
221.L_dest_not_aligned_m:
222	sub	r2, r13
223.L_dest_not_aligned_loop_m:
224	subi	r1, 1
225	subi	r0, 1
226	/* Makes the dest align.  */
227	ldb	r3, (r1, 0)
228	PRE_BNEZAD (r13)
229	stb	r3, (r0, 0)
230	BNEZAD (r13, .L_dest_not_aligned_loop_m)
231	cmplti	r2, 4
232	bt	.L_copy_by_byte_m
233	/* Check whether the src is aligned.  */
234	br	.L_dest_aligned_m
235END (memmove)
236
237libc_hidden_builtin_def (memmove)
238.weak memmove
239