xref: /original-bsd/sys/sparc/fpu/fpu_explode.c (revision 80bc2993)
1 /*
2  * Copyright (c) 1992 The Regents of the University of California.
3  * 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  * %sccs.include.redist.c%
10  *
11  *	@(#)fpu_explode.c	7.1 (Berkeley) 07/13/92
12  *
13  * from: $Header: fpu_explode.c,v 1.2 92/06/17 05:41:32 torek Exp $
14  */
15 
16 /*
17  * FPU subroutines: `explode' the machine's `packed binary' format numbers
18  * into our internal format.
19  */
20 
21 #include "sys/types.h"
22 
23 #include "machine/ieee.h"
24 #include "machine/instr.h"
25 #include "machine/reg.h"
26 
27 #include "fpu_arith.h"
28 #include "fpu_emu.h"
29 
30 /*
31  * N.B.: in all of the following, we assume the FP format is
32  *
33  *	---------------------------
34  *	| s | exponent | fraction |
35  *	---------------------------
36  *
37  * (which represents -1**s * 1.fraction * 2**exponent), so that the
38  * sign bit is way at the top (bit 31), the exponent is next, and
39  * then the remaining bits mark the fraction.  A zero exponent means
40  * zero or denormalized (0.fraction rather than 1.fraction), and the
41  * maximum possible exponent, 2bias+1, signals inf (fraction==0) or NaN.
42  *
43  * Since the sign bit is always the topmost bit---this holds even for
44  * integers---we set that outside all the *tof functions.  Each function
45  * returns the class code for the new number (but note that we use
46  * FPC_QNAN for all NaNs; fpu_explode will fix this if appropriate).
47  */
48 
49 /*
50  * int -> fpn.
51  */
52 int
53 fpu_itof(fp, i)
54 	register struct fpn *fp;
55 	register u_int i;
56 {
57 
58 	if (i == 0)
59 		return (FPC_ZERO);
60 	/*
61 	 * The value FP_1 represents 2^FP_LG, so set the exponent
62 	 * there and let normalization fix it up.  Convert negative
63 	 * numbers to sign-and-magnitude.  Note that this relies on
64 	 * fpu_norm()'s handling of `supernormals'; see fpu_subr.c.
65 	 */
66 	fp->fp_exp = FP_LG;
67 	fp->fp_mant[0] = (int)i < 0 ? -i : i;
68 	fp->fp_mant[1] = 0;
69 	fp->fp_mant[2] = 0;
70 	fp->fp_mant[3] = 0;
71 	fpu_norm(fp);
72 	return (FPC_NUM);
73 }
74 
75 #define	mask(nbits) ((1 << (nbits)) - 1)
76 
77 /*
78  * All external floating formats convert to internal in the same manner,
79  * as defined here.  Note that only normals get an implied 1.0 inserted.
80  */
81 #define	FP_TOF(exp, expbias, allfrac, f0, f1, f2, f3) \
82 	if (exp == 0) { \
83 		if (allfrac == 0) \
84 			return (FPC_ZERO); \
85 		fp->fp_exp = 1 - expbias; \
86 		fp->fp_mant[0] = f0; \
87 		fp->fp_mant[1] = f1; \
88 		fp->fp_mant[2] = f2; \
89 		fp->fp_mant[3] = f3; \
90 		fpu_norm(fp); \
91 		return (FPC_NUM); \
92 	} \
93 	if (exp == (2 * expbias + 1)) { \
94 		if (allfrac == 0) \
95 			return (FPC_INF); \
96 		fp->fp_mant[0] = f0; \
97 		fp->fp_mant[1] = f1; \
98 		fp->fp_mant[2] = f2; \
99 		fp->fp_mant[3] = f3; \
100 		return (FPC_QNAN); \
101 	} \
102 	fp->fp_exp = exp - expbias; \
103 	fp->fp_mant[0] = FP_1 | f0; \
104 	fp->fp_mant[1] = f1; \
105 	fp->fp_mant[2] = f2; \
106 	fp->fp_mant[3] = f3; \
107 	return (FPC_NUM)
108 
109 /*
110  * 32-bit single precision -> fpn.
111  * We assume a single occupies at most (64-FP_LG) bits in the internal
112  * format: i.e., needs at most fp_mant[0] and fp_mant[1].
113  */
114 int
115 fpu_stof(fp, i)
116 	register struct fpn *fp;
117 	register u_int i;
118 {
119 	register int exp;
120 	register u_int frac, f0, f1;
121 #define SNG_SHIFT (SNG_FRACBITS - FP_LG)
122 
123 	exp = (i >> (32 - 1 - SNG_EXPBITS)) & mask(SNG_EXPBITS);
124 	frac = i & mask(SNG_FRACBITS);
125 	f0 = frac >> SNG_SHIFT;
126 	f1 = frac << (32 - SNG_SHIFT);
127 	FP_TOF(exp, SNG_EXP_BIAS, frac, f0, f1, 0, 0);
128 }
129 
130 /*
131  * 64-bit double -> fpn.
132  * We assume this uses at most (96-FP_LG) bits.
133  */
134 int
135 fpu_dtof(fp, i, j)
136 	register struct fpn *fp;
137 	register u_int i, j;
138 {
139 	register int exp;
140 	register u_int frac, f0, f1, f2;
141 #define DBL_SHIFT (DBL_FRACBITS - 32 - FP_LG)
142 
143 	exp = (i >> (32 - 1 - DBL_EXPBITS)) & mask(DBL_EXPBITS);
144 	frac = i & mask(DBL_FRACBITS - 32);
145 	f0 = frac >> DBL_SHIFT;
146 	f1 = (frac << (32 - DBL_SHIFT)) | (j >> DBL_SHIFT);
147 	f2 = j << (32 - DBL_SHIFT);
148 	frac |= j;
149 	FP_TOF(exp, DBL_EXP_BIAS, frac, f0, f1, f2, 0);
150 }
151 
152 /*
153  * 128-bit extended -> fpn.
154  */
155 int
156 fpu_xtof(fp, i, j, k, l)
157 	register struct fpn *fp;
158 	register u_int i, j, k, l;
159 {
160 	register int exp;
161 	register u_int frac, f0, f1, f2, f3;
162 #define EXT_SHIFT (-(EXT_FRACBITS - 3 * 32 - FP_LG))	/* left shift! */
163 
164 	/*
165 	 * Note that ext and fpn `line up', hence no shifting needed.
166 	 */
167 	exp = (i >> (32 - 1 - EXT_EXPBITS)) & mask(EXT_EXPBITS);
168 	frac = i & mask(EXT_FRACBITS - 3 * 32);
169 	f0 = (frac << EXT_SHIFT) | (j >> (32 - EXT_SHIFT));
170 	f1 = (j << EXT_SHIFT) | (k >> (32 - EXT_SHIFT));
171 	f2 = (k << EXT_SHIFT) | (l >> (32 - EXT_SHIFT));
172 	f3 = l << EXT_SHIFT;
173 	frac |= j | k | l;
174 	FP_TOF(exp, EXT_EXP_BIAS, frac, f0, f1, f2, f3);
175 }
176 
177 /*
178  * Explode the contents of a register / regpair / regquad.
179  * If the input is a signalling NaN, an NV (invalid) exception
180  * will be set.  (Note that nothing but NV can occur until ALU
181  * operations are performed.)
182  */
183 void
184 fpu_explode(fe, fp, type, reg)
185 	register struct fpemu *fe;
186 	register struct fpn *fp;
187 	int type, reg;
188 {
189 	register u_int s, *space;
190 
191 	space = &fe->fe_fpstate->fs_regs[reg];
192 	s = space[0];
193 	fp->fp_sign = s >> 31;
194 	fp->fp_sticky = 0;
195 	switch (type) {
196 
197 	case FTYPE_INT:
198 		s = fpu_itof(fp, s);
199 		break;
200 
201 	case FTYPE_SNG:
202 		s = fpu_stof(fp, s);
203 		break;
204 
205 	case FTYPE_DBL:
206 		s = fpu_dtof(fp, s, space[1]);
207 		break;
208 
209 	case FTYPE_EXT:
210 		s = fpu_xtof(fp, s, space[1], space[2], space[3]);
211 		break;
212 
213 	default:
214 		panic("fpu_explode");
215 	}
216 	if (s == FPC_QNAN && (fp->fp_mant[0] & FP_QUIETBIT) == 0) {
217 		/*
218 		 * Input is a signalling NaN.  All operations that return
219 		 * an input NaN operand put it through a ``NaN conversion'',
220 		 * which basically just means ``turn on the quiet bit''.
221 		 * We do this here so that all NaNs internally look quiet
222 		 * (we can tell signalling ones by their class).
223 		 */
224 		fp->fp_mant[0] |= FP_QUIETBIT;
225 		fe->fe_cx = FSR_NV;	/* assert invalid operand */
226 		s = FPC_SNAN;
227 	}
228 	fp->fp_class = s;
229 }
230