|
|
1.1 ! root 1: /*- ! 2: * Copyright (c) 1985 The Regents of the University of California. ! 3: * All rights reserved. ! 4: * ! 5: * This code is derived from software contributed to Berkeley by ! 6: * Computer Consoles Inc. ! 7: * ! 8: * Redistribution and use in source and binary forms, with or without ! 9: * modification, are permitted provided that the following conditions ! 10: * are met: ! 11: * 1. Redistributions of source code must retain the above copyright ! 12: * notice, this list of conditions and the following disclaimer. ! 13: * 2. Redistributions in binary form must reproduce the above copyright ! 14: * notice, this list of conditions and the following disclaimer in the ! 15: * documentation and/or other materials provided with the distribution. ! 16: * 3. All advertising materials mentioning features or use of this software ! 17: * must display the following acknowledgement: ! 18: * This product includes software developed by the University of ! 19: * California, Berkeley and its contributors. ! 20: * 4. Neither the name of the University nor the names of its contributors ! 21: * may be used to endorse or promote products derived from this software ! 22: * without specific prior written permission. ! 23: * ! 24: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! 25: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 26: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 27: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! 28: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 29: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 30: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 31: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 32: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 33: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 34: * SUCH DAMAGE. ! 35: * ! 36: * @(#)fpe.c 7.1 (Berkeley) 12/6/90 ! 37: */ ! 38: ! 39: #include "../include/psl.h" ! 40: #include "../include/reg.h" ! 41: #include "../include/pte.h" ! 42: #include "../include/mtpr.h" ! 43: #include "../math/Kfp.h" ! 44: ! 45: #include "sys/param.h" ! 46: #include "sys/systm.h" ! 47: #include "sys/user.h" ! 48: #include "sys/proc.h" ! 49: #include "sys/seg.h" ! 50: #include "sys/acct.h" ! 51: #include "sys/kernel.h" ! 52: ! 53: /* ! 54: * Floating point emulation support. ! 55: */ ! 56: extern float Kcvtlf(), Kaddf(), Ksubf(), Kmulf(), Kdivf(); ! 57: extern double Kcvtld(), Kaddd(), Ksubd(), Kmuld(), Kdivd(); ! 58: extern float Ksinf(), Kcosf(), Katanf(), Klogf(), Ksqrtf(), Kexpf(); ! 59: ! 60: #define OP(dop) ((dop) &~ 01) /* precision-less version of opcode */ ! 61: #define isdouble(op) ((op) & 01) /* is opcode double or float */ ! 62: ! 63: struct fpetab { ! 64: int fpe_op; /* base opcode emulating */ ! 65: float (*fpe_ffunc)(); /* float version of op */ ! 66: double (*fpe_dfunc)(); /* double version of op */ ! 67: } fpetab[] = { ! 68: { OP(CVLD), Kcvtlf, Kcvtld }, ! 69: { OP(ADDD), Kaddf, Kaddd }, ! 70: { OP(SUBD), Ksubf, Ksubd }, ! 71: { OP(MULD), Kmulf, Kmuld }, ! 72: { OP(DIVD), Kdivf, Kdivd }, ! 73: { SINF, Ksinf, 0 }, ! 74: { COSF, Kcosf, 0 }, ! 75: { ATANF, Katanf, 0 }, ! 76: { LOGF, Klogf, 0 }, ! 77: { SQRTF, Ksqrtf, 0 }, ! 78: { EXPF, Kexpf, 0 }, ! 79: }; ! 80: #define NFPETAB (sizeof (fpetab) / sizeof (fpetab[0])) ! 81: ! 82: /* ! 83: * Emulate the FP opcode. Update psl as necessary. ! 84: * If OK, set opcode to 0, else to the FP exception #. ! 85: * Not all parameter longwords are relevant, depends on opcode. ! 86: * ! 87: * The entry mask is set by locore.s so ALL registers are saved. ! 88: * This enables FP opcodes to change user registers on return. ! 89: */ ! 90: /* WARNING!!!! THIS CODE MUST NOT PRODUCE ANY FLOATING POINT EXCEPTIONS */ ! 91: /*ARGSUSED*/ ! 92: fpemulate(hfsreg, acc_most, acc_least, dbl, op_most, op_least, opcode, pc, psl) ! 93: { ! 94: int r0, r1; /* must reserve space */ ! 95: register int *locr0 = ((int *)&psl)-PS; ! 96: register struct fpetab *fp; ! 97: int hfs = 0; /* returned data about exceptions */ ! 98: int type; /* opcode type, FLOAT or DOUBLE */ ! 99: union { float ff; int fi; } f_res; ! 100: union { double dd; int di[2]; } d_res; ! 101: int error = 0; ! 102: ! 103: #ifdef lint ! 104: r0 = 0; r0 = r0; r1 = 0; r1 = r1; ! 105: #endif ! 106: type = isdouble(opcode) ? DOUBLE : FLOAT; ! 107: for (fp = fpetab; fp < &fpetab[NFPETAB]; fp++) ! 108: if ((opcode & 0xfe) == fp->fpe_op) ! 109: break; ! 110: if (type == DOUBLE) { ! 111: if (fp->fpe_dfunc == 0) ! 112: fp = &fpetab[NFPETAB]; ! 113: else ! 114: locr0[PS] &= ~PSL_DBL; ! 115: } ! 116: if (fp >= &fpetab[NFPETAB]) { ! 117: opcode = DIV0_EXC; /* generate SIGILL - XXX */ ! 118: return (0); ! 119: } ! 120: switch (type) { ! 121: ! 122: case DOUBLE: ! 123: d_res.dd = (*fp->fpe_dfunc)(acc_most, acc_least, op_most, ! 124: op_least, &hfs); ! 125: if (d_res.di[0] == 0 && d_res.di[1] == 0) ! 126: locr0[PS] |= PSL_Z; ! 127: if (d_res.di[0] < 0) ! 128: locr0[PS] |= PSL_N; ! 129: break; ! 130: ! 131: case FLOAT: ! 132: f_res.ff = (*fp->fpe_ffunc)(acc_most, acc_least, op_most, ! 133: op_least, &hfs); ! 134: if (f_res.fi == 0) ! 135: locr0[PS] |= PSL_Z; ! 136: if (f_res.fi == 0) ! 137: locr0[PS] |= PSL_N; ! 138: break; ! 139: } ! 140: if (hfs & HFS_OVF) { ! 141: locr0[PS] |= PSL_V; /* turn on overflow bit */ ! 142: #ifdef notdef ! 143: if (locr0[PS] & PSL_IV) { /* overflow enabled? */ ! 144: #endif ! 145: opcode = OVF_EXC; ! 146: return ((hfs & HFS_DOM) ? EDOM : ERANGE); ! 147: #ifdef notdef ! 148: } ! 149: #endif ! 150: } else if (hfs & HFS_UNDF) { ! 151: if (locr0[PS] & PSL_FU) { /* underflow enabled? */ ! 152: opcode = UNDF_EXC; ! 153: return ((hfs & HFS_DOM) ? EDOM : ERANGE); ! 154: } ! 155: } else if (hfs & HFS_DIVZ) { ! 156: opcode = DIV0_EXC; ! 157: return (0); ! 158: } else if (hfs & HFS_DOM) ! 159: error = EDOM; ! 160: else if (hfs & HFS_RANGE) ! 161: error = ERANGE; ! 162: switch (type) { ! 163: ! 164: case DOUBLE: ! 165: if (hfs & (HFS_OVF|HFS_UNDF)) { ! 166: d_res.dd = 0.0; ! 167: locr0[PS] |= PSL_Z; ! 168: } ! 169: mvtodacc(d_res.di[0], d_res.di[1], &acc_most); ! 170: break; ! 171: ! 172: case FLOAT: ! 173: if (hfs & (HFS_OVF|HFS_UNDF)) { ! 174: f_res.ff = 0.0; ! 175: locr0[PS] |= PSL_Z; ! 176: } ! 177: mvtofacc(f_res.ff, &acc_most); ! 178: break; ! 179: } ! 180: opcode = 0; ! 181: return (error); ! 182: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.