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/fcnvfx.c $Revision: 1.1 $ 26 * 27 * Purpose: 28 * Single Floating-point to Single Fixed-point 29 * Single Floating-point to Double Fixed-point 30 * Double Floating-point to Single Fixed-point 31 * Double Floating-point to Double Fixed-point 32 * 33 * External Interfaces: 34 * dbl_to_dbl_fcnvfx(srcptr,nullptr,dstptr,status) 35 * dbl_to_sgl_fcnvfx(srcptr,nullptr,dstptr,status) 36 * sgl_to_dbl_fcnvfx(srcptr,nullptr,dstptr,status) 37 * sgl_to_sgl_fcnvfx(srcptr,nullptr,dstptr,status) 38 * 39 * Internal Interfaces: 40 * 41 * Theory: 42 * <<please update with a overview of the operation of this file>> 43 * 44 * END_DESC 45 */ 46 47 48 #include "float.h" 49 #include "sgl_float.h" 50 #include "dbl_float.h" 51 #include "cnv_float.h" 52 53 /* 54 * Single Floating-point to Single Fixed-point 55 */ 56 /*ARGSUSED*/ 57 int 58 sgl_to_sgl_fcnvfx( 59 sgl_floating_point *srcptr, 60 sgl_floating_point *nullptr, 61 int *dstptr, 62 sgl_floating_point *status) 63 { 64 register unsigned int src, temp; 65 register int src_exponent, result; 66 register boolean inexact = FALSE; 67 68 src = *srcptr; 69 src_exponent = Sgl_exponent(src) - SGL_BIAS; 70 71 /* 72 * Test for overflow 73 */ 74 if (src_exponent > SGL_FX_MAX_EXP) { 75 /* check for MININT */ 76 if ((src_exponent > SGL_FX_MAX_EXP + 1) || 77 Sgl_isnotzero_mantissa(src) || Sgl_iszero_sign(src)) { 78 if (Sgl_iszero_sign(src)) result = 0x7fffffff; 79 else result = 0x80000000; 80 81 if (Is_invalidtrap_enabled()) { 82 return(INVALIDEXCEPTION); 83 } 84 Set_invalidflag(); 85 *dstptr = result; 86 return(NOEXCEPTION); 87 } 88 } 89 /* 90 * Generate result 91 */ 92 if (src_exponent >= 0) { 93 temp = src; 94 Sgl_clear_signexponent_set_hidden(temp); 95 Int_from_sgl_mantissa(temp,src_exponent); 96 if (Sgl_isone_sign(src)) result = -Sgl_all(temp); 97 else result = Sgl_all(temp); 98 99 /* check for inexact */ 100 if (Sgl_isinexact_to_fix(src,src_exponent)) { 101 inexact = TRUE; 102 /* round result */ 103 switch (Rounding_mode()) { 104 case ROUNDPLUS: 105 if (Sgl_iszero_sign(src)) result++; 106 break; 107 case ROUNDMINUS: 108 if (Sgl_isone_sign(src)) result--; 109 break; 110 case ROUNDNEAREST: 111 if (Sgl_isone_roundbit(src,src_exponent)) { 112 if (Sgl_isone_stickybit(src,src_exponent) 113 || (Sgl_isone_lowmantissa(temp))) 114 if (Sgl_iszero_sign(src)) result++; 115 else result--; 116 } 117 } 118 } 119 } 120 else { 121 result = 0; 122 123 /* check for inexact */ 124 if (Sgl_isnotzero_exponentmantissa(src)) { 125 inexact = TRUE; 126 /* round result */ 127 switch (Rounding_mode()) { 128 case ROUNDPLUS: 129 if (Sgl_iszero_sign(src)) result++; 130 break; 131 case ROUNDMINUS: 132 if (Sgl_isone_sign(src)) result--; 133 break; 134 case ROUNDNEAREST: 135 if (src_exponent == -1) 136 if (Sgl_isnotzero_mantissa(src)) 137 if (Sgl_iszero_sign(src)) result++; 138 else result--; 139 } 140 } 141 } 142 *dstptr = result; 143 if (inexact) { 144 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); 145 else Set_inexactflag(); 146 } 147 return(NOEXCEPTION); 148 } 149 150 /* 151 * Single Floating-point to Double Fixed-point 152 */ 153 /*ARGSUSED*/ 154 int 155 sgl_to_dbl_fcnvfx( 156 sgl_floating_point *srcptr, 157 unsigned int *nullptr, 158 dbl_integer *dstptr, 159 unsigned int *status) 160 { 161 register int src_exponent, resultp1; 162 register unsigned int src, temp, resultp2; 163 register boolean inexact = FALSE; 164 165 src = *srcptr; 166 src_exponent = Sgl_exponent(src) - SGL_BIAS; 167 168 /* 169 * Test for overflow 170 */ 171 if (src_exponent > DBL_FX_MAX_EXP) { 172 /* check for MININT */ 173 if ((src_exponent > DBL_FX_MAX_EXP + 1) || 174 Sgl_isnotzero_mantissa(src) || Sgl_iszero_sign(src)) { 175 if (Sgl_iszero_sign(src)) { 176 resultp1 = 0x7fffffff; 177 resultp2 = 0xffffffff; 178 } 179 else { 180 resultp1 = 0x80000000; 181 resultp2 = 0; 182 } 183 if (Is_invalidtrap_enabled()) { 184 return(INVALIDEXCEPTION); 185 } 186 Set_invalidflag(); 187 Dint_copytoptr(resultp1,resultp2,dstptr); 188 return(NOEXCEPTION); 189 } 190 Dint_set_minint(resultp1,resultp2); 191 Dint_copytoptr(resultp1,resultp2,dstptr); 192 return(NOEXCEPTION); 193 } 194 /* 195 * Generate result 196 */ 197 if (src_exponent >= 0) { 198 temp = src; 199 Sgl_clear_signexponent_set_hidden(temp); 200 Dint_from_sgl_mantissa(temp,src_exponent,resultp1,resultp2); 201 if (Sgl_isone_sign(src)) { 202 Dint_setone_sign(resultp1,resultp2); 203 } 204 205 /* check for inexact */ 206 if (Sgl_isinexact_to_fix(src,src_exponent)) { 207 inexact = TRUE; 208 /* round result */ 209 switch (Rounding_mode()) { 210 case ROUNDPLUS: 211 if (Sgl_iszero_sign(src)) { 212 Dint_increment(resultp1,resultp2); 213 } 214 break; 215 case ROUNDMINUS: 216 if (Sgl_isone_sign(src)) { 217 Dint_decrement(resultp1,resultp2); 218 } 219 break; 220 case ROUNDNEAREST: 221 if (Sgl_isone_roundbit(src,src_exponent)) 222 if (Sgl_isone_stickybit(src,src_exponent) || 223 (Dint_isone_lowp2(resultp2))) 224 if (Sgl_iszero_sign(src)) { 225 Dint_increment(resultp1,resultp2); 226 } 227 else { 228 Dint_decrement(resultp1,resultp2); 229 } 230 } 231 } 232 } 233 else { 234 Dint_setzero(resultp1,resultp2); 235 236 /* check for inexact */ 237 if (Sgl_isnotzero_exponentmantissa(src)) { 238 inexact = TRUE; 239 /* round result */ 240 switch (Rounding_mode()) { 241 case ROUNDPLUS: 242 if (Sgl_iszero_sign(src)) { 243 Dint_increment(resultp1,resultp2); 244 } 245 break; 246 case ROUNDMINUS: 247 if (Sgl_isone_sign(src)) { 248 Dint_decrement(resultp1,resultp2); 249 } 250 break; 251 case ROUNDNEAREST: 252 if (src_exponent == -1) 253 if (Sgl_isnotzero_mantissa(src)) 254 if (Sgl_iszero_sign(src)) { 255 Dint_increment(resultp1,resultp2); 256 } 257 else { 258 Dint_decrement(resultp1,resultp2); 259 } 260 } 261 } 262 } 263 Dint_copytoptr(resultp1,resultp2,dstptr); 264 if (inexact) { 265 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); 266 else Set_inexactflag(); 267 } 268 return(NOEXCEPTION); 269 } 270 271 /* 272 * Double Floating-point to Single Fixed-point 273 */ 274 /*ARGSUSED*/ 275 int 276 dbl_to_sgl_fcnvfx( 277 dbl_floating_point *srcptr, 278 unsigned int *nullptr, 279 int *dstptr, 280 unsigned int *status) 281 { 282 register unsigned int srcp1,srcp2, tempp1,tempp2; 283 register int src_exponent, result; 284 register boolean inexact = FALSE; 285 286 Dbl_copyfromptr(srcptr,srcp1,srcp2); 287 src_exponent = Dbl_exponent(srcp1) - DBL_BIAS; 288 289 /* 290 * Test for overflow 291 */ 292 if (src_exponent > SGL_FX_MAX_EXP) { 293 /* check for MININT */ 294 if (Dbl_isoverflow_to_int(src_exponent,srcp1,srcp2)) { 295 if (Dbl_iszero_sign(srcp1)) result = 0x7fffffff; 296 else result = 0x80000000; 297 298 if (Is_invalidtrap_enabled()) { 299 return(INVALIDEXCEPTION); 300 } 301 Set_invalidflag(); 302 *dstptr = result; 303 return(NOEXCEPTION); 304 } 305 } 306 /* 307 * Generate result 308 */ 309 if (src_exponent >= 0) { 310 tempp1 = srcp1; 311 tempp2 = srcp2; 312 Dbl_clear_signexponent_set_hidden(tempp1); 313 Int_from_dbl_mantissa(tempp1,tempp2,src_exponent); 314 if (Dbl_isone_sign(srcp1) && (src_exponent <= SGL_FX_MAX_EXP)) 315 result = -Dbl_allp1(tempp1); 316 else result = Dbl_allp1(tempp1); 317 318 /* check for inexact */ 319 if (Dbl_isinexact_to_fix(srcp1,srcp2,src_exponent)) { 320 inexact = TRUE; 321 /* round result */ 322 switch (Rounding_mode()) { 323 case ROUNDPLUS: 324 if (Dbl_iszero_sign(srcp1)) result++; 325 break; 326 case ROUNDMINUS: 327 if (Dbl_isone_sign(srcp1)) result--; 328 break; 329 case ROUNDNEAREST: 330 if (Dbl_isone_roundbit(srcp1,srcp2,src_exponent)) 331 if (Dbl_isone_stickybit(srcp1,srcp2,src_exponent) || 332 (Dbl_isone_lowmantissap1(tempp1))) 333 if (Dbl_iszero_sign(srcp1)) result++; 334 else result--; 335 } 336 /* check for overflow */ 337 if ((Dbl_iszero_sign(srcp1) && result < 0) || 338 (Dbl_isone_sign(srcp1) && result > 0)) { 339 340 if (Dbl_iszero_sign(srcp1)) result = 0x7fffffff; 341 else result = 0x80000000; 342 343 if (Is_invalidtrap_enabled()) { 344 return(INVALIDEXCEPTION); 345 } 346 Set_invalidflag(); 347 *dstptr = result; 348 return(NOEXCEPTION); 349 } 350 } 351 } 352 else { 353 result = 0; 354 355 /* check for inexact */ 356 if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) { 357 inexact = TRUE; 358 /* round result */ 359 switch (Rounding_mode()) { 360 case ROUNDPLUS: 361 if (Dbl_iszero_sign(srcp1)) result++; 362 break; 363 case ROUNDMINUS: 364 if (Dbl_isone_sign(srcp1)) result--; 365 break; 366 case ROUNDNEAREST: 367 if (src_exponent == -1) 368 if (Dbl_isnotzero_mantissa(srcp1,srcp2)) 369 if (Dbl_iszero_sign(srcp1)) result++; 370 else result--; 371 } 372 } 373 } 374 *dstptr = result; 375 if (inexact) { 376 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); 377 else Set_inexactflag(); 378 } 379 return(NOEXCEPTION); 380 } 381 382 /* 383 * Double Floating-point to Double Fixed-point 384 */ 385 /*ARGSUSED*/ 386 int 387 dbl_to_dbl_fcnvfx( 388 dbl_floating_point *srcptr, 389 unsigned int *nullptr, 390 dbl_integer *dstptr, 391 unsigned int *status) 392 { 393 register int src_exponent, resultp1; 394 register unsigned int srcp1, srcp2, tempp1, tempp2, resultp2; 395 register boolean inexact = FALSE; 396 397 Dbl_copyfromptr(srcptr,srcp1,srcp2); 398 src_exponent = Dbl_exponent(srcp1) - DBL_BIAS; 399 400 /* 401 * Test for overflow 402 */ 403 if (src_exponent > DBL_FX_MAX_EXP) { 404 /* check for MININT */ 405 if ((src_exponent > DBL_FX_MAX_EXP + 1) || 406 Dbl_isnotzero_mantissa(srcp1,srcp2) || Dbl_iszero_sign(srcp1)) { 407 if (Dbl_iszero_sign(srcp1)) { 408 resultp1 = 0x7fffffff; 409 resultp2 = 0xffffffff; 410 } 411 else { 412 resultp1 = 0x80000000; 413 resultp2 = 0; 414 } 415 if (Is_invalidtrap_enabled()) { 416 return(INVALIDEXCEPTION); 417 } 418 Set_invalidflag(); 419 Dint_copytoptr(resultp1,resultp2,dstptr); 420 return(NOEXCEPTION); 421 } 422 } 423 424 /* 425 * Generate result 426 */ 427 if (src_exponent >= 0) { 428 tempp1 = srcp1; 429 tempp2 = srcp2; 430 Dbl_clear_signexponent_set_hidden(tempp1); 431 Dint_from_dbl_mantissa(tempp1,tempp2,src_exponent,resultp1, 432 resultp2); 433 if (Dbl_isone_sign(srcp1)) { 434 Dint_setone_sign(resultp1,resultp2); 435 } 436 437 /* check for inexact */ 438 if (Dbl_isinexact_to_fix(srcp1,srcp2,src_exponent)) { 439 inexact = TRUE; 440 /* round result */ 441 switch (Rounding_mode()) { 442 case ROUNDPLUS: 443 if (Dbl_iszero_sign(srcp1)) { 444 Dint_increment(resultp1,resultp2); 445 } 446 break; 447 case ROUNDMINUS: 448 if (Dbl_isone_sign(srcp1)) { 449 Dint_decrement(resultp1,resultp2); 450 } 451 break; 452 case ROUNDNEAREST: 453 if (Dbl_isone_roundbit(srcp1,srcp2,src_exponent)) 454 if (Dbl_isone_stickybit(srcp1,srcp2,src_exponent) || 455 (Dint_isone_lowp2(resultp2))) 456 if (Dbl_iszero_sign(srcp1)) { 457 Dint_increment(resultp1,resultp2); 458 } 459 else { 460 Dint_decrement(resultp1,resultp2); 461 } 462 } 463 } 464 } 465 else { 466 Dint_setzero(resultp1,resultp2); 467 468 /* check for inexact */ 469 if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) { 470 inexact = TRUE; 471 /* round result */ 472 switch (Rounding_mode()) { 473 case ROUNDPLUS: 474 if (Dbl_iszero_sign(srcp1)) { 475 Dint_increment(resultp1,resultp2); 476 } 477 break; 478 case ROUNDMINUS: 479 if (Dbl_isone_sign(srcp1)) { 480 Dint_decrement(resultp1,resultp2); 481 } 482 break; 483 case ROUNDNEAREST: 484 if (src_exponent == -1) 485 if (Dbl_isnotzero_mantissa(srcp1,srcp2)) 486 if (Dbl_iszero_sign(srcp1)) { 487 Dint_increment(resultp1,resultp2); 488 } 489 else { 490 Dint_decrement(resultp1,resultp2); 491 } 492 } 493 } 494 } 495 Dint_copytoptr(resultp1,resultp2,dstptr); 496 if (inexact) { 497 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); 498 else Set_inexactflag(); 499 } 500 return(NOEXCEPTION); 501 } 502