mirror of
https://gcc.gnu.org/git/gcc.git
synced 2025-01-06 02:53:52 +08:00
mips.md (UNSPEC_COMPARE_AND_SWAP_12): New unspec_volitile.
gcc/ 2008-04-23 David Daney <ddaney@avtrex.com> * config/mips/mips.md (UNSPEC_COMPARE_AND_SWAP_12): New unspec_volitile. (UNSPEC_SYNC_OLD_OP, UNSPEC_SYNC_NEW_OP, UNSPEC_SYNC_EXCHANGE, UNSPEC_MEMORY_BARRIER, UNSPEC_SET_GOT_VERSION, UNSPEC_UPDATE_GOT_VERSION): Renumber. (sync_compare_and_swap<mode>): New expand for QI and HI modes. (compare_and_swap_12): New insn. * config/mips/mips-protos.h (mips_expand_compare_and_swap_12): Declare. * config/mips/mips.c (mips_force_binary): New function. (mips_emit_int_order_test, mips_expand_synci_loop): Use it. (mips_expand_compare_and_swap_12): New function. * config/mips/mips.h (MIPS_COMPARE_AND_SWAP_12): New macro. gcc/testsuite/ * gcc.target/mips/gcc-have-sync-compare-and-swap-1.c: Expect __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 and __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 to be defined. * gcc.target/mips/gcc-have-sync-compare-and-swap-2.c: Likewise. From-SVN: r134695
This commit is contained in:
parent
a93a597ae7
commit
49bce30a21
@ -1,3 +1,18 @@
|
||||
2008-04-26 David Daney <ddaney@avtrex.com>
|
||||
|
||||
* config/mips/mips.md (UNSPEC_COMPARE_AND_SWAP_12): New
|
||||
unspec_volitile.
|
||||
(UNSPEC_SYNC_OLD_OP, UNSPEC_SYNC_NEW_OP, UNSPEC_SYNC_EXCHANGE,
|
||||
UNSPEC_MEMORY_BARRIER, UNSPEC_SET_GOT_VERSION,
|
||||
UNSPEC_UPDATE_GOT_VERSION): Renumber.
|
||||
(sync_compare_and_swap<mode>): New expand for QI and HI modes.
|
||||
(compare_and_swap_12): New insn.
|
||||
* config/mips/mips-protos.h (mips_expand_compare_and_swap_12): Declare.
|
||||
* config/mips/mips.c (mips_force_binary): New function.
|
||||
(mips_emit_int_order_test, mips_expand_synci_loop): Use it.
|
||||
(mips_expand_compare_and_swap_12): New function.
|
||||
* config/mips/mips.h (MIPS_COMPARE_AND_SWAP_12): New macro.
|
||||
|
||||
2008-04-25 Jan Hubicka <jh@suse.cz>
|
||||
|
||||
PR testsuite/35843
|
||||
|
@ -292,5 +292,6 @@ 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);
|
||||
|
||||
#endif /* ! GCC_MIPS_PROTOS_H */
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* Subroutines used for MIPS code generation.
|
||||
Copyright (C) 1989, 1990, 1991, 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.
|
||||
@ -2121,6 +2121,19 @@ mips_emit_binary (enum rtx_code code, rtx target, rtx op0, rtx op1)
|
||||
gen_rtx_fmt_ee (code, GET_MODE (target), op0, op1)));
|
||||
}
|
||||
|
||||
/* Compute (CODE OP0 OP1) and store the result in a new register
|
||||
of mode MODE. Return that new register. */
|
||||
|
||||
static rtx
|
||||
mips_force_binary (enum machine_mode mode, enum rtx_code code, rtx op0, rtx op1)
|
||||
{
|
||||
rtx reg;
|
||||
|
||||
reg = gen_reg_rtx (mode);
|
||||
mips_emit_binary (code, reg, op0, op1);
|
||||
return reg;
|
||||
}
|
||||
|
||||
/* Copy VALUE to a register and return that register. If new pseudos
|
||||
are allowed, copy it into a new register, otherwise use DEST. */
|
||||
|
||||
@ -3741,8 +3754,10 @@ mips_emit_int_order_test (enum rtx_code code, bool *invert_ptr,
|
||||
}
|
||||
else if (invert_ptr == 0)
|
||||
{
|
||||
rtx inv_target = gen_reg_rtx (GET_MODE (target));
|
||||
mips_emit_binary (inv_code, inv_target, cmp0, cmp1);
|
||||
rtx inv_target;
|
||||
|
||||
inv_target = mips_force_binary (GET_MODE (target),
|
||||
inv_code, cmp0, cmp1);
|
||||
mips_emit_binary (XOR, target, inv_target, const1_rtx);
|
||||
}
|
||||
else
|
||||
@ -5850,8 +5865,7 @@ mips_expand_synci_loop (rtx begin, rtx end)
|
||||
|
||||
emit_insn (gen_synci (begin));
|
||||
|
||||
cmp = gen_reg_rtx (Pmode);
|
||||
mips_emit_binary (GTU, cmp, begin, end);
|
||||
cmp = mips_force_binary (Pmode, GTU, begin, end);
|
||||
|
||||
mips_emit_binary (PLUS, begin, begin, inc);
|
||||
|
||||
@ -5859,6 +5873,68 @@ 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. */
|
||||
|
||||
void
|
||||
mips_expand_compare_and_swap_12 (rtx result, rtx mem, rtx oldval, rtx newval)
|
||||
{
|
||||
rtx orig_addr, memsi_addr, memsi, shift, shiftsi, unshifted_mask;
|
||||
rtx mask, inverted_mask, oldvalsi, old_shifted, newvalsi, new_shifted, res;
|
||||
|
||||
/* Compute the address of the containing SImode value. */
|
||||
orig_addr = force_reg (Pmode, XEXP (mem, 0));
|
||||
memsi_addr = mips_force_binary (Pmode, AND, orig_addr,
|
||||
force_reg (Pmode, GEN_INT (-4)));
|
||||
|
||||
/* Create a memory reference for it. */
|
||||
memsi = gen_rtx_MEM (SImode, memsi_addr);
|
||||
set_mem_alias_set (memsi, ALIAS_SET_MEMORY_BARRIER);
|
||||
MEM_VOLATILE_P (memsi) = MEM_VOLATILE_P (mem);
|
||||
|
||||
/* Work out the byte offset of the QImode or HImode value,
|
||||
counting from the least significant byte. */
|
||||
shift = mips_force_binary (Pmode, AND, orig_addr, GEN_INT (3));
|
||||
if (TARGET_BIG_ENDIAN)
|
||||
mips_emit_binary (XOR, shift, shift,
|
||||
GEN_INT (GET_MODE (mem) == QImode ? 3 : 2));
|
||||
|
||||
/* Multiply by eight to convert the shift value from bytes to bits. */
|
||||
mips_emit_binary (ASHIFT, shift, shift, GEN_INT (3));
|
||||
|
||||
/* Make the final shift an SImode value, so that it can be used in
|
||||
SImode operations. */
|
||||
shiftsi = force_reg (SImode, gen_lowpart (SImode, shift));
|
||||
|
||||
/* Set MASK to an inclusive mask of the QImode or HImode value. */
|
||||
unshifted_mask = GEN_INT (GET_MODE_MASK (GET_MODE (mem)));
|
||||
unshifted_mask = force_reg (SImode, unshifted_mask);
|
||||
mask = mips_force_binary (SImode, ASHIFT, unshifted_mask, shiftsi);
|
||||
|
||||
/* Compute the equivalent exclusive mask. */
|
||||
inverted_mask = gen_reg_rtx (SImode);
|
||||
emit_insn (gen_rtx_SET (VOIDmode, inverted_mask,
|
||||
gen_rtx_NOT (SImode, mask)));
|
||||
|
||||
/* Shift the old value into place. */
|
||||
oldvalsi = force_reg (SImode, gen_lowpart (SImode, oldval));
|
||||
old_shifted = mips_force_binary (SImode, ASHIFT, oldvalsi, shiftsi);
|
||||
|
||||
/* Do the same for the new value. */
|
||||
newvalsi = force_reg (SImode, gen_lowpart (SImode, newval));
|
||||
new_shifted = mips_force_binary (SImode, ASHIFT, newvalsi, shiftsi);
|
||||
|
||||
/* Do the SImode atomic access. */
|
||||
res = gen_reg_rtx (SImode);
|
||||
emit_insn (gen_compare_and_swap_12 (res, memsi, mask, inverted_mask,
|
||||
old_shifted, new_shifted));
|
||||
|
||||
/* 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
|
||||
bitfield of WIDTH bits starting BITPOS bits into *OP. When
|
||||
returning true, update *OP, *LEFT and *RIGHT as follows:
|
||||
|
@ -2904,6 +2904,30 @@ while (0)
|
||||
"\tnop\n" \
|
||||
"2:\tsync%-%]%>%)"
|
||||
|
||||
/* 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.
|
||||
|
||||
- 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%@,%4,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"
|
||||
|
||||
/* Return an asm string that atomically:
|
||||
|
||||
- Sets memory reference %0 to %0 INSN %1.
|
||||
|
@ -54,12 +54,13 @@
|
||||
(UNSPEC_SYNCI 35)
|
||||
(UNSPEC_SYNC 36)
|
||||
(UNSPEC_COMPARE_AND_SWAP 37)
|
||||
(UNSPEC_SYNC_OLD_OP 38)
|
||||
(UNSPEC_SYNC_NEW_OP 39)
|
||||
(UNSPEC_SYNC_EXCHANGE 40)
|
||||
(UNSPEC_MEMORY_BARRIER 41)
|
||||
(UNSPEC_SET_GOT_VERSION 42)
|
||||
(UNSPEC_UPDATE_GOT_VERSION 43)
|
||||
(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_ADDRESS_FIRST 100)
|
||||
|
||||
@ -4447,6 +4448,34 @@
|
||||
}
|
||||
[(set_attr "length" "32")])
|
||||
|
||||
(define_expand "sync_compare_and_swap<mode>"
|
||||
[(match_operand:SHORT 0 "register_operand")
|
||||
(match_operand:SHORT 1 "memory_operand")
|
||||
(match_operand:SHORT 2 "general_operand")
|
||||
(match_operand:SHORT 3 "general_operand")]
|
||||
"GENERATE_LL_SC"
|
||||
{
|
||||
mips_expand_compare_and_swap_12 (operands[0], operands[1],
|
||||
operands[2], operands[3]);
|
||||
DONE;
|
||||
})
|
||||
|
||||
;; Helper insn for mips_expand_compare_and_swap_12.
|
||||
(define_insn "compare_and_swap_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" "d")
|
||||
(match_operand:SI 5 "register_operand" "d")]
|
||||
UNSPEC_COMPARE_AND_SWAP_12))]
|
||||
"GENERATE_LL_SC"
|
||||
{
|
||||
return MIPS_COMPARE_AND_SWAP_12;
|
||||
}
|
||||
[(set_attr "length" "40")])
|
||||
|
||||
(define_insn "sync_add<mode>"
|
||||
[(set (match_operand:GPR 0 "memory_operand" "+R,R")
|
||||
(unspec_volatile:GPR
|
||||
|
@ -1,3 +1,10 @@
|
||||
2008-04-26 Richard Sandiford <rsandifo@nildram.co.uk>
|
||||
|
||||
* gcc.target/mips/gcc-have-sync-compare-and-swap-1.c: Expect
|
||||
__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 and
|
||||
__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 to be defined.
|
||||
* gcc.target/mips/gcc-have-sync-compare-and-swap-2.c: Likewise.
|
||||
|
||||
2008-04-25 Tobias Burnus <burnus@net-b.de>
|
||||
|
||||
* gfortran/array_constructor_23.f: Change REAL(10) into kind > 8.
|
||||
|
@ -1,11 +1,11 @@
|
||||
/* { dg-do preprocess } */
|
||||
/* { dg-mips-options "-mips2" } */
|
||||
|
||||
#ifdef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1
|
||||
#if defined (__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1) == defined (__mips16)
|
||||
#error nonono
|
||||
#endif
|
||||
|
||||
#ifdef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2
|
||||
#if defined (__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2) == defined (__mips16)
|
||||
#error nonono
|
||||
#endif
|
||||
|
||||
|
@ -1,11 +1,11 @@
|
||||
/* { dg-do preprocess } */
|
||||
/* { dg-mips-options "-mgp64" } */
|
||||
|
||||
#ifdef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1
|
||||
#if defined (__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1) == defined (__mips16)
|
||||
#error nonono
|
||||
#endif
|
||||
|
||||
#ifdef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2
|
||||
#if defined (__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2) == defined (__mips16)
|
||||
#error nonono
|
||||
#endif
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user