github.com/igggame/nebulas-go@v2.1.0+incompatible/nbre/3rd_party/SoftFloat-3e/source/s_mulAddF128M.c (about)

     1  
     2  /*============================================================================
     3  
     4  This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
     5  Package, Release 3e, by John R. Hauser.
     6  
     7  Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
     8  California.  All rights reserved.
     9  
    10  Redistribution and use in source and binary forms, with or without
    11  modification, are permitted provided that the following conditions are met:
    12  
    13   1. Redistributions of source code must retain the above copyright notice,
    14      this list of conditions, and the following disclaimer.
    15  
    16   2. Redistributions in binary form must reproduce the above copyright notice,
    17      this list of conditions, and the following disclaimer in the documentation
    18      and/or other materials provided with the distribution.
    19  
    20   3. Neither the name of the University nor the names of its contributors may
    21      be used to endorse or promote products derived from this software without
    22      specific prior written permission.
    23  
    24  THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
    25  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
    26  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
    27  DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
    28  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
    29  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
    30  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
    31  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    32  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
    33  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    34  
    35  =============================================================================*/
    36  
    37  #include <stdbool.h>
    38  #include <stdint.h>
    39  #include "platform.h"
    40  #include "internals.h"
    41  #include "specialize.h"
    42  #include "softfloat.h"
    43  
    44  void
    45   softfloat_mulAddF128M(
    46       const uint32_t *aWPtr,
    47       const uint32_t *bWPtr,
    48       const uint32_t *cWPtr,
    49       uint32_t *zWPtr,
    50       uint_fast8_t op
    51   )
    52  {
    53      uint32_t uiA96;
    54      int32_t expA;
    55      uint32_t uiB96;
    56      int32_t expB;
    57      uint32_t uiC96;
    58      bool signC;
    59      int32_t expC;
    60      bool signProd, prodIsInfinite;
    61      uint32_t *ptr, uiZ96, sigA[4];
    62      uint_fast8_t shiftDist;
    63      uint32_t sigX[5];
    64      int32_t expProd;
    65      uint32_t sigProd[8], wordSig;
    66      bool doSub;
    67      uint_fast8_t
    68       (*addCarryMRoutinePtr)(
    69           uint_fast8_t,
    70           const uint32_t *,
    71           const uint32_t *,
    72           uint_fast8_t,
    73           uint32_t *
    74       );
    75      int32_t expDiff;
    76      bool signZ;
    77      int32_t expZ;
    78      uint32_t *extSigPtr;
    79      uint_fast8_t carry;
    80      void (*roundPackRoutinePtr)( bool, int32_t, uint32_t *, uint32_t * );
    81  
    82      /*------------------------------------------------------------------------
    83      *------------------------------------------------------------------------*/
    84      uiA96 = aWPtr[indexWordHi( 4 )];
    85      expA = expF128UI96( uiA96 );
    86      uiB96 = bWPtr[indexWordHi( 4 )];
    87      expB = expF128UI96( uiB96 );
    88      uiC96 = cWPtr[indexWordHi( 4 )];
    89      signC = signF128UI96( uiC96 ) ^ (op == softfloat_mulAdd_subC);
    90      expC = expF128UI96( uiC96 );
    91      signProd =
    92          signF128UI96( uiA96 ) ^ signF128UI96( uiB96 )
    93              ^ (op == softfloat_mulAdd_subProd);
    94      /*------------------------------------------------------------------------
    95      *------------------------------------------------------------------------*/
    96      prodIsInfinite = false;
    97      if ( (expA == 0x7FFF) || (expB == 0x7FFF) ) {
    98          if ( softfloat_tryPropagateNaNF128M( aWPtr, bWPtr, zWPtr ) ) {
    99              goto propagateNaN_ZC;
   100          }
   101          ptr = (uint32_t *) aWPtr;
   102          if ( ! (uint32_t) (uiA96<<1) ) goto possibleInvalidProd;
   103          if ( ! (uint32_t) (uiB96<<1) ) {
   104              ptr = (uint32_t *) bWPtr;
   105       possibleInvalidProd:
   106              if (
   107                  ! (ptr[indexWord( 4, 2 )] | ptr[indexWord( 4, 1 )]
   108                         | ptr[indexWord( 4, 0 )])
   109              ) {
   110                  goto invalid;
   111              }
   112          }
   113          prodIsInfinite = true;
   114      }
   115      if ( expC == 0x7FFF ) {
   116          if (
   117              fracF128UI96( uiC96 )
   118                  || (cWPtr[indexWord( 4, 2 )] | cWPtr[indexWord( 4, 1 )]
   119                          | cWPtr[indexWord( 4, 0 )])
   120          ) {
   121              zWPtr[indexWordHi( 4 )] = 0;
   122              goto propagateNaN_ZC;
   123          }
   124          if ( prodIsInfinite && (signProd != signC) ) goto invalid;
   125          goto copyC;
   126      }
   127      if ( prodIsInfinite ) {
   128          uiZ96 = packToF128UI96( signProd, 0x7FFF, 0 );
   129          goto uiZ;
   130      }
   131      /*------------------------------------------------------------------------
   132      *------------------------------------------------------------------------*/
   133      if ( expA ) {
   134          sigA[indexWordHi( 4 )] = fracF128UI96( uiA96 ) | 0x00010000;
   135          sigA[indexWord( 4, 2 )] = aWPtr[indexWord( 4, 2 )];
   136          sigA[indexWord( 4, 1 )] = aWPtr[indexWord( 4, 1 )];
   137          sigA[indexWord( 4, 0 )] = aWPtr[indexWord( 4, 0 )];
   138      } else {
   139          expA = softfloat_shiftNormSigF128M( aWPtr, 0, sigA );
   140          if ( expA == -128 ) goto zeroProd;
   141      }
   142      if ( expB ) {
   143          sigX[indexWordHi( 4 )] = fracF128UI96( uiB96 ) | 0x00010000;
   144          sigX[indexWord( 4, 2 )] = bWPtr[indexWord( 4, 2 )];
   145          sigX[indexWord( 4, 1 )] = bWPtr[indexWord( 4, 1 )];
   146          sigX[indexWord( 4, 0 )] = bWPtr[indexWord( 4, 0 )];
   147      } else {
   148          expB = softfloat_shiftNormSigF128M( bWPtr, 0, sigX );
   149          if ( expB == -128 ) goto zeroProd;
   150      }
   151      /*------------------------------------------------------------------------
   152      *------------------------------------------------------------------------*/
   153      expProd = expA + expB - 0x3FF0;
   154      softfloat_mul128MTo256M( sigA, sigX, sigProd );
   155      /*------------------------------------------------------------------------
   156      *------------------------------------------------------------------------*/
   157      wordSig = fracF128UI96( uiC96 );
   158      if ( expC ) {
   159          --expC;
   160          wordSig |= 0x00010000;
   161      }
   162      sigX[indexWordHi( 5 )] = wordSig;
   163      sigX[indexWord( 5, 3 )] = cWPtr[indexWord( 4, 2 )];
   164      sigX[indexWord( 5, 2 )] = cWPtr[indexWord( 4, 1 )];
   165      sigX[indexWord( 5, 1 )] = cWPtr[indexWord( 4, 0 )];
   166      /*------------------------------------------------------------------------
   167      *------------------------------------------------------------------------*/
   168      doSub = (signProd != signC);
   169      addCarryMRoutinePtr =
   170          doSub ? softfloat_addComplCarryM : softfloat_addCarryM;
   171      expDiff = expProd - expC;
   172      if ( expDiff <= 0 ) {
   173          /*--------------------------------------------------------------------
   174          *--------------------------------------------------------------------*/
   175          signZ = signC;
   176          expZ = expC;
   177          if (
   178              sigProd[indexWord( 8, 2 )]
   179                  || (sigProd[indexWord( 8, 1 )] | sigProd[indexWord( 8, 0 )])
   180          ) {
   181              sigProd[indexWord( 8, 3 )] |= 1;
   182          }
   183          extSigPtr = &sigProd[indexMultiwordHi( 8, 5 )];
   184          if ( expDiff ) {
   185              softfloat_shiftRightJam160M( extSigPtr, -expDiff, extSigPtr );
   186          }
   187          carry = 0;
   188          if ( doSub ) {
   189              wordSig = extSigPtr[indexWordLo( 5 )];
   190              extSigPtr[indexWordLo( 5 )] = -wordSig;
   191              carry = ! wordSig;
   192          }
   193          (*addCarryMRoutinePtr)(
   194              4,
   195              &sigX[indexMultiwordHi( 5, 4 )],
   196              extSigPtr + indexMultiwordHi( 5, 4 ),
   197              carry,
   198              extSigPtr + indexMultiwordHi( 5, 4 )
   199          );
   200          wordSig = extSigPtr[indexWordHi( 5 )];
   201          if ( ! expZ ) {
   202              if ( wordSig & 0x80000000 ) {
   203                  signZ = ! signZ;
   204                  softfloat_negX160M( extSigPtr );
   205                  wordSig = extSigPtr[indexWordHi( 5 )];
   206              }
   207              goto checkCancellation;
   208          }
   209          if ( wordSig < 0x00010000 ) {
   210              --expZ;
   211              softfloat_add160M( extSigPtr, extSigPtr, extSigPtr );
   212              goto roundPack;
   213          }
   214          goto extSigReady_noCancellation;
   215      } else {
   216          /*--------------------------------------------------------------------
   217          *--------------------------------------------------------------------*/
   218          signZ = signProd;
   219          expZ = expProd;
   220          sigX[indexWordLo( 5 )] = 0;
   221          expDiff -= 128;
   222          if ( 0 <= expDiff ) {
   223              /*----------------------------------------------------------------
   224              *----------------------------------------------------------------*/
   225              if ( expDiff ) softfloat_shiftRightJam160M( sigX, expDiff, sigX );
   226              wordSig = sigX[indexWordLo( 5 )];
   227              carry = 0;
   228              if ( doSub ) {
   229                  carry = ! wordSig;
   230                  wordSig = -wordSig;
   231              }
   232              carry =
   233                  (*addCarryMRoutinePtr)(
   234                      4,
   235                      &sigProd[indexMultiwordLo( 8, 4 )],
   236                      &sigX[indexMultiwordHi( 5, 4 )],
   237                      carry,
   238                      &sigProd[indexMultiwordLo( 8, 4 )]
   239                  );
   240              sigProd[indexWord( 8, 2 )] |= wordSig;
   241              ptr = &sigProd[indexWord( 8, 4 )];
   242          } else {
   243              /*----------------------------------------------------------------
   244              *----------------------------------------------------------------*/
   245              shiftDist = expDiff & 31;
   246              if ( shiftDist ) {
   247                  softfloat_shortShiftRight160M( sigX, shiftDist, sigX );
   248              }
   249              expDiff >>= 5;
   250              extSigPtr =
   251                  &sigProd[indexMultiwordLo( 8, 5 )] - wordIncr
   252                      + expDiff * -wordIncr;
   253              carry =
   254                  (*addCarryMRoutinePtr)( 5, extSigPtr, sigX, doSub, extSigPtr );
   255              if ( expDiff == -4 ) {
   256                  /*------------------------------------------------------------
   257                  *------------------------------------------------------------*/
   258                  wordSig = sigProd[indexWordHi( 8 )];
   259                  if ( wordSig & 0x80000000 ) {
   260                      signZ = ! signZ;
   261                      softfloat_negX256M( sigProd );
   262                      wordSig = sigProd[indexWordHi( 8 )];
   263                  }
   264                  /*------------------------------------------------------------
   265                  *------------------------------------------------------------*/
   266                  if ( wordSig ) goto expProdBigger_noWordShift;
   267                  wordSig = sigProd[indexWord( 8, 6 )];
   268                  if ( 0x00040000 <= wordSig ) goto expProdBigger_noWordShift;
   269                  expZ -= 32;
   270                  extSigPtr = &sigProd[indexMultiwordHi( 8, 5 )] - wordIncr;
   271                  for (;;) {
   272                      if ( wordSig ) break;
   273                      wordSig = extSigPtr[indexWord( 5, 3 )];
   274                      if ( 0x00040000 <= wordSig ) break;
   275                      expZ -= 32;
   276                      extSigPtr -= wordIncr;
   277                      if ( extSigPtr == &sigProd[indexMultiwordLo( 8, 5 )] ) {
   278                          goto checkCancellation;
   279                      }
   280                  }
   281                  /*------------------------------------------------------------
   282                  *------------------------------------------------------------*/
   283                  ptr = extSigPtr + indexWordLo( 5 );
   284                  do {
   285                      ptr -= wordIncr;
   286                      if ( *ptr ) {
   287                          extSigPtr[indexWordLo( 5 )] |= 1;
   288                          break;
   289                      }
   290                  } while ( ptr != &sigProd[indexWordLo( 8 )] );
   291                  wordSig = extSigPtr[indexWordHi( 5 )];
   292                  goto extSigReady;
   293              }
   294              ptr = extSigPtr + indexWordHi( 5 ) + wordIncr;
   295          }
   296          /*--------------------------------------------------------------------
   297          *--------------------------------------------------------------------*/
   298          if ( carry != doSub ) {
   299              if ( doSub ) {
   300                  do {
   301                      wordSig = *ptr;
   302                      *ptr = wordSig - 1;
   303                      ptr += wordIncr;
   304                  } while ( ! wordSig );
   305              } else {
   306                  do {
   307                      wordSig = *ptr + 1;
   308                      *ptr = wordSig;
   309                      ptr += wordIncr;
   310                  } while ( ! wordSig );
   311              }
   312          }
   313          /*--------------------------------------------------------------------
   314          *--------------------------------------------------------------------*/
   315       expProdBigger_noWordShift:
   316          if (
   317              sigProd[indexWord( 8, 2 )]
   318                  || (sigProd[indexWord( 8, 1 )] | sigProd[indexWord( 8, 0 )])
   319          ) {
   320              sigProd[indexWord( 8, 3 )] |= 1;
   321          }
   322          extSigPtr = &sigProd[indexMultiwordHi( 8, 5 )];
   323          wordSig = extSigPtr[indexWordHi( 5 )];
   324      }
   325   extSigReady:
   326      roundPackRoutinePtr = softfloat_normRoundPackMToF128M;
   327      if ( wordSig < 0x00010000 ) goto doRoundPack;
   328   extSigReady_noCancellation:
   329      if ( 0x00020000 <= wordSig ) {
   330          ++expZ;
   331          softfloat_shortShiftRightJam160M( extSigPtr, 1, extSigPtr );
   332      }
   333   roundPack:
   334      roundPackRoutinePtr = softfloat_roundPackMToF128M;
   335   doRoundPack:
   336      (*roundPackRoutinePtr)( signZ, expZ, extSigPtr, zWPtr );
   337      return;
   338      /*------------------------------------------------------------------------
   339      *------------------------------------------------------------------------*/
   340   invalid:
   341      softfloat_invalidF128M( zWPtr );
   342   propagateNaN_ZC:
   343      softfloat_propagateNaNF128M( zWPtr, cWPtr, zWPtr );
   344      return;
   345      /*------------------------------------------------------------------------
   346      *------------------------------------------------------------------------*/
   347   zeroProd:
   348      if (
   349          ! (uint32_t) (uiC96<<1) && (signProd != signC)
   350              && ! cWPtr[indexWord( 4, 2 )]
   351              && ! (cWPtr[indexWord( 4, 1 )] | cWPtr[indexWord( 4, 0 )])
   352      ) {
   353          goto completeCancellation;
   354      }
   355   copyC:
   356      zWPtr[indexWordHi( 4 )] = uiC96;
   357      zWPtr[indexWord( 4, 2 )] = cWPtr[indexWord( 4, 2 )];
   358      zWPtr[indexWord( 4, 1 )] = cWPtr[indexWord( 4, 1 )];
   359      zWPtr[indexWord( 4, 0 )] = cWPtr[indexWord( 4, 0 )];
   360      return;
   361      /*------------------------------------------------------------------------
   362      *------------------------------------------------------------------------*/
   363   checkCancellation:
   364      if (
   365          wordSig
   366              || (extSigPtr[indexWord( 5, 3 )] | extSigPtr[indexWord( 5, 2 )])
   367              || (extSigPtr[indexWord( 5, 1 )] | extSigPtr[indexWord( 5, 0 )])
   368      ) {
   369          goto extSigReady;
   370      }
   371   completeCancellation:
   372      uiZ96 =
   373          packToF128UI96(
   374              (softfloat_roundingMode == softfloat_round_min), 0, 0 );
   375   uiZ:
   376      zWPtr[indexWordHi( 4 )] = uiZ96;
   377      zWPtr[indexWord( 4, 2 )] = 0;
   378      zWPtr[indexWord( 4, 1 )] = 0;
   379      zWPtr[indexWord( 4, 0 )] = 0;
   380  
   381  }
   382