OSDN Git Service

* config/rs6000/rs6000.h (CLASS_MAX_NREGS): DF goes in 1 register
authoraldyh <aldyh@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 14 Jan 2005 21:22:14 +0000 (21:22 +0000)
committeraldyh <aldyh@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 14 Jan 2005 21:22:14 +0000 (21:22 +0000)
on e500v2.
(CANNOT_CHANGE_MODE_CLASS): Restrict DI mode changes on e500v2.
(PREDICATE_CODES): Add rs6k_nonimmediate_operand.

* config/rs6000/rs6000.c (invalid_e500_subreg): New.
(rs6k_nonimmediate_operand): New.
(rs6000_legitimate_offset_address_p): Handle DI modes on e500v2
correctly.
(legitimate_lo_sum_address_p): Same.
(rs6000_legitimize_address): Same.
(rs6000_legitimize_reload_address): Same.
(rs6000_legitimate_address): Same.
(spe_build_register_parallel): Pass DF and DC modes in a DI
register.

* config/rs6000/rs6000.md ("*movsi_internal1"): Change predicate
to rs6k_nonimmediate_operand.

* config/rs6000/spe.md ("*frob_df_di"): New.
("*frob_di_df"): New.
("*frob_di_df_2"): New.
("*mov_sidf_e500_subreg0"): New.
("*mov_sidf_e500_subreg4"): New.
("*movdf_e500_double"): Change predicate to
rs6k_nonimmediate_operand.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@93665 138bc75d-0d04-0410-961f-82ee72b054a4

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

index 2d0d11b..53e9844 100644 (file)
@@ -1,5 +1,34 @@
 2005-01-14  Aldy Hernandez  <aldyh@redhat.com>
 
+       * config/rs6000/rs6000.h (CLASS_MAX_NREGS): DF goes in 1 register
+       on e500v2.
+       (CANNOT_CHANGE_MODE_CLASS): Restrict DI mode changes on e500v2.
+       (PREDICATE_CODES): Add rs6k_nonimmediate_operand.
+
+       * config/rs6000/rs6000.c (invalid_e500_subreg): New.
+       (rs6k_nonimmediate_operand): New.
+       (rs6000_legitimate_offset_address_p): Handle DI modes on e500v2
+       correctly.
+       (legitimate_lo_sum_address_p): Same.
+       (rs6000_legitimize_address): Same.
+       (rs6000_legitimize_reload_address): Same.
+       (rs6000_legitimate_address): Same.
+       (spe_build_register_parallel): Pass DF and DC modes in a DI
+       register.
+
+       * config/rs6000/rs6000.md ("*movsi_internal1"): Change predicate
+       to rs6k_nonimmediate_operand.
+
+       * config/rs6000/spe.md ("*frob_df_di"): New.
+       ("*frob_di_df"): New.
+       ("*frob_di_df_2"): New.
+       ("*mov_sidf_e500_subreg0"): New.
+       ("*mov_sidf_e500_subreg4"): New.
+       ("*movdf_e500_double"): Change predicate to
+       rs6k_nonimmediate_operand.
+
+2005-01-14  Aldy Hernandez  <aldyh@redhat.com>
+
        * postreload.c (move2add_note_store): Only call
        trunc_int_for_mode on scalar integers.
 
index a6a8871..a8586a6 100644 (file)
@@ -710,6 +710,7 @@ static rtx spe_expand_builtin (tree, rtx, bool *);
 static rtx spe_expand_stv_builtin (enum insn_code, tree);
 static rtx spe_expand_predicate_builtin (enum insn_code, tree, rtx);
 static rtx spe_expand_evsel_builtin (enum insn_code, tree, rtx);
+static bool invalid_e500_subreg (rtx, enum machine_mode);
 static int rs6000_emit_int_cmove (rtx, rtx, rtx, rtx);
 static rs6000_stack_t *rs6000_stack_info (void);
 static void debug_stack_info (rs6000_stack_t *);
@@ -3035,6 +3036,39 @@ input_operand (rtx op, enum machine_mode mode)
   return 0;
 }
 
+/* Return TRUE if OP is an invalid SUBREG operation on the e500.  */
+static bool
+invalid_e500_subreg (rtx op, enum machine_mode mode)
+{
+  /* Reject (subreg:SI (reg:DF)).  */
+  if (GET_CODE (op) == SUBREG
+      && mode == SImode
+      && REG_P (SUBREG_REG (op))
+      && GET_MODE (SUBREG_REG (op)) == DFmode)
+    return true;
+
+  /* Reject (subreg:DF (reg:DI)).  */
+  if (GET_CODE (op) == SUBREG
+      && mode == DFmode
+      && REG_P (SUBREG_REG (op))
+      && GET_MODE (SUBREG_REG (op)) == DImode)
+    return true;
+
+  return false;
+}
+
+/* Just like nonimmediate_operand, but return 0 for invalid SUBREG's
+   on the e500.  */
+int
+rs6k_nonimmediate_operand (rtx op, enum machine_mode mode)
+{
+  if (TARGET_E500_DOUBLE
+      && GET_CODE (op) == SUBREG
+      && invalid_e500_subreg (op, mode))
+    return 0;
+
+  return nonimmediate_operand (op, mode);
+}
 
 /* Darwin, AIX increases natural record alignment to doubleword if the first
    field is an FP double while the FP fields remain word aligned.  */
@@ -3248,6 +3282,14 @@ rs6000_legitimate_offset_address_p (enum machine_mode mode, rtx x, int strict)
        return SPE_CONST_OFFSET_OK (offset);
 
     case DImode:
+      /* On e500v2, we may have:
+
+          (subreg:DF (mem:DI (plus (reg) (const_int))) 0).
+
+         Which gets addressed with evldd instructions.  */
+      if (TARGET_E500_DOUBLE)
+       return SPE_CONST_OFFSET_OK (offset);
+
       if (mode == DFmode || !TARGET_POWERPC64)
        extra = 4;
       else if (offset & 3)
@@ -3326,7 +3368,8 @@ legitimate_lo_sum_address_p (enum machine_mode mode, rtx x, int strict)
     return false;
   if (!INT_REG_OK_FOR_BASE_P (XEXP (x, 0), strict))
     return false;
-  if (TARGET_E500_DOUBLE && mode == DFmode)
+  /* Restrict addressing for DI because of our SUBREG hackery.  */
+  if (TARGET_E500_DOUBLE && (mode == DFmode || mode == DImode))
     return false;
   x = XEXP (x, 1);
 
@@ -3403,7 +3446,8 @@ rs6000_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
           && GET_MODE_NUNITS (mode) == 1
           && ((TARGET_HARD_FLOAT && TARGET_FPRS)
               || TARGET_POWERPC64
-              || ((mode != DFmode || TARGET_E500_DOUBLE) && mode != TFmode))
+              || (((mode != DImode && mode != DFmode) || TARGET_E500_DOUBLE)
+                  && mode != TFmode))
           && (TARGET_POWERPC64 || mode != DImode)
           && mode != TImode)
     {
@@ -3423,8 +3467,11 @@ rs6000_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
       return reg;
     }
   else if (SPE_VECTOR_MODE (mode)
-          || (TARGET_E500_DOUBLE && mode == DFmode))
+          || (TARGET_E500_DOUBLE && (mode == DFmode
+                                     || mode == DImode)))
     {
+      if (mode == DImode)
+       return NULL_RTX;
       /* We accept [reg + reg] and [reg + OFFSET].  */
 
       if (GET_CODE (x) == PLUS)
@@ -3834,7 +3881,8 @@ 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)
+      && !(TARGET_E500_DOUBLE && (mode == DFmode
+                                 || mode == DImode))
       && !ALTIVEC_VECTOR_MODE (mode))
     {
       HOST_WIDE_INT val = INTVAL (XEXP (x, 1));
@@ -3942,7 +3990,8 @@ 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)
+      /* Restrict addressing for DI because of our SUBREG hackery.  */
+      && !(TARGET_E500_DOUBLE && (mode == DFmode || mode == DImode))
       && TARGET_UPDATE
       && legitimate_indirect_address_p (XEXP (x, 0), reg_ok_strict))
     return 1;
@@ -5084,31 +5133,23 @@ function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
 static rtx
 spe_build_register_parallel (enum machine_mode mode, int gregno)
 {
-  rtx r1, r2, r3, r4;
-  enum machine_mode inner = SImode;
+  rtx r1, r3;
 
   if (mode == DFmode)
     {
-      r1 = gen_rtx_REG (inner, gregno);
-      r1 = gen_rtx_EXPR_LIST (SImode, r1, const0_rtx);
-      r2 = gen_rtx_REG (inner, gregno + 1);
-      r2 = gen_rtx_EXPR_LIST (SImode, r2, GEN_INT (4));
-      return gen_rtx_PARALLEL (mode, gen_rtvec (2, r1, r2));
+      r1 = gen_rtx_REG (DImode, gregno);
+      r1 = gen_rtx_EXPR_LIST (VOIDmode, r1, const0_rtx);
+      return gen_rtx_PARALLEL (mode, gen_rtvec (1, r1));
     }
   else if (mode == DCmode)
     {
-      r1 = gen_rtx_REG (inner, gregno);
-      r1 = gen_rtx_EXPR_LIST (SImode, r1, const0_rtx);
-      r2 = gen_rtx_REG (inner, gregno + 1);
-      r2 = gen_rtx_EXPR_LIST (SImode, r2, GEN_INT (4));
-      r3 = gen_rtx_REG (inner, gregno + 2);
-      r3 = gen_rtx_EXPR_LIST (SImode, r3, GEN_INT (8));
-      r4 = gen_rtx_REG (inner, gregno + 3);
-      r4 = gen_rtx_EXPR_LIST (SImode, r4, GEN_INT (12));
-      return gen_rtx_PARALLEL (mode, gen_rtvec (4, r1, r2, r3, r4));
+      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));
+      return gen_rtx_PARALLEL (mode, gen_rtvec (2, r1, r3));
     }
-
-  abort ();
+  abort();
   return NULL_RTX;
 }
 
index 63c1b83..215fdcd 100644 (file)
@@ -1429,6 +1429,8 @@ enum reg_class
 #define CLASS_MAX_NREGS(CLASS, MODE)                                   \
  (((CLASS) == FLOAT_REGS)                                              \
   ? ((GET_MODE_SIZE (MODE) + UNITS_PER_FP_WORD - 1) / UNITS_PER_FP_WORD) \
+  : (TARGET_E500_DOUBLE && (CLASS) == GENERAL_REGS && (MODE) == DFmode) \
+  ? 1                                                                   \
   : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
 
 
@@ -1442,6 +1444,8 @@ enum reg_class
    ? reg_classes_intersect_p (FLOAT_REGS, CLASS)                         \
    : (TARGET_E500_DOUBLE && (((TO) == DFmode) + ((FROM) == DFmode)) == 1) \
    ? reg_classes_intersect_p (GENERAL_REGS, CLASS)                       \
+   : (TARGET_E500_DOUBLE && (((TO) == DImode) + ((FROM) == DImode)) == 1) \
+   ? reg_classes_intersect_p (GENERAL_REGS, CLASS)                       \
    : (TARGET_SPE && (SPE_VECTOR_MODE (FROM) + SPE_VECTOR_MODE (TO)) == 1) \
    ? reg_classes_intersect_p (GENERAL_REGS, CLASS)                       \
    : 0)
@@ -2588,6 +2592,7 @@ extern char rs6000_reg_names[][8];        /* register names (0 vs. %r0).  */
   {"current_file_function_operand", {SYMBOL_REF}},                        \
   {"input_operand", {SUBREG, MEM, REG, CONST_INT,                         \
                     CONST_DOUBLE, SYMBOL_REF}},                           \
+  {"rs6k_nonimmediate_operand", {SUBREG, MEM, REG}},                      \
   {"load_multiple_operation", {PARALLEL}},                                \
   {"store_multiple_operation", {PARALLEL}},                               \
   {"lmw_operation", {PARALLEL}},                                          \
index e3ba021..890088e 100644 (file)
    (set_attr "length" "4")])
 
 (define_insn "*movsi_internal1"
-  [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,m,r,r,r,r,r,*q,*c*l,*h,*h")
+  [(set (match_operand:SI 0 "rs6k_nonimmediate_operand" "=r,r,r,m,r,r,r,r,r,*q,*c*l,*h,*h")
        (match_operand:SI 1 "input_operand" "r,U,m,r,I,L,n,R,*h,r,r,r,0"))]
   "gpc_reg_operand (operands[0], SImode)
    || gpc_reg_operand (operands[1], SImode)"
index 6e40371..c43adcb 100644 (file)
    (set_attr  "length" "4")])
 
 ;; Double-precision floating point instructions.
+
+;; FIXME: Add o=r option.
+(define_insn "*frob_df_di"
+  [(set (match_operand:DF 0 "nonimmediate_operand" "=r,r")
+        (subreg:DF (match_operand:DI 1 "input_operand" "r,m") 0))]
+  "TARGET_E500_DOUBLE"
+  "@
+   evmergelo %0,%H1,%L1
+   evldd%X1 %0,%y1")
+
+(define_insn "*frob_di_df"
+  [(set (match_operand:DI 0 "nonimmediate_operand" "=&r")
+        (subreg:DI (match_operand:DF 1 "input_operand" "r") 0))]
+  "TARGET_E500_DOUBLE" /*one of these can be an mr */
+  "evmergehi %H0,%1,%1\;evmergelo %L0,%1,%1"
+  [(set_attr "length" "8")])
+
+(define_insn "*frob_di_df_2"
+  [(set (subreg:DF (match_operand:DI 0 "register_operand" "=&r") 0)
+       (match_operand:DF 1 "register_operand" "r"))]
+  "TARGET_E500_DOUBLE"
+  "evmergehi %H0,%1,%1\;evmergelo %L0,%1,%1"
+  [(set_attr "length" "8")])
+
+(define_insn "*mov_sidf_e500_subreg0"
+  [(set (subreg:SI (match_operand:DF 0 "register_operand" "+r") 0)
+       (match_operand:SI 1 "register_operand" "r"))]
+  "TARGET_E500_DOUBLE"
+  "evmergelo %0,%1,%0")
+
+(define_insn "*mov_sidf_e500_subreg4"
+  [(set (subreg:SI (match_operand:DF 0 "register_operand" "+r") 4)
+       (match_operand:SI 1 "register_operand" "r"))]
+  "TARGET_E500_DOUBLE"
+  "mr %0,%1")
+
+;; FIXME: Allow r=CONST0.
 (define_insn "*movdf_e500_double"
-  [(set (match_operand:DF 0 "nonimmediate_operand" "=r,r,m")
+  [(set (match_operand:DF 0 "rs6k_nonimmediate_operand" "=r,r,m")
        (match_operand:DF 1 "input_operand" "r,m,r"))]
   "TARGET_HARD_FLOAT && TARGET_E500_DOUBLE
     && (gpc_reg_operand (operands[0], DFmode)