OSDN Git Service

Backport from mainline:
[pf3gnuchains/gcc-fork.git] / gcc / config / tilegx / sync.md
1 ;; GCC machine description for Tilera TILE-Gx synchronization
2 ;; instructions.
3 ;; Copyright (C) 2011, 2012
4 ;; Free Software Foundation, Inc.
5 ;; Contributed by Walter Lee (walt@tilera.com)
6 ;;
7 ;; This file is part of GCC.
8 ;;
9 ;; GCC is free software; you can redistribute it and/or modify it
10 ;; under the terms of the GNU General Public License as published
11 ;; by the Free Software Foundation; either version 3, or (at your
12 ;; option) any later version.
13 ;;
14 ;; GCC is distributed in the hope that it will be useful, but WITHOUT
15 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16 ;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
17 ;; License for more details.
18 ;;
19 ;; You should have received a copy of the GNU General Public License
20 ;; along with GCC; see the file COPYING3.  If not see
21 ;; <http://www.gnu.org/licenses/>.
22
23 (define_code_iterator fetchop [plus ior and])
24 (define_code_attr fetchop_name [(plus "add") (ior "or") (and "and")])
25
26 (define_insn "mtspr_cmpexch<mode>"
27   [(set (reg:I48MODE TILEGX_CMPEXCH_REG)
28         (unspec_volatile:I48MODE
29          [(match_operand:I48MODE 0 "reg_or_0_operand" "rO")]
30          UNSPEC_SPR_MOVE))]
31   ""
32   "mtspr\tCMPEXCH_VALUE, %r0"
33   [(set_attr "type" "X1")])
34
35
36 (define_expand "atomic_compare_and_swap<mode>"
37   [(match_operand:DI 0 "register_operand" "")           ;; bool output
38    (match_operand:I48MODE 1 "register_operand" "")      ;; val output
39    (match_operand:I48MODE 2 "nonautoincmem_operand" "") ;; memory
40    (match_operand:I48MODE 3 "reg_or_0_operand" "")      ;; expected value
41    (match_operand:I48MODE 4 "reg_or_0_operand" "")      ;; desired value
42    (match_operand:SI 5 "const_int_operand" "")          ;; is_weak
43    (match_operand:SI 6 "const_int_operand" "")          ;; mod_s
44    (match_operand:SI 7 "const_int_operand" "")]         ;; mod_f
45   ""
46 {
47   enum memmodel mod_s = (enum memmodel) INTVAL (operands[6]);
48
49   if (operands[3] != const0_rtx)
50     operands[3] = force_reg (<MODE>mode, operands[3]);
51   if (operands[4] != const0_rtx)
52     operands[4] = force_reg (<MODE>mode, operands[4]);
53
54   tilegx_pre_atomic_barrier (mod_s);
55   emit_insn (gen_mtspr_cmpexch<mode> (operands[3]));
56   emit_insn (gen_atomic_compare_and_swap_bare<mode> (operands[1], operands[2],
57                                                    operands[4]));
58   tilegx_post_atomic_barrier (mod_s);
59   emit_insn (gen_insn_cmpeq_<mode>di (operands[0], operands[1], operands[3]));
60   DONE;
61 })
62
63
64 (define_insn "atomic_compare_and_swap_bare<mode>"
65   [(set (match_operand:I48MODE 0 "register_operand" "=r")
66         (match_operand:I48MODE 1 "nonautoincmem_operand" "+U"))
67    (set (match_dup 1)
68         (unspec_volatile:I48MODE
69          [(match_dup 1)
70          (reg:I48MODE TILEGX_CMPEXCH_REG)
71          (match_operand:I48MODE 2 "reg_or_0_operand" "rO")]
72          UNSPEC_CMPXCHG))]
73   ""
74   "cmpexch<four_if_si>\t%0, %1, %r2"
75   [(set_attr "type" "X1_L2")])
76
77
78 (define_expand "atomic_exchange<mode>"
79   [(match_operand:I48MODE 0 "register_operand" "")      ;; result
80    (match_operand:I48MODE 1 "nonautoincmem_operand" "") ;; memory
81    (match_operand:I48MODE 2 "reg_or_0_operand" "")      ;; input
82    (match_operand:SI 3 "const_int_operand" "")]         ;; model
83   ""
84 {
85   enum memmodel model = (enum memmodel) INTVAL (operands[3]);
86
87   tilegx_pre_atomic_barrier (model);
88   emit_insn (gen_atomic_exchange_bare<mode> (operands[0], operands[1],
89                                              operands[2]));
90   tilegx_post_atomic_barrier (model);
91   DONE;
92 })
93
94
95 (define_insn "atomic_exchange_bare<mode>"
96   [(set (match_operand:I48MODE 0 "register_operand" "=r")
97         (match_operand:I48MODE 1 "nonautoincmem_operand" "+U"))
98    (set (match_dup 1)
99         (unspec_volatile:I48MODE
100          [(match_operand:I48MODE 2 "reg_or_0_operand" "rO")]
101          UNSPEC_XCHG))]
102   ""
103   "exch<four_if_si>\t%0, %1, %r2"
104   [(set_attr "type" "X1_2cycle")])
105
106
107 (define_expand "atomic_fetch_<fetchop_name><mode>"
108   [(match_operand:I48MODE 0 "register_operand" "")      ;; result
109    (match_operand:I48MODE 1 "nonautoincmem_operand" "") ;; memory
110    (unspec_volatile:I48MODE
111     [(fetchop:I48MODE
112       (match_dup 1)
113       (match_operand:I48MODE 2 "reg_or_0_operand" ""))] ;; value
114     UNSPEC_ATOMIC)
115    (match_operand:SI 3 "const_int_operand" "")]         ;; model
116   ""
117 {
118   enum memmodel model = (enum memmodel) INTVAL (operands[3]);
119
120   tilegx_pre_atomic_barrier (model);
121   emit_insn (gen_atomic_fetch_<fetchop_name>_bare<mode> (operands[0],
122                                                          operands[1],
123                                                          operands[2]));
124   tilegx_post_atomic_barrier (model);
125   DONE;
126 })
127
128
129 (define_insn "atomic_fetch_<fetchop_name>_bare<mode>"
130   [(set (match_operand:I48MODE 0 "register_operand" "=r")
131         (match_operand:I48MODE 1 "nonautoincmem_operand" "+U"))
132    (set (match_dup 1)
133         (unspec_volatile:I48MODE
134          [(fetchop:I48MODE
135            (match_dup 1)
136            (match_operand:I48MODE 2 "reg_or_0_operand" "rO"))]
137            UNSPEC_ATOMIC))]
138   ""
139   "fetch<fetchop_name><four_if_si>\t%0, %1, %r2"
140   [(set_attr "type" "X1_2cycle")])
141
142
143 (define_expand "atomic_fetch_sub<mode>"
144   [(match_operand:I48MODE 0 "register_operand" "")      ;; result
145    (match_operand:I48MODE 1 "nonautoincmem_operand" "") ;; memory
146    (unspec_volatile:I48MODE
147     [(minus:I48MODE
148       (match_dup 1)
149       (match_operand:I48MODE 2 "reg_or_0_operand" ""))] ;; value
150     UNSPEC_ATOMIC)
151    (match_operand:SI 3 "const_int_operand" "")]         ;; model
152   ""
153 {
154   enum memmodel model = (enum memmodel) INTVAL (operands[3]);
155
156   if (operands[2] != const0_rtx)
157     emit_move_insn (operands[2], gen_rtx_NEG (<MODE>mode, operands[2]));
158
159   tilegx_pre_atomic_barrier (model);
160   emit_insn (gen_atomic_fetch_add_bare<mode> (operands[0],
161                                               operands[1],
162                                               operands[2]));
163   tilegx_post_atomic_barrier (model);
164   DONE;
165 })