Home | History | Annotate | Download | only in common
      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