Imported Upstream version 4.8.1
[platform/upstream/gcc48.git] / gcc / config / rs6000 / sync.md
1 ;; Machine description for PowerPC synchronization instructions.
2 ;; Copyright (C) 2005-2013 Free Software Foundation, Inc.
3 ;; Contributed by Geoffrey Keating.
4
5 ;; This file is part of GCC.
6
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.
11
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.
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 (define_mode_attr larx [(SI "lwarx") (DI "ldarx")])
22 (define_mode_attr stcx [(SI "stwcx.") (DI "stdcx.")])
23
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")])
30
31 (define_expand "mem_thread_fence"
32   [(match_operand:SI 0 "const_int_operand" "")]         ;; model
33   ""
34 {
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;
53 })
54
55 (define_expand "hwsync"
56   [(set (match_dup 0)
57         (unspec:BLK [(match_dup 0)] UNSPEC_SYNC))]
58   ""
59 {
60   operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
61   MEM_VOLATILE_P (operands[0]) = 1;
62 })
63
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")])
70
71 (define_expand "lwsync"
72   [(set (match_dup 0)
73         (unspec:BLK [(match_dup 0)] UNSPEC_LWSYNC))]
74   ""
75 {
76   operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
77   MEM_VOLATILE_P (operands[0]) = 1;
78 })
79
80 (define_insn "*lwsync"
81   [(set (match_operand:BLK 0 "" "")
82         (unspec:BLK [(match_dup 0)] UNSPEC_LWSYNC))]
83   ""
84 {
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";
92 }
93   [(set_attr "type" "sync")])
94
95 (define_insn "isync"
96   [(unspec_volatile:BLK [(const_int 0)] UNSPECV_ISYNC)]
97   ""
98   "isync"
99   [(set_attr "type" "isync")])
100
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")])
111
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   ""
117 {
118   enum memmodel model = (enum memmodel) INTVAL (operands[2]);
119
120   if (model == MEMMODEL_SEQ_CST)
121     emit_insn (gen_hwsync ());
122
123   emit_move_insn (operands[0], operands[1]);
124
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;
147 })
148
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   ""
154 {
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;
171 })
172
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.
176
177 (define_mode_iterator ATOMIC    [SI (DI "TARGET_POWERPC64")])
178
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")])
186
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")])
195
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   ""
206 {
207   rs6000_expand_atomic_compare_and_swap (operands);
208   DONE;
209 })
210
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   ""
217 {
218   rs6000_expand_atomic_exchange (operands);
219   DONE;
220 })
221
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   ""
228 {
229   rs6000_expand_atomic_op (<CODE>, operands[0], operands[1],
230                            NULL_RTX, NULL_RTX, operands[2]);
231   DONE;
232 })
233
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   ""
239 {
240   rs6000_expand_atomic_op (NOT, operands[0], operands[1],
241                            NULL_RTX, NULL_RTX, operands[2]);
242   DONE;
243 })
244
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   ""
252
253   rs6000_expand_atomic_op (<CODE>, operands[1], operands[2],
254                            operands[0], NULL_RTX, operands[3]);
255   DONE;
256 })
257
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   ""
264 {
265   rs6000_expand_atomic_op (NOT, operands[1], operands[2],
266                            operands[0], NULL_RTX, operands[3]);
267   DONE;
268 })
269
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   ""
277 {
278   rs6000_expand_atomic_op (<CODE>, operands[1], operands[2],
279                            NULL_RTX, operands[0], operands[3]);
280   DONE;
281 })
282
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   ""
289 {
290   rs6000_expand_atomic_op (NOT, operands[1], operands[2],
291                            NULL_RTX, operands[0], operands[3]);
292   DONE;
293 })