[SPARC]: Fix serial console device detection.
[linux-2.6] / arch / sh / mm / copy_page.S
1 /*
2  * copy_page, __copy_user_page, __copy_user implementation of SuperH
3  *
4  * Copyright (C) 2001  Niibe Yutaka & Kaz Kojima
5  * Copyright (C) 2002  Toshinobu Sugioka
6  * Copyright (C) 2006  Paul Mundt
7  */
8 #include <linux/linkage.h>
9 #include <asm/page.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 + PAGE_SIZE
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.l   .Lpsz,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 + PAGE_SIZE
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.l   .Lpsz,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         .align 2
133 .Lpsz:  .long   PAGE_SIZE
134 /*
135  * __kernel_size_t __copy_user(void *to, const void *from, __kernel_size_t n);
136  * Return the number of bytes NOT copied
137  */
138 #define EX(...)                 \
139         9999: __VA_ARGS__ ;             \
140         .section __ex_table, "a";       \
141         .long 9999b, 6000f      ;       \
142         .previous
143 ENTRY(__copy_user)
144         tst     r6,r6           ! Check explicitly for zero
145         bf      1f
146         rts
147          mov    #0,r0           ! normal return
148 1:
149         mov.l   r10,@-r15
150         mov.l   r9,@-r15
151         mov.l   r8,@-r15
152         mov     r4,r3
153         add     r6,r3           ! last destination address
154         mov     #12,r0          ! Check if small number of bytes
155         cmp/gt  r0,r6
156         bt      2f
157         bra     .L_cleanup_loop
158          nop
159 2:
160         neg     r5,r0           ! Calculate bytes needed to align source
161         add     #4,r0
162         and     #3,r0
163         tst     r0,r0
164         bt      .L_jump
165         mov     r0,r1
166
167 .L_loop1:
168         ! Copy bytes to align source
169 EX(     mov.b   @r5+,r0         )
170         dt      r1
171 EX(     mov.b   r0,@r4          )
172         add     #-1,r6
173         bf/s    .L_loop1
174          add    #1,r4
175
176 .L_jump:
177         mov     r6,r2           ! Calculate number of longwords to copy
178         shlr2   r2
179         tst     r2,r2
180         bt      .L_cleanup
181
182         mov     r4,r0           ! Jump to appropriate routine
183         and     #3,r0
184         mov     r0,r1
185         shll2   r1
186         mova    .L_jump_tbl,r0
187         mov.l   @(r0,r1),r1
188         jmp     @r1
189          nop
190
191         .align 2
192 .L_jump_tbl:
193         .long   .L_dest00
194         .long   .L_dest01
195         .long   .L_dest10
196         .long   .L_dest11
197
198 ! Destination = 00
199
200 .L_dest00:
201         mov     r2,r7
202         shlr2   r7
203         shlr    r7
204         tst     r7,r7
205         mov     #7,r0
206         bt/s    1f
207          and    r0,r2
208         .align 2
209 2:
210 EX(     mov.l   @r5+,r0         )
211 EX(     mov.l   @r5+,r8         )
212 EX(     mov.l   @r5+,r9         )
213 EX(     mov.l   @r5+,r10        )
214 EX(     mov.l   r0,@r4          )
215 EX(     mov.l   r8,@(4,r4)      )
216 EX(     mov.l   r9,@(8,r4)      )
217 EX(     mov.l   r10,@(12,r4)    )
218 EX(     mov.l   @r5+,r0         )
219 EX(     mov.l   @r5+,r8         )
220 EX(     mov.l   @r5+,r9         )
221 EX(     mov.l   @r5+,r10        )
222         dt      r7
223 EX(     mov.l   r0,@(16,r4)     )
224 EX(     mov.l   r8,@(20,r4)     )
225 EX(     mov.l   r9,@(24,r4)     )
226 EX(     mov.l   r10,@(28,r4)    )
227         bf/s    2b
228          add    #32,r4
229         tst     r2,r2
230         bt      .L_cleanup
231 1:
232 EX(     mov.l   @r5+,r0         )
233         dt      r2
234 EX(     mov.l   r0,@r4          )
235         bf/s    1b
236          add    #4,r4
237
238         bra     .L_cleanup
239          nop
240
241 ! Destination = 10
242
243 .L_dest10:
244         mov     r2,r7
245         shlr2   r7
246         shlr    r7
247         tst     r7,r7
248         mov     #7,r0
249         bt/s    1f
250          and    r0,r2
251 2:
252         dt      r7
253 #ifdef __LITTLE_ENDIAN__
254 EX(     mov.l   @r5+,r0         )
255 EX(     mov.l   @r5+,r1         )
256 EX(     mov.l   @r5+,r8         )
257 EX(     mov.l   @r5+,r9         )
258 EX(     mov.l   @r5+,r10        )
259 EX(     mov.w   r0,@r4          )
260         add     #2,r4
261         xtrct   r1,r0
262         xtrct   r8,r1
263         xtrct   r9,r8
264         xtrct   r10,r9
265
266 EX(     mov.l   r0,@r4          )
267 EX(     mov.l   r1,@(4,r4)      )
268 EX(     mov.l   r8,@(8,r4)      )
269 EX(     mov.l   r9,@(12,r4)     )
270
271 EX(     mov.l   @r5+,r1         )
272 EX(     mov.l   @r5+,r8         )
273 EX(     mov.l   @r5+,r0         )
274         xtrct   r1,r10
275         xtrct   r8,r1
276         xtrct   r0,r8
277         shlr16  r0
278 EX(     mov.l   r10,@(16,r4)    )
279 EX(     mov.l   r1,@(20,r4)     )
280 EX(     mov.l   r8,@(24,r4)     )
281 EX(     mov.w   r0,@(28,r4)     )
282         bf/s    2b
283          add    #30,r4
284 #else
285 EX(     mov.l   @(28,r5),r0     )
286 EX(     mov.l   @(24,r5),r8     )
287 EX(     mov.l   @(20,r5),r9     )
288 EX(     mov.l   @(16,r5),r10    )
289 EX(     mov.w   r0,@(30,r4)     )
290         add     #-2,r4
291         xtrct   r8,r0
292         xtrct   r9,r8
293         xtrct   r10,r9
294 EX(     mov.l   r0,@(28,r4)     )
295 EX(     mov.l   r8,@(24,r4)     )
296 EX(     mov.l   r9,@(20,r4)     )
297
298 EX(     mov.l   @(12,r5),r0     )
299 EX(     mov.l   @(8,r5),r8      )
300         xtrct   r0,r10
301 EX(     mov.l   @(4,r5),r9      )
302         mov.l   r10,@(16,r4)
303 EX(     mov.l   @r5,r10         )
304         xtrct   r8,r0
305         xtrct   r9,r8
306         xtrct   r10,r9
307 EX(     mov.l   r0,@(12,r4)     )
308 EX(     mov.l   r8,@(8,r4)      )
309         swap.w  r10,r0
310 EX(     mov.l   r9,@(4,r4)      )
311 EX(     mov.w   r0,@(2,r4)      )
312
313         add     #32,r5
314         bf/s    2b
315          add    #34,r4
316 #endif
317         tst     r2,r2
318         bt      .L_cleanup
319
320 1:      ! Read longword, write two words per iteration
321 EX(     mov.l   @r5+,r0         )
322         dt      r2
323 #ifdef __LITTLE_ENDIAN__
324 EX(     mov.w   r0,@r4          )
325         shlr16  r0
326 EX(     mov.w   r0,@(2,r4)      )
327 #else
328 EX(     mov.w   r0,@(2,r4)      )
329         shlr16  r0
330 EX(     mov.w   r0,@r4          )
331 #endif
332         bf/s    1b
333          add    #4,r4
334
335         bra     .L_cleanup
336          nop
337
338 ! Destination = 01 or 11
339
340 .L_dest01:
341 .L_dest11:
342         ! Read longword, write byte, word, byte per iteration
343 EX(     mov.l   @r5+,r0         )
344         dt      r2
345 #ifdef __LITTLE_ENDIAN__
346 EX(     mov.b   r0,@r4          )
347         shlr8   r0
348         add     #1,r4
349 EX(     mov.w   r0,@r4          )
350         shlr16  r0
351 EX(     mov.b   r0,@(2,r4)      )
352         bf/s    .L_dest01
353          add    #3,r4
354 #else
355 EX(     mov.b   r0,@(3,r4)      )
356         shlr8   r0
357         swap.w  r0,r7
358 EX(     mov.b   r7,@r4          )
359         add     #1,r4
360 EX(     mov.w   r0,@r4          )
361         bf/s    .L_dest01
362          add    #3,r4
363 #endif
364
365 ! Cleanup last few bytes
366 .L_cleanup:
367         mov     r6,r0
368         and     #3,r0
369         tst     r0,r0
370         bt      .L_exit
371         mov     r0,r6
372
373 .L_cleanup_loop:
374 EX(     mov.b   @r5+,r0         )
375         dt      r6
376 EX(     mov.b   r0,@r4          )
377         bf/s    .L_cleanup_loop
378          add    #1,r4
379
380 .L_exit:
381         mov     #0,r0           ! normal return
382 5000:
383
384 # Exception handler:
385 .section .fixup, "ax"
386 6000:
387         mov.l   8000f,r1
388         mov     r3,r0
389         jmp     @r1
390          sub    r4,r0
391         .align  2
392 8000:   .long   5000b
393
394 .previous
395         mov.l   @r15+,r8
396         mov.l   @r15+,r9
397         rts
398          mov.l  @r15+,r10