home *** CD-ROM | disk | FTP | other *** search
- /*-
- * Copyright (c) 1985 The Regents of the University of California.
- * All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Computer Consoles Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)fpe.c 7.1 (Berkeley) 12/6/90
- */
-
- #include "../include/psl.h"
- #include "../include/reg.h"
- #include "../include/pte.h"
- #include "../include/mtpr.h"
- #include "../math/Kfp.h"
-
- #include "sys/param.h"
- #include "sys/systm.h"
- #include "sys/user.h"
- #include "sys/proc.h"
- #include "sys/seg.h"
- #include "sys/acct.h"
- #include "sys/kernel.h"
-
- /*
- * Floating point emulation support.
- */
- extern float Kcvtlf(), Kaddf(), Ksubf(), Kmulf(), Kdivf();
- extern double Kcvtld(), Kaddd(), Ksubd(), Kmuld(), Kdivd();
- extern float Ksinf(), Kcosf(), Katanf(), Klogf(), Ksqrtf(), Kexpf();
-
- #define OP(dop) ((dop) &~ 01) /* precision-less version of opcode */
- #define isdouble(op) ((op) & 01) /* is opcode double or float */
-
- struct fpetab {
- int fpe_op; /* base opcode emulating */
- float (*fpe_ffunc)(); /* float version of op */
- double (*fpe_dfunc)(); /* double version of op */
- } fpetab[] = {
- { OP(CVLD), Kcvtlf, Kcvtld },
- { OP(ADDD), Kaddf, Kaddd },
- { OP(SUBD), Ksubf, Ksubd },
- { OP(MULD), Kmulf, Kmuld },
- { OP(DIVD), Kdivf, Kdivd },
- { SINF, Ksinf, 0 },
- { COSF, Kcosf, 0 },
- { ATANF, Katanf, 0 },
- { LOGF, Klogf, 0 },
- { SQRTF, Ksqrtf, 0 },
- { EXPF, Kexpf, 0 },
- };
- #define NFPETAB (sizeof (fpetab) / sizeof (fpetab[0]))
-
- /*
- * Emulate the FP opcode. Update psl as necessary.
- * If OK, set opcode to 0, else to the FP exception #.
- * Not all parameter longwords are relevant, depends on opcode.
- *
- * The entry mask is set by locore.s so ALL registers are saved.
- * This enables FP opcodes to change user registers on return.
- */
- /* WARNING!!!! THIS CODE MUST NOT PRODUCE ANY FLOATING POINT EXCEPTIONS */
- /*ARGSUSED*/
- fpemulate(hfsreg, acc_most, acc_least, dbl, op_most, op_least, opcode, pc, psl)
- {
- int r0, r1; /* must reserve space */
- register int *locr0 = ((int *)&psl)-PS;
- register struct fpetab *fp;
- int hfs = 0; /* returned data about exceptions */
- int type; /* opcode type, FLOAT or DOUBLE */
- union { float ff; int fi; } f_res;
- union { double dd; int di[2]; } d_res;
- int error = 0;
-
- #ifdef lint
- r0 = 0; r0 = r0; r1 = 0; r1 = r1;
- #endif
- type = isdouble(opcode) ? DOUBLE : FLOAT;
- for (fp = fpetab; fp < &fpetab[NFPETAB]; fp++)
- if ((opcode & 0xfe) == fp->fpe_op)
- break;
- if (type == DOUBLE) {
- if (fp->fpe_dfunc == 0)
- fp = &fpetab[NFPETAB];
- else
- locr0[PS] &= ~PSL_DBL;
- }
- if (fp >= &fpetab[NFPETAB]) {
- opcode = DIV0_EXC; /* generate SIGILL - XXX */
- return (0);
- }
- switch (type) {
-
- case DOUBLE:
- d_res.dd = (*fp->fpe_dfunc)(acc_most, acc_least, op_most,
- op_least, &hfs);
- if (d_res.di[0] == 0 && d_res.di[1] == 0)
- locr0[PS] |= PSL_Z;
- if (d_res.di[0] < 0)
- locr0[PS] |= PSL_N;
- break;
-
- case FLOAT:
- f_res.ff = (*fp->fpe_ffunc)(acc_most, acc_least, op_most,
- op_least, &hfs);
- if (f_res.fi == 0)
- locr0[PS] |= PSL_Z;
- if (f_res.fi == 0)
- locr0[PS] |= PSL_N;
- break;
- }
- if (hfs & HFS_OVF) {
- locr0[PS] |= PSL_V; /* turn on overflow bit */
- #ifdef notdef
- if (locr0[PS] & PSL_IV) { /* overflow enabled? */
- #endif
- opcode = OVF_EXC;
- return ((hfs & HFS_DOM) ? EDOM : ERANGE);
- #ifdef notdef
- }
- #endif
- } else if (hfs & HFS_UNDF) {
- if (locr0[PS] & PSL_FU) { /* underflow enabled? */
- opcode = UNDF_EXC;
- return ((hfs & HFS_DOM) ? EDOM : ERANGE);
- }
- } else if (hfs & HFS_DIVZ) {
- opcode = DIV0_EXC;
- return (0);
- } else if (hfs & HFS_DOM)
- error = EDOM;
- else if (hfs & HFS_RANGE)
- error = ERANGE;
- switch (type) {
-
- case DOUBLE:
- if (hfs & (HFS_OVF|HFS_UNDF)) {
- d_res.dd = 0.0;
- locr0[PS] |= PSL_Z;
- }
- mvtodacc(d_res.di[0], d_res.di[1], &acc_most);
- break;
-
- case FLOAT:
- if (hfs & (HFS_OVF|HFS_UNDF)) {
- f_res.ff = 0.0;
- locr0[PS] |= PSL_Z;
- }
- mvtofacc(f_res.ff, &acc_most);
- break;
- }
- opcode = 0;
- return (error);
- }
-