This is the mail archive of the gcc@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: Irix6 long doubles implemented wrong? (27_io/ostream_inserter_arith)


On Dec 26, 2002, Alexandre Oliva <aoliva@redhat.com> wrote:

> I doubt these further tweaks might have actually introduced any
> regressions, so...

Famous last words...  Kaveh sent me in private a list of regressions,
caused by:

> instead of keeping even more excess precision for the emulation
> of IRIX' long double to internally use the same number of bits as IEEE
> 854 128-bit long doubles, which would probably cause rounding problems
> unless I explicitly handled it, I arranged for the emulation library
> to already keep 106 bits of mantissa.

This broke the ``magic'' exponent adjustments in _fpmul_parts(), which
forced me to figure out where the heck those magic constants came
from, so I could clean them up.

> Or even when the exponent is so small that the most-significant
> double is normal but the least-significant one isn't.  In this case,
> I believe we should do some rounding, but I was not sure it actually
> mattered, so I just left it out.

And now I put it in, and fixed the representation and rounding of
denormals in the least-significant double, that was formerly a bit
off.  I used two additional programs to verify that denormals were
correct, and that they were being rounded correctly; for reference,
they're attached after the patch.

This patch fixes all failures that Kaveh pointed out in private, in
all optimization levels.  It's now undergoing a bootstrap&test cycle,
that should be done, well, some day :-)

In case it succeeds, ok for mainline (with Kaveh's patch) and 3.3?

Index: gcc/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	* config/mips/mips.h (LONG_DUBLE_TYPE_SIZE): Set to 128 on N32
	and N64.
	(MAX_FIXED_MODE_SIZE): Define to LONG_DOUBLE_TYPE_SIZE.
	(LIBGCC2_LONG_DOUBLE_TYPE_SIZE): Define.
	(BIGGEST_ALIGNMENT): Same as LONG_DOUBLE_TYPE_SIZE.
	(FUNCTION_VALUE_REGNO_P): Set for FP_RETURN+2 on N32 and N64.
	* config/mips/mips.c (mips_arg_info): Pass TFmode values in
	even FP registers on N32 and N64.
	(mips_va_start): Adjust alignment of ARG_POINTER_REGNUM.
	(mips_va_arg): Impose additional even-register-like alignment
	to 128-bit arguments.
	(override_options): Set TFmode format.  Set it as allowable in
	FP registers.
	(mips_function_value): Return TFmode in $f0 and $f2 on N32 or
	N64.
	* config/mips/_tilib.c (__negti2, __ashlti3, __lshrti3): New.
	* config/mips/t-iris6 (LIB2FUNCS_EXTRA): Add _tilib.c.
	(TPBIT): Set to tp-bit.c.
	(tp-bit.c): Create out of fp-bit.c.
	* Makefile.in (FPBIT_FUNCS): Added _sf_to_tf.
	(DBBIT_FUNCS): Added _df_to_tf.
	(TPBIT_FUNCS): New.
	(libgcc.mk): Pass TPBIT and TPBIT_FUNCS down.
	(LIBGCC_DEPS): Added TPBIT.
	* mklibgcc.in: Support TPBIT and TPBIT_FUNCS.
	* fp-bit.h: Define macros for TFmode floating-point constants
	in IEEE and IBM-extended TFmode types.  Declare functions
	according to L_ macros.
	(TMODES): Define if __LDBL_MANT_DIG__ has one of
	the newly-supported widths.
	(TFtype, TItype, UTItype): Define if TMODES is defined.
	(MAX_UDI_INT, MAX_DI_INT, BITS_PER_DI): Likewise.
	(F_T_BITOFF, D_T_BITOFF): Define.
	(IMPLICIT_1, IMPLICIT_2): Cast constants to types that are
	guaranteed to be wide enough.
	* config/fp-bit.c: Check for L_ macros for tf functions.
	(__thenan_tf): New.
	(nan): Adjust.
	(pack_d, unpack_d): Support IEEE 854 and IBM-extended TFmode
	types.
	(_fpmul_parts): Support TFmode.  Compute exponent adjustment
	from FRAC_NBITS, FRAC_BITS and NGARDS.
	(usi_to_float): Cast constants to be shifted to fractype
	instead of assuming long long is wide enough.
	(sf_to_tf, df_to_tf, __make_tp, tf_to_df, tf_to_sf): New.
	* print-rtl.c (print_rtx): Don't print MEM details in
	GENERATOR_FILEs.
	* rtl.c (get_mode_alignment): Moved to...
	* stor-layout.c: ... here.
	* calls.c (emit_library_call_value_1): Handle return values
	in a PARALLEL.
	* expr.c (emit_group_store): Initialize dst with CONST0_RTX
	for the appropriate mode.
	* optabs.c (expand_binop) <add, sub>: Return xtarget if we haven't
	been able to move the result to target.
	* real.h (struct real_format): Add denorm_p, remove has_denorm.
	* real.c: Adjust all formats and references to has_denorm.
	* c-common.c (builtin_define_float_constants): Use denorm_p to
	define DENORM_MIN.

Index: gcc/Makefile.in
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Makefile.in,v
retrieving revision 1.958
diff -u -p -r1.958 Makefile.in
--- gcc/Makefile.in 24 Nov 2002 20:43:01 -0000 1.958
+++ gcc/Makefile.in 27 Dec 2002 13:11:06 -0000
@@ -796,12 +796,17 @@ LIB2FUNCS_ST = _eprintf _bb __gcc_bcmp
 FPBIT_FUNCS = _pack_sf _unpack_sf _addsub_sf _mul_sf _div_sf \
     _fpcmp_parts_sf _compare_sf _eq_sf _ne_sf _gt_sf _ge_sf \
     _lt_sf _le_sf _unord_sf _si_to_sf _sf_to_si _negate_sf _make_sf \
-    _sf_to_df _thenan_sf _sf_to_usi _usi_to_sf
+    _sf_to_df _sf_to_tf _thenan_sf _sf_to_usi _usi_to_sf
 
 DPBIT_FUNCS = _pack_df _unpack_df _addsub_df _mul_df _div_df \
     _fpcmp_parts_df _compare_df _eq_df _ne_df _gt_df _ge_df \
     _lt_df _le_df _unord_df _si_to_df _df_to_si _negate_df _make_df \
-    _df_to_sf _thenan_df _df_to_usi _usi_to_df
+    _df_to_sf _df_to_tf _thenan_df _df_to_usi _usi_to_df
+
+TPBIT_FUNCS = _pack_tf _unpack_tf _addsub_tf _mul_tf _div_tf \
+    _fpcmp_parts_tf _compare_tf _eq_tf _ne_tf _gt_tf _ge_tf \
+    _lt_tf _le_tf _unord_tf _si_to_tf _tf_to_si _negate_tf _make_tf \
+    _tf_to_df _tf_to_sf _thenan_tf _tf_to_usi _usi_to_tf
 
 # These might cause a divide overflow trap and so are compiled with
 # unwinder info.
@@ -1021,6 +1026,8 @@ libgcc.mk: config.status Makefile mklibg
 	LIB2_DIVMOD_FUNCS='$(LIB2_DIVMOD_FUNCS)' \
 	DPBIT='$(DPBIT)' \
 	DPBIT_FUNCS='$(DPBIT_FUNCS)' \
+	TPBIT='$(TPBIT)' \
+	TPBIT_FUNCS='$(TPBIT_FUNCS)' \
 	MULTILIBS=`$(GCC_FOR_TARGET) --print-multi-lib` \
 	EXTRA_MULTILIB_PARTS='$(EXTRA_MULTILIB_PARTS)' \
 	SHLIB_LINK='$(SHLIB_LINK)' \
@@ -1040,8 +1047,9 @@ libgcc.mk: config.status Makefile mklibg
 LIBGCC_DEPS = $(GCC_PASSES) $(LANGUAGES) stmp-int-hdrs $(STMP_FIXPROTO) \
 	libgcc.mk $(srcdir)/libgcc2.c $(TCONFIG_H) \
 	$(MACHMODE_H) longlong.h gbl-ctors.h config.status stmp-int-hdrs \
-	tsystem.h $(FPBIT) $(DPBIT) $(LIB2ADD) $(LIB2ADD_ST) $(LIB2ADDEH) \
-	$(LIB2ADDEHDEP) $(EXTRA_PARTS) $(srcdir)/config/$(LIB1ASMSRC)
+	tsystem.h $(FPBIT) $(DPBIT) $(TPBIT) $(LIB2ADD) \
+	$(LIB2ADD_ST) $(LIB2ADDEH) $(LIB2ADDEHDEP) $(EXTRA_PARTS) \
+	$(srcdir)/config/$(LIB1ASMSRC)
 
 libgcc.a: $(LIBGCC_DEPS)
 	$(MAKE) GCC_FOR_TARGET="$(GCC_FOR_TARGET)" \
Index: gcc/c-common.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-common.c,v
retrieving revision 1.393
diff -u -p -r1.393 c-common.c
--- gcc/c-common.c 11 Dec 2002 06:36:04 -0000 1.393
+++ gcc/c-common.c 27 Dec 2002 13:11:10 -0000
@@ -4866,9 +4866,9 @@ builtin_define_float_constants (name_pre
      positive floating-point number, b**(emin-p).  Zero for formats that
      don't support denormals.  */
   sprintf (name, "__%s_DENORM_MIN__", name_prefix);
-  if (fmt->has_denorm)
+  if (fmt->denorm_p)
     {
-      sprintf (buf, "0x1p%d", (fmt->emin - fmt->p) * fmt->log2_b);
+      sprintf (buf, "0x1p%d", (fmt->emin - fmt->denorm_p) * fmt->log2_b);
       builtin_define_with_hex_fp_value (name, type, decimal_dig,
 					buf, fp_suffix);
     }
Index: gcc/calls.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/calls.c,v
retrieving revision 1.244
diff -u -p -r1.244 calls.c
--- gcc/calls.c 9 Dec 2002 17:54:03 -0000 1.244
+++ gcc/calls.c 27 Dec 2002 13:11:13 -0000
@@ -4131,7 +4131,7 @@ emit_library_call_value_1 (retval, orgfu
     {
       rtx insns;
 
-      if (valreg == 0 || GET_CODE (valreg) == PARALLEL)
+      if (valreg == 0)
 	{
 	  insns = get_insns ();
 	  end_sequence ();
@@ -4140,9 +4140,18 @@ emit_library_call_value_1 (retval, orgfu
       else
 	{
 	  rtx note = 0;
-	  rtx temp = gen_reg_rtx (GET_MODE (valreg));
+	  rtx temp;
 	  int i;
 
+	  if (GET_CODE (valreg) == PARALLEL)
+	    {
+	      temp = gen_reg_rtx (outmode);
+	      emit_group_store (temp, valreg, outmode);
+	      valreg = temp;
+	    }
+
+	  temp = gen_reg_rtx (GET_MODE (valreg));
+
 	  /* Construct an "equal form" for the value which mentions all the
 	     arguments in order as well as the function name.  */
 	  for (i = 0; i < nargs; i++)
@@ -4175,6 +4184,12 @@ emit_library_call_value_1 (retval, orgfu
 	    value = mem_value;
 	  if (value != mem_value)
 	    emit_move_insn (value, mem_value);
+	}
+      else if (GET_CODE (valreg) == PARALLEL)
+	{
+	  if (value == 0)
+	    value = gen_reg_rtx (outmode);
+	  emit_group_store (value, valreg, outmode);
 	}
       else if (value != 0)
 	emit_move_insn (value, valreg);
Index: gcc/expr.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/expr.c,v
retrieving revision 1.498.2.1
diff -u -p -r1.498.2.1 expr.c
--- gcc/expr.c 23 Dec 2002 16:47:20 -0000 1.498.2.1
+++ gcc/expr.c 27 Dec 2002 13:11:20 -0000
@@ -2436,7 +2436,7 @@ emit_group_store (orig_dst, src, ssize)
     {
       dst = gen_reg_rtx (GET_MODE (orig_dst));
       /* Make life a bit easier for combine.  */
-      emit_move_insn (dst, const0_rtx);
+      emit_move_insn (dst, CONST0_RTX (GET_MODE (orig_dst)));
     }
 
   /* Process the pieces.  */
Index: gcc/mklibgcc.in
===================================================================
RCS file: /cvs/gcc/gcc/gcc/mklibgcc.in,v
retrieving revision 1.48
diff -u -p -r1.48 mklibgcc.in
--- gcc/mklibgcc.in 3 Oct 2002 20:35:13 -0000 1.48
+++ gcc/mklibgcc.in 27 Dec 2002 13:11:20 -0000
@@ -21,6 +21,8 @@
 # LIB2_DIVMOD_FUNCS
 # DPBIT
 # DPBIT_FUNCS
+# TPBIT
+# TPBIT_FUNCS
 # LIBGCC
 # MULTILIBS
 # EXTRA_MULTILIB_PARTS
@@ -169,6 +171,21 @@ if [ "$DPBIT" ]; then
       echo $out: $DPBIT $fpbit_c_dep
       echo "	$gcc_compile" -DFINE_GRAINED_LIBRARIES $flags -DL$name \
 	-c $DPBIT -o $out
+    done
+    libgcc2_objs="$libgcc2_objs ${name}${objext}"
+  done
+fi
+
+if [ "$TPBIT" ]; then
+  for name in $TPBIT_FUNCS; do
+    for ml in $MULTILIBS; do
+      dir=`echo ${ml} | sed -e 's/;.*$//' -e 's/=/$(EQ)/g'`
+      flags=`echo ${ml} | sed -e 's/^[^;]*;//' -e 's/@/ -/g'`;
+      out="libgcc/${dir}/${name}${objext}"
+
+      echo $out: $TPBIT $fpbit_c_dep
+      echo "	$gcc_compile" -DFINE_GRAINED_LIBRARIES $flags -DL$name \
+	-c $TPBIT -o $out
     done
     libgcc2_objs="$libgcc2_objs ${name}${objext}"
   done
Index: gcc/optabs.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/optabs.c,v
retrieving revision 1.153
diff -u -p -r1.153 optabs.c
--- gcc/optabs.c 20 Nov 2002 21:52:59 -0000 1.153
+++ gcc/optabs.c 27 Dec 2002 13:11:22 -0000
@@ -1306,6 +1306,8 @@ expand_binop (mode, binoptab, op0, op1, 
 						   copy_rtx (xop0),
 						   copy_rtx (xop1)));
 	    }
+	  else
+	    target = xtarget;
 
 	  return target;
 	}
Index: gcc/print-rtl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/print-rtl.c,v
retrieving revision 1.91
diff -u -p -r1.91 print-rtl.c
--- gcc/print-rtl.c 16 Oct 2002 00:40:27 -0000 1.91
+++ gcc/print-rtl.c 27 Dec 2002 13:11:23 -0000
@@ -1,5 +1,5 @@
 /* Print RTL for GNU C Compiler.
-   Copyright (C) 1987, 1988, 1992, 1997, 1998, 1999, 2000
+   Copyright (C) 1987, 1988, 1992, 1997, 1998, 1999, 2000, 2002
    Free Software Foundation, Inc.
 
 This file is part of GCC.
@@ -491,6 +491,7 @@ print_rtx (in_rtx)
 
   switch (GET_CODE (in_rtx))
     {
+#ifndef GENERATOR_FILE
     case MEM:
       fputs (" [", outfile);
       fprintf (outfile, HOST_WIDE_INT_PRINT_DEC, MEM_ALIAS_SET (in_rtx));
@@ -518,7 +519,6 @@ print_rtx (in_rtx)
       fputc (']', outfile);
       break;
 
-#ifndef GENERATOR_FILE
     case CONST_DOUBLE:
       if (FLOAT_MODE_P (GET_MODE (in_rtx)))
 	{
Index: gcc/real.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/real.c,v
retrieving revision 1.105
diff -u -p -r1.105 real.c
--- gcc/real.c 17 Nov 2002 20:20:39 -0000 1.105
+++ gcc/real.c 27 Dec 2002 13:11:24 -0000
@@ -2353,7 +2353,7 @@ round_for_format (fmt, r)
     {
       int diff;
 
-      if (!fmt->has_denorm)
+      if (!fmt->denorm_p)
 	{
 	  /* Don't underflow completely until we've had a chance to round.  */
 	  if (r->exp < emin2m1)
@@ -2676,7 +2676,7 @@ decode_ieee_single (fmt, r, buf)
 
   if (exp == 0)
     {
-      if (image && fmt->has_denorm)
+      if (image && fmt->denorm_p)
 	{
 	  r->class = rvc_normal;
 	  r->sign = sign;
@@ -2719,12 +2719,12 @@ const struct real_format ieee_single_for
     2,
     1,
     24,
+    24,
     -125,
     128,
     true,
     true,
     true,
-    true,
     true
   };
 
@@ -2845,7 +2845,7 @@ decode_ieee_double (fmt, r, buf)
 
   if (exp == 0)
     {
-      if ((image_hi || image_lo) && fmt->has_denorm)
+      if ((image_hi || image_lo) && fmt->denorm_p)
 	{
 	  r->class = rvc_normal;
 	  r->sign = sign;
@@ -2912,12 +2912,12 @@ const struct real_format ieee_double_for
     2,
     1,
     53,
+    53,
     -1021,
     1024,
     true,
     true,
     true,
-    true,
     true
   };
 
@@ -3084,7 +3084,7 @@ decode_ieee_extended (fmt, r, buf)
 
   if (exp == 0)
     {
-      if ((sig_hi || sig_lo) && fmt->has_denorm)
+      if ((sig_hi || sig_lo) && fmt->denorm_p)
 	{
 	  r->class = rvc_normal;
 	  r->sign = sign;
@@ -3167,12 +3167,12 @@ const struct real_format ieee_extended_m
     2,
     1,
     64,
+    64,
     -16382,
     16384,
     true,
     true,
     true,
-    true,
     true
   };
 
@@ -3183,12 +3183,12 @@ const struct real_format ieee_extended_i
     2,
     1,
     64,
+    64,
     -16381,
     16384,
     true,
     true,
     true,
-    true,
     true
   };
 
@@ -3199,12 +3199,12 @@ const struct real_format ieee_extended_i
     2,
     1,
     64,
+    64,
     -16381,
     16384,
     true,
     true,
     true,
-    true,
     true
   };
 
@@ -3292,12 +3292,12 @@ const struct real_format ibm_extended_fo
     2,
     1,
     53 + 53,
+    53,
     -1021,
     1024,
     true,
     true,
     true,
-    true,
     true
   };
 
@@ -3461,7 +3461,7 @@ decode_ieee_quad (fmt, r, buf)
 
   if (exp == 0)
     {
-      if ((image3 | image2 | image1 | image0) && fmt->has_denorm)
+      if ((image3 | image2 | image1 | image0) && fmt->denorm_p)
 	{
 	  r->class = rvc_normal;
 	  r->sign = sign;
@@ -3545,12 +3545,12 @@ const struct real_format ieee_quad_forma
     2,
     1,
     113,
+    113,
     -16381,
     16384,
     true,
     true,
     true,
-    true,
     true
   };
 
@@ -3852,12 +3852,12 @@ const struct real_format vax_f_format = 
     2,
     1,
     24,
+    0,
     -127,
     127,
     false,
     false,
     false,
-    false,
     false
   };
 
@@ -3868,12 +3868,12 @@ const struct real_format vax_d_format = 
     2,
     1,
     56,
+    0,
     -127,
     127,
     false,
     false,
     false,
-    false,
     false
   };
 
@@ -3884,12 +3884,12 @@ const struct real_format vax_g_format = 
     2,
     1,
     53,
+    0,
     -1023,
     1023,
     false,
     false,
     false,
-    false,
     false
   };
 
@@ -4065,12 +4065,12 @@ const struct real_format i370_single_for
     16,
     4,
     6,
+    0, /* ??? The encoding does allow for "unnormals".  */
     -64,
     63,
     false,
     false,
     false, /* ??? The encoding does allow for "unnormals".  */
-    false, /* ??? The encoding does allow for "unnormals".  */
     false
   };
 
@@ -4081,12 +4081,12 @@ const struct real_format i370_double_for
     16,
     4,
     14,
+    0, /* ??? The encoding does allow for "unnormals".  */
     -64,
     63,
     false,
     false,
     false, /* ??? The encoding does allow for "unnormals".  */
-    false, /* ??? The encoding does allow for "unnormals".  */
     false
   };
 
@@ -4295,12 +4295,12 @@ const struct real_format c4x_single_form
     2,
     1,
     24,
+    0,
     -126,
     128,
     false,
     false,
     false,
-    false,
     false
   };
 
@@ -4311,12 +4311,12 @@ const struct real_format c4x_extended_fo
     2,
     1,
     32,
+    0,
     -126,
     128,
     false,
     false,
     false,
-    false,
     false
   };
 
@@ -4356,11 +4356,11 @@ const struct real_format real_internal_f
     2,
     1,
     SIGNIFICAND_BITS - 2,
+    0,
     -MAX_EXP,
     MAX_EXP,
     true,
     true,
-    false,
     true,
     true 
   };
Index: gcc/real.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/real.h,v
retrieving revision 1.59
diff -u -p -r1.59 real.h
--- gcc/real.h 22 Oct 2002 00:17:15 -0000 1.59
+++ gcc/real.h 27 Dec 2002 13:11:25 -0000
@@ -118,6 +118,11 @@ struct real_format
   /* Size of the significand in digits of radix B.  */
   int p;
 
+  /* One plus the size of the significand of a denormalized number, in
+     digits of radix B.  If zero, implies denormalized numbers are not
+     available.  */
+  int denorm_p;
+
   /* The minimum negative integer, x, such that b**(x-1) is normalized.  */
   int emin;
 
@@ -127,7 +132,6 @@ struct real_format
   /* Properties of the format.  */
   bool has_nans;
   bool has_inf;
-  bool has_denorm;
   bool has_signed_zero;
   bool qnan_msb_set;
 };
Index: gcc/rtl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/rtl.c,v
retrieving revision 1.120
diff -u -p -r1.120 rtl.c
--- gcc/rtl.c 14 Oct 2002 02:36:25 -0000 1.120
+++ gcc/rtl.c 27 Dec 2002 13:11:25 -0000
@@ -396,29 +396,6 @@ shallow_copy_rtx (orig)
 
   return copy;
 }
-
-/* Return the alignment of MODE. This will be bounded by 1 and
-   BIGGEST_ALIGNMENT.  */
-
-unsigned int
-get_mode_alignment (mode)
-     enum machine_mode mode;
-{
-  unsigned int alignment;
-
-  if (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT
-      || GET_MODE_CLASS (mode) == MODE_COMPLEX_INT)
-    alignment = GET_MODE_UNIT_SIZE (mode);
-  else
-    alignment = GET_MODE_SIZE (mode);
-
-  /* Extract the LSB of the size.  */
-  alignment = alignment & -alignment;
-  alignment *= BITS_PER_UNIT;
-
-  alignment = MIN (BIGGEST_ALIGNMENT, MAX (1, alignment));
-  return alignment;
-}
 
 /* This is 1 until after the rtl generation pass.  */
 int rtx_equal_function_value_matters;
Index: gcc/stor-layout.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/stor-layout.c,v
retrieving revision 1.134
diff -u -p -r1.134 stor-layout.c
--- gcc/stor-layout.c 20 Nov 2002 10:09:00 -0000 1.134
+++ gcc/stor-layout.c 27 Dec 2002 13:11:26 -0000
@@ -298,6 +298,29 @@ int_mode_for_mode (mode)
   return mode;
 }
 
+/* Return the alignment of MODE. This will be bounded by 1 and
+   BIGGEST_ALIGNMENT.  */
+
+unsigned int
+get_mode_alignment (mode)
+     enum machine_mode mode;
+{
+  unsigned int alignment;
+
+  if (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT
+      || GET_MODE_CLASS (mode) == MODE_COMPLEX_INT)
+    alignment = GET_MODE_UNIT_SIZE (mode);
+  else
+    alignment = GET_MODE_SIZE (mode);
+
+  /* Extract the LSB of the size.  */
+  alignment = alignment & -alignment;
+  alignment *= BITS_PER_UNIT;
+
+  alignment = MIN (BIGGEST_ALIGNMENT, MAX (1, alignment));
+  return alignment;
+}
+
 /* Return the value of VALUE, rounded up to a multiple of DIVISOR.
    This can only be applied to objects of a sizetype.  */
 
Index: gcc/config/fp-bit.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/fp-bit.c,v
retrieving revision 1.36
diff -u -p -r1.36 fp-bit.c
--- gcc/config/fp-bit.c 7 Oct 2002 08:47:09 -0000 1.36
+++ gcc/config/fp-bit.c 27 Dec 2002 13:11:28 -0000
@@ -130,6 +130,10 @@ void __lttf2 (void) { abort(); }
 const fp_number_type __thenan_sf = { CLASS_SNAN, 0, 0, {(fractype) 0} };
 #elif defined L_thenan_df
 const fp_number_type __thenan_df = { CLASS_SNAN, 0, 0, {(fractype) 0} };
+#elif defined L_thenan_tf
+const fp_number_type __thenan_tf = { CLASS_SNAN, 0, 0, {(fractype) 0} };
+#elif defined TFLOAT
+extern const fp_number_type __thenan_tf;
 #elif defined FLOAT
 extern const fp_number_type __thenan_sf;
 #else
@@ -141,7 +145,9 @@ static fp_number_type *
 nan (void)
 {
   /* Discard the const qualifier...  */
-#ifdef FLOAT  
+#ifdef TFLOAT
+  return (fp_number_type *) (& __thenan_tf);
+#elif defined FLOAT  
   return (fp_number_type *) (& __thenan_sf);
 #else
   return (fp_number_type *) (& __thenan_df);
@@ -180,7 +186,7 @@ flip_sign ( fp_number_type *  x)
 
 extern FLO_type pack_d ( fp_number_type * );
 
-#if defined(L_pack_df) || defined(L_pack_sf)
+#if defined(L_pack_df) || defined(L_pack_sf) || defined(L_pack_tf)
 FLO_type
 pack_d ( fp_number_type *  src)
 {
@@ -316,24 +322,92 @@ pack_d ( fp_number_type *  src)
   dst.bits.exp = exp;
   dst.bits.sign = sign;
 #else
+# if defined TFLOAT && defined HALFFRACBITS
+ {
+   halffractype high, low;
+
+   high = (fraction >> (FRACBITS - HALFFRACBITS));
+   high &= (((fractype)1) << HALFFRACBITS) - 1;
+   high |= ((fractype) (exp & ((1 << EXPBITS) - 1))) << HALFFRACBITS;
+   high |= ((fractype) (sign & 1)) << (HALFFRACBITS | EXPBITS);
+
+   low = (halffractype)fraction &
+     ((((halffractype)1) << (FRACBITS - HALFFRACBITS)) - 1);
+
+   if (exp == EXPMAX || exp == 0 || low == 0)
+     low = 0;
+   else
+     {
+       exp -= HALFFRACBITS + 1;
+
+       while (exp > 0
+	      && low < ((halffractype)1 << HALFFRACBITS))
+	 {
+	   low <<= 1;
+	   exp--;
+	 }
+
+       if (exp <= 0)
+	 {
+	   halffractype roundmsb, round;
+
+	   exp = -exp + 1;
+
+	   roundmsb = (1 << (exp - 1));
+	   round = low & ((roundmsb << 1) - 1);
+
+	   low >>= exp;
+	   exp = 0;
+
+	   if (round > roundmsb || (round == roundmsb && (low & 1)))
+	     {
+	       low++;
+	       if (low >= ((halffractype)1 << HALFFRACBITS))
+		 /* We don't shift left, since it has just become the
+		    smallest normal number, whose implicit 1 bit is
+		    now indicated by the non-zero exponent.  */
+		 exp++;
+	     }
+	 }
+
+       low &= ((halffractype)1 << HALFFRACBITS) - 1;
+       low |= ((fractype) (exp & ((1 << EXPBITS) - 1))) << HALFFRACBITS;
+       low |= ((fractype) (sign & 1)) << (HALFFRACBITS | EXPBITS);
+     }
+
+   dst.value_raw = (((fractype) high) << HALFSHIFT) | low;
+ }
+# else
   dst.value_raw = fraction & ((((fractype)1) << FRACBITS) - (fractype)1);
   dst.value_raw |= ((fractype) (exp & ((1 << EXPBITS) - 1))) << FRACBITS;
   dst.value_raw |= ((fractype) (sign & 1)) << (FRACBITS | EXPBITS);
+# endif
 #endif
 
 #if defined(FLOAT_WORD_ORDER_MISMATCH) && !defined(FLOAT)
+#ifdef TFLOAT
+  {
+    qrtrfractype tmp1 = dst.words[0];
+    qrtrfractype tmp2 = dst.words[1];
+    dst.words[0] = dst.words[3];
+    dst.words[1] = dst.words[2];
+    dst.words[2] = tmp2;
+    dst.words[3] = tmp1;
+  }
+#else
   {
     halffractype tmp = dst.words[0];
     dst.words[0] = dst.words[1];
     dst.words[1] = tmp;
   }
 #endif
+#endif
 
   return dst.value;
 }
 #endif
 
-#if defined(L_unpack_df) || defined(L_unpack_sf)
+#if defined(L_unpack_df) || defined(L_unpack_sf) || defined(L_unpack_tf)
 void
 unpack_d (FLO_union_type * src, fp_number_type * dst)
 {
@@ -347,8 +421,15 @@ unpack_d (FLO_union_type * src, fp_numbe
 #if defined(FLOAT_WORD_ORDER_MISMATCH) && !defined(FLOAT)
   FLO_union_type swapped;
 
+#ifdef TFLOAT
+  swapped.words[0] = src->words[3];
+  swapped.words[1] = src->words[2];
+  swapped.words[2] = src->words[1];
+  swapped.words[3] = src->words[0];
+#else
   swapped.words[0] = src->words[1];
   swapped.words[1] = src->words[0];
+#endif
   src = &swapped;
 #endif
   
@@ -357,9 +438,42 @@ unpack_d (FLO_union_type * src, fp_numbe
   exp = src->bits.exp;
   sign = src->bits.sign;
 #else
-  fraction = src->value_raw & ((((fractype)1) << FRACBITS) - (fractype)1);
+# if defined TFLOAT && defined HALFFRACBITS
+ {
+   halffractype high, low;
+   
+   high = src->value_raw >> HALFSHIFT;
+   low = src->value_raw & (((fractype)1 << HALFSHIFT) - 1);
+
+   fraction = high & ((((fractype)1) << HALFFRACBITS) - 1);
+   fraction <<= FRACBITS - HALFFRACBITS;
+   exp = ((int)(high >> HALFFRACBITS)) & ((1 << EXPBITS) - 1);
+   sign = ((int)(high >> (((HALFFRACBITS + EXPBITS))))) & 1;
+
+   if (exp != EXPMAX && exp != 0 && low != 0)
+     {
+       int lowexp = ((int)(low >> HALFFRACBITS)) & ((1 << EXPBITS) - 1);
+       int shift;
+       fractype xlow;
+
+       xlow = low & ((((fractype)1) << HALFFRACBITS) - 1);
+       if (lowexp)
+	 xlow |= (((halffractype)1) << HALFFRACBITS);
+       else
+	 lowexp = 1;
+       shift = (FRACBITS - HALFFRACBITS) - (exp - lowexp);
+       if (shift > 0)
+	 xlow <<= shift;
+       else if (shift < 0)
+	 xlow >>= -shift;
+       fraction += xlow;
+     }
+ }
+# else
+  fraction = src->value_raw & ((((fractype)1) << FRACBITS) - 1);
   exp = ((int)(src->value_raw >> FRACBITS)) & ((1 << EXPBITS) - 1);
   sign = ((int)(src->value_raw >> (FRACBITS + EXPBITS))) & 1;
+# endif
 #endif
 
   dst->sign = sign;
@@ -427,7 +541,7 @@ unpack_d (FLO_union_type * src, fp_numbe
 }
 #endif /* L_unpack_df || L_unpack_sf */
 
-#if defined(L_addsub_sf) || defined(L_addsub_df)
+#if defined(L_addsub_sf) || defined(L_addsub_df) || defined(L_addsub_tf)
 static fp_number_type *
 _fpadd_parts (fp_number_type * a,
 	      fp_number_type * b,
@@ -611,7 +725,7 @@ sub (FLO_type arg_a, FLO_type arg_b)
 }
 #endif /* L_addsub_sf || L_addsub_df */
 
-#if defined(L_mul_sf) || defined(L_mul_df)
+#if defined(L_mul_sf) || defined(L_mul_df) || defined(L_mul_tf)
 static inline __attribute__ ((__always_inline__)) fp_number_type *
 _fpmul_parts ( fp_number_type *  a,
 	       fp_number_type *  b,
@@ -660,7 +774,7 @@ _fpmul_parts ( fp_number_type *  a,
   /* Calculate the mantissa by multiplying both numbers to get a
      twice-as-wide number.  */
   {
-#if defined(NO_DI_MODE)
+#if defined(NO_DI_MODE) || defined(TFLOAT)
     {
       fractype x = a->fraction.ll;
       fractype ylow = b->fraction.ll;
@@ -723,13 +837,9 @@ _fpmul_parts ( fp_number_type *  a,
 #endif
   }
 
-  tmp->normal_exp = a->normal_exp + b->normal_exp;
+  tmp->normal_exp = a->normal_exp + b->normal_exp
+    + FRAC_NBITS - (FRACBITS + NGARDS);
   tmp->sign = a->sign != b->sign;
-#ifdef FLOAT
-  tmp->normal_exp += 2;		/* ??????????????? */
-#else
-  tmp->normal_exp += 4;		/* ??????????????? */
-#endif
   while (high >= IMPLICIT_2)
     {
       tmp->normal_exp++;
@@ -803,7 +913,7 @@ multiply (FLO_type arg_a, FLO_type arg_b
 }
 #endif /* L_mul_sf || L_mul_df */
 
-#if defined(L_div_sf) || defined(L_div_df)
+#if defined(L_div_sf) || defined(L_div_df) || defined(L_div_tf)
 static inline __attribute__ ((__always_inline__)) fp_number_type *
 _fpdiv_parts (fp_number_type * a,
 	      fp_number_type * b)
@@ -913,7 +1023,8 @@ divide (FLO_type arg_a, FLO_type arg_b)
 }
 #endif /* L_div_sf || L_div_df */
 
-#if defined(L_fpcmp_parts_sf) || defined(L_fpcmp_parts_df)
+#if defined(L_fpcmp_parts_sf) || defined(L_fpcmp_parts_df) \
+    || defined(L_fpcmp_parts_tf)
 /* according to the demo, fpcmp returns a comparison with 0... thus
    a<b -> -1
    a==b -> 0
@@ -998,7 +1109,7 @@ __fpcmp_parts (fp_number_type * a, fp_nu
 }
 #endif
 
-#if defined(L_compare_sf) || defined(L_compare_df)
+#if defined(L_compare_sf) || defined(L_compare_df) || defined(L_compoare_tf)
 CMPtype
 compare (FLO_type arg_a, FLO_type arg_b)
 {
@@ -1020,7 +1131,7 @@ compare (FLO_type arg_a, FLO_type arg_b)
 
 /* These should be optimized for their specific tasks someday.  */
 
-#if defined(L_eq_sf) || defined(L_eq_df)
+#if defined(L_eq_sf) || defined(L_eq_df) || defined(L_eq_tf)
 CMPtype
 _eq_f2 (FLO_type arg_a, FLO_type arg_b)
 {
@@ -1041,7 +1152,7 @@ _eq_f2 (FLO_type arg_a, FLO_type arg_b)
 }
 #endif /* L_eq_sf || L_eq_df */
 
-#if defined(L_ne_sf) || defined(L_ne_df)
+#if defined(L_ne_sf) || defined(L_ne_df) || defined(L_ne_tf)
 CMPtype
 _ne_f2 (FLO_type arg_a, FLO_type arg_b)
 {
@@ -1062,7 +1173,7 @@ _ne_f2 (FLO_type arg_a, FLO_type arg_b)
 }
 #endif /* L_ne_sf || L_ne_df */
 
-#if defined(L_gt_sf) || defined(L_gt_df)
+#if defined(L_gt_sf) || defined(L_gt_df) || defined(L_gt_tf)
 CMPtype
 _gt_f2 (FLO_type arg_a, FLO_type arg_b)
 {
@@ -1083,7 +1194,7 @@ _gt_f2 (FLO_type arg_a, FLO_type arg_b)
 }
 #endif /* L_gt_sf || L_gt_df */
 
-#if defined(L_ge_sf) || defined(L_ge_df)
+#if defined(L_ge_sf) || defined(L_ge_df) || defined(L_ge_tf)
 CMPtype
 _ge_f2 (FLO_type arg_a, FLO_type arg_b)
 {
@@ -1103,7 +1214,7 @@ _ge_f2 (FLO_type arg_a, FLO_type arg_b)
 }
 #endif /* L_ge_sf || L_ge_df */
 
-#if defined(L_lt_sf) || defined(L_lt_df)
+#if defined(L_lt_sf) || defined(L_lt_df) || defined(L_lt_tf)
 CMPtype
 _lt_f2 (FLO_type arg_a, FLO_type arg_b)
 {
@@ -1124,7 +1235,7 @@ _lt_f2 (FLO_type arg_a, FLO_type arg_b)
 }
 #endif /* L_lt_sf || L_lt_df */
 
-#if defined(L_le_sf) || defined(L_le_df)
+#if defined(L_le_sf) || defined(L_le_df) || defined(L_le_tf)
 CMPtype
 _le_f2 (FLO_type arg_a, FLO_type arg_b)
 {
@@ -1147,7 +1258,7 @@ _le_f2 (FLO_type arg_a, FLO_type arg_b)
 
 #endif /* ! US_SOFTWARE_GOFAST */
 
-#if defined(L_unord_sf) || defined(L_unord_df)
+#if defined(L_unord_sf) || defined(L_unord_df) || defined(L_unord_tf)
 CMPtype
 _unord_f2 (FLO_type arg_a, FLO_type arg_b)
 {
@@ -1165,7 +1276,7 @@ _unord_f2 (FLO_type arg_a, FLO_type arg_
 }
 #endif /* L_unord_sf || L_unord_df */
 
-#if defined(L_si_to_sf) || defined(L_si_to_df)
+#if defined(L_si_to_sf) || defined(L_si_to_df) || defined(L_si_to_tf)
 FLO_type
 si_to_float (SItype arg_a)
 {
@@ -1193,7 +1304,7 @@ si_to_float (SItype arg_a)
       else
 	in.fraction.ll = arg_a;
 
-      while (in.fraction.ll < (1LL << (FRACBITS + NGARDS)))
+      while (in.fraction.ll < ((fractype)1 << (FRACBITS + NGARDS)))
 	{
 	  in.fraction.ll <<= 1;
 	  in.normal_exp -= 1;
@@ -1203,7 +1314,7 @@ si_to_float (SItype arg_a)
 }
 #endif /* L_si_to_sf || L_si_to_df */
 
-#if defined(L_usi_to_sf) || defined(L_usi_to_df)
+#if defined(L_usi_to_sf) || defined(L_usi_to_df) || defined(L_usi_to_tf)
 FLO_type
 usi_to_float (USItype arg_a)
 {
@@ -1220,12 +1331,12 @@ usi_to_float (USItype arg_a)
       in.normal_exp = FRACBITS + NGARDS;
       in.fraction.ll = arg_a;
 
-      while (in.fraction.ll > (1LL << (FRACBITS + NGARDS)))
+      while (in.fraction.ll > ((fractype)1 << (FRACBITS + NGARDS)))
         {
           in.fraction.ll >>= 1;
           in.normal_exp += 1;
         }
-      while (in.fraction.ll < (1LL << (FRACBITS + NGARDS)))
+      while (in.fraction.ll < ((fractype)1 << (FRACBITS + NGARDS)))
 	{
 	  in.fraction.ll <<= 1;
 	  in.normal_exp -= 1;
@@ -1235,7 +1346,7 @@ usi_to_float (USItype arg_a)
 }
 #endif
 
-#if defined(L_sf_to_si) || defined(L_df_to_si)
+#if defined(L_sf_to_si) || defined(L_df_to_si) || defined(L_tf_to_si)
 SItype
 float_to_si (FLO_type arg_a)
 {
@@ -1263,8 +1374,8 @@ float_to_si (FLO_type arg_a)
 }
 #endif /* L_sf_to_si || L_df_to_si */
 
-#if defined(L_sf_to_usi) || defined(L_df_to_usi)
-#ifdef US_SOFTWARE_GOFAST
+#if defined(L_sf_to_usi) || defined(L_df_to_usi) || defined(L_tf_to_usi)
+#if defined US_SOFTWARE_GOFAST || defined(L_tf_to_usi)
 /* While libgcc2.c defines its own __fixunssfsi and __fixunsdfsi routines,
    we also define them for GOFAST because the ones in libgcc2.c have the
    wrong names and I'd rather define these here and keep GOFAST CYG-LOC's
@@ -1303,7 +1414,7 @@ float_to_usi (FLO_type arg_a)
 #endif /* US_SOFTWARE_GOFAST */
 #endif /* L_sf_to_usi || L_df_to_usi */
 
-#if defined(L_negate_sf) || defined(L_negate_df)
+#if defined(L_negate_sf) || defined(L_negate_df) || defined(L_negate_tf)
 FLO_type
 negate (FLO_type arg_a)
 {
@@ -1359,6 +1470,21 @@ sf_to_df (SFtype arg_a)
 }
 #endif /* L_sf_to_df */
 
+#if defined(L_sf_to_tf) && defined(TMODES)
+TFtype
+sf_to_tf (SFtype arg_a)
+{
+  fp_number_type in;
+  FLO_union_type au;
+
+  au.value = arg_a;
+  unpack_d (&au, &in);
+
+  return __make_tp (in.class, in.sign, in.normal_exp,
+		    ((UTItype) in.fraction.ll) << F_T_BITOFF);
+}
+#endif /* L_sf_to_df */
+
 #endif /* ! FLOAT_ONLY */
 #endif /* FLOAT */
 
@@ -1401,6 +1527,85 @@ df_to_sf (DFtype arg_a)
   return __make_fp (in.class, in.sign, in.normal_exp, sffrac);
 }
 #endif /* L_df_to_sf */
+
+#if defined(L_df_to_tf) && defined(TMODES) \
+    && !defined(FLOAT) && !defined(TFLOAT)
+TFtype
+df_to_tf (DFtype arg_a)
+{
+  fp_number_type in;
+  FLO_union_type au;
+
+  au.value = arg_a;
+  unpack_d (&au, &in);
+
+  return __make_tp (in.class, in.sign, in.normal_exp,
+		    ((UTItype) in.fraction.ll) << D_T_BITOFF);
+}
+#endif /* L_sf_to_df */
+
+#ifdef TFLOAT
+#if defined(L_make_tf)
+TFtype
+__make_tp(fp_class_type class,
+	     unsigned int sign,
+	     int exp, 
+	     UTItype frac)
+{
+  fp_number_type in;
+
+  in.class = class;
+  in.sign = sign;
+  in.normal_exp = exp;
+  in.fraction.ll = frac;
+  return pack_d (&in);
+}
+#endif /* L_make_tf */
+
+#if defined(L_tf_to_df)
+DFtype
+tf_to_df (TFtype arg_a)
+{
+  fp_number_type in;
+  UDItype sffrac;
+  FLO_union_type au;
+
+  au.value = arg_a;
+  unpack_d (&au, &in);
+
+  sffrac = in.fraction.ll >> D_T_BITOFF;
+
+  /* We set the lowest guard bit in SFFRAC if we discarded any non
+     zero bits.  */
+  if ((in.fraction.ll & (((UTItype) 1 << D_T_BITOFF) - 1)) != 0)
+    sffrac |= 1;
+
+  return __make_dp (in.class, in.sign, in.normal_exp, sffrac);
+}
+#endif /* L_tf_to_df */
+
+#if defined(L_tf_to_sf)
+SFtype
+tf_to_sf (TFtype arg_a)
+{
+  fp_number_type in;
+  USItype sffrac;
+  FLO_union_type au;
+
+  au.value = arg_a;
+  unpack_d (&au, &in);
+
+  sffrac = in.fraction.ll >> F_T_BITOFF;
+
+  /* We set the lowest guard bit in SFFRAC if we discarded any non
+     zero bits.  */
+  if ((in.fraction.ll & (((UTItype) 1 << F_T_BITOFF) - 1)) != 0)
+    sffrac |= 1;
+
+  return __make_fp (in.class, in.sign, in.normal_exp, sffrac);
+}
+#endif /* L_tf_to_sf */
+#endif /* TFLOAT */
 
 #endif /* ! FLOAT */
 #endif /* !EXTENDED_FLOAT_STUBS */
Index: gcc/config/fp-bit.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/fp-bit.h,v
retrieving revision 1.7
diff -u -p -r1.7 fp-bit.h
--- gcc/config/fp-bit.h 19 Jun 2002 23:01:59 -0000 1.7
+++ gcc/config/fp-bit.h 27 Dec 2002 13:11:28 -0000
@@ -1,5 +1,5 @@
 /* Header file for fp-bit.c.  */
-/* Copyright (C) 2000
+/* Copyright (C) 2000, 2002
    Free Software Foundation, Inc.
 
 This file is part of GNU CC.
@@ -87,12 +87,22 @@ Boston, MA 02111-1307, USA.  */
 #endif
 #endif /* ! FINE_GRAINED_LIBRARIES */
 
+#if __LDBL_MANT_DIG__ == 113 || __LDBL_MANT_DIG__ == 106
+# define TMODES
+#endif
+
 typedef float SFtype __attribute__ ((mode (SF)));
 typedef float DFtype __attribute__ ((mode (DF)));
+#ifdef TMODES
+typedef float TFtype __attribute__ ((mode (TF)));
+#endif
 
 typedef int HItype __attribute__ ((mode (HI)));
 typedef int SItype __attribute__ ((mode (SI)));
 typedef int DItype __attribute__ ((mode (DI)));
+#ifdef TMODES
+typedef int TItype __attribute__ ((mode (TI)));
+#endif
 
 /* The type of the result of a fp compare */
 #ifndef CMPtype
@@ -102,16 +112,68 @@ typedef int DItype __attribute__ ((mode 
 typedef unsigned int UHItype __attribute__ ((mode (HI)));
 typedef unsigned int USItype __attribute__ ((mode (SI)));
 typedef unsigned int UDItype __attribute__ ((mode (DI)));
+#ifdef TMODES
+typedef unsigned int UTItype __attribute__ ((mode (TI)));
+#endif
 
 #define MAX_USI_INT  (~(USItype)0)
 #define MAX_SI_INT   ((SItype) (MAX_USI_INT >> 1))
 #define BITS_PER_SI  (4 * BITS_PER_UNIT)
+#ifdef TMODES
+#define MAX_UDI_INT  (~(UDItype)0)
+#define MAX_DI_INT   ((DItype) (MAX_UDI_INT >> 1))
+#define BITS_PER_DI  (8 * BITS_PER_UNIT)
+#endif
 
 #ifdef FLOAT_ONLY
 #define NO_DI_MODE
 #endif
 
-#ifdef FLOAT
+#ifdef TFLOAT
+# ifndef TMODES
+#  error "TFLOAT requires long double to have 113 bits of mantissa"
+# endif
+
+#	define PREFIXFPDP tp
+#	define PREFIXSFDF tf
+#	define NGARDS 10L /* Is this right? */
+#	define GARDROUND 0x1ff
+#	define GARDMASK  0x3ff
+#	define GARDMSB   0x200
+#	define FRAC_NBITS 128
+
+# if __LDBL_MANT_DIG__ == 113 /* IEEE quad */
+#	define EXPBITS 15
+#	define EXPBIAS 16383
+#	define EXPMAX (0x7fff)
+#	define QUIET_NAN ((TItype)0x8 << 108)
+#	define FRACHIGH  ((TItype)0x8 << 124)
+#	define FRACHIGH2 ((TItype)0xc << 124)
+#	define FRACBITS 112
+# endif
+
+# if __LDBL_MANT_DIG__ == 106 /* IBM extended (double+double) */
+#	define EXPBITS 11
+#	define EXPBIAS 1023
+#	define EXPMAX (0x7ff)
+#	define QUIET_NAN ((TItype)0x8 << (48 + 64))
+#	define FRACHIGH  ((TItype)0x8 << 124)
+#	define FRACHIGH2 ((TItype)0xc << 124)
+#	define FRACBITS 105
+#	define HALFFRACBITS 52
+#	define HALFSHIFT 64
+# endif
+
+#	define pack_d __pack_t
+#	define unpack_d __unpack_t
+#	define __fpcmp_parts __fpcmp_parts_t
+	typedef UTItype fractype;
+	typedef UDItype halffractype;
+	typedef USItype qrtrfractype;
+#define qrtrfractype qrtrfractype
+	typedef TFtype FLO_type;
+	typedef TItype intfrac;
+#elif defined FLOAT
 #	define NGARDS    7L
 #	define GARDROUND 0x3f
 #	define GARDMASK  0x7f
@@ -157,7 +219,9 @@ typedef unsigned int UDItype __attribute
 #endif /* FLOAT */
 
 #ifdef US_SOFTWARE_GOFAST
-#	ifdef FLOAT
+#	ifdef TFLOAT
+#		error "GOFAST TFmode not supported"
+#	elif defined FLOAT
 #		define add 		fpadd
 #		define sub 		fpsub
 #		define multiply 	fpmul
@@ -170,8 +234,8 @@ typedef unsigned int UDItype __attribute
 #		define float_to_usi 	fptoui
 #		define negate 		__negsf2
 #		define sf_to_df		fptodp
-#		define dptofp 		dptofp
-#else
+#		define sf_to_tf		__extendsftf2
+#	else
 #		define add 		dpadd
 #		define sub 		dpsub
 #		define multiply 	dpmul
@@ -184,9 +248,30 @@ typedef unsigned int UDItype __attribute
 #		define float_to_usi 	dptoul
 #		define negate 		__negdf2
 #		define df_to_sf 	dptofp
+#		define df_to_tf 	__extenddftf2
 #	endif /* FLOAT */
 #else
-#	ifdef FLOAT
+#	ifdef TFLOAT
+#		define add 		__addtf3
+#		define sub 		__subtf3
+#		define multiply 	__multf3
+#		define divide 		__divtf3
+#		define compare 		__cmptf2
+#		define _eq_f2 		__eqtf2
+#		define _ne_f2 		__netf2
+#		define _gt_f2 		__gttf2
+#		define _ge_f2 		__getf2
+#		define _lt_f2 		__lttf2
+#		define _le_f2 		__letf2
+#		define _unord_f2	__unordtf2
+#		define usi_to_float 	__floatunsitf
+#		define si_to_float 	__floatsitf
+#		define float_to_si 	__fixtfsi
+#		define float_to_usi 	__fixunstfsi
+#		define negate 		__negtf2
+#		define tf_to_sf		__trunctfsf2
+#		define tf_to_df		__trunctfdf2
+#	elif defined FLOAT
 #		define add 		__addsf3
 #		define sub 		__subsf3
 #		define multiply 	__mulsf3
@@ -205,7 +290,8 @@ typedef unsigned int UDItype __attribute
 #		define float_to_usi 	__fixunssfsi
 #		define negate 		__negsf2
 #		define sf_to_df		__extendsfdf2
-#else
+#		define sf_to_tf		__extendsftf2
+#	else
 #		define add 		__adddf3
 #		define sub 		__subdf3
 #		define multiply 	__muldf3
@@ -224,6 +310,7 @@ typedef unsigned int UDItype __attribute
 #		define float_to_usi 	__fixunsdfsi
 #		define negate 		__negdf2
 #		define df_to_sf		__truncdfsf2
+#		define df_to_tf		__extenddftf2
 #	endif /* FLOAT */
 #endif /* US_SOFTWARE_GOFAST */
 
@@ -241,10 +328,15 @@ typedef unsigned int UDItype __attribute
  */
 #define F_D_BITOFF (52+8-(23+7))
 
+#ifdef TMODES
+# define F_T_BITOFF (__LDBL_MANT_DIG__-1+10-(23+7))
+# define D_T_BITOFF (__LDBL_MANT_DIG__-1+10-(52+8))
+#endif
+
 
 #define NORMAL_EXPMIN (-(EXPBIAS)+1)
-#define IMPLICIT_1 (1LL<<(FRACBITS+NGARDS))
-#define IMPLICIT_2 (1LL<<(FRACBITS+1+NGARDS))
+#define IMPLICIT_1 ((fractype)1<<(FRACBITS+NGARDS))
+#define IMPLICIT_2 ((fractype)1<<(FRACBITS+1+NGARDS))
 
 /* common types */
 
@@ -282,7 +374,11 @@ typedef union
   fractype value_raw;
 
 #ifndef FLOAT
+# ifdef qrtrfractype
+  qrtrfractype qwords[4];
+# else
   halffractype words[2];
+# endif
 #endif
 
 #ifdef FLOAT_BIT_ORDER_MISMATCH
@@ -317,82 +413,82 @@ FLO_union_type;
 
 /* Prototypes */
 
-#if defined(L_pack_df) || defined(L_pack_sf)
+#if defined(L_pack_df) || defined(L_pack_sf) || defined(L_pack_tf)
 extern FLO_type pack_d (fp_number_type *);
 #endif
 
 extern void unpack_d (FLO_union_type *, fp_number_type *);
 
-#if defined(L_addsub_sf) || defined(L_addsub_df)
+#if defined(L_addsub_sf) || defined(L_addsub_df) || defined(L_addsub_tf)
 extern FLO_type add (FLO_type, FLO_type);
 extern FLO_type sub (FLO_type, FLO_type);
 #endif
 
-#if defined(L_mul_sf) || defined(L_mul_df)
+#if defined(L_mul_sf) || defined(L_mul_df) || defined(L_mul_tf)
 extern FLO_type multiply (FLO_type, FLO_type);
 #endif
 
-#if defined(L_div_sf) || defined(L_div_df)
+#if defined(L_div_sf) || defined(L_div_df) || defined(L_div_tf)
 extern FLO_type divide (FLO_type, FLO_type);
 #endif
 
 extern int __fpcmp_parts (fp_number_type *, fp_number_type *);
 
-#if defined(L_compare_sf) || defined(L_compare_df)
+#if defined(L_compare_sf) || defined(L_compare_df) || defined(L_compare_tf)
 extern CMPtype compare (FLO_type, FLO_type);
 #endif
 
 #ifndef US_SOFTWARE_GOFAST
 
-#if defined(L_eq_sf) || defined(L_eq_df)
+#if defined(L_eq_sf) || defined(L_eq_df) || defined(L_eq_tf)
 extern CMPtype _eq_f2 (FLO_type, FLO_type);
 #endif
 
-#if defined(L_ne_sf) || defined(L_ne_df)
+#if defined(L_ne_sf) || defined(L_ne_df) || defined(L_ne_tf)
 extern CMPtype _ne_f2 (FLO_type, FLO_type);
 #endif
 
-#if defined(L_gt_sf) || defined(L_gt_df)
+#if defined(L_gt_sf) || defined(L_gt_df) || defined(L_gt_tf)
 extern CMPtype _gt_f2 (FLO_type, FLO_type);
 #endif
 
-#if defined(L_ge_sf) || defined(L_ge_df)
+#if defined(L_ge_sf) || defined(L_ge_df) || defined(L_ge_tf)
 extern CMPtype _ge_f2 (FLO_type, FLO_type);
 #endif
 
-#if defined(L_lt_sf) || defined(L_lt_df)
+#if defined(L_lt_sf) || defined(L_lt_df) || defined(L_lt_tf)
 extern CMPtype _lt_f2 (FLO_type, FLO_type);
 #endif
 
-#if defined(L_le_sf) || defined(L_le_df)
+#if defined(L_le_sf) || defined(L_le_df) || defined(L_le_tf)
 extern CMPtype _le_f2 (FLO_type, FLO_type);
 #endif
 
-#if defined(L_unord_sf) || defined(L_unord_df)
+#if defined(L_unord_sf) || defined(L_unord_df) || defined(L_unord_tf)
 extern CMPtype _unord_f2 (FLO_type, FLO_type);
 #endif
 
 #endif /* ! US_SOFTWARE_GOFAST */
 
-#if defined(L_si_to_sf) || defined(L_si_to_df)
+#if defined(L_si_to_sf) || defined(L_si_to_df) || defined(L_si_to_tf)
 extern FLO_type si_to_float (SItype);
 #endif
 
-#if defined(L_sf_to_si) || defined(L_df_to_si)
+#if defined(L_sf_to_si) || defined(L_df_to_si) || defined(L_tf_to_si)
 extern SItype float_to_si (FLO_type);
 #endif
 
-#if defined(L_sf_to_usi) || defined(L_df_to_usi)
+#if defined(L_sf_to_usi) || defined(L_df_to_usi) || defined(L_tf_to_usi)
 #ifdef US_SOFTWARE_GOFAST
 extern USItype float_to_usi (FLO_type);
 #endif
 #endif
 
-#if defined(L_usi_to_sf) || defined(L_usi_to_df)
+#if defined(L_usi_to_sf) || defined(L_usi_to_df) || defined(L_usi_to_tf)
 extern FLO_type usi_to_float (USItype);
 #endif
 
-#if defined(L_negate_sf) || defined(L_negate_df)
+#if defined(L_negate_sf) || defined(L_negate_df) || defined(L_negate_tf)
 extern FLO_type negate (FLO_type);
 #endif
 
@@ -405,6 +501,9 @@ extern DFtype __make_dp (fp_class_type, 
 #if defined(L_sf_to_df)
 extern DFtype sf_to_df (SFtype);
 #endif
+#if defined(L_sf_to_tf) && defined(TMODES)
+extern TFtype sf_to_tf (SFtype);
+#endif
 #endif /* ! FLOAT_ONLY */
 #endif /* FLOAT */
 
@@ -416,6 +515,24 @@ extern DFtype __make_dp (fp_class_type, 
 #if defined(L_df_to_sf)
 extern SFtype df_to_sf (DFtype);
 #endif
+#if defined(L_df_to_tf) && defined(TMODES)
+extern TFtype df_to_tf (DFtype);
+#endif
 #endif /* ! FLOAT */
+
+#ifdef TMODES
+extern TFtype __make_tp (fp_class_type, unsigned int, int, UTItype);
+#ifdef TFLOAT
+#if defined(L_tf_to_sf)
+extern SFtype tf_to_sf (TFtype);
+#endif
+#if defined(L_tf_to_df)
+extern DFtype tf_to_df (TFtype);
+#endif
+#if defined(L_di_to_tf)
+extern TFtype di_to_df (DItype);
+#endif
+#endif /* TFLOAT */
+#endif /* TMODES */
 
 #endif /* ! GCC_FP_BIT_H */
Index: gcc/config/mips/_tilib.c
===================================================================
RCS file: gcc/config/mips/_tilib.c
diff -N gcc/config/mips/_tilib.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gcc/config/mips/_tilib.c 27 Dec 2002 13:11:28 -0000
@@ -0,0 +1,154 @@
+/* A few TImode functions needed for TFmode emulated arithmetic.
+   Copyright 2002 Free Software Foundation, Inc.
+   Contributed by Alexandre Oliva <aoliva@redhat.com>
+
+This file is part of GNU CC.
+
+GNU CC 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.
+
+GNU CC 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 GNU CC; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+#include "tconfig.h"
+#include "tsystem.h"
+
+#ifndef LIBGCC2_WORDS_BIG_ENDIAN
+#define LIBGCC2_WORDS_BIG_ENDIAN WORDS_BIG_ENDIAN
+#endif
+
+#if _MIPS_SIM == 2 /* N32 */ || _MIPS_SIM == 3 /* 64 */
+
+typedef int TItype __attribute__ ((mode (TI)));
+typedef int DItype __attribute__ ((mode (DI)));
+typedef int SItype __attribute__ ((mode (SI)));
+
+typedef unsigned int UDItype __attribute__ ((mode (DI)));
+
+typedef union
+{
+  struct TIstruct {
+#if LIBGCC2_WORDS_BIG_ENDIAN
+    DItype high, low;
+#else
+    DItype low, high;
+#endif
+  } s;
+  TItype ll;
+} TIunion;
+
+TItype
+__negti2 (TItype u)
+{
+  TIunion w;
+  TIunion uu;
+
+  uu.ll = u;
+
+  w.s.low = -uu.s.low;
+  w.s.high = -uu.s.high - ((UDItype) w.s.low > 0);
+
+  return w.ll;
+}
+
+TItype
+__ashlti3 (TItype u, int b)
+{
+  TIunion w;
+  int bm;
+  TIunion uu;
+
+  if (b == 0)
+    return u;
+
+  uu.ll = u;
+
+  bm = (sizeof (DItype) * BITS_PER_UNIT) - b;
+  if (bm <= 0)
+    {
+      w.s.low = 0;
+      w.s.high = (UDItype) uu.s.low << -bm;
+    }
+  else
+    {
+      UDItype carries = (UDItype) uu.s.low >> bm;
+
+      w.s.low = (UDItype) uu.s.low << b;
+      w.s.high = ((UDItype) uu.s.high << b) | carries;
+    }
+
+  return w.ll;
+}
+
+#if 0
+TItype
+__ashrti3 (TItype u, int b)
+{
+  TIunion w;
+  int bm;
+  TIunion uu;
+
+  if (b == 0)
+    return u;
+
+  uu.ll = u;
+
+  bm = (sizeof (DItype) * BITS_PER_UNIT) - b;
+  if (bm <= 0)
+    {
+      /* w.s.high = 1..1 or 0..0 */
+      w.s.high = uu.s.high >> (sizeof (DItype) * BITS_PER_UNIT - 1);
+      w.s.low = uu.s.high >> -bm;
+    }
+  else
+    {
+      UDItype carries = (UDItype) uu.s.high << bm;
+
+      w.s.high = uu.s.high >> b;
+      w.s.low = ((UDItype) uu.s.low >> b) | carries;
+    }
+
+  return w.ll;
+}
+#endif
+
+TItype
+__lshrti3 (TItype u, int b)
+{
+  TIunion w;
+  int bm;
+  TIunion uu;
+
+  if (b == 0)
+    return u;
+
+  uu.ll = u;
+
+  bm = (sizeof (DItype) * BITS_PER_UNIT) - b;
+  if (bm <= 0)
+    {
+      w.s.high = 0;
+      w.s.low = (UDItype) uu.s.high >> -bm;
+    }
+  else
+    {
+      UDItype carries = (UDItype) uu.s.high << bm;
+
+      w.s.high = (UDItype) uu.s.high >> b;
+      w.s.low = ((UDItype) uu.s.low >> b) | carries;
+    }
+
+  return w.ll;
+}
+
+#endif /* N32 or N64 */
Index: gcc/config/mips/mips.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/mips/mips.c,v
retrieving revision 1.241
diff -u -p -r1.241 mips.c
--- gcc/config/mips/mips.c 12 Dec 2002 05:13:03 -0000 1.241
+++ gcc/config/mips/mips.c 27 Dec 2002 13:11:35 -0000
@@ -4286,7 +4286,9 @@ mips_arg_info (cum, mode, type, named, i
 
   info->fpr_p = false;
   if (GET_MODE_CLASS (mode) == MODE_FLOAT
-      && GET_MODE_SIZE (mode) <= UNITS_PER_FPVALUE)
+      && GET_MODE_SIZE (mode) <= UNITS_PER_FPVALUE * ((mips_abi == ABI_N32
+						       || mips_abi == ABI_64)
+						      ? 2 : 1))
     {
       switch (mips_abi)
 	{
@@ -4321,9 +4323,11 @@ mips_arg_info (cum, mode, type, named, i
 	 is a double, but $f14 if it is a single.  Otherwise, on a
 	 32-bit double-float machine, each FP argument must start in a
 	 new register pair.  */
-      even_reg_p = ((mips_abi == ABI_O64 && mode == SFmode) || FP_INC > 1);
+      even_reg_p = (GET_MODE_SIZE (mode) > UNITS_PER_FPVALUE /* TFmode */
+		    || (mips_abi == ABI_O64 && mode == SFmode)
+		    || FP_INC > 1);
     }
-  else if (!TARGET_64BIT)
+  else if (!TARGET_64BIT || mips_abi == ABI_N32 || mips_abi == ABI_64)
     {
       if (GET_MODE_CLASS (mode) == MODE_INT
 	  || GET_MODE_CLASS (mode) == MODE_FLOAT)
@@ -4712,6 +4716,15 @@ mips_va_start (valist, nextarg)
 {
   const CUMULATIVE_ARGS *cum = &current_function_args_info;
 
+  /* ARG_POINTER_REGNUM is initialized to STACK_POINTER_BOUNDARY, but
+     since the stack is aligned for a pair of argument-passing slots,
+     and the beginning of a variable argument list may be an odd slot,
+     we have to decrease its alignment.  */
+  if (cfun && cfun->emit->regno_pointer_align)
+    while (((current_function_pretend_args_size * BITS_PER_UNIT)
+	    & (REGNO_POINTER_ALIGN (ARG_POINTER_REGNUM) - 1)) != 0)
+      REGNO_POINTER_ALIGN (ARG_POINTER_REGNUM) /= 2;
+
   if (mips_abi == ABI_EABI)
     {
       int gpr_save_area_size;
@@ -5007,7 +5020,10 @@ mips_va_arg (valist, type)
 	 that alignments <= UNITS_PER_WORD are preserved by the va_arg
 	 increment mechanism.  */
 
-      if (TARGET_64BIT)
+      if ((mips_abi == ABI_N32 || mips_abi == ABI_64)
+	  && TYPE_ALIGN (type) > 64)
+	align = 16;
+      else if (TARGET_64BIT)
 	align = 8;
       else if (TYPE_ALIGN (type) > 32)
 	align = 8;
@@ -5365,6 +5381,8 @@ override_options ()
   else
     mips16 = 0;
 
+  real_format_for_mode[TFmode - QFmode] = &ibm_extended_format;
+
   mips_print_operand_punct['?'] = 1;
   mips_print_operand_punct['#'] = 1;
   mips_print_operand_punct['&'] = 1;
@@ -5454,7 +5472,10 @@ override_options ()
                         register. */
 		     || (mips_abi == ABI_MEABI && size <= 4))
 		    && (((class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
-			 && size <= UNITS_PER_FPVALUE)
+			 && size <= (UNITS_PER_FPVALUE
+				     * ((mips_abi == ABI_N32
+					 || mips_abi == ABI_64)
+					? 2 : 1)))
 			/* Allow integer modes that fit into a single
 			   register.  We need to put integers into FPRs
 			   when using instructions like cvt and trunc.  */
@@ -8271,8 +8292,24 @@ mips_function_value (valtype, func, mode
     }
   mclass = GET_MODE_CLASS (mode);
 
-  if (mclass == MODE_FLOAT && GET_MODE_SIZE (mode) <= UNITS_PER_FPVALUE)
+  if (mclass == MODE_FLOAT
+      && GET_MODE_SIZE (mode) <= UNITS_PER_FPVALUE)
     reg = FP_RETURN;
+
+  else if (mclass == MODE_FLOAT
+	   && mode == TFmode
+	   && (mips_abi == ABI_N32 || mips_abi == ABI_64))
+    /* long doubles are really split between f0 and f2, not f1.  Eek.  */
+    return gen_rtx_PARALLEL
+      (VOIDmode,
+       gen_rtvec (2,
+		  gen_rtx_EXPR_LIST (VOIDmode,
+				     gen_rtx_REG (DImode, FP_RETURN),
+				     GEN_INT (0)),
+		  gen_rtx_EXPR_LIST (VOIDmode,
+				     gen_rtx_REG (DImode, FP_RETURN + 2),
+				     GEN_INT (GET_MODE_SIZE (mode) / 2))));
+       
 
   else if (mclass == MODE_COMPLEX_FLOAT
 	   && GET_MODE_SIZE (mode) <= UNITS_PER_FPVALUE * 2)
Index: gcc/config/mips/mips.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/mips/mips.h,v
retrieving revision 1.227
diff -u -p -r1.227 mips.h
--- gcc/config/mips/mips.h 5 Nov 2002 12:41:52 -0000 1.227
+++ gcc/config/mips/mips.h 27 Dec 2002 13:11:38 -0000
@@ -1535,7 +1535,21 @@ do {							\
 /* A C expression for the size in bits of the type `long double' on
    the target machine.  If you don't define this, the default is two
    words.  */
-#define LONG_DOUBLE_TYPE_SIZE 64
+#define LONG_DOUBLE_TYPE_SIZE \
+  (mips_abi == ABI_N32 || mips_abi == ABI_64 ? 128 : 64)
+
+/* long double is not a fixed mode, but the idea is that, if we
+   support long double, we also want a 128-bit integer type.  */
+#define MAX_FIXED_MODE_SIZE LONG_DOUBLE_TYPE_SIZE
+
+#ifdef IN_LIBGCC2
+#if  (defined _ABIN32 && _MIPS_SIM == _ABIN32) \
+  || (defined _ABI64 && _MIPS_SIM == _ABI64)
+#  define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 128
+# else
+#  define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 64
+# endif
+#endif
 
 /* Width in bits of a pointer.
    See also the macro `Pmode' defined below.  */
@@ -1562,7 +1576,8 @@ do {							\
 #define STRUCTURE_SIZE_BOUNDARY 8
 
 /* There is no point aligning anything to a rounder boundary than this.  */
-#define BIGGEST_ALIGNMENT 64
+#define BIGGEST_ALIGNMENT ((mips_abi == ABI_N32 || mips_abi == ABI_64) \
+			   ? 128 : 64)
 
 /* Set this nonzero if move instructions will actually fail to work
    when given unaligned data.  */
@@ -2624,7 +2639,9 @@ extern enum reg_class mips_char_to_class
    On the MIPS, R2 R3 and F0 F2 are the only register thus used.
    Currently, R2 and F0 are only implemented  here (C has no complex type)  */
 
-#define FUNCTION_VALUE_REGNO_P(N) ((N) == GP_RETURN || (N) == FP_RETURN)
+#define FUNCTION_VALUE_REGNO_P(N) ((N) == GP_RETURN || (N) == FP_RETURN \
+  || ((mips_abi == ABI_N32 || mips_abi == ABI_64) && FP_RETURN != GP_RETURN \
+      && (N) == FP_RETURN + 2))
 
 /* 1 if N is a possible register number for function argument passing.
    We have no FP argument registers when soft-float.  When FP registers
Index: gcc/config/mips/t-iris6
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/mips/t-iris6,v
retrieving revision 1.16
diff -u -p -r1.16 t-iris6
--- gcc/config/mips/t-iris6 12 Nov 2002 11:15:48 -0000 1.16
+++ gcc/config/mips/t-iris6 27 Dec 2002 13:11:38 -0000
@@ -18,3 +18,16 @@ CRTSTUFF_T_CFLAGS=-g1
 # This is only needed in the static libgcc as a band-aid until gcc correctly
 # implements the N32/N64 ABI structure passing conventions
 LIB2FUNCS_STATIC_EXTRA = $(srcdir)/config/mips/irix6-libc-compat.c
+
+LIB2FUNCS_EXTRA = $(srcdir)/config/mips/_tilib.c
+
+TPBIT = tp-bit.c
+
+tp-bit.c: $(srcdir)/config/fp-bit.c
+	echo '#ifdef __MIPSEL__' > tp-bit.c
+	echo '# define FLOAT_BIT_ORDER_MISMATCH' >> tp-bit.c
+	echo '#endif' >> tp-bit.c
+	echo '#if __LDBL_MANT_DIG__ == 106' >> tp-bit.c
+	echo '# define TFLOAT' >> tp-bit.c
+	cat $(srcdir)/config/fp-bit.c >> tp-bit.c
+	echo '#endif' >> tp-bit.c
-- 
Alexandre Oliva   Enjoy Guarana', see http://www.ic.unicamp.br/~oliva/
Red Hat GCC Developer                 aoliva@{redhat.com, gcc.gnu.org}
CS PhD student at IC-Unicamp        oliva@{lsd.ic.unicamp.br, gnu.org}
Free Software Evangelist                Professional serial bug killer

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