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_<mode>"
104 [(unspec_volatile:BLK [(match_operand:INT1 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 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]));
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
155 enum memmodel model = (enum memmodel) INTVAL (operands[2]);
158 case MEMMODEL_RELAXED:
160 case MEMMODEL_RELEASE:
161 emit_insn (gen_lwsync ());
163 case MEMMODEL_SEQ_CST:
164 emit_insn (gen_hwsync ());
169 emit_move_insn (operands[0], operands[1]);
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))]
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"))]
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
207 rs6000_expand_atomic_compare_and_swap (operands);
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
218 rs6000_expand_atomic_exchange (operands);
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
229 rs6000_expand_atomic_op (<CODE>, operands[0], operands[1],
230 NULL_RTX, NULL_RTX, operands[2]);
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
240 rs6000_expand_atomic_op (NOT, operands[0], operands[1],
241 NULL_RTX, NULL_RTX, operands[2]);
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
253 rs6000_expand_atomic_op (<CODE>, operands[1], operands[2],
254 operands[0], NULL_RTX, operands[3]);
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
265 rs6000_expand_atomic_op (NOT, operands[1], operands[2],
266 operands[0], NULL_RTX, operands[3]);
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
278 rs6000_expand_atomic_op (<CODE>, operands[1], operands[2],
279 NULL_RTX, operands[0], operands[3]);
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
290 rs6000_expand_atomic_op (NOT, operands[1], operands[2],
291 NULL_RTX, operands[0], operands[3]);