xref: /netbsd-src/sys/arch/sparc/fpu/fpu_explode.c (revision d9158b13b5dfe46201430699a3f7a235ecf28df3)
1 /*
2  * Copyright (c) 1992, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * This software was developed by the Computer Systems Engineering group
6  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
7  * contributed to Berkeley.
8  *
9  * All advertising materials mentioning features or use of this software
10  * must display the following acknowledgement:
11  *	This product includes software developed by the University of
12  *	California, Lawrence Berkeley Laboratory.
13  *
14  * Redistribution and use in source and binary forms, with or without
15  * modification, are permitted provided that the following conditions
16  * are met:
17  * 1. Redistributions of source code must retain the above copyright
18  *    notice, this list of conditions and the following disclaimer.
19  * 2. Redistributions in binary form must reproduce the above copyright
20  *    notice, this list of conditions and the following disclaimer in the
21  *    documentation and/or other materials provided with the distribution.
22  * 3. All advertising materials mentioning features or use of this software
23  *    must display the following acknowledgement:
24  *	This product includes software developed by the University of
25  *	California, Berkeley and its contributors.
26  * 4. Neither the name of the University nor the names of its contributors
27  *    may be used to endorse or promote products derived from this software
28  *    without specific prior written permission.
29  *
30  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
31  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
32  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
34  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
35  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
36  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
37  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
38  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
39  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
40  * SUCH DAMAGE.
41  *
42  *	@(#)fpu_explode.c	8.1 (Berkeley) 6/11/93
43  *
44  * from: Header: fpu_explode.c,v 1.3 92/11/26 01:39:48 torek Exp
45  * $Id: fpu_explode.c,v 1.1 1993/10/02 10:22:57 deraadt Exp $
46  */
47 
48 /*
49  * FPU subroutines: `explode' the machine's `packed binary' format numbers
50  * into our internal format.
51  */
52 
53 #include <sys/types.h>
54 
55 #include <machine/ieee.h>
56 #include <machine/instr.h>
57 #include <machine/reg.h>
58 
59 #include <sparc/fpu/fpu_arith.h>
60 #include <sparc/fpu/fpu_emu.h>
61 
62 /*
63  * N.B.: in all of the following, we assume the FP format is
64  *
65  *	---------------------------
66  *	| s | exponent | fraction |
67  *	---------------------------
68  *
69  * (which represents -1**s * 1.fraction * 2**exponent), so that the
70  * sign bit is way at the top (bit 31), the exponent is next, and
71  * then the remaining bits mark the fraction.  A zero exponent means
72  * zero or denormalized (0.fraction rather than 1.fraction), and the
73  * maximum possible exponent, 2bias+1, signals inf (fraction==0) or NaN.
74  *
75  * Since the sign bit is always the topmost bit---this holds even for
76  * integers---we set that outside all the *tof functions.  Each function
77  * returns the class code for the new number (but note that we use
78  * FPC_QNAN for all NaNs; fpu_explode will fix this if appropriate).
79  */
80 
81 /*
82  * int -> fpn.
83  */
84 int
85 fpu_itof(fp, i)
86 	register struct fpn *fp;
87 	register u_int i;
88 {
89 
90 	if (i == 0)
91 		return (FPC_ZERO);
92 	/*
93 	 * The value FP_1 represents 2^FP_LG, so set the exponent
94 	 * there and let normalization fix it up.  Convert negative
95 	 * numbers to sign-and-magnitude.  Note that this relies on
96 	 * fpu_norm()'s handling of `supernormals'; see fpu_subr.c.
97 	 */
98 	fp->fp_exp = FP_LG;
99 	fp->fp_mant[0] = (int)i < 0 ? -i : i;
100 	fp->fp_mant[1] = 0;
101 	fp->fp_mant[2] = 0;
102 	fp->fp_mant[3] = 0;
103 	fpu_norm(fp);
104 	return (FPC_NUM);
105 }
106 
107 #define	mask(nbits) ((1 << (nbits)) - 1)
108 
109 /*
110  * All external floating formats convert to internal in the same manner,
111  * as defined here.  Note that only normals get an implied 1.0 inserted.
112  */
113 #define	FP_TOF(exp, expbias, allfrac, f0, f1, f2, f3) \
114 	if (exp == 0) { \
115 		if (allfrac == 0) \
116 			return (FPC_ZERO); \
117 		fp->fp_exp = 1 - expbias; \
118 		fp->fp_mant[0] = f0; \
119 		fp->fp_mant[1] = f1; \
120 		fp->fp_mant[2] = f2; \
121 		fp->fp_mant[3] = f3; \
122 		fpu_norm(fp); \
123 		return (FPC_NUM); \
124 	} \
125 	if (exp == (2 * expbias + 1)) { \
126 		if (allfrac == 0) \
127 			return (FPC_INF); \
128 		fp->fp_mant[0] = f0; \
129 		fp->fp_mant[1] = f1; \
130 		fp->fp_mant[2] = f2; \
131 		fp->fp_mant[3] = f3; \
132 		return (FPC_QNAN); \
133 	} \
134 	fp->fp_exp = exp - expbias; \
135 	fp->fp_mant[0] = FP_1 | f0; \
136 	fp->fp_mant[1] = f1; \
137 	fp->fp_mant[2] = f2; \
138 	fp->fp_mant[3] = f3; \
139 	return (FPC_NUM)
140 
141 /*
142  * 32-bit single precision -> fpn.
143  * We assume a single occupies at most (64-FP_LG) bits in the internal
144  * format: i.e., needs at most fp_mant[0] and fp_mant[1].
145  */
146 int
147 fpu_stof(fp, i)
148 	register struct fpn *fp;
149 	register u_int i;
150 {
151 	register int exp;
152 	register u_int frac, f0, f1;
153 #define SNG_SHIFT (SNG_FRACBITS - FP_LG)
154 
155 	exp = (i >> (32 - 1 - SNG_EXPBITS)) & mask(SNG_EXPBITS);
156 	frac = i & mask(SNG_FRACBITS);
157 	f0 = frac >> SNG_SHIFT;
158 	f1 = frac << (32 - SNG_SHIFT);
159 	FP_TOF(exp, SNG_EXP_BIAS, frac, f0, f1, 0, 0);
160 }
161 
162 /*
163  * 64-bit double -> fpn.
164  * We assume this uses at most (96-FP_LG) bits.
165  */
166 int
167 fpu_dtof(fp, i, j)
168 	register struct fpn *fp;
169 	register u_int i, j;
170 {
171 	register int exp;
172 	register u_int frac, f0, f1, f2;
173 #define DBL_SHIFT (DBL_FRACBITS - 32 - FP_LG)
174 
175 	exp = (i >> (32 - 1 - DBL_EXPBITS)) & mask(DBL_EXPBITS);
176 	frac = i & mask(DBL_FRACBITS - 32);
177 	f0 = frac >> DBL_SHIFT;
178 	f1 = (frac << (32 - DBL_SHIFT)) | (j >> DBL_SHIFT);
179 	f2 = j << (32 - DBL_SHIFT);
180 	frac |= j;
181 	FP_TOF(exp, DBL_EXP_BIAS, frac, f0, f1, f2, 0);
182 }
183 
184 /*
185  * 128-bit extended -> fpn.
186  */
187 int
188 fpu_xtof(fp, i, j, k, l)
189 	register struct fpn *fp;
190 	register u_int i, j, k, l;
191 {
192 	register int exp;
193 	register u_int frac, f0, f1, f2, f3;
194 #define EXT_SHIFT (-(EXT_FRACBITS - 3 * 32 - FP_LG))	/* left shift! */
195 
196 	/*
197 	 * Note that ext and fpn `line up', hence no shifting needed.
198 	 */
199 	exp = (i >> (32 - 1 - EXT_EXPBITS)) & mask(EXT_EXPBITS);
200 	frac = i & mask(EXT_FRACBITS - 3 * 32);
201 	f0 = (frac << EXT_SHIFT) | (j >> (32 - EXT_SHIFT));
202 	f1 = (j << EXT_SHIFT) | (k >> (32 - EXT_SHIFT));
203 	f2 = (k << EXT_SHIFT) | (l >> (32 - EXT_SHIFT));
204 	f3 = l << EXT_SHIFT;
205 	frac |= j | k | l;
206 	FP_TOF(exp, EXT_EXP_BIAS, frac, f0, f1, f2, f3);
207 }
208 
209 /*
210  * Explode the contents of a register / regpair / regquad.
211  * If the input is a signalling NaN, an NV (invalid) exception
212  * will be set.  (Note that nothing but NV can occur until ALU
213  * operations are performed.)
214  */
215 void
216 fpu_explode(fe, fp, type, reg)
217 	register struct fpemu *fe;
218 	register struct fpn *fp;
219 	int type, reg;
220 {
221 	register u_int s, *space;
222 
223 	space = &fe->fe_fpstate->fs_regs[reg];
224 	s = space[0];
225 	fp->fp_sign = s >> 31;
226 	fp->fp_sticky = 0;
227 	switch (type) {
228 
229 	case FTYPE_INT:
230 		s = fpu_itof(fp, s);
231 		break;
232 
233 	case FTYPE_SNG:
234 		s = fpu_stof(fp, s);
235 		break;
236 
237 	case FTYPE_DBL:
238 		s = fpu_dtof(fp, s, space[1]);
239 		break;
240 
241 	case FTYPE_EXT:
242 		s = fpu_xtof(fp, s, space[1], space[2], space[3]);
243 		break;
244 
245 	default:
246 		panic("fpu_explode");
247 	}
248 	if (s == FPC_QNAN && (fp->fp_mant[0] & FP_QUIETBIT) == 0) {
249 		/*
250 		 * Input is a signalling NaN.  All operations that return
251 		 * an input NaN operand put it through a ``NaN conversion'',
252 		 * which basically just means ``turn on the quiet bit''.
253 		 * We do this here so that all NaNs internally look quiet
254 		 * (we can tell signalling ones by their class).
255 		 */
256 		fp->fp_mant[0] |= FP_QUIETBIT;
257 		fe->fe_cx = FSR_NV;	/* assert invalid operand */
258 		s = FPC_SNAN;
259 	}
260 	fp->fp_class = s;
261 }
262