OSDN Git Service

gcc/
authorrsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 15 Nov 2008 14:26:07 +0000 (14:26 +0000)
committerrsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 15 Nov 2008 14:26:07 +0000 (14:26 +0000)
2008-11-15  Joshua Kinard  <kumba@gentoo.org>

* doc/invoke.texi (-mfix-r10000): Document.
* config/mips/mips.opt (mfix-r10000): New option.
* config/mips/mips-protos.h (mips_output_sync_loop): Declare.
* config/mips/mips.h (MIPS_COMPARE_AND_SWAP): Use %?.
(MIPS_COMPARE_AND_SWAP_12): Likewise.
(MIPS_SYNC_OP): Likewise.
(MIPS_SYNC_OP_12): Likewise.
(MIPS_SYNC_OLD_OP_12): Likewise.
(MIPS_SYNC_NEW_OP_12): Likewise.
(MIPS_SYNC_OLD_OP): Likewise.
(MIPS_SYNC_NAND): Likewise.
(MIPS_SYNC_OLD_NAND): Likewise.
(MIPS_SYNC_EXCHANGE): Likewise.
(MIPS_SYNC_EXCHANGE_12): Likewise.
(MIPS_SYNC_NEW_OP): Likewise, using %~ to fill branch-likely
delay slots.
(MIPS_SYNC_NEW_NAND): Likewise.
* config/mips/mips.c (mips_print_operand_punctuation): Handle '~'.
(mips_init_print_operand_punct): Treat '~' as a punctuation character.
(mips_output_sync_loop): New function.
(mips_override_options): Make -march=r10000 imply -mfix-r10000.
Make -mfix-r10000 require branch-likely instructions.
* config/mips/sync.md (sync_compare_and_swap<mode>): Use
mips_output_sync_loop.
(compare_and_swap_12): Likewise.
(sync_add<mode>): Likewise.
(sync_<optab>_12): Likewise.
(sync_old_<optab>_12): Likewise.
(sync_new_<optab>_12): Likewise.
(sync_nand_12): Likewise.
(sync_old_nand_12): Likewise.
(sync_new_nand_12): Likewise.
(sync_sub<mode>): Likewise.
(sync_old_add<mode>): Likewise.
(sync_old_sub<mode>): Likewise.
(sync_new_add<mode>): Likewise.
(sync_new_sub<mode>): Likewise.
(sync_<optab><mode>): Likewise.
(sync_old_<optab><mode>): Likewise.
(sync_new_<optab><mode>): Likewise.
(sync_nand<mode>): Likewise.
(sync_old_nand<mode>): Likewise.
(sync_new_nand<mode>): Likewise.
(sync_lock_test_and_set<mode>): Likewise.
(test_and_set_12): Likewise.

gcc/testsuite/
2008-11-15  Joshua Kinard  <kumba@gentoo.org>
    Richard Sandiford  <rdsandiford@goolemail.com>

* gcc.target/mips/fix-r10000-1.c: New test.
* gcc.target/mips/fix-r10000-2.c: Likewise.
* gcc.target/mips/fix-r10000-3.c: Likewise.
* gcc.target/mips/fix-r10000-4.c: Likewise.
* gcc.target/mips/fix-r10000-5.c: Likewise.
* gcc.target/mips/fix-r10000-6.c: Likewise.
* gcc.target/mips/fix-r10000-7.c: Likewise.
* gcc.target/mips/fix-r10000-8.c: Likewise.
* gcc.target/mips/fix-r10000-9.c: Likewise.
* gcc.target/mips/fix-r10000-10.c: Likewise.
* gcc.target/mips/fix-r10000-11.c: Likewise.
* gcc.target/mips/fix-r10000-12.c: Likewise.
* gcc.target/mips/fix-r10000-13.c: Likewise.
* gcc.target/mips/fix-r10000-14.c: Likewise.
* gcc.target/mips/fix-r10000-15.c: Likewise.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@141886 138bc75d-0d04-0410-961f-82ee72b054a4

23 files changed:
gcc/ChangeLog
gcc/config/mips/mips-protos.h
gcc/config/mips/mips.c
gcc/config/mips/mips.h
gcc/config/mips/mips.opt
gcc/config/mips/sync.md
gcc/doc/invoke.texi
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/mips/fix-r10000-1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/mips/fix-r10000-10.c [new file with mode: 0644]
gcc/testsuite/gcc.target/mips/fix-r10000-11.c [new file with mode: 0644]
gcc/testsuite/gcc.target/mips/fix-r10000-12.c [new file with mode: 0644]
gcc/testsuite/gcc.target/mips/fix-r10000-13.c [new file with mode: 0644]
gcc/testsuite/gcc.target/mips/fix-r10000-14.c [new file with mode: 0644]
gcc/testsuite/gcc.target/mips/fix-r10000-15.c [new file with mode: 0644]
gcc/testsuite/gcc.target/mips/fix-r10000-2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/mips/fix-r10000-3.c [new file with mode: 0644]
gcc/testsuite/gcc.target/mips/fix-r10000-4.c [new file with mode: 0644]
gcc/testsuite/gcc.target/mips/fix-r10000-5.c [new file with mode: 0644]
gcc/testsuite/gcc.target/mips/fix-r10000-6.c [new file with mode: 0644]
gcc/testsuite/gcc.target/mips/fix-r10000-7.c [new file with mode: 0644]
gcc/testsuite/gcc.target/mips/fix-r10000-8.c [new file with mode: 0644]
gcc/testsuite/gcc.target/mips/fix-r10000-9.c [new file with mode: 0644]

index 3c9d65c..a4e4609 100644 (file)
@@ -1,3 +1,51 @@
+2008-11-15  Joshua Kinard  <kumba@gentoo.org>
+
+       * doc/invoke.texi (-mfix-r10000): Document.
+       * config/mips/mips.opt (mfix-r10000): New option.
+       * config/mips/mips-protos.h (mips_output_sync_loop): Declare.
+       * config/mips/mips.h (MIPS_COMPARE_AND_SWAP): Use %?.
+       (MIPS_COMPARE_AND_SWAP_12): Likewise.
+       (MIPS_SYNC_OP): Likewise.
+       (MIPS_SYNC_OP_12): Likewise.
+       (MIPS_SYNC_OLD_OP_12): Likewise.
+       (MIPS_SYNC_NEW_OP_12): Likewise.
+       (MIPS_SYNC_OLD_OP): Likewise.
+       (MIPS_SYNC_NAND): Likewise.
+       (MIPS_SYNC_OLD_NAND): Likewise.
+       (MIPS_SYNC_EXCHANGE): Likewise.
+       (MIPS_SYNC_EXCHANGE_12): Likewise.
+       (MIPS_SYNC_NEW_OP): Likewise, using %~ to fill branch-likely
+       delay slots.
+       (MIPS_SYNC_NEW_NAND): Likewise.
+       * config/mips/mips.c (mips_print_operand_punctuation): Handle '~'.
+       (mips_init_print_operand_punct): Treat '~' as a punctuation character.
+       (mips_output_sync_loop): New function.
+       (mips_override_options): Make -march=r10000 imply -mfix-r10000.
+       Make -mfix-r10000 require branch-likely instructions.
+       * config/mips/sync.md (sync_compare_and_swap<mode>): Use
+       mips_output_sync_loop.
+       (compare_and_swap_12): Likewise.
+       (sync_add<mode>): Likewise.
+       (sync_<optab>_12): Likewise.
+       (sync_old_<optab>_12): Likewise.
+       (sync_new_<optab>_12): Likewise.
+       (sync_nand_12): Likewise.
+       (sync_old_nand_12): Likewise.
+       (sync_new_nand_12): Likewise.
+       (sync_sub<mode>): Likewise.
+       (sync_old_add<mode>): Likewise.
+       (sync_old_sub<mode>): Likewise.
+       (sync_new_add<mode>): Likewise.
+       (sync_new_sub<mode>): Likewise.
+       (sync_<optab><mode>): Likewise.
+       (sync_old_<optab><mode>): Likewise.
+       (sync_new_<optab><mode>): Likewise.
+       (sync_nand<mode>): Likewise.
+       (sync_old_nand<mode>): Likewise.
+       (sync_new_nand<mode>): Likewise.
+       (sync_lock_test_and_set<mode>): Likewise.
+       (test_and_set_12): Likewise.
+
 2008-11-15  Eric Botcazou  <ebotcazou@adacore.com>
 
        * gcc.c (cc1_options): Fix comment.
index 9403945..3fa67c9 100644 (file)
@@ -300,6 +300,7 @@ extern const char *mips_output_load_label (void);
 extern const char *mips_output_conditional_branch (rtx, rtx *, const char *,
                                                   const char *);
 extern const char *mips_output_order_conditional_branch (rtx, rtx *, bool);
+extern const char *mips_output_sync_loop (const char *);
 extern const char *mips_output_division (const char *, rtx *);
 extern unsigned int mips_hard_regno_nregs (int, enum machine_mode);
 extern bool mips_linked_madd_p (rtx, rtx);
index fa78c8b..5198fd3 100644 (file)
@@ -6909,6 +6909,7 @@ mips_print_operand_reloc (FILE *file, rtx op, enum mips_symbol_context context,
    '#' Print a nop if in a ".set noreorder" block.
    '/' Like '#', but do nothing within a delayed-branch sequence.
    '?' Print "l" if mips_branch_likely is true
+   '~' Print a nop if mips_branch_likely is true
    '.' Print the name of the register with a hard-wired zero (zero or $0).
    '@' Print the name of the assembler temporary register (at or $1).
    '^' Print the name of the pic call-through register (t9 or $25).
@@ -6983,6 +6984,11 @@ mips_print_operand_punctuation (FILE *file, int ch)
        putc ('l', file);
       break;
 
+    case '~':
+      if (mips_branch_likely)
+       fputs ("\n\tnop", file);
+      break;
+
     case '.':
       fputs (reg_names[GP_REG_FIRST + 0], file);
       break;
@@ -7026,7 +7032,7 @@ mips_init_print_operand_punct (void)
 {
   const char *p;
 
-  for (p = "()[]<>*#/?.@^+$|-"; *p; p++)
+  for (p = "()[]<>*#/?~.@^+$|-"; *p; p++)
     mips_print_operand_punct[(unsigned char) *p] = true;
 }
 
@@ -10250,6 +10256,17 @@ mips_output_order_conditional_branch (rtx insn, rtx *operands, bool inverted_p)
   return mips_output_conditional_branch (insn, operands, branch[1], branch[0]);
 }
 \f
+/* Return the assembly code for __sync_*() loop LOOP.  The loop should support
+   both normal and likely branches, using %? and %~ where appropriate.  */
+
+const char *
+mips_output_sync_loop (const char *loop)
+{
+  /* Use branch-likely instructions to work around the LL/SC R10000 errata.  */
+  mips_branch_likely = TARGET_FIX_R10000;
+  return loop;
+}
+\f
 /* Return the assembly code for DIV or DDIV instruction DIVISION, which has
    the operands given by OPERANDS.  Add in a divide-by-zero check if needed.
 
@@ -13971,6 +13988,24 @@ mips_override_options (void)
       && mips_matching_cpu_name_p (mips_arch_info->name, "r4400"))
     target_flags |= MASK_FIX_R4400;
 
+  /* Default to working around R10000 errata only if the processor
+     was selected explicitly.  */
+  if ((target_flags_explicit & MASK_FIX_R10000) == 0
+      && mips_matching_cpu_name_p (mips_arch_info->name, "r10000"))
+    target_flags |= MASK_FIX_R10000;
+
+  /* Make sure that branch-likely instructions available when using
+     -mfix-r10000.  The instructions are not available if either:
+
+       1. -mno-branch-likely was passed.
+       2. The selected ISA does not support branch-likely and
+          the command line does not include -mbranch-likely.  */
+  if (TARGET_FIX_R10000
+      && ((target_flags_explicit & MASK_BRANCHLIKELY) == 0
+          ? !ISA_HAS_BRANCHLIKELY
+          : !TARGET_BRANCHLIKELY))
+    sorry ("%qs requires branch-likely instructions", "-mfix-r10000");
+
   /* Save base state of options.  */
   mips_base_target_flags = target_flags;
   mips_base_delayed_branch = flag_delayed_branch;
index 354c4c5..8ae2b20 100644 (file)
@@ -3090,7 +3090,7 @@ while (0)
   "\tbne\t%0,%z2,2f\n"                         \
   "\t" OP "\t%@,%3\n"                          \
   "\tsc" SUFFIX "\t%@,%1\n"                    \
-  "\tbeq\t%@,%.,1b\n"                          \
+  "\tbeq%?\t%@,%.,1b\n"                                \
   "\tnop\n"                                    \
   "\tsync%-%]%>%)\n"                           \
   "2:\n"
@@ -3115,7 +3115,7 @@ while (0)
   "\tand\t%@,%0,%3\n"                          \
   OPS                                          \
   "\tsc\t%@,%1\n"                              \
-  "\tbeq\t%@,%.,1b\n"                          \
+  "\tbeq%?\t%@,%.,1b\n"                                \
   "\tnop\n"                                    \
   "\tsync%-%]%>%)\n"                           \
   "2:\n"
@@ -3135,7 +3135,7 @@ while (0)
   "1:\tll" SUFFIX "\t%@,%0\n"                  \
   "\t" INSN "\t%@,%@,%1\n"                     \
   "\tsc" SUFFIX "\t%@,%0\n"                    \
-  "\tbeq\t%@,%.,1b\n"                          \
+  "\tbeq%?\t%@,%.,1b\n"                                \
   "\tnop\n"                                    \
   "\tsync%-%]%>%)"
 
@@ -3160,7 +3160,7 @@ while (0)
   "\tand\t%4,%4,%1\n"                          \
   "\tor\t%@,%@,%4\n"                           \
   "\tsc\t%@,%0\n"                              \
-  "\tbeq\t%@,%.,1b\n"                          \
+  "\tbeq%?\t%@,%.,1b\n"                                \
   "\tnop\n"                                    \
   "\tsync%-%]%>%)"
 
@@ -3193,7 +3193,7 @@ while (0)
   "\tand\t%5,%5,%2\n"                          \
   "\tor\t%@,%@,%5\n"                           \
   "\tsc\t%@,%1\n"                              \
-  "\tbeq\t%@,%.,1b\n"                          \
+  "\tbeq%?\t%@,%.,1b\n"                                \
   "\tnop\n"                                    \
   "\tsync%-%]%>%)"
 
@@ -3223,7 +3223,7 @@ while (0)
   "\tand\t%0,%0,%2\n"                          \
   "\tor\t%@,%@,%0\n"                           \
   "\tsc\t%@,%1\n"                              \
-  "\tbeq\t%@,%.,1b\n"                          \
+  "\tbeq%?\t%@,%.,1b\n"                                \
   "\tnop\n"                                    \
   "\tsync%-%]%>%)"
 
@@ -3243,7 +3243,7 @@ while (0)
   "1:\tll" SUFFIX "\t%0,%1\n"                  \
   "\t" INSN "\t%@,%0,%2\n"                     \
   "\tsc" SUFFIX "\t%@,%1\n"                    \
-  "\tbeq\t%@,%.,1b\n"                          \
+  "\tbeq%?\t%@,%.,1b\n"                                \
   "\tnop\n"                                    \
   "\tsync%-%]%>%)"
 
@@ -3260,7 +3260,7 @@ while (0)
   "1:\tll" SUFFIX "\t%0,%1\n"                  \
   "\t" INSN "\t%@,%0,%2\n"                     \
   "\tsc" SUFFIX "\t%@,%1\n"                    \
-  "\tbeq\t%@,%.,1b\n"                          \
+  "\tbeq%?\t%@,%.,1b%~\n"                      \
   "\t" INSN "\t%0,%0,%2\n"                     \
   "\tsync%-%]%>%)"
 
@@ -3277,7 +3277,7 @@ while (0)
   "\tnor\t%@,%@,%.\n"                          \
   "\t" INSN "\t%@,%@,%1\n"                     \
   "\tsc" SUFFIX "\t%@,%0\n"                    \
-  "\tbeq\t%@,%.,1b\n"                          \
+  "\tbeq%?\t%@,%.,1b\n"                                \
   "\tnop\n"                                    \
   "\tsync%-%]%>%)"
 
@@ -3296,7 +3296,7 @@ while (0)
   "\tnor\t%@,%0,%.\n"                          \
   "\t" INSN "\t%@,%@,%2\n"                     \
   "\tsc" SUFFIX "\t%@,%1\n"                    \
-  "\tbeq\t%@,%.,1b\n"                          \
+  "\tbeq%?\t%@,%.,1b\n"                                \
   "\tnop\n"                                    \
   "\tsync%-%]%>%)"
 
@@ -3315,7 +3315,7 @@ while (0)
   "\tnor\t%0,%0,%.\n"                          \
   "\t" INSN "\t%@,%0,%2\n"                     \
   "\tsc" SUFFIX "\t%@,%1\n"                    \
-  "\tbeq\t%@,%.,1b\n"                          \
+  "\tbeq%?\t%@,%.,1b%~\n"                      \
   "\t" INSN "\t%0,%0,%2\n"                     \
   "\tsync%-%]%>%)"
 
@@ -3333,7 +3333,7 @@ while (0)
   "1:\tll" SUFFIX "\t%0,%1\n"                  \
   "\t" OP "\t%@,%2\n"                          \
   "\tsc" SUFFIX "\t%@,%1\n"                    \
-  "\tbeq\t%@,%.,1b\n"                          \
+  "\tbeq%?\t%@,%.,1b\n"                                \
   "\tnop\n"                                    \
   "\tsync%-%]%>%)"
 
@@ -3357,7 +3357,7 @@ while (0)
   "\tand\t%@,%0,%3\n"                          \
   OPS                                          \
   "\tsc\t%@,%1\n"                              \
-  "\tbeq\t%@,%.,1b\n"                          \
+  "\tbeq%?\t%@,%.,1b\n"                                \
   "\tnop\n"                                    \
   "\tsync%-%]%>%)"
 
index f192f0b..c7e78ff 100644 (file)
@@ -112,6 +112,10 @@ mfix-r4400
 Target Report Mask(FIX_R4400)
 Work around certain R4400 errata
 
+mfix-r10000
+Target Report Mask(FIX_R10000)
+Work around certain R10000 errata
+
 mfix-sb1
 Target Report Var(TARGET_FIX_SB1)
 Work around errata for early SB-1 revision 2 cores
index 0052f46..286ca36 100644 (file)
@@ -43,9 +43,9 @@
   "GENERATE_LL_SC"
 {
   if (which_alternative == 0)
-    return MIPS_COMPARE_AND_SWAP ("<d>", "li");
+    return mips_output_sync_loop (MIPS_COMPARE_AND_SWAP ("<d>", "li"));
   else
-    return MIPS_COMPARE_AND_SWAP ("<d>", "move");
+    return mips_output_sync_loop (MIPS_COMPARE_AND_SWAP ("<d>", "move"));
 }
   [(set_attr "length" "32")])
 
   "GENERATE_LL_SC"
 {
   if (which_alternative == 0)
-    return MIPS_COMPARE_AND_SWAP_12 (MIPS_COMPARE_AND_SWAP_12_NONZERO_OP);
+    return (mips_output_sync_loop
+           (MIPS_COMPARE_AND_SWAP_12 (MIPS_COMPARE_AND_SWAP_12_NONZERO_OP)));
   else
-    return MIPS_COMPARE_AND_SWAP_12 (MIPS_COMPARE_AND_SWAP_12_ZERO_OP);
+    return (mips_output_sync_loop
+           (MIPS_COMPARE_AND_SWAP_12 (MIPS_COMPARE_AND_SWAP_12_ZERO_OP)));
 }
   [(set_attr "length" "40,36")])
 
@@ -91,9 +93,9 @@
   "GENERATE_LL_SC"
 {
   if (which_alternative == 0)
-    return MIPS_SYNC_OP ("<d>", "<d>addiu");   
+    return mips_output_sync_loop (MIPS_SYNC_OP ("<d>", "<d>addiu"));
   else
-    return MIPS_SYNC_OP ("<d>", "<d>addu");    
+    return mips_output_sync_loop (MIPS_SYNC_OP ("<d>", "<d>addu"));
 }
   [(set_attr "length" "28")])
 
    (clobber (match_scratch:SI 4 "=&d"))]
   "GENERATE_LL_SC"
 {
-    return MIPS_SYNC_OP_12 ("<insn>", MIPS_SYNC_OP_12_NOT_NOP);        
+    return (mips_output_sync_loop
+           (MIPS_SYNC_OP_12 ("<insn>", MIPS_SYNC_OP_12_NOT_NOP)));
 }
   [(set_attr "length" "40")])
 
    (clobber (match_scratch:SI 5 "=&d"))]
   "GENERATE_LL_SC"
 {
-    return MIPS_SYNC_OLD_OP_12 ("<insn>", MIPS_SYNC_OLD_OP_12_NOT_NOP,
-                               MIPS_SYNC_OLD_OP_12_NOT_NOP_REG);       
+    return (mips_output_sync_loop
+           (MIPS_SYNC_OLD_OP_12 ("<insn>", MIPS_SYNC_OLD_OP_12_NOT_NOP,
+                                 MIPS_SYNC_OLD_OP_12_NOT_NOP_REG)));
 }
   [(set_attr "length" "40")])
 
           (match_dup 4)] UNSPEC_SYNC_NEW_OP_12))]
   "GENERATE_LL_SC"
 {
-    return MIPS_SYNC_NEW_OP_12 ("<insn>", MIPS_SYNC_NEW_OP_12_NOT_NOP);
+    return (mips_output_sync_loop
+           (MIPS_SYNC_NEW_OP_12 ("<insn>", MIPS_SYNC_NEW_OP_12_NOT_NOP)));
 }
   [(set_attr "length" "40")])
 
    (clobber (match_scratch:SI 4 "=&d"))]
   "GENERATE_LL_SC"
 {
-    return MIPS_SYNC_OP_12 ("and", MIPS_SYNC_OP_12_NOT_NOT);   
+    return (mips_output_sync_loop
+           (MIPS_SYNC_OP_12 ("and", MIPS_SYNC_OP_12_NOT_NOT)));
 }
   [(set_attr "length" "44")])
 
    (clobber (match_scratch:SI 5 "=&d"))]
   "GENERATE_LL_SC"
 {
-    return MIPS_SYNC_OLD_OP_12 ("and", MIPS_SYNC_OLD_OP_12_NOT_NOT,
-                               MIPS_SYNC_OLD_OP_12_NOT_NOT_REG);       
+    return (mips_output_sync_loop
+           (MIPS_SYNC_OLD_OP_12 ("and", MIPS_SYNC_OLD_OP_12_NOT_NOT,
+                                 MIPS_SYNC_OLD_OP_12_NOT_NOT_REG)));
 }
   [(set_attr "length" "44")])
 
           (match_dup 4)] UNSPEC_SYNC_NEW_OP_12))]
   "GENERATE_LL_SC"
 {
-    return MIPS_SYNC_NEW_OP_12 ("and", MIPS_SYNC_NEW_OP_12_NOT_NOT);
+    return (mips_output_sync_loop
+           (MIPS_SYNC_NEW_OP_12 ("and", MIPS_SYNC_NEW_OP_12_NOT_NOT)));
 }
   [(set_attr "length" "40")])
 
         UNSPEC_SYNC_OLD_OP))]
   "GENERATE_LL_SC"
 {
-  return MIPS_SYNC_OP ("<d>", "<d>subu");      
+  return mips_output_sync_loop (MIPS_SYNC_OP ("<d>", "<d>subu"));
 }
   [(set_attr "length" "28")])
 
   "GENERATE_LL_SC"
 {
   if (which_alternative == 0)
-    return MIPS_SYNC_OLD_OP ("<d>", "<d>addiu");       
+    return mips_output_sync_loop (MIPS_SYNC_OLD_OP ("<d>", "<d>addiu"));
   else
-    return MIPS_SYNC_OLD_OP ("<d>", "<d>addu");        
+    return mips_output_sync_loop (MIPS_SYNC_OLD_OP ("<d>", "<d>addu"));
 }
   [(set_attr "length" "28")])
 
         UNSPEC_SYNC_OLD_OP))]
   "GENERATE_LL_SC"
 {
-  return MIPS_SYNC_OLD_OP ("<d>", "<d>subu");  
+  return mips_output_sync_loop (MIPS_SYNC_OLD_OP ("<d>", "<d>subu"));
 }
   [(set_attr "length" "28")])
 
   "GENERATE_LL_SC"
 {
   if (which_alternative == 0)
-    return MIPS_SYNC_NEW_OP ("<d>", "<d>addiu");       
+    return mips_output_sync_loop (MIPS_SYNC_NEW_OP ("<d>", "<d>addiu"));
   else
-    return MIPS_SYNC_NEW_OP ("<d>", "<d>addu");        
+    return mips_output_sync_loop (MIPS_SYNC_NEW_OP ("<d>", "<d>addu"));
 }
   [(set_attr "length" "28")])
 
         UNSPEC_SYNC_NEW_OP))]
   "GENERATE_LL_SC"
 {
-  return MIPS_SYNC_NEW_OP ("<d>", "<d>subu");  
+  return mips_output_sync_loop (MIPS_SYNC_NEW_OP ("<d>", "<d>subu"));
 }
   [(set_attr "length" "28")])
 
   "GENERATE_LL_SC"
 {
   if (which_alternative == 0)
-    return MIPS_SYNC_OP ("<d>", "<immediate_insn>");   
+    return mips_output_sync_loop (MIPS_SYNC_OP ("<d>", "<immediate_insn>"));
   else
-    return MIPS_SYNC_OP ("<d>", "<insn>");     
+    return mips_output_sync_loop (MIPS_SYNC_OP ("<d>", "<insn>"));
 }
   [(set_attr "length" "28")])
 
   "GENERATE_LL_SC"
 {
   if (which_alternative == 0)
-    return MIPS_SYNC_OLD_OP ("<d>", "<immediate_insn>");       
+    return (mips_output_sync_loop
+           (MIPS_SYNC_OLD_OP ("<d>", "<immediate_insn>")));
   else
-    return MIPS_SYNC_OLD_OP ("<d>", "<insn>"); 
+    return mips_output_sync_loop (MIPS_SYNC_OLD_OP ("<d>", "<insn>"));
 }
   [(set_attr "length" "28")])
 
   "GENERATE_LL_SC"
 {
   if (which_alternative == 0)
-    return MIPS_SYNC_NEW_OP ("<d>", "<immediate_insn>");       
+    return (mips_output_sync_loop
+           (MIPS_SYNC_NEW_OP ("<d>", "<immediate_insn>")));
   else
-    return MIPS_SYNC_NEW_OP ("<d>", "<insn>"); 
+    return mips_output_sync_loop (MIPS_SYNC_NEW_OP ("<d>", "<insn>"));
 }
   [(set_attr "length" "28")])
 
   "GENERATE_LL_SC"
 {
   if (which_alternative == 0)
-    return MIPS_SYNC_NAND ("<d>", "andi");     
+    return mips_output_sync_loop (MIPS_SYNC_NAND ("<d>", "andi"));
   else
-    return MIPS_SYNC_NAND ("<d>", "and");      
+    return mips_output_sync_loop (MIPS_SYNC_NAND ("<d>", "and"));
 }
   [(set_attr "length" "32")])
 
   "GENERATE_LL_SC"
 {
   if (which_alternative == 0)
-    return MIPS_SYNC_OLD_NAND ("<d>", "andi"); 
+    return mips_output_sync_loop (MIPS_SYNC_OLD_NAND ("<d>", "andi"));
   else
-    return MIPS_SYNC_OLD_NAND ("<d>", "and");  
+    return mips_output_sync_loop (MIPS_SYNC_OLD_NAND ("<d>", "and"));
 }
   [(set_attr "length" "32")])
 
   "GENERATE_LL_SC"
 {
   if (which_alternative == 0)
-    return MIPS_SYNC_NEW_NAND ("<d>", "andi"); 
+    return mips_output_sync_loop (MIPS_SYNC_NEW_NAND ("<d>", "andi"));
   else
-    return MIPS_SYNC_NEW_NAND ("<d>", "and");  
+    return mips_output_sync_loop (MIPS_SYNC_NEW_NAND ("<d>", "and"));
 }
   [(set_attr "length" "32")])
 
   "GENERATE_LL_SC"
 {
   if (which_alternative == 0)
-    return MIPS_SYNC_EXCHANGE ("<d>", "li");
+    return mips_output_sync_loop (MIPS_SYNC_EXCHANGE ("<d>", "li"));
   else
-    return MIPS_SYNC_EXCHANGE ("<d>", "move");
+    return mips_output_sync_loop (MIPS_SYNC_EXCHANGE ("<d>", "move"));
 }
   [(set_attr "length" "24")])
 
   "GENERATE_LL_SC"
 {
   if (which_alternative == 0)
-    return MIPS_SYNC_EXCHANGE_12 (MIPS_SYNC_EXCHANGE_12_NONZERO_OP);
+    return (mips_output_sync_loop
+           (MIPS_SYNC_EXCHANGE_12 (MIPS_SYNC_EXCHANGE_12_NONZERO_OP)));
   else
-    return MIPS_SYNC_EXCHANGE_12 (MIPS_SYNC_EXCHANGE_12_ZERO_OP);
+    return (mips_output_sync_loop
+           (MIPS_SYNC_EXCHANGE_12 (MIPS_SYNC_EXCHANGE_12_ZERO_OP)));
 }
   [(set_attr "length" "28,24")])
index ce62152..cc66b45 100644 (file)
@@ -668,8 +668,8 @@ Objective-C and Objective-C++ Dialects}.
 -mmemcpy  -mno-memcpy  -mlong-calls  -mno-long-calls @gol
 -mmad  -mno-mad  -mfused-madd  -mno-fused-madd  -nocpp @gol
 -mfix-r4000  -mno-fix-r4000  -mfix-r4400  -mno-fix-r4400 @gol
--mfix-vr4120  -mno-fix-vr4120  -mfix-vr4130  -mno-fix-vr4130 @gol
--mfix-sb1  -mno-fix-sb1 @gol
+-mfix-r10000 -mno-fix-r10000  -mfix-vr4120  -mno-fix-vr4120 @gol
+-mfix-vr4130  -mno-fix-vr4130  -mfix-sb1  -mno-fix-sb1 @gol
 -mflush-func=@var{func}  -mno-flush-func @gol
 -mbranch-cost=@var{num}  -mbranch-likely  -mno-branch-likely @gol
 -mfp-exceptions -mno-fp-exceptions @gol
@@ -12833,6 +12833,22 @@ A double-word or a variable shift may give an incorrect result if executed
 immediately after starting an integer division.
 @end itemize
 
+@item -mfix-r10000
+@itemx -mno-fix-r10000
+@opindex mfix-r10000
+@opindex mno-fix-r10000
+Work around certain R10000 errata:
+@itemize @minus
+@item
+@code{ll}/@code{sc} sequences may not behave atomically on revisions
+prior to 3.0.  They may deadlock on revisions 2.6 and earlier.
+@end itemize
+
+This option can only be used if the target architecture supports
+branch-likely instructions.  @option{-mfix-r10000} is the default when
+@option{-march=r10000} is used; @option{-mno-fix-r10000} is the default
+otherwise.
+
 @item -mfix-vr4120
 @itemx -mno-fix-vr4120
 @opindex mfix-vr4120
index b64bf63..1a4a0d2 100644 (file)
@@ -1,3 +1,22 @@
+2008-11-15  Joshua Kinard  <kumba@gentoo.org>
+           Richard Sandiford  <rdsandiford@goolemail.com>
+
+       * gcc.target/mips/fix-r10000-1.c: New test.
+       * gcc.target/mips/fix-r10000-2.c: Likewise.
+       * gcc.target/mips/fix-r10000-3.c: Likewise.
+       * gcc.target/mips/fix-r10000-4.c: Likewise.
+       * gcc.target/mips/fix-r10000-5.c: Likewise.
+       * gcc.target/mips/fix-r10000-6.c: Likewise.
+       * gcc.target/mips/fix-r10000-7.c: Likewise.
+       * gcc.target/mips/fix-r10000-8.c: Likewise.
+       * gcc.target/mips/fix-r10000-9.c: Likewise.
+       * gcc.target/mips/fix-r10000-10.c: Likewise.
+       * gcc.target/mips/fix-r10000-11.c: Likewise.
+       * gcc.target/mips/fix-r10000-12.c: Likewise.
+       * gcc.target/mips/fix-r10000-13.c: Likewise.
+       * gcc.target/mips/fix-r10000-14.c: Likewise.
+       * gcc.target/mips/fix-r10000-15.c: Likewise.
+
 2008-11-15  Jakub Jelinek  <jakub@redhat.com>
 
        PR c++/37561
diff --git a/gcc/testsuite/gcc.target/mips/fix-r10000-1.c b/gcc/testsuite/gcc.target/mips/fix-r10000-1.c
new file mode 100644 (file)
index 0000000..e72974b
--- /dev/null
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-mips-options "-O2 -march=mips4 -mfix-r10000" } */
+/* { dg-final { scan-assembler-times "\tbeql\t" 3 } } */
+
+NOMIPS16 int
+f1 (int *z)
+{
+  return __sync_fetch_and_add (z, 42);
+}
+
+NOMIPS16 short
+f2 (short *z)
+{
+  return __sync_fetch_and_add (z, 42);
+}
+
+NOMIPS16 char
+f3 (char *z)
+{
+  return __sync_fetch_and_add (z, 42);
+}
diff --git a/gcc/testsuite/gcc.target/mips/fix-r10000-10.c b/gcc/testsuite/gcc.target/mips/fix-r10000-10.c
new file mode 100644 (file)
index 0000000..a6dbfa3
--- /dev/null
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-mips-options "-O2 -march=mips4 -mfix-r10000" } */
+/* { dg-final { scan-assembler-times "\tbeql\t" 3 } } */
+
+NOMIPS16 int
+f1 (int *z)
+{
+  return __sync_and_and_fetch (z, 42);
+}
+
+NOMIPS16 short
+f2 (short *z)
+{
+  return __sync_and_and_fetch (z, 42);
+}
+
+NOMIPS16 char
+f3 (char *z)
+{
+  return __sync_and_and_fetch (z, 42);
+}
diff --git a/gcc/testsuite/gcc.target/mips/fix-r10000-11.c b/gcc/testsuite/gcc.target/mips/fix-r10000-11.c
new file mode 100644 (file)
index 0000000..4bf16e1
--- /dev/null
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-mips-options "-O2 -march=mips4 -mfix-r10000" } */
+/* { dg-final { scan-assembler-times "\tbeql\t" 3 } } */
+
+NOMIPS16 int
+f1 (int *z)
+{
+  return __sync_xor_and_fetch (z, 42);
+}
+
+NOMIPS16 short
+f2 (short *z)
+{
+  return __sync_xor_and_fetch (z, 42);
+}
+
+NOMIPS16 char
+f3 (char *z)
+{
+  return __sync_xor_and_fetch (z, 42);
+}
diff --git a/gcc/testsuite/gcc.target/mips/fix-r10000-12.c b/gcc/testsuite/gcc.target/mips/fix-r10000-12.c
new file mode 100644 (file)
index 0000000..0381c24
--- /dev/null
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-mips-options "-O2 -march=mips4 -mfix-r10000" } */
+/* { dg-final { scan-assembler-times "\tbeql\t" 3 } } */
+
+NOMIPS16 int
+f1 (int *z)
+{
+  return __sync_nand_and_fetch (z, 42);
+}
+
+NOMIPS16 short
+f2 (short *z)
+{
+  return __sync_nand_and_fetch (z, 42);
+}
+
+NOMIPS16 char
+f3 (char *z)
+{
+  return __sync_nand_and_fetch (z, 42);
+}
diff --git a/gcc/testsuite/gcc.target/mips/fix-r10000-13.c b/gcc/testsuite/gcc.target/mips/fix-r10000-13.c
new file mode 100644 (file)
index 0000000..7e1efc8
--- /dev/null
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-mips-options "-O2 -march=mips4 -mfix-r10000" } */
+/* { dg-final { scan-assembler-times "\tbeql\t" 3 } } */
+
+NOMIPS16 int
+f1 (int *z)
+{
+  return __sync_bool_compare_and_swap (z, 0, 42);
+}
+
+NOMIPS16 short
+f2 (short *z)
+{
+  return __sync_bool_compare_and_swap (z, 0, 42);
+}
+
+NOMIPS16 char
+f3 (char *z)
+{
+  return __sync_bool_compare_and_swap (z, 0, 42);
+}
diff --git a/gcc/testsuite/gcc.target/mips/fix-r10000-14.c b/gcc/testsuite/gcc.target/mips/fix-r10000-14.c
new file mode 100644 (file)
index 0000000..8d8fe09
--- /dev/null
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-mips-options "-O2 -march=mips4 -mfix-r10000" } */
+/* { dg-final { scan-assembler-times "\tbeql\t" 3 } } */
+
+NOMIPS16 int
+f1 (int *z)
+{
+  return __sync_val_compare_and_swap (z, 0, 42);
+}
+
+NOMIPS16 short
+f2 (short *z)
+{
+  return __sync_val_compare_and_swap (z, 0, 42);
+}
+
+NOMIPS16 char
+f3 (char *z)
+{
+  return __sync_val_compare_and_swap (z, 0, 42);
+}
diff --git a/gcc/testsuite/gcc.target/mips/fix-r10000-15.c b/gcc/testsuite/gcc.target/mips/fix-r10000-15.c
new file mode 100644 (file)
index 0000000..fd7d036
--- /dev/null
@@ -0,0 +1,33 @@
+/* { dg-do compile } */
+/* { dg-mips-options "-O2 -march=mips4 -mfix-r10000" } */
+/* { dg-final { scan-assembler-times "\tbeql\t" 3 } } */
+
+NOMIPS16 int
+f1 (int *z)
+{
+  int result;
+
+  result = __sync_lock_test_and_set (z, 42);
+  __sync_lock_release (z);
+  return result;
+}
+
+NOMIPS16 short
+f2 (short *z)
+{
+  short result;
+
+  result = __sync_lock_test_and_set (z, 42);
+  __sync_lock_release (z);
+  return result;
+}
+
+NOMIPS16 char
+f3 (char *z)
+{
+  char result;
+
+  result = __sync_lock_test_and_set (z, 42);
+  __sync_lock_release (z);
+  return result;
+}
diff --git a/gcc/testsuite/gcc.target/mips/fix-r10000-2.c b/gcc/testsuite/gcc.target/mips/fix-r10000-2.c
new file mode 100644 (file)
index 0000000..900a697
--- /dev/null
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-mips-options "-O2 -march=mips4 -mfix-r10000" } */
+/* { dg-final { scan-assembler-times "\tbeql\t" 3 } } */
+
+NOMIPS16 int
+f1 (int *z, int amt)
+{
+  return __sync_fetch_and_sub (z, amt);
+}
+
+NOMIPS16 short
+f2 (short *z, short amt)
+{
+  return __sync_fetch_and_sub (z, amt);
+}
+
+NOMIPS16 char
+f3 (char *z, char amt)
+{
+  return __sync_fetch_and_sub (z, amt);
+}
diff --git a/gcc/testsuite/gcc.target/mips/fix-r10000-3.c b/gcc/testsuite/gcc.target/mips/fix-r10000-3.c
new file mode 100644 (file)
index 0000000..de74e97
--- /dev/null
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-mips-options "-O2 -march=mips4 -mfix-r10000" } */
+/* { dg-final { scan-assembler-times "\tbeql\t" 3 } } */
+
+NOMIPS16 int
+f1 (int *z)
+{
+  return __sync_fetch_and_or (z, 42);
+}
+
+NOMIPS16 short
+f2 (short *z)
+{
+  return __sync_fetch_and_or (z, 42);
+}
+
+NOMIPS16 char
+f3 (char *z)
+{
+  return __sync_fetch_and_or (z, 42);
+}
diff --git a/gcc/testsuite/gcc.target/mips/fix-r10000-4.c b/gcc/testsuite/gcc.target/mips/fix-r10000-4.c
new file mode 100644 (file)
index 0000000..0c962ee
--- /dev/null
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-mips-options "-O2 -march=mips4 -mfix-r10000" } */
+/* { dg-final { scan-assembler-times "\tbeql\t" 3 } } */
+
+NOMIPS16 int
+f1 (int *z)
+{
+  return __sync_fetch_and_and (z, 42);
+}
+
+NOMIPS16 short
+f2 (short *z)
+{
+  return __sync_fetch_and_and (z, 42);
+}
+
+NOMIPS16 char
+f3 (char *z)
+{
+  return __sync_fetch_and_and (z, 42);
+}
diff --git a/gcc/testsuite/gcc.target/mips/fix-r10000-5.c b/gcc/testsuite/gcc.target/mips/fix-r10000-5.c
new file mode 100644 (file)
index 0000000..15a0704
--- /dev/null
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-mips-options "-O2 -march=mips4 -mfix-r10000" } */
+/* { dg-final { scan-assembler-times "\tbeql\t" 3 } } */
+
+NOMIPS16 int
+f1 (int *z)
+{
+  return __sync_fetch_and_xor (z, 42);
+}
+
+NOMIPS16 short
+f2 (short *z)
+{
+  return __sync_fetch_and_xor (z, 42);
+}
+
+NOMIPS16 char
+f3 (char *z)
+{
+  return __sync_fetch_and_xor (z, 42);
+}
diff --git a/gcc/testsuite/gcc.target/mips/fix-r10000-6.c b/gcc/testsuite/gcc.target/mips/fix-r10000-6.c
new file mode 100644 (file)
index 0000000..2751369
--- /dev/null
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-mips-options "-O2 -march=mips4 -mfix-r10000" } */
+/* { dg-final { scan-assembler-times "\tbeql\t" 3 } } */
+
+NOMIPS16 int
+f1 (int *z)
+{
+  return __sync_fetch_and_nand (z, 42);
+}
+
+NOMIPS16 short
+f2 (short *z)
+{
+  return __sync_fetch_and_nand (z, 42);
+}
+
+NOMIPS16 char
+f3 (char *z)
+{
+  return __sync_fetch_and_nand (z, 42);
+}
diff --git a/gcc/testsuite/gcc.target/mips/fix-r10000-7.c b/gcc/testsuite/gcc.target/mips/fix-r10000-7.c
new file mode 100644 (file)
index 0000000..bbe9856
--- /dev/null
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-mips-options "-O2 -march=mips4 -mfix-r10000" } */
+/* { dg-final { scan-assembler-times "\tbeql\t" 3 } } */
+
+NOMIPS16 int
+f1 (int *z)
+{
+  return __sync_add_and_fetch (z, 42);
+}
+
+NOMIPS16 short
+f2 (short *z)
+{
+  return __sync_add_and_fetch (z, 42);
+}
+
+NOMIPS16 char
+f3 (char *z)
+{
+  return __sync_add_and_fetch (z, 42);
+}
diff --git a/gcc/testsuite/gcc.target/mips/fix-r10000-8.c b/gcc/testsuite/gcc.target/mips/fix-r10000-8.c
new file mode 100644 (file)
index 0000000..6e990a6
--- /dev/null
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-mips-options "-O2 -march=mips4 -mfix-r10000" } */
+/* { dg-final { scan-assembler-times "\tbeql\t" 3 } } */
+
+NOMIPS16 int
+f1 (int *z, int amt)
+{
+  return __sync_sub_and_fetch (z, amt);
+}
+
+NOMIPS16 short
+f2 (short *z, short amt)
+{
+  return __sync_sub_and_fetch (z, amt);
+}
+
+NOMIPS16 char
+f3 (char *z, char amt)
+{
+  return __sync_sub_and_fetch (z, amt);
+}
diff --git a/gcc/testsuite/gcc.target/mips/fix-r10000-9.c b/gcc/testsuite/gcc.target/mips/fix-r10000-9.c
new file mode 100644 (file)
index 0000000..8373c42
--- /dev/null
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-mips-options "-O2 -march=mips4 -mfix-r10000" } */
+/* { dg-final { scan-assembler-times "\tbeql\t" 3 } } */
+
+NOMIPS16 int
+f1 (int *z)
+{
+  return __sync_or_and_fetch (z, 42);
+}
+
+NOMIPS16 short
+f2 (short *z)
+{
+  return __sync_or_and_fetch (z, 42);
+}
+
+NOMIPS16 char
+f3 (char *z)
+{
+  return __sync_or_and_fetch (z, 42);
+}