xref: /onnv-gate/usr/src/lib/libbc/libc/gen/common/pack_float.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate  * Copyright (c) 1988-1995, by Sun Microsystems, Inc.
24*0Sstevel@tonic-gate  */
25*0Sstevel@tonic-gate 
26*0Sstevel@tonic-gate #pragma	ident	"%Z%%M%	%I%	%E% SMI"
27*0Sstevel@tonic-gate 
28*0Sstevel@tonic-gate #include "base_conversion.h"
29*0Sstevel@tonic-gate 
30*0Sstevel@tonic-gate void
_fp_rightshift(pu,n)31*0Sstevel@tonic-gate _fp_rightshift(pu, n)
32*0Sstevel@tonic-gate 	unpacked       *pu;
33*0Sstevel@tonic-gate 	int             n;
34*0Sstevel@tonic-gate 
35*0Sstevel@tonic-gate /* Right shift significand sticky by n bits.  */
36*0Sstevel@tonic-gate 
37*0Sstevel@tonic-gate {
38*0Sstevel@tonic-gate 	int             i;
39*0Sstevel@tonic-gate 
40*0Sstevel@tonic-gate 	if (n >= (32 * UNPACKED_SIZE)) {	/* drastic */
41*0Sstevel@tonic-gate 		for (i = 0; (pu->significand[i] == 0) && (i < UNPACKED_SIZE); i++);
42*0Sstevel@tonic-gate 		if (i >= UNPACKED_SIZE) {
43*0Sstevel@tonic-gate 			pu->fpclass = fp_zero;
44*0Sstevel@tonic-gate 			return;
45*0Sstevel@tonic-gate 		} else {
46*0Sstevel@tonic-gate 			for (i = 0; i < (UNPACKED_SIZE - 1); i++)
47*0Sstevel@tonic-gate 				pu->significand[i] = 0;
48*0Sstevel@tonic-gate 			pu->significand[UNPACKED_SIZE - 1] = 1;
49*0Sstevel@tonic-gate 			return;
50*0Sstevel@tonic-gate 		}
51*0Sstevel@tonic-gate 	}
52*0Sstevel@tonic-gate 	while (n >= 32) {	/* big shift */
53*0Sstevel@tonic-gate 		if (pu->significand[UNPACKED_SIZE - 1] != 0)
54*0Sstevel@tonic-gate 			pu->significand[UNPACKED_SIZE - 2] |= 1;
55*0Sstevel@tonic-gate 		for (i = UNPACKED_SIZE - 2; i >= 0; i--)
56*0Sstevel@tonic-gate 			pu->significand[i + 1] = pu->significand[i];
57*0Sstevel@tonic-gate 		pu->significand[0] = 0;
58*0Sstevel@tonic-gate 		n -= 32;
59*0Sstevel@tonic-gate 	}
60*0Sstevel@tonic-gate 	if (n >= 1) {		/* small shift */
61*0Sstevel@tonic-gate 		unsigned long   high, low, shiftout = 0;
62*0Sstevel@tonic-gate 		for (i = 0; i < UNPACKED_SIZE; i++) {
63*0Sstevel@tonic-gate 			high = pu->significand[i] >> n;
64*0Sstevel@tonic-gate 			low = pu->significand[i] << (32 - n);
65*0Sstevel@tonic-gate 			pu->significand[i] = shiftout | high;
66*0Sstevel@tonic-gate 			shiftout = low;
67*0Sstevel@tonic-gate 		}
68*0Sstevel@tonic-gate 		if (shiftout != 0)
69*0Sstevel@tonic-gate 			pu->significand[UNPACKED_SIZE - 1] |= 1;
70*0Sstevel@tonic-gate 	}
71*0Sstevel@tonic-gate }
72*0Sstevel@tonic-gate 
73*0Sstevel@tonic-gate PRIVATE int
overflow_to_infinity(sign)74*0Sstevel@tonic-gate overflow_to_infinity(sign)
75*0Sstevel@tonic-gate 	int             sign;
76*0Sstevel@tonic-gate 
77*0Sstevel@tonic-gate /* Returns 1 if overflow should go to infinity, 0 if to max finite. */
78*0Sstevel@tonic-gate 
79*0Sstevel@tonic-gate {
80*0Sstevel@tonic-gate 	int             inf;
81*0Sstevel@tonic-gate 
82*0Sstevel@tonic-gate 	switch (_fp_current_direction) {
83*0Sstevel@tonic-gate 	case fp_nearest:
84*0Sstevel@tonic-gate 		inf = 1;
85*0Sstevel@tonic-gate 		break;
86*0Sstevel@tonic-gate 	case fp_tozero:
87*0Sstevel@tonic-gate 		inf = 0;
88*0Sstevel@tonic-gate 		break;
89*0Sstevel@tonic-gate 	case fp_positive:
90*0Sstevel@tonic-gate 		inf = !sign;
91*0Sstevel@tonic-gate 		break;
92*0Sstevel@tonic-gate 	case fp_negative:
93*0Sstevel@tonic-gate 		inf = sign;
94*0Sstevel@tonic-gate 		break;
95*0Sstevel@tonic-gate 	}
96*0Sstevel@tonic-gate 	return (inf);
97*0Sstevel@tonic-gate }
98*0Sstevel@tonic-gate 
99*0Sstevel@tonic-gate PRIVATE void
round(pu,roundword)100*0Sstevel@tonic-gate round(pu, roundword)
101*0Sstevel@tonic-gate 	unpacked       *pu;
102*0Sstevel@tonic-gate 
103*0Sstevel@tonic-gate /*
104*0Sstevel@tonic-gate  * Round according to current rounding mode. pu must be shifted to so that
105*0Sstevel@tonic-gate  * the roundbit is pu->significand[roundword] & 0x80000000
106*0Sstevel@tonic-gate  */
107*0Sstevel@tonic-gate 
108*0Sstevel@tonic-gate {
109*0Sstevel@tonic-gate 	int             increment;	/* boolean to indicate round up */
110*0Sstevel@tonic-gate 	int             is;
111*0Sstevel@tonic-gate 	unsigned	msw;		/* msw before increment */
112*0Sstevel@tonic-gate 
113*0Sstevel@tonic-gate 	for (is = (roundword + 1); is < UNPACKED_SIZE; is++)
114*0Sstevel@tonic-gate 		if (pu->significand[is] != 0) {	/* Condense extra bits into
115*0Sstevel@tonic-gate 						 * sticky bottom of
116*0Sstevel@tonic-gate 						 * roundword. */
117*0Sstevel@tonic-gate 			pu->significand[roundword] |= 1;
118*0Sstevel@tonic-gate 			break;
119*0Sstevel@tonic-gate 		}
120*0Sstevel@tonic-gate 	if (pu->significand[roundword] == 0)
121*0Sstevel@tonic-gate 		return;
122*0Sstevel@tonic-gate 	_fp_set_exception(fp_inexact);
123*0Sstevel@tonic-gate 	switch (_fp_current_direction) {
124*0Sstevel@tonic-gate 	case fp_nearest:
125*0Sstevel@tonic-gate 		increment = pu->significand[roundword] >= 0x80000000;
126*0Sstevel@tonic-gate 		break;
127*0Sstevel@tonic-gate 	case fp_tozero:
128*0Sstevel@tonic-gate 		increment = 0;
129*0Sstevel@tonic-gate 		break;
130*0Sstevel@tonic-gate 	case fp_positive:
131*0Sstevel@tonic-gate 		increment = (pu->sign == 0) & (pu->significand[roundword] != 0);
132*0Sstevel@tonic-gate 		break;
133*0Sstevel@tonic-gate 	case fp_negative:
134*0Sstevel@tonic-gate 		increment = (pu->sign != 0) & (pu->significand[roundword] != 0);
135*0Sstevel@tonic-gate 		break;
136*0Sstevel@tonic-gate 	}
137*0Sstevel@tonic-gate 	if (increment) {
138*0Sstevel@tonic-gate 		msw=pu->significand[0];		/* save msw before round */
139*0Sstevel@tonic-gate 		is = roundword;
140*0Sstevel@tonic-gate 		do {
141*0Sstevel@tonic-gate 			is--;
142*0Sstevel@tonic-gate 			pu->significand[is]++;
143*0Sstevel@tonic-gate 		}
144*0Sstevel@tonic-gate 		while ((pu->significand[is] == 0) && (is > 0));
145*0Sstevel@tonic-gate 		if (pu->significand[0] < msw) {	/* rounding carried out */
146*0Sstevel@tonic-gate 			pu->exponent++;
147*0Sstevel@tonic-gate 			pu->significand[0] = 0x80000000;
148*0Sstevel@tonic-gate 		}
149*0Sstevel@tonic-gate 	}
150*0Sstevel@tonic-gate 	if ((_fp_current_direction == fp_nearest) && (pu->significand[roundword] == 0x80000000)) {	/* ambiguous case */
151*0Sstevel@tonic-gate 		pu->significand[roundword - 1] &= ~1;	/* force round to even */
152*0Sstevel@tonic-gate 	}
153*0Sstevel@tonic-gate }
154*0Sstevel@tonic-gate 
155*0Sstevel@tonic-gate void
_pack_single(pu,px)156*0Sstevel@tonic-gate _pack_single(pu, px)
157*0Sstevel@tonic-gate 	unpacked       *pu;	/* unpacked result */
158*0Sstevel@tonic-gate 	single         *px;	/* packed single */
159*0Sstevel@tonic-gate {
160*0Sstevel@tonic-gate 	single_equivalence kluge;
161*0Sstevel@tonic-gate 
162*0Sstevel@tonic-gate 	kluge.f.msw.sign = pu->sign;
163*0Sstevel@tonic-gate 	switch (pu->fpclass) {
164*0Sstevel@tonic-gate 	case fp_zero:
165*0Sstevel@tonic-gate 		kluge.f.msw.exponent = 0;
166*0Sstevel@tonic-gate 		kluge.f.msw.significand = 0;
167*0Sstevel@tonic-gate 		break;
168*0Sstevel@tonic-gate 	case fp_infinity:
169*0Sstevel@tonic-gate infinity:
170*0Sstevel@tonic-gate 		kluge.f.msw.exponent = 0xff;
171*0Sstevel@tonic-gate 		kluge.f.msw.significand = 0;
172*0Sstevel@tonic-gate 		break;
173*0Sstevel@tonic-gate 	case fp_quiet:
174*0Sstevel@tonic-gate 		kluge.f.msw.exponent = 0xff;
175*0Sstevel@tonic-gate 		kluge.f.msw.significand = 0x400000 | (0x3fffff & (pu->significand[0] >> 8));
176*0Sstevel@tonic-gate 		break;
177*0Sstevel@tonic-gate 	case fp_normal:
178*0Sstevel@tonic-gate 		_fp_rightshift(pu, 8);
179*0Sstevel@tonic-gate 		pu->exponent += SINGLE_BIAS;
180*0Sstevel@tonic-gate 		if (pu->exponent <= 0) {
181*0Sstevel@tonic-gate 			kluge.f.msw.exponent = 0;
182*0Sstevel@tonic-gate 			_fp_rightshift(pu, 1 - pu->exponent);
183*0Sstevel@tonic-gate 			round(pu, 1);
184*0Sstevel@tonic-gate 			if (pu->significand[0] == 0x800000) {	/* rounded back up to
185*0Sstevel@tonic-gate 								 * normal */
186*0Sstevel@tonic-gate 				kluge.f.msw.exponent = 1;
187*0Sstevel@tonic-gate 				kluge.f.msw.significand = 0;
188*0Sstevel@tonic-gate 				_fp_set_exception(fp_underflow);
189*0Sstevel@tonic-gate 				goto ret;
190*0Sstevel@tonic-gate 			}
191*0Sstevel@tonic-gate 			if (_fp_current_exceptions & (1 << fp_inexact))
192*0Sstevel@tonic-gate 				_fp_set_exception(fp_underflow);
193*0Sstevel@tonic-gate 			kluge.f.msw.significand = 0x7fffff & pu->significand[0];
194*0Sstevel@tonic-gate 			goto ret;
195*0Sstevel@tonic-gate 		}
196*0Sstevel@tonic-gate 		round(pu, 1);
197*0Sstevel@tonic-gate 		if (pu->significand[0] == 0x1000000) {	/* rounding overflow */
198*0Sstevel@tonic-gate 			pu->significand[0] = 0x800000;
199*0Sstevel@tonic-gate 			pu->exponent += 1;
200*0Sstevel@tonic-gate 		}
201*0Sstevel@tonic-gate 		if (pu->exponent >= 0xff) {
202*0Sstevel@tonic-gate 			_fp_set_exception(fp_overflow);
203*0Sstevel@tonic-gate 			_fp_set_exception(fp_inexact);
204*0Sstevel@tonic-gate 			if (overflow_to_infinity(pu->sign))
205*0Sstevel@tonic-gate 				goto infinity;
206*0Sstevel@tonic-gate 			kluge.f.msw.exponent = 0xfe;
207*0Sstevel@tonic-gate 			kluge.f.msw.significand = 0x7fffff;
208*0Sstevel@tonic-gate 			goto ret;
209*0Sstevel@tonic-gate 		}
210*0Sstevel@tonic-gate 		kluge.f.msw.exponent = pu->exponent;
211*0Sstevel@tonic-gate 		kluge.f.msw.significand = 0x7fffff & pu->significand[0];
212*0Sstevel@tonic-gate 	}
213*0Sstevel@tonic-gate ret:
214*0Sstevel@tonic-gate 	*px = kluge.x;
215*0Sstevel@tonic-gate }
216*0Sstevel@tonic-gate 
217*0Sstevel@tonic-gate void
_pack_double(pu,px)218*0Sstevel@tonic-gate _pack_double(pu, px)
219*0Sstevel@tonic-gate 	unpacked       *pu;	/* unpacked result */
220*0Sstevel@tonic-gate 	double         *px;	/* packed double */
221*0Sstevel@tonic-gate {
222*0Sstevel@tonic-gate 	double_equivalence kluge;
223*0Sstevel@tonic-gate 
224*0Sstevel@tonic-gate 	kluge.f.msw.sign = pu->sign;
225*0Sstevel@tonic-gate 	switch (pu->fpclass) {
226*0Sstevel@tonic-gate 	case fp_zero:
227*0Sstevel@tonic-gate 		kluge.f.msw.exponent = 0;
228*0Sstevel@tonic-gate 		kluge.f.msw.significand = 0;
229*0Sstevel@tonic-gate 		kluge.f.significand2 = 0;
230*0Sstevel@tonic-gate 		break;
231*0Sstevel@tonic-gate 	case fp_infinity:
232*0Sstevel@tonic-gate infinity:
233*0Sstevel@tonic-gate 		kluge.f.msw.exponent = 0x7ff;
234*0Sstevel@tonic-gate 		kluge.f.msw.significand = 0;
235*0Sstevel@tonic-gate 		kluge.f.significand2 = 0;
236*0Sstevel@tonic-gate 		break;
237*0Sstevel@tonic-gate 	case fp_quiet:
238*0Sstevel@tonic-gate 		kluge.f.msw.exponent = 0x7ff;
239*0Sstevel@tonic-gate 		_fp_rightshift(pu, 11);
240*0Sstevel@tonic-gate 		kluge.f.msw.significand = 0x80000 | (0x7ffff & pu->significand[0]);
241*0Sstevel@tonic-gate 		kluge.f.significand2 = pu->significand[1];
242*0Sstevel@tonic-gate 		break;
243*0Sstevel@tonic-gate 	case fp_normal:
244*0Sstevel@tonic-gate 		_fp_rightshift(pu, 11);
245*0Sstevel@tonic-gate 		pu->exponent += DOUBLE_BIAS;
246*0Sstevel@tonic-gate 		if (pu->exponent <= 0) {	/* underflow */
247*0Sstevel@tonic-gate 			kluge.f.msw.exponent = 0;
248*0Sstevel@tonic-gate 			_fp_rightshift(pu, 1 - pu->exponent);
249*0Sstevel@tonic-gate 			round(pu, 2);
250*0Sstevel@tonic-gate 			if (pu->significand[0] == 0x100000) {	/* rounded back up to
251*0Sstevel@tonic-gate 								 * normal */
252*0Sstevel@tonic-gate 				kluge.f.msw.exponent = 1;
253*0Sstevel@tonic-gate 				kluge.f.msw.significand = 0;
254*0Sstevel@tonic-gate 				kluge.f.significand2 = 0;
255*0Sstevel@tonic-gate 				_fp_set_exception(fp_underflow);
256*0Sstevel@tonic-gate 				goto ret;
257*0Sstevel@tonic-gate 			}
258*0Sstevel@tonic-gate 			if (_fp_current_exceptions & (1 << fp_inexact))
259*0Sstevel@tonic-gate 				_fp_set_exception(fp_underflow);
260*0Sstevel@tonic-gate 			kluge.f.msw.exponent = 0;
261*0Sstevel@tonic-gate 			kluge.f.msw.significand = 0xfffff & pu->significand[0];
262*0Sstevel@tonic-gate 			kluge.f.significand2 = pu->significand[1];
263*0Sstevel@tonic-gate 			goto ret;
264*0Sstevel@tonic-gate 		}
265*0Sstevel@tonic-gate 		round(pu, 2);
266*0Sstevel@tonic-gate 		if (pu->significand[0] == 0x200000) {	/* rounding overflow */
267*0Sstevel@tonic-gate 			pu->significand[0] = 0x100000;
268*0Sstevel@tonic-gate 			pu->exponent += 1;
269*0Sstevel@tonic-gate 		}
270*0Sstevel@tonic-gate 		if (pu->exponent >= 0x7ff) {	/* overflow */
271*0Sstevel@tonic-gate 			_fp_set_exception(fp_overflow);
272*0Sstevel@tonic-gate 			_fp_set_exception(fp_inexact);
273*0Sstevel@tonic-gate 			if (overflow_to_infinity(pu->sign))
274*0Sstevel@tonic-gate 				goto infinity;
275*0Sstevel@tonic-gate 			kluge.f.msw.exponent = 0x7fe;
276*0Sstevel@tonic-gate 			kluge.f.msw.significand = 0xfffff;
277*0Sstevel@tonic-gate 			kluge.f.significand2 = 0xffffffff;
278*0Sstevel@tonic-gate 			goto ret;
279*0Sstevel@tonic-gate 		}
280*0Sstevel@tonic-gate 		kluge.f.msw.exponent = pu->exponent;
281*0Sstevel@tonic-gate 		kluge.f.msw.significand = 0xfffff & pu->significand[0];
282*0Sstevel@tonic-gate 		kluge.f.significand2 = pu->significand[1];
283*0Sstevel@tonic-gate 		break;
284*0Sstevel@tonic-gate 	}
285*0Sstevel@tonic-gate ret:
286*0Sstevel@tonic-gate 	*px = kluge.x;
287*0Sstevel@tonic-gate }
288*0Sstevel@tonic-gate 
289*0Sstevel@tonic-gate void
_pack_extended(pu,px)290*0Sstevel@tonic-gate _pack_extended(pu, px)
291*0Sstevel@tonic-gate 	unpacked       *pu;	/* unpacked result */
292*0Sstevel@tonic-gate 	extended       *px;	/* packed extended */
293*0Sstevel@tonic-gate {
294*0Sstevel@tonic-gate 	extended_equivalence kluge;
295*0Sstevel@tonic-gate 
296*0Sstevel@tonic-gate 	kluge.f.msw.sign = pu->sign;
297*0Sstevel@tonic-gate 	switch (pu->fpclass) {
298*0Sstevel@tonic-gate 	case fp_zero:
299*0Sstevel@tonic-gate 		kluge.f.msw.exponent = 0;
300*0Sstevel@tonic-gate 		kluge.f.significand = 0;
301*0Sstevel@tonic-gate 		kluge.f.significand2 = 0;
302*0Sstevel@tonic-gate 		break;
303*0Sstevel@tonic-gate 	case fp_infinity:
304*0Sstevel@tonic-gate infinity:
305*0Sstevel@tonic-gate 		kluge.f.msw.exponent = 0x7fff;
306*0Sstevel@tonic-gate 		kluge.f.significand = 0;
307*0Sstevel@tonic-gate 		kluge.f.significand2 = 0;
308*0Sstevel@tonic-gate 		break;
309*0Sstevel@tonic-gate 	case fp_quiet:
310*0Sstevel@tonic-gate 		kluge.f.msw.exponent = 0x7fff;
311*0Sstevel@tonic-gate 		kluge.f.significand = 0x40000000 | (0x7fffffff & pu->significand[0]);
312*0Sstevel@tonic-gate 		kluge.f.significand2 = pu->significand[1];
313*0Sstevel@tonic-gate 		break;
314*0Sstevel@tonic-gate 	case fp_normal:
315*0Sstevel@tonic-gate 		switch (_fp_current_precision) {
316*0Sstevel@tonic-gate 		case fp_single:
317*0Sstevel@tonic-gate 			{
318*0Sstevel@tonic-gate 				single          s;
319*0Sstevel@tonic-gate 				_pack_single(pu, &s);
320*0Sstevel@tonic-gate 				_unpack_single(pu, &s);
321*0Sstevel@tonic-gate 				break;
322*0Sstevel@tonic-gate 			}
323*0Sstevel@tonic-gate 		case fp_double:
324*0Sstevel@tonic-gate 			{
325*0Sstevel@tonic-gate 				double          s;
326*0Sstevel@tonic-gate 				_pack_double(pu, &s);
327*0Sstevel@tonic-gate 				_unpack_double(pu, &s);
328*0Sstevel@tonic-gate 				break;
329*0Sstevel@tonic-gate 			}
330*0Sstevel@tonic-gate 		}
331*0Sstevel@tonic-gate 		pu->exponent += EXTENDED_BIAS;
332*0Sstevel@tonic-gate 		if (pu->exponent <= 0) {	/* underflow */
333*0Sstevel@tonic-gate 			kluge.f.msw.exponent = 0;
334*0Sstevel@tonic-gate 			_fp_rightshift(pu, -pu->exponent);
335*0Sstevel@tonic-gate 			round(pu, 2);
336*0Sstevel@tonic-gate 			if (_fp_current_exceptions & (1 << fp_inexact))
337*0Sstevel@tonic-gate 				_fp_set_exception(fp_underflow);
338*0Sstevel@tonic-gate 			kluge.f.msw.exponent = 0;
339*0Sstevel@tonic-gate 			kluge.f.significand = pu->significand[0];
340*0Sstevel@tonic-gate 			kluge.f.significand2 = pu->significand[1];
341*0Sstevel@tonic-gate 			goto ret;
342*0Sstevel@tonic-gate 		}
343*0Sstevel@tonic-gate 		round(pu, 2);
344*0Sstevel@tonic-gate 		if (pu->exponent >= 0x7fff) {	/* overflow */
345*0Sstevel@tonic-gate 			_fp_set_exception(fp_overflow);
346*0Sstevel@tonic-gate 			_fp_set_exception(fp_inexact);
347*0Sstevel@tonic-gate 			if (overflow_to_infinity(pu->sign))
348*0Sstevel@tonic-gate 				goto infinity;
349*0Sstevel@tonic-gate 			kluge.f.msw.exponent = 0x7ffe;
350*0Sstevel@tonic-gate 			kluge.f.significand = 0xffffffff;
351*0Sstevel@tonic-gate 			kluge.f.significand2 = 0xffffffff;
352*0Sstevel@tonic-gate 			goto ret;
353*0Sstevel@tonic-gate 		}
354*0Sstevel@tonic-gate 		kluge.f.msw.exponent = pu->exponent;
355*0Sstevel@tonic-gate 		kluge.f.significand = pu->significand[0];
356*0Sstevel@tonic-gate 		kluge.f.significand2 = pu->significand[1];
357*0Sstevel@tonic-gate 		break;
358*0Sstevel@tonic-gate 	}
359*0Sstevel@tonic-gate ret:
360*0Sstevel@tonic-gate 	(*px)[0] = kluge.x[0];
361*0Sstevel@tonic-gate 	(*px)[1] = kluge.x[1];
362*0Sstevel@tonic-gate 	(*px)[2] = kluge.x[2];
363*0Sstevel@tonic-gate }
364*0Sstevel@tonic-gate 
365*0Sstevel@tonic-gate void
_pack_quadruple(pu,px)366*0Sstevel@tonic-gate _pack_quadruple(pu, px)
367*0Sstevel@tonic-gate 	unpacked       *pu;	/* unpacked result */
368*0Sstevel@tonic-gate 	quadruple      *px;	/* packed quadruple */
369*0Sstevel@tonic-gate {
370*0Sstevel@tonic-gate 	quadruple_equivalence kluge;
371*0Sstevel@tonic-gate 	int             i;
372*0Sstevel@tonic-gate 
373*0Sstevel@tonic-gate 	kluge.f.msw.sign = pu->sign;
374*0Sstevel@tonic-gate 	switch (pu->fpclass) {
375*0Sstevel@tonic-gate 	case fp_zero:
376*0Sstevel@tonic-gate 		kluge.f.msw.exponent = 0;
377*0Sstevel@tonic-gate 		kluge.f.msw.significand = 0;
378*0Sstevel@tonic-gate 		kluge.f.significand2 = 0;
379*0Sstevel@tonic-gate 		kluge.f.significand3 = 0;
380*0Sstevel@tonic-gate 		kluge.f.significand4 = 0;
381*0Sstevel@tonic-gate 		break;
382*0Sstevel@tonic-gate 	case fp_infinity:
383*0Sstevel@tonic-gate infinity:
384*0Sstevel@tonic-gate 		kluge.f.msw.exponent = 0x7fff;
385*0Sstevel@tonic-gate 		kluge.f.msw.significand = 0;
386*0Sstevel@tonic-gate 		kluge.f.significand2 = 0;
387*0Sstevel@tonic-gate 		kluge.f.significand3 = 0;
388*0Sstevel@tonic-gate 		kluge.f.significand4 = 0;
389*0Sstevel@tonic-gate 		break;
390*0Sstevel@tonic-gate 	case fp_quiet:
391*0Sstevel@tonic-gate 		kluge.f.msw.exponent = 0x7fff;
392*0Sstevel@tonic-gate 		_fp_rightshift(pu, 15);
393*0Sstevel@tonic-gate 		kluge.f.msw.significand = 0x8000 | (0xffff & pu->significand[0]);
394*0Sstevel@tonic-gate 		kluge.f.significand2 = pu->significand[1];
395*0Sstevel@tonic-gate 		kluge.f.significand3 = pu->significand[2];
396*0Sstevel@tonic-gate 		kluge.f.significand4 = pu->significand[3];
397*0Sstevel@tonic-gate 		break;
398*0Sstevel@tonic-gate 	case fp_normal:
399*0Sstevel@tonic-gate 		_fp_rightshift(pu, 15);
400*0Sstevel@tonic-gate 		pu->exponent += QUAD_BIAS;
401*0Sstevel@tonic-gate 		if (pu->exponent <= 0) {	/* underflow */
402*0Sstevel@tonic-gate 			kluge.f.msw.exponent = 0;
403*0Sstevel@tonic-gate 			_fp_rightshift(pu, 1 - pu->exponent);
404*0Sstevel@tonic-gate 			round(pu, 4);
405*0Sstevel@tonic-gate 			if (pu->significand[0] == 0x10000) {	/* rounded back up to
406*0Sstevel@tonic-gate 								 * normal */
407*0Sstevel@tonic-gate 				kluge.f.msw.exponent = 1;
408*0Sstevel@tonic-gate 				kluge.f.msw.significand = 0;
409*0Sstevel@tonic-gate 				kluge.f.significand2 = 0;
410*0Sstevel@tonic-gate 				kluge.f.significand3 = 0;
411*0Sstevel@tonic-gate 				kluge.f.significand4 = 0;
412*0Sstevel@tonic-gate 				_fp_set_exception(fp_underflow);
413*0Sstevel@tonic-gate 				goto ret;
414*0Sstevel@tonic-gate 			}
415*0Sstevel@tonic-gate 			if (_fp_current_exceptions & (1 << fp_inexact))
416*0Sstevel@tonic-gate 				_fp_set_exception(fp_underflow);
417*0Sstevel@tonic-gate 			kluge.f.msw.exponent = 0;
418*0Sstevel@tonic-gate 			kluge.f.msw.significand = 0xffff & pu->significand[0];
419*0Sstevel@tonic-gate 			kluge.f.significand2 = pu->significand[1];
420*0Sstevel@tonic-gate 			kluge.f.significand3 = pu->significand[2];
421*0Sstevel@tonic-gate 			kluge.f.significand4 = pu->significand[3];
422*0Sstevel@tonic-gate 			goto ret;
423*0Sstevel@tonic-gate 		}
424*0Sstevel@tonic-gate 		round(pu, 4);
425*0Sstevel@tonic-gate 		if (pu->significand[0] == 0x20000) {	/* rounding overflow */
426*0Sstevel@tonic-gate 			pu->significand[0] = 0x10000;
427*0Sstevel@tonic-gate 			pu->exponent += 1;
428*0Sstevel@tonic-gate 		}
429*0Sstevel@tonic-gate 		if (pu->exponent >= 0x7fff) {	/* overflow */
430*0Sstevel@tonic-gate 			_fp_set_exception(fp_overflow);
431*0Sstevel@tonic-gate 			_fp_set_exception(fp_inexact);
432*0Sstevel@tonic-gate 			if (overflow_to_infinity(pu->sign))
433*0Sstevel@tonic-gate 				goto infinity;
434*0Sstevel@tonic-gate 			kluge.f.msw.exponent = 0x7ffe;
435*0Sstevel@tonic-gate 			kluge.f.msw.significand = 0xffff;
436*0Sstevel@tonic-gate 			kluge.f.significand2 = 0xffffffff;
437*0Sstevel@tonic-gate 			kluge.f.significand3 = 0xffffffff;
438*0Sstevel@tonic-gate 			kluge.f.significand4 = 0xffffffff;
439*0Sstevel@tonic-gate 			goto ret;
440*0Sstevel@tonic-gate 		}
441*0Sstevel@tonic-gate 		kluge.f.msw.exponent = pu->exponent;
442*0Sstevel@tonic-gate 		kluge.f.msw.significand = pu->significand[0] & 0xffff;
443*0Sstevel@tonic-gate 		kluge.f.significand2 = pu->significand[1];
444*0Sstevel@tonic-gate 		kluge.f.significand3 = pu->significand[2];
445*0Sstevel@tonic-gate 		kluge.f.significand4 = pu->significand[3];
446*0Sstevel@tonic-gate 		break;
447*0Sstevel@tonic-gate 	}
448*0Sstevel@tonic-gate ret:
449*0Sstevel@tonic-gate #ifdef __STDC__
450*0Sstevel@tonic-gate 	*px = kluge.x;
451*0Sstevel@tonic-gate #else
452*0Sstevel@tonic-gate 	for (i = 0; i < 4; i++)
453*0Sstevel@tonic-gate 		px->u[i] = kluge.x.u[i];
454*0Sstevel@tonic-gate #endif
455*0Sstevel@tonic-gate }
456