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