OSDN Git Service

Revert delta 190174
[pf3gnuchains/gcc-fork.git] / gcc / config / ia64 / sync.md
1 ;; GCC machine description for IA-64 synchronization instructions.
2 ;; Copyright (C) 2005, 2007, 2008, 2009, 2010
3 ;; Free Software Foundation, Inc.
4 ;;
5 ;; This file is part of GCC.
6 ;;
7 ;; GCC is free software; you can redistribute it and/or modify
8 ;; it under the terms of the GNU General Public License as published by
9 ;; the Free Software Foundation; either version 3, or (at your option)
10 ;; any later version.
11 ;;
12 ;; GCC is distributed in the hope that it will be useful,
13 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 ;; GNU General Public License for more details.
16 ;;
17 ;; You should have received a copy of the GNU General Public License
18 ;; along with GCC; see the file COPYING3.  If not see
19 ;; <http://www.gnu.org/licenses/>.
20
21 ;; Conversion to C++11 memory model based on
22 ;; http://www.cl.cam.ac.uk/~pes20/cpp/cpp0xmappings.html
23
24 (define_mode_iterator IMODE [QI HI SI DI])
25 (define_mode_iterator I124MODE [QI HI SI])
26 (define_mode_iterator I48MODE [SI DI])
27 (define_mode_attr modesuffix [(QI "1") (HI "2") (SI "4") (DI "8")])
28
29 (define_code_iterator FETCHOP [plus minus ior xor and])
30 (define_code_attr fetchop_name
31   [(plus "add") (minus "sub") (ior "or") (xor "xor") (and "and")])
32
33 (define_expand "mem_thread_fence"
34   [(match_operand:SI 0 "const_int_operand" "")]         ;; model
35   ""
36 {
37   if (INTVAL (operands[0]) == MEMMODEL_SEQ_CST)
38     emit_insn (gen_memory_barrier ());
39   DONE;
40 })
41
42 (define_expand "memory_barrier"
43   [(set (match_dup 0)
44         (unspec:BLK [(match_dup 0)] UNSPEC_MF))]
45   ""
46 {
47   operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
48   MEM_VOLATILE_P (operands[0]) = 1;
49 })
50
51 (define_insn "*memory_barrier"
52   [(set (match_operand:BLK 0 "" "")
53         (unspec:BLK [(match_dup 0)] UNSPEC_MF))]
54   ""
55   "mf"
56   [(set_attr "itanium_class" "syst_m")])
57
58 (define_expand "atomic_load<mode>"
59   [(match_operand:IMODE 0 "gr_register_operand" "")             ;; output
60    (match_operand:IMODE 1 "memory_operand" "")                  ;; memory
61    (match_operand:SI 2 "const_int_operand" "")]                 ;; model
62   ""
63 {
64   enum memmodel model = (enum memmodel) INTVAL (operands[2]);
65
66   /* Unless the memory model is relaxed, we want to emit ld.acq, which
67      will happen automatically for volatile memories.  */
68   gcc_assert (model == MEMMODEL_RELAXED || MEM_VOLATILE_P (operands[1]));
69   emit_move_insn (operands[0], operands[1]);
70   DONE;
71 })
72
73 (define_expand "atomic_store<mode>"
74   [(match_operand:IMODE 0 "memory_operand" "")                  ;; memory
75    (match_operand:IMODE 1 "gr_reg_or_0_operand" "")             ;; input
76    (match_operand:SI 2 "const_int_operand" "")]                 ;; model
77   ""
78 {
79   enum memmodel model = (enum memmodel) INTVAL (operands[2]);
80
81   /* Unless the memory model is relaxed, we want to emit st.rel, which
82      will happen automatically for volatile memories.  */
83   gcc_assert (model == MEMMODEL_RELAXED || MEM_VOLATILE_P (operands[0]));
84   emit_move_insn (operands[0], operands[1]);
85
86   /* Sequentially consistent stores need a subsequent MF.  See
87      http://www.decadent.org.uk/pipermail/cpp-threads/2008-December/001952.html
88      for a discussion of why a MF is needed here, but not for atomic_load.  */
89   if (model == MEMMODEL_SEQ_CST)
90     emit_insn (gen_memory_barrier ());
91   DONE;
92 })
93
94 (define_expand "atomic_compare_and_swap<mode>"
95   [(match_operand:DI 0 "gr_register_operand" "")                ;; bool out
96    (match_operand:IMODE 1 "gr_register_operand" "")             ;; val out
97    (match_operand:IMODE 2 "not_postinc_memory_operand" "")      ;; memory
98    (match_operand:IMODE 3 "gr_register_operand" "")             ;; expected
99    (match_operand:IMODE 4 "gr_reg_or_0_operand" "")             ;; desired
100    (match_operand:SI 5 "const_int_operand" "")                  ;; is_weak
101    (match_operand:SI 6 "const_int_operand" "")                  ;; succ model
102    (match_operand:SI 7 "const_int_operand" "")]                 ;; fail model
103   ""
104 {
105   enum memmodel model = (enum memmodel) INTVAL (operands[6]);
106   rtx ccv = gen_rtx_REG (DImode, AR_CCV_REGNUM);
107   rtx dval, eval;
108
109   eval = gen_reg_rtx (DImode);
110   convert_move (eval, operands[3], 1);
111   emit_move_insn (ccv, eval);
112
113   if (<MODE>mode == DImode)
114     dval = operands[1];
115   else
116     dval = gen_reg_rtx (DImode);
117
118   switch (model)
119     {
120     case MEMMODEL_RELAXED:
121     case MEMMODEL_ACQUIRE:
122     case MEMMODEL_CONSUME:
123       emit_insn (gen_cmpxchg_acq_<mode> (dval, operands[2], ccv, operands[4]));
124       break;
125     case MEMMODEL_RELEASE:
126       emit_insn (gen_cmpxchg_rel_<mode> (dval, operands[2], ccv, operands[4]));
127       break;
128     case MEMMODEL_ACQ_REL:
129     case MEMMODEL_SEQ_CST:
130       emit_insn (gen_cmpxchg_rel_<mode> (dval, operands[2], ccv, operands[4]));
131       emit_insn (gen_memory_barrier ());
132       break;
133     default:
134       gcc_unreachable ();
135     }
136
137   if (<MODE>mode != DImode)
138     emit_move_insn (operands[1], gen_lowpart (<MODE>mode, dval));
139
140   emit_insn (gen_cstoredi4 (operands[0], gen_rtx_EQ (DImode, dval, eval),
141                             dval, eval));
142   DONE;
143 })
144
145 (define_insn "cmpxchg_acq_<mode>"
146   [(set (match_operand:DI 0 "gr_register_operand" "=r")
147         (zero_extend:DI
148           (match_operand:I124MODE 1 "not_postinc_memory_operand" "+S")))
149    (set (match_dup 1)
150         (unspec:I124MODE
151           [(match_dup 1)
152            (match_operand:DI 2 "ar_ccv_reg_operand" "")
153            (match_operand:I124MODE 3 "gr_reg_or_0_operand" "rO")]
154           UNSPEC_CMPXCHG_ACQ))]
155   ""
156   "cmpxchg<modesuffix>.acq %0 = %1, %r3, %2"
157   [(set_attr "itanium_class" "sem")])
158
159 (define_insn "cmpxchg_rel_<mode>"
160   [(set (match_operand:DI 0 "gr_register_operand" "=r")
161         (zero_extend:DI
162           (match_operand:I124MODE 1 "not_postinc_memory_operand" "+S")))
163    (set (match_dup 1)
164         (unspec:I124MODE
165           [(match_dup 1)
166            (match_operand:DI 2 "ar_ccv_reg_operand" "")
167            (match_operand:I124MODE 3 "gr_reg_or_0_operand" "rO")]
168           UNSPEC_CMPXCHG_REL))]
169   ""
170   "cmpxchg<modesuffix>.rel %0 = %1, %r3, %2"
171   [(set_attr "itanium_class" "sem")])
172
173 (define_insn "cmpxchg_acq_di"
174   [(set (match_operand:DI 0 "gr_register_operand" "=r")
175         (match_operand:DI 1 "not_postinc_memory_operand" "+S"))
176    (set (match_dup 1)
177         (unspec:DI [(match_dup 1)
178                     (match_operand:DI 2 "ar_ccv_reg_operand" "")
179                     (match_operand:DI 3 "gr_reg_or_0_operand" "rO")]
180                    UNSPEC_CMPXCHG_ACQ))]
181   ""
182   "cmpxchg8.acq %0 = %1, %r3, %2"
183   [(set_attr "itanium_class" "sem")])
184
185 (define_insn "cmpxchg_rel_di"
186   [(set (match_operand:DI 0 "gr_register_operand" "=r")
187         (match_operand:DI 1 "not_postinc_memory_operand" "+S"))
188    (set (match_dup 1)
189         (unspec:DI [(match_dup 1)
190                     (match_operand:DI 2 "ar_ccv_reg_operand" "")
191                     (match_operand:DI 3 "gr_reg_or_0_operand" "rO")]
192                    UNSPEC_CMPXCHG_REL))]
193   ""
194   "cmpxchg8.rel %0 = %1, %r3, %2"
195   [(set_attr "itanium_class" "sem")])
196
197 (define_expand "atomic_exchange<mode>"
198   [(match_operand:IMODE 0 "gr_register_operand" "")             ;; output
199    (match_operand:IMODE 1 "not_postinc_memory_operand" "")      ;; memory
200    (match_operand:IMODE 2 "gr_reg_or_0_operand" "")             ;; input
201    (match_operand:SI 3 "const_int_operand" "")]                 ;; succ model
202   ""
203 {
204   enum memmodel model = (enum memmodel) INTVAL (operands[3]);
205
206   switch (model)
207     {
208     case MEMMODEL_RELAXED:
209     case MEMMODEL_ACQUIRE:
210     case MEMMODEL_CONSUME:
211       break;
212     case MEMMODEL_RELEASE:
213     case MEMMODEL_ACQ_REL:
214     case MEMMODEL_SEQ_CST:
215       emit_insn (gen_memory_barrier ());
216       break;
217     default:
218       gcc_unreachable ();
219     }
220   emit_insn (gen_xchg_acq_<mode> (operands[0], operands[1], operands[2]));
221   DONE;
222 })
223
224 ;; Note that XCHG is always memory model acquire.
225 (define_insn "xchg_acq_<mode>"
226   [(set (match_operand:IMODE 0 "gr_register_operand" "=r")
227         (match_operand:IMODE 1 "not_postinc_memory_operand" "+S"))
228    (set (match_dup 1)
229         (match_operand:IMODE 2 "gr_reg_or_0_operand" "rO"))]
230   ""
231   "xchg<modesuffix> %0 = %1, %r2"
232   [(set_attr "itanium_class" "sem")])
233
234 (define_expand "atomic_<fetchop_name><mode>"
235   [(set (match_operand:IMODE 0 "memory_operand" "")
236         (FETCHOP:IMODE (match_dup 0)
237           (match_operand:IMODE 1 "nonmemory_operand" "")))
238    (use (match_operand:SI 2 "const_int_operand" ""))]
239   ""
240 {
241   ia64_expand_atomic_op (<CODE>, operands[0], operands[1], NULL, NULL,
242                          (enum memmodel) INTVAL (operands[2]));
243   DONE;
244 })
245
246 (define_expand "atomic_nand<mode>"
247   [(set (match_operand:IMODE 0 "memory_operand" "")
248         (not:IMODE
249           (and:IMODE (match_dup 0)
250                      (match_operand:IMODE 1 "nonmemory_operand" ""))))
251    (use (match_operand:SI 2 "const_int_operand" ""))]
252   ""
253 {
254   ia64_expand_atomic_op (NOT, operands[0], operands[1], NULL, NULL,
255                          (enum memmodel) INTVAL (operands[2]));
256   DONE;
257 })
258
259 (define_expand "atomic_fetch_<fetchop_name><mode>"
260   [(set (match_operand:IMODE 0 "gr_register_operand" "")
261         (FETCHOP:IMODE 
262           (match_operand:IMODE 1 "memory_operand" "")
263           (match_operand:IMODE 2 "nonmemory_operand" "")))
264    (use (match_operand:SI 3 "const_int_operand" ""))]
265   ""
266 {
267   ia64_expand_atomic_op (<CODE>, operands[1], operands[2], operands[0], NULL,
268                          (enum memmodel) INTVAL (operands[3]));
269   DONE;
270 })
271
272 (define_expand "atomic_fetch_nand<mode>"
273   [(set (match_operand:IMODE 0 "gr_register_operand" "")
274         (not:IMODE 
275           (and:IMODE (match_operand:IMODE 1 "memory_operand" "")
276                      (match_operand:IMODE 2 "nonmemory_operand" ""))))
277    (use (match_operand:SI 3 "const_int_operand" ""))]
278   ""
279 {
280   ia64_expand_atomic_op (NOT, operands[1], operands[2], operands[0], NULL,
281                          (enum memmodel) INTVAL (operands[3]));
282   DONE;
283 })
284
285 (define_expand "atomic_<fetchop_name>_fetch<mode>"
286   [(set (match_operand:IMODE 0 "gr_register_operand" "")
287         (FETCHOP:IMODE 
288           (match_operand:IMODE 1 "memory_operand" "")
289           (match_operand:IMODE 2 "nonmemory_operand" "")))
290    (use (match_operand:SI 3 "const_int_operand" ""))]
291   ""
292 {
293   ia64_expand_atomic_op (<CODE>, operands[1], operands[2], NULL, operands[0],
294                          (enum memmodel) INTVAL (operands[3]));
295   DONE;
296 })
297
298 (define_expand "atomic_nand_fetch<mode>"
299   [(set (match_operand:IMODE 0 "gr_register_operand" "")
300         (not:IMODE 
301           (and:IMODE (match_operand:IMODE 1 "memory_operand" "")
302                      (match_operand:IMODE 2 "nonmemory_operand" ""))))
303    (use (match_operand:SI 3 "const_int_operand" ""))]
304   ""
305 {
306   ia64_expand_atomic_op (NOT, operands[1], operands[2], NULL, operands[0],
307                          (enum memmodel) INTVAL (operands[3]));
308   DONE;
309 })
310
311 (define_insn "fetchadd_acq_<mode>"
312   [(set (match_operand:I48MODE 0 "gr_register_operand" "=r")
313         (match_operand:I48MODE 1 "not_postinc_memory_operand" "+S"))
314    (set (match_dup 1)
315         (unspec:I48MODE [(match_dup 1)
316                          (match_operand:I48MODE 2 "fetchadd_operand" "n")]
317                         UNSPEC_FETCHADD_ACQ))]
318   ""
319   "fetchadd<modesuffix>.acq %0 = %1, %2"
320   [(set_attr "itanium_class" "sem")])
321
322 (define_insn "fetchadd_rel_<mode>"
323   [(set (match_operand:I48MODE 0 "gr_register_operand" "=r")
324         (match_operand:I48MODE 1 "not_postinc_memory_operand" "+S"))
325    (set (match_dup 1)
326         (unspec:I48MODE [(match_dup 1)
327                          (match_operand:I48MODE 2 "fetchadd_operand" "n")]
328                         UNSPEC_FETCHADD_REL))]
329   ""
330   "fetchadd<modesuffix>.rel %0 = %1, %2"
331   [(set_attr "itanium_class" "sem")])