]>
Commit | Line | Data |
---|---|---|
1da177e4 LT |
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 | ||
00fc0e0d AV |
29 | #include <asm/export.h> |
30 | ||
1da177e4 LT |
31 | /* Allow an exception for an insn; exit if we get one. */ |
32 | #define EXI(x,y...) \ | |
33 | 99: x,##y; \ | |
34 | .section __ex_table,"a"; \ | |
35 | .long 99b - .; \ | |
36 | lda $31, $exitin-99b($31); \ | |
37 | .previous | |
38 | ||
39 | #define EXO(x,y...) \ | |
40 | 99: x,##y; \ | |
41 | .section __ex_table,"a"; \ | |
42 | .long 99b - .; \ | |
43 | lda $31, $exitout-99b($31); \ | |
44 | .previous | |
45 | ||
46 | .set noat | |
47 | .align 4 | |
48 | .globl __copy_user | |
49 | .ent __copy_user | |
50 | __copy_user: | |
51 | .prologue 0 | |
52 | and $6,7,$3 | |
53 | beq $0,$35 | |
54 | beq $3,$36 | |
55 | subq $3,8,$3 | |
56 | .align 4 | |
57 | $37: | |
58 | EXI( ldq_u $1,0($7) ) | |
59 | EXO( ldq_u $2,0($6) ) | |
60 | extbl $1,$7,$1 | |
61 | mskbl $2,$6,$2 | |
62 | insbl $1,$6,$1 | |
63 | addq $3,1,$3 | |
64 | bis $1,$2,$1 | |
65 | EXO( stq_u $1,0($6) ) | |
66 | subq $0,1,$0 | |
67 | addq $6,1,$6 | |
68 | addq $7,1,$7 | |
69 | beq $0,$41 | |
70 | bne $3,$37 | |
71 | $36: | |
72 | and $7,7,$1 | |
73 | bic $0,7,$4 | |
74 | beq $1,$43 | |
75 | beq $4,$48 | |
76 | EXI( ldq_u $3,0($7) ) | |
77 | .align 4 | |
78 | $50: | |
79 | EXI( ldq_u $2,8($7) ) | |
80 | subq $4,8,$4 | |
81 | extql $3,$7,$3 | |
82 | extqh $2,$7,$1 | |
83 | bis $3,$1,$1 | |
84 | EXO( stq $1,0($6) ) | |
85 | addq $7,8,$7 | |
86 | subq $0,8,$0 | |
87 | addq $6,8,$6 | |
88 | bis $2,$2,$3 | |
89 | bne $4,$50 | |
90 | $48: | |
91 | beq $0,$41 | |
92 | .align 4 | |
93 | $57: | |
94 | EXI( ldq_u $1,0($7) ) | |
95 | EXO( ldq_u $2,0($6) ) | |
96 | extbl $1,$7,$1 | |
97 | mskbl $2,$6,$2 | |
98 | insbl $1,$6,$1 | |
99 | bis $1,$2,$1 | |
100 | EXO( stq_u $1,0($6) ) | |
101 | subq $0,1,$0 | |
102 | addq $6,1,$6 | |
103 | addq $7,1,$7 | |
104 | bne $0,$57 | |
105 | br $31,$41 | |
106 | .align 4 | |
107 | $43: | |
108 | beq $4,$65 | |
109 | .align 4 | |
110 | $66: | |
111 | EXI( ldq $1,0($7) ) | |
112 | subq $4,8,$4 | |
113 | EXO( stq $1,0($6) ) | |
114 | addq $7,8,$7 | |
115 | subq $0,8,$0 | |
116 | addq $6,8,$6 | |
117 | bne $4,$66 | |
118 | $65: | |
119 | beq $0,$41 | |
120 | EXI( ldq $2,0($7) ) | |
121 | EXO( ldq $1,0($6) ) | |
122 | mskql $2,$0,$2 | |
123 | mskqh $1,$0,$1 | |
124 | bis $2,$1,$2 | |
125 | EXO( stq $2,0($6) ) | |
126 | bis $31,$31,$0 | |
127 | $41: | |
128 | $35: | |
1da177e4 | 129 | $exitin: |
085354f9 | 130 | $exitout: |
1da177e4 LT |
131 | ret $31,($28),1 |
132 | ||
133 | .end __copy_user | |
00fc0e0d | 134 | EXPORT_SYMBOL(__copy_user) |