1/* SPDX-License-Identifier: GPL-2.0 */
2/* $Id: memcpy.S,v 1.3 2001/07/27 11:50:52 gniibe Exp $
3 *
4 * "memcpy" implementation of SuperH
5 *
6 * Copyright (C) 1999  Niibe Yutaka
7 *
8 */
9
10/*
11 * void *memcpy(void *dst, const void *src, size_t n);
12 * No overlap between the memory of DST and of SRC are assumed.
13 */
14
15#include <linux/linkage.h>
16ENTRY(memcpy)
17	tst	r6,r6
18	bt/s	9f		! if n=0, do nothing
19	 mov	r4,r0
20	sub	r4,r5		! From here, r5 has the distance to r0
21	add	r6,r0		! From here, r0 points the end of copying point
22	mov	#12,r1
23	cmp/gt	r6,r1
24	bt/s	7f		! if it's too small, copy a byte at once
25	 add	#-1,r5
26	add	#1,r5
27	!			From here, r6 is free
28	!
29	!      r4   -->  [ ...  ] DST             [ ...  ] SRC
30	!	         [ ...  ]                 [ ...  ]
31	!	           :                        :
32	!      r0   -->  [ ...  ]       r0+r5 --> [ ...  ]
33	!
34	!
35	mov	r5,r1
36	mov	#3,r2
37	and	r2,r1
38	shll2	r1
39	mov	r0,r3		! Save the value on R0 to R3
40	mova	jmptable,r0
41	add	r1,r0
42	mov.l	@r0,r1
43	jmp	@r1
44	 mov	r3,r0		! and back to R0
45	.balign	4
46jmptable:
47	.long	case0
48	.long	case1
49	.long	case2
50	.long	case3
51
52	! copy a byte at once
537:	mov	r4,r2
54	add	#1,r2
558:
56	cmp/hi	r2,r0
57	mov.b	@(r0,r5),r1
58	bt/s	8b			! while (r0>r2)
59	 mov.b	r1,@-r0
609:
61	rts
62	 nop
63
64case0:
65	!
66	!	GHIJ KLMN OPQR -->  GHIJ KLMN OPQR
67	!
68	! First, align to long word boundary
69	mov	r0,r3
70	and	r2,r3
71	tst	r3,r3
72	bt/s	2f
73	 add	#-4,r5
74	add	#3,r5
751:	dt	r3
76	mov.b	@(r0,r5),r1
77	bf/s	1b
78	 mov.b	r1,@-r0
79	!
80	add	#-3,r5
812:	! Second, copy a long word at once
82	mov	r4,r2
83	add	#7,r2
843:	mov.l	@(r0,r5),r1
85	cmp/hi	r2,r0
86	bt/s	3b
87	 mov.l	r1,@-r0
88	!
89	! Third, copy a byte at once, if necessary
90	cmp/eq	r4,r0
91	bt/s	9b
92	 add	#3,r5
93	bra	8b
94	 add	#-6,r2
95
96case1:
97	!
98	!	GHIJ KLMN OPQR -->  ...G HIJK LMNO PQR.
99	!
100	! First, align to long word boundary
101	mov	r0,r3
102	and	r2,r3
103	tst	r3,r3
104	bt/s	2f
105	 add	#-1,r5
1061:	dt	r3
107	mov.b	@(r0,r5),r1
108	bf/s	1b
109	 mov.b	r1,@-r0
110	!
1112:	! Second, read a long word and write a long word at once
112	mov.l	@(r0,r5),r1
113	add	#-4,r5
114	mov	r4,r2
115	add	#7,r2
116	!
117#ifdef __LITTLE_ENDIAN__
1183:	mov	r1,r3		! RQPO
119	shll16	r3
120	shll8	r3		! Oxxx
121	mov.l	@(r0,r5),r1	! NMLK
122	mov	r1,r6
123	shlr8	r6		! xNML
124	or	r6,r3		! ONML
125	cmp/hi	r2,r0
126	bt/s	3b
127	 mov.l	r3,@-r0
128#else
1293:	mov	r1,r3		! OPQR
130	shlr16	r3
131	shlr8	r3		! xxxO
132	mov.l	@(r0,r5),r1	! KLMN
133	mov	r1,r6
134	shll8	r6		! LMNx
135	or	r6,r3		! LMNO
136	cmp/hi	r2,r0
137	bt/s	3b
138	 mov.l	r3,@-r0
139#endif
140	!
141	! Third, copy a byte at once, if necessary
142	cmp/eq	r4,r0
143	bt/s	9b
144	 add	#4,r5
145	bra	8b
146	 add	#-6,r2
147
148case2:
149	!
150	!	GHIJ KLMN OPQR -->  ..GH IJKL MNOP QR..
151	!
152	! First, align to word boundary
153	tst	#1,r0
154	bt/s	2f
155	 add	#-1,r5
156	mov.b	@(r0,r5),r1
157	mov.b	r1,@-r0
158	!
1592:	! Second, read a word and write a word at once
160	add	#-1,r5
161	mov	r4,r2
162	add	#3,r2
163	!
1643:	mov.w	@(r0,r5),r1
165	cmp/hi	r2,r0
166	bt/s	3b
167	 mov.w	r1,@-r0
168	!
169	! Third, copy a byte at once, if necessary
170	cmp/eq	r4,r0
171	bt/s	9b
172	 add	#1,r5
173	mov.b	@(r0,r5),r1
174	rts
175	 mov.b	r1,@-r0
176
177case3:
178	!
179	!	GHIJ KLMN OPQR -->  .GHI JKLM NOPQ R...
180	!
181	! First, align to long word boundary
182	mov	r0,r3
183	and	r2,r3
184	tst	r3,r3
185	bt/s	2f
186	 add	#-1,r5
1871:	dt	r3
188	mov.b	@(r0,r5),r1
189	bf/s	1b
190	 mov.b	r1,@-r0
191	!
1922:	! Second, read a long word and write a long word at once
193	add	#-2,r5
194	mov.l	@(r0,r5),r1
195	add	#-4,r5
196	mov	r4,r2
197	add	#7,r2
198	!
199#ifdef __LITTLE_ENDIAN__
2003:	mov	r1,r3		! RQPO
201	shll8	r3		! QPOx
202	mov.l	@(r0,r5),r1	! NMLK
203	mov	r1,r6
204	shlr16	r6
205	shlr8	r6		! xxxN
206	or	r6,r3		! QPON
207	cmp/hi	r2,r0
208	bt/s	3b
209	 mov.l	r3,@-r0
210#else
2113:	mov	r1,r3		! OPQR
212	shlr8	r3		! xOPQ
213	mov.l	@(r0,r5),r1	! KLMN
214	mov	r1,r6
215	shll16	r6
216	shll8	r6		! Nxxx
217	or	r6,r3		! NOPQ
218	cmp/hi	r2,r0
219	bt/s	3b
220	 mov.l	r3,@-r0
221#endif
222	!
223	! Third, copy a byte at once, if necessary
224	cmp/eq	r4,r0
225	bt/s	9b
226	 add	#6,r5
227	bra	8b
228	 add	#-6,r2
229