|
|
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.