1 /* 2 * Linux/PA-RISC Project (http://www.parisc-linux.org/) 3 * 4 * Floating-point emulation code 5 * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org> 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 2, or (at your option) 10 * any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 */ 21 /* 22 * BEGIN_DESC 23 * 24 * File: 25 * @(#) pa/spmath/fcnvfu.c $Revision: 1.1 $ 26 * 27 * Purpose: 28 * Floating-point to Unsigned Fixed-point Converts 29 * 30 * External Interfaces: 31 * dbl_to_dbl_fcnvfu(srcptr,nullptr,dstptr,status) 32 * dbl_to_sgl_fcnvfu(srcptr,nullptr,dstptr,status) 33 * sgl_to_dbl_fcnvfu(srcptr,nullptr,dstptr,status) 34 * sgl_to_sgl_fcnvfu(srcptr,nullptr,dstptr,status) 35 * 36 * Internal Interfaces: 37 * 38 * Theory: 39 * <<please update with a overview of the operation of this file>> 40 * 41 * END_DESC 42 */ 43 44 45 #include "float.h" 46 #include "sgl_float.h" 47 #include "dbl_float.h" 48 #include "cnv_float.h" 49 50 /************************************************************************ 51 * Floating-point to Unsigned Fixed-point Converts * 52 ************************************************************************/ 53 54 /* 55 * Single Floating-point to Single Unsigned Fixed 56 */ 57 /*ARGSUSED*/ 58 int 59 sgl_to_sgl_fcnvfu( 60 sgl_floating_point *srcptr, 61 unsigned int *nullptr, 62 unsigned int *dstptr, 63 unsigned int *status) 64 { 65 register unsigned int src, result; 66 register int src_exponent; 67 register boolean inexact = FALSE; 68 69 src = *srcptr; 70 src_exponent = Sgl_exponent(src) - SGL_BIAS; 71 72 /* 73 * Test for overflow 74 */ 75 if (src_exponent > SGL_FX_MAX_EXP + 1) { 76 if (Sgl_isone_sign(src)) { 77 result = 0; 78 } else { 79 result = 0xffffffff; 80 } 81 if (Is_invalidtrap_enabled()) { 82 return(INVALIDEXCEPTION); 83 } 84 Set_invalidflag(); 85 *dstptr = result; 86 return(NOEXCEPTION); 87 } 88 /* 89 * Generate result 90 */ 91 if (src_exponent >= 0) { 92 /* 93 * Check sign. 94 * If negative, trap unimplemented. 95 */ 96 if (Sgl_isone_sign(src)) { 97 result = 0; 98 if (Is_invalidtrap_enabled()) { 99 return(INVALIDEXCEPTION); 100 } 101 Set_invalidflag(); 102 *dstptr = result; 103 return(NOEXCEPTION); 104 } 105 Sgl_clear_signexponent_set_hidden(src); 106 Suint_from_sgl_mantissa(src,src_exponent,result); 107 108 /* check for inexact */ 109 if (Sgl_isinexact_to_unsigned(src,src_exponent)) { 110 inexact = TRUE; 111 /* round result */ 112 switch (Rounding_mode()) { 113 case ROUNDPLUS: 114 result++; 115 break; 116 case ROUNDMINUS: /* never negative */ 117 break; 118 case ROUNDNEAREST: 119 if (Sgl_isone_roundbit(src,src_exponent) && 120 (Sgl_isone_stickybit(src,src_exponent) || 121 (result & 1))) { 122 result++; 123 } 124 break; 125 } 126 } 127 } else { 128 result = 0; 129 130 /* check for inexact */ 131 if (Sgl_isnotzero_exponentmantissa(src)) { 132 inexact = TRUE; 133 /* round result */ 134 switch (Rounding_mode()) { 135 case ROUNDPLUS: 136 if (Sgl_iszero_sign(src)) { 137 result++; 138 } 139 break; 140 case ROUNDMINUS: 141 if (Sgl_isone_sign(src)) { 142 result = 0; 143 if (Is_invalidtrap_enabled()) { 144 return(INVALIDEXCEPTION); 145 } 146 Set_invalidflag(); 147 inexact = FALSE; 148 } 149 break; 150 case ROUNDNEAREST: 151 if (src_exponent == -1 && 152 Sgl_isnotzero_mantissa(src)) { 153 if (Sgl_isone_sign(src)) { 154 result = 0; 155 if (Is_invalidtrap_enabled()) { 156 return(INVALIDEXCEPTION); 157 } 158 Set_invalidflag(); 159 inexact = FALSE; 160 } 161 else result++; 162 } 163 break; 164 } 165 } 166 } 167 *dstptr = result; 168 if (inexact) { 169 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); 170 else Set_inexactflag(); 171 } 172 return(NOEXCEPTION); 173 } 174 175 /* 176 * Single Floating-point to Double Unsigned Fixed 177 */ 178 /*ARGSUSED*/ 179 int 180 sgl_to_dbl_fcnvfu( 181 sgl_floating_point *srcptr, 182 unsigned int *nullptr, 183 dbl_unsigned *dstptr, 184 unsigned int *status) 185 { 186 register int src_exponent; 187 register unsigned int src, resultp1, resultp2; 188 register boolean inexact = FALSE; 189 190 src = *srcptr; 191 src_exponent = Sgl_exponent(src) - SGL_BIAS; 192 193 /* 194 * Test for overflow 195 */ 196 if (src_exponent > DBL_FX_MAX_EXP + 1) { 197 if (Sgl_isone_sign(src)) { 198 resultp1 = resultp2 = 0; 199 } else { 200 resultp1 = resultp2 = 0xffffffff; 201 } 202 if (Is_invalidtrap_enabled()) { 203 return(INVALIDEXCEPTION); 204 } 205 Set_invalidflag(); 206 Duint_copytoptr(resultp1,resultp2,dstptr); 207 return(NOEXCEPTION); 208 } 209 /* 210 * Generate result 211 */ 212 if (src_exponent >= 0) { 213 /* 214 * Check sign. 215 * If negative, trap unimplemented. 216 */ 217 if (Sgl_isone_sign(src)) { 218 resultp1 = resultp2 = 0; 219 if (Is_invalidtrap_enabled()) { 220 return(INVALIDEXCEPTION); 221 } 222 Set_invalidflag(); 223 Duint_copytoptr(resultp1,resultp2,dstptr); 224 return(NOEXCEPTION); 225 } 226 Sgl_clear_signexponent_set_hidden(src); 227 Duint_from_sgl_mantissa(src,src_exponent,resultp1,resultp2); 228 229 /* check for inexact */ 230 if (Sgl_isinexact_to_unsigned(src,src_exponent)) { 231 inexact = TRUE; 232 /* round result */ 233 switch (Rounding_mode()) { 234 case ROUNDPLUS: 235 Duint_increment(resultp1,resultp2); 236 break; 237 case ROUNDMINUS: /* never negative */ 238 break; 239 case ROUNDNEAREST: 240 if (Sgl_isone_roundbit(src,src_exponent) && 241 (Sgl_isone_stickybit(src,src_exponent) || 242 Duint_isone_lowp2(resultp2))) { 243 Duint_increment(resultp1,resultp2); 244 } 245 break; 246 } 247 } 248 } else { 249 Duint_setzero(resultp1,resultp2); 250 251 /* check for inexact */ 252 if (Sgl_isnotzero_exponentmantissa(src)) { 253 inexact = TRUE; 254 /* round result */ 255 switch (Rounding_mode()) { 256 case ROUNDPLUS: 257 if (Sgl_iszero_sign(src)) { 258 Duint_increment(resultp1,resultp2); 259 } 260 break; 261 case ROUNDMINUS: 262 if (Sgl_isone_sign(src)) { 263 resultp1 = resultp2 = 0; 264 if (Is_invalidtrap_enabled()) { 265 return(INVALIDEXCEPTION); 266 } 267 Set_invalidflag(); 268 inexact = FALSE; 269 } 270 break; 271 case ROUNDNEAREST: 272 if (src_exponent == -1 && 273 Sgl_isnotzero_mantissa(src)) { 274 if (Sgl_isone_sign(src)) { 275 resultp1 = 0; 276 resultp2 = 0; 277 if (Is_invalidtrap_enabled()) { 278 return(INVALIDEXCEPTION); 279 } 280 Set_invalidflag(); 281 inexact = FALSE; 282 } 283 else Duint_increment(resultp1,resultp2); 284 } 285 } 286 } 287 } 288 Duint_copytoptr(resultp1,resultp2,dstptr); 289 if (inexact) { 290 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); 291 else Set_inexactflag(); 292 } 293 return(NOEXCEPTION); 294 } 295 296 /* 297 * Double Floating-point to Single Unsigned Fixed 298 */ 299 /*ARGSUSED*/ 300 int 301 dbl_to_sgl_fcnvfu (dbl_floating_point * srcptr, unsigned int *nullptr, 302 unsigned int *dstptr, unsigned int *status) 303 { 304 register unsigned int srcp1, srcp2, result; 305 register int src_exponent; 306 register boolean inexact = FALSE; 307 308 Dbl_copyfromptr(srcptr,srcp1,srcp2); 309 src_exponent = Dbl_exponent(srcp1) - DBL_BIAS; 310 311 /* 312 * Test for overflow 313 */ 314 if (src_exponent > SGL_FX_MAX_EXP + 1) { 315 if (Dbl_isone_sign(srcp1)) { 316 result = 0; 317 } else { 318 result = 0xffffffff; 319 } 320 if (Is_invalidtrap_enabled()) { 321 return(INVALIDEXCEPTION); 322 } 323 Set_invalidflag(); 324 *dstptr = result; 325 return(NOEXCEPTION); 326 } 327 /* 328 * Generate result 329 */ 330 if (src_exponent >= 0) { 331 /* 332 * Check sign. 333 * If negative, trap unimplemented. 334 */ 335 if (Dbl_isone_sign(srcp1)) { 336 result = 0; 337 if (Is_invalidtrap_enabled()) { 338 return(INVALIDEXCEPTION); 339 } 340 Set_invalidflag(); 341 *dstptr = result; 342 return(NOEXCEPTION); 343 } 344 Dbl_clear_signexponent_set_hidden(srcp1); 345 Suint_from_dbl_mantissa(srcp1,srcp2,src_exponent,result); 346 347 /* check for inexact */ 348 if (Dbl_isinexact_to_unsigned(srcp1,srcp2,src_exponent)) { 349 inexact = TRUE; 350 /* round result */ 351 switch (Rounding_mode()) { 352 case ROUNDPLUS: 353 result++; 354 break; 355 case ROUNDMINUS: /* never negative */ 356 break; 357 case ROUNDNEAREST: 358 if(Dbl_isone_roundbit(srcp1,srcp2,src_exponent) && 359 (Dbl_isone_stickybit(srcp1,srcp2,src_exponent)|| 360 result&1)) 361 result++; 362 break; 363 } 364 /* check for overflow */ 365 if (result == 0) { 366 result = 0xffffffff; 367 if (Is_invalidtrap_enabled()) { 368 return(INVALIDEXCEPTION); 369 } 370 Set_invalidflag(); 371 *dstptr = result; 372 return(NOEXCEPTION); 373 } 374 } 375 } else { 376 result = 0; 377 378 /* check for inexact */ 379 if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) { 380 inexact = TRUE; 381 /* round result */ 382 switch (Rounding_mode()) { 383 case ROUNDPLUS: 384 if (Dbl_iszero_sign(srcp1)) result++; 385 break; 386 case ROUNDMINUS: 387 if (Dbl_isone_sign(srcp1)) { 388 result = 0; 389 if (Is_invalidtrap_enabled()) { 390 return(INVALIDEXCEPTION); 391 } 392 Set_invalidflag(); 393 inexact = FALSE; 394 } 395 break; 396 case ROUNDNEAREST: 397 if (src_exponent == -1 && 398 Dbl_isnotzero_mantissa(srcp1,srcp2)) 399 if (Dbl_isone_sign(srcp1)) { 400 result = 0; 401 if (Is_invalidtrap_enabled()) { 402 return(INVALIDEXCEPTION); 403 } 404 Set_invalidflag(); 405 inexact = FALSE; 406 } 407 else result++; 408 } 409 } 410 } 411 *dstptr = result; 412 if (inexact) { 413 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); 414 else Set_inexactflag(); 415 } 416 return(NOEXCEPTION); 417 } 418 419 /* 420 * Double Floating-point to Double Unsigned Fixed 421 */ 422 /*ARGSUSED*/ 423 int 424 dbl_to_dbl_fcnvfu (dbl_floating_point * srcptr, unsigned int *nullptr, 425 dbl_unsigned * dstptr, unsigned int *status) 426 { 427 register int src_exponent; 428 register unsigned int srcp1, srcp2, resultp1, resultp2; 429 register boolean inexact = FALSE; 430 431 Dbl_copyfromptr(srcptr,srcp1,srcp2); 432 src_exponent = Dbl_exponent(srcp1) - DBL_BIAS; 433 434 /* 435 * Test for overflow 436 */ 437 if (src_exponent > DBL_FX_MAX_EXP + 1) { 438 if (Dbl_isone_sign(srcp1)) { 439 resultp1 = resultp2 = 0; 440 } else { 441 resultp1 = resultp2 = 0xffffffff; 442 } 443 if (Is_invalidtrap_enabled()) { 444 return(INVALIDEXCEPTION); 445 } 446 Set_invalidflag(); 447 Duint_copytoptr(resultp1,resultp2,dstptr); 448 return(NOEXCEPTION); 449 } 450 451 /* 452 * Generate result 453 */ 454 if (src_exponent >= 0) { 455 /* 456 * Check sign. 457 * If negative, trap unimplemented. 458 */ 459 if (Dbl_isone_sign(srcp1)) { 460 resultp1 = resultp2 = 0; 461 if (Is_invalidtrap_enabled()) { 462 return(INVALIDEXCEPTION); 463 } 464 Set_invalidflag(); 465 Duint_copytoptr(resultp1,resultp2,dstptr); 466 return(NOEXCEPTION); 467 } 468 Dbl_clear_signexponent_set_hidden(srcp1); 469 Duint_from_dbl_mantissa(srcp1,srcp2,src_exponent,resultp1, 470 resultp2); 471 472 /* check for inexact */ 473 if (Dbl_isinexact_to_unsigned(srcp1,srcp2,src_exponent)) { 474 inexact = TRUE; 475 /* round result */ 476 switch (Rounding_mode()) { 477 case ROUNDPLUS: 478 Duint_increment(resultp1,resultp2); 479 break; 480 case ROUNDMINUS: /* never negative */ 481 break; 482 case ROUNDNEAREST: 483 if(Dbl_isone_roundbit(srcp1,srcp2,src_exponent)) 484 if(Dbl_isone_stickybit(srcp1,srcp2,src_exponent) || 485 Duint_isone_lowp2(resultp2)) 486 Duint_increment(resultp1,resultp2); 487 } 488 } 489 } else { 490 Duint_setzero(resultp1,resultp2); 491 492 /* check for inexact */ 493 if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) { 494 inexact = TRUE; 495 /* round result */ 496 switch (Rounding_mode()) { 497 case ROUNDPLUS: 498 if (Dbl_iszero_sign(srcp1)) { 499 Duint_increment(resultp1,resultp2); 500 } 501 break; 502 case ROUNDMINUS: 503 if (Dbl_isone_sign(srcp1)) { 504 resultp1 = resultp2 = 0; 505 if (Is_invalidtrap_enabled()) { 506 return(INVALIDEXCEPTION); 507 } 508 Set_invalidflag(); 509 inexact = FALSE; 510 } 511 break; 512 case ROUNDNEAREST: 513 if (src_exponent == -1 && 514 Dbl_isnotzero_mantissa(srcp1,srcp2)) 515 if (Dbl_iszero_sign(srcp1)) { 516 Duint_increment(resultp1,resultp2); 517 } else { 518 resultp1 = 0; 519 resultp2 = 0; 520 if (Is_invalidtrap_enabled()) { 521 return(INVALIDEXCEPTION); 522 } 523 Set_invalidflag(); 524 inexact = FALSE; 525 } 526 } 527 } 528 } 529 Duint_copytoptr(resultp1,resultp2,dstptr); 530 if (inexact) { 531 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); 532 else Set_inexactflag(); 533 } 534 return(NOEXCEPTION); 535 } 536 537