xref: /linux/arch/loongarch/kernel/fpu.S (revision 7bbf6d15e935abbb3d604c1fa157350e84a26f98)
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 <linux/export.h>
10#include <asm/asm.h>
11#include <asm/asmmacro.h>
12#include <asm/asm-extable.h>
13#include <asm/asm-offsets.h>
14#include <asm/errno.h>
15#include <asm/fpregdef.h>
16#include <asm/loongarch.h>
17#include <asm/regdef.h>
18#include <asm/unwind_hints.h>
19
20#define FPU_REG_WIDTH		8
21#define LSX_REG_WIDTH		16
22#define LASX_REG_WIDTH		32
23
24	.macro	EX insn, reg, src, offs
25.ex\@:	\insn	\reg, \src, \offs
26	_asm_extable .ex\@, .L_fpu_fault
27	.endm
28
29	.macro sc_save_fp base
30	EX	fst.d	$f0,  \base, (0 * FPU_REG_WIDTH)
31	EX	fst.d	$f1,  \base, (1 * FPU_REG_WIDTH)
32	EX	fst.d	$f2,  \base, (2 * FPU_REG_WIDTH)
33	EX	fst.d	$f3,  \base, (3 * FPU_REG_WIDTH)
34	EX	fst.d	$f4,  \base, (4 * FPU_REG_WIDTH)
35	EX	fst.d	$f5,  \base, (5 * FPU_REG_WIDTH)
36	EX	fst.d	$f6,  \base, (6 * FPU_REG_WIDTH)
37	EX	fst.d	$f7,  \base, (7 * FPU_REG_WIDTH)
38	EX	fst.d	$f8,  \base, (8 * FPU_REG_WIDTH)
39	EX	fst.d	$f9,  \base, (9 * FPU_REG_WIDTH)
40	EX	fst.d	$f10, \base, (10 * FPU_REG_WIDTH)
41	EX	fst.d	$f11, \base, (11 * FPU_REG_WIDTH)
42	EX	fst.d	$f12, \base, (12 * FPU_REG_WIDTH)
43	EX	fst.d	$f13, \base, (13 * FPU_REG_WIDTH)
44	EX	fst.d	$f14, \base, (14 * FPU_REG_WIDTH)
45	EX	fst.d	$f15, \base, (15 * FPU_REG_WIDTH)
46	EX	fst.d	$f16, \base, (16 * FPU_REG_WIDTH)
47	EX	fst.d	$f17, \base, (17 * FPU_REG_WIDTH)
48	EX	fst.d	$f18, \base, (18 * FPU_REG_WIDTH)
49	EX	fst.d	$f19, \base, (19 * FPU_REG_WIDTH)
50	EX	fst.d	$f20, \base, (20 * FPU_REG_WIDTH)
51	EX	fst.d	$f21, \base, (21 * FPU_REG_WIDTH)
52	EX	fst.d	$f22, \base, (22 * FPU_REG_WIDTH)
53	EX	fst.d	$f23, \base, (23 * FPU_REG_WIDTH)
54	EX	fst.d	$f24, \base, (24 * FPU_REG_WIDTH)
55	EX	fst.d	$f25, \base, (25 * FPU_REG_WIDTH)
56	EX	fst.d	$f26, \base, (26 * FPU_REG_WIDTH)
57	EX	fst.d	$f27, \base, (27 * FPU_REG_WIDTH)
58	EX	fst.d	$f28, \base, (28 * FPU_REG_WIDTH)
59	EX	fst.d	$f29, \base, (29 * FPU_REG_WIDTH)
60	EX	fst.d	$f30, \base, (30 * FPU_REG_WIDTH)
61	EX	fst.d	$f31, \base, (31 * FPU_REG_WIDTH)
62	.endm
63
64	.macro sc_restore_fp base
65	EX	fld.d	$f0,  \base, (0 * FPU_REG_WIDTH)
66	EX	fld.d	$f1,  \base, (1 * FPU_REG_WIDTH)
67	EX	fld.d	$f2,  \base, (2 * FPU_REG_WIDTH)
68	EX	fld.d	$f3,  \base, (3 * FPU_REG_WIDTH)
69	EX	fld.d	$f4,  \base, (4 * FPU_REG_WIDTH)
70	EX	fld.d	$f5,  \base, (5 * FPU_REG_WIDTH)
71	EX	fld.d	$f6,  \base, (6 * FPU_REG_WIDTH)
72	EX	fld.d	$f7,  \base, (7 * FPU_REG_WIDTH)
73	EX	fld.d	$f8,  \base, (8 * FPU_REG_WIDTH)
74	EX	fld.d	$f9,  \base, (9 * FPU_REG_WIDTH)
75	EX	fld.d	$f10, \base, (10 * FPU_REG_WIDTH)
76	EX	fld.d	$f11, \base, (11 * FPU_REG_WIDTH)
77	EX	fld.d	$f12, \base, (12 * FPU_REG_WIDTH)
78	EX	fld.d	$f13, \base, (13 * FPU_REG_WIDTH)
79	EX	fld.d	$f14, \base, (14 * FPU_REG_WIDTH)
80	EX	fld.d	$f15, \base, (15 * FPU_REG_WIDTH)
81	EX	fld.d	$f16, \base, (16 * FPU_REG_WIDTH)
82	EX	fld.d	$f17, \base, (17 * FPU_REG_WIDTH)
83	EX	fld.d	$f18, \base, (18 * FPU_REG_WIDTH)
84	EX	fld.d	$f19, \base, (19 * FPU_REG_WIDTH)
85	EX	fld.d	$f20, \base, (20 * FPU_REG_WIDTH)
86	EX	fld.d	$f21, \base, (21 * FPU_REG_WIDTH)
87	EX	fld.d	$f22, \base, (22 * FPU_REG_WIDTH)
88	EX	fld.d	$f23, \base, (23 * FPU_REG_WIDTH)
89	EX	fld.d	$f24, \base, (24 * FPU_REG_WIDTH)
90	EX	fld.d	$f25, \base, (25 * FPU_REG_WIDTH)
91	EX	fld.d	$f26, \base, (26 * FPU_REG_WIDTH)
92	EX	fld.d	$f27, \base, (27 * FPU_REG_WIDTH)
93	EX	fld.d	$f28, \base, (28 * FPU_REG_WIDTH)
94	EX	fld.d	$f29, \base, (29 * FPU_REG_WIDTH)
95	EX	fld.d	$f30, \base, (30 * FPU_REG_WIDTH)
96	EX	fld.d	$f31, \base, (31 * FPU_REG_WIDTH)
97	.endm
98
99#ifdef CONFIG_32BIT
100	.macro sc_save_fcc thread tmp0 tmp1
101	movcf2gr	\tmp0, $fcc0
102	move		\tmp1, \tmp0
103	movcf2gr	\tmp0, $fcc1
104	bstrins.w	\tmp1, \tmp0, 15, 8
105	movcf2gr	\tmp0, $fcc2
106	bstrins.w	\tmp1, \tmp0, 23, 16
107	movcf2gr	\tmp0, $fcc3
108	bstrins.w	\tmp1, \tmp0, 31, 24
109	EX	st.w	\tmp1, \thread, THREAD_FCC
110	movcf2gr	\tmp0, $fcc4
111	move		\tmp1, \tmp0
112	movcf2gr	\tmp0, $fcc5
113	bstrins.w	\tmp1, \tmp0, 15, 8
114	movcf2gr	\tmp0, $fcc6
115	bstrins.w	\tmp1, \tmp0, 23, 16
116	movcf2gr	\tmp0, $fcc7
117	bstrins.w	\tmp1, \tmp0, 31, 24
118	EX	st.w	\tmp1, \thread, (THREAD_FCC + 4)
119	.endm
120
121	.macro sc_restore_fcc thread tmp0 tmp1
122	EX	ld.w	\tmp0, \thread, THREAD_FCC
123	bstrpick.w	\tmp1, \tmp0, 7, 0
124	movgr2cf	$fcc0, \tmp1
125	bstrpick.w	\tmp1, \tmp0, 15, 8
126	movgr2cf	$fcc1, \tmp1
127	bstrpick.w	\tmp1, \tmp0, 23, 16
128	movgr2cf	$fcc2, \tmp1
129	bstrpick.w	\tmp1, \tmp0, 31, 24
130	movgr2cf	$fcc3, \tmp1
131	EX	ld.w	\tmp0, \thread, (THREAD_FCC + 4)
132	bstrpick.w	\tmp1, \tmp0, 7, 0
133	movgr2cf	$fcc4, \tmp1
134	bstrpick.w	\tmp1, \tmp0, 15, 8
135	movgr2cf	$fcc5, \tmp1
136	bstrpick.w	\tmp1, \tmp0, 23, 16
137	movgr2cf	$fcc6, \tmp1
138	bstrpick.w	\tmp1, \tmp0, 31, 24
139	movgr2cf	$fcc7, \tmp1
140	.endm
141#else
142	.macro sc_save_fcc base, tmp0, tmp1
143	movcf2gr	\tmp0, $fcc0
144	move		\tmp1, \tmp0
145	movcf2gr	\tmp0, $fcc1
146	bstrins.d	\tmp1, \tmp0, 15, 8
147	movcf2gr	\tmp0, $fcc2
148	bstrins.d	\tmp1, \tmp0, 23, 16
149	movcf2gr	\tmp0, $fcc3
150	bstrins.d	\tmp1, \tmp0, 31, 24
151	movcf2gr	\tmp0, $fcc4
152	bstrins.d	\tmp1, \tmp0, 39, 32
153	movcf2gr	\tmp0, $fcc5
154	bstrins.d	\tmp1, \tmp0, 47, 40
155	movcf2gr	\tmp0, $fcc6
156	bstrins.d	\tmp1, \tmp0, 55, 48
157	movcf2gr	\tmp0, $fcc7
158	bstrins.d	\tmp1, \tmp0, 63, 56
159	EX	st.d	\tmp1, \base, 0
160	.endm
161
162	.macro sc_restore_fcc base, tmp0, tmp1
163	EX	ld.d	\tmp0, \base, 0
164	bstrpick.d	\tmp1, \tmp0, 7, 0
165	movgr2cf	$fcc0, \tmp1
166	bstrpick.d	\tmp1, \tmp0, 15, 8
167	movgr2cf	$fcc1, \tmp1
168	bstrpick.d	\tmp1, \tmp0, 23, 16
169	movgr2cf	$fcc2, \tmp1
170	bstrpick.d	\tmp1, \tmp0, 31, 24
171	movgr2cf	$fcc3, \tmp1
172	bstrpick.d	\tmp1, \tmp0, 39, 32
173	movgr2cf	$fcc4, \tmp1
174	bstrpick.d	\tmp1, \tmp0, 47, 40
175	movgr2cf	$fcc5, \tmp1
176	bstrpick.d	\tmp1, \tmp0, 55, 48
177	movgr2cf	$fcc6, \tmp1
178	bstrpick.d	\tmp1, \tmp0, 63, 56
179	movgr2cf	$fcc7, \tmp1
180	.endm
181#endif
182
183	.macro sc_save_fcsr base, tmp0
184	movfcsr2gr	\tmp0, fcsr0
185	EX	st.w	\tmp0, \base, 0
186#if defined(CONFIG_CPU_HAS_LBT)
187	/* TM bit is always 0 if LBT not supported */
188	andi		\tmp0, \tmp0, FPU_CSR_TM
189	beqz		\tmp0, 1f
190	x86clrtm
1911:
192#endif
193	.endm
194
195	.macro sc_restore_fcsr base, tmp0
196	EX	ld.w	\tmp0, \base, 0
197	movgr2fcsr	fcsr0, \tmp0
198	.endm
199
200	.macro sc_save_lsx base
201#ifdef CONFIG_CPU_HAS_LSX
202	EX	vst	$vr0,  \base, (0 * LSX_REG_WIDTH)
203	EX	vst	$vr1,  \base, (1 * LSX_REG_WIDTH)
204	EX	vst	$vr2,  \base, (2 * LSX_REG_WIDTH)
205	EX	vst	$vr3,  \base, (3 * LSX_REG_WIDTH)
206	EX	vst	$vr4,  \base, (4 * LSX_REG_WIDTH)
207	EX	vst	$vr5,  \base, (5 * LSX_REG_WIDTH)
208	EX	vst	$vr6,  \base, (6 * LSX_REG_WIDTH)
209	EX	vst	$vr7,  \base, (7 * LSX_REG_WIDTH)
210	EX	vst	$vr8,  \base, (8 * LSX_REG_WIDTH)
211	EX	vst	$vr9,  \base, (9 * LSX_REG_WIDTH)
212	EX	vst	$vr10, \base, (10 * LSX_REG_WIDTH)
213	EX	vst	$vr11, \base, (11 * LSX_REG_WIDTH)
214	EX	vst	$vr12, \base, (12 * LSX_REG_WIDTH)
215	EX	vst	$vr13, \base, (13 * LSX_REG_WIDTH)
216	EX	vst	$vr14, \base, (14 * LSX_REG_WIDTH)
217	EX	vst	$vr15, \base, (15 * LSX_REG_WIDTH)
218	EX	vst	$vr16, \base, (16 * LSX_REG_WIDTH)
219	EX	vst	$vr17, \base, (17 * LSX_REG_WIDTH)
220	EX	vst	$vr18, \base, (18 * LSX_REG_WIDTH)
221	EX	vst	$vr19, \base, (19 * LSX_REG_WIDTH)
222	EX	vst	$vr20, \base, (20 * LSX_REG_WIDTH)
223	EX	vst	$vr21, \base, (21 * LSX_REG_WIDTH)
224	EX	vst	$vr22, \base, (22 * LSX_REG_WIDTH)
225	EX	vst	$vr23, \base, (23 * LSX_REG_WIDTH)
226	EX	vst	$vr24, \base, (24 * LSX_REG_WIDTH)
227	EX	vst	$vr25, \base, (25 * LSX_REG_WIDTH)
228	EX	vst	$vr26, \base, (26 * LSX_REG_WIDTH)
229	EX	vst	$vr27, \base, (27 * LSX_REG_WIDTH)
230	EX	vst	$vr28, \base, (28 * LSX_REG_WIDTH)
231	EX	vst	$vr29, \base, (29 * LSX_REG_WIDTH)
232	EX	vst	$vr30, \base, (30 * LSX_REG_WIDTH)
233	EX	vst	$vr31, \base, (31 * LSX_REG_WIDTH)
234#endif
235	.endm
236
237	.macro sc_restore_lsx base
238#ifdef CONFIG_CPU_HAS_LSX
239	EX	vld	$vr0,  \base, (0 * LSX_REG_WIDTH)
240	EX	vld	$vr1,  \base, (1 * LSX_REG_WIDTH)
241	EX	vld	$vr2,  \base, (2 * LSX_REG_WIDTH)
242	EX	vld	$vr3,  \base, (3 * LSX_REG_WIDTH)
243	EX	vld	$vr4,  \base, (4 * LSX_REG_WIDTH)
244	EX	vld	$vr5,  \base, (5 * LSX_REG_WIDTH)
245	EX	vld	$vr6,  \base, (6 * LSX_REG_WIDTH)
246	EX	vld	$vr7,  \base, (7 * LSX_REG_WIDTH)
247	EX	vld	$vr8,  \base, (8 * LSX_REG_WIDTH)
248	EX	vld	$vr9,  \base, (9 * LSX_REG_WIDTH)
249	EX	vld	$vr10, \base, (10 * LSX_REG_WIDTH)
250	EX	vld	$vr11, \base, (11 * LSX_REG_WIDTH)
251	EX	vld	$vr12, \base, (12 * LSX_REG_WIDTH)
252	EX	vld	$vr13, \base, (13 * LSX_REG_WIDTH)
253	EX	vld	$vr14, \base, (14 * LSX_REG_WIDTH)
254	EX	vld	$vr15, \base, (15 * LSX_REG_WIDTH)
255	EX	vld	$vr16, \base, (16 * LSX_REG_WIDTH)
256	EX	vld	$vr17, \base, (17 * LSX_REG_WIDTH)
257	EX	vld	$vr18, \base, (18 * LSX_REG_WIDTH)
258	EX	vld	$vr19, \base, (19 * LSX_REG_WIDTH)
259	EX	vld	$vr20, \base, (20 * LSX_REG_WIDTH)
260	EX	vld	$vr21, \base, (21 * LSX_REG_WIDTH)
261	EX	vld	$vr22, \base, (22 * LSX_REG_WIDTH)
262	EX	vld	$vr23, \base, (23 * LSX_REG_WIDTH)
263	EX	vld	$vr24, \base, (24 * LSX_REG_WIDTH)
264	EX	vld	$vr25, \base, (25 * LSX_REG_WIDTH)
265	EX	vld	$vr26, \base, (26 * LSX_REG_WIDTH)
266	EX	vld	$vr27, \base, (27 * LSX_REG_WIDTH)
267	EX	vld	$vr28, \base, (28 * LSX_REG_WIDTH)
268	EX	vld	$vr29, \base, (29 * LSX_REG_WIDTH)
269	EX	vld	$vr30, \base, (30 * LSX_REG_WIDTH)
270	EX	vld	$vr31, \base, (31 * LSX_REG_WIDTH)
271#endif
272	.endm
273
274	.macro sc_save_lasx base
275#ifdef CONFIG_CPU_HAS_LASX
276	EX	xvst	$xr0,  \base, (0 * LASX_REG_WIDTH)
277	EX	xvst	$xr1,  \base, (1 * LASX_REG_WIDTH)
278	EX	xvst	$xr2,  \base, (2 * LASX_REG_WIDTH)
279	EX	xvst	$xr3,  \base, (3 * LASX_REG_WIDTH)
280	EX	xvst	$xr4,  \base, (4 * LASX_REG_WIDTH)
281	EX	xvst	$xr5,  \base, (5 * LASX_REG_WIDTH)
282	EX	xvst	$xr6,  \base, (6 * LASX_REG_WIDTH)
283	EX	xvst	$xr7,  \base, (7 * LASX_REG_WIDTH)
284	EX	xvst	$xr8,  \base, (8 * LASX_REG_WIDTH)
285	EX	xvst	$xr9,  \base, (9 * LASX_REG_WIDTH)
286	EX	xvst	$xr10, \base, (10 * LASX_REG_WIDTH)
287	EX	xvst	$xr11, \base, (11 * LASX_REG_WIDTH)
288	EX	xvst	$xr12, \base, (12 * LASX_REG_WIDTH)
289	EX	xvst	$xr13, \base, (13 * LASX_REG_WIDTH)
290	EX	xvst	$xr14, \base, (14 * LASX_REG_WIDTH)
291	EX	xvst	$xr15, \base, (15 * LASX_REG_WIDTH)
292	EX	xvst	$xr16, \base, (16 * LASX_REG_WIDTH)
293	EX	xvst	$xr17, \base, (17 * LASX_REG_WIDTH)
294	EX	xvst	$xr18, \base, (18 * LASX_REG_WIDTH)
295	EX	xvst	$xr19, \base, (19 * LASX_REG_WIDTH)
296	EX	xvst	$xr20, \base, (20 * LASX_REG_WIDTH)
297	EX	xvst	$xr21, \base, (21 * LASX_REG_WIDTH)
298	EX	xvst	$xr22, \base, (22 * LASX_REG_WIDTH)
299	EX	xvst	$xr23, \base, (23 * LASX_REG_WIDTH)
300	EX	xvst	$xr24, \base, (24 * LASX_REG_WIDTH)
301	EX	xvst	$xr25, \base, (25 * LASX_REG_WIDTH)
302	EX	xvst	$xr26, \base, (26 * LASX_REG_WIDTH)
303	EX	xvst	$xr27, \base, (27 * LASX_REG_WIDTH)
304	EX	xvst	$xr28, \base, (28 * LASX_REG_WIDTH)
305	EX	xvst	$xr29, \base, (29 * LASX_REG_WIDTH)
306	EX	xvst	$xr30, \base, (30 * LASX_REG_WIDTH)
307	EX	xvst	$xr31, \base, (31 * LASX_REG_WIDTH)
308#endif
309	.endm
310
311	.macro sc_restore_lasx base
312#ifdef CONFIG_CPU_HAS_LASX
313	EX	xvld	$xr0,  \base, (0 * LASX_REG_WIDTH)
314	EX	xvld	$xr1,  \base, (1 * LASX_REG_WIDTH)
315	EX	xvld	$xr2,  \base, (2 * LASX_REG_WIDTH)
316	EX	xvld	$xr3,  \base, (3 * LASX_REG_WIDTH)
317	EX	xvld	$xr4,  \base, (4 * LASX_REG_WIDTH)
318	EX	xvld	$xr5,  \base, (5 * LASX_REG_WIDTH)
319	EX	xvld	$xr6,  \base, (6 * LASX_REG_WIDTH)
320	EX	xvld	$xr7,  \base, (7 * LASX_REG_WIDTH)
321	EX	xvld	$xr8,  \base, (8 * LASX_REG_WIDTH)
322	EX	xvld	$xr9,  \base, (9 * LASX_REG_WIDTH)
323	EX	xvld	$xr10, \base, (10 * LASX_REG_WIDTH)
324	EX	xvld	$xr11, \base, (11 * LASX_REG_WIDTH)
325	EX	xvld	$xr12, \base, (12 * LASX_REG_WIDTH)
326	EX	xvld	$xr13, \base, (13 * LASX_REG_WIDTH)
327	EX	xvld	$xr14, \base, (14 * LASX_REG_WIDTH)
328	EX	xvld	$xr15, \base, (15 * LASX_REG_WIDTH)
329	EX	xvld	$xr16, \base, (16 * LASX_REG_WIDTH)
330	EX	xvld	$xr17, \base, (17 * LASX_REG_WIDTH)
331	EX	xvld	$xr18, \base, (18 * LASX_REG_WIDTH)
332	EX	xvld	$xr19, \base, (19 * LASX_REG_WIDTH)
333	EX	xvld	$xr20, \base, (20 * LASX_REG_WIDTH)
334	EX	xvld	$xr21, \base, (21 * LASX_REG_WIDTH)
335	EX	xvld	$xr22, \base, (22 * LASX_REG_WIDTH)
336	EX	xvld	$xr23, \base, (23 * LASX_REG_WIDTH)
337	EX	xvld	$xr24, \base, (24 * LASX_REG_WIDTH)
338	EX	xvld	$xr25, \base, (25 * LASX_REG_WIDTH)
339	EX	xvld	$xr26, \base, (26 * LASX_REG_WIDTH)
340	EX	xvld	$xr27, \base, (27 * LASX_REG_WIDTH)
341	EX	xvld	$xr28, \base, (28 * LASX_REG_WIDTH)
342	EX	xvld	$xr29, \base, (29 * LASX_REG_WIDTH)
343	EX	xvld	$xr30, \base, (30 * LASX_REG_WIDTH)
344	EX	xvld	$xr31, \base, (31 * LASX_REG_WIDTH)
345#endif
346	.endm
347
348/*
349 * Save a thread's fp context.
350 */
351SYM_FUNC_START(_save_fp)
352	fpu_save_csr	a0 t1
353	fpu_save_double	a0 t1			# clobbers t1
354	fpu_save_cc	a0 t1 t2		# clobbers t1, t2
355	jr		ra
356SYM_FUNC_END(_save_fp)
357EXPORT_SYMBOL(_save_fp)
358
359/*
360 * Restore a thread's fp context.
361 */
362SYM_FUNC_START(_restore_fp)
363	fpu_restore_double	a0 t1		# clobbers t1
364	fpu_restore_csr		a0 t1 t2
365	fpu_restore_cc		a0 t1 t2	# clobbers t1, t2
366	jr			ra
367SYM_FUNC_END(_restore_fp)
368
369#ifdef CONFIG_CPU_HAS_LSX
370
371/*
372 * Save a thread's LSX vector context.
373 */
374SYM_FUNC_START(_save_lsx)
375	lsx_save_all	a0 t1 t2
376	jr	ra
377SYM_FUNC_END(_save_lsx)
378EXPORT_SYMBOL(_save_lsx)
379
380/*
381 * Restore a thread's LSX vector context.
382 */
383SYM_FUNC_START(_restore_lsx)
384	lsx_restore_all	a0 t1 t2
385	jr	ra
386SYM_FUNC_END(_restore_lsx)
387
388SYM_FUNC_START(_save_lsx_upper)
389	lsx_save_all_upper a0 t0 t1
390	jr	ra
391SYM_FUNC_END(_save_lsx_upper)
392
393SYM_FUNC_START(_restore_lsx_upper)
394	lsx_restore_all_upper a0 t0 t1
395	jr	ra
396SYM_FUNC_END(_restore_lsx_upper)
397EXPORT_SYMBOL(_restore_lsx_upper)
398
399SYM_FUNC_START(_init_lsx_upper)
400	lsx_init_all_upper t1
401	jr	ra
402SYM_FUNC_END(_init_lsx_upper)
403#endif
404
405#ifdef CONFIG_CPU_HAS_LASX
406
407/*
408 * Save a thread's LASX vector context.
409 */
410SYM_FUNC_START(_save_lasx)
411	lasx_save_all	a0 t1 t2
412	jr	ra
413SYM_FUNC_END(_save_lasx)
414EXPORT_SYMBOL(_save_lasx)
415
416/*
417 * Restore a thread's LASX vector context.
418 */
419SYM_FUNC_START(_restore_lasx)
420	lasx_restore_all a0 t1 t2
421	jr	ra
422SYM_FUNC_END(_restore_lasx)
423
424SYM_FUNC_START(_save_lasx_upper)
425	lasx_save_all_upper a0 t0 t1
426	jr	ra
427SYM_FUNC_END(_save_lasx_upper)
428
429SYM_FUNC_START(_restore_lasx_upper)
430	lasx_restore_all_upper a0 t0 t1
431	jr	ra
432SYM_FUNC_END(_restore_lasx_upper)
433EXPORT_SYMBOL(_restore_lasx_upper)
434
435SYM_FUNC_START(_init_lasx_upper)
436	lasx_init_all_upper t1
437	jr	ra
438SYM_FUNC_END(_init_lasx_upper)
439#endif
440
441/*
442 * Load the FPU with signalling NANS.  This bit pattern we're using has
443 * the property that no matter whether considered as single or as double
444 * precision represents signaling NANS.
445 *
446 * The value to initialize fcsr0 to comes in $a0.
447 */
448
449SYM_FUNC_START(_init_fpu)
450	li.w	t1, CSR_EUEN_FPEN
451	csrxchg	t1, t1, LOONGARCH_CSR_EUEN
452
453	movgr2fcsr	fcsr0, a0
454
455	li.w	t1, -1				# SNaN
456
457#ifdef CONFIG_32BIT
458	movgr2fr.w	$f0, t1
459	movgr2frh.w	$f0, t1
460	movgr2fr.w	$f1, t1
461	movgr2frh.w	$f1, t1
462	movgr2fr.w	$f2, t1
463	movgr2frh.w	$f2, t1
464	movgr2fr.w	$f3, t1
465	movgr2frh.w	$f3, t1
466	movgr2fr.w	$f4, t1
467	movgr2frh.w	$f4, t1
468	movgr2fr.w	$f5, t1
469	movgr2frh.w	$f5, t1
470	movgr2fr.w	$f6, t1
471	movgr2frh.w	$f6, t1
472	movgr2fr.w	$f7, t1
473	movgr2frh.w	$f7, t1
474	movgr2fr.w	$f8, t1
475	movgr2frh.w	$f8, t1
476	movgr2fr.w	$f9, t1
477	movgr2frh.w	$f9, t1
478	movgr2fr.w	$f10, t1
479	movgr2frh.w	$f10, t1
480	movgr2fr.w	$f11, t1
481	movgr2frh.w	$f11, t1
482	movgr2fr.w	$f12, t1
483	movgr2frh.w	$f12, t1
484	movgr2fr.w	$f13, t1
485	movgr2frh.w	$f13, t1
486	movgr2fr.w	$f14, t1
487	movgr2frh.w	$f14, t1
488	movgr2fr.w	$f15, t1
489	movgr2frh.w	$f15, t1
490	movgr2fr.w	$f16, t1
491	movgr2frh.w	$f16, t1
492	movgr2fr.w	$f17, t1
493	movgr2frh.w	$f17, t1
494	movgr2fr.w	$f18, t1
495	movgr2frh.w	$f18, t1
496	movgr2fr.w	$f19, t1
497	movgr2frh.w	$f19, t1
498	movgr2fr.w	$f20, t1
499	movgr2frh.w	$f20, t1
500	movgr2fr.w	$f21, t1
501	movgr2frh.w	$f21, t1
502	movgr2fr.w	$f22, t1
503	movgr2frh.w	$f22, t1
504	movgr2fr.w	$f23, t1
505	movgr2frh.w	$f23, t1
506	movgr2fr.w	$f24, t1
507	movgr2frh.w	$f24, t1
508	movgr2fr.w	$f25, t1
509	movgr2frh.w	$f25, t1
510	movgr2fr.w	$f26, t1
511	movgr2frh.w	$f26, t1
512	movgr2fr.w	$f27, t1
513	movgr2frh.w	$f27, t1
514	movgr2fr.w	$f28, t1
515	movgr2frh.w	$f28, t1
516	movgr2fr.w	$f29, t1
517	movgr2frh.w	$f29, t1
518	movgr2fr.w	$f30, t1
519	movgr2frh.w	$f30, t1
520	movgr2fr.w	$f31, t1
521	movgr2frh.w	$f31, t1
522#else
523	movgr2fr.d	$f0, t1
524	movgr2fr.d	$f1, t1
525	movgr2fr.d	$f2, t1
526	movgr2fr.d	$f3, t1
527	movgr2fr.d	$f4, t1
528	movgr2fr.d	$f5, t1
529	movgr2fr.d	$f6, t1
530	movgr2fr.d	$f7, t1
531	movgr2fr.d	$f8, t1
532	movgr2fr.d	$f9, t1
533	movgr2fr.d	$f10, t1
534	movgr2fr.d	$f11, t1
535	movgr2fr.d	$f12, t1
536	movgr2fr.d	$f13, t1
537	movgr2fr.d	$f14, t1
538	movgr2fr.d	$f15, t1
539	movgr2fr.d	$f16, t1
540	movgr2fr.d	$f17, t1
541	movgr2fr.d	$f18, t1
542	movgr2fr.d	$f19, t1
543	movgr2fr.d	$f20, t1
544	movgr2fr.d	$f21, t1
545	movgr2fr.d	$f22, t1
546	movgr2fr.d	$f23, t1
547	movgr2fr.d	$f24, t1
548	movgr2fr.d	$f25, t1
549	movgr2fr.d	$f26, t1
550	movgr2fr.d	$f27, t1
551	movgr2fr.d	$f28, t1
552	movgr2fr.d	$f29, t1
553	movgr2fr.d	$f30, t1
554	movgr2fr.d	$f31, t1
555#endif
556
557	jr	ra
558SYM_FUNC_END(_init_fpu)
559
560/*
561 * a0: fpregs
562 * a1: fcc
563 * a2: fcsr
564 */
565SYM_FUNC_START(_save_fp_context)
566	sc_save_fcc	a1 t1 t2
567	sc_save_fcsr	a2 t1
568	sc_save_fp	a0
569	li.w		a0, 0				# success
570	jr		ra
571SYM_FUNC_END(_save_fp_context)
572EXPORT_SYMBOL_GPL(_save_fp_context)
573
574/*
575 * a0: fpregs
576 * a1: fcc
577 * a2: fcsr
578 */
579SYM_FUNC_START(_restore_fp_context)
580	sc_restore_fp	a0
581	sc_restore_fcc	a1 t1 t2
582	sc_restore_fcsr	a2 t1
583	li.w		a0, 0				# success
584	jr		ra
585SYM_FUNC_END(_restore_fp_context)
586EXPORT_SYMBOL_GPL(_restore_fp_context)
587
588/*
589 * a0: fpregs
590 * a1: fcc
591 * a2: fcsr
592 */
593SYM_FUNC_START(_save_lsx_context)
594	sc_save_fcc a1, t0, t1
595	sc_save_fcsr a2, t0
596	sc_save_lsx a0
597	li.w	a0, 0					# success
598	jr	ra
599SYM_FUNC_END(_save_lsx_context)
600EXPORT_SYMBOL_GPL(_save_lsx_context)
601
602/*
603 * a0: fpregs
604 * a1: fcc
605 * a2: fcsr
606 */
607SYM_FUNC_START(_restore_lsx_context)
608	sc_restore_lsx a0
609	sc_restore_fcc a1, t1, t2
610	sc_restore_fcsr a2, t1
611	li.w	a0, 0					# success
612	jr	ra
613SYM_FUNC_END(_restore_lsx_context)
614EXPORT_SYMBOL_GPL(_restore_lsx_context)
615
616/*
617 * a0: fpregs
618 * a1: fcc
619 * a2: fcsr
620 */
621SYM_FUNC_START(_save_lasx_context)
622	sc_save_fcc a1, t0, t1
623	sc_save_fcsr a2, t0
624	sc_save_lasx a0
625	li.w	a0, 0					# success
626	jr	ra
627SYM_FUNC_END(_save_lasx_context)
628EXPORT_SYMBOL_GPL(_save_lasx_context)
629
630/*
631 * a0: fpregs
632 * a1: fcc
633 * a2: fcsr
634 */
635SYM_FUNC_START(_restore_lasx_context)
636	sc_restore_lasx a0
637	sc_restore_fcc a1, t1, t2
638	sc_restore_fcsr a2, t1
639	li.w	a0, 0					# success
640	jr	ra
641SYM_FUNC_END(_restore_lasx_context)
642EXPORT_SYMBOL_GPL(_restore_lasx_context)
643
644.L_fpu_fault:
645	li.w	a0, -EFAULT				# failure
646	jr	ra
647
648#ifdef CONFIG_CPU_HAS_LBT
649STACK_FRAME_NON_STANDARD _restore_fp
650#ifdef CONFIG_CPU_HAS_LSX
651STACK_FRAME_NON_STANDARD _restore_lsx
652#endif
653#ifdef CONFIG_CPU_HAS_LASX
654STACK_FRAME_NON_STANDARD _restore_lasx
655#endif
656#endif
657