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 #pragma ident	"%Z%%M%	%I%	%E% SMI"
     23 
     24 /*
     25  * Copyright (c) 1988 by Sun Microsystems, Inc.
     26  */
     27 
     28 /* Utility functions for Sparc FPU simulator. */
     29 
     30 #include "_Qquad.h"
     31 #include "_Qglobals.h"
     32 
     33 
     34 void
     35 fpu_normalize(pu)
     36 	unpacked       *pu;
     37 
     38 /* Normalize a number.  Does not affect zeros, infs, or NaNs. */
     39 /* The number will be normalized to 113 bit extended:
     40  * 		0x0001####,0x########,0x########,0x########.
     41  */
     42 
     43 {
     44 	unsigned u,u0,u1,u2,u3,m,n,k;
     45 	u0 = pu->significand[0];
     46 	u1 = pu->significand[1];
     47 	u2 = pu->significand[2];
     48 	u3 = pu->significand[3];
     49 	if ((*pu).fpclass == fp_normal) {
     50 		if ((u0|u1|u2|u3)==0) {
     51 			(*pu).fpclass = fp_zero;
     52 			return;
     53 		}
     54 		while (u0 == 0) {
     55 			u0 = u1; u1=u2; u2=u3; u3=0;
     56 			(*pu).exponent = (*pu).exponent - 32;
     57 		}
     58 		if (u0>=0x20000) { 	/* u3 should be zero */
     59 			n=1; u = u0>>1;
     60 			while(u>=0x20000) {u >>= 1; n += 1;}
     61 			m = (1<<n)-1;
     62 			k = 32-n;
     63 			(*pu).exponent += n;
     64 			u3 = ((u2&m)<<k)|(u3>>n);
     65 			u2 = ((u1&m)<<k)|(u2>>n);
     66 			u1 = ((u0&m)<<k)|(u1>>n);
     67 			u0 = u;
     68 		} else if(u0<0x10000) {
     69 			n=1; u = u0<<1;
     70 			while(u<0x10000) {u <<= 1; n += 1;}
     71 			k = 32-n;
     72 			m = -(1<<k);
     73 			(*pu).exponent -= n;
     74 			u0 = (u0<<n)|((u1&m)>>k);
     75 			u1 = (u1<<n)|((u2&m)>>k);
     76 			u2 = (u2<<n)|((u3&m)>>k);
     77 			u3 = (u3<<n);
     78 		}
     79 		pu->significand[0] = u0;
     80 		pu->significand[1] = u1;
     81 		pu->significand[2] = u2;
     82 		pu->significand[3] = u3;
     83 	}
     84 }
     85 
     86 void
     87 fpu_rightshift(pu, n)
     88 	unpacked       *pu;
     89 	int             n;
     90 
     91 /* Right shift significand sticky by n bits.  */
     92 
     93 {
     94 	unsigned m,k,j,u0,u1,u2,u3;
     95 	if (n > 113) {		/* drastic */
     96 		if (((*pu).significand[0] | (*pu).significand[1]
     97 			| (*pu).significand[2] | (*pu).significand[3]) == 0){
     98 						/* really zero */
     99 			pu->fpclass = fp_zero;
    100 			return;
    101 		} else {
    102 			pu->rounded = 0;
    103 			pu->sticky  = 1;
    104 			pu->significand[3] = 0;
    105 			pu->significand[2] = 0;
    106 			pu->significand[1] = 0;
    107 			pu->significand[0] = 0;
    108 			return;
    109 		}
    110 	}
    111 	while (n >= 32) {	/* big shift */
    112 		pu->sticky  |= pu->rounded | (pu->significand[3]&0x7fffffff);
    113 		pu->rounded  = (*pu).significand[3]>>31;
    114 		(*pu).significand[3] = (*pu).significand[2];
    115 		(*pu).significand[2] = (*pu).significand[1];
    116 		(*pu).significand[1] = (*pu).significand[0];
    117 		(*pu).significand[0] = 0;
    118 		n -= 32;
    119 	}
    120 	if (n > 0) {		/* small shift */
    121 		u0 = pu->significand[0];
    122 		u1 = pu->significand[1];
    123 		u2 = pu->significand[2];
    124 		u3 = pu->significand[3];
    125 		m = (1<<n)-1;
    126 		k = 32 - n;
    127 		j = (1<<(n-1))-1;
    128 		pu->sticky |= pu->rounded | (u3&j);
    129 		pu->rounded = (u3&m)>>(n-1);
    130 		pu->significand[3] = ((u2&m)<<k)|(u3>>n);
    131 		pu->significand[2] = ((u1&m)<<k)|(u2>>n);
    132 		pu->significand[1] = ((u0&m)<<k)|(u1>>n);
    133 		pu->significand[0] = u0>>n;
    134 	}
    135 }
    136 
    137 void
    138 fpu_set_exception(ex)
    139 	enum fp_exception_type ex;
    140 
    141 /* Set the exception bit in the current exception register. */
    142 
    143 {
    144 	_fp_current_exceptions |= 1 << (int) ex;
    145 }
    146 
    147 void
    148 fpu_error_nan(pu)
    149 	unpacked       *pu;
    150 
    151 {				/* Set invalid exception and error nan in *pu */
    152 
    153 	fpu_set_exception(fp_invalid);
    154 	pu->significand[0] = 0x7fffffff|((pu->sign)<<31);
    155 	pu->significand[1] = 0xffffffff;
    156 	pu->significand[2] = 0xffffffff;
    157 	pu->significand[3] = 0xffffffff;
    158 }
    159 
    160 /* the following fpu_add3wc should be inlined as
    161  *	.inline	_fpu_add3wc,3
    162  *	ld	[%o1],%o4		! sum = x
    163  *	addcc	-1,%o3,%g0		! restore last carry in cc reg
    164  *	addxcc	%o4,%o2,%o4		! sum = sum + y + last carry
    165  *	st	%o4,[%o0]		! *z  = sum
    166  *	addx	%g0,%g0,%o0		! return new carry
    167  *	.end
    168  */
    169 
    170 unsigned
    171 fpu_add3wc(z,x,y,carry)
    172 	unsigned *z,x,y,carry;
    173 {				/*  *z = x + y + carry, set carry; */
    174 	if(carry==0) {
    175 		*z = x+y;
    176 		return (*z<y);
    177 	} else {
    178 		*z = x+y+1;
    179 		return (*z<=y);
    180 	}
    181 }
    182 
    183 /* the following fpu_sub3wc should be inlined as
    184  *	.inline	_fpu_sub3wc,3
    185  *	ld	[%o1],%o4		! sum = *x
    186  *	addcc	-1,%o3,%g0		! restore last carry in cc reg
    187  *	subxcc	%o4,%o2,%o4		! sum = sum - y - last carry
    188  *	st	%o4,[%o0]		! *x  = sum
    189  *	addx	%g0,%g0,%o0		! return new carry
    190  *	.end
    191  */
    192 
    193 unsigned
    194 fpu_sub3wc(z,x,y,carry)
    195 	unsigned *z,x,y,carry;
    196 {				/*  *z = x - y - carry, set carry; */
    197 	if(carry==0) {
    198 		*z = x-y;
    199 		return (*z>x);
    200 	} else {
    201 		*z = x-y-1;
    202 		return (*z>=x);
    203 	}
    204 }
    205 
    206 /* the following fpu_neg2wc should be inlined as
    207  *	.inline	_fpu_neg2wc,2
    208  *	ld	[%o1],%o3		! tmp = *x
    209  *	addcc	-1,%o2,%g0		! restore last carry in cc reg
    210  *	subxcc	%g0,%o3,%o3		! sum = 0 - tmp - last carry
    211  *	st	%o3,[%o0]		! *x  = sum
    212  *	addx	%g0,%g0,%o0		! return new carry
    213  *	.end
    214  */
    215 
    216 unsigned
    217 fpu_neg2wc(z,x,carry)
    218 	unsigned *z,x,carry;
    219 {				/*  *x = 0 - *x - carry, set carry; */
    220 	if(carry==0) {
    221 		*z = -x;
    222 		return ((*z)!=0);
    223 	} else {
    224 		*z = -x-1;
    225 		return 1;
    226 	}
    227 }
    228 
    229 int
    230 fpu_cmpli(x,y,n)
    231 	unsigned x[],y[]; int n;
    232 {				/* compare two unsigned array */
    233 	int i;
    234 	i=0;
    235 	while(i<n)  {
    236 		if(x[i]>y[i]) return 1;
    237 		else if(x[i]<y[i]) return -1;
    238 		i++;
    239 	}
    240 	return 0;
    241 }
    242 
    243 #ifdef DEBUG
    244 void
    245 display_unpacked(pu)
    246 	unpacked       *pu;
    247 
    248 /* Print out unpacked record.	 */
    249 
    250 {
    251 	(void) printf(" unpacked ");
    252 	if (pu->sign)
    253 		(void) printf("-");
    254 	else
    255 		(void) printf("+");
    256 
    257 	switch (pu->fpclass) {
    258 	case fp_zero:
    259 		(void) printf("0     ");
    260 		break;
    261 	case fp_normal:
    262 		(void) printf("normal");
    263 		break;
    264 	case fp_infinity:
    265 		(void) printf("Inf   ");
    266 		break;
    267 	case fp_quiet:
    268 	case fp_signaling:
    269 		(void) printf("nan   ");
    270 		break;
    271 	}
    272 	(void) printf(" %X %X %X %X (%X,%X) exponent %X \n",
    273 		pu->significand[0], pu->significand[1],pu->significand[2],
    274 		pu->significand[3], (pu->rounded!=0),
    275 		(pu->sticky!=0),pu->exponent);
    276 }
    277 #endif
    278 
    279