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