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

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

DEFINITIONS

This source file includes following definitions.
  1. sgl_fdiv

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

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