aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog14
-rw-r--r--gcc/config/mips/mips.c28
-rw-r--r--gcc/config/mips/mips.h21
-rw-r--r--gcc/config/mips/mips.md49
4 files changed, 95 insertions, 17 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 0822e65..4740503 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,19 @@
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,
mips_count_memory_refs, mips_fill_delay_slot): Remove.
* config/mips/mips.h (delay_type, dslots_load_total,
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
index 29c0cd6..b487f2b 100644
--- a/gcc/config/mips/mips.c
+++ b/gcc/config/mips/mips.c
@@ -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;
diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h
index e6d9945..2f1a4ee 100644
--- a/gcc/config/mips/mips.h
+++ b/gcc/config/mips/mips.h
@@ -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. */
diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md
index 3284ba9..c91d27f 100644
--- a/gcc/config/mips/mips.md
+++ b/gcc/config/mips/mips.md
@@ -193,17 +193,33 @@
"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"
@@ -211,8 +227,9 @@
;; 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")))
@@ -2274,7 +2291,7 @@
"
{
- 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]));
@@ -2287,7 +2304,7 @@
(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")])
@@ -2299,7 +2316,7 @@
(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";