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
This commit is contained in:
David Daney 2008-05-20 23:13:13 +00:00 committed by David Daney
parent a35f6a358e
commit 06d1961718
5 changed files with 499 additions and 52 deletions

View file

@ -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

View file

@ -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 */

View file

@ -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));
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);
/* 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));
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

View file

@ -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,40 +2908,31 @@ 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 \
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" \
"\tor\t%@,%@,%5\n" \
OPS \
"\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 \
"%(%<%[%|sync\n" \
"1:\tll\t%0,%1\n" \
"\tand\t%@,%0,%2\n" \
"\tbne\t%@,%z4,2f\n" \
"\tand\t%@,%0,%3\n" \
"\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:
@ -2958,6 +2949,97 @@ while (0)
"\tnop\n" \
"\tsync%-%]%>%)"
/* 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.
@ -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];

View file

@ -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