10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5*6812Sraf * Common Development and Distribution License (the "License").
6*6812Sraf * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
21*6812Sraf
220Sstevel@tonic-gate /*
23*6812Sraf * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
240Sstevel@tonic-gate * Use is subject to license terms.
250Sstevel@tonic-gate */
260Sstevel@tonic-gate
270Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
280Sstevel@tonic-gate
29*6812Sraf #include "lint.h"
300Sstevel@tonic-gate #include "base_conversion.h"
310Sstevel@tonic-gate
320Sstevel@tonic-gate static void
__fp_rightshift(unpacked * pu,int n)330Sstevel@tonic-gate __fp_rightshift(unpacked *pu, int n)
340Sstevel@tonic-gate
350Sstevel@tonic-gate /* Right shift significand sticky by n bits. */
360Sstevel@tonic-gate
370Sstevel@tonic-gate {
380Sstevel@tonic-gate int i;
390Sstevel@tonic-gate
400Sstevel@tonic-gate if (n >= (32 * UNPACKED_SIZE)) { /* drastic */
410Sstevel@tonic-gate for (i = 0; (pu->significand[i] == 0) && (i < UNPACKED_SIZE);
420Sstevel@tonic-gate i++);
430Sstevel@tonic-gate if (i >= UNPACKED_SIZE) {
440Sstevel@tonic-gate pu->fpclass = fp_zero;
450Sstevel@tonic-gate return;
460Sstevel@tonic-gate } else {
470Sstevel@tonic-gate for (i = 0; i < (UNPACKED_SIZE - 1); i++)
480Sstevel@tonic-gate pu->significand[i] = 0;
490Sstevel@tonic-gate pu->significand[UNPACKED_SIZE - 1] = 1;
500Sstevel@tonic-gate return;
510Sstevel@tonic-gate }
520Sstevel@tonic-gate }
530Sstevel@tonic-gate while (n >= 32) { /* big shift */
540Sstevel@tonic-gate if (pu->significand[UNPACKED_SIZE - 1] != 0)
550Sstevel@tonic-gate pu->significand[UNPACKED_SIZE - 2] |= 1;
560Sstevel@tonic-gate for (i = UNPACKED_SIZE - 2; i >= 0; i--)
570Sstevel@tonic-gate pu->significand[i + 1] = pu->significand[i];
580Sstevel@tonic-gate pu->significand[0] = 0;
590Sstevel@tonic-gate n -= 32;
600Sstevel@tonic-gate }
610Sstevel@tonic-gate if (n >= 1) { /* small shift */
620Sstevel@tonic-gate unsigned int high, low, shiftout = 0;
630Sstevel@tonic-gate for (i = 0; i < UNPACKED_SIZE; i++) {
640Sstevel@tonic-gate high = pu->significand[i] >> n;
650Sstevel@tonic-gate low = pu->significand[i] << (32 - n);
660Sstevel@tonic-gate pu->significand[i] = shiftout | high;
670Sstevel@tonic-gate shiftout = low;
680Sstevel@tonic-gate }
690Sstevel@tonic-gate if (shiftout != 0)
700Sstevel@tonic-gate pu->significand[UNPACKED_SIZE - 1] |= 1;
710Sstevel@tonic-gate }
720Sstevel@tonic-gate }
730Sstevel@tonic-gate
740Sstevel@tonic-gate static int
overflow_to_infinity(int sign,enum fp_direction_type rd)750Sstevel@tonic-gate overflow_to_infinity(int sign, enum fp_direction_type rd)
760Sstevel@tonic-gate
770Sstevel@tonic-gate /* Returns 1 if overflow should go to infinity, 0 if to max finite. */
780Sstevel@tonic-gate
790Sstevel@tonic-gate {
800Sstevel@tonic-gate int inf;
810Sstevel@tonic-gate
820Sstevel@tonic-gate switch (rd) {
830Sstevel@tonic-gate case fp_nearest:
840Sstevel@tonic-gate inf = 1;
850Sstevel@tonic-gate break;
860Sstevel@tonic-gate case fp_tozero:
870Sstevel@tonic-gate inf = 0;
880Sstevel@tonic-gate break;
890Sstevel@tonic-gate case fp_positive:
900Sstevel@tonic-gate inf = !sign;
910Sstevel@tonic-gate break;
920Sstevel@tonic-gate case fp_negative:
930Sstevel@tonic-gate inf = sign;
940Sstevel@tonic-gate break;
950Sstevel@tonic-gate }
960Sstevel@tonic-gate return (inf);
970Sstevel@tonic-gate }
980Sstevel@tonic-gate
990Sstevel@tonic-gate static void
round(unpacked * pu,int roundword,enum fp_direction_type rd,int * ex)1000Sstevel@tonic-gate round(unpacked *pu, int roundword, enum fp_direction_type rd, int *ex)
1010Sstevel@tonic-gate /*
1020Sstevel@tonic-gate * Round according to current rounding mode. pu must be shifted to so that
1030Sstevel@tonic-gate * the roundbit is pu->significand[roundword] & 0x80000000
1040Sstevel@tonic-gate */
1050Sstevel@tonic-gate {
1060Sstevel@tonic-gate int increment; /* boolean to indicate round up */
1070Sstevel@tonic-gate int is;
1080Sstevel@tonic-gate unsigned msw; /* msw before increment */
1090Sstevel@tonic-gate
1100Sstevel@tonic-gate for (is = (roundword + 1); is < UNPACKED_SIZE; is++)
1110Sstevel@tonic-gate if (pu->significand[is] != 0) {
1120Sstevel@tonic-gate /* Condense extra bits into sticky bottom of roundword. */
1130Sstevel@tonic-gate pu->significand[roundword] |= 1;
1140Sstevel@tonic-gate break;
1150Sstevel@tonic-gate }
1160Sstevel@tonic-gate if (pu->significand[roundword] == 0)
1170Sstevel@tonic-gate return;
1180Sstevel@tonic-gate *ex |= (1 << fp_inexact);
1190Sstevel@tonic-gate switch (rd) {
1200Sstevel@tonic-gate case fp_nearest:
1210Sstevel@tonic-gate increment = pu->significand[roundword] >= 0x80000000;
1220Sstevel@tonic-gate break;
1230Sstevel@tonic-gate case fp_tozero:
1240Sstevel@tonic-gate increment = 0;
1250Sstevel@tonic-gate break;
1260Sstevel@tonic-gate case fp_positive:
1270Sstevel@tonic-gate increment = (pu->sign == 0) & (pu->significand[roundword] != 0);
1280Sstevel@tonic-gate break;
1290Sstevel@tonic-gate case fp_negative:
1300Sstevel@tonic-gate increment = (pu->sign != 0) & (pu->significand[roundword] != 0);
1310Sstevel@tonic-gate break;
1320Sstevel@tonic-gate }
1330Sstevel@tonic-gate if (increment) {
1340Sstevel@tonic-gate msw = pu->significand[0]; /* save msw before round */
1350Sstevel@tonic-gate is = roundword;
1360Sstevel@tonic-gate do {
1370Sstevel@tonic-gate is--;
1380Sstevel@tonic-gate pu->significand[is]++;
1390Sstevel@tonic-gate }
1400Sstevel@tonic-gate while ((pu->significand[is] == 0) && (is > 0));
1410Sstevel@tonic-gate if (pu->significand[0] < msw) { /* rounding carried out */
1420Sstevel@tonic-gate pu->exponent++;
1430Sstevel@tonic-gate pu->significand[0] = 0x80000000;
1440Sstevel@tonic-gate }
1450Sstevel@tonic-gate }
1460Sstevel@tonic-gate if ((rd == fp_nearest) &&
1470Sstevel@tonic-gate (pu->significand[roundword] == 0x80000000)) {
1480Sstevel@tonic-gate /* ambiguous case */
1490Sstevel@tonic-gate pu->significand[roundword - 1] &= ~1; /* force round to even */
1500Sstevel@tonic-gate }
1510Sstevel@tonic-gate }
1520Sstevel@tonic-gate
1530Sstevel@tonic-gate void
__pack_single(unpacked * pu,single * px,enum fp_direction_type rd,fp_exception_field_type * ex)1540Sstevel@tonic-gate __pack_single(unpacked *pu, single *px, enum fp_direction_type rd,
1550Sstevel@tonic-gate fp_exception_field_type *ex)
1560Sstevel@tonic-gate {
1570Sstevel@tonic-gate single_equivalence kluge;
1580Sstevel@tonic-gate int e;
1590Sstevel@tonic-gate
1600Sstevel@tonic-gate e = 0;
1610Sstevel@tonic-gate kluge.f.msw.sign = pu->sign;
1620Sstevel@tonic-gate switch (pu->fpclass) {
1630Sstevel@tonic-gate case fp_zero:
1640Sstevel@tonic-gate kluge.f.msw.exponent = 0;
1650Sstevel@tonic-gate kluge.f.msw.significand = 0;
1660Sstevel@tonic-gate break;
1670Sstevel@tonic-gate case fp_infinity:
1680Sstevel@tonic-gate infinity:
1690Sstevel@tonic-gate kluge.f.msw.exponent = 0xff;
1700Sstevel@tonic-gate kluge.f.msw.significand = 0;
1710Sstevel@tonic-gate break;
1720Sstevel@tonic-gate case fp_quiet:
1730Sstevel@tonic-gate kluge.f.msw.exponent = 0xff;
1740Sstevel@tonic-gate kluge.f.msw.significand = 0x400000 |
175*6812Sraf (0x3fffff & (pu->significand[0] >> 8));
1760Sstevel@tonic-gate break;
1770Sstevel@tonic-gate case fp_normal:
1780Sstevel@tonic-gate __fp_rightshift(pu, 8);
1790Sstevel@tonic-gate pu->exponent += SINGLE_BIAS;
1800Sstevel@tonic-gate if (pu->exponent <= 0) {
1810Sstevel@tonic-gate kluge.f.msw.exponent = 0;
1820Sstevel@tonic-gate __fp_rightshift(pu, 1 - pu->exponent);
1830Sstevel@tonic-gate round(pu, 1, rd, &e);
1840Sstevel@tonic-gate if (pu->significand[0] == 0x800000) {
1850Sstevel@tonic-gate /* rounded back up to normal */
1860Sstevel@tonic-gate kluge.f.msw.exponent = 1;
1870Sstevel@tonic-gate kluge.f.msw.significand = 0;
1880Sstevel@tonic-gate e |= (1 << fp_underflow);
1890Sstevel@tonic-gate goto ret;
1900Sstevel@tonic-gate }
1910Sstevel@tonic-gate if (e & (1 << fp_inexact))
1920Sstevel@tonic-gate e |= (1 << fp_underflow);
1930Sstevel@tonic-gate kluge.f.msw.significand = 0x7fffff & pu->significand[0];
1940Sstevel@tonic-gate goto ret;
1950Sstevel@tonic-gate }
1960Sstevel@tonic-gate round(pu, 1, rd, &e);
1970Sstevel@tonic-gate if (pu->significand[0] == 0x1000000) { /* rounding overflow */
1980Sstevel@tonic-gate pu->significand[0] = 0x800000;
1990Sstevel@tonic-gate pu->exponent += 1;
2000Sstevel@tonic-gate }
2010Sstevel@tonic-gate if (pu->exponent >= 0xff) {
2020Sstevel@tonic-gate e |= (1 << fp_overflow) | (1 << fp_inexact);
2030Sstevel@tonic-gate if (overflow_to_infinity(pu->sign, rd))
2040Sstevel@tonic-gate goto infinity;
2050Sstevel@tonic-gate kluge.f.msw.exponent = 0xfe;
2060Sstevel@tonic-gate kluge.f.msw.significand = 0x7fffff;
2070Sstevel@tonic-gate goto ret;
2080Sstevel@tonic-gate }
2090Sstevel@tonic-gate kluge.f.msw.exponent = pu->exponent;
2100Sstevel@tonic-gate kluge.f.msw.significand = 0x7fffff & pu->significand[0];
2110Sstevel@tonic-gate }
2120Sstevel@tonic-gate ret:
2130Sstevel@tonic-gate *px = kluge.x;
2140Sstevel@tonic-gate *ex = (fp_exception_field_type)e;
2150Sstevel@tonic-gate }
2160Sstevel@tonic-gate
2170Sstevel@tonic-gate void
__pack_double(unpacked * pu,double * px,enum fp_direction_type rd,fp_exception_field_type * ex)2180Sstevel@tonic-gate __pack_double(unpacked *pu, double *px, enum fp_direction_type rd,
2190Sstevel@tonic-gate fp_exception_field_type *ex)
2200Sstevel@tonic-gate {
2210Sstevel@tonic-gate double_equivalence kluge;
2220Sstevel@tonic-gate int e;
2230Sstevel@tonic-gate
2240Sstevel@tonic-gate e = 0;
2250Sstevel@tonic-gate kluge.f.msw.sign = pu->sign;
2260Sstevel@tonic-gate switch (pu->fpclass) {
2270Sstevel@tonic-gate case fp_zero:
2280Sstevel@tonic-gate kluge.f.msw.exponent = 0;
2290Sstevel@tonic-gate kluge.f.msw.significand = 0;
2300Sstevel@tonic-gate kluge.f.significand2 = 0;
2310Sstevel@tonic-gate break;
2320Sstevel@tonic-gate case fp_infinity:
2330Sstevel@tonic-gate infinity:
2340Sstevel@tonic-gate kluge.f.msw.exponent = 0x7ff;
2350Sstevel@tonic-gate kluge.f.msw.significand = 0;
2360Sstevel@tonic-gate kluge.f.significand2 = 0;
2370Sstevel@tonic-gate break;
2380Sstevel@tonic-gate case fp_quiet:
2390Sstevel@tonic-gate kluge.f.msw.exponent = 0x7ff;
2400Sstevel@tonic-gate __fp_rightshift(pu, 11);
2410Sstevel@tonic-gate kluge.f.msw.significand = 0x80000 |
242*6812Sraf (0x7ffff & pu->significand[0]);
2430Sstevel@tonic-gate kluge.f.significand2 = pu->significand[1];
2440Sstevel@tonic-gate break;
2450Sstevel@tonic-gate case fp_normal:
2460Sstevel@tonic-gate __fp_rightshift(pu, 11);
2470Sstevel@tonic-gate pu->exponent += DOUBLE_BIAS;
2480Sstevel@tonic-gate if (pu->exponent <= 0) { /* underflow */
2490Sstevel@tonic-gate __fp_rightshift(pu, 1 - pu->exponent);
2500Sstevel@tonic-gate round(pu, 2, rd, &e);
2510Sstevel@tonic-gate if (pu->significand[0] == 0x100000) {
2520Sstevel@tonic-gate /* rounded back up to normal */
2530Sstevel@tonic-gate kluge.f.msw.exponent = 1;
2540Sstevel@tonic-gate kluge.f.msw.significand = 0;
2550Sstevel@tonic-gate kluge.f.significand2 = 0;
2560Sstevel@tonic-gate e |= (1 << fp_underflow);
2570Sstevel@tonic-gate goto ret;
2580Sstevel@tonic-gate }
2590Sstevel@tonic-gate if (e & (1 << fp_inexact))
2600Sstevel@tonic-gate e |= (1 << fp_underflow);
2610Sstevel@tonic-gate kluge.f.msw.exponent = 0;
2620Sstevel@tonic-gate kluge.f.msw.significand = 0xfffff & pu->significand[0];
2630Sstevel@tonic-gate kluge.f.significand2 = pu->significand[1];
2640Sstevel@tonic-gate goto ret;
2650Sstevel@tonic-gate }
2660Sstevel@tonic-gate round(pu, 2, rd, &e);
2670Sstevel@tonic-gate if (pu->significand[0] == 0x200000) { /* rounding overflow */
2680Sstevel@tonic-gate pu->significand[0] = 0x100000;
2690Sstevel@tonic-gate pu->exponent += 1;
2700Sstevel@tonic-gate }
2710Sstevel@tonic-gate if (pu->exponent >= 0x7ff) { /* overflow */
2720Sstevel@tonic-gate e |= (1 << fp_overflow) | (1 << fp_inexact);
2730Sstevel@tonic-gate if (overflow_to_infinity(pu->sign, rd))
2740Sstevel@tonic-gate goto infinity;
2750Sstevel@tonic-gate kluge.f.msw.exponent = 0x7fe;
2760Sstevel@tonic-gate kluge.f.msw.significand = 0xfffff;
2770Sstevel@tonic-gate kluge.f.significand2 = 0xffffffff;
2780Sstevel@tonic-gate goto ret;
2790Sstevel@tonic-gate }
2800Sstevel@tonic-gate kluge.f.msw.exponent = pu->exponent;
2810Sstevel@tonic-gate kluge.f.msw.significand = 0xfffff & pu->significand[0];
2820Sstevel@tonic-gate kluge.f.significand2 = pu->significand[1];
2830Sstevel@tonic-gate break;
2840Sstevel@tonic-gate }
2850Sstevel@tonic-gate ret:
2860Sstevel@tonic-gate *px = kluge.x;
2870Sstevel@tonic-gate *ex = (fp_exception_field_type)e;
2880Sstevel@tonic-gate }
2890Sstevel@tonic-gate
2900Sstevel@tonic-gate void
__pack_extended(unpacked * pu,extended * px,enum fp_direction_type rd,fp_exception_field_type * ex)2910Sstevel@tonic-gate __pack_extended(unpacked *pu, extended *px, enum fp_direction_type rd,
2920Sstevel@tonic-gate fp_exception_field_type *ex)
2930Sstevel@tonic-gate {
2940Sstevel@tonic-gate extended_equivalence kluge;
2950Sstevel@tonic-gate int e;
2960Sstevel@tonic-gate
2970Sstevel@tonic-gate e = 0;
2980Sstevel@tonic-gate kluge.f.msw.sign = pu->sign;
2990Sstevel@tonic-gate switch (pu->fpclass) {
3000Sstevel@tonic-gate case fp_zero:
3010Sstevel@tonic-gate kluge.f.msw.exponent = 0;
3020Sstevel@tonic-gate kluge.f.significand = 0;
3030Sstevel@tonic-gate kluge.f.significand2 = 0;
3040Sstevel@tonic-gate break;
3050Sstevel@tonic-gate case fp_infinity:
3060Sstevel@tonic-gate infinity:
3070Sstevel@tonic-gate kluge.f.msw.exponent = 0x7fff;
3080Sstevel@tonic-gate kluge.f.significand = 0x80000000;
3090Sstevel@tonic-gate kluge.f.significand2 = 0;
3100Sstevel@tonic-gate break;
3110Sstevel@tonic-gate case fp_quiet:
3120Sstevel@tonic-gate kluge.f.msw.exponent = 0x7fff;
3130Sstevel@tonic-gate kluge.f.significand = 0x40000000 | pu->significand[0];
3140Sstevel@tonic-gate kluge.f.significand2 = pu->significand[1];
3150Sstevel@tonic-gate break;
3160Sstevel@tonic-gate case fp_normal:
3170Sstevel@tonic-gate pu->exponent += EXTENDED_BIAS;
3180Sstevel@tonic-gate if (pu->exponent <= 0) { /* underflow */
3190Sstevel@tonic-gate __fp_rightshift(pu, 1 - pu->exponent);
3200Sstevel@tonic-gate round(pu, 2, rd, &e);
3210Sstevel@tonic-gate if (pu->significand[0] == 0x80000000u) {
3220Sstevel@tonic-gate /* rounded back up to normal */
3230Sstevel@tonic-gate kluge.f.msw.exponent = 1;
3240Sstevel@tonic-gate kluge.f.significand = 0x80000000u;
3250Sstevel@tonic-gate kluge.f.significand2 = 0;
3260Sstevel@tonic-gate e |= (1 << fp_underflow);
3270Sstevel@tonic-gate goto ret;
3280Sstevel@tonic-gate }
3290Sstevel@tonic-gate if (e & (1 << fp_inexact))
3300Sstevel@tonic-gate e |= (1 << fp_underflow);
3310Sstevel@tonic-gate kluge.f.msw.exponent = 0;
3320Sstevel@tonic-gate kluge.f.significand = pu->significand[0];
3330Sstevel@tonic-gate kluge.f.significand2 = pu->significand[1];
3340Sstevel@tonic-gate goto ret;
3350Sstevel@tonic-gate }
3360Sstevel@tonic-gate round(pu, 2, rd, &e);
3370Sstevel@tonic-gate if (pu->exponent >= 0x7fff) { /* overflow */
3380Sstevel@tonic-gate e |= (1 << fp_overflow) | (1 << fp_inexact);
3390Sstevel@tonic-gate if (overflow_to_infinity(pu->sign, rd))
3400Sstevel@tonic-gate goto infinity;
3410Sstevel@tonic-gate kluge.f.msw.exponent = 0x7ffe;
3420Sstevel@tonic-gate kluge.f.significand = 0xffffffff;
3430Sstevel@tonic-gate kluge.f.significand2 = 0xffffffff;
3440Sstevel@tonic-gate goto ret;
3450Sstevel@tonic-gate }
3460Sstevel@tonic-gate kluge.f.msw.exponent = pu->exponent;
3470Sstevel@tonic-gate kluge.f.significand = pu->significand[0];
3480Sstevel@tonic-gate kluge.f.significand2 = pu->significand[1];
3490Sstevel@tonic-gate break;
3500Sstevel@tonic-gate }
3510Sstevel@tonic-gate ret:
3520Sstevel@tonic-gate (*px)[0] = kluge.x[0];
3530Sstevel@tonic-gate (*px)[1] = kluge.x[1];
3540Sstevel@tonic-gate (*px)[2] = kluge.x[2];
3550Sstevel@tonic-gate *ex = (fp_exception_field_type)e;
3560Sstevel@tonic-gate }
3570Sstevel@tonic-gate
3580Sstevel@tonic-gate void
__pack_quadruple(unpacked * pu,quadruple * px,enum fp_direction_type rd,fp_exception_field_type * ex)3590Sstevel@tonic-gate __pack_quadruple(unpacked *pu, quadruple *px, enum fp_direction_type rd,
3600Sstevel@tonic-gate fp_exception_field_type *ex)
3610Sstevel@tonic-gate {
3620Sstevel@tonic-gate quadruple_equivalence kluge;
3630Sstevel@tonic-gate int e;
3640Sstevel@tonic-gate
3650Sstevel@tonic-gate e = 0;
3660Sstevel@tonic-gate kluge.f.msw.sign = pu->sign;
3670Sstevel@tonic-gate switch (pu->fpclass) {
3680Sstevel@tonic-gate case fp_zero:
3690Sstevel@tonic-gate kluge.f.msw.exponent = 0;
3700Sstevel@tonic-gate kluge.f.msw.significand = 0;
3710Sstevel@tonic-gate kluge.f.significand2 = 0;
3720Sstevel@tonic-gate kluge.f.significand3 = 0;
3730Sstevel@tonic-gate kluge.f.significand4 = 0;
3740Sstevel@tonic-gate break;
3750Sstevel@tonic-gate case fp_infinity:
3760Sstevel@tonic-gate infinity:
3770Sstevel@tonic-gate kluge.f.msw.exponent = 0x7fff;
3780Sstevel@tonic-gate kluge.f.msw.significand = 0;
3790Sstevel@tonic-gate kluge.f.significand2 = 0;
3800Sstevel@tonic-gate kluge.f.significand3 = 0;
3810Sstevel@tonic-gate kluge.f.significand4 = 0;
3820Sstevel@tonic-gate break;
3830Sstevel@tonic-gate case fp_quiet:
3840Sstevel@tonic-gate kluge.f.msw.exponent = 0x7fff;
3850Sstevel@tonic-gate __fp_rightshift(pu, 15);
3860Sstevel@tonic-gate kluge.f.msw.significand = 0x8000 |
387*6812Sraf (0xffff & pu->significand[0]);
3880Sstevel@tonic-gate kluge.f.significand2 = pu->significand[1];
3890Sstevel@tonic-gate kluge.f.significand3 = pu->significand[2];
3900Sstevel@tonic-gate kluge.f.significand4 = pu->significand[3];
3910Sstevel@tonic-gate break;
3920Sstevel@tonic-gate case fp_normal:
3930Sstevel@tonic-gate __fp_rightshift(pu, 15);
3940Sstevel@tonic-gate pu->exponent += QUAD_BIAS;
3950Sstevel@tonic-gate if (pu->exponent <= 0) { /* underflow */
3960Sstevel@tonic-gate __fp_rightshift(pu, 1 - pu->exponent);
3970Sstevel@tonic-gate round(pu, 4, rd, &e);
3980Sstevel@tonic-gate if (pu->significand[0] == 0x10000) {
3990Sstevel@tonic-gate /* rounded back up to normal */
4000Sstevel@tonic-gate kluge.f.msw.exponent = 1;
4010Sstevel@tonic-gate kluge.f.msw.significand = 0;
4020Sstevel@tonic-gate kluge.f.significand2 = 0;
4030Sstevel@tonic-gate kluge.f.significand3 = 0;
4040Sstevel@tonic-gate kluge.f.significand4 = 0;
4050Sstevel@tonic-gate e |= (1 << fp_underflow);
4060Sstevel@tonic-gate goto ret;
4070Sstevel@tonic-gate }
4080Sstevel@tonic-gate if (e & (1 << fp_inexact))
4090Sstevel@tonic-gate e |= (1 << fp_underflow);
4100Sstevel@tonic-gate kluge.f.msw.exponent = 0;
4110Sstevel@tonic-gate kluge.f.msw.significand = 0xffff & pu->significand[0];
4120Sstevel@tonic-gate kluge.f.significand2 = pu->significand[1];
4130Sstevel@tonic-gate kluge.f.significand3 = pu->significand[2];
4140Sstevel@tonic-gate kluge.f.significand4 = pu->significand[3];
4150Sstevel@tonic-gate goto ret;
4160Sstevel@tonic-gate }
4170Sstevel@tonic-gate round(pu, 4, rd, &e);
4180Sstevel@tonic-gate if (pu->significand[0] == 0x20000) { /* rounding overflow */
4190Sstevel@tonic-gate pu->significand[0] = 0x10000;
4200Sstevel@tonic-gate pu->exponent += 1;
4210Sstevel@tonic-gate }
4220Sstevel@tonic-gate if (pu->exponent >= 0x7fff) { /* overflow */
4230Sstevel@tonic-gate e |= (1 << fp_overflow) | (1 << fp_inexact);
4240Sstevel@tonic-gate if (overflow_to_infinity(pu->sign, rd))
4250Sstevel@tonic-gate goto infinity;
4260Sstevel@tonic-gate kluge.f.msw.exponent = 0x7ffe;
4270Sstevel@tonic-gate kluge.f.msw.significand = 0xffff;
4280Sstevel@tonic-gate kluge.f.significand2 = 0xffffffff;
4290Sstevel@tonic-gate kluge.f.significand3 = 0xffffffff;
4300Sstevel@tonic-gate kluge.f.significand4 = 0xffffffff;
4310Sstevel@tonic-gate goto ret;
4320Sstevel@tonic-gate }
4330Sstevel@tonic-gate kluge.f.msw.exponent = pu->exponent;
4340Sstevel@tonic-gate kluge.f.msw.significand = pu->significand[0] & 0xffff;
4350Sstevel@tonic-gate kluge.f.significand2 = pu->significand[1];
4360Sstevel@tonic-gate kluge.f.significand3 = pu->significand[2];
4370Sstevel@tonic-gate kluge.f.significand4 = pu->significand[3];
4380Sstevel@tonic-gate break;
4390Sstevel@tonic-gate }
4400Sstevel@tonic-gate ret:
4410Sstevel@tonic-gate *px = kluge.x;
4420Sstevel@tonic-gate *ex = (fp_exception_field_type)e;
4430Sstevel@tonic-gate }
444