public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
* Irix6 long doubles implemented wrong?  (27_io/ostream_inserter_arith)
@ 2002-12-14 14:09 Kaveh R. Ghazi
  2002-12-16  9:24 ` Rainer Orth
  2002-12-16  9:51 ` Alexandre Oliva
  0 siblings, 2 replies; 72+ messages in thread
From: Kaveh R. Ghazi @ 2002-12-14 14:09 UTC (permalink / raw)
  To: gcc-bugs, gcc; +Cc: libstdc++, oldham, ro

I'm getting wierd (i.e. I think wrong) results for long doubles on
mips-irix6.  Consider the following C testcase:

#include <stdio.h>
int main()
{
  char buf[1024];
  long double ldin[] = { 1.0L, 1.0L, 1.0L };
  long double ldout[3];

  fprintf (stdout, "sizeof(long double) == %d\n", (int) sizeof ldin[0]);
  sprintf (buf, "%Lf %Lf %Lf", ldin[0], ldin[1], ldin[2]);
  sscanf (buf, "%Lf %Lf %Lf", &ldout[0], &ldout[1], &ldout[2]);
  fprintf (stdout, "<%Lf><%Lf><%Lf>\n", ldout[0], ldout[1], ldout[2]);
  return 0;
}

Compiling and then running this program with "cc -n32" or "cc -64" on
irix6.2 or irix6.5 (correctly I believe for these ABIs) yields:

 > sizeof(long double) == 16
 > <1.000000><1.000000><1.000000>

Compiling and then running this program with "gcc -mabi=n32" or
"gcc -mabi=64" on irix6.2 or irix6.5 (erroneously) yields:

 > sizeof(long double) == 8
 > <1.000000><0.000000><-nan0xffffffff>
 > Bus error (core dumped)

This appears to occur for all gcc versions from 2.8.1 through the
current CVS trunk.

As you can see, gcc's sizeof (long double) doesn't agree with that
from the system compiler and I would assume therefore that gcc also
disagrees with libc's notion of long double.  This means that the %Lf
specifier is hosed and cannot be used from gcc on irix6.

I believe this is the cause of the 27_io/ostream_inserter_arith.cc
failures we've been getting on irix6.

See also http://gcc.gnu.org/ml/gcc-bugs/2001-08/msg00088.html which
apears to be the same issue.

Does anyone have any thoughts on this?  (Or better yet a fix?)

		Thanks,
		--Kaveh
--
Kaveh R. Ghazi			ghazi@caip.rutgers.edu

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: Irix6 long doubles implemented wrong?  (27_io/ostream_inserter_arith)
  2002-12-14 14:09 Irix6 long doubles implemented wrong? (27_io/ostream_inserter_arith) Kaveh R. Ghazi
@ 2002-12-16  9:24 ` Rainer Orth
  2002-12-16  9:51 ` Alexandre Oliva
  1 sibling, 0 replies; 72+ messages in thread
From: Rainer Orth @ 2002-12-16  9:24 UTC (permalink / raw)
  To: Kaveh R. Ghazi; +Cc: gcc-bugs, gcc, libstdc++, oldham

Kaveh R. Ghazi writes:

> As you can see, gcc's sizeof (long double) doesn't agree with that
> from the system compiler and I would assume therefore that gcc also
> disagrees with libc's notion of long double.  This means that the %Lf
> specifier is hosed and cannot be used from gcc on irix6.
> 
> I believe this is the cause of the 27_io/ostream_inserter_arith.cc
> failures we've been getting on irix6.
> 
> See also http://gcc.gnu.org/ml/gcc-bugs/2001-08/msg00088.html which
> apears to be the same issue.

It is.  The following comment from config/mips/abi64.h (lost when the
definitions from that file were merged into mips.h) still applies:

/* ??? Unimplemented stuff follows.  */

/* ??? Add support for 16 byte/128 bit long doubles here when
   mips_abi != ABI32.  */

> Does anyone have any thoughts on this?  (Or better yet a fix?)

I didn't have much time to work on gcc lately, but David Edelsohn's support
or 128-bit long doubles in AIX (implemented as a pair of 64-bit doubles)
applies to IRIX 6 long doubles as well, since both platforms use the same
format as documented in math(3M).

	Rainer

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: Irix6 long doubles implemented wrong?  (27_io/ostream_inserter_arith)
  2002-12-14 14:09 Irix6 long doubles implemented wrong? (27_io/ostream_inserter_arith) Kaveh R. Ghazi
  2002-12-16  9:24 ` Rainer Orth
@ 2002-12-16  9:51 ` Alexandre Oliva
  2002-12-16  9:52   ` Rainer Orth
  2002-12-16 21:58   ` Kaveh R. Ghazi
  1 sibling, 2 replies; 72+ messages in thread
From: Alexandre Oliva @ 2002-12-16  9:51 UTC (permalink / raw)
  To: Kaveh R. Ghazi; +Cc: gcc-bugs, gcc, libstdc++, oldham, ro

On Dec 14, 2002, "Kaveh R. Ghazi" <ghazi@caip.rutgers.edu> wrote:

> Does anyone have any thoughts on this?  (Or better yet a fix?)

I've been working on a patch that will enable us to switch to 128-bit
long doubles on mips n32 and n64, but I still need a little bit of
polishing and checking (I know that my current patch still doesn't
pass long double arguments in the right registers).  I expect to have
it finished in the next few days.

That said, I'm not sure it would be wise to break the gcc ABI on IRIX
6 by introducing this change.  It's not like long double is the most
widely used type, but still, I'm a bit concerned about changing it.
Opinions?

-- 
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

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: Irix6 long doubles implemented wrong?  (27_io/ostream_inserter_arith)
  2002-12-16  9:51 ` Alexandre Oliva
@ 2002-12-16  9:52   ` Rainer Orth
  2002-12-16 12:23     ` Eric Christopher
  2002-12-16 21:58   ` Kaveh R. Ghazi
  1 sibling, 1 reply; 72+ messages in thread
From: Rainer Orth @ 2002-12-16  9:52 UTC (permalink / raw)
  To: Alexandre Oliva; +Cc: Kaveh R. Ghazi, gcc-bugs, gcc, libstdc++, oldham

Alexandre Oliva writes:

> I've been working on a patch that will enable us to switch to 128-bit
> long doubles on mips n32 and n64, but I still need a little bit of
> polishing and checking (I know that my current patch still doesn't
> pass long double arguments in the right registers).  I expect to have
> it finished in the next few days.

Great.

> That said, I'm not sure it would be wise to break the gcc ABI on IRIX
> 6 by introducing this change.  It's not like long double is the most
> widely used type, but still, I'm a bit concerned about changing it.
> Opinions?

On the contrary: we shouldn't introduce a GCC ABI (which is especially
useless since it doesn't interoperate with libc as is the case with 64-bit
long double), but try to implement the vendor ABI correctly.  I think the
same is true for the major other ABI non-conformance on IRIX, namely
passing of small structures (where Jim Wilson is working on a fix, as I
understand).  This has caused so many people trouble and required
platform-specific work-arounds in so many packages that we should get this
right once and for all, even if this means non-interoperability with the
older (broken) GCC implementation.

	Rainer

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: Irix6 long doubles implemented wrong?  (27_io/ostream_inserter_arith)
  2002-12-16  9:52   ` Rainer Orth
@ 2002-12-16 12:23     ` Eric Christopher
  0 siblings, 0 replies; 72+ messages in thread
From: Eric Christopher @ 2002-12-16 12:23 UTC (permalink / raw)
  To: Rainer Orth
  Cc: Alexandre Oliva, Kaveh R. Ghazi, gcc-bugs, gcc, libstdc++, oldham


> understand).  This has caused so many people trouble and required
> platform-specific work-arounds in so many packages that we should get this
> right once and for all, even if this means non-interoperability with the
> older (broken) GCC implementation.
> 

I'm inclined to agree with Rainer here. If we're going to say that we
want to support the ABI that we do, we need to support as much as we
possibly can. If we can support 128-bit long doubles we should.

-eric

-- 
Yeah, I used to play basketball...

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: Irix6 long doubles implemented wrong?  (27_io/ostream_inserter_arith)
  2002-12-16  9:51 ` Alexandre Oliva
  2002-12-16  9:52   ` Rainer Orth
@ 2002-12-16 21:58   ` Kaveh R. Ghazi
  2002-12-21 10:45     ` Alexandre Oliva
  1 sibling, 1 reply; 72+ messages in thread
From: Kaveh R. Ghazi @ 2002-12-16 21:58 UTC (permalink / raw)
  To: aoliva; +Cc: gcc-bugs, gcc, libstdc++, oldham, ro

 > From: Alexandre Oliva <aoliva@redhat.com>
 > 
 > On Dec 14, 2002, "Kaveh R. Ghazi" <ghazi@caip.rutgers.edu> wrote:
 > 
 > > Does anyone have any thoughts on this?  (Or better yet a fix?)
 > 
 > I've been working on a patch that will enable us to switch to 128-bit
 > long doubles on mips n32 and n64, but I still need a little bit of
 > polishing and checking (I know that my current patch still doesn't
 > pass long double arguments in the right registers).  I expect to have
 > it finished in the next few days.

Excellent!  Let me know if I can be of service testing your patch.


 > That said, I'm not sure it would be wise to break the gcc ABI on IRIX
 > 6 by introducing this change.  It's not like long double is the most
 > widely used type, but still, I'm a bit concerned about changing it.
 > Opinions?

Considering the current irix libc incompatibility, one cannot
currently input or output long doubles using stdio.  What good is
that? :-)

I definitely support fixing the ABI, perhaps even on the 3.3 branch if
the patch is not too invasive.

		Thanks,
		--Kaveh
--
Kaveh R. Ghazi			ghazi@caip.rutgers.edu

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: Irix6 long doubles implemented wrong?  (27_io/ostream_inserter_arith)
  2002-12-16 21:58   ` Kaveh R. Ghazi
@ 2002-12-21 10:45     ` Alexandre Oliva
  2002-12-22  6:02       ` Kaveh R. Ghazi
  2002-12-22 10:24       ` Alexandre Oliva
  0 siblings, 2 replies; 72+ messages in thread
From: Alexandre Oliva @ 2002-12-21 10:45 UTC (permalink / raw)
  To: Kaveh R. Ghazi; +Cc: gcc-bugs, gcc, libstdc++, oldham, ro

On Dec 17, 2002, "Kaveh R. Ghazi" <ghazi@caip.rutgers.edu> wrote:

>> From: Alexandre Oliva <aoliva@redhat.com>
>> 
>> On Dec 14, 2002, "Kaveh R. Ghazi" <ghazi@caip.rutgers.edu> wrote:
>> 
>> > Does anyone have any thoughts on this?  (Or better yet a fix?)
>> 
>> I've been working on a patch that will enable us to switch to 128-bit
>> long doubles on mips n32 and n64, but I still need a little bit of
>> polishing and checking (I know that my current patch still doesn't
>> pass long double arguments in the right registers).  I expect to have
>> it finished in the next few days.

> Excellent!  Let me know if I can be of service testing your patch.

Thanks.  It's taking longer than I expected, because I hadn't realized
IRIX actually used a different 128-bit long double format than IEEE
854 long double, which I had blindly assumed.  I've now introduced
support for both in my copy of gcc/config/fp-bit.c, and adjusted the
function-calling conventions, but this happened to uncover a number of
problems in GCC.  Some had to do with the inability to get PARALLELs
in return values of libcalls, which I've already fixed.  The other has
to do with some gcse problems that, because of some gratuitous copying
introduced inside such libcalls when PARALLELs are used, it ends up
replacing uses of the REG_RETVAL of the libcall with uses of a pseudo
internal to the libcall.  Then, the RETVAL ends up dead, and we delete
the entire libcall sequence.  Oops :-)

I've worked around that too, but I'm still observing mis-compilation
of the multiply code, in what appears to be another gcse/libcall
problem, or perhaps just another occurrence of the same problem, that
happens not to be worked around with the fixes I've put in.

> I definitely support fixing the ABI, perhaps even on the 3.3 branch if
> the patch is not too invasive.

None of the patches seem risky, and they actually do fix real bugs,
but, the more code I have to tweak, the less likely I fell this will
find its way into the 3.3 branch :-(

-- 
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

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: Irix6 long doubles implemented wrong?  (27_io/ostream_inserter_arith)
  2002-12-21 10:45     ` Alexandre Oliva
@ 2002-12-22  6:02       ` Kaveh R. Ghazi
  2002-12-22 10:24       ` Alexandre Oliva
  1 sibling, 0 replies; 72+ messages in thread
From: Kaveh R. Ghazi @ 2002-12-22  6:02 UTC (permalink / raw)
  To: aoliva; +Cc: gcc-bugs, gcc, libstdc++, oldham, ro

 > From: Alexandre Oliva <aoliva@redhat.com>
 > 
 > On Dec 17, 2002, "Kaveh R. Ghazi" <ghazi@caip.rutgers.edu> wrote:
 > 
 > > I definitely support fixing the ABI, perhaps even on the 3.3 branch if
 > > the patch is not too invasive.
 > 
 > None of the patches seem risky, and they actually do fix real bugs,
 > but, the more code I have to tweak, the less likely I fell this will
 > find its way into the 3.3 branch :-(

Well, that can be evaluated once you post the patch.  Perhaps if you
split it into pieces, each addressing separate problems it might help
the reviewer "see" that each piece is safe.

Obviously, if you can create testcases separate from your mips work
that triggers some problem or crash that would help smooth the way for
each of these extra fixes.

In any case, even just having your work on the trunk is mega-better
than the current situation.  So thanks a lot for working on this.

		--Kaveh
--
Kaveh R. Ghazi			ghazi@caip.rutgers.edu

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: Irix6 long doubles implemented wrong?  (27_io/ostream_inserter_arith)
  2002-12-21 10:45     ` Alexandre Oliva
  2002-12-22  6:02       ` Kaveh R. Ghazi
@ 2002-12-22 10:24       ` Alexandre Oliva
  2002-12-22 10:35         ` Alexandre Oliva
  2002-12-23  9:46         ` Alexandre Oliva
  1 sibling, 2 replies; 72+ messages in thread
From: Alexandre Oliva @ 2002-12-22 10:24 UTC (permalink / raw)
  To: Kaveh R. Ghazi, gcc-patches; +Cc: gcc-bugs, gcc, libstdc++, oldham, ro

[-- Attachment #1: Type: text/plain, Size: 2190 bytes --]

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

> The other has to do with some gcse problems that, because of some
> gratuitous copying introduced inside such libcalls when PARALLELs
> are used, it ends up replacing uses of the REG_RETVAL of the libcall
> with uses of a pseudo internal to the libcall.  Then, the RETVAL
> ends up dead, and we delete the entire libcall sequence.  Oops :-)

It turned out that it wasn't gcse's fault, but rather a problem in
open-coded add/sub operations for wide types that failed to store the
result of a wide add/sub computation in the target without returning
the location of the result to the caller.  Oops.

>> I definitely support fixing the ABI, perhaps even on the 3.3 branch if
>> the patch is not too invasive.

> None of the patches seem risky, and they actually do fix real bugs,
> but, the more code I have to tweak, the less likely I fell this will
> find its way into the 3.3 branch :-(

s/fell/feel/

Anyway, I'm more confident about being able to get this patch in than
what I had last night, since I could revert the most intrusive parts
after fixing the aforementioned bug.  The result is almost pretty.
Tested in the 3.3 branch with a mips-sgi-irix6.5 bootstrap, as well as
by visual inspection of the assembly code emitted for some of the
attached source programs, as well as by execution of the programs that
contained main().

I feel I may be missing some additional rounding in the code that
packs back to the native long double format of irix, but I've now idea
of how to tell whether it's actually necessary.  Do any FP experts
care to comment?

Oh, it would probably be appropriate for us to use the native long
double function calls on IRIX, but since I was implementing this for a
different operating system, and I wanted to make sure the
implementation was compatible with that of IRIX, I didn't make the
effort to use the native IRIX library.  I'll leave that as an exercise
for those who actually care about long double performance on IRIX.
The performance of the current implementation is probably awful,
especially on multiplies and divides.  Get it right first, optimize
later, if ever :-D

Ok to install?


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: gcc-mips-tfmode-emul.patch --]
[-- Type: text/x-patch, Size: 40952 bytes --]

? gcc/config/mips/_tilib.c
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.
	(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 and IBM-extended TFmode types.
	(_fpmul_parts): Support TFmode.
	(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.

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 22 Dec 2002 03:38:03 -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/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 22 Dec 2002 03:38:08 -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
diff -u -p -r1.498 expr.c
--- gcc/expr.c 13 Dec 2002 00:17:18 -0000 1.498
+++ gcc/expr.c 22 Dec 2002 03:38:19 -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 22 Dec 2002 03:38:19 -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 22 Dec 2002 03:38: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 22 Dec 2002 03:38:22 -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/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 22 Dec 2002 03:38:23 -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;
-}
 \f
 /* 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 22 Dec 2002 03:38:24 -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 22 Dec 2002 03:38:26 -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,80 @@ 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
+     {
+       const int ngards = FRACBITS - 2 * HALFFRACBITS - 1;
+
+       exp -= HALFFRACBITS + 1;
+
+       while (low < ((halffractype)1 << (HALFFRACBITS + ngards)))
+	 {
+	   low <<= 1;
+	   exp--;
+	 }
+
+       if (exp < -HALFFRACBITS)
+	 low = exp = sign = 0;
+       else if (exp < 0)
+	 {
+	   low >>= -exp;
+	   exp = 0;
+	 }
+
+       low >>= ngards;
+
+       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 +409,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 +426,34 @@ 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);
+
+       low &= (((fractype)1) << HALFFRACBITS) - 1;
+       if (lowexp)
+	 low |= ((halffractype)1) << HALFFRACBITS;
+       fraction |= ((fractype)low << (FRACBITS - HALFFRACBITS))
+				  >> (exp - lowexp);
+     }
+ }
+# 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 +521,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 +705,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 +754,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;
@@ -725,7 +819,9 @@ _fpmul_parts ( fp_number_type *  a,
 
   tmp->normal_exp = a->normal_exp + b->normal_exp;
   tmp->sign = a->sign != b->sign;
-#ifdef FLOAT
+#ifdef TFLOAT
+  tmp->normal_exp += 6;		/* ??????????????? */
+#elif defined FLOAT
   tmp->normal_exp += 2;		/* ??????????????? */
 #else
   tmp->normal_exp += 4;		/* ??????????????? */
@@ -803,7 +899,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 +1009,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 +1095,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 +1117,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 +1138,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 +1159,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 +1180,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 +1200,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 +1221,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 +1244,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 +1262,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 +1290,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 +1300,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 +1317,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 +1332,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 +1360,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 +1400,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 +1456,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 +1513,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 22 Dec 2002 03:38:26 -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 112
+#	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 */
 
@@ -240,11 +327,13 @@ typedef unsigned int UDItype __attribute
    (double::FRAC_BITS+double::NGARDS-(float::FRAC_BITS-float::NGARDS))
  */
 #define F_D_BITOFF (52+8-(23+7))
+#define F_T_BITOFF (113+10-(23+7))
+#define D_T_BITOFF (113+10-(52+8))
 
 
 #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 +371,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 +410,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 +498,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 +512,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 */
+
+#if defined TFLOAT && defined(TMODES)
+#if defined(L_make_tf)
+extern TFtype __make_tp (fp_class_type, unsigned int, int, UTItype);
+#endif
+#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
 
 #endif /* ! GCC_FP_BIT_H */
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 22 Dec 2002 03:38:33 -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)
@@ -5365,6 +5369,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 +5460,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 +8280,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 22 Dec 2002 03:38:37 -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 22 Dec 2002 03:38:37 -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

[-- Attachment #3: Type: text/plain, Size: 289 bytes --]


-- 
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

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: Irix6 long doubles implemented wrong?  (27_io/ostream_inserter_arith)
  2002-12-22 10:24       ` Alexandre Oliva
@ 2002-12-22 10:35         ` Alexandre Oliva
  2002-12-23  9:46         ` Alexandre Oliva
  1 sibling, 0 replies; 72+ messages in thread
From: Alexandre Oliva @ 2002-12-22 10:35 UTC (permalink / raw)
  To: Kaveh R. Ghazi; +Cc: gcc-patches, gcc-bugs, gcc, libstdc++, oldham, ro

[-- Attachment #1: Type: text/plain, Size: 405 bytes --]

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

> Tested in the 3.3 branch with a mips-sgi-irix6.5 bootstrap, as well as
> by visual inspection of the assembly code emitted for some of the
> attached source programs, as well as by execution of the programs that
> contained main().

Err...  These programs.  I tested variations of the last one to get
more coverage of arithmetic operations.


[-- Attachment #2: fpcst.c --]
[-- Type: application/octet-stream, Size: 169 bytes --]

long double one = 1;
long double two = 2;
long double minus_one = -1;
long double onek = 1024;
long double onemeg = 1048576;
long double small = 0.1234567890123456789l;

[-- Attachment #3: fpabi.c --]
[-- Type: application/octet-stream, Size: 97 bytes --]

#include <stdio.h>
main() {
  long double i = 1.0l, j = 1.12345l;
  printf("%Lf %Lf\n", i, j);
}

[-- Attachment #4: fpprint.c --]
[-- Type: application/octet-stream, Size: 97 bytes --]

#include <stdio.h>
main() {
  long double i = 1.0l, j = 1.12345l;
  printf("%Lf %Lf\n", i, j);
}

[-- Attachment #5: fpcheck.c --]
[-- Type: application/octet-stream, Size: 325 bytes --]

#include <stdio.h>
long double y = 0;
main() {
  union { long double ld; long long ll[2]; } x = { 15.0l };

  while (x.ld > 0)
    {
      printf ("0x%016llx.%016llx = %L35.30g\n", x.ll[0], x.ll[1], x.ld);
      x.ld += y;
      printf ("0x%016llx.%016llx = %L35.30g\n", x.ll[0], x.ll[1], x.ld);
      x.ld /= 10.0l;
    }
}

[-- Attachment #6: Type: text/plain, Size: 289 bytes --]


-- 
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

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: Irix6 long doubles implemented wrong?  (27_io/ostream_inserter_arith)
  2002-12-22 10:24       ` Alexandre Oliva
  2002-12-22 10:35         ` Alexandre Oliva
@ 2002-12-23  9:46         ` Alexandre Oliva
  2002-12-24 11:07           ` Kaveh R. Ghazi
                             ` (2 more replies)
  1 sibling, 3 replies; 72+ messages in thread
From: Alexandre Oliva @ 2002-12-23  9:46 UTC (permalink / raw)
  To: Kaveh R. Ghazi; +Cc: gcc-patches, gcc-bugs, gcc, libstdc++, oldham, ro

[-- Attachment #1: Type: text/plain, Size: 161 bytes --]

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

> ? gcc/config/mips/_tilib.c

Here's the file that I had failed to cvs add before taking the diff:


[-- Attachment #2: _tilib.c --]
[-- Type: application/octet-stream, Size: 3002 bytes --]

/* 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 */

[-- Attachment #3: Type: text/plain, Size: 289 bytes --]


-- 
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

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: Irix6 long doubles implemented wrong?  (27_io/ostream_inserter_arith)
  2002-12-23  9:46         ` Alexandre Oliva
@ 2002-12-24 11:07           ` Kaveh R. Ghazi
  2002-12-25  8:04             ` Alexandre Oliva
  2002-12-24 18:15           ` Kaveh R. Ghazi
  2003-01-07 22:40           ` Richard Henderson
  2 siblings, 1 reply; 72+ messages in thread
From: Kaveh R. Ghazi @ 2002-12-24 11:07 UTC (permalink / raw)
  To: aoliva; +Cc: gcc-bugs, gcc-patches, gcc, libstdc++, oldham, ro

 > From: Alexandre Oliva <aoliva@redhat.com>
 > 
 > On Dec 22, 2002, Alexandre Oliva <aoliva@redhat.com> wrote:
 > 
 > > ? gcc/config/mips/_tilib.c
 > 
 > Here's the file that I had failed to cvs add before taking the diff:

I tried out this stuff on irix6.5 against the trunk.  I had to add
this minor patch for it to work there as opposed to 3.3-pre:

--- gcc-CVS20021223/gcc/config/mips/_tilib.c~	2002-12-23 17:11:54.306377600 -0500
+++ gcc-CVS20021223/gcc/config/mips/_tilib.c	2002-12-23 17:08:53.719848000 -0500
@@ -22,6 +22,8 @@ Boston, MA 02111-1307, USA.  */
 
 #include "tconfig.h"
 #include "tsystem.h"
+#include "coretypes.h"
+#include "tm.h"
 
 #ifndef LIBGCC2_WORDS_BIG_ENDIAN
 #define LIBGCC2_WORDS_BIG_ENDIAN WORDS_BIG_ENDIAN


Bootstrap went ok, however there were a couple of regressions in the
c-torture testsuite:

 > FAIL: gcc.c-torture/execute/va-arg-5.c execution,  -O0
 > FAIL: gcc.c-torture/execute/va-arg-5.c execution,  -O1
 > FAIL: gcc.c-torture/execute/va-arg-5.c execution,  -O2
 > FAIL: gcc.c-torture/execute/va-arg-5.c execution,  -O3 -fomit-frame-pointer
 > FAIL: gcc.c-torture/execute/va-arg-5.c execution,  -O3 -g
 > FAIL: gcc.c-torture/execute/va-arg-5.c execution,  -Os
 > FAIL: gcc.c-torture/execute/ieee/20011123-1.c execution,  -O0
 > FAIL: gcc.c-torture/execute/ieee/20011123-1.c execution,  -O1
 > FAIL: gcc.c-torture/execute/ieee/20011123-1.c execution,  -O2
 > FAIL: gcc.c-torture/execute/ieee/20011123-1.c execution,  -O3 -fomit-frame-pointer
 > FAIL: gcc.c-torture/execute/ieee/20011123-1.c execution,  -O3 -g
 > FAIL: gcc.c-torture/execute/ieee/20011123-1.c execution,  -Os

These tests both manipulate long doubles.

Also the original test 27_io/ostream_inserter_arith still fails.
However it looks as if it's in a different place, I'll check further
and provide details.

		--Kaveh
--
Kaveh R. Ghazi			ghazi@caip.rutgers.edu

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: Irix6 long doubles implemented wrong? (27_io/ostream_inserter_arith)
  2002-12-23  9:46         ` Alexandre Oliva
  2002-12-24 11:07           ` Kaveh R. Ghazi
@ 2002-12-24 18:15           ` Kaveh R. Ghazi
  2003-01-07 22:16             ` Richard Henderson
  2003-01-07 22:40           ` Richard Henderson
  2 siblings, 1 reply; 72+ messages in thread
From: Kaveh R. Ghazi @ 2002-12-24 18:15 UTC (permalink / raw)
  To: aoliva; +Cc: gcc-bugs, gcc-patches, gcc, libstdc++, oldham, ro


 > Also the original test 27_io/ostream_inserter_arith still fails.
 > However it looks as if it's in a different place, I'll check further
 > and provide details.

Scratch that, I think 27_io/ostream_inserter_arith is failing in the
same place.

On another issue, I'm also getting this new failure:

 > FAIL: 18_support/numeric_limits.cc execution test

This one is dying in the test:

 > test_denorm_min<long double>();

I think the value tested here is mistakenly indistinguishable from
zero.

		--Kaveh
--
Kaveh R. Ghazi			ghazi@caip.rutgers.edu

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: Irix6 long doubles implemented wrong?  (27_io/ostream_inserter_arith)
  2002-12-24 11:07           ` Kaveh R. Ghazi
@ 2002-12-25  8:04             ` Alexandre Oliva
  2002-12-26 13:48               ` Alexandre Oliva
  0 siblings, 1 reply; 72+ messages in thread
From: Alexandre Oliva @ 2002-12-25  8:04 UTC (permalink / raw)
  To: Kaveh R. Ghazi; +Cc: gcc-bugs, gcc-patches, gcc, libstdc++, oldham, ro

On Dec 24, 2002, "Kaveh R. Ghazi" <ghazi@caip.rutgers.edu> wrote:

> Bootstrap went ok, however there were a couple of regressions in the
> c-torture testsuite:

Thanks for catching these.  The fix for va-arg-5.c didn't make it to
the patch I posted, and the bootstrap obviously didn't catch the lack
of support for getting long double arguments in varargs lists.  Oops
:-) ieee/20011123-1.c may be a victim of the rounding issue I
mentioned in my earlier e-mail.  I'll investigate it and post a
revised patch.

It looks like it's time for me to get expect and dejagnu to build and
work on IRIX again... :-(

-- 
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

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: Irix6 long doubles implemented wrong?  (27_io/ostream_inserter_arith)
  2002-12-25  8:04             ` Alexandre Oliva
@ 2002-12-26 13:48               ` Alexandre Oliva
  2002-12-27  7:06                 ` Alexandre Oliva
  0 siblings, 1 reply; 72+ messages in thread
From: Alexandre Oliva @ 2002-12-26 13:48 UTC (permalink / raw)
  To: Kaveh R. Ghazi; +Cc: gcc-bugs, gcc-patches, gcc, libstdc++, oldham, ro

[-- Attachment #1: Type: text/plain, Size: 4020 bytes --]

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

> On Dec 24, 2002, "Kaveh R. Ghazi" <ghazi@caip.rutgers.edu> wrote:
>> Bootstrap went ok, however there were a couple of regressions in the
>> c-torture testsuite:

> Thanks for catching these.  The fix for va-arg-5.c didn't make it to
> the patch I posted, and the bootstrap obviously didn't catch the lack
> of support for getting long double arguments in varargs lists.  Oops
> :-)

> ieee/20011123-1.c may be a victim of the rounding issue I mentioned
> in my earlier e-mail.  I'll investigate it and post a revised patch.

It was actually a victim of __make_tp not having been declared in the
translation units that called it.  Eek.  So much for testing by
hand...

The libstdc++-v3 failures had to do with __LDBL_DENORM_MIN__ being set
incorrectly.  I ended up changing the real_format structure such that,
instead of assuming the same number of bits is available for the
mantissa of normalized and denormalized numbers and using a bool to
tell whether denorms are available, the number of denorm mantissa bits
is specified by itself, and we test whether it's zero to check whether
denorms are supported.  Then we can tell real.c that only 53 bits are
available in the denorm mantissa of a long double format that has 106
bits of mantissa for normals.  Hmm...  It's actually 52.  /me ponders
whether to adjust the new comment in real.h or all entries, and
figures he can't make his mind up :-)  Suggestions?

> It looks like it's time for me to get expect and dejagnu to build and
> work on IRIX again... :-(

Done.  Wasn't that hard, I just had to find the patches for expect to
build and work on IRIX that I had come up with a while ago.

Anyway, here's the patch for the 3.3 branch.  No failures in
libstdc++-v3 with it (and a number of XPASSes).  Full bootstrap and
test cycle still going, but I've verified by hand that
gcc.c-torture/execute/{va-arg-5.c,ieee/20011123-1.c} now pass, and I
doubt these further tweaks might have actually introduced any
regressions, so...  Ok to install in the 3.3 branch (plus Kaveh's
patch for gcc/config/mips/_tilib.c in mainline), if bootstrap and
regression testing completes?

Oh, I made another change that should speed things up a little bit
too: 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 means we never get excess
precision in the final result, even if the would-be-implicit-1 bit of
the least-significant double turns out to be zero and we have to look
for some other less-significant bit for it.  It sounded like a good
idea at first, but I've now realized it may mess up numeric models
that actually depend on exact knowledge of the number of mantissa
bits.  Not that this knowledge can actually be relied upon in case of
denorms...  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.

Another case that I haven't handled is that of numbers that are too
large to represent in a single double, but that could be represented
with the addition of the two doubles, using the maximum exponent on
both.  I figured this is probably not something that is meant to be
done, since the documentation of this format explicitly states that it
doesn't extend the range of exponents, when compared with double.

Also, there's no check that the sign of the least-significant double
is the same as that of the most-significant one, nor is there a check
that the LSD is NaN or +/-Inf.  I'm treating all these cases as
constraint violations in the long double format, that invoke undefined
behavior.  Hope that's ok.

Anyway, enough rambling.  Here's the patch.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: gcc-mips-tfmode-emul-take3.patch --]
[-- Type: text/x-patch, Size: 51093 bytes --]

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_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.
	(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 26 Dec 2002 00:06:33 -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 26 Dec 2002 00:06:37 -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 26 Dec 2002 00:06:40 -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 26 Dec 2002 00:06:46 -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 26 Dec 2002 00:06:47 -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 26 Dec 2002 00:06:50 -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 26 Dec 2002 00:06:50 -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 26 Dec 2002 00:06:51 -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
   };
 \f
@@ -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
   };
 \f
@@ -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
   };
 \f
@@ -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 26 Dec 2002 00:06:52 -0000
@@ -118,6 +118,11 @@ struct real_format
   /* Size of the significand in digits of radix B.  */
   int p;
 
+  /* 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 26 Dec 2002 00:06:52 -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;
-}
 \f
 /* 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 26 Dec 2002 00:06:53 -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 26 Dec 2002 00:06:55 -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,76 @@ 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 (low < ((halffractype)1 << HALFFRACBITS))
+	 {
+	   low <<= 1;
+	   exp--;
+	 }
+
+       if (exp < -HALFFRACBITS)
+	 low = exp = sign = 0;
+       else if (exp < 0)
+	 {
+	   low >>= -exp;
+	   exp = 0;
+	 }
+
+       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 +405,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 +422,34 @@ 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);
+
+       low &= (((fractype)1) << HALFFRACBITS) - 1;
+       if (lowexp)
+	 low |= ((halffractype)1) << HALFFRACBITS;
+       fraction += ((fractype)low << (FRACBITS - HALFFRACBITS))
+				  >> (exp - lowexp);
+     }
+ }
+# 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 +517,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 +701,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 +750,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;
@@ -725,7 +815,9 @@ _fpmul_parts ( fp_number_type *  a,
 
   tmp->normal_exp = a->normal_exp + b->normal_exp;
   tmp->sign = a->sign != b->sign;
-#ifdef FLOAT
+#ifdef TFLOAT
+  tmp->normal_exp += 6;		/* ??????????????? */
+#elif defined FLOAT
   tmp->normal_exp += 2;		/* ??????????????? */
 #else
   tmp->normal_exp += 4;		/* ??????????????? */
@@ -803,7 +895,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 +1005,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 +1091,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 +1113,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 +1134,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 +1155,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 +1176,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 +1196,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 +1217,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 +1240,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 +1258,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 +1286,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 +1296,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 +1313,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 +1328,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 +1356,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 +1396,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 +1452,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 +1509,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 26 Dec 2002 00:06:55 -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 26 Dec 2002 00:06:55 -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 26 Dec 2002 00:07:02 -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)
@@ -5007,7 +5011,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 +5372,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 +5463,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 +8283,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 26 Dec 2002 00:07:05 -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 26 Dec 2002 00:07:05 -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

[-- Attachment #3: Type: text/plain, Size: 289 bytes --]


-- 
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

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: Irix6 long doubles implemented wrong?  (27_io/ostream_inserter_arith)
  2002-12-26 13:48               ` Alexandre Oliva
@ 2002-12-27  7:06                 ` Alexandre Oliva
  2002-12-29  0:22                   ` Kaveh R. Ghazi
  2003-01-07 22:57                   ` Richard Henderson
  0 siblings, 2 replies; 72+ messages in thread
From: Alexandre Oliva @ 2002-12-27  7:06 UTC (permalink / raw)
  To: Kaveh R. Ghazi; +Cc: gcc-bugs, gcc-patches, gcc, libstdc++, oldham, ro

[-- Attachment #1: Type: text/plain, Size: 1519 bytes --]

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?


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: gcc-mips-tfmode-emul-take4.patch --]
[-- Type: text/x-patch, Size: 52593 bytes --]

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
   };
 \f
@@ -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
   };
 \f
@@ -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
   };
 \f
@@ -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;
-}
 \f
 /* 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

[-- Attachment #3: Type: text/plain, Size: 289 bytes --]


-- 
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

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: Irix6 long doubles implemented wrong?  (27_io/ostream_inserter_arith)
  2002-12-27  7:06                 ` Alexandre Oliva
@ 2002-12-29  0:22                   ` Kaveh R. Ghazi
  2002-12-29  6:06                     ` Alexandre Oliva
  2003-01-07 22:57                   ` Richard Henderson
  1 sibling, 1 reply; 72+ messages in thread
From: Kaveh R. Ghazi @ 2002-12-29  0:22 UTC (permalink / raw)
  To: aoliva; +Cc: gcc-bugs, gcc-patches, gcc, libstdc++, oldham, ro

 > From: Alexandre Oliva <aoliva@redhat.com>
 > 
 > 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.
 > 	[...]


Success!  This one worked for me w/3.3, no regressions and the
original 27_io/ostream_inserter_arith now passes.

	Thanks a bunch Alexandre :-)

		--Kaveh
--
Kaveh R. Ghazi			ghazi@caip.rutgers.edu

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: Irix6 long doubles implemented wrong?  (27_io/ostream_inserter_arith)
  2002-12-29  0:22                   ` Kaveh R. Ghazi
@ 2002-12-29  6:06                     ` Alexandre Oliva
  0 siblings, 0 replies; 72+ messages in thread
From: Alexandre Oliva @ 2002-12-29  6:06 UTC (permalink / raw)
  To: Kaveh R. Ghazi; +Cc: gcc-bugs, gcc-patches, gcc, libstdc++, oldham, ro

On Dec 29, 2002, "Kaveh R. Ghazi" <ghazi@caip.rutgers.edu> wrote:

>> From: Alexandre Oliva <aoliva@redhat.com>
>> 
>> 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.
>> [...]

> Success!  This one worked for me w/3.3, no regressions and the
> original 27_io/ostream_inserter_arith now passes.

Yay!  I got such results too, so I think we're safe here.  Now, does
anyone with global write privileges care to review this?

> 	Thanks a bunch Alexandre :-)

And thank you for all the testing!  It helped very much!

-- 
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

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: Irix6 long doubles implemented wrong? (27_io/ostream_inserter_arith)
  2002-12-24 18:15           ` Kaveh R. Ghazi
@ 2003-01-07 22:16             ` Richard Henderson
  0 siblings, 0 replies; 72+ messages in thread
From: Richard Henderson @ 2003-01-07 22:16 UTC (permalink / raw)
  To: Kaveh R. Ghazi; +Cc: aoliva, gcc-bugs, gcc-patches, gcc, libstdc++, oldham, ro

On Tue, Dec 24, 2002 at 02:07:19PM -0500, Kaveh R. Ghazi wrote:
>  > test_denorm_min<long double>();
> 
> I think the value tested here is mistakenly indistinguishable from
> zero.

Correct.  The double-double format doesn't support denormals
in an LIA-1 conformant way.


r~

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: Irix6 long doubles implemented wrong?  (27_io/ostream_inserter_arith)
  2002-12-23  9:46         ` Alexandre Oliva
  2002-12-24 11:07           ` Kaveh R. Ghazi
  2002-12-24 18:15           ` Kaveh R. Ghazi
@ 2003-01-07 22:40           ` Richard Henderson
  2003-01-08 18:04             ` Alexandre Oliva
  2 siblings, 1 reply; 72+ messages in thread
From: Richard Henderson @ 2003-01-07 22:40 UTC (permalink / raw)
  To: Alexandre Oliva
  Cc: Kaveh R. Ghazi, gcc-patches, gcc-bugs, gcc, libstdc++, oldham, ro

On Mon, Dec 23, 2002 at 02:12:55PM -0200, Alexandre Oliva wrote:
> > ? gcc/config/mips/_tilib.c

Why don't these routines come from libgcc2.c?


r~

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: Irix6 long doubles implemented wrong?  (27_io/ostream_inserter_arith)
  2002-12-27  7:06                 ` Alexandre Oliva
  2002-12-29  0:22                   ` Kaveh R. Ghazi
@ 2003-01-07 22:57                   ` Richard Henderson
  2003-01-08 18:16                     ` Alexandre Oliva
                                       ` (9 more replies)
  1 sibling, 10 replies; 72+ messages in thread
From: Richard Henderson @ 2003-01-07 22:57 UTC (permalink / raw)
  To: Alexandre Oliva
  Cc: Kaveh R. Ghazi, gcc-bugs, gcc-patches, gcc, libstdc++, oldham, ro

This should have been split into several smaller patches.

On Fri, Dec 27, 2002 at 11:47:15AM -0200, Alexandre Oliva wrote:
> 	* 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.

Ok.

> 	* 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.

Ok, I guess.

I'd kinda prefer that we use different names for the routines
than __addtf etc for the IBM format.  This would allow the
IBM double-double format and the IEEE quad format routines to
co-exist on one platform, which would allow non-Irix to use a
more sensible format unambiguously.

I won't insist on this though.

> 	* print-rtl.c (print_rtx): Don't print MEM details in
> 	GENERATOR_FILEs.

Ok.

> 	* rtl.c (get_mode_alignment): Moved to...
> 	* stor-layout.c: ... here.

Ok.

> 	* calls.c (emit_library_call_value_1): Handle return values
> 	in a PARALLEL.

Ok.  Yet another clue that these routines should be removed,
and replaced with the generic call functions.

> 	* expr.c (emit_group_store): Initialize dst with CONST0_RTX
> 	for the appropriate mode.

Ok.

> 	* optabs.c (expand_binop) <add, sub>: Return xtarget if we haven't
> 	been able to move the result to target.

Ok, I guess.  How does this come up?

> 	* 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.

This one's sticky.  Strictly speaking, the double-double format
isn't LIA-1 compliant (too few denormal bits), and so libstdc++
ought to be setting denorm_min to zero.  On the other hand, I
can see that this value might still be useful for some people.

Run it by the libstdc++ language lawyers.



r~

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: Irix6 long doubles implemented wrong?  (27_io/ostream_inserter_arith)
  2003-01-07 22:40           ` Richard Henderson
@ 2003-01-08 18:04             ` Alexandre Oliva
  2003-01-08 22:29               ` Richard Henderson
  0 siblings, 1 reply; 72+ messages in thread
From: Alexandre Oliva @ 2003-01-08 18:04 UTC (permalink / raw)
  To: Richard Henderson
  Cc: Kaveh R. Ghazi, gcc-patches, gcc-bugs, gcc, libstdc++, oldham, ro

On Jan  7, 2003, Richard Henderson <rth@redhat.com> wrote:

> On Mon, Dec 23, 2002 at 02:12:55PM -0200, Alexandre Oliva wrote:
>> > ? gcc/config/mips/_tilib.c

> Why don't these routines come from libgcc2.c?

I didn't feel like implementing all of TImode emulation in libgcc.  We
don't fully support TImode, only as little as needed to get the TFmode
emulation to compile.  It could be folded into libgcc2, for sure.
Should it?

-- 
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

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: Irix6 long doubles implemented wrong?  (27_io/ostream_inserter_arith)
  2003-01-07 22:57                   ` Richard Henderson
@ 2003-01-08 18:16                     ` Alexandre Oliva
  2003-01-08 22:19                       ` Richard Henderson
  2003-01-10  1:18                     ` Alexandre Oliva
                                       ` (8 subsequent siblings)
  9 siblings, 1 reply; 72+ messages in thread
From: Alexandre Oliva @ 2003-01-08 18:16 UTC (permalink / raw)
  To: Richard Henderson
  Cc: Kaveh R. Ghazi, gcc-bugs, gcc-patches, gcc, libstdc++, oldham, ro

On Jan  7, 2003, Richard Henderson <rth@redhat.com> wrote:

>> * 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.

> This one's sticky.  Strictly speaking, the double-double format
> isn't LIA-1 compliant (too few denormal bits)

I've no idea of what LIA-1 is, but it does have as many denormal bits
as normal bits, it's just that the minimum exponent for a denormal is
higher than that of a plain doubles, since denormals start with the
higher double still being normal.

-- 
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

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: Irix6 long doubles implemented wrong?  (27_io/ostream_inserter_arith)
  2003-01-08 18:16                     ` Alexandre Oliva
@ 2003-01-08 22:19                       ` Richard Henderson
  2003-01-09  9:29                         ` Alexandre Oliva
  0 siblings, 1 reply; 72+ messages in thread
From: Richard Henderson @ 2003-01-08 22:19 UTC (permalink / raw)
  To: Alexandre Oliva
  Cc: Kaveh R. Ghazi, gcc-bugs, gcc-patches, gcc, libstdc++, oldham, ro

On Wed, Jan 08, 2003 at 03:17:49PM -0200, Alexandre Oliva wrote:
> I've no idea of what LIA-1 is, but it does have as many denormal bits
> as normal bits, it's just that the minimum exponent for a denormal is
> higher than that of a plain doubles, since denormals start with the
> higher double still being normal.

Huh?  No it doesn't.  The minimum normalized double-double is
{ DBL_MIN_FLT, 0 }.


r~

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: Irix6 long doubles implemented wrong?  (27_io/ostream_inserter_arith)
  2003-01-08 18:04             ` Alexandre Oliva
@ 2003-01-08 22:29               ` Richard Henderson
  2003-01-08 22:46                 ` Zack Weinberg
  2003-01-09  7:27                 ` Alexandre Oliva
  0 siblings, 2 replies; 72+ messages in thread
From: Richard Henderson @ 2003-01-08 22:29 UTC (permalink / raw)
  To: Alexandre Oliva
  Cc: Kaveh R. Ghazi, gcc-patches, gcc-bugs, gcc, libstdc++, oldham, ro

On Wed, Jan 08, 2003 at 03:12:52PM -0200, Alexandre Oliva wrote:
> I didn't feel like implementing all of TImode emulation in libgcc.  We
> don't fully support TImode, only as little as needed to get the TFmode
> emulation to compile.  It could be folded into libgcc2, for sure.
> Should it?

Ug.  No.  I didn't realize this was TImode support for 32-bit.

Ideally you wouldn't need TImode at all.  I realize it probably
made things easier with the existing fp-bit.c.

Blah.

I suggest that these routines _not_ be exported from libgcc.so.
They only exist to support the TFmode bits.



r~

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: Irix6 long doubles implemented wrong?  (27_io/ostream_inserter_arith)
  2003-01-08 22:29               ` Richard Henderson
@ 2003-01-08 22:46                 ` Zack Weinberg
  2003-01-08 23:13                   ` Richard Henderson
  2003-01-09  7:27                 ` Alexandre Oliva
  1 sibling, 1 reply; 72+ messages in thread
From: Zack Weinberg @ 2003-01-08 22:46 UTC (permalink / raw)
  To: Richard Henderson
  Cc: Alexandre Oliva, Kaveh R. Ghazi, gcc-patches, gcc-bugs, gcc,
	libstdc++,
	oldham, ro

Richard Henderson <rth@redhat.com> writes:

> Ideally you wouldn't need TImode at all.  I realize it probably
> made things easier with the existing fp-bit.c.

Maybe this is a good excuse to dust off Teje's ieeelib.c?

zw

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: Irix6 long doubles implemented wrong? (27_io/ostream_inserter_arith)
  2003-01-08 22:46                 ` Zack Weinberg
@ 2003-01-08 23:13                   ` Richard Henderson
  0 siblings, 0 replies; 72+ messages in thread
From: Richard Henderson @ 2003-01-08 23:13 UTC (permalink / raw)
  To: Zack Weinberg
  Cc: Alexandre Oliva, Kaveh R. Ghazi, gcc-patches, gcc-bugs, gcc,
	libstdc++,
	oldham, ro

On Wed, Jan 08, 2003 at 02:18:50PM -0800, Zack Weinberg wrote:
> Maybe this is a good excuse to dust off Teje's ieeelib.c?

Either that or copy the code from glibc that Jakub and I worked on.



r~

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: Irix6 long doubles implemented wrong?  (27_io/ostream_inserter_arith)
  2003-01-08 22:29               ` Richard Henderson
  2003-01-08 22:46                 ` Zack Weinberg
@ 2003-01-09  7:27                 ` Alexandre Oliva
  1 sibling, 0 replies; 72+ messages in thread
From: Alexandre Oliva @ 2003-01-09  7:27 UTC (permalink / raw)
  To: Richard Henderson
  Cc: Kaveh R. Ghazi, gcc-patches, gcc-bugs, gcc, libstdc++, oldham, ro

On Jan  8, 2003, Richard Henderson <rth@redhat.com> wrote:

> I suggest that these routines _not_ be exported from libgcc.so.
> They only exist to support the TFmode bits.

Right.  I thought the default was to not export.  Isn't it?

-- 
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

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: Irix6 long doubles implemented wrong?  (27_io/ostream_inserter_arith)
  2003-01-08 22:19                       ` Richard Henderson
@ 2003-01-09  9:29                         ` Alexandre Oliva
  2003-01-09  9:38                           ` Alexandre Oliva
  0 siblings, 1 reply; 72+ messages in thread
From: Alexandre Oliva @ 2003-01-09  9:29 UTC (permalink / raw)
  To: Richard Henderson
  Cc: Kaveh R. Ghazi, gcc-bugs, gcc-patches, gcc, libstdc++, oldham, ro

On Jan  8, 2003, Richard Henderson <rth@redhat.com> wrote:

> On Wed, Jan 08, 2003 at 03:17:49PM -0200, Alexandre Oliva wrote:
>> I've no idea of what LIA-1 is, but it does have as many denormal bits
>> as normal bits, it's just that the minimum exponent for a denormal is
>> higher than that of a plain doubles, since denormals start with the
>> higher double still being normal.

> Huh?  No it doesn't.  The minimum normalized double-double is
> { DBL_MIN_FLT, 0 }.

Nevermind, I was thinking having a denormal in the lower double would
make the whole thing denormal, but in this case the lower double
definitely isn't denormal.

Anyway, without this hunk, we get an incorrect DENORM_MIN, and tests
fail.  DENORM_MIN isn't as low as MIN_FLT / 2**106, and that's the
problem.  This was the cleanest way I found to introduce the
possibility of having fewer denorm bits than mantissa bits, which is
exactly the case of this FP format.

Any better suggestions on how to accomplish this?  I think claiming we
don't have denormals is not the right answer either.

-- 
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

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: Irix6 long doubles implemented wrong?  (27_io/ostream_inserter_arith)
  2003-01-09  9:29                         ` Alexandre Oliva
@ 2003-01-09  9:38                           ` Alexandre Oliva
  0 siblings, 0 replies; 72+ messages in thread
From: Alexandre Oliva @ 2003-01-09  9:38 UTC (permalink / raw)
  To: Richard Henderson
  Cc: Kaveh R. Ghazi, gcc-bugs, gcc-patches, gcc, libstdc++, oldham, ro

On Jan  9, 2003, Alexandre Oliva <aoliva@redhat.com> wrote:

> On Jan  8, 2003, Richard Henderson <rth@redhat.com> wrote:
>> On Wed, Jan 08, 2003 at 03:17:49PM -0200, Alexandre Oliva wrote:
>>> I've no idea of what LIA-1 is, but it does have as many denormal bits
>>> as normal bits, it's just that the minimum exponent for a denormal is
>>> higher than that of a plain doubles, since denormals start with the
>>> higher double still being normal.

>> Huh?  No it doesn't.  The minimum normalized double-double is
>> { DBL_MIN_FLT, 0 }.

> Nevermind, I was thinking having a denormal in the lower double would
> make the whole thing denormal, but in this case the lower double
> definitely isn't denormal.

On third thought :-), it actually is a denormal, not in the double
representation, but in the notion that implies that denormals don't
have as much precision as normals.  Even though there is an implicit
one in the representation of the first double, if you represented the
mantissa as a sequence of 106 bits, you'd get this implicit one within
the denormal range.  The fact that you can represent it as a normal is
just an artifact of the long double representation.  Well, not really,
since the exponent range still enables you to represent it as normal,
but it really depends on which aspects of denormals matter.  My
thought is that loss of mantissa bits is more important than whether
there is an implied one next to the MSB of the mantissa, so I'm now
trying to model that.  This means LDBL_MIN_FLT should be bumped up to
represent this fact too, but I suspect this would trigger other sorts
of problems, so...  There's no Right Thing (TM) to do...

Darn, who came up with this long double representation, and why? :-(

-- 
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

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: Irix6 long doubles implemented wrong?  (27_io/ostream_inserter_arith)
  2003-01-07 22:57                   ` Richard Henderson
  2003-01-08 18:16                     ` Alexandre Oliva
@ 2003-01-10  1:18                     ` Alexandre Oliva
  2003-01-10  2:29                       ` Richard Henderson
  2003-01-10  1:37                     ` Alexandre Oliva
                                       ` (7 subsequent siblings)
  9 siblings, 1 reply; 72+ messages in thread
From: Alexandre Oliva @ 2003-01-10  1:18 UTC (permalink / raw)
  To: Richard Henderson
  Cc: Kaveh R. Ghazi, gcc-bugs, gcc-patches, gcc, libstdc++, oldham, ro

On Jan  7, 2003, Richard Henderson <rth@redhat.com> wrote:

>> * 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.

> This one's sticky.  Strictly speaking, the double-double format
> isn't LIA-1 compliant (too few denormal bits), and so libstdc++
> ought to be setting denorm_min to zero.  On the other hand, I
> can see that this value might still be useful for some people.

> Run it by the libstdc++ language lawyers.

I've just gone through the C++ Standard's numeric_limits definitions
and the C99's float.h specification, and I couldn't find any reason
to not use the definitions the way I've introduced them.  The fact
that they get the libstdc++-v3 testsuite to pass in cases it didn't
before seems to be a good indication that it is good enough.

Ok to check it all in?

-- 
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

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: Irix6 long doubles implemented wrong?  (27_io/ostream_inserter_arith)
  2003-01-07 22:57                   ` Richard Henderson
  2003-01-08 18:16                     ` Alexandre Oliva
  2003-01-10  1:18                     ` Alexandre Oliva
@ 2003-01-10  1:37                     ` Alexandre Oliva
  2003-01-26 10:07                     ` Alexandre Oliva
                                       ` (6 subsequent siblings)
  9 siblings, 0 replies; 72+ messages in thread
From: Alexandre Oliva @ 2003-01-10  1:37 UTC (permalink / raw)
  To: Richard Henderson
  Cc: Kaveh R. Ghazi, gcc-bugs, gcc-patches, gcc, libstdc++, oldham, ro

On Jan  7, 2003, Richard Henderson <rth@redhat.com> wrote:

>> * optabs.c (expand_binop) <add, sub>: Return xtarget if we haven't
>> been able to move the result to target.

> Ok, I guess.  How does this come up?

There's no movti insn, so the test that decides whether it's possible
to move the result to the final location fails and we omit the move at
that point.  It ends up being emitted as a multi-insn move sequence
upstream, as long as we return the correct location of the result.

FWIW, I had movti patterns in my patch at some point, that split into
pairs of DI moves, but it proved to be pointless, so I took it out.

-- 
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

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: Irix6 long doubles implemented wrong?  (27_io/ostream_inserter_arith)
  2003-01-10  1:18                     ` Alexandre Oliva
@ 2003-01-10  2:29                       ` Richard Henderson
  2003-01-19 21:02                         ` Kaveh R. Ghazi
  0 siblings, 1 reply; 72+ messages in thread
From: Richard Henderson @ 2003-01-10  2:29 UTC (permalink / raw)
  To: Alexandre Oliva
  Cc: Kaveh R. Ghazi, gcc-bugs, gcc-patches, gcc, libstdc++, oldham, ro

On Thu, Jan 09, 2003 at 09:53:55PM -0200, Alexandre Oliva wrote:
> I've just gone through the C++ Standard's numeric_limits definitions
> and the C99's float.h specification, and I couldn't find any reason
> to not use the definitions the way I've introduced them. 

Irritatingly, I think my copy of LIA-1 is at home on a machine
that's powered off.  But C++ references it, so I think you have
to look there and not in the C++ standard directly.

What I remember is that min denormal must be 2**-p below the
min normalized number.  Which isn't satisfied in this case.

> The fact
> that they get the libstdc++-v3 testsuite to pass in cases it didn't
> before seems to be a good indication that it is good enough.

Feh.  I wrote those test cases.  Don't take them as definitive.


r~

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: Irix6 long doubles implemented wrong? (27_io/ostream_inserter_arith)
  2003-01-10  2:29                       ` Richard Henderson
@ 2003-01-19 21:02                         ` Kaveh R. Ghazi
  2003-01-19 22:15                           ` Alexandre Oliva
  0 siblings, 1 reply; 72+ messages in thread
From: Kaveh R. Ghazi @ 2003-01-19 21:02 UTC (permalink / raw)
  To: aoliva; +Cc: gcc-bugs, gcc-patches, gcc, ghazi, libstdc++, oldham, ro, rth


So, what happened to the irix6 long double patch?

		--Kaveh
--
Kaveh R. Ghazi			ghazi@caip.rutgers.edu

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: Irix6 long doubles implemented wrong? (27_io/ostream_inserter_arith)
  2003-01-19 21:02                         ` Kaveh R. Ghazi
@ 2003-01-19 22:15                           ` Alexandre Oliva
  2003-01-26 13:00                             ` Alexandre Oliva
  2003-01-26 15:20                             ` Alexandre Oliva
  0 siblings, 2 replies; 72+ messages in thread
From: Alexandre Oliva @ 2003-01-19 22:15 UTC (permalink / raw)
  To: Kaveh R. Ghazi; +Cc: gcc-bugs, gcc-patches, gcc, libstdc++, oldham, ro, rth

On Jan 19, 2003, "Kaveh R. Ghazi" <ghazi@caip.rutgers.edu> wrote:

> So, what happened to the irix6 long double patch?

It will require some changes, after all.

As per my reading of LIA (this morning, talk about coincidence :-),
the minimum normal exponent should be set such that all 107
significant bits are available (and it's 107, not 106, as I
implemented it) for normals.  This means we'll consider denormals even
numbers that have only the lower double as a denormal.  Which is in
line with one of the approaches I had suggested (not that it counts
much; I've probably enumerated all approaches that could possibly make
sense, and most that couldn't :-D

This conclusion was drawn based on the formal definition of the
normalized and denormalized sets, as well as the informal definitions
of normalized (those values of a floating point type F that provide
the full precision allowed by that type) and denormalized (those that
don't), regardless of the actual representation.  I believe this
settles it.  Now it just needs someone to implement these changes.
Unfortunately, the mips64-linux-gnu port I'd been working on, that
looked like would need IRIX compatibility in terms of floating point
format, ended up with a different format, so I no longer have a good
reason to put work time into finishing the patch.  I've been trying to
find spare time to do it in a voluntary basis, but spare time is
approaching non-existence from the negative range :-)

Anyway, if I had the time, I'd start by adding 53 to the minimum
exponent range in real.c and fp-bit.h, bumping up the mantissa size by
1 and reverting the denorm_p changes I made in real.c and c-common.c.
This would probably require some tweaks in the functions that convert
into and out of ibm_extended_format in real.c, such that the change in
the minimum exponent doesn't change the representation of any numbers,
and probably some similar fixes in fp-bit.c, for the same reason.
Would you like to give it a try?  Or would you rather my cobble up
some day a new version of the patch for you to try?  Please let me
know.

-- 
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

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: Irix6 long doubles implemented wrong?  (27_io/ostream_inserter_arith)
  2003-01-07 22:57                   ` Richard Henderson
                                       ` (2 preceding siblings ...)
  2003-01-10  1:37                     ` Alexandre Oliva
@ 2003-01-26 10:07                     ` Alexandre Oliva
  2003-01-26 10:42                     ` Alexandre Oliva
                                       ` (5 subsequent siblings)
  9 siblings, 0 replies; 72+ messages in thread
From: Alexandre Oliva @ 2003-01-26 10:07 UTC (permalink / raw)
  To: Richard Henderson
  Cc: Kaveh R. Ghazi, gcc-bugs, gcc-patches, gcc, libstdc++, oldham, ro

[-- Attachment #1: Type: text/plain, Size: 354 bytes --]

I'm going to check in the hunks that you've approved that make sense
by themselves, in both 3.3 branch and mainline, leaving out the
IRIX-specific hunks that still require some fixing.

On Jan  7, 2003, Richard Henderson <rth@redhat.com> wrote:

>> * print-rtl.c (print_rtx): Don't print MEM details in
>> GENERATOR_FILEs.

> Ok.

I'm checking this in.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: gcc-mips-tfmode-print-rtl.patch --]
[-- Type: text/x-patch, Size: 1072 bytes --]

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

	* print-rtl.c (print_rtx): Don't print MEM details in
	GENERATOR_FILEs.

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 26 Jan 2003 08:57:03 -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, 2003
    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)))
 	{

[-- Attachment #3: Type: text/plain, Size: 289 bytes --]


-- 
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

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: Irix6 long doubles implemented wrong?  (27_io/ostream_inserter_arith)
  2003-01-07 22:57                   ` Richard Henderson
                                       ` (3 preceding siblings ...)
  2003-01-26 10:07                     ` Alexandre Oliva
@ 2003-01-26 10:42                     ` Alexandre Oliva
  2003-01-26 10:45                     ` Alexandre Oliva
                                       ` (4 subsequent siblings)
  9 siblings, 0 replies; 72+ messages in thread
From: Alexandre Oliva @ 2003-01-26 10:42 UTC (permalink / raw)
  To: Richard Henderson
  Cc: Kaveh R. Ghazi, gcc-bugs, gcc-patches, gcc, libstdc++, oldham, ro

[-- Attachment #1: Type: text/plain, Size: 156 bytes --]

On Jan  7, 2003, Richard Henderson <rth@redhat.com> wrote:

>> * rtl.c (get_mode_alignment): Moved to...
>> * stor-layout.c: ... here.

> Ok.

Checked in.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: gcc-mips-tfmode-get-mode-align.patch --]
[-- Type: text/x-patch, Size: 2809 bytes --]

Index: gcc/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>
	* rtl.c (get_mode_alignment): Moved to...
	* stor-layout.c: ... here.

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 26 Jan 2003 09:01:24 -0000
@@ -1,6 +1,6 @@
 /* RTL utility routines.
-   Copyright (C) 1987, 1988, 1991, 1994, 1997, 1998, 1999, 2000, 2001, 2002
-   Free Software Foundation, Inc.
+   Copyright (C) 1987, 1988, 1991, 1994, 1997, 1998, 1999, 2000, 2001, 2002,
+   2003 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -395,29 +395,6 @@ shallow_copy_rtx (orig)
 	  sizeof (struct rtx_def) + sizeof (rtunion) * (n - 1));
 
   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;
 }
 \f
 /* This is 1 until after the rtl generation pass.  */
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 26 Jan 2003 09:01:25 -0000
@@ -1,6 +1,6 @@
 /* C-compiler utilities for types and variables storage layout
    Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1996, 1998,
-   1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -296,6 +296,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.

[-- Attachment #3: Type: text/plain, Size: 289 bytes --]


-- 
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

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: Irix6 long doubles implemented wrong?  (27_io/ostream_inserter_arith)
  2003-01-07 22:57                   ` Richard Henderson
                                       ` (4 preceding siblings ...)
  2003-01-26 10:42                     ` Alexandre Oliva
@ 2003-01-26 10:45                     ` Alexandre Oliva
  2003-01-26 10:53                     ` Alexandre Oliva
                                       ` (3 subsequent siblings)
  9 siblings, 0 replies; 72+ messages in thread
From: Alexandre Oliva @ 2003-01-26 10:45 UTC (permalink / raw)
  To: Richard Henderson
  Cc: Kaveh R. Ghazi, gcc-bugs, gcc-patches, gcc, libstdc++, oldham, ro

[-- Attachment #1: Type: text/plain, Size: 165 bytes --]

On Jan  7, 2003, Richard Henderson <rth@redhat.com> wrote:

>> * calls.c (emit_library_call_value_1): Handle return values
>> in a PARALLEL.

> Ok.

Checking in...


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: gcc-mips-tfmode-calls.patch --]
[-- Type: text/x-patch, Size: 1866 bytes --]

Index: gcc/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>
	* calls.c (emit_library_call_value_1): Handle return values
	in a PARALLEL.

Index: gcc/calls.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/calls.c,v
retrieving revision 1.244.2.2
diff -u -p -r1.244.2.2 calls.c
--- gcc/calls.c 24 Jan 2003 23:15:23 -0000 1.244.2.2
+++ gcc/calls.c 26 Jan 2003 09:04:28 -0000
@@ -1,6 +1,6 @@
 /* Convert function calls to rtl insns, for GNU C compiler.
    Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998
-   1999, 2000, 2001 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -4142,7 +4142,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 ();
@@ -4151,9 +4151,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++)
@@ -4186,6 +4195,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);

[-- Attachment #3: Type: text/plain, Size: 289 bytes --]


-- 
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

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: Irix6 long doubles implemented wrong?  (27_io/ostream_inserter_arith)
  2003-01-07 22:57                   ` Richard Henderson
                                       ` (5 preceding siblings ...)
  2003-01-26 10:45                     ` Alexandre Oliva
@ 2003-01-26 10:53                     ` Alexandre Oliva
  2003-01-26 12:07                     ` Alexandre Oliva
                                       ` (2 subsequent siblings)
  9 siblings, 0 replies; 72+ messages in thread
From: Alexandre Oliva @ 2003-01-26 10:53 UTC (permalink / raw)
  To: Richard Henderson
  Cc: Kaveh R. Ghazi, gcc-bugs, gcc-patches, gcc, libstdc++, oldham, ro

[-- Attachment #1: Type: text/plain, Size: 176 bytes --]

On Jan  7, 2003, Richard Henderson <rth@redhat.com> wrote:

>> * expr.c (emit_group_store): Initialize dst with CONST0_RTX
>> for the appropriate mode.

> Ok.

Checking in...


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: gcc-mips-tfmode-expr.patch --]
[-- Type: text/x-patch, Size: 739 bytes --]

Index: gcc/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>
	* expr.c (emit_group_store): Initialize dst with CONST0_RTX
	for the appropriate mode.

Index: gcc/expr.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/expr.c,v
retrieving revision 1.498.2.2
diff -u -p -r1.498.2.2 expr.c
--- gcc/expr.c 11 Jan 2003 22:43:52 -0000 1.498.2.2
+++ gcc/expr.c 26 Jan 2003 09:08:05 -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.  */

[-- Attachment #3: Type: text/plain, Size: 289 bytes --]


-- 
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

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: Irix6 long doubles implemented wrong?  (27_io/ostream_inserter_arith)
  2003-01-07 22:57                   ` Richard Henderson
                                       ` (6 preceding siblings ...)
  2003-01-26 10:53                     ` Alexandre Oliva
@ 2003-01-26 12:07                     ` Alexandre Oliva
  2003-01-26 12:20                     ` Alexandre Oliva
  2003-01-26 12:50                     ` Alexandre Oliva
  9 siblings, 0 replies; 72+ messages in thread
From: Alexandre Oliva @ 2003-01-26 12:07 UTC (permalink / raw)
  To: Richard Henderson
  Cc: Kaveh R. Ghazi, gcc-bugs, gcc-patches, gcc, libstdc++, oldham, ro

[-- Attachment #1: Type: text/plain, Size: 196 bytes --]

On Jan  7, 2003, Richard Henderson <rth@redhat.com> wrote:

>> * optabs.c (expand_binop) <add, sub>: Return xtarget if we haven't
>> been able to move the result to target.

> Ok

Checking in...


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: gcc-mips-tfmode-optabs.patch --]
[-- Type: text/x-patch, Size: 964 bytes --]

Index: gcc/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>
	* optabs.c (expand_binop) <add, sub>: Return xtarget if we haven't
	been able to move the result to target.

Index: gcc/optabs.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/optabs.c,v
retrieving revision 1.153.2.1
diff -u -p -r1.153.2.1 optabs.c
--- gcc/optabs.c 9 Jan 2003 12:40:44 -0000 1.153.2.1
+++ gcc/optabs.c 26 Jan 2003 09:10:23 -0000
@@ -1,6 +1,6 @@
 /* Expand the basic unary and binary arithmetic operations, for GNU compiler.
    Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2003 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -1307,6 +1307,8 @@ expand_binop (mode, binoptab, op0, op1, 
 						   copy_rtx (xop0),
 						   copy_rtx (xop1)));
 	    }
+	  else
+	    target = xtarget;
 
 	  return target;
 	}

[-- Attachment #3: Type: text/plain, Size: 289 bytes --]


-- 
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

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: Irix6 long doubles implemented wrong?  (27_io/ostream_inserter_arith)
  2003-01-07 22:57                   ` Richard Henderson
                                       ` (7 preceding siblings ...)
  2003-01-26 12:07                     ` Alexandre Oliva
@ 2003-01-26 12:20                     ` Alexandre Oliva
  2003-01-26 12:50                     ` Alexandre Oliva
  9 siblings, 0 replies; 72+ messages in thread
From: Alexandre Oliva @ 2003-01-26 12:20 UTC (permalink / raw)
  To: Richard Henderson
  Cc: Kaveh R. Ghazi, gcc-bugs, gcc-patches, gcc, libstdc++, oldham, ro

[-- Attachment #1: Type: text/plain, Size: 387 bytes --]

On Jan  7, 2003, Richard Henderson <rth@redhat.com> wrote:

> On Fri, Dec 27, 2002 at 11:47:15AM -0200, Alexandre Oliva wrote:
>> * 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.

> Ok.

Checking in...


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: gcc-mips-tfmode-makefiles.patch --]
[-- Type: text/x-patch, Size: 3910 bytes --]

Index: gcc/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>
	* 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.

Index: gcc/Makefile.in
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Makefile.in,v
retrieving revision 1.958.2.2
diff -u -p -r1.958.2.2 Makefile.in
--- gcc/Makefile.in 9 Jan 2003 12:40:43 -0000 1.958.2.2
+++ gcc/Makefile.in 26 Jan 2003 09:14:44 -0000
@@ -798,12 +798,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.
@@ -1023,6 +1028,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)' \
@@ -1042,8 +1049,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/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 26 Jan 2003 09:14:44 -0000
@@ -1,6 +1,6 @@
 #!/bin/sh
 # Construct makefile for libgcc.
-#   Copyright (C) 2000, 2002 Free Software Foundation, Inc.
+#   Copyright (C) 2000, 2002, 2003 Free Software Foundation, Inc.
 #
 # This file is part of GCC.
 
@@ -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

[-- Attachment #3: Type: text/plain, Size: 289 bytes --]


-- 
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

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: Irix6 long doubles implemented wrong?  (27_io/ostream_inserter_arith)
  2003-01-07 22:57                   ` Richard Henderson
                                       ` (8 preceding siblings ...)
  2003-01-26 12:20                     ` Alexandre Oliva
@ 2003-01-26 12:50                     ` Alexandre Oliva
  9 siblings, 0 replies; 72+ messages in thread
From: Alexandre Oliva @ 2003-01-26 12:50 UTC (permalink / raw)
  To: Richard Henderson
  Cc: Kaveh R. Ghazi, gcc-bugs, gcc-patches, gcc, libstdc++, oldham, ro

[-- Attachment #1: Type: text/plain, Size: 1112 bytes --]

On Jan  7, 2003, Richard Henderson <rth@redhat.com> wrote:

>> * 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.

> Ok

I'm checking this in, leaving out the parts that support the IBM
extended format, that still need some tweaking.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: gcc-mips-tfmode-fp-bit.patch --]
[-- Type: text/x-patch, Size: 22550 bytes --]

Index: gcc/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>
	* config/fp-bit.h: Define macros for TFmode floating-point
	constants in IEEE quad TFmode type.  Declare functions according
	to L_ macros.
	(TMODES): Define if __LDBL_MANT_DIG__ is 113.
	(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 quad type.
	(_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.

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 26 Jan 2003 09:26:55 -0000
@@ -1,6 +1,6 @@
 /* This is a software floating point library which can be used
    for targets without hardware floating point. 
-   Copyright (C) 1994, 1995, 1996, 1997, 1998, 2000, 2001, 2002
+   Copyright (C) 1994, 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2003
    Free Software Foundation, Inc.
 
 This file is free software; you can redistribute it and/or modify it
@@ -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)
 {
@@ -322,18 +328,29 @@ pack_d ( fp_number_type *  src)
 #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 +364,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,7 +381,7 @@ 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);
+  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
@@ -427,7 +451,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 +635,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 +684,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 +747,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 +823,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 +933,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 +1019,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 +1041,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 +1062,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 +1083,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 +1104,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 +1124,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 +1145,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 +1168,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 +1186,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 +1214,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 +1224,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 +1241,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 +1256,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 +1284,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 +1324,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 +1380,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 +1437,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 26 Jan 2003 09:26:55 -0000
@@ -1,5 +1,5 @@
 /* Header file for fp-bit.c.  */
-/* Copyright (C) 2000
+/* Copyright (C) 2000, 2002, 2003
    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
+# 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,56 @@ 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
+
+#	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 +207,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 +222,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 +236,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 +278,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 +298,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 +316,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 +362,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 +401,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 +489,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 +503,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 */

[-- Attachment #3: Type: text/plain, Size: 289 bytes --]


-- 
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

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: Irix6 long doubles implemented wrong? (27_io/ostream_inserter_arith)
  2003-01-19 22:15                           ` Alexandre Oliva
@ 2003-01-26 13:00                             ` Alexandre Oliva
  2003-01-28 17:32                               ` Alexandre Oliva
  2003-01-26 15:20                             ` Alexandre Oliva
  1 sibling, 1 reply; 72+ messages in thread
From: Alexandre Oliva @ 2003-01-26 13:00 UTC (permalink / raw)
  To: Kaveh R. Ghazi; +Cc: gcc-bugs, gcc-patches, gcc, libstdc++, oldham, ro, rth

[-- Attachment #1: Type: text/plain, Size: 571 bytes --]

On Jan 19, 2003, Alexandre Oliva <aoliva@redhat.com> wrote:

> the minimum normal exponent should be set such that all 107
> significant bits are available (and it's 107, not 106, as I
> implemented it) for normals.

It can't possibly be 107.  IRIX must be doing something wrong in
setting LDBL_MANT_DIG to 107, since there are only 53 bits of
precision in each double, even if you count the implicit 1s.  Besides,
the emulation I implemented worked correctly down to the least
significant bits with IRIX's printf, so I'm checking these bits in
too, per rth's approval.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: gcc-mips-tfmode-fp-bit-ibmext.patch --]
[-- Type: text/x-patch, Size: 4851 bytes --]

Index: gcc/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>
	* fp-bit.h: Define macros for TFmode floating-point constants
	in IBM-extended TFmode types.
	(TMODES): Define if __LDBL_MANT_DIG__ has the newly-supported
	widths.
	* config/fp-bit.c (pack_d, unpack_d): Support IBM-extended
	TFmode type.

Index: gcc/config/fp-bit.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/fp-bit.c,v
retrieving revision 1.36.4.1
diff -u -p -r1.36.4.1 fp-bit.c
--- gcc/config/fp-bit.c 26 Jan 2003 09:30:38 -0000 1.36.4.1
+++ gcc/config/fp-bit.c 26 Jan 2003 10:01:20 -0000
@@ -322,9 +322,66 @@ 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)
@@ -381,9 +438,42 @@ unpack_d (FLO_union_type * src, fp_numbe
   exp = src->bits.exp;
   sign = src->bits.sign;
 #else
+# 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;
Index: gcc/config/fp-bit.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/fp-bit.h,v
retrieving revision 1.7.18.1
diff -u -p -r1.7.18.1 fp-bit.h
--- gcc/config/fp-bit.h 26 Jan 2003 09:30:38 -0000 1.7.18.1
+++ gcc/config/fp-bit.h 26 Jan 2003 10:01:20 -0000
@@ -87,7 +87,7 @@ Boston, MA 02111-1307, USA.  */
 #endif
 #endif /* ! FINE_GRAINED_LIBRARIES */
 
-#if __LDBL_MANT_DIG__ == 113
+#if __LDBL_MANT_DIG__ == 113 || __LDBL_MANT_DIG__ == 106
 # define TMODES
 #endif
 
@@ -150,6 +150,18 @@ typedef unsigned int UTItype __attribute
 #	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

[-- Attachment #3: Type: text/plain, Size: 289 bytes --]


-- 
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

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: Irix6 long doubles implemented wrong? (27_io/ostream_inserter_arith)
  2003-01-19 22:15                           ` Alexandre Oliva
  2003-01-26 13:00                             ` Alexandre Oliva
@ 2003-01-26 15:20                             ` Alexandre Oliva
  2003-01-26 16:14                               ` Alexandre Oliva
  1 sibling, 1 reply; 72+ messages in thread
From: Alexandre Oliva @ 2003-01-26 15:20 UTC (permalink / raw)
  To: Kaveh R. Ghazi; +Cc: gcc-bugs, gcc-patches, gcc, libstdc++, oldham, ro, rth

[-- Attachment #1: Type: text/plain, Size: 1693 bytes --]

On Jan 19, 2003, Alexandre Oliva <aoliva@redhat.com> wrote:

> This means we'll consider denormals even numbers that have only the
> lower double as a denormal.  Which is in line with one of the
> approaches I had suggested (not that it counts much; I've probably
> enumerated all approaches that could possibly make sense, and most
> that couldn't :-D

> This conclusion was drawn based on the formal definition of the
> normalized and denormalized sets, as well as the informal definitions
> of normalized (those values of a floating point type F that provide
> the full precision allowed by that type) and denormalized (those that
> don't), regardless of the actual representation.  I believe this
> settles it.

> Anyway, if I had the time, I'd start by adding 53 to the minimum
> exponent range in real.c

This patch implements this change.  I've already done some testing on
IRIX, and it appears to give correct results, but bootstrap and
libstdc++ testing is still running.  Ok to install in 3.3 and mainline
if it completes?

> and fp-bit.h

There's no such thing there.  The code already works as expected.

> bumping up the mantissa size by 1

Wrong, as explained in another e-mail.

> and reverting the denorm_p changes I made in real.c and c-common.c.

Or rather not even putting them in.

> This would probably require some tweaks in the functions that convert
> into and out of ibm_extended_format in real.c,

It doesn't, they're simple enough that the change in the minimum
exponent doesn't affect them at all.

> and probably some similar fixes in fp-bit.c

No changes needed there either.  It's not really concerned about where
the boundary between normals and denormals is.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: gcc-mips-tfmode-ibmext-minexp.patch --]
[-- Type: text/x-patch, Size: 545 bytes --]

Index: gcc/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>
	* real.c (ibm_extended_format): Add 53 to minimum exponent.

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 26 Jan 2003 10:47:06 -0000
@@ -3292,7 +3292,7 @@ const struct real_format ibm_extended_fo
     2,
     1,
     53 + 53,
-    -1021,
+    -1021 + 53,
     1024,
     true,
     true,

[-- Attachment #3: Type: text/plain, Size: 289 bytes --]


-- 
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

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: Irix6 long doubles implemented wrong? (27_io/ostream_inserter_arith)
  2003-01-26 15:20                             ` Alexandre Oliva
@ 2003-01-26 16:14                               ` Alexandre Oliva
  2003-01-26 18:40                                 ` Kaveh R. Ghazi
                                                   ` (2 more replies)
  0 siblings, 3 replies; 72+ messages in thread
From: Alexandre Oliva @ 2003-01-26 16:14 UTC (permalink / raw)
  To: Kaveh R. Ghazi; +Cc: gcc-bugs, gcc-patches, gcc, libstdc++, oldham, ro, rth

[-- Attachment #1: Type: text/plain, Size: 435 bytes --]

On Jan 26, 2003, Alexandre Oliva <aoliva@redhat.com> wrote:

> 	* real.c (ibm_extended_format): Add 53 to minimum exponent.

Turned out this got encode_ibm_extended very confused when presented
with denormals, not only numbers that had to be represented as
denormal doubles, but also those that could still use a normal double
for the upper part.  This new patch fixes it, and actually passes the
numeric_limits test.  Ok to install?


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: gcc-mips-tfmode-ibmext-minexp.patch --]
[-- Type: text/x-patch, Size: 1748 bytes --]

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

	* real.c (ibm_extended_format): Add 53 to minimum exponent.
	(encode_ibm_extended): Adjust.

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 26 Jan 2003 12:43:40 -0000
@@ -1,6 +1,6 @@
 /* real.c - software floating point emulation.
    Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2002 Free Software Foundation, Inc.
+   1999, 2000, 2002, 2003 Free Software Foundation, Inc.
    Contributed by Stephen L. Moshier (moshier@world.std.com).
    Re-written by Richard Henderson  <rth@redhat.com>
 
@@ -3254,8 +3254,23 @@ encode_ibm_extended (fmt, buf, r)
       u = *r;
       clear_significand_below (&u, SIGNIFICAND_BITS - 53);
 
-      /* v = remainder containing additional 53 bits of significand.  */
-      do_add (&v, r, &u, 1);
+      normalize (&u);
+      /* If the upper double is zero, we have a denormal double, so
+	 move it to the first double and leave the second as zero.  */
+      if (u.class == rvc_zero)
+	{
+	  v = u;
+	  u = *r;
+	  normalize (&u);
+	}
+      else
+	{
+	  /* v = remainder containing additional 53 bits of significand.  */
+	  do_add (&v, r, &u, 1);
+	  round_for_format (&ieee_double_format, &v);
+	}
+
+      round_for_format (&ieee_double_format, &u);
 
       encode_ieee_double (&ieee_double_format, &buf[0], &u);
       encode_ieee_double (&ieee_double_format, &buf[2], &v);
@@ -3292,7 +3307,7 @@ const struct real_format ibm_extended_fo
     2,
     1,
     53 + 53,
-    -1021,
+    -1021 + 53,
     1024,
     true,
     true,

[-- Attachment #3: Type: text/plain, Size: 289 bytes --]


-- 
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

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: Irix6 long doubles implemented wrong? (27_io/ostream_inserter_arith)
  2003-01-26 16:14                               ` Alexandre Oliva
@ 2003-01-26 18:40                                 ` Kaveh R. Ghazi
  2003-01-26 21:24                                 ` Kaveh R. Ghazi
  2003-01-26 21:54                                 ` Richard Henderson
  2 siblings, 0 replies; 72+ messages in thread
From: Kaveh R. Ghazi @ 2003-01-26 18:40 UTC (permalink / raw)
  To: aoliva; +Cc: gcc-bugs, gcc-patches, gcc, libstdc++, oldham, ro, rth

 > From: Alexandre Oliva <aoliva@redhat.com>
 > 
 > On Jan 26, 2003, Alexandre Oliva <aoliva@redhat.com> wrote:
 > 
 > > 	* real.c (ibm_extended_format): Add 53 to minimum exponent.
 > 
 > Turned out this got encode_ibm_extended very confused when presented
 > with denormals, not only numbers that had to be represented as
 > denormal doubles, but also those that could still use a normal double
 > for the upper part.  This new patch fixes it, and actually passes the
 > numeric_limits test.  Ok to install?

Great Alexandre, thanks!

I'm going to try and test this on irix6.5.  I took a 3.3 checkout from
this morning plus the following three patches:

http://gcc.gnu.org/ml/gcc-patches/2003-01/msg02039.html
http://gcc.gnu.org/ml/gcc-patches/2003-01/msg02026.html
http://gcc.gnu.org/ml/gcc-patches/2003-01/msg02041.html

Is that the correct set?  (Results should be done tonight.)

		--Kaveh
--
Kaveh R. Ghazi			ghazi@caip.rutgers.edu

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: Irix6 long doubles implemented wrong? (27_io/ostream_inserter_arith)
  2003-01-26 16:14                               ` Alexandre Oliva
  2003-01-26 18:40                                 ` Kaveh R. Ghazi
@ 2003-01-26 21:24                                 ` Kaveh R. Ghazi
  2003-01-26 21:25                                   ` Alexandre Oliva
  2003-01-27  9:17                                   ` Kaveh R. Ghazi
  2003-01-26 21:54                                 ` Richard Henderson
  2 siblings, 2 replies; 72+ messages in thread
From: Kaveh R. Ghazi @ 2003-01-26 21:24 UTC (permalink / raw)
  To: aoliva; +Cc: gcc-bugs, gcc-patches, gcc, libstdc++, oldham, ro, rth

 > I'm going to try and test this on irix6.5.  I took a 3.3 checkout from
 > this morning plus the following three patches:
 > 
 > http://gcc.gnu.org/ml/gcc-patches/2003-01/msg02039.html
 > http://gcc.gnu.org/ml/gcc-patches/2003-01/msg02026.html
 > http://gcc.gnu.org/ml/gcc-patches/2003-01/msg02041.html
 > 
 > Is that the correct set?  (Results should be done tonight.)

Well that was a dismal failure.  It bootstrapped but I get 178
libstdc++-v3 execute errors and 18_support/numeric_limits.cc fails
compilation:

ld32: ERROR   33 : Unresolved text symbol "__gttf2" -- 1st referenced
by /var/tmp//cc40eXre.o.
        Use linker option -v to see when and which objects, archives
	and dsos are loaded.
ld32: ERROR   33 : Unresolved text symbol "__addtf3" -- 1st referenced
by /var/tmp//cc40eXre.o.
        Use linker option -v to see when and which objects, archives
	and dsos are loaded.
ld32: ERROR   33 : Unresolved text symbol "__eqtf2" -- 1st referenced
by /var/tmp//cc40eXre.o.
        Use linker option -v to see when and which objects, archives
	and dsos are loaded.
ld32: ERROR   33 : Unresolved text symbol "__netf2" -- 1st referenced
by /var/tmp//cc40eXre.o.
        Use linker option -v to see when and which objects, archives
	and dsos are loaded.
ld32: INFO    152: Output file removed because of error.
collect2: ld returned 2 exit status

It's quite possible I misapplied the patches...

--
Kaveh R. Ghazi			ghazi@caip.rutgers.edu

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: Irix6 long doubles implemented wrong? (27_io/ostream_inserter_arith)
  2003-01-26 21:24                                 ` Kaveh R. Ghazi
@ 2003-01-26 21:25                                   ` Alexandre Oliva
  2003-01-27  9:17                                   ` Kaveh R. Ghazi
  1 sibling, 0 replies; 72+ messages in thread
From: Alexandre Oliva @ 2003-01-26 21:25 UTC (permalink / raw)
  To: Kaveh R. Ghazi; +Cc: gcc-bugs, gcc-patches, gcc, libstdc++, oldham, ro, rth

On Jan 26, 2003, "Kaveh R. Ghazi" <ghazi@caip.rutgers.edu> wrote:

> ld32: ERROR   33 : Unresolved text symbol "__gttf2" -- 1st referenced
> by /var/tmp//cc40eXre.o.

Hmm...  This could result from your check-out not having the second
round of changes to gcc/config/fp-bit.[ch].  Does it?

-- 
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

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: Irix6 long doubles implemented wrong? (27_io/ostream_inserter_arith)
  2003-01-26 16:14                               ` Alexandre Oliva
  2003-01-26 18:40                                 ` Kaveh R. Ghazi
  2003-01-26 21:24                                 ` Kaveh R. Ghazi
@ 2003-01-26 21:54                                 ` Richard Henderson
  2 siblings, 0 replies; 72+ messages in thread
From: Richard Henderson @ 2003-01-26 21:54 UTC (permalink / raw)
  To: Alexandre Oliva
  Cc: Kaveh R. Ghazi, gcc-bugs, gcc-patches, gcc, libstdc++, oldham, ro

On Sun, Jan 26, 2003 at 10:48:18AM -0200, Alexandre Oliva wrote:
> 	* real.c (ibm_extended_format): Add 53 to minimum exponent.
> 	(encode_ibm_extended): Adjust.

Ok.

Thanks for working out a proper definition of "denormal" for
this fp type.  Someone might want to look at the AIX headers
and file a bug with IBM if the value doesn't correspond.  ;-)


r~

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: Irix6 long doubles implemented wrong? (27_io/ostream_inserter_arith)
  2003-01-26 21:24                                 ` Kaveh R. Ghazi
  2003-01-26 21:25                                   ` Alexandre Oliva
@ 2003-01-27  9:17                                   ` Kaveh R. Ghazi
  2003-01-27 10:40                                     ` Alexandre Oliva
  2003-01-27 10:41                                     ` Alexandre Oliva
  1 sibling, 2 replies; 72+ messages in thread
From: Kaveh R. Ghazi @ 2003-01-27  9:17 UTC (permalink / raw)
  To: aoliva; +Cc: gcc-bugs, gcc-patches, gcc, libstdc++, oldham, ro, rth

 > From: Alexandre Oliva
 > 
 > On Jan 26, 2003, "Kaveh R. Ghazi" <ghazi@caip.rutgers.edu> wrote:
 > 
 > > ld32: ERROR   33 : Unresolved text symbol "__gttf2" -- 1st referenced
 > > by /var/tmp//cc40eXre.o.
 > 
 > Hmm...  This could result from your check-out not having the second
 > round of changes to gcc/config/fp-bit.[ch].  Does it?

I think it did, but I'll try again with a fresh cvs update.

I'm using the patch below against 3.3. If it's not correct, would you
please send me your combined diffs and tell me whether I should use
a 3.3 or 3.4 snapshot?

		Thanks,
		--Kaveh

PS: what were your results on irix6?


diff -rup orig/egcc-CVS20030126/gcc/config/mips/_tilib.c egcc-CVS20030126/gcc/config/mips/_tilib.c
--- orig/egcc-CVS20030126/gcc/config/mips/_tilib.c	2003-01-26 09:08:00.770641267 -0500
+++ egcc-CVS20030126/gcc/config/mips/_tilib.c	2003-01-26 09:07:10.494518827 -0500
@@ -0,0 +1,154 @@
+/* A few TImode functions needed for TFmode emulated arithmetic.
+   Copyright 2002, 2003 Free Software Foundation, Inc.
+   Contributed by Alexandre Oliva <aoliva@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 "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 */
diff -rup orig/egcc-CVS20030126/gcc/config/mips/mips.c egcc-CVS20030126/gcc/config/mips/mips.c
--- orig/egcc-CVS20030126/gcc/config/mips/mips.c	2003-01-19 16:00:13.000000000 -0500
+++ egcc-CVS20030126/gcc/config/mips/mips.c	2003-01-26 09:07:10.534508498 -0500
@@ -4280,7 +4280,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)
 	{
@@ -4315,9 +4317,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)
@@ -4706,6 +4710,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;
@@ -4998,7 +5011,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;
@@ -5452,7 +5468,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.  */
@@ -8264,9 +8283,25 @@ 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)
     {
diff -rup orig/egcc-CVS20030126/gcc/config/mips/mips.h egcc-CVS20030126/gcc/config/mips/mips.h
--- orig/egcc-CVS20030126/gcc/config/mips/mips.h	2003-01-19 16:00:13.000000000 -0500
+++ egcc-CVS20030126/gcc/config/mips/mips.h	2003-01-26 09:07:10.554508315 -0500
@@ -1565,7 +1565,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.  */
@@ -1592,7 +1606,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.  */
@@ -2654,7 +2669,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
diff -rup orig/egcc-CVS20030126/gcc/config/mips/t-iris6 egcc-CVS20030126/gcc/config/mips/t-iris6
--- orig/egcc-CVS20030126/gcc/config/mips/t-iris6	2002-11-12 07:00:49.000000000 -0500
+++ egcc-CVS20030126/gcc/config/mips/t-iris6	2003-01-26 09:07:23.483427752 -0500
@@ -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
diff -rup orig/egcc-CVS20030126/gcc/real.c egcc-CVS20030126/gcc/real.c
--- orig/egcc-CVS20030126/gcc/real.c	2003-01-15 13:59:54.000000000 -0500
+++ egcc-CVS20030126/gcc/real.c	2003-01-26 09:06:02.199729192 -0500
@@ -3261,8 +3261,23 @@ encode_ibm_extended (fmt, buf, r)
       u = *r;
       clear_significand_below (&u, SIGNIFICAND_BITS - 53);
 
-      /* v = remainder containing additional 53 bits of significand.  */
-      do_add (&v, r, &u, 1);
+      normalize (&u);
+      /* If the upper double is zero, we have a denormal double, so
+	 move it to the first double and leave the second as zero.  */
+      if (u.class == rvc_zero)
+	{
+	  v = u;
+	  u = *r;
+	  normalize (&u);
+	}
+      else
+	{
+	  /* v = remainder containing additional 53 bits of significand.  */
+	  do_add (&v, r, &u, 1);
+	  round_for_format (&ieee_double_format, &v);
+	}
+
+      round_for_format (&ieee_double_format, &u);
 
       encode_ieee_double (&ieee_double_format, &buf[0], &u);
       encode_ieee_double (&ieee_double_format, &buf[2], &v);
@@ -3299,7 +3314,7 @@ const struct real_format ibm_extended_fo
     2,
     1,
     53 + 53,
-    -1021,
+    -1021 + 53,
     1024,
     -1,
     true,

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: Irix6 long doubles implemented wrong? (27_io/ostream_inserter_arith)
  2003-01-27  9:17                                   ` Kaveh R. Ghazi
@ 2003-01-27 10:40                                     ` Alexandre Oliva
  2003-01-28  4:52                                       ` Kaveh R. Ghazi
  2003-01-27 10:41                                     ` Alexandre Oliva
  1 sibling, 1 reply; 72+ messages in thread
From: Alexandre Oliva @ 2003-01-27 10:40 UTC (permalink / raw)
  To: Kaveh R. Ghazi; +Cc: gcc-bugs, gcc-patches, gcc, libstdc++, oldham, ro, rth

On Jan 27, 2003, "Kaveh R. Ghazi" <ghazi@caip.rutgers.edu> wrote:

>> From: Alexandre Oliva
>> 
>> On Jan 26, 2003, "Kaveh R. Ghazi" <ghazi@caip.rutgers.edu> wrote:
>> 
>> > ld32: ERROR   33 : Unresolved text symbol "__gttf2" -- 1st referenced
>> > by /var/tmp//cc40eXre.o.
>> 
>> Hmm...  This could result from your check-out not having the second
>> round of changes to gcc/config/fp-bit.[ch].  Does it?

> I think it did, but I'll try again with a fresh cvs update.

> I'm using the patch below against 3.3.

Ah, you're missing one little bit that has already made it to mainline
(in a slightly different form, along with the rest of the
mips64-linux-gnu port), that I still had in my tree and in the patch
for 3.3, but I ended up posting the patch for mainline, it seems.
Sorry about that.

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 15 Jan 2003 09:18:58 -0000
@@ -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;

-- 
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

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: Irix6 long doubles implemented wrong? (27_io/ostream_inserter_arith)
  2003-01-27  9:17                                   ` Kaveh R. Ghazi
  2003-01-27 10:40                                     ` Alexandre Oliva
@ 2003-01-27 10:41                                     ` Alexandre Oliva
  1 sibling, 0 replies; 72+ messages in thread
From: Alexandre Oliva @ 2003-01-27 10:41 UTC (permalink / raw)
  To: Kaveh R. Ghazi; +Cc: gcc-bugs, gcc-patches, gcc, libstdc++, oldham, ro, rth

On Jan 27, 2003, "Kaveh R. Ghazi" <ghazi@caip.rutgers.edu> wrote:

> PS: what were your results on irix6?

No regressions.  In particular, the numeric_limits (sp?) libstdc++-v3
test passed.

-- 
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

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: Irix6 long doubles implemented wrong? (27_io/ostream_inserter_arith)
  2003-01-27 10:40                                     ` Alexandre Oliva
@ 2003-01-28  4:52                                       ` Kaveh R. Ghazi
  2003-01-28 17:31                                         ` Alexandre Oliva
  0 siblings, 1 reply; 72+ messages in thread
From: Kaveh R. Ghazi @ 2003-01-28  4:52 UTC (permalink / raw)
  To: aoliva; +Cc: gcc-bugs, gcc-patches, gcc, libstdc++, oldham, ro, rth

 > From: Alexandre Oliva <aoliva@redhat.com>
 > 
 > Ah, you're missing one little bit that has already made it to mainline
 > (in a slightly different form, along with the rest of the
 > mips64-linux-gnu port), that I still had in my tree and in the patch
 > for 3.3, but I ended up posting the patch for mainline, it seems.
 > Sorry about that.

Yup that was it, 3.3 testsuite looks good now.  Thanks again!

PS: over here:
http://gcc.gnu.org/ml/gcc/2002-12/msg01310.html
you mentioned something about using the native irix library for some
of the math to speed it up.  What needs to be done there?  Can you
explain it to me (somewhat verbosely? :-)

--
Kaveh R. Ghazi			ghazi@caip.rutgers.edu

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: Irix6 long doubles implemented wrong? (27_io/ostream_inserter_arith)
  2003-01-28  4:52                                       ` Kaveh R. Ghazi
@ 2003-01-28 17:31                                         ` Alexandre Oliva
  2003-01-28 19:11                                           ` Kaveh R. Ghazi
  0 siblings, 1 reply; 72+ messages in thread
From: Alexandre Oliva @ 2003-01-28 17:31 UTC (permalink / raw)
  To: Kaveh R. Ghazi; +Cc: gcc-bugs, gcc-patches, gcc, libstdc++, oldham, ro, rth

On Jan 28, 2003, "Kaveh R. Ghazi" <ghazi@caip.rutgers.edu> wrote:

> PS: over here:
> http://gcc.gnu.org/ml/gcc/2002-12/msg01310.html
> you mentioned something about using the native irix library for some
> of the math to speed it up.  What needs to be done there?  Can you
> explain it to me (somewhat verbosely? :-)

Have a look at the macro GOFAST_RENAME_LIBCALLS in
gcc/config/gofast.h.  gofast is a FP emulation library that uses entry
points different from those used by GCC, so GOFAST_RENAME_LIBCALLS
arranges for GCC to issue calls using these entry points instead of
those it traditionally does.

You assignment :-) is to: (i) find out the name of the functions that
IRIX uses for long double floating-point operations and (ii) add
similar assignments to the optab arrays and libfunc variables such
that we issue calls to the IRIX-specific names.  An optional (iii) is
to change the name of the functions emitted for the emulation library
in gcc/config/fp-bit.h in the case of __LDBL_MANT_DIG__ == 106, and/or
disable it completely on IRIX (removing tp-bit.c from t-iris6), so
that we use only the native implementation.

Please let me know if you could use some further clarification of any
of the items above, and thanks in advance if you have a chance of
looking into them.

-- 
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

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: Irix6 long doubles implemented wrong? (27_io/ostream_inserter_arith)
  2003-01-26 13:00                             ` Alexandre Oliva
@ 2003-01-28 17:32                               ` Alexandre Oliva
  2003-01-28 23:38                                 ` Alexandre Oliva
  0 siblings, 1 reply; 72+ messages in thread
From: Alexandre Oliva @ 2003-01-28 17:32 UTC (permalink / raw)
  To: Kaveh R. Ghazi; +Cc: gcc-bugs, gcc-patches, gcc, libstdc++, oldham, ro, rth

On Jan 26, 2003, Alexandre Oliva <aoliva@redhat.com> wrote:

> On Jan 19, 2003, Alexandre Oliva <aoliva@redhat.com> wrote:
>> the minimum normal exponent should be set such that all 107
>> significant bits are available (and it's 107, not 106, as I
>> implemented it) for normals.

> It can't possibly be 107.

On second (or rather nth) thought, it possibly can, if you take
advantage of the sign bit of the second double.  But then you have to
allow it to be different from the sign of the first double, which we
don't, and the conversion routines would have to be tweaked to take
advantage of it without losing the additional bit of precision.

Furthermore, a way to implement most of the emulation without having
to use integers has occurred to me.  Here's the idea.

For addition of two long-doubles composed of a pair of doubles

- add the most significant double of each number.  If the result is
  infinity, NaN, copy it to the second double of the result and
  you're done

- otherwise, figure out which of the numbers you're adding has the
  biggest exponent.  Take a copy of the result obtained so far into a
  temporary say tmp and, from it, subtract the most significant double
  of each of the input operands.  Now this temporary contains the
  negated value of whatever bits there were in the high doubles that
  had to be thrown away due to rounding or limited precision from the
  high part of the result.

- assign to the low part of the result the result of adding the
  negated temporary, the low doubles of the input operands, highest
  exponent first

in pseudo-code (untested):

long double tfadd (long double in1, long double in2) {
  long double result;
  double tmp;

  result.high = in1.high + in2.high;

  if (isinf (result.high) || isnan (result.high))
    { result.low = result.high; return result; }

  result.low = in1.low + in2.low;

  if (in1.exponent < in2.exponent)
    result.low -= result.high - in1.high - in2.high;
  else
    result.low -= result.high - in2.high - in1.high;

  return result;
}


For negation, just negate each double individually.

For subtraction, negate the second operand and add.

For widening multiplication (double x double -> long double):

- multiply the doubles into the high part of the result

- if the result is infinity, a nan or zero, copy the high part of the
  low part and stop.

- divide the result by one of the input doubles into tmp1

- subtract the other input double from tmp1 into tmp2

- multiply tmp2 by the other input double into the low part of the
  result

long double tfdfmult (double in1, double in2) {
  long double result;

  result.high = in1 * in2;

  if (isinf (result.high) || isnan (result.high) || result.high == 0.0)
    result.low = result.high;
  else
    result.low = (result.high / in1 - in2) * in1;

  return result;
}


For multiplication of two long doubles:

- widen-multiply each pair of doubles, and add the results from least
  to most significant.

long double tfmult (long double in1, long double in2) {
  if (exponent (in1) < exponent (in2))
    swap (in1, in2);

  return tfdfmult (in1.low, in2.low)  + tfdfmult (in1.low, in2.high)
       + tfdfmult (in1.high, in2.low) + tfdfmult (in1.high, in2.high);
}


To invert: ???  this is the missing bit :-(

To divide, invert the divisor and multiply.


For the numerical experts, are there any flaws in the procedures
above?  Any ideas on how to implement inversion without losing
(much) precision?

-- 
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

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: Irix6 long doubles implemented wrong? (27_io/ostream_inserter_arith)
  2003-01-28 17:31                                         ` Alexandre Oliva
@ 2003-01-28 19:11                                           ` Kaveh R. Ghazi
  2003-01-28 19:23                                             ` Kaveh R. Ghazi
  0 siblings, 1 reply; 72+ messages in thread
From: Kaveh R. Ghazi @ 2003-01-28 19:11 UTC (permalink / raw)
  To: aoliva; +Cc: gcc-bugs, gcc-patches, gcc, libstdc++, oldham, ro, rth

 > From: Alexandre Oliva <aoliva@redhat.com>
 > 
 > On Jan 28, 2003, "Kaveh R. Ghazi" <ghazi@caip.rutgers.edu> wrote:
 > 
 > > PS: over here:
 > > http://gcc.gnu.org/ml/gcc/2002-12/msg01310.html
 > > you mentioned something about using the native irix library for some
 > > of the math to speed it up.  What needs to be done there?  Can you
 > > explain it to me (somewhat verbosely? :-)
 > 
 > Have a look at the macro GOFAST_RENAME_LIBCALLS in
 > gcc/config/gofast.h.  gofast is a FP emulation library that uses entry
 > points different from those used by GCC, so GOFAST_RENAME_LIBCALLS
 > arranges for GCC to issue calls using these entry points instead of
 > those it traditionally does.
 > 
 > You assignment :-) is to: (i) find out the name of the functions that
 > IRIX uses for long double floating-point operations


Well I tried man pages, sgi's website and search engines without any
luck.  So instead I tried reverse engineering by compiling a small
program with cc -n32 -S and seeing what I got.  I used this code:

	extern TYPE foo(double a, TYPE b)
	{
	  TYPE x = a OP b;
	  return x;
	}

My knowledge of assembly is limited and I'm certainly no floating
point expert.  But it seems to me that the routines for * / + and -
are named __q_mul, __q_div, __q_add and __q_sub.  There are widening
routines named __q_ext and __q_extd for widening a float and a double
respectively.  Is there any other operation we need to figure out?

Also I'm sure the calling convention needs to be understood to see if
these are drop in replacements for our own, but I'd like some help on
that.  I've included the assembly for TYPE='long double' and OP='*'.
It's pretty easy to follow especially given the helpful comments
inserted by the irix cc compiler.  Is this enough info to proceed?

		Thanks,
		--Kaveh


	.set	noreorder
	.set	noat
	#  /usr/lib32/cmplrs/be::7.30
	#ism	1275524910

	#-----------------------------------------------------------
	# Compiling f2.c (/tmp/ctmB.BAAa5-Hr-)
	#-----------------------------------------------------------

	#-----------------------------------------------------------
	# Options:
	#-----------------------------------------------------------
	#  Target:R10000, ISA:mips4, Pointer Size:32
	#  -O0	(Optimization level)
	#  -g0	(Debug level)
	#  -m1	(Report warnings)
	#-----------------------------------------------------------

	.file	1	"/a/teal/caip5/ghazi/f2.c"

	.section .text, 1, 0x00000006, 4, 16
.text:
	.section .text

	# Program Unit: foo
	.ent	foo
	.globl	foo
foo:	# 0x0
	.dynsym	foo	sto_default
	.frame	$sp, 64, $31
	.mask	0x80000000, -48
	# x = 0
	# lcl_spill_temp_0 = 16
	# lcl_spill_temp_1 = 24
	.loc	1 2 1
 #   1  extern TYPE foo(double a, TYPE b)
 #   2  {
.BB1.foo:	# 0x0
	addiu $sp,$sp,-64             	#  
	sd $gp,24($sp)                	#  lcl_spill_temp_1
	sd $31,16($sp)                	#  lcl_spill_temp_0
	lui $1,%hi(%neg(%gp_rel(foo)))	#  foo
	addiu $1,$1,%lo(%neg(%gp_rel(foo)))	#  foo
	addu $gp,$25,$1               	#  
	sdc1 $f12,32($sp)             	#  a
	sdc1 $f14,48($sp)             	#  b
	sdc1 $f15,56($sp)             	#  b+8
	.loc	1 3 8
 #   3    TYPE x = a OP b;
	ldc1 $f12,32($sp)             	#  a
	lw $25,%call16(__q_extd)($gp) 	#  __q_extd
	jalr $25                      	#  __q_extd
	nop                           	#  
.BB2.foo:	# 0x34
	mov.d $f12,$f0                	#  
	mov.d $f13,$f2                	#  
	ldc1 $f14,48($sp)             	#  b
	ldc1 $f15,56($sp)             	#  b+8
	lw $25,%call16(__q_mul)($gp)  	#  __q_mul
	jalr $25                      	#  __q_mul
	nop                           	#  
.BB3.foo:	# 0x50
	sdc1 $f0,0($sp)               	#  x
	sdc1 $f2,8($sp)               	#  x+8
	.loc	1 4 3
 #   4    return x;
	ldc1 $f0,0($sp)               	#  x
	ldc1 $f2,8($sp)               	#  x+8
	ld $gp,24($sp)                	#  lcl_spill_temp_1
	ld $31,16($sp)                	#  lcl_spill_temp_0
	addiu $sp,$sp,64              	#  
	jr $31                        	#  
	nop                           	#  
	.end	foo
	.section .text
	.align 4
	.gpvalue 30720

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: Irix6 long doubles implemented wrong? (27_io/ostream_inserter_arith)
  2003-01-28 19:11                                           ` Kaveh R. Ghazi
@ 2003-01-28 19:23                                             ` Kaveh R. Ghazi
  2003-01-28 19:47                                               ` Rainer Orth
       [not found]                                               ` <15926.49701.3! 59482.666471@xayide.TechFak.Uni-Bielefeld.DE>
  0 siblings, 2 replies; 72+ messages in thread
From: Kaveh R. Ghazi @ 2003-01-28 19:23 UTC (permalink / raw)
  To: aoliva; +Cc: gcc-bugs, gcc-patches, gcc, libstdc++, oldham, ro, rth

 > From: "Kaveh R. Ghazi"
 > 
 > My knowledge of assembly is limited and I'm certainly no floating
 > point expert.  But it seems to me that the routines for * / + and -
 > are named __q_mul, __q_div, __q_add and __q_sub.  There are widening
 > routines named __q_ext and __q_extd for widening a float and a double
 > respectively.  Is there any other operation we need to figure out?

Poking around some more turned up these routines in libc.so.

[662]   | 263004512|      40|FUNC |GLOB |DEFAULT  |MIPS_TEXT|__q_ext
[663]   | 263004592|      44|FUNC |GLOB |DEFAULT  |MIPS_TEXT|__q_floti
[664]   | 263004636|      44|FUNC |GLOB |DEFAULT  |MIPS_TEXT|__q_flotj
[665]   | 263004680|      52|FUNC |GLOB |DEFAULT  |MIPS_TEXT|__q_flotju
[666]   | 263004800|     112|FUNC |GLOB |DEFAULT  |MIPS_TEXT|__q_flotku
[667]   | 263005200|      48|FUNC |GLOB |DEFAULT  |MIPS_TEXT|__q_ne
[668]   | 263005248|      28|FUNC |GLOB |DEFAULT  |MIPS_TEXT|__q_neg
[672]   | 262962368|    1236|FUNC |GLOB |DEFAULT  |MIPS_TEXT|__q_mul
[3293]  | 263003000|    1464|FUNC |GLOB |DEFAULT  |MIPS_TEXT|__q_div
[3294]  | 263004464|      48|FUNC |GLOB |DEFAULT  |MIPS_TEXT|__q_eq
[3295]  | 263004552|      40|FUNC |GLOB |DEFAULT  |MIPS_TEXT|__q_extd
[3296]  | 263004732|      68|FUNC |GLOB |DEFAULT  |MIPS_TEXT|__q_flotk
[3297]  | 263004912|      72|FUNC |GLOB |DEFAULT  |MIPS_TEXT|__q_ge
[3298]  | 263004984|      72|FUNC |GLOB |DEFAULT  |MIPS_TEXT|__q_gt
[3299]  | 263005056|      72|FUNC |GLOB |DEFAULT  |MIPS_TEXT|__q_le
[3300]  | 263005128|      72|FUNC |GLOB |DEFAULT  |MIPS_TEXT|__q_lt
[3301]  | 262961324|    1044|FUNC |GLOB |DEFAULT  |MIPS_TEXT|__q_add
[3302]  | 262963604|    1052|FUNC |GLOB |DEFAULT  |MIPS_TEXT|__q_sub

I think it's obvious some are comparison operators.  The ones with
__q_flot* seem to be integer conversions, but I'm not sure what each
one does specifically.

--
Kaveh R. Ghazi			ghazi@caip.rutgers.edu

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: Irix6 long doubles implemented wrong? (27_io/ostream_inserter_arith)
  2003-01-28 19:23                                             ` Kaveh R. Ghazi
@ 2003-01-28 19:47                                               ` Rainer Orth
       [not found]                                               ` <15926.49701.3! 59482.666471@xayide.TechFak.Uni-Bielefeld.DE>
  1 sibling, 0 replies; 72+ messages in thread
From: Rainer Orth @ 2003-01-28 19:47 UTC (permalink / raw)
  To: Kaveh R. Ghazi
  Cc: aoliva, gcc-bugs, gcc-patches, gcc, libstdc++, oldham, ro, rth

Kaveh R. Ghazi writes:

> I think it's obvious some are comparison operators.  The ones with
> __q_flot* seem to be integer conversions, but I'm not sure what each
> one does specifically.

There's the MIPS Processor ABI Conformance Guide Version 3.0 Draft 4
(dated: July 18, 1997) a.k.a. The Black Book.  It used to be available from
www.mipsabi.org, but this site has been closed down when the MIPS ABI group
dissolved.  I couldn't locate a copy on the Web, but have a local copy
here.  Maybe SGI could make it available again?  Their Dave Anderson has
always been quite helpful getting all sorts of ABI and toolset information.

Here's the relevant section from Appendix D: Platform Implementation Notes,
D4-5:

Support for long double Datatype
NOTE
The routines described here are for support of a 128-bit (quad-word) long double datatype in the 64-bit 3
ABI. The 32-bit ABI uses a 64-bit long double and does not require these routines.
Figure D-3: libc Contents, Internal Routines for long double Support
__q_add __q_div __q_eq __q_ext 3
__q_extd __q_floti __q_flotj __q_flotju 3
__q_flotk __q_flotku __q_ge __q_gt 3
__q_le __q_lt __q_mul __q_ne 3
__q_neg __q_sub __sngl_q __dble_q 3
__ii_qint __ji_qint __ji_quint __ki_qint 3
__ki_quint _qtoa 3
Data Definitions for long double Datatype
The following prototypes are provided for system implementors. They do not appear in any standard system 3
header file.

Figure D-4: Prototypes for Internal long double Support Routines
long double __q_add( double, double, double, double ); 3
long double __q_div( double, double, double, double ); 3
int32_t __q_eq( double, double, double, double ); 3
long double __q_ext( float ); 3
long double __q_extd( double ); 3
long double __q_floti( int16_t ); 3
long double __q_flotj( int32_t ); 3
long double __q_flotju( uint32_t ); 3
long double __q_flotk( int64_t ); 3
long double __q_flotku( uint64_t ); 3
int32_t __q_ge( double, double, double, double ); 3
int32_t __q_gt( double, double, double, double ); 3
int32_t __q_le( double, double, double, double ); 3
int32_t __q_lt( double, double, double, double ); 3
long double __q_mul( double, double, double, double ); 3
int32_t __q_ne( double, double, double, double ); 3
long double __q_neg( double, double ); 3
long double __q_sub( double, double, double, double ); 3
float __sngl_q( double, double ); 3
double __dble_q( double, double ); 3
int16_t __ii_qint( double, double ); 3
int32_t __ji_qint( double, double ); 3
uint32_t __ji_quint( double, double ); 3
int64_t __ki_qint( double, double ); 3
uint64_t __ki_quint( double, double ); 3
int _qtoa( char *, int, long double, int ); 3

This is all I've been able to locate in publicly available documentation.

	Rainer

-----------------------------------------------------------------------------
Rainer Orth, Faculty of Technology, Bielefeld University

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: Irix6 long doubles implemented wrong? (27_io/ostream_inserter_arith)
  2003-01-28 17:32                               ` Alexandre Oliva
@ 2003-01-28 23:38                                 ` Alexandre Oliva
  0 siblings, 0 replies; 72+ messages in thread
From: Alexandre Oliva @ 2003-01-28 23:38 UTC (permalink / raw)
  To: Kaveh R. Ghazi; +Cc: gcc-bugs, gcc-patches, gcc, libstdc++, oldham, ro, rth

On Jan 28, 2003, Alexandre Oliva <aoliva@redhat.com> wrote:

> To invert: ???  this is the missing bit :-(

> To divide, invert the divisor and multiply.

Just figured out how to do division, using addition, subtraction and
multiplication:

- obtain an initial estimate of the result by dividing the high
  parts

- compute a residue by subtracting from the dividend the result of
  multiplying the result estimate and the divisor

- divide the high part of the residue by the high part of the divisor,
  and add it to the result

- repeat the last two steps until the result stops changing


I think it doesn't take more than 2 iterations for the result to
stabilize.  Here's the pseudo code:

long double divide(long double in1, long double in2) {
  long double result, prev;

  result.high = in1.high / in2.high;

  if (isinf (result.high) || isnan (result.high)) {
    result.low = result.high;
    return result;
  }

  result.low = 0.0;

  do {
    long double partial;
    prev = result;
    partial.high = (in1 - result * in2).high / in2.high;
    partial.low = 0.0;
    result += partial;
  } while (result != prev);

  return result;
}


Other operations, such as extending from double, compares, etc, are
pretty obvious, so I'll refrain from posting them here.  Conversion
to/from int can be done with extension to/truncation from double, and
conversion to/from long long takes a bit more work to use all 64 bits,
but that's it.  Wheee!

Any candidates to implement say gcc/config/tp-ibmext-bit.c using these
ideas, even though we have no immediate use for them?

-- 
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

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: Irix6 long doubles implemented wrong? (27_io/ostream_inserter_arith)
       [not found]                                               ` <15926.49701.3! 59482.666471@xayide.TechFak.Uni-Bielefeld.DE>
@ 2003-01-29  6:56                                                 ` Kaveh R. Ghazi
  2003-01-29 10:07                                                   ` Richard Henderson
  0 siblings, 1 reply; 72+ messages in thread
From: Kaveh R. Ghazi @ 2003-01-29  6:56 UTC (permalink / raw)
  To: ro; +Cc: aoliva, gcc-bugs, gcc-patches, gcc, libstdc++, oldham, rth

 > From: Rainer Orth <ro@TechFak.Uni-Bielefeld.DE>
 > 
 > There's the MIPS Processor ABI Conformance Guide Version 3.0 Draft 4
 > (dated: July 18, 1997) a.k.a. The Black Book.  It used to be available from
 > www.mipsabi.org, but this site has been closed down when the MIPS ABI group
 > dissolved.  I couldn't locate a copy on the Web, but have a local copy
 > here.  Maybe SGI could make it available again?  Their Dave Anderson has
 > always been quite helpful getting all sorts of ABI and toolset information.
 > 
 > Here's the relevant section from Appendix D: Platform Implementation Notes,
 > D4-5:


Thanks!  That was exactly what I needed.  Here's something I'm
currently testing.  I think I'm on the right track, my preliminary
tests shows it works and yields timing results comparable to cc.

Notes:

1.  Rainer's list included the following functions for which I
    couldn't glean a corresponding optabs entry:

long double __q_floti( int16_t ); 3
long double __q_flotju( uint32_t ); 3
long double __q_flotku( uint64_t ); 3
long double __q_neg( double, double ); 3
int16_t __ii_qint( double, double ); 3

2.  Conversely, there were several optabs TF entries for which I couldn't
    determine something in the irix libc list.  There were:

unordtf2_libfunc
floattitf_libfunc
fixtfti_libfunc
fixunstfti_libfunc
cmp_optab->handlers[(int) TFmode].libfunc (E.g. set by gofast)

3.  I notice neither irix nor optabs seems to have functions to
    convert *unsigned* ints to floating points.  Yet it seems to
    work.  Perhaps the C promotion rules mandate some intermediate
    type conversion that already exists.


Anyway, any comments on the notes or the patch?  Thanks.


diff -rup orig/egcc-3.3-CVS20030127/gcc/config/mips/iris6.h egcc-3.3-CVS20030127/gcc/config/mips/iris6.h
--- orig/egcc-3.3-CVS20030127/gcc/config/mips/iris6.h	2003-01-27 22:31:46.000000000 -0500
+++ egcc-3.3-CVS20030127/gcc/config/mips/iris6.h	2003-01-28 16:27:13.521707000 -0500
@@ -511,3 +511,31 @@ do {									 \
 %{mabi=32: -32}%{mabi=n32: -n32}%{mabi=64: -64}%{!mabi*: -n32}"
 
 #define MIPS_TFMODE_FORMAT ibm_extended_format
+
+#define INIT_NATIVE_TFP_OPTABS \
+do { \
+  add_optab->handlers[(int) TFmode].libfunc = init_one_libfunc ("__q_add"); \
+  sub_optab->handlers[(int) TFmode].libfunc = init_one_libfunc ("__q_sub"); \
+  smul_optab->handlers[(int) TFmode].libfunc = init_one_libfunc ("__q_mul"); \
+  sdiv_optab->handlers[(int) TFmode].libfunc = init_one_libfunc ("__q_div"); \
+\
+  extendsftf2_libfunc = init_one_libfunc ("__q_ext"); \
+  extenddftf2_libfunc = init_one_libfunc ("__q_extd"); \
+  trunctfsf2_libfunc = init_one_libfunc ("__sngl_q"); \
+  trunctfdf2_libfunc = init_one_libfunc ("__dble_q"); \
+\
+  eqtf2_libfunc = init_one_libfunc ("__q_eq"); \
+  netf2_libfunc = init_one_libfunc ("__q_ne"); \
+  gttf2_libfunc = init_one_libfunc ("__q_gt"); \
+  getf2_libfunc = init_one_libfunc ("__q_ge"); \
+  lttf2_libfunc = init_one_libfunc ("__q_lt"); \
+  letf2_libfunc = init_one_libfunc ("__q_le"); \
+\
+  fixtfsi_libfunc = init_one_libfunc ("__ji_qint"); \
+  fixtfdi_libfunc = init_one_libfunc ("__ki_qint"); \
+  fixunstfsi_libfunc = init_one_libfunc ("__ji_quint"); \
+  fixunstfdi_libfunc = init_one_libfunc ("__ki_quint"); \
+\
+  floatsitf_libfunc = init_one_libfunc ("__q_flotj"); \
+  floatditf_libfunc = init_one_libfunc ("__q_flotk"); \
+} while (0)
diff -rup orig/egcc-3.3-CVS20030127/gcc/config.gcc egcc-3.3-CVS20030127/gcc/config.gcc
--- orig/egcc-3.3-CVS20030127/gcc/config.gcc	2003-01-04 17:00:25.000000000 -0500
+++ egcc-3.3-CVS20030127/gcc/config.gcc	2003-01-28 14:39:51.670349000 -0500
@@ -2879,6 +2879,7 @@ mips*-*-*)
 		tm_file="gofast.h $tm_file"
 		tmake_file="mips/t-gofast $tmake_file"
 	else
+		tm_defines="INIT_SUBTARGET_OPTABS=INIT_NATIVE_TFP_OPTABS $tm_defines"
 		tmake_file="mips/t-mips $tmake_file"
 	fi
 	;;

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: Irix6 long doubles implemented wrong? (27_io/ostream_inserter_arith)
  2003-01-29  6:56                                                 ` Kaveh R. Ghazi
@ 2003-01-29 10:07                                                   ` Richard Henderson
  2003-01-29 13:39                                                     ` Alexandre Oliva
                                                                       ` (2 more replies)
  0 siblings, 3 replies; 72+ messages in thread
From: Richard Henderson @ 2003-01-29 10:07 UTC (permalink / raw)
  To: Kaveh R. Ghazi; +Cc: ro, aoliva, gcc-bugs, gcc-patches, gcc, libstdc++, oldham

On Tue, Jan 28, 2003 at 08:32:19PM -0500, Kaveh R. Ghazi wrote:
> long double __q_floti( int16_t ); 3
> long double __q_flotju( uint32_t ); 3
> long double __q_flotku( uint64_t ); 3

	floathitf2
	floatunssitf2
	floatunsditf2

> long double __q_neg( double, double ); 3

	negtf2

> int16_t __ii_qint( double, double ); 3

	fix_trunctfhi2

> 2.  Conversely, there were several optabs TF entries for which I couldn't
>     determine something in the irix libc list.  There were:
> 
> unordtf2_libfunc

This one may be a problem.  We don't know what the actual
return values are for the comparison functions.  By rights
it ought to be a tri-state value off of EQ or NE.

> floattitf_libfunc
> fixtfti_libfunc
> fixunstfti_libfunc

There were no TImode functions listed.

> 3.  I notice neither irix nor optabs seems to have functions to
>     convert *unsigned* ints to floating points.

For gcc, see "floatuns<MI><MF>2".
For Irix, see __q_flotju as opposed to __q_flotj.


r~

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: Irix6 long doubles implemented wrong? (27_io/ostream_inserter_arith)
  2003-01-29 10:07                                                   ` Richard Henderson
@ 2003-01-29 13:39                                                     ` Alexandre Oliva
  2003-01-29 17:26                                                     ` Kaveh R. Ghazi
  2003-01-30  8:05                                                     ` Irix6 long doubles implemented wrong? (27_io/ostream_inserter_arith) Kaveh R. Ghazi
  2 siblings, 0 replies; 72+ messages in thread
From: Alexandre Oliva @ 2003-01-29 13:39 UTC (permalink / raw)
  To: Richard Henderson
  Cc: Kaveh R. Ghazi, ro, gcc-bugs, gcc-patches, gcc, libstdc++, oldham

On Jan 29, 2003, Richard Henderson <rth@redhat.com> wrote:

>> unordtf2_libfunc

> This one may be a problem.

GCC knows what to do if it's not defined, unless you actually use the
unord builtin (or maybe even if we do).  Remember that gofast has the
same problem, and we do generate correct code for it regardless.

-- 
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

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: Irix6 long doubles implemented wrong? (27_io/ostream_inserter_arith)
  2003-01-29 10:07                                                   ` Richard Henderson
  2003-01-29 13:39                                                     ` Alexandre Oliva
@ 2003-01-29 17:26                                                     ` Kaveh R. Ghazi
  2003-01-29 18:10                                                       ` Richard Henderson
  2003-01-30  8:05                                                     ` Irix6 long doubles implemented wrong? (27_io/ostream_inserter_arith) Kaveh R. Ghazi
  2 siblings, 1 reply; 72+ messages in thread
From: Kaveh R. Ghazi @ 2003-01-29 17:26 UTC (permalink / raw)
  To: rth; +Cc: aoliva, gcc-bugs, gcc-patches, gcc, libstdc++, oldham, ro

 > From: Richard Henderson <rth@redhat.com>
 > 
 > On Tue, Jan 28, 2003 at 08:32:19PM -0500, Kaveh R. Ghazi wrote:
 > 
 > 	floathitf2
 > 	floatunssitf2
 > 	floatunsditf2
 > 	negtf2
 > 	fix_trunctfhi2

Sorry I wasn't clear.  I can conceptually come up with the names, what
I don't see are entries for them in libfuncs.h so I assume I can't
just start using them.

Is it safe to simply add the appropriate entries to enum libfunc_index
and magically everything will work?

 > 
 > > 3.  I notice neither irix nor optabs seems to have functions to
 > >     convert *unsigned* ints to floating points.
 > 
 > For gcc, see "floatuns<MI><MF>2".
 > r~

Ditto above.

		Thanks,
		--Kaveh
--
Kaveh R. Ghazi			ghazi@caip.rutgers.edu

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: Irix6 long doubles implemented wrong? (27_io/ostream_inserter_arith)
  2003-01-29 17:26                                                     ` Kaveh R. Ghazi
@ 2003-01-29 18:10                                                       ` Richard Henderson
  2003-01-30 23:31                                                         ` Irix6 native long double libcalls progress report (and problem) Kaveh R. Ghazi
  0 siblings, 1 reply; 72+ messages in thread
From: Richard Henderson @ 2003-01-29 18:10 UTC (permalink / raw)
  To: Kaveh R. Ghazi; +Cc: aoliva, gcc-bugs, gcc-patches, gcc, libstdc++, oldham, ro

On Wed, Jan 29, 2003 at 11:15:02AM -0500, Kaveh R. Ghazi wrote:
>  > From: Richard Henderson <rth@redhat.com>
>  > 
>  > On Tue, Jan 28, 2003 at 08:32:19PM -0500, Kaveh R. Ghazi wrote:
>  > 
>  > 	floathitf2
>  > 	floatunssitf2
>  > 	floatunsditf2
>  > 	negtf2
>  > 	fix_trunctfhi2
> 
> Sorry I wasn't clear.  I can conceptually come up with the names, what
> I don't see are entries for them in libfuncs.h so I assume I can't
> just start using them.
> 
> Is it safe to simply add the appropriate entries to enum libfunc_index
> and magically everything will work?

No, you'd have to modify code as well.  See how the _libfuncs
are used in optabs.c.  Probably no sense in adding the HImode bits.

The unsigned conversions on the other hand...  Well, a little
rearrangement of the code is needed.  GCC does not itself provide
unsigned->float conversion routines (which is silly) and so it
synthesizes with libcall + extra code.



r~

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: Irix6 long doubles implemented wrong? (27_io/ostream_inserter_arith)
  2003-01-29 10:07                                                   ` Richard Henderson
  2003-01-29 13:39                                                     ` Alexandre Oliva
  2003-01-29 17:26                                                     ` Kaveh R. Ghazi
@ 2003-01-30  8:05                                                     ` Kaveh R. Ghazi
  2003-02-03 13:07                                                       ` Alexandre Oliva
  2 siblings, 1 reply; 72+ messages in thread
From: Kaveh R. Ghazi @ 2003-01-30  8:05 UTC (permalink / raw)
  To: rth; +Cc: aoliva, gcc-bugs, gcc-patches, gcc, libstdc++, oldham, ro

 > From: Richard Henderson <rth@redhat.com>
 > > 
 > > unordtf2_libfunc
 > 
 > This one may be a problem.  We don't know what the actual
 > return values are for the comparison functions.  By rights
 > it ought to be a tri-state value off of EQ or NE.

I'm not sure what you mean.  Are you saying that all the gcc
comparison functions are tri-state (-1,0,1) or just the unord one?

The Irix native comparison ops all return 0 or 1 (true/false).  I
tested them all manually.  They don't seem to work when I use them as
replacements for the gcc comparison ops.  I get funky results when I
try test programs, not sure why.

		--Kaveh
--
Kaveh R. Ghazi			ghazi@caip.rutgers.edu

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Irix6 native long double libcalls progress report (and problem)
  2003-01-29 18:10                                                       ` Richard Henderson
@ 2003-01-30 23:31                                                         ` Kaveh R. Ghazi
  2003-01-30 23:49                                                           ` Richard Henderson
  0 siblings, 1 reply; 72+ messages in thread
From: Kaveh R. Ghazi @ 2003-01-30 23:31 UTC (permalink / raw)
  To: rth; +Cc: aoliva, gcc-bugs, gcc-patches, gcc, libstdc++, oldham, ro

I got pretty far getting Irix6 to use it's native libc long double
routines.  I managed to come up with a patch and run some timing
tests, for long double ops in isolation I'm getting speedups from 5x
to 20x over the gcc routines depending on the operation performed.

So far so good.  In the case of the comparison ops, they don't have
the same return values that gcc expects, so I commented them out.  And
in another case, the gcc routines are better, so I commented out those
too.  What's left is in the patch at the end of this message.

When I ran the testsuite however, I get one new failure in
execute/conversion.c.  The problem boils down to this:

 > long double
 > ull2ld(u)
 >      unsigned long long int u;
 > {
 >   return u;
 > }
 > 

Then we crash on this code:

 >   if (ull2ld(~0ULL) != (long double) ~0ULL)
 >     abort();

I.e. supposedly the value passed through and converted in a function
is different than the same constant cast inline.

I added some code to check out what we're actually getting:


 > #include <stdio.h>
 > extern void abort(void);
 > 
 > long double
 > ull2ld(u)
 >      unsigned long long int u;
 > {
 >   return u;
 > }
 > 
 > int main()
 > {
 >   fprintf (stderr, "%.25Le\n%.25Le\n%Le\n", ull2ld(~0ULL),
 > 	   (long double) ~0ULL, ull2ld(~0ULL) - (long double) ~0ULL);
 >   {
 >     union f { long double ld; unsigned long long ll[2]; }
 >     f1 = { ull2ld(~0ULL) }, f2 = { (long double) ~0ULL };
 >     
 >     fprintf (stderr, "%llx %016llx\n%llx %016llx\n",
 > 	     f1.ll[0], f1.ll[1], f2.ll[0], f2.ll[1]);
 >   }
 > 
 >   if (ull2ld(~0ULL) != (long double) ~0ULL)
 >     abort();
 >   
 >   return 0;
 > }
 >  

With gcc-3.3 from last night plus the patch, it yields:

1.8446744073709551615000000e+19
1.8446744073709551615000000e+19
0.000000e+00
43f0000000000000 bff0000000000000
43efffffffffffff 409ffc0000000000
Abort (core dumped)

As you can see, the numbers are equal in value.  To see whether the
value was different in some far out Nth decimal place, I subtracted
them and it results in zero point zero.

But the bit patterns are different!  And I'm guessing that this
confuses the gcc comparison function.

What's going on here?  Ideas?

		Thanks,
		--Kaveh


2003-01-30  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>

	* mips/iris6.h (INIT_NATIVE_TFP_OPTABS): Define.
	* config.gcc: Set INIT_SUBTARGET_OPTABS to INIT_NATIVE_TFP_OPTABS
	for irix6 when not enabling "gofast" routines.

diff -rup orig/egcc-3.3-CVS20030129/gcc/config/mips/iris6.h egcc-3.3-CVS20030129/gcc/config/mips/iris6.h
--- orig/egcc-3.3-CVS20030129/gcc/config/mips/iris6.h	Mon Jan 27 22:31:46 2003
+++ egcc-3.3-CVS20030129/gcc/config/mips/iris6.h	Thu Jan 30 08:56:54 2003
@@ -511,3 +511,35 @@ do {									 \
 %{mabi=32: -32}%{mabi=n32: -n32}%{mabi=64: -64}%{!mabi*: -n32}"
 
 #define MIPS_TFMODE_FORMAT ibm_extended_format
+
+/* Faster long double routines from irix6 libc.  */
+#define INIT_NATIVE_TFP_OPTABS \
+do { \
+  add_optab->handlers[(int) TFmode].libfunc = init_one_libfunc ("__q_add"); \
+  sub_optab->handlers[(int) TFmode].libfunc = init_one_libfunc ("__q_sub"); \
+  smul_optab->handlers[(int) TFmode].libfunc = init_one_libfunc ("__q_mul"); \
+  sdiv_optab->handlers[(int) TFmode].libfunc = init_one_libfunc ("__q_div"); \
+  neg_optab->handlers[(int) TFmode].libfunc = init_one_libfunc ("__q_neg"); \
+\
+  extendsftf2_libfunc = init_one_libfunc ("__q_ext"); \
+  extenddftf2_libfunc = init_one_libfunc ("__q_extd"); \
+  trunctfsf2_libfunc = init_one_libfunc ("__sngl_q"); \
+  trunctfdf2_libfunc = init_one_libfunc ("__dble_q"); \
+\
+  /* These routines return 0/1, we need tri-state -1,0.1.  */ \
+  /*eqtf2_libfunc = init_one_libfunc ("__q_eq");*/ \
+  /*netf2_libfunc = init_one_libfunc ("__q_ne");*/ \
+  /*gttf2_libfunc = init_one_libfunc ("__q_gt");*/ \
+  /*getf2_libfunc = init_one_libfunc ("__q_ge");*/ \
+  /*lttf2_libfunc = init_one_libfunc ("__q_lt");*/ \
+  /*letf2_libfunc = init_one_libfunc ("__q_le");*/ \
+\
+  /* These two routines are actually slower.  */ \
+  /*fixtfsi_libfunc = init_one_libfunc ("__ji_qint");*/ \
+  /*fixunstfsi_libfunc = init_one_libfunc ("__ji_quint");*/ \
+  fixtfdi_libfunc = init_one_libfunc ("__ki_qint"); \
+  fixunstfdi_libfunc = init_one_libfunc ("__ki_quint"); \
+\
+  floatsitf_libfunc = init_one_libfunc ("__q_flotj"); \
+  floatditf_libfunc = init_one_libfunc ("__q_flotk"); \
+} while (0)
diff -rup orig/egcc-3.3-CVS20030127/gcc/config.gcc egcc-3.3-CVS20030127/gcc/config.gcc
--- orig/egcc-3.3-CVS20030127/gcc/config.gcc	2003-01-04 17:00:25.000000000 -0500
+++ egcc-3.3-CVS20030127/gcc/config.gcc	2003-01-28 14:39:51.670349000 -0500
@@ -2879,6 +2879,7 @@ mips*-*-*)
 		tm_file="gofast.h $tm_file"
 		tmake_file="mips/t-gofast $tmake_file"
 	else
+		tm_defines="INIT_SUBTARGET_OPTABS=INIT_NATIVE_TFP_OPTABS $tm_defines"
 		tmake_file="mips/t-mips $tmake_file"
 	fi
 	;;

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: Irix6 native long double libcalls progress report (and problem)
  2003-01-30 23:31                                                         ` Irix6 native long double libcalls progress report (and problem) Kaveh R. Ghazi
@ 2003-01-30 23:49                                                           ` Richard Henderson
  2003-02-03 13:22                                                             ` Alexandre Oliva
  0 siblings, 1 reply; 72+ messages in thread
From: Richard Henderson @ 2003-01-30 23:49 UTC (permalink / raw)
  To: Kaveh R. Ghazi; +Cc: aoliva, gcc-bugs, gcc-patches, gcc, libstdc++, oldham, ro

On Thu, Jan 30, 2003 at 04:51:45PM -0500, Kaveh R. Ghazi wrote:
> 43f0000000000000 bff0000000000000
> 43efffffffffffff 409ffc0000000000

Hmm.  They seem to be doing some of what Alex proposed a while
ago -- making use of the sign bit.

Theirs is (2**64, -1), ours is (0xfffffffffffff800, 0x7ff).

> But the bit patterns are different!  And I'm guessing that this
> confuses the gcc comparison function.

Almost certainly.

As for using SGI's comparison routines, you can do that from
expanders in the backend, with direct calls to emit_library_call
etc.  That's what I do for Tru64's long double library.


r~

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: Irix6 long doubles implemented wrong? (27_io/ostream_inserter_arith)
  2003-01-30  8:05                                                     ` Irix6 long doubles implemented wrong? (27_io/ostream_inserter_arith) Kaveh R. Ghazi
@ 2003-02-03 13:07                                                       ` Alexandre Oliva
  2003-02-03 15:18                                                         ` Kaveh R. Ghazi
  0 siblings, 1 reply; 72+ messages in thread
From: Alexandre Oliva @ 2003-02-03 13:07 UTC (permalink / raw)
  To: Kaveh R. Ghazi; +Cc: rth, gcc-bugs, gcc-patches, gcc, libstdc++, oldham, ro

On Jan 30, 2003, "Kaveh R. Ghazi" <ghazi@caip.rutgers.edu> wrote:

>> From: Richard Henderson <rth@redhat.com>
>> > 
>> > unordtf2_libfunc
>> 
>> This one may be a problem.  We don't know what the actual
>> return values are for the comparison functions.  By rights
>> it ought to be a tri-state value off of EQ or NE.

> I'm not sure what you mean.  Are you saying that all the gcc
> comparison functions are tri-state (-1,0,1) or just the unord one?

There is L_compare_[sdt]f, that is tri-state, but none of the others
are, it's just that you sometimes can't distinguish unord from false
on the others, such as those of gofast.  If there's no equivalent to
the tri-state compare on IRIX, just set the corresponding entry in
optabs NULL, and GCC will find other ways to implement it, using eq,
ne, gt, ge, lt and le.

-- 
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

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: Irix6 native long double libcalls progress report (and problem)
  2003-01-30 23:49                                                           ` Richard Henderson
@ 2003-02-03 13:22                                                             ` Alexandre Oliva
  0 siblings, 0 replies; 72+ messages in thread
From: Alexandre Oliva @ 2003-02-03 13:22 UTC (permalink / raw)
  To: Richard Henderson
  Cc: Kaveh R. Ghazi, gcc-bugs, gcc-patches, gcc, libstdc++, oldham, ro

On Jan 30, 2003, Richard Henderson <rth@redhat.com> wrote:

> On Thu, Jan 30, 2003 at 04:51:45PM -0500, Kaveh R. Ghazi wrote:
>> 43f0000000000000 bff0000000000000
>> 43efffffffffffff 409ffc0000000000

> Hmm.  They seem to be doing some of what Alex proposed a while
> ago -- making use of the sign bit.

Yup.  I've been debating how to fix this with Kaveh in private, but I
thought I'd post some of the thoughts here, for the record.

One relatively easy ways out is to just introduce a new, 107-bit
format in real.c, tell GCC to use that on IRIX, In (a copy of)
encode_ibm_extended, instead of clear_significant_below, you'll want
normalize and round_for_format ieee_double_format.  The copy of
decode_ibm_extended can be an exact copy, and the definition of
ibm_extended_format just need the `+ 53's changed to `+ 54'.

There's some weirdness you'll probably run into having to do with the
maximum number that can be represented.  Even though, by the
definition of 11 bits of exponent and 106 of mantissa (plus the
implicit 1), you'd expect to be able to represent a number with 106
ones in the mantissa and the maximum exponent, you actually can't,
because the addition of a smaller double can't get us there, and
subtracting from a larger first double doesn't work either, since
incrementing it would overflow.  Oops.  Anyway, that's something that
can be worked around somehow when we get to that point.  I have some
ideas, but I don't quite like any of them.  Maybe bring it up in the
list?

Another simple fix that has just occurred to me is to tweak unpack_d
in fp-bit.c so as to compare the sign bits of the upper and lower
doubles and, instead of blindly doing `fraction += xlow', doing
`fraction -= xlow' if the sign bits differ.  This won't get us quite
there in terms of supporting 107 bits of precision (which is
impossible anyway, since for a ``nearly-infinite'' upper double you
get only 106 bits anyway), but should be close enough for the
emulation to be called functional.  Something like this:

--- fp-bit.c.~1.39.~	2003-01-26 08:06:25.000000000 -0200
+++ fp-bit.c	2003-02-03 11:18:35.000000000 -0200
@@ -455,6 +455,7 @@ unpack_d (FLO_union_type * src, fp_numbe
    if (exp != EXPMAX && exp != 0 && low != 0)
      {
        int lowexp = ((int)(low >> HALFFRACBITS)) & ((1 << EXPBITS) - 1);
+       int lowsign = ((int)(low >> (((HALFFRACBITS + EXPBITS))))) & 1;
        int shift;
        fractype xlow;
 
@@ -468,7 +469,10 @@ unpack_d (FLO_union_type * src, fp_numbe
 	 xlow <<= shift;
        else if (shift < 0)
 	 xlow >>= -shift;
-       fraction += xlow;
+       if (sign == lowsign)
+	 fraction += xlow;
+       else
+	 fraction -= xlow;
      }
  }
 # else

-- 
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

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: Irix6 long doubles implemented wrong? (27_io/ostream_inserter_arith)
  2003-02-03 13:07                                                       ` Alexandre Oliva
@ 2003-02-03 15:18                                                         ` Kaveh R. Ghazi
  2003-02-03 16:37                                                           ` Alexandre Oliva
  0 siblings, 1 reply; 72+ messages in thread
From: Kaveh R. Ghazi @ 2003-02-03 15:18 UTC (permalink / raw)
  To: aoliva; +Cc: gcc-bugs, gcc-patches, gcc, libstdc++, oldham, ro, rth

 > From: Alexandre Oliva <aoliva@redhat.com>
 > 
 > On Jan 30, 2003, "Kaveh R. Ghazi" <ghazi@caip.rutgers.edu> wrote:
 > 
 > >> From: Richard Henderson <rth@redhat.com>
 > >> > 
 > >> > unordtf2_libfunc
 > >> 
 > >> This one may be a problem.  We don't know what the actual
 > >> return values are for the comparison functions.  By rights
 > >> it ought to be a tri-state value off of EQ or NE.
 > 
 > > I'm not sure what you mean.  Are you saying that all the gcc
 > > comparison functions are tri-state (-1,0,1) or just the unord one?
 > 
 > There is L_compare_[sdt]f, that is tri-state, but none of the others
 > are, it's just that you sometimes can't distinguish unord from false
 > on the others, such as those of gofast.  If there's no equivalent to
 > the tri-state compare on IRIX, just set the corresponding entry in
 > optabs NULL, and GCC will find other ways to implement it, using eq,
 > ne, gt, ge, lt and le.

Sorry, I'm seeing something different.  First looking at fp-bit.c, all
of the comparison ops (e.g. _eq_f2) call __fpcmp_parts which returns a
tri-state value.  I.e. it's not just L_compare_[sdt]f.

Second, looking at prepare_float_lib_cmp in optabs.c if the optabs are
NULL, it'll only swap GE <-> LE and GT <-> LT in both directions.  So
if at least one or the other isn't defined how will it work?

Anyway, I just found FLOAT_LIB_COMPARE_RETURNS_BOOL in tm.texi which,
judging by the name, appears to be exactly what I need. :-)

		--Kaveh
--
Kaveh R. Ghazi			ghazi@caip.rutgers.edu

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: Irix6 long doubles implemented wrong? (27_io/ostream_inserter_arith)
  2003-02-03 15:18                                                         ` Kaveh R. Ghazi
@ 2003-02-03 16:37                                                           ` Alexandre Oliva
  0 siblings, 0 replies; 72+ messages in thread
From: Alexandre Oliva @ 2003-02-03 16:37 UTC (permalink / raw)
  To: Kaveh R. Ghazi; +Cc: gcc-bugs, gcc-patches, gcc, libstdc++, oldham, ro, rth

On Feb  3, 2003, "Kaveh R. Ghazi" <ghazi@caip.rutgers.edu> wrote:

> Sorry, I'm seeing something different.  First looking at fp-bit.c, all
> of the comparison ops (e.g. _eq_f2) call __fpcmp_parts which returns a
> tri-state value.  I.e. it's not just L_compare_[sdt]f.

Right, but GCC doesn't really care about the 3 states, only about the
truth conditions being met.

> Second, looking at prepare_float_lib_cmp in optabs.c if the optabs are
> NULL, it'll only swap GE <-> LE and GT <-> LT in both directions.  So
> if at least one or the other isn't defined how will it work?

It won't.  I believe this should be enough to get you going, though.

> Anyway, I just found FLOAT_LIB_COMPARE_RETURNS_BOOL in tm.texi which,
> judging by the name, appears to be exactly what I need. :-)

Oh.  How nice.  I didn't realize we had something like this.  In fact,
I hadn't realized that our compare functions weren't bool-like before
I looked at them again today :-)

-- 
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

^ permalink raw reply	[flat|nested] 72+ messages in thread

* RE: Irix6 long doubles implemented wrong?  (27_io/ostream_inserter_arith)
@ 2002-12-17  0:18 Billinghurst, David (CRTS)
  0 siblings, 0 replies; 72+ messages in thread
From: Billinghurst, David (CRTS) @ 2002-12-17  0:18 UTC (permalink / raw)
  To: Kaveh R. Ghazi, aoliva; +Cc: gcc, libstdc++

I'd prefer that it was correct, even if this means breaking the gcc ABI.

-----Original Message-----
From: Kaveh R. Ghazi [mailto:ghazi@caip.rutgers.edu]
Sent: Tuesday, 17 December 2002 4:32 PM
To: aoliva@redhat.com
Cc: gcc-bugs@gcc.gnu.org; gcc@gcc.gnu.org; libstdc++@gcc.gnu.org;
oldham@codesourcery.com; ro@TechFak.Uni-Bielefeld.DE
Subject: Re: Irix6 long doubles implemented wrong?
(27_io/ostream_inserter_arith)


 > From: Alexandre Oliva <aoliva@redhat.com>
 > 
 > On Dec 14, 2002, "Kaveh R. Ghazi" <ghazi@caip.rutgers.edu> wrote:
 > 
 > > Does anyone have any thoughts on this?  (Or better yet a fix?)
 > 
 > I've been working on a patch that will enable us to switch to 128-bit
 > long doubles on mips n32 and n64, but I still need a little bit of
 > polishing and checking (I know that my current patch still doesn't
 > pass long double arguments in the right registers).  I expect to have
 > it finished in the next few days.

Excellent!  Let me know if I can be of service testing your patch.


 > That said, I'm not sure it would be wise to break the gcc ABI on IRIX
 > 6 by introducing this change.  It's not like long double is the most
 > widely used type, but still, I'm a bit concerned about changing it.
 > Opinions?

Considering the current irix libc incompatibility, one cannot
currently input or output long doubles using stdio.  What good is
that? :-)

I definitely support fixing the ABI, perhaps even on the 3.3 branch if
the patch is not too invasive.

		Thanks,
		--Kaveh
--
Kaveh R. Ghazi			ghazi@caip.rutgers.edu

^ permalink raw reply	[flat|nested] 72+ messages in thread

end of thread, other threads:[~2003-02-03 16:37 UTC | newest]

Thread overview: 72+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2002-12-14 14:09 Irix6 long doubles implemented wrong? (27_io/ostream_inserter_arith) Kaveh R. Ghazi
2002-12-16  9:24 ` Rainer Orth
2002-12-16  9:51 ` Alexandre Oliva
2002-12-16  9:52   ` Rainer Orth
2002-12-16 12:23     ` Eric Christopher
2002-12-16 21:58   ` Kaveh R. Ghazi
2002-12-21 10:45     ` Alexandre Oliva
2002-12-22  6:02       ` Kaveh R. Ghazi
2002-12-22 10:24       ` Alexandre Oliva
2002-12-22 10:35         ` Alexandre Oliva
2002-12-23  9:46         ` Alexandre Oliva
2002-12-24 11:07           ` Kaveh R. Ghazi
2002-12-25  8:04             ` Alexandre Oliva
2002-12-26 13:48               ` Alexandre Oliva
2002-12-27  7:06                 ` Alexandre Oliva
2002-12-29  0:22                   ` Kaveh R. Ghazi
2002-12-29  6:06                     ` Alexandre Oliva
2003-01-07 22:57                   ` Richard Henderson
2003-01-08 18:16                     ` Alexandre Oliva
2003-01-08 22:19                       ` Richard Henderson
2003-01-09  9:29                         ` Alexandre Oliva
2003-01-09  9:38                           ` Alexandre Oliva
2003-01-10  1:18                     ` Alexandre Oliva
2003-01-10  2:29                       ` Richard Henderson
2003-01-19 21:02                         ` Kaveh R. Ghazi
2003-01-19 22:15                           ` Alexandre Oliva
2003-01-26 13:00                             ` Alexandre Oliva
2003-01-28 17:32                               ` Alexandre Oliva
2003-01-28 23:38                                 ` Alexandre Oliva
2003-01-26 15:20                             ` Alexandre Oliva
2003-01-26 16:14                               ` Alexandre Oliva
2003-01-26 18:40                                 ` Kaveh R. Ghazi
2003-01-26 21:24                                 ` Kaveh R. Ghazi
2003-01-26 21:25                                   ` Alexandre Oliva
2003-01-27  9:17                                   ` Kaveh R. Ghazi
2003-01-27 10:40                                     ` Alexandre Oliva
2003-01-28  4:52                                       ` Kaveh R. Ghazi
2003-01-28 17:31                                         ` Alexandre Oliva
2003-01-28 19:11                                           ` Kaveh R. Ghazi
2003-01-28 19:23                                             ` Kaveh R. Ghazi
2003-01-28 19:47                                               ` Rainer Orth
     [not found]                                               ` <15926.49701.3! 59482.666471@xayide.TechFak.Uni-Bielefeld.DE>
2003-01-29  6:56                                                 ` Kaveh R. Ghazi
2003-01-29 10:07                                                   ` Richard Henderson
2003-01-29 13:39                                                     ` Alexandre Oliva
2003-01-29 17:26                                                     ` Kaveh R. Ghazi
2003-01-29 18:10                                                       ` Richard Henderson
2003-01-30 23:31                                                         ` Irix6 native long double libcalls progress report (and problem) Kaveh R. Ghazi
2003-01-30 23:49                                                           ` Richard Henderson
2003-02-03 13:22                                                             ` Alexandre Oliva
2003-01-30  8:05                                                     ` Irix6 long doubles implemented wrong? (27_io/ostream_inserter_arith) Kaveh R. Ghazi
2003-02-03 13:07                                                       ` Alexandre Oliva
2003-02-03 15:18                                                         ` Kaveh R. Ghazi
2003-02-03 16:37                                                           ` Alexandre Oliva
2003-01-27 10:41                                     ` Alexandre Oliva
2003-01-26 21:54                                 ` Richard Henderson
2003-01-10  1:37                     ` Alexandre Oliva
2003-01-26 10:07                     ` Alexandre Oliva
2003-01-26 10:42                     ` Alexandre Oliva
2003-01-26 10:45                     ` Alexandre Oliva
2003-01-26 10:53                     ` Alexandre Oliva
2003-01-26 12:07                     ` Alexandre Oliva
2003-01-26 12:20                     ` Alexandre Oliva
2003-01-26 12:50                     ` Alexandre Oliva
2002-12-24 18:15           ` Kaveh R. Ghazi
2003-01-07 22:16             ` Richard Henderson
2003-01-07 22:40           ` Richard Henderson
2003-01-08 18:04             ` Alexandre Oliva
2003-01-08 22:29               ` Richard Henderson
2003-01-08 22:46                 ` Zack Weinberg
2003-01-08 23:13                   ` Richard Henderson
2003-01-09  7:27                 ` Alexandre Oliva
2002-12-17  0:18 Billinghurst, David (CRTS)

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).