1 | /* |
2 | * This file is subject to the terms and conditions of the GNU General Public |
3 | * License. See the file "COPYING" in the main directory of this archive |
4 | * for more details. |
5 | * |
6 | * Copyright (C) 1996, 1998 by Ralf Baechle |
7 | * |
8 | * Multi-arch abstraction and asm macros for easier reading: |
9 | * Copyright (C) 1996 David S. Miller (davem@davemloft.net) |
10 | * |
11 | * Further modifications to make this work: |
12 | * Copyright (c) 1998 Harald Koerfgen |
13 | */ |
14 | #include <linux/export.h> |
15 | #include <asm/asm.h> |
16 | #include <asm/asmmacro.h> |
17 | #include <asm/errno.h> |
18 | #include <asm/fpregdef.h> |
19 | #include <asm/mipsregs.h> |
20 | #include <asm/asm-offsets.h> |
21 | #include <asm/regdef.h> |
22 | |
23 | #define EX(a,b) \ |
24 | 9: a,##b; \ |
25 | .section __ex_table,"a"; \ |
26 | PTR_WD 9b,fault; \ |
27 | .previous |
28 | |
29 | #define EX2(a,b) \ |
30 | 9: a,##b; \ |
31 | .section __ex_table,"a"; \ |
32 | PTR_WD 9b,fault; \ |
33 | PTR_WD 9b+4,fault; \ |
34 | .previous |
35 | |
36 | .set mips1 |
37 | |
38 | /* |
39 | * Save a thread's fp context. |
40 | */ |
41 | LEAF(_save_fp) |
42 | EXPORT_SYMBOL(_save_fp) |
43 | fpu_save_single a0, t1 # clobbers t1 |
44 | jr ra |
45 | END(_save_fp) |
46 | |
47 | /* |
48 | * Restore a thread's fp context. |
49 | */ |
50 | LEAF(_restore_fp) |
51 | fpu_restore_single a0, t1 # clobbers t1 |
52 | jr ra |
53 | END(_restore_fp) |
54 | |
55 | .set noreorder |
56 | |
57 | /** |
58 | * _save_fp_context() - save FP context from the FPU |
59 | * @a0 - pointer to fpregs field of sigcontext |
60 | * @a1 - pointer to fpc_csr field of sigcontext |
61 | * |
62 | * Save FP context, including the 32 FP data registers and the FP |
63 | * control & status register, from the FPU to signal context. |
64 | */ |
65 | LEAF(_save_fp_context) |
66 | .set push |
67 | .set hardfloat |
68 | li v0, 0 # assume success |
69 | cfc1 t1, fcr31 |
70 | EX2(s.d $f0, 0(a0)) |
71 | EX2(s.d $f2, 16(a0)) |
72 | EX2(s.d $f4, 32(a0)) |
73 | EX2(s.d $f6, 48(a0)) |
74 | EX2(s.d $f8, 64(a0)) |
75 | EX2(s.d $f10, 80(a0)) |
76 | EX2(s.d $f12, 96(a0)) |
77 | EX2(s.d $f14, 112(a0)) |
78 | EX2(s.d $f16, 128(a0)) |
79 | EX2(s.d $f18, 144(a0)) |
80 | EX2(s.d $f20, 160(a0)) |
81 | EX2(s.d $f22, 176(a0)) |
82 | EX2(s.d $f24, 192(a0)) |
83 | EX2(s.d $f26, 208(a0)) |
84 | EX2(s.d $f28, 224(a0)) |
85 | EX2(s.d $f30, 240(a0)) |
86 | jr ra |
87 | EX(sw t1, (a1)) |
88 | .set pop |
89 | END(_save_fp_context) |
90 | |
91 | /** |
92 | * _restore_fp_context() - restore FP context to the FPU |
93 | * @a0 - pointer to fpregs field of sigcontext |
94 | * @a1 - pointer to fpc_csr field of sigcontext |
95 | * |
96 | * Restore FP context, including the 32 FP data registers and the FP |
97 | * control & status register, from signal context to the FPU. |
98 | */ |
99 | LEAF(_restore_fp_context) |
100 | .set push |
101 | .set hardfloat |
102 | li v0, 0 # assume success |
103 | EX(lw t0, (a1)) |
104 | EX2(l.d $f0, 0(a0)) |
105 | EX2(l.d $f2, 16(a0)) |
106 | EX2(l.d $f4, 32(a0)) |
107 | EX2(l.d $f6, 48(a0)) |
108 | EX2(l.d $f8, 64(a0)) |
109 | EX2(l.d $f10, 80(a0)) |
110 | EX2(l.d $f12, 96(a0)) |
111 | EX2(l.d $f14, 112(a0)) |
112 | EX2(l.d $f16, 128(a0)) |
113 | EX2(l.d $f18, 144(a0)) |
114 | EX2(l.d $f20, 160(a0)) |
115 | EX2(l.d $f22, 176(a0)) |
116 | EX2(l.d $f24, 192(a0)) |
117 | EX2(l.d $f26, 208(a0)) |
118 | EX2(l.d $f28, 224(a0)) |
119 | EX2(l.d $f30, 240(a0)) |
120 | jr ra |
121 | ctc1 t0, fcr31 |
122 | .set pop |
123 | END(_restore_fp_context) |
124 | .set reorder |
125 | |
126 | .type fault, @function |
127 | .ent fault |
128 | fault: li v0, -EFAULT |
129 | jr ra |
130 | .end fault |
131 | |