This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
Re: Irix6 long doubles implemented wrong? (27_io/ostream_inserter_arith)
> 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 = ¤t_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,