xref: /illumos-gate/usr/src/lib/libc/port/fp/pack_float.c (revision 1da57d55)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7257d1b4Sraf  * Common Development and Distribution License (the "License").
6*7257d1b4Sraf  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
21*7257d1b4Sraf 
227c478bd9Sstevel@tonic-gate /*
23*7257d1b4Sraf  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
27*7257d1b4Sraf #include "lint.h"
287c478bd9Sstevel@tonic-gate #include "base_conversion.h"
297c478bd9Sstevel@tonic-gate 
307c478bd9Sstevel@tonic-gate static void
__fp_rightshift(unpacked * pu,int n)317c478bd9Sstevel@tonic-gate __fp_rightshift(unpacked *pu, int n)
327c478bd9Sstevel@tonic-gate 
337c478bd9Sstevel@tonic-gate /* Right shift significand sticky by n bits.  */
347c478bd9Sstevel@tonic-gate 
357c478bd9Sstevel@tonic-gate {
367c478bd9Sstevel@tonic-gate 	int		i;
377c478bd9Sstevel@tonic-gate 
387c478bd9Sstevel@tonic-gate 	if (n >= (32 * UNPACKED_SIZE)) {	/* drastic */
397c478bd9Sstevel@tonic-gate 		for (i = 0; (pu->significand[i] == 0) && (i < UNPACKED_SIZE);
407c478bd9Sstevel@tonic-gate 				i++);
417c478bd9Sstevel@tonic-gate 		if (i >= UNPACKED_SIZE) {
427c478bd9Sstevel@tonic-gate 			pu->fpclass = fp_zero;
437c478bd9Sstevel@tonic-gate 			return;
447c478bd9Sstevel@tonic-gate 		} else {
457c478bd9Sstevel@tonic-gate 			for (i = 0; i < (UNPACKED_SIZE - 1); i++)
467c478bd9Sstevel@tonic-gate 				pu->significand[i] = 0;
477c478bd9Sstevel@tonic-gate 			pu->significand[UNPACKED_SIZE - 1] = 1;
487c478bd9Sstevel@tonic-gate 			return;
497c478bd9Sstevel@tonic-gate 		}
507c478bd9Sstevel@tonic-gate 	}
517c478bd9Sstevel@tonic-gate 	while (n >= 32) {	/* big shift */
527c478bd9Sstevel@tonic-gate 		if (pu->significand[UNPACKED_SIZE - 1] != 0)
537c478bd9Sstevel@tonic-gate 			pu->significand[UNPACKED_SIZE - 2] |= 1;
547c478bd9Sstevel@tonic-gate 		for (i = UNPACKED_SIZE - 2; i >= 0; i--)
557c478bd9Sstevel@tonic-gate 			pu->significand[i + 1] = pu->significand[i];
567c478bd9Sstevel@tonic-gate 		pu->significand[0] = 0;
577c478bd9Sstevel@tonic-gate 		n -= 32;
587c478bd9Sstevel@tonic-gate 	}
597c478bd9Sstevel@tonic-gate 	if (n >= 1) {		/* small shift */
607c478bd9Sstevel@tonic-gate 		unsigned int   high, low, shiftout = 0;
617c478bd9Sstevel@tonic-gate 		for (i = 0; i < UNPACKED_SIZE; i++) {
627c478bd9Sstevel@tonic-gate 			high = pu->significand[i] >> n;
637c478bd9Sstevel@tonic-gate 			low = pu->significand[i] << (32 - n);
647c478bd9Sstevel@tonic-gate 			pu->significand[i] = shiftout | high;
657c478bd9Sstevel@tonic-gate 			shiftout = low;
667c478bd9Sstevel@tonic-gate 		}
677c478bd9Sstevel@tonic-gate 		if (shiftout != 0)
687c478bd9Sstevel@tonic-gate 			pu->significand[UNPACKED_SIZE - 1] |= 1;
697c478bd9Sstevel@tonic-gate 	}
707c478bd9Sstevel@tonic-gate }
717c478bd9Sstevel@tonic-gate 
727c478bd9Sstevel@tonic-gate static int
overflow_to_infinity(int sign,enum fp_direction_type rd)737c478bd9Sstevel@tonic-gate overflow_to_infinity(int sign, enum fp_direction_type rd)
747c478bd9Sstevel@tonic-gate 
757c478bd9Sstevel@tonic-gate /* Returns 1 if overflow should go to infinity, 0 if to max finite. */
767c478bd9Sstevel@tonic-gate 
777c478bd9Sstevel@tonic-gate {
787c478bd9Sstevel@tonic-gate 	int		inf;
797c478bd9Sstevel@tonic-gate 
807c478bd9Sstevel@tonic-gate 	switch (rd) {
817c478bd9Sstevel@tonic-gate 	case fp_nearest:
827c478bd9Sstevel@tonic-gate 		inf = 1;
837c478bd9Sstevel@tonic-gate 		break;
847c478bd9Sstevel@tonic-gate 	case fp_tozero:
857c478bd9Sstevel@tonic-gate 		inf = 0;
867c478bd9Sstevel@tonic-gate 		break;
877c478bd9Sstevel@tonic-gate 	case fp_positive:
887c478bd9Sstevel@tonic-gate 		inf = !sign;
897c478bd9Sstevel@tonic-gate 		break;
907c478bd9Sstevel@tonic-gate 	case fp_negative:
917c478bd9Sstevel@tonic-gate 		inf = sign;
927c478bd9Sstevel@tonic-gate 		break;
937c478bd9Sstevel@tonic-gate 	}
947c478bd9Sstevel@tonic-gate 	return (inf);
957c478bd9Sstevel@tonic-gate }
967c478bd9Sstevel@tonic-gate 
977c478bd9Sstevel@tonic-gate static void
round(unpacked * pu,int roundword,enum fp_direction_type rd,int * ex)987c478bd9Sstevel@tonic-gate round(unpacked *pu, int roundword, enum fp_direction_type rd, int *ex)
997c478bd9Sstevel@tonic-gate /*
1007c478bd9Sstevel@tonic-gate  * Round according to current rounding mode. pu must be shifted to so that
1017c478bd9Sstevel@tonic-gate  * the roundbit is pu->significand[roundword] & 0x80000000
1027c478bd9Sstevel@tonic-gate  */
1037c478bd9Sstevel@tonic-gate {
1047c478bd9Sstevel@tonic-gate 	int		increment;	/* boolean to indicate round up */
1057c478bd9Sstevel@tonic-gate 	int		is;
1067c478bd9Sstevel@tonic-gate 	unsigned	msw;		/* msw before increment */
1077c478bd9Sstevel@tonic-gate 
1087c478bd9Sstevel@tonic-gate 	for (is = (roundword + 1); is < UNPACKED_SIZE; is++)
1097c478bd9Sstevel@tonic-gate 		if (pu->significand[is] != 0) {
1107c478bd9Sstevel@tonic-gate 		/* Condense extra bits into sticky bottom of roundword. */
1117c478bd9Sstevel@tonic-gate 			pu->significand[roundword] |= 1;
1127c478bd9Sstevel@tonic-gate 			break;
1137c478bd9Sstevel@tonic-gate 		}
1147c478bd9Sstevel@tonic-gate 	if (pu->significand[roundword] == 0)
1157c478bd9Sstevel@tonic-gate 		return;
1167c478bd9Sstevel@tonic-gate 	*ex |= (1 << fp_inexact);
1177c478bd9Sstevel@tonic-gate 	switch (rd) {
1187c478bd9Sstevel@tonic-gate 	case fp_nearest:
1197c478bd9Sstevel@tonic-gate 		increment = pu->significand[roundword] >= 0x80000000;
1207c478bd9Sstevel@tonic-gate 		break;
1217c478bd9Sstevel@tonic-gate 	case fp_tozero:
1227c478bd9Sstevel@tonic-gate 		increment = 0;
1237c478bd9Sstevel@tonic-gate 		break;
1247c478bd9Sstevel@tonic-gate 	case fp_positive:
1257c478bd9Sstevel@tonic-gate 		increment = (pu->sign == 0) & (pu->significand[roundword] != 0);
1267c478bd9Sstevel@tonic-gate 		break;
1277c478bd9Sstevel@tonic-gate 	case fp_negative:
1287c478bd9Sstevel@tonic-gate 		increment = (pu->sign != 0) & (pu->significand[roundword] != 0);
1297c478bd9Sstevel@tonic-gate 		break;
1307c478bd9Sstevel@tonic-gate 	}
1317c478bd9Sstevel@tonic-gate 	if (increment) {
1327c478bd9Sstevel@tonic-gate 		msw = pu->significand[0];	/* save msw before round */
1337c478bd9Sstevel@tonic-gate 		is = roundword;
1347c478bd9Sstevel@tonic-gate 		do {
1357c478bd9Sstevel@tonic-gate 			is--;
1367c478bd9Sstevel@tonic-gate 			pu->significand[is]++;
1377c478bd9Sstevel@tonic-gate 		}
1387c478bd9Sstevel@tonic-gate 		while ((pu->significand[is] == 0) && (is > 0));
1397c478bd9Sstevel@tonic-gate 		if (pu->significand[0] < msw) {	/* rounding carried out */
1407c478bd9Sstevel@tonic-gate 			pu->exponent++;
1417c478bd9Sstevel@tonic-gate 			pu->significand[0] = 0x80000000;
1427c478bd9Sstevel@tonic-gate 		}
1437c478bd9Sstevel@tonic-gate 	}
1447c478bd9Sstevel@tonic-gate 	if ((rd == fp_nearest) &&
1457c478bd9Sstevel@tonic-gate 		(pu->significand[roundword] == 0x80000000)) {
1467c478bd9Sstevel@tonic-gate 		/* ambiguous case */
1477c478bd9Sstevel@tonic-gate 		pu->significand[roundword - 1] &= ~1; /* force round to even */
1487c478bd9Sstevel@tonic-gate 	}
1497c478bd9Sstevel@tonic-gate }
1507c478bd9Sstevel@tonic-gate 
1517c478bd9Sstevel@tonic-gate void
__pack_single(unpacked * pu,single * px,enum fp_direction_type rd,fp_exception_field_type * ex)1527c478bd9Sstevel@tonic-gate __pack_single(unpacked *pu, single *px, enum fp_direction_type rd,
1537c478bd9Sstevel@tonic-gate 	fp_exception_field_type *ex)
1547c478bd9Sstevel@tonic-gate {
1557c478bd9Sstevel@tonic-gate 	single_equivalence kluge;
1567c478bd9Sstevel@tonic-gate 	int		e;
1577c478bd9Sstevel@tonic-gate 
1587c478bd9Sstevel@tonic-gate 	e = 0;
1597c478bd9Sstevel@tonic-gate 	kluge.f.msw.sign = pu->sign;
1607c478bd9Sstevel@tonic-gate 	switch (pu->fpclass) {
1617c478bd9Sstevel@tonic-gate 	case fp_zero:
1627c478bd9Sstevel@tonic-gate 		kluge.f.msw.exponent = 0;
1637c478bd9Sstevel@tonic-gate 		kluge.f.msw.significand = 0;
1647c478bd9Sstevel@tonic-gate 		break;
1657c478bd9Sstevel@tonic-gate 	case fp_infinity:
1667c478bd9Sstevel@tonic-gate infinity:
1677c478bd9Sstevel@tonic-gate 		kluge.f.msw.exponent = 0xff;
1687c478bd9Sstevel@tonic-gate 		kluge.f.msw.significand = 0;
1697c478bd9Sstevel@tonic-gate 		break;
1707c478bd9Sstevel@tonic-gate 	case fp_quiet:
1717c478bd9Sstevel@tonic-gate 		kluge.f.msw.exponent = 0xff;
1727c478bd9Sstevel@tonic-gate 		kluge.f.msw.significand = 0x400000 |
173*7257d1b4Sraf 		    (0x3fffff & (pu->significand[0] >> 8));
1747c478bd9Sstevel@tonic-gate 		break;
1757c478bd9Sstevel@tonic-gate 	case fp_normal:
1767c478bd9Sstevel@tonic-gate 		__fp_rightshift(pu, 8);
1777c478bd9Sstevel@tonic-gate 		pu->exponent += SINGLE_BIAS;
1787c478bd9Sstevel@tonic-gate 		if (pu->exponent <= 0) {
1797c478bd9Sstevel@tonic-gate 			kluge.f.msw.exponent = 0;
1807c478bd9Sstevel@tonic-gate 			__fp_rightshift(pu, 1 - pu->exponent);
1817c478bd9Sstevel@tonic-gate 			round(pu, 1, rd, &e);
1827c478bd9Sstevel@tonic-gate 			if (pu->significand[0] == 0x800000) {
1837c478bd9Sstevel@tonic-gate 				/* rounded back up to normal */
1847c478bd9Sstevel@tonic-gate 				kluge.f.msw.exponent = 1;
1857c478bd9Sstevel@tonic-gate 				kluge.f.msw.significand = 0;
1867c478bd9Sstevel@tonic-gate 				e |= (1 << fp_underflow);
1877c478bd9Sstevel@tonic-gate 				goto ret;
1887c478bd9Sstevel@tonic-gate 			}
1897c478bd9Sstevel@tonic-gate 			if (e & (1 << fp_inexact))
1907c478bd9Sstevel@tonic-gate 				e |= (1 << fp_underflow);
1917c478bd9Sstevel@tonic-gate 			kluge.f.msw.significand = 0x7fffff & pu->significand[0];
1927c478bd9Sstevel@tonic-gate 			goto ret;
1937c478bd9Sstevel@tonic-gate 		}
1947c478bd9Sstevel@tonic-gate 		round(pu, 1, rd, &e);
1957c478bd9Sstevel@tonic-gate 		if (pu->significand[0] == 0x1000000) {	/* rounding overflow */
1967c478bd9Sstevel@tonic-gate 			pu->significand[0] = 0x800000;
1977c478bd9Sstevel@tonic-gate 			pu->exponent += 1;
1987c478bd9Sstevel@tonic-gate 		}
1997c478bd9Sstevel@tonic-gate 		if (pu->exponent >= 0xff) {
2007c478bd9Sstevel@tonic-gate 			e |= (1 << fp_overflow) | (1 << fp_inexact);
2017c478bd9Sstevel@tonic-gate 			if (overflow_to_infinity(pu->sign, rd))
2027c478bd9Sstevel@tonic-gate 				goto infinity;
2037c478bd9Sstevel@tonic-gate 			kluge.f.msw.exponent = 0xfe;
2047c478bd9Sstevel@tonic-gate 			kluge.f.msw.significand = 0x7fffff;
2057c478bd9Sstevel@tonic-gate 			goto ret;
2067c478bd9Sstevel@tonic-gate 		}
2077c478bd9Sstevel@tonic-gate 		kluge.f.msw.exponent = pu->exponent;
2087c478bd9Sstevel@tonic-gate 		kluge.f.msw.significand = 0x7fffff & pu->significand[0];
2097c478bd9Sstevel@tonic-gate 	}
2107c478bd9Sstevel@tonic-gate ret:
2117c478bd9Sstevel@tonic-gate 	*px = kluge.x;
2127c478bd9Sstevel@tonic-gate 	*ex = (fp_exception_field_type)e;
2137c478bd9Sstevel@tonic-gate }
2147c478bd9Sstevel@tonic-gate 
2157c478bd9Sstevel@tonic-gate void
__pack_double(unpacked * pu,double * px,enum fp_direction_type rd,fp_exception_field_type * ex)2167c478bd9Sstevel@tonic-gate __pack_double(unpacked *pu, double *px, enum fp_direction_type rd,
2177c478bd9Sstevel@tonic-gate 	fp_exception_field_type *ex)
2187c478bd9Sstevel@tonic-gate {
2197c478bd9Sstevel@tonic-gate 	double_equivalence kluge;
2207c478bd9Sstevel@tonic-gate 	int		e;
2217c478bd9Sstevel@tonic-gate 
2227c478bd9Sstevel@tonic-gate 	e = 0;
2237c478bd9Sstevel@tonic-gate 	kluge.f.msw.sign = pu->sign;
2247c478bd9Sstevel@tonic-gate 	switch (pu->fpclass) {
2257c478bd9Sstevel@tonic-gate 	case fp_zero:
2267c478bd9Sstevel@tonic-gate 		kluge.f.msw.exponent = 0;
2277c478bd9Sstevel@tonic-gate 		kluge.f.msw.significand = 0;
2287c478bd9Sstevel@tonic-gate 		kluge.f.significand2 = 0;
2297c478bd9Sstevel@tonic-gate 		break;
2307c478bd9Sstevel@tonic-gate 	case fp_infinity:
2317c478bd9Sstevel@tonic-gate infinity:
2327c478bd9Sstevel@tonic-gate 		kluge.f.msw.exponent = 0x7ff;
2337c478bd9Sstevel@tonic-gate 		kluge.f.msw.significand = 0;
2347c478bd9Sstevel@tonic-gate 		kluge.f.significand2 = 0;
2357c478bd9Sstevel@tonic-gate 		break;
2367c478bd9Sstevel@tonic-gate 	case fp_quiet:
2377c478bd9Sstevel@tonic-gate 		kluge.f.msw.exponent = 0x7ff;
2387c478bd9Sstevel@tonic-gate 		__fp_rightshift(pu, 11);
2397c478bd9Sstevel@tonic-gate 		kluge.f.msw.significand = 0x80000 |
240*7257d1b4Sraf 		    (0x7ffff & pu->significand[0]);
2417c478bd9Sstevel@tonic-gate 		kluge.f.significand2 = pu->significand[1];
2427c478bd9Sstevel@tonic-gate 		break;
2437c478bd9Sstevel@tonic-gate 	case fp_normal:
2447c478bd9Sstevel@tonic-gate 		__fp_rightshift(pu, 11);
2457c478bd9Sstevel@tonic-gate 		pu->exponent += DOUBLE_BIAS;
2467c478bd9Sstevel@tonic-gate 		if (pu->exponent <= 0) {	/* underflow */
2477c478bd9Sstevel@tonic-gate 			__fp_rightshift(pu, 1 - pu->exponent);
2487c478bd9Sstevel@tonic-gate 			round(pu, 2, rd, &e);
2497c478bd9Sstevel@tonic-gate 			if (pu->significand[0] == 0x100000) {
2507c478bd9Sstevel@tonic-gate 				/* rounded back up to normal */
2517c478bd9Sstevel@tonic-gate 				kluge.f.msw.exponent = 1;
2527c478bd9Sstevel@tonic-gate 				kluge.f.msw.significand = 0;
2537c478bd9Sstevel@tonic-gate 				kluge.f.significand2 = 0;
2547c478bd9Sstevel@tonic-gate 				e |= (1 << fp_underflow);
2557c478bd9Sstevel@tonic-gate 				goto ret;
2567c478bd9Sstevel@tonic-gate 			}
2577c478bd9Sstevel@tonic-gate 			if (e & (1 << fp_inexact))
2587c478bd9Sstevel@tonic-gate 				e |= (1 << fp_underflow);
2597c478bd9Sstevel@tonic-gate 			kluge.f.msw.exponent = 0;
2607c478bd9Sstevel@tonic-gate 			kluge.f.msw.significand = 0xfffff & pu->significand[0];
2617c478bd9Sstevel@tonic-gate 			kluge.f.significand2 = pu->significand[1];
2627c478bd9Sstevel@tonic-gate 			goto ret;
2637c478bd9Sstevel@tonic-gate 		}
2647c478bd9Sstevel@tonic-gate 		round(pu, 2, rd, &e);
2657c478bd9Sstevel@tonic-gate 		if (pu->significand[0] == 0x200000) {	/* rounding overflow */
2667c478bd9Sstevel@tonic-gate 			pu->significand[0] = 0x100000;
2677c478bd9Sstevel@tonic-gate 			pu->exponent += 1;
2687c478bd9Sstevel@tonic-gate 		}
2697c478bd9Sstevel@tonic-gate 		if (pu->exponent >= 0x7ff) {	/* overflow */
2707c478bd9Sstevel@tonic-gate 			e |= (1 << fp_overflow) | (1 << fp_inexact);
2717c478bd9Sstevel@tonic-gate 			if (overflow_to_infinity(pu->sign, rd))
2727c478bd9Sstevel@tonic-gate 				goto infinity;
2737c478bd9Sstevel@tonic-gate 			kluge.f.msw.exponent = 0x7fe;
2747c478bd9Sstevel@tonic-gate 			kluge.f.msw.significand = 0xfffff;
2757c478bd9Sstevel@tonic-gate 			kluge.f.significand2 = 0xffffffff;
2767c478bd9Sstevel@tonic-gate 			goto ret;
2777c478bd9Sstevel@tonic-gate 		}
2787c478bd9Sstevel@tonic-gate 		kluge.f.msw.exponent = pu->exponent;
2797c478bd9Sstevel@tonic-gate 		kluge.f.msw.significand = 0xfffff & pu->significand[0];
2807c478bd9Sstevel@tonic-gate 		kluge.f.significand2 = pu->significand[1];
2817c478bd9Sstevel@tonic-gate 		break;
2827c478bd9Sstevel@tonic-gate 	}
2837c478bd9Sstevel@tonic-gate ret:
2847c478bd9Sstevel@tonic-gate 	*px = kluge.x;
2857c478bd9Sstevel@tonic-gate 	*ex = (fp_exception_field_type)e;
2867c478bd9Sstevel@tonic-gate }
2877c478bd9Sstevel@tonic-gate 
2887c478bd9Sstevel@tonic-gate void
__pack_extended(unpacked * pu,extended * px,enum fp_direction_type rd,fp_exception_field_type * ex)2897c478bd9Sstevel@tonic-gate __pack_extended(unpacked *pu, extended *px, enum fp_direction_type rd,
2907c478bd9Sstevel@tonic-gate 	fp_exception_field_type *ex)
2917c478bd9Sstevel@tonic-gate {
2927c478bd9Sstevel@tonic-gate 	extended_equivalence kluge;
2937c478bd9Sstevel@tonic-gate 	int		e;
2947c478bd9Sstevel@tonic-gate 
2957c478bd9Sstevel@tonic-gate 	e = 0;
2967c478bd9Sstevel@tonic-gate 	kluge.f.msw.sign = pu->sign;
2977c478bd9Sstevel@tonic-gate 	switch (pu->fpclass) {
2987c478bd9Sstevel@tonic-gate 	case fp_zero:
2997c478bd9Sstevel@tonic-gate 		kluge.f.msw.exponent = 0;
3007c478bd9Sstevel@tonic-gate 		kluge.f.significand = 0;
3017c478bd9Sstevel@tonic-gate 		kluge.f.significand2 = 0;
3027c478bd9Sstevel@tonic-gate 		break;
3037c478bd9Sstevel@tonic-gate 	case fp_infinity:
3047c478bd9Sstevel@tonic-gate infinity:
3057c478bd9Sstevel@tonic-gate 		kluge.f.msw.exponent = 0x7fff;
3067c478bd9Sstevel@tonic-gate 		kluge.f.significand = 0x80000000;
3077c478bd9Sstevel@tonic-gate 		kluge.f.significand2 = 0;
3087c478bd9Sstevel@tonic-gate 		break;
3097c478bd9Sstevel@tonic-gate 	case fp_quiet:
3107c478bd9Sstevel@tonic-gate 		kluge.f.msw.exponent = 0x7fff;
3117c478bd9Sstevel@tonic-gate 		kluge.f.significand = 0x40000000 | pu->significand[0];
3127c478bd9Sstevel@tonic-gate 		kluge.f.significand2 = pu->significand[1];
3137c478bd9Sstevel@tonic-gate 		break;
3147c478bd9Sstevel@tonic-gate 	case fp_normal:
3157c478bd9Sstevel@tonic-gate 		pu->exponent += EXTENDED_BIAS;
3167c478bd9Sstevel@tonic-gate 		if (pu->exponent <= 0) {	/* underflow */
3177c478bd9Sstevel@tonic-gate 			__fp_rightshift(pu, 1 - pu->exponent);
3187c478bd9Sstevel@tonic-gate 			round(pu, 2, rd, &e);
3197c478bd9Sstevel@tonic-gate 			if (pu->significand[0] == 0x80000000u) {
3207c478bd9Sstevel@tonic-gate 				/* rounded back up to normal */
3217c478bd9Sstevel@tonic-gate 				kluge.f.msw.exponent = 1;
3227c478bd9Sstevel@tonic-gate 				kluge.f.significand = 0x80000000u;
3237c478bd9Sstevel@tonic-gate 				kluge.f.significand2 = 0;
3247c478bd9Sstevel@tonic-gate 				e |= (1 << fp_underflow);
3257c478bd9Sstevel@tonic-gate 				goto ret;
3267c478bd9Sstevel@tonic-gate 			}
3277c478bd9Sstevel@tonic-gate 			if (e & (1 << fp_inexact))
3287c478bd9Sstevel@tonic-gate 				e |= (1 << fp_underflow);
3297c478bd9Sstevel@tonic-gate 			kluge.f.msw.exponent = 0;
3307c478bd9Sstevel@tonic-gate 			kluge.f.significand = pu->significand[0];
3317c478bd9Sstevel@tonic-gate 			kluge.f.significand2 = pu->significand[1];
3327c478bd9Sstevel@tonic-gate 			goto ret;
3337c478bd9Sstevel@tonic-gate 		}
3347c478bd9Sstevel@tonic-gate 		round(pu, 2, rd, &e);
3357c478bd9Sstevel@tonic-gate 		if (pu->exponent >= 0x7fff) {	/* overflow */
3367c478bd9Sstevel@tonic-gate 			e |= (1 << fp_overflow) | (1 << fp_inexact);
3377c478bd9Sstevel@tonic-gate 			if (overflow_to_infinity(pu->sign, rd))
3387c478bd9Sstevel@tonic-gate 				goto infinity;
3397c478bd9Sstevel@tonic-gate 			kluge.f.msw.exponent = 0x7ffe;
3407c478bd9Sstevel@tonic-gate 			kluge.f.significand = 0xffffffff;
3417c478bd9Sstevel@tonic-gate 			kluge.f.significand2 = 0xffffffff;
3427c478bd9Sstevel@tonic-gate 			goto ret;
3437c478bd9Sstevel@tonic-gate 		}
3447c478bd9Sstevel@tonic-gate 		kluge.f.msw.exponent = pu->exponent;
3457c478bd9Sstevel@tonic-gate 		kluge.f.significand = pu->significand[0];
3467c478bd9Sstevel@tonic-gate 		kluge.f.significand2 = pu->significand[1];
3477c478bd9Sstevel@tonic-gate 		break;
3487c478bd9Sstevel@tonic-gate 	}
3497c478bd9Sstevel@tonic-gate ret:
3507c478bd9Sstevel@tonic-gate 	(*px)[0] = kluge.x[0];
3517c478bd9Sstevel@tonic-gate 	(*px)[1] = kluge.x[1];
3527c478bd9Sstevel@tonic-gate 	(*px)[2] = kluge.x[2];
3537c478bd9Sstevel@tonic-gate 	*ex = (fp_exception_field_type)e;
3547c478bd9Sstevel@tonic-gate }
3557c478bd9Sstevel@tonic-gate 
3567c478bd9Sstevel@tonic-gate void
__pack_quadruple(unpacked * pu,quadruple * px,enum fp_direction_type rd,fp_exception_field_type * ex)3577c478bd9Sstevel@tonic-gate __pack_quadruple(unpacked *pu, quadruple *px, enum fp_direction_type rd,
3587c478bd9Sstevel@tonic-gate 	fp_exception_field_type *ex)
3597c478bd9Sstevel@tonic-gate {
3607c478bd9Sstevel@tonic-gate 	quadruple_equivalence kluge;
3617c478bd9Sstevel@tonic-gate 	int		e;
3627c478bd9Sstevel@tonic-gate 
3637c478bd9Sstevel@tonic-gate 	e = 0;
3647c478bd9Sstevel@tonic-gate 	kluge.f.msw.sign = pu->sign;
3657c478bd9Sstevel@tonic-gate 	switch (pu->fpclass) {
3667c478bd9Sstevel@tonic-gate 	case fp_zero:
3677c478bd9Sstevel@tonic-gate 		kluge.f.msw.exponent = 0;
3687c478bd9Sstevel@tonic-gate 		kluge.f.msw.significand = 0;
3697c478bd9Sstevel@tonic-gate 		kluge.f.significand2 = 0;
3707c478bd9Sstevel@tonic-gate 		kluge.f.significand3 = 0;
3717c478bd9Sstevel@tonic-gate 		kluge.f.significand4 = 0;
3727c478bd9Sstevel@tonic-gate 		break;
3737c478bd9Sstevel@tonic-gate 	case fp_infinity:
3747c478bd9Sstevel@tonic-gate infinity:
3757c478bd9Sstevel@tonic-gate 		kluge.f.msw.exponent = 0x7fff;
3767c478bd9Sstevel@tonic-gate 		kluge.f.msw.significand = 0;
3777c478bd9Sstevel@tonic-gate 		kluge.f.significand2 = 0;
3787c478bd9Sstevel@tonic-gate 		kluge.f.significand3 = 0;
3797c478bd9Sstevel@tonic-gate 		kluge.f.significand4 = 0;
3807c478bd9Sstevel@tonic-gate 		break;
3817c478bd9Sstevel@tonic-gate 	case fp_quiet:
3827c478bd9Sstevel@tonic-gate 		kluge.f.msw.exponent = 0x7fff;
3837c478bd9Sstevel@tonic-gate 		__fp_rightshift(pu, 15);
3847c478bd9Sstevel@tonic-gate 		kluge.f.msw.significand = 0x8000 |
385*7257d1b4Sraf 		    (0xffff & pu->significand[0]);
3867c478bd9Sstevel@tonic-gate 		kluge.f.significand2 = pu->significand[1];
3877c478bd9Sstevel@tonic-gate 		kluge.f.significand3 = pu->significand[2];
3887c478bd9Sstevel@tonic-gate 		kluge.f.significand4 = pu->significand[3];
3897c478bd9Sstevel@tonic-gate 		break;
3907c478bd9Sstevel@tonic-gate 	case fp_normal:
3917c478bd9Sstevel@tonic-gate 		__fp_rightshift(pu, 15);
3927c478bd9Sstevel@tonic-gate 		pu->exponent += QUAD_BIAS;
3937c478bd9Sstevel@tonic-gate 		if (pu->exponent <= 0) {	/* underflow */
3947c478bd9Sstevel@tonic-gate 			__fp_rightshift(pu, 1 - pu->exponent);
3957c478bd9Sstevel@tonic-gate 			round(pu, 4, rd, &e);
3967c478bd9Sstevel@tonic-gate 			if (pu->significand[0] == 0x10000) {
3977c478bd9Sstevel@tonic-gate 				/* rounded back up to normal */
3987c478bd9Sstevel@tonic-gate 				kluge.f.msw.exponent = 1;
3997c478bd9Sstevel@tonic-gate 				kluge.f.msw.significand = 0;
4007c478bd9Sstevel@tonic-gate 				kluge.f.significand2 = 0;
4017c478bd9Sstevel@tonic-gate 				kluge.f.significand3 = 0;
4027c478bd9Sstevel@tonic-gate 				kluge.f.significand4 = 0;
4037c478bd9Sstevel@tonic-gate 				e |= (1 << fp_underflow);
4047c478bd9Sstevel@tonic-gate 				goto ret;
4057c478bd9Sstevel@tonic-gate 			}
4067c478bd9Sstevel@tonic-gate 			if (e & (1 << fp_inexact))
4077c478bd9Sstevel@tonic-gate 				e |= (1 << fp_underflow);
4087c478bd9Sstevel@tonic-gate 			kluge.f.msw.exponent = 0;
4097c478bd9Sstevel@tonic-gate 			kluge.f.msw.significand = 0xffff & pu->significand[0];
4107c478bd9Sstevel@tonic-gate 			kluge.f.significand2 = pu->significand[1];
4117c478bd9Sstevel@tonic-gate 			kluge.f.significand3 = pu->significand[2];
4127c478bd9Sstevel@tonic-gate 			kluge.f.significand4 = pu->significand[3];
4137c478bd9Sstevel@tonic-gate 			goto ret;
4147c478bd9Sstevel@tonic-gate 		}
4157c478bd9Sstevel@tonic-gate 		round(pu, 4, rd, &e);
4167c478bd9Sstevel@tonic-gate 		if (pu->significand[0] == 0x20000) {	/* rounding overflow */
4177c478bd9Sstevel@tonic-gate 			pu->significand[0] = 0x10000;
4187c478bd9Sstevel@tonic-gate 			pu->exponent += 1;
4197c478bd9Sstevel@tonic-gate 		}
4207c478bd9Sstevel@tonic-gate 		if (pu->exponent >= 0x7fff) {	/* overflow */
4217c478bd9Sstevel@tonic-gate 			e |= (1 << fp_overflow) | (1 << fp_inexact);
4227c478bd9Sstevel@tonic-gate 			if (overflow_to_infinity(pu->sign, rd))
4237c478bd9Sstevel@tonic-gate 				goto infinity;
4247c478bd9Sstevel@tonic-gate 			kluge.f.msw.exponent = 0x7ffe;
4257c478bd9Sstevel@tonic-gate 			kluge.f.msw.significand = 0xffff;
4267c478bd9Sstevel@tonic-gate 			kluge.f.significand2 = 0xffffffff;
4277c478bd9Sstevel@tonic-gate 			kluge.f.significand3 = 0xffffffff;
4287c478bd9Sstevel@tonic-gate 			kluge.f.significand4 = 0xffffffff;
4297c478bd9Sstevel@tonic-gate 			goto ret;
4307c478bd9Sstevel@tonic-gate 		}
4317c478bd9Sstevel@tonic-gate 		kluge.f.msw.exponent = pu->exponent;
4327c478bd9Sstevel@tonic-gate 		kluge.f.msw.significand = pu->significand[0] & 0xffff;
4337c478bd9Sstevel@tonic-gate 		kluge.f.significand2 = pu->significand[1];
4347c478bd9Sstevel@tonic-gate 		kluge.f.significand3 = pu->significand[2];
4357c478bd9Sstevel@tonic-gate 		kluge.f.significand4 = pu->significand[3];
4367c478bd9Sstevel@tonic-gate 		break;
4377c478bd9Sstevel@tonic-gate 	}
4387c478bd9Sstevel@tonic-gate ret:
4397c478bd9Sstevel@tonic-gate 	*px = kluge.x;
4407c478bd9Sstevel@tonic-gate 	*ex = (fp_exception_field_type)e;
4417c478bd9Sstevel@tonic-gate }
442