Annotation of 43BSDReno/sys/tahoemath/fpe.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.