Merge git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6 into for-linus
[linux-2.6] / arch / sh / lib / clear_page.S
1 /*
2  * __clear_user_page, __clear_user, clear_page implementation of SuperH
3  *
4  * Copyright (C) 2001  Kaz Kojima
5  * Copyright (C) 2001, 2002  Niibe Yutaka
6  * Copyright (C) 2006  Paul Mundt
7  */
8 #include <linux/linkage.h>
9 #include <asm/page.h>
10
11 /*
12  * clear_page
13  * @to: P1 address
14  *
15  * void clear_page(void *to)
16  */
17
18 /*
19  * r0 --- scratch
20  * r4 --- to
21  * r5 --- to + PAGE_SIZE
22  */
23 ENTRY(clear_page)
24         mov     r4,r5
25         mov.l   .Llimit,r0
26         add     r0,r5
27         mov     #0,r0
28         !
29 1:
30 #if defined(CONFIG_CPU_SH3)
31         mov.l   r0,@r4
32 #elif defined(CONFIG_CPU_SH4)
33         movca.l r0,@r4
34         mov     r4,r1
35 #endif
36         add     #32,r4
37         mov.l   r0,@-r4
38         mov.l   r0,@-r4
39         mov.l   r0,@-r4
40         mov.l   r0,@-r4
41         mov.l   r0,@-r4
42         mov.l   r0,@-r4
43         mov.l   r0,@-r4
44 #if defined(CONFIG_CPU_SH4)
45         ocbwb   @r1
46 #endif
47         cmp/eq  r5,r4
48         bf/s    1b
49          add    #28,r4
50         !
51         rts
52          nop
53
54         .balign 4
55 .Llimit:        .long   (PAGE_SIZE-28)
56
57 ENTRY(__clear_user)
58         !
59         mov     #0, r0
60         mov     #0xe0, r1       ! 0xffffffe0
61         !
62         ! r4..(r4+31)&~32          -------- not aligned [ Area 0 ]
63         ! (r4+31)&~32..(r4+r5)&~32 -------- aligned     [ Area 1 ]
64         ! (r4+r5)&~32..r4+r5       -------- not aligned [ Area 2 ]
65         !
66         ! Clear area 0
67         mov     r4, r2
68         !
69         tst     r1, r5          ! length < 32
70         bt      .Larea2         ! skip to remainder
71         !
72         add     #31, r2
73         and     r1, r2
74         cmp/eq  r4, r2
75         bt      .Larea1
76         mov     r2, r3
77         sub     r4, r3
78         mov     r3, r7
79         mov     r4, r2
80         !
81 .L0:    dt      r3
82 0:      mov.b   r0, @r2
83         bf/s    .L0
84          add    #1, r2
85         !
86         sub     r7, r5
87         mov     r2, r4
88 .Larea1:
89         mov     r4, r3
90         add     r5, r3
91         and     r1, r3
92         cmp/hi  r2, r3
93         bf      .Larea2
94         !
95         ! Clear area 1
96 #if defined(CONFIG_CPU_SH4)
97 1:      movca.l r0, @r2
98 #else
99 1:      mov.l   r0, @r2
100 #endif
101         add     #4, r2
102 2:      mov.l   r0, @r2
103         add     #4, r2
104 3:      mov.l   r0, @r2
105         add     #4, r2
106 4:      mov.l   r0, @r2
107         add     #4, r2
108 5:      mov.l   r0, @r2
109         add     #4, r2
110 6:      mov.l   r0, @r2
111         add     #4, r2
112 7:      mov.l   r0, @r2
113         add     #4, r2
114 8:      mov.l   r0, @r2
115         add     #4, r2
116         cmp/hi  r2, r3
117         bt/s    1b
118          nop
119         !
120         ! Clear area 2
121 .Larea2:
122         mov     r4, r3
123         add     r5, r3
124         cmp/hs  r3, r2
125         bt/s    .Ldone
126          sub    r2, r3
127 .L2:    dt      r3
128 9:      mov.b   r0, @r2
129         bf/s    .L2
130          add    #1, r2
131         !
132 .Ldone: rts
133          mov    #0, r0  ! return 0 as normal return
134
135         ! return the number of bytes remained
136 .Lbad_clear_user:
137         mov     r4, r0
138         add     r5, r0
139         rts
140          sub    r2, r0
141
142 .section __ex_table,"a"
143         .align 2
144         .long   0b, .Lbad_clear_user
145         .long   1b, .Lbad_clear_user
146         .long   2b, .Lbad_clear_user
147         .long   3b, .Lbad_clear_user
148         .long   4b, .Lbad_clear_user
149         .long   5b, .Lbad_clear_user
150         .long   6b, .Lbad_clear_user
151         .long   7b, .Lbad_clear_user
152         .long   8b, .Lbad_clear_user
153         .long   9b, .Lbad_clear_user
154 .previous