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 (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #include "lint.h" 28 #include "base_conversion.h" 29 30 /* Right shift significand sticky by n bits. */ 31 static void 32 __fp_rightshift(unpacked *pu, int n) 33 { 34 int i; 35 36 if (n >= (32 * UNPACKED_SIZE)) { /* drastic */ 37 for (i = 0; i < UNPACKED_SIZE && pu->significand[i] == 0; i++) 38 ; 39 if (i >= UNPACKED_SIZE) { 40 pu->fpclass = fp_zero; 41 return; 42 } else { 43 for (i = 0; i < (UNPACKED_SIZE - 1); i++) 44 pu->significand[i] = 0; 45 pu->significand[UNPACKED_SIZE - 1] = 1; 46 return; 47 } 48 } 49 while (n >= 32) { /* big shift */ 50 if (pu->significand[UNPACKED_SIZE - 1] != 0) 51 pu->significand[UNPACKED_SIZE - 2] |= 1; 52 for (i = UNPACKED_SIZE - 2; i >= 0; i--) 53 pu->significand[i + 1] = pu->significand[i]; 54 pu->significand[0] = 0; 55 n -= 32; 56 } 57 if (n >= 1) { /* small shift */ 58 unsigned int high, low, shiftout = 0; 59 for (i = 0; i < UNPACKED_SIZE; i++) { 60 high = pu->significand[i] >> n; 61 low = pu->significand[i] << (32 - n); 62 pu->significand[i] = shiftout | high; 63 shiftout = low; 64 } 65 if (shiftout != 0) 66 pu->significand[UNPACKED_SIZE - 1] |= 1; 67 } 68 } 69 70 /* Returns 1 if overflow should go to infinity, 0 if to max finite. */ 71 static int 72 overflow_to_infinity(int sign, enum fp_direction_type rd) 73 { 74 int inf; 75 76 switch (rd) { 77 case fp_nearest: 78 inf = 1; 79 break; 80 case fp_tozero: 81 inf = 0; 82 break; 83 case fp_positive: 84 inf = !sign; 85 break; 86 case fp_negative: 87 inf = sign; 88 break; 89 } 90 return (inf); 91 } 92 93 /* 94 * Round according to current rounding mode. pu must be shifted to so that 95 * the roundbit is pu->significand[roundword] & 0x80000000 96 */ 97 static void 98 round(unpacked *pu, int roundword, enum fp_direction_type rd, int *ex) 99 { 100 int increment; /* boolean to indicate round up */ 101 int is; 102 unsigned msw; /* msw before increment */ 103 104 for (is = (roundword + 1); is < UNPACKED_SIZE; is++) 105 if (pu->significand[is] != 0) { 106 /* Condense extra bits into sticky bottom of roundword. */ 107 pu->significand[roundword] |= 1; 108 break; 109 } 110 if (pu->significand[roundword] == 0) 111 return; 112 *ex |= (1 << fp_inexact); 113 switch (rd) { 114 case fp_nearest: 115 increment = pu->significand[roundword] >= 0x80000000; 116 break; 117 case fp_tozero: 118 increment = 0; 119 break; 120 case fp_positive: 121 increment = (pu->sign == 0) & (pu->significand[roundword] != 0); 122 break; 123 case fp_negative: 124 increment = (pu->sign != 0) & (pu->significand[roundword] != 0); 125 break; 126 } 127 if (increment) { 128 msw = pu->significand[0]; /* save msw before round */ 129 is = roundword; 130 do { 131 is--; 132 pu->significand[is]++; 133 } 134 while ((pu->significand[is] == 0) && (is > 0)) 135 ; 136 if (pu->significand[0] < msw) { /* rounding carried out */ 137 pu->exponent++; 138 pu->significand[0] = 0x80000000; 139 } 140 } 141 if ((rd == fp_nearest) && 142 (pu->significand[roundword] == 0x80000000)) { 143 /* ambiguous case */ 144 pu->significand[roundword - 1] &= ~1; /* force round to even */ 145 } 146 } 147 148 void 149 __pack_single(unpacked *pu, single *px, enum fp_direction_type rd, 150 fp_exception_field_type *ex) 151 { 152 single_equivalence kluge; 153 int e; 154 155 e = 0; 156 kluge.f.msw.sign = pu->sign; 157 switch (pu->fpclass) { 158 case fp_zero: 159 kluge.f.msw.exponent = 0; 160 kluge.f.msw.significand = 0; 161 break; 162 case fp_infinity: 163 infinity: 164 kluge.f.msw.exponent = 0xff; 165 kluge.f.msw.significand = 0; 166 break; 167 case fp_quiet: 168 kluge.f.msw.exponent = 0xff; 169 kluge.f.msw.significand = 0x400000 | 170 (0x3fffff & (pu->significand[0] >> 8)); 171 break; 172 case fp_normal: 173 __fp_rightshift(pu, 8); 174 pu->exponent += SINGLE_BIAS; 175 if (pu->exponent <= 0) { 176 kluge.f.msw.exponent = 0; 177 __fp_rightshift(pu, 1 - pu->exponent); 178 round(pu, 1, rd, &e); 179 if (pu->significand[0] == 0x800000) { 180 /* rounded back up to normal */ 181 kluge.f.msw.exponent = 1; 182 kluge.f.msw.significand = 0; 183 e |= (1 << fp_underflow); 184 goto ret; 185 } 186 if (e & (1 << fp_inexact)) 187 e |= (1 << fp_underflow); 188 kluge.f.msw.significand = 0x7fffff & pu->significand[0]; 189 goto ret; 190 } 191 round(pu, 1, rd, &e); 192 if (pu->significand[0] == 0x1000000) { /* rounding overflow */ 193 pu->significand[0] = 0x800000; 194 pu->exponent += 1; 195 } 196 if (pu->exponent >= 0xff) { 197 e |= (1 << fp_overflow) | (1 << fp_inexact); 198 if (overflow_to_infinity(pu->sign, rd)) 199 goto infinity; 200 kluge.f.msw.exponent = 0xfe; 201 kluge.f.msw.significand = 0x7fffff; 202 goto ret; 203 } 204 kluge.f.msw.exponent = pu->exponent; 205 kluge.f.msw.significand = 0x7fffff & pu->significand[0]; 206 } 207 ret: 208 *px = kluge.x; 209 *ex = (fp_exception_field_type)e; 210 } 211 212 void 213 __pack_double(unpacked *pu, double *px, enum fp_direction_type rd, 214 fp_exception_field_type *ex) 215 { 216 double_equivalence kluge; 217 int e; 218 219 e = 0; 220 kluge.f.msw.sign = pu->sign; 221 switch (pu->fpclass) { 222 case fp_zero: 223 kluge.f.msw.exponent = 0; 224 kluge.f.msw.significand = 0; 225 kluge.f.significand2 = 0; 226 break; 227 case fp_infinity: 228 infinity: 229 kluge.f.msw.exponent = 0x7ff; 230 kluge.f.msw.significand = 0; 231 kluge.f.significand2 = 0; 232 break; 233 case fp_quiet: 234 kluge.f.msw.exponent = 0x7ff; 235 __fp_rightshift(pu, 11); 236 kluge.f.msw.significand = 0x80000 | 237 (0x7ffff & pu->significand[0]); 238 kluge.f.significand2 = pu->significand[1]; 239 break; 240 case fp_normal: 241 __fp_rightshift(pu, 11); 242 pu->exponent += DOUBLE_BIAS; 243 if (pu->exponent <= 0) { /* underflow */ 244 __fp_rightshift(pu, 1 - pu->exponent); 245 round(pu, 2, rd, &e); 246 if (pu->significand[0] == 0x100000) { 247 /* rounded back up to normal */ 248 kluge.f.msw.exponent = 1; 249 kluge.f.msw.significand = 0; 250 kluge.f.significand2 = 0; 251 e |= (1 << fp_underflow); 252 goto ret; 253 } 254 if (e & (1 << fp_inexact)) 255 e |= (1 << fp_underflow); 256 kluge.f.msw.exponent = 0; 257 kluge.f.msw.significand = 0xfffff & pu->significand[0]; 258 kluge.f.significand2 = pu->significand[1]; 259 goto ret; 260 } 261 round(pu, 2, rd, &e); 262 if (pu->significand[0] == 0x200000) { /* rounding overflow */ 263 pu->significand[0] = 0x100000; 264 pu->exponent += 1; 265 } 266 if (pu->exponent >= 0x7ff) { /* overflow */ 267 e |= (1 << fp_overflow) | (1 << fp_inexact); 268 if (overflow_to_infinity(pu->sign, rd)) 269 goto infinity; 270 kluge.f.msw.exponent = 0x7fe; 271 kluge.f.msw.significand = 0xfffff; 272 kluge.f.significand2 = 0xffffffff; 273 goto ret; 274 } 275 kluge.f.msw.exponent = pu->exponent; 276 kluge.f.msw.significand = 0xfffff & pu->significand[0]; 277 kluge.f.significand2 = pu->significand[1]; 278 break; 279 } 280 ret: 281 *px = kluge.x; 282 *ex = (fp_exception_field_type)e; 283 } 284 285 void 286 __pack_extended(unpacked *pu, extended *px, enum fp_direction_type rd, 287 fp_exception_field_type *ex) 288 { 289 extended_equivalence kluge; 290 int e; 291 292 e = 0; 293 kluge.f.msw.sign = pu->sign; 294 switch (pu->fpclass) { 295 case fp_zero: 296 kluge.f.msw.exponent = 0; 297 kluge.f.significand = 0; 298 kluge.f.significand2 = 0; 299 break; 300 case fp_infinity: 301 infinity: 302 kluge.f.msw.exponent = 0x7fff; 303 kluge.f.significand = 0x80000000; 304 kluge.f.significand2 = 0; 305 break; 306 case fp_quiet: 307 kluge.f.msw.exponent = 0x7fff; 308 kluge.f.significand = 0x40000000 | pu->significand[0]; 309 kluge.f.significand2 = pu->significand[1]; 310 break; 311 case fp_normal: 312 pu->exponent += EXTENDED_BIAS; 313 if (pu->exponent <= 0) { /* underflow */ 314 __fp_rightshift(pu, 1 - pu->exponent); 315 round(pu, 2, rd, &e); 316 if (pu->significand[0] == 0x80000000u) { 317 /* rounded back up to normal */ 318 kluge.f.msw.exponent = 1; 319 kluge.f.significand = 0x80000000u; 320 kluge.f.significand2 = 0; 321 e |= (1 << fp_underflow); 322 goto ret; 323 } 324 if (e & (1 << fp_inexact)) 325 e |= (1 << fp_underflow); 326 kluge.f.msw.exponent = 0; 327 kluge.f.significand = pu->significand[0]; 328 kluge.f.significand2 = pu->significand[1]; 329 goto ret; 330 } 331 round(pu, 2, rd, &e); 332 if (pu->exponent >= 0x7fff) { /* overflow */ 333 e |= (1 << fp_overflow) | (1 << fp_inexact); 334 if (overflow_to_infinity(pu->sign, rd)) 335 goto infinity; 336 kluge.f.msw.exponent = 0x7ffe; 337 kluge.f.significand = 0xffffffff; 338 kluge.f.significand2 = 0xffffffff; 339 goto ret; 340 } 341 kluge.f.msw.exponent = pu->exponent; 342 kluge.f.significand = pu->significand[0]; 343 kluge.f.significand2 = pu->significand[1]; 344 break; 345 } 346 ret: 347 (*px)[0] = kluge.x[0]; 348 (*px)[1] = kluge.x[1]; 349 (*px)[2] = kluge.x[2]; 350 *ex = (fp_exception_field_type)e; 351 } 352 353 void 354 __pack_quadruple(unpacked *pu, quadruple *px, enum fp_direction_type rd, 355 fp_exception_field_type *ex) 356 { 357 quadruple_equivalence kluge; 358 int e; 359 360 e = 0; 361 kluge.f.msw.sign = pu->sign; 362 switch (pu->fpclass) { 363 case fp_zero: 364 kluge.f.msw.exponent = 0; 365 kluge.f.msw.significand = 0; 366 kluge.f.significand2 = 0; 367 kluge.f.significand3 = 0; 368 kluge.f.significand4 = 0; 369 break; 370 case fp_infinity: 371 infinity: 372 kluge.f.msw.exponent = 0x7fff; 373 kluge.f.msw.significand = 0; 374 kluge.f.significand2 = 0; 375 kluge.f.significand3 = 0; 376 kluge.f.significand4 = 0; 377 break; 378 case fp_quiet: 379 kluge.f.msw.exponent = 0x7fff; 380 __fp_rightshift(pu, 15); 381 kluge.f.msw.significand = 0x8000 | 382 (0xffff & pu->significand[0]); 383 kluge.f.significand2 = pu->significand[1]; 384 kluge.f.significand3 = pu->significand[2]; 385 kluge.f.significand4 = pu->significand[3]; 386 break; 387 case fp_normal: 388 __fp_rightshift(pu, 15); 389 pu->exponent += QUAD_BIAS; 390 if (pu->exponent <= 0) { /* underflow */ 391 __fp_rightshift(pu, 1 - pu->exponent); 392 round(pu, 4, rd, &e); 393 if (pu->significand[0] == 0x10000) { 394 /* rounded back up to normal */ 395 kluge.f.msw.exponent = 1; 396 kluge.f.msw.significand = 0; 397 kluge.f.significand2 = 0; 398 kluge.f.significand3 = 0; 399 kluge.f.significand4 = 0; 400 e |= (1 << fp_underflow); 401 goto ret; 402 } 403 if (e & (1 << fp_inexact)) 404 e |= (1 << fp_underflow); 405 kluge.f.msw.exponent = 0; 406 kluge.f.msw.significand = 0xffff & pu->significand[0]; 407 kluge.f.significand2 = pu->significand[1]; 408 kluge.f.significand3 = pu->significand[2]; 409 kluge.f.significand4 = pu->significand[3]; 410 goto ret; 411 } 412 round(pu, 4, rd, &e); 413 if (pu->significand[0] == 0x20000) { /* rounding overflow */ 414 pu->significand[0] = 0x10000; 415 pu->exponent += 1; 416 } 417 if (pu->exponent >= 0x7fff) { /* overflow */ 418 e |= (1 << fp_overflow) | (1 << fp_inexact); 419 if (overflow_to_infinity(pu->sign, rd)) 420 goto infinity; 421 kluge.f.msw.exponent = 0x7ffe; 422 kluge.f.msw.significand = 0xffff; 423 kluge.f.significand2 = 0xffffffff; 424 kluge.f.significand3 = 0xffffffff; 425 kluge.f.significand4 = 0xffffffff; 426 goto ret; 427 } 428 kluge.f.msw.exponent = pu->exponent; 429 kluge.f.msw.significand = pu->significand[0] & 0xffff; 430 kluge.f.significand2 = pu->significand[1]; 431 kluge.f.significand3 = pu->significand[2]; 432 kluge.f.significand4 = pu->significand[3]; 433 break; 434 } 435 ret: 436 *px = kluge.x; 437 *ex = (fp_exception_field_type)e; 438 } 439