mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-19 08:20:32 +08:00
s390.c (s390_expand_atomic): New function.
2005-12-07 Adrian Straetling <straetling@de.ibm.com> * config/s390/s390.c (s390_expand_atomic): New function. Adjust comment of helper functions. * config/s390/s390-protos.h (s390_expand_atomic): Declare. * config/s390/s390.md ("ATOMIC"): New code macro. ("atomic"): Corresponding new code attribute. ("sync_lock_test_and_set[hq]i", "sync_{new_,old_,}{and,ior,xor,add,sub,nand}[hq]i"): New pattern. From-SVN: r108180
This commit is contained in:
parent
3093f076e1
commit
45d18331f6
@ -1,3 +1,13 @@
|
||||
2005-12-07 Adrian Straetling <straetling@de.ibm.com>
|
||||
|
||||
* config/s390/s390.c (s390_expand_atomic): New function.
|
||||
Adjust comment of helper functions.
|
||||
* config/s390/s390-protos.h (s390_expand_atomic): Declare.
|
||||
* config/s390/s390.md ("ATOMIC"): New code macro.
|
||||
("atomic"): Corresponding new code attribute.
|
||||
("sync_lock_test_and_set[hq]i",
|
||||
"sync_{new_,old_,}{and,ior,xor,add,sub,nand}[hq]i"): New pattern.
|
||||
|
||||
2005-12-07 Adrian Straetling <straetling@de.ibm.com>
|
||||
|
||||
* config/s390/s390.c (s390_expand_mask_and_shift,
|
||||
|
@ -76,6 +76,8 @@ extern void s390_expand_cmpmem (rtx, rtx, rtx, rtx);
|
||||
extern bool s390_expand_addcc (enum rtx_code, rtx, rtx, rtx, rtx, rtx);
|
||||
extern bool s390_expand_insv (rtx, rtx, rtx, rtx);
|
||||
extern void s390_expand_cs_hqi (enum machine_mode, rtx, rtx, rtx, rtx);
|
||||
extern void s390_expand_atomic (enum machine_mode, enum rtx_code,
|
||||
rtx, rtx, rtx, bool);
|
||||
extern rtx s390_return_addr_rtx (int, rtx);
|
||||
extern rtx s390_back_chain_rtx (void);
|
||||
extern rtx s390_emit_call (rtx, rtx, rtx, rtx);
|
||||
|
@ -3972,8 +3972,8 @@ s390_expand_insv (rtx dest, rtx op1, rtx op2, rtx src)
|
||||
return false;
|
||||
}
|
||||
|
||||
/* A subroutine of s390_expand_cs_hqi which returns a register which holds VAL
|
||||
of mode MODE shifted by COUNT bits. */
|
||||
/* A subroutine of s390_expand_cs_hqi and s390_expand_atomic which returns a
|
||||
register that holds VAL of mode MODE shifted by COUNT bits. */
|
||||
|
||||
static inline rtx
|
||||
s390_expand_mask_and_shift (rtx val, enum machine_mode mode, rtx count)
|
||||
@ -3996,10 +3996,10 @@ struct alignment_context
|
||||
bool aligned; /* True if memory is aliged, false else. */
|
||||
};
|
||||
|
||||
/* A subroutine of s390_expand_cs_hqi to initialize the structure AC for
|
||||
transparent simplifying, if the memory alignment is known to be at least
|
||||
32bit. MEM is the memory location for the actual operation and MODE its
|
||||
mode. */
|
||||
/* A subroutine of s390_expand_cs_hqi and s390_expand_atomic to initialize
|
||||
structure AC for transparent simplifying, if the memory alignment is known
|
||||
to be at least 32bit. MEM is the memory location for the actual operation
|
||||
and MODE its mode. */
|
||||
|
||||
static void
|
||||
init_alignment_context (struct alignment_context *ac, rtx mem,
|
||||
@ -4122,6 +4122,97 @@ s390_expand_cs_hqi (enum machine_mode mode, rtx target, rtx mem, rtx cmp, rtx ne
|
||||
NULL_RTX, 1, OPTAB_DIRECT), 1);
|
||||
}
|
||||
|
||||
/* Expand an atomic operation CODE of mode MODE. MEM is the memory location
|
||||
and VAL the value to play with. If AFTER is true then store the the value
|
||||
MEM holds after the operation, if AFTER is false then store the value MEM
|
||||
holds before the operation. If TARGET is zero then discard that value, else
|
||||
store it to TARGET. */
|
||||
|
||||
void
|
||||
s390_expand_atomic (enum machine_mode mode, enum rtx_code code,
|
||||
rtx target, rtx mem, rtx val, bool after)
|
||||
{
|
||||
struct alignment_context ac;
|
||||
rtx cmp;
|
||||
rtx new = gen_reg_rtx (SImode);
|
||||
rtx orig = gen_reg_rtx (SImode);
|
||||
rtx csloop = gen_label_rtx ();
|
||||
|
||||
gcc_assert (!target || register_operand (target, VOIDmode));
|
||||
gcc_assert (MEM_P (mem));
|
||||
|
||||
init_alignment_context (&ac, mem, mode);
|
||||
|
||||
/* Shift val to the correct bit positions.
|
||||
Preserve "icm", but prevent "ex icm". */
|
||||
if (!(ac.aligned && code == SET && MEM_P (val)))
|
||||
val = s390_expand_mask_and_shift (val, mode, ac.shift);
|
||||
|
||||
/* Further preparation insns. */
|
||||
if (code == PLUS || code == MINUS)
|
||||
emit_move_insn (orig, val);
|
||||
else if (code == MULT || code == AND) /* val = "11..1<val>11..1" */
|
||||
val = expand_simple_binop (SImode, XOR, val, ac.modemaski,
|
||||
NULL_RTX, 1, OPTAB_DIRECT);
|
||||
|
||||
/* Load full word. Subsequent loads are performed by CS. */
|
||||
cmp = force_reg (SImode, ac.memsi);
|
||||
|
||||
/* Start CS loop. */
|
||||
emit_label (csloop);
|
||||
emit_move_insn (new, cmp);
|
||||
|
||||
/* Patch new with val at correct position. */
|
||||
switch (code)
|
||||
{
|
||||
case PLUS:
|
||||
case MINUS:
|
||||
val = expand_simple_binop (SImode, code, new, orig,
|
||||
NULL_RTX, 1, OPTAB_DIRECT);
|
||||
val = expand_simple_binop (SImode, AND, val, ac.modemask,
|
||||
NULL_RTX, 1, OPTAB_DIRECT);
|
||||
/* FALLTHRU */
|
||||
case SET:
|
||||
if (ac.aligned && MEM_P (val))
|
||||
store_bit_field (new, GET_MODE_BITSIZE (mode), 0, SImode, val);
|
||||
else
|
||||
{
|
||||
new = expand_simple_binop (SImode, AND, new, ac.modemaski,
|
||||
NULL_RTX, 1, OPTAB_DIRECT);
|
||||
new = expand_simple_binop (SImode, IOR, new, val,
|
||||
NULL_RTX, 1, OPTAB_DIRECT);
|
||||
}
|
||||
break;
|
||||
case AND:
|
||||
case IOR:
|
||||
case XOR:
|
||||
new = expand_simple_binop (SImode, code, new, val,
|
||||
NULL_RTX, 1, OPTAB_DIRECT);
|
||||
break;
|
||||
case MULT: /* NAND */
|
||||
new = expand_simple_binop (SImode, XOR, new, ac.modemask,
|
||||
NULL_RTX, 1, OPTAB_DIRECT);
|
||||
new = expand_simple_binop (SImode, AND, new, val,
|
||||
NULL_RTX, 1, OPTAB_DIRECT);
|
||||
break;
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
}
|
||||
/* Emit compare_and_swap pattern. */
|
||||
emit_insn (gen_sync_compare_and_swap_ccsi (cmp, ac.memsi, cmp, new));
|
||||
|
||||
/* Loop until swapped (unlikely?). */
|
||||
s390_emit_jump (csloop, gen_rtx_fmt_ee (NE, CCZ1mode,
|
||||
gen_rtx_REG (CCZ1mode, CC_REGNUM),
|
||||
const0_rtx));
|
||||
|
||||
/* Return the correct part of the bitfield. */
|
||||
if (target)
|
||||
convert_move (target, expand_simple_binop (SImode, LSHIFTRT,
|
||||
after ? new : cmp, ac.shift,
|
||||
NULL_RTX, 1, OPTAB_DIRECT), 1);
|
||||
}
|
||||
|
||||
/* This is called from dwarf2out.c via TARGET_ASM_OUTPUT_DWARF_DTPREL.
|
||||
We need to emit DTP-relative relocations. */
|
||||
|
||||
|
@ -315,6 +315,11 @@
|
||||
;; the same template.
|
||||
(define_code_macro SHIFT [ashift lshiftrt])
|
||||
|
||||
;; These macros allow to combine most atomic operations.
|
||||
(define_code_macro ATOMIC [and ior xor plus minus mult])
|
||||
(define_code_attr atomic [(and "and") (ior "ior") (xor "xor")
|
||||
(plus "add") (minus "sub") (mult "nand")])
|
||||
|
||||
|
||||
;; In FPR templates, a string like "lt<de>br" will expand to "ltdbr" in DFmode
|
||||
;; and "ltebr" in SFmode.
|
||||
@ -7340,6 +7345,45 @@
|
||||
(set_attr "type" "sem")])
|
||||
|
||||
|
||||
;
|
||||
; Other atomic instruction patterns.
|
||||
;
|
||||
|
||||
(define_expand "sync_lock_test_and_set<mode>"
|
||||
[(match_operand:HQI 0 "register_operand")
|
||||
(match_operand:HQI 1 "memory_operand")
|
||||
(match_operand:HQI 2 "general_operand")]
|
||||
""
|
||||
"s390_expand_atomic (<MODE>mode, SET, operands[0], operands[1],
|
||||
operands[2], false); DONE;")
|
||||
|
||||
(define_expand "sync_<atomic><mode>"
|
||||
[(set (match_operand:HQI 0 "memory_operand")
|
||||
(ATOMIC:HQI (match_dup 0)
|
||||
(match_operand:HQI 1 "general_operand")))]
|
||||
""
|
||||
"s390_expand_atomic (<MODE>mode, <CODE>, NULL_RTX, operands[0],
|
||||
operands[1], false); DONE;")
|
||||
|
||||
(define_expand "sync_old_<atomic><mode>"
|
||||
[(set (match_operand:HQI 0 "register_operand")
|
||||
(match_operand:HQI 1 "memory_operand"))
|
||||
(set (match_dup 1)
|
||||
(ATOMIC:HQI (match_dup 1)
|
||||
(match_operand:HQI 2 "general_operand")))]
|
||||
""
|
||||
"s390_expand_atomic (<MODE>mode, <CODE>, operands[0], operands[1],
|
||||
operands[2], false); DONE;")
|
||||
|
||||
(define_expand "sync_new_<atomic><mode>"
|
||||
[(set (match_operand:HQI 0 "register_operand")
|
||||
(ATOMIC:HQI (match_operand:HQI 1 "memory_operand")
|
||||
(match_operand:HQI 2 "general_operand")))
|
||||
(set (match_dup 1) (ATOMIC:HQI (match_dup 1) (match_dup 2)))]
|
||||
""
|
||||
"s390_expand_atomic (<MODE>mode, <CODE>, operands[0], operands[1],
|
||||
operands[2], true); DONE;")
|
||||
|
||||
;;
|
||||
;;- Miscellaneous instructions.
|
||||
;;
|
||||
|
Loading…
x
Reference in New Issue
Block a user