Commit 17caeff2 by Joseph Myers Committed by Joseph Myers

rs6000-c.c (rs6000_cpu_cpp_builtins): Define _SOFT_DOUBLE if doubles use software floating-point.

gcc:
	* config/rs6000/rs6000-c.c (rs6000_cpu_cpp_builtins): Define
	_SOFT_DOUBLE if doubles use software floating-point.
	* config/rs6000/libgcc-ppc-glibc.ver: Export additional long
	double functions if _SOFT_DOUBLE, not _SOFT_FLOAT.
	* config/rs6000/darwin-ldouble.c: Also compile functions for
	hard-float without FPRs.  Use fmsub function for all __NO_FPRS__
	cases.  Compile extra functions if _SOFT_DOUBLE, not _SOFT_FLOAT.
	* config/rs6000/linuxspe.h (SUBSUBTARGET_OVERRIDE_OPTIONS): Remove
	commented-out long double override.
	(CPP_LONGDOUBLE_DEFAULT_SPEC): Likewise.
	* config/rs6000/eabispe.h: Likewise.
	* config/rs6000/rs6000.c (rs6000_override_options): Don't override
	long double for non-SPE.
	(rs6000_handle_option): Likewise.
	(invalid_e500_subreg): Disallow more subregs involding DImode,
	DFmode, TImode or TFmode.
	(rs6000_legitimate_offset_address_p): Check TFmode offsets for
	E500 double.
	(legitimate_lo_sum_address_p): Also check for TFmode for E500
	double.
	(rs6000_legitimize_address): Also handle TFmode for E500 double.
	(rs6000_legitimize_reload_address): Also handle TFmode for E500
	double.
	(rs6000_legitimate_address): Also check for TFmode for E500
	double.
	(rs6000_emit_move): Use DFmode subregs of TFmode for E500 double.
	(spe_build_register_parallel): Handle TFmode and TCmode.
	(rs6000_spe_function_arg): Handle TFmode and TCmode for E500
	double.
	(function_arg): Handle TFmode and TCmode for E500 double.
	(rs6000_init_libfuncs): Initialize extra libfuncs for soft double
	in general.
	(print_operand): Handle TFmode and TImode for %y.
	(rs6000_generate_compare): Handle TFmode comparisons for E500
	double.
	(spe_func_has_64bit_regs_p): Check for TFmode for E500 double.
	(rs6000_function_value): Handle TFmode and TCmode for E500 double.
	(rs6000_libcall_value): Handle TFmode and TCmode for E500 double.
	* config/rs6000/rs6000.h (CANNOT_CHANGE_MODE_CLASS): Check for
	TFmode for E500 double.
	* config/rs6000/rs6000.md (FP): Allow TF for E500 double.
	(floatsidf2): Enable for E500 double.
	(movtf_softfloat): Use rs6000_nonimmediate_operand.
	(extenddftf2): Change to extenddftf2_fprs.
	(extenddftf2): Call gen_spe_extenddftf2 or gen_extenddftf2_fprs
	depending on TARGET_E500_DOUBLE.
	(extendsftf2): Enable for E500 double.
	(trunctfdf2): Enable for E500 double.
	(trunctfsf2): Change to trunctfsf2_fprs.
	(trunctfsf2): Call gen_spe_trunctfsf2 or gen_trunctfsf2_fprs
	depending on TARGET_E500_DOUBLE.
	(floatsitf2): Enable for E500 double.
	(fix_trunctfsi2): Change to fix_trunctfsi2_fprs.
	(fix_trunctfsi2): Call gen_spe_fix_trunctfsi2 or
	gen_fix_trunctfsi2_fprs depending on TARGET_E500_DOUBLE.
	(negtf2): Change to negtf2_internal.
	(negtf2): New expander.
	(abstf2): Enable for E500 double.  Call gen_spe_abstf2_tst,
	gen_spe_abstf2_cmp or gen_abstf2_internal depending on
	TARGET_E500_DOUBLE and flag_unsafe_math_optimizations.
	(movdi_internal32): Use rs6000_nonimmediate_operand.
	(unnamed splitter): Likewise.
	* config/rs6000/spe.md (CMPTFEQ_GPR, TSTTFEQ_GPR, CMPTFGT_GPR,
	TSTTFGT_GPR, CMPTFLT_GPR, TSTTFLT_GPR): New unspecs.
	(SPE64TF, DITI): New mode macros.
	(frob_df_di): Change to frob_<SPE64:mode>_<DITI:mode>; allow more
	modes.
	(frob_tf_ti): New.
	(frob_<mode>_di_2): New.
	(frob_tf_di_8_2): New.
	(frob_di_df): Change to frob_di_<mode>; allow more modes.
	(frob_ti_tf): New.
	(frob_di_df_2): Change to frob_<DITI:mode>_<SPE64:mode>_2; allow
	more modes.
	(frob_ti_<mode>_8_2): New.
	(frob_ti_tf_2): New.
	(mov_si<mode>_e500_subreg0, mov_si<mode>_e500_subreg0_2,
	mov_si<mode>_e500_subreg4, mov_si<mode>_e500_subreg4_2): Allow
	TFmode.
	(mov_sitf_e500_subreg8, mov_sitf_e500_subreg8_2,
	mov_sitf_e500_subreg12, mov_sitf_e500_subreg12_2): New.
	(spe_trunctfdf2_internal1, spe_trunctfsf2, spe_extenddftf2,
	spe_fix_trunctfsi2, spe_fix_trunctfsi2_internal,
	spe_negtf2_internal, spe_abstf2_cmp, spe_abstf2_tst): New.
	(cmptfeq_gpr, tsttfeq_gpr, cmptfgt_gpr, tsttfgt_gpr, cmptflt_gpr,
	tsttflt_gp): New.

libgcc:
	* config/rs6000/t-ldbl128: Always use -mlong-double-128.

From-SVN: r121085
parent dc569621
2007-01-23 Joseph Myers <joseph@codesourcery.com>
* config/rs6000/rs6000-c.c (rs6000_cpu_cpp_builtins): Define
_SOFT_DOUBLE if doubles use software floating-point.
* config/rs6000/libgcc-ppc-glibc.ver: Export additional long
double functions if _SOFT_DOUBLE, not _SOFT_FLOAT.
* config/rs6000/darwin-ldouble.c: Also compile functions for
hard-float without FPRs. Use fmsub function for all __NO_FPRS__
cases. Compile extra functions if _SOFT_DOUBLE, not _SOFT_FLOAT.
* config/rs6000/linuxspe.h (SUBSUBTARGET_OVERRIDE_OPTIONS): Remove
commented-out long double override.
(CPP_LONGDOUBLE_DEFAULT_SPEC): Likewise.
* config/rs6000/eabispe.h: Likewise.
* config/rs6000/rs6000.c (rs6000_override_options): Don't override
long double for non-SPE.
(rs6000_handle_option): Likewise.
(invalid_e500_subreg): Disallow more subregs involding DImode,
DFmode, TImode or TFmode.
(rs6000_legitimate_offset_address_p): Check TFmode offsets for
E500 double.
(legitimate_lo_sum_address_p): Also check for TFmode for E500
double.
(rs6000_legitimize_address): Also handle TFmode for E500 double.
(rs6000_legitimize_reload_address): Also handle TFmode for E500
double.
(rs6000_legitimate_address): Also check for TFmode for E500
double.
(rs6000_emit_move): Use DFmode subregs of TFmode for E500 double.
(spe_build_register_parallel): Handle TFmode and TCmode.
(rs6000_spe_function_arg): Handle TFmode and TCmode for E500
double.
(function_arg): Handle TFmode and TCmode for E500 double.
(rs6000_init_libfuncs): Initialize extra libfuncs for soft double
in general.
(print_operand): Handle TFmode and TImode for %y.
(rs6000_generate_compare): Handle TFmode comparisons for E500
double.
(spe_func_has_64bit_regs_p): Check for TFmode for E500 double.
(rs6000_function_value): Handle TFmode and TCmode for E500 double.
(rs6000_libcall_value): Handle TFmode and TCmode for E500 double.
* config/rs6000/rs6000.h (CANNOT_CHANGE_MODE_CLASS): Check for
TFmode for E500 double.
* config/rs6000/rs6000.md (FP): Allow TF for E500 double.
(floatsidf2): Enable for E500 double.
(movtf_softfloat): Use rs6000_nonimmediate_operand.
(extenddftf2): Change to extenddftf2_fprs.
(extenddftf2): Call gen_spe_extenddftf2 or gen_extenddftf2_fprs
depending on TARGET_E500_DOUBLE.
(extendsftf2): Enable for E500 double.
(trunctfdf2): Enable for E500 double.
(trunctfsf2): Change to trunctfsf2_fprs.
(trunctfsf2): Call gen_spe_trunctfsf2 or gen_trunctfsf2_fprs
depending on TARGET_E500_DOUBLE.
(floatsitf2): Enable for E500 double.
(fix_trunctfsi2): Change to fix_trunctfsi2_fprs.
(fix_trunctfsi2): Call gen_spe_fix_trunctfsi2 or
gen_fix_trunctfsi2_fprs depending on TARGET_E500_DOUBLE.
(negtf2): Change to negtf2_internal.
(negtf2): New expander.
(abstf2): Enable for E500 double. Call gen_spe_abstf2_tst,
gen_spe_abstf2_cmp or gen_abstf2_internal depending on
TARGET_E500_DOUBLE and flag_unsafe_math_optimizations.
(movdi_internal32): Use rs6000_nonimmediate_operand.
(unnamed splitter): Likewise.
* config/rs6000/spe.md (CMPTFEQ_GPR, TSTTFEQ_GPR, CMPTFGT_GPR,
TSTTFGT_GPR, CMPTFLT_GPR, TSTTFLT_GPR): New unspecs.
(SPE64TF, DITI): New mode macros.
(frob_df_di): Change to frob_<SPE64:mode>_<DITI:mode>; allow more
modes.
(frob_tf_ti): New.
(frob_<mode>_di_2): New.
(frob_tf_di_8_2): New.
(frob_di_df): Change to frob_di_<mode>; allow more modes.
(frob_ti_tf): New.
(frob_di_df_2): Change to frob_<DITI:mode>_<SPE64:mode>_2; allow
more modes.
(frob_ti_<mode>_8_2): New.
(frob_ti_tf_2): New.
(mov_si<mode>_e500_subreg0, mov_si<mode>_e500_subreg0_2,
mov_si<mode>_e500_subreg4, mov_si<mode>_e500_subreg4_2): Allow
TFmode.
(mov_sitf_e500_subreg8, mov_sitf_e500_subreg8_2,
mov_sitf_e500_subreg12, mov_sitf_e500_subreg12_2): New.
(spe_trunctfdf2_internal1, spe_trunctfsf2, spe_extenddftf2,
spe_fix_trunctfsi2, spe_fix_trunctfsi2_internal,
spe_negtf2_internal, spe_abstf2_cmp, spe_abstf2_tst): New.
(cmptfeq_gpr, tsttfeq_gpr, cmptfgt_gpr, tsttfgt_gpr, cmptflt_gpr,
tsttflt_gp): New.
2007-01-23 Ian Lance Taylor <iant@google.com> 2007-01-23 Ian Lance Taylor <iant@google.com>
* Makefile.in (OBJS-common): Reformat, alphabetize, but put * Makefile.in (OBJS-common): Reformat, alphabetize, but put
......
/* 128-bit long double support routines for Darwin. /* 128-bit long double support routines for Darwin.
Copyright (C) 1993, 2003, 2004, 2005, 2006 Copyright (C) 1993, 2003, 2004, 2005, 2006, 2007
Free Software Foundation, Inc. Free Software Foundation, Inc.
This file is part of GCC. This file is part of GCC.
...@@ -49,8 +49,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA ...@@ -49,8 +49,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
This code currently assumes big-endian. */ This code currently assumes big-endian. */
#if ((!defined (__NO_FPRS__) || defined (_SOFT_FLOAT)) \ #if (!defined (__LITTLE_ENDIAN__) \
&& !defined (__LITTLE_ENDIAN__) \
&& (defined (__MACH__) || defined (__powerpc__) || defined (_AIX))) && (defined (__MACH__) || defined (__powerpc__) || defined (_AIX)))
#define fabs(x) __builtin_fabs(x) #define fabs(x) __builtin_fabs(x)
...@@ -145,7 +144,7 @@ __gcc_qsub (double a, double b, double c, double d) ...@@ -145,7 +144,7 @@ __gcc_qsub (double a, double b, double c, double d)
return __gcc_qadd (a, b, -c, -d); return __gcc_qadd (a, b, -c, -d);
} }
#ifdef _SOFT_FLOAT #ifdef __NO_FPRS__
static double fmsub (double, double, double); static double fmsub (double, double, double);
#endif #endif
...@@ -164,7 +163,7 @@ __gcc_qmul (double a, double b, double c, double d) ...@@ -164,7 +163,7 @@ __gcc_qmul (double a, double b, double c, double d)
/* Sum terms of two highest orders. */ /* Sum terms of two highest orders. */
/* Use fused multiply-add to get low part of a * c. */ /* Use fused multiply-add to get low part of a * c. */
#ifndef _SOFT_FLOAT #ifndef __NO_FPRS__
asm ("fmsub %0,%1,%2,%3" : "=f"(tau) : "f"(a), "f"(c), "f"(t)); asm ("fmsub %0,%1,%2,%3" : "=f"(tau) : "f"(a), "f"(c), "f"(t));
#else #else
tau = fmsub (a, c, t); tau = fmsub (a, c, t);
...@@ -201,7 +200,7 @@ __gcc_qdiv (double a, double b, double c, double d) ...@@ -201,7 +200,7 @@ __gcc_qdiv (double a, double b, double c, double d)
numerically necessary. */ numerically necessary. */
/* Use fused multiply-add to get low part of c * t. */ /* Use fused multiply-add to get low part of c * t. */
#ifndef _SOFT_FLOAT #ifndef __NO_FPRS__
asm ("fmsub %0,%1,%2,%3" : "=f"(sigma) : "f"(c), "f"(t), "f"(s)); asm ("fmsub %0,%1,%2,%3" : "=f"(sigma) : "f"(c), "f"(t), "f"(s));
#else #else
sigma = fmsub (c, t, s); sigma = fmsub (c, t, s);
...@@ -219,7 +218,7 @@ __gcc_qdiv (double a, double b, double c, double d) ...@@ -219,7 +218,7 @@ __gcc_qdiv (double a, double b, double c, double d)
return z.ldval; return z.ldval;
} }
#if defined (_SOFT_FLOAT) && defined (__LONG_DOUBLE_128__) #if defined (_SOFT_DOUBLE) && defined (__LONG_DOUBLE_128__)
long double __gcc_qneg (double, double); long double __gcc_qneg (double, double);
int __gcc_qeq (double, double, double, double); int __gcc_qeq (double, double, double, double);
...@@ -362,6 +361,10 @@ __gcc_utoq (unsigned int a) ...@@ -362,6 +361,10 @@ __gcc_utoq (unsigned int a)
return __gcc_dtoq ((double) a); return __gcc_dtoq ((double) a);
} }
#endif
#ifdef __NO_FPRS__
#include "config/soft-fp/soft-fp.h" #include "config/soft-fp/soft-fp.h"
#include "config/soft-fp/double.h" #include "config/soft-fp/double.h"
#include "config/soft-fp/quad.h" #include "config/soft-fp/quad.h"
......
/* Core target definitions for GNU compiler /* Core target definitions for GNU compiler
for PowerPC embedded targeted systems with SPE support. for PowerPC embedded targeted systems with SPE support.
Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007
Free Software Foundation, Inc.
Contributed by Aldy Hernandez (aldyh@redhat.com). Contributed by Aldy Hernandez (aldyh@redhat.com).
This file is part of GCC. This file is part of GCC.
...@@ -35,9 +36,6 @@ ...@@ -35,9 +36,6 @@
rs6000_spe_abi = 1; \ rs6000_spe_abi = 1; \
if (!rs6000_explicit_options.float_gprs) \ if (!rs6000_explicit_options.float_gprs) \
rs6000_float_gprs = 1; \ rs6000_float_gprs = 1; \
/* See note below. */ \
/*if (!rs6000_explicit_options.long_double)*/ \
/* rs6000_long_double_type_size = 128;*/ \
if (!rs6000_explicit_options.spe) \ if (!rs6000_explicit_options.spe) \
rs6000_spe = 1; \ rs6000_spe = 1; \
if (!rs6000_explicit_options.isel) \ if (!rs6000_explicit_options.isel) \
...@@ -52,8 +50,7 @@ ...@@ -52,8 +50,7 @@
specifications, until I properly fix the emulation. specifications, until I properly fix the emulation.
Enable these later. Enable these later.
#undef CPP_LONGDOUBLE_DEFAULT_SPEC #define RS6000_DEFAULT_LONG_DOUBLE_SIZE (TARGET_SPE ? 128 : 64)
#define CPP_LONGDOUBLE_DEFAULT_SPEC "-D__LONG_DOUBLE_128__=1"
*/ */
#undef ASM_DEFAULT_SPEC #undef ASM_DEFAULT_SPEC
......
...@@ -31,7 +31,7 @@ GCC_4.2.0 { ...@@ -31,7 +31,7 @@ GCC_4.2.0 {
__gcc_qmul __gcc_qmul
__gcc_qdiv __gcc_qdiv
%ifdef _SOFT_FLOAT %ifdef _SOFT_DOUBLE
__gcc_qneg __gcc_qneg
__gcc_qeq __gcc_qeq
__gcc_qne __gcc_qne
......
...@@ -35,9 +35,6 @@ ...@@ -35,9 +35,6 @@
rs6000_spe_abi = 1; \ rs6000_spe_abi = 1; \
if (!rs6000_explicit_options.float_gprs) \ if (!rs6000_explicit_options.float_gprs) \
rs6000_float_gprs = 1; \ rs6000_float_gprs = 1; \
/* See note below. */ \
/*if (!rs6000_explicit_options.long_double)*/ \
/* rs6000_long_double_type_size = 128;*/ \
if (!rs6000_explicit_options.spe) \ if (!rs6000_explicit_options.spe) \
rs6000_spe = 1; \ rs6000_spe = 1; \
if (!rs6000_explicit_options.isel) \ if (!rs6000_explicit_options.isel) \
...@@ -45,16 +42,5 @@ ...@@ -45,16 +42,5 @@
if (target_flags & MASK_64BIT) \ if (target_flags & MASK_64BIT) \
error ("-m64 not supported in this configuration") error ("-m64 not supported in this configuration")
/* The e500 ABI says that either long doubles are 128 bits, or if
implemented in any other size, the compiler/linker should error out.
We have no emulation libraries for 128 bit long doubles, and I hate
the dozens of failures on the regression suite. So I'm breaking ABI
specifications, until I properly fix the emulation.
Enable these later.
#undef CPP_LONGDOUBLE_DEFAULT_SPEC
#define CPP_LONGDOUBLE_DEFAULT_SPEC "-D__LONG_DOUBLE_128__=1"
*/
#undef ASM_DEFAULT_SPEC #undef ASM_DEFAULT_SPEC
#define ASM_DEFAULT_SPEC "-mppc -mspe -me500" #define ASM_DEFAULT_SPEC "-mppc -mspe -me500"
/* Subroutines for the C front end on the POWER and PowerPC architectures. /* Subroutines for the C front end on the POWER and PowerPC architectures.
Copyright (C) 2002, 2003, 2004, 2005 Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007
Free Software Foundation, Inc. Free Software Foundation, Inc.
Contributed by Zack Weinberg <zack@codesourcery.com> Contributed by Zack Weinberg <zack@codesourcery.com>
...@@ -124,6 +124,8 @@ rs6000_cpu_cpp_builtins (cpp_reader *pfile) ...@@ -124,6 +124,8 @@ rs6000_cpu_cpp_builtins (cpp_reader *pfile)
builtin_define ("__SPE__"); builtin_define ("__SPE__");
if (TARGET_SOFT_FLOAT) if (TARGET_SOFT_FLOAT)
builtin_define ("_SOFT_FLOAT"); builtin_define ("_SOFT_FLOAT");
if (!(TARGET_HARD_FLOAT && (TARGET_FPRS || TARGET_E500_DOUBLE)))
builtin_define ("_SOFT_DOUBLE");
/* Used by lwarx/stwcx. errata work-around. */ /* Used by lwarx/stwcx. errata work-around. */
if (rs6000_cpu == PROCESSOR_PPC405) if (rs6000_cpu == PROCESSOR_PPC405)
builtin_define ("__PPC405__"); builtin_define ("__PPC405__");
......
...@@ -1464,8 +1464,6 @@ rs6000_override_options (const char *default_cpu) ...@@ -1464,8 +1464,6 @@ rs6000_override_options (const char *default_cpu)
rs6000_float_gprs = 0; rs6000_float_gprs = 0;
if (!rs6000_explicit_options.isel) if (!rs6000_explicit_options.isel)
rs6000_isel = 0; rs6000_isel = 0;
if (!rs6000_explicit_options.long_double)
rs6000_long_double_type_size = RS6000_DEFAULT_LONG_DOUBLE_SIZE;
} }
/* Detect invalid option combinations with E500. */ /* Detect invalid option combinations with E500. */
...@@ -1892,9 +1890,6 @@ rs6000_handle_option (size_t code, const char *arg, int value) ...@@ -1892,9 +1890,6 @@ rs6000_handle_option (size_t code, const char *arg, int value)
case OPT_mspe_: case OPT_mspe_:
rs6000_explicit_options.spe = true; rs6000_explicit_options.spe = true;
rs6000_parse_yes_no_option ("spe", arg, &(rs6000_spe)); rs6000_parse_yes_no_option ("spe", arg, &(rs6000_spe));
/* No SPE means 64-bit long doubles, even if an E500. */
if (!rs6000_spe)
rs6000_long_double_type_size = 64;
break; break;
case OPT_mdebug_: case OPT_mdebug_:
...@@ -2718,18 +2713,22 @@ invalid_e500_subreg (rtx op, enum machine_mode mode) ...@@ -2718,18 +2713,22 @@ invalid_e500_subreg (rtx op, enum machine_mode mode)
{ {
if (TARGET_E500_DOUBLE) if (TARGET_E500_DOUBLE)
{ {
/* Reject (subreg:SI (reg:DF)). */ /* Reject (subreg:SI (reg:DF)); likewise with subreg:DI or
subreg:TI and reg:TF. */
if (GET_CODE (op) == SUBREG if (GET_CODE (op) == SUBREG
&& mode == SImode && (mode == SImode || mode == DImode || mode == TImode)
&& REG_P (SUBREG_REG (op)) && REG_P (SUBREG_REG (op))
&& GET_MODE (SUBREG_REG (op)) == DFmode) && (GET_MODE (SUBREG_REG (op)) == DFmode
|| GET_MODE (SUBREG_REG (op)) == TFmode))
return true; return true;
/* Reject (subreg:DF (reg:DI)). */ /* Reject (subreg:DF (reg:DI)); likewise with subreg:TF and
reg:TI. */
if (GET_CODE (op) == SUBREG if (GET_CODE (op) == SUBREG
&& mode == DFmode && (mode == DFmode || mode == TFmode)
&& REG_P (SUBREG_REG (op)) && REG_P (SUBREG_REG (op))
&& GET_MODE (SUBREG_REG (op)) == DImode) && (GET_MODE (SUBREG_REG (op)) == DImode
|| GET_MODE (SUBREG_REG (op)) == TImode))
return true; return true;
} }
...@@ -2989,6 +2988,10 @@ rs6000_legitimate_offset_address_p (enum machine_mode mode, rtx x, int strict) ...@@ -2989,6 +2988,10 @@ rs6000_legitimate_offset_address_p (enum machine_mode mode, rtx x, int strict)
break; break;
case TFmode: case TFmode:
if (TARGET_E500_DOUBLE)
return (SPE_CONST_OFFSET_OK (offset)
&& SPE_CONST_OFFSET_OK (offset + 8));
case TImode: case TImode:
if (mode == TFmode || !TARGET_POWERPC64) if (mode == TFmode || !TARGET_POWERPC64)
extra = 12; extra = 12;
...@@ -3067,7 +3070,8 @@ legitimate_lo_sum_address_p (enum machine_mode mode, rtx x, int strict) ...@@ -3067,7 +3070,8 @@ legitimate_lo_sum_address_p (enum machine_mode mode, rtx x, int strict)
if (!INT_REG_OK_FOR_BASE_P (XEXP (x, 0), strict)) if (!INT_REG_OK_FOR_BASE_P (XEXP (x, 0), strict))
return false; return false;
/* Restrict addressing for DI because of our SUBREG hackery. */ /* Restrict addressing for DI because of our SUBREG hackery. */
if (TARGET_E500_DOUBLE && (mode == DFmode || mode == DImode)) if (TARGET_E500_DOUBLE && (mode == DFmode || mode == TFmode
|| mode == DImode))
return false; return false;
x = XEXP (x, 1); x = XEXP (x, 1);
...@@ -3165,7 +3169,7 @@ rs6000_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED, ...@@ -3165,7 +3169,7 @@ rs6000_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
return reg; return reg;
} }
else if (SPE_VECTOR_MODE (mode) else if (SPE_VECTOR_MODE (mode)
|| (TARGET_E500_DOUBLE && (mode == DFmode || (TARGET_E500_DOUBLE && (mode == DFmode || mode == TFmode
|| mode == DImode))) || mode == DImode)))
{ {
if (mode == DImode) if (mode == DImode)
...@@ -3570,7 +3574,7 @@ rs6000_legitimize_reload_address (rtx x, enum machine_mode mode, ...@@ -3570,7 +3574,7 @@ rs6000_legitimize_reload_address (rtx x, enum machine_mode mode,
&& REG_MODE_OK_FOR_BASE_P (XEXP (x, 0), mode) && REG_MODE_OK_FOR_BASE_P (XEXP (x, 0), mode)
&& GET_CODE (XEXP (x, 1)) == CONST_INT && GET_CODE (XEXP (x, 1)) == CONST_INT
&& !SPE_VECTOR_MODE (mode) && !SPE_VECTOR_MODE (mode)
&& !(TARGET_E500_DOUBLE && (mode == DFmode && !(TARGET_E500_DOUBLE && (mode == DFmode || mode == TFmode
|| mode == DImode)) || mode == DImode))
&& !ALTIVEC_VECTOR_MODE (mode)) && !ALTIVEC_VECTOR_MODE (mode))
{ {
...@@ -3707,7 +3711,8 @@ rs6000_legitimate_address (enum machine_mode mode, rtx x, int reg_ok_strict) ...@@ -3707,7 +3711,8 @@ rs6000_legitimate_address (enum machine_mode mode, rtx x, int reg_ok_strict)
&& !SPE_VECTOR_MODE (mode) && !SPE_VECTOR_MODE (mode)
&& mode != TFmode && mode != TFmode
/* Restrict addressing for DI because of our SUBREG hackery. */ /* Restrict addressing for DI because of our SUBREG hackery. */
&& !(TARGET_E500_DOUBLE && (mode == DFmode || mode == DImode)) && !(TARGET_E500_DOUBLE && (mode == DFmode || mode == TFmode
|| mode == DImode))
&& TARGET_UPDATE && TARGET_UPDATE
&& legitimate_indirect_address_p (XEXP (x, 0), reg_ok_strict)) && legitimate_indirect_address_p (XEXP (x, 0), reg_ok_strict))
return 1; return 1;
...@@ -4222,14 +4227,15 @@ rs6000_emit_move (rtx dest, rtx source, enum machine_mode mode) ...@@ -4222,14 +4227,15 @@ rs6000_emit_move (rtx dest, rtx source, enum machine_mode mode)
{ {
/* DImode is used, not DFmode, because simplify_gen_subreg doesn't /* DImode is used, not DFmode, because simplify_gen_subreg doesn't
know how to get a DFmode SUBREG of a TFmode. */ know how to get a DFmode SUBREG of a TFmode. */
rs6000_emit_move (simplify_gen_subreg (DImode, operands[0], mode, 0), enum machine_mode imode = (TARGET_E500_DOUBLE ? DFmode : DImode);
simplify_gen_subreg (DImode, operands[1], mode, 0), rs6000_emit_move (simplify_gen_subreg (imode, operands[0], mode, 0),
DImode); simplify_gen_subreg (imode, operands[1], mode, 0),
rs6000_emit_move (simplify_gen_subreg (DImode, operands[0], mode, imode);
GET_MODE_SIZE (DImode)), rs6000_emit_move (simplify_gen_subreg (imode, operands[0], mode,
simplify_gen_subreg (DImode, operands[1], mode, GET_MODE_SIZE (imode)),
GET_MODE_SIZE (DImode)), simplify_gen_subreg (imode, operands[1], mode,
DImode); GET_MODE_SIZE (imode)),
imode);
return; return;
} }
...@@ -5019,7 +5025,7 @@ function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode, ...@@ -5019,7 +5025,7 @@ function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
static rtx static rtx
spe_build_register_parallel (enum machine_mode mode, int gregno) spe_build_register_parallel (enum machine_mode mode, int gregno)
{ {
rtx r1, r3; rtx r1, r3, r5, r7;
switch (mode) switch (mode)
{ {
...@@ -5029,12 +5035,24 @@ spe_build_register_parallel (enum machine_mode mode, int gregno) ...@@ -5029,12 +5035,24 @@ spe_build_register_parallel (enum machine_mode mode, int gregno)
return gen_rtx_PARALLEL (mode, gen_rtvec (1, r1)); return gen_rtx_PARALLEL (mode, gen_rtvec (1, r1));
case DCmode: case DCmode:
case TFmode:
r1 = gen_rtx_REG (DImode, gregno); r1 = gen_rtx_REG (DImode, gregno);
r1 = gen_rtx_EXPR_LIST (VOIDmode, r1, const0_rtx); r1 = gen_rtx_EXPR_LIST (VOIDmode, r1, const0_rtx);
r3 = gen_rtx_REG (DImode, gregno + 2); r3 = gen_rtx_REG (DImode, gregno + 2);
r3 = gen_rtx_EXPR_LIST (VOIDmode, r3, GEN_INT (8)); r3 = gen_rtx_EXPR_LIST (VOIDmode, r3, GEN_INT (8));
return gen_rtx_PARALLEL (mode, gen_rtvec (2, r1, r3)); return gen_rtx_PARALLEL (mode, gen_rtvec (2, r1, r3));
case TCmode:
r1 = gen_rtx_REG (DImode, gregno);
r1 = gen_rtx_EXPR_LIST (VOIDmode, r1, const0_rtx);
r3 = gen_rtx_REG (DImode, gregno + 2);
r3 = gen_rtx_EXPR_LIST (VOIDmode, r3, GEN_INT (8));
r5 = gen_rtx_REG (DImode, gregno + 4);
r5 = gen_rtx_EXPR_LIST (VOIDmode, r5, GEN_INT (16));
r7 = gen_rtx_REG (DImode, gregno + 6);
r7 = gen_rtx_EXPR_LIST (VOIDmode, r7, GEN_INT (24));
return gen_rtx_PARALLEL (mode, gen_rtvec (4, r1, r3, r5, r7));
default: default:
gcc_unreachable (); gcc_unreachable ();
} }
...@@ -5049,7 +5067,8 @@ rs6000_spe_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, ...@@ -5049,7 +5067,8 @@ rs6000_spe_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
/* On E500 v2, double arithmetic is done on the full 64-bit GPR, but /* On E500 v2, double arithmetic is done on the full 64-bit GPR, but
are passed and returned in a pair of GPRs for ABI compatibility. */ are passed and returned in a pair of GPRs for ABI compatibility. */
if (TARGET_E500_DOUBLE && (mode == DFmode || mode == DCmode)) if (TARGET_E500_DOUBLE && (mode == DFmode || mode == DCmode
|| mode == TFmode || mode == TCmode))
{ {
int n_words = rs6000_arg_size (mode, type); int n_words = rs6000_arg_size (mode, type);
...@@ -5467,7 +5486,9 @@ function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, ...@@ -5467,7 +5486,9 @@ function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
else if (TARGET_SPE_ABI && TARGET_SPE else if (TARGET_SPE_ABI && TARGET_SPE
&& (SPE_VECTOR_MODE (mode) && (SPE_VECTOR_MODE (mode)
|| (TARGET_E500_DOUBLE && (mode == DFmode || (TARGET_E500_DOUBLE && (mode == DFmode
|| mode == DCmode)))) || mode == DCmode
|| mode == TFmode
|| mode == TCmode))))
return rs6000_spe_function_arg (cum, mode, type); return rs6000_spe_function_arg (cum, mode, type);
else if (abi == ABI_V4) else if (abi == ABI_V4)
...@@ -9420,7 +9441,7 @@ rs6000_init_libfuncs (void) ...@@ -9420,7 +9441,7 @@ rs6000_init_libfuncs (void)
set_optab_libfunc (smul_optab, TFmode, "__gcc_qmul"); set_optab_libfunc (smul_optab, TFmode, "__gcc_qmul");
set_optab_libfunc (sdiv_optab, TFmode, "__gcc_qdiv"); set_optab_libfunc (sdiv_optab, TFmode, "__gcc_qdiv");
if (TARGET_SOFT_FLOAT) if (!(TARGET_HARD_FLOAT && (TARGET_FPRS || TARGET_E500_DOUBLE)))
{ {
set_optab_libfunc (neg_optab, TFmode, "__gcc_qneg"); set_optab_libfunc (neg_optab, TFmode, "__gcc_qneg");
set_optab_libfunc (eq_optab, TFmode, "__gcc_qeq"); set_optab_libfunc (eq_optab, TFmode, "__gcc_qeq");
...@@ -11034,7 +11055,9 @@ print_operand (FILE *file, rtx x, int code) ...@@ -11034,7 +11055,9 @@ print_operand (FILE *file, rtx x, int code)
/* Ugly hack because %y is overloaded. */ /* Ugly hack because %y is overloaded. */
if ((TARGET_SPE || TARGET_E500_DOUBLE) if ((TARGET_SPE || TARGET_E500_DOUBLE)
&& GET_MODE_SIZE (GET_MODE (x)) == 8) && (GET_MODE_SIZE (GET_MODE (x)) == 8
|| GET_MODE (x) == TFmode
|| GET_MODE (x) == TImode))
{ {
/* Handle [reg]. */ /* Handle [reg]. */
if (GET_CODE (tmp) == REG) if (GET_CODE (tmp) == REG)
...@@ -11366,6 +11389,14 @@ rs6000_generate_compare (enum rtx_code code) ...@@ -11366,6 +11389,14 @@ rs6000_generate_compare (enum rtx_code code)
rs6000_compare_op1); rs6000_compare_op1);
break; break;
case TFmode:
cmp = flag_unsafe_math_optimizations
? gen_tsttfeq_gpr (compare_result, rs6000_compare_op0,
rs6000_compare_op1)
: gen_cmptfeq_gpr (compare_result, rs6000_compare_op0,
rs6000_compare_op1);
break;
default: default:
gcc_unreachable (); gcc_unreachable ();
} }
...@@ -11390,6 +11421,14 @@ rs6000_generate_compare (enum rtx_code code) ...@@ -11390,6 +11421,14 @@ rs6000_generate_compare (enum rtx_code code)
rs6000_compare_op1); rs6000_compare_op1);
break; break;
case TFmode:
cmp = flag_unsafe_math_optimizations
? gen_tsttfgt_gpr (compare_result, rs6000_compare_op0,
rs6000_compare_op1)
: gen_cmptfgt_gpr (compare_result, rs6000_compare_op0,
rs6000_compare_op1);
break;
default: default:
gcc_unreachable (); gcc_unreachable ();
} }
...@@ -11414,6 +11453,14 @@ rs6000_generate_compare (enum rtx_code code) ...@@ -11414,6 +11453,14 @@ rs6000_generate_compare (enum rtx_code code)
rs6000_compare_op1); rs6000_compare_op1);
break; break;
case TFmode:
cmp = flag_unsafe_math_optimizations
? gen_tsttflt_gpr (compare_result, rs6000_compare_op0,
rs6000_compare_op1)
: gen_cmptflt_gpr (compare_result, rs6000_compare_op0,
rs6000_compare_op1);
break;
default: default:
gcc_unreachable (); gcc_unreachable ();
} }
...@@ -11457,6 +11504,14 @@ rs6000_generate_compare (enum rtx_code code) ...@@ -11457,6 +11504,14 @@ rs6000_generate_compare (enum rtx_code code)
rs6000_compare_op1); rs6000_compare_op1);
break; break;
case TFmode:
cmp = flag_unsafe_math_optimizations
? gen_tsttfeq_gpr (compare_result2, rs6000_compare_op0,
rs6000_compare_op1)
: gen_cmptfeq_gpr (compare_result2, rs6000_compare_op0,
rs6000_compare_op1);
break;
default: default:
gcc_unreachable (); gcc_unreachable ();
} }
...@@ -13504,7 +13559,7 @@ spe_func_has_64bit_regs_p (void) ...@@ -13504,7 +13559,7 @@ spe_func_has_64bit_regs_p (void)
if (SPE_VECTOR_MODE (mode)) if (SPE_VECTOR_MODE (mode))
return true; return true;
if (TARGET_E500_DOUBLE && mode == DFmode) if (TARGET_E500_DOUBLE && (mode == DFmode || mode == TFmode))
return true; return true;
} }
} }
...@@ -20274,7 +20329,8 @@ rs6000_function_value (tree valtype, tree func ATTRIBUTE_UNUSED) ...@@ -20274,7 +20329,8 @@ rs6000_function_value (tree valtype, tree func ATTRIBUTE_UNUSED)
&& ALTIVEC_VECTOR_MODE (mode)) && ALTIVEC_VECTOR_MODE (mode))
regno = ALTIVEC_ARG_RETURN; regno = ALTIVEC_ARG_RETURN;
else if (TARGET_E500_DOUBLE && TARGET_HARD_FLOAT else if (TARGET_E500_DOUBLE && TARGET_HARD_FLOAT
&& (mode == DFmode || mode == DCmode)) && (mode == DFmode || mode == DCmode
|| mode == TFmode || mode == TCmode))
return spe_build_register_parallel (mode, GP_ARG_RETURN); return spe_build_register_parallel (mode, GP_ARG_RETURN);
else else
regno = GP_ARG_RETURN; regno = GP_ARG_RETURN;
...@@ -20314,7 +20370,8 @@ rs6000_libcall_value (enum machine_mode mode) ...@@ -20314,7 +20370,8 @@ rs6000_libcall_value (enum machine_mode mode)
else if (COMPLEX_MODE_P (mode) && targetm.calls.split_complex_arg) else if (COMPLEX_MODE_P (mode) && targetm.calls.split_complex_arg)
return rs6000_complex_function_value (mode); return rs6000_complex_function_value (mode);
else if (TARGET_E500_DOUBLE && TARGET_HARD_FLOAT else if (TARGET_E500_DOUBLE && TARGET_HARD_FLOAT
&& (mode == DFmode || mode == DCmode)) && (mode == DFmode || mode == DCmode
|| mode == TFmode || mode == TCmode))
return spe_build_register_parallel (mode, GP_ARG_RETURN); return spe_build_register_parallel (mode, GP_ARG_RETURN);
else else
regno = GP_ARG_RETURN; regno = GP_ARG_RETURN;
......
...@@ -1160,6 +1160,7 @@ enum reg_class ...@@ -1160,6 +1160,7 @@ enum reg_class
&& reg_classes_intersect_p (FLOAT_REGS, CLASS)) \ && reg_classes_intersect_p (FLOAT_REGS, CLASS)) \
: (((TARGET_E500_DOUBLE \ : (((TARGET_E500_DOUBLE \
&& ((((TO) == DFmode) + ((FROM) == DFmode)) == 1 \ && ((((TO) == DFmode) + ((FROM) == DFmode)) == 1 \
|| (((TO) == TFmode) + ((FROM) == TFmode)) == 1 \
|| (((TO) == DImode) + ((FROM) == DImode)) == 1)) \ || (((TO) == DImode) + ((FROM) == DImode)) == 1)) \
|| (TARGET_SPE \ || (TARGET_SPE \
&& (SPE_VECTOR_MODE (FROM) + SPE_VECTOR_MODE (TO)) == 1)) \ && (SPE_VECTOR_MODE (FROM) + SPE_VECTOR_MODE (TO)) == 1)) \
......
...@@ -176,7 +176,9 @@ ...@@ -176,7 +176,9 @@
(define_mode_macro FP [(SF "TARGET_HARD_FLOAT") (define_mode_macro FP [(SF "TARGET_HARD_FLOAT")
(DF "TARGET_HARD_FLOAT && (TARGET_FPRS || TARGET_E500_DOUBLE)") (DF "TARGET_HARD_FLOAT && (TARGET_FPRS || TARGET_E500_DOUBLE)")
(TF "!TARGET_IEEEQUAD (TF "!TARGET_IEEEQUAD
&& TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128")]) && TARGET_HARD_FLOAT
&& (TARGET_FPRS || TARGET_E500_DOUBLE)
&& TARGET_LONG_DOUBLE_128")])
; Various instructions that come in SI and DI forms. ; Various instructions that come in SI and DI forms.
; A generic w/d attribute, for things like cmpw/cmpd. ; A generic w/d attribute, for things like cmpw/cmpd.
...@@ -5730,7 +5732,7 @@ ...@@ -5730,7 +5732,7 @@
(clobber (match_dup 4)) (clobber (match_dup 4))
(clobber (match_dup 5)) (clobber (match_dup 5))
(clobber (match_dup 6))])] (clobber (match_dup 6))])]
"TARGET_HARD_FLOAT && TARGET_FPRS" "TARGET_HARD_FLOAT && (TARGET_FPRS || TARGET_E500_DOUBLE)"
" "
{ {
if (TARGET_E500_DOUBLE) if (TARGET_E500_DOUBLE)
...@@ -8538,7 +8540,7 @@ ...@@ -8538,7 +8540,7 @@
[(set_attr "length" "8,8,8,20,20,16")]) [(set_attr "length" "8,8,8,20,20,16")])
(define_insn_and_split "*movtf_softfloat" (define_insn_and_split "*movtf_softfloat"
[(set (match_operand:TF 0 "nonimmediate_operand" "=r,Y,r") [(set (match_operand:TF 0 "rs6000_nonimmediate_operand" "=r,Y,r")
(match_operand:TF 1 "input_operand" "YGHF,r,r"))] (match_operand:TF 1 "input_operand" "YGHF,r,r"))]
"!TARGET_IEEEQUAD "!TARGET_IEEEQUAD
&& (TARGET_SOFT_FLOAT || !TARGET_FPRS) && TARGET_LONG_DOUBLE_128 && (TARGET_SOFT_FLOAT || !TARGET_FPRS) && TARGET_LONG_DOUBLE_128
...@@ -8551,6 +8553,21 @@ ...@@ -8551,6 +8553,21 @@
[(set_attr "length" "20,20,16")]) [(set_attr "length" "20,20,16")])
(define_expand "extenddftf2" (define_expand "extenddftf2"
[(set (match_operand:TF 0 "nonimmediate_operand" "")
(float_extend:TF (match_operand:DF 1 "input_operand" "")))]
"!TARGET_IEEEQUAD
&& TARGET_HARD_FLOAT
&& (TARGET_FPRS || TARGET_E500_DOUBLE)
&& TARGET_LONG_DOUBLE_128"
{
if (TARGET_E500_DOUBLE)
emit_insn (gen_spe_extenddftf2 (operands[0], operands[1]));
else
emit_insn (gen_extenddftf2_fprs (operands[0], operands[1]));
DONE;
})
(define_expand "extenddftf2_fprs"
[(parallel [(set (match_operand:TF 0 "nonimmediate_operand" "") [(parallel [(set (match_operand:TF 0 "nonimmediate_operand" "")
(float_extend:TF (match_operand:DF 1 "input_operand" ""))) (float_extend:TF (match_operand:DF 1 "input_operand" "")))
(use (match_dup 2))])] (use (match_dup 2))])]
...@@ -8586,7 +8603,9 @@ ...@@ -8586,7 +8603,9 @@
[(set (match_operand:TF 0 "nonimmediate_operand" "") [(set (match_operand:TF 0 "nonimmediate_operand" "")
(float_extend:TF (match_operand:SF 1 "gpc_reg_operand" "")))] (float_extend:TF (match_operand:SF 1 "gpc_reg_operand" "")))]
"!TARGET_IEEEQUAD "!TARGET_IEEEQUAD
&& TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128" && TARGET_HARD_FLOAT
&& (TARGET_FPRS || TARGET_E500_DOUBLE)
&& TARGET_LONG_DOUBLE_128"
{ {
rtx tmp = gen_reg_rtx (DFmode); rtx tmp = gen_reg_rtx (DFmode);
emit_insn (gen_extendsfdf2 (tmp, operands[1])); emit_insn (gen_extendsfdf2 (tmp, operands[1]));
...@@ -8598,7 +8617,9 @@ ...@@ -8598,7 +8617,9 @@
[(set (match_operand:DF 0 "gpc_reg_operand" "") [(set (match_operand:DF 0 "gpc_reg_operand" "")
(float_truncate:DF (match_operand:TF 1 "gpc_reg_operand" "")))] (float_truncate:DF (match_operand:TF 1 "gpc_reg_operand" "")))]
"!TARGET_IEEEQUAD "!TARGET_IEEEQUAD
&& TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128" && TARGET_HARD_FLOAT
&& (TARGET_FPRS || TARGET_E500_DOUBLE)
&& TARGET_LONG_DOUBLE_128"
"") "")
(define_insn_and_split "trunctfdf2_internal1" (define_insn_and_split "trunctfdf2_internal1"
...@@ -8625,7 +8646,22 @@ ...@@ -8625,7 +8646,22 @@
"fadd %0,%1,%L1" "fadd %0,%1,%L1"
[(set_attr "type" "fp")]) [(set_attr "type" "fp")])
(define_insn_and_split "trunctfsf2" (define_expand "trunctfsf2"
[(set (match_operand:SF 0 "gpc_reg_operand" "")
(float_truncate:SF (match_operand:TF 1 "gpc_reg_operand" "")))]
"!TARGET_IEEEQUAD
&& TARGET_HARD_FLOAT
&& (TARGET_FPRS || TARGET_E500_DOUBLE)
&& TARGET_LONG_DOUBLE_128"
{
if (TARGET_E500_DOUBLE)
emit_insn (gen_spe_trunctfsf2 (operands[0], operands[1]));
else
emit_insn (gen_trunctfsf2_fprs (operands[0], operands[1]));
DONE;
})
(define_insn_and_split "trunctfsf2_fprs"
[(set (match_operand:SF 0 "gpc_reg_operand" "=f") [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
(float_truncate:SF (match_operand:TF 1 "gpc_reg_operand" "f"))) (float_truncate:SF (match_operand:TF 1 "gpc_reg_operand" "f")))
(clobber (match_scratch:DF 2 "=f"))] (clobber (match_scratch:DF 2 "=f"))]
...@@ -8643,7 +8679,9 @@ ...@@ -8643,7 +8679,9 @@
[(set (match_operand:TF 0 "gpc_reg_operand" "") [(set (match_operand:TF 0 "gpc_reg_operand" "")
(float:TF (match_operand:SI 1 "gpc_reg_operand" "")))] (float:TF (match_operand:SI 1 "gpc_reg_operand" "")))]
"!TARGET_IEEEQUAD "!TARGET_IEEEQUAD
&& TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128" && TARGET_HARD_FLOAT
&& (TARGET_FPRS || TARGET_E500_DOUBLE)
&& TARGET_LONG_DOUBLE_128"
{ {
rtx tmp = gen_reg_rtx (DFmode); rtx tmp = gen_reg_rtx (DFmode);
expand_float (tmp, operands[1], false); expand_float (tmp, operands[1], false);
...@@ -8664,6 +8702,22 @@ ...@@ -8664,6 +8702,22 @@
(set_attr "length" "20")]) (set_attr "length" "20")])
(define_expand "fix_trunctfsi2" (define_expand "fix_trunctfsi2"
[(set (match_operand:SI 0 "gpc_reg_operand" "")
(fix:SI (match_operand:TF 1 "gpc_reg_operand" "")))]
"!TARGET_IEEEQUAD
&& (TARGET_POWER2 || TARGET_POWERPC)
&& TARGET_HARD_FLOAT
&& (TARGET_FPRS || TARGET_E500_DOUBLE)
&& TARGET_LONG_DOUBLE_128"
{
if (TARGET_E500_DOUBLE)
emit_insn (gen_spe_fix_trunctfsi2 (operands[0], operands[1]));
else
emit_insn (gen_fix_trunctfsi2_fprs (operands[0], operands[1]));
DONE;
})
(define_expand "fix_trunctfsi2_fprs"
[(parallel [(set (match_operand:SI 0 "gpc_reg_operand" "") [(parallel [(set (match_operand:SI 0 "gpc_reg_operand" "")
(fix:SI (match_operand:TF 1 "gpc_reg_operand" ""))) (fix:SI (match_operand:TF 1 "gpc_reg_operand" "")))
(clobber (match_dup 2)) (clobber (match_dup 2))
...@@ -8705,7 +8759,16 @@ ...@@ -8705,7 +8759,16 @@
DONE; DONE;
}) })
(define_insn "negtf2" (define_expand "negtf2"
[(set (match_operand:TF 0 "gpc_reg_operand" "")
(neg:TF (match_operand:TF 1 "gpc_reg_operand" "")))]
"!TARGET_IEEEQUAD
&& TARGET_HARD_FLOAT
&& (TARGET_FPRS || TARGET_E500_DOUBLE)
&& TARGET_LONG_DOUBLE_128"
"")
(define_insn "negtf2_internal"
[(set (match_operand:TF 0 "gpc_reg_operand" "=f") [(set (match_operand:TF 0 "gpc_reg_operand" "=f")
(neg:TF (match_operand:TF 1 "gpc_reg_operand" "f")))] (neg:TF (match_operand:TF 1 "gpc_reg_operand" "f")))]
"!TARGET_IEEEQUAD "!TARGET_IEEEQUAD
...@@ -8721,14 +8784,24 @@ ...@@ -8721,14 +8784,24 @@
(set_attr "length" "8")]) (set_attr "length" "8")])
(define_expand "abstf2" (define_expand "abstf2"
[(set (match_operand:TF 0 "gpc_reg_operand" "=f") [(set (match_operand:TF 0 "gpc_reg_operand" "")
(abs:TF (match_operand:TF 1 "gpc_reg_operand" "f")))] (abs:TF (match_operand:TF 1 "gpc_reg_operand" "")))]
"!TARGET_IEEEQUAD "!TARGET_IEEEQUAD
&& TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128" && TARGET_HARD_FLOAT
&& (TARGET_FPRS || TARGET_E500_DOUBLE)
&& TARGET_LONG_DOUBLE_128"
" "
{ {
rtx label = gen_label_rtx (); rtx label = gen_label_rtx ();
emit_insn (gen_abstf2_internal (operands[0], operands[1], label)); if (TARGET_E500_DOUBLE)
{
if (flag_unsafe_math_optimizations)
emit_insn (gen_spe_abstf2_tst (operands[0], operands[1], label));
else
emit_insn (gen_spe_abstf2_cmp (operands[0], operands[1], label));
}
else
emit_insn (gen_abstf2_internal (operands[0], operands[1], label));
emit_label (label); emit_label (label);
DONE; DONE;
}") }")
...@@ -8761,7 +8834,7 @@ ...@@ -8761,7 +8834,7 @@
; List r->r after r->"o<>", otherwise reload will try to reload a ; List r->r after r->"o<>", otherwise reload will try to reload a
; non-offsettable address by using r->r which won't make progress. ; non-offsettable address by using r->r which won't make progress.
(define_insn "*movdi_internal32" (define_insn "*movdi_internal32"
[(set (match_operand:DI 0 "nonimmediate_operand" "=o<>,r,r,*f,*f,m,r") [(set (match_operand:DI 0 "rs6000_nonimmediate_operand" "=o<>,r,r,*f,*f,m,r")
(match_operand:DI 1 "input_operand" "r,r,m,f,m,f,IJKnGHF"))] (match_operand:DI 1 "input_operand" "r,r,m,f,m,f,IJKnGHF"))]
"! TARGET_POWERPC64 "! TARGET_POWERPC64
&& (gpc_reg_operand (operands[0], DImode) && (gpc_reg_operand (operands[0], DImode)
...@@ -8798,7 +8871,7 @@ ...@@ -8798,7 +8871,7 @@
}") }")
(define_split (define_split
[(set (match_operand:DI 0 "nonimmediate_operand" "") [(set (match_operand:DI 0 "rs6000_nonimmediate_operand" "")
(match_operand:DI 1 "input_operand" ""))] (match_operand:DI 1 "input_operand" ""))]
"reload_completed && !TARGET_POWERPC64 "reload_completed && !TARGET_POWERPC64
&& gpr_or_gpr_p (operands[0], operands[1])" && gpr_or_gpr_p (operands[0], operands[1])"
......
;; e500 SPE description ;; e500 SPE description
;; Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. ;; Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007
;; Free Software Foundation, Inc.
;; Contributed by Aldy Hernandez (aldy@quesejoda.com) ;; Contributed by Aldy Hernandez (aldy@quesejoda.com)
;; This file is part of GCC. ;; This file is part of GCC.
...@@ -29,12 +30,24 @@ ...@@ -29,12 +30,24 @@
(TSTDFGT_GPR 1009) (TSTDFGT_GPR 1009)
(CMPDFLT_GPR 1010) (CMPDFLT_GPR 1010)
(TSTDFLT_GPR 1011) (TSTDFLT_GPR 1011)
(E500_CR_IOR_COMPARE 1012) (CMPTFEQ_GPR 1012)
(TSTTFEQ_GPR 1013)
(CMPTFGT_GPR 1014)
(TSTTFGT_GPR 1015)
(CMPTFLT_GPR 1016)
(TSTTFLT_GPR 1017)
(E500_CR_IOR_COMPARE 1018)
]) ])
;; Modes using a 64-bit register. ;; Modes using a 64-bit register.
(define_mode_macro SPE64 [DF V4HI V2SF V1DI V2SI]) (define_mode_macro SPE64 [DF V4HI V2SF V1DI V2SI])
;; Likewise, but allow TFmode (two registers) as well.
(define_mode_macro SPE64TF [DF V4HI V2SF V1DI V2SI TF])
;; DImode and TImode.
(define_mode_macro DITI [DI TI])
(define_insn "*negsf2_gpr" (define_insn "*negsf2_gpr"
[(set (match_operand:SF 0 "gpc_reg_operand" "=r") [(set (match_operand:SF 0 "gpc_reg_operand" "=r")
(neg:SF (match_operand:SF 1 "gpc_reg_operand" "r")))] (neg:SF (match_operand:SF 1 "gpc_reg_operand" "r")))]
...@@ -2198,25 +2211,57 @@ ...@@ -2198,25 +2211,57 @@
;; Double-precision floating point instructions. ;; Double-precision floating point instructions.
;; FIXME: Add o=r option. ;; FIXME: Add o=r option.
(define_insn "*frob_df_di" (define_insn "*frob_<SPE64:mode>_<DITI:mode>"
[(set (match_operand:DF 0 "nonimmediate_operand" "=r,r") [(set (match_operand:SPE64 0 "nonimmediate_operand" "=r,r")
(subreg:DF (match_operand:DI 1 "input_operand" "r,m") 0))] (subreg:SPE64 (match_operand:DITI 1 "input_operand" "r,m") 0))]
"(TARGET_E500_DOUBLE && <SPE64:MODE>mode == DFmode)
|| (TARGET_SPE && <SPE64:MODE>mode != DFmode)"
"@
evmergelo %0,%1,%L1
evldd%X1 %0,%y1")
(define_insn "*frob_tf_ti"
[(set (match_operand:TF 0 "gpc_reg_operand" "=r")
(subreg:TF (match_operand:TI 1 "gpc_reg_operand" "r") 0))]
"TARGET_E500_DOUBLE" "TARGET_E500_DOUBLE"
"evmergelo %0,%1,%L1\;evmergelo %L0,%Y1,%Z1")
(define_insn "*frob_<mode>_di_2"
[(set (subreg:DI (match_operand:SPE64TF 0 "nonimmediate_operand" "+&r,r") 0)
(match_operand:DI 1 "input_operand" "r,m"))]
"(TARGET_E500_DOUBLE && (<MODE>mode == DFmode || <MODE>mode == TFmode))
|| (TARGET_SPE && <MODE>mode != DFmode && <MODE>mode != TFmode)"
"@ "@
evmergelo %0,%1,%L1 evmergelo %0,%1,%L1
evldd%X1 %0,%y1") evldd%X1 %0,%y1")
(define_insn "*frob_di_df" (define_insn "*frob_tf_di_8_2"
[(set (match_operand:DI 0 "nonimmediate_operand" "=&r") [(set (subreg:DI (match_operand:TF 0 "nonimmediate_operand" "+&r,r") 8)
(subreg:DI (match_operand:DF 1 "input_operand" "r") 0))] (match_operand:DI 1 "input_operand" "r,m"))]
"TARGET_E500_DOUBLE" "TARGET_E500_DOUBLE"
"@
evmergelo %L0,%1,%L1
evldd%X1 %L0,%y1")
(define_insn "*frob_di_<mode>"
[(set (match_operand:DI 0 "nonimmediate_operand" "=&r")
(subreg:DI (match_operand:SPE64TF 1 "input_operand" "r") 0))]
"(TARGET_E500_DOUBLE && (<MODE>mode == DFmode || <MODE>mode == TFmode))
|| (TARGET_SPE && <MODE>mode != DFmode && <MODE>mode != TFmode)"
"evmergehi %0,%1,%1\;mr %L0,%1" "evmergehi %0,%1,%1\;mr %L0,%1"
[(set_attr "length" "8")]) [(set_attr "length" "8")])
(define_insn "*frob_di_df_2" (define_insn "*frob_ti_tf"
[(set (subreg:DF (match_operand:DI 0 "register_operand" "=&r,r") 0) [(set (match_operand:TI 0 "nonimmediate_operand" "=&r")
(match_operand:DF 1 "input_operand" "r,m"))] (subreg:TI (match_operand:TF 1 "input_operand" "r") 0))]
"TARGET_E500_DOUBLE" "TARGET_E500_DOUBLE"
"evmergehi %0,%1,%1\;mr %L0,%1\;evmergehi %Y0,%L1,%L1\;mr %Z0,%L1")
(define_insn "*frob_<DITI:mode>_<SPE64:mode>_2"
[(set (subreg:SPE64 (match_operand:DITI 0 "register_operand" "+&r,r") 0)
(match_operand:SPE64 1 "input_operand" "r,m"))]
"(TARGET_E500_DOUBLE && <SPE64:MODE>mode == DFmode)
|| (TARGET_SPE && <SPE64:MODE>mode != DFmode)"
"* "*
{ {
switch (which_alternative) switch (which_alternative)
...@@ -2244,10 +2289,43 @@ ...@@ -2244,10 +2289,43 @@
}" }"
[(set_attr "length" "8,8")]) [(set_attr "length" "8,8")])
; As the above, but TImode at offset 8.
(define_insn "*frob_ti_<mode>_8_2"
[(set (subreg:SPE64 (match_operand:TI 0 "register_operand" "+&r,r") 8)
(match_operand:SPE64 1 "input_operand" "r,m"))]
"(TARGET_E500_DOUBLE && <MODE>mode == DFmode)
|| (TARGET_SPE && <MODE>mode != DFmode)"
"*
{
switch (which_alternative)
{
default:
gcc_unreachable ();
case 0:
return \"evmergehi %Y0,%1,%1\;mr %Z0,%1\";
case 1:
if (!offsettable_nonstrict_memref_p (operands[1]))
return \"evldd%X1 %Z0,%y1\;evmergehi %Y0,%Z0,%Z0\";
if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1,
operands[1], 0))
return \"{l|lwz} %Z0,%L1\;{l|lwz} %Y0,%1\";
else
return \"{l%U1%X1|lwz%U1%X1} %Y0,%1\;{l|lwz} %Z0,%L1\";
}
}"
[(set_attr "length" "8,8")])
(define_insn "*frob_ti_tf_2"
[(set (subreg:TF (match_operand:TI 0 "gpc_reg_operand" "=&r") 0)
(match_operand:TF 1 "gpc_reg_operand" "r"))]
"TARGET_E500_DOUBLE"
"evmergehi %0,%1,%1\;mr %L0,%1\;evmergehi %Y0,%L1,%L1\;mr %Z0,%L1")
(define_insn "*mov_si<mode>_e500_subreg0" (define_insn "*mov_si<mode>_e500_subreg0"
[(set (subreg:SI (match_operand:SPE64 0 "register_operand" "+r,&r") 0) [(set (subreg:SI (match_operand:SPE64TF 0 "register_operand" "+r,&r") 0)
(match_operand:SI 1 "input_operand" "r,m"))] (match_operand:SI 1 "input_operand" "r,m"))]
"(TARGET_E500_DOUBLE && <MODE>mode == DFmode) || (TARGET_SPE && <MODE>mode != DFmode)" "(TARGET_E500_DOUBLE && (<MODE>mode == DFmode || <MODE>mode == TFmode))
|| (TARGET_SPE && <MODE>mode != DFmode && <MODE>mode != TFmode)"
"@ "@
evmergelo %0,%1,%0 evmergelo %0,%1,%0
evmergelohi %0,%0,%0\;{l%U1%X1|lwz%U1%X1} %0,%1\;evmergelohi %0,%0,%0") evmergelohi %0,%0,%0\;{l%U1%X1|lwz%U1%X1} %0,%1\;evmergelohi %0,%0,%0")
...@@ -2256,28 +2334,63 @@ ...@@ -2256,28 +2334,63 @@
;; the offset. ;; the offset.
(define_insn "*mov_si<mode>_e500_subreg0_2" (define_insn "*mov_si<mode>_e500_subreg0_2"
[(set (match_operand:SI 0 "rs6000_nonimmediate_operand" "+r,m") [(set (match_operand:SI 0 "rs6000_nonimmediate_operand" "+r,m")
(subreg:SI (match_operand:SPE64 1 "register_operand" "+r,&r") 0))] (subreg:SI (match_operand:SPE64TF 1 "register_operand" "+r,&r") 0))]
"(TARGET_E500_DOUBLE && <MODE>mode == DFmode) || (TARGET_SPE && <MODE>mode != DFmode)" "(TARGET_E500_DOUBLE && (<MODE>mode == DFmode || <MODE>mode == TFmode))
|| (TARGET_SPE && <MODE>mode != DFmode && <MODE>mode != TFmode)"
"@ "@
evmergehi %0,%0,%1 evmergehi %0,%0,%1
evmergelohi %1,%1,%1\;{st%U0%X0|stw%U0%X0} %1,%0") evmergelohi %1,%1,%1\;{st%U0%X0|stw%U0%X0} %1,%0")
(define_insn "*mov_si<mode>_e500_subreg4" (define_insn "*mov_si<mode>_e500_subreg4"
[(set (subreg:SI (match_operand:SPE64 0 "register_operand" "+r,r") 4) [(set (subreg:SI (match_operand:SPE64TF 0 "register_operand" "+r,r") 4)
(match_operand:SI 1 "input_operand" "r,m"))] (match_operand:SI 1 "input_operand" "r,m"))]
"(TARGET_E500_DOUBLE && <MODE>mode == DFmode) || (TARGET_SPE && <MODE>mode != DFmode)" "(TARGET_E500_DOUBLE && (<MODE>mode == DFmode || <MODE>mode == TFmode))
|| (TARGET_SPE && <MODE>mode != DFmode && <MODE>mode != TFmode)"
"@ "@
mr %0,%1 mr %0,%1
{l%U1%X1|lwz%U1%X1} %0,%1") {l%U1%X1|lwz%U1%X1} %0,%1")
(define_insn "*mov_si<mode>_e500_subreg4_2" (define_insn "*mov_si<mode>_e500_subreg4_2"
[(set (match_operand:SI 0 "rs6000_nonimmediate_operand" "+r,m") [(set (match_operand:SI 0 "rs6000_nonimmediate_operand" "+r,m")
(subreg:SI (match_operand:SPE64 1 "register_operand" "r,r") 4))] (subreg:SI (match_operand:SPE64TF 1 "register_operand" "r,r") 4))]
"(TARGET_E500_DOUBLE && <MODE>mode == DFmode) || (TARGET_SPE && <MODE>mode != DFmode)" "(TARGET_E500_DOUBLE && (<MODE>mode == DFmode || <MODE>mode == TFmode))
|| (TARGET_SPE && <MODE>mode != DFmode && <MODE>mode != TFmode)"
"@ "@
mr %0,%1 mr %0,%1
{st%U0%X0|stw%U0%X0} %1,%0") {st%U0%X0|stw%U0%X0} %1,%0")
(define_insn "*mov_sitf_e500_subreg8"
[(set (subreg:SI (match_operand:TF 0 "register_operand" "+r,&r") 8)
(match_operand:SI 1 "input_operand" "r,m"))]
"TARGET_E500_DOUBLE"
"@
evmergelo %L0,%1,%L0
evmergelohi %L0,%L0,%L0\;{l%U1%X1|lwz%U1%X1} %L0,%1\;evmergelohi %L0,%L0,%L0")
(define_insn "*mov_sitf_e500_subreg8_2"
[(set (match_operand:SI 0 "rs6000_nonimmediate_operand" "+r,m")
(subreg:SI (match_operand:TF 1 "register_operand" "+r,&r") 8))]
"TARGET_E500_DOUBLE"
"@
evmergehi %0,%0,%L1
evmergelohi %L1,%L1,%L1\;{st%U0%X0|stw%U0%X0} %L1,%0")
(define_insn "*mov_sitf_e500_subreg12"
[(set (subreg:SI (match_operand:TF 0 "register_operand" "+r,r") 12)
(match_operand:SI 1 "input_operand" "r,m"))]
"TARGET_E500_DOUBLE"
"@
mr %L0,%1
{l%U1%X1|lwz%U1%X1} %L0,%1")
(define_insn "*mov_sitf_e500_subreg12_2"
[(set (match_operand:SI 0 "rs6000_nonimmediate_operand" "+r,m")
(subreg:SI (match_operand:TF 1 "register_operand" "r,r") 12))]
"TARGET_E500_DOUBLE"
"@
mr %0,%L1
{st%U0%X0|stw%U0%X0} %L1,%0")
;; FIXME: Allow r=CONST0. ;; FIXME: Allow r=CONST0.
(define_insn "*movdf_e500_double" (define_insn "*movdf_e500_double"
[(set (match_operand:DF 0 "rs6000_nonimmediate_operand" "=r,r,m") [(set (match_operand:DF 0 "rs6000_nonimmediate_operand" "=r,r,m")
...@@ -2354,6 +2467,133 @@ ...@@ -2354,6 +2467,133 @@
"TARGET_HARD_FLOAT && TARGET_E500_DOUBLE" "TARGET_HARD_FLOAT && TARGET_E500_DOUBLE"
"efddiv %0,%1,%2") "efddiv %0,%1,%2")
;; Double-precision floating point instructions for IBM long double.
(define_insn_and_split "spe_trunctfdf2_internal1"
[(set (match_operand:DF 0 "gpc_reg_operand" "=r,?r")
(float_truncate:DF (match_operand:TF 1 "gpc_reg_operand" "0,r")))]
"!TARGET_IEEEQUAD
&& TARGET_HARD_FLOAT && TARGET_E500_DOUBLE && TARGET_LONG_DOUBLE_128"
"@
#
evor %0,%1,%1"
"&& reload_completed && REGNO (operands[0]) == REGNO (operands[1])"
[(const_int 0)]
{
emit_note (NOTE_INSN_DELETED);
DONE;
})
(define_insn_and_split "spe_trunctfsf2"
[(set (match_operand:SF 0 "gpc_reg_operand" "=r")
(float_truncate:SF (match_operand:TF 1 "gpc_reg_operand" "r")))
(clobber (match_scratch:DF 2 "=r"))]
"!TARGET_IEEEQUAD
&& TARGET_HARD_FLOAT && TARGET_E500_DOUBLE && TARGET_LONG_DOUBLE_128"
"#"
"&& reload_completed"
[(set (match_dup 2)
(float_truncate:DF (match_dup 1)))
(set (match_dup 0)
(float_truncate:SF (match_dup 2)))]
"")
(define_insn "spe_extenddftf2"
[(set (match_operand:TF 0 "rs6000_nonimmediate_operand" "=r,?r,r,o")
(float_extend:TF (match_operand:DF 1 "input_operand" "0,r,m,r")))
(clobber (match_scratch:DF 2 "=X,X,X,&r"))]
"!TARGET_IEEEQUAD
&& TARGET_HARD_FLOAT && TARGET_E500_DOUBLE && TARGET_LONG_DOUBLE_128"
"@
evxor %L0,%L0,%L0
evor %0,%1,%1\;evxor %L0,%L0,%L0
evldd%X1 %0,%y1\;evxor %L0,%L0,%L0
evstdd%X0 %1,%y0\;evxor %2,%2,%2\;evstdd %2,%Y0")
(define_expand "spe_fix_trunctfsi2"
[(parallel [(set (match_operand:SI 0 "gpc_reg_operand" "")
(fix:SI (match_operand:TF 1 "gpc_reg_operand" "")))
(clobber (match_dup 2))
(clobber (match_dup 3))
(clobber (match_dup 4))])]
"!TARGET_IEEEQUAD
&& TARGET_HARD_FLOAT && TARGET_E500_DOUBLE && TARGET_LONG_DOUBLE_128"
{
operands[2] = gen_reg_rtx (DFmode);
operands[3] = gen_reg_rtx (SImode);
operands[4] = gen_reg_rtx (SImode);
})
; Like fix_trunc_helper, add with rounding towards 0.
(define_insn "spe_fix_trunctfsi2_internal"
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
(fix:SI (match_operand:TF 1 "gpc_reg_operand" "r")))
(clobber (match_operand:DF 2 "gpc_reg_operand" "=r"))
(clobber (match_operand:SI 3 "gpc_reg_operand" "=&r"))
(clobber (match_operand:SI 4 "gpc_reg_operand" "=&r"))]
"!TARGET_IEEEQUAD
&& TARGET_HARD_FLOAT && TARGET_E500_DOUBLE && TARGET_LONG_DOUBLE_128"
"mfspefscr %3\;rlwinm %4,%3,0,0,29\;ori %4,%4,1\;efdadd %2,%1,%L1\;mtspefscr %3\;efdctsiz %0, %2")
(define_insn "spe_negtf2_internal"
[(set (match_operand:TF 0 "gpc_reg_operand" "=r")
(neg:TF (match_operand:TF 1 "gpc_reg_operand" "r")))]
"!TARGET_IEEEQUAD
&& TARGET_HARD_FLOAT && TARGET_E500_DOUBLE && TARGET_LONG_DOUBLE_128"
"*
{
if (REGNO (operands[0]) == REGNO (operands[1]) + 1)
return \"efdneg %L0,%L1\;efdneg %0,%1\";
else
return \"efdneg %0,%1\;efdneg %L0,%L1\";
}")
(define_expand "spe_abstf2_cmp"
[(set (match_operand:TF 0 "gpc_reg_operand" "=f")
(match_operand:TF 1 "gpc_reg_operand" "f"))
(set (match_dup 3) (match_dup 5))
(set (match_dup 5) (abs:DF (match_dup 5)))
(set (match_dup 4) (unspec:CCFP [(compare:CCFP (match_dup 3)
(match_dup 5))] CMPDFEQ_GPR))
(set (pc) (if_then_else (eq (match_dup 4) (const_int 0))
(label_ref (match_operand 2 "" ""))
(pc)))
(set (match_dup 6) (neg:DF (match_dup 6)))]
"!TARGET_IEEEQUAD
&& TARGET_HARD_FLOAT && TARGET_E500_DOUBLE && TARGET_LONG_DOUBLE_128"
"
{
const int hi_word = FLOAT_WORDS_BIG_ENDIAN ? 0 : GET_MODE_SIZE (DFmode);
const int lo_word = FLOAT_WORDS_BIG_ENDIAN ? GET_MODE_SIZE (DFmode) : 0;
operands[3] = gen_reg_rtx (DFmode);
operands[4] = gen_reg_rtx (CCFPmode);
operands[5] = simplify_gen_subreg (DFmode, operands[0], TFmode, hi_word);
operands[6] = simplify_gen_subreg (DFmode, operands[0], TFmode, lo_word);
}")
(define_expand "spe_abstf2_tst"
[(set (match_operand:TF 0 "gpc_reg_operand" "=f")
(match_operand:TF 1 "gpc_reg_operand" "f"))
(set (match_dup 3) (match_dup 5))
(set (match_dup 5) (abs:DF (match_dup 5)))
(set (match_dup 4) (unspec:CCFP [(compare:CCFP (match_dup 3)
(match_dup 5))] TSTDFEQ_GPR))
(set (pc) (if_then_else (eq (match_dup 4) (const_int 0))
(label_ref (match_operand 2 "" ""))
(pc)))
(set (match_dup 6) (neg:DF (match_dup 6)))]
"!TARGET_IEEEQUAD
&& TARGET_HARD_FLOAT && TARGET_E500_DOUBLE && TARGET_LONG_DOUBLE_128"
"
{
const int hi_word = FLOAT_WORDS_BIG_ENDIAN ? 0 : GET_MODE_SIZE (DFmode);
const int lo_word = FLOAT_WORDS_BIG_ENDIAN ? GET_MODE_SIZE (DFmode) : 0;
operands[3] = gen_reg_rtx (DFmode);
operands[4] = gen_reg_rtx (CCFPmode);
operands[5] = simplify_gen_subreg (DFmode, operands[0], TFmode, hi_word);
operands[6] = simplify_gen_subreg (DFmode, operands[0], TFmode, lo_word);
}")
;; Vector move instructions. ;; Vector move instructions.
(define_expand "movv2si" (define_expand "movv2si"
...@@ -2803,6 +3043,80 @@ ...@@ -2803,6 +3043,80 @@
"efdtstlt %0,%1,%2" "efdtstlt %0,%1,%2"
[(set_attr "type" "veccmpsimple")]) [(set_attr "type" "veccmpsimple")])
;; Same thing, but for IBM long double.
(define_insn "cmptfeq_gpr"
[(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
(unspec:CCFP
[(compare:CCFP (match_operand:TF 1 "gpc_reg_operand" "r")
(match_operand:TF 2 "gpc_reg_operand" "r"))]
CMPTFEQ_GPR))]
"!TARGET_IEEEQUAD
&& TARGET_HARD_FLOAT && TARGET_E500_DOUBLE && TARGET_LONG_DOUBLE_128
&& !flag_unsafe_math_optimizations"
"efdcmpeq %0,%1,%2\;bng %0,$+8\;efdcmpeq %0,%L1,%L2"
[(set_attr "type" "veccmp")])
(define_insn "tsttfeq_gpr"
[(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
(unspec:CCFP
[(compare:CCFP (match_operand:TF 1 "gpc_reg_operand" "r")
(match_operand:TF 2 "gpc_reg_operand" "r"))]
TSTTFEQ_GPR))]
"!TARGET_IEEEQUAD
&& TARGET_HARD_FLOAT && TARGET_E500_DOUBLE && TARGET_LONG_DOUBLE_128
&& flag_unsafe_math_optimizations"
"efdtsteq %0,%1,%2\;bng %0,$+8\;efdtsteq %0,%L1,%L2"
[(set_attr "type" "veccmpsimple")])
(define_insn "cmptfgt_gpr"
[(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
(unspec:CCFP
[(compare:CCFP (match_operand:TF 1 "gpc_reg_operand" "r")
(match_operand:TF 2 "gpc_reg_operand" "r"))]
CMPTFGT_GPR))]
"!TARGET_IEEEQUAD
&& TARGET_HARD_FLOAT && TARGET_E500_DOUBLE && TARGET_LONG_DOUBLE_128
&& !flag_unsafe_math_optimizations"
"efdcmpgt %0,%1,%2\;bgt %0,$+16\;efdcmpeq %0,%1,%2\;bng %0,$+8\;efdcmpgt %0,%L1,%L2"
[(set_attr "type" "veccmp")])
(define_insn "tsttfgt_gpr"
[(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
(unspec:CCFP
[(compare:CCFP (match_operand:TF 1 "gpc_reg_operand" "r")
(match_operand:TF 2 "gpc_reg_operand" "r"))]
TSTTFGT_GPR))]
"!TARGET_IEEEQUAD
&& TARGET_HARD_FLOAT && TARGET_E500_DOUBLE && TARGET_LONG_DOUBLE_128
&& flag_unsafe_math_optimizations"
"efdtstgt %0,%1,%2\;bgt %0,$+16\;efdtsteq %0,%1,%2\;bng %0,$+8\;efdtstgt %0,%L1,%L2"
[(set_attr "type" "veccmpsimple")])
(define_insn "cmptflt_gpr"
[(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
(unspec:CCFP
[(compare:CCFP (match_operand:TF 1 "gpc_reg_operand" "r")
(match_operand:TF 2 "gpc_reg_operand" "r"))]
CMPTFLT_GPR))]
"!TARGET_IEEEQUAD
&& TARGET_HARD_FLOAT && TARGET_E500_DOUBLE && TARGET_LONG_DOUBLE_128
&& !flag_unsafe_math_optimizations"
"efdcmplt %0,%1,%2\;bgt %0,$+16\;efdcmpeq %0,%1,%2\;bng %0,$+8\;efdcmplt %0,%L1,%L2"
[(set_attr "type" "veccmp")])
(define_insn "tsttflt_gpr"
[(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
(unspec:CCFP
[(compare:CCFP (match_operand:TF 1 "gpc_reg_operand" "r")
(match_operand:TF 2 "gpc_reg_operand" "r"))]
TSTTFLT_GPR))]
"!TARGET_IEEEQUAD
&& TARGET_HARD_FLOAT && TARGET_E500_DOUBLE && TARGET_LONG_DOUBLE_128
&& flag_unsafe_math_optimizations"
"efdtstlt %0,%1,%2\;bgt %0,$+16\;efdtsteq %0,%1,%2\;bng %0,$+8\;efdtstlt %0,%L1,%L2"
[(set_attr "type" "veccmpsimple")])
;; Like cceq_ior_compare, but compare the GT bits. ;; Like cceq_ior_compare, but compare the GT bits.
(define_insn "e500_cr_ior_compare" (define_insn "e500_cr_ior_compare"
[(set (match_operand:CCFP 0 "cc_reg_operand" "=y") [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
......
2007-01-23 Joseph Myers <joseph@codesourcery.com>
* config/rs6000/t-ldbl128: Always use -mlong-double-128.
2007-01-21 Andrew Pinski <pinskia@gmail.com> 2007-01-21 Andrew Pinski <pinskia@gmail.com>
PR target/30519 PR target/30519
......
SHLIB_MAPFILES += $(gcc_srcdir)/config/rs6000/libgcc-ppc-glibc.ver SHLIB_MAPFILES += $(gcc_srcdir)/config/rs6000/libgcc-ppc-glibc.ver
# Use -mlong-double-128 only when not compiling nof libgcc.
predefined-macros := $(shell true | $(CC) $(CFLAGS) -x c -dD -E -)
ifeq ($(findstring _SOFT_FLOAT,$(predefined-macros)),)
HOST_LIBGCC2_CFLAGS += -mlong-double-128 HOST_LIBGCC2_CFLAGS += -mlong-double-128
endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment