|
|
1.1 ! root 1: /* fpe.c 1.3 90/06/21 */ ! 2: ! 3: #include "../tahoe/psl.h" ! 4: #include "../tahoe/reg.h" ! 5: #include "../tahoe/pte.h" ! 6: #include "../tahoe/mtpr.h" ! 7: #include "../tahoemath/Kfp.h" ! 8: ! 9: #include "param.h" ! 10: #include "systm.h" ! 11: #include "user.h" ! 12: #include "proc.h" ! 13: #include "seg.h" ! 14: #include "acct.h" ! 15: #include "kernel.h" ! 16: ! 17: /* ! 18: * Floating point emulation support. ! 19: */ ! 20: extern float Kcvtlf(), Kaddf(), Ksubf(), Kmulf(), Kdivf(); ! 21: extern double Kcvtld(), Kaddd(), Ksubd(), Kmuld(), Kdivd(); ! 22: extern float Ksinf(), Kcosf(), Katanf(), Klogf(), Ksqrtf(), Kexpf(); ! 23: ! 24: #define OP(dop) ((dop) &~ 01) /* precision-less version of opcode */ ! 25: #define isdouble(op) ((op) & 01) /* is opcode double or float */ ! 26: ! 27: struct fpetab { ! 28: int fpe_op; /* base opcode emulating */ ! 29: float (*fpe_ffunc)(); /* float version of op */ ! 30: double (*fpe_dfunc)(); /* double version of op */ ! 31: } fpetab[] = { ! 32: { OP(CVLD), Kcvtlf, Kcvtld }, ! 33: { OP(ADDD), Kaddf, Kaddd }, ! 34: { OP(SUBD), Ksubf, Ksubd }, ! 35: { OP(MULD), Kmulf, Kmuld }, ! 36: { OP(DIVD), Kdivf, Kdivd }, ! 37: { SINF, Ksinf, 0 }, ! 38: { COSF, Kcosf, 0 }, ! 39: { ATANF, Katanf, 0 }, ! 40: { LOGF, Klogf, 0 }, ! 41: { SQRTF, Ksqrtf, 0 }, ! 42: { EXPF, Kexpf, 0 }, ! 43: }; ! 44: #define NFPETAB (sizeof (fpetab) / sizeof (fpetab[0])) ! 45: ! 46: /* ! 47: * Emulate the FP opcode. Update psl as necessary. ! 48: * If OK, set opcode to 0, else to the FP exception #. ! 49: * Not all parameter longwords are relevant, depends on opcode. ! 50: * ! 51: * The entry mask is set by locore.s so ALL registers are saved. ! 52: * This enables FP opcodes to change user registers on return. ! 53: */ ! 54: /* WARNING!!!! THIS CODE MUST NOT PRODUCE ANY FLOATING POINT EXCEPTIONS */ ! 55: /*ARGSUSED*/ ! 56: fpemulate(hfsreg, acc_most, acc_least, dbl, op_most, op_least, opcode, pc, psl) ! 57: { ! 58: int r0, r1; /* must reserve space */ ! 59: register int *locr0 = ((int *)&psl)-PS; ! 60: register struct fpetab *fp; ! 61: int hfs = 0; /* returned data about exceptions */ ! 62: int type; /* opcode type, FLOAT or DOUBLE */ ! 63: union { float ff; int fi; } f_res; ! 64: union { double dd; int di[2]; } d_res; ! 65: int error = 0; ! 66: ! 67: #ifdef lint ! 68: r0 = 0; r0 = r0; r1 = 0; r1 = r1; ! 69: #endif ! 70: type = isdouble(opcode) ? DOUBLE : FLOAT; ! 71: for (fp = fpetab; fp < &fpetab[NFPETAB]; fp++) ! 72: if ((opcode & 0xfe) == fp->fpe_op) ! 73: break; ! 74: if (type == DOUBLE) { ! 75: if (fp->fpe_dfunc == 0) ! 76: fp = &fpetab[NFPETAB]; ! 77: else ! 78: locr0[PS] &= ~PSL_DBL; ! 79: } ! 80: if (fp >= &fpetab[NFPETAB]) { ! 81: opcode = DIV0_EXC; /* generate SIGILL - XXX */ ! 82: return (0); ! 83: } ! 84: switch (type) { ! 85: ! 86: case DOUBLE: ! 87: d_res.dd = (*fp->fpe_dfunc)(acc_most, acc_least, op_most, ! 88: op_least, &hfs); ! 89: if (d_res.di[0] == 0 && d_res.di[1] == 0) ! 90: locr0[PS] |= PSL_Z; ! 91: if (d_res.di[0] < 0) ! 92: locr0[PS] |= PSL_N; ! 93: break; ! 94: ! 95: case FLOAT: ! 96: f_res.ff = (*fp->fpe_ffunc)(acc_most, acc_least, op_most, ! 97: op_least, &hfs); ! 98: if (f_res.fi == 0) ! 99: locr0[PS] |= PSL_Z; ! 100: if (f_res.fi == 0) ! 101: locr0[PS] |= PSL_N; ! 102: break; ! 103: } ! 104: if (hfs & HFS_OVF) { ! 105: locr0[PS] |= PSL_V; /* turn on overflow bit */ ! 106: #ifdef notdef ! 107: if (locr0[PS] & PSL_IV) { /* overflow enabled? */ ! 108: #endif ! 109: opcode = OVF_EXC; ! 110: return ((hfs & HFS_DOM) ? EDOM : ERANGE); ! 111: #ifdef notdef ! 112: } ! 113: #endif ! 114: } else if (hfs & HFS_UNDF) { ! 115: if (locr0[PS] & PSL_FU) { /* underflow enabled? */ ! 116: opcode = UNDF_EXC; ! 117: return ((hfs & HFS_DOM) ? EDOM : ERANGE); ! 118: } ! 119: } else if (hfs & HFS_DIVZ) { ! 120: opcode = DIV0_EXC; ! 121: return (0); ! 122: } else if (hfs & HFS_DOM) ! 123: error = EDOM; ! 124: else if (hfs & HFS_RANGE) ! 125: error = ERANGE; ! 126: switch (type) { ! 127: ! 128: case DOUBLE: ! 129: if (hfs & (HFS_OVF|HFS_UNDF)) { ! 130: d_res.dd = 0.0; ! 131: locr0[PS] |= PSL_Z; ! 132: } ! 133: mvtodacc(d_res.di[0], d_res.di[1], &acc_most); ! 134: break; ! 135: ! 136: case FLOAT: ! 137: if (hfs & (HFS_OVF|HFS_UNDF)) { ! 138: f_res.ff = 0.0; ! 139: locr0[PS] |= PSL_Z; ! 140: } ! 141: mvtofacc(f_res.ff, &acc_most); ! 142: break; ! 143: } ! 144: opcode = 0; ! 145: return (error); ! 146: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.