[BACK]Return to lcore_float.S CVS log [TXT][DIR] Up to [local] / sys / arch / mips64 / mips64

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