+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.
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);
'#' 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).
putc ('l', file);
break;
+ case '~':
+ if (mips_branch_likely)
+ fputs ("\n\tnop", file);
+ break;
+
case '.':
fputs (reg_names[GP_REG_FIRST + 0], file);
break;
{
const char *p;
- for (p = "()[]<>*#/?.@^+$|-"; *p; p++)
+ for (p = "()[]<>*#/?~.@^+$|-"; *p; p++)
mips_print_operand_punct[(unsigned char) *p] = true;
}
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.
&& 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;
"\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"
"\tand\t%@,%0,%3\n" \
OPS \
"\tsc\t%@,%1\n" \
- "\tbeq\t%@,%.,1b\n" \
+ "\tbeq%?\t%@,%.,1b\n" \
"\tnop\n" \
"\tsync%-%]%>%)\n" \
"2:\n"
"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%-%]%>%)"
"\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%-%]%>%)"
"\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%-%]%>%)"
"\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%-%]%>%)"
"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%-%]%>%)"
"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%-%]%>%)"
"\tnor\t%@,%@,%.\n" \
"\t" INSN "\t%@,%@,%1\n" \
"\tsc" SUFFIX "\t%@,%0\n" \
- "\tbeq\t%@,%.,1b\n" \
+ "\tbeq%?\t%@,%.,1b\n" \
"\tnop\n" \
"\tsync%-%]%>%)"
"\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%-%]%>%)"
"\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%-%]%>%)"
"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%-%]%>%)"
"\tand\t%@,%0,%3\n" \
OPS \
"\tsc\t%@,%1\n" \
- "\tbeq\t%@,%.,1b\n" \
+ "\tbeq%?\t%@,%.,1b\n" \
"\tnop\n" \
"\tsync%-%]%>%)"
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
"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")])
"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")])
-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
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
+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
--- /dev/null
+/* { 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);
+}
--- /dev/null
+/* { 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);
+}
--- /dev/null
+/* { 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);
+}
--- /dev/null
+/* { 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);
+}
--- /dev/null
+/* { 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);
+}
--- /dev/null
+/* { 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);
+}
--- /dev/null
+/* { 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;
+}
--- /dev/null
+/* { 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);
+}
--- /dev/null
+/* { 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);
+}
--- /dev/null
+/* { 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);
+}
--- /dev/null
+/* { 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);
+}
--- /dev/null
+/* { 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);
+}
--- /dev/null
+/* { 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);
+}
--- /dev/null
+/* { 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);
+}
--- /dev/null
+/* { 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);
+}