mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-19 12:21:15 +08:00
alpha.c (alpha_split_atomic_op): New.
* config/alpha/alpha.c (alpha_split_atomic_op): New. (alphaev5_insn_pipe): Add LD_L, ST_C, MB types. (alphaev4_insn_pipe): Likewise. Correct IST and LDSYM pipes. * config/alpha/alpha-protos.h: Update. * config/alpha/alpha.md (UNSPECV_MB, UNSPECV_LL, UNSPECV_SC): New. (UNSPECV_ATOMIC, UNSPECV_CMPXCHG, UNSPECV_XCHG): New. (attr type): Add ld_l, st_c, mb. (andsi_internal, andnotsi3, iorsi_internal, one_cmplsi_internal, iornotsi3, xorsi_internal, xornotsi3): New. * config/alpha/ev4.md (ev4_ld): Add ld_l. (ev4_ist_c, ev4_mb): New. * config/alpha/ev5.md (ev5_st): Add st_c, mb. (ev5_ld_l): New. * config/alpha/ev6.md (ev6_ild): Add ld_l. (ev6_ist): Add st_c. (ev6_mb): New. * config/alpha/sync.md: New file. From-SVN: r98328
This commit is contained in:
parent
46c94db618
commit
0b196b187b
@ -1,3 +1,23 @@
|
||||
2005-04-18 Richard Henderson <rth@redhat.com>
|
||||
|
||||
* config/alpha/alpha.c (alpha_split_atomic_op): New.
|
||||
(alphaev5_insn_pipe): Add LD_L, ST_C, MB types.
|
||||
(alphaev4_insn_pipe): Likewise. Correct IST and LDSYM pipes.
|
||||
* config/alpha/alpha-protos.h: Update.
|
||||
* config/alpha/alpha.md (UNSPECV_MB, UNSPECV_LL, UNSPECV_SC): New.
|
||||
(UNSPECV_ATOMIC, UNSPECV_CMPXCHG, UNSPECV_XCHG): New.
|
||||
(attr type): Add ld_l, st_c, mb.
|
||||
(andsi_internal, andnotsi3, iorsi_internal, one_cmplsi_internal,
|
||||
iornotsi3, xorsi_internal, xornotsi3): New.
|
||||
* config/alpha/ev4.md (ev4_ld): Add ld_l.
|
||||
(ev4_ist_c, ev4_mb): New.
|
||||
* config/alpha/ev5.md (ev5_st): Add st_c, mb.
|
||||
(ev5_ld_l): New.
|
||||
* config/alpha/ev6.md (ev6_ild): Add ld_l.
|
||||
(ev6_ist): Add st_c.
|
||||
(ev6_mb): New.
|
||||
* config/alpha/sync.md: New file.
|
||||
|
||||
2005-04-18 Richard Henderson <rth@redhat.com>
|
||||
|
||||
* builtins.c (expand_builtin_sync_operation): Fold nand to and
|
||||
|
@ -101,6 +101,7 @@ extern rtx alpha_emit_setcc (enum rtx_code);
|
||||
extern int alpha_split_conditional_move (enum rtx_code, rtx, rtx, rtx, rtx);
|
||||
extern void alpha_emit_xfloating_arith (enum rtx_code, rtx[]);
|
||||
extern void alpha_emit_xfloating_cvt (enum rtx_code, rtx[]);
|
||||
extern void alpha_split_atomic_op (enum rtx_code, rtx, rtx, rtx, rtx, rtx);
|
||||
#endif
|
||||
|
||||
extern rtx alpha_need_linkage (const char *, int);
|
||||
|
@ -4469,6 +4469,64 @@ alpha_expand_builtin_vector_binop (rtx (*gen) (rtx, rtx, rtx),
|
||||
|
||||
emit_insn ((*gen) (op0, op1, op2));
|
||||
}
|
||||
|
||||
/* Expand an an atomic fetch-and-operate pattern. CODE is the binary operation
|
||||
to perform. MEM is the memory on which to operate. VAL is the second
|
||||
operand of the binary operator. BEFORE and AFTER are optional locations to
|
||||
return the value of MEM either before of after the operation. SCRATCH is
|
||||
a scratch register. */
|
||||
|
||||
void
|
||||
alpha_split_atomic_op (enum rtx_code code, rtx mem, rtx val,
|
||||
rtx before, rtx after, rtx scratch)
|
||||
{
|
||||
enum machine_mode mode = GET_MODE (mem);
|
||||
rtx label, cond, x;
|
||||
rtx very_unlikely = GEN_INT (REG_BR_PROB_BASE / 100 - 1);
|
||||
|
||||
emit_insn (gen_memory_barrier ());
|
||||
|
||||
label = gen_label_rtx ();
|
||||
emit_label (label);
|
||||
label = gen_rtx_LABEL_REF (DImode, label);
|
||||
|
||||
if (before == NULL)
|
||||
before = scratch;
|
||||
|
||||
if (mode == SImode)
|
||||
emit_insn (gen_load_locked_si (before, mem));
|
||||
else if (mode == DImode)
|
||||
emit_insn (gen_load_locked_di (before, mem));
|
||||
else
|
||||
gcc_unreachable ();
|
||||
|
||||
if (code == NOT)
|
||||
{
|
||||
x = gen_rtx_NOT (mode, val);
|
||||
x = gen_rtx_AND (mode, x, before);
|
||||
}
|
||||
else
|
||||
x = gen_rtx_fmt_ee (code, mode, before, val);
|
||||
|
||||
emit_insn (gen_rtx_SET (VOIDmode, scratch, x));
|
||||
if (after)
|
||||
emit_insn (gen_rtx_SET (VOIDmode, after, copy_rtx (x)));
|
||||
|
||||
cond = gen_rtx_REG (DImode, REGNO (scratch));
|
||||
if (mode == SImode)
|
||||
emit_insn (gen_store_conditional_si (cond, mem, scratch));
|
||||
else if (mode == DImode)
|
||||
emit_insn (gen_store_conditional_di (cond, mem, scratch));
|
||||
else
|
||||
gcc_unreachable ();
|
||||
|
||||
x = gen_rtx_EQ (DImode, cond, const0_rtx);
|
||||
x = gen_rtx_IF_THEN_ELSE (VOIDmode, x, label, pc_rtx);
|
||||
x = emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, x));
|
||||
REG_NOTES (x) = gen_rtx_EXPR_LIST (REG_BR_PROB, very_unlikely, NULL_RTX);
|
||||
|
||||
emit_insn (gen_memory_barrier ());
|
||||
}
|
||||
|
||||
/* Adjust the cost of a scheduling dependency. Return the new cost of
|
||||
a dependency LINK or INSN on DEP_INSN. COST is the current cost. */
|
||||
@ -8479,21 +8537,22 @@ alphaev4_insn_pipe (rtx insn)
|
||||
switch (get_attr_type (insn))
|
||||
{
|
||||
case TYPE_ILD:
|
||||
case TYPE_LDSYM:
|
||||
case TYPE_FLD:
|
||||
case TYPE_LD_L:
|
||||
return EV4_IBX;
|
||||
|
||||
case TYPE_LDSYM:
|
||||
case TYPE_IADD:
|
||||
case TYPE_ILOG:
|
||||
case TYPE_ICMOV:
|
||||
case TYPE_ICMP:
|
||||
case TYPE_IST:
|
||||
case TYPE_FST:
|
||||
case TYPE_SHIFT:
|
||||
case TYPE_IMUL:
|
||||
case TYPE_FBR:
|
||||
return EV4_IB0;
|
||||
|
||||
case TYPE_IST:
|
||||
case TYPE_MISC:
|
||||
case TYPE_IBR:
|
||||
case TYPE_JSR:
|
||||
@ -8503,6 +8562,8 @@ alphaev4_insn_pipe (rtx insn)
|
||||
case TYPE_FADD:
|
||||
case TYPE_FDIV:
|
||||
case TYPE_FMUL:
|
||||
case TYPE_ST_C:
|
||||
case TYPE_MB:
|
||||
return EV4_IB1;
|
||||
|
||||
default:
|
||||
@ -8535,6 +8596,9 @@ alphaev5_insn_pipe (rtx insn)
|
||||
case TYPE_IMUL:
|
||||
case TYPE_MISC:
|
||||
case TYPE_MVI:
|
||||
case TYPE_LD_L:
|
||||
case TYPE_ST_C:
|
||||
case TYPE_MB:
|
||||
return EV5_E0;
|
||||
|
||||
case TYPE_IBR:
|
||||
|
@ -76,6 +76,12 @@
|
||||
(UNSPECV_SET_TP 12)
|
||||
(UNSPECV_RPCC 13)
|
||||
(UNSPECV_SETJMPR_ER 14) ; builtin_setjmp_receiver fragment
|
||||
(UNSPECV_MB 15)
|
||||
(UNSPECV_LL 16) ; load-locked
|
||||
(UNSPECV_SC 17) ; store-conditional
|
||||
(UNSPECV_ATOMIC 18)
|
||||
(UNSPECV_CMPXCHG 19)
|
||||
(UNSPECV_XCHG 20)
|
||||
])
|
||||
|
||||
;; Where necessary, the suffixes _le and _be are used to distinguish between
|
||||
@ -97,7 +103,8 @@
|
||||
|
||||
(define_attr "type"
|
||||
"ild,fld,ldsym,ist,fst,ibr,callpal,fbr,jsr,iadd,ilog,shift,icmov,fcmov,
|
||||
icmp,imul,fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi,none"
|
||||
icmp,imul,fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,mb,ld_l,st_c,
|
||||
multi,none"
|
||||
(const_string "iadd"))
|
||||
|
||||
;; Describe a user's asm statement.
|
||||
@ -1100,7 +1107,20 @@
|
||||
[(set_attr "type" "jsr")
|
||||
(set_attr "length" "8")])
|
||||
|
||||
;; Next are the basic logical operations. These only exist in DImode.
|
||||
;; Next are the basic logical operations. We only expose the DImode operations
|
||||
;; to the rtl expanders, but SImode versions exist for combine as well as for
|
||||
;; the atomic operation splitters.
|
||||
|
||||
(define_insn "*andsi_internal"
|
||||
[(set (match_operand:SI 0 "register_operand" "=r,r,r")
|
||||
(and:SI (match_operand:SI 1 "reg_or_0_operand" "%rJ,rJ,rJ")
|
||||
(match_operand:SI 2 "and_operand" "rI,N,MH")))]
|
||||
""
|
||||
"@
|
||||
and %r1,%2,%0
|
||||
bic %r1,%N2,%0
|
||||
zapnot %r1,%m2,%0"
|
||||
[(set_attr "type" "ilog,ilog,shift")])
|
||||
|
||||
(define_insn "anddi3"
|
||||
[(set (match_operand:DI 0 "register_operand" "=r,r,r")
|
||||
@ -1275,6 +1295,14 @@
|
||||
"zapnot %1,15,%0"
|
||||
[(set_attr "type" "shift")])
|
||||
|
||||
(define_insn "*andnotsi3"
|
||||
[(set (match_operand:SI 0 "register_operand" "=r")
|
||||
(and:SI (not:SI (match_operand:SI 1 "reg_or_8bit_operand" "rI"))
|
||||
(match_operand:SI 2 "reg_or_0_operand" "rJ")))]
|
||||
""
|
||||
"bic %r2,%1,%0"
|
||||
[(set_attr "type" "ilog")])
|
||||
|
||||
(define_insn "andnotdi3"
|
||||
[(set (match_operand:DI 0 "register_operand" "=r")
|
||||
(and:DI (not:DI (match_operand:DI 1 "reg_or_8bit_operand" "rI"))
|
||||
@ -1283,6 +1311,16 @@
|
||||
"bic %r2,%1,%0"
|
||||
[(set_attr "type" "ilog")])
|
||||
|
||||
(define_insn "*iorsi_internal"
|
||||
[(set (match_operand:SI 0 "register_operand" "=r,r")
|
||||
(ior:SI (match_operand:SI 1 "reg_or_0_operand" "%rJ,rJ")
|
||||
(match_operand:SI 2 "or_operand" "rI,N")))]
|
||||
""
|
||||
"@
|
||||
bis %r1,%2,%0
|
||||
ornot %r1,%N2,%0"
|
||||
[(set_attr "type" "ilog")])
|
||||
|
||||
(define_insn "iordi3"
|
||||
[(set (match_operand:DI 0 "register_operand" "=r,r")
|
||||
(ior:DI (match_operand:DI 1 "reg_or_0_operand" "%rJ,rJ")
|
||||
@ -1293,6 +1331,13 @@
|
||||
ornot %r1,%N2,%0"
|
||||
[(set_attr "type" "ilog")])
|
||||
|
||||
(define_insn "*one_cmplsi_internal"
|
||||
[(set (match_operand:SI 0 "register_operand" "=r")
|
||||
(not:SI (match_operand:SI 1 "reg_or_8bit_operand" "rI")))]
|
||||
""
|
||||
"ornot $31,%1,%0"
|
||||
[(set_attr "type" "ilog")])
|
||||
|
||||
(define_insn "one_cmpldi2"
|
||||
[(set (match_operand:DI 0 "register_operand" "=r")
|
||||
(not:DI (match_operand:DI 1 "reg_or_8bit_operand" "rI")))]
|
||||
@ -1300,7 +1345,15 @@
|
||||
"ornot $31,%1,%0"
|
||||
[(set_attr "type" "ilog")])
|
||||
|
||||
(define_insn "*iornot"
|
||||
(define_insn "*iornotsi3"
|
||||
[(set (match_operand:SI 0 "register_operand" "=r")
|
||||
(ior:SI (not:SI (match_operand:SI 1 "reg_or_8bit_operand" "rI"))
|
||||
(match_operand:SI 2 "reg_or_0_operand" "rJ")))]
|
||||
""
|
||||
"ornot %r2,%1,%0"
|
||||
[(set_attr "type" "ilog")])
|
||||
|
||||
(define_insn "*iornotdi3"
|
||||
[(set (match_operand:DI 0 "register_operand" "=r")
|
||||
(ior:DI (not:DI (match_operand:DI 1 "reg_or_8bit_operand" "rI"))
|
||||
(match_operand:DI 2 "reg_or_0_operand" "rJ")))]
|
||||
@ -1308,6 +1361,16 @@
|
||||
"ornot %r2,%1,%0"
|
||||
[(set_attr "type" "ilog")])
|
||||
|
||||
(define_insn "*xorsi_internal"
|
||||
[(set (match_operand:SI 0 "register_operand" "=r,r")
|
||||
(xor:SI (match_operand:SI 1 "reg_or_0_operand" "%rJ,rJ")
|
||||
(match_operand:SI 2 "or_operand" "rI,N")))]
|
||||
""
|
||||
"@
|
||||
xor %r1,%2,%0
|
||||
eqv %r1,%N2,%0"
|
||||
[(set_attr "type" "ilog")])
|
||||
|
||||
(define_insn "xordi3"
|
||||
[(set (match_operand:DI 0 "register_operand" "=r,r")
|
||||
(xor:DI (match_operand:DI 1 "reg_or_0_operand" "%rJ,rJ")
|
||||
@ -1318,7 +1381,15 @@
|
||||
eqv %r1,%N2,%0"
|
||||
[(set_attr "type" "ilog")])
|
||||
|
||||
(define_insn "*xornot"
|
||||
(define_insn "*xornotsi3"
|
||||
[(set (match_operand:SI 0 "register_operand" "=r")
|
||||
(not:SI (xor:SI (match_operand:SI 1 "register_operand" "%rJ")
|
||||
(match_operand:SI 2 "register_operand" "rI"))))]
|
||||
""
|
||||
"eqv %r1,%2,%0"
|
||||
[(set_attr "type" "ilog")])
|
||||
|
||||
(define_insn "*xornotdi3"
|
||||
[(set (match_operand:DI 0 "register_operand" "=r")
|
||||
(not:DI (xor:DI (match_operand:DI 1 "register_operand" "%rJ")
|
||||
(match_operand:DI 2 "register_operand" "rI"))))]
|
||||
@ -7705,6 +7776,8 @@
|
||||
"unpkbw %r1,%0"
|
||||
[(set_attr "type" "mvi")])
|
||||
|
||||
(include "sync.md")
|
||||
|
||||
;; The call patterns are at the end of the file because their
|
||||
;; wildcard operand0 interferes with nice recognition.
|
||||
|
||||
|
@ -39,7 +39,7 @@
|
||||
; in user-specified memory latency, so return 1 here.
|
||||
(define_insn_reservation "ev4_ld" 1
|
||||
(and (eq_attr "tune" "ev4")
|
||||
(eq_attr "type" "ild,fld,ldsym"))
|
||||
(eq_attr "type" "ild,fld,ldsym,ld_l"))
|
||||
"ev4_ib01+ev4_abox")
|
||||
|
||||
; Stores can issue before the data (but not address) is ready.
|
||||
@ -48,11 +48,26 @@
|
||||
(eq_attr "type" "ist"))
|
||||
"ev4_ib1+ev4_abox")
|
||||
|
||||
; ??? Separate from ev4_ist because store_data_bypass_p can't handle
|
||||
; the patterns with multiple sets, like store-conditional.
|
||||
(define_insn_reservation "ev4_ist_c" 1
|
||||
(and (eq_attr "tune" "ev4")
|
||||
(eq_attr "type" "st_c"))
|
||||
"ev4_ib1+ev4_abox")
|
||||
|
||||
(define_insn_reservation "ev4_fst" 1
|
||||
(and (eq_attr "tune" "ev4")
|
||||
(eq_attr "type" "fst"))
|
||||
"ev4_ib0+ev4_abox")
|
||||
|
||||
; Memory barrier blocks ABOX insns until it's acknowledged by the external
|
||||
; memory bus. This may be *quite* slow. Setting this to 4 cycles gets
|
||||
; about all the benefit without making the DFA too large.
|
||||
(define_insn_reservation "ev4_mb" 4
|
||||
(and (eq_attr "tune" "ev4")
|
||||
(eq_attr "type" "mb"))
|
||||
"ev4_ib1+ev4_abox,ev4_abox*3")
|
||||
|
||||
; Branches have no delay cost, but do tie up the unit for two cycles.
|
||||
(define_insn_reservation "ev4_ibr" 2
|
||||
(and (eq_attr "tune" "ev4")
|
||||
|
@ -43,7 +43,7 @@
|
||||
|
||||
(define_insn_reservation "ev5_st" 1
|
||||
(and (eq_attr "tune" "ev5")
|
||||
(eq_attr "type" "ist,fst"))
|
||||
(eq_attr "type" "ist,fst,st_c,mb"))
|
||||
"ev5_e0+ev5_st")
|
||||
|
||||
; Loads from L0 complete in two cycles. adjust_cost still factors
|
||||
@ -53,6 +53,11 @@
|
||||
(eq_attr "type" "ild,fld,ldsym"))
|
||||
"ev5_e01+ev5_ld")
|
||||
|
||||
(define_insn_reservation "ev5_ld_l" 1
|
||||
(and (eq_attr "tune" "ev5")
|
||||
(eq_attr "type" "ld_l"))
|
||||
"ev5_e0+ev5_ld")
|
||||
|
||||
; Integer branches slot only to E1.
|
||||
(define_insn_reservation "ev5_ibr" 1
|
||||
(and (eq_attr "tune" "ev5")
|
||||
@ -129,7 +134,7 @@
|
||||
; Model this instead with increased latency on the input instruction.
|
||||
|
||||
(define_bypass 3
|
||||
"ev5_ld,ev5_shift,ev5_mvi,ev5_cmov,ev5_iadd,ev5_ilogcmp"
|
||||
"ev5_ld,ev5_ld_l,ev5_shift,ev5_mvi,ev5_cmov,ev5_iadd,ev5_ilogcmp"
|
||||
"ev5_imull,ev5_imulq,ev5_imulh")
|
||||
|
||||
(define_bypass 9 "ev5_imull" "ev5_imull,ev5_imulq,ev5_imulh")
|
||||
|
@ -53,14 +53,19 @@
|
||||
; adjust_cost still factors in user-specified memory latency, so return 1 here.
|
||||
(define_insn_reservation "ev6_ild" 1
|
||||
(and (eq_attr "tune" "ev6")
|
||||
(eq_attr "type" "ild,ldsym"))
|
||||
(eq_attr "type" "ild,ldsym,ld_l"))
|
||||
"ev6_l")
|
||||
|
||||
(define_insn_reservation "ev6_ist" 1
|
||||
(and (eq_attr "tune" "ev6")
|
||||
(eq_attr "type" "ist"))
|
||||
(eq_attr "type" "ist,st_c"))
|
||||
"ev6_l")
|
||||
|
||||
(define_insn_reservation "ev6_mb" 1
|
||||
(and (eq_attr "tune" "ev6")
|
||||
(eq_attr "type" "mb"))
|
||||
"ev6_l1")
|
||||
|
||||
; FP loads take at least 4 clocks. adjust_cost still factors
|
||||
; in user-specified memory latency, so return 2 here.
|
||||
(define_insn_reservation "ev6_fld" 2
|
||||
|
319
gcc/config/alpha/sync.md
Normal file
319
gcc/config/alpha/sync.md
Normal file
@ -0,0 +1,319 @@
|
||||
;; GCC machine description for Alpha synchronization instructions.
|
||||
;; Copyright (C) 2005
|
||||
;; Free Software Foundation, Inc.
|
||||
;;
|
||||
;; This file is part of GCC.
|
||||
;;
|
||||
;; GCC is free software; you can redistribute it and/or modify
|
||||
;; it under the terms of the GNU General Public License as published by
|
||||
;; the Free Software Foundation; either version 2, or (at your option)
|
||||
;; any later version.
|
||||
;;
|
||||
;; GCC is distributed in the hope that it will be useful,
|
||||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;; GNU General Public License for more details.
|
||||
;;
|
||||
;; You should have received a copy of the GNU General Public License
|
||||
;; along with GCC; see the file COPYING. If not, write to
|
||||
;; the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
;; Boston, MA 02111-1307, USA.
|
||||
|
||||
(define_mode_macro I48MODE [SI DI])
|
||||
(define_mode_attr modesuffix [(SI "l") (DI "q")])
|
||||
|
||||
(define_code_macro FETCHOP [plus minus ior xor and])
|
||||
(define_code_attr fetchop_name
|
||||
[(plus "add") (minus "sub") (ior "ior") (xor "xor") (and "and")])
|
||||
(define_code_attr fetchop_pred
|
||||
[(plus "add_operand") (minus "reg_or_8bit_operand")
|
||||
(ior "or_operand") (xor "or_operand") (and "and_operand")])
|
||||
(define_code_attr fetchop_constr
|
||||
[(plus "rKL") (minus "rI") (ior "rIN") (xor "rIN") (and "riNHM")])
|
||||
|
||||
|
||||
(define_expand "memory_barrier"
|
||||
[(set (mem:BLK (match_dup 0))
|
||||
(unspec_volatile:BLK [(mem:BLK (match_dup 0))] UNSPECV_MB))]
|
||||
""
|
||||
{
|
||||
operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (DImode));
|
||||
MEM_VOLATILE_P (operands[0]) = 1;
|
||||
})
|
||||
|
||||
(define_insn "*mb_internal"
|
||||
[(set (match_operand:BLK 0 "" "")
|
||||
(unspec_volatile:BLK [(match_operand:BLK 1 "" "")] UNSPECV_MB))]
|
||||
""
|
||||
"mb"
|
||||
[(set_attr "type" "mb")])
|
||||
|
||||
(define_insn "load_locked_<mode>"
|
||||
[(set (match_operand:I48MODE 0 "register_operand" "=r")
|
||||
(unspec_volatile:I48MODE
|
||||
[(match_operand:I48MODE 1 "memory_operand" "m")]
|
||||
UNSPECV_LL))]
|
||||
""
|
||||
"ld<modesuffix>_l %0,%1"
|
||||
[(set_attr "type" "ld_l")])
|
||||
|
||||
(define_insn "store_conditional_<mode>"
|
||||
[(set (match_operand:DI 0 "register_operand" "=r")
|
||||
(unspec_volatile:DI [(const_int 0)] UNSPECV_SC))
|
||||
(set (match_operand:I48MODE 1 "memory_operand" "=m")
|
||||
(match_operand:I48MODE 2 "reg_or_0_operand" "0"))]
|
||||
""
|
||||
"st<modesuffix>_c %0,%1"
|
||||
[(set_attr "type" "st_c")])
|
||||
|
||||
;; The Alpha Architecture Handbook says that it is UNPREDICTABLE whether
|
||||
;; the lock is cleared by a TAKEN branch. If we were to honor that, it
|
||||
;; would mean that we could not expand a ll/sc sequence until after the
|
||||
;; final basic-block reordering pass. Fortunately, it appears that no
|
||||
;; Alpha implementation ever built actually clears the lock on branches,
|
||||
;; taken or not.
|
||||
|
||||
(define_insn_and_split "sync_<fetchop_name><mode>"
|
||||
[(set (match_operand:I48MODE 0 "memory_operand" "+m")
|
||||
(unspec_volatile:I48MODE
|
||||
[(FETCHOP:I48MODE (match_dup 0)
|
||||
(match_operand:I48MODE 1 "<fetchop_pred>" "<fetchop_constr>"))]
|
||||
UNSPECV_ATOMIC))
|
||||
(clobber (match_scratch:I48MODE 2 "=&r"))]
|
||||
""
|
||||
"#"
|
||||
"reload_completed"
|
||||
[(const_int 0)]
|
||||
{
|
||||
alpha_split_atomic_op (<CODE>, operands[0], operands[1],
|
||||
NULL, NULL, operands[2]);
|
||||
DONE;
|
||||
}
|
||||
[(set_attr "type" "multi")])
|
||||
|
||||
(define_insn_and_split "sync_nand<mode>"
|
||||
[(set (match_operand:I48MODE 0 "memory_operand" "+m")
|
||||
(unspec_volatile:I48MODE
|
||||
[(and:I48MODE
|
||||
(not:I48MODE
|
||||
(match_operand:I48MODE 1 "reg_or_8bit_operand" "rI"))
|
||||
(match_dup 0))]
|
||||
UNSPECV_ATOMIC))
|
||||
(clobber (match_scratch:I48MODE 2 "=&r"))]
|
||||
""
|
||||
"#"
|
||||
"reload_completed"
|
||||
[(const_int 0)]
|
||||
{
|
||||
alpha_split_atomic_op (NOT, operands[0], operands[1],
|
||||
NULL, NULL, operands[2]);
|
||||
DONE;
|
||||
}
|
||||
[(set_attr "type" "multi")])
|
||||
|
||||
(define_insn_and_split "sync_old_<fetchop_name><mode>"
|
||||
[(set (match_operand:I48MODE 0 "register_operand" "=&r")
|
||||
(match_operand:I48MODE 1 "memory_operand" "+m"))
|
||||
(set (match_dup 1)
|
||||
(unspec_volatile:I48MODE
|
||||
[(FETCHOP:I48MODE (match_dup 1)
|
||||
(match_operand:I48MODE 2 "<fetchop_pred>" "<fetchop_constr>"))]
|
||||
UNSPECV_ATOMIC))
|
||||
(clobber (match_scratch:I48MODE 3 "=&r"))]
|
||||
""
|
||||
"#"
|
||||
"reload_completed"
|
||||
[(const_int 0)]
|
||||
{
|
||||
alpha_split_atomic_op (<CODE>, operands[1], operands[2],
|
||||
operands[0], NULL, operands[3]);
|
||||
DONE;
|
||||
}
|
||||
[(set_attr "type" "multi")])
|
||||
|
||||
(define_insn_and_split "sync_old_nand<mode>"
|
||||
[(set (match_operand:I48MODE 0 "register_operand" "=&r")
|
||||
(match_operand:I48MODE 1 "memory_operand" "+m"))
|
||||
(set (match_dup 1)
|
||||
(unspec_volatile:I48MODE
|
||||
[(and:I48MODE
|
||||
(not:I48MODE
|
||||
(match_operand:I48MODE 2 "reg_or_8bit_operand" "rI"))
|
||||
(match_dup 1))]
|
||||
UNSPECV_ATOMIC))
|
||||
(clobber (match_scratch:I48MODE 3 "=&r"))]
|
||||
""
|
||||
"#"
|
||||
"reload_completed"
|
||||
[(const_int 0)]
|
||||
{
|
||||
alpha_split_atomic_op (NOT, operands[1], operands[2],
|
||||
operands[0], NULL, operands[3]);
|
||||
DONE;
|
||||
}
|
||||
[(set_attr "type" "multi")])
|
||||
|
||||
(define_insn_and_split "sync_new_<fetchop_name><mode>"
|
||||
[(set (match_operand:I48MODE 0 "register_operand" "=&r")
|
||||
(FETCHOP:I48MODE
|
||||
(match_operand:I48MODE 1 "memory_operand" "+m")
|
||||
(match_operand:I48MODE 2 "<fetchop_pred>" "<fetchop_constr>")))
|
||||
(set (match_dup 1)
|
||||
(unspec_volatile:I48MODE
|
||||
[(FETCHOP:I48MODE (match_dup 1) (match_dup 2))]
|
||||
UNSPECV_ATOMIC))
|
||||
(clobber (match_scratch:I48MODE 3 "=&r"))]
|
||||
""
|
||||
"#"
|
||||
"reload_completed"
|
||||
[(const_int 0)]
|
||||
{
|
||||
alpha_split_atomic_op (<CODE>, operands[1], operands[2],
|
||||
NULL, operands[0], operands[3]);
|
||||
DONE;
|
||||
}
|
||||
[(set_attr "type" "multi")])
|
||||
|
||||
(define_insn_and_split "sync_new_nand<mode>"
|
||||
[(set (match_operand:I48MODE 0 "register_operand" "=&r")
|
||||
(and:I48MODE
|
||||
(not:I48MODE
|
||||
(match_operand:I48MODE 2 "reg_or_8bit_operand" "rI"))
|
||||
(match_operand:I48MODE 1 "memory_operand" "+m")))
|
||||
(set (match_dup 1)
|
||||
(unspec_volatile:I48MODE
|
||||
[(and:I48MODE (not:I48MODE (match_dup 2)) (match_dup 1))]
|
||||
UNSPECV_ATOMIC))
|
||||
(clobber (match_scratch:I48MODE 3 "=&r"))]
|
||||
""
|
||||
"#"
|
||||
"reload_completed"
|
||||
[(const_int 0)]
|
||||
{
|
||||
alpha_split_atomic_op (NOT, operands[1], operands[2],
|
||||
NULL, operands[0], operands[3]);
|
||||
DONE;
|
||||
}
|
||||
[(set_attr "type" "multi")])
|
||||
|
||||
(define_expand "sync_compare_and_swap<mode>"
|
||||
[(parallel
|
||||
[(set (match_operand:I48MODE 0 "register_operand" "")
|
||||
(match_operand:I48MODE 1 "memory_operand" ""))
|
||||
(set (match_dup 1)
|
||||
(unspec_volatile:I48MODE
|
||||
[(match_operand:I48MODE 2 "reg_or_8bit_operand" "")
|
||||
(match_operand:I48MODE 3 "add_operand" "rKL")]
|
||||
UNSPECV_CMPXCHG))
|
||||
(clobber (match_scratch:I48MODE 4 "=&r"))])]
|
||||
""
|
||||
{
|
||||
if (<MODE>mode == SImode)
|
||||
operands[2] = convert_modes (DImode, SImode, operands[2], 0);
|
||||
})
|
||||
|
||||
(define_insn_and_split "*sync_compare_and_swap<mode>"
|
||||
[(set (match_operand:I48MODE 0 "register_operand" "=&r")
|
||||
(match_operand:I48MODE 1 "memory_operand" "+m"))
|
||||
(set (match_dup 1)
|
||||
(unspec_volatile:I48MODE
|
||||
[(match_operand:DI 2 "reg_or_8bit_operand" "rI")
|
||||
(match_operand:I48MODE 3 "add_operand" "rKL")]
|
||||
UNSPECV_CMPXCHG))
|
||||
(clobber (match_scratch:I48MODE 4 "=&r"))]
|
||||
""
|
||||
"#"
|
||||
"reload_completed"
|
||||
[(const_int 0)]
|
||||
{
|
||||
rtx retval, mem, oldval, newval, scratch;
|
||||
rtx cond, label1, label2, x;
|
||||
rtx very_unlikely = GEN_INT (REG_BR_PROB_BASE / 100 - 1);
|
||||
|
||||
retval = operands[0];
|
||||
mem = operands[1];
|
||||
oldval = operands[2];
|
||||
newval = operands[3];
|
||||
scratch = operands[4];
|
||||
cond = gen_lowpart (DImode, scratch);
|
||||
|
||||
emit_insn (gen_memory_barrier ());
|
||||
|
||||
label1 = gen_rtx_LABEL_REF (DImode, gen_label_rtx ());
|
||||
label2 = gen_rtx_LABEL_REF (DImode, gen_label_rtx ());
|
||||
emit_label (XEXP (label1, 0));
|
||||
|
||||
emit_insn (gen_load_locked_<mode> (retval, mem));
|
||||
|
||||
x = gen_lowpart (DImode, retval);
|
||||
x = gen_rtx_EQ (DImode, x, oldval);
|
||||
if (oldval != const0_rtx)
|
||||
{
|
||||
emit_insn (gen_rtx_SET (VOIDmode, cond, x));
|
||||
x = gen_rtx_EQ (DImode, cond, const0_rtx);
|
||||
}
|
||||
x = gen_rtx_IF_THEN_ELSE (VOIDmode, x, label2, pc_rtx);
|
||||
x = emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, x));
|
||||
REG_NOTES (x) = gen_rtx_EXPR_LIST (REG_BR_PROB, very_unlikely, NULL_RTX);
|
||||
|
||||
emit_move_insn (scratch, newval);
|
||||
emit_move_insn (retval, newval);
|
||||
|
||||
emit_insn (gen_store_conditional_<mode> (cond, mem, scratch));
|
||||
|
||||
x = gen_rtx_EQ (DImode, cond, const0_rtx);
|
||||
x = gen_rtx_IF_THEN_ELSE (VOIDmode, x, label1, pc_rtx);
|
||||
x = emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, x));
|
||||
REG_NOTES (x) = gen_rtx_EXPR_LIST (REG_BR_PROB, very_unlikely, NULL_RTX);
|
||||
|
||||
emit_label (XEXP (label2, 0));
|
||||
emit_insn (gen_memory_barrier ());
|
||||
DONE;
|
||||
}
|
||||
[(set_attr "type" "multi")])
|
||||
|
||||
(define_insn_and_split "sync_lock_test_and_set<mode>"
|
||||
[(set (match_operand:I48MODE 0 "register_operand" "=&r")
|
||||
(match_operand:I48MODE 1 "memory_operand" "+m"))
|
||||
(set (match_dup 1)
|
||||
(unspec_volatile:I48MODE
|
||||
[(match_operand:I48MODE 2 "add_operand" "rKL")]
|
||||
UNSPECV_XCHG))
|
||||
(clobber (match_scratch:I48MODE 3 "=&r"))]
|
||||
""
|
||||
"#"
|
||||
"reload_completed"
|
||||
[(const_int 0)]
|
||||
{
|
||||
rtx retval, mem, val, scratch;
|
||||
rtx cond, label1, label2, x;
|
||||
rtx very_unlikely = GEN_INT (REG_BR_PROB_BASE / 100 - 1);
|
||||
|
||||
retval = operands[0];
|
||||
mem = operands[1];
|
||||
val = operands[2];
|
||||
scratch = operands[3];
|
||||
cond = gen_lowpart (DImode, scratch);
|
||||
|
||||
emit_insn (gen_memory_barrier ());
|
||||
|
||||
label1 = gen_rtx_LABEL_REF (DImode, gen_label_rtx ());
|
||||
label2 = gen_rtx_LABEL_REF (DImode, gen_label_rtx ());
|
||||
emit_label (XEXP (label1, 0));
|
||||
|
||||
emit_insn (gen_load_locked_<mode> (retval, mem));
|
||||
|
||||
emit_move_insn (scratch, val);
|
||||
|
||||
emit_insn (gen_store_conditional_<mode> (cond, mem, scratch));
|
||||
|
||||
x = gen_rtx_EQ (DImode, cond, const0_rtx);
|
||||
x = gen_rtx_IF_THEN_ELSE (VOIDmode, x, label1, pc_rtx);
|
||||
x = emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, x));
|
||||
REG_NOTES (x) = gen_rtx_EXPR_LIST (REG_BR_PROB, very_unlikely, NULL_RTX);
|
||||
|
||||
emit_label (XEXP (label2, 0));
|
||||
emit_insn (gen_memory_barrier ());
|
||||
DONE;
|
||||
}
|
||||
[(set_attr "type" "multi")])
|
Loading…
x
Reference in New Issue
Block a user