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:
parent
8fd5bcbe95
commit
915167f5a5
@ -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'.
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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")
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user