xref: /openbsd-src/sys/arch/mips64/mips64/lcore_float.S (revision 4452dbdacf59a707aac2c0ffc2909762ac11182c)
1/*	$OpenBSD: lcore_float.S,v 1.23 2019/01/14 15:02:57 visa Exp $ */
2
3/*
4 * Copyright (c) 2001-2003 Opsycon AB  (www.opsycon.se / www.opsycon.com)
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
16 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
19 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 */
28#include <sys/errno.h>
29#include <sys/syscall.h>
30
31#include <machine/param.h>
32#include <machine/asm.h>
33#include <machine/cpu.h>
34#include <mips64/mips_cpu.h>
35#include <machine/regnum.h>
36#include <machine/cpustate.h>
37
38#include "assym.h"
39
40	.set	mips3
41	.set	noreorder		# Noreorder is default style!
42	.set	hardfloat
43
44/*----------------------------------------------------------------------------
45 *
46 * MipsSwitchFPState --
47 *
48 *	Save the current state into 'from' and restore it from 'to'.
49 *
50 *	MipsSwitchFPState(from, to)
51 *		struct proc *from;
52 *		struct user *to;
53 *
54 * Results:
55 *	None.
56 *
57 * Side effects:
58 *	None.
59 *
60 *----------------------------------------------------------------------------
61 */
62LEAF(MipsSwitchFPState, 0)
63	MFC0	t1, COP_0_STATUS_REG	# Save old SR
64	MFC0_HAZARD
65	or	t0, t1, SR_COP_1_BIT|SR_FR_32	# enable the coprocessor
66	MTC0	t0, COP_0_STATUS_REG
67	MTC0_SR_CU_HAZARD
68
69	beq	a0, zero, 1f		# skip save if NULL pointer
70	 NOP
71/*
72 * First read out the status register to make sure that all FP operations
73 * have completed.
74 */
75	PTR_L	a0, P_ADDR(a0)		# get pointer to pcb for proc
76	cfc1	t0, FPC_CSR		# stall til FP done
77	cfc1	t0, FPC_CSR		# now get status
78	LI	t3, ~SR_COP_1_BIT
79	REG_L	t2, PCB_REGS+(SR * REGSZ)(a0)	# get CPU status register
80	REG_S	t0, PCB_FPREGS+(32 * REGSZ)(a0)	# save FP status
81	and	t2, t2, t3			# clear COP_1 enable bit
82	REG_S	t2, PCB_REGS+(SR * REGSZ)(a0)	# save new status register
83/*
84 * Save the floating point registers.
85 */
86	sdc1	$f0, PCB_FPREGS+(0 * REGSZ)(a0)
87	sdc1	$f1, PCB_FPREGS+(1 * REGSZ)(a0)
88	sdc1	$f2, PCB_FPREGS+(2 * REGSZ)(a0)
89	sdc1	$f3, PCB_FPREGS+(3 * REGSZ)(a0)
90	sdc1	$f4, PCB_FPREGS+(4 * REGSZ)(a0)
91	sdc1	$f5, PCB_FPREGS+(5 * REGSZ)(a0)
92	sdc1	$f6, PCB_FPREGS+(6 * REGSZ)(a0)
93	sdc1	$f7, PCB_FPREGS+(7 * REGSZ)(a0)
94	sdc1	$f8, PCB_FPREGS+(8 * REGSZ)(a0)
95	sdc1	$f9, PCB_FPREGS+(9 * REGSZ)(a0)
96	sdc1	$f10, PCB_FPREGS+(10 * REGSZ)(a0)
97	sdc1	$f11, PCB_FPREGS+(11 * REGSZ)(a0)
98	sdc1	$f12, PCB_FPREGS+(12 * REGSZ)(a0)
99	sdc1	$f13, PCB_FPREGS+(13 * REGSZ)(a0)
100	sdc1	$f14, PCB_FPREGS+(14 * REGSZ)(a0)
101	sdc1	$f15, PCB_FPREGS+(15 * REGSZ)(a0)
102	sdc1	$f16, PCB_FPREGS+(16 * REGSZ)(a0)
103	sdc1	$f17, PCB_FPREGS+(17 * REGSZ)(a0)
104	sdc1	$f18, PCB_FPREGS+(18 * REGSZ)(a0)
105	sdc1	$f19, PCB_FPREGS+(19 * REGSZ)(a0)
106	sdc1	$f20, PCB_FPREGS+(20 * REGSZ)(a0)
107	sdc1	$f21, PCB_FPREGS+(21 * REGSZ)(a0)
108	sdc1	$f22, PCB_FPREGS+(22 * REGSZ)(a0)
109	sdc1	$f23, PCB_FPREGS+(23 * REGSZ)(a0)
110	sdc1	$f24, PCB_FPREGS+(24 * REGSZ)(a0)
111	sdc1	$f25, PCB_FPREGS+(25 * REGSZ)(a0)
112	sdc1	$f26, PCB_FPREGS+(26 * REGSZ)(a0)
113	sdc1	$f27, PCB_FPREGS+(27 * REGSZ)(a0)
114	sdc1	$f28, PCB_FPREGS+(28 * REGSZ)(a0)
115	sdc1	$f29, PCB_FPREGS+(29 * REGSZ)(a0)
116	sdc1	$f30, PCB_FPREGS+(30 * REGSZ)(a0)
117	sdc1	$f31, PCB_FPREGS+(31 * REGSZ)(a0)
118
1191:
120/*
121 *  Restore the floating point registers.
122 */
123	REG_L	t0, PCB_FPREGS+(32 * REGSZ)(a1)	# get status register
124	ldc1	$f0, PCB_FPREGS+(0 * REGSZ)(a1)
125	ldc1	$f1, PCB_FPREGS+(1 * REGSZ)(a1)
126	ldc1	$f2, PCB_FPREGS+(2 * REGSZ)(a1)
127	ldc1	$f3, PCB_FPREGS+(3 * REGSZ)(a1)
128	ldc1	$f4, PCB_FPREGS+(4 * REGSZ)(a1)
129	ldc1	$f5, PCB_FPREGS+(5 * REGSZ)(a1)
130	ldc1	$f6, PCB_FPREGS+(6 * REGSZ)(a1)
131	ldc1	$f7, PCB_FPREGS+(7 * REGSZ)(a1)
132	ldc1	$f8, PCB_FPREGS+(8 * REGSZ)(a1)
133	ldc1	$f9, PCB_FPREGS+(9 * REGSZ)(a1)
134	ldc1	$f10, PCB_FPREGS+(10 * REGSZ)(a1)
135	ldc1	$f11, PCB_FPREGS+(11 * REGSZ)(a1)
136	ldc1	$f12, PCB_FPREGS+(12 * REGSZ)(a1)
137	ldc1	$f13, PCB_FPREGS+(13 * REGSZ)(a1)
138	ldc1	$f14, PCB_FPREGS+(14 * REGSZ)(a1)
139	ldc1	$f15, PCB_FPREGS+(15 * REGSZ)(a1)
140	ldc1	$f16, PCB_FPREGS+(16 * REGSZ)(a1)
141	ldc1	$f17, PCB_FPREGS+(17 * REGSZ)(a1)
142	ldc1	$f18, PCB_FPREGS+(18 * REGSZ)(a1)
143	ldc1	$f19, PCB_FPREGS+(19 * REGSZ)(a1)
144	ldc1	$f20, PCB_FPREGS+(20 * REGSZ)(a1)
145	ldc1	$f21, PCB_FPREGS+(21 * REGSZ)(a1)
146	ldc1	$f22, PCB_FPREGS+(22 * REGSZ)(a1)
147	ldc1	$f23, PCB_FPREGS+(23 * REGSZ)(a1)
148	ldc1	$f24, PCB_FPREGS+(24 * REGSZ)(a1)
149	ldc1	$f25, PCB_FPREGS+(25 * REGSZ)(a1)
150	ldc1	$f26, PCB_FPREGS+(26 * REGSZ)(a1)
151	ldc1	$f27, PCB_FPREGS+(27 * REGSZ)(a1)
152	ldc1	$f28, PCB_FPREGS+(28 * REGSZ)(a1)
153	ldc1	$f29, PCB_FPREGS+(29 * REGSZ)(a1)
154	ldc1	$f30, PCB_FPREGS+(30 * REGSZ)(a1)
155	ldc1	$f31, PCB_FPREGS+(31 * REGSZ)(a1)
156
157	ctc1	t0, FPC_CSR
158	NOP
159
160	MTC0	t1, COP_0_STATUS_REG	# Restore the status register.
161	MTC0_SR_CU_HAZARD
162	j	ra
163	 NOP
164END(MipsSwitchFPState)
165
166LEAF(MipsSwitchFPState16, 0)
167	MFC0	t1, COP_0_STATUS_REG	# Save old SR
168	MFC0_HAZARD
169	or	t0, t1, SR_COP_1_BIT	# enable the coprocessor
170	MTC0	t0, COP_0_STATUS_REG
171	MTC0_SR_CU_HAZARD
172
173	beq	a0, zero, 1f		# skip save if NULL pointer
174	 NOP
175/*
176 * First read out the status register to make sure that all FP operations
177 * have completed.
178 */
179	PTR_L	a0, P_ADDR(a0)		# get pointer to pcb for proc
180	cfc1	t0, FPC_CSR		# stall til FP done
181	cfc1	t0, FPC_CSR		# now get status
182	LI	t3, ~SR_COP_1_BIT
183	REG_L	t2, PCB_REGS+(SR * REGSZ)(a0)	# get CPU status register
184	REG_S	t0, PCB_FPREGS+(32 * REGSZ)(a0)	# save FP status
185	and	t2, t2, t3			# clear COP_1 enable bit
186	REG_S	t2, PCB_REGS+(SR * REGSZ)(a0)	# save new status register
187/*
188 * Save the floating point registers.
189 */
190	swc1	$f0, PCB_FPREGS+(0 * REGSZ)(a0)
191	swc1	$f1, PCB_FPREGS+(1 * REGSZ)(a0)
192	swc1	$f2, PCB_FPREGS+(2 * REGSZ)(a0)
193	swc1	$f3, PCB_FPREGS+(3 * REGSZ)(a0)
194	swc1	$f4, PCB_FPREGS+(4 * REGSZ)(a0)
195	swc1	$f5, PCB_FPREGS+(5 * REGSZ)(a0)
196	swc1	$f6, PCB_FPREGS+(6 * REGSZ)(a0)
197	swc1	$f7, PCB_FPREGS+(7 * REGSZ)(a0)
198	swc1	$f8, PCB_FPREGS+(8 * REGSZ)(a0)
199	swc1	$f9, PCB_FPREGS+(9 * REGSZ)(a0)
200	swc1	$f10, PCB_FPREGS+(10 * REGSZ)(a0)
201	swc1	$f11, PCB_FPREGS+(11 * REGSZ)(a0)
202	swc1	$f12, PCB_FPREGS+(12 * REGSZ)(a0)
203	swc1	$f13, PCB_FPREGS+(13 * REGSZ)(a0)
204	swc1	$f14, PCB_FPREGS+(14 * REGSZ)(a0)
205	swc1	$f15, PCB_FPREGS+(15 * REGSZ)(a0)
206	swc1	$f16, PCB_FPREGS+(16 * REGSZ)(a0)
207	swc1	$f17, PCB_FPREGS+(17 * REGSZ)(a0)
208	swc1	$f18, PCB_FPREGS+(18 * REGSZ)(a0)
209	swc1	$f19, PCB_FPREGS+(19 * REGSZ)(a0)
210	swc1	$f20, PCB_FPREGS+(20 * REGSZ)(a0)
211	swc1	$f21, PCB_FPREGS+(21 * REGSZ)(a0)
212	swc1	$f22, PCB_FPREGS+(22 * REGSZ)(a0)
213	swc1	$f23, PCB_FPREGS+(23 * REGSZ)(a0)
214	swc1	$f24, PCB_FPREGS+(24 * REGSZ)(a0)
215	swc1	$f25, PCB_FPREGS+(25 * REGSZ)(a0)
216	swc1	$f26, PCB_FPREGS+(26 * REGSZ)(a0)
217	swc1	$f27, PCB_FPREGS+(27 * REGSZ)(a0)
218	swc1	$f28, PCB_FPREGS+(28 * REGSZ)(a0)
219	swc1	$f29, PCB_FPREGS+(29 * REGSZ)(a0)
220	swc1	$f30, PCB_FPREGS+(30 * REGSZ)(a0)
221	swc1	$f31, PCB_FPREGS+(31 * REGSZ)(a0)
222
2231:
224/*
225 *  Restore the floating point registers.
226 */
227	REG_L	t0, PCB_FPREGS+(32 * REGSZ)(a1)	# get status register
228	lwc1	$f0, PCB_FPREGS+(0 * REGSZ)(a1)
229	lwc1	$f1, PCB_FPREGS+(1 * REGSZ)(a1)
230	lwc1	$f2, PCB_FPREGS+(2 * REGSZ)(a1)
231	lwc1	$f3, PCB_FPREGS+(3 * REGSZ)(a1)
232	lwc1	$f4, PCB_FPREGS+(4 * REGSZ)(a1)
233	lwc1	$f5, PCB_FPREGS+(5 * REGSZ)(a1)
234	lwc1	$f6, PCB_FPREGS+(6 * REGSZ)(a1)
235	lwc1	$f7, PCB_FPREGS+(7 * REGSZ)(a1)
236	lwc1	$f8, PCB_FPREGS+(8 * REGSZ)(a1)
237	lwc1	$f9, PCB_FPREGS+(9 * REGSZ)(a1)
238	lwc1	$f10, PCB_FPREGS+(10 * REGSZ)(a1)
239	lwc1	$f11, PCB_FPREGS+(11 * REGSZ)(a1)
240	lwc1	$f12, PCB_FPREGS+(12 * REGSZ)(a1)
241	lwc1	$f13, PCB_FPREGS+(13 * REGSZ)(a1)
242	lwc1	$f14, PCB_FPREGS+(14 * REGSZ)(a1)
243	lwc1	$f15, PCB_FPREGS+(15 * REGSZ)(a1)
244	lwc1	$f16, PCB_FPREGS+(16 * REGSZ)(a1)
245	lwc1	$f17, PCB_FPREGS+(17 * REGSZ)(a1)
246	lwc1	$f18, PCB_FPREGS+(18 * REGSZ)(a1)
247	lwc1	$f19, PCB_FPREGS+(19 * REGSZ)(a1)
248	lwc1	$f20, PCB_FPREGS+(20 * REGSZ)(a1)
249	lwc1	$f21, PCB_FPREGS+(21 * REGSZ)(a1)
250	lwc1	$f22, PCB_FPREGS+(22 * REGSZ)(a1)
251	lwc1	$f23, PCB_FPREGS+(23 * REGSZ)(a1)
252	lwc1	$f24, PCB_FPREGS+(24 * REGSZ)(a1)
253	lwc1	$f25, PCB_FPREGS+(25 * REGSZ)(a1)
254	lwc1	$f26, PCB_FPREGS+(26 * REGSZ)(a1)
255	lwc1	$f27, PCB_FPREGS+(27 * REGSZ)(a1)
256	lwc1	$f28, PCB_FPREGS+(28 * REGSZ)(a1)
257	lwc1	$f29, PCB_FPREGS+(29 * REGSZ)(a1)
258	lwc1	$f30, PCB_FPREGS+(30 * REGSZ)(a1)
259	lwc1	$f31, PCB_FPREGS+(31 * REGSZ)(a1)
260
261	ctc1	t0, FPC_CSR
262	NOP
263
264	MTC0	t1, COP_0_STATUS_REG	# Restore the status register.
265	MTC0_SR_CU_HAZARD
266	j	ra
267	 NOP
268END(MipsSwitchFPState16)
269
270/*----------------------------------------------------------------------------
271 *
272 * MipsSaveCurFPState --
273 *
274 *	Save the current floating point coprocessor state.
275 *
276 *	MipsSaveCurFPState(p)
277 *		struct proc *p;
278 *
279 * Results:
280 *	None.
281 *
282 * Side effects:
283 *	curcpu()->ci_fpuproc is cleared.
284 *
285 *----------------------------------------------------------------------------
286 */
287LEAF(MipsSaveCurFPState, 0)
288	PTR_L	a0, P_ADDR(a0)			# get pointer to pcb for proc
289	MFC0	t1, COP_0_STATUS_REG	# Disable interrupts and
290	MFC0_HAZARD
291	or	t0, t1, SR_COP_1_BIT|SR_FR_32	# enable the coprocessor
292	MTC0	t0, COP_0_STATUS_REG
293	MTC0_SR_IE_HAZARD
294	GET_CPU_INFO(t2, t3)
295	PTR_S	zero, CI_FPUPROC(t2)		# indicate state has been saved
296/*
297 * First read out the status register to make sure that all FP operations
298 * have completed.
299 */
300	REG_L	t2, PCB_REGS+(SR * REGSZ)(a0)	# get CPU status register
301	LI	t3, ~SR_COP_1_BIT
302	and	t2, t2, t3			# clear COP_1 enable bit
303	cfc1	t0, FPC_CSR		# stall til FP done
304	cfc1	t0, FPC_CSR		# now get status
305	REG_S	t2, PCB_REGS+(SR * REGSZ)(a0)	# save new status register
306	REG_S	t0, PCB_FPREGS+(32 * REGSZ)(a0)	# save FP status
307/*
308 * Save the floating point registers.
309 */
310	sdc1	$f0, PCB_FPREGS+(0 * REGSZ)(a0)
311	sdc1	$f1, PCB_FPREGS+(1 * REGSZ)(a0)
312	sdc1	$f2, PCB_FPREGS+(2 * REGSZ)(a0)
313	sdc1	$f3, PCB_FPREGS+(3 * REGSZ)(a0)
314	sdc1	$f4, PCB_FPREGS+(4 * REGSZ)(a0)
315	sdc1	$f5, PCB_FPREGS+(5 * REGSZ)(a0)
316	sdc1	$f6, PCB_FPREGS+(6 * REGSZ)(a0)
317	sdc1	$f7, PCB_FPREGS+(7 * REGSZ)(a0)
318	sdc1	$f8, PCB_FPREGS+(8 * REGSZ)(a0)
319	sdc1	$f9, PCB_FPREGS+(9 * REGSZ)(a0)
320	sdc1	$f10, PCB_FPREGS+(10 * REGSZ)(a0)
321	sdc1	$f11, PCB_FPREGS+(11 * REGSZ)(a0)
322	sdc1	$f12, PCB_FPREGS+(12 * REGSZ)(a0)
323	sdc1	$f13, PCB_FPREGS+(13 * REGSZ)(a0)
324	sdc1	$f14, PCB_FPREGS+(14 * REGSZ)(a0)
325	sdc1	$f15, PCB_FPREGS+(15 * REGSZ)(a0)
326	sdc1	$f16, PCB_FPREGS+(16 * REGSZ)(a0)
327	sdc1	$f17, PCB_FPREGS+(17 * REGSZ)(a0)
328	sdc1	$f18, PCB_FPREGS+(18 * REGSZ)(a0)
329	sdc1	$f19, PCB_FPREGS+(19 * REGSZ)(a0)
330	sdc1	$f20, PCB_FPREGS+(20 * REGSZ)(a0)
331	sdc1	$f21, PCB_FPREGS+(21 * REGSZ)(a0)
332	sdc1	$f22, PCB_FPREGS+(22 * REGSZ)(a0)
333	sdc1	$f23, PCB_FPREGS+(23 * REGSZ)(a0)
334	sdc1	$f24, PCB_FPREGS+(24 * REGSZ)(a0)
335	sdc1	$f25, PCB_FPREGS+(25 * REGSZ)(a0)
336	sdc1	$f26, PCB_FPREGS+(26 * REGSZ)(a0)
337	sdc1	$f27, PCB_FPREGS+(27 * REGSZ)(a0)
338	sdc1	$f28, PCB_FPREGS+(28 * REGSZ)(a0)
339	sdc1	$f29, PCB_FPREGS+(29 * REGSZ)(a0)
340	sdc1	$f30, PCB_FPREGS+(30 * REGSZ)(a0)
341	sdc1	$f31, PCB_FPREGS+(31 * REGSZ)(a0)
342
343	MTC0	t1, COP_0_STATUS_REG	# Restore the status register.
344	MTC0_SR_IE_HAZARD
345	j	ra
346	 NOP
347END(MipsSaveCurFPState)
348
349LEAF(MipsSaveCurFPState16, 0)
350	PTR_L	a0, P_ADDR(a0)			# get pointer to pcb for proc
351	MFC0	t1, COP_0_STATUS_REG	# Disable interrupts and
352	MFC0_HAZARD
353	or	t0, t1, SR_COP_1_BIT	# enable the coprocessor
354	MTC0	t0, COP_0_STATUS_REG
355	MTC0_SR_IE_HAZARD
356	GET_CPU_INFO(t2, t3)
357	PTR_S	zero, CI_FPUPROC(t2)		# indicate state has been saved
358/*
359 * First read out the status register to make sure that all FP operations
360 * have completed.
361 */
362	REG_L	t2, PCB_REGS+(SR * REGSZ)(a0)	# get CPU status register
363	LI	t3, ~SR_COP_1_BIT
364	and	t2, t2, t3			# clear COP_1 enable bit
365	cfc1	t0, FPC_CSR		# stall til FP done
366	cfc1	t0, FPC_CSR		# now get status
367	REG_S	t2, PCB_REGS+(SR * REGSZ)(a0)	# save new status register
368	REG_S	t0, PCB_FPREGS+(32 * REGSZ)(a0)	# save FP status
369/*
370 * Save the floating point registers.
371 */
372	swc1	$f0, PCB_FPREGS+(0 * REGSZ)(a0)
373	swc1	$f1, PCB_FPREGS+(1 * REGSZ)(a0)
374	swc1	$f2, PCB_FPREGS+(2 * REGSZ)(a0)
375	swc1	$f3, PCB_FPREGS+(3 * REGSZ)(a0)
376	swc1	$f4, PCB_FPREGS+(4 * REGSZ)(a0)
377	swc1	$f5, PCB_FPREGS+(5 * REGSZ)(a0)
378	swc1	$f6, PCB_FPREGS+(6 * REGSZ)(a0)
379	swc1	$f7, PCB_FPREGS+(7 * REGSZ)(a0)
380	swc1	$f8, PCB_FPREGS+(8 * REGSZ)(a0)
381	swc1	$f9, PCB_FPREGS+(9 * REGSZ)(a0)
382	swc1	$f10, PCB_FPREGS+(10 * REGSZ)(a0)
383	swc1	$f11, PCB_FPREGS+(11 * REGSZ)(a0)
384	swc1	$f12, PCB_FPREGS+(12 * REGSZ)(a0)
385	swc1	$f13, PCB_FPREGS+(13 * REGSZ)(a0)
386	swc1	$f14, PCB_FPREGS+(14 * REGSZ)(a0)
387	swc1	$f15, PCB_FPREGS+(15 * REGSZ)(a0)
388	swc1	$f16, PCB_FPREGS+(16 * REGSZ)(a0)
389	swc1	$f17, PCB_FPREGS+(17 * REGSZ)(a0)
390	swc1	$f18, PCB_FPREGS+(18 * REGSZ)(a0)
391	swc1	$f19, PCB_FPREGS+(19 * REGSZ)(a0)
392	swc1	$f20, PCB_FPREGS+(20 * REGSZ)(a0)
393	swc1	$f21, PCB_FPREGS+(21 * REGSZ)(a0)
394	swc1	$f22, PCB_FPREGS+(22 * REGSZ)(a0)
395	swc1	$f23, PCB_FPREGS+(23 * REGSZ)(a0)
396	swc1	$f24, PCB_FPREGS+(24 * REGSZ)(a0)
397	swc1	$f25, PCB_FPREGS+(25 * REGSZ)(a0)
398	swc1	$f26, PCB_FPREGS+(26 * REGSZ)(a0)
399	swc1	$f27, PCB_FPREGS+(27 * REGSZ)(a0)
400	swc1	$f28, PCB_FPREGS+(28 * REGSZ)(a0)
401	swc1	$f29, PCB_FPREGS+(29 * REGSZ)(a0)
402	swc1	$f30, PCB_FPREGS+(30 * REGSZ)(a0)
403	swc1	$f31, PCB_FPREGS+(31 * REGSZ)(a0)
404
405	MTC0	t1, COP_0_STATUS_REG	# Restore the status register.
406	MTC0_SR_IE_HAZARD
407	j	ra
408	 NOP
409END(MipsSaveCurFPState16)
410
411/*----------------------------------------------------------------------------
412 *
413 * cp1_get_prid
414 *
415 *	Get the floating point co-processor id.
416 *
417 *	cp1_get_prid(void)
418 *
419 * Results:
420 *	FPC_ID
421 *
422 * Side effects:
423 *	None.
424 *
425 *----------------------------------------------------------------------------
426 */
427LEAF(cp1_get_prid, 0)
428	MFC0	v1, COP_0_STATUS_REG
429	MFC0_HAZARD
430	li	a0, SR_COP_1_BIT
431	or	v1, a0
432	MTC0	v1, COP_0_STATUS_REG
433	MTC0_SR_CU_HAZARD
434	cfc1	v0, FPC_ID
435	xor	v1, a0
436	MTC0	v1, COP_0_STATUS_REG
437	MTC0_SR_CU_HAZARD
438	jr	ra
439	 NOP
440END(cp1_get_prid)
441