diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /arch/sh/mm/copy_page.S |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'arch/sh/mm/copy_page.S')
-rw-r--r-- | arch/sh/mm/copy_page.S | 397 |
1 files changed, 397 insertions, 0 deletions
diff --git a/arch/sh/mm/copy_page.S b/arch/sh/mm/copy_page.S new file mode 100644 index 000000000000..1addffe117c3 --- /dev/null +++ b/arch/sh/mm/copy_page.S | |||
@@ -0,0 +1,397 @@ | |||
1 | /* $Id: copy_page.S,v 1.8 2003/08/25 17:03:10 lethal Exp $ | ||
2 | * | ||
3 | * copy_page, __copy_user_page, __copy_user implementation of SuperH | ||
4 | * | ||
5 | * Copyright (C) 2001 Niibe Yutaka & Kaz Kojima | ||
6 | * Copyright (C) 2002 Toshinobu Sugioka | ||
7 | * | ||
8 | */ | ||
9 | #include <linux/linkage.h> | ||
10 | |||
11 | /* | ||
12 | * copy_page_slow | ||
13 | * @to: P1 address | ||
14 | * @from: P1 address | ||
15 | * | ||
16 | * void copy_page_slow(void *to, void *from) | ||
17 | */ | ||
18 | |||
19 | /* | ||
20 | * r0, r1, r2, r3, r4, r5, r6, r7 --- scratch | ||
21 | * r8 --- from + 4096 | ||
22 | * r9 --- not used | ||
23 | * r10 --- to | ||
24 | * r11 --- from | ||
25 | */ | ||
26 | ENTRY(copy_page_slow) | ||
27 | mov.l r8,@-r15 | ||
28 | mov.l r10,@-r15 | ||
29 | mov.l r11,@-r15 | ||
30 | mov r4,r10 | ||
31 | mov r5,r11 | ||
32 | mov r5,r8 | ||
33 | mov.w .L4096,r0 | ||
34 | add r0,r8 | ||
35 | ! | ||
36 | 1: mov.l @r11+,r0 | ||
37 | mov.l @r11+,r1 | ||
38 | mov.l @r11+,r2 | ||
39 | mov.l @r11+,r3 | ||
40 | mov.l @r11+,r4 | ||
41 | mov.l @r11+,r5 | ||
42 | mov.l @r11+,r6 | ||
43 | mov.l @r11+,r7 | ||
44 | #if defined(CONFIG_CPU_SH3) | ||
45 | mov.l r0,@r10 | ||
46 | #elif defined(CONFIG_CPU_SH4) | ||
47 | movca.l r0,@r10 | ||
48 | mov r10,r0 | ||
49 | #endif | ||
50 | add #32,r10 | ||
51 | mov.l r7,@-r10 | ||
52 | mov.l r6,@-r10 | ||
53 | mov.l r5,@-r10 | ||
54 | mov.l r4,@-r10 | ||
55 | mov.l r3,@-r10 | ||
56 | mov.l r2,@-r10 | ||
57 | mov.l r1,@-r10 | ||
58 | #if defined(CONFIG_CPU_SH4) | ||
59 | ocbwb @r0 | ||
60 | #endif | ||
61 | cmp/eq r11,r8 | ||
62 | bf/s 1b | ||
63 | add #28,r10 | ||
64 | ! | ||
65 | mov.l @r15+,r11 | ||
66 | mov.l @r15+,r10 | ||
67 | mov.l @r15+,r8 | ||
68 | rts | ||
69 | nop | ||
70 | |||
71 | #if defined(CONFIG_CPU_SH4) | ||
72 | /* | ||
73 | * __copy_user_page | ||
74 | * @to: P1 address (with same color) | ||
75 | * @from: P1 address | ||
76 | * @orig_to: P1 address | ||
77 | * | ||
78 | * void __copy_user_page(void *to, void *from, void *orig_to) | ||
79 | */ | ||
80 | |||
81 | /* | ||
82 | * r0, r1, r2, r3, r4, r5, r6, r7 --- scratch | ||
83 | * r8 --- from + 4096 | ||
84 | * r9 --- orig_to | ||
85 | * r10 --- to | ||
86 | * r11 --- from | ||
87 | */ | ||
88 | ENTRY(__copy_user_page) | ||
89 | mov.l r8,@-r15 | ||
90 | mov.l r9,@-r15 | ||
91 | mov.l r10,@-r15 | ||
92 | mov.l r11,@-r15 | ||
93 | mov r4,r10 | ||
94 | mov r5,r11 | ||
95 | mov r6,r9 | ||
96 | mov r5,r8 | ||
97 | mov.w .L4096,r0 | ||
98 | add r0,r8 | ||
99 | ! | ||
100 | 1: ocbi @r9 | ||
101 | add #32,r9 | ||
102 | mov.l @r11+,r0 | ||
103 | mov.l @r11+,r1 | ||
104 | mov.l @r11+,r2 | ||
105 | mov.l @r11+,r3 | ||
106 | mov.l @r11+,r4 | ||
107 | mov.l @r11+,r5 | ||
108 | mov.l @r11+,r6 | ||
109 | mov.l @r11+,r7 | ||
110 | movca.l r0,@r10 | ||
111 | mov r10,r0 | ||
112 | add #32,r10 | ||
113 | mov.l r7,@-r10 | ||
114 | mov.l r6,@-r10 | ||
115 | mov.l r5,@-r10 | ||
116 | mov.l r4,@-r10 | ||
117 | mov.l r3,@-r10 | ||
118 | mov.l r2,@-r10 | ||
119 | mov.l r1,@-r10 | ||
120 | ocbwb @r0 | ||
121 | cmp/eq r11,r8 | ||
122 | bf/s 1b | ||
123 | add #28,r10 | ||
124 | ! | ||
125 | mov.l @r15+,r11 | ||
126 | mov.l @r15+,r10 | ||
127 | mov.l @r15+,r9 | ||
128 | mov.l @r15+,r8 | ||
129 | rts | ||
130 | nop | ||
131 | #endif | ||
132 | .L4096: .word 4096 | ||
133 | /* | ||
134 | * __kernel_size_t __copy_user(void *to, const void *from, __kernel_size_t n); | ||
135 | * Return the number of bytes NOT copied | ||
136 | */ | ||
137 | #define EX(...) \ | ||
138 | 9999: __VA_ARGS__ ; \ | ||
139 | .section __ex_table, "a"; \ | ||
140 | .long 9999b, 6000f ; \ | ||
141 | .previous | ||
142 | ENTRY(__copy_user) | ||
143 | tst r6,r6 ! Check explicitly for zero | ||
144 | bf 1f | ||
145 | rts | ||
146 | mov #0,r0 ! normal return | ||
147 | 1: | ||
148 | mov.l r10,@-r15 | ||
149 | mov.l r9,@-r15 | ||
150 | mov.l r8,@-r15 | ||
151 | mov r4,r3 | ||
152 | add r6,r3 ! last destination address | ||
153 | mov #12,r0 ! Check if small number of bytes | ||
154 | cmp/gt r0,r6 | ||
155 | bt 2f | ||
156 | bra .L_cleanup_loop | ||
157 | nop | ||
158 | 2: | ||
159 | neg r5,r0 ! Calculate bytes needed to align source | ||
160 | add #4,r0 | ||
161 | and #3,r0 | ||
162 | tst r0,r0 | ||
163 | bt .L_jump | ||
164 | mov r0,r1 | ||
165 | |||
166 | .L_loop1: | ||
167 | ! Copy bytes to align source | ||
168 | EX( mov.b @r5+,r0 ) | ||
169 | dt r1 | ||
170 | EX( mov.b r0,@r4 ) | ||
171 | add #-1,r6 | ||
172 | bf/s .L_loop1 | ||
173 | add #1,r4 | ||
174 | |||
175 | .L_jump: | ||
176 | mov r6,r2 ! Calculate number of longwords to copy | ||
177 | shlr2 r2 | ||
178 | tst r2,r2 | ||
179 | bt .L_cleanup | ||
180 | |||
181 | mov r4,r0 ! Jump to appropriate routine | ||
182 | and #3,r0 | ||
183 | mov r0,r1 | ||
184 | shll2 r1 | ||
185 | mova .L_jump_tbl,r0 | ||
186 | mov.l @(r0,r1),r1 | ||
187 | jmp @r1 | ||
188 | nop | ||
189 | |||
190 | .align 2 | ||
191 | .L_jump_tbl: | ||
192 | .long .L_dest00 | ||
193 | .long .L_dest01 | ||
194 | .long .L_dest10 | ||
195 | .long .L_dest11 | ||
196 | |||
197 | ! Destination = 00 | ||
198 | |||
199 | .L_dest00: | ||
200 | mov r2,r7 | ||
201 | shlr2 r7 | ||
202 | shlr r7 | ||
203 | tst r7,r7 | ||
204 | mov #7,r0 | ||
205 | bt/s 1f | ||
206 | and r0,r2 | ||
207 | .align 2 | ||
208 | 2: | ||
209 | EX( mov.l @r5+,r0 ) | ||
210 | EX( mov.l @r5+,r8 ) | ||
211 | EX( mov.l @r5+,r9 ) | ||
212 | EX( mov.l @r5+,r10 ) | ||
213 | EX( mov.l r0,@r4 ) | ||
214 | EX( mov.l r8,@(4,r4) ) | ||
215 | EX( mov.l r9,@(8,r4) ) | ||
216 | EX( mov.l r10,@(12,r4) ) | ||
217 | EX( mov.l @r5+,r0 ) | ||
218 | EX( mov.l @r5+,r8 ) | ||
219 | EX( mov.l @r5+,r9 ) | ||
220 | EX( mov.l @r5+,r10 ) | ||
221 | dt r7 | ||
222 | EX( mov.l r0,@(16,r4) ) | ||
223 | EX( mov.l r8,@(20,r4) ) | ||
224 | EX( mov.l r9,@(24,r4) ) | ||
225 | EX( mov.l r10,@(28,r4) ) | ||
226 | bf/s 2b | ||
227 | add #32,r4 | ||
228 | tst r2,r2 | ||
229 | bt .L_cleanup | ||
230 | 1: | ||
231 | EX( mov.l @r5+,r0 ) | ||
232 | dt r2 | ||
233 | EX( mov.l r0,@r4 ) | ||
234 | bf/s 1b | ||
235 | add #4,r4 | ||
236 | |||
237 | bra .L_cleanup | ||
238 | nop | ||
239 | |||
240 | ! Destination = 10 | ||
241 | |||
242 | .L_dest10: | ||
243 | mov r2,r7 | ||
244 | shlr2 r7 | ||
245 | shlr r7 | ||
246 | tst r7,r7 | ||
247 | mov #7,r0 | ||
248 | bt/s 1f | ||
249 | and r0,r2 | ||
250 | 2: | ||
251 | dt r7 | ||
252 | #ifdef __LITTLE_ENDIAN__ | ||
253 | EX( mov.l @r5+,r0 ) | ||
254 | EX( mov.l @r5+,r1 ) | ||
255 | EX( mov.l @r5+,r8 ) | ||
256 | EX( mov.l @r5+,r9 ) | ||
257 | EX( mov.l @r5+,r10 ) | ||
258 | EX( mov.w r0,@r4 ) | ||
259 | add #2,r4 | ||
260 | xtrct r1,r0 | ||
261 | xtrct r8,r1 | ||
262 | xtrct r9,r8 | ||
263 | xtrct r10,r9 | ||
264 | |||
265 | EX( mov.l r0,@r4 ) | ||
266 | EX( mov.l r1,@(4,r4) ) | ||
267 | EX( mov.l r8,@(8,r4) ) | ||
268 | EX( mov.l r9,@(12,r4) ) | ||
269 | |||
270 | EX( mov.l @r5+,r1 ) | ||
271 | EX( mov.l @r5+,r8 ) | ||
272 | EX( mov.l @r5+,r0 ) | ||
273 | xtrct r1,r10 | ||
274 | xtrct r8,r1 | ||
275 | xtrct r0,r8 | ||
276 | shlr16 r0 | ||
277 | EX( mov.l r10,@(16,r4) ) | ||
278 | EX( mov.l r1,@(20,r4) ) | ||
279 | EX( mov.l r8,@(24,r4) ) | ||
280 | EX( mov.w r0,@(28,r4) ) | ||
281 | bf/s 2b | ||
282 | add #30,r4 | ||
283 | #else | ||
284 | EX( mov.l @(28,r5),r0 ) | ||
285 | EX( mov.l @(24,r5),r8 ) | ||
286 | EX( mov.l @(20,r5),r9 ) | ||
287 | EX( mov.l @(16,r5),r10 ) | ||
288 | EX( mov.w r0,@(30,r4) ) | ||
289 | add #-2,r4 | ||
290 | xtrct r8,r0 | ||
291 | xtrct r9,r8 | ||
292 | xtrct r10,r9 | ||
293 | EX( mov.l r0,@(28,r4) ) | ||
294 | EX( mov.l r8,@(24,r4) ) | ||
295 | EX( mov.l r9,@(20,r4) ) | ||
296 | |||
297 | EX( mov.l @(12,r5),r0 ) | ||
298 | EX( mov.l @(8,r5),r8 ) | ||
299 | xtrct r0,r10 | ||
300 | EX( mov.l @(4,r5),r9 ) | ||
301 | mov.l r10,@(16,r4) | ||
302 | EX( mov.l @r5,r10 ) | ||
303 | xtrct r8,r0 | ||
304 | xtrct r9,r8 | ||
305 | xtrct r10,r9 | ||
306 | EX( mov.l r0,@(12,r4) ) | ||
307 | EX( mov.l r8,@(8,r4) ) | ||
308 | swap.w r10,r0 | ||
309 | EX( mov.l r9,@(4,r4) ) | ||
310 | EX( mov.w r0,@(2,r4) ) | ||
311 | |||
312 | add #32,r5 | ||
313 | bf/s 2b | ||
314 | add #34,r4 | ||
315 | #endif | ||
316 | tst r2,r2 | ||
317 | bt .L_cleanup | ||
318 | |||
319 | 1: ! Read longword, write two words per iteration | ||
320 | EX( mov.l @r5+,r0 ) | ||
321 | dt r2 | ||
322 | #ifdef __LITTLE_ENDIAN__ | ||
323 | EX( mov.w r0,@r4 ) | ||
324 | shlr16 r0 | ||
325 | EX( mov.w r0,@(2,r4) ) | ||
326 | #else | ||
327 | EX( mov.w r0,@(2,r4) ) | ||
328 | shlr16 r0 | ||
329 | EX( mov.w r0,@r4 ) | ||
330 | #endif | ||
331 | bf/s 1b | ||
332 | add #4,r4 | ||
333 | |||
334 | bra .L_cleanup | ||
335 | nop | ||
336 | |||
337 | ! Destination = 01 or 11 | ||
338 | |||
339 | .L_dest01: | ||
340 | .L_dest11: | ||
341 | ! Read longword, write byte, word, byte per iteration | ||
342 | EX( mov.l @r5+,r0 ) | ||
343 | dt r2 | ||
344 | #ifdef __LITTLE_ENDIAN__ | ||
345 | EX( mov.b r0,@r4 ) | ||
346 | shlr8 r0 | ||
347 | add #1,r4 | ||
348 | EX( mov.w r0,@r4 ) | ||
349 | shlr16 r0 | ||
350 | EX( mov.b r0,@(2,r4) ) | ||
351 | bf/s .L_dest01 | ||
352 | add #3,r4 | ||
353 | #else | ||
354 | EX( mov.b r0,@(3,r4) ) | ||
355 | shlr8 r0 | ||
356 | swap.w r0,r7 | ||
357 | EX( mov.b r7,@r4 ) | ||
358 | add #1,r4 | ||
359 | EX( mov.w r0,@r4 ) | ||
360 | bf/s .L_dest01 | ||
361 | add #3,r4 | ||
362 | #endif | ||
363 | |||
364 | ! Cleanup last few bytes | ||
365 | .L_cleanup: | ||
366 | mov r6,r0 | ||
367 | and #3,r0 | ||
368 | tst r0,r0 | ||
369 | bt .L_exit | ||
370 | mov r0,r6 | ||
371 | |||
372 | .L_cleanup_loop: | ||
373 | EX( mov.b @r5+,r0 ) | ||
374 | dt r6 | ||
375 | EX( mov.b r0,@r4 ) | ||
376 | bf/s .L_cleanup_loop | ||
377 | add #1,r4 | ||
378 | |||
379 | .L_exit: | ||
380 | mov #0,r0 ! normal return | ||
381 | 5000: | ||
382 | |||
383 | # Exception handler: | ||
384 | .section .fixup, "ax" | ||
385 | 6000: | ||
386 | mov.l 8000f,r1 | ||
387 | mov r3,r0 | ||
388 | jmp @r1 | ||
389 | sub r4,r0 | ||
390 | .align 2 | ||
391 | 8000: .long 5000b | ||
392 | |||
393 | .previous | ||
394 | mov.l @r15+,r8 | ||
395 | mov.l @r15+,r9 | ||
396 | rts | ||
397 | mov.l @r15+,r10 | ||