/sys/mips/mips/swtch.S
Assembly | 583 lines | 563 code | 20 blank | 0 comment | 9 complexity | 3d27684e47995b51c596067586d60dcd MD5 | raw file
- /* $OpenBSD: locore.S,v 1.18 1998/09/15 10:58:53 pefo Exp $ */
- /*-
- * Copyright (c) 1992, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Digital Equipment Corporation and Ralph Campbell.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * Copyright (C) 1989 Digital Equipment Corporation.
- * Permission to use, copy, modify, and distribute this software and
- * its documentation for any purpose and without fee is hereby granted,
- * provided that the above copyright notice appears in all copies.
- * Digital Equipment Corporation makes no representations about the
- * suitability of this software for any purpose. It is provided "as is"
- * without express or implied warranty.
- *
- * from: Header: /sprite/src/kernel/mach/ds3100.md/RCS/loMem.s,
- * v 1.1 89/07/11 17:55:04 nelson Exp SPRITE (DECWRL)
- * from: Header: /sprite/src/kernel/mach/ds3100.md/RCS/machAsm.s,
- * v 9.2 90/01/29 18:00:39 shirriff Exp SPRITE (DECWRL)
- * from: Header: /sprite/src/kernel/vm/ds3100.md/vmPmaxAsm.s,
- * v 1.1 89/07/10 14:27:41 nelson Exp SPRITE (DECWRL)
- *
- * from: @(#)locore.s 8.5 (Berkeley) 1/4/94
- * JNPR: swtch.S,v 1.6.2.1 2007/09/10 10:36:50 girish
- * $FreeBSD$
- */
- /*
- * Contains code that is the first executed at boot time plus
- * assembly language support routines.
- */
- #include "opt_cputype.h"
- #include <sys/syscall.h>
- #include <machine/asm.h>
- #include <machine/cpu.h>
- #include <machine/cpuregs.h>
- #include <machine/regnum.h>
- #include <machine/pte.h>
- #include "assym.s"
- .set noreorder # Noreorder is default style!
- #define SAVE_U_PCB_REG(reg, offs, base) \
- REG_S reg, U_PCB_REGS + (SZREG * offs) (base)
- #define RESTORE_U_PCB_REG(reg, offs, base) \
- REG_L reg, U_PCB_REGS + (SZREG * offs) (base)
- #define SAVE_U_PCB_FPREG(reg, offs, base) \
- FP_S reg, U_PCB_FPREGS + (SZFPREG * offs) (base)
- #define RESTORE_U_PCB_FPREG(reg, offs, base) \
- FP_L reg, U_PCB_FPREGS + (SZFPREG * offs) (base)
- #define SAVE_U_PCB_FPSR(reg, offs, base) \
- REG_S reg, U_PCB_FPREGS + (SZFPREG * offs) (base)
- #define RESTORE_U_PCB_FPSR(reg, offs, base) \
- REG_L reg, U_PCB_FPREGS + (SZFPREG * offs) (base)
- #define SAVE_U_PCB_CONTEXT(reg, offs, base) \
- REG_S reg, U_PCB_CONTEXT + (SZREG * offs) (base)
- #define RESTORE_U_PCB_CONTEXT(reg, offs, base) \
- REG_L reg, U_PCB_CONTEXT + (SZREG * offs) (base)
- /*
- * Setup for and return to user.
- */
- LEAF(fork_trampoline)
- move a0,s0
- move a1,s1
- jal _C_LABEL(fork_exit)
- move a2,s2 #BDSlot
- DO_AST
- mfc0 v0, MIPS_COP_0_STATUS
- and v0, ~(MIPS_SR_INT_IE)
- mtc0 v0, MIPS_COP_0_STATUS # disable interrupts
- COP0_SYNC
- /*
- * The use of k1 for storing the PCB pointer must be done only
- * after interrupts are disabled. Otherwise it will get overwritten
- * by the interrupt code.
- */
- .set noat
- GET_CPU_PCPU(k1)
- PTR_L k1, PC_CURPCB(k1)
- RESTORE_U_PCB_REG(t0, MULLO, k1)
- RESTORE_U_PCB_REG(t1, MULHI, k1)
- mtlo t0
- mthi t1
- RESTORE_U_PCB_REG(a0, PC, k1)
- RESTORE_U_PCB_REG(AT, AST, k1)
- RESTORE_U_PCB_REG(v0, V0, k1)
- MTC0 a0, MIPS_COP_0_EXC_PC # set return address
- RESTORE_U_PCB_REG(v1, V1, k1)
- RESTORE_U_PCB_REG(a0, A0, k1)
- RESTORE_U_PCB_REG(a1, A1, k1)
- RESTORE_U_PCB_REG(a2, A2, k1)
- RESTORE_U_PCB_REG(a3, A3, k1)
- RESTORE_U_PCB_REG(t0, T0, k1)
- RESTORE_U_PCB_REG(t1, T1, k1)
- RESTORE_U_PCB_REG(t2, T2, k1)
- RESTORE_U_PCB_REG(t3, T3, k1)
- RESTORE_U_PCB_REG(ta0, TA0, k1)
- RESTORE_U_PCB_REG(ta1, TA1, k1)
- RESTORE_U_PCB_REG(ta2, TA2, k1)
- RESTORE_U_PCB_REG(ta3, TA3, k1)
- RESTORE_U_PCB_REG(s0, S0, k1)
- RESTORE_U_PCB_REG(s1, S1, k1)
- RESTORE_U_PCB_REG(s2, S2, k1)
- RESTORE_U_PCB_REG(s3, S3, k1)
- RESTORE_U_PCB_REG(s4, S4, k1)
- RESTORE_U_PCB_REG(s5, S5, k1)
- RESTORE_U_PCB_REG(s6, S6, k1)
- RESTORE_U_PCB_REG(s7, S7, k1)
- RESTORE_U_PCB_REG(t8, T8, k1)
- RESTORE_U_PCB_REG(t9, T9, k1)
- RESTORE_U_PCB_REG(k0, SR, k1)
- RESTORE_U_PCB_REG(gp, GP, k1)
- RESTORE_U_PCB_REG(s8, S8, k1)
- RESTORE_U_PCB_REG(ra, RA, k1)
- RESTORE_U_PCB_REG(sp, SP, k1)
- li k1, ~MIPS_SR_INT_MASK
- and k0, k0, k1
- mfc0 k1, MIPS_COP_0_STATUS
- and k1, k1, MIPS_SR_INT_MASK
- or k0, k0, k1
- mtc0 k0, MIPS_COP_0_STATUS # switch to user mode (when eret...)
- HAZARD_DELAY
- sync
- eret
- .set at
- END(fork_trampoline)
- /*
- * Update pcb, saving current processor state.
- * Note: this only works if pcbp != curproc's pcb since
- * cpu_switch() will copy over pcb_context.
- *
- * savectx(struct pcb *pcbp);
- */
- LEAF(savectx)
- SAVE_U_PCB_CONTEXT(s0, PREG_S0, a0)
- SAVE_U_PCB_CONTEXT(s1, PREG_S1, a0)
- SAVE_U_PCB_CONTEXT(s2, PREG_S2, a0)
- SAVE_U_PCB_CONTEXT(s3, PREG_S3, a0)
- mfc0 v0, MIPS_COP_0_STATUS
- SAVE_U_PCB_CONTEXT(s4, PREG_S4, a0)
- SAVE_U_PCB_CONTEXT(s5, PREG_S5, a0)
- SAVE_U_PCB_CONTEXT(s6, PREG_S6, a0)
- SAVE_U_PCB_CONTEXT(s7, PREG_S7, a0)
- SAVE_U_PCB_CONTEXT(sp, PREG_SP, a0)
- SAVE_U_PCB_CONTEXT(s8, PREG_S8, a0)
- SAVE_U_PCB_CONTEXT(ra, PREG_RA, a0)
- SAVE_U_PCB_CONTEXT(v0, PREG_SR, a0)
- SAVE_U_PCB_CONTEXT(gp, PREG_GP, a0)
- move v0, ra /* save 'ra' before we trash it */
- jal 1f
- nop
- 1:
- SAVE_U_PCB_CONTEXT(ra, PREG_PC, a0)
- move ra, v0 /* restore 'ra' before returning */
- j ra
- move v0, zero
- END(savectx)
- NON_LEAF(cpu_throw, CALLFRAME_SIZ, ra)
- mfc0 t0, MIPS_COP_0_STATUS # t0 = saved status register
- nop
- nop
- and a3, t0, ~(MIPS_SR_INT_IE)
- mtc0 a3, MIPS_COP_0_STATUS # Disable all interrupts
- ITLBNOPFIX
- j mips_sw1 # We're not interested in old
- # thread's context, so jump
- # right to action
- nop # BDSLOT
- END(cpu_throw)
- /*
- * cpu_switch(struct thread *old, struct thread *new, struct mutex *mtx);
- * a0 - old
- * a1 - new
- * a2 - mtx
- * Find the highest priority process and resume it.
- */
- NON_LEAF(cpu_switch, CALLFRAME_SIZ, ra)
- mfc0 t0, MIPS_COP_0_STATUS # t0 = saved status register
- nop
- nop
- and a3, t0, ~(MIPS_SR_INT_IE)
- mtc0 a3, MIPS_COP_0_STATUS # Disable all interrupts
- ITLBNOPFIX
- beqz a0, mips_sw1
- move a3, a0
- PTR_L a0, TD_PCB(a0) # load PCB addr of curproc
- SAVE_U_PCB_CONTEXT(sp, PREG_SP, a0) # save old sp
- PTR_SUBU sp, sp, CALLFRAME_SIZ
- REG_S ra, CALLFRAME_RA(sp)
- .mask 0x80000000, (CALLFRAME_RA - CALLFRAME_SIZ)
- SAVE_U_PCB_CONTEXT(s0, PREG_S0, a0) # do a 'savectx()'
- SAVE_U_PCB_CONTEXT(s1, PREG_S1, a0)
- SAVE_U_PCB_CONTEXT(s2, PREG_S2, a0)
- SAVE_U_PCB_CONTEXT(s3, PREG_S3, a0)
- SAVE_U_PCB_CONTEXT(s4, PREG_S4, a0)
- SAVE_U_PCB_CONTEXT(s5, PREG_S5, a0)
- SAVE_U_PCB_CONTEXT(s6, PREG_S6, a0)
- SAVE_U_PCB_CONTEXT(s7, PREG_S7, a0)
- SAVE_U_PCB_CONTEXT(s8, PREG_S8, a0)
- SAVE_U_PCB_CONTEXT(ra, PREG_RA, a0) # save return address
- SAVE_U_PCB_CONTEXT(t0, PREG_SR, a0) # save status register
- SAVE_U_PCB_CONTEXT(gp, PREG_GP, a0)
- jal getpc
- nop
- getpc:
- SAVE_U_PCB_CONTEXT(ra, PREG_PC, a0) # save return address
- PTR_S a2, TD_LOCK(a3) # Switchout td_lock
- mips_sw1:
- #if defined(SMP) && defined(SCHED_ULE)
- PTR_LA t0, _C_LABEL(blocked_lock)
- blocked_loop:
- PTR_L t1, TD_LOCK(a1)
- beq t0, t1, blocked_loop
- nop
- #endif
- move s7, a1 # Store newthread
- /*
- * Switch to new context.
- */
- GET_CPU_PCPU(a3)
- PTR_S a1, PC_CURTHREAD(a3)
- PTR_L a2, TD_PCB(a1)
- PTR_S a2, PC_CURPCB(a3)
- PTR_L v0, TD_KSTACK(a1)
- #if defined(__mips_n64)
- PTR_LI s0, MIPS_XKSEG_START
- #else
- PTR_LI s0, MIPS_KSEG2_START # If Uarea addr is below kseg2,
- #endif
- bltu v0, s0, sw2 # no need to insert in TLB.
- PTE_L a1, TD_UPTE + 0(s7) # a1 = u. pte #0
- PTE_L a2, TD_UPTE + PTESIZE(s7) # a2 = u. pte #1
- /*
- * Wiredown the USPACE of newproc in TLB entry#0. Check whether target
- * USPACE is already in another place of TLB before that, and if so
- * invalidate that TLB entry.
- * NOTE: This is hard coded to UPAGES == 2.
- * Also, there should be no TLB faults at this point.
- */
- MTC0 v0, MIPS_COP_0_TLB_HI # VPN = va
- HAZARD_DELAY
- tlbp # probe VPN
- HAZARD_DELAY
- mfc0 s0, MIPS_COP_0_TLB_INDEX
- HAZARD_DELAY
- PTR_LI t1, MIPS_KSEG0_START # invalidate tlb entry
- bltz s0, entry0set
- nop
- sll s0, PAGE_SHIFT + 1
- addu t1, s0
- MTC0 t1, MIPS_COP_0_TLB_HI
- PTE_MTC0 zero, MIPS_COP_0_TLB_LO0
- PTE_MTC0 zero, MIPS_COP_0_TLB_LO1
- HAZARD_DELAY
- tlbwi
- HAZARD_DELAY
- MTC0 v0, MIPS_COP_0_TLB_HI # set VPN again
- entry0set:
- /* SMP!! - Works only for unshared TLB case - i.e. no v-cpus */
- mtc0 zero, MIPS_COP_0_TLB_INDEX # TLB entry #0
- HAZARD_DELAY
- PTE_MTC0 a1, MIPS_COP_0_TLB_LO0 # upte[0]
- HAZARD_DELAY
- PTE_MTC0 a2, MIPS_COP_0_TLB_LO1 # upte[1]
- HAZARD_DELAY
- tlbwi # set TLB entry #0
- HAZARD_DELAY
- /*
- * Now running on new u struct.
- */
- sw2:
- PTR_L s0, TD_PCB(s7)
- RESTORE_U_PCB_CONTEXT(sp, PREG_SP, s0)
- PTR_LA t1, _C_LABEL(pmap_activate) # s7 = new proc pointer
- jalr t1 # s7 = new proc pointer
- move a0, s7 # BDSLOT
- /*
- * Restore registers and return.
- */
- move a0, s0
- RESTORE_U_PCB_CONTEXT(gp, PREG_GP, a0)
- RESTORE_U_PCB_CONTEXT(v0, PREG_SR, a0) # restore kernel context
- RESTORE_U_PCB_CONTEXT(ra, PREG_RA, a0)
- RESTORE_U_PCB_CONTEXT(s0, PREG_S0, a0)
- RESTORE_U_PCB_CONTEXT(s1, PREG_S1, a0)
- RESTORE_U_PCB_CONTEXT(s2, PREG_S2, a0)
- RESTORE_U_PCB_CONTEXT(s3, PREG_S3, a0)
- RESTORE_U_PCB_CONTEXT(s4, PREG_S4, a0)
- RESTORE_U_PCB_CONTEXT(s5, PREG_S5, a0)
- RESTORE_U_PCB_CONTEXT(s6, PREG_S6, a0)
- RESTORE_U_PCB_CONTEXT(s7, PREG_S7, a0)
- RESTORE_U_PCB_CONTEXT(s8, PREG_S8, a0)
- mfc0 t0, MIPS_COP_0_STATUS
- and t0, t0, MIPS_SR_INT_MASK
- and v0, v0, ~MIPS_SR_INT_MASK
- or v0, v0, t0
- mtc0 v0, MIPS_COP_0_STATUS
- ITLBNOPFIX
- j ra
- nop
- END(cpu_switch)
- /*----------------------------------------------------------------------------
- *
- * MipsSwitchFPState --
- *
- * Save the current state into 'from' and restore it from 'to'.
- *
- * MipsSwitchFPState(from, to)
- * struct thread *from;
- * struct trapframe *to;
- *
- * Results:
- * None.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------------
- */
- LEAF(MipsSwitchFPState)
- mfc0 t1, MIPS_COP_0_STATUS # Save old SR
- li t0, MIPS_SR_COP_1_BIT # enable the coprocessor
- mtc0 t0, MIPS_COP_0_STATUS
- ITLBNOPFIX
- beq a0, zero, 1f # skip save if NULL pointer
- nop
- /*
- * First read out the status register to make sure that all FP operations
- * have completed.
- */
- PTR_L a0, TD_PCB(a0) # get pointer to pcb for proc
- cfc1 t0, MIPS_FPU_CSR # stall til FP done
- cfc1 t0, MIPS_FPU_CSR # now get status
- li t3, ~MIPS_SR_COP_1_BIT
- RESTORE_U_PCB_REG(t2, PS, a0) # get CPU status register
- SAVE_U_PCB_FPSR(t0, FSR_NUM, a0) # save FP status
- and t2, t2, t3 # clear COP_1 enable bit
- SAVE_U_PCB_REG(t2, PS, a0) # save new status register
- /*
- * Save the floating point registers.
- */
- SAVE_U_PCB_FPREG($f0, F0_NUM, a0)
- SAVE_U_PCB_FPREG($f1, F1_NUM, a0)
- SAVE_U_PCB_FPREG($f2, F2_NUM, a0)
- SAVE_U_PCB_FPREG($f3, F3_NUM, a0)
- SAVE_U_PCB_FPREG($f4, F4_NUM, a0)
- SAVE_U_PCB_FPREG($f5, F5_NUM, a0)
- SAVE_U_PCB_FPREG($f6, F6_NUM, a0)
- SAVE_U_PCB_FPREG($f7, F7_NUM, a0)
- SAVE_U_PCB_FPREG($f8, F8_NUM, a0)
- SAVE_U_PCB_FPREG($f9, F9_NUM, a0)
- SAVE_U_PCB_FPREG($f10, F10_NUM, a0)
- SAVE_U_PCB_FPREG($f11, F11_NUM, a0)
- SAVE_U_PCB_FPREG($f12, F12_NUM, a0)
- SAVE_U_PCB_FPREG($f13, F13_NUM, a0)
- SAVE_U_PCB_FPREG($f14, F14_NUM, a0)
- SAVE_U_PCB_FPREG($f15, F15_NUM, a0)
- SAVE_U_PCB_FPREG($f16, F16_NUM, a0)
- SAVE_U_PCB_FPREG($f17, F17_NUM, a0)
- SAVE_U_PCB_FPREG($f18, F18_NUM, a0)
- SAVE_U_PCB_FPREG($f19, F19_NUM, a0)
- SAVE_U_PCB_FPREG($f20, F20_NUM, a0)
- SAVE_U_PCB_FPREG($f21, F21_NUM, a0)
- SAVE_U_PCB_FPREG($f22, F22_NUM, a0)
- SAVE_U_PCB_FPREG($f23, F23_NUM, a0)
- SAVE_U_PCB_FPREG($f24, F24_NUM, a0)
- SAVE_U_PCB_FPREG($f25, F25_NUM, a0)
- SAVE_U_PCB_FPREG($f26, F26_NUM, a0)
- SAVE_U_PCB_FPREG($f27, F27_NUM, a0)
- SAVE_U_PCB_FPREG($f28, F28_NUM, a0)
- SAVE_U_PCB_FPREG($f29, F29_NUM, a0)
- SAVE_U_PCB_FPREG($f30, F30_NUM, a0)
- SAVE_U_PCB_FPREG($f31, F31_NUM, a0)
- 1:
- /*
- * Restore the floating point registers.
- */
- RESTORE_U_PCB_FPSR(t0, FSR_NUM, a1) # get status register
- RESTORE_U_PCB_FPREG($f0, F0_NUM, a1)
- RESTORE_U_PCB_FPREG($f1, F1_NUM, a1)
- RESTORE_U_PCB_FPREG($f2, F2_NUM, a1)
- RESTORE_U_PCB_FPREG($f3, F3_NUM, a1)
- RESTORE_U_PCB_FPREG($f4, F4_NUM, a1)
- RESTORE_U_PCB_FPREG($f5, F5_NUM, a1)
- RESTORE_U_PCB_FPREG($f6, F6_NUM, a1)
- RESTORE_U_PCB_FPREG($f7, F7_NUM, a1)
- RESTORE_U_PCB_FPREG($f8, F8_NUM, a1)
- RESTORE_U_PCB_FPREG($f9, F9_NUM, a1)
- RESTORE_U_PCB_FPREG($f10, F10_NUM, a1)
- RESTORE_U_PCB_FPREG($f11, F11_NUM, a1)
- RESTORE_U_PCB_FPREG($f12, F12_NUM, a1)
- RESTORE_U_PCB_FPREG($f13, F13_NUM, a1)
- RESTORE_U_PCB_FPREG($f14, F14_NUM, a1)
- RESTORE_U_PCB_FPREG($f15, F15_NUM, a1)
- RESTORE_U_PCB_FPREG($f16, F16_NUM, a1)
- RESTORE_U_PCB_FPREG($f17, F17_NUM, a1)
- RESTORE_U_PCB_FPREG($f18, F18_NUM, a1)
- RESTORE_U_PCB_FPREG($f19, F19_NUM, a1)
- RESTORE_U_PCB_FPREG($f20, F20_NUM, a1)
- RESTORE_U_PCB_FPREG($f21, F21_NUM, a1)
- RESTORE_U_PCB_FPREG($f22, F22_NUM, a1)
- RESTORE_U_PCB_FPREG($f23, F23_NUM, a1)
- RESTORE_U_PCB_FPREG($f24, F24_NUM, a1)
- RESTORE_U_PCB_FPREG($f25, F25_NUM, a1)
- RESTORE_U_PCB_FPREG($f26, F26_NUM, a1)
- RESTORE_U_PCB_FPREG($f27, F27_NUM, a1)
- RESTORE_U_PCB_FPREG($f28, F28_NUM, a1)
- RESTORE_U_PCB_FPREG($f29, F29_NUM, a1)
- RESTORE_U_PCB_FPREG($f30, F30_NUM, a1)
- RESTORE_U_PCB_FPREG($f31, F31_NUM, a1)
- and t0, t0, ~MIPS_FPU_EXCEPTION_BITS
- ctc1 t0, MIPS_FPU_CSR
- nop
- mtc0 t1, MIPS_COP_0_STATUS # Restore the status register.
- ITLBNOPFIX
- j ra
- nop
- END(MipsSwitchFPState)
- /*----------------------------------------------------------------------------
- *
- * MipsSaveCurFPState --
- *
- * Save the current floating point coprocessor state.
- *
- * MipsSaveCurFPState(td)
- * struct thread *td;
- *
- * Results:
- * None.
- *
- * Side effects:
- * machFPCurProcPtr is cleared.
- *
- *----------------------------------------------------------------------------
- */
- LEAF(MipsSaveCurFPState)
- PTR_L a0, TD_PCB(a0) # get pointer to pcb for thread
- mfc0 t1, MIPS_COP_0_STATUS # Disable interrupts and
- li t0, MIPS_SR_COP_1_BIT # enable the coprocessor
- mtc0 t0, MIPS_COP_0_STATUS
- ITLBNOPFIX
- GET_CPU_PCPU(a1)
- PTR_S zero, PC_FPCURTHREAD(a1) # indicate state has been saved
- /*
- * First read out the status register to make sure that all FP operations
- * have completed.
- */
- RESTORE_U_PCB_REG(t2, PS, a0) # get CPU status register
- li t3, ~MIPS_SR_COP_1_BIT
- and t2, t2, t3 # clear COP_1 enable bit
- cfc1 t0, MIPS_FPU_CSR # stall til FP done
- cfc1 t0, MIPS_FPU_CSR # now get status
- SAVE_U_PCB_REG(t2, PS, a0) # save new status register
- SAVE_U_PCB_FPSR(t0, FSR_NUM, a0) # save FP status
- /*
- * Save the floating point registers.
- */
- SAVE_U_PCB_FPREG($f0, F0_NUM, a0)
- SAVE_U_PCB_FPREG($f1, F1_NUM, a0)
- SAVE_U_PCB_FPREG($f2, F2_NUM, a0)
- SAVE_U_PCB_FPREG($f3, F3_NUM, a0)
- SAVE_U_PCB_FPREG($f4, F4_NUM, a0)
- SAVE_U_PCB_FPREG($f5, F5_NUM, a0)
- SAVE_U_PCB_FPREG($f6, F6_NUM, a0)
- SAVE_U_PCB_FPREG($f7, F7_NUM, a0)
- SAVE_U_PCB_FPREG($f8, F8_NUM, a0)
- SAVE_U_PCB_FPREG($f9, F9_NUM, a0)
- SAVE_U_PCB_FPREG($f10, F10_NUM, a0)
- SAVE_U_PCB_FPREG($f11, F11_NUM, a0)
- SAVE_U_PCB_FPREG($f12, F12_NUM, a0)
- SAVE_U_PCB_FPREG($f13, F13_NUM, a0)
- SAVE_U_PCB_FPREG($f14, F14_NUM, a0)
- SAVE_U_PCB_FPREG($f15, F15_NUM, a0)
- SAVE_U_PCB_FPREG($f16, F16_NUM, a0)
- SAVE_U_PCB_FPREG($f17, F17_NUM, a0)
- SAVE_U_PCB_FPREG($f18, F18_NUM, a0)
- SAVE_U_PCB_FPREG($f19, F19_NUM, a0)
- SAVE_U_PCB_FPREG($f20, F20_NUM, a0)
- SAVE_U_PCB_FPREG($f21, F21_NUM, a0)
- SAVE_U_PCB_FPREG($f22, F22_NUM, a0)
- SAVE_U_PCB_FPREG($f23, F23_NUM, a0)
- SAVE_U_PCB_FPREG($f24, F24_NUM, a0)
- SAVE_U_PCB_FPREG($f25, F25_NUM, a0)
- SAVE_U_PCB_FPREG($f26, F26_NUM, a0)
- SAVE_U_PCB_FPREG($f27, F27_NUM, a0)
- SAVE_U_PCB_FPREG($f28, F28_NUM, a0)
- SAVE_U_PCB_FPREG($f29, F29_NUM, a0)
- SAVE_U_PCB_FPREG($f30, F30_NUM, a0)
- SAVE_U_PCB_FPREG($f31, F31_NUM, a0)
- mtc0 t1, MIPS_COP_0_STATUS # Restore the status register.
- ITLBNOPFIX
- j ra
- nop
- END(MipsSaveCurFPState)
- /*
- * When starting init, call this to configure the process for user
- * mode. This will be inherited by other processes.
- */
- LEAF_NOPROFILE(prepare_usermode)
- j ra
- nop
- END(prepare_usermode)
- /*
- * This code is copied the user's stack for returning from signal handlers
- * (see sendsig() and sigreturn()). We have to compute the address
- * of the sigcontext struct for the sigreturn call.
- */
- .globl _C_LABEL(sigcode)
- _C_LABEL(sigcode):
- PTR_ADDU a0, sp, SIGF_UC # address of ucontext
- li v0, SYS_sigreturn
- # sigreturn (ucp)
- syscall
- break 0 # just in case sigreturn fails
- .globl _C_LABEL(esigcode)
- _C_LABEL(esigcode):
- .data
- .globl szsigcode
- szsigcode:
- .long esigcode-sigcode
- .text