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 */ 73LEAF(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 141END(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 */ 150LEAF(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 1691: 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 175END(savectx) 176 177NESTED(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 188END(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 */ 197NESTED(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 225getpc: 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 264userland_cop2: 265 266 PTR_L a0, TD_UCOP2(a3) 267 beqz a0, no_cop2_context 268 nop 269 270do_cop2_save: 271 jal octeon_cop2_save 272 nop 273 274no_cop2_context: 275 move a3, s3 276 move a2, s2 277 move a1, s1 278 move a0, s0 279 280cop2_untouched: 281#endif 282 283 PTR_S a2, TD_LOCK(a3) # Switchout td_lock 284 285mips_sw1: 286#if defined(SMP) && defined(SCHED_ULE) 287 PTR_LA t0, _C_LABEL(blocked_lock) 288blocked_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 337entry0set: 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 */ 350sw2: 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 387cpu_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 396END(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 */ 416LEAF(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 4801: 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 527END(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 */ 546LEAF(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 565END(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 */ 584LEAF(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 652END(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 671szsigcode: 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 688szsigcode32: 689 .long esigcode32-sigcode32 690 .text 691#endif 692