From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 11290 invoked by alias); 22 Dec 2002 03:43:53 -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 11259 invoked from network); 22 Dec 2002 03:43:51 -0000 Received: from unknown (HELO lacrosse.corp.redhat.com) (66.187.233.200) by 209.249.29.67 with SMTP; 22 Dec 2002 03:43:51 -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 gBM3hXY00336; Sat, 21 Dec 2002 22:43:33 -0500 Received: from free.redhat.lsd.ic.unicamp.br (localhost.localdomain [127.0.0.1]) by free.redhat.lsd.ic.unicamp.br (8.12.5/8.12.5) with ESMTP id gBM3hXeo010663; Sun, 22 Dec 2002 01:43:33 -0200 Received: (from aoliva@localhost) by free.redhat.lsd.ic.unicamp.br (8.12.5/8.12.5/Submit) id gBM3hWho010659; Sun, 22 Dec 2002 01:43:32 -0200 To: "Kaveh R. Ghazi" , gcc-patches@gcc.gnu.org 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) References: <200212142145.QAA25890@caip.rutgers.edu> <200212170531.AAA15561@caip.rutgers.edu> From: Alexandre Oliva Organization: GCC Team, Red Hat Date: Sun, 22 Dec 2002 10:24: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/msg01317.txt.bz2 --=-=-= Content-length: 2190 On Dec 21, 2002, Alexandre Oliva 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? --=-=-= Content-Type: text/x-patch Content-Disposition: inline; filename=gcc-mips-tfmode-emul.patch Content-length: 40952 ? gcc/config/mips/_tilib.c 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. (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) : 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; -} /* 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 -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 --=-=-= 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 --=-=-=--