aboutsummaryrefslogtreecommitdiff
path: root/gcc/config
diff options
context:
space:
mode:
authorcgd <cgd@138bc75d-0d04-0410-961f-82ee72b054a4>2003-08-22 22:36:42 +0000
committercgd <cgd@138bc75d-0d04-0410-961f-82ee72b054a4>2003-08-22 22:36:42 +0000
commitaae4c6423e72f16322265cb00d61d44f27364efe (patch)
tree696b3199dad4763226cb2c4ca1d91a77a4c97568 /gcc/config
parentec64a609bf7f60b8d6c0329280df99fbe5d8ca6c (diff)
2003-08-22 Chris Demetriou <cgd@broadcom.com>
* config/mips/mips.h (MASK_FIX_SB1, TARGET_FIX_SB1): New defines. (TARGET_SWITCHES): Add -mfix-sb1 and -mno-fix-sb1. * config/mips/mips.md (divdf3, divsf3, sqrtdf2, sqrtsf2): Work around SB-1 errata if TARGET_FIX_SB1 is set. (recip.d insn, recip.s insn, rsqrt.d insn, rsqrt.s insn): Likewise. * doc/invoke.texi: Document MIPS -mfix-sb1 and -mno-fix-sb1. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@70707 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config')
-rw-r--r--gcc/config/mips/mips.h6
-rw-r--r--gcc/config/mips/mips.md141
2 files changed, 130 insertions, 17 deletions
diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h
index 27a4a03eeb4..38aa9510487 100644
--- a/gcc/config/mips/mips.h
+++ b/gcc/config/mips/mips.h
@@ -170,6 +170,7 @@ extern const struct mips_cpu_info *mips_tune_info;
#define MASK_UNINIT_CONST_IN_RODATA \
0x00800000 /* Store uninitialized
consts in rodata */
+#define MASK_FIX_SB1 0x01000000 /* Work around SB-1 errata. */
/* Debug switches, not documented */
#define MASK_DEBUG 0 /* unused */
@@ -255,6 +256,7 @@ extern const struct mips_cpu_info *mips_tune_info;
#define TARGET_BRANCHLIKELY (target_flags & MASK_BRANCHLIKELY)
+#define TARGET_FIX_SB1 (target_flags & MASK_FIX_SB1)
/* True if we should use NewABI-style relocation operators for
symbolic addresses. This is never true for mips16 code,
@@ -580,6 +582,10 @@ extern const struct mips_cpu_info *mips_tune_info;
N_("Work around early 4300 hardware bug")}, \
{"no-fix4300", -MASK_4300_MUL_FIX, \
N_("Don't work around early 4300 hardware bug")}, \
+ {"fix-sb1", MASK_FIX_SB1, \
+ N_("Work around errata for early SB-1 revision 2 cores")}, \
+ {"no-fix-sb1", -MASK_FIX_SB1, \
+ N_("Don't work around errata for early SB-1 revision 2 cores")}, \
{"check-zero-division",-MASK_NO_CHECK_ZERO_DIV, \
N_("Trap on integer divide by zero")}, \
{"no-check-zero-division", MASK_NO_CHECK_ZERO_DIV, \
diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md
index 832140e409e..e843d53734c 100644
--- a/gcc/config/mips/mips.md
+++ b/gcc/config/mips/mips.md
@@ -2365,41 +2365,104 @@
;; ....................
;;
+;; This pattern works around the early SB-1 rev2 core "F1" erratum:
+;;
+;; If an mfc1 or dmfc1 happens to access the floating point register
+;; file at the same time a long latency operation (div, sqrt, recip,
+;; sqrt) iterates an intermediate result back through the floating
+;; point register file bypass, then instead returning the correct
+;; register value the mfc1 or dmfc1 operation returns the intermediate
+;; result of the long latency operation.
+;;
+;; The workaround is to insert an unconditional 'mov' from/to the
+;; long latency op destination register.
(define_insn "divdf3"
[(set (match_operand:DF 0 "register_operand" "=f")
(div:DF (match_operand:DF 1 "register_operand" "f")
(match_operand:DF 2 "register_operand" "f")))]
"TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT"
- "div.d\t%0,%1,%2"
+{
+ if (TARGET_FIX_SB1)
+ return "div.d\t%0,%1,%2\;mov.d\t%0,%0";
+ else
+ return "div.d\t%0,%1,%2";
+}
[(set_attr "type" "fdiv")
- (set_attr "mode" "DF")])
+ (set_attr "mode" "DF")
+ (set (attr "length")
+ (if_then_else (ne (symbol_ref "TARGET_FIX_SB1") (const_int 0))
+ (const_int 8)
+ (const_int 4)))])
+
+;; This pattern works around the early SB-1 rev2 core "F1" erratum (see
+;; "divdf3" comment for details).
+;;
+;; This pattern works around the early SB-1 rev2 core "F2" erratum:
+;;
+;; In certain cases, div.s and div.ps may have a rounding error
+;; and/or wrong inexact flag.
+;;
+;; Therefore, we only allow div.s if not working around SB-1 rev2
+;; errata, or if working around those errata and a slight loss of
+;; precision is OK (i.e., flag_unsafe_math_optimizations is set).
(define_insn "divsf3"
[(set (match_operand:SF 0 "register_operand" "=f")
(div:SF (match_operand:SF 1 "register_operand" "f")
(match_operand:SF 2 "register_operand" "f")))]
- "TARGET_HARD_FLOAT"
- "div.s\t%0,%1,%2"
+ "TARGET_HARD_FLOAT && (!TARGET_FIX_SB1 || flag_unsafe_math_optimizations)"
+{
+ if (TARGET_FIX_SB1)
+ return "div.s\t%0,%1,%2\;mov.s\t%0,%0";
+ else
+ return "div.s\t%0,%1,%2";
+}
[(set_attr "type" "fdiv")
- (set_attr "mode" "SF")])
+ (set_attr "mode" "SF")
+ (set (attr "length")
+ (if_then_else (ne (symbol_ref "TARGET_FIX_SB1") (const_int 0))
+ (const_int 8)
+ (const_int 4)))])
+;; This pattern works around the early SB-1 rev2 core "F1" erratum (see
+;; "divdf3" comment for details).
(define_insn ""
[(set (match_operand:DF 0 "register_operand" "=f")
(div:DF (match_operand:DF 1 "const_float_1_operand" "")
(match_operand:DF 2 "register_operand" "f")))]
"ISA_HAS_FP4 && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && flag_unsafe_math_optimizations"
- "recip.d\t%0,%2"
+{
+ if (TARGET_FIX_SB1)
+ return "recip.d\t%0,%2\;mov.d\t%0,%0";
+ else
+ return "recip.d\t%0,%2";
+}
[(set_attr "type" "fdiv")
- (set_attr "mode" "DF")])
+ (set_attr "mode" "DF")
+ (set (attr "length")
+ (if_then_else (ne (symbol_ref "TARGET_FIX_SB1") (const_int 0))
+ (const_int 8)
+ (const_int 4)))])
+;; This pattern works around the early SB-1 rev2 core "F1" erratum (see
+;; "divdf3" comment for details).
(define_insn ""
[(set (match_operand:SF 0 "register_operand" "=f")
(div:SF (match_operand:SF 1 "const_float_1_operand" "")
(match_operand:SF 2 "register_operand" "f")))]
"ISA_HAS_FP4 && TARGET_HARD_FLOAT && flag_unsafe_math_optimizations"
- "recip.s\t%0,%2"
+{
+ if (TARGET_FIX_SB1)
+ return "recip.s\t%0,%2\;mov.s\t%0,%0";
+ else
+ return "recip.s\t%0,%2";
+}
[(set_attr "type" "fdiv")
- (set_attr "mode" "SF")])
+ (set_attr "mode" "SF")
+ (set (attr "length")
+ (if_then_else (ne (symbol_ref "TARGET_FIX_SB1") (const_int 0))
+ (const_int 8)
+ (const_int 4)))])
(define_insn "divmodsi4"
[(set (match_operand:SI 0 "register_operand" "=l")
@@ -2456,39 +2519,83 @@
;;
;; ....................
+;; This pattern works around the early SB-1 rev2 core "F1" erratum (see
+;; "divdf3" comment for details).
(define_insn "sqrtdf2"
[(set (match_operand:DF 0 "register_operand" "=f")
(sqrt:DF (match_operand:DF 1 "register_operand" "f")))]
"TARGET_HARD_FLOAT && HAVE_SQRT_P() && TARGET_DOUBLE_FLOAT"
- "sqrt.d\t%0,%1"
+{
+ if (TARGET_FIX_SB1)
+ return "sqrt.d\t%0,%1\;mov.d\t%0,%0";
+ else
+ return "sqrt.d\t%0,%1";
+}
[(set_attr "type" "fsqrt")
- (set_attr "mode" "DF")])
+ (set_attr "mode" "DF")
+ (set (attr "length")
+ (if_then_else (ne (symbol_ref "TARGET_FIX_SB1") (const_int 0))
+ (const_int 8)
+ (const_int 4)))])
+;; This pattern works around the early SB-1 rev2 core "F1" erratum (see
+;; "divdf3" comment for details).
(define_insn "sqrtsf2"
[(set (match_operand:SF 0 "register_operand" "=f")
(sqrt:SF (match_operand:SF 1 "register_operand" "f")))]
"TARGET_HARD_FLOAT && HAVE_SQRT_P()"
- "sqrt.s\t%0,%1"
+{
+ if (TARGET_FIX_SB1)
+ return "sqrt.s\t%0,%1\;mov.s\t%0,%0";
+ else
+ return "sqrt.s\t%0,%1";
+}
[(set_attr "type" "fsqrt")
- (set_attr "mode" "SF")])
+ (set_attr "mode" "SF")
+ (set (attr "length")
+ (if_then_else (ne (symbol_ref "TARGET_FIX_SB1") (const_int 0))
+ (const_int 8)
+ (const_int 4)))])
+;; This pattern works around the early SB-1 rev2 core "F1" erratum (see
+;; "divdf3" comment for details).
(define_insn ""
[(set (match_operand:DF 0 "register_operand" "=f")
(div:DF (match_operand:DF 1 "const_float_1_operand" "")
(sqrt:DF (match_operand:DF 2 "register_operand" "f"))))]
"ISA_HAS_FP4 && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && flag_unsafe_math_optimizations"
- "rsqrt.d\t%0,%2"
+{
+ if (TARGET_FIX_SB1)
+ return "rsqrt.d\t%0,%2\;mov.d\t%0,%0";
+ else
+ return "rsqrt.d\t%0,%2";
+}
[(set_attr "type" "frsqrt")
- (set_attr "mode" "DF")])
+ (set_attr "mode" "DF")
+ (set (attr "length")
+ (if_then_else (ne (symbol_ref "TARGET_FIX_SB1") (const_int 0))
+ (const_int 8)
+ (const_int 4)))])
+;; This pattern works around the early SB-1 rev2 core "F1" erratum (see
+;; "divdf3" comment for details).
(define_insn ""
[(set (match_operand:SF 0 "register_operand" "=f")
(div:SF (match_operand:SF 1 "const_float_1_operand" "")
(sqrt:SF (match_operand:SF 2 "register_operand" "f"))))]
"ISA_HAS_FP4 && TARGET_HARD_FLOAT && flag_unsafe_math_optimizations"
- "rsqrt.s\t%0,%2"
+{
+ if (TARGET_FIX_SB1)
+ return "rsqrt.s\t%0,%2\;mov.s\t%0,%0";
+ else
+ return "rsqrt.s\t%0,%2";
+}
[(set_attr "type" "frsqrt")
- (set_attr "mode" "SF")])
+ (set_attr "mode" "SF")
+ (set (attr "length")
+ (if_then_else (ne (symbol_ref "TARGET_FIX_SB1") (const_int 0))
+ (const_int 8)
+ (const_int 4)))])
;;
;; ....................