summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog44
-rw-r--r--gcc/config.gcc5
-rw-r--r--gcc/config/rs6000/e500-double.h25
-rw-r--r--gcc/config/rs6000/eabi.h6
-rw-r--r--gcc/config/rs6000/linuxspe.h6
-rw-r--r--gcc/config/rs6000/rs6000.c140
-rw-r--r--gcc/config/rs6000/rs6000.h2
-rw-r--r--gcc/config/rs6000/spe.md72
-rw-r--r--gcc/doc/invoke.texi17
9 files changed, 280 insertions, 37 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 49f28bed75f..6264a63df16 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,47 @@
+2004-10-21 Aldy Hernandez <aldyh@redhat.com>
+
+ * config.gcc: Add support for --enable-e500_double.
+
+ * config/rs6000/e500-double.h: New file.
+
+ * config/rs6000/rs6000.h: Define TARGET_E500_SINGLE and
+ TARGET_E500_DOUBLE.
+
+ * config/rs6000/eabi.h: Define TARGET_E500_SINGLE and
+ TARGET_E500_DOUBLE.
+
+ * config/rs6000/linuxspe.h: Same.
+
+ * doc/invoke.texi (Option Summary): Document new options for
+ mfloat-gprs.
+ (RS/6000 and PowerPC Options): Same.
+
+ * config/rs6000/rs6000.c (rs6000_parse_float_gprs_option): New
+ function.
+ (rs6000_override_options): Use it. Use
+ SUB3TARGET_OVERRIDE_OPTIONS.
+ Add 8548 to processor_target_table.
+ (rs6000_legitimate_address): Handle e500 doubles.
+ (rs6000_legitimize_address): Same.
+ (rs6000_legitimize_reload_address): Same.
+ (rs6000_hard_regno_nregs): Same.
+ (spe_func_has_64bit_regs_p): Same.
+ (emit_frame_save): Same.
+ (gen_frame_mem_offset): Same.
+ (rs6000_dwarf_register_span): Same.
+ (rs6000_generate_compare): Same.
+ (easy_fp_constant): Same.
+ (legitimate_offset_address_p): Same.
+
+ * config/rs6000/spe.md: (cmdfeq_gpr): New.
+ (tstdfeq_gpr): New.
+ (cmpdfgt_gpr): New.
+ (tstdfgt_gpr): New.
+ (tstdfgt_gpr): New.
+ (cmpdflt_gpr): New.
+ (tstdflt_gpr): New.
+ Add new constants.
+
2004-10-21 Giovanni Bajo <giovannibajo@gcc.gnu.org>
* config/arc/lib1funcs.asm (___umulsidi3): Fix typo.
diff --git a/gcc/config.gcc b/gcc/config.gcc
index 0308fc9c8ee..c1820ccb831 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -2665,6 +2665,11 @@ fi
c_target_objs="${c_target_objs} rs6000-c.o"
cxx_target_objs="${cxx_target_objs} rs6000-c.o"
tmake_file="rs6000/t-rs6000 ${tmake_file}"
+
+ if test x$enable_e500_double = xyes
+ then
+ tm_file="$tm_file rs6000/e500-double.h"
+ fi
;;
sparc*-*-*)
diff --git a/gcc/config/rs6000/e500-double.h b/gcc/config/rs6000/e500-double.h
new file mode 100644
index 00000000000..5f0c734762e
--- /dev/null
+++ b/gcc/config/rs6000/e500-double.h
@@ -0,0 +1,25 @@
+/* Target definitions for E500 with double precision FP.
+ Copyright (C) 2004 Free Software Foundation, Inc.
+ Contributed by Aldy Hernandez (aldyh@redhat.com).
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING. If not, write to the
+ Free Software Foundation, 59 Temple Place - Suite 330, Boston,
+ MA 02111-1307, USA. */
+
+#undef SUB3TARGET_OVERRIDE_OPTIONS
+#define SUB3TARGET_OVERRIDE_OPTIONS \
+ if (rs6000_float_gprs_string == NULL) \
+ rs6000_float_gprs = 2;
diff --git a/gcc/config/rs6000/eabi.h b/gcc/config/rs6000/eabi.h
index ff8df2c3e41..8de75a6cee2 100644
--- a/gcc/config/rs6000/eabi.h
+++ b/gcc/config/rs6000/eabi.h
@@ -49,9 +49,13 @@
#undef TARGET_E500
#undef TARGET_ISEL
#undef TARGET_FPRS
+#undef TARGET_E500_SINGLE
+#undef TARGET_E500_DOUBLE
#define TARGET_SPE_ABI rs6000_spe_abi
#define TARGET_SPE rs6000_spe
#define TARGET_E500 (rs6000_cpu == PROCESSOR_PPC8540)
#define TARGET_ISEL rs6000_isel
-#define TARGET_FPRS (!rs6000_float_gprs)
+#define TARGET_FPRS (rs6000_float_gprs == 0)
+#define TARGET_E500_SINGLE (TARGET_HARD_FLOAT && rs6000_float_gprs == 1)
+#define TARGET_E500_DOUBLE (TARGET_HARD_FLOAT && rs6000_float_gprs == 2)
diff --git a/gcc/config/rs6000/linuxspe.h b/gcc/config/rs6000/linuxspe.h
index 36b494e5961..f4e02ebf624 100644
--- a/gcc/config/rs6000/linuxspe.h
+++ b/gcc/config/rs6000/linuxspe.h
@@ -32,12 +32,16 @@
#undef TARGET_E500
#undef TARGET_ISEL
#undef TARGET_FPRS
+#undef TARGET_E500_SINGLE
+#undef TARGET_E500_DOUBLE
#define TARGET_SPE_ABI rs6000_spe_abi
#define TARGET_SPE rs6000_spe
#define TARGET_E500 (rs6000_cpu == PROCESSOR_PPC8540)
#define TARGET_ISEL rs6000_isel
-#define TARGET_FPRS (!rs6000_float_gprs)
+#define TARGET_FPRS (rs6000_float_gprs == 0)
+#define TARGET_E500_SINGLE (TARGET_HARD_FLOAT && rs6000_float_gprs == 1)
+#define TARGET_E500_DOUBLE (TARGET_HARD_FLOAT && rs6000_float_gprs == 2)
#undef SUBSUBTARGET_OVERRIDE_OPTIONS
#define SUBSUBTARGET_OVERRIDE_OPTIONS \
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 7d2d1d9b794..6117bdb6b60 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -723,6 +723,7 @@ static void rs6000_parse_abi_options (void);
static void rs6000_parse_alignment_option (void);
static void rs6000_parse_tls_size_option (void);
static void rs6000_parse_yes_no_option (const char *, const char *, int *);
+static void rs6000_parse_float_gprs_option (void);
static int first_altivec_reg_to_save (void);
static unsigned int compute_vrsave_mask (void);
static void compute_save_world_info(rs6000_stack_t *info_ptr);
@@ -1119,6 +1120,8 @@ rs6000_override_options (const char *default_cpu)
{"821", PROCESSOR_MPCCORE, POWERPC_BASE_MASK | MASK_SOFT_FLOAT},
{"823", PROCESSOR_MPCCORE, POWERPC_BASE_MASK | MASK_SOFT_FLOAT},
{"8540", PROCESSOR_PPC8540, POWERPC_BASE_MASK | MASK_PPC_GFXOPT},
+ /* 8548 has a dummy entry for now. */
+ {"8548", PROCESSOR_PPC8540, POWERPC_BASE_MASK | MASK_PPC_GFXOPT},
{"860", PROCESSOR_MPCCORE, POWERPC_BASE_MASK | MASK_SOFT_FLOAT},
{"970", PROCESSOR_POWER4,
POWERPC_7400_MASK | MASK_PPC_GPOPT | MASK_MFCRF | MASK_POWERPC64},
@@ -1292,14 +1295,14 @@ rs6000_override_options (const char *default_cpu)
/* Handle -malign-XXXXX option. */
rs6000_parse_alignment_option ();
+ rs6000_parse_float_gprs_option ();
+
/* Handle generic -mFOO=YES/NO options. */
rs6000_parse_yes_no_option ("vrsave", rs6000_altivec_vrsave_string,
&rs6000_altivec_vrsave);
rs6000_parse_yes_no_option ("isel", rs6000_isel_string,
&rs6000_isel);
rs6000_parse_yes_no_option ("spe", rs6000_spe_string, &rs6000_spe);
- rs6000_parse_yes_no_option ("float-gprs", rs6000_float_gprs_string,
- &rs6000_float_gprs);
/* Handle -mtls-size option. */
rs6000_parse_tls_size_option ();
@@ -1310,6 +1313,9 @@ rs6000_override_options (const char *default_cpu)
#ifdef SUBSUBTARGET_OVERRIDE_OPTIONS
SUBSUBTARGET_OVERRIDE_OPTIONS;
#endif
+#ifdef SUB3TARGET_OVERRIDE_OPTIONS
+ SUB3TARGET_OVERRIDE_OPTIONS;
+#endif
if (TARGET_E500)
{
@@ -1622,6 +1628,23 @@ rs6000_parse_abi_options (void)
error ("unknown ABI specified: '%s'", rs6000_abi_string);
}
+/* Handle -mfloat-gprs= options. */
+static void
+rs6000_parse_float_gprs_option (void)
+{
+ if (rs6000_float_gprs_string == 0)
+ return;
+ else if (! strcmp (rs6000_float_gprs_string, "yes")
+ || ! strcmp (rs6000_float_gprs_string, "single"))
+ rs6000_float_gprs = 1;
+ else if (! strcmp (rs6000_float_gprs_string, "double"))
+ rs6000_float_gprs = 2;
+ else if (! strcmp (rs6000_float_gprs_string, "no"))
+ rs6000_float_gprs = 0;
+ else
+ error ("invalid option for -mfloat-gprs");
+}
+
/* Handle -malign-XXXXXX options. */
static void
rs6000_parse_alignment_option (void)
@@ -2163,7 +2186,7 @@ easy_fp_constant (rtx op, enum machine_mode mode)
return 0;
/* Consider all constants with -msoft-float to be easy. */
- if ((TARGET_SOFT_FLOAT || !TARGET_FPRS)
+ if ((TARGET_SOFT_FLOAT || TARGET_E500_SINGLE)
&& mode != DImode)
return 1;
@@ -2197,6 +2220,9 @@ easy_fp_constant (rtx op, enum machine_mode mode)
long k[2];
REAL_VALUE_TYPE rv;
+ if (TARGET_E500_DOUBLE)
+ return 0;
+
REAL_VALUE_FROM_CONST_DOUBLE (rv, op);
REAL_VALUE_TO_TARGET_DOUBLE (rv, k);
@@ -3173,6 +3199,9 @@ rs6000_legitimate_offset_address_p (enum machine_mode mode, rtx x, int strict)
return SPE_CONST_OFFSET_OK (offset);
case DFmode:
+ if (TARGET_E500_DOUBLE)
+ return SPE_CONST_OFFSET_OK (offset);
+
case DImode:
if (mode == DFmode || !TARGET_POWERPC64)
extra = 4;
@@ -3325,7 +3354,7 @@ rs6000_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
&& GET_MODE_NUNITS (mode) == 1
&& ((TARGET_HARD_FLOAT && TARGET_FPRS)
|| TARGET_POWERPC64
- || (mode != DFmode && mode != TFmode))
+ || ((mode != DFmode || TARGET_E500_DOUBLE) && mode != TFmode))
&& (TARGET_POWERPC64 || mode != DImode)
&& mode != TImode)
{
@@ -3344,7 +3373,8 @@ rs6000_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
reg = force_reg (Pmode, x);
return reg;
}
- else if (SPE_VECTOR_MODE (mode))
+ else if (SPE_VECTOR_MODE (mode)
+ || (TARGET_E500_DOUBLE && mode == DFmode))
{
/* We accept [reg + reg] and [reg + OFFSET]. */
@@ -3388,7 +3418,8 @@ rs6000_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
&& GET_CODE (x) != CONST_INT
&& GET_CODE (x) != CONST_DOUBLE
&& CONSTANT_P (x)
- && ((TARGET_HARD_FLOAT && TARGET_FPRS) || mode != DFmode)
+ && ((TARGET_HARD_FLOAT && TARGET_FPRS)
+ || (mode != DFmode || TARGET_E500_DOUBLE))
&& mode != DImode
&& mode != TImode)
{
@@ -3735,6 +3766,7 @@ rs6000_legitimize_reload_address (rtx x, enum machine_mode mode,
&& REG_MODE_OK_FOR_BASE_P (XEXP (x, 0), mode)
&& GET_CODE (XEXP (x, 1)) == CONST_INT
&& !SPE_VECTOR_MODE (mode)
+ && !(TARGET_E500_DOUBLE && mode == DFmode)
&& !ALTIVEC_VECTOR_MODE (mode))
{
HOST_WIDE_INT val = INTVAL (XEXP (x, 1));
@@ -3838,6 +3870,7 @@ rs6000_legitimate_address (enum machine_mode mode, rtx x, int reg_ok_strict)
if ((GET_CODE (x) == PRE_INC || GET_CODE (x) == PRE_DEC)
&& !ALTIVEC_VECTOR_MODE (mode)
&& !SPE_VECTOR_MODE (mode)
+ && !(TARGET_E500_DOUBLE && mode == DFmode)
&& TARGET_UPDATE
&& legitimate_indirect_address_p (XEXP (x, 0), reg_ok_strict))
return 1;
@@ -3859,7 +3892,7 @@ rs6000_legitimate_address (enum machine_mode mode, rtx x, int reg_ok_strict)
&& mode != TFmode
&& ((TARGET_HARD_FLOAT && TARGET_FPRS)
|| TARGET_POWERPC64
- || (mode != DFmode && mode != TFmode))
+ || ((mode != DFmode || TARGET_E500_DOUBLE) && mode != TFmode))
&& (TARGET_POWERPC64 || mode != DImode)
&& legitimate_indexed_address_p (x, reg_ok_strict))
return 1;
@@ -3924,6 +3957,9 @@ rs6000_hard_regno_nregs (int regno, enum machine_mode mode)
if (FP_REGNO_P (regno))
return (GET_MODE_SIZE (mode) + UNITS_PER_FP_WORD - 1) / UNITS_PER_FP_WORD;
+ if (TARGET_E500_DOUBLE && mode == DFmode)
+ return 1;
+
if (SPE_SIMD_REGNO_P (regno) && TARGET_SPE && SPE_VECTOR_MODE (mode))
return (GET_MODE_SIZE (mode) + UNITS_PER_SPE_WORD - 1) / UNITS_PER_SPE_WORD;
@@ -10864,6 +10900,10 @@ rs6000_generate_compare (enum rtx_code code)
&& rs6000_compare_fp_p)
{
rtx cmp, or1, or2, or_result, compare_result2;
+ enum machine_mode op_mode = GET_MODE (rs6000_compare_op0);
+
+ if (op_mode == VOIDmode)
+ op_mode = GET_MODE (rs6000_compare_op1);
/* Note: The E500 comparison instructions set the GT bit (x +
1), on success. This explains the mess. */
@@ -10871,28 +10911,52 @@ rs6000_generate_compare (enum rtx_code code)
switch (code)
{
case EQ: case UNEQ: case NE: case LTGT:
- cmp = flag_finite_math_only
- ? gen_tstsfeq_gpr (compare_result, rs6000_compare_op0,
- rs6000_compare_op1)
- : gen_cmpsfeq_gpr (compare_result, rs6000_compare_op0,
- rs6000_compare_op1);
+ if (op_mode == SFmode)
+ cmp = flag_finite_math_only
+ ? gen_tstsfeq_gpr (compare_result, rs6000_compare_op0,
+ rs6000_compare_op1)
+ : gen_cmpsfeq_gpr (compare_result, rs6000_compare_op0,
+ rs6000_compare_op1);
+ else if (op_mode == DFmode)
+ cmp = flag_finite_math_only
+ ? gen_tstdfeq_gpr (compare_result, rs6000_compare_op0,
+ rs6000_compare_op1)
+ : gen_cmpdfeq_gpr (compare_result, rs6000_compare_op0,
+ rs6000_compare_op1);
+ else abort ();
break;
case GT: case GTU: case UNGT: case UNGE: case GE: case GEU:
- cmp = flag_finite_math_only
- ? gen_tstsfgt_gpr (compare_result, rs6000_compare_op0,
- rs6000_compare_op1)
- : gen_cmpsfgt_gpr (compare_result, rs6000_compare_op0,
- rs6000_compare_op1);
+ if (op_mode == SFmode)
+ cmp = flag_finite_math_only
+ ? gen_tstsfgt_gpr (compare_result, rs6000_compare_op0,
+ rs6000_compare_op1)
+ : gen_cmpsfgt_gpr (compare_result, rs6000_compare_op0,
+ rs6000_compare_op1);
+ else if (op_mode == DFmode)
+ cmp = flag_finite_math_only
+ ? gen_tstdfgt_gpr (compare_result, rs6000_compare_op0,
+ rs6000_compare_op1)
+ : gen_cmpdfgt_gpr (compare_result, rs6000_compare_op0,
+ rs6000_compare_op1);
+ else abort ();
break;
case LT: case LTU: case UNLT: case UNLE: case LE: case LEU:
- cmp = flag_finite_math_only
- ? gen_tstsflt_gpr (compare_result, rs6000_compare_op0,
- rs6000_compare_op1)
- : gen_cmpsflt_gpr (compare_result, rs6000_compare_op0,
- rs6000_compare_op1);
+ if (op_mode == SFmode)
+ cmp = flag_finite_math_only
+ ? gen_tstsflt_gpr (compare_result, rs6000_compare_op0,
+ rs6000_compare_op1)
+ : gen_cmpsflt_gpr (compare_result, rs6000_compare_op0,
+ rs6000_compare_op1);
+ else if (op_mode == DFmode)
+ cmp = flag_finite_math_only
+ ? gen_tstdflt_gpr (compare_result, rs6000_compare_op0,
+ rs6000_compare_op1)
+ : gen_cmpdflt_gpr (compare_result, rs6000_compare_op0,
+ rs6000_compare_op1);
+ else abort ();
break;
- default:
- abort ();
+ default:
+ abort ();
}
/* Synthesize LE and GE from LT/GT || EQ. */
@@ -10915,11 +10979,19 @@ rs6000_generate_compare (enum rtx_code code)
compare_result2 = gen_reg_rtx (CCFPmode);
/* Do the EQ. */
- cmp = flag_finite_math_only
- ? gen_tstsfeq_gpr (compare_result2, rs6000_compare_op0,
- rs6000_compare_op1)
- : gen_cmpsfeq_gpr (compare_result2, rs6000_compare_op0,
- rs6000_compare_op1);
+ if (op_mode == SFmode)
+ cmp = flag_finite_math_only
+ ? gen_tstsfeq_gpr (compare_result2, rs6000_compare_op0,
+ rs6000_compare_op1)
+ : gen_cmpsfeq_gpr (compare_result2, rs6000_compare_op0,
+ rs6000_compare_op1);
+ else if (op_mode == DFmode)
+ cmp = flag_finite_math_only
+ ? gen_tstdfeq_gpr (compare_result2, rs6000_compare_op0,
+ rs6000_compare_op1)
+ : gen_cmpdfeq_gpr (compare_result2, rs6000_compare_op0,
+ rs6000_compare_op1);
+ else abort ();
emit_insn (cmp);
or1 = gen_rtx_GT (SImode, compare_result, const0_rtx);
@@ -13289,6 +13361,7 @@ emit_frame_save (rtx frame_reg, rtx frame_ptr, enum machine_mode mode,
/* Some cases that need register indexed addressing. */
if ((TARGET_ALTIVEC_ABI && ALTIVEC_VECTOR_MODE (mode))
+ || (TARGET_E500_DOUBLE && mode == DFmode)
|| (TARGET_SPE_ABI
&& SPE_VECTOR_MODE (mode)
&& !SPE_CONST_OFFSET_OK (offset)))
@@ -13328,7 +13401,8 @@ gen_frame_mem_offset (enum machine_mode mode, rtx reg, int offset)
int_rtx = GEN_INT (offset);
- if (TARGET_SPE_ABI && SPE_VECTOR_MODE (mode))
+ if ((TARGET_SPE_ABI && SPE_VECTOR_MODE (mode))
+ || (TARGET_E500_DOUBLE && mode == DFmode))
{
offset_rtx = gen_rtx_REG (Pmode, FIXED_SCRATCH);
emit_move_insn (offset_rtx, int_rtx);
@@ -18082,7 +18156,11 @@ rs6000_dwarf_register_span (rtx reg)
{
unsigned regno;
- if (!TARGET_SPE || !SPE_VECTOR_MODE (GET_MODE (reg)))
+ if (TARGET_SPE
+ && (SPE_VECTOR_MODE (GET_MODE (reg))
+ || (TARGET_E500_DOUBLE && GET_MODE (reg) == DFmode)))
+ ;
+ else
return NULL_RTX;
regno = REGNO (reg);
diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h
index 28932aa661e..0a209b674cf 100644
--- a/gcc/config/rs6000/rs6000.h
+++ b/gcc/config/rs6000/rs6000.h
@@ -568,6 +568,8 @@ extern const char *rs6000_warn_altivec_long_switch;
#define TARGET_E500 0
#define TARGET_ISEL 0
#define TARGET_FPRS 1
+#define TARGET_E500_SINGLE 0
+#define TARGET_E500_DOUBLE 0
/* Sometimes certain combinations of command options do not make sense
on a particular target machine. You can define a macro
diff --git a/gcc/config/rs6000/spe.md b/gcc/config/rs6000/spe.md
index 3627c88fe63..6a130021a5b 100644
--- a/gcc/config/rs6000/spe.md
+++ b/gcc/config/rs6000/spe.md
@@ -21,7 +21,15 @@
(define_constants
[(SPE_ACC_REGNO 111)
- (SPEFSCR_REGNO 112)])
+ (SPEFSCR_REGNO 112)
+
+ (CMPDFEQ_GPR 1006)
+ (TSTDFEQ_GPR 1007)
+ (CMPDFGT_GPR 1008)
+ (TSTDFGT_GPR 1009)
+ (CMPDFLT_GPR 1010)
+ (TSTDFLT_GPR 1011)
+ ])
(define_insn "*negsf2_gpr"
[(set (match_operand:SF 0 "gpc_reg_operand" "=r")
@@ -2532,3 +2540,65 @@
"TARGET_HARD_FLOAT && !TARGET_FPRS && flag_unsafe_math_optimizations"
"efststlt %0,%1,%2"
[(set_attr "type" "veccmpsimple")])
+
+;; Same thing, but for double-precision.
+
+(define_insn "cmpdfeq_gpr"
+ [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
+ (unspec:CCFP
+ [(compare:CCFP (match_operand:DF 1 "gpc_reg_operand" "r")
+ (match_operand:DF 2 "gpc_reg_operand" "r"))]
+ CMPDFEQ_GPR))]
+ "TARGET_HARD_FLOAT && TARGET_E500_DOUBLE && !flag_unsafe_math_optimizations"
+ "efdcmpeq %0,%1,%2"
+ [(set_attr "type" "veccmp")])
+
+(define_insn "tstdfeq_gpr"
+ [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
+ (unspec:CCFP
+ [(compare:CCFP (match_operand:DF 1 "gpc_reg_operand" "r")
+ (match_operand:DF 2 "gpc_reg_operand" "r"))]
+ TSTDFEQ_GPR))]
+ "TARGET_HARD_FLOAT && TARGET_E500_DOUBLE && flag_unsafe_math_optimizations"
+ "efdtsteq %0,%1,%2"
+ [(set_attr "type" "veccmpsimple")])
+
+(define_insn "cmpdfgt_gpr"
+ [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
+ (unspec:CCFP
+ [(compare:CCFP (match_operand:DF 1 "gpc_reg_operand" "r")
+ (match_operand:DF 2 "gpc_reg_operand" "r"))]
+ CMPDFGT_GPR))]
+ "TARGET_HARD_FLOAT && TARGET_E500_DOUBLE && !flag_unsafe_math_optimizations"
+ "efdcmpgt %0,%1,%2"
+ [(set_attr "type" "veccmp")])
+
+(define_insn "tstdfgt_gpr"
+ [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
+ (unspec:CCFP
+ [(compare:CCFP (match_operand:DF 1 "gpc_reg_operand" "r")
+ (match_operand:DF 2 "gpc_reg_operand" "r"))]
+ TSTDFGT_GPR))]
+ "TARGET_HARD_FLOAT && TARGET_E500_DOUBLE && flag_unsafe_math_optimizations"
+ "efdtstgt %0,%1,%2"
+ [(set_attr "type" "veccmpsimple")])
+
+(define_insn "cmpdflt_gpr"
+ [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
+ (unspec:CCFP
+ [(compare:CCFP (match_operand:DF 1 "gpc_reg_operand" "r")
+ (match_operand:DF 2 "gpc_reg_operand" "r"))]
+ CMPDFLT_GPR))]
+ "TARGET_HARD_FLOAT && TARGET_E500_DOUBLE && !flag_unsafe_math_optimizations"
+ "efdcmplt %0,%1,%2"
+ [(set_attr "type" "veccmp")])
+
+(define_insn "tstdflt_gpr"
+ [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
+ (unspec:CCFP
+ [(compare:CCFP (match_operand:DF 1 "gpc_reg_operand" "r")
+ (match_operand:DF 2 "gpc_reg_operand" "r"))]
+ TSTDFLT_GPR))]
+ "TARGET_HARD_FLOAT && TARGET_E500_DOUBLE && flag_unsafe_math_optimizations"
+ "efdtstlt %0,%1,%2"
+ [(set_attr "type" "veccmpsimple")])
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 66e87a15990..a2b0d83df0c 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -616,7 +616,7 @@ See RS/6000 and PowerPC Options.
-mabi=spe -mabi=no-spe @gol
-misel=yes -misel=no @gol
-mspe=yes -mspe=no @gol
--mfloat-gprs=yes -mfloat-gprs=no @gol
+-mfloat-gprs=yes -mfloat-gprs=no -mfloat-gprs=single -mfloat-gprs=double @gol
-mprototype -mno-prototype @gol
-msim -mmvme -mads -myellowknife -memb -msdata @gol
-msdata=@var{opt} -mvxworks -mwindiss -G @var{num} -pthread}
@@ -10279,12 +10279,23 @@ This switch enables or disables the generation of ISEL instructions.
This switch enables or disables the generation of SPE simd
instructions.
-@item -mfloat-gprs=@var{yes/no}
+@item -mfloat-gprs=@var{yes/single/double/no}
@itemx -mfloat-gprs
@opindex mfloat-gprs
This switch enables or disables the generation of floating point
operations on the general purpose registers for architectures that
-support it. This option is currently only available on the MPC8540.
+support it.
+
+The argument @var{yes} or @var{single} enables the use of
+single-precision floating point operations.
+
+The argument @var{double} enables the use of single and
+double-precision floating point operations.
+
+The argument @var{no} disables floating point operations on the
+general purpose registers.
+
+This option is currently only available on the MPC854x.
@item -m32
@itemx -m64
OpenPOWER on IntegriCloud