Logo Search packages:      
Sourcecode: linux version File versions

fmpyfadd.c

/*
 * Linux/PA-RISC Project (http://www.parisc-linux.org/)
 *
 * Floating-point emulation code
 *  Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
 *
 *    This program is free software; you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation; either version 2, or (at your option)
 *    any later version.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with this program; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
/*
 * BEGIN_DESC
 *
 *  File:
 *    @(#)  pa/spmath/fmpyfadd.c          $Revision: 1.1 $
 *
 *  Purpose:
 *    Double Floating-point Multiply Fused Add
 *    Double Floating-point Multiply Negate Fused Add
 *    Single Floating-point Multiply Fused Add
 *    Single Floating-point Multiply Negate Fused Add
 *
 *  External Interfaces:
 *    dbl_fmpyfadd(src1ptr,src2ptr,src3ptr,status,dstptr)
 *    dbl_fmpynfadd(src1ptr,src2ptr,src3ptr,status,dstptr)
 *    sgl_fmpyfadd(src1ptr,src2ptr,src3ptr,status,dstptr)
 *    sgl_fmpynfadd(src1ptr,src2ptr,src3ptr,status,dstptr)
 *
 *  Internal Interfaces:
 *
 *  Theory:
 *    <<please update with a overview of the operation of this file>>
 *
 * END_DESC
*/


#include "float.h"
#include "sgl_float.h"
#include "dbl_float.h"


/*
 *  Double Floating-point Multiply Fused Add
 */

int
dbl_fmpyfadd(
          dbl_floating_point *src1ptr,
          dbl_floating_point *src2ptr,
          dbl_floating_point *src3ptr,
          unsigned int *status,
          dbl_floating_point *dstptr)
{
      unsigned int opnd1p1, opnd1p2, opnd2p1, opnd2p2, opnd3p1, opnd3p2;
      register unsigned int tmpresp1, tmpresp2, tmpresp3, tmpresp4;
      unsigned int rightp1, rightp2, rightp3, rightp4;
      unsigned int resultp1, resultp2 = 0, resultp3 = 0, resultp4 = 0;
      register int mpy_exponent, add_exponent, count;
      boolean inexact = FALSE, is_tiny = FALSE;

      unsigned int signlessleft1, signlessright1, save;
      register int result_exponent, diff_exponent;
      int sign_save, jumpsize;
      
      Dbl_copyfromptr(src1ptr,opnd1p1,opnd1p2);
      Dbl_copyfromptr(src2ptr,opnd2p1,opnd2p2);
      Dbl_copyfromptr(src3ptr,opnd3p1,opnd3p2);

      /* 
       * set sign bit of result of multiply
       */
      if (Dbl_sign(opnd1p1) ^ Dbl_sign(opnd2p1)) 
            Dbl_setnegativezerop1(resultp1); 
      else Dbl_setzerop1(resultp1);

      /*
       * Generate multiply exponent 
       */
      mpy_exponent = Dbl_exponent(opnd1p1) + Dbl_exponent(opnd2p1) - DBL_BIAS;

      /*
       * check first operand for NaN's or infinity
       */
      if (Dbl_isinfinity_exponent(opnd1p1)) {
            if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) {
                  if (Dbl_isnotnan(opnd2p1,opnd2p2) &&
                      Dbl_isnotnan(opnd3p1,opnd3p2)) {
                        if (Dbl_iszero_exponentmantissa(opnd2p1,opnd2p2)) {
                              /* 
                               * invalid since operands are infinity 
                               * and zero 
                               */
                              if (Is_invalidtrap_enabled())
                                    return(OPC_2E_INVALIDEXCEPTION);
                              Set_invalidflag();
                              Dbl_makequietnan(resultp1,resultp2);
                              Dbl_copytoptr(resultp1,resultp2,dstptr);
                              return(NOEXCEPTION);
                        }
                        /*
                         * Check third operand for infinity with a
                         *  sign opposite of the multiply result
                         */
                        if (Dbl_isinfinity(opnd3p1,opnd3p2) &&
                            (Dbl_sign(resultp1) ^ Dbl_sign(opnd3p1))) {
                              /* 
                               * invalid since attempting a magnitude
                               * subtraction of infinities
                               */
                              if (Is_invalidtrap_enabled())
                                    return(OPC_2E_INVALIDEXCEPTION);
                              Set_invalidflag();
                              Dbl_makequietnan(resultp1,resultp2);
                              Dbl_copytoptr(resultp1,resultp2,dstptr);
                              return(NOEXCEPTION);
                        }

                        /*
                         * return infinity
                         */
                        Dbl_setinfinity_exponentmantissa(resultp1,resultp2);
                        Dbl_copytoptr(resultp1,resultp2,dstptr);
                        return(NOEXCEPTION);
                  }
            }
            else {
                  /*
                   * is NaN; signaling or quiet?
                   */
                  if (Dbl_isone_signaling(opnd1p1)) {
                        /* trap if INVALIDTRAP enabled */
                        if (Is_invalidtrap_enabled()) 
                              return(OPC_2E_INVALIDEXCEPTION);
                        /* make NaN quiet */
                        Set_invalidflag();
                        Dbl_set_quiet(opnd1p1);
                  }
                  /* 
                   * is second operand a signaling NaN? 
                   */
                  else if (Dbl_is_signalingnan(opnd2p1)) {
                        /* trap if INVALIDTRAP enabled */
                        if (Is_invalidtrap_enabled())
                              return(OPC_2E_INVALIDEXCEPTION);
                        /* make NaN quiet */
                        Set_invalidflag();
                        Dbl_set_quiet(opnd2p1);
                        Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
                        return(NOEXCEPTION);
                  }
                  /* 
                   * is third operand a signaling NaN? 
                   */
                  else if (Dbl_is_signalingnan(opnd3p1)) {
                        /* trap if INVALIDTRAP enabled */
                        if (Is_invalidtrap_enabled())
                              return(OPC_2E_INVALIDEXCEPTION);
                        /* make NaN quiet */
                        Set_invalidflag();
                        Dbl_set_quiet(opnd3p1);
                        Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
                        return(NOEXCEPTION);
                  }
                  /*
                   * return quiet NaN
                   */
                  Dbl_copytoptr(opnd1p1,opnd1p2,dstptr);
                  return(NOEXCEPTION);
            }
      }

      /*
       * check second operand for NaN's or infinity
       */
      if (Dbl_isinfinity_exponent(opnd2p1)) {
            if (Dbl_iszero_mantissa(opnd2p1,opnd2p2)) {
                  if (Dbl_isnotnan(opnd3p1,opnd3p2)) {
                        if (Dbl_iszero_exponentmantissa(opnd1p1,opnd1p2)) {
                              /* 
                               * invalid since multiply operands are
                               * zero & infinity
                               */
                              if (Is_invalidtrap_enabled())
                                    return(OPC_2E_INVALIDEXCEPTION);
                              Set_invalidflag();
                              Dbl_makequietnan(opnd2p1,opnd2p2);
                              Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
                              return(NOEXCEPTION);
                        }

                        /*
                         * Check third operand for infinity with a
                         *  sign opposite of the multiply result
                         */
                        if (Dbl_isinfinity(opnd3p1,opnd3p2) &&
                            (Dbl_sign(resultp1) ^ Dbl_sign(opnd3p1))) {
                              /* 
                               * invalid since attempting a magnitude
                               * subtraction of infinities
                               */
                              if (Is_invalidtrap_enabled())
                                          return(OPC_2E_INVALIDEXCEPTION);
                                    Set_invalidflag();
                                    Dbl_makequietnan(resultp1,resultp2);
                              Dbl_copytoptr(resultp1,resultp2,dstptr);
                              return(NOEXCEPTION);
                        }

                        /*
                         * return infinity
                         */
                        Dbl_setinfinity_exponentmantissa(resultp1,resultp2);
                        Dbl_copytoptr(resultp1,resultp2,dstptr);
                        return(NOEXCEPTION);
                  }
            }
            else {
                  /*
                   * is NaN; signaling or quiet?
                   */
                  if (Dbl_isone_signaling(opnd2p1)) {
                        /* trap if INVALIDTRAP enabled */
                        if (Is_invalidtrap_enabled())
                              return(OPC_2E_INVALIDEXCEPTION);
                        /* make NaN quiet */
                        Set_invalidflag();
                        Dbl_set_quiet(opnd2p1);
                  }
                  /* 
                   * is third operand a signaling NaN? 
                   */
                  else if (Dbl_is_signalingnan(opnd3p1)) {
                              /* trap if INVALIDTRAP enabled */
                              if (Is_invalidtrap_enabled())
                                    return(OPC_2E_INVALIDEXCEPTION);
                              /* make NaN quiet */
                              Set_invalidflag();
                              Dbl_set_quiet(opnd3p1);
                        Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
                              return(NOEXCEPTION);
                  }
                  /*
                   * return quiet NaN
                   */
                  Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
                  return(NOEXCEPTION);
            }
      }

      /*
       * check third operand for NaN's or infinity
       */
      if (Dbl_isinfinity_exponent(opnd3p1)) {
            if (Dbl_iszero_mantissa(opnd3p1,opnd3p2)) {
                  /* return infinity */
                  Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
                  return(NOEXCEPTION);
            } else {
                  /*
                   * is NaN; signaling or quiet?
                   */
                  if (Dbl_isone_signaling(opnd3p1)) {
                        /* trap if INVALIDTRAP enabled */
                        if (Is_invalidtrap_enabled())
                              return(OPC_2E_INVALIDEXCEPTION);
                        /* make NaN quiet */
                        Set_invalidflag();
                        Dbl_set_quiet(opnd3p1);
                  }
                  /*
                   * return quiet NaN
                   */
                  Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
                  return(NOEXCEPTION);
            }
      }

      /*
       * Generate multiply mantissa
       */
      if (Dbl_isnotzero_exponent(opnd1p1)) {
            /* set hidden bit */
            Dbl_clear_signexponent_set_hidden(opnd1p1);
      }
      else {
            /* check for zero */
            if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) {
                  /*
                   * Perform the add opnd3 with zero here.
                   */
                  if (Dbl_iszero_exponentmantissa(opnd3p1,opnd3p2)) {
                        if (Is_rounding_mode(ROUNDMINUS)) {
                              Dbl_or_signs(opnd3p1,resultp1);
                        } else {
                              Dbl_and_signs(opnd3p1,resultp1);
                        }
                  }
                  /*
                   * Now let's check for trapped underflow case.
                   */
                  else if (Dbl_iszero_exponent(opnd3p1) &&
                           Is_underflowtrap_enabled()) {
                              /* need to normalize results mantissa */
                              sign_save = Dbl_signextendedsign(opnd3p1);
                        result_exponent = 0;
                              Dbl_leftshiftby1(opnd3p1,opnd3p2);
                              Dbl_normalize(opnd3p1,opnd3p2,result_exponent);
                              Dbl_set_sign(opnd3p1,/*using*/sign_save);
                              Dbl_setwrapped_exponent(opnd3p1,result_exponent,
                                          unfl);
                              Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
                              /* inexact = FALSE */
                              return(OPC_2E_UNDERFLOWEXCEPTION);
                  }
                  Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
                  return(NOEXCEPTION);
            }
            /* is denormalized, adjust exponent */
            Dbl_clear_signexponent(opnd1p1);
            Dbl_leftshiftby1(opnd1p1,opnd1p2);
            Dbl_normalize(opnd1p1,opnd1p2,mpy_exponent);
      }
      /* opnd2 needs to have hidden bit set with msb in hidden bit */
      if (Dbl_isnotzero_exponent(opnd2p1)) {
            Dbl_clear_signexponent_set_hidden(opnd2p1);
      }
      else {
            /* check for zero */
            if (Dbl_iszero_mantissa(opnd2p1,opnd2p2)) {
                  /*
                   * Perform the add opnd3 with zero here.
                   */
                  if (Dbl_iszero_exponentmantissa(opnd3p1,opnd3p2)) {
                        if (Is_rounding_mode(ROUNDMINUS)) {
                              Dbl_or_signs(opnd3p1,resultp1);
                        } else {
                              Dbl_and_signs(opnd3p1,resultp1);
                        }
                  }
                  /*
                   * Now let's check for trapped underflow case.
                   */
                  else if (Dbl_iszero_exponent(opnd3p1) &&
                      Is_underflowtrap_enabled()) {
                              /* need to normalize results mantissa */
                              sign_save = Dbl_signextendedsign(opnd3p1);
                        result_exponent = 0;
                              Dbl_leftshiftby1(opnd3p1,opnd3p2);
                              Dbl_normalize(opnd3p1,opnd3p2,result_exponent);
                              Dbl_set_sign(opnd3p1,/*using*/sign_save);
                              Dbl_setwrapped_exponent(opnd3p1,result_exponent,
                                          unfl);
                              Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
                              /* inexact = FALSE */
                        return(OPC_2E_UNDERFLOWEXCEPTION);
                  }
                  Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
                  return(NOEXCEPTION);
            }
            /* is denormalized; want to normalize */
            Dbl_clear_signexponent(opnd2p1);
            Dbl_leftshiftby1(opnd2p1,opnd2p2);
            Dbl_normalize(opnd2p1,opnd2p2,mpy_exponent);
      }

      /* Multiply the first two source mantissas together */

      /* 
       * The intermediate result will be kept in tmpres,
       * which needs enough room for 106 bits of mantissa,
       * so lets call it a Double extended.
       */
      Dblext_setzero(tmpresp1,tmpresp2,tmpresp3,tmpresp4);

      /* 
       * Four bits at a time are inspected in each loop, and a 
       * simple shift and add multiply algorithm is used. 
       */ 
      for (count = DBL_P-1; count >= 0; count -= 4) {
            Dblext_rightshiftby4(tmpresp1,tmpresp2,tmpresp3,tmpresp4);
            if (Dbit28p2(opnd1p2)) {
                  /* Fourword_add should be an ADD followed by 3 ADDC's */
                  Fourword_add(tmpresp1, tmpresp2, tmpresp3, tmpresp4, 
                   opnd2p1<<3 | opnd2p2>>29, opnd2p2<<3, 0, 0);
            }
            if (Dbit29p2(opnd1p2)) {
                  Fourword_add(tmpresp1, tmpresp2, tmpresp3, tmpresp4,
                   opnd2p1<<2 | opnd2p2>>30, opnd2p2<<2, 0, 0);
            }
            if (Dbit30p2(opnd1p2)) {
                  Fourword_add(tmpresp1, tmpresp2, tmpresp3, tmpresp4,
                   opnd2p1<<1 | opnd2p2>>31, opnd2p2<<1, 0, 0);
            }
            if (Dbit31p2(opnd1p2)) {
                  Fourword_add(tmpresp1, tmpresp2, tmpresp3, tmpresp4,
                   opnd2p1, opnd2p2, 0, 0);
            }
            Dbl_rightshiftby4(opnd1p1,opnd1p2);
      }
      if (Is_dexthiddenoverflow(tmpresp1)) {
            /* result mantissa >= 2 (mantissa overflow) */
            mpy_exponent++;
            Dblext_rightshiftby1(tmpresp1,tmpresp2,tmpresp3,tmpresp4);
      }

      /*
       * Restore the sign of the mpy result which was saved in resultp1.
       * The exponent will continue to be kept in mpy_exponent.
       */
      Dblext_set_sign(tmpresp1,Dbl_sign(resultp1));

      /* 
       * No rounding is required, since the result of the multiply
       * is exact in the extended format.
       */

      /*
       * Now we are ready to perform the add portion of the operation.
       *
       * The exponents need to be kept as integers for now, since the
       * multiply result might not fit into the exponent field.  We
       * can't overflow or underflow because of this yet, since the
       * add could bring the final result back into range.
       */
      add_exponent = Dbl_exponent(opnd3p1);

      /*
       * Check for denormalized or zero add operand.
       */
      if (add_exponent == 0) {
            /* check for zero */
            if (Dbl_iszero_mantissa(opnd3p1,opnd3p2)) {
                  /* right is zero */
                  /* Left can't be zero and must be result.
                   *
                   * The final result is now in tmpres and mpy_exponent,
                   * and needs to be rounded and squeezed back into
                   * double precision format from double extended.
                   */
                  result_exponent = mpy_exponent;
                  Dblext_copy(tmpresp1,tmpresp2,tmpresp3,tmpresp4,
                        resultp1,resultp2,resultp3,resultp4);
                  sign_save = Dbl_signextendedsign(resultp1);/*save sign*/
                  goto round;
            }

            /* 
             * Neither are zeroes.  
             * Adjust exponent and normalize add operand.
             */
            sign_save = Dbl_signextendedsign(opnd3p1);      /* save sign */
            Dbl_clear_signexponent(opnd3p1);
            Dbl_leftshiftby1(opnd3p1,opnd3p2);
            Dbl_normalize(opnd3p1,opnd3p2,add_exponent);
            Dbl_set_sign(opnd3p1,sign_save);    /* restore sign */
      } else {
            Dbl_clear_exponent_set_hidden(opnd3p1);
      }
      /*
       * Copy opnd3 to the double extended variable called right.
       */
      Dbl_copyto_dblext(opnd3p1,opnd3p2,rightp1,rightp2,rightp3,rightp4);

      /*
       * A zero "save" helps discover equal operands (for later),
       * and is used in swapping operands (if needed).
       */
      Dblext_xortointp1(tmpresp1,rightp1,/*to*/save);

      /*
       * Compare magnitude of operands.
       */
      Dblext_copytoint_exponentmantissap1(tmpresp1,signlessleft1);
      Dblext_copytoint_exponentmantissap1(rightp1,signlessright1);
      if (mpy_exponent < add_exponent || mpy_exponent == add_exponent &&
          Dblext_ismagnitudeless(tmpresp2,rightp2,signlessleft1,signlessright1)){
            /*
             * Set the left operand to the larger one by XOR swap.
             * First finish the first word "save".
             */
            Dblext_xorfromintp1(save,rightp1,/*to*/rightp1);
            Dblext_xorfromintp1(save,tmpresp1,/*to*/tmpresp1);
            Dblext_swap_lower(tmpresp2,tmpresp3,tmpresp4,
                  rightp2,rightp3,rightp4);
            /* also setup exponents used in rest of routine */
            diff_exponent = add_exponent - mpy_exponent;
            result_exponent = add_exponent;
      } else {
            /* also setup exponents used in rest of routine */
            diff_exponent = mpy_exponent - add_exponent;
            result_exponent = mpy_exponent;
      }
      /* Invariant: left is not smaller than right. */

      /*
       * Special case alignment of operands that would force alignment
       * beyond the extent of the extension.  A further optimization
       * could special case this but only reduces the path length for
       * this infrequent case.
       */
      if (diff_exponent > DBLEXT_THRESHOLD) {
            diff_exponent = DBLEXT_THRESHOLD;
      }

      /* Align right operand by shifting it to the right */
      Dblext_clear_sign(rightp1);
      Dblext_right_align(rightp1,rightp2,rightp3,rightp4,
            /*shifted by*/diff_exponent);
      
      /* Treat sum and difference of the operands separately. */
      if ((int)save < 0) {
            /*
             * Difference of the two operands.  Overflow can occur if the
             * multiply overflowed.  A borrow can occur out of the hidden
             * bit and force a post normalization phase.
             */
            Dblext_subtract(tmpresp1,tmpresp2,tmpresp3,tmpresp4,
                  rightp1,rightp2,rightp3,rightp4,
                  resultp1,resultp2,resultp3,resultp4);
            sign_save = Dbl_signextendedsign(resultp1);
            if (Dbl_iszero_hidden(resultp1)) {
                  /* Handle normalization */
            /* A straight foward algorithm would now shift the
             * result and extension left until the hidden bit
             * becomes one.  Not all of the extension bits need
             * participate in the shift.  Only the two most 
             * significant bits (round and guard) are needed.
             * If only a single shift is needed then the guard
             * bit becomes a significant low order bit and the
             * extension must participate in the rounding.
             * If more than a single shift is needed, then all
             * bits to the right of the guard bit are zeros, 
             * and the guard bit may or may not be zero. */
                  Dblext_leftshiftby1(resultp1,resultp2,resultp3,
                        resultp4);

                  /* Need to check for a zero result.  The sign and
                   * exponent fields have already been zeroed.  The more
                   * efficient test of the full object can be used.
                   */
                   if(Dblext_iszero(resultp1,resultp2,resultp3,resultp4)){
                        /* Must have been "x-x" or "x+(-x)". */
                        if (Is_rounding_mode(ROUNDMINUS))
                              Dbl_setone_sign(resultp1);
                        Dbl_copytoptr(resultp1,resultp2,dstptr);
                        return(NOEXCEPTION);
                  }
                  result_exponent--;

                  /* Look to see if normalization is finished. */
                  if (Dbl_isone_hidden(resultp1)) {
                        /* No further normalization is needed */
                        goto round;
                  }

                  /* Discover first one bit to determine shift amount.
                   * Use a modified binary search.  We have already
                   * shifted the result one position right and still
                   * not found a one so the remainder of the extension
                   * must be zero and simplifies rounding. */
                  /* Scan bytes */
                  while (Dbl_iszero_hiddenhigh7mantissa(resultp1)) {
                        Dblext_leftshiftby8(resultp1,resultp2,resultp3,resultp4);
                        result_exponent -= 8;
                  }
                  /* Now narrow it down to the nibble */
                  if (Dbl_iszero_hiddenhigh3mantissa(resultp1)) {
                        /* The lower nibble contains the
                         * normalizing one */
                        Dblext_leftshiftby4(resultp1,resultp2,resultp3,resultp4);
                        result_exponent -= 4;
                  }
                  /* Select case where first bit is set (already
                   * normalized) otherwise select the proper shift. */
                  jumpsize = Dbl_hiddenhigh3mantissa(resultp1);
                  if (jumpsize <= 7) switch(jumpsize) {
                  case 1:
                        Dblext_leftshiftby3(resultp1,resultp2,resultp3,
                              resultp4);
                        result_exponent -= 3;
                        break;
                  case 2:
                  case 3:
                        Dblext_leftshiftby2(resultp1,resultp2,resultp3,
                              resultp4);
                        result_exponent -= 2;
                        break;
                  case 4:
                  case 5:
                  case 6:
                  case 7:
                        Dblext_leftshiftby1(resultp1,resultp2,resultp3,
                              resultp4);
                        result_exponent -= 1;
                        break;
                  }
            } /* end if (hidden...)... */
      /* Fall through and round */
      } /* end if (save < 0)... */
      else {
            /* Add magnitudes */
            Dblext_addition(tmpresp1,tmpresp2,tmpresp3,tmpresp4,
                  rightp1,rightp2,rightp3,rightp4,
                  /*to*/resultp1,resultp2,resultp3,resultp4);
            sign_save = Dbl_signextendedsign(resultp1);
            if (Dbl_isone_hiddenoverflow(resultp1)) {
                  /* Prenormalization required. */
                  Dblext_arithrightshiftby1(resultp1,resultp2,resultp3,
                        resultp4);
                  result_exponent++;
            } /* end if hiddenoverflow... */
      } /* end else ...add magnitudes... */

      /* Round the result.  If the extension and lower two words are
       * all zeros, then the result is exact.  Otherwise round in the
       * correct direction.  Underflow is possible. If a postnormalization
       * is necessary, then the mantissa is all zeros so no shift is needed.
       */
  round:
      if (result_exponent <= 0 && !Is_underflowtrap_enabled()) {
            Dblext_denormalize(resultp1,resultp2,resultp3,resultp4,
                  result_exponent,is_tiny);
      }
      Dbl_set_sign(resultp1,/*using*/sign_save);
      if (Dblext_isnotzero_mantissap3(resultp3) || 
          Dblext_isnotzero_mantissap4(resultp4)) {
            inexact = TRUE;
            switch(Rounding_mode()) {
            case ROUNDNEAREST: /* The default. */
                  if (Dblext_isone_highp3(resultp3)) {
                        /* at least 1/2 ulp */
                        if (Dblext_isnotzero_low31p3(resultp3) ||
                            Dblext_isnotzero_mantissap4(resultp4) ||
                            Dblext_isone_lowp2(resultp2)) {
                              /* either exactly half way and odd or
                               * more than 1/2ulp */
                              Dbl_increment(resultp1,resultp2);
                        }
                  }
                  break;

            case ROUNDPLUS:
                  if (Dbl_iszero_sign(resultp1)) {
                        /* Round up positive results */
                        Dbl_increment(resultp1,resultp2);
                  }
                  break;
          
            case ROUNDMINUS:
                  if (Dbl_isone_sign(resultp1)) {
                        /* Round down negative results */
                        Dbl_increment(resultp1,resultp2);
                  }
          
            case ROUNDZERO:;
                  /* truncate is simple */
            } /* end switch... */
            if (Dbl_isone_hiddenoverflow(resultp1)) result_exponent++;
      }
      if (result_exponent >= DBL_INFINITY_EXPONENT) {
                /* trap if OVERFLOWTRAP enabled */
                if (Is_overflowtrap_enabled()) {
                        /*
                         * Adjust bias of result
                         */
                        Dbl_setwrapped_exponent(resultp1,result_exponent,ovfl);
                        Dbl_copytoptr(resultp1,resultp2,dstptr);
                        if (inexact)
                            if (Is_inexacttrap_enabled())
                                return (OPC_2E_OVERFLOWEXCEPTION |
                              OPC_2E_INEXACTEXCEPTION);
                            else Set_inexactflag();
                        return (OPC_2E_OVERFLOWEXCEPTION);
                }
                inexact = TRUE;
                Set_overflowflag();
                /* set result to infinity or largest number */
                Dbl_setoverflow(resultp1,resultp2);

      } else if (result_exponent <= 0) {  /* underflow case */
            if (Is_underflowtrap_enabled()) {
                        /*
                         * Adjust bias of result
                         */
                  Dbl_setwrapped_exponent(resultp1,result_exponent,unfl);
                  Dbl_copytoptr(resultp1,resultp2,dstptr);
                        if (inexact)
                            if (Is_inexacttrap_enabled())
                                return (OPC_2E_UNDERFLOWEXCEPTION |
                              OPC_2E_INEXACTEXCEPTION);
                            else Set_inexactflag();
                  return(OPC_2E_UNDERFLOWEXCEPTION);
            }
            else if (inexact && is_tiny) Set_underflowflag();
      }
      else Dbl_set_exponent(resultp1,result_exponent);
      Dbl_copytoptr(resultp1,resultp2,dstptr);
      if (inexact) 
            if (Is_inexacttrap_enabled()) return(OPC_2E_INEXACTEXCEPTION);
            else Set_inexactflag();
      return(NOEXCEPTION);
}

/*
 *  Double Floating-point Multiply Negate Fused Add
 */

dbl_fmpynfadd(src1ptr,src2ptr,src3ptr,status,dstptr)

dbl_floating_point *src1ptr, *src2ptr, *src3ptr, *dstptr;
unsigned int *status;
{
      unsigned int opnd1p1, opnd1p2, opnd2p1, opnd2p2, opnd3p1, opnd3p2;
      register unsigned int tmpresp1, tmpresp2, tmpresp3, tmpresp4;
      unsigned int rightp1, rightp2, rightp3, rightp4;
      unsigned int resultp1, resultp2 = 0, resultp3 = 0, resultp4 = 0;
      register int mpy_exponent, add_exponent, count;
      boolean inexact = FALSE, is_tiny = FALSE;

      unsigned int signlessleft1, signlessright1, save;
      register int result_exponent, diff_exponent;
      int sign_save, jumpsize;
      
      Dbl_copyfromptr(src1ptr,opnd1p1,opnd1p2);
      Dbl_copyfromptr(src2ptr,opnd2p1,opnd2p2);
      Dbl_copyfromptr(src3ptr,opnd3p1,opnd3p2);

      /* 
       * set sign bit of result of multiply
       */
      if (Dbl_sign(opnd1p1) ^ Dbl_sign(opnd2p1)) 
            Dbl_setzerop1(resultp1);
      else
            Dbl_setnegativezerop1(resultp1); 

      /*
       * Generate multiply exponent 
       */
      mpy_exponent = Dbl_exponent(opnd1p1) + Dbl_exponent(opnd2p1) - DBL_BIAS;

      /*
       * check first operand for NaN's or infinity
       */
      if (Dbl_isinfinity_exponent(opnd1p1)) {
            if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) {
                  if (Dbl_isnotnan(opnd2p1,opnd2p2) &&
                      Dbl_isnotnan(opnd3p1,opnd3p2)) {
                        if (Dbl_iszero_exponentmantissa(opnd2p1,opnd2p2)) {
                              /* 
                               * invalid since operands are infinity 
                               * and zero 
                               */
                              if (Is_invalidtrap_enabled())
                                    return(OPC_2E_INVALIDEXCEPTION);
                              Set_invalidflag();
                              Dbl_makequietnan(resultp1,resultp2);
                              Dbl_copytoptr(resultp1,resultp2,dstptr);
                              return(NOEXCEPTION);
                        }
                        /*
                         * Check third operand for infinity with a
                         *  sign opposite of the multiply result
                         */
                        if (Dbl_isinfinity(opnd3p1,opnd3p2) &&
                            (Dbl_sign(resultp1) ^ Dbl_sign(opnd3p1))) {
                              /* 
                               * invalid since attempting a magnitude
                               * subtraction of infinities
                               */
                              if (Is_invalidtrap_enabled())
                                    return(OPC_2E_INVALIDEXCEPTION);
                              Set_invalidflag();
                              Dbl_makequietnan(resultp1,resultp2);
                              Dbl_copytoptr(resultp1,resultp2,dstptr);
                              return(NOEXCEPTION);
                        }

                        /*
                         * return infinity
                         */
                        Dbl_setinfinity_exponentmantissa(resultp1,resultp2);
                        Dbl_copytoptr(resultp1,resultp2,dstptr);
                        return(NOEXCEPTION);
                  }
            }
            else {
                  /*
                   * is NaN; signaling or quiet?
                   */
                  if (Dbl_isone_signaling(opnd1p1)) {
                        /* trap if INVALIDTRAP enabled */
                        if (Is_invalidtrap_enabled()) 
                              return(OPC_2E_INVALIDEXCEPTION);
                        /* make NaN quiet */
                        Set_invalidflag();
                        Dbl_set_quiet(opnd1p1);
                  }
                  /* 
                   * is second operand a signaling NaN? 
                   */
                  else if (Dbl_is_signalingnan(opnd2p1)) {
                        /* trap if INVALIDTRAP enabled */
                        if (Is_invalidtrap_enabled())
                              return(OPC_2E_INVALIDEXCEPTION);
                        /* make NaN quiet */
                        Set_invalidflag();
                        Dbl_set_quiet(opnd2p1);
                        Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
                        return(NOEXCEPTION);
                  }
                  /* 
                   * is third operand a signaling NaN? 
                   */
                  else if (Dbl_is_signalingnan(opnd3p1)) {
                        /* trap if INVALIDTRAP enabled */
                        if (Is_invalidtrap_enabled())
                              return(OPC_2E_INVALIDEXCEPTION);
                        /* make NaN quiet */
                        Set_invalidflag();
                        Dbl_set_quiet(opnd3p1);
                        Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
                        return(NOEXCEPTION);
                  }
                  /*
                   * return quiet NaN
                   */
                  Dbl_copytoptr(opnd1p1,opnd1p2,dstptr);
                  return(NOEXCEPTION);
            }
      }

      /*
       * check second operand for NaN's or infinity
       */
      if (Dbl_isinfinity_exponent(opnd2p1)) {
            if (Dbl_iszero_mantissa(opnd2p1,opnd2p2)) {
                  if (Dbl_isnotnan(opnd3p1,opnd3p2)) {
                        if (Dbl_iszero_exponentmantissa(opnd1p1,opnd1p2)) {
                              /* 
                               * invalid since multiply operands are
                               * zero & infinity
                               */
                              if (Is_invalidtrap_enabled())
                                    return(OPC_2E_INVALIDEXCEPTION);
                              Set_invalidflag();
                              Dbl_makequietnan(opnd2p1,opnd2p2);
                              Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
                              return(NOEXCEPTION);
                        }

                        /*
                         * Check third operand for infinity with a
                         *  sign opposite of the multiply result
                         */
                        if (Dbl_isinfinity(opnd3p1,opnd3p2) &&
                            (Dbl_sign(resultp1) ^ Dbl_sign(opnd3p1))) {
                              /* 
                               * invalid since attempting a magnitude
                               * subtraction of infinities
                               */
                              if (Is_invalidtrap_enabled())
                                          return(OPC_2E_INVALIDEXCEPTION);
                                    Set_invalidflag();
                                    Dbl_makequietnan(resultp1,resultp2);
                              Dbl_copytoptr(resultp1,resultp2,dstptr);
                              return(NOEXCEPTION);
                        }

                        /*
                         * return infinity
                         */
                        Dbl_setinfinity_exponentmantissa(resultp1,resultp2);
                        Dbl_copytoptr(resultp1,resultp2,dstptr);
                        return(NOEXCEPTION);
                  }
            }
            else {
                  /*
                   * is NaN; signaling or quiet?
                   */
                  if (Dbl_isone_signaling(opnd2p1)) {
                        /* trap if INVALIDTRAP enabled */
                        if (Is_invalidtrap_enabled())
                              return(OPC_2E_INVALIDEXCEPTION);
                        /* make NaN quiet */
                        Set_invalidflag();
                        Dbl_set_quiet(opnd2p1);
                  }
                  /* 
                   * is third operand a signaling NaN? 
                   */
                  else if (Dbl_is_signalingnan(opnd3p1)) {
                              /* trap if INVALIDTRAP enabled */
                              if (Is_invalidtrap_enabled())
                                    return(OPC_2E_INVALIDEXCEPTION);
                              /* make NaN quiet */
                              Set_invalidflag();
                              Dbl_set_quiet(opnd3p1);
                        Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
                              return(NOEXCEPTION);
                  }
                  /*
                   * return quiet NaN
                   */
                  Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
                  return(NOEXCEPTION);
            }
      }

      /*
       * check third operand for NaN's or infinity
       */
      if (Dbl_isinfinity_exponent(opnd3p1)) {
            if (Dbl_iszero_mantissa(opnd3p1,opnd3p2)) {
                  /* return infinity */
                  Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
                  return(NOEXCEPTION);
            } else {
                  /*
                   * is NaN; signaling or quiet?
                   */
                  if (Dbl_isone_signaling(opnd3p1)) {
                        /* trap if INVALIDTRAP enabled */
                        if (Is_invalidtrap_enabled())
                              return(OPC_2E_INVALIDEXCEPTION);
                        /* make NaN quiet */
                        Set_invalidflag();
                        Dbl_set_quiet(opnd3p1);
                  }
                  /*
                   * return quiet NaN
                   */
                  Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
                  return(NOEXCEPTION);
            }
      }

      /*
       * Generate multiply mantissa
       */
      if (Dbl_isnotzero_exponent(opnd1p1)) {
            /* set hidden bit */
            Dbl_clear_signexponent_set_hidden(opnd1p1);
      }
      else {
            /* check for zero */
            if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) {
                  /*
                   * Perform the add opnd3 with zero here.
                   */
                  if (Dbl_iszero_exponentmantissa(opnd3p1,opnd3p2)) {
                        if (Is_rounding_mode(ROUNDMINUS)) {
                              Dbl_or_signs(opnd3p1,resultp1);
                        } else {
                              Dbl_and_signs(opnd3p1,resultp1);
                        }
                  }
                  /*
                   * Now let's check for trapped underflow case.
                   */
                  else if (Dbl_iszero_exponent(opnd3p1) &&
                           Is_underflowtrap_enabled()) {
                              /* need to normalize results mantissa */
                              sign_save = Dbl_signextendedsign(opnd3p1);
                        result_exponent = 0;
                              Dbl_leftshiftby1(opnd3p1,opnd3p2);
                              Dbl_normalize(opnd3p1,opnd3p2,result_exponent);
                              Dbl_set_sign(opnd3p1,/*using*/sign_save);
                              Dbl_setwrapped_exponent(opnd3p1,result_exponent,
                                          unfl);
                              Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
                              /* inexact = FALSE */
                              return(OPC_2E_UNDERFLOWEXCEPTION);
                  }
                  Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
                  return(NOEXCEPTION);
            }
            /* is denormalized, adjust exponent */
            Dbl_clear_signexponent(opnd1p1);
            Dbl_leftshiftby1(opnd1p1,opnd1p2);
            Dbl_normalize(opnd1p1,opnd1p2,mpy_exponent);
      }
      /* opnd2 needs to have hidden bit set with msb in hidden bit */
      if (Dbl_isnotzero_exponent(opnd2p1)) {
            Dbl_clear_signexponent_set_hidden(opnd2p1);
      }
      else {
            /* check for zero */
            if (Dbl_iszero_mantissa(opnd2p1,opnd2p2)) {
                  /*
                   * Perform the add opnd3 with zero here.
                   */
                  if (Dbl_iszero_exponentmantissa(opnd3p1,opnd3p2)) {
                        if (Is_rounding_mode(ROUNDMINUS)) {
                              Dbl_or_signs(opnd3p1,resultp1);
                        } else {
                              Dbl_and_signs(opnd3p1,resultp1);
                        }
                  }
                  /*
                   * Now let's check for trapped underflow case.
                   */
                  else if (Dbl_iszero_exponent(opnd3p1) &&
                      Is_underflowtrap_enabled()) {
                              /* need to normalize results mantissa */
                              sign_save = Dbl_signextendedsign(opnd3p1);
                        result_exponent = 0;
                              Dbl_leftshiftby1(opnd3p1,opnd3p2);
                              Dbl_normalize(opnd3p1,opnd3p2,result_exponent);
                              Dbl_set_sign(opnd3p1,/*using*/sign_save);
                              Dbl_setwrapped_exponent(opnd3p1,result_exponent,
                                          unfl);
                              Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
                              /* inexact = FALSE */
                              return(OPC_2E_UNDERFLOWEXCEPTION);
                  }
                  Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
                  return(NOEXCEPTION);
            }
            /* is denormalized; want to normalize */
            Dbl_clear_signexponent(opnd2p1);
            Dbl_leftshiftby1(opnd2p1,opnd2p2);
            Dbl_normalize(opnd2p1,opnd2p2,mpy_exponent);
      }

      /* Multiply the first two source mantissas together */

      /* 
       * The intermediate result will be kept in tmpres,
       * which needs enough room for 106 bits of mantissa,
       * so lets call it a Double extended.
       */
      Dblext_setzero(tmpresp1,tmpresp2,tmpresp3,tmpresp4);

      /* 
       * Four bits at a time are inspected in each loop, and a 
       * simple shift and add multiply algorithm is used. 
       */ 
      for (count = DBL_P-1; count >= 0; count -= 4) {
            Dblext_rightshiftby4(tmpresp1,tmpresp2,tmpresp3,tmpresp4);
            if (Dbit28p2(opnd1p2)) {
                  /* Fourword_add should be an ADD followed by 3 ADDC's */
                  Fourword_add(tmpresp1, tmpresp2, tmpresp3, tmpresp4, 
                   opnd2p1<<3 | opnd2p2>>29, opnd2p2<<3, 0, 0);
            }
            if (Dbit29p2(opnd1p2)) {
                  Fourword_add(tmpresp1, tmpresp2, tmpresp3, tmpresp4,
                   opnd2p1<<2 | opnd2p2>>30, opnd2p2<<2, 0, 0);
            }
            if (Dbit30p2(opnd1p2)) {
                  Fourword_add(tmpresp1, tmpresp2, tmpresp3, tmpresp4,
                   opnd2p1<<1 | opnd2p2>>31, opnd2p2<<1, 0, 0);
            }
            if (Dbit31p2(opnd1p2)) {
                  Fourword_add(tmpresp1, tmpresp2, tmpresp3, tmpresp4,
                   opnd2p1, opnd2p2, 0, 0);
            }
            Dbl_rightshiftby4(opnd1p1,opnd1p2);
      }
      if (Is_dexthiddenoverflow(tmpresp1)) {
            /* result mantissa >= 2 (mantissa overflow) */
            mpy_exponent++;
            Dblext_rightshiftby1(tmpresp1,tmpresp2,tmpresp3,tmpresp4);
      }

      /*
       * Restore the sign of the mpy result which was saved in resultp1.
       * The exponent will continue to be kept in mpy_exponent.
       */
      Dblext_set_sign(tmpresp1,Dbl_sign(resultp1));

      /* 
       * No rounding is required, since the result of the multiply
       * is exact in the extended format.
       */

      /*
       * Now we are ready to perform the add portion of the operation.
       *
       * The exponents need to be kept as integers for now, since the
       * multiply result might not fit into the exponent field.  We
       * can't overflow or underflow because of this yet, since the
       * add could bring the final result back into range.
       */
      add_exponent = Dbl_exponent(opnd3p1);

      /*
       * Check for denormalized or zero add operand.
       */
      if (add_exponent == 0) {
            /* check for zero */
            if (Dbl_iszero_mantissa(opnd3p1,opnd3p2)) {
                  /* right is zero */
                  /* Left can't be zero and must be result.
                   *
                   * The final result is now in tmpres and mpy_exponent,
                   * and needs to be rounded and squeezed back into
                   * double precision format from double extended.
                   */
                  result_exponent = mpy_exponent;
                  Dblext_copy(tmpresp1,tmpresp2,tmpresp3,tmpresp4,
                        resultp1,resultp2,resultp3,resultp4);
                  sign_save = Dbl_signextendedsign(resultp1);/*save sign*/
                  goto round;
            }

            /* 
             * Neither are zeroes.  
             * Adjust exponent and normalize add operand.
             */
            sign_save = Dbl_signextendedsign(opnd3p1);      /* save sign */
            Dbl_clear_signexponent(opnd3p1);
            Dbl_leftshiftby1(opnd3p1,opnd3p2);
            Dbl_normalize(opnd3p1,opnd3p2,add_exponent);
            Dbl_set_sign(opnd3p1,sign_save);    /* restore sign */
      } else {
            Dbl_clear_exponent_set_hidden(opnd3p1);
      }
      /*
       * Copy opnd3 to the double extended variable called right.
       */
      Dbl_copyto_dblext(opnd3p1,opnd3p2,rightp1,rightp2,rightp3,rightp4);

      /*
       * A zero "save" helps discover equal operands (for later),
       * and is used in swapping operands (if needed).
       */
      Dblext_xortointp1(tmpresp1,rightp1,/*to*/save);

      /*
       * Compare magnitude of operands.
       */
      Dblext_copytoint_exponentmantissap1(tmpresp1,signlessleft1);
      Dblext_copytoint_exponentmantissap1(rightp1,signlessright1);
      if (mpy_exponent < add_exponent || mpy_exponent == add_exponent &&
          Dblext_ismagnitudeless(tmpresp2,rightp2,signlessleft1,signlessright1)){
            /*
             * Set the left operand to the larger one by XOR swap.
             * First finish the first word "save".
             */
            Dblext_xorfromintp1(save,rightp1,/*to*/rightp1);
            Dblext_xorfromintp1(save,tmpresp1,/*to*/tmpresp1);
            Dblext_swap_lower(tmpresp2,tmpresp3,tmpresp4,
                  rightp2,rightp3,rightp4);
            /* also setup exponents used in rest of routine */
            diff_exponent = add_exponent - mpy_exponent;
            result_exponent = add_exponent;
      } else {
            /* also setup exponents used in rest of routine */
            diff_exponent = mpy_exponent - add_exponent;
            result_exponent = mpy_exponent;
      }
      /* Invariant: left is not smaller than right. */

      /*
       * Special case alignment of operands that would force alignment
       * beyond the extent of the extension.  A further optimization
       * could special case this but only reduces the path length for
       * this infrequent case.
       */
      if (diff_exponent > DBLEXT_THRESHOLD) {
            diff_exponent = DBLEXT_THRESHOLD;
      }

      /* Align right operand by shifting it to the right */
      Dblext_clear_sign(rightp1);
      Dblext_right_align(rightp1,rightp2,rightp3,rightp4,
            /*shifted by*/diff_exponent);
      
      /* Treat sum and difference of the operands separately. */
      if ((int)save < 0) {
            /*
             * Difference of the two operands.  Overflow can occur if the
             * multiply overflowed.  A borrow can occur out of the hidden
             * bit and force a post normalization phase.
             */
            Dblext_subtract(tmpresp1,tmpresp2,tmpresp3,tmpresp4,
                  rightp1,rightp2,rightp3,rightp4,
                  resultp1,resultp2,resultp3,resultp4);
            sign_save = Dbl_signextendedsign(resultp1);
            if (Dbl_iszero_hidden(resultp1)) {
                  /* Handle normalization */
            /* A straight foward algorithm would now shift the
             * result and extension left until the hidden bit
             * becomes one.  Not all of the extension bits need
             * participate in the shift.  Only the two most 
             * significant bits (round and guard) are needed.
             * If only a single shift is needed then the guard
             * bit becomes a significant low order bit and the
             * extension must participate in the rounding.
             * If more than a single shift is needed, then all
             * bits to the right of the guard bit are zeros, 
             * and the guard bit may or may not be zero. */
                  Dblext_leftshiftby1(resultp1,resultp2,resultp3,
                        resultp4);

                  /* Need to check for a zero result.  The sign and
                   * exponent fields have already been zeroed.  The more
                   * efficient test of the full object can be used.
                   */
                   if (Dblext_iszero(resultp1,resultp2,resultp3,resultp4)) {
                        /* Must have been "x-x" or "x+(-x)". */
                        if (Is_rounding_mode(ROUNDMINUS))
                              Dbl_setone_sign(resultp1);
                        Dbl_copytoptr(resultp1,resultp2,dstptr);
                        return(NOEXCEPTION);
                  }
                  result_exponent--;

                  /* Look to see if normalization is finished. */
                  if (Dbl_isone_hidden(resultp1)) {
                        /* No further normalization is needed */
                        goto round;
                  }

                  /* Discover first one bit to determine shift amount.
                   * Use a modified binary search.  We have already
                   * shifted the result one position right and still
                   * not found a one so the remainder of the extension
                   * must be zero and simplifies rounding. */
                  /* Scan bytes */
                  while (Dbl_iszero_hiddenhigh7mantissa(resultp1)) {
                        Dblext_leftshiftby8(resultp1,resultp2,resultp3,resultp4);
                        result_exponent -= 8;
                  }
                  /* Now narrow it down to the nibble */
                  if (Dbl_iszero_hiddenhigh3mantissa(resultp1)) {
                        /* The lower nibble contains the
                         * normalizing one */
                        Dblext_leftshiftby4(resultp1,resultp2,resultp3,resultp4);
                        result_exponent -= 4;
                  }
                  /* Select case where first bit is set (already
                   * normalized) otherwise select the proper shift. */
                  jumpsize = Dbl_hiddenhigh3mantissa(resultp1);
                  if (jumpsize <= 7) switch(jumpsize) {
                  case 1:
                        Dblext_leftshiftby3(resultp1,resultp2,resultp3,
                              resultp4);
                        result_exponent -= 3;
                        break;
                  case 2:
                  case 3:
                        Dblext_leftshiftby2(resultp1,resultp2,resultp3,
                              resultp4);
                        result_exponent -= 2;
                        break;
                  case 4:
                  case 5:
                  case 6:
                  case 7:
                        Dblext_leftshiftby1(resultp1,resultp2,resultp3,
                              resultp4);
                        result_exponent -= 1;
                        break;
                  }
            } /* end if (hidden...)... */
      /* Fall through and round */
      } /* end if (save < 0)... */
      else {
            /* Add magnitudes */
            Dblext_addition(tmpresp1,tmpresp2,tmpresp3,tmpresp4,
                  rightp1,rightp2,rightp3,rightp4,
                  /*to*/resultp1,resultp2,resultp3,resultp4);
            sign_save = Dbl_signextendedsign(resultp1);
            if (Dbl_isone_hiddenoverflow(resultp1)) {
                  /* Prenormalization required. */
                  Dblext_arithrightshiftby1(resultp1,resultp2,resultp3,
                        resultp4);
                  result_exponent++;
            } /* end if hiddenoverflow... */
      } /* end else ...add magnitudes... */

      /* Round the result.  If the extension and lower two words are
       * all zeros, then the result is exact.  Otherwise round in the
       * correct direction.  Underflow is possible. If a postnormalization
       * is necessary, then the mantissa is all zeros so no shift is needed.
       */
  round:
      if (result_exponent <= 0 && !Is_underflowtrap_enabled()) {
            Dblext_denormalize(resultp1,resultp2,resultp3,resultp4,
                  result_exponent,is_tiny);
      }
      Dbl_set_sign(resultp1,/*using*/sign_save);
      if (Dblext_isnotzero_mantissap3(resultp3) || 
          Dblext_isnotzero_mantissap4(resultp4)) {
            inexact = TRUE;
            switch(Rounding_mode()) {
            case ROUNDNEAREST: /* The default. */
                  if (Dblext_isone_highp3(resultp3)) {
                        /* at least 1/2 ulp */
                        if (Dblext_isnotzero_low31p3(resultp3) ||
                            Dblext_isnotzero_mantissap4(resultp4) ||
                            Dblext_isone_lowp2(resultp2)) {
                              /* either exactly half way and odd or
                               * more than 1/2ulp */
                              Dbl_increment(resultp1,resultp2);
                        }
                  }
                  break;

            case ROUNDPLUS:
                  if (Dbl_iszero_sign(resultp1)) {
                        /* Round up positive results */
                        Dbl_increment(resultp1,resultp2);
                  }
                  break;
          
            case ROUNDMINUS:
                  if (Dbl_isone_sign(resultp1)) {
                        /* Round down negative results */
                        Dbl_increment(resultp1,resultp2);
                  }
          
            case ROUNDZERO:;
                  /* truncate is simple */
            } /* end switch... */
            if (Dbl_isone_hiddenoverflow(resultp1)) result_exponent++;
      }
      if (result_exponent >= DBL_INFINITY_EXPONENT) {
            /* Overflow */
            if (Is_overflowtrap_enabled()) {
                        /*
                         * Adjust bias of result
                         */
                        Dbl_setwrapped_exponent(resultp1,result_exponent,ovfl);
                        Dbl_copytoptr(resultp1,resultp2,dstptr);
                        if (inexact)
                            if (Is_inexacttrap_enabled())
                                return (OPC_2E_OVERFLOWEXCEPTION |
                              OPC_2E_INEXACTEXCEPTION);
                            else Set_inexactflag();
                        return (OPC_2E_OVERFLOWEXCEPTION);
            }
            inexact = TRUE;
            Set_overflowflag();
            Dbl_setoverflow(resultp1,resultp2);
      } else if (result_exponent <= 0) {  /* underflow case */
            if (Is_underflowtrap_enabled()) {
                        /*
                         * Adjust bias of result
                         */
                  Dbl_setwrapped_exponent(resultp1,result_exponent,unfl);
                  Dbl_copytoptr(resultp1,resultp2,dstptr);
                        if (inexact)
                            if (Is_inexacttrap_enabled())
                                return (OPC_2E_UNDERFLOWEXCEPTION |
                              OPC_2E_INEXACTEXCEPTION);
                            else Set_inexactflag();
                  return(OPC_2E_UNDERFLOWEXCEPTION);
            }
            else if (inexact && is_tiny) Set_underflowflag();
      }
      else Dbl_set_exponent(resultp1,result_exponent);
      Dbl_copytoptr(resultp1,resultp2,dstptr);
      if (inexact) 
            if (Is_inexacttrap_enabled()) return(OPC_2E_INEXACTEXCEPTION);
            else Set_inexactflag();
      return(NOEXCEPTION);
}

/*
 *  Single Floating-point Multiply Fused Add
 */

sgl_fmpyfadd(src1ptr,src2ptr,src3ptr,status,dstptr)

sgl_floating_point *src1ptr, *src2ptr, *src3ptr, *dstptr;
unsigned int *status;
{
      unsigned int opnd1, opnd2, opnd3;
      register unsigned int tmpresp1, tmpresp2;
      unsigned int rightp1, rightp2;
      unsigned int resultp1, resultp2 = 0;
      register int mpy_exponent, add_exponent, count;
      boolean inexact = FALSE, is_tiny = FALSE;

      unsigned int signlessleft1, signlessright1, save;
      register int result_exponent, diff_exponent;
      int sign_save, jumpsize;
      
      Sgl_copyfromptr(src1ptr,opnd1);
      Sgl_copyfromptr(src2ptr,opnd2);
      Sgl_copyfromptr(src3ptr,opnd3);

      /* 
       * set sign bit of result of multiply
       */
      if (Sgl_sign(opnd1) ^ Sgl_sign(opnd2)) 
            Sgl_setnegativezero(resultp1); 
      else Sgl_setzero(resultp1);

      /*
       * Generate multiply exponent 
       */
      mpy_exponent = Sgl_exponent(opnd1) + Sgl_exponent(opnd2) - SGL_BIAS;

      /*
       * check first operand for NaN's or infinity
       */
      if (Sgl_isinfinity_exponent(opnd1)) {
            if (Sgl_iszero_mantissa(opnd1)) {
                  if (Sgl_isnotnan(opnd2) && Sgl_isnotnan(opnd3)) {
                        if (Sgl_iszero_exponentmantissa(opnd2)) {
                              /* 
                               * invalid since operands are infinity 
                               * and zero 
                               */
                              if (Is_invalidtrap_enabled())
                                    return(OPC_2E_INVALIDEXCEPTION);
                              Set_invalidflag();
                              Sgl_makequietnan(resultp1);
                              Sgl_copytoptr(resultp1,dstptr);
                              return(NOEXCEPTION);
                        }
                        /*
                         * Check third operand for infinity with a
                         *  sign opposite of the multiply result
                         */
                        if (Sgl_isinfinity(opnd3) &&
                            (Sgl_sign(resultp1) ^ Sgl_sign(opnd3))) {
                              /* 
                               * invalid since attempting a magnitude
                               * subtraction of infinities
                               */
                              if (Is_invalidtrap_enabled())
                                    return(OPC_2E_INVALIDEXCEPTION);
                              Set_invalidflag();
                              Sgl_makequietnan(resultp1);
                              Sgl_copytoptr(resultp1,dstptr);
                              return(NOEXCEPTION);
                        }

                        /*
                         * return infinity
                         */
                        Sgl_setinfinity_exponentmantissa(resultp1);
                        Sgl_copytoptr(resultp1,dstptr);
                        return(NOEXCEPTION);
                  }
            }
            else {
                  /*
                   * is NaN; signaling or quiet?
                   */
                  if (Sgl_isone_signaling(opnd1)) {
                        /* trap if INVALIDTRAP enabled */
                        if (Is_invalidtrap_enabled()) 
                              return(OPC_2E_INVALIDEXCEPTION);
                        /* make NaN quiet */
                        Set_invalidflag();
                        Sgl_set_quiet(opnd1);
                  }
                  /* 
                   * is second operand a signaling NaN? 
                   */
                  else if (Sgl_is_signalingnan(opnd2)) {
                        /* trap if INVALIDTRAP enabled */
                        if (Is_invalidtrap_enabled())
                              return(OPC_2E_INVALIDEXCEPTION);
                        /* make NaN quiet */
                        Set_invalidflag();
                        Sgl_set_quiet(opnd2);
                        Sgl_copytoptr(opnd2,dstptr);
                        return(NOEXCEPTION);
                  }
                  /* 
                   * is third operand a signaling NaN? 
                   */
                  else if (Sgl_is_signalingnan(opnd3)) {
                        /* trap if INVALIDTRAP enabled */
                        if (Is_invalidtrap_enabled())
                              return(OPC_2E_INVALIDEXCEPTION);
                        /* make NaN quiet */
                        Set_invalidflag();
                        Sgl_set_quiet(opnd3);
                        Sgl_copytoptr(opnd3,dstptr);
                        return(NOEXCEPTION);
                  }
                  /*
                   * return quiet NaN
                   */
                  Sgl_copytoptr(opnd1,dstptr);
                  return(NOEXCEPTION);
            }
      }

      /*
       * check second operand for NaN's or infinity
       */
      if (Sgl_isinfinity_exponent(opnd2)) {
            if (Sgl_iszero_mantissa(opnd2)) {
                  if (Sgl_isnotnan(opnd3)) {
                        if (Sgl_iszero_exponentmantissa(opnd1)) {
                              /* 
                               * invalid since multiply operands are
                               * zero & infinity
                               */
                              if (Is_invalidtrap_enabled())
                                    return(OPC_2E_INVALIDEXCEPTION);
                              Set_invalidflag();
                              Sgl_makequietnan(opnd2);
                              Sgl_copytoptr(opnd2,dstptr);
                              return(NOEXCEPTION);
                        }

                        /*
                         * Check third operand for infinity with a
                         *  sign opposite of the multiply result
                         */
                        if (Sgl_isinfinity(opnd3) &&
                            (Sgl_sign(resultp1) ^ Sgl_sign(opnd3))) {
                              /* 
                               * invalid since attempting a magnitude
                               * subtraction of infinities
                               */
                              if (Is_invalidtrap_enabled())
                                          return(OPC_2E_INVALIDEXCEPTION);
                                    Set_invalidflag();
                                    Sgl_makequietnan(resultp1);
                              Sgl_copytoptr(resultp1,dstptr);
                              return(NOEXCEPTION);
                        }

                        /*
                         * return infinity
                         */
                        Sgl_setinfinity_exponentmantissa(resultp1);
                        Sgl_copytoptr(resultp1,dstptr);
                        return(NOEXCEPTION);
                  }
            }
            else {
                  /*
                   * is NaN; signaling or quiet?
                   */
                  if (Sgl_isone_signaling(opnd2)) {
                        /* trap if INVALIDTRAP enabled */
                        if (Is_invalidtrap_enabled())
                              return(OPC_2E_INVALIDEXCEPTION);
                        /* make NaN quiet */
                        Set_invalidflag();
                        Sgl_set_quiet(opnd2);
                  }
                  /* 
                   * is third operand a signaling NaN? 
                   */
                  else if (Sgl_is_signalingnan(opnd3)) {
                              /* trap if INVALIDTRAP enabled */
                              if (Is_invalidtrap_enabled())
                                    return(OPC_2E_INVALIDEXCEPTION);
                              /* make NaN quiet */
                              Set_invalidflag();
                              Sgl_set_quiet(opnd3);
                        Sgl_copytoptr(opnd3,dstptr);
                              return(NOEXCEPTION);
                  }
                  /*
                   * return quiet NaN
                   */
                  Sgl_copytoptr(opnd2,dstptr);
                  return(NOEXCEPTION);
            }
      }

      /*
       * check third operand for NaN's or infinity
       */
      if (Sgl_isinfinity_exponent(opnd3)) {
            if (Sgl_iszero_mantissa(opnd3)) {
                  /* return infinity */
                  Sgl_copytoptr(opnd3,dstptr);
                  return(NOEXCEPTION);
            } else {
                  /*
                   * is NaN; signaling or quiet?
                   */
                  if (Sgl_isone_signaling(opnd3)) {
                        /* trap if INVALIDTRAP enabled */
                        if (Is_invalidtrap_enabled())
                              return(OPC_2E_INVALIDEXCEPTION);
                        /* make NaN quiet */
                        Set_invalidflag();
                        Sgl_set_quiet(opnd3);
                  }
                  /*
                   * return quiet NaN
                   */
                  Sgl_copytoptr(opnd3,dstptr);
                  return(NOEXCEPTION);
            }
      }

      /*
       * Generate multiply mantissa
       */
      if (Sgl_isnotzero_exponent(opnd1)) {
            /* set hidden bit */
            Sgl_clear_signexponent_set_hidden(opnd1);
      }
      else {
            /* check for zero */
            if (Sgl_iszero_mantissa(opnd1)) {
                  /*
                   * Perform the add opnd3 with zero here.
                   */
                  if (Sgl_iszero_exponentmantissa(opnd3)) {
                        if (Is_rounding_mode(ROUNDMINUS)) {
                              Sgl_or_signs(opnd3,resultp1);
                        } else {
                              Sgl_and_signs(opnd3,resultp1);
                        }
                  }
                  /*
                   * Now let's check for trapped underflow case.
                   */
                  else if (Sgl_iszero_exponent(opnd3) &&
                           Is_underflowtrap_enabled()) {
                              /* need to normalize results mantissa */
                              sign_save = Sgl_signextendedsign(opnd3);
                        result_exponent = 0;
                              Sgl_leftshiftby1(opnd3);
                              Sgl_normalize(opnd3,result_exponent);
                              Sgl_set_sign(opnd3,/*using*/sign_save);
                              Sgl_setwrapped_exponent(opnd3,result_exponent,
                                          unfl);
                              Sgl_copytoptr(opnd3,dstptr);
                              /* inexact = FALSE */
                              return(OPC_2E_UNDERFLOWEXCEPTION);
                  }
                  Sgl_copytoptr(opnd3,dstptr);
                  return(NOEXCEPTION);
            }
            /* is denormalized, adjust exponent */
            Sgl_clear_signexponent(opnd1);
            Sgl_leftshiftby1(opnd1);
            Sgl_normalize(opnd1,mpy_exponent);
      }
      /* opnd2 needs to have hidden bit set with msb in hidden bit */
      if (Sgl_isnotzero_exponent(opnd2)) {
            Sgl_clear_signexponent_set_hidden(opnd2);
      }
      else {
            /* check for zero */
            if (Sgl_iszero_mantissa(opnd2)) {
                  /*
                   * Perform the add opnd3 with zero here.
                   */
                  if (Sgl_iszero_exponentmantissa(opnd3)) {
                        if (Is_rounding_mode(ROUNDMINUS)) {
                              Sgl_or_signs(opnd3,resultp1);
                        } else {
                              Sgl_and_signs(opnd3,resultp1);
                        }
                  }
                  /*
                   * Now let's check for trapped underflow case.
                   */
                  else if (Sgl_iszero_exponent(opnd3) &&
                      Is_underflowtrap_enabled()) {
                              /* need to normalize results mantissa */
                              sign_save = Sgl_signextendedsign(opnd3);
                        result_exponent = 0;
                              Sgl_leftshiftby1(opnd3);
                              Sgl_normalize(opnd3,result_exponent);
                              Sgl_set_sign(opnd3,/*using*/sign_save);
                              Sgl_setwrapped_exponent(opnd3,result_exponent,
                                          unfl);
                              Sgl_copytoptr(opnd3,dstptr);
                              /* inexact = FALSE */
                              return(OPC_2E_UNDERFLOWEXCEPTION);
                  }
                  Sgl_copytoptr(opnd3,dstptr);
                  return(NOEXCEPTION);
            }
            /* is denormalized; want to normalize */
            Sgl_clear_signexponent(opnd2);
            Sgl_leftshiftby1(opnd2);
            Sgl_normalize(opnd2,mpy_exponent);
      }

      /* Multiply the first two source mantissas together */

      /* 
       * The intermediate result will be kept in tmpres,
       * which needs enough room for 106 bits of mantissa,
       * so lets call it a Double extended.
       */
      Sglext_setzero(tmpresp1,tmpresp2);

      /* 
       * Four bits at a time are inspected in each loop, and a 
       * simple shift and add multiply algorithm is used. 
       */ 
      for (count = SGL_P-1; count >= 0; count -= 4) {
            Sglext_rightshiftby4(tmpresp1,tmpresp2);
            if (Sbit28(opnd1)) {
                  /* Twoword_add should be an ADD followed by 2 ADDC's */
                  Twoword_add(tmpresp1, tmpresp2, opnd2<<3, 0);
            }
            if (Sbit29(opnd1)) {
                  Twoword_add(tmpresp1, tmpresp2, opnd2<<2, 0);
            }
            if (Sbit30(opnd1)) {
                  Twoword_add(tmpresp1, tmpresp2, opnd2<<1, 0);
            }
            if (Sbit31(opnd1)) {
                  Twoword_add(tmpresp1, tmpresp2, opnd2, 0);
            }
            Sgl_rightshiftby4(opnd1);
      }
      if (Is_sexthiddenoverflow(tmpresp1)) {
            /* result mantissa >= 2 (mantissa overflow) */
            mpy_exponent++;
            Sglext_rightshiftby4(tmpresp1,tmpresp2);
      } else {
            Sglext_rightshiftby3(tmpresp1,tmpresp2);
      }

      /*
       * Restore the sign of the mpy result which was saved in resultp1.
       * The exponent will continue to be kept in mpy_exponent.
       */
      Sglext_set_sign(tmpresp1,Sgl_sign(resultp1));

      /* 
       * No rounding is required, since the result of the multiply
       * is exact in the extended format.
       */

      /*
       * Now we are ready to perform the add portion of the operation.
       *
       * The exponents need to be kept as integers for now, since the
       * multiply result might not fit into the exponent field.  We
       * can't overflow or underflow because of this yet, since the
       * add could bring the final result back into range.
       */
      add_exponent = Sgl_exponent(opnd3);

      /*
       * Check for denormalized or zero add operand.
       */
      if (add_exponent == 0) {
            /* check for zero */
            if (Sgl_iszero_mantissa(opnd3)) {
                  /* right is zero */
                  /* Left can't be zero and must be result.
                   *
                   * The final result is now in tmpres and mpy_exponent,
                   * and needs to be rounded and squeezed back into
                   * double precision format from double extended.
                   */
                  result_exponent = mpy_exponent;
                  Sglext_copy(tmpresp1,tmpresp2,resultp1,resultp2);
                  sign_save = Sgl_signextendedsign(resultp1);/*save sign*/
                  goto round;
            }

            /* 
             * Neither are zeroes.  
             * Adjust exponent and normalize add operand.
             */
            sign_save = Sgl_signextendedsign(opnd3);  /* save sign */
            Sgl_clear_signexponent(opnd3);
            Sgl_leftshiftby1(opnd3);
            Sgl_normalize(opnd3,add_exponent);
            Sgl_set_sign(opnd3,sign_save);            /* restore sign */
      } else {
            Sgl_clear_exponent_set_hidden(opnd3);
      }
      /*
       * Copy opnd3 to the double extended variable called right.
       */
      Sgl_copyto_sglext(opnd3,rightp1,rightp2);

      /*
       * A zero "save" helps discover equal operands (for later),
       * and is used in swapping operands (if needed).
       */
      Sglext_xortointp1(tmpresp1,rightp1,/*to*/save);

      /*
       * Compare magnitude of operands.
       */
      Sglext_copytoint_exponentmantissa(tmpresp1,signlessleft1);
      Sglext_copytoint_exponentmantissa(rightp1,signlessright1);
      if (mpy_exponent < add_exponent || mpy_exponent == add_exponent &&
          Sglext_ismagnitudeless(signlessleft1,signlessright1)) {
            /*
             * Set the left operand to the larger one by XOR swap.
             * First finish the first word "save".
             */
            Sglext_xorfromintp1(save,rightp1,/*to*/rightp1);
            Sglext_xorfromintp1(save,tmpresp1,/*to*/tmpresp1);
            Sglext_swap_lower(tmpresp2,rightp2);
            /* also setup exponents used in rest of routine */
            diff_exponent = add_exponent - mpy_exponent;
            result_exponent = add_exponent;
      } else {
            /* also setup exponents used in rest of routine */
            diff_exponent = mpy_exponent - add_exponent;
            result_exponent = mpy_exponent;
      }
      /* Invariant: left is not smaller than right. */

      /*
       * Special case alignment of operands that would force alignment
       * beyond the extent of the extension.  A further optimization
       * could special case this but only reduces the path length for
       * this infrequent case.
       */
      if (diff_exponent > SGLEXT_THRESHOLD) {
            diff_exponent = SGLEXT_THRESHOLD;
      }

      /* Align right operand by shifting it to the right */
      Sglext_clear_sign(rightp1);
      Sglext_right_align(rightp1,rightp2,/*shifted by*/diff_exponent);
      
      /* Treat sum and difference of the operands separately. */
      if ((int)save < 0) {
            /*
             * Difference of the two operands.  Overflow can occur if the
             * multiply overflowed.  A borrow can occur out of the hidden
             * bit and force a post normalization phase.
             */
            Sglext_subtract(tmpresp1,tmpresp2, rightp1,rightp2,
                  resultp1,resultp2);
            sign_save = Sgl_signextendedsign(resultp1);
            if (Sgl_iszero_hidden(resultp1)) {
                  /* Handle normalization */
            /* A straight foward algorithm would now shift the
             * result and extension left until the hidden bit
             * becomes one.  Not all of the extension bits need
             * participate in the shift.  Only the two most 
             * significant bits (round and guard) are needed.
             * If only a single shift is needed then the guard
             * bit becomes a significant low order bit and the
             * extension must participate in the rounding.
             * If more than a single shift is needed, then all
             * bits to the right of the guard bit are zeros, 
             * and the guard bit may or may not be zero. */
                  Sglext_leftshiftby1(resultp1,resultp2);

                  /* Need to check for a zero result.  The sign and
                   * exponent fields have already been zeroed.  The more
                   * efficient test of the full object can be used.
                   */
                   if (Sglext_iszero(resultp1,resultp2)) {
                        /* Must have been "x-x" or "x+(-x)". */
                        if (Is_rounding_mode(ROUNDMINUS))
                              Sgl_setone_sign(resultp1);
                        Sgl_copytoptr(resultp1,dstptr);
                        return(NOEXCEPTION);
                  }
                  result_exponent--;

                  /* Look to see if normalization is finished. */
                  if (Sgl_isone_hidden(resultp1)) {
                        /* No further normalization is needed */
                        goto round;
                  }

                  /* Discover first one bit to determine shift amount.
                   * Use a modified binary search.  We have already
                   * shifted the result one position right and still
                   * not found a one so the remainder of the extension
                   * must be zero and simplifies rounding. */
                  /* Scan bytes */
                  while (Sgl_iszero_hiddenhigh7mantissa(resultp1)) {
                        Sglext_leftshiftby8(resultp1,resultp2);
                        result_exponent -= 8;
                  }
                  /* Now narrow it down to the nibble */
                  if (Sgl_iszero_hiddenhigh3mantissa(resultp1)) {
                        /* The lower nibble contains the
                         * normalizing one */
                        Sglext_leftshiftby4(resultp1,resultp2);
                        result_exponent -= 4;
                  }
                  /* Select case where first bit is set (already
                   * normalized) otherwise select the proper shift. */
                  jumpsize = Sgl_hiddenhigh3mantissa(resultp1);
                  if (jumpsize <= 7) switch(jumpsize) {
                  case 1:
                        Sglext_leftshiftby3(resultp1,resultp2);
                        result_exponent -= 3;
                        break;
                  case 2:
                  case 3:
                        Sglext_leftshiftby2(resultp1,resultp2);
                        result_exponent -= 2;
                        break;
                  case 4:
                  case 5:
                  case 6:
                  case 7:
                        Sglext_leftshiftby1(resultp1,resultp2);
                        result_exponent -= 1;
                        break;
                  }
            } /* end if (hidden...)... */
      /* Fall through and round */
      } /* end if (save < 0)... */
      else {
            /* Add magnitudes */
            Sglext_addition(tmpresp1,tmpresp2,
                  rightp1,rightp2, /*to*/resultp1,resultp2);
            sign_save = Sgl_signextendedsign(resultp1);
            if (Sgl_isone_hiddenoverflow(resultp1)) {
                  /* Prenormalization required. */
                  Sglext_arithrightshiftby1(resultp1,resultp2);
                  result_exponent++;
            } /* end if hiddenoverflow... */
      } /* end else ...add magnitudes... */

      /* Round the result.  If the extension and lower two words are
       * all zeros, then the result is exact.  Otherwise round in the
       * correct direction.  Underflow is possible. If a postnormalization
       * is necessary, then the mantissa is all zeros so no shift is needed.
       */
  round:
      if (result_exponent <= 0 && !Is_underflowtrap_enabled()) {
            Sglext_denormalize(resultp1,resultp2,result_exponent,is_tiny);
      }
      Sgl_set_sign(resultp1,/*using*/sign_save);
      if (Sglext_isnotzero_mantissap2(resultp2)) {
            inexact = TRUE;
            switch(Rounding_mode()) {
            case ROUNDNEAREST: /* The default. */
                  if (Sglext_isone_highp2(resultp2)) {
                        /* at least 1/2 ulp */
                        if (Sglext_isnotzero_low31p2(resultp2) ||
                            Sglext_isone_lowp1(resultp1)) {
                              /* either exactly half way and odd or
                               * more than 1/2ulp */
                              Sgl_increment(resultp1);
                        }
                  }
                  break;

            case ROUNDPLUS:
                  if (Sgl_iszero_sign(resultp1)) {
                        /* Round up positive results */
                        Sgl_increment(resultp1);
                  }
                  break;
          
            case ROUNDMINUS:
                  if (Sgl_isone_sign(resultp1)) {
                        /* Round down negative results */
                        Sgl_increment(resultp1);
                  }
          
            case ROUNDZERO:;
                  /* truncate is simple */
            } /* end switch... */
            if (Sgl_isone_hiddenoverflow(resultp1)) result_exponent++;
      }
      if (result_exponent >= SGL_INFINITY_EXPONENT) {
            /* Overflow */
            if (Is_overflowtrap_enabled()) {
                        /*
                         * Adjust bias of result
                         */
                        Sgl_setwrapped_exponent(resultp1,result_exponent,ovfl);
                        Sgl_copytoptr(resultp1,dstptr);
                        if (inexact)
                            if (Is_inexacttrap_enabled())
                                return (OPC_2E_OVERFLOWEXCEPTION |
                              OPC_2E_INEXACTEXCEPTION);
                            else Set_inexactflag();
                        return (OPC_2E_OVERFLOWEXCEPTION);
            }
            inexact = TRUE;
            Set_overflowflag();
            Sgl_setoverflow(resultp1);
      } else if (result_exponent <= 0) {  /* underflow case */
            if (Is_underflowtrap_enabled()) {
                        /*
                         * Adjust bias of result
                         */
                  Sgl_setwrapped_exponent(resultp1,result_exponent,unfl);
                  Sgl_copytoptr(resultp1,dstptr);
                        if (inexact)
                            if (Is_inexacttrap_enabled())
                                return (OPC_2E_UNDERFLOWEXCEPTION |
                              OPC_2E_INEXACTEXCEPTION);
                            else Set_inexactflag();
                  return(OPC_2E_UNDERFLOWEXCEPTION);
            }
            else if (inexact && is_tiny) Set_underflowflag();
      }
      else Sgl_set_exponent(resultp1,result_exponent);
      Sgl_copytoptr(resultp1,dstptr);
      if (inexact) 
            if (Is_inexacttrap_enabled()) return(OPC_2E_INEXACTEXCEPTION);
            else Set_inexactflag();
      return(NOEXCEPTION);
}

/*
 *  Single Floating-point Multiply Negate Fused Add
 */

sgl_fmpynfadd(src1ptr,src2ptr,src3ptr,status,dstptr)

sgl_floating_point *src1ptr, *src2ptr, *src3ptr, *dstptr;
unsigned int *status;
{
      unsigned int opnd1, opnd2, opnd3;
      register unsigned int tmpresp1, tmpresp2;
      unsigned int rightp1, rightp2;
      unsigned int resultp1, resultp2 = 0;
      register int mpy_exponent, add_exponent, count;
      boolean inexact = FALSE, is_tiny = FALSE;

      unsigned int signlessleft1, signlessright1, save;
      register int result_exponent, diff_exponent;
      int sign_save, jumpsize;
      
      Sgl_copyfromptr(src1ptr,opnd1);
      Sgl_copyfromptr(src2ptr,opnd2);
      Sgl_copyfromptr(src3ptr,opnd3);

      /* 
       * set sign bit of result of multiply
       */
      if (Sgl_sign(opnd1) ^ Sgl_sign(opnd2)) 
            Sgl_setzero(resultp1);
      else 
            Sgl_setnegativezero(resultp1); 

      /*
       * Generate multiply exponent 
       */
      mpy_exponent = Sgl_exponent(opnd1) + Sgl_exponent(opnd2) - SGL_BIAS;

      /*
       * check first operand for NaN's or infinity
       */
      if (Sgl_isinfinity_exponent(opnd1)) {
            if (Sgl_iszero_mantissa(opnd1)) {
                  if (Sgl_isnotnan(opnd2) && Sgl_isnotnan(opnd3)) {
                        if (Sgl_iszero_exponentmantissa(opnd2)) {
                              /* 
                               * invalid since operands are infinity 
                               * and zero 
                               */
                              if (Is_invalidtrap_enabled())
                                    return(OPC_2E_INVALIDEXCEPTION);
                              Set_invalidflag();
                              Sgl_makequietnan(resultp1);
                              Sgl_copytoptr(resultp1,dstptr);
                              return(NOEXCEPTION);
                        }
                        /*
                         * Check third operand for infinity with a
                         *  sign opposite of the multiply result
                         */
                        if (Sgl_isinfinity(opnd3) &&
                            (Sgl_sign(resultp1) ^ Sgl_sign(opnd3))) {
                              /* 
                               * invalid since attempting a magnitude
                               * subtraction of infinities
                               */
                              if (Is_invalidtrap_enabled())
                                    return(OPC_2E_INVALIDEXCEPTION);
                              Set_invalidflag();
                              Sgl_makequietnan(resultp1);
                              Sgl_copytoptr(resultp1,dstptr);
                              return(NOEXCEPTION);
                        }

                        /*
                         * return infinity
                         */
                        Sgl_setinfinity_exponentmantissa(resultp1);
                        Sgl_copytoptr(resultp1,dstptr);
                        return(NOEXCEPTION);
                  }
            }
            else {
                  /*
                   * is NaN; signaling or quiet?
                   */
                  if (Sgl_isone_signaling(opnd1)) {
                        /* trap if INVALIDTRAP enabled */
                        if (Is_invalidtrap_enabled()) 
                              return(OPC_2E_INVALIDEXCEPTION);
                        /* make NaN quiet */
                        Set_invalidflag();
                        Sgl_set_quiet(opnd1);
                  }
                  /* 
                   * is second operand a signaling NaN? 
                   */
                  else if (Sgl_is_signalingnan(opnd2)) {
                        /* trap if INVALIDTRAP enabled */
                        if (Is_invalidtrap_enabled())
                              return(OPC_2E_INVALIDEXCEPTION);
                        /* make NaN quiet */
                        Set_invalidflag();
                        Sgl_set_quiet(opnd2);
                        Sgl_copytoptr(opnd2,dstptr);
                        return(NOEXCEPTION);
                  }
                  /* 
                   * is third operand a signaling NaN? 
                   */
                  else if (Sgl_is_signalingnan(opnd3)) {
                        /* trap if INVALIDTRAP enabled */
                        if (Is_invalidtrap_enabled())
                              return(OPC_2E_INVALIDEXCEPTION);
                        /* make NaN quiet */
                        Set_invalidflag();
                        Sgl_set_quiet(opnd3);
                        Sgl_copytoptr(opnd3,dstptr);
                        return(NOEXCEPTION);
                  }
                  /*
                   * return quiet NaN
                   */
                  Sgl_copytoptr(opnd1,dstptr);
                  return(NOEXCEPTION);
            }
      }

      /*
       * check second operand for NaN's or infinity
       */
      if (Sgl_isinfinity_exponent(opnd2)) {
            if (Sgl_iszero_mantissa(opnd2)) {
                  if (Sgl_isnotnan(opnd3)) {
                        if (Sgl_iszero_exponentmantissa(opnd1)) {
                              /* 
                               * invalid since multiply operands are
                               * zero & infinity
                               */
                              if (Is_invalidtrap_enabled())
                                    return(OPC_2E_INVALIDEXCEPTION);
                              Set_invalidflag();
                              Sgl_makequietnan(opnd2);
                              Sgl_copytoptr(opnd2,dstptr);
                              return(NOEXCEPTION);
                        }

                        /*
                         * Check third operand for infinity with a
                         *  sign opposite of the multiply result
                         */
                        if (Sgl_isinfinity(opnd3) &&
                            (Sgl_sign(resultp1) ^ Sgl_sign(opnd3))) {
                              /* 
                               * invalid since attempting a magnitude
                               * subtraction of infinities
                               */
                              if (Is_invalidtrap_enabled())
                                          return(OPC_2E_INVALIDEXCEPTION);
                                    Set_invalidflag();
                                    Sgl_makequietnan(resultp1);
                              Sgl_copytoptr(resultp1,dstptr);
                              return(NOEXCEPTION);
                        }

                        /*
                         * return infinity
                         */
                        Sgl_setinfinity_exponentmantissa(resultp1);
                        Sgl_copytoptr(resultp1,dstptr);
                        return(NOEXCEPTION);
                  }
            }
            else {
                  /*
                   * is NaN; signaling or quiet?
                   */
                  if (Sgl_isone_signaling(opnd2)) {
                        /* trap if INVALIDTRAP enabled */
                        if (Is_invalidtrap_enabled())
                              return(OPC_2E_INVALIDEXCEPTION);
                        /* make NaN quiet */
                        Set_invalidflag();
                        Sgl_set_quiet(opnd2);
                  }
                  /* 
                   * is third operand a signaling NaN? 
                   */
                  else if (Sgl_is_signalingnan(opnd3)) {
                              /* trap if INVALIDTRAP enabled */
                              if (Is_invalidtrap_enabled())
                                    return(OPC_2E_INVALIDEXCEPTION);
                              /* make NaN quiet */
                              Set_invalidflag();
                              Sgl_set_quiet(opnd3);
                        Sgl_copytoptr(opnd3,dstptr);
                              return(NOEXCEPTION);
                  }
                  /*
                   * return quiet NaN
                   */
                  Sgl_copytoptr(opnd2,dstptr);
                  return(NOEXCEPTION);
            }
      }

      /*
       * check third operand for NaN's or infinity
       */
      if (Sgl_isinfinity_exponent(opnd3)) {
            if (Sgl_iszero_mantissa(opnd3)) {
                  /* return infinity */
                  Sgl_copytoptr(opnd3,dstptr);
                  return(NOEXCEPTION);
            } else {
                  /*
                   * is NaN; signaling or quiet?
                   */
                  if (Sgl_isone_signaling(opnd3)) {
                        /* trap if INVALIDTRAP enabled */
                        if (Is_invalidtrap_enabled())
                              return(OPC_2E_INVALIDEXCEPTION);
                        /* make NaN quiet */
                        Set_invalidflag();
                        Sgl_set_quiet(opnd3);
                  }
                  /*
                   * return quiet NaN
                   */
                  Sgl_copytoptr(opnd3,dstptr);
                  return(NOEXCEPTION);
            }
      }

      /*
       * Generate multiply mantissa
       */
      if (Sgl_isnotzero_exponent(opnd1)) {
            /* set hidden bit */
            Sgl_clear_signexponent_set_hidden(opnd1);
      }
      else {
            /* check for zero */
            if (Sgl_iszero_mantissa(opnd1)) {
                  /*
                   * Perform the add opnd3 with zero here.
                   */
                  if (Sgl_iszero_exponentmantissa(opnd3)) {
                        if (Is_rounding_mode(ROUNDMINUS)) {
                              Sgl_or_signs(opnd3,resultp1);
                        } else {
                              Sgl_and_signs(opnd3,resultp1);
                        }
                  }
                  /*
                   * Now let's check for trapped underflow case.
                   */
                  else if (Sgl_iszero_exponent(opnd3) &&
                           Is_underflowtrap_enabled()) {
                              /* need to normalize results mantissa */
                              sign_save = Sgl_signextendedsign(opnd3);
                        result_exponent = 0;
                              Sgl_leftshiftby1(opnd3);
                              Sgl_normalize(opnd3,result_exponent);
                              Sgl_set_sign(opnd3,/*using*/sign_save);
                              Sgl_setwrapped_exponent(opnd3,result_exponent,
                                          unfl);
                              Sgl_copytoptr(opnd3,dstptr);
                              /* inexact = FALSE */
                              return(OPC_2E_UNDERFLOWEXCEPTION);
                  }
                  Sgl_copytoptr(opnd3,dstptr);
                  return(NOEXCEPTION);
            }
            /* is denormalized, adjust exponent */
            Sgl_clear_signexponent(opnd1);
            Sgl_leftshiftby1(opnd1);
            Sgl_normalize(opnd1,mpy_exponent);
      }
      /* opnd2 needs to have hidden bit set with msb in hidden bit */
      if (Sgl_isnotzero_exponent(opnd2)) {
            Sgl_clear_signexponent_set_hidden(opnd2);
      }
      else {
            /* check for zero */
            if (Sgl_iszero_mantissa(opnd2)) {
                  /*
                   * Perform the add opnd3 with zero here.
                   */
                  if (Sgl_iszero_exponentmantissa(opnd3)) {
                        if (Is_rounding_mode(ROUNDMINUS)) {
                              Sgl_or_signs(opnd3,resultp1);
                        } else {
                              Sgl_and_signs(opnd3,resultp1);
                        }
                  }
                  /*
                   * Now let's check for trapped underflow case.
                   */
                  else if (Sgl_iszero_exponent(opnd3) &&
                      Is_underflowtrap_enabled()) {
                              /* need to normalize results mantissa */
                              sign_save = Sgl_signextendedsign(opnd3);
                        result_exponent = 0;
                              Sgl_leftshiftby1(opnd3);
                              Sgl_normalize(opnd3,result_exponent);
                              Sgl_set_sign(opnd3,/*using*/sign_save);
                              Sgl_setwrapped_exponent(opnd3,result_exponent,
                                          unfl);
                              Sgl_copytoptr(opnd3,dstptr);
                              /* inexact = FALSE */
                              return(OPC_2E_UNDERFLOWEXCEPTION);
                  }
                  Sgl_copytoptr(opnd3,dstptr);
                  return(NOEXCEPTION);
            }
            /* is denormalized; want to normalize */
            Sgl_clear_signexponent(opnd2);
            Sgl_leftshiftby1(opnd2);
            Sgl_normalize(opnd2,mpy_exponent);
      }

      /* Multiply the first two source mantissas together */

      /* 
       * The intermediate result will be kept in tmpres,
       * which needs enough room for 106 bits of mantissa,
       * so lets call it a Double extended.
       */
      Sglext_setzero(tmpresp1,tmpresp2);

      /* 
       * Four bits at a time are inspected in each loop, and a 
       * simple shift and add multiply algorithm is used. 
       */ 
      for (count = SGL_P-1; count >= 0; count -= 4) {
            Sglext_rightshiftby4(tmpresp1,tmpresp2);
            if (Sbit28(opnd1)) {
                  /* Twoword_add should be an ADD followed by 2 ADDC's */
                  Twoword_add(tmpresp1, tmpresp2, opnd2<<3, 0);
            }
            if (Sbit29(opnd1)) {
                  Twoword_add(tmpresp1, tmpresp2, opnd2<<2, 0);
            }
            if (Sbit30(opnd1)) {
                  Twoword_add(tmpresp1, tmpresp2, opnd2<<1, 0);
            }
            if (Sbit31(opnd1)) {
                  Twoword_add(tmpresp1, tmpresp2, opnd2, 0);
            }
            Sgl_rightshiftby4(opnd1);
      }
      if (Is_sexthiddenoverflow(tmpresp1)) {
            /* result mantissa >= 2 (mantissa overflow) */
            mpy_exponent++;
            Sglext_rightshiftby4(tmpresp1,tmpresp2);
      } else {
            Sglext_rightshiftby3(tmpresp1,tmpresp2);
      }

      /*
       * Restore the sign of the mpy result which was saved in resultp1.
       * The exponent will continue to be kept in mpy_exponent.
       */
      Sglext_set_sign(tmpresp1,Sgl_sign(resultp1));

      /* 
       * No rounding is required, since the result of the multiply
       * is exact in the extended format.
       */

      /*
       * Now we are ready to perform the add portion of the operation.
       *
       * The exponents need to be kept as integers for now, since the
       * multiply result might not fit into the exponent field.  We
       * can't overflow or underflow because of this yet, since the
       * add could bring the final result back into range.
       */
      add_exponent = Sgl_exponent(opnd3);

      /*
       * Check for denormalized or zero add operand.
       */
      if (add_exponent == 0) {
            /* check for zero */
            if (Sgl_iszero_mantissa(opnd3)) {
                  /* right is zero */
                  /* Left can't be zero and must be result.
                   *
                   * The final result is now in tmpres and mpy_exponent,
                   * and needs to be rounded and squeezed back into
                   * double precision format from double extended.
                   */
                  result_exponent = mpy_exponent;
                  Sglext_copy(tmpresp1,tmpresp2,resultp1,resultp2);
                  sign_save = Sgl_signextendedsign(resultp1);/*save sign*/
                  goto round;
            }

            /* 
             * Neither are zeroes.  
             * Adjust exponent and normalize add operand.
             */
            sign_save = Sgl_signextendedsign(opnd3);  /* save sign */
            Sgl_clear_signexponent(opnd3);
            Sgl_leftshiftby1(opnd3);
            Sgl_normalize(opnd3,add_exponent);
            Sgl_set_sign(opnd3,sign_save);            /* restore sign */
      } else {
            Sgl_clear_exponent_set_hidden(opnd3);
      }
      /*
       * Copy opnd3 to the double extended variable called right.
       */
      Sgl_copyto_sglext(opnd3,rightp1,rightp2);

      /*
       * A zero "save" helps discover equal operands (for later),
       * and is used in swapping operands (if needed).
       */
      Sglext_xortointp1(tmpresp1,rightp1,/*to*/save);

      /*
       * Compare magnitude of operands.
       */
      Sglext_copytoint_exponentmantissa(tmpresp1,signlessleft1);
      Sglext_copytoint_exponentmantissa(rightp1,signlessright1);
      if (mpy_exponent < add_exponent || mpy_exponent == add_exponent &&
          Sglext_ismagnitudeless(signlessleft1,signlessright1)) {
            /*
             * Set the left operand to the larger one by XOR swap.
             * First finish the first word "save".
             */
            Sglext_xorfromintp1(save,rightp1,/*to*/rightp1);
            Sglext_xorfromintp1(save,tmpresp1,/*to*/tmpresp1);
            Sglext_swap_lower(tmpresp2,rightp2);
            /* also setup exponents used in rest of routine */
            diff_exponent = add_exponent - mpy_exponent;
            result_exponent = add_exponent;
      } else {
            /* also setup exponents used in rest of routine */
            diff_exponent = mpy_exponent - add_exponent;
            result_exponent = mpy_exponent;
      }
      /* Invariant: left is not smaller than right. */

      /*
       * Special case alignment of operands that would force alignment
       * beyond the extent of the extension.  A further optimization
       * could special case this but only reduces the path length for
       * this infrequent case.
       */
      if (diff_exponent > SGLEXT_THRESHOLD) {
            diff_exponent = SGLEXT_THRESHOLD;
      }

      /* Align right operand by shifting it to the right */
      Sglext_clear_sign(rightp1);
      Sglext_right_align(rightp1,rightp2,/*shifted by*/diff_exponent);
      
      /* Treat sum and difference of the operands separately. */
      if ((int)save < 0) {
            /*
             * Difference of the two operands.  Overflow can occur if the
             * multiply overflowed.  A borrow can occur out of the hidden
             * bit and force a post normalization phase.
             */
            Sglext_subtract(tmpresp1,tmpresp2, rightp1,rightp2,
                  resultp1,resultp2);
            sign_save = Sgl_signextendedsign(resultp1);
            if (Sgl_iszero_hidden(resultp1)) {
                  /* Handle normalization */
            /* A straight foward algorithm would now shift the
             * result and extension left until the hidden bit
             * becomes one.  Not all of the extension bits need
             * participate in the shift.  Only the two most 
             * significant bits (round and guard) are needed.
             * If only a single shift is needed then the guard
             * bit becomes a significant low order bit and the
             * extension must participate in the rounding.
             * If more than a single shift is needed, then all
             * bits to the right of the guard bit are zeros, 
             * and the guard bit may or may not be zero. */
                  Sglext_leftshiftby1(resultp1,resultp2);

                  /* Need to check for a zero result.  The sign and
                   * exponent fields have already been zeroed.  The more
                   * efficient test of the full object can be used.
                   */
                   if (Sglext_iszero(resultp1,resultp2)) {
                        /* Must have been "x-x" or "x+(-x)". */
                        if (Is_rounding_mode(ROUNDMINUS))
                              Sgl_setone_sign(resultp1);
                        Sgl_copytoptr(resultp1,dstptr);
                        return(NOEXCEPTION);
                  }
                  result_exponent--;

                  /* Look to see if normalization is finished. */
                  if (Sgl_isone_hidden(resultp1)) {
                        /* No further normalization is needed */
                        goto round;
                  }

                  /* Discover first one bit to determine shift amount.
                   * Use a modified binary search.  We have already
                   * shifted the result one position right and still
                   * not found a one so the remainder of the extension
                   * must be zero and simplifies rounding. */
                  /* Scan bytes */
                  while (Sgl_iszero_hiddenhigh7mantissa(resultp1)) {
                        Sglext_leftshiftby8(resultp1,resultp2);
                        result_exponent -= 8;
                  }
                  /* Now narrow it down to the nibble */
                  if (Sgl_iszero_hiddenhigh3mantissa(resultp1)) {
                        /* The lower nibble contains the
                         * normalizing one */
                        Sglext_leftshiftby4(resultp1,resultp2);
                        result_exponent -= 4;
                  }
                  /* Select case where first bit is set (already
                   * normalized) otherwise select the proper shift. */
                  jumpsize = Sgl_hiddenhigh3mantissa(resultp1);
                  if (jumpsize <= 7) switch(jumpsize) {
                  case 1:
                        Sglext_leftshiftby3(resultp1,resultp2);
                        result_exponent -= 3;
                        break;
                  case 2:
                  case 3:
                        Sglext_leftshiftby2(resultp1,resultp2);
                        result_exponent -= 2;
                        break;
                  case 4:
                  case 5:
                  case 6:
                  case 7:
                        Sglext_leftshiftby1(resultp1,resultp2);
                        result_exponent -= 1;
                        break;
                  }
            } /* end if (hidden...)... */
      /* Fall through and round */
      } /* end if (save < 0)... */
      else {
            /* Add magnitudes */
            Sglext_addition(tmpresp1,tmpresp2,
                  rightp1,rightp2, /*to*/resultp1,resultp2);
            sign_save = Sgl_signextendedsign(resultp1);
            if (Sgl_isone_hiddenoverflow(resultp1)) {
                  /* Prenormalization required. */
                  Sglext_arithrightshiftby1(resultp1,resultp2);
                  result_exponent++;
            } /* end if hiddenoverflow... */
      } /* end else ...add magnitudes... */

      /* Round the result.  If the extension and lower two words are
       * all zeros, then the result is exact.  Otherwise round in the
       * correct direction.  Underflow is possible. If a postnormalization
       * is necessary, then the mantissa is all zeros so no shift is needed.
       */
  round:
      if (result_exponent <= 0 && !Is_underflowtrap_enabled()) {
            Sglext_denormalize(resultp1,resultp2,result_exponent,is_tiny);
      }
      Sgl_set_sign(resultp1,/*using*/sign_save);
      if (Sglext_isnotzero_mantissap2(resultp2)) {
            inexact = TRUE;
            switch(Rounding_mode()) {
            case ROUNDNEAREST: /* The default. */
                  if (Sglext_isone_highp2(resultp2)) {
                        /* at least 1/2 ulp */
                        if (Sglext_isnotzero_low31p2(resultp2) ||
                            Sglext_isone_lowp1(resultp1)) {
                              /* either exactly half way and odd or
                               * more than 1/2ulp */
                              Sgl_increment(resultp1);
                        }
                  }
                  break;

            case ROUNDPLUS:
                  if (Sgl_iszero_sign(resultp1)) {
                        /* Round up positive results */
                        Sgl_increment(resultp1);
                  }
                  break;
          
            case ROUNDMINUS:
                  if (Sgl_isone_sign(resultp1)) {
                        /* Round down negative results */
                        Sgl_increment(resultp1);
                  }
          
            case ROUNDZERO:;
                  /* truncate is simple */
            } /* end switch... */
            if (Sgl_isone_hiddenoverflow(resultp1)) result_exponent++;
      }
      if (result_exponent >= SGL_INFINITY_EXPONENT) {
            /* Overflow */
            if (Is_overflowtrap_enabled()) {
                        /*
                         * Adjust bias of result
                         */
                        Sgl_setwrapped_exponent(resultp1,result_exponent,ovfl);
                        Sgl_copytoptr(resultp1,dstptr);
                        if (inexact)
                            if (Is_inexacttrap_enabled())
                                return (OPC_2E_OVERFLOWEXCEPTION |
                              OPC_2E_INEXACTEXCEPTION);
                            else Set_inexactflag();
                        return (OPC_2E_OVERFLOWEXCEPTION);
            }
            inexact = TRUE;
            Set_overflowflag();
            Sgl_setoverflow(resultp1);
      } else if (result_exponent <= 0) {  /* underflow case */
            if (Is_underflowtrap_enabled()) {
                        /*
                         * Adjust bias of result
                         */
                  Sgl_setwrapped_exponent(resultp1,result_exponent,unfl);
                  Sgl_copytoptr(resultp1,dstptr);
                        if (inexact)
                            if (Is_inexacttrap_enabled())
                                return (OPC_2E_UNDERFLOWEXCEPTION |
                              OPC_2E_INEXACTEXCEPTION);
                            else Set_inexactflag();
                  return(OPC_2E_UNDERFLOWEXCEPTION);
            }
            else if (inexact && is_tiny) Set_underflowflag();
      }
      else Sgl_set_exponent(resultp1,result_exponent);
      Sgl_copytoptr(resultp1,dstptr);
      if (inexact) 
            if (Is_inexacttrap_enabled()) return(OPC_2E_INEXACTEXCEPTION);
            else Set_inexactflag();
      return(NOEXCEPTION);
}


Generated by  Doxygen 1.6.0   Back to index