This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Bootstrap failure on solaris2.7 (was: new real.c implementation)


 > From: Richard Henderson <rth@redhat.com>
 > 
 > On Tue, Sep 17, 2002 at 04:43:50PM -0400, Kaveh R. Ghazi wrote:
 > > I'm getting another (different) bootstrap failure in stage1 for
 > > sparc-sun-solaris2.7:
 > > 
 > >  > ./xgcc -B./ -B/usr/local/sparc-sun-solaris2.7/bin/ -isystem
 > >  >   /usr/local/sparc-sun-solaris2.7/include -isystem
 > >  >   /usr/local/sparc-sun-solaris2.7/sys-include -c -o crt1.o -x
 > >  >   assembler-with-cpp
 > >  >   ../../egcc-CVS20020917/gcc/config/sparc/sol2-c1.asm
 > >  > cc1: internal compiler error: in ?, at real.c:1964
 > >  > Please submit a full bug report,
 > >  > with preprocessed source if appropriate.
 > >  > See <URL:http://www.gnu.org/software/gcc/bugs.html> for instructions.
 > >  > make[2]: *** [crt1.o] Error 1
 > >  > make[2]: Leaving directory `/tmp/kg/basel/build/gcc'
 > >  > make[1]: *** [stage1_build] Error 2
 > > 
 > > This occurs if I use cc for stage1.
 > 
 > I can reproduce this, but I don't seem to be able to debug it.
 > We don't seem to have dbx installed, and gdb won't read cc's
 > debug information.
 > 
 > >   [4] real_digit(n = -1), line 1964 in "real.c"
 > 
 > This should never happen.  N should be between 0 and 9.
 > 
 > Can you find out why this happened?
 > r~


Ok I'm still having problems bootstrapping with cc on solaris2 and I
haven't had a lot of luck with dbx, the code is all very confusing.
But I was able to narrow down what code is causing trouble.  If I
bootstrap with cc for stage1 (wait for the crash) then recompile
real.c with gcc (2.95.2) and proceed, then the resulting cc1 can
compile minimal files.

Ok no surprise its real.c, however I narrowed down which functions
inside there that are the problem.  I created a real2.c file and moved
code there until I got a good cc1.  Turns out three functions are
critical: normalize, real_to_integer and do_multiply.  If just these
functions are compiled with gcc things work.  Don't know why, perhaps
there's a bug in solaris2's cc or some subtle difference like the bool
thing.

This isn't all, cause the bootstrap will die later on in a different
place if I continue.  However its a start, hope its helpful.  I've
included the patch I used to move the three functions into real2.c so
you can compile just that part with gcc and reproduce this.  Apply the
patch, bootstrap with cc for stage1, wait for the crash, recompile
real2.c with gcc, make libbackend.a, compile cc1 with gcc too, then
proceed.  It should be able to compile sol2-c1.asm, but I get a
different crash compiling crtbegin.o later on.

		--Kaveh


diff -rup orig/egcc-CVS20020920/gcc/Makefile.in egcc-CVS20020920/gcc/Makefile.in
--- orig/egcc-CVS20020920/gcc/Makefile.in	2002-09-16 16:00:13.000000000 -0400
+++ egcc-CVS20020920/gcc/Makefile.in	2002-09-20 20:44:04.460836395 -0400
@@ -744,7 +744,7 @@ OBJS = alias.o bb-reorder.o bitmap.o bui
  integrate.o intl.o jump.o  langhooks.o lcm.o lists.o local-alloc.o	   \
  loop.o mbchar.o optabs.o params.o predict.o print-rtl.o print-tree.o	   \
  profile.o ra.o ra-build.o ra-colorize.o ra-debug.o ra-rewrite.o	   \
- real.o recog.o reg-stack.o regclass.o regmove.o regrename.o		   \
+ real.o real2.o recog.o reg-stack.o regclass.o regmove.o regrename.o	   \
  reload.o reload1.o reorg.o resource.o rtl.o rtlanal.o rtl-error.o	   \
  sbitmap.o sched-deps.o sched-ebb.o sched-rgn.o sched-vis.o sdbout.o	   \
  sibcall.o simplify-rtx.o ssa.o ssa-ccp.o ssa-dce.o stmt.o		   \
@@ -1462,7 +1462,8 @@ emit-rtl.o : emit-rtl.c $(CONFIG_H) $(SY
    function.h $(REGS_H) insn-config.h $(RECOG_H) real.h $(GGC_H) \
    $(EXPR_H) $(srcdir)/../include/obstack.h hard-reg-set.h bitmap.h toplev.h \
    $(HASHTAB_H) $(TM_P_H) debug.h langhooks.h
-real.o : real.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) toplev.h $(TM_P_H)
+real.o : real.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) toplev.h $(TM_P_H) real.h
+real2.o : real2.c $(CONFIG_H) $(SYSTEM_H) $(TM_P_H) real.h
 integrate.o : integrate.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) flags.h \
    debug.h $(INTEGRATE_H) insn-config.h $(EXPR_H) real.h $(REGS_H) \
    intl.h function.h output.h $(RECOG_H) except.h toplev.h $(LOOP_H) \
diff -rup orig/egcc-CVS20020920/gcc/real.c egcc-CVS20020920/gcc/real.c
--- orig/egcc-CVS20020920/gcc/real.c	2002-09-20 16:00:23.000000000 -0400
+++ egcc-CVS20020920/gcc/real.c	2002-09-20 20:38:42.789065084 -0400
@@ -106,19 +106,13 @@ struct real_format
 static const struct real_format *fmt_for_mode[TFmode - QFmode + 1];
 
 
-static void get_zero PARAMS ((REAL_VALUE_TYPE *, int));
-static void get_canonical_qnan PARAMS ((REAL_VALUE_TYPE *, int));
 static void get_canonical_snan PARAMS ((REAL_VALUE_TYPE *, int));
-static void get_inf PARAMS ((REAL_VALUE_TYPE *, int));
 static void sticky_rshift_significand PARAMS ((REAL_VALUE_TYPE *,
 					       const REAL_VALUE_TYPE *,
 					       unsigned int));
 static void rshift_significand PARAMS ((REAL_VALUE_TYPE *,
 					const REAL_VALUE_TYPE *,
 					unsigned int));
-static void lshift_significand PARAMS ((REAL_VALUE_TYPE *,
-					const REAL_VALUE_TYPE *,
-					unsigned int));
 static void lshift_significand_1 PARAMS ((REAL_VALUE_TYPE *,
 					  const REAL_VALUE_TYPE *));
 static bool add_significands PARAMS ((REAL_VALUE_TYPE *r,
@@ -139,13 +133,7 @@ static void clear_significand_below PARA
 static bool div_significands PARAMS ((REAL_VALUE_TYPE *,
 				      const REAL_VALUE_TYPE *,
 				      const REAL_VALUE_TYPE *));
-static void normalize PARAMS ((REAL_VALUE_TYPE *));
 
-static void do_add PARAMS ((REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *,
-			    const REAL_VALUE_TYPE *, int));
-static void do_multiply PARAMS ((REAL_VALUE_TYPE *,
-				 const REAL_VALUE_TYPE *,
-				 const REAL_VALUE_TYPE *));
 static void do_divide PARAMS ((REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *,
 			       const REAL_VALUE_TYPE *));
 static int do_compare PARAMS ((const REAL_VALUE_TYPE *,
@@ -161,7 +149,7 @@ static void round_for_format PARAMS ((co
 
 /* Initialize R with a positive zero.  */
 
-static inline void
+void
 get_zero (r, sign)
      REAL_VALUE_TYPE *r;
      int sign;
@@ -172,7 +160,7 @@ get_zero (r, sign)
 
 /* Initialize R with the canonical quiet NaN.  */
 
-static inline void
+void
 get_canonical_qnan (r, sign)
      REAL_VALUE_TYPE *r;
      int sign;
@@ -194,7 +182,7 @@ get_canonical_snan (r, sign)
   r->sig[SIGSZ-1] = SIG_MSB >> 2;
 }
 
-static inline void
+void
 get_inf (r, sign)
      REAL_VALUE_TYPE *r;
      int sign;
@@ -281,7 +269,7 @@ rshift_significand (r, a, n)
 /* Left-shift the significand of A by N bits; put the result in the
    significand of R.  */
 
-static void
+void
 lshift_significand (r, a, n)
      REAL_VALUE_TYPE *r;
      const REAL_VALUE_TYPE *a;
@@ -531,57 +519,10 @@ div_significands (r, a, b)
   return inexact != 0;
 }
 
-/* Adjust the exponent and significand of R such that the most
-   significant bit is set.  We underflow to zero and overflow to
-   infinity here, without denormals.  (The intermediate representation
-   exponent is large enough to handle target denormals normalized.)  */
-
-static void
-normalize (r)
-     REAL_VALUE_TYPE *r;
-{
-  int shift = 0, exp;
-  int i, j;
-
-  /* Find the first word that is non-zero.  */
-  for (i = SIGSZ - 1; i >= 0; i--)
-    if (r->sig[i] == 0)
-      shift += HOST_BITS_PER_LONG;
-    else
-      break;
-
-  /* Zero significand flushes to zero.  */
-  if (i < 0)
-    {
-      r->class = rvc_zero;
-      r->exp = 0;
-      return;
-    }
-
-  /* Find the first bit that is non-zero.  */
-  for (j = 0; ; j++)
-    if (r->sig[i] & ((unsigned long)1 << (HOST_BITS_PER_LONG - 1 - j)))
-      break;
-  shift += j;
-
-  if (shift > 0)
-    {
-      exp = r->exp - shift;
-      if (exp > MAX_EXP)
-	get_inf (r, r->sign);
-      else if (exp < -MAX_EXP)
-	get_zero (r, r->sign);
-      else
-	{
-	  r->exp = exp;
-	  lshift_significand (r, r, shift);
-	}
-    }
-}
 
 /* Return R = A + (SUBTRACT_P ? -B : B).  */
 
-static void
+void
 do_add (r, a, b, subtract_p)
      REAL_VALUE_TYPE *r;
      const REAL_VALUE_TYPE *a, *b;
@@ -713,135 +654,6 @@ do_add (r, a, b, subtract_p)
     r->sign = 0;
 }
 
-/* Return R = A * B.  */
-
-static void
-do_multiply (r, a, b)
-     REAL_VALUE_TYPE *r;
-     const REAL_VALUE_TYPE *a, *b;
-{
-  REAL_VALUE_TYPE u, t, *rr;
-  unsigned int i, j, k;
-  int sign = a->sign ^ b->sign;
-
-  switch (CLASS2 (a->class, b->class))
-    {
-    case CLASS2 (rvc_zero, rvc_zero):
-    case CLASS2 (rvc_zero, rvc_normal):
-    case CLASS2 (rvc_normal, rvc_zero):
-      /* +-0 * ANY = 0 with appropriate sign.  */
-      get_zero (r, sign);
-      return;
-
-    case CLASS2 (rvc_zero, rvc_nan):
-    case CLASS2 (rvc_normal, rvc_nan):
-    case CLASS2 (rvc_inf, rvc_nan):
-    case CLASS2 (rvc_nan, rvc_nan):
-      /* ANY * NaN = NaN.  */
-      *r = *b;
-      r->sign = sign;
-      return;
-
-    case CLASS2 (rvc_nan, rvc_zero):
-    case CLASS2 (rvc_nan, rvc_normal):
-    case CLASS2 (rvc_nan, rvc_inf):
-      /* NaN * ANY = NaN.  */
-      *r = *a;
-      r->sign = sign;
-      return;
-
-    case CLASS2 (rvc_zero, rvc_inf):
-    case CLASS2 (rvc_inf, rvc_zero):
-      /* 0 * Inf = NaN */
-      get_canonical_qnan (r, sign);
-      return;
-
-    case CLASS2 (rvc_inf, rvc_inf):
-    case CLASS2 (rvc_normal, rvc_inf):
-    case CLASS2 (rvc_inf, rvc_normal):
-      /* Inf * Inf = Inf, R * Inf = Inf */
-    overflow:
-      get_inf (r, sign);
-      return;
-
-    case CLASS2 (rvc_normal, rvc_normal):
-      break;
-
-    default:
-      abort ();
-    }
-
-  if (r == a || r == b)
-    rr = &t;
-  else
-    rr = r;
-  get_zero (rr, 0);
-
-  u.class = rvc_normal;
-  u.sign = 0;
-
-  /* Collect all the partial products.  Since we don't have sure access
-     to a widening multiply, we split each long into two half-words.
-
-     Consider the long-hand form of a four half-word multiplication:
-
-		 A  B  C  D
-	      *  E  F  G  H
-	     --------------
-                DE DF DG DH
-	     CE CF CG CH
-	  BE BF BG BH
-       AE AF AG AH
-
-     We construct partial products of the widened half-word products
-     that are known to not overlap, e.g. DF+DH.  Each such partial
-     product is given its proper exponent, which allows us to sum them
-     and obtain the finished product.  */
-
-  for (i = 0; i < SIGSZ * 2; ++i)
-    {
-      unsigned long ai = a->sig[i / 2];
-      if (i & 1)
-	ai >>= HOST_BITS_PER_LONG / 2;
-      else
-	ai &= ((unsigned long)1 << (HOST_BITS_PER_LONG / 2)) - 1;
-
-      if (ai == 0)
-	continue;
-
-      for (j = 0; j < 2; ++j)
-	{
-	  int exp = (a->exp - (2*SIGSZ-1-i)*(HOST_BITS_PER_LONG/2)
-		     + (b->exp - (1-j)*(HOST_BITS_PER_LONG/2)));
-
-	  if (exp > MAX_EXP)
-	    goto overflow;
-	  if (exp < -MAX_EXP)
-	    /* Would underflow to zero, which we shouldn't bother adding.  */
-	    continue;
-
-	  u.exp = exp;
-
-	  for (k = j; k < SIGSZ * 2; k += 2)
-	    {
-	      unsigned long bi = b->sig[k / 2];
-	      if (k & 1)
-		bi >>= HOST_BITS_PER_LONG / 2;
-	      else
-		bi &= ((unsigned long)1 << (HOST_BITS_PER_LONG / 2)) - 1;
-
-	      u.sig[k / 2] = ai * bi;
-	    }
-
-	  do_add (rr, rr, &u, 0);
-	}
-    }
-
-  rr->sign = sign;
-  if (rr != r)
-    *r = t;
-}
-
 /* Return R = A / B.  */
 
 static void
@@ -1300,55 +1112,6 @@ exact_real_inverse (mode, r)
   return true;
 }
 
-/* Render R as an integer.  */
-
-HOST_WIDE_INT
-real_to_integer (r)
-     const REAL_VALUE_TYPE *r;
-{
-  unsigned HOST_WIDE_INT i;
-
-  switch (r->class)
-    {
-    case rvc_zero:
-    underflow:
-      return 0;
-
-    case rvc_inf:
-    case rvc_nan:
-    overflow:
-      i = (unsigned HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT - 1);
-      if (!r->sign)
-	i--;
-      return i;
-
-    case rvc_normal:
-      if (r->exp <= 0)
-	goto underflow;
-      if (r->exp > HOST_BITS_PER_WIDE_INT)
-	goto overflow;
-
-      if (HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG)
-	i = r->sig[SIGSZ-1];
-      else if (HOST_BITS_PER_WIDE_INT == 2*HOST_BITS_PER_LONG)
-	{
-	  i = r->sig[SIGSZ-1];
-	  i = i << (HOST_BITS_PER_LONG - 1) << 1;
-	  i |= r->sig[SIGSZ-2];
-	}
-      else
-	abort ();
-
-      i >>= HOST_BITS_PER_WIDE_INT - r->exp;
-
-      if (r->sign)
-	i = -i;
-      return i;
-
-    default:
-      abort ();
-    }
-}
 
 /* Likewise, but to an integer pair, HI+LOW.  */
 
diff -rup orig/egcc-CVS20020920/gcc/real.h egcc-CVS20020920/gcc/real.h
--- orig/egcc-CVS20020920/gcc/real.h	2002-09-20 16:00:23.000000000 -0400
+++ egcc-CVS20020920/gcc/real.h	2002-09-20 20:38:25.550768468 -0400
@@ -287,4 +287,18 @@ extern bool exact_real_inverse	PARAMS ((
 extern tree build_real			PARAMS ((tree, REAL_VALUE_TYPE));
 
 
+/* TEMPORARILY extern */
+extern void normalize PARAMS ((REAL_VALUE_TYPE *));
+extern void get_inf PARAMS ((REAL_VALUE_TYPE *, int));
+extern void lshift_significand PARAMS ((REAL_VALUE_TYPE *,
+					const REAL_VALUE_TYPE *,
+					unsigned int));
+extern void get_zero PARAMS ((REAL_VALUE_TYPE *, int));
+extern void do_multiply PARAMS ((REAL_VALUE_TYPE *,
+				 const REAL_VALUE_TYPE *,
+				 const REAL_VALUE_TYPE *));
+extern void do_add PARAMS ((REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *,
+			    const REAL_VALUE_TYPE *, int));
+extern void get_canonical_qnan PARAMS ((REAL_VALUE_TYPE *, int));
+
 #endif /* ! GCC_REAL_H */
diff -rup orig/egcc-CVS20020920/gcc/real2.c egcc-CVS20020920/gcc/real2.c
--- orig/egcc-CVS20020920/gcc/real2.c	2002-09-20 20:46:30.077874421 -0400
+++ egcc-CVS20020920/gcc/real2.c	2002-09-20 20:43:34.152318410 -0400
@@ -0,0 +1,258 @@
+/* real.c - software floating point emulation.
+   Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998,
+   1999, 2000, 2002 Free Software Foundation, Inc.
+   Contributed by Stephen L. Moshier (moshier@world.std.com).
+   Re-written by Richard Henderson  <rth@redhat.com>
+
+   This file is part of GCC.
+
+   GCC 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.
+
+   GCC 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 GCC; see the file COPYING.  If not, write to the Free
+   Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+   02111-1307, USA.  */
+
+#include "config.h"
+#include "system.h"
+#include "real.h"
+#include "tm_p.h"
+
+/* Used to classify two numbers simultaneously.  */
+#define CLASS2(A, B)  ((A) << 2 | (B))
+
+/* Adjust the exponent and significand of R such that the most
+   significant bit is set.  We underflow to zero and overflow to
+   infinity here, without denormals.  (The intermediate representation
+   exponent is large enough to handle target denormals normalized.)  */
+
+void
+normalize (r)
+     REAL_VALUE_TYPE *r;
+{
+  int shift = 0, exp;
+  int i, j;
+
+  /* Find the first word that is non-zero.  */
+  for (i = SIGSZ - 1; i >= 0; i--)
+    if (r->sig[i] == 0)
+      shift += HOST_BITS_PER_LONG;
+    else
+      break;
+
+  /* Zero significand flushes to zero.  */
+  if (i < 0)
+    {
+      r->class = rvc_zero;
+      r->exp = 0;
+      return;
+    }
+
+  /* Find the first bit that is non-zero.  */
+  for (j = 0; ; j++)
+    if (r->sig[i] & ((unsigned long)1 << (HOST_BITS_PER_LONG - 1 - j)))
+      break;
+  shift += j;
+
+  if (shift > 0)
+    {
+      exp = r->exp - shift;
+      if (exp > MAX_EXP)
+	get_inf (r, r->sign);
+      else if (exp < -MAX_EXP)
+	get_zero (r, r->sign);
+      else
+	{
+	  r->exp = exp;
+	  lshift_significand (r, r, shift);
+	}
+    }
+}
+
+/* Render R as an integer.  */
+
+HOST_WIDE_INT
+real_to_integer (r)
+     const REAL_VALUE_TYPE *r;
+{
+  unsigned HOST_WIDE_INT i;
+
+  switch (r->class)
+    {
+    case rvc_zero:
+    underflow:
+      return 0;
+
+    case rvc_inf:
+    case rvc_nan:
+    overflow:
+      i = (unsigned HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT - 1);
+      if (!r->sign)
+	i--;
+      return i;
+
+    case rvc_normal:
+      if (r->exp <= 0)
+	goto underflow;
+      if (r->exp > HOST_BITS_PER_WIDE_INT)
+	goto overflow;
+
+      if (HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG)
+	i = r->sig[SIGSZ-1];
+      else if (HOST_BITS_PER_WIDE_INT == 2*HOST_BITS_PER_LONG)
+	{
+	  i = r->sig[SIGSZ-1];
+	  i = i << (HOST_BITS_PER_LONG - 1) << 1;
+	  i |= r->sig[SIGSZ-2];
+	}
+      else
+	abort ();
+
+      i >>= HOST_BITS_PER_WIDE_INT - r->exp;
+
+      if (r->sign)
+	i = -i;
+      return i;
+
+    default:
+      abort ();
+    }
+}
+
+/* Return R = A * B.  */
+
+void
+do_multiply (r, a, b)
+     REAL_VALUE_TYPE *r;
+     const REAL_VALUE_TYPE *a, *b;
+{
+  REAL_VALUE_TYPE u, t, *rr;
+  unsigned int i, j, k;
+  int sign = a->sign ^ b->sign;
+
+  switch (CLASS2 (a->class, b->class))
+    {
+    case CLASS2 (rvc_zero, rvc_zero):
+    case CLASS2 (rvc_zero, rvc_normal):
+    case CLASS2 (rvc_normal, rvc_zero):
+      /* +-0 * ANY = 0 with appropriate sign.  */
+      get_zero (r, sign);
+      return;
+
+    case CLASS2 (rvc_zero, rvc_nan):
+    case CLASS2 (rvc_normal, rvc_nan):
+    case CLASS2 (rvc_inf, rvc_nan):
+    case CLASS2 (rvc_nan, rvc_nan):
+      /* ANY * NaN = NaN.  */
+      *r = *b;
+      r->sign = sign;
+      return;
+
+    case CLASS2 (rvc_nan, rvc_zero):
+    case CLASS2 (rvc_nan, rvc_normal):
+    case CLASS2 (rvc_nan, rvc_inf):
+      /* NaN * ANY = NaN.  */
+      *r = *a;
+      r->sign = sign;
+      return;
+
+    case CLASS2 (rvc_zero, rvc_inf):
+    case CLASS2 (rvc_inf, rvc_zero):
+      /* 0 * Inf = NaN */
+      get_canonical_qnan (r, sign);
+      return;
+
+    case CLASS2 (rvc_inf, rvc_inf):
+    case CLASS2 (rvc_normal, rvc_inf):
+    case CLASS2 (rvc_inf, rvc_normal):
+      /* Inf * Inf = Inf, R * Inf = Inf */
+    overflow:
+      get_inf (r, sign);
+      return;
+
+    case CLASS2 (rvc_normal, rvc_normal):
+      break;
+
+    default:
+      abort ();
+    }
+
+  if (r == a || r == b)
+    rr = &t;
+  else
+    rr = r;
+  get_zero (rr, 0);
+
+  u.class = rvc_normal;
+  u.sign = 0;
+
+  /* Collect all the partial products.  Since we don't have sure access
+     to a widening multiply, we split each long into two half-words.
+
+     Consider the long-hand form of a four half-word multiplication:
+
+		 A  B  C  D
+	      *  E  F  G  H
+	     --------------
+                DE DF DG DH
+	     CE CF CG CH
+	  BE BF BG BH
+       AE AF AG AH
+
+     We construct partial products of the widened half-word products
+     that are known to not overlap, e.g. DF+DH.  Each such partial
+     product is given its proper exponent, which allows us to sum them
+     and obtain the finished product.  */
+
+  for (i = 0; i < SIGSZ * 2; ++i)
+    {
+      unsigned long ai = a->sig[i / 2];
+      if (i & 1)
+	ai >>= HOST_BITS_PER_LONG / 2;
+      else
+	ai &= ((unsigned long)1 << (HOST_BITS_PER_LONG / 2)) - 1;
+
+      if (ai == 0)
+	continue;
+
+      for (j = 0; j < 2; ++j)
+	{
+	  int exp = (a->exp - (2*SIGSZ-1-i)*(HOST_BITS_PER_LONG/2)
+		     + (b->exp - (1-j)*(HOST_BITS_PER_LONG/2)));
+
+	  if (exp > MAX_EXP)
+	    goto overflow;
+	  if (exp < -MAX_EXP)
+	    /* Would underflow to zero, which we shouldn't bother adding.  */
+	    continue;
+
+	  u.exp = exp;
+
+	  for (k = j; k < SIGSZ * 2; k += 2)
+	    {
+	      unsigned long bi = b->sig[k / 2];
+	      if (k & 1)
+		bi >>= HOST_BITS_PER_LONG / 2;
+	      else
+		bi &= ((unsigned long)1 << (HOST_BITS_PER_LONG / 2)) - 1;
+
+	      u.sig[k / 2] = ai * bi;
+	    }
+
+	  do_add (rr, rr, &u, 0);
+	}
+    }
+
+  rr->sign = sign;
+  if (rr != r)
+    *r = t;
+}
+


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]