(memory): Change r4100/r4300 support.
authorJim Wilson <wilson@gcc.gnu.org>
Mon, 17 Jun 1996 19:01:47 +0000 (12:01 -0700)
committerJim Wilson <wilson@gcc.gnu.org>
Mon, 17 Jun 1996 19:01:47 +0000 (12:01 -0700)
(imuldiv): Add r4300 support.
(high, low): New patterns.
(movsi, movdi): Add LO_SUM support.
(movsi_internal1, movsi_internal2): Use move_operand instead of
general_operand.
(movstrsi_internal, movstrsi_internal2): Delete R constraint.
(call, call_value): Pass address instead of MEM to call_insn_operand.
Call gen_call_{value_}internal0 instead of internal1.
(call_internal0, call_value_internal0, call_multiple_internal0):
New patterns.
(call_internal1, call_internal2, call_value_internal1,
call_value_internal2, call_value_multiple_internal2): Add explicit
MEM before target address.

From-SVN: r12287

gcc/config/mips/mips.md

index f75e73773edb86eb155a66fcf107368d7034740f..fe58fdda774ab02f6d77bb67cb36db78d321b40f 100644 (file)
   3 0)
 
 (define_function_unit "memory" 1 0
-  (and (eq_attr "type" "load") (eq_attr "cpu" "r3000,r4600,r4650"))
+  (and (eq_attr "type" "load") (eq_attr "cpu" "r3000,r4600,r4650,r4100,r4300"))
   2 0)
 
-(define_function_unit "memory" 1 0
-  (and (eq_attr "type" "load") (eq_attr "cpu" "r4100,r4300"))
-  1 0)
-
 (define_function_unit "memory"   1 0 (eq_attr "type" "store") 1 0)
 
 (define_function_unit "memory"   1 0 (eq_attr "type" "xfer") 2 0)
   (and (eq_attr "type" "fadd") (eq_attr "cpu" "r4300"))
   3 3)
 
+(define_function_unit "imuldiv" 1 0
+  (and (eq_attr "type" "fcmp,fabs,fneg") (eq_attr "cpu" "r4300"))
+  1 1)
+
 (define_function_unit "imuldiv" 1 0
   (and (eq_attr "type" "fmul") (and (eq_attr "mode" "SF") (eq_attr "cpu" "r4300")))
   5 5)
 ;;  ....................
 ;;
 
-;; Vr4300 has a CPU bug where multiplies with certain operands may
-;; corrupt immediately following multiplies. This is a simple fix to
-;; insert NOPs.
+;; Early Vr4300 silicon has a CPU bug where multiplies with certain
+;; operands may corrupt immediately following multiplies. This is a
+;; simple fix to insert NOPs.
 
 (define_expand "muldf3"
   [(set (match_operand:DF 0 "register_operand" "=f")
@@ -3108,6 +3108,30 @@ move\\t%0,%z4\\n\\
    (set_attr "mode"    "SI")
    (set_attr "length"  "2,4")])
 
+;; These two patterns support loading addresses with two instructions instead
+;; of using the macro instruction la.
+
+;; ??? mips_move_1word has support for HIGH, so this pattern may be
+;; unnecessary.
+
+(define_insn "high"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (high:SI (match_operand:SI 1 "immediate_operand" "")))]
+  "mips_split_addresses"
+  "lui\\t%0,%%hi(%1) # high"
+  [(set_attr "type"    "move")
+   (set_attr "length"  "1")])
+
+(define_insn "low"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (lo_sum:SI (match_operand:SI 1 "register_operand" "r")
+                  (match_operand:SI 2 "immediate_operand" "")))]
+  "mips_split_addresses"
+  "addiu\\t%0,%1,%%lo(%2) # low"
+  [(set_attr "type"    "arith")
+   (set_attr "mode"    "SI")
+   (set_attr "length"  "1")])
+
 ;; 64-bit integer moves
 
 ;; Unlike most other insns, the move insns can't be split with
@@ -3120,6 +3144,18 @@ move\\t%0,%z4\\n\\
   ""
   "
 {
+  if (mips_split_addresses && mips_check_split (operands[1], DImode))
+    {
+      enum machine_mode mode = GET_MODE (operands[0]);
+      rtx tem = ((reload_in_progress | reload_completed)
+                ? operands[0] : gen_reg_rtx (mode));
+
+      emit_insn (gen_rtx (SET, VOIDmode, tem,
+                         gen_rtx (HIGH, mode, operands[1])));
+
+      operands[1] = gen_rtx (LO_SUM, mode, tem, operands[1]);
+    }
+
   /* If we are generating embedded PIC code, and we are referring to a
      symbol in the .text section, we must use an offset from the start
      of the function.  */
@@ -3359,6 +3395,18 @@ move\\t%0,%z4\\n\\
   ""
   "
 {
+  if (mips_split_addresses && mips_check_split (operands[1], SImode))
+    {
+      enum machine_mode mode = GET_MODE (operands[0]);
+      rtx tem = ((reload_in_progress | reload_completed)
+                ? operands[0] : gen_reg_rtx (mode));
+
+      emit_insn (gen_rtx (SET, VOIDmode, tem,
+                         gen_rtx (HIGH, mode, operands[1])));
+
+      operands[1] = gen_rtx (LO_SUM, mode, tem, operands[1]);
+    }
+
   /* If we are generating embedded PIC code, and we are referring to a
      symbol in the .text section, we must use an offset from the start
      of the function.  */
@@ -3406,7 +3454,7 @@ move\\t%0,%z4\\n\\
 
 (define_insn "movsi_internal1"
   [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,d,d,d,d,R,m,*d,*f*z,*f,*f,*f,*R,*m,*x,*x,*d,*d")
-       (match_operand:SI 1 "general_operand" "d,S,IKL,Mnis,R,m,dJ,dJ,*f*z,*d,*f,*R,*m,*f,*f,I,*d,*x,*a"))]
+       (match_operand:SI 1 "move_operand" "d,S,IKL,Mnis,R,m,dJ,dJ,*f*z,*d,*f,*R,*m,*f,*f,I,*d,*x,*a"))]
   "TARGET_DEBUG_H_MODE
    && (register_operand (operands[0], SImode)
        || register_operand (operands[1], SImode)
@@ -3418,7 +3466,7 @@ move\\t%0,%z4\\n\\
 
 (define_insn "movsi_internal2"
   [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,d,d,d,d,R,m,*d,*z,*x,*d,*x,*d")
-       (match_operand:SI 1 "general_operand" "d,S,IKL,Mnis,R,m,dJ,dJ,*z,*d,I,*x,*d,*a"))]
+       (match_operand:SI 1 "move_operand" "d,S,IKL,Mnis,R,m,dJ,dJ,*z,*d,I,*x,*d,*a"))]
   "!TARGET_DEBUG_H_MODE
    && (register_operand (operands[0], SImode)
        || register_operand (operands[1], SImode)
@@ -3714,8 +3762,8 @@ move\\t%0,%z4\\n\\
 ;; Insn generated by block moves
 
 (define_insn "movstrsi_internal"
-  [(set (match_operand:BLK 0 "memory_operand" "=Ro")   ;; destination
-       (match_operand:BLK 1 "memory_operand" "Ro"))    ;; source
+  [(set (match_operand:BLK 0 "memory_operand" "=o")    ;; destination
+       (match_operand:BLK 1 "memory_operand" "o"))     ;; source
    (clobber (match_scratch:SI 4 "=&d"))                        ;; temp 1
    (clobber (match_scratch:SI 5 "=&d"))                        ;; temp 2
    (clobber (match_scratch:SI 6 "=&d"))                        ;; temp 3
@@ -3773,8 +3821,8 @@ move\\t%0,%z4\\n\\
   "")
 
 (define_insn "movstrsi_internal2"
-  [(set (match_operand:BLK 0 "memory_operand" "=Ro")   ;; destination
-       (match_operand:BLK 1 "memory_operand" "Ro"))    ;; source
+  [(set (match_operand:BLK 0 "memory_operand" "=o")    ;; destination
+       (match_operand:BLK 1 "memory_operand" "o"))     ;; source
    (clobber (match_scratch:SI 4 "=&d"))                        ;; temp 1
    (clobber (match_scratch:SI 5 "=&d"))                        ;; temp 2
    (clobber (match_scratch:SI 6 "=&d"))                        ;; temp 3
@@ -6277,7 +6325,7 @@ move\\t%0,%z4\\n\\
     {
       addr = XEXP (operands[0], 0);
       if ((GET_CODE (addr) != REG && (!CONSTANT_ADDRESS_P (addr) || TARGET_LONG_CALLS))
-         || ! call_insn_operand (operands[0], VOIDmode))
+         || ! call_insn_operand (addr, VOIDmode))
        XEXP (operands[0], 0) = copy_to_mode_reg (Pmode, addr);
 
       /* In order to pass small structures by value in registers
@@ -6297,20 +6345,27 @@ move\\t%0,%z4\\n\\
            emit_insn (RTVEC_ELT (adjust, i));
        }
 
-      emit_call_insn (gen_call_internal1 (operands[0], operands[1],
+      emit_call_insn (gen_call_internal0 (operands[0], operands[1],
                                          gen_rtx (REG, SImode, GP_REG_FIRST + 31)));
       DONE;
     }
 }")
 
+(define_expand "call_internal0"
+  [(parallel [(call (match_operand 0 "" "")
+                   (match_operand 1 "" ""))
+             (clobber (match_operand:SI 2 "" ""))])]
+  ""
+  "")
+
 (define_insn "call_internal1"
-  [(call (match_operand 0 "call_insn_operand" "m")
+  [(call (mem (match_operand 0 "call_insn_operand" "ri"))
         (match_operand 1 "" "i"))
    (clobber (match_operand:SI 2 "register_operand" "=d"))]
   "!TARGET_ABICALLS && !TARGET_LONG_CALLS"
   "*
 {
-  register rtx target = XEXP (operands[0], 0);
+  register rtx target = operands[0];
 
   if (GET_CODE (target) == SYMBOL_REF)
     return \"%*jal\\t%0\";
@@ -6332,13 +6387,13 @@ move\\t%0,%z4\\n\\
    (set_attr "length"  "1")])
 
 (define_insn "call_internal2"
-  [(call (match_operand 0 "call_insn_operand" "m")
+  [(call (mem (match_operand 0 "call_insn_operand" "ri"))
         (match_operand 1 "" "i"))
    (clobber (match_operand:SI 2 "register_operand" "=d"))]
   "TARGET_ABICALLS && !TARGET_LONG_CALLS"
   "*
 {
-  register rtx target = XEXP (operands[0], 0);
+  register rtx target = operands[0];
 
   if (GET_CODE (target) == SYMBOL_REF)
     return \"jal\\t%0\";
@@ -6431,7 +6486,7 @@ move\\t%0,%z4\\n\\
     {
       addr = XEXP (operands[1], 0);
       if ((GET_CODE (addr) != REG && (!CONSTANT_ADDRESS_P (addr) || TARGET_LONG_CALLS))
-         || ! call_insn_operand (operands[1], VOIDmode))
+         || ! call_insn_operand (addr, VOIDmode))
        XEXP (operands[1], 0) = copy_to_mode_reg (Pmode, addr);
 
       /* In order to pass small structures by value in registers
@@ -6455,7 +6510,7 @@ move\\t%0,%z4\\n\\
         results.  */
       if (GET_CODE (operands[0]) == PARALLEL)
        {
-         emit_call_insn (gen_call_value_multiple_internal2
+         emit_call_insn (gen_call_value_multiple_internal0
                          (XEXP (XVECEXP (operands[0], 0, 0), 0),
                           operands[1], operands[2],
                           XEXP (XVECEXP (operands[0], 0, 1), 0),
@@ -6463,22 +6518,30 @@ move\\t%0,%z4\\n\\
          DONE;
        }
 
-      emit_call_insn (gen_call_value_internal1 (operands[0], operands[1], operands[2],
-                                               gen_rtx (REG, SImode, GP_REG_FIRST + 31)));
+      emit_call_insn (gen_call_value_internal0 (operands[0], operands[1], operands[2],
+                                               gen_rtx (REG, Pmode, GP_REG_FIRST + 31)));
 
       DONE;
     }
 }")
 
+(define_expand "call_value_internal0"
+  [(parallel [(set (match_operand 0 "" "")
+                  (call (match_operand 1 "" "")
+                        (match_operand 2 "" "")))
+             (clobber (match_operand:SI 3 "" ""))])]
+  ""
+  "")
+
 (define_insn "call_value_internal1"
   [(set (match_operand 0 "register_operand" "=df")
-        (call (match_operand 1 "call_insn_operand" "m")
+        (call (mem (match_operand 1 "call_insn_operand" "ri"))
               (match_operand 2 "" "i")))
    (clobber (match_operand:SI 3 "register_operand" "=d"))]
   "!TARGET_ABICALLS && !TARGET_LONG_CALLS"
   "*
 {
-  register rtx target = XEXP (operands[1], 0);
+  register rtx target = operands[1];
 
   if (GET_CODE (target) == SYMBOL_REF)
     return \"%*jal\\t%1\";
@@ -6501,13 +6564,13 @@ move\\t%0,%z4\\n\\
 
 (define_insn "call_value_internal2"
   [(set (match_operand 0 "register_operand" "=df")
-        (call (match_operand 1 "call_insn_operand" "m")
+        (call (mem (match_operand 1 "call_insn_operand" "ri"))
               (match_operand 2 "" "i")))
    (clobber (match_operand:SI 3 "register_operand" "=d"))]
   "TARGET_ABICALLS && !TARGET_LONG_CALLS"
   "*
 {
-  register rtx target = XEXP (operands[1], 0);
+  register rtx target = operands[1];
 
   if (GET_CODE (target) == SYMBOL_REF)
     return \"jal\\t%1\";
@@ -6587,21 +6650,32 @@ move\\t%0,%z4\\n\\
    (set_attr "mode"    "none")
    (set_attr "length"  "2")])
 
+(define_insn "call_value_multiple_internal0"
+  [(parallel [(set (match_operand 0 "" "")
+                  (call (match_operand 1 "" "")
+                        (match_operand 2 "" "")))
+             (set (match_operand 3 "" "")
+                  (call (match_dup 1)
+                        (match_dup 2)))
+             (clobber (match_operand:SI 4 "" ""))])]
+  ""
+  "")
+
 ;; ??? May eventually need all 6 versions of the call patterns with multiple
 ;; return values.
 
 (define_insn "call_value_multiple_internal2"
   [(set (match_operand 0 "register_operand" "=df")
-        (call (match_operand 1 "call_insn_operand" "m")
+        (call (mem (match_operand 1 "call_insn_operand" "ri"))
               (match_operand 2 "" "i")))
    (set (match_operand 3 "register_operand" "=df")
-        (call (match_dup 1)
+        (call (mem (match_dup 1))
               (match_dup 2)))
    (clobber (match_operand:SI 4 "register_operand" "=d"))]
   "TARGET_ABICALLS && !TARGET_LONG_CALLS"
   "*
 {
-  register rtx target = XEXP (operands[1], 0);
+  register rtx target = operands[1];
 
   if (GET_CODE (target) == SYMBOL_REF)
     return \"jal\\t%1\";