]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/mips/mips/swtch.S
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / sys / mips / mips / swtch.S
1 /*      $OpenBSD: locore.S,v 1.18 1998/09/15 10:58:53 pefo Exp $        */
2 /*-
3  * Copyright (c) 1992, 1993
4  *      The Regents of the University of California.  All rights reserved.
5  *
6  * This code is derived from software contributed to Berkeley by
7  * Digital Equipment Corporation and Ralph Campbell.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  *
33  * Copyright (C) 1989 Digital Equipment Corporation.
34  * Permission to use, copy, modify, and distribute this software and
35  * its documentation for any purpose and without fee is hereby granted,
36  * provided that the above copyright notice appears in all copies.
37  * Digital Equipment Corporation makes no representations about the
38  * suitability of this software for any purpose.  It is provided "as is"
39  * without express or implied warranty.
40  *
41  * from: Header: /sprite/src/kernel/mach/ds3100.md/RCS/loMem.s,
42  *      v 1.1 89/07/11 17:55:04 nelson Exp  SPRITE (DECWRL)
43  * from: Header: /sprite/src/kernel/mach/ds3100.md/RCS/machAsm.s,
44  *      v 9.2 90/01/29 18:00:39 shirriff Exp  SPRITE (DECWRL)
45  * from: Header: /sprite/src/kernel/vm/ds3100.md/vmPmaxAsm.s,
46  *      v 1.1 89/07/10 14:27:41 nelson Exp  SPRITE (DECWRL)
47  *
48  *      from: @(#)locore.s      8.5 (Berkeley) 1/4/94
49  *      JNPR: swtch.S,v 1.6.2.1 2007/09/10 10:36:50 girish
50  * $FreeBSD$
51  */
52
53 /*
54  *      Contains code that is the first executed at boot time plus
55  *      assembly language support routines.
56  */
57
58 #include <sys/syscall.h>
59 #include <machine/asm.h>
60 #include <machine/cpu.h>
61 #include <machine/cpuregs.h>
62 #include <machine/regnum.h>
63 #include <machine/pte.h>
64 #include <machine/pcb.h>
65
66 #include "assym.inc"
67
68         .set    noreorder                       # Noreorder is default style!
69
70 /*
71  * Setup for and return to user.
72  */
73 LEAF(fork_trampoline)
74         move    a0,s0
75         move    a1,s1
76         jal     _C_LABEL(fork_exit)
77         move    a2,s2                     #BDSlot
78
79         DO_AST
80
81         mfc0    v0, MIPS_COP_0_STATUS
82         and     v0, ~(MIPS_SR_INT_IE)
83         mtc0    v0, MIPS_COP_0_STATUS   # disable interrupts
84         COP0_SYNC
85 /*
86  * The use of k1 for storing the PCB pointer must be done only
87  * after interrupts are disabled.  Otherwise it will get overwritten
88  * by the interrupt code.
89  */
90         .set    noat
91         GET_CPU_PCPU(k1)
92         PTR_L   k1, PC_CURPCB(k1)
93
94         RESTORE_U_PCB_REG(t0, MULLO, k1)
95         RESTORE_U_PCB_REG(t1, MULHI, k1)
96         mtlo    t0
97         mthi    t1
98         RESTORE_U_PCB_REG(a0, PC, k1)
99         RESTORE_U_PCB_REG(AT, AST, k1)
100         RESTORE_U_PCB_REG(v0, V0, k1)
101         MTC0    a0, MIPS_COP_0_EXC_PC   # set return address
102
103         RESTORE_U_PCB_REG(v1, V1, k1)
104         RESTORE_U_PCB_REG(a0, A0, k1)
105         RESTORE_U_PCB_REG(a1, A1, k1)
106         RESTORE_U_PCB_REG(a2, A2, k1)
107         RESTORE_U_PCB_REG(a3, A3, k1)
108         RESTORE_U_PCB_REG(t0, T0, k1)
109         RESTORE_U_PCB_REG(t1, T1, k1)
110         RESTORE_U_PCB_REG(t2, T2, k1)
111         RESTORE_U_PCB_REG(t3, T3, k1)
112         RESTORE_U_PCB_REG(ta0, TA0, k1)
113         RESTORE_U_PCB_REG(ta1, TA1, k1)
114         RESTORE_U_PCB_REG(ta2, TA2, k1)
115         RESTORE_U_PCB_REG(ta3, TA3, k1)
116         RESTORE_U_PCB_REG(s0, S0, k1)
117         RESTORE_U_PCB_REG(s1, S1, k1)
118         RESTORE_U_PCB_REG(s2, S2, k1)
119         RESTORE_U_PCB_REG(s3, S3, k1)
120         RESTORE_U_PCB_REG(s4, S4, k1)
121         RESTORE_U_PCB_REG(s5, S5, k1)
122         RESTORE_U_PCB_REG(s6, S6, k1)
123         RESTORE_U_PCB_REG(s7, S7, k1)
124         RESTORE_U_PCB_REG(t8, T8, k1)
125         RESTORE_U_PCB_REG(t9, T9, k1)
126         RESTORE_U_PCB_REG(k0, SR, k1)
127         RESTORE_U_PCB_REG(gp, GP, k1)
128         RESTORE_U_PCB_REG(s8, S8, k1)
129         RESTORE_U_PCB_REG(ra, RA, k1)
130         RESTORE_U_PCB_REG(sp, SP, k1)
131         li      k1, ~MIPS_SR_INT_MASK
132         and     k0, k0, k1
133         mfc0    k1, MIPS_COP_0_STATUS
134         and     k1, k1, MIPS_SR_INT_MASK
135         or      k0, k0, k1
136         mtc0    k0, MIPS_COP_0_STATUS   # switch to user mode (when eret...)
137         HAZARD_DELAY
138         sync
139         eret
140         .set    at
141 END(fork_trampoline)
142
143 /*
144  * Update pcb, saving current processor state.
145  * Note: this only works if pcbp != curproc's pcb since
146  * cpu_switch() will copy over pcb_context.
147  *
148  *      savectx(struct pcb *pcbp);
149  */
150 LEAF(savectx)
151         SAVE_U_PCB_CONTEXT(s0, PCB_REG_S0, a0)
152         SAVE_U_PCB_CONTEXT(s1, PCB_REG_S1, a0)
153         SAVE_U_PCB_CONTEXT(s2, PCB_REG_S2, a0)
154         SAVE_U_PCB_CONTEXT(s3, PCB_REG_S3, a0)
155         mfc0    v0, MIPS_COP_0_STATUS
156         SAVE_U_PCB_CONTEXT(s4, PCB_REG_S4, a0)
157         SAVE_U_PCB_CONTEXT(s5, PCB_REG_S5, a0)
158         SAVE_U_PCB_CONTEXT(s6, PCB_REG_S6, a0)
159         SAVE_U_PCB_CONTEXT(s7, PCB_REG_S7, a0)
160         SAVE_U_PCB_CONTEXT(sp, PCB_REG_SP, a0)
161         SAVE_U_PCB_CONTEXT(s8, PCB_REG_S8, a0)
162         SAVE_U_PCB_CONTEXT(ra, PCB_REG_RA, a0)
163         SAVE_U_PCB_CONTEXT(v0, PCB_REG_SR, a0)
164         SAVE_U_PCB_CONTEXT(gp, PCB_REG_GP, a0)
165
166         move    v0, ra                  /* save 'ra' before we trash it */
167         jal     1f
168         nop
169 1:
170         SAVE_U_PCB_CONTEXT(ra, PCB_REG_PC, a0)
171         move    ra, v0                  /* restore 'ra' before returning */
172
173         j       ra
174         move    v0, zero
175 END(savectx)
176
177 NESTED(cpu_throw, CALLFRAME_SIZ, ra)
178         mfc0    t0, MIPS_COP_0_STATUS           # t0 = saved status register
179         nop
180         nop
181         and     a3, t0, ~(MIPS_SR_INT_IE)
182         mtc0    a3, MIPS_COP_0_STATUS           # Disable all interrupts
183         ITLBNOPFIX
184         j       mips_sw1                        # We're not interested in old 
185                                                 # thread's context, so jump 
186                                                 # right to action
187         nop                                     # BDSLOT
188 END(cpu_throw)
189
190 /*
191  * cpu_switch(struct thread *old, struct thread *new, struct mutex *mtx);
192  *      a0 - old
193  *      a1 - new
194  *      a2 - mtx
195  * Find the highest priority process and resume it.
196  */
197 NESTED(cpu_switch, CALLFRAME_SIZ, ra)
198         mfc0    t0, MIPS_COP_0_STATUS           # t0 = saved status register
199         nop
200         nop
201         and     a3, t0, ~(MIPS_SR_INT_IE)       
202         mtc0    a3, MIPS_COP_0_STATUS           # Disable all interrupts
203         ITLBNOPFIX
204         beqz    a0, mips_sw1
205         move    a3, a0
206         PTR_L   a0, TD_PCB(a0)          # load PCB addr of curproc
207         SAVE_U_PCB_CONTEXT(sp, PCB_REG_SP, a0)          # save old sp
208         PTR_SUBU        sp, sp, CALLFRAME_SIZ
209         REG_S   ra, CALLFRAME_RA(sp)
210         .mask   0x80000000, (CALLFRAME_RA - CALLFRAME_SIZ)
211         SAVE_U_PCB_CONTEXT(s0, PCB_REG_S0, a0)          # do a 'savectx()'
212         SAVE_U_PCB_CONTEXT(s1, PCB_REG_S1, a0)
213         SAVE_U_PCB_CONTEXT(s2, PCB_REG_S2, a0)
214         SAVE_U_PCB_CONTEXT(s3, PCB_REG_S3, a0)
215         SAVE_U_PCB_CONTEXT(s4, PCB_REG_S4, a0)
216         SAVE_U_PCB_CONTEXT(s5, PCB_REG_S5, a0)
217         SAVE_U_PCB_CONTEXT(s6, PCB_REG_S6, a0)
218         SAVE_U_PCB_CONTEXT(s7, PCB_REG_S7, a0)
219         SAVE_U_PCB_CONTEXT(s8, PCB_REG_S8, a0)
220         SAVE_U_PCB_CONTEXT(ra, PCB_REG_RA, a0)          # save return address
221         SAVE_U_PCB_CONTEXT(t0, PCB_REG_SR, a0)          # save status register
222         SAVE_U_PCB_CONTEXT(gp, PCB_REG_GP, a0)
223         jal     getpc
224         nop
225 getpc:
226         SAVE_U_PCB_CONTEXT(ra, PCB_REG_PC, a0)          # save return address
227
228 #ifdef CPU_CNMIPS
229
230         lw      t2, TD_MDFLAGS(a3)              # get md_flags
231         and     t1, t2, MDTD_COP2USED
232         beqz    t1, cop2_untouched
233         nop
234
235         /* Clear cop2used flag */
236         and     t2, t2, ~MDTD_COP2USED
237         sw      t2, TD_MDFLAGS(a3)
238
239         and     t2, t0, ~MIPS_SR_COP_2_BIT      # clear COP_2 enable bit
240         SAVE_U_PCB_CONTEXT(t2, PCB_REG_SR, a0)  # save status register
241
242         RESTORE_U_PCB_REG(t0, PS, a0)           # get CPU status register
243         and     t2, t0, ~MIPS_SR_COP_2_BIT      # clear COP_2 enable bit
244         SAVE_U_PCB_REG(t2, PS, a0)              # save stratus register
245
246         /* preserve a0..a3 */
247         move    s0, a0
248         move    s1, a1
249         move    s2, a2
250         move    s3, a3
251
252         /* does kernel own COP2 context? */
253         lw      t1, TD_COP2OWNER(a3)            # get md_cop2owner
254         beqz    t1, userland_cop2               # 0 - it's userland context
255         nop
256
257         PTR_L   a0, TD_COP2(a3)
258         beqz    a0, no_cop2_context
259         nop
260
261         j       do_cop2_save
262         nop
263
264 userland_cop2:
265
266         PTR_L   a0, TD_UCOP2(a3)
267         beqz    a0, no_cop2_context
268         nop
269
270 do_cop2_save:
271         jal     octeon_cop2_save
272         nop
273
274 no_cop2_context:
275         move    a3, s3
276         move    a2, s2
277         move    a1, s1
278         move    a0, s0
279
280 cop2_untouched:
281 #endif
282
283         PTR_S   a2, TD_LOCK(a3)                 # Switchout td_lock 
284
285 mips_sw1:
286 #if defined(SMP) && defined(SCHED_ULE)
287         PTR_LA  t0, _C_LABEL(blocked_lock)
288 blocked_loop:
289         PTR_L   t1, TD_LOCK(a1)
290         beq     t0, t1, blocked_loop
291         nop
292 #endif
293         move    s7, a1  # Store newthread
294 /*
295  * Switch to new context.
296  */
297         GET_CPU_PCPU(a3)
298         PTR_S   a1, PC_CURTHREAD(a3)
299         PTR_L   a2, TD_PCB(a1)
300         PTR_S   a2, PC_CURPCB(a3)
301         PTR_L   v0, TD_KSTACK(a1)
302 #if defined(__mips_n64)
303         PTR_LI  s0, MIPS_XKSEG_START
304 #else
305         PTR_LI  s0, MIPS_KSEG2_START            # If Uarea addr is below kseg2,
306 #endif
307         bltu    v0, s0, sw2                     # no need to insert in TLB.
308         PTE_L   a1, TD_UPTE + 0(s7)             # a1 = u. pte #0
309         PTE_L   a2, TD_UPTE + PTESIZE(s7)       # a2 = u. pte #1
310 /*
311  * Wiredown the USPACE of newproc in TLB entry#0.  Check whether target
312  * USPACE is already in another place of TLB before that, and if so
313  * invalidate that TLB entry.
314  * NOTE: This is hard coded to UPAGES == 2.
315  * Also, there should be no TLB faults at this point.
316  */
317         MTC0    v0, MIPS_COP_0_TLB_HI           # VPN = va
318         HAZARD_DELAY
319         tlbp                                    # probe VPN
320         HAZARD_DELAY
321         mfc0    s0, MIPS_COP_0_TLB_INDEX
322         HAZARD_DELAY
323
324         PTR_LI  t1, MIPS_KSEG0_START            # invalidate tlb entry
325         bltz    s0, entry0set
326         nop
327         sll     s0, PAGE_SHIFT + 1
328         addu    t1, s0
329         MTC0    t1, MIPS_COP_0_TLB_HI
330         PTE_MTC0        zero, MIPS_COP_0_TLB_LO0
331         PTE_MTC0        zero, MIPS_COP_0_TLB_LO1
332         HAZARD_DELAY
333         tlbwi
334         HAZARD_DELAY
335         MTC0    v0, MIPS_COP_0_TLB_HI           # set VPN again
336
337 entry0set:
338 /* SMP!! - Works only for  unshared TLB case - i.e. no v-cpus */
339         mtc0    zero, MIPS_COP_0_TLB_INDEX              # TLB entry #0
340         HAZARD_DELAY
341         PTE_MTC0        a1, MIPS_COP_0_TLB_LO0          # upte[0]
342         HAZARD_DELAY
343         PTE_MTC0        a2, MIPS_COP_0_TLB_LO1          # upte[1]
344         HAZARD_DELAY
345         tlbwi                                   # set TLB entry #0
346         HAZARD_DELAY
347 /*
348  * Now running on new u struct.
349  */
350 sw2:
351         PTR_L   s0, TD_PCB(s7)
352         RESTORE_U_PCB_CONTEXT(sp, PCB_REG_SP, s0)
353         PTR_LA  t1, _C_LABEL(pmap_activate)     # s7 = new proc pointer
354         jalr    t1                              # s7 = new proc pointer
355         move    a0, s7                          # BDSLOT
356 /*
357  * Restore registers and return.
358  */
359         move    a0, s0
360         move    a1, s7
361         RESTORE_U_PCB_CONTEXT(gp, PCB_REG_GP, a0)
362         RESTORE_U_PCB_CONTEXT(v0, PCB_REG_SR, a0)       # restore kernel context
363         RESTORE_U_PCB_CONTEXT(ra, PCB_REG_RA, a0)
364         RESTORE_U_PCB_CONTEXT(s0, PCB_REG_S0, a0)
365         RESTORE_U_PCB_CONTEXT(s1, PCB_REG_S1, a0)
366         RESTORE_U_PCB_CONTEXT(s2, PCB_REG_S2, a0)
367         RESTORE_U_PCB_CONTEXT(s3, PCB_REG_S3, a0)
368         RESTORE_U_PCB_CONTEXT(s4, PCB_REG_S4, a0)
369         RESTORE_U_PCB_CONTEXT(s5, PCB_REG_S5, a0)
370         RESTORE_U_PCB_CONTEXT(s6, PCB_REG_S6, a0)
371         RESTORE_U_PCB_CONTEXT(s7, PCB_REG_S7, a0)
372         RESTORE_U_PCB_CONTEXT(s8, PCB_REG_S8, a0)
373
374         mfc0    t0, MIPS_COP_0_STATUS
375         and     t0, t0, MIPS_SR_INT_MASK
376         and     v0, v0, ~MIPS_SR_INT_MASK
377         or      v0, v0, t0
378         mtc0    v0, MIPS_COP_0_STATUS
379         ITLBNOPFIX
380 /*
381  * Set the new thread's TLS pointer.
382  *
383  * Note that this code is removed if the CPU doesn't support ULRI by
384  * remove_userlocal_code() in cpu.c.
385  */
386         .globl  cpu_switch_set_userlocal
387 cpu_switch_set_userlocal:
388         PTR_L   t0, TD_MDTLS(a1)                # Get TLS pointer
389         PTR_L   t1, TD_PROC(a1)
390         PTR_L   t1, P_MDTLS_TCB_OFFSET(t1)      # Get TLS/TCB offset
391         PTR_ADDU v0, t0, t1
392         MTC0    v0, MIPS_COP_0_USERLOCAL, 2     # write it to ULR for rdhwr
393
394         j       ra
395         nop
396 END(cpu_switch)
397
398 /*----------------------------------------------------------------------------
399  *
400  * MipsSwitchFPState --
401  *
402  *      Save the current state into 'from' and restore it from 'to'.
403  *
404  *      MipsSwitchFPState(from, to)
405  *              struct thread *from;
406  *              struct trapframe *to;
407  *
408  * Results:
409  *      None.
410  *
411  * Side effects:
412  *      None.
413  *
414  *----------------------------------------------------------------------------
415  */
416 LEAF(MipsSwitchFPState)
417         .set push
418         .set hardfloat
419         mfc0    t1, MIPS_COP_0_STATUS   # Save old SR
420         HAZARD_DELAY
421 #if defined(__mips_n32) || defined(__mips_n64)
422         or      t0, t1, MIPS_SR_COP_1_BIT | MIPS_SR_FR  # enable the coprocessor
423 #else
424         or      t0, t1, MIPS_SR_COP_1_BIT               # enable the coprocessor
425 #endif
426         mtc0    t0, MIPS_COP_0_STATUS
427         HAZARD_DELAY
428         ITLBNOPFIX
429
430         beq     a0, zero, 1f            # skip save if NULL pointer
431         nop
432 /*
433  * First read out the status register to make sure that all FP operations
434  * have completed.
435  */
436         PTR_L   a0, TD_PCB(a0)                  # get pointer to pcb for proc
437         cfc1    t0, MIPS_FPU_CSR                # stall til FP done
438         cfc1    t0, MIPS_FPU_CSR                # now get status
439         li      t3, ~MIPS_SR_COP_1_BIT
440         RESTORE_U_PCB_REG(t2, PS, a0)           # get CPU status register
441         SAVE_U_PCB_FPSR(t0, FSR_NUM, a0)        # save FP status
442         and     t2, t2, t3                      # clear COP_1 enable bit
443         SAVE_U_PCB_REG(t2, PS, a0)              # save new status register
444 /*
445  * Save the floating point registers.
446  */
447         SAVE_U_PCB_FPREG($f0, F0_NUM, a0)
448         SAVE_U_PCB_FPREG($f1, F1_NUM, a0)
449         SAVE_U_PCB_FPREG($f2, F2_NUM, a0)
450         SAVE_U_PCB_FPREG($f3, F3_NUM, a0)
451         SAVE_U_PCB_FPREG($f4, F4_NUM, a0)
452         SAVE_U_PCB_FPREG($f5, F5_NUM, a0)
453         SAVE_U_PCB_FPREG($f6, F6_NUM, a0)
454         SAVE_U_PCB_FPREG($f7, F7_NUM, a0)
455         SAVE_U_PCB_FPREG($f8, F8_NUM, a0)
456         SAVE_U_PCB_FPREG($f9, F9_NUM, a0)
457         SAVE_U_PCB_FPREG($f10, F10_NUM, a0)
458         SAVE_U_PCB_FPREG($f11, F11_NUM, a0)
459         SAVE_U_PCB_FPREG($f12, F12_NUM, a0)
460         SAVE_U_PCB_FPREG($f13, F13_NUM, a0)
461         SAVE_U_PCB_FPREG($f14, F14_NUM, a0)
462         SAVE_U_PCB_FPREG($f15, F15_NUM, a0)
463         SAVE_U_PCB_FPREG($f16, F16_NUM, a0)
464         SAVE_U_PCB_FPREG($f17, F17_NUM, a0)
465         SAVE_U_PCB_FPREG($f18, F18_NUM, a0)
466         SAVE_U_PCB_FPREG($f19, F19_NUM, a0)
467         SAVE_U_PCB_FPREG($f20, F20_NUM, a0)
468         SAVE_U_PCB_FPREG($f21, F21_NUM, a0)
469         SAVE_U_PCB_FPREG($f22, F22_NUM, a0)
470         SAVE_U_PCB_FPREG($f23, F23_NUM, a0)
471         SAVE_U_PCB_FPREG($f24, F24_NUM, a0)
472         SAVE_U_PCB_FPREG($f25, F25_NUM, a0)
473         SAVE_U_PCB_FPREG($f26, F26_NUM, a0)
474         SAVE_U_PCB_FPREG($f27, F27_NUM, a0)
475         SAVE_U_PCB_FPREG($f28, F28_NUM, a0)
476         SAVE_U_PCB_FPREG($f29, F29_NUM, a0)
477         SAVE_U_PCB_FPREG($f30, F30_NUM, a0)
478         SAVE_U_PCB_FPREG($f31, F31_NUM, a0)
479
480 1:
481 /*
482  *  Restore the floating point registers.
483  */
484         RESTORE_U_PCB_FPSR(t0, FSR_NUM, a1)     # get status register
485         RESTORE_U_PCB_FPREG($f0, F0_NUM, a1)
486         RESTORE_U_PCB_FPREG($f1, F1_NUM, a1)
487         RESTORE_U_PCB_FPREG($f2, F2_NUM, a1)
488         RESTORE_U_PCB_FPREG($f3, F3_NUM, a1)
489         RESTORE_U_PCB_FPREG($f4, F4_NUM, a1)
490         RESTORE_U_PCB_FPREG($f5, F5_NUM, a1)
491         RESTORE_U_PCB_FPREG($f6, F6_NUM, a1)
492         RESTORE_U_PCB_FPREG($f7, F7_NUM, a1)
493         RESTORE_U_PCB_FPREG($f8, F8_NUM, a1)
494         RESTORE_U_PCB_FPREG($f9, F9_NUM, a1)
495         RESTORE_U_PCB_FPREG($f10, F10_NUM, a1)
496         RESTORE_U_PCB_FPREG($f11, F11_NUM, a1)
497         RESTORE_U_PCB_FPREG($f12, F12_NUM, a1)
498         RESTORE_U_PCB_FPREG($f13, F13_NUM, a1)
499         RESTORE_U_PCB_FPREG($f14, F14_NUM, a1)
500         RESTORE_U_PCB_FPREG($f15, F15_NUM, a1)
501         RESTORE_U_PCB_FPREG($f16, F16_NUM, a1)
502         RESTORE_U_PCB_FPREG($f17, F17_NUM, a1)
503         RESTORE_U_PCB_FPREG($f18, F18_NUM, a1)
504         RESTORE_U_PCB_FPREG($f19, F19_NUM, a1)
505         RESTORE_U_PCB_FPREG($f20, F20_NUM, a1)
506         RESTORE_U_PCB_FPREG($f21, F21_NUM, a1)
507         RESTORE_U_PCB_FPREG($f22, F22_NUM, a1)
508         RESTORE_U_PCB_FPREG($f23, F23_NUM, a1)
509         RESTORE_U_PCB_FPREG($f24, F24_NUM, a1)
510         RESTORE_U_PCB_FPREG($f25, F25_NUM, a1)
511         RESTORE_U_PCB_FPREG($f26, F26_NUM, a1)
512         RESTORE_U_PCB_FPREG($f27, F27_NUM, a1)
513         RESTORE_U_PCB_FPREG($f28, F28_NUM, a1)
514         RESTORE_U_PCB_FPREG($f29, F29_NUM, a1)
515         RESTORE_U_PCB_FPREG($f30, F30_NUM, a1)
516         RESTORE_U_PCB_FPREG($f31, F31_NUM, a1)
517
518         and     t0, t0, ~MIPS_FPU_EXCEPTION_BITS
519         ctc1    t0, MIPS_FPU_CSR
520         nop
521
522         mtc0    t1, MIPS_COP_0_STATUS           # Restore the status register.
523         ITLBNOPFIX
524         j       ra
525         nop
526         .set pop
527 END(MipsSwitchFPState)
528
529 /*----------------------------------------------------------------------------
530  *
531  * MipsFPID --
532  *
533  *      Read and return the floating point implementation register.
534  *
535  *      uint32_t
536  *      MipsFPID(void)
537  *
538  * Results:
539  *      Floating point implementation register.
540  *
541  * Side effects:
542  *      None.
543  *
544  *----------------------------------------------------------------------------
545  */
546 LEAF(MipsFPID)
547         .set push
548         .set hardfloat
549         mfc0    t1, MIPS_COP_0_STATUS           # Save the status register.
550         HAZARD_DELAY
551 #if defined(__mips_n32) || defined(__mips_n64)
552         or      t0, t1, MIPS_SR_COP_1_BIT | MIPS_SR_FR
553 #else
554         or      t0, t1, MIPS_SR_COP_1_BIT
555 #endif
556         mtc0    t0, MIPS_COP_0_STATUS           # Enable the coprocessor
557         HAZARD_DELAY
558         ITLBNOPFIX
559         cfc1    v0, MIPS_FPU_ID
560         mtc0    t1, MIPS_COP_0_STATUS           # Restore the status register.
561         ITLBNOPFIX
562         j       ra
563         nop
564         .set pop
565 END(MipsFPID)
566
567 /*----------------------------------------------------------------------------
568  *
569  * MipsSaveCurFPState --
570  *
571  *      Save the current floating point coprocessor state.
572  *
573  *      MipsSaveCurFPState(td)
574  *              struct thread *td;
575  *
576  * Results:
577  *      None.
578  *
579  * Side effects:
580  *      machFPCurProcPtr is cleared.
581  *
582  *----------------------------------------------------------------------------
583  */
584 LEAF(MipsSaveCurFPState)
585         .set push
586         .set hardfloat
587         PTR_L   a0, TD_PCB(a0)                  # get pointer to pcb for thread
588         mfc0    t1, MIPS_COP_0_STATUS           # Disable interrupts and
589         HAZARD_DELAY
590 #if defined(__mips_n32) || defined(__mips_n64)
591         or      t0, t1, MIPS_SR_COP_1_BIT | MIPS_SR_FR          #  enable the coprocessor
592 #else
593         or      t0, t1, MIPS_SR_COP_1_BIT                       #  enable the coprocessor
594 #endif
595         mtc0    t0, MIPS_COP_0_STATUS
596         HAZARD_DELAY
597         ITLBNOPFIX
598         GET_CPU_PCPU(a1)
599         PTR_S   zero, PC_FPCURTHREAD(a1)        # indicate state has been saved
600 /*
601  * First read out the status register to make sure that all FP operations
602  * have completed.
603  */
604         RESTORE_U_PCB_REG(t2, PS, a0)           # get CPU status register
605         li      t3, ~MIPS_SR_COP_1_BIT
606         and     t2, t2, t3                      # clear COP_1 enable bit
607         cfc1    t0, MIPS_FPU_CSR                # stall til FP done
608         cfc1    t0, MIPS_FPU_CSR                # now get status
609         SAVE_U_PCB_REG(t2, PS, a0)              # save new status register
610         SAVE_U_PCB_FPSR(t0, FSR_NUM, a0)        # save FP status
611 /*
612  * Save the floating point registers.
613  */
614         SAVE_U_PCB_FPREG($f0, F0_NUM, a0)
615         SAVE_U_PCB_FPREG($f1, F1_NUM, a0)
616         SAVE_U_PCB_FPREG($f2, F2_NUM, a0)
617         SAVE_U_PCB_FPREG($f3, F3_NUM, a0)
618         SAVE_U_PCB_FPREG($f4, F4_NUM, a0)
619         SAVE_U_PCB_FPREG($f5, F5_NUM, a0)
620         SAVE_U_PCB_FPREG($f6, F6_NUM, a0)
621         SAVE_U_PCB_FPREG($f7, F7_NUM, a0)
622         SAVE_U_PCB_FPREG($f8, F8_NUM, a0)
623         SAVE_U_PCB_FPREG($f9, F9_NUM, a0)
624         SAVE_U_PCB_FPREG($f10, F10_NUM, a0)
625         SAVE_U_PCB_FPREG($f11, F11_NUM, a0)
626         SAVE_U_PCB_FPREG($f12, F12_NUM, a0)
627         SAVE_U_PCB_FPREG($f13, F13_NUM, a0)
628         SAVE_U_PCB_FPREG($f14, F14_NUM, a0)
629         SAVE_U_PCB_FPREG($f15, F15_NUM, a0)
630         SAVE_U_PCB_FPREG($f16, F16_NUM, a0)
631         SAVE_U_PCB_FPREG($f17, F17_NUM, a0)
632         SAVE_U_PCB_FPREG($f18, F18_NUM, a0)
633         SAVE_U_PCB_FPREG($f19, F19_NUM, a0)
634         SAVE_U_PCB_FPREG($f20, F20_NUM, a0)
635         SAVE_U_PCB_FPREG($f21, F21_NUM, a0)
636         SAVE_U_PCB_FPREG($f22, F22_NUM, a0)
637         SAVE_U_PCB_FPREG($f23, F23_NUM, a0)
638         SAVE_U_PCB_FPREG($f24, F24_NUM, a0)
639         SAVE_U_PCB_FPREG($f25, F25_NUM, a0)
640         SAVE_U_PCB_FPREG($f26, F26_NUM, a0)
641         SAVE_U_PCB_FPREG($f27, F27_NUM, a0)
642         SAVE_U_PCB_FPREG($f28, F28_NUM, a0)
643         SAVE_U_PCB_FPREG($f29, F29_NUM, a0)
644         SAVE_U_PCB_FPREG($f30, F30_NUM, a0)
645         SAVE_U_PCB_FPREG($f31, F31_NUM, a0)
646
647         mtc0    t1, MIPS_COP_0_STATUS           # Restore the status register.
648         ITLBNOPFIX
649         j       ra
650         nop
651         .set pop
652 END(MipsSaveCurFPState)
653
654 /*
655  * This code is copied the user's stack for returning from signal handlers
656  * (see sendsig() and sigreturn()). We have to compute the address
657  * of the sigcontext struct for the sigreturn call.
658  */
659         .globl  _C_LABEL(sigcode)
660 _C_LABEL(sigcode):
661         PTR_ADDU        a0, sp, SIGF_UC         # address of ucontext
662         li              v0, SYS_sigreturn
663 # sigreturn (ucp)
664         syscall
665         break   0                               # just in case sigreturn fails
666         .globl  _C_LABEL(esigcode)
667 _C_LABEL(esigcode):
668
669         .data
670         .globl  szsigcode
671 szsigcode:
672         .long   esigcode-sigcode
673         .text
674
675 #if (defined(__mips_n32) || defined(__mips_n64)) && defined(COMPAT_FREEBSD32)
676         .globl  _C_LABEL(sigcode32)
677 _C_LABEL(sigcode32):
678         addu            a0, sp, SIGF32_UC       # address of ucontext
679         li              v0, SYS_sigreturn
680 # sigreturn (ucp)
681         syscall
682         break   0                               # just in case sigreturn fails
683         .globl  _C_LABEL(esigcode32)
684 _C_LABEL(esigcode32):
685
686         .data
687         .globl  szsigcode32
688 szsigcode32:
689         .long   esigcode32-sigcode32
690         .text
691 #endif