From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 22589 invoked by alias); 26 Dec 2002 02:12:32 -0000 Mailing-List: contact gcc-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Archive: List-Post: List-Help: Sender: gcc-owner@gcc.gnu.org Received: (qmail 22561 invoked from network); 26 Dec 2002 02:12:30 -0000 Received: from unknown (HELO lacrosse.corp.redhat.com) (66.187.233.200) by 209.249.29.67 with SMTP; 26 Dec 2002 02:12:30 -0000 Received: from free.redhat.lsd.ic.unicamp.br (aoliva2.cipe.redhat.com [10.0.1.156]) by lacrosse.corp.redhat.com (8.11.6/8.9.3) with ESMTP id gBQ2C2Y13925; Wed, 25 Dec 2002 21:12:02 -0500 Received: from free.redhat.lsd.ic.unicamp.br (localhost.localdomain [127.0.0.1]) by free.redhat.lsd.ic.unicamp.br (8.12.6/8.12.6) with ESMTP id gBQ2C101024664; Thu, 26 Dec 2002 00:12:01 -0200 Received: (from aoliva@localhost) by free.redhat.lsd.ic.unicamp.br (8.12.6/8.12.6/Submit) id gBQ2BxmU024658; Thu, 26 Dec 2002 00:11:59 -0200 To: "Kaveh R. Ghazi" Cc: gcc-bugs@gcc.gnu.org, gcc-patches@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) References: <200212142145.QAA25890@caip.rutgers.edu> <200212170531.AAA15561@caip.rutgers.edu> <200212241434.JAA22361@caip.rutgers.edu> From: Alexandre Oliva Organization: GCC Team, Red Hat Date: Thu, 26 Dec 2002 13:48:00 -0000 In-Reply-To: Message-ID: User-Agent: Gnus/5.09 (Gnus v5.9.0) Emacs/21.2 MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" X-SW-Source: 2002-12/txt/msg01427.txt.bz2 --=-=-= Content-length: 4020 On Dec 24, 2002, Alexandre Oliva wrote: > On Dec 24, 2002, "Kaveh R. Ghazi" 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. --=-=-= Content-Type: text/x-patch Content-Disposition: inline; filename=gcc-mips-tfmode-emul-take3.patch Content-length: 51093 Index: gcc/ChangeLog from Alexandre Oliva * 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) : 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 }; @@ -3852,12 +3852,12 @@ const struct real_format vax_f_format = 2, 1, 24, + 0, -127, 127, false, false, false, - false, false }; @@ -3868,12 +3868,12 @@ const struct real_format vax_d_format = 2, 1, 56, + 0, -127, 127, false, false, false, - false, false }; @@ -3884,12 +3884,12 @@ const struct real_format vax_g_format = 2, 1, 53, + 0, -1023, 1023, false, false, false, - false, false }; @@ -4065,12 +4065,12 @@ const struct real_format i370_single_for 16, 4, 6, + 0, /* ??? The encoding does allow for "unnormals". */ -64, 63, false, false, false, /* ??? The encoding does allow for "unnormals". */ - false, /* ??? The encoding does allow for "unnormals". */ false }; @@ -4081,12 +4081,12 @@ const struct real_format i370_double_for 16, 4, 14, + 0, /* ??? The encoding does allow for "unnormals". */ -64, 63, false, false, false, /* ??? The encoding does allow for "unnormals". */ - false, /* ??? The encoding does allow for "unnormals". */ false }; @@ -4295,12 +4295,12 @@ const struct real_format c4x_single_form 2, 1, 24, + 0, -126, 128, false, false, false, - false, false }; @@ -4311,12 +4311,12 @@ const struct real_format c4x_extended_fo 2, 1, 32, + 0, -126, 128, false, false, false, - false, false }; @@ -4356,11 +4356,11 @@ const struct real_format real_internal_f 2, 1, SIGNIFICAND_BITS - 2, + 0, -MAX_EXP, MAX_EXP, true, true, - false, true, true }; Index: gcc/real.h =================================================================== RCS file: /cvs/gcc/gcc/gcc/real.h,v retrieving revision 1.59 diff -u -p -r1.59 real.h --- gcc/real.h 22 Oct 2002 00:17:15 -0000 1.59 +++ gcc/real.h 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; -} /* 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 -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 + +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 --=-=-= Content-length: 289 -- 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 --=-=-=--