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

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

DEFINITIONS

This source file includes following definitions.
  1. sgl_to_sgl_fcnvfu
  2. sgl_to_dbl_fcnvfu
  3. dbl_to_sgl_fcnvfu
  4. dbl_to_dbl_fcnvfu

   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 

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