xref: /titanic_51/usr/src/lib/libbc/libc/gen/common/_unpack_dble.c (revision 5d54f3d8999eac1762fe0a8c7177d20f1f201fae)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 1988 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include "base_conversion.h"
30 
31 /* Normalize a number.  Does not affect zeros, infs, or NaNs. */
32 void
33 _fp_normalize(unpacked *pu)
34 {
35 	int             i;
36 	short unsigned  nlzwords, nlzbits;
37 	long unsigned   t;
38 
39 	if ((*pu).fpclass == fp_normal) {
40 		for (nlzwords = 0; (pu->significand[nlzwords] == 0) && (nlzwords < UNPACKED_SIZE); nlzwords++);
41 		if (nlzwords >= UNPACKED_SIZE) {
42 			(*pu).fpclass = fp_zero;
43 			return;
44 		}
45 		if (nlzwords > 0) {
46 			for (i = 0; i < UNPACKED_SIZE - nlzwords; i++)
47 				pu->significand[i] = pu->significand[i + nlzwords];
48 			for (; i < UNPACKED_SIZE; i++)
49 				pu->significand[i] = 0;
50 			pu->exponent -= 32 * nlzwords;
51 		}
52 		for (; pu->significand[UNPACKED_SIZE - 1 - nlzwords] == 0; nlzwords++);
53 		/* nlzwords is now the count of trailing zero words. */
54 
55 		nlzbits = 0;
56 		t = pu->significand[0];
57 		/* TESTS to determine normalize count.	 */
58 
59 #define SHIFTMACRO(n) if (t <= (((unsigned long) 0xffffffff) >> n)) { t = t<<n ; nlzbits += n ; }
60 		SHIFTMACRO(16);
61 		SHIFTMACRO(8);
62 		SHIFTMACRO(4);
63 		SHIFTMACRO(2);
64 		SHIFTMACRO(1);
65 		pu->exponent -= nlzbits;
66 		if (nlzbits >= 1) {	/* small shift */
67 			unsigned long   high, low, shiftout = 0;
68 			for (i = UNPACKED_SIZE - 1 - nlzwords; i >= 0; i--) {
69 				high = pu->significand[i] << nlzbits;
70 				low = pu->significand[i] >> (32 - nlzbits);
71 				pu->significand[i] = shiftout | high;
72 				shiftout = low;
73 			}
74 		}
75 	}
76 }
77 
78 /* Set the exception bit in the current exception register. */
79 void
80 _fp_set_exception(enum fp_exception_type ex)
81 {
82 	_fp_current_exceptions |= 1 << (int) ex;
83 }
84 
85 enum fp_class_type
86 _class_double(double *x)
87 {
88 	double_equivalence kluge;
89 
90 	kluge.x = *x;
91 	if (kluge.f.msw.exponent == 0) {	/* 0 or sub */
92 		if ((kluge.f.msw.significand == 0) && (kluge.f.significand2 == 0))
93 			return fp_zero;
94 		else
95 			return fp_subnormal;
96 	} else if (kluge.f.msw.exponent == 0x7ff) {	/* inf or nan */
97 		if ((kluge.f.msw.significand == 0) && (kluge.f.significand2 == 0))
98 			return fp_infinity;
99 		else if (kluge.f.msw.significand >= 0x40000)
100 			return fp_quiet;
101 		else
102 			return fp_signaling;
103 	} else
104 		return fp_normal;
105 }
106 
107 
108 /* Left shift significand by 11 <= n <= 16 bits.  Affect all classes.	 */
109 void
110 _fp_leftshift(unpacked *pu, unsigned n)
111 {
112 	int             i;
113 
114 	unsigned long   high, low, shiftout = 0;
115 	for (i = UNPACKED_SIZE - 1; i >= 0; i--) {
116 		high = pu->significand[i] << n;
117 		low = pu->significand[i] >> (32 - n);
118 		pu->significand[i] = shiftout | high;
119 		shiftout = low;
120 	}
121 }
122 
123 
124 void
125 _unpack_double(unpacked *pu, double *px)
126 {
127 	double_equivalence x;
128 	int             i;
129 
130 	x.x = *px;
131 	(*pu).sign = x.f.msw.sign;
132 	pu->significand[1] = x.f.significand2;
133 	for (i = 2; i < UNPACKED_SIZE; i++)
134 		pu->significand[i] = 0;
135 	if (x.f.msw.exponent == 0) {	/* zero or sub */
136 		if ((x.f.msw.significand == 0) && (x.f.significand2 == 0)) {	/* zero */
137 			pu->fpclass = fp_zero;
138 			return;
139 		} else {	/* subnormal */
140 			pu->fpclass = fp_normal;
141 			pu->exponent = 12 - DOUBLE_BIAS;
142 			pu->significand[0] = x.f.msw.significand;
143 			_fp_normalize(pu);
144 			return;
145 		}
146 	} else if (x.f.msw.exponent == 0x7ff) {	/* inf or nan */
147 		if ((x.f.msw.significand == 0) && (x.f.significand2 == 0)) {	/* inf */
148 			pu->fpclass = fp_infinity;
149 			return;
150 		} else {	/* nan */
151 			if ((x.f.msw.significand & 0x80000) != 0) {	/* quiet */
152 				pu->fpclass = fp_quiet;
153 			} else {/* signaling */
154 				pu->fpclass = fp_quiet;
155 				_fp_set_exception(fp_invalid);
156 			}
157 			pu->significand[0] = 0x80000 | x.f.msw.significand;
158 			_fp_leftshift(pu, 11);
159 			return;
160 		}
161 	}
162 	(*pu).exponent = x.f.msw.exponent - DOUBLE_BIAS;
163 	(*pu).fpclass = fp_normal;
164 	(*pu).significand[0] = 0x100000 | x.f.msw.significand;
165 	_fp_leftshift(pu, 11);
166 }
167 
168 enum fp_class_type
169 _class_quadruple(quadruple *x)
170 {
171 	quadruple_equivalence kluge;
172 	int             i;
173 
174 	for (i = 0; i < 4; i++)
175 #ifdef __STDC__
176 		kluge.x = *x;
177 #else
178 		kluge.x.u[i] = x->u[i];
179 #endif
180 	if (kluge.f.msw.exponent == 0) {	/* 0 or sub */
181 		if ((kluge.f.msw.significand == 0) && (kluge.f.significand2 == 0) && (kluge.f.significand3 == 0) && (kluge.f.significand4 == 0))
182 			return fp_zero;
183 		else
184 			return fp_subnormal;
185 	} else if (kluge.f.msw.exponent == 0x7fff) {	/* inf or nan */
186 		if ((kluge.f.msw.significand == 0) && (kluge.f.significand2 == 0) && (kluge.f.significand3 == 0) && (kluge.f.significand4 == 0))
187 			return fp_infinity;
188 		else if ((kluge.f.msw.significand & 0xffff) >= 0x8000)
189 			return fp_quiet;
190 		else
191 			return fp_signaling;
192 	} else
193 		return fp_normal;
194 }
195 
196 void
197 _unpack_quadruple(unpacked *pu, quadruple *px)
198 {
199 	quadruple_equivalence x;
200 	int             i;
201 
202 	for (i = 0; i < 4; i++)
203 #ifdef __STDC__
204 		x.x = *px;
205 #else
206 		x.x.u[i] = px->u[i];
207 #endif
208 	(*pu).sign = x.f.msw.sign;
209 	pu->significand[1] = x.f.significand2;
210 	pu->significand[2] = x.f.significand3;
211 	pu->significand[3] = x.f.significand4;
212 	for (i = 4; i < UNPACKED_SIZE; i++)
213 		pu->significand[i] = 0;
214 	if (x.f.msw.exponent == 0) {	/* zero or sub */
215 		if ((x.f.msw.significand | x.f.significand2 | x.f.significand3 | x.f.significand4) == 0) {	/* zero */
216 			pu->fpclass = fp_zero;
217 			goto ret;
218 		} else {	/* subnormal */
219 			pu->fpclass = fp_normal;
220 			pu->exponent = 16 - QUAD_BIAS;
221 			pu->significand[0] = x.f.msw.significand;
222 			_fp_normalize(pu);
223 			goto ret;
224 		}
225 	} else if (x.f.msw.exponent == 0x7fff) {	/* inf or nan */
226 		if ((x.f.msw.significand | x.f.significand2 | x.f.significand3 | x.f.significand4) == 0) {	/* inf */
227 			pu->fpclass = fp_infinity;
228 			goto ret;
229 		} else {	/* nan */
230 			if ((x.f.msw.significand & 0x8000) != 0) {	/* quiet */
231 				pu->fpclass = fp_quiet;
232 			} else {/* signaling */
233 				pu->fpclass = fp_quiet;
234 				_fp_set_exception(fp_invalid);
235 			}
236 			pu->significand[0] = 0x8000 | x.f.msw.significand;
237 			_fp_leftshift(pu, 16);
238 			goto ret;
239 		}
240 	}
241 	(*pu).exponent = x.f.msw.exponent - QUAD_BIAS;
242 	(*pu).fpclass = fp_normal;
243 	(*pu).significand[0] = 0x10000 | x.f.msw.significand;
244 	_fp_leftshift(pu, 15);
245 ret:
246 	/*
247 	 * printf("/n _unpack_quadruple ") ; _display_unpacked(pu);
248 	 */
249 	return;
250 }
251