]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
2003-08-22 Chris Demetriou <cgd@broadcom.com>
authorcgd <cgd@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 22 Aug 2003 22:36:42 +0000 (22:36 +0000)
committercgd <cgd@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 22 Aug 2003 22:36:42 +0000 (22:36 +0000)
        * 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

gcc/ChangeLog
gcc/config/mips/mips.h
gcc/config/mips/mips.md
gcc/doc/invoke.texi

index f97afe2b005c8ea5442a66cb217eb4109478b63f..85e8b8778e0635bd04bfe451bf67fea0c38126ec 100644 (file)
@@ -1,3 +1,12 @@
+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.
+
 2003-08-22  Roger Sayle  <roger@eyesopen.com>
 
        * hashtable.c (ht_expand): Avoid calculating rehash for the common
index 27a4a03eeb4707fffaba32d5f4ae03b11923e41f..38aa951048735e4cb6fabedeede5ad4616de19e6 100644 (file)
@@ -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,                   \
index 832140e409e35809370f6d796e5cc2892eee69f6..e843d53734ceafde209d79c78cd3e2f9f69e9588 100644 (file)
 ;;  ....................
 ;;
 
+;; 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")
 ;;
 ;;  ....................
 
+;; 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)))])
 \f
 ;;
 ;;  ....................
index 029c469659dc0a085b1e5547380c9800ee4b258e..d68eb0efaf8f8c9304af14f52b4c0e36a2312227 100644 (file)
@@ -479,7 +479,8 @@ in the following sections.
 -m4650  -msingle-float  -mmad @gol
 -EL  -EB  -G @var{num}  -nocpp @gol
 -mabi=32  -mabi=n32  -mabi=64  -mabi=eabi  -mabi-fake-default @gol
--mfix7000  -mno-crt0 -mflush-func=@var{func} -mno-flush-func @gol
+-mfix7000  -mfix-sb1  -mno-fix-sb1 @gol
+-mno-crt0 -mflush-func=@var{func} -mno-flush-func @gol
 -mbranch-likely -mno-branch-likely}
 
 @emph{i386 and x86-64 Options}
@@ -8168,6 +8169,13 @@ Pass an option to gas which will cause nops to be inserted if
 the read of the destination register of an mfhi or mflo instruction
 occurs in the following two instructions.
 
+@item -mfix-sb1
+@itemx -mno-fix-sb1
+@opindex mfix-sb1
+Work around certain SB-1 CPU core errata.
+(This flag currently works around the SB-1 revision 2
+``F1'' and ``F2'' floating point errata.)
+
 @item -no-crt0
 @opindex no-crt0
 Do not include the default crt0.