diff options
author | ramana <ramana@138bc75d-0d04-0410-961f-82ee72b054a4> | 2010-08-18 08:25:33 +0000 |
---|---|---|
committer | ramana <ramana@138bc75d-0d04-0410-961f-82ee72b054a4> | 2010-08-18 08:25:33 +0000 |
commit | 06df6b178d3f0777243244b847004e5c1292e3f0 (patch) | |
tree | abb90a18a297a681918852c397794998d5918643 /gcc/config/arm/sync.md | |
parent | 2cda520abcf9bcadf20415fb5566b9030495aa71 (diff) | |
download | gcc-06df6b178d3f0777243244b847004e5c1292e3f0.tar.gz |
For Marcus - Implement sync primitives inline for ARM.
2010-08-18 Marcus Shawcroft <marcus.shawcroft@arm.com>
* config/arm/arm-protos.h (arm_expand_sync): New.
(arm_output_memory_barrier, arm_output_sync_insn): New.
(arm_sync_loop_insns): New.
* config/arm/arm.c (FL_ARCH7): New.
(FL_FOR_ARCH7): Include FL_ARCH7.
(arm_arch7): New.
(arm_print_operand): Support %C markup.
(arm_legitimize_sync_memory): New.
(arm_emit, arm_insn_count, arm_count, arm_output_asm_insn): New.
(arm_process_output_memory_barrier, arm_output_memory_barrier): New.
(arm_ldrex_suffix, arm_output_ldrex, arm_output_strex): New.
(arm_output_op2, arm_output_op3, arm_output_sync_loop): New.
(arm_get_sync_operand, FETCH_SYNC_OPERAND): New.
(arm_process_output_sync_insn, arm_output_sync_insn): New.
(arm_sync_loop_insns,arm_call_generator, arm_expand_sync): New.
* config/arm/arm.h (struct arm_sync_generator): New.
(TARGET_HAVE_DMB, TARGET_HAVE_DMB_MCR): New.
(TARGET_HAVE_MEMORY_BARRIER): New.
(TARGET_HAVE_LDREX, TARGET_HAVE_LDREXBHD): New.
* config/arm/arm.md: Include sync.md.
(UNSPEC_MEMORY_BARRIER): New.
(VUNSPEC_SYNC_COMPARE_AND_SWAP, VUNSPEC_SYNC_LOCK): New.
(VUNSPEC_SYNC_OP):New.
(VUNSPEC_SYNC_NEW_OP, VUNSPEC_SYNC_OLD_OP): New.
(sync_result, sync_memory, sync_required_value): New attributes.
(sync_new_value, sync_t1, sync_t2): Likewise.
(sync_release_barrier, sync_op): Likewise.
(length): Add logic to length attribute defintion to call
arm_sync_loop_insns when appropriate.
* config/arm/sync.md: New file.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@163327 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config/arm/sync.md')
-rw-r--r-- | gcc/config/arm/sync.md | 594 |
1 files changed, 594 insertions, 0 deletions
diff --git a/gcc/config/arm/sync.md b/gcc/config/arm/sync.md new file mode 100644 index 00000000000..7fd38d75484 --- /dev/null +++ b/gcc/config/arm/sync.md @@ -0,0 +1,594 @@ +;; Machine description for ARM processor synchronization primitives. +;; Copyright (C) 2010 Free Software Foundation, Inc. +;; Written by Marcus Shawcroft (marcus.shawcroft@arm.com) +;; +;; 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 3, 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 COPYING3. If not see +;; <http://www.gnu.org/licenses/>. */ + +;; ARMV6 introduced ldrex and strex instruction. These instruction +;; access SI width data. In order to implement synchronization +;; primitives for the narrower QI and HI modes we insert appropriate +;; AND/OR sequences into the synchronization loop to mask out the +;; relevant component of an SI access. + +(define_expand "memory_barrier" + [(set (match_dup 0) + (unspec:BLK [(match_dup 0)] UNSPEC_MEMORY_BARRIER))] + "TARGET_HAVE_MEMORY_BARRIER" +{ + operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode)); + MEM_VOLATILE_P (operands[0]) = 1; +}) + +(define_expand "sync_compare_and_swapsi" + [(set (match_operand:SI 0 "s_register_operand") + (unspec_volatile:SI [(match_operand:SI 1 "memory_operand") + (match_operand:SI 2 "s_register_operand") + (match_operand:SI 3 "s_register_operand")] + VUNSPEC_SYNC_COMPARE_AND_SWAP))] + "TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER" + { + struct arm_sync_generator generator; + generator.op = arm_sync_generator_omrn; + generator.u.omrn = gen_arm_sync_compare_and_swapsi; + arm_expand_sync (SImode, &generator, operands[0], operands[1], operands[2], + operands[3]); + DONE; + }) + +(define_mode_iterator NARROW [QI HI]) + +(define_expand "sync_compare_and_swap<mode>" + [(set (match_operand:NARROW 0 "s_register_operand") + (unspec_volatile:NARROW [(match_operand:NARROW 1 "memory_operand") + (match_operand:NARROW 2 "s_register_operand") + (match_operand:NARROW 3 "s_register_operand")] + VUNSPEC_SYNC_COMPARE_AND_SWAP))] + "TARGET_HAVE_LDREXBHD && TARGET_HAVE_MEMORY_BARRIER" + { + struct arm_sync_generator generator; + generator.op = arm_sync_generator_omrn; + generator.u.omrn = gen_arm_sync_compare_and_swap<mode>; + arm_expand_sync (<MODE>mode, &generator, operands[0], operands[1], + operands[2], operands[3]); + DONE; + }) + +(define_expand "sync_lock_test_and_setsi" + [(match_operand:SI 0 "s_register_operand") + (match_operand:SI 1 "memory_operand") + (match_operand:SI 2 "s_register_operand")] + "TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER" + { + struct arm_sync_generator generator; + generator.op = arm_sync_generator_omn; + generator.u.omn = gen_arm_sync_lock_test_and_setsi; + arm_expand_sync (SImode, &generator, operands[0], operands[1], NULL, + operands[2]); + DONE; + }) + +(define_expand "sync_lock_test_and_set<mode>" + [(match_operand:NARROW 0 "s_register_operand") + (match_operand:NARROW 1 "memory_operand") + (match_operand:NARROW 2 "s_register_operand")] + "TARGET_HAVE_LDREXBHD && TARGET_HAVE_MEMORY_BARRIER" + { + struct arm_sync_generator generator; + generator.op = arm_sync_generator_omn; + generator.u.omn = gen_arm_sync_lock_test_and_set<mode>; + arm_expand_sync (<MODE>mode, &generator, operands[0], operands[1], NULL, + operands[2]); + DONE; + }) + +(define_code_iterator syncop [plus minus ior xor and]) + +(define_code_attr sync_optab [(ior "ior") + (xor "xor") + (and "and") + (plus "add") + (minus "sub")]) + +(define_expand "sync_<sync_optab>si" + [(match_operand:SI 0 "memory_operand") + (match_operand:SI 1 "s_register_operand") + (syncop:SI (match_dup 0) (match_dup 1))] + "TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER" + { + struct arm_sync_generator generator; + generator.op = arm_sync_generator_omn; + generator.u.omn = gen_arm_sync_new_<sync_optab>si; + arm_expand_sync (SImode, &generator, NULL, operands[0], NULL, operands[1]); + DONE; + }) + +(define_expand "sync_nandsi" + [(match_operand:SI 0 "memory_operand") + (match_operand:SI 1 "s_register_operand") + (not:SI (and:SI (match_dup 0) (match_dup 1)))] + "TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER" + { + struct arm_sync_generator generator; + generator.op = arm_sync_generator_omn; + generator.u.omn = gen_arm_sync_new_nandsi; + arm_expand_sync (SImode, &generator, NULL, operands[0], NULL, operands[1]); + DONE; + }) + +(define_expand "sync_<sync_optab><mode>" + [(match_operand:NARROW 0 "memory_operand") + (match_operand:NARROW 1 "s_register_operand") + (syncop:NARROW (match_dup 0) (match_dup 1))] + "TARGET_HAVE_LDREXBHD && TARGET_HAVE_MEMORY_BARRIER" + { + struct arm_sync_generator generator; + generator.op = arm_sync_generator_omn; + generator.u.omn = gen_arm_sync_new_<sync_optab><mode>; + arm_expand_sync (<MODE>mode, &generator, NULL, operands[0], NULL, + operands[1]); + DONE; + }) + +(define_expand "sync_nand<mode>" + [(match_operand:NARROW 0 "memory_operand") + (match_operand:NARROW 1 "s_register_operand") + (not:NARROW (and:NARROW (match_dup 0) (match_dup 1)))] + "TARGET_HAVE_LDREXBHD && TARGET_HAVE_MEMORY_BARRIER" + { + struct arm_sync_generator generator; + generator.op = arm_sync_generator_omn; + generator.u.omn = gen_arm_sync_new_nand<mode>; + arm_expand_sync (<MODE>mode, &generator, NULL, operands[0], NULL, + operands[1]); + DONE; + }) + +(define_expand "sync_new_<sync_optab>si" + [(match_operand:SI 0 "s_register_operand") + (match_operand:SI 1 "memory_operand") + (match_operand:SI 2 "s_register_operand") + (syncop:SI (match_dup 1) (match_dup 2))] + "TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER" + { + struct arm_sync_generator generator; + generator.op = arm_sync_generator_omn; + generator.u.omn = gen_arm_sync_new_<sync_optab>si; + arm_expand_sync (SImode, &generator, operands[0], operands[1], NULL, + operands[2]); + DONE; + }) + +(define_expand "sync_new_nandsi" + [(match_operand:SI 0 "s_register_operand") + (match_operand:SI 1 "memory_operand") + (match_operand:SI 2 "s_register_operand") + (not:SI (and:SI (match_dup 1) (match_dup 2)))] + "TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER" + { + struct arm_sync_generator generator; + generator.op = arm_sync_generator_omn; + generator.u.omn = gen_arm_sync_new_nandsi; + arm_expand_sync (SImode, &generator, operands[0], operands[1], NULL, + operands[2]); + DONE; + }) + +(define_expand "sync_new_<sync_optab><mode>" + [(match_operand:NARROW 0 "s_register_operand") + (match_operand:NARROW 1 "memory_operand") + (match_operand:NARROW 2 "s_register_operand") + (syncop:NARROW (match_dup 1) (match_dup 2))] + "TARGET_HAVE_LDREXBHD && TARGET_HAVE_MEMORY_BARRIER" + { + struct arm_sync_generator generator; + generator.op = arm_sync_generator_omn; + generator.u.omn = gen_arm_sync_new_<sync_optab><mode>; + arm_expand_sync (<MODE>mode, &generator, operands[0], operands[1], + NULL, operands[2]); + DONE; + }) + +(define_expand "sync_new_nand<mode>" + [(match_operand:NARROW 0 "s_register_operand") + (match_operand:NARROW 1 "memory_operand") + (match_operand:NARROW 2 "s_register_operand") + (not:NARROW (and:NARROW (match_dup 1) (match_dup 2)))] + "TARGET_HAVE_LDREXBHD && TARGET_HAVE_MEMORY_BARRIER" + { + struct arm_sync_generator generator; + generator.op = arm_sync_generator_omn; + generator.u.omn = gen_arm_sync_new_nand<mode>; + arm_expand_sync (<MODE>mode, &generator, operands[0], operands[1], + NULL, operands[2]); + DONE; + }); + +(define_expand "sync_old_<sync_optab>si" + [(match_operand:SI 0 "s_register_operand") + (match_operand:SI 1 "memory_operand") + (match_operand:SI 2 "s_register_operand") + (syncop:SI (match_dup 1) (match_dup 2))] + "TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER" + { + struct arm_sync_generator generator; + generator.op = arm_sync_generator_omn; + generator.u.omn = gen_arm_sync_old_<sync_optab>si; + arm_expand_sync (SImode, &generator, operands[0], operands[1], NULL, + operands[2]); + DONE; + }) + +(define_expand "sync_old_nandsi" + [(match_operand:SI 0 "s_register_operand") + (match_operand:SI 1 "memory_operand") + (match_operand:SI 2 "s_register_operand") + (not:SI (and:SI (match_dup 1) (match_dup 2)))] + "TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER" + { + struct arm_sync_generator generator; + generator.op = arm_sync_generator_omn; + generator.u.omn = gen_arm_sync_old_nandsi; + arm_expand_sync (SImode, &generator, operands[0], operands[1], NULL, + operands[2]); + DONE; + }) + +(define_expand "sync_old_<sync_optab><mode>" + [(match_operand:NARROW 0 "s_register_operand") + (match_operand:NARROW 1 "memory_operand") + (match_operand:NARROW 2 "s_register_operand") + (syncop:NARROW (match_dup 1) (match_dup 2))] + "TARGET_HAVE_LDREXBHD && TARGET_HAVE_MEMORY_BARRIER" + { + struct arm_sync_generator generator; + generator.op = arm_sync_generator_omn; + generator.u.omn = gen_arm_sync_old_<sync_optab><mode>; + arm_expand_sync (<MODE>mode, &generator, operands[0], operands[1], + NULL, operands[2]); + DONE; + }) + +(define_expand "sync_old_nand<mode>" + [(match_operand:NARROW 0 "s_register_operand") + (match_operand:NARROW 1 "memory_operand") + (match_operand:NARROW 2 "s_register_operand") + (not:NARROW (and:NARROW (match_dup 1) (match_dup 2)))] + "TARGET_HAVE_LDREXBHD && TARGET_HAVE_MEMORY_BARRIER" + { + struct arm_sync_generator generator; + generator.op = arm_sync_generator_omn; + generator.u.omn = gen_arm_sync_old_nand<mode>; + arm_expand_sync (<MODE>mode, &generator, operands[0], operands[1], + NULL, operands[2]); + DONE; + }) + +(define_insn "arm_sync_compare_and_swapsi" + [(set (match_operand:SI 0 "s_register_operand" "=&r") + (unspec_volatile:SI + [(match_operand:SI 1 "memory_operand" "+m") + (match_operand:SI 2 "s_register_operand" "r") + (match_operand:SI 3 "s_register_operand" "r")] + VUNSPEC_SYNC_COMPARE_AND_SWAP)) + (set (match_dup 1) (unspec_volatile:SI [(match_dup 2)] + VUNSPEC_SYNC_COMPARE_AND_SWAP)) + (clobber:SI (match_scratch:SI 4 "=&r")) + (set (reg:CC CC_REGNUM) (unspec_volatile:CC [(match_dup 1)] + VUNSPEC_SYNC_COMPARE_AND_SWAP)) + ] + "TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER" + { + return arm_output_sync_insn (insn, operands); + } + [(set_attr "sync_result" "0") + (set_attr "sync_memory" "1") + (set_attr "sync_required_value" "2") + (set_attr "sync_new_value" "3") + (set_attr "sync_t1" "0") + (set_attr "sync_t2" "4") + (set_attr "conds" "nocond") + (set_attr "predicable" "no")]) + +(define_insn "arm_sync_compare_and_swap<mode>" + [(set (match_operand:SI 0 "s_register_operand" "=&r") + (zero_extend:SI + (unspec_volatile:NARROW + [(match_operand:NARROW 1 "memory_operand" "+m") + (match_operand:SI 2 "s_register_operand" "r") + (match_operand:SI 3 "s_register_operand" "r")] + VUNSPEC_SYNC_COMPARE_AND_SWAP))) + (set (match_dup 1) (unspec_volatile:NARROW [(match_dup 2)] + VUNSPEC_SYNC_COMPARE_AND_SWAP)) + (clobber:SI (match_scratch:SI 4 "=&r")) + (set (reg:CC CC_REGNUM) (unspec_volatile:CC [(match_dup 1)] + VUNSPEC_SYNC_COMPARE_AND_SWAP)) + ] + "TARGET_HAVE_LDREXBHD && TARGET_HAVE_MEMORY_BARRIER" + { + return arm_output_sync_insn (insn, operands); + } + [(set_attr "sync_result" "0") + (set_attr "sync_memory" "1") + (set_attr "sync_required_value" "2") + (set_attr "sync_new_value" "3") + (set_attr "sync_t1" "0") + (set_attr "sync_t2" "4") + (set_attr "conds" "nocond") + (set_attr "predicable" "no")]) + +(define_insn "arm_sync_lock_test_and_setsi" + [(set (match_operand:SI 0 "s_register_operand" "=&r") + (match_operand:SI 1 "memory_operand" "+m")) + (set (match_dup 1) + (unspec_volatile:SI [(match_operand:SI 2 "s_register_operand" "r")] + VUNSPEC_SYNC_LOCK)) + (clobber (reg:CC CC_REGNUM)) + (clobber (match_scratch:SI 3 "=&r"))] + "TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER" + { + return arm_output_sync_insn (insn, operands); + } + [(set_attr "sync_release_barrier" "no") + (set_attr "sync_result" "0") + (set_attr "sync_memory" "1") + (set_attr "sync_new_value" "2") + (set_attr "sync_t1" "0") + (set_attr "sync_t2" "3") + (set_attr "conds" "nocond") + (set_attr "predicable" "no")]) + +(define_insn "arm_sync_lock_test_and_set<mode>" + [(set (match_operand:SI 0 "s_register_operand" "=&r") + (zero_extend:SI (match_operand:NARROW 1 "memory_operand" "+m"))) + (set (match_dup 1) + (unspec_volatile:NARROW [(match_operand:SI 2 "s_register_operand" "r")] + VUNSPEC_SYNC_LOCK)) + (clobber (reg:CC CC_REGNUM)) + (clobber (match_scratch:SI 3 "=&r"))] + "TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER" + { + return arm_output_sync_insn (insn, operands); + } + [(set_attr "sync_release_barrier" "no") + (set_attr "sync_result" "0") + (set_attr "sync_memory" "1") + (set_attr "sync_new_value" "2") + (set_attr "sync_t1" "0") + (set_attr "sync_t2" "3") + (set_attr "conds" "nocond") + (set_attr "predicable" "no")]) + +(define_insn "arm_sync_new_<sync_optab>si" + [(set (match_operand:SI 0 "s_register_operand" "=&r") + (unspec_volatile:SI [(syncop:SI + (match_operand:SI 1 "memory_operand" "+m") + (match_operand:SI 2 "s_register_operand" "r")) + ] + VUNSPEC_SYNC_NEW_OP)) + (set (match_dup 1) + (unspec_volatile:SI [(match_dup 1) (match_dup 2)] + VUNSPEC_SYNC_NEW_OP)) + (clobber (reg:CC CC_REGNUM)) + (clobber (match_scratch:SI 3 "=&r"))] + "TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER" + { + return arm_output_sync_insn (insn, operands); + } + [(set_attr "sync_result" "0") + (set_attr "sync_memory" "1") + (set_attr "sync_new_value" "2") + (set_attr "sync_t1" "0") + (set_attr "sync_t2" "3") + (set_attr "sync_op" "<sync_optab>") + (set_attr "conds" "nocond") + (set_attr "predicable" "no")]) + +(define_insn "arm_sync_new_nandsi" + [(set (match_operand:SI 0 "s_register_operand" "=&r") + (unspec_volatile:SI [(not:SI (and:SI + (match_operand:SI 1 "memory_operand" "+m") + (match_operand:SI 2 "s_register_operand" "r"))) + ] + VUNSPEC_SYNC_NEW_OP)) + (set (match_dup 1) + (unspec_volatile:SI [(match_dup 1) (match_dup 2)] + VUNSPEC_SYNC_NEW_OP)) + (clobber (reg:CC CC_REGNUM)) + (clobber (match_scratch:SI 3 "=&r"))] + "TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER" + { + return arm_output_sync_insn (insn, operands); + } + [(set_attr "sync_result" "0") + (set_attr "sync_memory" "1") + (set_attr "sync_new_value" "2") + (set_attr "sync_t1" "0") + (set_attr "sync_t2" "3") + (set_attr "sync_op" "nand") + (set_attr "conds" "nocond") + (set_attr "predicable" "no")]) + +(define_insn "arm_sync_new_<sync_optab><mode>" + [(set (match_operand:SI 0 "s_register_operand" "=&r") + (unspec_volatile:SI [(syncop:SI + (zero_extend:SI + (match_operand:NARROW 1 "memory_operand" "+m")) + (match_operand:SI 2 "s_register_operand" "r")) + ] + VUNSPEC_SYNC_NEW_OP)) + (set (match_dup 1) + (unspec_volatile:NARROW [(match_dup 1) (match_dup 2)] + VUNSPEC_SYNC_NEW_OP)) + (clobber (reg:CC CC_REGNUM)) + (clobber (match_scratch:SI 3 "=&r"))] + "TARGET_HAVE_LDREXBHD && TARGET_HAVE_MEMORY_BARRIER" + { + return arm_output_sync_insn (insn, operands); + } + [(set_attr "sync_result" "0") + (set_attr "sync_memory" "1") + (set_attr "sync_new_value" "2") + (set_attr "sync_t1" "0") + (set_attr "sync_t2" "3") + (set_attr "sync_op" "<sync_optab>") + (set_attr "conds" "nocond") + (set_attr "predicable" "no")]) + +(define_insn "arm_sync_new_nand<mode>" + [(set (match_operand:SI 0 "s_register_operand" "=&r") + (unspec_volatile:SI + [(not:SI + (and:SI + (zero_extend:SI + (match_operand:NARROW 1 "memory_operand" "+m")) + (match_operand:SI 2 "s_register_operand" "r"))) + ] VUNSPEC_SYNC_NEW_OP)) + (set (match_dup 1) + (unspec_volatile:NARROW [(match_dup 1) (match_dup 2)] + VUNSPEC_SYNC_NEW_OP)) + (clobber (reg:CC CC_REGNUM)) + (clobber (match_scratch:SI 3 "=&r"))] + "TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER" + { + return arm_output_sync_insn (insn, operands); + } + [(set_attr "sync_result" "0") + (set_attr "sync_memory" "1") + (set_attr "sync_new_value" "2") + (set_attr "sync_t1" "0") + (set_attr "sync_t2" "3") + (set_attr "sync_op" "nand") + (set_attr "conds" "nocond") + (set_attr "predicable" "no")]) + +(define_insn "arm_sync_old_<sync_optab>si" + [(set (match_operand:SI 0 "s_register_operand" "=&r") + (unspec_volatile:SI [(syncop:SI + (match_operand:SI 1 "memory_operand" "+m") + (match_operand:SI 2 "s_register_operand" "r")) + ] + VUNSPEC_SYNC_OLD_OP)) + (set (match_dup 1) + (unspec_volatile:SI [(match_dup 1) (match_dup 2)] + VUNSPEC_SYNC_OLD_OP)) + (clobber (reg:CC CC_REGNUM)) + (clobber (match_scratch:SI 3 "=&r")) + (clobber (match_scratch:SI 4 "=&r"))] + "TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER" + { + return arm_output_sync_insn (insn, operands); + } + [(set_attr "sync_result" "0") + (set_attr "sync_memory" "1") + (set_attr "sync_new_value" "2") + (set_attr "sync_t1" "3") + (set_attr "sync_t2" "4") + (set_attr "sync_op" "<sync_optab>") + (set_attr "conds" "nocond") + (set_attr "predicable" "no")]) + +(define_insn "arm_sync_old_nandsi" + [(set (match_operand:SI 0 "s_register_operand" "=&r") + (unspec_volatile:SI [(not:SI (and:SI + (match_operand:SI 1 "memory_operand" "+m") + (match_operand:SI 2 "s_register_operand" "r"))) + ] + VUNSPEC_SYNC_OLD_OP)) + (set (match_dup 1) + (unspec_volatile:SI [(match_dup 1) (match_dup 2)] + VUNSPEC_SYNC_OLD_OP)) + (clobber (reg:CC CC_REGNUM)) + (clobber (match_scratch:SI 3 "=&r")) + (clobber (match_scratch:SI 4 "=&r"))] + "TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER" + { + return arm_output_sync_insn (insn, operands); + } + [(set_attr "sync_result" "0") + (set_attr "sync_memory" "1") + (set_attr "sync_new_value" "2") + (set_attr "sync_t1" "3") + (set_attr "sync_t2" "4") + (set_attr "sync_op" "nand") + (set_attr "conds" "nocond") + (set_attr "predicable" "no")]) + +(define_insn "arm_sync_old_<sync_optab><mode>" + [(set (match_operand:SI 0 "s_register_operand" "=&r") + (unspec_volatile:SI [(syncop:SI + (zero_extend:SI + (match_operand:NARROW 1 "memory_operand" "+m")) + (match_operand:SI 2 "s_register_operand" "r")) + ] + VUNSPEC_SYNC_OLD_OP)) + (set (match_dup 1) + (unspec_volatile:NARROW [(match_dup 1) (match_dup 2)] + VUNSPEC_SYNC_OLD_OP)) + (clobber (reg:CC CC_REGNUM)) + (clobber (match_scratch:SI 3 "=&r")) + (clobber (match_scratch:SI 4 "=&r"))] + "TARGET_HAVE_LDREXBHD && TARGET_HAVE_MEMORY_BARRIER" + { + return arm_output_sync_insn (insn, operands); + } + [(set_attr "sync_result" "0") + (set_attr "sync_memory" "1") + (set_attr "sync_new_value" "2") + (set_attr "sync_t1" "3") + (set_attr "sync_t2" "4") + (set_attr "sync_op" "<sync_optab>") + (set_attr "conds" "nocond") + (set_attr "predicable" "no")]) + +(define_insn "arm_sync_old_nand<mode>" + [(set (match_operand:SI 0 "s_register_operand" "=&r") + (unspec_volatile:SI [(not:SI (and:SI + (zero_extend:SI + (match_operand:NARROW 1 "memory_operand" "+m")) + (match_operand:SI 2 "s_register_operand" "r"))) + ] + VUNSPEC_SYNC_OLD_OP)) + (set (match_dup 1) + (unspec_volatile:NARROW [(match_dup 1) (match_dup 2)] + VUNSPEC_SYNC_OLD_OP)) + (clobber (reg:CC CC_REGNUM)) + (clobber (match_scratch:SI 3 "=&r")) + (clobber (match_scratch:SI 4 "=&r"))] + "TARGET_HAVE_LDREXBHD && TARGET_HAVE_MEMORY_BARRIER" + { + return arm_output_sync_insn (insn, operands); + } + [(set_attr "sync_result" "0") + (set_attr "sync_memory" "1") + (set_attr "sync_new_value" "2") + (set_attr "sync_t1" "3") + (set_attr "sync_t2" "4") + (set_attr "sync_op" "nand") + (set_attr "conds" "nocond") + (set_attr "predicable" "no")]) + +(define_insn "*memory_barrier" + [(set (match_operand:BLK 0 "" "") + (unspec:BLK [(match_dup 0)] UNSPEC_MEMORY_BARRIER))] + "TARGET_HAVE_MEMORY_BARRIER" + { + return arm_output_memory_barrier (operands); + } + [(set_attr "length" "4") + (set_attr "conds" "unconditional") + (set_attr "predicable" "no")]) + |