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