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