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
35 enum memmodel model = (enum memmodel) INTVAL (operands[0]);
38 case MEMMODEL_RELAXED:
40 case MEMMODEL_CONSUME:
41 case MEMMODEL_ACQUIRE:
42 case MEMMODEL_RELEASE:
43 case MEMMODEL_ACQ_REL:
44 emit_insn (gen_lwsync ());
46 case MEMMODEL_SEQ_CST:
47 emit_insn (gen_hwsync ());
55 (define_expand "hwsync"
57 (unspec:BLK [(match_dup 0)] UNSPEC_SYNC))]
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))]
69 [(set_attr "type" "sync")])
71 (define_expand "lwsync"
73 (unspec:BLK [(match_dup 0)] UNSPEC_LWSYNC))]
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))]
85 /* Some AIX assemblers don't accept lwsync, so we use a .long. */
88 else if (TARGET_LWSYNC_INSTRUCTION)
91 return ".long 0x7c2004ac";
93 [(set_attr "type" "sync")])
96 [(unspec_volatile:BLK [(const_int 0)] UNSPECV_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")]
106 (clobber (match_scratch:CC 1 "=y"))]
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
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]);
127 case MEMMODEL_RELAXED:
129 case MEMMODEL_CONSUME:
130 case MEMMODEL_ACQUIRE:
131 case MEMMODEL_SEQ_CST:
132 emit_insn (gen_loadsync (operands[0]));
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
146 enum memmodel model = (enum memmodel) INTVAL (operands[2]);
149 case MEMMODEL_RELAXED:
151 case MEMMODEL_RELEASE:
152 emit_insn (gen_lwsync ());
154 case MEMMODEL_SEQ_CST:
155 emit_insn (gen_hwsync ());
160 emit_move_insn (operands[0], operands[1]);
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))]
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"))]
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
198 rs6000_expand_atomic_compare_and_swap (operands);
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
209 rs6000_expand_atomic_exchange (operands);
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
220 rs6000_expand_atomic_op (<CODE>, operands[0], operands[1],
221 NULL_RTX, NULL_RTX, operands[2]);
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
231 rs6000_expand_atomic_op (NOT, operands[0], operands[1],
232 NULL_RTX, NULL_RTX, operands[2]);
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
244 rs6000_expand_atomic_op (<CODE>, operands[1], operands[2],
245 operands[0], NULL_RTX, operands[3]);
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
256 rs6000_expand_atomic_op (NOT, operands[1], operands[2],
257 operands[0], NULL_RTX, operands[3]);
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
269 rs6000_expand_atomic_op (<CODE>, operands[1], operands[2],
270 NULL_RTX, operands[0], operands[3]);
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
281 rs6000_expand_atomic_op (NOT, operands[1], operands[2],
282 NULL_RTX, operands[0], operands[3]);