config.gcc (powerpc-*-linux*spe*): Use t-dfprules.
authorJoseph Myers <joseph@codesourcery.com>
Thu, 5 Jun 2008 23:03:11 +0000 (00:03 +0100)
committerJoseph Myers <jsm28@gcc.gnu.org>
Thu, 5 Jun 2008 23:03:11 +0000 (00:03 +0100)
* config.gcc (powerpc-*-linux*spe*): Use t-dfprules.
* config/rs6000/dfp.md (negdd2, absdd2, negtd2, abstd2): Do not
enable for TARGET_E500_DOUBLE.
(*movdd_softfloat32): Also enable for !TARGET_FPRS.
* config/rs6000/rs6000.c (invalid_e500_subreg): Treat decimal
floating-point modes like integer modes for E500 double.
(rs6000_legitimate_offset_address_p): Likewise.
(rs6000_legitimize_address): Likewise.  Do not allow REG+REG
addressing for DDmode for E500 double.
(rs6000_hard_regno_nregs): Do not treat decimal floating-point
modes as using 64-bits of registers for E500 double.
(spe_build_register_parallel): Do not handle DDmode or TDmode.
(rs6000_spe_function_arg): Do not handle DDmode or TDmode
specially for E500 double.
(function_arg): Do not call rs6000_spe_function_arg for DDmode or
TDmode for E500 double.
(rs6000_gimplify_va_arg): Only handle SDmode in registers
specially if TARGET_HARD_FLOAT && TARGET_FPRS.
(rs6000_split_multireg_move): Do not handle TDmode specially for
E500 double.
(spe_func_has_64bit_regs_p): Do not treat DDmode or TDmode as
using 64-bit registers for E500 double.
(emit_frame_save): Do not handle DDmode specially for E500 double.
(gen_frame_mem_offset): Likewise.
(rs6000_function_value): Do not call spe_build_register_parallel
for DDmode or TDmode.
(rs6000_libcall_value): Likewise.
* config/rs6000/rs6000.h (LOCAL_ALIGNMENT, MEMBER_TYPE_FORCES_BLK,
DATA_ALIGNMENT, CLASS_MAX_NREGS): Do not handle DDmode specially
for E500 double.

From-SVN: r136416

gcc/ChangeLog
gcc/config.gcc
gcc/config/rs6000/dfp.md
gcc/config/rs6000/rs6000.c
gcc/config/rs6000/rs6000.h

index b10677e779b7baf1e962c906185ed35ae1f5c2d9..3cb7ec5d3d723a3554b224fb22529b80cd156b59 100644 (file)
@@ -1,3 +1,36 @@
+2008-06-05  Joseph Myers  <joseph@codesourcery.com>
+
+       * config.gcc (powerpc-*-linux*spe*): Use t-dfprules.
+       * config/rs6000/dfp.md (negdd2, absdd2, negtd2, abstd2): Do not
+       enable for TARGET_E500_DOUBLE.
+       (*movdd_softfloat32): Also enable for !TARGET_FPRS.
+       * config/rs6000/rs6000.c (invalid_e500_subreg): Treat decimal
+       floating-point modes like integer modes for E500 double.
+       (rs6000_legitimate_offset_address_p): Likewise.
+       (rs6000_legitimize_address): Likewise.  Do not allow REG+REG
+       addressing for DDmode for E500 double.
+       (rs6000_hard_regno_nregs): Do not treat decimal floating-point
+       modes as using 64-bits of registers for E500 double.
+       (spe_build_register_parallel): Do not handle DDmode or TDmode.
+       (rs6000_spe_function_arg): Do not handle DDmode or TDmode
+       specially for E500 double.
+       (function_arg): Do not call rs6000_spe_function_arg for DDmode or
+       TDmode for E500 double.
+       (rs6000_gimplify_va_arg): Only handle SDmode in registers
+       specially if TARGET_HARD_FLOAT && TARGET_FPRS.
+       (rs6000_split_multireg_move): Do not handle TDmode specially for
+       E500 double.
+       (spe_func_has_64bit_regs_p): Do not treat DDmode or TDmode as
+       using 64-bit registers for E500 double.
+       (emit_frame_save): Do not handle DDmode specially for E500 double.
+       (gen_frame_mem_offset): Likewise.
+       (rs6000_function_value): Do not call spe_build_register_parallel
+       for DDmode or TDmode.
+       (rs6000_libcall_value): Likewise.
+       * config/rs6000/rs6000.h (LOCAL_ALIGNMENT, MEMBER_TYPE_FORCES_BLK,
+       DATA_ALIGNMENT, CLASS_MAX_NREGS): Do not handle DDmode specially
+       for E500 double.
+
 2008-06-04  H.J. Lu  <hongjiu.lu@intel.com>
 
        * config/i386/i386.c (setup_incoming_varargs_64): Fix a typo
index 806728794f14d9fed0604f6916ef23d542c3c73e..399d80c633b0ffeb9a3318a83dbc89b37ec6fe3f 100644 (file)
@@ -1989,7 +1989,7 @@ powerpc-*-linux*altivec*)
 powerpc-*-linux*spe*)
        tm_file="${tm_file} dbxelf.h elfos.h svr4.h freebsd-spec.h rs6000/sysv4.h rs6000/linux.h rs6000/linuxspe.h rs6000/e500.h"
        extra_options="${extra_options} rs6000/sysv4.opt"
-       tmake_file="rs6000/t-fprules rs6000/t-fprules-softfp soft-fp/t-softfp rs6000/t-ppcos ${tmake_file} rs6000/t-ppccomm"
+       tmake_file="t-dfprules rs6000/t-fprules rs6000/t-fprules-softfp soft-fp/t-softfp rs6000/t-ppcos ${tmake_file} rs6000/t-ppccomm"
        ;;
 powerpc-*-linux*paired*)
         tm_file="${tm_file} dbxelf.h elfos.h svr4.h freebsd-spec.h rs6000/sysv4.h rs6000/linux.h rs6000/750cl.h"
index 2d111b8df648825bd812de558689e5c5191cd3fa..90eaa2a0d5568fe476928e3fc0cb12c4e184c015 100644 (file)
 (define_expand "negdd2"
   [(set (match_operand:DD 0 "gpc_reg_operand" "")
        (neg:DD (match_operand:DD 1 "gpc_reg_operand" "")))]
-  "TARGET_HARD_FLOAT && (TARGET_FPRS || TARGET_E500_DOUBLE)"
+  "TARGET_HARD_FLOAT && TARGET_FPRS"
   "")
 
 (define_insn "*negdd2_fpr"
 (define_expand "absdd2"
   [(set (match_operand:DD 0 "gpc_reg_operand" "")
        (abs:DD (match_operand:DD 1 "gpc_reg_operand" "")))]
-  "TARGET_HARD_FLOAT && (TARGET_FPRS || TARGET_E500_DOUBLE)"
+  "TARGET_HARD_FLOAT && TARGET_FPRS"
   "")
 
 (define_insn "*absdd2_fpr"
 (define_insn "*movdd_softfloat32"
   [(set (match_operand:DD 0 "nonimmediate_operand" "=r,r,m,r,r,r")
        (match_operand:DD 1 "input_operand" "r,m,r,G,H,F"))]
-  "! TARGET_POWERPC64 && TARGET_SOFT_FLOAT
+  "! TARGET_POWERPC64 && (TARGET_SOFT_FLOAT || !TARGET_FPRS)
    && (gpc_reg_operand (operands[0], DDmode)
        || gpc_reg_operand (operands[1], DDmode))"
   "*
 (define_expand "negtd2"
   [(set (match_operand:TD 0 "gpc_reg_operand" "")
        (neg:TD (match_operand:TD 1 "gpc_reg_operand" "")))]
-  "TARGET_HARD_FLOAT && (TARGET_FPRS || TARGET_E500_DOUBLE)"
+  "TARGET_HARD_FLOAT && TARGET_FPRS"
   "")
 
 (define_insn "*negtd2_fpr"
 (define_expand "abstd2"
   [(set (match_operand:TD 0 "gpc_reg_operand" "")
        (abs:TD (match_operand:TD 1 "gpc_reg_operand" "")))]
-  "TARGET_HARD_FLOAT && (TARGET_FPRS || TARGET_E500_DOUBLE)"
+  "TARGET_HARD_FLOAT && TARGET_FPRS"
   "")
 
 (define_insn "*abstd2_fpr"
index 197347677977d363e778dae938fd9fc5735a887b..8493e771ae19cccb7ba47deb8da48ec63dfb3e38 100644 (file)
@@ -3199,24 +3199,26 @@ invalid_e500_subreg (rtx op, enum machine_mode mode)
   if (TARGET_E500_DOUBLE)
     {
       /* Reject (subreg:SI (reg:DF)); likewise with subreg:DI or
-        subreg:TI and reg:TF.  */
+        subreg:TI and reg:TF.  Decimal float modes are like integer
+        modes (only low part of each register used) for this
+        purpose.  */
       if (GET_CODE (op) == SUBREG
-         && (mode == SImode || mode == DImode || mode == TImode)
+         && (mode == SImode || mode == DImode || mode == TImode
+             || mode == DDmode || mode == TDmode)
          && REG_P (SUBREG_REG (op))
          && (GET_MODE (SUBREG_REG (op)) == DFmode
-             || GET_MODE (SUBREG_REG (op)) == TFmode
-             || GET_MODE (SUBREG_REG (op)) == DDmode
-             || GET_MODE (SUBREG_REG (op)) == TDmode))
+             || GET_MODE (SUBREG_REG (op)) == TFmode))
        return true;
 
       /* Reject (subreg:DF (reg:DI)); likewise with subreg:TF and
         reg:TI.  */
       if (GET_CODE (op) == SUBREG
-         && (mode == DFmode || mode == TFmode
-             || mode == DDmode || mode == TDmode)
+         && (mode == DFmode || mode == TFmode)
          && REG_P (SUBREG_REG (op))
          && (GET_MODE (SUBREG_REG (op)) == DImode
-             || GET_MODE (SUBREG_REG (op)) == TImode))
+             || GET_MODE (SUBREG_REG (op)) == TImode
+             || GET_MODE (SUBREG_REG (op)) == DDmode
+             || GET_MODE (SUBREG_REG (op)) == TDmode))
        return true;
     }
 
@@ -3467,10 +3469,10 @@ rs6000_legitimate_offset_address_p (enum machine_mode mode, rtx x, int strict)
       return SPE_CONST_OFFSET_OK (offset);
 
     case DFmode:
-    case DDmode:
       if (TARGET_E500_DOUBLE)
        return SPE_CONST_OFFSET_OK (offset);
 
+    case DDmode:
     case DImode:
       /* On e500v2, we may have:
 
@@ -3487,11 +3489,11 @@ rs6000_legitimate_offset_address_p (enum machine_mode mode, rtx x, int strict)
       break;
 
     case TFmode:
-    case TDmode:
       if (TARGET_E500_DOUBLE)
        return (SPE_CONST_OFFSET_OK (offset)
                && SPE_CONST_OFFSET_OK (offset + 8));
 
+    case TDmode:
     case TImode:
       if (mode == TFmode || mode == TDmode || !TARGET_POWERPC64)
        extra = 12;
@@ -3638,7 +3640,8 @@ rs6000_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
       && !(SPE_VECTOR_MODE (mode)
           || ALTIVEC_VECTOR_MODE (mode)
           || (TARGET_E500_DOUBLE && (mode == DFmode || mode == TFmode
-                                     || mode == DImode))))
+                                     || mode == DImode || mode == DDmode
+                                     || mode == TDmode))))
     {
       HOST_WIDE_INT high_int, low_int;
       rtx sum;
@@ -3655,7 +3658,7 @@ rs6000_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
           && ((TARGET_HARD_FLOAT && TARGET_FPRS)
               || TARGET_POWERPC64
               || ((mode != DImode && mode != DFmode && mode != DDmode)
-                  || TARGET_E500_DOUBLE))
+                  || (TARGET_E500_DOUBLE && mode != DDmode)))
           && (TARGET_POWERPC64 || mode != DImode)
           && mode != TImode
           && mode != TFmode
@@ -3704,7 +3707,7 @@ rs6000_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
             reg + offset] is not a legitimate addressing mode.  */
          y = gen_rtx_PLUS (Pmode, op1, op2);
 
-         if (GET_MODE_SIZE (mode) > 8 && REG_P (op2))
+         if ((GET_MODE_SIZE (mode) > 8 || mode == DDmode) && REG_P (op2))
            return force_reg (Pmode, y);
          else
            return y;
@@ -4265,7 +4268,8 @@ rs6000_legitimate_address (enum machine_mode mode, rtx x, int reg_ok_strict)
       && mode != TDmode
       && ((TARGET_HARD_FLOAT && TARGET_FPRS)
          || TARGET_POWERPC64
-         || ((mode != DFmode && mode != DDmode) || TARGET_E500_DOUBLE))
+         || (mode != DFmode && mode != DDmode)
+         || (TARGET_E500_DOUBLE && mode != DDmode))
       && (TARGET_POWERPC64 || mode != DImode)
       && legitimate_indexed_address_p (x, reg_ok_strict))
     return 1;
@@ -4389,7 +4393,8 @@ rs6000_hard_regno_nregs (int regno, enum machine_mode mode)
      would require function_arg and rs6000_spe_function_arg to handle
      SCmode so as to pass the value correctly in a pair of
      registers.  */
-  if (TARGET_E500_DOUBLE && FLOAT_MODE_P (mode) && mode != SCmode)
+  if (TARGET_E500_DOUBLE && FLOAT_MODE_P (mode) && mode != SCmode
+      && !DECIMAL_FLOAT_MODE_P (mode))
     return (GET_MODE_SIZE (mode) + UNITS_PER_FP_WORD - 1) / UNITS_PER_FP_WORD;
 
   return (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
@@ -5664,14 +5669,12 @@ spe_build_register_parallel (enum machine_mode mode, int gregno)
   switch (mode)
     {
     case DFmode:
-    case DDmode:
       r1 = gen_rtx_REG (DImode, gregno);
       r1 = gen_rtx_EXPR_LIST (VOIDmode, r1, const0_rtx);
       return gen_rtx_PARALLEL (mode, gen_rtvec (1, r1));
 
     case DCmode:
     case TFmode:
-    case TDmode:
       r1 = gen_rtx_REG (DImode, gregno);
       r1 = gen_rtx_EXPR_LIST (VOIDmode, r1, const0_rtx);
       r3 = gen_rtx_REG (DImode, gregno + 2);
@@ -5704,13 +5707,12 @@ 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
      are passed and returned in a pair of GPRs for ABI compatibility.  */
   if (TARGET_E500_DOUBLE && (mode == DFmode || mode == TFmode
-                            || mode == DDmode || mode == TDmode
                             || mode == DCmode || mode == TCmode))
     {
       int n_words = rs6000_arg_size (mode, type);
 
       /* Doubles go in an odd/even register pair (r5/r6, etc).  */
-      if (mode == DFmode || mode == DDmode)
+      if (mode == DFmode)
        gregno += (1 - gregno) & 1;
 
       /* Multi-reg args are not split between registers and stack.  */
@@ -6123,10 +6125,8 @@ function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
   else if (TARGET_SPE_ABI && TARGET_SPE
           && (SPE_VECTOR_MODE (mode)
               || (TARGET_E500_DOUBLE && (mode == DFmode
-                                         || mode == DDmode
                                          || mode == DCmode
                                          || mode == TFmode
-                                         || mode == TDmode
                                          || mode == TCmode))))
     return rs6000_spe_function_arg (cum, mode, type);
 
@@ -6885,7 +6885,9 @@ rs6000_gimplify_va_arg (tree valist, tree type, tree *pre_p, tree *post_p)
 
       /* _Decimal32 varargs are located in the second word of the 64-bit
         FP register for 32-bit binaries.  */
-      if (!TARGET_POWERPC64 && TYPE_MODE (type) == SDmode)
+      if (!TARGET_POWERPC64
+         && TARGET_HARD_FLOAT && TARGET_FPRS
+         && TYPE_MODE (type) == SDmode)
        t = build2 (POINTER_PLUS_EXPR, TREE_TYPE (t), t, size_int (size));
 
       t = build2 (GIMPLE_MODIFY_STMT, void_type_node, addr, t);
@@ -14015,8 +14017,8 @@ rs6000_split_multireg_move (rtx dst, rtx src)
     reg_mode = DECIMAL_FLOAT_MODE_P (mode) ? DDmode : DFmode;
   else if (ALTIVEC_REGNO_P (reg))
     reg_mode = V16QImode;
-  else if (TARGET_E500_DOUBLE && (mode == TFmode || mode == TDmode))
-    reg_mode = DECIMAL_FLOAT_MODE_P (mode) ? DDmode : DFmode;
+  else if (TARGET_E500_DOUBLE && mode == TFmode)
+    reg_mode = DFmode;
   else
     reg_mode = word_mode;
   reg_mode_size = GET_MODE_SIZE (reg_mode);
@@ -14757,8 +14759,7 @@ spe_func_has_64bit_regs_p (void)
 
              if (SPE_VECTOR_MODE (mode))
                return true;
-             if (TARGET_E500_DOUBLE && (mode == DFmode || mode == TFmode
-                                        || mode == DDmode || mode == TDmode))
+             if (TARGET_E500_DOUBLE && (mode == DFmode || mode == TFmode))
                return true;
            }
        }
@@ -15509,7 +15510,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 || mode == DDmode))
+      || (TARGET_E500_DOUBLE && mode == DFmode)
       || (TARGET_SPE_ABI
          && SPE_VECTOR_MODE (mode)
          && !SPE_CONST_OFFSET_OK (offset)))
@@ -15549,7 +15550,7 @@ 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))
-      || (TARGET_E500_DOUBLE && (mode == DFmode || mode == DDmode)))
+      || (TARGET_E500_DOUBLE && mode == DFmode))
     {
       offset_rtx = gen_rtx_REG (Pmode, FIXED_SCRATCH);
       emit_move_insn (offset_rtx, int_rtx);
@@ -21864,8 +21865,8 @@ rs6000_function_value (const_tree valtype, const_tree func ATTRIBUTE_UNUSED)
           && ALTIVEC_VECTOR_MODE (mode))
     regno = ALTIVEC_ARG_RETURN;
   else if (TARGET_E500_DOUBLE && TARGET_HARD_FLOAT
-          && (mode == DFmode || mode == DDmode || mode == DCmode
-              || mode == TFmode || mode == TDmode || mode == TCmode))
+          && (mode == DFmode || mode == DCmode
+              || mode == TFmode || mode == TCmode))
     return spe_build_register_parallel (mode, GP_ARG_RETURN);
   else
     regno = GP_ARG_RETURN;
@@ -21906,8 +21907,8 @@ rs6000_libcall_value (enum machine_mode mode)
   else if (COMPLEX_MODE_P (mode) && targetm.calls.split_complex_arg)
     return rs6000_complex_function_value (mode);
   else if (TARGET_E500_DOUBLE && TARGET_HARD_FLOAT
-          && (mode == DFmode || mode == DDmode || mode == DCmode
-              || mode == TFmode || mode == TDmode || mode == TCmode))
+          && (mode == DFmode || mode == DCmode
+              || mode == TFmode || mode == TCmode))
     return spe_build_register_parallel (mode, GP_ARG_RETURN);
   else
     regno = GP_ARG_RETURN;
index 442f72708b0c9a8ce101515eae2c1866586bc4ea..4c225a3f0e7cac4b31bce3f7774730db2d07f17d 100644 (file)
@@ -583,7 +583,7 @@ extern enum rs6000_nop_insertion rs6000_sched_insert_nops;
 #define LOCAL_ALIGNMENT(TYPE, ALIGN)                           \
   ((TARGET_ALTIVEC && TREE_CODE (TYPE) == VECTOR_TYPE) ? 128 : \
     (TARGET_E500_DOUBLE                                                \
-     && (TYPE_MODE (TYPE) == DFmode || TYPE_MODE (TYPE) == DDmode)) ? 64 : \
+     && TYPE_MODE (TYPE) == DFmode) ? 64 : \
     ((TARGET_SPE && TREE_CODE (TYPE) == VECTOR_TYPE \
      && SPE_VECTOR_MODE (TYPE_MODE (TYPE))) || (TARGET_PAIRED_FLOAT \
         && TREE_CODE (TYPE) == VECTOR_TYPE \
@@ -609,7 +609,7 @@ extern enum rs6000_nop_insertion rs6000_sched_insert_nops;
    fit into 1, whereas DI still needs two.  */
 #define MEMBER_TYPE_FORCES_BLK(FIELD, MODE) \
   ((TARGET_SPE && TREE_CODE (TREE_TYPE (FIELD)) == VECTOR_TYPE) \
-   || (TARGET_E500_DOUBLE && ((MODE) == DFmode || (MODE) == DDmode)))
+   || (TARGET_E500_DOUBLE && (MODE) == DFmode))
 
 /* A bit-field declared as `int' forces `int' alignment for the struct.  */
 #define PCC_BITFIELD_TYPE_MATTERS 1
@@ -630,7 +630,7 @@ extern enum rs6000_nop_insertion rs6000_sched_insert_nops;
   (TREE_CODE (TYPE) == VECTOR_TYPE ? ((TARGET_SPE_ABI \
    || TARGET_PAIRED_FLOAT) ? 64 : 128) \
    : (TARGET_E500_DOUBLE                       \
-      && (TYPE_MODE (TYPE) == DFmode || TYPE_MODE (TYPE) == DDmode)) ? 64 \
+      && TYPE_MODE (TYPE) == DFmode) ? 64 \
    : TREE_CODE (TYPE) == ARRAY_TYPE            \
    && TYPE_MODE (TREE_TYPE (TYPE)) == QImode   \
    && (ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN))
@@ -1212,7 +1212,7 @@ enum reg_class
  (((CLASS) == FLOAT_REGS)                                              \
   ? ((GET_MODE_SIZE (MODE) + UNITS_PER_FP_WORD - 1) / UNITS_PER_FP_WORD) \
   : (TARGET_E500_DOUBLE && (CLASS) == GENERAL_REGS                     \
-     && ((MODE) == DFmode || (MODE) == DDmode))                                \
+     && (MODE) == DFmode)                              \
   ? 1                                                                   \
   : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))