Commit | Line | Data |
---|---|---|
803b0fc5 HC |
1 | /* SPDX-License-Identifier: GPL-2.0 */ |
2 | /* | |
3 | * Author: Lu Zeng <zenglu@loongson.cn> | |
4 | * Pei Huang <huangpei@loongson.cn> | |
5 | * Huacai Chen <chenhuacai@loongson.cn> | |
6 | * | |
7 | * Copyright (C) 2020-2022 Loongson Technology Corporation Limited | |
8 | */ | |
9 | #include <asm/asm.h> | |
10 | #include <asm/asmmacro.h> | |
508f28c6 | 11 | #include <asm/asm-extable.h> |
803b0fc5 HC |
12 | #include <asm/asm-offsets.h> |
13 | #include <asm/errno.h> | |
14 | #include <asm/export.h> | |
15 | #include <asm/fpregdef.h> | |
16 | #include <asm/loongarch.h> | |
17 | #include <asm/regdef.h> | |
18 | ||
19 | #define FPU_REG_WIDTH 8 | |
20 | #define LSX_REG_WIDTH 16 | |
21 | #define LASX_REG_WIDTH 32 | |
22 | ||
23 | .macro EX insn, reg, src, offs | |
24 | .ex\@: \insn \reg, \src, \offs | |
508f28c6 | 25 | _asm_extable .ex\@, fault |
803b0fc5 HC |
26 | .endm |
27 | ||
28 | .macro sc_save_fp base | |
f5c3c22f WX |
29 | EX fst.d $f0, \base, (0 * FPU_REG_WIDTH) |
30 | EX fst.d $f1, \base, (1 * FPU_REG_WIDTH) | |
31 | EX fst.d $f2, \base, (2 * FPU_REG_WIDTH) | |
32 | EX fst.d $f3, \base, (3 * FPU_REG_WIDTH) | |
33 | EX fst.d $f4, \base, (4 * FPU_REG_WIDTH) | |
34 | EX fst.d $f5, \base, (5 * FPU_REG_WIDTH) | |
35 | EX fst.d $f6, \base, (6 * FPU_REG_WIDTH) | |
36 | EX fst.d $f7, \base, (7 * FPU_REG_WIDTH) | |
37 | EX fst.d $f8, \base, (8 * FPU_REG_WIDTH) | |
38 | EX fst.d $f9, \base, (9 * FPU_REG_WIDTH) | |
39 | EX fst.d $f10, \base, (10 * FPU_REG_WIDTH) | |
40 | EX fst.d $f11, \base, (11 * FPU_REG_WIDTH) | |
41 | EX fst.d $f12, \base, (12 * FPU_REG_WIDTH) | |
42 | EX fst.d $f13, \base, (13 * FPU_REG_WIDTH) | |
43 | EX fst.d $f14, \base, (14 * FPU_REG_WIDTH) | |
44 | EX fst.d $f15, \base, (15 * FPU_REG_WIDTH) | |
45 | EX fst.d $f16, \base, (16 * FPU_REG_WIDTH) | |
46 | EX fst.d $f17, \base, (17 * FPU_REG_WIDTH) | |
47 | EX fst.d $f18, \base, (18 * FPU_REG_WIDTH) | |
48 | EX fst.d $f19, \base, (19 * FPU_REG_WIDTH) | |
49 | EX fst.d $f20, \base, (20 * FPU_REG_WIDTH) | |
50 | EX fst.d $f21, \base, (21 * FPU_REG_WIDTH) | |
51 | EX fst.d $f22, \base, (22 * FPU_REG_WIDTH) | |
52 | EX fst.d $f23, \base, (23 * FPU_REG_WIDTH) | |
53 | EX fst.d $f24, \base, (24 * FPU_REG_WIDTH) | |
54 | EX fst.d $f25, \base, (25 * FPU_REG_WIDTH) | |
55 | EX fst.d $f26, \base, (26 * FPU_REG_WIDTH) | |
56 | EX fst.d $f27, \base, (27 * FPU_REG_WIDTH) | |
57 | EX fst.d $f28, \base, (28 * FPU_REG_WIDTH) | |
58 | EX fst.d $f29, \base, (29 * FPU_REG_WIDTH) | |
59 | EX fst.d $f30, \base, (30 * FPU_REG_WIDTH) | |
60 | EX fst.d $f31, \base, (31 * FPU_REG_WIDTH) | |
803b0fc5 HC |
61 | .endm |
62 | ||
63 | .macro sc_restore_fp base | |
f5c3c22f WX |
64 | EX fld.d $f0, \base, (0 * FPU_REG_WIDTH) |
65 | EX fld.d $f1, \base, (1 * FPU_REG_WIDTH) | |
66 | EX fld.d $f2, \base, (2 * FPU_REG_WIDTH) | |
67 | EX fld.d $f3, \base, (3 * FPU_REG_WIDTH) | |
68 | EX fld.d $f4, \base, (4 * FPU_REG_WIDTH) | |
69 | EX fld.d $f5, \base, (5 * FPU_REG_WIDTH) | |
70 | EX fld.d $f6, \base, (6 * FPU_REG_WIDTH) | |
71 | EX fld.d $f7, \base, (7 * FPU_REG_WIDTH) | |
72 | EX fld.d $f8, \base, (8 * FPU_REG_WIDTH) | |
73 | EX fld.d $f9, \base, (9 * FPU_REG_WIDTH) | |
74 | EX fld.d $f10, \base, (10 * FPU_REG_WIDTH) | |
75 | EX fld.d $f11, \base, (11 * FPU_REG_WIDTH) | |
76 | EX fld.d $f12, \base, (12 * FPU_REG_WIDTH) | |
77 | EX fld.d $f13, \base, (13 * FPU_REG_WIDTH) | |
78 | EX fld.d $f14, \base, (14 * FPU_REG_WIDTH) | |
79 | EX fld.d $f15, \base, (15 * FPU_REG_WIDTH) | |
80 | EX fld.d $f16, \base, (16 * FPU_REG_WIDTH) | |
81 | EX fld.d $f17, \base, (17 * FPU_REG_WIDTH) | |
82 | EX fld.d $f18, \base, (18 * FPU_REG_WIDTH) | |
83 | EX fld.d $f19, \base, (19 * FPU_REG_WIDTH) | |
84 | EX fld.d $f20, \base, (20 * FPU_REG_WIDTH) | |
85 | EX fld.d $f21, \base, (21 * FPU_REG_WIDTH) | |
86 | EX fld.d $f22, \base, (22 * FPU_REG_WIDTH) | |
87 | EX fld.d $f23, \base, (23 * FPU_REG_WIDTH) | |
88 | EX fld.d $f24, \base, (24 * FPU_REG_WIDTH) | |
89 | EX fld.d $f25, \base, (25 * FPU_REG_WIDTH) | |
90 | EX fld.d $f26, \base, (26 * FPU_REG_WIDTH) | |
91 | EX fld.d $f27, \base, (27 * FPU_REG_WIDTH) | |
92 | EX fld.d $f28, \base, (28 * FPU_REG_WIDTH) | |
93 | EX fld.d $f29, \base, (29 * FPU_REG_WIDTH) | |
94 | EX fld.d $f30, \base, (30 * FPU_REG_WIDTH) | |
95 | EX fld.d $f31, \base, (31 * FPU_REG_WIDTH) | |
803b0fc5 HC |
96 | .endm |
97 | ||
98 | .macro sc_save_fcc base, tmp0, tmp1 | |
99 | movcf2gr \tmp0, $fcc0 | |
f5c3c22f | 100 | move \tmp1, \tmp0 |
803b0fc5 HC |
101 | movcf2gr \tmp0, $fcc1 |
102 | bstrins.d \tmp1, \tmp0, 15, 8 | |
103 | movcf2gr \tmp0, $fcc2 | |
104 | bstrins.d \tmp1, \tmp0, 23, 16 | |
105 | movcf2gr \tmp0, $fcc3 | |
106 | bstrins.d \tmp1, \tmp0, 31, 24 | |
107 | movcf2gr \tmp0, $fcc4 | |
108 | bstrins.d \tmp1, \tmp0, 39, 32 | |
109 | movcf2gr \tmp0, $fcc5 | |
110 | bstrins.d \tmp1, \tmp0, 47, 40 | |
111 | movcf2gr \tmp0, $fcc6 | |
112 | bstrins.d \tmp1, \tmp0, 55, 48 | |
113 | movcf2gr \tmp0, $fcc7 | |
114 | bstrins.d \tmp1, \tmp0, 63, 56 | |
f5c3c22f | 115 | EX st.d \tmp1, \base, 0 |
803b0fc5 HC |
116 | .endm |
117 | ||
118 | .macro sc_restore_fcc base, tmp0, tmp1 | |
f5c3c22f | 119 | EX ld.d \tmp0, \base, 0 |
803b0fc5 HC |
120 | bstrpick.d \tmp1, \tmp0, 7, 0 |
121 | movgr2cf $fcc0, \tmp1 | |
122 | bstrpick.d \tmp1, \tmp0, 15, 8 | |
123 | movgr2cf $fcc1, \tmp1 | |
124 | bstrpick.d \tmp1, \tmp0, 23, 16 | |
125 | movgr2cf $fcc2, \tmp1 | |
126 | bstrpick.d \tmp1, \tmp0, 31, 24 | |
127 | movgr2cf $fcc3, \tmp1 | |
128 | bstrpick.d \tmp1, \tmp0, 39, 32 | |
129 | movgr2cf $fcc4, \tmp1 | |
130 | bstrpick.d \tmp1, \tmp0, 47, 40 | |
131 | movgr2cf $fcc5, \tmp1 | |
132 | bstrpick.d \tmp1, \tmp0, 55, 48 | |
133 | movgr2cf $fcc6, \tmp1 | |
134 | bstrpick.d \tmp1, \tmp0, 63, 56 | |
135 | movgr2cf $fcc7, \tmp1 | |
136 | .endm | |
137 | ||
138 | .macro sc_save_fcsr base, tmp0 | |
139 | movfcsr2gr \tmp0, fcsr0 | |
f5c3c22f | 140 | EX st.w \tmp0, \base, 0 |
803b0fc5 HC |
141 | .endm |
142 | ||
143 | .macro sc_restore_fcsr base, tmp0 | |
f5c3c22f | 144 | EX ld.w \tmp0, \base, 0 |
803b0fc5 HC |
145 | movgr2fcsr fcsr0, \tmp0 |
146 | .endm | |
147 | ||
803b0fc5 HC |
148 | /* |
149 | * Save a thread's fp context. | |
150 | */ | |
151 | SYM_FUNC_START(_save_fp) | |
152 | fpu_save_csr a0 t1 | |
f5c3c22f | 153 | fpu_save_double a0 t1 # clobbers t1 |
803b0fc5 | 154 | fpu_save_cc a0 t1 t2 # clobbers t1, t2 |
f5c3c22f | 155 | jr ra |
803b0fc5 HC |
156 | SYM_FUNC_END(_save_fp) |
157 | EXPORT_SYMBOL(_save_fp) | |
158 | ||
159 | /* | |
160 | * Restore a thread's fp context. | |
161 | */ | |
162 | SYM_FUNC_START(_restore_fp) | |
f5c3c22f WX |
163 | fpu_restore_double a0 t1 # clobbers t1 |
164 | fpu_restore_csr a0 t1 | |
165 | fpu_restore_cc a0 t1 t2 # clobbers t1, t2 | |
166 | jr ra | |
803b0fc5 HC |
167 | SYM_FUNC_END(_restore_fp) |
168 | ||
169 | /* | |
170 | * Load the FPU with signalling NANS. This bit pattern we're using has | |
171 | * the property that no matter whether considered as single or as double | |
172 | * precision represents signaling NANS. | |
173 | * | |
174 | * The value to initialize fcsr0 to comes in $a0. | |
175 | */ | |
176 | ||
177 | SYM_FUNC_START(_init_fpu) | |
178 | li.w t1, CSR_EUEN_FPEN | |
179 | csrxchg t1, t1, LOONGARCH_CSR_EUEN | |
180 | ||
181 | movgr2fcsr fcsr0, a0 | |
182 | ||
183 | li.w t1, -1 # SNaN | |
184 | ||
185 | movgr2fr.d $f0, t1 | |
186 | movgr2fr.d $f1, t1 | |
187 | movgr2fr.d $f2, t1 | |
188 | movgr2fr.d $f3, t1 | |
189 | movgr2fr.d $f4, t1 | |
190 | movgr2fr.d $f5, t1 | |
191 | movgr2fr.d $f6, t1 | |
192 | movgr2fr.d $f7, t1 | |
193 | movgr2fr.d $f8, t1 | |
194 | movgr2fr.d $f9, t1 | |
195 | movgr2fr.d $f10, t1 | |
196 | movgr2fr.d $f11, t1 | |
197 | movgr2fr.d $f12, t1 | |
198 | movgr2fr.d $f13, t1 | |
199 | movgr2fr.d $f14, t1 | |
200 | movgr2fr.d $f15, t1 | |
201 | movgr2fr.d $f16, t1 | |
202 | movgr2fr.d $f17, t1 | |
203 | movgr2fr.d $f18, t1 | |
204 | movgr2fr.d $f19, t1 | |
205 | movgr2fr.d $f20, t1 | |
206 | movgr2fr.d $f21, t1 | |
207 | movgr2fr.d $f22, t1 | |
208 | movgr2fr.d $f23, t1 | |
209 | movgr2fr.d $f24, t1 | |
210 | movgr2fr.d $f25, t1 | |
211 | movgr2fr.d $f26, t1 | |
212 | movgr2fr.d $f27, t1 | |
213 | movgr2fr.d $f28, t1 | |
214 | movgr2fr.d $f29, t1 | |
215 | movgr2fr.d $f30, t1 | |
216 | movgr2fr.d $f31, t1 | |
217 | ||
07b48069 | 218 | jr ra |
803b0fc5 HC |
219 | SYM_FUNC_END(_init_fpu) |
220 | ||
221 | /* | |
222 | * a0: fpregs | |
223 | * a1: fcc | |
224 | * a2: fcsr | |
225 | */ | |
226 | SYM_FUNC_START(_save_fp_context) | |
f5c3c22f WX |
227 | sc_save_fcc a1 t1 t2 |
228 | sc_save_fcsr a2 t1 | |
229 | sc_save_fp a0 | |
230 | li.w a0, 0 # success | |
231 | jr ra | |
803b0fc5 HC |
232 | SYM_FUNC_END(_save_fp_context) |
233 | ||
234 | /* | |
235 | * a0: fpregs | |
236 | * a1: fcc | |
237 | * a2: fcsr | |
238 | */ | |
239 | SYM_FUNC_START(_restore_fp_context) | |
f5c3c22f WX |
240 | sc_restore_fp a0 |
241 | sc_restore_fcc a1 t1 t2 | |
242 | sc_restore_fcsr a2 t1 | |
243 | li.w a0, 0 # success | |
244 | jr ra | |
803b0fc5 HC |
245 | SYM_FUNC_END(_restore_fp_context) |
246 | ||
247 | SYM_FUNC_START(fault) | |
248 | li.w a0, -EFAULT # failure | |
07b48069 | 249 | jr ra |
803b0fc5 | 250 | SYM_FUNC_END(fault) |