linux/arch/parisc/math-emu/fcnvfx.c
<<
>>
Prefs
   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*/
  57int
  58sgl_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*/
 154int
 155sgl_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*/
 275int
 276dbl_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*/
 386int
 387dbl_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