Merge tag 'block-6.2-2023-01-27' of git://git.kernel.dk/linux
[linux-2.6-block.git] / arch / loongarch / kernel / fpu.S
CommitLineData
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 */
151SYM_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
156SYM_FUNC_END(_save_fp)
157EXPORT_SYMBOL(_save_fp)
158
159/*
160 * Restore a thread's fp context.
161 */
162SYM_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
167SYM_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
177SYM_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
219SYM_FUNC_END(_init_fpu)
220
221/*
222 * a0: fpregs
223 * a1: fcc
224 * a2: fcsr
225 */
226SYM_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
232SYM_FUNC_END(_save_fp_context)
233
234/*
235 * a0: fpregs
236 * a1: fcc
237 * a2: fcsr
238 */
239SYM_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
245SYM_FUNC_END(_restore_fp_context)
246
247SYM_FUNC_START(fault)
248 li.w a0, -EFAULT # failure
07b48069 249 jr ra
803b0fc5 250SYM_FUNC_END(fault)