gcc/
[official-gcc.git] / gcc / config / rs6000 / sync.md
blobddf2ae7494509f6c412e4d7d4dc09d3e2ceb16a2
1 ;; Machine description for PowerPC synchronization instructions.
2 ;; Copyright (C) 2005-2012 Free Software Foundation, Inc.
3 ;; Contributed by Geoffrey Keating.
5 ;; This file is part of GCC.
7 ;; GCC is free software; you can redistribute it and/or modify it
8 ;; under the terms of the GNU General Public License as published
9 ;; by the Free Software Foundation; either version 3, or (at your
10 ;; option) any later version.
12 ;; GCC is distributed in the hope that it will be useful, but WITHOUT
13 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 ;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
15 ;; License for more details.
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/>.
21 (define_mode_attr larx [(SI "lwarx") (DI "ldarx")])
22 (define_mode_attr stcx [(SI "stwcx.") (DI "stdcx.")])
24 (define_code_iterator FETCHOP [plus minus ior xor and])
25 (define_code_attr fetchop_name
26   [(plus "add") (minus "sub") (ior "or") (xor "xor") (and "and")])
27 (define_code_attr fetchop_pred
28   [(plus "add_operand") (minus "gpc_reg_operand")
29    (ior "logical_operand") (xor "logical_operand") (and "and_operand")])
31 (define_expand "mem_thread_fence"
32   [(match_operand:SI 0 "const_int_operand" "")]         ;; model
33   ""
35   enum memmodel model = (enum memmodel) INTVAL (operands[0]);
36   switch (model)
37     {
38     case MEMMODEL_RELAXED:
39       break;
40     case MEMMODEL_CONSUME:
41     case MEMMODEL_ACQUIRE:
42     case MEMMODEL_RELEASE:
43     case MEMMODEL_ACQ_REL:
44       emit_insn (gen_lwsync ());
45       break;
46     case MEMMODEL_SEQ_CST:
47       emit_insn (gen_hwsync ());
48       break;
49     default:
50       gcc_unreachable ();
51     }
52   DONE;
55 (define_expand "hwsync"
56   [(set (match_dup 0)
57         (unspec:BLK [(match_dup 0)] UNSPEC_SYNC))]
58   ""
60   operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
61   MEM_VOLATILE_P (operands[0]) = 1;
64 (define_insn "*hwsync"
65   [(set (match_operand:BLK 0 "" "")
66         (unspec:BLK [(match_dup 0)] UNSPEC_SYNC))]
67   ""
68   "sync"
69   [(set_attr "type" "sync")])
71 (define_expand "lwsync"
72   [(set (match_dup 0)
73         (unspec:BLK [(match_dup 0)] UNSPEC_LWSYNC))]
74   ""
76   operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
77   MEM_VOLATILE_P (operands[0]) = 1;
80 (define_insn "*lwsync"
81   [(set (match_operand:BLK 0 "" "")
82         (unspec:BLK [(match_dup 0)] UNSPEC_LWSYNC))]
83   ""
85   /* Some AIX assemblers don't accept lwsync, so we use a .long.  */
86   if (TARGET_NO_LWSYNC)
87     return "sync";
88   else if (TARGET_LWSYNC_INSTRUCTION)
89     return "lwsync";
90   else
91     return ".long 0x7c2004ac";
93   [(set_attr "type" "sync")])
95 (define_insn "isync"
96   [(unspec_volatile:BLK [(const_int 0)] UNSPECV_ISYNC)]
97   ""
98   "isync"
99   [(set_attr "type" "isync")])
101 ;; The control dependency used for load dependency described
102 ;; in B.2.3 of the Power ISA 2.06B.
103 (define_insn "loadsync_<mode>"
104   [(unspec_volatile:BLK [(match_operand:INT1 0 "register_operand" "r")]
105                         UNSPECV_ISYNC)
106    (clobber (match_scratch:CC 1 "=y"))]
107   ""
108   "cmpw %1,%0,%0\;bne- %1,$+4\;isync"
109   [(set_attr "type" "isync")
110    (set_attr "length" "12")])
112 (define_expand "atomic_load<mode>"
113   [(set (match_operand:INT1 0 "register_operand" "")            ;; output
114         (match_operand:INT1 1 "memory_operand" ""))             ;; memory
115    (use (match_operand:SI 2 "const_int_operand" ""))]           ;; model
116   ""
118   enum memmodel model = (enum memmodel) INTVAL (operands[2]);
120   if (model == MEMMODEL_SEQ_CST)
121     emit_insn (gen_hwsync ());
123   emit_move_insn (operands[0], operands[1]);
125   switch (model)
126     {
127     case MEMMODEL_RELAXED:
128       break;
129     case MEMMODEL_CONSUME:
130     case MEMMODEL_ACQUIRE:
131     case MEMMODEL_SEQ_CST:
132       if (GET_MODE (operands[0]) == QImode)
133         emit_insn (gen_loadsync_qi (operands[0]));
134       else if (GET_MODE (operands[0]) == HImode)
135         emit_insn (gen_loadsync_hi (operands[0]));
136       else if (GET_MODE (operands[0]) == SImode)
137         emit_insn (gen_loadsync_si (operands[0]));
138       else if (GET_MODE (operands[0]) == DImode)
139         emit_insn (gen_loadsync_di (operands[0]));
140       else
141         gcc_unreachable ();
142       break;
143     default:
144       gcc_unreachable ();
145     }
146   DONE;
149 (define_expand "atomic_store<mode>"
150   [(set (match_operand:INT1 0 "memory_operand" "")              ;; memory
151         (match_operand:INT1 1 "register_operand" ""))           ;; input
152    (use (match_operand:SI 2 "const_int_operand" ""))]           ;; model
153   ""
155   enum memmodel model = (enum memmodel) INTVAL (operands[2]);
156   switch (model)
157     {
158     case MEMMODEL_RELAXED:
159       break;
160     case MEMMODEL_RELEASE:
161       emit_insn (gen_lwsync ());
162       break;
163     case MEMMODEL_SEQ_CST:
164       emit_insn (gen_hwsync ());
165       break;
166     default:
167       gcc_unreachable ();
168     }
169   emit_move_insn (operands[0], operands[1]);
170   DONE;
173 ;; ??? Power ISA 2.06B says that there *is* a load-{byte,half}-and-reserve
174 ;; opcode that is "phased-in".  Not implemented as of Power7, so not yet used,
175 ;; but let's prepare the macros anyway.
177 (define_mode_iterator ATOMIC    [SI (DI "TARGET_POWERPC64")])
179 (define_insn "load_locked<mode>"
180   [(set (match_operand:ATOMIC 0 "gpc_reg_operand" "=r")
181         (unspec_volatile:ATOMIC
182          [(match_operand:ATOMIC 1 "memory_operand" "Z")] UNSPECV_LL))]
183   ""
184   "<larx> %0,%y1"
185   [(set_attr "type" "load_l")])
187 (define_insn "store_conditional<mode>"
188   [(set (match_operand:CC 0 "cc_reg_operand" "=x")
189         (unspec_volatile:CC [(const_int 0)] UNSPECV_SC))
190    (set (match_operand:ATOMIC 1 "memory_operand" "=Z")
191         (match_operand:ATOMIC 2 "gpc_reg_operand" "r"))]
192   ""
193   "<stcx> %2,%y1"
194   [(set_attr "type" "store_c")])
196 (define_expand "atomic_compare_and_swap<mode>"
197   [(match_operand:SI 0 "gpc_reg_operand" "")            ;; bool out
198    (match_operand:INT1 1 "gpc_reg_operand" "")          ;; val out
199    (match_operand:INT1 2 "memory_operand" "")           ;; memory
200    (match_operand:INT1 3 "reg_or_short_operand" "")     ;; expected
201    (match_operand:INT1 4 "gpc_reg_operand" "")          ;; desired
202    (match_operand:SI 5 "const_int_operand" "")          ;; is_weak
203    (match_operand:SI 6 "const_int_operand" "")          ;; model succ
204    (match_operand:SI 7 "const_int_operand" "")]         ;; model fail
205   ""
207   rs6000_expand_atomic_compare_and_swap (operands);
208   DONE;
211 (define_expand "atomic_exchange<mode>"
212   [(match_operand:INT1 0 "gpc_reg_operand" "")          ;; output
213    (match_operand:INT1 1 "memory_operand" "")           ;; memory
214    (match_operand:INT1 2 "gpc_reg_operand" "")          ;; input
215    (match_operand:SI 3 "const_int_operand" "")]         ;; model
216   ""
218   rs6000_expand_atomic_exchange (operands);
219   DONE;
222 (define_expand "atomic_<fetchop_name><mode>"
223   [(match_operand:INT1 0 "memory_operand" "")           ;; memory
224    (FETCHOP:INT1 (match_dup 0)
225      (match_operand:INT1 1 "<fetchop_pred>" ""))        ;; operand
226    (match_operand:SI 2 "const_int_operand" "")]         ;; model
227   ""
229   rs6000_expand_atomic_op (<CODE>, operands[0], operands[1],
230                            NULL_RTX, NULL_RTX, operands[2]);
231   DONE;
234 (define_expand "atomic_nand<mode>"
235   [(match_operand:INT1 0 "memory_operand" "")           ;; memory
236    (match_operand:INT1 1 "gpc_reg_operand" "")          ;; operand
237    (match_operand:SI 2 "const_int_operand" "")]         ;; model
238   ""
240   rs6000_expand_atomic_op (NOT, operands[0], operands[1],
241                            NULL_RTX, NULL_RTX, operands[2]);
242   DONE;
245 (define_expand "atomic_fetch_<fetchop_name><mode>"
246   [(match_operand:INT1 0 "gpc_reg_operand" "")          ;; output
247    (match_operand:INT1 1 "memory_operand" "")           ;; memory
248    (FETCHOP:INT1 (match_dup 1)
249      (match_operand:INT1 2 "<fetchop_pred>" ""))        ;; operand
250    (match_operand:SI 3 "const_int_operand" "")]         ;; model
251   ""
253   rs6000_expand_atomic_op (<CODE>, operands[1], operands[2],
254                            operands[0], NULL_RTX, operands[3]);
255   DONE;
258 (define_expand "atomic_fetch_nand<mode>"
259   [(match_operand:INT1 0 "gpc_reg_operand" "")          ;; output
260    (match_operand:INT1 1 "memory_operand" "")           ;; memory
261    (match_operand:INT1 2 "gpc_reg_operand" "")          ;; operand
262    (match_operand:SI 3 "const_int_operand" "")]         ;; model
263   ""
265   rs6000_expand_atomic_op (NOT, operands[1], operands[2],
266                            operands[0], NULL_RTX, operands[3]);
267   DONE;
270 (define_expand "atomic_<fetchop_name>_fetch<mode>"
271   [(match_operand:INT1 0 "gpc_reg_operand" "")          ;; output
272    (match_operand:INT1 1 "memory_operand" "")           ;; memory
273    (FETCHOP:INT1 (match_dup 1)
274      (match_operand:INT1 2 "<fetchop_pred>" ""))        ;; operand
275    (match_operand:SI 3 "const_int_operand" "")]         ;; model
276   ""
278   rs6000_expand_atomic_op (<CODE>, operands[1], operands[2],
279                            NULL_RTX, operands[0], operands[3]);
280   DONE;
283 (define_expand "atomic_nand_fetch<mode>"
284   [(match_operand:INT1 0 "gpc_reg_operand" "")          ;; output
285    (match_operand:INT1 1 "memory_operand" "")           ;; memory
286    (match_operand:INT1 2 "gpc_reg_operand" "")          ;; operand
287    (match_operand:SI 3 "const_int_operand" "")]         ;; model
288   ""
290   rs6000_expand_atomic_op (NOT, operands[1], operands[2],
291                            NULL_RTX, operands[0], operands[3]);
292   DONE;