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 | |