root/arch/parisc/math-emu/fcnvfx.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. sgl_to_sgl_fcnvfx
  2. sgl_to_dbl_fcnvfx
  3. dbl_to_sgl_fcnvfx
  4. dbl_to_dbl_fcnvfx

   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 }

/* [<][>][^][v][top][bottom][index][help] */