more changes on original files
[linux-2.4.git] / arch / alpha / lib / copy_user.S
1 /*
2  * arch/alpha/lib/copy_user.S
3  *
4  * Copy to/from user space, handling exceptions as we go..  This
5  * isn't exactly pretty.
6  *
7  * This is essentially the same as "memcpy()", but with a few twists.
8  * Notably, we have to make sure that $0 is always up-to-date and
9  * contains the right "bytes left to copy" value (and that it is updated
10  * only _after_ a successful copy). There is also some rather minor
11  * exception setup stuff..
12  *
13  * NOTE! This is not directly C-callable, because the calling semantics are
14  * different:
15  *
16  * Inputs:
17  *      length in $0
18  *      destination address in $6
19  *      source address in $7
20  *      return address in $28
21  *
22  * Outputs:
23  *      bytes left to copy in $0
24  *
25  * Clobbers:
26  *      $1,$2,$3,$4,$5,$6,$7
27  */
28
29 /* Allow an exception for an insn; exit if we get one.  */
30 #define EXI(x,y...)                     \
31         99: x,##y;                      \
32         .section __ex_table,"a";        \
33         .gprel32 99b;                   \
34         lda $31, $exitin-99b($31);      \
35         .previous
36
37 #define EXO(x,y...)                     \
38         99: x,##y;                      \
39         .section __ex_table,"a";        \
40         .gprel32 99b;                   \
41         lda $31, $exitout-99b($31);     \
42         .previous
43
44         .set noat
45         .align 3
46         .globl __copy_user
47         .ent __copy_user
48 __copy_user:
49         ldgp $29,0($27)                 # we do exceptions -- we need the gp.
50         .prologue 1
51         and $6,7,$3
52         beq $0,$35
53         beq $3,$36
54         subq $3,8,$3
55         .align 5
56 $37:
57         EXI( ldq_u $1,0($7) )
58         EXO( ldq_u $2,0($6) )
59         extbl $1,$7,$1
60         mskbl $2,$6,$2
61         insbl $1,$6,$1
62         addq $3,1,$3
63         bis $1,$2,$1
64         EXO( stq_u $1,0($6) )
65         subq $0,1,$0
66         addq $6,1,$6
67         addq $7,1,$7
68         beq $0,$41
69         bne $3,$37
70 $36:
71         and $7,7,$1
72         bic $0,7,$4
73         beq $1,$43
74         beq $4,$48
75         EXI( ldq_u $3,0($7) )
76         .align 5
77 $50:
78         EXI( ldq_u $2,8($7) )
79         subq $4,8,$4
80         extql $3,$7,$3
81         extqh $2,$7,$1
82         bis $3,$1,$1
83         EXO( stq $1,0($6) )
84         addq $7,8,$7
85         subq $0,8,$0
86         addq $6,8,$6
87         bis $2,$2,$3
88         bne $4,$50
89 $48:
90         beq $0,$41
91         .align 5
92 $57:
93         EXI( ldq_u $1,0($7) )
94         EXO( ldq_u $2,0($6) )
95         extbl $1,$7,$1
96         mskbl $2,$6,$2
97         insbl $1,$6,$1
98         bis $1,$2,$1
99         EXO( stq_u $1,0($6) )
100         subq $0,1,$0
101         addq $6,1,$6
102         addq $7,1,$7
103         bne $0,$57
104         br $31,$41
105         .align 4
106 $43:
107         beq $4,$65
108         .align 5
109 $66:
110         EXI( ldq $1,0($7) )
111         subq $4,8,$4
112         EXO( stq $1,0($6) )
113         addq $7,8,$7
114         subq $0,8,$0
115         addq $6,8,$6
116         bne $4,$66
117 $65:
118         beq $0,$41
119         EXI( ldq $2,0($7) )
120         EXO( ldq $1,0($6) )
121         mskql $2,$0,$2
122         mskqh $1,$0,$1
123         bis $2,$1,$2
124         EXO( stq $2,0($6) )
125         bis $31,$31,$0
126 $41:
127 $35:
128 $exitout:
129         ret $31,($28),1
130
131 $exitin:
132         /* A stupid byte-by-byte zeroing of the rest of the output
133            buffer.  This cures security holes by never leaving 
134            random kernel data around to be copied elsewhere.  */
135
136         mov $0,$1
137 $101:
138         EXO ( ldq_u $2,0($6) )
139         subq $1,1,$1
140         mskbl $2,$6,$2
141         EXO ( stq_u $2,0($6) )
142         addq $6,1,$6
143         bgt $1,$101
144         ret $31,($28),1
145
146         .end __copy_user