1 | /* SPDX-License-Identifier: GPL-2.0 */ |
2 | /* |
3 | * arch/alpha/lib/copy_user.S |
4 | * |
5 | * Copy to/from user space, handling exceptions as we go.. This |
6 | * isn't exactly pretty. |
7 | * |
8 | * This is essentially the same as "memcpy()", but with a few twists. |
9 | * Notably, we have to make sure that $0 is always up-to-date and |
10 | * contains the right "bytes left to copy" value (and that it is updated |
11 | * only _after_ a successful copy). There is also some rather minor |
12 | * exception setup stuff.. |
13 | */ |
14 | |
15 | #include <linux/export.h> |
16 | |
17 | /* Allow an exception for an insn; exit if we get one. */ |
18 | #define EXI(x,y...) \ |
19 | 99: x,##y; \ |
20 | .section __ex_table,"a"; \ |
21 | .long 99b - .; \ |
22 | lda $31, $exitin-99b($31); \ |
23 | .previous |
24 | |
25 | #define EXO(x,y...) \ |
26 | 99: x,##y; \ |
27 | .section __ex_table,"a"; \ |
28 | .long 99b - .; \ |
29 | lda $31, $exitout-99b($31); \ |
30 | .previous |
31 | |
32 | .set noat |
33 | .align 4 |
34 | .globl __copy_user |
35 | .ent __copy_user |
36 | __copy_user: |
37 | .prologue 0 |
38 | mov $18,$0 |
39 | and $16,7,$3 |
40 | beq $0,$35 |
41 | beq $3,$36 |
42 | subq $3,8,$3 |
43 | .align 4 |
44 | $37: |
45 | EXI( ldq_u $1,0($17) ) |
46 | EXO( ldq_u $2,0($16) ) |
47 | extbl $1,$17,$1 |
48 | mskbl $2,$16,$2 |
49 | insbl $1,$16,$1 |
50 | addq $3,1,$3 |
51 | bis $1,$2,$1 |
52 | EXO( stq_u $1,0($16) ) |
53 | subq $0,1,$0 |
54 | addq $16,1,$16 |
55 | addq $17,1,$17 |
56 | beq $0,$41 |
57 | bne $3,$37 |
58 | $36: |
59 | and $17,7,$1 |
60 | bic $0,7,$4 |
61 | beq $1,$43 |
62 | beq $4,$48 |
63 | EXI( ldq_u $3,0($17) ) |
64 | .align 4 |
65 | $50: |
66 | EXI( ldq_u $2,8($17) ) |
67 | subq $4,8,$4 |
68 | extql $3,$17,$3 |
69 | extqh $2,$17,$1 |
70 | bis $3,$1,$1 |
71 | EXO( stq $1,0($16) ) |
72 | addq $17,8,$17 |
73 | subq $0,8,$0 |
74 | addq $16,8,$16 |
75 | bis $2,$2,$3 |
76 | bne $4,$50 |
77 | $48: |
78 | beq $0,$41 |
79 | .align 4 |
80 | $57: |
81 | EXI( ldq_u $1,0($17) ) |
82 | EXO( ldq_u $2,0($16) ) |
83 | extbl $1,$17,$1 |
84 | mskbl $2,$16,$2 |
85 | insbl $1,$16,$1 |
86 | bis $1,$2,$1 |
87 | EXO( stq_u $1,0($16) ) |
88 | subq $0,1,$0 |
89 | addq $16,1,$16 |
90 | addq $17,1,$17 |
91 | bne $0,$57 |
92 | br $31,$41 |
93 | .align 4 |
94 | $43: |
95 | beq $4,$65 |
96 | .align 4 |
97 | $66: |
98 | EXI( ldq $1,0($17) ) |
99 | subq $4,8,$4 |
100 | EXO( stq $1,0($16) ) |
101 | addq $17,8,$17 |
102 | subq $0,8,$0 |
103 | addq $16,8,$16 |
104 | bne $4,$66 |
105 | $65: |
106 | beq $0,$41 |
107 | EXI( ldq $2,0($17) ) |
108 | EXO( ldq $1,0($16) ) |
109 | mskql $2,$0,$2 |
110 | mskqh $1,$0,$1 |
111 | bis $2,$1,$2 |
112 | EXO( stq $2,0($16) ) |
113 | bis $31,$31,$0 |
114 | $41: |
115 | $35: |
116 | $exitin: |
117 | $exitout: |
118 | ret $31,($26),1 |
119 | |
120 | .end __copy_user |
121 | EXPORT_SYMBOL(__copy_user) |
122 | |