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>
16 ENTRY(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
24 2:	.long	memcpy
25 1:
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
56 jmptable:
57 	.long	case0
58 	.long	case1
59 	.long	case2
60 	.long	case3
61 
62 	! copy a byte at once
63 8:	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
68 9:
69 	add	r4,r0
70 	rts
71 	 sub	r6,r0
72 
73 case_none:
74 	bra	8b
75 	 add	#-1,r4
76 
77 case0:
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
89 1:	dt	r2
90 	mov.b	@r0+,r1
91 	bf/s	1b
92 	 mov.b	r1,@(r0,r4)
93 	!
94 2:	! Second, copy a long word at once
95 	add	#-3,r4
96 	add	#-3,r5
97 3:	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 
110 case3:
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
122 1:	dt	r2
123 	mov.b	@r0+,r1
124 	bf/s	1b
125 	 mov.b	r1,@(r0,r4)
126 	!
127 2:	! 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
135 3:	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
147 3:	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 
168 case2:
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 	!
179 2:	! Second, read a word and write a word at once
180 	add	#-1,r4
181 	add	#-1,r5
182 	!
183 3:	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 
198 case1:
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
210 1:	dt	r2
211 	mov.b	@r0+,r1
212 	bf/s	1b
213 	 mov.b	r1,@(r0,r4)
214 	!
215 2:	! 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
223 3:	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
236 3:	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