2012-08-15 Segher Boessenkool <segher@kernel.crashing.org>
[official-gcc.git] / gcc / config / rs6000 / sync.md
blob59ad0c6103e99e9b059c46d0b314a78a4da0d396
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   "{dcs|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   "{ics|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"
104   [(unspec_volatile:BLK [(match_operand 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       emit_insn (gen_loadsync (operands[0]));
133       break;
134     default:
135       gcc_unreachable ();
136     }
137   DONE;
140 (define_expand "atomic_store<mode>"
141   [(set (match_operand:INT1 0 "memory_operand" "")              ;; memory
142         (match_operand:INT1 1 "register_operand" ""))           ;; input
143    (use (match_operand:SI 2 "const_int_operand" ""))]           ;; model
144   ""
146   enum memmodel model = (enum memmodel) INTVAL (operands[2]);
147   switch (model)
148     {
149     case MEMMODEL_RELAXED:
150       break;
151     case MEMMODEL_RELEASE:
152       emit_insn (gen_lwsync ());
153       break;
154     case MEMMODEL_SEQ_CST:
155       emit_insn (gen_hwsync ());
156       break;
157     default:
158       gcc_unreachable ();
159     }
160   emit_move_insn (operands[0], operands[1]);
161   DONE;
164 ;; ??? Power ISA 2.06B says that there *is* a load-{byte,half}-and-reserve
165 ;; opcode that is "phased-in".  Not implemented as of Power7, so not yet used,
166 ;; but let's prepare the macros anyway.
168 (define_mode_iterator ATOMIC    [SI (DI "TARGET_64BIT")])
170 (define_insn "load_locked<mode>"
171   [(set (match_operand:ATOMIC 0 "gpc_reg_operand" "=r")
172         (unspec_volatile:ATOMIC
173          [(match_operand:ATOMIC 1 "memory_operand" "Z")] UNSPECV_LL))]
174   ""
175   "<larx> %0,%y1"
176   [(set_attr "type" "load_l")])
178 (define_insn "store_conditional<mode>"
179   [(set (match_operand:CC 0 "cc_reg_operand" "=x")
180         (unspec_volatile:CC [(const_int 0)] UNSPECV_SC))
181    (set (match_operand:ATOMIC 1 "memory_operand" "=Z")
182         (match_operand:ATOMIC 2 "gpc_reg_operand" "r"))]
183   ""
184   "<stcx> %2,%y1"
185   [(set_attr "type" "store_c")])
187 (define_expand "atomic_compare_and_swap<mode>"
188   [(match_operand:SI 0 "gpc_reg_operand" "")            ;; bool out
189    (match_operand:INT1 1 "gpc_reg_operand" "")          ;; val out
190    (match_operand:INT1 2 "memory_operand" "")           ;; memory
191    (match_operand:INT1 3 "reg_or_short_operand" "")     ;; expected
192    (match_operand:INT1 4 "gpc_reg_operand" "")          ;; desired
193    (match_operand:SI 5 "const_int_operand" "")          ;; is_weak
194    (match_operand:SI 6 "const_int_operand" "")          ;; model succ
195    (match_operand:SI 7 "const_int_operand" "")]         ;; model fail
196   ""
198   rs6000_expand_atomic_compare_and_swap (operands);
199   DONE;
202 (define_expand "atomic_exchange<mode>"
203   [(match_operand:INT1 0 "gpc_reg_operand" "")          ;; output
204    (match_operand:INT1 1 "memory_operand" "")           ;; memory
205    (match_operand:INT1 2 "gpc_reg_operand" "")          ;; input
206    (match_operand:SI 3 "const_int_operand" "")]         ;; model
207   ""
209   rs6000_expand_atomic_exchange (operands);
210   DONE;
213 (define_expand "atomic_<fetchop_name><mode>"
214   [(match_operand:INT1 0 "memory_operand" "")           ;; memory
215    (FETCHOP:INT1 (match_dup 0)
216      (match_operand:INT1 1 "<fetchop_pred>" ""))        ;; operand
217    (match_operand:SI 2 "const_int_operand" "")]         ;; model
218   ""
220   rs6000_expand_atomic_op (<CODE>, operands[0], operands[1],
221                            NULL_RTX, NULL_RTX, operands[2]);
222   DONE;
225 (define_expand "atomic_nand<mode>"
226   [(match_operand:INT1 0 "memory_operand" "")           ;; memory
227    (match_operand:INT1 1 "gpc_reg_operand" "")          ;; operand
228    (match_operand:SI 2 "const_int_operand" "")]         ;; model
229   ""
231   rs6000_expand_atomic_op (NOT, operands[0], operands[1],
232                            NULL_RTX, NULL_RTX, operands[2]);
233   DONE;
236 (define_expand "atomic_fetch_<fetchop_name><mode>"
237   [(match_operand:INT1 0 "gpc_reg_operand" "")          ;; output
238    (match_operand:INT1 1 "memory_operand" "")           ;; memory
239    (FETCHOP:INT1 (match_dup 1)
240      (match_operand:INT1 2 "<fetchop_pred>" ""))        ;; operand
241    (match_operand:SI 3 "const_int_operand" "")]         ;; model
242   ""
244   rs6000_expand_atomic_op (<CODE>, operands[1], operands[2],
245                            operands[0], NULL_RTX, operands[3]);
246   DONE;
249 (define_expand "atomic_fetch_nand<mode>"
250   [(match_operand:INT1 0 "gpc_reg_operand" "")          ;; output
251    (match_operand:INT1 1 "memory_operand" "")           ;; memory
252    (match_operand:INT1 2 "gpc_reg_operand" "")          ;; operand
253    (match_operand:SI 3 "const_int_operand" "")]         ;; model
254   ""
256   rs6000_expand_atomic_op (NOT, operands[1], operands[2],
257                            operands[0], NULL_RTX, operands[3]);
258   DONE;
261 (define_expand "atomic_<fetchop_name>_fetch<mode>"
262   [(match_operand:INT1 0 "gpc_reg_operand" "")          ;; output
263    (match_operand:INT1 1 "memory_operand" "")           ;; memory
264    (FETCHOP:INT1 (match_dup 1)
265      (match_operand:INT1 2 "<fetchop_pred>" ""))        ;; operand
266    (match_operand:SI 3 "const_int_operand" "")]         ;; model
267   ""
269   rs6000_expand_atomic_op (<CODE>, operands[1], operands[2],
270                            NULL_RTX, operands[0], operands[3]);
271   DONE;
274 (define_expand "atomic_nand_fetch<mode>"
275   [(match_operand:INT1 0 "gpc_reg_operand" "")          ;; output
276    (match_operand:INT1 1 "memory_operand" "")           ;; memory
277    (match_operand:INT1 2 "gpc_reg_operand" "")          ;; operand
278    (match_operand:SI 3 "const_int_operand" "")]         ;; model
279   ""
281   rs6000_expand_atomic_op (NOT, operands[1], operands[2],
282                            NULL_RTX, operands[0], operands[3]);
283   DONE;