diff options
author | rsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4> | 2011-10-14 14:38:58 +0000 |
---|---|---|
committer | rsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4> | 2011-10-14 14:38:58 +0000 |
commit | f048bfc483f40d6ddbcd064b9a1a078d97db42b4 (patch) | |
tree | adbc04b256497bcf813eba5879fbee6b2f56343e /gcc/config/arm | |
parent | b3902c959fc7f80947ca0970877b625345bd6fd0 (diff) | |
download | gcc-f048bfc483f40d6ddbcd064b9a1a078d97db42b4.tar.gz |
gcc/
2011-10-14 David Alan Gilbert <david.gilbert@linaro.org>
* config/arm/arm.c (arm_output_ldrex): Support ldrexd.
(arm_output_strex): Support strexd.
(arm_output_it): New helper to output it in Thumb2 mode only.
(arm_output_sync_loop): Support DI mode. Change comment to
not support const_int.
(arm_expand_sync): Support DI mode.
* config/arm/arm.h (TARGET_HAVE_LDREXBHD): Split into LDREXBH
and LDREXD.
* config/arm/iterators.md (NARROW): move from sync.md.
(QHSD): New iterator for all current ARM integer modes.
(SIDI): New iterator for SI and DI modes only.
* config/arm/sync.md (sync_predtab): New mode_attr.
(sync_compare_and_swapsi): Fold into sync_compare_and_swap<mode>.
(sync_lock_test_and_setsi): Fold into sync_lock_test_and_setsi<mode>.
(sync_<sync_optab>si): Fold into sync_<sync_optab><mode>.
(sync_nandsi): Fold into sync_nand<mode>.
(sync_new_<sync_optab>si): Fold into sync_new_<sync_optab><mode>.
(sync_new_nandsi): Fold into sync_new_nand<mode>.
(sync_old_<sync_optab>si): Fold into sync_old_<sync_optab><mode>.
(sync_old_nandsi): Fold into sync_old_nand<mode>.
(sync_compare_and_swap<mode>): Support SI & DI.
(sync_lock_test_and_set<mode>): Likewise.
(sync_<sync_optab><mode>): Likewise.
(sync_nand<mode>): Likewise.
(sync_new_<sync_optab><mode>): Likewise.
(sync_new_nand<mode>): Likewise.
(sync_old_<sync_optab><mode>): Likewise.
(sync_old_nand<mode>): Likewise.
(arm_sync_compare_and_swapsi): Turn into iterator on SI & DI.
(arm_sync_lock_test_and_setsi): Likewise.
(arm_sync_new_<sync_optab>si): Likewise.
(arm_sync_new_nandsi): Likewise.
(arm_sync_old_<sync_optab>si): Likewise.
(arm_sync_old_nandsi): Likewise.
(arm_sync_compare_and_swap<mode> NARROW): use sync_predtab, fix indent.
(arm_sync_lock_test_and_setsi<mode> NARROW): Likewise.
(arm_sync_new_<sync_optab><mode> NARROW): Likewise.
(arm_sync_new_nand<mode> NARROW): Likewise.
(arm_sync_old_<sync_optab><mode> NARROW): Likewise.
(arm_sync_old_nand<mode> NARROW): Likewise.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@179981 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config/arm')
-rw-r--r-- | gcc/config/arm/arm.c | 173 | ||||
-rw-r--r-- | gcc/config/arm/arm.h | 8 | ||||
-rw-r--r-- | gcc/config/arm/iterators.md | 9 | ||||
-rw-r--r-- | gcc/config/arm/sync.md | 424 |
4 files changed, 314 insertions, 300 deletions
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index 93386f036d3..a429c192fdb 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -24042,12 +24042,26 @@ arm_output_ldrex (emit_f emit, rtx target, rtx memory) { - const char *suffix = arm_ldrex_suffix (mode); - rtx operands[2]; + rtx operands[3]; operands[0] = target; - operands[1] = memory; - arm_output_asm_insn (emit, 0, operands, "ldrex%s\t%%0, %%C1", suffix); + if (mode != DImode) + { + const char *suffix = arm_ldrex_suffix (mode); + operands[1] = memory; + arm_output_asm_insn (emit, 0, operands, "ldrex%s\t%%0, %%C1", suffix); + } + else + { + /* The restrictions on target registers in ARM mode are that the two + registers are consecutive and the first one is even; Thumb is + actually more flexible, but DI should give us this anyway. + Note that the 1st register always gets the lowest word in memory. */ + gcc_assert ((REGNO (target) & 1) == 0); + operands[1] = gen_rtx_REG (SImode, REGNO (target) + 1); + operands[2] = memory; + arm_output_asm_insn (emit, 0, operands, "ldrexd\t%%0, %%1, %%C2"); + } } /* Emit a strex{b,h,d, } instruction appropriate for the specified @@ -24060,14 +24074,41 @@ arm_output_strex (emit_f emit, rtx value, rtx memory) { - const char *suffix = arm_ldrex_suffix (mode); - rtx operands[3]; + rtx operands[4]; operands[0] = result; operands[1] = value; - operands[2] = memory; - arm_output_asm_insn (emit, 0, operands, "strex%s%s\t%%0, %%1, %%C2", suffix, - cc); + if (mode != DImode) + { + const char *suffix = arm_ldrex_suffix (mode); + operands[2] = memory; + arm_output_asm_insn (emit, 0, operands, "strex%s%s\t%%0, %%1, %%C2", + suffix, cc); + } + else + { + /* The restrictions on target registers in ARM mode are that the two + registers are consecutive and the first one is even; Thumb is + actually more flexible, but DI should give us this anyway. + Note that the 1st register always gets the lowest word in memory. */ + gcc_assert ((REGNO (value) & 1) == 0 || TARGET_THUMB2); + operands[2] = gen_rtx_REG (SImode, REGNO (value) + 1); + operands[3] = memory; + arm_output_asm_insn (emit, 0, operands, "strexd%s\t%%0, %%1, %%2, %%C3", + cc); + } +} + +/* Helper to emit an it instruction in Thumb2 mode only; although the assembler + will ignore it in ARM mode, emitting it will mess up instruction counts we + sometimes keep 'flags' are the extra t's and e's if it's more than one + instruction that is conditional. */ +static void +arm_output_it (emit_f emit, const char *flags, const char *cond) +{ + rtx operands[1]; /* Don't actually use the operand. */ + if (TARGET_THUMB2) + arm_output_asm_insn (emit, 0, operands, "it%s\t%s", flags, cond); } /* Helper to emit a two operand instruction. */ @@ -24109,7 +24150,7 @@ arm_output_op3 (emit_f emit, const char *mnemonic, rtx d, rtx a, rtx b) required_value: - RTX register or const_int representing the required old_value for + RTX register representing the required old_value for the modify to continue, if NULL no comparsion is performed. */ static void arm_output_sync_loop (emit_f emit, @@ -24123,7 +24164,13 @@ arm_output_sync_loop (emit_f emit, enum attr_sync_op sync_op, int early_barrier_required) { - rtx operands[1]; + rtx operands[2]; + /* We'll use the lo for the normal rtx in the none-DI case + as well as the least-sig word in the DI case. */ + rtx old_value_lo, required_value_lo, new_value_lo, t1_lo; + rtx old_value_hi, required_value_hi, new_value_hi, t1_hi; + + bool is_di = mode == DImode; gcc_assert (t1 != t2); @@ -24134,82 +24181,142 @@ arm_output_sync_loop (emit_f emit, arm_output_ldrex (emit, mode, old_value, memory); + if (is_di) + { + old_value_lo = gen_lowpart (SImode, old_value); + old_value_hi = gen_highpart (SImode, old_value); + if (required_value) + { + required_value_lo = gen_lowpart (SImode, required_value); + required_value_hi = gen_highpart (SImode, required_value); + } + else + { + /* Silence false potentially unused warning. */ + required_value_lo = NULL_RTX; + required_value_hi = NULL_RTX; + } + new_value_lo = gen_lowpart (SImode, new_value); + new_value_hi = gen_highpart (SImode, new_value); + t1_lo = gen_lowpart (SImode, t1); + t1_hi = gen_highpart (SImode, t1); + } + else + { + old_value_lo = old_value; + new_value_lo = new_value; + required_value_lo = required_value; + t1_lo = t1; + + /* Silence false potentially unused warning. */ + t1_hi = NULL_RTX; + new_value_hi = NULL_RTX; + required_value_hi = NULL_RTX; + old_value_hi = NULL_RTX; + } + if (required_value) { - rtx operands[2]; + operands[0] = old_value_lo; + operands[1] = required_value_lo; - operands[0] = old_value; - operands[1] = required_value; arm_output_asm_insn (emit, 0, operands, "cmp\t%%0, %%1"); + if (is_di) + { + arm_output_it (emit, "", "eq"); + arm_output_op2 (emit, "cmpeq", old_value_hi, required_value_hi); + } arm_output_asm_insn (emit, 0, operands, "bne\t%sLSYB%%=", LOCAL_LABEL_PREFIX); } switch (sync_op) { case SYNC_OP_ADD: - arm_output_op3 (emit, "add", t1, old_value, new_value); + arm_output_op3 (emit, is_di ? "adds" : "add", + t1_lo, old_value_lo, new_value_lo); + if (is_di) + arm_output_op3 (emit, "adc", t1_hi, old_value_hi, new_value_hi); break; case SYNC_OP_SUB: - arm_output_op3 (emit, "sub", t1, old_value, new_value); + arm_output_op3 (emit, is_di ? "subs" : "sub", + t1_lo, old_value_lo, new_value_lo); + if (is_di) + arm_output_op3 (emit, "sbc", t1_hi, old_value_hi, new_value_hi); break; case SYNC_OP_IOR: - arm_output_op3 (emit, "orr", t1, old_value, new_value); + arm_output_op3 (emit, "orr", t1_lo, old_value_lo, new_value_lo); + if (is_di) + arm_output_op3 (emit, "orr", t1_hi, old_value_hi, new_value_hi); break; case SYNC_OP_XOR: - arm_output_op3 (emit, "eor", t1, old_value, new_value); + arm_output_op3 (emit, "eor", t1_lo, old_value_lo, new_value_lo); + if (is_di) + arm_output_op3 (emit, "eor", t1_hi, old_value_hi, new_value_hi); break; case SYNC_OP_AND: - arm_output_op3 (emit,"and", t1, old_value, new_value); + arm_output_op3 (emit,"and", t1_lo, old_value_lo, new_value_lo); + if (is_di) + arm_output_op3 (emit, "and", t1_hi, old_value_hi, new_value_hi); break; case SYNC_OP_NAND: - arm_output_op3 (emit, "and", t1, old_value, new_value); - arm_output_op2 (emit, "mvn", t1, t1); + arm_output_op3 (emit, "and", t1_lo, old_value_lo, new_value_lo); + if (is_di) + arm_output_op3 (emit, "and", t1_hi, old_value_hi, new_value_hi); + arm_output_op2 (emit, "mvn", t1_lo, t1_lo); + if (is_di) + arm_output_op2 (emit, "mvn", t1_hi, t1_hi); break; case SYNC_OP_NONE: t1 = new_value; + t1_lo = new_value_lo; + if (is_di) + t1_hi = new_value_hi; break; } + /* Note that the result of strex is a 0/1 flag that's always 1 register. */ if (t2) { - arm_output_strex (emit, mode, "", t2, t1, memory); - operands[0] = t2; - arm_output_asm_insn (emit, 0, operands, "teq\t%%0, #0"); - arm_output_asm_insn (emit, 0, operands, "bne\t%sLSYT%%=", - LOCAL_LABEL_PREFIX); + arm_output_strex (emit, mode, "", t2, t1, memory); + operands[0] = t2; + arm_output_asm_insn (emit, 0, operands, "teq\t%%0, #0"); + arm_output_asm_insn (emit, 0, operands, "bne\t%sLSYT%%=", + LOCAL_LABEL_PREFIX); } else { /* Use old_value for the return value because for some operations the old_value can easily be restored. This saves one register. */ - arm_output_strex (emit, mode, "", old_value, t1, memory); - operands[0] = old_value; + arm_output_strex (emit, mode, "", old_value_lo, t1, memory); + operands[0] = old_value_lo; arm_output_asm_insn (emit, 0, operands, "teq\t%%0, #0"); arm_output_asm_insn (emit, 0, operands, "bne\t%sLSYT%%=", LOCAL_LABEL_PREFIX); + /* Note that we only used the _lo half of old_value as a temporary + so in DI we don't have to restore the _hi part. */ switch (sync_op) { case SYNC_OP_ADD: - arm_output_op3 (emit, "sub", old_value, t1, new_value); + arm_output_op3 (emit, "sub", old_value_lo, t1_lo, new_value_lo); break; case SYNC_OP_SUB: - arm_output_op3 (emit, "add", old_value, t1, new_value); + arm_output_op3 (emit, "add", old_value_lo, t1_lo, new_value_lo); break; case SYNC_OP_XOR: - arm_output_op3 (emit, "eor", old_value, t1, new_value); + arm_output_op3 (emit, "eor", old_value_lo, t1_lo, new_value_lo); break; case SYNC_OP_NONE: - arm_output_op2 (emit, "mov", old_value, required_value); + arm_output_op2 (emit, "mov", old_value_lo, required_value_lo); break; default: @@ -24315,7 +24422,7 @@ arm_expand_sync (enum machine_mode mode, target = gen_reg_rtx (mode); memory = arm_legitimize_sync_memory (memory); - if (mode != SImode) + if (mode != SImode && mode != DImode) { rtx load_temp = gen_reg_rtx (SImode); diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h index 19381fb36c2..271b44126c3 100644 --- a/gcc/config/arm/arm.h +++ b/gcc/config/arm/arm.h @@ -297,8 +297,12 @@ extern void (*arm_lang_output_object_attributes_hook)(void); /* Nonzero if this chip supports ldrex and strex */ #define TARGET_HAVE_LDREX ((arm_arch6 && TARGET_ARM) || arm_arch7) -/* Nonzero if this chip supports ldrex{bhd} and strex{bhd}. */ -#define TARGET_HAVE_LDREXBHD ((arm_arch6k && TARGET_ARM) || arm_arch7) +/* Nonzero if this chip supports ldrex{bh} and strex{bh}. */ +#define TARGET_HAVE_LDREXBH ((arm_arch6k && TARGET_ARM) || arm_arch7) + +/* Nonzero if this chip supports ldrexd and strexd. */ +#define TARGET_HAVE_LDREXD (((arm_arch6k && TARGET_ARM) || arm_arch7) \ + && arm_arch_notm) /* Nonzero if integer division instructions supported. */ #define TARGET_IDIV ((TARGET_ARM && arm_arch_arm_hwdiv) \ diff --git a/gcc/config/arm/iterators.md b/gcc/config/arm/iterators.md index da1f7af9b7a..85dd641d597 100644 --- a/gcc/config/arm/iterators.md +++ b/gcc/config/arm/iterators.md @@ -33,6 +33,15 @@ ;; A list of integer modes that are up to one word long (define_mode_iterator QHSI [QI HI SI]) +;; A list of integer modes that are less than a word +(define_mode_iterator NARROW [QI HI]) + +;; A list of all the integer modes upto 64bit +(define_mode_iterator QHSD [QI HI SI DI]) + +;; A list of the 32bit and 64bit integer modes +(define_mode_iterator SIDI [SI DI]) + ;; Integer element sizes implemented by IWMMXT. (define_mode_iterator VMMX [V2SI V4HI V8QI]) diff --git a/gcc/config/arm/sync.md b/gcc/config/arm/sync.md index 689a235c16f..40ee93c35d1 100644 --- a/gcc/config/arm/sync.md +++ b/gcc/config/arm/sync.md @@ -1,6 +1,7 @@ ;; Machine description for ARM processor synchronization primitives. ;; Copyright (C) 2010 Free Software Foundation, Inc. ;; Written by Marcus Shawcroft (marcus.shawcroft@arm.com) +;; 64bit Atomics by Dave Gilbert (david.gilbert@linaro.org) ;; ;; This file is part of GCC. ;; @@ -33,31 +34,24 @@ 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_mode_attr sync_predtab [(SI "TARGET_HAVE_LDREX && + TARGET_HAVE_MEMORY_BARRIER") + (QI "TARGET_HAVE_LDREXBH && + TARGET_HAVE_MEMORY_BARRIER") + (HI "TARGET_HAVE_LDREXBH && + TARGET_HAVE_MEMORY_BARRIER") + (DI "TARGET_HAVE_LDREXD && + ARM_DOUBLEWORD_ALIGN && + TARGET_HAVE_MEMORY_BARRIER")]) (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")] + [(set (match_operand:QHSD 0 "s_register_operand") + (unspec_volatile:QHSD [(match_operand:QHSD 1 "memory_operand") + (match_operand:QHSD 2 "s_register_operand") + (match_operand:QHSD 3 "s_register_operand")] VUNSPEC_SYNC_COMPARE_AND_SWAP))] - "TARGET_HAVE_LDREXBHD && TARGET_HAVE_MEMORY_BARRIER" + "<sync_predtab>" { struct arm_sync_generator generator; generator.op = arm_sync_generator_omrn; @@ -67,25 +61,11 @@ 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" + [(match_operand:QHSD 0 "s_register_operand") + (match_operand:QHSD 1 "memory_operand") + (match_operand:QHSD 2 "s_register_operand")] + "<sync_predtab>" { struct arm_sync_generator generator; generator.op = arm_sync_generator_omn; @@ -115,51 +95,25 @@ (plus "*") (minus "*")]) -(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" + [(match_operand:QHSD 0 "memory_operand") + (match_operand:QHSD 1 "s_register_operand") + (syncop:QHSD (match_dup 0) (match_dup 1))] + "<sync_predtab>" { 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]); + 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" + [(match_operand:QHSD 0 "memory_operand") + (match_operand:QHSD 1 "s_register_operand") + (not:QHSD (and:QHSD (match_dup 0) (match_dup 1)))] + "<sync_predtab>" { struct arm_sync_generator generator; generator.op = arm_sync_generator_omn; @@ -169,57 +123,27 @@ 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" + [(match_operand:QHSD 0 "s_register_operand") + (match_operand:QHSD 1 "memory_operand") + (match_operand:QHSD 2 "s_register_operand") + (syncop:QHSD (match_dup 1) (match_dup 2))] + "<sync_predtab>" { 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]); + 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" + [(match_operand:QHSD 0 "s_register_operand") + (match_operand:QHSD 1 "memory_operand") + (match_operand:QHSD 2 "s_register_operand") + (not:QHSD (and:QHSD (match_dup 1) (match_dup 2)))] + "<sync_predtab>" { struct arm_sync_generator generator; generator.op = arm_sync_generator_omn; @@ -229,57 +153,27 @@ 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" + [(match_operand:QHSD 0 "s_register_operand") + (match_operand:QHSD 1 "memory_operand") + (match_operand:QHSD 2 "s_register_operand") + (syncop:QHSD (match_dup 1) (match_dup 2))] + "<sync_predtab>" { 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]); + 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" + [(match_operand:QHSD 0 "s_register_operand") + (match_operand:QHSD 1 "memory_operand") + (match_operand:QHSD 2 "s_register_operand") + (not:QHSD (and:QHSD (match_dup 1) (match_dup 2)))] + "<sync_predtab>" { struct arm_sync_generator generator; generator.op = arm_sync_generator_omn; @@ -289,22 +183,22 @@ DONE; }) -(define_insn "arm_sync_compare_and_swapsi" - [(set (match_operand:SI 0 "s_register_operand" "=&r") - (unspec_volatile:SI - [(match_operand:SI 1 "arm_sync_memory_operand" "+Q") - (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)] +(define_insn "arm_sync_compare_and_swap<mode>" + [(set (match_operand:SIDI 0 "s_register_operand" "=&r") + (unspec_volatile:SIDI + [(match_operand:SIDI 1 "arm_sync_memory_operand" "+Q") + (match_operand:SIDI 2 "s_register_operand" "r") + (match_operand:SIDI 3 "s_register_operand" "r")] + VUNSPEC_SYNC_COMPARE_AND_SWAP)) + (set (match_dup 1) (unspec_volatile:SIDI [(match_dup 2)] VUNSPEC_SYNC_COMPARE_AND_SWAP)) (set (reg:CC CC_REGNUM) (unspec_volatile:CC [(match_dup 1)] VUNSPEC_SYNC_COMPARE_AND_SWAP)) ] - "TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER" + "<sync_predtab>" { return arm_output_sync_insn (insn, operands); - } + } [(set_attr "sync_result" "0") (set_attr "sync_memory" "1") (set_attr "sync_required_value" "2") @@ -318,7 +212,7 @@ (zero_extend:SI (unspec_volatile:NARROW [(match_operand:NARROW 1 "arm_sync_memory_operand" "+Q") - (match_operand:SI 2 "s_register_operand" "r") + (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)] @@ -326,10 +220,10 @@ (set (reg:CC CC_REGNUM) (unspec_volatile:CC [(match_dup 1)] VUNSPEC_SYNC_COMPARE_AND_SWAP)) ] - "TARGET_HAVE_LDREXBHD && TARGET_HAVE_MEMORY_BARRIER" + "<sync_predtab>" { return arm_output_sync_insn (insn, operands); - } + } [(set_attr "sync_result" "0") (set_attr "sync_memory" "1") (set_attr "sync_required_value" "2") @@ -338,18 +232,18 @@ (set_attr "conds" "clob") (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 "arm_sync_memory_operand" "+Q")) +(define_insn "arm_sync_lock_test_and_set<mode>" + [(set (match_operand:SIDI 0 "s_register_operand" "=&r") + (match_operand:SIDI 1 "arm_sync_memory_operand" "+Q")) (set (match_dup 1) - (unspec_volatile:SI [(match_operand:SI 2 "s_register_operand" "r")] - VUNSPEC_SYNC_LOCK)) + (unspec_volatile:SIDI [(match_operand:SIDI 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" + "<sync_predtab>" { return arm_output_sync_insn (insn, operands); - } + } [(set_attr "sync_release_barrier" "no") (set_attr "sync_result" "0") (set_attr "sync_memory" "1") @@ -364,10 +258,10 @@ (zero_extend:SI (match_operand:NARROW 1 "arm_sync_memory_operand" "+Q"))) (set (match_dup 1) (unspec_volatile:NARROW [(match_operand:SI 2 "s_register_operand" "r")] - VUNSPEC_SYNC_LOCK)) + VUNSPEC_SYNC_LOCK)) (clobber (reg:CC CC_REGNUM)) (clobber (match_scratch:SI 3 "=&r"))] - "TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER" + "<sync_predtab>" { return arm_output_sync_insn (insn, operands); } @@ -380,22 +274,22 @@ (set_attr "conds" "clob") (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 "arm_sync_memory_operand" "+Q") - (match_operand:SI 2 "s_register_operand" "r")) - ] - VUNSPEC_SYNC_NEW_OP)) +(define_insn "arm_sync_new_<sync_optab><mode>" + [(set (match_operand:SIDI 0 "s_register_operand" "=&r") + (unspec_volatile:SIDI [(syncop:SIDI + (match_operand:SIDI 1 "arm_sync_memory_operand" "+Q") + (match_operand:SIDI 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)) + (unspec_volatile:SIDI [(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" + "<sync_predtab>" { return arm_output_sync_insn (insn, operands); - } + } [(set_attr "sync_result" "0") (set_attr "sync_memory" "1") (set_attr "sync_new_value" "2") @@ -405,54 +299,54 @@ (set_attr "conds" "clob") (set_attr "predicable" "no")]) -(define_insn "arm_sync_new_nandsi" +(define_insn "arm_sync_new_<sync_optab><mode>" [(set (match_operand:SI 0 "s_register_operand" "=&r") - (unspec_volatile:SI [(not:SI (and:SI - (match_operand:SI 1 "arm_sync_memory_operand" "+Q") - (match_operand:SI 2 "s_register_operand" "r"))) - ] - VUNSPEC_SYNC_NEW_OP)) + (unspec_volatile:SI [(syncop:SI + (zero_extend:SI + (match_operand:NARROW 1 "arm_sync_memory_operand" "+Q")) + (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)) + (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" + "<sync_predtab>" { 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 "sync_op" "<sync_optab>") (set_attr "conds" "clob") (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 "arm_sync_memory_operand" "+Q")) - (match_operand:SI 2 "s_register_operand" "r")) - ] - VUNSPEC_SYNC_NEW_OP)) +(define_insn "arm_sync_new_nand<mode>" + [(set (match_operand:SIDI 0 "s_register_operand" "=&r") + (unspec_volatile:SIDI [(not:SIDI (and:SIDI + (match_operand:SIDI 1 "arm_sync_memory_operand" "+Q") + (match_operand:SIDI 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)) + (unspec_volatile:SIDI [(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" + "<sync_predtab>" { 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 "sync_op" "nand") (set_attr "conds" "clob") (set_attr "predicable" "no")]) @@ -461,19 +355,19 @@ (unspec_volatile:SI [(not:SI (and:SI - (zero_extend:SI - (match_operand:NARROW 1 "arm_sync_memory_operand" "+Q")) - (match_operand:SI 2 "s_register_operand" "r"))) + (zero_extend:SI + (match_operand:NARROW 1 "arm_sync_memory_operand" "+Q")) + (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)) + VUNSPEC_SYNC_NEW_OP)) (clobber (reg:CC CC_REGNUM)) (clobber (match_scratch:SI 3 "=&r"))] - "TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER" + "<sync_predtab>" { return arm_output_sync_insn (insn, operands); - } + } [(set_attr "sync_result" "0") (set_attr "sync_memory" "1") (set_attr "sync_new_value" "2") @@ -483,20 +377,20 @@ (set_attr "conds" "clob") (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 "arm_sync_memory_operand" "+Q") - (match_operand:SI 2 "s_register_operand" "r")) - ] - VUNSPEC_SYNC_OLD_OP)) +(define_insn "arm_sync_old_<sync_optab><mode>" + [(set (match_operand:SIDI 0 "s_register_operand" "=&r") + (unspec_volatile:SIDI [(syncop:SIDI + (match_operand:SIDI 1 "arm_sync_memory_operand" "+Q") + (match_operand:SIDI 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)) + (unspec_volatile:SIDI [(match_dup 1) (match_dup 2)] + VUNSPEC_SYNC_OLD_OP)) (clobber (reg:CC CC_REGNUM)) - (clobber (match_scratch:SI 3 "=&r")) + (clobber (match_scratch:SIDI 3 "=&r")) (clobber (match_scratch:SI 4 "<sync_clobber>"))] - "TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER" + "<sync_predtab>" { return arm_output_sync_insn (insn, operands); } @@ -509,20 +403,21 @@ (set_attr "conds" "clob") (set_attr "predicable" "no")]) -(define_insn "arm_sync_old_nandsi" +(define_insn "arm_sync_old_<sync_optab><mode>" [(set (match_operand:SI 0 "s_register_operand" "=&r") - (unspec_volatile:SI [(not:SI (and:SI - (match_operand:SI 1 "arm_sync_memory_operand" "+Q") - (match_operand:SI 2 "s_register_operand" "r"))) - ] - VUNSPEC_SYNC_OLD_OP)) + (unspec_volatile:SI [(syncop:SI + (zero_extend:SI + (match_operand:NARROW 1 "arm_sync_memory_operand" "+Q")) + (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)) + (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_LDREX && TARGET_HAVE_MEMORY_BARRIER" + (clobber (match_scratch:SI 4 "<sync_clobber>"))] + "<sync_predtab>" { return arm_output_sync_insn (insn, operands); } @@ -530,26 +425,25 @@ (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 "sync_t2" "<sync_t2_reqd>") + (set_attr "sync_op" "<sync_optab>") (set_attr "conds" "clob") (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 "arm_sync_memory_operand" "+Q")) - (match_operand:SI 2 "s_register_operand" "r")) - ] - VUNSPEC_SYNC_OLD_OP)) +(define_insn "arm_sync_old_nand<mode>" + [(set (match_operand:SIDI 0 "s_register_operand" "=&r") + (unspec_volatile:SIDI [(not:SIDI (and:SIDI + (match_operand:SIDI 1 "arm_sync_memory_operand" "+Q") + (match_operand:SIDI 2 "s_register_operand" "r"))) + ] + VUNSPEC_SYNC_OLD_OP)) (set (match_dup 1) - (unspec_volatile:NARROW [(match_dup 1) (match_dup 2)] + (unspec_volatile:SIDI [(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 "<sync_clobber>"))] - "TARGET_HAVE_LDREXBHD && TARGET_HAVE_MEMORY_BARRIER" + (clobber (match_scratch:SIDI 3 "=&r")) + (clobber (match_scratch:SI 4 "=&r"))] + "<sync_predtab>" { return arm_output_sync_insn (insn, operands); } @@ -557,26 +451,26 @@ (set_attr "sync_memory" "1") (set_attr "sync_new_value" "2") (set_attr "sync_t1" "3") - (set_attr "sync_t2" "<sync_t2_reqd>") - (set_attr "sync_op" "<sync_optab>") + (set_attr "sync_t2" "4") + (set_attr "sync_op" "nand") (set_attr "conds" "clob") (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 "arm_sync_memory_operand" "+Q")) - (match_operand:SI 2 "s_register_operand" "r"))) - ] - VUNSPEC_SYNC_OLD_OP)) + (unspec_volatile:SI [(not:SI (and:SI + (zero_extend:SI + (match_operand:NARROW 1 "arm_sync_memory_operand" "+Q")) + (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)) + (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" + "<sync_predtab>" { return arm_output_sync_insn (insn, operands); } |