/* $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_compat.h" #include #include #include #include #include #include #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 #ifdef CPU_CNMIPS lw t2, TD_MDFLAGS(a3) # get md_flags and t1, t2, MDTD_COP2USED beqz t1, cop2_untouched nop /* Clear cop2used flag */ and t2, t2, ~MDTD_COP2USED sw t2, TD_MDFLAGS(a3) and t2, t0, ~MIPS_SR_COP_2_BIT # clear COP_2 enable bit SAVE_U_PCB_CONTEXT(t2, PREG_SR, a0) # save status register RESTORE_U_PCB_REG(t0, PS, a0) # get CPU status register and t2, t0, ~MIPS_SR_COP_2_BIT # clear COP_2 enable bit SAVE_U_PCB_REG(t2, PS, a0) # save stratus register /* preserve a0..a3 */ move s0, a0 move s1, a1 move s2, a2 move s3, a3 /* does kernel own COP2 context? */ lw t1, TD_COP2OWNER(a3) # get md_cop2owner beqz t1, userland_cop2 # 0 - it's userland context nop PTR_L a0, TD_COP2(a3) beqz a0, no_cop2_context nop j do_cop2_save nop userland_cop2: PTR_L a0, TD_UCOP2(a3) beqz a0, no_cop2_context nop do_cop2_save: jal octeon_cop2_save nop no_cop2_context: move a3, s3 move a2, s2 move a1, s1 move a0, s0 cop2_untouched: #endif 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) /* * 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 #if (defined(__mips_n32) || defined(__mips_n64)) && defined(COMPAT_FREEBSD32) .globl _C_LABEL(sigcode32) _C_LABEL(sigcode32): addu a0, sp, SIGF32_UC # address of ucontext li v0, SYS_sigreturn # sigreturn (ucp) syscall break 0 # just in case sigreturn fails .globl _C_LABEL(esigcode32) _C_LABEL(esigcode32): .data .globl szsigcode32 szsigcode32: .long esigcode32-sigcode32 .text #endif