|
|
1.1 root 1: /* $NetBSD: fpu_subr.c,v 1.12 2013/04/21 02:50:48 isaki Exp $ */
2:
3: /*
4: * Copyright (c) 1992, 1993
5: * The Regents of the University of California. All rights reserved.
6: *
7: * This software was developed by the Computer Systems Engineering group
8: * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
9: * contributed to Berkeley.
10: *
11: * All advertising materials mentioning features or use of this software
12: * must display the following acknowledgement:
13: * This product includes software developed by the University of
14: * California, Lawrence Berkeley Laboratory.
15: *
16: * Redistribution and use in source and binary forms, with or without
17: * modification, are permitted provided that the following conditions
18: * are met:
19: * 1. Redistributions of source code must retain the above copyright
20: * notice, this list of conditions and the following disclaimer.
21: * 2. Redistributions in binary form must reproduce the above copyright
22: * notice, this list of conditions and the following disclaimer in the
23: * documentation and/or other materials provided with the distribution.
24: * 3. Neither the name of the University nor the names of its contributors
25: * may be used to endorse or promote products derived from this software
26: * without specific prior written permission.
27: *
28: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
29: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
32: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38: * SUCH DAMAGE.
39: *
40: * @(#)fpu_subr.c 8.1 (Berkeley) 6/11/93
41: */
42:
43: /*
44: * FPU subroutines.
45: */
46:
47: #include "fpu_emulate.h"
48:
49: /*
50: * m68020 or later has a BFFFO instruction, therefore use it.
51: * Otherwise, use C version.
52: */
53: static inline int
54: bfffo(uint32_t src)
55: {
56: int offset;
57: #if defined(__m68k__) && !defined(__mc68010__)
58: __asm volatile("bfffo %1{#0:#32},%0" : "=d"(offset) : "g"(src));
59: #else
60: int width = 32;
61: for (offset = 0; width-- > 0 && (int)src >= 0; src <<= 1) {
62: offset++;
63: }
64: #endif
65: return offset;
66: }
67:
68: /*
69: * Shift the given number right rsh bits. Any bits that `fall off' will get
70: * shoved into the sticky field; we return the resulting sticky. Note that
71: * shifting NaNs is legal (this will never shift all bits out); a NaN's
72: * sticky field is ignored anyway.
73: */
74: int
75: fpu_shr(struct fpn *fp, int rsh)
76: {
77: uint32_t m0, m1, m2, s;
78: int lsh;
79:
80: #ifdef DIAGNOSTIC
81: if (rsh < 0 || (fp->fp_class != FPC_NUM && !ISNAN(fp)))
82: panic("fpu_rightshift 1");
83: #endif
84:
85: m0 = fp->fp_mant[0];
86: m1 = fp->fp_mant[1];
87: m2 = fp->fp_mant[2];
88:
89: /* If shifting all the bits out, take a shortcut. */
90: if (rsh >= FP_NMANT) {
91: #ifdef DIAGNOSTIC
92: if ((m0 | m1 | m2) == 0)
93: panic("fpu_rightshift 2");
94: #endif
95: fp->fp_mant[0] = 0;
96: fp->fp_mant[1] = 0;
97: fp->fp_mant[2] = 0;
98: #ifdef notdef
99: if ((m0 | m1 | m2) == 0)
100: fp->fp_class = FPC_ZERO;
101: else
102: #endif
103: fp->fp_sticky = 1;
104: return (1);
105: }
106:
107: /* Squish out full words. */
108: s = fp->fp_sticky;
109: if (rsh >= 32 * 2) {
110: s |= m2 | m1;
111: m2 = m0, m1 = 0, m0 = 0;
112: } else if (rsh >= 32) {
113: s |= m2;
114: m2 = m1, m1 = m0, m0 = 0;
115: }
116:
117: /* Handle any remaining partial word. */
118: if ((rsh &= 31) != 0) {
119: lsh = 32 - rsh;
120: s |= m2 << lsh;
121: m2 = (m2 >> rsh) | (m1 << lsh);
122: m1 = (m1 >> rsh) | (m0 << lsh);
123: m0 >>= rsh;
124: }
125: fp->fp_mant[0] = m0;
126: fp->fp_mant[1] = m1;
127: fp->fp_mant[2] = m2;
128: fp->fp_sticky = s;
129: return (s);
130: }
131:
132: /*
133: * Force a number to be normal, i.e., make its fraction have all zero
134: * bits before FP_1, then FP_1, then all 1 bits. This is used for denorms
135: * and (sometimes) for intermediate results.
136: *
137: * Internally, this may use a `supernormal' -- a number whose fp_mant
138: * is greater than or equal to 2.0 -- so as a side effect you can hand it
139: * a supernormal and it will fix it (provided fp->fp_mant[2] == 0).
140: */
141: void
142: fpu_norm(struct fpn *fp)
143: {
144: uint32_t m0, m1, m2, sup, nrm;
145: int lsh, rsh, exp;
146:
147: exp = fp->fp_exp;
148: m0 = fp->fp_mant[0];
149: m1 = fp->fp_mant[1];
150: m2 = fp->fp_mant[2];
151:
152: /* Handle severe subnormals with 32-bit moves. */
153: if (m0 == 0) {
154: if (m1) {
155: m0 = m1;
156: m1 = m2;
157: m2 = 0;
158: exp -= 32;
159: } else if (m2) {
160: m0 = m2;
161: m1 = 0;
162: m2 = 0;
163: exp -= 2 * 32;
164: } else {
165: fp->fp_class = FPC_ZERO;
166: return;
167: }
168: }
169:
170: /* Now fix any supernormal or remaining subnormal. */
171: nrm = FP_1;
172: sup = nrm << 1;
173: if (m0 >= sup) {
174: /*
175: * We have a supernormal number. We need to shift it right.
176: * We may assume m2==0.
177: */
178: rsh = bfffo(m0);
179: rsh = 31 - rsh - FP_LG;
180: exp += rsh;
181: lsh = 32 - rsh;
182: m2 = m1 << lsh;
183: m1 = (m1 >> rsh) | (m0 << lsh);
184: m0 = (m0 >> rsh);
185: } else if (m0 < nrm) {
186: /*
187: * We have a regular denorm (a subnormal number), and need
188: * to shift it left.
189: */
190: lsh = bfffo(m0);
191: lsh = FP_LG - 31 + lsh;
192: exp -= lsh;
193: rsh = 32 - lsh;
194: m0 = (m0 << lsh) | (m1 >> rsh);
195: m1 = (m1 << lsh) | (m2 >> rsh);
196: m2 <<= lsh;
197: }
198:
199: fp->fp_exp = exp;
200: fp->fp_mant[0] = m0;
201: fp->fp_mant[1] = m1;
202: fp->fp_mant[2] = m2;
203: }
204:
205: /*
206: * Concoct a `fresh' Quiet NaN per Appendix N.
207: * As a side effect, we set OPERR for the current exceptions.
208: */
209: struct fpn *
210: fpu_newnan(struct fpemu *fe)
211: {
212: struct fpn *fp;
213:
214: fe->fe_fpsr |= FPSR_OPERR;
215: fp = &fe->fe_f3;
216: fp->fp_class = FPC_QNAN;
217: fp->fp_sign = 0;
218: fp->fp_mant[0] = FP_2 - 1;
219: fp->fp_mant[1] = fp->fp_mant[2] = ~0;
220: return (fp);
221: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.