swtch.S revision 206716
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 * 4. 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: head/sys/mips/mips/swtch.S 206716 2010-04-17 00:05:22Z jmallett $ 51 */ 52 53/* 54 * Contains code that is the first executed at boot time plus 55 * assembly language support routines. 56 */ 57 58#include "opt_cputype.h" 59#include <sys/syscall.h> 60#include <machine/asm.h> 61#include <machine/cpu.h> 62#include <machine/cpuregs.h> 63#include <machine/regnum.h> 64#include <machine/pte.h> 65 66#include "assym.s" 67 68#if defined(ISA_MIPS32) 69#undef WITH_64BIT_CP0 70#elif defined(ISA_MIPS64) 71#define WITH_64BIT_CP0 72#elif defined(ISA_MIPS3) 73#define WITH_64BIT_CP0 74#else 75#error "Please write the code for this ISA" 76#endif 77 78#ifdef WITH_64BIT_CP0 79#define _SLL dsll 80#define _SRL dsrl 81#define _MFC0 dmfc0 82#define _MTC0 dmtc0 83#define WIRED_SHIFT 34 84#else 85#define _SLL sll 86#define _SRL srl 87#define _MFC0 mfc0 88#define _MTC0 mtc0 89#define WIRED_SHIFT 2 90#endif 91 .set noreorder # Noreorder is default style! 92#if defined(ISA_MIPS32) 93 .set mips32 94#elif defined(ISA_MIPS64) 95 .set mips64 96#elif defined(ISA_MIPS3) 97 .set mips3 98#endif 99 100#if defined(ISA_MIPS32) 101#define STORE sw /* 32 bit mode regsave instruction */ 102#define LOAD lw /* 32 bit mode regload instruction */ 103#define RSIZE 4 /* 32 bit mode register size */ 104#define STORE_FP swc1 /* 32 bit mode fp regsave instruction */ 105#define LOAD_FP lwc1 /* 32 bit mode fp regload instruction */ 106#define FP_RSIZE 4 /* 32 bit mode fp register size */ 107#else 108#define STORE sd /* 64 bit mode regsave instruction */ 109#define LOAD ld /* 64 bit mode regload instruction */ 110#define RSIZE 8 /* 64 bit mode register size */ 111#define STORE_FP sdc1 /* 64 bit mode fp regsave instruction */ 112#define LOAD_FP ldc1 /* 64 bit mode fp regload instruction */ 113#define FP_RSIZE 8 /* 64 bit mode fp register size */ 114#endif 115 116/* 117 * FREEBSD_DEVELOPERS_FIXME 118 * Some MIPS CPU may need delays using nops between executing CP0 Instructions 119 */ 120 121#if 1 122#define HAZARD_DELAY nop ; nop ; nop ; nop 123#else 124#define HAZARD_DELAY 125#endif 126 127#define SAVE_U_PCB_REG(reg, offs, base) \ 128 STORE reg, U_PCB_REGS + (RSIZE * offs) (base) 129 130#define RESTORE_U_PCB_REG(reg, offs, base) \ 131 LOAD reg, U_PCB_REGS + (RSIZE * offs) (base) 132 133#define SAVE_U_PCB_FPREG(reg, offs, base) \ 134 STORE_FP reg, U_PCB_FPREGS + (FP_RSIZE * offs) (base) 135 136#define RESTORE_U_PCB_FPREG(reg, offs, base) \ 137 LOAD_FP reg, U_PCB_FPREGS + (FP_RSIZE * offs) (base) 138 139#define SAVE_U_PCB_FPSR(reg, offs, base) \ 140 STORE reg, U_PCB_FPREGS + (FP_RSIZE * offs) (base) 141 142#define RESTORE_U_PCB_FPSR(reg, offs, base) \ 143 LOAD reg, U_PCB_FPREGS + (FP_RSIZE * offs) (base) 144 145#define SAVE_U_PCB_CONTEXT(reg, offs, base) \ 146 STORE reg, U_PCB_CONTEXT + (RSIZE * offs) (base) 147 148#define RESTORE_U_PCB_CONTEXT(reg, offs, base) \ 149 LOAD reg, U_PCB_CONTEXT + (RSIZE * offs) (base) 150 151#define ITLBNOPFIX nop;nop;nop;nop;nop;nop;nop;nop;nop;nop; 152 153/* 154 * Setup for and return to user. 155 */ 156LEAF(fork_trampoline) 157 move a0,s0 158 move a1,s1 159 jal _C_LABEL(fork_exit) 160 move a2,s2 #BDSlot 161 162 DO_AST 163 164 mfc0 v0, COP_0_STATUS_REG 165 and v0, ~(SR_INT_ENAB) 166 mtc0 v0, COP_0_STATUS_REG # disable interrupts 167 COP0_SYNC 168/* 169 * The use of k1 for storing the PCB pointer must be done only 170 * after interrupts are disabled. Otherwise it will get overwritten 171 * by the interrupt code. 172 */ 173 .set noat 174 GET_CPU_PCPU(k1) 175 lw k1, PC_CURPCB(k1) 176 177 RESTORE_U_PCB_REG(t0, MULLO, k1) 178 RESTORE_U_PCB_REG(t1, MULHI, k1) 179 mtlo t0 180 mthi t1 181 RESTORE_U_PCB_REG(a0, PC, k1) 182 RESTORE_U_PCB_REG(AT, AST, k1) 183 RESTORE_U_PCB_REG(v0, V0, k1) 184 _MTC0 a0, COP_0_EXC_PC # set return address 185 186 RESTORE_U_PCB_REG(v1, V1, k1) 187 RESTORE_U_PCB_REG(a0, A0, k1) 188 RESTORE_U_PCB_REG(a1, A1, k1) 189 RESTORE_U_PCB_REG(a2, A2, k1) 190 RESTORE_U_PCB_REG(a3, A3, k1) 191 RESTORE_U_PCB_REG(t0, T0, k1) 192 RESTORE_U_PCB_REG(t1, T1, k1) 193 RESTORE_U_PCB_REG(t2, T2, k1) 194 RESTORE_U_PCB_REG(t3, T3, k1) 195 RESTORE_U_PCB_REG(ta0, TA0, k1) 196 RESTORE_U_PCB_REG(ta1, TA1, k1) 197 RESTORE_U_PCB_REG(ta2, TA2, k1) 198 RESTORE_U_PCB_REG(ta3, TA3, k1) 199 RESTORE_U_PCB_REG(s0, S0, k1) 200 RESTORE_U_PCB_REG(s1, S1, k1) 201 RESTORE_U_PCB_REG(s2, S2, k1) 202 RESTORE_U_PCB_REG(s3, S3, k1) 203 RESTORE_U_PCB_REG(s4, S4, k1) 204 RESTORE_U_PCB_REG(s5, S5, k1) 205 RESTORE_U_PCB_REG(s6, S6, k1) 206 RESTORE_U_PCB_REG(s7, S7, k1) 207 RESTORE_U_PCB_REG(t8, T8, k1) 208 RESTORE_U_PCB_REG(t9, T9, k1) 209 RESTORE_U_PCB_REG(k0, SR, k1) 210 RESTORE_U_PCB_REG(gp, GP, k1) 211 RESTORE_U_PCB_REG(s8, S8, k1) 212 RESTORE_U_PCB_REG(ra, RA, k1) 213 RESTORE_U_PCB_REG(sp, SP, k1) 214 li k1, ~SR_INT_MASK 215 and k0, k0, k1 216 mfc0 k1, COP_0_STATUS_REG 217 and k1, k1, SR_INT_MASK 218 or k0, k0, k1 219 mtc0 k0, COP_0_STATUS_REG # switch to user mode (when eret...) 220 HAZARD_DELAY 221 sync 222 eret 223 .set at 224END(fork_trampoline) 225 226/* 227 * Update pcb, saving current processor state. 228 * Note: this only works if pcbp != curproc's pcb since 229 * cpu_switch() will copy over pcb_context. 230 * 231 * savectx(struct pcb *pcbp); 232 */ 233LEAF(savectx) 234 SAVE_U_PCB_CONTEXT(s0, PREG_S0, a0) 235 SAVE_U_PCB_CONTEXT(s1, PREG_S1, a0) 236 SAVE_U_PCB_CONTEXT(s2, PREG_S2, a0) 237 SAVE_U_PCB_CONTEXT(s3, PREG_S3, a0) 238 mfc0 v0, COP_0_STATUS_REG 239 SAVE_U_PCB_CONTEXT(s4, PREG_S4, a0) 240 SAVE_U_PCB_CONTEXT(s5, PREG_S5, a0) 241 SAVE_U_PCB_CONTEXT(s6, PREG_S6, a0) 242 SAVE_U_PCB_CONTEXT(s7, PREG_S7, a0) 243 SAVE_U_PCB_CONTEXT(sp, PREG_SP, a0) 244 SAVE_U_PCB_CONTEXT(s8, PREG_S8, a0) 245 SAVE_U_PCB_CONTEXT(ra, PREG_RA, a0) 246 SAVE_U_PCB_CONTEXT(v0, PREG_SR, a0) 247 SAVE_U_PCB_CONTEXT(gp, PREG_GP, a0) 248 249 move v0, ra /* save 'ra' before we trash it */ 250 jal 1f 251 nop 2521: 253 SAVE_U_PCB_CONTEXT(ra, PREG_PC, a0) 254 move ra, v0 /* restore 'ra' before returning */ 255 256 /* 257 * FREEBSD_DEVELOPERS_FIXME: 258 * In case there are CPU-specific registers that need 259 * to be saved with the other registers do so here. 260 */ 261 j ra 262 move v0, zero 263END(savectx) 264 265 266KSEG0TEXT_START; 267 268NON_LEAF(mips_cpu_throw, STAND_FRAME_SIZE, ra) 269 mfc0 t0, COP_0_STATUS_REG # t0 = saved status register 270 nop 271 nop 272 and a3, t0, ~(SR_INT_ENAB) 273 mtc0 a3, COP_0_STATUS_REG # Disable all interrupts 274 ITLBNOPFIX 275 j mips_sw1 # We're not interested in old 276 # thread's context, so jump 277 # right to action 278 nop # BDSLOT 279END(mips_cpu_throw) 280 281/* 282 * cpu_switch(struct thread *old, struct thread *new, struct mutex *mtx); 283 * a0 - old 284 * a1 - new 285 * a2 - mtx 286 * Find the highest priority process and resume it. 287 */ 288NON_LEAF(cpu_switch, STAND_FRAME_SIZE, ra) 289 mfc0 t0, COP_0_STATUS_REG # t0 = saved status register 290 nop 291 nop 292 and a3, t0, ~(SR_INT_ENAB) 293 mtc0 a3, COP_0_STATUS_REG # Disable all interrupts 294 ITLBNOPFIX 295 beqz a0, mips_sw1 296 move a3, a0 297 lw a0, TD_PCB(a0) # load PCB addr of curproc 298 SAVE_U_PCB_CONTEXT(sp, PREG_SP, a0) # save old sp 299 subu sp, sp, STAND_FRAME_SIZE 300 sw ra, STAND_RA_OFFSET(sp) 301 .mask 0x80000000, (STAND_RA_OFFSET - STAND_FRAME_SIZE) 302 SAVE_U_PCB_CONTEXT(s0, PREG_S0, a0) # do a 'savectx()' 303 SAVE_U_PCB_CONTEXT(s1, PREG_S1, a0) 304 SAVE_U_PCB_CONTEXT(s2, PREG_S2, a0) 305 SAVE_U_PCB_CONTEXT(s3, PREG_S3, a0) 306 SAVE_U_PCB_CONTEXT(s4, PREG_S4, a0) 307 SAVE_U_PCB_CONTEXT(s5, PREG_S5, a0) 308 SAVE_U_PCB_CONTEXT(s6, PREG_S6, a0) 309 SAVE_U_PCB_CONTEXT(s7, PREG_S7, a0) 310 SAVE_U_PCB_CONTEXT(s8, PREG_S8, a0) 311 SAVE_U_PCB_CONTEXT(ra, PREG_RA, a0) # save return address 312 SAVE_U_PCB_CONTEXT(t0, PREG_SR, a0) # save status register 313 SAVE_U_PCB_CONTEXT(gp, PREG_GP, a0) 314 jal getpc 315 nop 316getpc: 317 SAVE_U_PCB_CONTEXT(ra, PREG_PC, a0) # save return address 318 /* 319 * FREEBSD_DEVELOPERS_FIXME: 320 * In case there are CPU-specific registers that need 321 * to be saved with the other registers do so here. 322 */ 323 324 sw a2, TD_LOCK(a3) # Switchout td_lock 325 326mips_sw1: 327#if defined(SMP) && defined(SCHED_ULE) 328 PTR_LA t0, _C_LABEL(blocked_lock) 329blocked_loop: 330 lw t1, TD_LOCK(a1) 331 beq t0, t1, blocked_loop 332 nop 333#endif 334 move s7, a1 # Store newthread 335/* 336 * Switch to new context. 337 */ 338 GET_CPU_PCPU(a3) 339 sw a1, PC_CURTHREAD(a3) 340 lw a2, TD_PCB(a1) 341 sw a2, PC_CURPCB(a3) 342 lw v0, TD_REALKSTACK(a1) 343 li s0, MIPS_KSEG2_START # If Uarea addr is below kseg2, 344 bltu v0, s0, sw2 # no need to insert in TLB. 345 lw a1, TD_UPTE+0(s7) # t0 = first u. pte 346 lw a2, TD_UPTE+4(s7) # t1 = 2nd u. pte 347 and s0, v0, PTE_ODDPG 348 beq s0, zero, entry0 349 nop 350 351 PANIC_KSEG0("USPACE sat on odd page boundary", t1) 352 353/* 354 * Wiredown the USPACE of newproc in TLB entry#0. Check whether target 355 * USPACE is already in another place of TLB before that, and if so 356 * invalidate that TLB entry. 357 * NOTE: This is hard coded to UPAGES == 2. 358 * Also, there should be no TLB faults at this point. 359 */ 360entry0: 361 mtc0 v0, COP_0_TLB_HI # VPN = va 362 HAZARD_DELAY 363 tlbp # probe VPN 364 HAZARD_DELAY 365 mfc0 s0, COP_0_TLB_INDEX 366 nop 367pgm: 368 bltz s0, entry0set 369 li t1, MIPS_KSEG0_START # invalidate tlb entry 370 sll s0, PAGE_SHIFT + 1 371 addu t1, s0 372 mtc0 t1, COP_0_TLB_HI 373 mtc0 zero, COP_0_TLB_LO0 374 mtc0 zero, COP_0_TLB_LO1 375 HAZARD_DELAY 376 tlbwi 377 HAZARD_DELAY 378 mtc0 v0, COP_0_TLB_HI # set VPN again 379entry0set: 380/* SMP!! - Works only for unshared TLB case - i.e. no v-cpus */ 381 mtc0 zero, COP_0_TLB_INDEX # TLB entry #0 382# or a1, PG_G 383 mtc0 a1, COP_0_TLB_LO0 # upte[0] 384# or a2, PG_G 385 mtc0 a2, COP_0_TLB_LO1 # upte[1] 386 HAZARD_DELAY 387 tlbwi # set TLB entry #0 388 HAZARD_DELAY 389/* 390 * Now running on new u struct. 391 */ 392sw2: 393 PTR_LA t1, _C_LABEL(pmap_activate) # s7 = new proc pointer 394 jalr t1 # s7 = new proc pointer 395 move a0, s7 # BDSLOT 396/* 397 * Restore registers and return. 398 */ 399 lw a0, TD_PCB(s7) 400 RESTORE_U_PCB_CONTEXT(gp, PREG_GP, a0) 401 RESTORE_U_PCB_CONTEXT(v0, PREG_SR, a0) # restore kernel context 402 RESTORE_U_PCB_CONTEXT(ra, PREG_RA, a0) 403 RESTORE_U_PCB_CONTEXT(s0, PREG_S0, a0) 404 RESTORE_U_PCB_CONTEXT(s1, PREG_S1, a0) 405 RESTORE_U_PCB_CONTEXT(s2, PREG_S2, a0) 406 RESTORE_U_PCB_CONTEXT(s3, PREG_S3, a0) 407 RESTORE_U_PCB_CONTEXT(s4, PREG_S4, a0) 408 RESTORE_U_PCB_CONTEXT(s5, PREG_S5, a0) 409 RESTORE_U_PCB_CONTEXT(s6, PREG_S6, a0) 410 RESTORE_U_PCB_CONTEXT(s7, PREG_S7, a0) 411 RESTORE_U_PCB_CONTEXT(sp, PREG_SP, a0) 412 RESTORE_U_PCB_CONTEXT(s8, PREG_S8, a0) 413 /* 414 * FREEBSD_DEVELOPERS_FIXME: 415 * In case there are CPU-specific registers that need 416 * to be restored with the other registers do so here. 417 */ 418 mfc0 t0, COP_0_STATUS_REG 419 and t0, t0, SR_INT_MASK 420 and v0, v0, ~SR_INT_MASK 421 or v0, v0, t0 422 mtc0 v0, COP_0_STATUS_REG 423 ITLBNOPFIX 424 425 j ra 426 nop 427END(cpu_switch) 428KSEG0TEXT_END; 429 430/*---------------------------------------------------------------------------- 431 * 432 * MipsSwitchFPState -- 433 * 434 * Save the current state into 'from' and restore it from 'to'. 435 * 436 * MipsSwitchFPState(from, to) 437 * struct thread *from; 438 * struct trapframe *to; 439 * 440 * Results: 441 * None. 442 * 443 * Side effects: 444 * None. 445 * 446 *---------------------------------------------------------------------------- 447 */ 448LEAF(MipsSwitchFPState) 449 mfc0 t1, COP_0_STATUS_REG # Save old SR 450 li t0, SR_COP_1_BIT # enable the coprocessor 451 mtc0 t0, COP_0_STATUS_REG 452 ITLBNOPFIX 453 454 beq a0, zero, 1f # skip save if NULL pointer 455 nop 456/* 457 * First read out the status register to make sure that all FP operations 458 * have completed. 459 */ 460 lw a0, TD_PCB(a0) # get pointer to pcb for proc 461 cfc1 t0, FPC_CSR # stall til FP done 462 cfc1 t0, FPC_CSR # now get status 463 li t3, ~SR_COP_1_BIT 464 RESTORE_U_PCB_REG(t2, PS, a0) # get CPU status register 465 SAVE_U_PCB_FPSR(t0, FSR_NUM, a0) # save FP status 466 and t2, t2, t3 # clear COP_1 enable bit 467 SAVE_U_PCB_REG(t2, PS, a0) # save new status register 468/* 469 * Save the floating point registers. 470 */ 471 SAVE_U_PCB_FPREG($f0, F0_NUM, a0) 472 SAVE_U_PCB_FPREG($f1, F1_NUM, a0) 473 SAVE_U_PCB_FPREG($f2, F2_NUM, a0) 474 SAVE_U_PCB_FPREG($f3, F3_NUM, a0) 475 SAVE_U_PCB_FPREG($f4, F4_NUM, a0) 476 SAVE_U_PCB_FPREG($f5, F5_NUM, a0) 477 SAVE_U_PCB_FPREG($f6, F6_NUM, a0) 478 SAVE_U_PCB_FPREG($f7, F7_NUM, a0) 479 SAVE_U_PCB_FPREG($f8, F8_NUM, a0) 480 SAVE_U_PCB_FPREG($f9, F9_NUM, a0) 481 SAVE_U_PCB_FPREG($f10, F10_NUM, a0) 482 SAVE_U_PCB_FPREG($f11, F11_NUM, a0) 483 SAVE_U_PCB_FPREG($f12, F12_NUM, a0) 484 SAVE_U_PCB_FPREG($f13, F13_NUM, a0) 485 SAVE_U_PCB_FPREG($f14, F14_NUM, a0) 486 SAVE_U_PCB_FPREG($f15, F15_NUM, a0) 487 SAVE_U_PCB_FPREG($f16, F16_NUM, a0) 488 SAVE_U_PCB_FPREG($f17, F17_NUM, a0) 489 SAVE_U_PCB_FPREG($f18, F18_NUM, a0) 490 SAVE_U_PCB_FPREG($f19, F19_NUM, a0) 491 SAVE_U_PCB_FPREG($f20, F20_NUM, a0) 492 SAVE_U_PCB_FPREG($f21, F21_NUM, a0) 493 SAVE_U_PCB_FPREG($f22, F22_NUM, a0) 494 SAVE_U_PCB_FPREG($f23, F23_NUM, a0) 495 SAVE_U_PCB_FPREG($f24, F24_NUM, a0) 496 SAVE_U_PCB_FPREG($f25, F25_NUM, a0) 497 SAVE_U_PCB_FPREG($f26, F26_NUM, a0) 498 SAVE_U_PCB_FPREG($f27, F27_NUM, a0) 499 SAVE_U_PCB_FPREG($f28, F28_NUM, a0) 500 SAVE_U_PCB_FPREG($f29, F29_NUM, a0) 501 SAVE_U_PCB_FPREG($f30, F30_NUM, a0) 502 SAVE_U_PCB_FPREG($f31, F31_NUM, a0) 503 5041: 505/* 506 * Restore the floating point registers. 507 */ 508 RESTORE_U_PCB_FPSR(t0, FSR_NUM, a1) # get status register 509 RESTORE_U_PCB_FPREG($f0, F0_NUM, a1) 510 RESTORE_U_PCB_FPREG($f1, F1_NUM, a1) 511 RESTORE_U_PCB_FPREG($f2, F2_NUM, a1) 512 RESTORE_U_PCB_FPREG($f3, F3_NUM, a1) 513 RESTORE_U_PCB_FPREG($f4, F4_NUM, a1) 514 RESTORE_U_PCB_FPREG($f5, F5_NUM, a1) 515 RESTORE_U_PCB_FPREG($f6, F6_NUM, a1) 516 RESTORE_U_PCB_FPREG($f7, F7_NUM, a1) 517 RESTORE_U_PCB_FPREG($f8, F8_NUM, a1) 518 RESTORE_U_PCB_FPREG($f9, F9_NUM, a1) 519 RESTORE_U_PCB_FPREG($f10, F10_NUM, a1) 520 RESTORE_U_PCB_FPREG($f11, F11_NUM, a1) 521 RESTORE_U_PCB_FPREG($f12, F12_NUM, a1) 522 RESTORE_U_PCB_FPREG($f13, F13_NUM, a1) 523 RESTORE_U_PCB_FPREG($f14, F14_NUM, a1) 524 RESTORE_U_PCB_FPREG($f15, F15_NUM, a1) 525 RESTORE_U_PCB_FPREG($f16, F16_NUM, a1) 526 RESTORE_U_PCB_FPREG($f17, F17_NUM, a1) 527 RESTORE_U_PCB_FPREG($f18, F18_NUM, a1) 528 RESTORE_U_PCB_FPREG($f19, F19_NUM, a1) 529 RESTORE_U_PCB_FPREG($f20, F20_NUM, a1) 530 RESTORE_U_PCB_FPREG($f21, F21_NUM, a1) 531 RESTORE_U_PCB_FPREG($f22, F22_NUM, a1) 532 RESTORE_U_PCB_FPREG($f23, F23_NUM, a1) 533 RESTORE_U_PCB_FPREG($f24, F24_NUM, a1) 534 RESTORE_U_PCB_FPREG($f25, F25_NUM, a1) 535 RESTORE_U_PCB_FPREG($f26, F26_NUM, a1) 536 RESTORE_U_PCB_FPREG($f27, F27_NUM, a1) 537 RESTORE_U_PCB_FPREG($f28, F28_NUM, a1) 538 RESTORE_U_PCB_FPREG($f29, F29_NUM, a1) 539 RESTORE_U_PCB_FPREG($f30, F30_NUM, a1) 540 RESTORE_U_PCB_FPREG($f31, F31_NUM, a1) 541 542 and t0, t0, ~FPC_EXCEPTION_BITS 543 ctc1 t0, FPC_CSR 544 nop 545 546 mtc0 t1, COP_0_STATUS_REG # Restore the status register. 547 ITLBNOPFIX 548 j ra 549 nop 550END(MipsSwitchFPState) 551 552/*---------------------------------------------------------------------------- 553 * 554 * MipsSaveCurFPState -- 555 * 556 * Save the current floating point coprocessor state. 557 * 558 * MipsSaveCurFPState(td) 559 * struct thread *td; 560 * 561 * Results: 562 * None. 563 * 564 * Side effects: 565 * machFPCurProcPtr is cleared. 566 * 567 *---------------------------------------------------------------------------- 568 */ 569LEAF(MipsSaveCurFPState) 570 lw a0, TD_PCB(a0) # get pointer to pcb for thread 571 mfc0 t1, COP_0_STATUS_REG # Disable interrupts and 572 li t0, SR_COP_1_BIT # enable the coprocessor 573 mtc0 t0, COP_0_STATUS_REG 574 ITLBNOPFIX 575 GET_CPU_PCPU(a1) 576 sw zero, PC_FPCURTHREAD(a1) # indicate state has been saved 577/* 578 * First read out the status register to make sure that all FP operations 579 * have completed. 580 */ 581 RESTORE_U_PCB_REG(t2, PS, a0) # get CPU status register 582 li t3, ~SR_COP_1_BIT 583 and t2, t2, t3 # clear COP_1 enable bit 584 cfc1 t0, FPC_CSR # stall til FP done 585 cfc1 t0, FPC_CSR # now get status 586 SAVE_U_PCB_REG(t2, PS, a0) # save new status register 587 SAVE_U_PCB_FPSR(t0, FSR_NUM, a0) # save FP status 588/* 589 * Save the floating point registers. 590 */ 591 SAVE_U_PCB_FPREG($f0, F0_NUM, a0) 592 SAVE_U_PCB_FPREG($f1, F1_NUM, a0) 593 SAVE_U_PCB_FPREG($f2, F2_NUM, a0) 594 SAVE_U_PCB_FPREG($f3, F3_NUM, a0) 595 SAVE_U_PCB_FPREG($f4, F4_NUM, a0) 596 SAVE_U_PCB_FPREG($f5, F5_NUM, a0) 597 SAVE_U_PCB_FPREG($f6, F6_NUM, a0) 598 SAVE_U_PCB_FPREG($f7, F7_NUM, a0) 599 SAVE_U_PCB_FPREG($f8, F8_NUM, a0) 600 SAVE_U_PCB_FPREG($f9, F9_NUM, a0) 601 SAVE_U_PCB_FPREG($f10, F10_NUM, a0) 602 SAVE_U_PCB_FPREG($f11, F11_NUM, a0) 603 SAVE_U_PCB_FPREG($f12, F12_NUM, a0) 604 SAVE_U_PCB_FPREG($f13, F13_NUM, a0) 605 SAVE_U_PCB_FPREG($f14, F14_NUM, a0) 606 SAVE_U_PCB_FPREG($f15, F15_NUM, a0) 607 SAVE_U_PCB_FPREG($f16, F16_NUM, a0) 608 SAVE_U_PCB_FPREG($f17, F17_NUM, a0) 609 SAVE_U_PCB_FPREG($f18, F18_NUM, a0) 610 SAVE_U_PCB_FPREG($f19, F19_NUM, a0) 611 SAVE_U_PCB_FPREG($f20, F20_NUM, a0) 612 SAVE_U_PCB_FPREG($f21, F21_NUM, a0) 613 SAVE_U_PCB_FPREG($f22, F22_NUM, a0) 614 SAVE_U_PCB_FPREG($f23, F23_NUM, a0) 615 SAVE_U_PCB_FPREG($f24, F24_NUM, a0) 616 SAVE_U_PCB_FPREG($f25, F25_NUM, a0) 617 SAVE_U_PCB_FPREG($f26, F26_NUM, a0) 618 SAVE_U_PCB_FPREG($f27, F27_NUM, a0) 619 SAVE_U_PCB_FPREG($f28, F28_NUM, a0) 620 SAVE_U_PCB_FPREG($f29, F29_NUM, a0) 621 SAVE_U_PCB_FPREG($f30, F30_NUM, a0) 622 SAVE_U_PCB_FPREG($f31, F31_NUM, a0) 623 624 mtc0 t1, COP_0_STATUS_REG # Restore the status register. 625 ITLBNOPFIX 626 j ra 627 nop 628END(MipsSaveCurFPState) 629 630/* 631 * When starting init, call this to configure the process for user 632 * mode. This will be inherited by other processes. 633 */ 634LEAF_NOPROFILE(prepare_usermode) 635 j ra 636 nop 637END(prepare_usermode) 638 639 640/* 641 * This code is copied the user's stack for returning from signal handlers 642 * (see sendsig() and sigreturn()). We have to compute the address 643 * of the sigcontext struct for the sigreturn call. 644 */ 645 .globl _C_LABEL(sigcode) 646_C_LABEL(sigcode): 647 addu a0, sp, SIGF_UC # address of ucontext 648 li v0, SYS_sigreturn 649# sigreturn (ucp) 650 syscall 651 break 0 # just in case sigreturn fails 652 .globl _C_LABEL(esigcode) 653_C_LABEL(esigcode): 654 655 .data 656 .globl szsigcode 657szsigcode: 658 .long esigcode-sigcode 659 .text 660