1/* SPDX-License-Identifier: GPL-2.0 */
2/* $Id: memmove.S,v 1.2 2001/07/27 11:51:09 gniibe Exp $
3 *
4 * "memmove" implementation of SuperH
5 *
6 * Copyright (C) 1999  Niibe Yutaka
7 *
8 */
9
10/*
11 * void *memmove(void *dst, const void *src, size_t n);
12 * The memory areas may overlap.
13 */
14
15#include <linux/linkage.h>
16ENTRY(memmove)
17	! if dest > src, call memcpy (it copies in decreasing order)
18	cmp/hi	r5,r4
19	bf	1f
20	mov.l	2f,r0
21	jmp	@r0
22	 nop
23	.balign 4
242:	.long	memcpy
251:
26	sub	r5,r4		! From here, r4 has the distance to r0
27	tst	r6,r6
28	bt/s	9f		! if n=0, do nothing
29	 mov	r5,r0
30	add	r6,r5
31	mov	#12,r1
32	cmp/gt	r6,r1
33	bt/s	8f		! if it's too small, copy a byte at once
34	 add	#-1,r4
35	add	#1,r4
36	!
37	!                [ ...  ] DST             [ ...  ] SRC
38	!	         [ ...  ]                 [ ...  ]
39	!	           :                        :
40	!      r0+r4-->  [ ...  ]       r0    --> [ ...  ]
41	!	           :                        :
42	!	         [ ...  ]                 [ ...  ]
43	!			        r5    -->
44	!
45	mov	r4,r1
46	mov	#3,r2
47	and	r2,r1
48	shll2	r1
49	mov	r0,r3		! Save the value on R0 to R3
50	mova	jmptable,r0
51	add	r1,r0
52	mov.l	@r0,r1
53	jmp	@r1
54	 mov	r3,r0		! and back to R0
55	.balign	4
56jmptable:
57	.long	case0
58	.long	case1
59	.long	case2
60	.long	case3
61
62	! copy a byte at once
638:	mov.b	@r0+,r1
64	cmp/hs	r5,r0
65	bf/s	8b			! while (r0<r5)
66	 mov.b	r1,@(r0,r4)
67	add	#1,r4
689:
69	add	r4,r0
70	rts
71	 sub	r6,r0
72
73case_none:
74	bra	8b
75	 add	#-1,r4
76
77case0:
78	!
79	!	GHIJ KLMN OPQR -->  GHIJ KLMN OPQR
80	!
81	! First, align to long word boundary
82	mov	r0,r3
83	and	r2,r3
84	tst	r3,r3
85	bt/s	2f
86	 add	#-1,r4
87	mov	#4,r2
88	sub	r3,r2
891:	dt	r2
90	mov.b	@r0+,r1
91	bf/s	1b
92	 mov.b	r1,@(r0,r4)
93	!
942:	! Second, copy a long word at once
95	add	#-3,r4
96	add	#-3,r5
973:	mov.l	@r0+,r1
98	cmp/hs	r5,r0
99	bf/s	3b
100	 mov.l	r1,@(r0,r4)
101	add	#3,r5
102	!
103	! Third, copy a byte at once, if necessary
104	cmp/eq	r5,r0
105	bt/s	9b
106	 add	#4,r4
107	bra	8b
108	 add	#-1,r4
109
110case3:
111	!
112	!	GHIJ KLMN OPQR -->  ...G HIJK LMNO PQR.
113	!
114	! First, align to long word boundary
115	mov	r0,r3
116	and	r2,r3
117	tst	r3,r3
118	bt/s	2f
119	 add	#-1,r4
120	mov	#4,r2
121	sub	r3,r2
1221:	dt	r2
123	mov.b	@r0+,r1
124	bf/s	1b
125	 mov.b	r1,@(r0,r4)
126	!
1272:	! Second, read a long word and write a long word at once
128	add	#-2,r4
129	mov.l	@(r0,r4),r1
130	add	#-7,r5
131	add	#-4,r4
132	!
133#ifdef __LITTLE_ENDIAN__
134	shll8	r1
1353:	mov	r1,r3		! JIHG
136	shlr8	r3		! xJIH
137	mov.l	@r0+,r1		! NMLK
138	mov	r1,r2
139	shll16	r2
140	shll8	r2		! Kxxx
141	or	r2,r3		! KJIH
142	cmp/hs	r5,r0
143	bf/s	3b
144	 mov.l	r3,@(r0,r4)
145#else
146	shlr8	r1
1473:	mov	r1,r3		! GHIJ
148	shll8	r3		! HIJx
149	mov.l	@r0+,r1		! KLMN
150	mov	r1,r2
151	shlr16	r2
152	shlr8	r2		! xxxK
153	or	r2,r3		! HIJK
154	cmp/hs	r5,r0
155	bf/s	3b
156	 mov.l	r3,@(r0,r4)
157#endif
158	add	#7,r5
159	!
160	! Third, copy a byte at once, if necessary
161	cmp/eq	r5,r0
162	bt/s	9b
163	 add	#7,r4
164	add	#-3,r0
165	bra	8b
166	 add	#-1,r4
167
168case2:
169	!
170	!	GHIJ KLMN OPQR -->  ..GH IJKL MNOP QR..
171	!
172	! First, align to word boundary
173	tst	#1,r0
174	bt/s	2f
175	 add	#-1,r4
176	mov.b	@r0+,r1
177	mov.b	r1,@(r0,r4)
178	!
1792:	! Second, read a word and write a word at once
180	add	#-1,r4
181	add	#-1,r5
182	!
1833:	mov.w	@r0+,r1
184	cmp/hs	r5,r0
185	bf/s	3b
186	 mov.w	r1,@(r0,r4)
187	add	#1,r5
188	!
189	! Third, copy a byte at once, if necessary
190	cmp/eq	r5,r0
191	bt/s	9b
192	 add	#2,r4
193	mov.b	@r0,r1
194	mov.b	r1,@(r0,r4)
195	bra	9b
196	 add	#1,r0
197
198case1:
199	!
200	!	GHIJ KLMN OPQR -->  .GHI JKLM NOPQ R...
201	!
202	! First, align to long word boundary
203	mov	r0,r3
204	and	r2,r3
205	tst	r3,r3
206	bt/s	2f
207	 add	#-1,r4
208	mov	#4,r2
209	sub	r3,r2
2101:	dt	r2
211	mov.b	@r0+,r1
212	bf/s	1b
213	 mov.b	r1,@(r0,r4)
214	!
2152:	! Second, read a long word and write a long word at once
216	mov.l	@(r0,r4),r1
217	add	#-7,r5
218	add	#-4,r4
219	!
220#ifdef __LITTLE_ENDIAN__
221	shll16	r1
222	shll8	r1
2233:	mov	r1,r3		! JIHG
224	shlr16	r3
225	shlr8	r3		! xxxJ
226	mov.l	@r0+,r1		! NMLK
227	mov	r1,r2
228	shll8	r2		! MLKx
229	or	r2,r3		! MLKJ
230	cmp/hs	r5,r0
231	bf/s	3b
232	 mov.l	r3,@(r0,r4)
233#else
234	shlr16	r1
235	shlr8	r1
2363:	mov	r1,r3		! GHIJ
237	shll16	r3
238	shll8	r3		! Jxxx
239	mov.l	@r0+,r1		! KLMN
240	mov	r1,r2
241	shlr8	r2		! xKLM
242	or	r2,r3		! JKLM
243	cmp/hs	r5,r0
244	bf/s	3b		! while(r0<r5)
245	 mov.l	r3,@(r0,r4)
246#endif
247	add	#7,r5
248	!
249	! Third, copy a byte at once, if necessary
250	cmp/eq	r5,r0
251	bt/s	9b
252	 add	#5,r4
253	add	#-3,r0
254	bra	8b
255	 add	#-1,r4
256