1 ;; Machine description for PowerPC synchronization instructions.
2 ;; Copyright (C) 2005, 2007, 2008, 2009, 2011
3 ;; Free Software Foundation, Inc.
4 ;; Contributed by Geoffrey Keating.
6 ;; This file is part of GCC.
8 ;; GCC is free software; you can redistribute it and/or modify it
9 ;; under the terms of the GNU General Public License as published
10 ;; by the Free Software Foundation; either version 3, or (at your
11 ;; option) any later version.
13 ;; GCC is distributed in the hope that it will be useful, but WITHOUT
14 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 ;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
16 ;; License for more details.
18 ;; You should have received a copy of the GNU General Public License
19 ;; along with GCC; see the file COPYING3. If not see
20 ;; <http://www.gnu.org/licenses/>.
22 (define_mode_attr larx [(SI "lwarx") (DI "ldarx")])
23 (define_mode_attr stcx [(SI "stwcx.") (DI "stdcx.")])
25 (define_code_iterator FETCHOP [plus minus ior xor and])
26 (define_code_attr fetchop_name
27 [(plus "add") (minus "sub") (ior "or") (xor "xor") (and "and")])
28 (define_code_attr fetchop_pred
29 [(plus "add_operand") (minus "gpc_reg_operand")
30 (ior "logical_operand") (xor "logical_operand") (and "and_operand")])
32 (define_expand "mem_thread_fence"
33 [(match_operand:SI 0 "const_int_operand" "")] ;; model
36 enum memmodel model = (enum memmodel) INTVAL (operands[0]);
39 case MEMMODEL_RELAXED:
41 case MEMMODEL_CONSUME:
42 case MEMMODEL_ACQUIRE:
43 case MEMMODEL_RELEASE:
44 case MEMMODEL_ACQ_REL:
45 emit_insn (gen_lwsync ());
47 case MEMMODEL_SEQ_CST:
48 emit_insn (gen_hwsync ());
56 (define_expand "hwsync"
58 (unspec:BLK [(match_dup 0)] UNSPEC_SYNC))]
61 operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
62 MEM_VOLATILE_P (operands[0]) = 1;
65 (define_insn "*hwsync"
66 [(set (match_operand:BLK 0 "" "")
67 (unspec:BLK [(match_dup 0)] UNSPEC_SYNC))]
70 [(set_attr "type" "sync")])
72 (define_expand "lwsync"
74 (unspec:BLK [(match_dup 0)] UNSPEC_LWSYNC))]
77 operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
78 MEM_VOLATILE_P (operands[0]) = 1;
81 (define_insn "*lwsync"
82 [(set (match_operand:BLK 0 "" "")
83 (unspec:BLK [(match_dup 0)] UNSPEC_LWSYNC))]
86 /* Some AIX assemblers don't accept lwsync, so we use a .long. */
89 else if (TARGET_LWSYNC_INSTRUCTION)
92 return ".long 0x7c2004ac";
94 [(set_attr "type" "sync")])
97 [(unspec_volatile:BLK [(const_int 0)] UNSPECV_ISYNC)]
100 [(set_attr "type" "isync")])
102 ;; The control dependency used for load dependency described
103 ;; in B.2.3 of the Power ISA 2.06B.
104 (define_insn "loadsync"
105 [(unspec_volatile:BLK [(match_operand 0 "register_operand" "r")]
107 (clobber (match_scratch:CC 1 "=y"))]
109 "cmpw %1,%0,%0\;bne- %1,$+4\;isync"
110 [(set_attr "type" "isync")
111 (set_attr "length" "12")])
113 (define_expand "atomic_load<mode>"
114 [(set (match_operand:INT1 0 "register_operand" "") ;; output
115 (match_operand:INT1 1 "memory_operand" "")) ;; memory
116 (use (match_operand:SI 2 "const_int_operand" ""))] ;; model
119 enum memmodel model = (enum memmodel) INTVAL (operands[2]);
121 if (model == MEMMODEL_SEQ_CST)
122 emit_insn (gen_hwsync ());
124 emit_move_insn (operands[0], operands[1]);
128 case MEMMODEL_RELAXED:
130 case MEMMODEL_CONSUME:
131 case MEMMODEL_ACQUIRE:
132 case MEMMODEL_SEQ_CST:
133 emit_insn (gen_loadsync (operands[0]));
141 (define_expand "atomic_store<mode>"
142 [(set (match_operand:INT1 0 "memory_operand" "") ;; memory
143 (match_operand:INT1 1 "register_operand" "")) ;; input
144 (use (match_operand:SI 2 "const_int_operand" ""))] ;; model
147 enum memmodel model = (enum memmodel) INTVAL (operands[2]);
150 case MEMMODEL_RELAXED:
152 case MEMMODEL_RELEASE:
153 emit_insn (gen_lwsync ());
155 case MEMMODEL_SEQ_CST:
156 emit_insn (gen_hwsync ());
161 emit_move_insn (operands[0], operands[1]);
165 ;; ??? Power ISA 2.06B says that there *is* a load-{byte,half}-and-reserve
166 ;; opcode that is "phased-in". Not implemented as of Power7, so not yet used,
167 ;; but let's prepare the macros anyway.
169 (define_mode_iterator ATOMIC [SI (DI "TARGET_64BIT")])
171 (define_insn "load_locked<mode>"
172 [(set (match_operand:ATOMIC 0 "gpc_reg_operand" "=r")
173 (unspec_volatile:ATOMIC
174 [(match_operand:ATOMIC 1 "memory_operand" "Z")] UNSPECV_LL))]
177 [(set_attr "type" "load_l")])
179 (define_insn "store_conditional<mode>"
180 [(set (match_operand:CC 0 "cc_reg_operand" "=x")
181 (unspec_volatile:CC [(const_int 0)] UNSPECV_SC))
182 (set (match_operand:ATOMIC 1 "memory_operand" "=Z")
183 (match_operand:ATOMIC 2 "gpc_reg_operand" "r"))]
186 [(set_attr "type" "store_c")])
188 (define_expand "atomic_compare_and_swap<mode>"
189 [(match_operand:SI 0 "gpc_reg_operand" "") ;; bool out
190 (match_operand:INT1 1 "gpc_reg_operand" "") ;; val out
191 (match_operand:INT1 2 "memory_operand" "") ;; memory
192 (match_operand:INT1 3 "reg_or_short_operand" "") ;; expected
193 (match_operand:INT1 4 "gpc_reg_operand" "") ;; desired
194 (match_operand:SI 5 "const_int_operand" "") ;; is_weak
195 (match_operand:SI 6 "const_int_operand" "") ;; model succ
196 (match_operand:SI 7 "const_int_operand" "")] ;; model fail
199 rs6000_expand_atomic_compare_and_swap (operands);
203 (define_expand "atomic_exchange<mode>"
204 [(match_operand:INT1 0 "gpc_reg_operand" "") ;; output
205 (match_operand:INT1 1 "memory_operand" "") ;; memory
206 (match_operand:INT1 2 "gpc_reg_operand" "") ;; input
207 (match_operand:SI 3 "const_int_operand" "")] ;; model
210 rs6000_expand_atomic_exchange (operands);
214 (define_expand "atomic_<fetchop_name><mode>"
215 [(match_operand:INT1 0 "memory_operand" "") ;; memory
216 (FETCHOP:INT1 (match_dup 0)
217 (match_operand:INT1 1 "<fetchop_pred>" "")) ;; operand
218 (match_operand:SI 2 "const_int_operand" "")] ;; model
221 rs6000_expand_atomic_op (<CODE>, operands[0], operands[1],
222 NULL_RTX, NULL_RTX, operands[2]);
226 (define_expand "atomic_nand<mode>"
227 [(match_operand:INT1 0 "memory_operand" "") ;; memory
228 (match_operand:INT1 1 "gpc_reg_operand" "") ;; operand
229 (match_operand:SI 2 "const_int_operand" "")] ;; model
232 rs6000_expand_atomic_op (NOT, operands[0], operands[1],
233 NULL_RTX, NULL_RTX, operands[2]);
237 (define_expand "atomic_fetch_<fetchop_name><mode>"
238 [(match_operand:INT1 0 "gpc_reg_operand" "") ;; output
239 (match_operand:INT1 1 "memory_operand" "") ;; memory
240 (FETCHOP:INT1 (match_dup 1)
241 (match_operand:INT1 2 "<fetchop_pred>" "")) ;; operand
242 (match_operand:SI 3 "const_int_operand" "")] ;; model
245 rs6000_expand_atomic_op (<CODE>, operands[1], operands[2],
246 operands[0], NULL_RTX, operands[3]);
250 (define_expand "atomic_fetch_nand<mode>"
251 [(match_operand:INT1 0 "gpc_reg_operand" "") ;; output
252 (match_operand:INT1 1 "memory_operand" "") ;; memory
253 (match_operand:INT1 2 "gpc_reg_operand" "") ;; operand
254 (match_operand:SI 3 "const_int_operand" "")] ;; model
257 rs6000_expand_atomic_op (NOT, operands[1], operands[2],
258 operands[0], NULL_RTX, operands[3]);
262 (define_expand "atomic_<fetchop_name>_fetch<mode>"
263 [(match_operand:INT1 0 "gpc_reg_operand" "") ;; output
264 (match_operand:INT1 1 "memory_operand" "") ;; memory
265 (FETCHOP:INT1 (match_dup 1)
266 (match_operand:INT1 2 "<fetchop_pred>" "")) ;; operand
267 (match_operand:SI 3 "const_int_operand" "")] ;; model
270 rs6000_expand_atomic_op (<CODE>, operands[1], operands[2],
271 NULL_RTX, operands[0], operands[3]);
275 (define_expand "atomic_nand_fetch<mode>"
276 [(match_operand:INT1 0 "gpc_reg_operand" "") ;; output
277 (match_operand:INT1 1 "memory_operand" "") ;; memory
278 (match_operand:INT1 2 "gpc_reg_operand" "") ;; operand
279 (match_operand:SI 3 "const_int_operand" "")] ;; model
282 rs6000_expand_atomic_op (NOT, operands[1], operands[2],
283 NULL_RTX, operands[0], operands[3]);