aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Daney <ddaney@avtrex.com>2008-05-20 23:13:13 +0000
committerDavid Daney <daney@gcc.gnu.org>2008-05-20 23:13:13 +0000
commit06d1961718e14e5f9661d8885e15a63ce65add07 (patch)
treedcc935675df1915afcb14aa2e9eb7d61b0844bdd
parenta35f6a358ea2e2638e663b038aaaf42b981008cb (diff)
downloadgcc-06d1961718e14e5f9661d8885e15a63ce65add07.zip
gcc-06d1961718e14e5f9661d8885e15a63ce65add07.tar.gz
gcc-06d1961718e14e5f9661d8885e15a63ce65add07.tar.bz2
mips.md (UNSPEC_SYNC_NEW_OP_12, [...]): New define_constants.
2008-05-20 David Daney <ddaney@avtrex.com> * config/mips/mips.md (UNSPEC_SYNC_NEW_OP_12, UNSPEC_SYNC_OLD_OP_12, UNSPEC_SYNC_EXCHANGE_12): New define_constants. (UNSPEC_SYNC_EXCHANGE, UNSPEC_MEMORY_BARRIER, UNSPEC_SET_GOT_VERSION, UNSPEC_UPDATE_GOT_VERSION): Renumber. (optab, insn): Add 'plus' and 'minus' to define_code_attr. (atomic_hiqi_op): New define_code_iterator. (sync_compare_and_swap<mode>): Call mips_expand_atomic_qihi instead of mips_expand_compare_and_swap_12. (compare_and_swap_12): Use MIPS_COMPARE_AND_SWAP_12 instead of MIPS_COMPARE_AND_SWAP_12_0. Pass argument to MIPS_COMPARE_AND_SWAP_12. (sync_<optab><mode>, sync_old_<optab><mode>, sync_new_<optab><mode>, sync_nand<mode>, sync_old_nand<mode>, sync_new_nand<mode>): New define_expands for HI and QI mode operands. (sync_<optab>_12, sync_old_<optab>_12, sync_new_<optab>_12, sync_nand_12, sync_old_nand_12, sync_new_nand_12): New insns. (sync_lock_test_and_set<mode>): New define_expand for HI and QI modes. (test_and_set_12): New insn. (sync_old_add<mode>, sync_new_add<mode>, sync_old_<optab><mode>, sync_new_<optab><mode>, sync_old_nand<mode>, sync_new_nand<mode>, sync_lock_test_and_set<mode>): Add early clobber to operand 0 for SI and DI mode insns. * config/mips/mips-protos.h (mips_gen_fn_6, mips_gen_fn_5, mips_gen_fn_4): New typedefs. (mips_gen_fn_ptrs): Define new union type. (mips_expand_compare_and_swap_12): Remove declaration. (mips_expand_atomic_qihi): Declare function. * config/mips/mips.c (mips_expand_compare_and_swap_12): Rename to... (mips_expand_atomic_qihi): ... this. Use new generator function parameter. * config/mips/mips.h (MIPS_COMPARE_AND_SWAP_12): Add OPS parameter. (MIPS_COMPARE_AND_SWAP_12_0): Delete macro. (MIPS_COMPARE_AND_SWAP_12_ZERO_OP, MIPS_COMPARE_AND_SWAP_12_NONZERO_OP, MIPS_SYNC_OP_12, MIPS_SYNC_OP_12_NOT_NOP, MIPS_SYNC_OP_12_NOT_NOT, MIPS_SYNC_OLD_OP_12, MIPS_SYNC_OLD_OP_12_NOT_NOP, MIPS_SYNC_OLD_OP_12_NOT_NOP_REG, MIPS_SYNC_OLD_OP_12_NOT_NOT, MIPS_SYNC_OLD_OP_12_NOT_NOT_REG, MIPS_SYNC_NEW_OP_12, MIPS_SYNC_NEW_OP_12_NOT_NOP, MIPS_SYNC_NEW_OP_12_NOT_NOT, MIPS_SYNC_EXCHANGE_12, MIPS_SYNC_EXCHANGE_12_ZERO_OP, MIPS_SYNC_EXCHANGE_12_NONZERO_OP): New macros. From-SVN: r135684
-rw-r--r--gcc/ChangeLog50
-rw-r--r--gcc/config/mips/mips-protos.h10
-rw-r--r--gcc/config/mips/mips.c51
-rw-r--r--gcc/config/mips/mips.h145
-rw-r--r--gcc/config/mips/mips.md297
5 files changed, 500 insertions, 53 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 41e28d4..f354031 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,53 @@
+2008-05-20 David Daney <ddaney@avtrex.com>
+
+ * config/mips/mips.md (UNSPEC_SYNC_NEW_OP_12,
+ UNSPEC_SYNC_OLD_OP_12,
+ UNSPEC_SYNC_EXCHANGE_12): New define_constants.
+ (UNSPEC_SYNC_EXCHANGE, UNSPEC_MEMORY_BARRIER,
+ UNSPEC_SET_GOT_VERSION,
+ UNSPEC_UPDATE_GOT_VERSION): Renumber.
+ (optab, insn): Add 'plus' and 'minus' to define_code_attr.
+ (atomic_hiqi_op): New define_code_iterator.
+ (sync_compare_and_swap<mode>): Call
+ mips_expand_atomic_qihi instead of
+ mips_expand_compare_and_swap_12.
+ (compare_and_swap_12): Use MIPS_COMPARE_AND_SWAP_12 instead of
+ MIPS_COMPARE_AND_SWAP_12_0. Pass argument to
+ MIPS_COMPARE_AND_SWAP_12.
+ (sync_<optab><mode>, sync_old_<optab><mode>,
+ sync_new_<optab><mode>, sync_nand<mode>, sync_old_nand<mode>,
+ sync_new_nand<mode>): New define_expands for HI and QI mode
+ operands.
+ (sync_<optab>_12, sync_old_<optab>_12, sync_new_<optab>_12,
+ sync_nand_12, sync_old_nand_12, sync_new_nand_12): New insns.
+ (sync_lock_test_and_set<mode>): New define_expand for HI and QI
+ modes.
+ (test_and_set_12): New insn.
+ (sync_old_add<mode>, sync_new_add<mode>, sync_old_<optab><mode>,
+ sync_new_<optab><mode>, sync_old_nand<mode>,
+ sync_new_nand<mode>, sync_lock_test_and_set<mode>): Add early
+ clobber to operand 0 for SI and DI mode insns.
+ * config/mips/mips-protos.h (mips_gen_fn_6, mips_gen_fn_5,
+ mips_gen_fn_4): New typedefs.
+ (mips_gen_fn_ptrs): Define new union type.
+ (mips_expand_compare_and_swap_12): Remove declaration.
+ (mips_expand_atomic_qihi): Declare function.
+ * config/mips/mips.c (mips_expand_compare_and_swap_12): Rename to...
+ (mips_expand_atomic_qihi): ... this. Use new generator function
+ parameter.
+ * config/mips/mips.h (MIPS_COMPARE_AND_SWAP_12): Add OPS parameter.
+ (MIPS_COMPARE_AND_SWAP_12_0): Delete macro.
+ (MIPS_COMPARE_AND_SWAP_12_ZERO_OP,
+ MIPS_COMPARE_AND_SWAP_12_NONZERO_OP,
+ MIPS_SYNC_OP_12, MIPS_SYNC_OP_12_NOT_NOP,
+ MIPS_SYNC_OP_12_NOT_NOT, MIPS_SYNC_OLD_OP_12,
+ MIPS_SYNC_OLD_OP_12_NOT_NOP, MIPS_SYNC_OLD_OP_12_NOT_NOP_REG,
+ MIPS_SYNC_OLD_OP_12_NOT_NOT, MIPS_SYNC_OLD_OP_12_NOT_NOT_REG,
+ MIPS_SYNC_NEW_OP_12, MIPS_SYNC_NEW_OP_12_NOT_NOP,
+ MIPS_SYNC_NEW_OP_12_NOT_NOT, MIPS_SYNC_EXCHANGE_12,
+ MIPS_SYNC_EXCHANGE_12_ZERO_OP,
+ MIPS_SYNC_EXCHANGE_12_NONZERO_OP): New macros.
+
2008-05-20 H.J. Lu <hongjiu.lu@intel.com>
* config/i386/i386.c (ix86_expand_vector_init_one_nonzero): Add
diff --git a/gcc/config/mips/mips-protos.h b/gcc/config/mips/mips-protos.h
index fbac8fc..db65aab 100644
--- a/gcc/config/mips/mips-protos.h
+++ b/gcc/config/mips/mips-protos.h
@@ -292,6 +292,14 @@ extern bool mips_use_ins_ext_p (rtx, HOST_WIDE_INT, HOST_WIDE_INT);
extern const char *mips16e_output_save_restore (rtx, HOST_WIDE_INT);
extern bool mips16e_save_restore_pattern_p (rtx, HOST_WIDE_INT,
struct mips16e_save_restore_info *);
-extern void mips_expand_compare_and_swap_12 (rtx, rtx, rtx, rtx);
+union mips_gen_fn_ptrs
+{
+ rtx (*fn_6) (rtx, rtx, rtx, rtx, rtx, rtx);
+ rtx (*fn_5) (rtx, rtx, rtx, rtx, rtx);
+ rtx (*fn_4) (rtx, rtx, rtx, rtx);
+};
+
+extern void mips_expand_atomic_qihi (union mips_gen_fn_ptrs,
+ rtx, rtx, rtx, rtx);
#endif /* ! GCC_MIPS_PROTOS_H */
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
index 2189533..6cb0d29 100644
--- a/gcc/config/mips/mips.c
+++ b/gcc/config/mips/mips.c
@@ -5873,14 +5873,29 @@ mips_expand_synci_loop (rtx begin, rtx end)
emit_jump_insn (gen_condjump (cmp_result, label));
}
-/* Expand a QI or HI mode compare_and_swap. The operands are the same
- as for the generator function. */
+/* Expand a QI or HI mode atomic memory operation.
+
+ GENERATOR contains a pointer to the gen_* function that generates
+ the SI mode underlying atomic operation using masks that we
+ calculate.
+
+ RESULT is the return register for the operation. Its value is NULL
+ if unused.
+
+ MEM is the location of the atomic access.
+
+ OLDVAL is the first operand for the operation.
+
+ NEWVAL is the optional second operand for the operation. Its value
+ is NULL if unused. */
void
-mips_expand_compare_and_swap_12 (rtx result, rtx mem, rtx oldval, rtx newval)
+mips_expand_atomic_qihi (union mips_gen_fn_ptrs generator,
+ rtx result, rtx mem, rtx oldval, rtx newval)
{
rtx orig_addr, memsi_addr, memsi, shift, shiftsi, unshifted_mask;
- rtx unshifted_mask_reg, mask, inverted_mask, res;
+ rtx unshifted_mask_reg, mask, inverted_mask, si_op;
+ rtx res = NULL;
enum machine_mode mode;
mode = GET_MODE (mem);
@@ -5927,7 +5942,7 @@ mips_expand_compare_and_swap_12 (rtx result, rtx mem, rtx oldval, rtx newval)
}
/* Do the same for the new value. */
- if (newval != const0_rtx)
+ if (newval && newval != const0_rtx)
{
newval = convert_modes (SImode, mode, newval, true);
newval = force_reg (SImode, newval);
@@ -5935,14 +5950,24 @@ mips_expand_compare_and_swap_12 (rtx result, rtx mem, rtx oldval, rtx newval)
}
/* Do the SImode atomic access. */
- res = gen_reg_rtx (SImode);
- emit_insn (gen_compare_and_swap_12 (res, memsi, mask, inverted_mask,
- oldval, newval));
-
- /* Shift and convert the result. */
- mips_emit_binary (AND, res, res, mask);
- mips_emit_binary (LSHIFTRT, res, res, shiftsi);
- mips_emit_move (result, gen_lowpart (GET_MODE (result), res));
+ if (result)
+ res = gen_reg_rtx (SImode);
+ if (newval)
+ si_op = generator.fn_6 (res, memsi, mask, inverted_mask, oldval, newval);
+ else if (result)
+ si_op = generator.fn_5 (res, memsi, mask, inverted_mask, oldval);
+ else
+ si_op = generator.fn_4 (memsi, mask, inverted_mask, oldval);
+
+ emit_insn (si_op);
+
+ if (result)
+ {
+ /* Shift and convert the result. */
+ mips_emit_binary (AND, res, res, mask);
+ mips_emit_binary (LSHIFTRT, res, res, shiftsi);
+ mips_emit_move (result, gen_lowpart (GET_MODE (result), res));
+ }
}
/* Return true if it is possible to use left/right accesses for a
diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h
index 9f59f1a..7655527 100644
--- a/gcc/config/mips/mips.h
+++ b/gcc/config/mips/mips.h
@@ -1,6 +1,6 @@
/* Definitions of target machine for GNU compiler. MIPS version.
Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998
- 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008
Free Software Foundation, Inc.
Contributed by A. Lichnewsky (lich@inria.inria.fr).
Changed by Michael Meissner (meissner@osf.org).
@@ -2908,41 +2908,32 @@ while (0)
/* Return an asm string that atomically:
- Given that %2 contains a bit mask and %3 the inverted mask and
- that %4 and %5 have already been ANDed with $2.
+ that %4 and %5 have already been ANDed with %2.
- Compares the bits in memory reference %1 selected by mask %2 to
register %4 and, if they are equal, changes the selected bits
in memory to %5.
- Sets register %0 to the old value of memory reference %1.
- */
-#define MIPS_COMPARE_AND_SWAP_12 \
- "%(%<%[%|sync\n" \
- "1:\tll\t%0,%1\n" \
- "\tand\t%@,%0,%2\n" \
- "\tbne\t%@,%z4,2f\n" \
- "\tand\t%@,%0,%3\n" \
- "\tor\t%@,%@,%5\n" \
- "\tsc\t%@,%1\n" \
- "\tbeq\t%@,%.,1b\n" \
- "\tnop\n" \
- "\tsync%-%]%>%)\n" \
- "2:\n"
-/* Like MIPS_COMPARE_AND_SWAP_12, except %5 is a constant zero,
- so the OR can be omitted. */
-#define MIPS_COMPARE_AND_SWAP_12_0 \
+ OPS are the instructions needed to OR %5 with %@. */
+#define MIPS_COMPARE_AND_SWAP_12(OPS) \
"%(%<%[%|sync\n" \
"1:\tll\t%0,%1\n" \
"\tand\t%@,%0,%2\n" \
"\tbne\t%@,%z4,2f\n" \
"\tand\t%@,%0,%3\n" \
+ OPS \
"\tsc\t%@,%1\n" \
"\tbeq\t%@,%.,1b\n" \
"\tnop\n" \
"\tsync%-%]%>%)\n" \
"2:\n"
+#define MIPS_COMPARE_AND_SWAP_12_ZERO_OP ""
+#define MIPS_COMPARE_AND_SWAP_12_NONZERO_OP "\tor\t%@,%@,%5\n"
+
+
/* Return an asm string that atomically:
- Sets memory reference %0 to %0 INSN %1.
@@ -2960,6 +2951,97 @@ while (0)
/* Return an asm string that atomically:
+ - Given that %1 contains a bit mask and %2 the inverted mask and
+ that %3 has already been ANDed with %1.
+
+ - Sets the selected bits of memory reference %0 to %0 INSN %3.
+
+ - Uses scratch register %4.
+
+ NOT_OP are the optional instructions to do a bit-wise not
+ operation in conjunction with an AND INSN to generate a sync_nand
+ operation. */
+#define MIPS_SYNC_OP_12(INSN, NOT_OP) \
+ "%(%<%[%|sync\n" \
+ "1:\tll\t%4,%0\n" \
+ "\tand\t%@,%4,%2\n" \
+ NOT_OP \
+ "\t" INSN "\t%4,%4,%z3\n" \
+ "\tand\t%4,%4,%1\n" \
+ "\tor\t%@,%@,%4\n" \
+ "\tsc\t%@,%0\n" \
+ "\tbeq\t%@,%.,1b\n" \
+ "\tnop\n" \
+ "\tsync%-%]%>%)"
+
+#define MIPS_SYNC_OP_12_NOT_NOP ""
+#define MIPS_SYNC_OP_12_NOT_NOT "\tnor\t%4,%4,%.\n"
+
+/* Return an asm string that atomically:
+
+ - Given that %2 contains a bit mask and %3 the inverted mask and
+ that %4 has already been ANDed with %2.
+
+ - Sets the selected bits of memory reference %1 to %1 INSN %4.
+
+ - Sets %0 to the original value of %1.
+
+ - Uses scratch register %5.
+
+ NOT_OP are the optional instructions to do a bit-wise not
+ operation in conjunction with an AND INSN to generate a sync_nand
+ operation.
+
+ REG is used in conjunction with NOT_OP and is used to select the
+ register operated on by the INSN. */
+#define MIPS_SYNC_OLD_OP_12(INSN, NOT_OP, REG) \
+ "%(%<%[%|sync\n" \
+ "1:\tll\t%0,%1\n" \
+ "\tand\t%@,%0,%3\n" \
+ NOT_OP \
+ "\t" INSN "\t%5," REG ",%z4\n" \
+ "\tand\t%5,%5,%2\n" \
+ "\tor\t%@,%@,%5\n" \
+ "\tsc\t%@,%1\n" \
+ "\tbeq\t%@,%.,1b\n" \
+ "\tnop\n" \
+ "\tsync%-%]%>%)"
+
+#define MIPS_SYNC_OLD_OP_12_NOT_NOP ""
+#define MIPS_SYNC_OLD_OP_12_NOT_NOP_REG "%0"
+#define MIPS_SYNC_OLD_OP_12_NOT_NOT "\tnor\t%5,%0,%.\n"
+#define MIPS_SYNC_OLD_OP_12_NOT_NOT_REG "%5"
+
+/* Return an asm string that atomically:
+
+ - Given that %2 contains a bit mask and %3 the inverted mask and
+ that %4 has already been ANDed with %2.
+
+ - Sets the selected bits of memory reference %1 to %1 INSN %4.
+
+ - Sets %0 to the new value of %1.
+
+ NOT_OP are the optional instructions to do a bit-wise not
+ operation in conjunction with an AND INSN to generate a sync_nand
+ operation. */
+#define MIPS_SYNC_NEW_OP_12(INSN, NOT_OP) \
+ "%(%<%[%|sync\n" \
+ "1:\tll\t%0,%1\n" \
+ "\tand\t%@,%0,%3\n" \
+ NOT_OP \
+ "\t" INSN "\t%0,%0,%z4\n" \
+ "\tand\t%0,%0,%2\n" \
+ "\tor\t%@,%@,%0\n" \
+ "\tsc\t%@,%1\n" \
+ "\tbeq\t%@,%.,1b\n" \
+ "\tnop\n" \
+ "\tsync%-%]%>%)"
+
+#define MIPS_SYNC_NEW_OP_12_NOT_NOP ""
+#define MIPS_SYNC_NEW_OP_12_NOT_NOT "\tnor\t%0,%0,%.\n"
+
+/* Return an asm string that atomically:
+
- Sets memory reference %1 to %1 INSN %2.
- Sets register %0 to the old value of memory reference %1.
@@ -3065,6 +3147,33 @@ while (0)
"\tnop\n" \
"\tsync%-%]%>%)"
+/* Return an asm string that atomically:
+
+ - Given that %2 contains an inclusive mask, %3 and exclusive mask
+ and %4 has already been ANDed with the inclusive mask.
+
+ - Sets bits selected by the inclusive mask of memory reference %1
+ to %4.
+
+ - Sets register %0 to the old value of memory reference %1.
+
+ OPS are the instructions needed to OR %4 with %@.
+
+ Operand %2 is unused, but needed as to give the test_and_set_12
+ insn the five operands expected by the expander. */
+#define MIPS_SYNC_EXCHANGE_12(OPS) \
+ "%(%<%[%|\n" \
+ "1:\tll\t%0,%1\n" \
+ "\tand\t%@,%0,%3\n" \
+ OPS \
+ "\tsc\t%@,%1\n" \
+ "\tbeq\t%@,%.,1b\n" \
+ "\tnop\n" \
+ "\tsync%-%]%>%)"
+
+#define MIPS_SYNC_EXCHANGE_12_ZERO_OP ""
+#define MIPS_SYNC_EXCHANGE_12_NONZERO_OP "\tor\t%@,%@,%4\n"
+
#ifndef USED_FOR_TARGET
extern const enum reg_class mips_regno_to_class[];
extern bool mips_hard_regno_mode_ok[][FIRST_PSEUDO_REGISTER];
diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md
index a423529..2b789ee 100644
--- a/gcc/config/mips/mips.md
+++ b/gcc/config/mips/mips.md
@@ -1,6 +1,6 @@
;; Mips.md Machine Description for MIPS based processors
;; Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-;; 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
+;; 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
;; Free Software Foundation, Inc.
;; Contributed by A. Lichnewsky, lich@inria.inria.fr
;; Changes by Michael Meissner, meissner@osf.org
@@ -57,10 +57,13 @@
(UNSPEC_COMPARE_AND_SWAP_12 38)
(UNSPEC_SYNC_OLD_OP 39)
(UNSPEC_SYNC_NEW_OP 40)
- (UNSPEC_SYNC_EXCHANGE 41)
- (UNSPEC_MEMORY_BARRIER 42)
- (UNSPEC_SET_GOT_VERSION 43)
- (UNSPEC_UPDATE_GOT_VERSION 44)
+ (UNSPEC_SYNC_NEW_OP_12 41)
+ (UNSPEC_SYNC_OLD_OP_12 42)
+ (UNSPEC_SYNC_EXCHANGE 43)
+ (UNSPEC_SYNC_EXCHANGE_12 44)
+ (UNSPEC_MEMORY_BARRIER 45)
+ (UNSPEC_SET_GOT_VERSION 46)
+ (UNSPEC_UPDATE_GOT_VERSION 47)
(UNSPEC_ADDRESS_FIRST 100)
@@ -639,7 +642,9 @@
(lshiftrt "lshr")
(ior "ior")
(xor "xor")
- (and "and")])
+ (and "and")
+ (plus "add")
+ (minus "sub")])
;; <insn> expands to the name of the insn that implements a particular code.
(define_code_attr insn [(ashift "sll")
@@ -647,7 +652,9 @@
(lshiftrt "srl")
(ior "or")
(xor "xor")
- (and "and")])
+ (and "and")
+ (plus "addu")
+ (minus "subu")])
;; <fcond> is the c.cond.fmt condition associated with a particular code.
(define_code_attr fcond [(unordered "un")
@@ -671,6 +678,8 @@
;; a particular code to operate in immediate values.
(define_code_attr immediate_insn [(ior "ori") (xor "xori") (and "andi")])
+;; Atomic HI and QI operations
+(define_code_iterator atomic_hiqi_op [plus minus ior xor and])
;; .........................
;;
@@ -4455,12 +4464,14 @@
(match_operand:SHORT 3 "general_operand")]
"GENERATE_LL_SC"
{
- mips_expand_compare_and_swap_12 (operands[0], operands[1],
- operands[2], operands[3]);
+ union mips_gen_fn_ptrs generator;
+ generator.fn_6 = gen_compare_and_swap_12;
+ mips_expand_atomic_qihi (generator,
+ operands[0], operands[1], operands[2], operands[3]);
DONE;
})
-;; Helper insn for mips_expand_compare_and_swap_12.
+;; Helper insn for mips_expand_atomic_qihi.
(define_insn "compare_and_swap_12"
[(set (match_operand:SI 0 "register_operand" "=&d,&d")
(match_operand:SI 1 "memory_operand" "+R,R"))
@@ -4473,9 +4484,9 @@
"GENERATE_LL_SC"
{
if (which_alternative == 0)
- return MIPS_COMPARE_AND_SWAP_12;
+ return MIPS_COMPARE_AND_SWAP_12 (MIPS_COMPARE_AND_SWAP_12_NONZERO_OP);
else
- return MIPS_COMPARE_AND_SWAP_12_0;
+ return MIPS_COMPARE_AND_SWAP_12 (MIPS_COMPARE_AND_SWAP_12_ZERO_OP);
}
[(set_attr "length" "40,36")])
@@ -4483,8 +4494,8 @@
[(set (match_operand:GPR 0 "memory_operand" "+R,R")
(unspec_volatile:GPR
[(plus:GPR (match_dup 0)
- (match_operand:GPR 1 "arith_operand" "I,d"))]
- UNSPEC_SYNC_OLD_OP))]
+ (match_operand:GPR 1 "arith_operand" "I,d"))]
+ UNSPEC_SYNC_OLD_OP))]
"GENERATE_LL_SC"
{
if (which_alternative == 0)
@@ -4494,6 +4505,220 @@
}
[(set_attr "length" "28")])
+(define_expand "sync_<optab><mode>"
+ [(set (match_operand:SHORT 0 "memory_operand")
+ (unspec_volatile:SHORT
+ [(atomic_hiqi_op:SHORT (match_dup 0)
+ (match_operand:SHORT 1 "general_operand"))]
+ UNSPEC_SYNC_OLD_OP))]
+ "GENERATE_LL_SC"
+{
+ union mips_gen_fn_ptrs generator;
+ generator.fn_4 = gen_sync_<optab>_12;
+ mips_expand_atomic_qihi (generator,
+ NULL, operands[0], operands[1], NULL);
+ DONE;
+})
+
+;; Helper insn for sync_<optab><mode>
+(define_insn "sync_<optab>_12"
+ [(set (match_operand:SI 0 "memory_operand" "+R")
+ (unspec_volatile:SI
+ [(match_operand:SI 1 "register_operand" "d")
+ (match_operand:SI 2 "register_operand" "d")
+ (atomic_hiqi_op:SI (match_dup 0)
+ (match_operand:SI 3 "register_operand" "dJ"))]
+ UNSPEC_SYNC_OLD_OP_12))
+ (clobber (match_scratch:SI 4 "=&d"))]
+ "GENERATE_LL_SC"
+{
+ return MIPS_SYNC_OP_12 ("<insn>", MIPS_SYNC_OP_12_NOT_NOP);
+}
+ [(set_attr "length" "40")])
+
+(define_expand "sync_old_<optab><mode>"
+ [(parallel [
+ (set (match_operand:SHORT 0 "register_operand")
+ (match_operand:SHORT 1 "memory_operand"))
+ (set (match_dup 1)
+ (unspec_volatile:SHORT [(atomic_hiqi_op:SHORT
+ (match_dup 1)
+ (match_operand:SHORT 2 "general_operand"))]
+ UNSPEC_SYNC_OLD_OP))])]
+ "GENERATE_LL_SC"
+{
+ union mips_gen_fn_ptrs generator;
+ generator.fn_5 = gen_sync_old_<optab>_12;
+ mips_expand_atomic_qihi (generator,
+ operands[0], operands[1], operands[2], NULL);
+ DONE;
+})
+
+;; Helper insn for sync_old_<optab><mode>
+(define_insn "sync_old_<optab>_12"
+ [(set (match_operand:SI 0 "register_operand" "=&d")
+ (match_operand:SI 1 "memory_operand" "+R"))
+ (set (match_dup 1)
+ (unspec_volatile:SI
+ [(match_operand:SI 2 "register_operand" "d")
+ (match_operand:SI 3 "register_operand" "d")
+ (atomic_hiqi_op:SI (match_dup 0)
+ (match_operand:SI 4 "register_operand" "dJ"))]
+ UNSPEC_SYNC_OLD_OP_12))
+ (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);
+}
+ [(set_attr "length" "40")])
+
+(define_expand "sync_new_<optab><mode>"
+ [(parallel [
+ (set (match_operand:SHORT 0 "register_operand")
+ (unspec_volatile:SHORT [(atomic_hiqi_op:SHORT
+ (match_operand:SHORT 1 "memory_operand")
+ (match_operand:SHORT 2 "general_operand"))]
+ UNSPEC_SYNC_NEW_OP))
+ (set (match_dup 1)
+ (unspec_volatile:SHORT [(match_dup 1) (match_dup 2)]
+ UNSPEC_SYNC_NEW_OP))])]
+ "GENERATE_LL_SC"
+{
+ union mips_gen_fn_ptrs generator;
+ generator.fn_5 = gen_sync_new_<optab>_12;
+ mips_expand_atomic_qihi (generator,
+ operands[0], operands[1], operands[2], NULL);
+ DONE;
+})
+
+;; Helper insn for sync_new_<optab><mode>
+(define_insn "sync_new_<optab>_12"
+ [(set (match_operand:SI 0 "register_operand" "=&d")
+ (unspec_volatile:SI
+ [(match_operand:SI 1 "memory_operand" "+R")
+ (match_operand:SI 2 "register_operand" "d")
+ (match_operand:SI 3 "register_operand" "d")
+ (atomic_hiqi_op:SI (match_dup 0)
+ (match_operand:SI 4 "register_operand" "dJ"))]
+ UNSPEC_SYNC_NEW_OP_12))
+ (set (match_dup 1)
+ (unspec_volatile:SI
+ [(match_dup 1)
+ (match_dup 2)
+ (match_dup 3)
+ (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);
+}
+ [(set_attr "length" "40")])
+
+(define_expand "sync_nand<mode>"
+ [(set (match_operand:SHORT 0 "memory_operand")
+ (unspec_volatile:SHORT
+ [(match_dup 0)
+ (match_operand:SHORT 1 "general_operand")]
+ UNSPEC_SYNC_OLD_OP))]
+ "GENERATE_LL_SC"
+{
+ union mips_gen_fn_ptrs generator;
+ generator.fn_4 = gen_sync_nand_12;
+ mips_expand_atomic_qihi (generator,
+ NULL, operands[0], operands[1], NULL);
+ DONE;
+})
+
+;; Helper insn for sync_nand<mode>
+(define_insn "sync_nand_12"
+ [(set (match_operand:SI 0 "memory_operand" "+R")
+ (unspec_volatile:SI
+ [(match_operand:SI 1 "register_operand" "d")
+ (match_operand:SI 2 "register_operand" "d")
+ (match_dup 0)
+ (match_operand:SI 3 "register_operand" "dJ")]
+ UNSPEC_SYNC_OLD_OP_12))
+ (clobber (match_scratch:SI 4 "=&d"))]
+ "GENERATE_LL_SC"
+{
+ return MIPS_SYNC_OP_12 ("and", MIPS_SYNC_OP_12_NOT_NOT);
+}
+ [(set_attr "length" "44")])
+
+(define_expand "sync_old_nand<mode>"
+ [(parallel [
+ (set (match_operand:SHORT 0 "register_operand")
+ (match_operand:SHORT 1 "memory_operand"))
+ (set (match_dup 1)
+ (unspec_volatile:SHORT [(match_dup 1)
+ (match_operand:SHORT 2 "general_operand")]
+ UNSPEC_SYNC_OLD_OP))])]
+ "GENERATE_LL_SC"
+{
+ union mips_gen_fn_ptrs generator;
+ generator.fn_5 = gen_sync_old_nand_12;
+ mips_expand_atomic_qihi (generator,
+ operands[0], operands[1], operands[2], NULL);
+ DONE;
+})
+
+;; Helper insn for sync_old_nand<mode>
+(define_insn "sync_old_nand_12"
+ [(set (match_operand:SI 0 "register_operand" "=&d")
+ (match_operand:SI 1 "memory_operand" "+R"))
+ (set (match_dup 1)
+ (unspec_volatile:SI
+ [(match_operand:SI 2 "register_operand" "d")
+ (match_operand:SI 3 "register_operand" "d")
+ (match_operand:SI 4 "register_operand" "dJ")]
+ UNSPEC_SYNC_OLD_OP_12))
+ (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);
+}
+ [(set_attr "length" "44")])
+
+(define_expand "sync_new_nand<mode>"
+ [(parallel [
+ (set (match_operand:SHORT 0 "register_operand")
+ (unspec_volatile:SHORT [(match_operand:SHORT 1 "memory_operand")
+ (match_operand:SHORT 2 "general_operand")]
+ UNSPEC_SYNC_NEW_OP))
+ (set (match_dup 1)
+ (unspec_volatile:SHORT [(match_dup 1) (match_dup 2)]
+ UNSPEC_SYNC_NEW_OP))])]
+ "GENERATE_LL_SC"
+{
+ union mips_gen_fn_ptrs generator;
+ generator.fn_5 = gen_sync_new_nand_12;
+ mips_expand_atomic_qihi (generator,
+ operands[0], operands[1], operands[2], NULL);
+ DONE;
+})
+
+;; Helper insn for sync_new_nand<mode>
+(define_insn "sync_new_nand_12"
+ [(set (match_operand:SI 0 "register_operand" "=&d")
+ (unspec_volatile:SI
+ [(match_operand:SI 1 "memory_operand" "+R")
+ (match_operand:SI 2 "register_operand" "d")
+ (match_operand:SI 3 "register_operand" "d")
+ (match_operand:SI 4 "register_operand" "dJ")]
+ UNSPEC_SYNC_NEW_OP_12))
+ (set (match_dup 1)
+ (unspec_volatile:SI
+ [(match_dup 1)
+ (match_dup 2)
+ (match_dup 3)
+ (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);
+}
+ [(set_attr "length" "40")])
+
(define_insn "sync_sub<mode>"
[(set (match_operand:GPR 0 "memory_operand" "+R")
(unspec_volatile:GPR
@@ -4507,7 +4732,7 @@
[(set_attr "length" "28")])
(define_insn "sync_old_add<mode>"
- [(set (match_operand:GPR 0 "register_operand" "=d,&d")
+ [(set (match_operand:GPR 0 "register_operand" "=&d,&d")
(match_operand:GPR 1 "memory_operand" "+R,R"))
(set (match_dup 1)
(unspec_volatile:GPR
@@ -4538,7 +4763,7 @@
[(set_attr "length" "28")])
(define_insn "sync_new_add<mode>"
- [(set (match_operand:GPR 0 "register_operand" "=d,&d")
+ [(set (match_operand:GPR 0 "register_operand" "=&d,&d")
(plus:GPR (match_operand:GPR 1 "memory_operand" "+R,R")
(match_operand:GPR 2 "arith_operand" "I,d")))
(set (match_dup 1)
@@ -4584,7 +4809,7 @@
[(set_attr "length" "28")])
(define_insn "sync_old_<optab><mode>"
- [(set (match_operand:GPR 0 "register_operand" "=d,&d")
+ [(set (match_operand:GPR 0 "register_operand" "=&d,&d")
(match_operand:GPR 1 "memory_operand" "+R,R"))
(set (match_dup 1)
(unspec_volatile:GPR
@@ -4601,7 +4826,7 @@
[(set_attr "length" "28")])
(define_insn "sync_new_<optab><mode>"
- [(set (match_operand:GPR 0 "register_operand" "=d,&d")
+ [(set (match_operand:GPR 0 "register_operand" "=&d,&d")
(match_operand:GPR 1 "memory_operand" "+R,R"))
(set (match_dup 1)
(unspec_volatile:GPR
@@ -4631,7 +4856,7 @@
[(set_attr "length" "32")])
(define_insn "sync_old_nand<mode>"
- [(set (match_operand:GPR 0 "register_operand" "=d,&d")
+ [(set (match_operand:GPR 0 "register_operand" "=&d,&d")
(match_operand:GPR 1 "memory_operand" "+R,R"))
(set (match_dup 1)
(unspec_volatile:GPR [(match_operand:GPR 2 "uns_arith_operand" "K,d")]
@@ -4646,7 +4871,7 @@
[(set_attr "length" "32")])
(define_insn "sync_new_nand<mode>"
- [(set (match_operand:GPR 0 "register_operand" "=d,&d")
+ [(set (match_operand:GPR 0 "register_operand" "=&d,&d")
(match_operand:GPR 1 "memory_operand" "+R,R"))
(set (match_dup 1)
(unspec_volatile:GPR [(match_operand:GPR 2 "uns_arith_operand" "K,d")]
@@ -4661,7 +4886,7 @@
[(set_attr "length" "32")])
(define_insn "sync_lock_test_and_set<mode>"
- [(set (match_operand:GPR 0 "register_operand" "=d,&d")
+ [(set (match_operand:GPR 0 "register_operand" "=&d,&d")
(match_operand:GPR 1 "memory_operand" "+R,R"))
(set (match_dup 1)
(unspec_volatile:GPR [(match_operand:GPR 2 "arith_operand" "I,d")]
@@ -4674,6 +4899,36 @@
return MIPS_SYNC_EXCHANGE ("<d>", "move");
}
[(set_attr "length" "24")])
+
+(define_expand "sync_lock_test_and_set<mode>"
+ [(match_operand:SHORT 0 "register_operand")
+ (match_operand:SHORT 1 "memory_operand")
+ (match_operand:SHORT 2 "general_operand")]
+ "GENERATE_LL_SC"
+{
+ union mips_gen_fn_ptrs generator;
+ generator.fn_5 = gen_test_and_set_12;
+ mips_expand_atomic_qihi (generator,
+ operands[0], operands[1], operands[2], NULL);
+ DONE;
+})
+
+(define_insn "test_and_set_12"
+ [(set (match_operand:SI 0 "register_operand" "=&d,&d")
+ (match_operand:SI 1 "memory_operand" "+R,R"))
+ (set (match_dup 1)
+ (unspec_volatile:SI [(match_operand:SI 2 "register_operand" "d,d")
+ (match_operand:SI 3 "register_operand" "d,d")
+ (match_operand:SI 4 "arith_operand" "d,J")]
+ UNSPEC_SYNC_EXCHANGE_12))]
+ "GENERATE_LL_SC"
+{
+ if (which_alternative == 0)
+ return MIPS_SYNC_EXCHANGE_12 (MIPS_SYNC_EXCHANGE_12_NONZERO_OP);
+ else
+ return MIPS_SYNC_EXCHANGE_12 (MIPS_SYNC_EXCHANGE_12_ZERO_OP);
+}
+ [(set_attr "length" "28,24")])
;; Block moves, see mips.c for more details.
;; Argument 0 is the destination