Annotation of sys/arch/mips64/mips64/lcore_float.S, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: lcore_float.S,v 1.14 2007/07/16 20:23:09 miod Exp $ */
! 2:
! 3: /*
! 4: * Copyright (c) 2001-2003 Opsycon AB (www.opsycon.se / www.opsycon.com)
! 5: *
! 6: * Redistribution and use in source and binary forms, with or without
! 7: * modification, are permitted provided that the following conditions
! 8: * are met:
! 9: * 1. Redistributions of source code must retain the above copyright
! 10: * notice, this list of conditions and the following disclaimer.
! 11: * 2. Redistributions in binary form must reproduce the above copyright
! 12: * notice, this list of conditions and the following disclaimer in the
! 13: * documentation and/or other materials provided with the distribution.
! 14: *
! 15: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
! 16: * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
! 17: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 18: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
! 19: * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 20: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 21: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 22: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 23: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 24: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 25: * SUCH DAMAGE.
! 26: *
! 27: */
! 28: #include <sys/errno.h>
! 29: #include <sys/syscall.h>
! 30:
! 31: #include <machine/param.h>
! 32: #include <machine/psl.h>
! 33: #include <machine/asm.h>
! 34: #include <machine/cpu.h>
! 35: #include <machine/regnum.h>
! 36: #include <machine/cpustate.h>
! 37: #include <machine/pte.h>
! 38:
! 39: #include "assym.h"
! 40:
! 41: #define curproc (cpu_info_primary + CI_CURPROC)
! 42:
! 43: .set noreorder # Noreorder is default style!
! 44:
! 45: .set mips3
! 46:
! 47: /*----------------------------------------------------------------------------
! 48: *
! 49: * MipsSwitchFPState --
! 50: *
! 51: * Save the current state into 'from' and restore it from 'to'.
! 52: *
! 53: * MipsSwitchFPState(from, to)
! 54: * struct proc *from;
! 55: * struct user *to;
! 56: *
! 57: * Results:
! 58: * None.
! 59: *
! 60: * Side effects:
! 61: * None.
! 62: *
! 63: *----------------------------------------------------------------------------
! 64: */
! 65: LEAF(MipsSwitchFPState, 0)
! 66: mfc0 t1, COP_0_STATUS_REG # Save old SR
! 67: or t0, t1, SR_COP_1_BIT|SR_FR_32 # enable the coprocessor
! 68: mtc0 t0, COP_0_STATUS_REG
! 69: ITLBNOPFIX
! 70:
! 71: beq a0, zero, 1f # skip save if NULL pointer
! 72: nop
! 73: /*
! 74: * First read out the status register to make sure that all FP operations
! 75: * have completed.
! 76: */
! 77: PTR_L a0, P_ADDR(a0) # get pointer to pcb for proc
! 78: cfc1 t0, FPC_CSR # stall til FP done
! 79: cfc1 t0, FPC_CSR # now get status
! 80: li t3, ~SR_COP_1_BIT
! 81: REG_L t2, PCB_REGS+(PS * REGSZ)(a0) # get CPU status register
! 82: REG_S t0, PCB_FPREGS+(32 * REGSZ)(a0) # save FP status
! 83: and t2, t2, t3 # clear COP_1 enable bit
! 84: REG_S t2, PCB_REGS+(PS * REGSZ)(a0) # save new status register
! 85: /*
! 86: * Save the floating point registers.
! 87: */
! 88: sdc1 $f0, PCB_FPREGS+(0 * REGSZ)(a0)
! 89: sdc1 $f1, PCB_FPREGS+(1 * REGSZ)(a0)
! 90: sdc1 $f2, PCB_FPREGS+(2 * REGSZ)(a0)
! 91: sdc1 $f3, PCB_FPREGS+(3 * REGSZ)(a0)
! 92: sdc1 $f4, PCB_FPREGS+(4 * REGSZ)(a0)
! 93: sdc1 $f5, PCB_FPREGS+(5 * REGSZ)(a0)
! 94: sdc1 $f6, PCB_FPREGS+(6 * REGSZ)(a0)
! 95: sdc1 $f7, PCB_FPREGS+(7 * REGSZ)(a0)
! 96: sdc1 $f8, PCB_FPREGS+(8 * REGSZ)(a0)
! 97: sdc1 $f9, PCB_FPREGS+(9 * REGSZ)(a0)
! 98: sdc1 $f10, PCB_FPREGS+(10 * REGSZ)(a0)
! 99: sdc1 $f11, PCB_FPREGS+(11 * REGSZ)(a0)
! 100: sdc1 $f12, PCB_FPREGS+(12 * REGSZ)(a0)
! 101: sdc1 $f13, PCB_FPREGS+(13 * REGSZ)(a0)
! 102: sdc1 $f14, PCB_FPREGS+(14 * REGSZ)(a0)
! 103: sdc1 $f15, PCB_FPREGS+(15 * REGSZ)(a0)
! 104: sdc1 $f16, PCB_FPREGS+(16 * REGSZ)(a0)
! 105: sdc1 $f17, PCB_FPREGS+(17 * REGSZ)(a0)
! 106: sdc1 $f18, PCB_FPREGS+(18 * REGSZ)(a0)
! 107: sdc1 $f19, PCB_FPREGS+(19 * REGSZ)(a0)
! 108: sdc1 $f20, PCB_FPREGS+(20 * REGSZ)(a0)
! 109: sdc1 $f21, PCB_FPREGS+(21 * REGSZ)(a0)
! 110: sdc1 $f22, PCB_FPREGS+(22 * REGSZ)(a0)
! 111: sdc1 $f23, PCB_FPREGS+(23 * REGSZ)(a0)
! 112: sdc1 $f24, PCB_FPREGS+(24 * REGSZ)(a0)
! 113: sdc1 $f25, PCB_FPREGS+(25 * REGSZ)(a0)
! 114: sdc1 $f26, PCB_FPREGS+(26 * REGSZ)(a0)
! 115: sdc1 $f27, PCB_FPREGS+(27 * REGSZ)(a0)
! 116: sdc1 $f28, PCB_FPREGS+(28 * REGSZ)(a0)
! 117: sdc1 $f29, PCB_FPREGS+(29 * REGSZ)(a0)
! 118: sdc1 $f30, PCB_FPREGS+(30 * REGSZ)(a0)
! 119: sdc1 $f31, PCB_FPREGS+(31 * REGSZ)(a0)
! 120:
! 121: 1:
! 122: /*
! 123: * Restore the floating point registers.
! 124: */
! 125: REG_L t0, PCB_FPREGS+(32 * REGSZ)(a1) # get status register
! 126: ldc1 $f0, PCB_FPREGS+(0 * REGSZ)(a1)
! 127: ldc1 $f1, PCB_FPREGS+(1 * REGSZ)(a1)
! 128: ldc1 $f2, PCB_FPREGS+(2 * REGSZ)(a1)
! 129: ldc1 $f3, PCB_FPREGS+(3 * REGSZ)(a1)
! 130: ldc1 $f4, PCB_FPREGS+(4 * REGSZ)(a1)
! 131: ldc1 $f5, PCB_FPREGS+(5 * REGSZ)(a1)
! 132: ldc1 $f6, PCB_FPREGS+(6 * REGSZ)(a1)
! 133: ldc1 $f7, PCB_FPREGS+(7 * REGSZ)(a1)
! 134: ldc1 $f8, PCB_FPREGS+(8 * REGSZ)(a1)
! 135: ldc1 $f9, PCB_FPREGS+(9 * REGSZ)(a1)
! 136: ldc1 $f10, PCB_FPREGS+(10 * REGSZ)(a1)
! 137: ldc1 $f11, PCB_FPREGS+(11 * REGSZ)(a1)
! 138: ldc1 $f12, PCB_FPREGS+(12 * REGSZ)(a1)
! 139: ldc1 $f13, PCB_FPREGS+(13 * REGSZ)(a1)
! 140: ldc1 $f14, PCB_FPREGS+(14 * REGSZ)(a1)
! 141: ldc1 $f15, PCB_FPREGS+(15 * REGSZ)(a1)
! 142: ldc1 $f16, PCB_FPREGS+(16 * REGSZ)(a1)
! 143: ldc1 $f17, PCB_FPREGS+(17 * REGSZ)(a1)
! 144: ldc1 $f18, PCB_FPREGS+(18 * REGSZ)(a1)
! 145: ldc1 $f19, PCB_FPREGS+(19 * REGSZ)(a1)
! 146: ldc1 $f20, PCB_FPREGS+(20 * REGSZ)(a1)
! 147: ldc1 $f21, PCB_FPREGS+(21 * REGSZ)(a1)
! 148: ldc1 $f22, PCB_FPREGS+(22 * REGSZ)(a1)
! 149: ldc1 $f23, PCB_FPREGS+(23 * REGSZ)(a1)
! 150: ldc1 $f24, PCB_FPREGS+(24 * REGSZ)(a1)
! 151: ldc1 $f25, PCB_FPREGS+(25 * REGSZ)(a1)
! 152: ldc1 $f26, PCB_FPREGS+(26 * REGSZ)(a1)
! 153: ldc1 $f27, PCB_FPREGS+(27 * REGSZ)(a1)
! 154: ldc1 $f28, PCB_FPREGS+(28 * REGSZ)(a1)
! 155: ldc1 $f29, PCB_FPREGS+(29 * REGSZ)(a1)
! 156: ldc1 $f30, PCB_FPREGS+(30 * REGSZ)(a1)
! 157: ldc1 $f31, PCB_FPREGS+(31 * REGSZ)(a1)
! 158:
! 159: and t0, t0, ~FPC_EXCEPTION_BITS
! 160: ctc1 t0, FPC_CSR
! 161: nop
! 162:
! 163: mtc0 t1, COP_0_STATUS_REG # Restore the status register.
! 164: ITLBNOPFIX
! 165: j ra
! 166: nop
! 167: END(MipsSwitchFPState)
! 168:
! 169: LEAF(MipsSwitchFPState16, 0)
! 170: mfc0 t1, COP_0_STATUS_REG # Save old SR
! 171: or t0, t1, SR_COP_1_BIT # enable the coprocessor
! 172: mtc0 t0, COP_0_STATUS_REG
! 173: ITLBNOPFIX
! 174:
! 175: beq a0, zero, 1f # skip save if NULL pointer
! 176: nop
! 177: /*
! 178: * First read out the status register to make sure that all FP operations
! 179: * have completed.
! 180: */
! 181: PTR_L a0, P_ADDR(a0) # get pointer to pcb for proc
! 182: cfc1 t0, FPC_CSR # stall til FP done
! 183: cfc1 t0, FPC_CSR # now get status
! 184: li t3, ~SR_COP_1_BIT
! 185: REG_L t2, PCB_REGS+(PS * REGSZ)(a0) # get CPU status register
! 186: REG_S t0, PCB_FPREGS+(32 * REGSZ)(a0) # save FP status
! 187: and t2, t2, t3 # clear COP_1 enable bit
! 188: REG_S t2, PCB_REGS+(PS * REGSZ)(a0) # save new status register
! 189: /*
! 190: * Save the floating point registers.
! 191: */
! 192: swc1 $f0, PCB_FPREGS+(0 * REGSZ)(a0)
! 193: swc1 $f1, PCB_FPREGS+(1 * REGSZ)(a0)
! 194: swc1 $f2, PCB_FPREGS+(2 * REGSZ)(a0)
! 195: swc1 $f3, PCB_FPREGS+(3 * REGSZ)(a0)
! 196: swc1 $f4, PCB_FPREGS+(4 * REGSZ)(a0)
! 197: swc1 $f5, PCB_FPREGS+(5 * REGSZ)(a0)
! 198: swc1 $f6, PCB_FPREGS+(6 * REGSZ)(a0)
! 199: swc1 $f7, PCB_FPREGS+(7 * REGSZ)(a0)
! 200: swc1 $f8, PCB_FPREGS+(8 * REGSZ)(a0)
! 201: swc1 $f9, PCB_FPREGS+(9 * REGSZ)(a0)
! 202: swc1 $f10, PCB_FPREGS+(10 * REGSZ)(a0)
! 203: swc1 $f11, PCB_FPREGS+(11 * REGSZ)(a0)
! 204: swc1 $f12, PCB_FPREGS+(12 * REGSZ)(a0)
! 205: swc1 $f13, PCB_FPREGS+(13 * REGSZ)(a0)
! 206: swc1 $f14, PCB_FPREGS+(14 * REGSZ)(a0)
! 207: swc1 $f15, PCB_FPREGS+(15 * REGSZ)(a0)
! 208: swc1 $f16, PCB_FPREGS+(16 * REGSZ)(a0)
! 209: swc1 $f17, PCB_FPREGS+(17 * REGSZ)(a0)
! 210: swc1 $f18, PCB_FPREGS+(18 * REGSZ)(a0)
! 211: swc1 $f19, PCB_FPREGS+(19 * REGSZ)(a0)
! 212: swc1 $f20, PCB_FPREGS+(20 * REGSZ)(a0)
! 213: swc1 $f21, PCB_FPREGS+(21 * REGSZ)(a0)
! 214: swc1 $f22, PCB_FPREGS+(22 * REGSZ)(a0)
! 215: swc1 $f23, PCB_FPREGS+(23 * REGSZ)(a0)
! 216: swc1 $f24, PCB_FPREGS+(24 * REGSZ)(a0)
! 217: swc1 $f25, PCB_FPREGS+(25 * REGSZ)(a0)
! 218: swc1 $f26, PCB_FPREGS+(26 * REGSZ)(a0)
! 219: swc1 $f27, PCB_FPREGS+(27 * REGSZ)(a0)
! 220: swc1 $f28, PCB_FPREGS+(28 * REGSZ)(a0)
! 221: swc1 $f29, PCB_FPREGS+(29 * REGSZ)(a0)
! 222: swc1 $f30, PCB_FPREGS+(30 * REGSZ)(a0)
! 223: swc1 $f31, PCB_FPREGS+(31 * REGSZ)(a0)
! 224:
! 225: 1:
! 226: /*
! 227: * Restore the floating point registers.
! 228: */
! 229: REG_L t0, PCB_FPREGS+(32 * REGSZ)(a1) # get status register
! 230: lwc1 $f0, PCB_FPREGS+(0 * REGSZ)(a1)
! 231: lwc1 $f1, PCB_FPREGS+(1 * REGSZ)(a1)
! 232: lwc1 $f2, PCB_FPREGS+(2 * REGSZ)(a1)
! 233: lwc1 $f3, PCB_FPREGS+(3 * REGSZ)(a1)
! 234: lwc1 $f4, PCB_FPREGS+(4 * REGSZ)(a1)
! 235: lwc1 $f5, PCB_FPREGS+(5 * REGSZ)(a1)
! 236: lwc1 $f6, PCB_FPREGS+(6 * REGSZ)(a1)
! 237: lwc1 $f7, PCB_FPREGS+(7 * REGSZ)(a1)
! 238: lwc1 $f8, PCB_FPREGS+(8 * REGSZ)(a1)
! 239: lwc1 $f9, PCB_FPREGS+(9 * REGSZ)(a1)
! 240: lwc1 $f10, PCB_FPREGS+(10 * REGSZ)(a1)
! 241: lwc1 $f11, PCB_FPREGS+(11 * REGSZ)(a1)
! 242: lwc1 $f12, PCB_FPREGS+(12 * REGSZ)(a1)
! 243: lwc1 $f13, PCB_FPREGS+(13 * REGSZ)(a1)
! 244: lwc1 $f14, PCB_FPREGS+(14 * REGSZ)(a1)
! 245: lwc1 $f15, PCB_FPREGS+(15 * REGSZ)(a1)
! 246: lwc1 $f16, PCB_FPREGS+(16 * REGSZ)(a1)
! 247: lwc1 $f17, PCB_FPREGS+(17 * REGSZ)(a1)
! 248: lwc1 $f18, PCB_FPREGS+(18 * REGSZ)(a1)
! 249: lwc1 $f19, PCB_FPREGS+(19 * REGSZ)(a1)
! 250: lwc1 $f20, PCB_FPREGS+(20 * REGSZ)(a1)
! 251: lwc1 $f21, PCB_FPREGS+(21 * REGSZ)(a1)
! 252: lwc1 $f22, PCB_FPREGS+(22 * REGSZ)(a1)
! 253: lwc1 $f23, PCB_FPREGS+(23 * REGSZ)(a1)
! 254: lwc1 $f24, PCB_FPREGS+(24 * REGSZ)(a1)
! 255: lwc1 $f25, PCB_FPREGS+(25 * REGSZ)(a1)
! 256: lwc1 $f26, PCB_FPREGS+(26 * REGSZ)(a1)
! 257: lwc1 $f27, PCB_FPREGS+(27 * REGSZ)(a1)
! 258: lwc1 $f28, PCB_FPREGS+(28 * REGSZ)(a1)
! 259: lwc1 $f29, PCB_FPREGS+(29 * REGSZ)(a1)
! 260: lwc1 $f30, PCB_FPREGS+(30 * REGSZ)(a1)
! 261: lwc1 $f31, PCB_FPREGS+(31 * REGSZ)(a1)
! 262:
! 263: and t0, t0, ~FPC_EXCEPTION_BITS
! 264: ctc1 t0, FPC_CSR
! 265: nop
! 266:
! 267: mtc0 t1, COP_0_STATUS_REG # Restore the status register.
! 268: ITLBNOPFIX
! 269: j ra
! 270: nop
! 271: END(MipsSwitchFPState16)
! 272:
! 273: /*----------------------------------------------------------------------------
! 274: *
! 275: * MipsSaveCurFPState --
! 276: *
! 277: * Save the current floating point coprocessor state.
! 278: *
! 279: * MipsSaveCurFPState(p)
! 280: * struct proc *p;
! 281: *
! 282: * Results:
! 283: * None.
! 284: *
! 285: * Side effects:
! 286: * machFPCurProcPtr is cleared.
! 287: *
! 288: *----------------------------------------------------------------------------
! 289: */
! 290: LEAF(MipsSaveCurFPState, 0)
! 291: PTR_L a0, P_ADDR(a0) # get pointer to pcb for proc
! 292: mfc0 t1, COP_0_STATUS_REG # Disable interrupts and
! 293: or t0, t1, SR_COP_1_BIT|SR_FR_32 # enable the coprocessor
! 294: mtc0 t0, COP_0_STATUS_REG
! 295: ITLBNOPFIX
! 296: PTR_S zero, machFPCurProcPtr # indicate state has been saved
! 297: /*
! 298: * First read out the status register to make sure that all FP operations
! 299: * have completed.
! 300: */
! 301: REG_L t2, PCB_REGS+(PS * REGSZ)(a0) # get CPU status register
! 302: li t3, ~SR_COP_1_BIT
! 303: and t2, t2, t3 # clear COP_1 enable bit
! 304: cfc1 t0, FPC_CSR # stall til FP done
! 305: cfc1 t0, FPC_CSR # now get status
! 306: REG_S t2, PCB_REGS+(PS * REGSZ)(a0) # save new status register
! 307: REG_S t0, PCB_FPREGS+(32 * REGSZ)(a0) # save FP status
! 308: /*
! 309: * Save the floating point registers.
! 310: */
! 311: sdc1 $f0, PCB_FPREGS+(0 * REGSZ)(a0)
! 312: sdc1 $f1, PCB_FPREGS+(1 * REGSZ)(a0)
! 313: sdc1 $f2, PCB_FPREGS+(2 * REGSZ)(a0)
! 314: sdc1 $f3, PCB_FPREGS+(3 * REGSZ)(a0)
! 315: sdc1 $f4, PCB_FPREGS+(4 * REGSZ)(a0)
! 316: sdc1 $f5, PCB_FPREGS+(5 * REGSZ)(a0)
! 317: sdc1 $f6, PCB_FPREGS+(6 * REGSZ)(a0)
! 318: sdc1 $f7, PCB_FPREGS+(7 * REGSZ)(a0)
! 319: sdc1 $f8, PCB_FPREGS+(8 * REGSZ)(a0)
! 320: sdc1 $f9, PCB_FPREGS+(9 * REGSZ)(a0)
! 321: sdc1 $f10, PCB_FPREGS+(10 * REGSZ)(a0)
! 322: sdc1 $f11, PCB_FPREGS+(11 * REGSZ)(a0)
! 323: sdc1 $f12, PCB_FPREGS+(12 * REGSZ)(a0)
! 324: sdc1 $f13, PCB_FPREGS+(13 * REGSZ)(a0)
! 325: sdc1 $f14, PCB_FPREGS+(14 * REGSZ)(a0)
! 326: sdc1 $f15, PCB_FPREGS+(15 * REGSZ)(a0)
! 327: sdc1 $f16, PCB_FPREGS+(16 * REGSZ)(a0)
! 328: sdc1 $f17, PCB_FPREGS+(17 * REGSZ)(a0)
! 329: sdc1 $f18, PCB_FPREGS+(18 * REGSZ)(a0)
! 330: sdc1 $f19, PCB_FPREGS+(19 * REGSZ)(a0)
! 331: sdc1 $f20, PCB_FPREGS+(20 * REGSZ)(a0)
! 332: sdc1 $f21, PCB_FPREGS+(21 * REGSZ)(a0)
! 333: sdc1 $f22, PCB_FPREGS+(22 * REGSZ)(a0)
! 334: sdc1 $f23, PCB_FPREGS+(23 * REGSZ)(a0)
! 335: sdc1 $f24, PCB_FPREGS+(24 * REGSZ)(a0)
! 336: sdc1 $f25, PCB_FPREGS+(25 * REGSZ)(a0)
! 337: sdc1 $f26, PCB_FPREGS+(26 * REGSZ)(a0)
! 338: sdc1 $f27, PCB_FPREGS+(27 * REGSZ)(a0)
! 339: sdc1 $f28, PCB_FPREGS+(28 * REGSZ)(a0)
! 340: sdc1 $f29, PCB_FPREGS+(29 * REGSZ)(a0)
! 341: sdc1 $f30, PCB_FPREGS+(30 * REGSZ)(a0)
! 342: sdc1 $f31, PCB_FPREGS+(31 * REGSZ)(a0)
! 343:
! 344: mtc0 t1, COP_0_STATUS_REG # Restore the status register.
! 345: ITLBNOPFIX
! 346: j ra
! 347: nop
! 348: END(MipsSaveCurFPState)
! 349:
! 350: LEAF(MipsSaveCurFPState16, 0)
! 351: PTR_L a0, P_ADDR(a0) # get pointer to pcb for proc
! 352: mfc0 t1, COP_0_STATUS_REG # Disable interrupts and
! 353: or t0, t1, SR_COP_1_BIT # enable the coprocessor
! 354: mtc0 t0, COP_0_STATUS_REG
! 355: ITLBNOPFIX
! 356: PTR_S zero, machFPCurProcPtr # indicate state has been saved
! 357: /*
! 358: * First read out the status register to make sure that all FP operations
! 359: * have completed.
! 360: */
! 361: REG_L t2, PCB_REGS+(PS * REGSZ)(a0) # get CPU status register
! 362: li t3, ~SR_COP_1_BIT
! 363: and t2, t2, t3 # clear COP_1 enable bit
! 364: cfc1 t0, FPC_CSR # stall til FP done
! 365: cfc1 t0, FPC_CSR # now get status
! 366: REG_S t2, PCB_REGS+(PS * REGSZ)(a0) # save new status register
! 367: REG_S t0, PCB_FPREGS+(32 * REGSZ)(a0) # save FP status
! 368: /*
! 369: * Save the floating point registers.
! 370: */
! 371: swc1 $f0, PCB_FPREGS+(0 * REGSZ)(a0)
! 372: swc1 $f1, PCB_FPREGS+(1 * REGSZ)(a0)
! 373: swc1 $f2, PCB_FPREGS+(2 * REGSZ)(a0)
! 374: swc1 $f3, PCB_FPREGS+(3 * REGSZ)(a0)
! 375: swc1 $f4, PCB_FPREGS+(4 * REGSZ)(a0)
! 376: swc1 $f5, PCB_FPREGS+(5 * REGSZ)(a0)
! 377: swc1 $f6, PCB_FPREGS+(6 * REGSZ)(a0)
! 378: swc1 $f7, PCB_FPREGS+(7 * REGSZ)(a0)
! 379: swc1 $f8, PCB_FPREGS+(8 * REGSZ)(a0)
! 380: swc1 $f9, PCB_FPREGS+(9 * REGSZ)(a0)
! 381: swc1 $f10, PCB_FPREGS+(10 * REGSZ)(a0)
! 382: swc1 $f11, PCB_FPREGS+(11 * REGSZ)(a0)
! 383: swc1 $f12, PCB_FPREGS+(12 * REGSZ)(a0)
! 384: swc1 $f13, PCB_FPREGS+(13 * REGSZ)(a0)
! 385: swc1 $f14, PCB_FPREGS+(14 * REGSZ)(a0)
! 386: swc1 $f15, PCB_FPREGS+(15 * REGSZ)(a0)
! 387: swc1 $f16, PCB_FPREGS+(16 * REGSZ)(a0)
! 388: swc1 $f17, PCB_FPREGS+(17 * REGSZ)(a0)
! 389: swc1 $f18, PCB_FPREGS+(18 * REGSZ)(a0)
! 390: swc1 $f19, PCB_FPREGS+(19 * REGSZ)(a0)
! 391: swc1 $f20, PCB_FPREGS+(20 * REGSZ)(a0)
! 392: swc1 $f21, PCB_FPREGS+(21 * REGSZ)(a0)
! 393: swc1 $f22, PCB_FPREGS+(22 * REGSZ)(a0)
! 394: swc1 $f23, PCB_FPREGS+(23 * REGSZ)(a0)
! 395: swc1 $f24, PCB_FPREGS+(24 * REGSZ)(a0)
! 396: swc1 $f25, PCB_FPREGS+(25 * REGSZ)(a0)
! 397: swc1 $f26, PCB_FPREGS+(26 * REGSZ)(a0)
! 398: swc1 $f27, PCB_FPREGS+(27 * REGSZ)(a0)
! 399: swc1 $f28, PCB_FPREGS+(28 * REGSZ)(a0)
! 400: swc1 $f29, PCB_FPREGS+(29 * REGSZ)(a0)
! 401: swc1 $f30, PCB_FPREGS+(30 * REGSZ)(a0)
! 402: swc1 $f31, PCB_FPREGS+(31 * REGSZ)(a0)
! 403:
! 404: mtc0 t1, COP_0_STATUS_REG # Restore the status register.
! 405: ITLBNOPFIX
! 406: j ra
! 407: nop
! 408: END(MipsSaveCurFPState16)
! 409:
! 410: /*----------------------------------------------------------------------------
! 411: *
! 412: * MipsFPTrap --
! 413: *
! 414: * Handle a floating point Trap.
! 415: *
! 416: * MipsFPTrap(statusReg, causeReg, pc)
! 417: * unsigned statusReg;
! 418: * unsigned causeReg;
! 419: * unsigned pc;
! 420: *
! 421: * Results:
! 422: * None.
! 423: *
! 424: * Side effects:
! 425: * None.
! 426: *
! 427: *----------------------------------------------------------------------------
! 428: */
! 429: NON_LEAF(MipsFPTrap, FRAMESZ(CF_SZ), ra)
! 430: PTR_SUBU sp, sp, FRAMESZ(CF_SZ)
! 431: mfc0 t0, COP_0_STATUS_REG
! 432: PTR_S ra, CF_RA_OFFS(sp)
! 433: .mask 0x80000000, (CF_RA_OFFS - FRAMESZ(CF_SZ))
! 434:
! 435: PTR_S a2, 2*REGSZ(sp)
! 436: PTR_S a3, 3*REGSZ(sp)
! 437: or t1, t0, SR_COP_1_BIT
! 438: mtc0 t1, COP_0_STATUS_REG
! 439: ITLBNOPFIX
! 440: cfc1 t1, FPC_CSR # stall til FP done
! 441: cfc1 t1, FPC_CSR # now get status
! 442: nop
! 443: sll t2, t1, (31-17) # unimplemented operation?
! 444: bgez t2, 3f # no, normal trap
! 445: nop
! 446: /*
! 447: * We got an unimplemented operation trap so fetch the instruction,
! 448: * compute the next PC and emulate the instruction.
! 449: */
! 450: bgez a1, 1f # Check the branch delay bit.
! 451: nop
! 452: /*
! 453: * The instruction is in the branch delay slot so the branch will have to
! 454: * be emulated to get the resulting PC.
! 455: */
! 456: PTR_L a0, curprocpaddr # first arg is ptr to CPU regs
! 457: move a1, a2 # second arg is instruction PC
! 458: move a2, t1 # third arg is the FP CSR
! 459: jal MipsEmulateBranch # compute PC after branch
! 460: move a3, zero # fourth arg is FALSE
! 461: /*
! 462: * Now load the floating-point instruction in the branch delay slot
! 463: * to be emulated.
! 464: */
! 465: PTR_L a2, 2*REGSZ(sp) # restore EXC pc
! 466: b 2f
! 467: lw a0, 4(a2) # a0 = coproc instruction
! 468: /*
! 469: * This is not in the branch delay slot so calculate the resulting
! 470: * PC (epc + 4) into v0 and continue to MipsEmulateFP().
! 471: */
! 472: 1:
! 473: lw a0, 0(a2) # a0 = coproc instruction
! 474: PTR_ADDU v0, a2, 4 # v0 = next pc
! 475: 2:
! 476: PTR_L a3, curprocpaddr # first arg is ptr to CPU regs
! 477: PTR_S v0, PCB_REGS+(PC * REGSZ)(a3) # save new pc
! 478: /*
! 479: * Check to see if the instruction to be emulated is a floating-point
! 480: * instruction.
! 481: */
! 482: srl a3, a0, OPCODE_SHIFT
! 483: beq a3, OPCODE_C1, 5f # this should never fail
! 484: nop
! 485: /*
! 486: * Send a floating point exception signal to the current process.
! 487: */
! 488: 3:
! 489: cfc1 a2, FPC_CSR # code = FP exceptions
! 490: PTR_L a0, curproc # get current process
! 491: PTR_L a4, 3*REGSZ(sp)
! 492: and v0, a2, FPC_EXCEPTION_INEXACT
! 493: bnez v0, 4f
! 494: li a3, 6
! 495: and v0, a2, FPC_EXCEPTION_UNDERFLOW
! 496: bnez v0, 4f
! 497: li a3, 5
! 498: and v0, a2, FPC_EXCEPTION_OVERFLOW
! 499: bnez v0, 4f
! 500: li a3, 4
! 501: and v0, a2, FPC_EXCEPTION_DIV0
! 502: bnez v0, 4f
! 503: li a3, 3
! 504: li a3, 7 # XXX FPE_FLTINV
! 505: 4:
! 506: ctc1 zero, FPC_CSR # Clear exceptions
! 507: jal trapsignal
! 508: li a1, SIGFPE
! 509: b FPReturn
! 510: nop
! 511:
! 512: /*
! 513: * Finally, we can call MipsEmulateFP() where a0 is the instruction to emulate.
! 514: */
! 515: 5:
! 516: jal MipsEmulateFP
! 517: nop
! 518:
! 519: bnez v0, 3b # Emulation failed.
! 520: nop
! 521:
! 522: /*
! 523: * Turn off the floating point coprocessor and return.
! 524: */
! 525: FPReturn:
! 526: mfc0 t0, COP_0_STATUS_REG
! 527: PTR_L ra, CF_RA_OFFS(sp)
! 528: and t0, t0, ~SR_COP_1_BIT
! 529: mtc0 t0, COP_0_STATUS_REG
! 530: ITLBNOPFIX
! 531: j ra
! 532: PTR_ADDU sp, sp, FRAMESZ(CF_SZ)
! 533: END(MipsFPTrap)
! 534:
! 535: /*----------------------------------------------------------------------------
! 536: *
! 537: * cp1_get_prid
! 538: *
! 539: * Get the floating point co-processor id.
! 540: *
! 541: * cp1_get_prid(void)
! 542: *
! 543: * Results:
! 544: * FPC_ID
! 545: *
! 546: * Side effects:
! 547: * None.
! 548: *
! 549: *----------------------------------------------------------------------------
! 550: */
! 551: LEAF(cp1_get_prid, 0)
! 552: mfc0 v1, COP_0_STATUS_REG
! 553: li a0, SR_COP_1_BIT
! 554: or v1, a0
! 555: mtc0 v1, COP_0_STATUS_REG
! 556: ITLBNOPFIX
! 557: cfc1 v0, FPC_ID
! 558: xor v1, a0
! 559: mtc0 v1, COP_0_STATUS_REG
! 560: ITLBNOPFIX
! 561: jr ra
! 562: nop
! 563: END(cp1_get_prid)
! 564:
CVSweb