Index: ChangeLog

2005-04-21  Geoffrey Keating  <geoffk@apple.com>

	* config/rs6000/rs6000-protos.h (rs6000_emit_sync): New.
	* config/rs6000/rs6000.c (rs6000_emit_vector_compare): Use
	gen_rtx_* not gen_rtx_fmt_*.
	(rs6000_emit_vector_select): Likewise.
	(rs6000_emit_sync): New.
	* config/rs6000/rs6000.md (GPR, INT, INT1): New mode macros.
	(larx, stcx, cmp): New mode substitutions.
	(UNSPEC_SYNC, UNSPEC_SYNC_OP, UNSPEC_SYNC_SWAP, UNSPEC_LWSYNC,
	UNSPEC_ISYNC): New constants.
	(rlwinm): Give name.
	(memory_barrier, isync, lwsync): New insns.
	(sync_compare_and_swap<mode>, sync_lock_test_and_set<mode>): New insn.
	(sync_lock_release<mode>): New expander.
	(sync_add<mode>, sync_sub<mode>, sync_ior<mode>, sync_and<mode>,
	sync_xor<mode>, sync_nand<mode>, sync_old_add<mode>,
	sync_old_sub<mode>, sync_old_ior<mode>, sync_old_and<mode>,
	sync_old_xor<mode>, sync_old_nand<mode>, sync_new_add<mode>,
	sync_new_sub<mode>, sync_new_ior<mode>, sync_new_and<mode>,
	sync_new_xor<mode>, sync_new_nand<mode>): New expanders.
	(sync_add<mode>_internal, sync_addshort_internal,
	sync_sub<mode>_internal, sync_andsi_internal, sync_anddi_internal,
	sync_boolsi_internal, sync_booldi_internal, sync_boolc<mode>_internal,
	sync_boolc<mode>_internal2, sync_boolcc<mode>_internal): New insns.

	* doc/md.texi (Standard Names): sync_compare_and_swap's operand 0
	is the memory before, not after, the operation.  Clarify
	barrier requirements.

Index: testsuite/ChangeLog
2005-04-21  Geoffrey Keating  <geoffk@apple.com>

	* lib/target-supports.exp (check_effective_target_sync_int_long):
	Add powerpc*.

From-SVN: r98527
This commit is contained in:
Geoffrey Keating 2005-04-21 21:13:41 +00:00 committed by Geoffrey Keating
parent 8fd5bcbe95
commit 915167f5a5
7 changed files with 698 additions and 25 deletions

View File

@ -1,3 +1,33 @@
2005-04-21 Geoffrey Keating <geoffk@apple.com>
* config/rs6000/rs6000-protos.h (rs6000_emit_sync): New.
* config/rs6000/rs6000.c (rs6000_emit_vector_compare): Use
gen_rtx_* not gen_rtx_fmt_*.
(rs6000_emit_vector_select): Likewise.
(rs6000_emit_sync): New.
* config/rs6000/rs6000.md (GPR, INT, INT1): New mode macros.
(larx, stcx, cmp): New mode substitutions.
(UNSPEC_SYNC, UNSPEC_SYNC_OP, UNSPEC_SYNC_SWAP, UNSPEC_LWSYNC,
UNSPEC_ISYNC): New constants.
(rlwinm): Give name.
(memory_barrier, isync, lwsync): New insns.
(sync_compare_and_swap<mode>, sync_lock_test_and_set<mode>): New insn.
(sync_lock_release<mode>): New expander.
(sync_add<mode>, sync_sub<mode>, sync_ior<mode>, sync_and<mode>,
sync_xor<mode>, sync_nand<mode>, sync_old_add<mode>,
sync_old_sub<mode>, sync_old_ior<mode>, sync_old_and<mode>,
sync_old_xor<mode>, sync_old_nand<mode>, sync_new_add<mode>,
sync_new_sub<mode>, sync_new_ior<mode>, sync_new_and<mode>,
sync_new_xor<mode>, sync_new_nand<mode>): New expanders.
(sync_add<mode>_internal, sync_addshort_internal,
sync_sub<mode>_internal, sync_andsi_internal, sync_anddi_internal,
sync_boolsi_internal, sync_booldi_internal, sync_boolc<mode>_internal,
sync_boolc<mode>_internal2, sync_boolcc<mode>_internal): New insns.
* doc/md.texi (Standard Names): sync_compare_and_swap's operand 0
is the memory before, not after, the operation. Clarify
barrier requirements.
2005-04-21 Nathan Sidwell <nathan@codesourcery.com>
* cfghooks.h (struct cfg_hooks): Reword comments to avoid 'abort'.

View File

@ -80,6 +80,8 @@ extern rtx rs6000_emit_set_const (rtx, enum machine_mode, rtx, int);
extern int rs6000_emit_cmove (rtx, rtx, rtx, rtx);
extern int rs6000_emit_vector_cond_expr (rtx, rtx, rtx, rtx, rtx, rtx);
extern void rs6000_emit_minmax (rtx, enum rtx_code, rtx, rtx);
extern void rs6000_emit_sync (enum rtx_code, enum machine_mode,
rtx, rtx, rtx, rtx, bool);
extern void output_toc (FILE *, rtx, int, enum machine_mode);
extern void rs6000_initialize_trampoline (rtx, rtx, rtx);
extern rtx rs6000_longcall_ref (rtx);

View File

@ -10620,12 +10620,10 @@ rs6000_emit_vector_compare (enum rtx_code rcode,
}
}
emit_insn (gen_rtx_fmt_ee (SET,
VOIDmode,
mask,
gen_rtx_fmt_Ei (UNSPEC, dest_mode,
gen_rtvec (2, op0, op1),
vec_cmp_insn)));
emit_insn (gen_rtx_SET (VOIDmode, mask,
gen_rtx_UNSPEC (dest_mode,
gen_rtvec (2, op0, op1),
vec_cmp_insn)));
if (dmode != dest_mode)
{
rtx temp = gen_reg_rtx (dest_mode);
@ -10676,10 +10674,10 @@ rs6000_emit_vector_select (rtx dest, rtx op1, rtx op2, rtx mask)
/* For each vector element, select op1 when mask is 1 otherwise
select op2. */
t = gen_rtx_fmt_ee (SET, VOIDmode, temp,
gen_rtx_fmt_Ei (UNSPEC, dest_mode,
gen_rtvec (3, op2, op1, mask),
vsel_insn_index));
t = gen_rtx_SET (VOIDmode, temp,
gen_rtx_UNSPEC (dest_mode,
gen_rtvec (3, op2, op1, mask),
vsel_insn_index));
emit_insn (t);
emit_move_insn (dest, temp);
return;
@ -10960,6 +10958,183 @@ rs6000_emit_minmax (rtx dest, enum rtx_code code, rtx op0, rtx op1)
emit_move_insn (dest, target);
}
/* Emit instructions to perform a load-reserved/store-conditional operation.
The operation performed is an atomic
(set M (CODE:MODE M OP))
If not NULL, BEFORE is atomically set to M before the operation, and
AFTER is set to M after the operation (that is, (CODE:MODE M OP)).
If SYNC_P then a memory barrier is emitted before the operation.
Either OP or M may be wrapped in a NOT operation. */
void
rs6000_emit_sync (enum rtx_code code, enum machine_mode mode,
rtx m, rtx op, rtx before_param, rtx after_param,
bool sync_p)
{
enum machine_mode used_mode;
rtx the_op, set_before, set_after, set_atomic, cc_scratch, before, after;
rtx used_m;
rtvec vec;
HOST_WIDE_INT imask = GET_MODE_MASK (mode);
rtx shift = NULL_RTX;
if (sync_p)
emit_insn (gen_memory_barrier ());
if (GET_CODE (m) == NOT)
used_m = XEXP (m, 0);
else
used_m = m;
/* If this is smaller than SImode, we'll have to use SImode with
adjustments. */
if (mode == QImode || mode == HImode)
{
rtx newop, oldop;
if (MEM_ALIGN (used_m) >= 32)
{
int ishift = 0;
if (BYTES_BIG_ENDIAN)
ishift = GET_MODE_BITSIZE (SImode) - GET_MODE_BITSIZE (mode);
shift = GEN_INT (ishift);
}
else
{
rtx addrSI, aligned_addr;
addrSI = force_reg (SImode, gen_lowpart_common (SImode,
XEXP (used_m, 0)));
shift = gen_reg_rtx (SImode);
emit_insn (gen_rlwinm (shift, addrSI, GEN_INT (3),
GEN_INT (0x18)));
aligned_addr = expand_binop (Pmode, and_optab,
XEXP (used_m, 0),
GEN_INT (-4), NULL_RTX,
1, OPTAB_LIB_WIDEN);
used_m = change_address (used_m, SImode, aligned_addr);
set_mem_align (used_m, 32);
/* It's safe to keep the old alias set of USED_M, because
the operation is atomic and only affects the original
USED_M. */
if (GET_CODE (m) == NOT)
m = gen_rtx_NOT (SImode, used_m);
else
m = used_m;
}
if (GET_CODE (op) == NOT)
{
oldop = lowpart_subreg (SImode, XEXP (op, 0), mode);
oldop = gen_rtx_NOT (SImode, oldop);
}
else
oldop = lowpart_subreg (SImode, op, mode);
switch (code)
{
case IOR:
case XOR:
newop = expand_binop (SImode, and_optab,
oldop, GEN_INT (imask), NULL_RTX,
1, OPTAB_LIB_WIDEN);
emit_insn (gen_ashlsi3 (newop, newop, shift));
break;
case AND:
newop = expand_binop (SImode, ior_optab,
oldop, GEN_INT (~imask), NULL_RTX,
1, OPTAB_LIB_WIDEN);
emit_insn (gen_ashlsi3 (newop, newop, shift));
break;
case PLUS:
{
rtx mask;
newop = expand_binop (SImode, and_optab,
oldop, GEN_INT (imask), NULL_RTX,
1, OPTAB_LIB_WIDEN);
emit_insn (gen_ashlsi3 (newop, newop, shift));
mask = gen_reg_rtx (SImode);
emit_move_insn (mask, GEN_INT (imask));
emit_insn (gen_ashlsi3 (mask, mask, shift));
newop = gen_rtx_AND (SImode, gen_rtx_PLUS (SImode, m, newop),
mask);
newop = gen_rtx_IOR (SImode, newop,
gen_rtx_AND (SImode,
gen_rtx_NOT (SImode, mask),
m));
break;
}
default:
gcc_unreachable ();
}
op = newop;
used_mode = SImode;
before = gen_reg_rtx (used_mode);
after = gen_reg_rtx (used_mode);
}
else
{
used_mode = mode;
before = before_param;
after = after_param;
if (before == NULL_RTX)
before = gen_reg_rtx (used_mode);
if (after == NULL_RTX)
after = gen_reg_rtx (used_mode);
}
if (code == PLUS && used_mode != mode)
the_op = op; /* Computed above. */
else if (GET_CODE (op) == NOT && GET_CODE (m) != NOT)
the_op = gen_rtx_fmt_ee (code, used_mode, op, m);
else
the_op = gen_rtx_fmt_ee (code, used_mode, m, op);
set_after = gen_rtx_SET (VOIDmode, after, the_op);
set_before = gen_rtx_SET (VOIDmode, before, used_m);
set_atomic = gen_rtx_SET (VOIDmode, used_m,
gen_rtx_UNSPEC (used_mode, gen_rtvec (1, the_op),
UNSPEC_SYNC_OP));
cc_scratch = gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (CCmode));
if (code == PLUS && used_mode != mode)
vec = gen_rtvec (5, set_after, set_before, set_atomic, cc_scratch,
gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (SImode)));
else
vec = gen_rtvec (4, set_after, set_before, set_atomic, cc_scratch);
emit_insn (gen_rtx_PARALLEL (VOIDmode, vec));
/* Shift and mask the return values properly. */
if (used_mode != mode && before_param)
{
emit_insn (gen_lshrsi3 (before, before, shift));
convert_move (before_param, before, 1);
}
if (used_mode != mode && after_param)
{
emit_insn (gen_lshrsi3 (after, after, shift));
convert_move (after_param, after, 1);
}
/* The previous sequence will end with a branch that's dependent on
the conditional store, so placing an isync will ensure that no
other instructions (especially, no load or store instructions)
can start before the atomic operation completes. */
if (sync_p)
emit_insn (gen_isync ());
}
/* Emit instructions to move SRC to DST. Called by splitters for
multi-register moves. It will emit at most one instruction for
each register that is accessed; that is, it won't emit li/lis pairs

View File

@ -52,6 +52,11 @@
(UNSPEC_FIX_TRUNC_TF 30) ; fadd, rounding towards zero
(UNSPEC_MV_CR_GT 31) ; move_from_CR_eq_bit
(UNSPEC_STFIWX 32)
(UNSPEC_SYNC 33)
(UNSPEC_SYNC_OP 34)
(UNSPEC_SYNC_SWAP 35)
(UNSPEC_LWSYNC 36)
(UNSPEC_ISYNC 37)
])
;;
@ -108,10 +113,28 @@
(include "darwin.md")
;; This mode macro allows :P to be used for patterns that operate on
;; pointer-sized quantities. Exactly one of the two alternatives will match.
;; Mode macros
; This mode macro allows :GPR to be used to indicate the allowable size
; of whole values in GPRs.
(define_mode_macro GPR [SI (DI "TARGET_POWERPC64")])
; Any supported integer mode
(define_mode_macro INT [QI HI SI DI TI])
; Any supported integer mode that fits in one register
(define_mode_macro INT1 [QI HI SI (DI "TARGET_POWERPC64")])
; This mode macro allows :P to be used for patterns that operate on
; pointer-sized quantities. Exactly one of the two alternatives will match.
(define_mode_macro P [(SI "Pmode == SImode") (DI "Pmode == DImode")])
; Various instructions that come in SI and DI forms.
(define_mode_attr larx [(SI "lwarx") (DI "ldarx")])
(define_mode_attr stcx [(SI "stwcx.") (DI "stdcx.")])
(define_mode_attr cmp [(SI "cmpw") (DI "cmpd")])
;; Start with fixed-point load and store insns. Here we put only the more
;; complex forms. Basic data transfer is done later.
@ -3742,7 +3765,7 @@
(const_int 0)))]
"")
(define_insn ""
(define_insn "rlwinm"
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
(and:SI (ashift:SI (match_operand:SI 1 "gpc_reg_operand" "r")
(match_operand:SI 2 "const_int_operand" "i"))
@ -14733,6 +14756,433 @@
return INTVAL (operands[1]) ? \"dcbtst %a0\" : \"dcbt %a0\";
}"
[(set_attr "type" "load")])
; Atomic instructions
(define_insn "memory_barrier"
[(set (mem:BLK (match_scratch 0 "X"))
(unspec:BLK [(mem:BLK (match_scratch 1 "X"))] UNSPEC_SYNC))]
""
"{ics|sync}")
(define_insn "sync_compare_and_swap<mode>"
[(set (match_operand:GPR 1 "memory_operand" "+Z")
(unspec:GPR [(match_dup 1)
(match_operand:GPR 2 "reg_or_short_operand" "rI")
(match_operand:GPR 3 "gpc_reg_operand" "r")]
UNSPEC_SYNC_SWAP))
(set (match_operand:GPR 0 "gpc_reg_operand" "=&r") (match_dup 1))
(set (mem:BLK (match_scratch 5 "X"))
(unspec:BLK [(mem:BLK (match_scratch 6 "X"))] UNSPEC_SYNC))
(clobber (match_scratch:CC 4 "=&x"))]
"TARGET_POWERPC"
"sync\n0:\t<larx> %0,%y1\n\t<cmp>%I2 %0,%2\n\tbne- 1f\n\t<stcx> %3,%y1\n\tbne- 0b\n\t1:\tisync"
[(set_attr "length" "28")])
(define_expand "sync_add<mode>"
[(use (match_operand:INT1 0 "memory_operand" ""))
(use (match_operand:INT1 1 "add_operand" ""))]
"TARGET_POWERPC"
"
{
rs6000_emit_sync (PLUS, <MODE>mode, operands[0], operands[1],
NULL_RTX, NULL_RTX, true);
DONE;
}")
(define_expand "sync_sub<mode>"
[(use (match_operand:GPR 0 "memory_operand" ""))
(use (match_operand:GPR 1 "gpc_reg_operand" ""))]
"TARGET_POWERPC"
"
{
rs6000_emit_sync (MINUS, <MODE>mode, operands[0], operands[1],
NULL_RTX, NULL_RTX, true);
DONE;
}")
(define_expand "sync_ior<mode>"
[(use (match_operand:INT1 0 "memory_operand" ""))
(use (match_operand:INT1 1 "logical_operand" ""))]
"TARGET_POWERPC"
"
{
rs6000_emit_sync (IOR, <MODE>mode, operands[0], operands[1],
NULL_RTX, NULL_RTX, true);
DONE;
}")
(define_expand "sync_and<mode>"
[(use (match_operand:INT1 0 "memory_operand" ""))
(use (match_operand:INT1 1 "and_operand" ""))]
"TARGET_POWERPC"
"
{
rs6000_emit_sync (AND, <MODE>mode, operands[0], operands[1],
NULL_RTX, NULL_RTX, true);
DONE;
}")
(define_expand "sync_xor<mode>"
[(use (match_operand:INT1 0 "memory_operand" ""))
(use (match_operand:INT1 1 "logical_operand" ""))]
"TARGET_POWERPC"
"
{
rs6000_emit_sync (XOR, <MODE>mode, operands[0], operands[1],
NULL_RTX, NULL_RTX, true);
DONE;
}")
(define_expand "sync_nand<mode>"
[(use (match_operand:INT1 0 "memory_operand" ""))
(use (match_operand:INT1 1 "gpc_reg_operand" ""))]
"TARGET_POWERPC"
"
{
rs6000_emit_sync (AND, <MODE>mode,
gen_rtx_NOT (<MODE>mode, operands[0]),
operands[1],
NULL_RTX, NULL_RTX, true);
DONE;
}")
(define_expand "sync_old_add<mode>"
[(use (match_operand:INT1 0 "gpc_reg_operand" ""))
(use (match_operand:INT1 1 "memory_operand" ""))
(use (match_operand:INT1 2 "add_operand" ""))]
"TARGET_POWERPC"
"
{
rs6000_emit_sync (PLUS, <MODE>mode, operands[1], operands[2],
operands[0], NULL_RTX, true);
DONE;
}")
(define_expand "sync_old_sub<mode>"
[(use (match_operand:GPR 0 "gpc_reg_operand" ""))
(use (match_operand:GPR 1 "memory_operand" ""))
(use (match_operand:GPR 2 "gpc_reg_operand" ""))]
"TARGET_POWERPC"
"
{
rs6000_emit_sync (MINUS, <MODE>mode, operands[1], operands[2],
operands[0], NULL_RTX, true);
DONE;
}")
(define_expand "sync_old_ior<mode>"
[(use (match_operand:INT1 0 "gpc_reg_operand" ""))
(use (match_operand:INT1 1 "memory_operand" ""))
(use (match_operand:INT1 2 "logical_operand" ""))]
"TARGET_POWERPC"
"
{
rs6000_emit_sync (IOR, <MODE>mode, operands[1], operands[2],
operands[0], NULL_RTX, true);
DONE;
}")
(define_expand "sync_old_and<mode>"
[(use (match_operand:INT1 0 "gpc_reg_operand" ""))
(use (match_operand:INT1 1 "memory_operand" ""))
(use (match_operand:INT1 2 "and_operand" ""))]
"TARGET_POWERPC"
"
{
rs6000_emit_sync (AND, <MODE>mode, operands[1], operands[2],
operands[0], NULL_RTX, true);
DONE;
}")
(define_expand "sync_old_xor<mode>"
[(use (match_operand:INT1 0 "gpc_reg_operand" ""))
(use (match_operand:INT1 1 "memory_operand" ""))
(use (match_operand:INT1 2 "logical_operand" ""))]
"TARGET_POWERPC"
"
{
rs6000_emit_sync (XOR, <MODE>mode, operands[1], operands[2],
operands[0], NULL_RTX, true);
DONE;
}")
(define_expand "sync_old_nand<mode>"
[(use (match_operand:INT1 0 "gpc_reg_operand" ""))
(use (match_operand:INT1 1 "memory_operand" ""))
(use (match_operand:INT1 2 "gpc_reg_operand" ""))]
"TARGET_POWERPC"
"
{
rs6000_emit_sync (AND, <MODE>mode,
gen_rtx_NOT (<MODE>mode, operands[1]),
operands[2],
operands[0], NULL_RTX, true);
DONE;
}")
(define_expand "sync_new_add<mode>"
[(use (match_operand:INT1 0 "gpc_reg_operand" ""))
(use (match_operand:INT1 1 "memory_operand" ""))
(use (match_operand:INT1 2 "add_operand" ""))]
"TARGET_POWERPC"
"
{
rs6000_emit_sync (PLUS, <MODE>mode, operands[1], operands[2],
NULL_RTX, operands[0], true);
DONE;
}")
(define_expand "sync_new_sub<mode>"
[(use (match_operand:GPR 0 "gpc_reg_operand" ""))
(use (match_operand:GPR 1 "memory_operand" ""))
(use (match_operand:GPR 2 "gpc_reg_operand" ""))]
"TARGET_POWERPC"
"
{
rs6000_emit_sync (MINUS, <MODE>mode, operands[1], operands[2],
NULL_RTX, operands[0], true);
DONE;
}")
(define_expand "sync_new_ior<mode>"
[(use (match_operand:INT1 0 "gpc_reg_operand" ""))
(use (match_operand:INT1 1 "memory_operand" ""))
(use (match_operand:INT1 2 "logical_operand" ""))]
"TARGET_POWERPC"
"
{
rs6000_emit_sync (IOR, <MODE>mode, operands[1], operands[2],
NULL_RTX, operands[0], true);
DONE;
}")
(define_expand "sync_new_and<mode>"
[(use (match_operand:INT1 0 "gpc_reg_operand" ""))
(use (match_operand:INT1 1 "memory_operand" ""))
(use (match_operand:INT1 2 "and_operand" ""))]
"TARGET_POWERPC"
"
{
rs6000_emit_sync (AND, <MODE>mode, operands[1], operands[2],
NULL_RTX, operands[0], true);
DONE;
}")
(define_expand "sync_new_xor<mode>"
[(use (match_operand:INT1 0 "gpc_reg_operand" ""))
(use (match_operand:INT1 1 "memory_operand" ""))
(use (match_operand:INT1 2 "logical_operand" ""))]
"TARGET_POWERPC"
"
{
rs6000_emit_sync (XOR, <MODE>mode, operands[1], operands[2],
NULL_RTX, operands[0], true);
DONE;
}")
(define_expand "sync_new_nand<mode>"
[(use (match_operand:INT1 0 "gpc_reg_operand" ""))
(use (match_operand:INT1 1 "memory_operand" ""))
(use (match_operand:INT1 2 "gpc_reg_operand" ""))]
"TARGET_POWERPC"
"
{
rs6000_emit_sync (AND, <MODE>mode,
gen_rtx_NOT (<MODE>mode, operands[1]),
operands[2],
NULL_RTX, operands[0], true);
DONE;
}")
; the sync_*_internal patterns all have these operands:
; 0 - memory location
; 1 - operand
; 2 - value in memory after operation
; 3 - value in memory immediately before operation
(define_insn "*sync_add<mode>_internal"
[(set (match_operand:GPR 2 "gpc_reg_operand" "=&r,&r")
(plus:GPR (match_operand:GPR 0 "memory_operand" "+Z,Z")
(match_operand:GPR 1 "add_operand" "rI,L")))
(set (match_operand:GPR 3 "gpc_reg_operand" "=&b,&b") (match_dup 0))
(set (match_dup 0)
(unspec:GPR [(plus:GPR (match_dup 0) (match_dup 1))]
UNSPEC_SYNC_OP))
(clobber (match_scratch:CC 4 "=&x,&x"))]
"TARGET_POWERPC"
"@
0:\t<larx> %3,%y0\n\tadd%I1 %2,%3,%1\n\t<stcx> %2,%y0\n\tbne- 0b
0:\t<larx> %3,%y0\n\taddis %2,%3,%v1\n\t<stcx> %2,%y0\n\tbne- 0b"
[(set_attr "length" "16,16")])
(define_insn "*sync_addshort_internal"
[(set (match_operand:SI 2 "gpc_reg_operand" "=&r")
(ior:SI (and:SI (plus:SI (match_operand:SI 0 "memory_operand" "+Z")
(match_operand:SI 1 "add_operand" "rI"))
(match_operand:SI 4 "gpc_reg_operand" "r"))
(and:SI (not:SI (match_dup 4)) (match_dup 0))))
(set (match_operand:SI 3 "gpc_reg_operand" "=&b") (match_dup 0))
(set (match_dup 0)
(unspec:SI [(ior:SI (and:SI (plus:SI (match_dup 0) (match_dup 1))
(match_dup 4))
(and:SI (not:SI (match_dup 4)) (match_dup 0)))]
UNSPEC_SYNC_OP))
(clobber (match_scratch:CC 5 "=&x"))
(clobber (match_scratch:SI 6 "=&r"))]
"TARGET_POWERPC"
"0:\tlwarx %3,%y0\n\tadd%I1 %2,%3,%1\n\tandc %6,%3,%4\n\tand %2,%2,%4\n\tor %2,%2,%6\n\tstwcx. %2,%y0\n\tbne- 0b"
[(set_attr "length" "28")])
(define_insn "*sync_sub<mode>_internal"
[(set (match_operand:GPR 2 "gpc_reg_operand" "=&r")
(minus:GPR (match_operand:GPR 0 "memory_operand" "+Z")
(match_operand:GPR 1 "gpc_reg_operand" "r")))
(set (match_operand:GPR 3 "gpc_reg_operand" "=&b") (match_dup 0))
(set (match_dup 0)
(unspec:GPR [(minus:GPR (match_dup 0) (match_dup 1))]
UNSPEC_SYNC_OP))
(clobber (match_scratch:CC 4 "=&x"))]
"TARGET_POWERPC"
"0:\t<larx> %3,%y0\n\tsubf %2,%1,%3\n\t<stcx> %2,%y0\n\tbne- 0b"
[(set_attr "length" "16")])
(define_insn "*sync_andsi_internal"
[(set (match_operand:SI 2 "gpc_reg_operand" "=&r,&r,&r,&r")
(and:SI (match_operand:SI 0 "memory_operand" "+Z,Z,Z,Z")
(match_operand:SI 1 "and_operand" "r,T,K,L")))
(set (match_operand:SI 3 "gpc_reg_operand" "=&b,&b,&b,&b") (match_dup 0))
(set (match_dup 0)
(unspec:SI [(and:SI (match_dup 0) (match_dup 1))]
UNSPEC_SYNC_OP))
(clobber (match_scratch:CC 4 "=&x,&x,&x,&x"))]
"TARGET_POWERPC"
"@
0:\tlwarx %3,%y0\n\tand %2,%3,%1\n\tstwcx. %2,%y0\n\tbne- 0b
0:\tlwarx %3,%y0\n\trlwinm %2,%3,0,%m1,%M1\n\tstwcx. %2,%y0\n\tbne- 0b
0:\tlwarx %3,%y0\n\tandi. %2,%3,%b1\n\tstwcx. %2,%y0\n\tbne- 0b
0:\tlwarx %3,%y0\n\tandis. %2,%3,%u1\n\tstwcx. %2,%y0\n\tbne- 0b"
[(set_attr "length" "16,16,16,16")])
(define_insn "*sync_anddi_internal"
[(set (match_operand:DI 2 "gpc_reg_operand" "=&r,&r,&r,&r,&r")
(and:DI (match_operand:DI 0 "memory_operand" "+Z,Z,Z,Z,Z")
(match_operand:DI 1 "and_operand" "r,S,T,K,J")))
(set (match_operand:DI 3 "gpc_reg_operand" "=&b,&b,&b,&b,&b") (match_dup 0))
(set (match_dup 0)
(unspec:DI [(and:DI (match_dup 0) (match_dup 1))]
UNSPEC_SYNC_OP))
(clobber (match_scratch:CC 4 "=&x,&x,&x,&x,&x"))]
"TARGET_POWERPC64"
"@
0:\tldarx %3,%y0\n\tand %2,%3,%1\n\tstdcx. %2,%y0\n\tbne- 0b
0:\tldarx %3,%y0\n\trldic%B1 %2,%3,0,%S1\n\tstdcx. %2,%y0\n\tbne- 0b
0:\tldarx %3,%y0\n\trlwinm %2,%3,0,%m1,%M1\n\tstdcx. %2,%y0\n\tbne- 0b
0:\tldarx %3,%y0\n\tandi. %2,%3,%b1\n\tstdcx. %2,%y0\n\tbne- 0b
0:\tldarx %3,%y0\n\tandis. %2,%3,%b1\n\tstdcx. %2,%y0\n\tbne- 0b"
[(set_attr "length" "16,16,16,16,16")])
(define_insn "*sync_boolsi_internal"
[(set (match_operand:SI 2 "gpc_reg_operand" "=&r,&r,&r")
(match_operator:SI 4 "boolean_or_operator"
[(match_operand:SI 0 "memory_operand" "+Z,Z,Z")
(match_operand:SI 1 "logical_operand" "r,K,L")]))
(set (match_operand:SI 3 "gpc_reg_operand" "=&b,&b,&b") (match_dup 0))
(set (match_dup 0) (unspec:SI [(match_dup 4)] UNSPEC_SYNC_OP))
(clobber (match_scratch:CC 5 "=&x,&x,&x"))]
"TARGET_POWERPC"
"@
0:\tlwarx %3,%y0\n\t%q4 %2,%3,%1\n\tstwcx. %2,%y0\n\tbne- 0b
0:\tlwarx %3,%y0\n\t%q4i %2,%3,%b1\n\tstwcx. %2,%y0\n\tbne- 0b
0:\tlwarx %3,%y0\n\t%q4is %2,%3,%u1\n\tstwcx. %2,%y0\n\tbne- 0b"
[(set_attr "length" "16,16,16")])
(define_insn "*sync_booldi_internal"
[(set (match_operand:DI 2 "gpc_reg_operand" "=&r,&r,&r")
(match_operator:DI 4 "boolean_or_operator"
[(match_operand:DI 0 "memory_operand" "+Z,Z,Z")
(match_operand:DI 1 "logical_operand" "r,K,JF")]))
(set (match_operand:DI 3 "gpc_reg_operand" "=&b,&b,&b") (match_dup 0))
(set (match_dup 0) (unspec:DI [(match_dup 4)] UNSPEC_SYNC_OP))
(clobber (match_scratch:CC 5 "=&x,&x,&x"))]
"TARGET_POWERPC64"
"@
0:\tldarx %3,%y0\n\t%q4 %2,%3,%1\n\tstdcx. %2,%y0\n\tbne- 0b
0:\tldarx %3,%y0\n\t%q4i %2,%3,%b1\n\tstdcx. %2,%y0\n\tbne- 0b
0:\tldarx %3,%y0\n\t%q4is %2,%3,%u1\n\tstdcx. %2,%y0\n\tbne- 0b"
[(set_attr "length" "16,16,16")])
(define_insn "*sync_boolc<mode>_internal"
[(set (match_operand:GPR 2 "gpc_reg_operand" "=&r")
(match_operator:GPR 4 "boolean_operator"
[(not:GPR (match_operand:GPR 0 "memory_operand" "+Z"))
(match_operand:GPR 1 "gpc_reg_operand" "r")]))
(set (match_operand:GPR 3 "gpc_reg_operand" "=&b") (match_dup 0))
(set (match_dup 0) (unspec:GPR [(match_dup 4)] UNSPEC_SYNC_OP))
(clobber (match_scratch:CC 5 "=&x"))]
"TARGET_POWERPC"
"0:\t<larx> %3,%y0\n\t%q4 %2,%1,%3\n\t<stcx> %2,%y0\n\tbne- 0b"
[(set_attr "length" "16")])
(define_insn "*sync_boolc<mode>_internal2"
[(set (match_operand:GPR 2 "gpc_reg_operand" "=&r")
(match_operator:GPR 4 "boolean_operator"
[(not:GPR (match_operand:GPR 1 "gpc_reg_operand" "r"))
(match_operand:GPR 0 "memory_operand" "+Z")]))
(set (match_operand:GPR 3 "gpc_reg_operand" "=&b") (match_dup 0))
(set (match_dup 0) (unspec:GPR [(match_dup 4)] UNSPEC_SYNC_OP))
(clobber (match_scratch:CC 5 "=&x"))]
"TARGET_POWERPC"
"0:\t<larx> %3,%y0\n\t%q4 %2,%3,%1\n\t<stcx> %2,%y0\n\tbne- 0b"
[(set_attr "length" "16")])
(define_insn "*sync_boolcc<mode>_internal"
[(set (match_operand:GPR 2 "gpc_reg_operand" "=&r")
(match_operator:GPR 4 "boolean_operator"
[(not:GPR (match_operand:GPR 0 "memory_operand" "+Z"))
(not:GPR (match_operand:GPR 1 "gpc_reg_operand" "r"))]))
(set (match_operand:GPR 3 "gpc_reg_operand" "=&b") (match_dup 0))
(set (match_dup 0) (unspec:GPR [(match_dup 4)] UNSPEC_SYNC_OP))
(clobber (match_scratch:CC 5 "=&x"))]
"TARGET_POWERPC"
"0:\t<larx> %3,%y0\n\t%q4 %2,%1,%3\n\t<stcx> %2,%y0\n\tbne- 0b"
[(set_attr "length" "16")])
(define_insn "isync"
[(set (mem:BLK (match_scratch 0 "X"))
(unspec:BLK [(mem:BLK (match_scratch 1 "X"))] UNSPEC_ISYNC))]
"TARGET_POWERPC"
"isync")
(define_insn "sync_lock_test_and_set<mode>"
[(set (match_operand:GPR 0 "gpc_reg_operand" "=&r")
(match_operand:GPR 1 "memory_operand" "+Z"))
(set (match_dup 1) (unspec:GPR [(match_operand:GPR 2 "gpc_reg_operand" "r")]
UNSPEC_SYNC_OP))
(clobber (match_scratch:CC 3 "=&x"))
(set (mem:BLK (match_scratch 4 "X"))
(unspec:BLK [(mem:BLK (match_scratch 5 "X"))] UNSPEC_ISYNC))]
"TARGET_POWERPC"
"0:\t<larx> %0,%y1\n\t<stcx> %2,%y1\n\tbne- 0b\n\tisync"
[(set_attr "length" "16")])
(define_expand "sync_lock_release<mode>"
[(use (match_operand:INT 0 "memory_operand"))]
""
"
{
emit_insn (gen_lwsync ());
emit_move_insn (operands[0], CONST0_RTX (<MODE>mode));
DONE;
}")
(define_insn "lwsync"
[(set (mem:BLK (match_scratch 0 "X"))
(unspec:BLK [(mem:BLK (match_scratch 1 "X"))] UNSPEC_LWSYNC))]
""
"lwsync")
(include "altivec.md")
(include "spe.md")

View File

@ -3952,14 +3952,16 @@ operation. Operand 1 is the memory on which the atomic operation is
performed. Operand 2 is the ``old'' value to be compared against the
current contents of the memory location. Operand 3 is the ``new'' value
to store in the memory if the compare succeeds. Operand 0 is the result
of the operation; it should contain the current contents of the memory
after the operation. If the compare succeeds, this should obviously be
a copy of operand 3.
of the operation; it should contain the contents of the memory
before the operation. If the compare succeeds, this should obviously be
a copy of operand 2.
This pattern must show that both operand 0 and operand 1 are modified.
This pattern must issue any memory barrier instructions such that the
pattern as a whole acts as a full barrier.
This pattern must issue any memory barrier instructions such that all
memory operations before the atomic operation occur before the atomic
operation and all memory operations after the atomic operation occur
after the atomic operation.
@cindex @code{sync_compare_and_swap_cc@var{mode}} instruction pattern
@item @samp{sync_compare_and_swap_cc@var{mode}}
@ -3991,8 +3993,10 @@ Operand 1 is the second operand to the binary operator.
The ``nand'' operation is @code{op0 & ~op1}.
This pattern must issue any memory barrier instructions such that the
pattern as a whole acts as a full barrier.
This pattern must issue any memory barrier instructions such that all
memory operations before the atomic operation occur before the atomic
operation and all memory operations after the atomic operation occur
after the atomic operation.
If these patterns are not defined, the operation will be constructed
from a compare-and-swap operation, if defined.
@ -4013,8 +4017,10 @@ Operand 0 is the result value, operand 1 is the memory on which the
atomic operation is performed, and operand 2 is the second operand
to the binary operator.
This pattern must issue any memory barrier instructions such that the
pattern as a whole acts as a full barrier.
This pattern must issue any memory barrier instructions such that all
memory operations before the atomic operation occur before the atomic
operation and all memory operations after the atomic operation occur
after the atomic operation.
If these patterns are not defined, the operation will be constructed
from a compare-and-swap operation, if defined.
@ -4052,7 +4058,8 @@ an atomic test-and-set bit operation. The result operand should contain
The true contents of the memory operand are implementation defined.
This pattern must issue any memory barrier instructions such that the
pattern as a whole acts as an acquire barrier.
pattern as a whole acts as an acquire barrier, that is all memory
operations after the pattern do not occur until the lock is acquired.
If this pattern is not defined, the operation will be constructed from
a compare-and-swap operation, if defined.
@ -4065,7 +4072,8 @@ This pattern, if defined, releases a lock set by
that contains the lock.
This pattern must issue any memory barrier instructions such that the
pattern as a whole acts as a release barrier.
pattern as a whole acts as a release barrier, that is the lock is
released only after all previous memory operations have completed.
If this pattern is not defined, then a @code{memory_barrier} pattern
will be emitted, followed by a store of zero to the memory operand.

View File

@ -1,3 +1,8 @@
2005-04-21 Geoffrey Keating <geoffk@apple.com>
* lib/target-supports.exp (check_effective_target_sync_int_long):
Add powerpc*.
2005-04-21 Richard Sandiford <rsandifo@redhat.com>
* gcc.target/mips/branch-1.c: New test.

View File

@ -883,10 +883,13 @@ proc check_effective_target_sync_int_long { } {
verbose "check_effective_target_sync_int_long: using cached result" 2
} else {
set et_sync_int_long_saved 0
# This is intentionally powerpc but not rs6000, rs6000 doesn't have the
# load-reserved/store-conditional instructions.
if { [istarget ia64-*-*]
|| [istarget i?86-*-*]
|| [istarget x86_64-*-*]
|| [istarget alpha*-*-*] } {
|| [istarget alpha*-*-*]
|| [istarget powerpc*-*-*] } {
set et_sync_int_long_saved 1
}
}