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