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

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

DEFINITIONS

This source file includes following definitions.
  1. sgl_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/sfmpy.c               $Revision: 1.1 $
  13  *
  14  *  Purpose:
  15  *      Single Precision Floating-point Multiply
  16  *
  17  *  External Interfaces:
  18  *      sgl_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 "sgl_float.h"
  31 
  32 /*
  33  *  Single Precision Floating-point Multiply
  34  */
  35 
  36 int
  37 sgl_fmpy(
  38     sgl_floating_point *srcptr1,
  39     sgl_floating_point *srcptr2,
  40     sgl_floating_point *dstptr,
  41     unsigned int *status)
  42 {
  43         register unsigned int opnd1, opnd2, opnd3, result;
  44         register int dest_exponent, count;
  45         register boolean inexact = FALSE, guardbit = FALSE, stickybit = FALSE;
  46         boolean is_tiny;
  47 
  48         opnd1 = *srcptr1;
  49         opnd2 = *srcptr2;
  50         /* 
  51          * set sign bit of result 
  52          */
  53         if (Sgl_sign(opnd1) ^ Sgl_sign(opnd2)) Sgl_setnegativezero(result);  
  54         else Sgl_setzero(result);
  55         /*
  56          * check first operand for NaN's or infinity
  57          */
  58         if (Sgl_isinfinity_exponent(opnd1)) {
  59                 if (Sgl_iszero_mantissa(opnd1)) {
  60                         if (Sgl_isnotnan(opnd2)) {
  61                                 if (Sgl_iszero_exponentmantissa(opnd2)) {
  62                                         /* 
  63                                          * invalid since operands are infinity 
  64                                          * and zero 
  65                                          */
  66                                         if (Is_invalidtrap_enabled()) 
  67                                                 return(INVALIDEXCEPTION);
  68                                         Set_invalidflag();
  69                                         Sgl_makequietnan(result);
  70                                         *dstptr = result;
  71                                         return(NOEXCEPTION);
  72                                 }
  73                                 /*
  74                                  * return infinity
  75                                  */
  76                                 Sgl_setinfinity_exponentmantissa(result);
  77                                 *dstptr = result;
  78                                 return(NOEXCEPTION);
  79                         }
  80                 }
  81                 else {
  82                         /*
  83                          * is NaN; signaling or quiet?
  84                          */
  85                         if (Sgl_isone_signaling(opnd1)) {
  86                                 /* trap if INVALIDTRAP enabled */
  87                                 if (Is_invalidtrap_enabled()) 
  88                                         return(INVALIDEXCEPTION);
  89                                 /* make NaN quiet */
  90                                 Set_invalidflag();
  91                                 Sgl_set_quiet(opnd1);
  92                         }
  93                         /* 
  94                          * is second operand a signaling NaN? 
  95                          */
  96                         else if (Sgl_is_signalingnan(opnd2)) {
  97                                 /* trap if INVALIDTRAP enabled */
  98                                 if (Is_invalidtrap_enabled()) 
  99                                         return(INVALIDEXCEPTION);
 100                                 /* make NaN quiet */
 101                                 Set_invalidflag();
 102                                 Sgl_set_quiet(opnd2);
 103                                 *dstptr = opnd2;
 104                                 return(NOEXCEPTION);
 105                         }
 106                         /*
 107                          * return quiet NaN
 108                          */
 109                         *dstptr = opnd1;
 110                         return(NOEXCEPTION);
 111                 }
 112         }
 113         /*
 114          * check second operand for NaN's or infinity
 115          */
 116         if (Sgl_isinfinity_exponent(opnd2)) {
 117                 if (Sgl_iszero_mantissa(opnd2)) {
 118                         if (Sgl_iszero_exponentmantissa(opnd1)) {
 119                                 /* invalid since operands are zero & infinity */
 120                                 if (Is_invalidtrap_enabled()) 
 121                                         return(INVALIDEXCEPTION);
 122                                 Set_invalidflag();
 123                                 Sgl_makequietnan(opnd2);
 124                                 *dstptr = opnd2;
 125                                 return(NOEXCEPTION);
 126                         }
 127                         /*
 128                          * return infinity
 129                          */
 130                         Sgl_setinfinity_exponentmantissa(result);
 131                         *dstptr = result;
 132                         return(NOEXCEPTION);
 133                 }
 134                 /*
 135                  * is NaN; signaling or quiet?
 136                  */
 137                 if (Sgl_isone_signaling(opnd2)) {
 138                         /* trap if INVALIDTRAP enabled */
 139                         if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
 140 
 141                         /* make NaN quiet */
 142                         Set_invalidflag();
 143                         Sgl_set_quiet(opnd2);
 144                 }
 145                 /*
 146                  * return quiet NaN
 147                  */
 148                 *dstptr = opnd2;
 149                 return(NOEXCEPTION);
 150         }
 151         /*
 152          * Generate exponent 
 153          */
 154         dest_exponent = Sgl_exponent(opnd1) + Sgl_exponent(opnd2) - SGL_BIAS;
 155 
 156         /*
 157          * Generate mantissa
 158          */
 159         if (Sgl_isnotzero_exponent(opnd1)) {
 160                 /* set hidden bit */
 161                 Sgl_clear_signexponent_set_hidden(opnd1);
 162         }
 163         else {
 164                 /* check for zero */
 165                 if (Sgl_iszero_mantissa(opnd1)) {
 166                         Sgl_setzero_exponentmantissa(result);
 167                         *dstptr = result;
 168                         return(NOEXCEPTION);
 169                 }
 170                 /* is denormalized, adjust exponent */
 171                 Sgl_clear_signexponent(opnd1);
 172                 Sgl_leftshiftby1(opnd1);
 173                 Sgl_normalize(opnd1,dest_exponent);
 174         }
 175         /* opnd2 needs to have hidden bit set with msb in hidden bit */
 176         if (Sgl_isnotzero_exponent(opnd2)) {
 177                 Sgl_clear_signexponent_set_hidden(opnd2);
 178         }
 179         else {
 180                 /* check for zero */
 181                 if (Sgl_iszero_mantissa(opnd2)) {
 182                         Sgl_setzero_exponentmantissa(result);
 183                         *dstptr = result;
 184                         return(NOEXCEPTION);
 185                 }
 186                 /* is denormalized; want to normalize */
 187                 Sgl_clear_signexponent(opnd2);
 188                 Sgl_leftshiftby1(opnd2);
 189                 Sgl_normalize(opnd2,dest_exponent);
 190         }
 191 
 192         /* Multiply two source mantissas together */
 193 
 194         Sgl_leftshiftby4(opnd2);     /* make room for guard bits */
 195         Sgl_setzero(opnd3);
 196         /*
 197          * Four bits at a time are inspected in each loop, and a
 198          * simple shift and add multiply algorithm is used.
 199          */
 200         for (count=1;count<SGL_P;count+=4) {
 201                 stickybit |= Slow4(opnd3);
 202                 Sgl_rightshiftby4(opnd3);
 203                 if (Sbit28(opnd1)) Sall(opnd3) += (Sall(opnd2) << 3);
 204                 if (Sbit29(opnd1)) Sall(opnd3) += (Sall(opnd2) << 2);
 205                 if (Sbit30(opnd1)) Sall(opnd3) += (Sall(opnd2) << 1);
 206                 if (Sbit31(opnd1)) Sall(opnd3) += Sall(opnd2);
 207                 Sgl_rightshiftby4(opnd1);
 208         }
 209         /* make sure result is left-justified */
 210         if (Sgl_iszero_sign(opnd3)) {
 211                 Sgl_leftshiftby1(opnd3);
 212         }
 213         else {
 214                 /* result mantissa >= 2. */
 215                 dest_exponent++;
 216         }
 217         /* check for denormalized result */
 218         while (Sgl_iszero_sign(opnd3)) {
 219                 Sgl_leftshiftby1(opnd3);
 220                 dest_exponent--;
 221         }
 222         /*
 223          * check for guard, sticky and inexact bits
 224          */
 225         stickybit |= Sgl_all(opnd3) << (SGL_BITLENGTH - SGL_EXP_LENGTH + 1);
 226         guardbit = Sbit24(opnd3);
 227         inexact = guardbit | stickybit;
 228 
 229         /* re-align mantissa */
 230         Sgl_rightshiftby8(opnd3);
 231 
 232         /* 
 233          * round result 
 234          */
 235         if (inexact && (dest_exponent>0 || Is_underflowtrap_enabled())) {
 236                 Sgl_clear_signexponent(opnd3);
 237                 switch (Rounding_mode()) {
 238                         case ROUNDPLUS: 
 239                                 if (Sgl_iszero_sign(result)) 
 240                                         Sgl_increment(opnd3);
 241                                 break;
 242                         case ROUNDMINUS: 
 243                                 if (Sgl_isone_sign(result)) 
 244                                         Sgl_increment(opnd3);
 245                                 break;
 246                         case ROUNDNEAREST:
 247                                 if (guardbit) {
 248                                 if (stickybit || Sgl_isone_lowmantissa(opnd3))
 249                                 Sgl_increment(opnd3);
 250                                 }
 251                 }
 252                 if (Sgl_isone_hidden(opnd3)) dest_exponent++;
 253         }
 254         Sgl_set_mantissa(result,opnd3);
 255 
 256         /* 
 257          * Test for overflow
 258          */
 259         if (dest_exponent >= SGL_INFINITY_EXPONENT) {
 260                 /* trap if OVERFLOWTRAP enabled */
 261                 if (Is_overflowtrap_enabled()) {
 262                         /*
 263                          * Adjust bias of result
 264                          */
 265                         Sgl_setwrapped_exponent(result,dest_exponent,ovfl);
 266                         *dstptr = result;
 267                         if (inexact) 
 268                             if (Is_inexacttrap_enabled())
 269                                 return(OVERFLOWEXCEPTION | INEXACTEXCEPTION);
 270                             else Set_inexactflag();
 271                         return(OVERFLOWEXCEPTION);
 272                 }
 273                 inexact = TRUE;
 274                 Set_overflowflag();
 275                 /* set result to infinity or largest number */
 276                 Sgl_setoverflow(result);
 277         }
 278         /* 
 279          * Test for underflow
 280          */
 281         else if (dest_exponent <= 0) {
 282                 /* trap if UNDERFLOWTRAP enabled */
 283                 if (Is_underflowtrap_enabled()) {
 284                         /*
 285                          * Adjust bias of result
 286                          */
 287                         Sgl_setwrapped_exponent(result,dest_exponent,unfl);
 288                         *dstptr = result;
 289                         if (inexact) 
 290                             if (Is_inexacttrap_enabled())
 291                                 return(UNDERFLOWEXCEPTION | INEXACTEXCEPTION);
 292                             else Set_inexactflag();
 293                         return(UNDERFLOWEXCEPTION);
 294                 }
 295 
 296                 /* Determine if should set underflow flag */
 297                 is_tiny = TRUE;
 298                 if (dest_exponent == 0 && inexact) {
 299                         switch (Rounding_mode()) {
 300                         case ROUNDPLUS: 
 301                                 if (Sgl_iszero_sign(result)) {
 302                                         Sgl_increment(opnd3);
 303                                         if (Sgl_isone_hiddenoverflow(opnd3))
 304                                             is_tiny = FALSE;
 305                                         Sgl_decrement(opnd3);
 306                                 }
 307                                 break;
 308                         case ROUNDMINUS: 
 309                                 if (Sgl_isone_sign(result)) {
 310                                         Sgl_increment(opnd3);
 311                                         if (Sgl_isone_hiddenoverflow(opnd3))
 312                                             is_tiny = FALSE;
 313                                         Sgl_decrement(opnd3);
 314                                 }
 315                                 break;
 316                         case ROUNDNEAREST:
 317                                 if (guardbit && (stickybit || 
 318                                     Sgl_isone_lowmantissa(opnd3))) {
 319                                         Sgl_increment(opnd3);
 320                                         if (Sgl_isone_hiddenoverflow(opnd3))
 321                                             is_tiny = FALSE;
 322                                         Sgl_decrement(opnd3);
 323                                 }
 324                                 break;
 325                         }
 326                 }
 327 
 328                 /*
 329                  * denormalize result or set to signed zero
 330                  */
 331                 stickybit = inexact;
 332                 Sgl_denormalize(opnd3,dest_exponent,guardbit,stickybit,inexact);
 333 
 334                 /* return zero or smallest number */
 335                 if (inexact) {
 336                         switch (Rounding_mode()) {
 337                         case ROUNDPLUS: 
 338                                 if (Sgl_iszero_sign(result)) {
 339                                         Sgl_increment(opnd3);
 340                                 }
 341                                 break;
 342                         case ROUNDMINUS: 
 343                                 if (Sgl_isone_sign(result)) {
 344                                         Sgl_increment(opnd3);
 345                                 }
 346                                 break;
 347                         case ROUNDNEAREST:
 348                                 if (guardbit && (stickybit || 
 349                                     Sgl_isone_lowmantissa(opnd3))) {
 350                                         Sgl_increment(opnd3);
 351                                 }
 352                                 break;
 353                         }
 354                 if (is_tiny) Set_underflowflag();
 355                 }
 356                 Sgl_set_exponentmantissa(result,opnd3);
 357         }
 358         else Sgl_set_exponent(result,dest_exponent);
 359         *dstptr = result;
 360 
 361         /* check for inexact */
 362         if (inexact) {
 363                 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
 364                 else Set_inexactflag();
 365         }
 366         return(NOEXCEPTION);
 367 }

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