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