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

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

DEFINITIONS

This source file includes following definitions.
  1. dbl_fmpy

   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/dfmpy.c               $Revision: 1.1 $
  13  *
  14  *  Purpose:
  15  *      Double Precision Floating-point Multiply
  16  *
  17  *  External Interfaces:
  18  *      dbl_fmpy(srcptr1,srcptr2,dstptr,status)
  19  *
  20  *  Internal Interfaces:
  21  *
  22  *  Theory:
  23  *      <<please update with a overview of the operation of this file>>
  24  *
  25  * END_DESC
  26 */
  27 
  28 
  29 #include "float.h"
  30 #include "dbl_float.h"
  31 
  32 /*
  33  *  Double Precision Floating-point Multiply
  34  */
  35 
  36 int
  37 dbl_fmpy(
  38             dbl_floating_point *srcptr1,
  39             dbl_floating_point *srcptr2,
  40             dbl_floating_point *dstptr,
  41             unsigned int *status)
  42 {
  43         register unsigned int opnd1p1, opnd1p2, opnd2p1, opnd2p2;
  44         register unsigned int opnd3p1, opnd3p2, resultp1, resultp2;
  45         register int dest_exponent, count;
  46         register boolean inexact = FALSE, guardbit = FALSE, stickybit = FALSE;
  47         boolean is_tiny;
  48 
  49         Dbl_copyfromptr(srcptr1,opnd1p1,opnd1p2);
  50         Dbl_copyfromptr(srcptr2,opnd2p1,opnd2p2);
  51 
  52         /* 
  53          * set sign bit of result 
  54          */
  55         if (Dbl_sign(opnd1p1) ^ Dbl_sign(opnd2p1)) 
  56                 Dbl_setnegativezerop1(resultp1); 
  57         else Dbl_setzerop1(resultp1);
  58         /*
  59          * check first operand for NaN's or infinity
  60          */
  61         if (Dbl_isinfinity_exponent(opnd1p1)) {
  62                 if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) {
  63                         if (Dbl_isnotnan(opnd2p1,opnd2p2)) {
  64                                 if (Dbl_iszero_exponentmantissa(opnd2p1,opnd2p2)) {
  65                                         /* 
  66                                          * invalid since operands are infinity 
  67                                          * and zero 
  68                                          */
  69                                         if (Is_invalidtrap_enabled())
  70                                                 return(INVALIDEXCEPTION);
  71                                         Set_invalidflag();
  72                                         Dbl_makequietnan(resultp1,resultp2);
  73                                         Dbl_copytoptr(resultp1,resultp2,dstptr);
  74                                         return(NOEXCEPTION);
  75                                 }
  76                                 /*
  77                                  * return infinity
  78                                  */
  79                                 Dbl_setinfinity_exponentmantissa(resultp1,resultp2);
  80                                 Dbl_copytoptr(resultp1,resultp2,dstptr);
  81                                 return(NOEXCEPTION);
  82                         }
  83                 }
  84                 else {
  85                         /*
  86                          * is NaN; signaling or quiet?
  87                          */
  88                         if (Dbl_isone_signaling(opnd1p1)) {
  89                                 /* trap if INVALIDTRAP enabled */
  90                                 if (Is_invalidtrap_enabled()) 
  91                                         return(INVALIDEXCEPTION);
  92                                 /* make NaN quiet */
  93                                 Set_invalidflag();
  94                                 Dbl_set_quiet(opnd1p1);
  95                         }
  96                         /* 
  97                          * is second operand a signaling NaN? 
  98                          */
  99                         else if (Dbl_is_signalingnan(opnd2p1)) {
 100                                 /* trap if INVALIDTRAP enabled */
 101                                 if (Is_invalidtrap_enabled())
 102                                         return(INVALIDEXCEPTION);
 103                                 /* make NaN quiet */
 104                                 Set_invalidflag();
 105                                 Dbl_set_quiet(opnd2p1);
 106                                 Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
 107                                 return(NOEXCEPTION);
 108                         }
 109                         /*
 110                          * return quiet NaN
 111                          */
 112                         Dbl_copytoptr(opnd1p1,opnd1p2,dstptr);
 113                         return(NOEXCEPTION);
 114                 }
 115         }
 116         /*
 117          * check second operand for NaN's or infinity
 118          */
 119         if (Dbl_isinfinity_exponent(opnd2p1)) {
 120                 if (Dbl_iszero_mantissa(opnd2p1,opnd2p2)) {
 121                         if (Dbl_iszero_exponentmantissa(opnd1p1,opnd1p2)) {
 122                                 /* invalid since operands are zero & infinity */
 123                                 if (Is_invalidtrap_enabled())
 124                                         return(INVALIDEXCEPTION);
 125                                 Set_invalidflag();
 126                                 Dbl_makequietnan(opnd2p1,opnd2p2);
 127                                 Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
 128                                 return(NOEXCEPTION);
 129                         }
 130                         /*
 131                          * return infinity
 132                          */
 133                         Dbl_setinfinity_exponentmantissa(resultp1,resultp2);
 134                         Dbl_copytoptr(resultp1,resultp2,dstptr);
 135                         return(NOEXCEPTION);
 136                 }
 137                 /*
 138                  * is NaN; signaling or quiet?
 139                  */
 140                 if (Dbl_isone_signaling(opnd2p1)) {
 141                         /* trap if INVALIDTRAP enabled */
 142                         if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
 143                         /* make NaN quiet */
 144                         Set_invalidflag();
 145                         Dbl_set_quiet(opnd2p1);
 146                 }
 147                 /*
 148                  * return quiet NaN
 149                  */
 150                 Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
 151                 return(NOEXCEPTION);
 152         }
 153         /*
 154          * Generate exponent 
 155          */
 156         dest_exponent = Dbl_exponent(opnd1p1) + Dbl_exponent(opnd2p1) -DBL_BIAS;
 157 
 158         /*
 159          * Generate mantissa
 160          */
 161         if (Dbl_isnotzero_exponent(opnd1p1)) {
 162                 /* set hidden bit */
 163                 Dbl_clear_signexponent_set_hidden(opnd1p1);
 164         }
 165         else {
 166                 /* check for zero */
 167                 if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) {
 168                         Dbl_setzero_exponentmantissa(resultp1,resultp2);
 169                         Dbl_copytoptr(resultp1,resultp2,dstptr);
 170                         return(NOEXCEPTION);
 171                 }
 172                 /* is denormalized, adjust exponent */
 173                 Dbl_clear_signexponent(opnd1p1);
 174                 Dbl_leftshiftby1(opnd1p1,opnd1p2);
 175                 Dbl_normalize(opnd1p1,opnd1p2,dest_exponent);
 176         }
 177         /* opnd2 needs to have hidden bit set with msb in hidden bit */
 178         if (Dbl_isnotzero_exponent(opnd2p1)) {
 179                 Dbl_clear_signexponent_set_hidden(opnd2p1);
 180         }
 181         else {
 182                 /* check for zero */
 183                 if (Dbl_iszero_mantissa(opnd2p1,opnd2p2)) {
 184                         Dbl_setzero_exponentmantissa(resultp1,resultp2);
 185                         Dbl_copytoptr(resultp1,resultp2,dstptr);
 186                         return(NOEXCEPTION);
 187                 }
 188                 /* is denormalized; want to normalize */
 189                 Dbl_clear_signexponent(opnd2p1);
 190                 Dbl_leftshiftby1(opnd2p1,opnd2p2);
 191                 Dbl_normalize(opnd2p1,opnd2p2,dest_exponent);
 192         }
 193 
 194         /* Multiply two source mantissas together */
 195 
 196         /* make room for guard bits */
 197         Dbl_leftshiftby7(opnd2p1,opnd2p2);
 198         Dbl_setzero(opnd3p1,opnd3p2);
 199         /* 
 200          * Four bits at a time are inspected in each loop, and a 
 201          * simple shift and add multiply algorithm is used. 
 202          */ 
 203         for (count=1;count<=DBL_P;count+=4) {
 204                 stickybit |= Dlow4p2(opnd3p2);
 205                 Dbl_rightshiftby4(opnd3p1,opnd3p2);
 206                 if (Dbit28p2(opnd1p2)) {
 207                         /* Twoword_add should be an ADDC followed by an ADD. */
 208                         Twoword_add(opnd3p1, opnd3p2, opnd2p1<<3 | opnd2p2>>29, 
 209                                     opnd2p2<<3);
 210                 }
 211                 if (Dbit29p2(opnd1p2)) {
 212                         Twoword_add(opnd3p1, opnd3p2, opnd2p1<<2 | opnd2p2>>30, 
 213                                     opnd2p2<<2);
 214                 }
 215                 if (Dbit30p2(opnd1p2)) {
 216                         Twoword_add(opnd3p1, opnd3p2, opnd2p1<<1 | opnd2p2>>31,
 217                                     opnd2p2<<1);
 218                 }
 219                 if (Dbit31p2(opnd1p2)) {
 220                         Twoword_add(opnd3p1, opnd3p2, opnd2p1, opnd2p2);
 221                 }
 222                 Dbl_rightshiftby4(opnd1p1,opnd1p2);
 223         }
 224         if (Dbit3p1(opnd3p1)==0) {
 225                 Dbl_leftshiftby1(opnd3p1,opnd3p2);
 226         }
 227         else {
 228                 /* result mantissa >= 2. */
 229                 dest_exponent++;
 230         }
 231         /* check for denormalized result */
 232         while (Dbit3p1(opnd3p1)==0) {
 233                 Dbl_leftshiftby1(opnd3p1,opnd3p2);
 234                 dest_exponent--;
 235         }
 236         /*
 237          * check for guard, sticky and inexact bits 
 238          */
 239         stickybit |= Dallp2(opnd3p2) << 25;
 240         guardbit = (Dallp2(opnd3p2) << 24) >> 31;
 241         inexact = guardbit | stickybit;
 242 
 243         /* align result mantissa */
 244         Dbl_rightshiftby8(opnd3p1,opnd3p2);
 245 
 246         /* 
 247          * round result 
 248          */
 249         if (inexact && (dest_exponent>0 || Is_underflowtrap_enabled())) {
 250                 Dbl_clear_signexponent(opnd3p1);
 251                 switch (Rounding_mode()) {
 252                         case ROUNDPLUS: 
 253                                 if (Dbl_iszero_sign(resultp1)) 
 254                                         Dbl_increment(opnd3p1,opnd3p2);
 255                                 break;
 256                         case ROUNDMINUS: 
 257                                 if (Dbl_isone_sign(resultp1)) 
 258                                         Dbl_increment(opnd3p1,opnd3p2);
 259                                 break;
 260                         case ROUNDNEAREST:
 261                                 if (guardbit) {
 262                                 if (stickybit || Dbl_isone_lowmantissap2(opnd3p2))
 263                                 Dbl_increment(opnd3p1,opnd3p2);
 264                                 }
 265                 }
 266                 if (Dbl_isone_hidden(opnd3p1)) dest_exponent++;
 267         }
 268         Dbl_set_mantissa(resultp1,resultp2,opnd3p1,opnd3p2);
 269 
 270         /* 
 271          * Test for overflow
 272          */
 273         if (dest_exponent >= DBL_INFINITY_EXPONENT) {
 274                 /* trap if OVERFLOWTRAP enabled */
 275                 if (Is_overflowtrap_enabled()) {
 276                         /*
 277                          * Adjust bias of result
 278                          */
 279                         Dbl_setwrapped_exponent(resultp1,dest_exponent,ovfl);
 280                         Dbl_copytoptr(resultp1,resultp2,dstptr);
 281                         if (inexact) 
 282                             if (Is_inexacttrap_enabled())
 283                                 return (OVERFLOWEXCEPTION | INEXACTEXCEPTION);
 284                             else Set_inexactflag();
 285                         return (OVERFLOWEXCEPTION);
 286                 }
 287                 inexact = TRUE;
 288                 Set_overflowflag();
 289                 /* set result to infinity or largest number */
 290                 Dbl_setoverflow(resultp1,resultp2);
 291         }
 292         /* 
 293          * Test for underflow
 294          */
 295         else if (dest_exponent <= 0) {
 296                 /* trap if UNDERFLOWTRAP enabled */
 297                 if (Is_underflowtrap_enabled()) {
 298                         /*
 299                          * Adjust bias of result
 300                          */
 301                         Dbl_setwrapped_exponent(resultp1,dest_exponent,unfl);
 302                         Dbl_copytoptr(resultp1,resultp2,dstptr);
 303                         if (inexact) 
 304                             if (Is_inexacttrap_enabled())
 305                                 return (UNDERFLOWEXCEPTION | INEXACTEXCEPTION);
 306                             else Set_inexactflag();
 307                         return (UNDERFLOWEXCEPTION);
 308                 }
 309 
 310                 /* Determine if should set underflow flag */
 311                 is_tiny = TRUE;
 312                 if (dest_exponent == 0 && inexact) {
 313                         switch (Rounding_mode()) {
 314                         case ROUNDPLUS: 
 315                                 if (Dbl_iszero_sign(resultp1)) {
 316                                         Dbl_increment(opnd3p1,opnd3p2);
 317                                         if (Dbl_isone_hiddenoverflow(opnd3p1))
 318                                             is_tiny = FALSE;
 319                                         Dbl_decrement(opnd3p1,opnd3p2);
 320                                 }
 321                                 break;
 322                         case ROUNDMINUS: 
 323                                 if (Dbl_isone_sign(resultp1)) {
 324                                         Dbl_increment(opnd3p1,opnd3p2);
 325                                         if (Dbl_isone_hiddenoverflow(opnd3p1))
 326                                             is_tiny = FALSE;
 327                                         Dbl_decrement(opnd3p1,opnd3p2);
 328                                 }
 329                                 break;
 330                         case ROUNDNEAREST:
 331                                 if (guardbit && (stickybit || 
 332                                     Dbl_isone_lowmantissap2(opnd3p2))) {
 333                                         Dbl_increment(opnd3p1,opnd3p2);
 334                                         if (Dbl_isone_hiddenoverflow(opnd3p1))
 335                                             is_tiny = FALSE;
 336                                         Dbl_decrement(opnd3p1,opnd3p2);
 337                                 }
 338                                 break;
 339                         }
 340                 }
 341 
 342                 /*
 343                  * denormalize result or set to signed zero
 344                  */
 345                 stickybit = inexact;
 346                 Dbl_denormalize(opnd3p1,opnd3p2,dest_exponent,guardbit,
 347                  stickybit,inexact);
 348 
 349                 /* return zero or smallest number */
 350                 if (inexact) {
 351                         switch (Rounding_mode()) {
 352                         case ROUNDPLUS: 
 353                                 if (Dbl_iszero_sign(resultp1)) {
 354                                         Dbl_increment(opnd3p1,opnd3p2);
 355                                 }
 356                                 break;
 357                         case ROUNDMINUS: 
 358                                 if (Dbl_isone_sign(resultp1)) {
 359                                         Dbl_increment(opnd3p1,opnd3p2);
 360                                 }
 361                                 break;
 362                         case ROUNDNEAREST:
 363                                 if (guardbit && (stickybit || 
 364                                     Dbl_isone_lowmantissap2(opnd3p2))) {
 365                                         Dbl_increment(opnd3p1,opnd3p2);
 366                                 }
 367                                 break;
 368                         }
 369                         if (is_tiny) Set_underflowflag();
 370                 }
 371                 Dbl_set_exponentmantissa(resultp1,resultp2,opnd3p1,opnd3p2);
 372         }
 373         else Dbl_set_exponent(resultp1,dest_exponent);
 374         /* check for inexact */
 375         Dbl_copytoptr(resultp1,resultp2,dstptr);
 376         if (inexact) {
 377                 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
 378                 else Set_inexactflag();
 379         }
 380         return(NOEXCEPTION);
 381 }

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