mips.h (ISA_HAS_LOAD_DELAY, [...]): New macros.
authorRichard Sandiford <rsandifo@redhat.com>
Mon, 19 May 2003 07:36:28 +0000 (07:36 +0000)
committerRichard Sandiford <rsandifo@gcc.gnu.org>
Mon, 19 May 2003 07:36:28 +0000 (07:36 +0000)
* config/mips/mips.h (ISA_HAS_LOAD_DELAY, ISA_HAS_XFER_DELAY,
ISA_HAS_FCMP_DELAY, ISA_HAS_HILO_INTERLOCKS): New macros.
(PREDICATE_CODES): Add hilo_operand.
* config/mips/mips.c (hilo_operand): New predicate.
(mips_adjust_insn_length): Account for the number nops that might
be needed to avoid hardware hazards.
* config/mips/mips.md (dslot): Remove attribute.
(hazard): New attribute.
(can_delay): Use it.  Check for calls, branches & jumps.
(muldi3): Use the standard dmult pattern for mips16 code.
(muldi3_internal, muldi3_internal2): Adjust conditions accordingly.

From-SVN: r66952

gcc/ChangeLog
gcc/config/mips/mips.c
gcc/config/mips/mips.h
gcc/config/mips/mips.md

index 0822e65e0e84ce6c08179965b6f5bfce44567634..47405031138c7d84ed9529e112d897cf42e08b50 100644 (file)
@@ -1,3 +1,17 @@
+2003-05-19  Richard Sandiford  <rsandifo@redhat.com>
+
+       * config/mips/mips.h (ISA_HAS_LOAD_DELAY, ISA_HAS_XFER_DELAY,
+       ISA_HAS_FCMP_DELAY, ISA_HAS_HILO_INTERLOCKS): New macros.
+       (PREDICATE_CODES): Add hilo_operand.
+       * config/mips/mips.c (hilo_operand): New predicate.
+       (mips_adjust_insn_length): Account for the number nops that might
+       be needed to avoid hardware hazards.
+       * config/mips/mips.md (dslot): Remove attribute.
+       (hazard): New attribute.
+       (can_delay): Use it.  Check for calls, branches & jumps.
+       (muldi3): Use the standard dmult pattern for mips16 code.
+       (muldi3_internal, muldi3_internal2): Adjust conditions accordingly.
+
 2003-05-19  Richard Sandiford  <rsandifo@redhat.com>
 
        * config/mips/mips-protos.h (final_prescan_insn,
index 29c0cd693a7b1b45b5246b4c9f47ebaa96172eeb..b487f2b14861c3e6a4207ac68d80d28a7d6108d8 100644 (file)
@@ -1507,6 +1507,18 @@ const_float_1_operand (op, mode)
   return REAL_VALUES_EQUAL (d, dconst1);
 }
 
+/* Return true if OP is either the HI or LO register.  */
+
+int
+hilo_operand (op, mode)
+     rtx op;
+     enum machine_mode mode;
+{
+  return ((mode == VOIDmode || mode == GET_MODE (op))
+         && REG_P (op)
+         && (REGNO (op) == HI_REGNUM || REGNO (op) == LO_REGNUM));
+}
+
 /* Return nonzero if the code of this rtx pattern is EQ or NE.  */
 
 int
@@ -9897,6 +9909,22 @@ mips_adjust_insn_length (insn, length)
                              || GET_CODE (insn) == CALL_INSN)))
     length += 4;
 
+  /* See how many nops might be needed to avoid hardware hazards.  */
+  if (INSN_CODE (insn) >= 0)
+    switch (get_attr_hazard (insn))
+      {
+      case HAZARD_NONE:
+       break;
+
+      case HAZARD_DELAY:
+       length += 4;
+       break;
+
+      case HAZARD_HILO:
+       length += 8;
+       break;
+      }
+
   /* All MIPS16 instructions are a measly two bytes.  */
   if (TARGET_MIPS16)
     length /= 2;
index e6d994510e0bffa39c8e36cc0d79f0f1cf7d2e75..2f1a4eeda09b11d440a35afdebf2685b3490d4c2 100644 (file)
@@ -945,6 +945,24 @@ extern void                sbss_section PARAMS ((void));
                                  && (ISA_MIPS32R2                      \
                                      ))
 
+/* True if the result of a load is not available to the next instruction.
+   A nop will then be needed between instructions like "lw $4,..."
+   and "addiu $4,$4,1".  */
+#define ISA_HAS_LOAD_DELAY     (mips_isa == 1                          \
+                                && !TARGET_MIPS3900                    \
+                                && !TARGET_MIPS16)
+
+/* Likewise mtc1 and mfc1.  */
+#define ISA_HAS_XFER_DELAY     (mips_isa <= 3)
+
+/* Likewise floating-point comparisons.  */
+#define ISA_HAS_FCMP_DELAY     (mips_isa <= 3)
+
+/* True if mflo and mfhi can be immediately followed by instructions
+   which write to the HI and LO registers.  Most targets require a
+   two-instruction gap.  */
+#define ISA_HAS_HILO_INTERLOCKS        (TARGET_MIPS5500 || TARGET_SB1)
+
 /* CC1_SPEC causes -mips3 and -mips4 to set -mfp64 and -mgp64; -mips1 or
    -mips2 sets -mfp32 and -mgp32.  This can be overridden by an explicit
    -mfp32, -mfp64, -mgp32 or -mgp64.  -mfp64 sets MASK_FLOAT64 in
@@ -3374,7 +3392,8 @@ typedef struct mips_args {
                                  REG, MEM}},                           \
   {"consttable_operand",       { LABEL_REF, SYMBOL_REF, CONST_INT,     \
                                  CONST_DOUBLE, CONST }},               \
-  {"fcc_register_operand",     { REG, SUBREG }},
+  {"fcc_register_operand",     { REG, SUBREG }},                       \
+  {"hilo_operand",             { REG }},
 
 /* A list of predicates that do special things with modes, and so
    should not elicit warnings for VOIDmode match_operand.  */
index 3284ba926e2b044dd80e4d43e9389b687b16041b..c91d27f14f419421076496971cbff11fb09bc923 100644 (file)
   "default,4kc,5kc,20kc,m4k,r3000,r3900,r6000,r4000,r4100,r4111,r4120,r4300,r4600,r4650,r5000,r5400,r5500,r8000,sb1,sr71000"
   (const (symbol_ref "mips_cpu_attr")))
 
-;; Does the instruction have a mandatory delay slot?
-;;   The 3900, is (mostly) mips1, but does not have a mandatory load delay
-;;   slot.
-(define_attr "dslot" "no,yes"
-  (if_then_else (ior (eq_attr "type" "branch,jump,call,xfer,hilo,fcmp")
-                    (and (eq_attr "type" "load")
-                         (and (eq (symbol_ref "mips_isa") (const_int 1))
-                              (and (eq (symbol_ref "mips16") (const_int 0))
-                                    (eq_attr "cpu" "!r3900")))))
-               (const_string "yes")
-               (const_string "no")))
+;; The type of hardware hazard associated with this instruction.
+;; DELAY means that the next instruction cannot read the result
+;; of this one.  HILO means that the next two instructions cannot
+;; write to HI or LO.
+(define_attr "hazard" "none,delay,hilo"
+  (cond [(and (eq_attr "type" "load")
+             (ne (symbol_ref "ISA_HAS_LOAD_DELAY") (const_int 0)))
+        (const_string "delay")
+
+        (and (eq_attr "type" "xfer")
+             (ne (symbol_ref "ISA_HAS_XFER_DELAY") (const_int 0)))
+        (const_string "delay")
+
+        (and (eq_attr "type" "fcmp")
+             (ne (symbol_ref "ISA_HAS_FCMP_DELAY") (const_int 0)))
+        (const_string "delay")
+
+        ;; The r4000 multiplication patterns include an mflo instruction.
+        (and (eq_attr "type" "imul")
+             (ne (symbol_ref "TARGET_MIPS4000") (const_int 0)))
+        (const_string "hilo")
+
+        (and (eq_attr "type" "hilo")
+             (and (eq (symbol_ref "ISA_HAS_HILO_INTERLOCKS") (const_int 0))
+                  (match_operand 1 "hilo_operand" "")))
+        (const_string "hilo")]
+       (const_string "none")))
 
 ;; Is it a single instruction?
 (define_attr "single_insn" "no,yes"
 
 ;; Can the instruction be put into a delay slot?
 (define_attr "can_delay" "no,yes"
-  (if_then_else (and (eq_attr "dslot" "no")
-                    (eq_attr "single_insn" "yes"))
+  (if_then_else (and (eq_attr "type" "!branch,call,jump")
+                    (and (eq_attr "hazard" "none")
+                         (eq_attr "single_insn" "yes")))
                (const_string "yes")
                (const_string "no")))
 
 
   "
 {
-  if (GENERATE_MULT3_DI || TARGET_MIPS4000 || TARGET_MIPS16)
+  if (GENERATE_MULT3_DI || TARGET_MIPS4000)
     emit_insn (gen_muldi3_internal2 (operands[0], operands[1], operands[2]));
   else
     emit_insn (gen_muldi3_internal (operands[0], operands[1], operands[2]));
                 (match_operand:DI 2 "register_operand" "d")))
    (clobber (match_scratch:DI 3 "=h"))
    (clobber (match_scratch:DI 4 "=a"))]
-  "TARGET_64BIT && !TARGET_MIPS4000 && !TARGET_MIPS16"
+  "TARGET_64BIT && !TARGET_MIPS4000"
   "dmult\\t%1,%2"
   [(set_attr "type"    "imul")
    (set_attr "mode"    "DI")])
    (clobber (match_scratch:DI 3 "=h"))
    (clobber (match_scratch:DI 4 "=l"))
    (clobber (match_scratch:DI 5 "=a"))]
-  "TARGET_64BIT && (GENERATE_MULT3_DI || TARGET_MIPS4000 || TARGET_MIPS16)"
+  "TARGET_64BIT && (GENERATE_MULT3_DI || TARGET_MIPS4000)"
   {
     if (GENERATE_MULT3_DI)
       return "dmult\t%0,%1,%2";