]>
Commit | Line | Data |
---|---|---|
f565b0a1 | 1 | ;; Machine description for PowerPC synchronization instructions. |
a945c346 | 2 | ;; Copyright (C) 2005-2024 Free Software Foundation, Inc. |
f565b0a1 DE |
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 | |
2f83c7d6 | 9 | ;; by the Free Software Foundation; either version 3, or (at your |
f565b0a1 DE |
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 | |
2f83c7d6 NC |
18 | ;; along with GCC; see the file COPYING3. If not see |
19 | ;; <http://www.gnu.org/licenses/>. | |
f565b0a1 | 20 | |
4b02c962 MM |
21 | (define_mode_attr larx [(QI "lbarx") |
22 | (HI "lharx") | |
23 | (SI "lwarx") | |
24 | (DI "ldarx") | |
25 | (TI "lqarx")]) | |
26 | ||
27 | (define_mode_attr stcx [(QI "stbcx.") | |
28 | (HI "sthcx.") | |
29 | (SI "stwcx.") | |
30 | (DI "stdcx.") | |
31 | (TI "stqcx.")]) | |
f565b0a1 | 32 | |
3abcb3a7 | 33 | (define_code_iterator FETCHOP [plus minus ior xor and]) |
9f0076e5 | 34 | (define_code_attr fetchop_name |
3877ce45 | 35 | [(plus "add") (minus "sub") (ior "or") (xor "xor") (and "and")]) |
9f0076e5 | 36 | (define_code_attr fetchop_pred |
4b02c962 | 37 | [(plus "add_operand") (minus "int_reg_operand") |
9f0076e5 | 38 | (ior "logical_operand") (xor "logical_operand") (and "and_operand")]) |
9f0076e5 | 39 | |
2747a046 | 40 | (define_expand "mem_thread_fence" |
ad18eed2 | 41 | [(match_operand:SI 0 "const_int_operand")] ;; model |
2747a046 RH |
42 | "" |
43 | { | |
39e150e8 | 44 | enum memmodel model = memmodel_base (INTVAL (operands[0])); |
2747a046 RH |
45 | switch (model) |
46 | { | |
47 | case MEMMODEL_RELAXED: | |
48 | break; | |
49 | case MEMMODEL_CONSUME: | |
50 | case MEMMODEL_ACQUIRE: | |
51 | case MEMMODEL_RELEASE: | |
52 | case MEMMODEL_ACQ_REL: | |
53 | emit_insn (gen_lwsync ()); | |
54 | break; | |
55 | case MEMMODEL_SEQ_CST: | |
56 | emit_insn (gen_hwsync ()); | |
57 | break; | |
58 | default: | |
59 | gcc_unreachable (); | |
60 | } | |
61 | DONE; | |
62 | }) | |
63 | ||
64 | (define_expand "hwsync" | |
1a8c13b3 UB |
65 | [(set (match_dup 0) |
66 | (unspec:BLK [(match_dup 0)] UNSPEC_SYNC))] | |
f565b0a1 | 67 | "" |
b52110d4 DE |
68 | { |
69 | operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode)); | |
70 | MEM_VOLATILE_P (operands[0]) = 1; | |
71 | }) | |
72 | ||
2747a046 | 73 | (define_insn "*hwsync" |
b52110d4 | 74 | [(set (match_operand:BLK 0 "" "") |
1a8c13b3 | 75 | (unspec:BLK [(match_dup 0)] UNSPEC_SYNC))] |
b52110d4 | 76 | "" |
6b39bc38 | 77 | "sync" |
b52110d4 DE |
78 | [(set_attr "type" "sync")]) |
79 | ||
2747a046 RH |
80 | (define_expand "lwsync" |
81 | [(set (match_dup 0) | |
82 | (unspec:BLK [(match_dup 0)] UNSPEC_LWSYNC))] | |
83 | "" | |
b52110d4 | 84 | { |
2747a046 RH |
85 | operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode)); |
86 | MEM_VOLATILE_P (operands[0]) = 1; | |
b52110d4 | 87 | }) |
f565b0a1 | 88 | |
2747a046 RH |
89 | (define_insn "*lwsync" |
90 | [(set (match_operand:BLK 0 "" "") | |
91 | (unspec:BLK [(match_dup 0)] UNSPEC_LWSYNC))] | |
92 | "" | |
9fc75b97 | 93 | { |
2747a046 RH |
94 | if (TARGET_NO_LWSYNC) |
95 | return "sync"; | |
2747a046 | 96 | else |
2660fecc | 97 | return "lwsync"; |
2747a046 RH |
98 | } |
99 | [(set_attr "type" "sync")]) | |
9fc75b97 | 100 | |
2747a046 RH |
101 | (define_insn "isync" |
102 | [(unspec_volatile:BLK [(const_int 0)] UNSPECV_ISYNC)] | |
103 | "" | |
6b39bc38 | 104 | "isync" |
2747a046 | 105 | [(set_attr "type" "isync")]) |
9fc75b97 | 106 | |
bf245bf4 PH |
107 | ;; Types that we should provide atomic instructions for. |
108 | (define_mode_iterator AINT [QI | |
109 | HI | |
110 | SI | |
111 | (DI "TARGET_POWERPC64") | |
112 | (TI "TARGET_SYNC_TI")]) | |
113 | ||
2747a046 RH |
114 | ;; The control dependency used for load dependency described |
115 | ;; in B.2.3 of the Power ISA 2.06B. | |
1ba24090 | 116 | (define_insn "loadsync_<mode>" |
bf245bf4 | 117 | [(unspec_volatile:BLK [(match_operand:AINT 0 "register_operand" "r")] |
2747a046 RH |
118 | UNSPECV_ISYNC) |
119 | (clobber (match_scratch:CC 1 "=y"))] | |
120 | "" | |
121 | "cmpw %1,%0,%0\;bne- %1,$+4\;isync" | |
122 | [(set_attr "type" "isync") | |
123 | (set_attr "length" "12")]) | |
124 | ||
3bcdb5de | 125 | ;; If TARGET_PREFIXED, always use plq rather than lq. |
bf245bf4 PH |
126 | (define_insn "load_quadpti" |
127 | [(set (match_operand:PTI 0 "quad_int_reg_operand" "=&r") | |
128 | (unspec:PTI | |
129 | [(match_operand:TI 1 "quad_memory_operand" "wQ")] UNSPEC_LSQ))] | |
130 | "TARGET_SYNC_TI | |
131 | && !reg_mentioned_p (operands[0], operands[1])" | |
132 | "lq %0,%1" | |
3bcdb5de | 133 | [(set_attr "type" "load") |
9a5a1e27 | 134 | (set_attr "size" "128") |
3bcdb5de AS |
135 | (set (attr "prefixed") (if_then_else (match_test "TARGET_PREFIXED") |
136 | (const_string "yes") | |
137 | (const_string "no")))]) | |
138 | ||
139 | ;; Pattern load_quadpti will always use plq for atomic TImode if | |
140 | ;; TARGET_PREFIXED. It has the correct doubleword ordering on either LE | |
141 | ;; or BE, so we can just move the result into the output register and | |
142 | ;; do not need to do the doubleword swap for LE. Also this avoids any | |
143 | ;; confusion about whether the lq vs plq might be used based on whether | |
144 | ;; op1 has PC-relative addressing. We could potentially allow BE to | |
145 | ;; use lq because it doesn't have the doubleword ordering problem. | |
2747a046 | 146 | (define_expand "atomic_load<mode>" |
ad18eed2 SB |
147 | [(set (match_operand:AINT 0 "register_operand") ;; output |
148 | (match_operand:AINT 1 "memory_operand")) ;; memory | |
149 | (use (match_operand:SI 2 "const_int_operand"))] ;; model | |
2747a046 | 150 | "" |
9fc75b97 | 151 | { |
bf245bf4 PH |
152 | if (<MODE>mode == TImode && !TARGET_SYNC_TI) |
153 | FAIL; | |
154 | ||
39e150e8 | 155 | enum memmodel model = memmodel_base (INTVAL (operands[2])); |
9fc75b97 | 156 | |
46b35980 | 157 | if (is_mm_seq_cst (model)) |
2747a046 | 158 | emit_insn (gen_hwsync ()); |
f565b0a1 | 159 | |
bf245bf4 PH |
160 | if (<MODE>mode != TImode) |
161 | emit_move_insn (operands[0], operands[1]); | |
162 | else | |
163 | { | |
164 | rtx op0 = operands[0]; | |
165 | rtx op1 = operands[1]; | |
166 | rtx pti_reg = gen_reg_rtx (PTImode); | |
167 | ||
ba6bf284 | 168 | if (!quad_address_p (XEXP (op1, 0), TImode, false)) |
bf245bf4 PH |
169 | { |
170 | rtx old_addr = XEXP (op1, 0); | |
171 | rtx new_addr = force_reg (Pmode, old_addr); | |
172 | operands[1] = op1 = replace_equiv_address (op1, new_addr); | |
173 | } | |
174 | ||
175 | emit_insn (gen_load_quadpti (pti_reg, op1)); | |
176 | ||
3bcdb5de | 177 | if (WORDS_BIG_ENDIAN || TARGET_PREFIXED) |
bf245bf4 PH |
178 | emit_move_insn (op0, gen_lowpart (TImode, pti_reg)); |
179 | else | |
180 | { | |
181 | emit_move_insn (gen_lowpart (DImode, op0), gen_highpart (DImode, pti_reg)); | |
182 | emit_move_insn (gen_highpart (DImode, op0), gen_lowpart (DImode, pti_reg)); | |
183 | } | |
184 | } | |
2747a046 RH |
185 | |
186 | switch (model) | |
9f0076e5 | 187 | { |
2747a046 RH |
188 | case MEMMODEL_RELAXED: |
189 | break; | |
190 | case MEMMODEL_CONSUME: | |
191 | case MEMMODEL_ACQUIRE: | |
192 | case MEMMODEL_SEQ_CST: | |
4b02c962 | 193 | emit_insn (gen_loadsync_<mode> (operands[0])); |
2747a046 RH |
194 | break; |
195 | default: | |
196 | gcc_unreachable (); | |
9f0076e5 | 197 | } |
f565b0a1 | 198 | DONE; |
9f0076e5 | 199 | }) |
f565b0a1 | 200 | |
3bcdb5de | 201 | ;; If TARGET_PREFIXED, always use pstq rather than stq. |
bf245bf4 PH |
202 | (define_insn "store_quadpti" |
203 | [(set (match_operand:PTI 0 "quad_memory_operand" "=wQ") | |
204 | (unspec:PTI | |
205 | [(match_operand:PTI 1 "quad_int_reg_operand" "r")] UNSPEC_LSQ))] | |
206 | "TARGET_SYNC_TI" | |
207 | "stq %1,%0" | |
3bcdb5de | 208 | [(set_attr "type" "store") |
9a5a1e27 | 209 | (set_attr "size" "128") |
3bcdb5de AS |
210 | (set (attr "prefixed") (if_then_else (match_test "TARGET_PREFIXED") |
211 | (const_string "yes") | |
212 | (const_string "no")))]) | |
bf245bf4 | 213 | |
3bcdb5de AS |
214 | ;; Pattern store_quadpti will always use pstq if TARGET_PREFIXED, |
215 | ;; so the doubleword swap is never needed in that case. | |
2747a046 | 216 | (define_expand "atomic_store<mode>" |
ad18eed2 SB |
217 | [(set (match_operand:AINT 0 "memory_operand") ;; memory |
218 | (match_operand:AINT 1 "register_operand")) ;; input | |
219 | (use (match_operand:SI 2 "const_int_operand"))] ;; model | |
2747a046 | 220 | "" |
f565b0a1 | 221 | { |
bf245bf4 PH |
222 | if (<MODE>mode == TImode && !TARGET_SYNC_TI) |
223 | FAIL; | |
224 | ||
39e150e8 | 225 | enum memmodel model = memmodel_base (INTVAL (operands[2])); |
2747a046 RH |
226 | switch (model) |
227 | { | |
228 | case MEMMODEL_RELAXED: | |
229 | break; | |
230 | case MEMMODEL_RELEASE: | |
231 | emit_insn (gen_lwsync ()); | |
232 | break; | |
233 | case MEMMODEL_SEQ_CST: | |
234 | emit_insn (gen_hwsync ()); | |
235 | break; | |
236 | default: | |
237 | gcc_unreachable (); | |
238 | } | |
bf245bf4 PH |
239 | if (<MODE>mode != TImode) |
240 | emit_move_insn (operands[0], operands[1]); | |
241 | else | |
242 | { | |
243 | rtx op0 = operands[0]; | |
244 | rtx op1 = operands[1]; | |
245 | rtx pti_reg = gen_reg_rtx (PTImode); | |
246 | ||
ba6bf284 | 247 | if (!quad_address_p (XEXP (op0, 0), TImode, false)) |
bf245bf4 PH |
248 | { |
249 | rtx old_addr = XEXP (op0, 0); | |
250 | rtx new_addr = force_reg (Pmode, old_addr); | |
251 | operands[0] = op0 = replace_equiv_address (op0, new_addr); | |
252 | } | |
253 | ||
3bcdb5de | 254 | if (WORDS_BIG_ENDIAN || TARGET_PREFIXED) |
bf245bf4 PH |
255 | emit_move_insn (pti_reg, gen_lowpart (PTImode, op1)); |
256 | else | |
257 | { | |
258 | emit_move_insn (gen_lowpart (DImode, pti_reg), gen_highpart (DImode, op1)); | |
259 | emit_move_insn (gen_highpart (DImode, pti_reg), gen_lowpart (DImode, op1)); | |
260 | } | |
261 | ||
262 | emit_insn (gen_store_quadpti (gen_lowpart (PTImode, op0), pti_reg)); | |
263 | } | |
264 | ||
f565b0a1 | 265 | DONE; |
9f0076e5 | 266 | }) |
f565b0a1 | 267 | |
4b02c962 MM |
268 | ;; Any supported integer mode that has atomic l<x>arx/st<x>cx. instrucitons |
269 | ;; other than the quad memory operations, which have special restrictions. | |
270 | ;; Byte/halfword atomic instructions were added in ISA 2.06B, but were phased | |
271 | ;; in and did not show up until power8. TImode atomic lqarx/stqcx. require | |
272 | ;; special handling due to even/odd register requirements. | |
273 | (define_mode_iterator ATOMIC [(QI "TARGET_SYNC_HI_QI") | |
274 | (HI "TARGET_SYNC_HI_QI") | |
275 | SI | |
276 | (DI "TARGET_POWERPC64")]) | |
277 | ||
2747a046 | 278 | (define_insn "load_locked<mode>" |
4b02c962 | 279 | [(set (match_operand:ATOMIC 0 "int_reg_operand" "=r") |
2747a046 RH |
280 | (unspec_volatile:ATOMIC |
281 | [(match_operand:ATOMIC 1 "memory_operand" "Z")] UNSPECV_LL))] | |
a441dedb | 282 | "" |
2747a046 RH |
283 | "<larx> %0,%y1" |
284 | [(set_attr "type" "load_l")]) | |
f565b0a1 | 285 | |
4b02c962 MM |
286 | (define_insn "load_locked<QHI:mode>_si" |
287 | [(set (match_operand:SI 0 "int_reg_operand" "=r") | |
288 | (unspec_volatile:SI | |
289 | [(match_operand:QHI 1 "memory_operand" "Z")] UNSPECV_LL))] | |
290 | "TARGET_SYNC_HI_QI" | |
291 | "<QHI:larx> %0,%y1" | |
292 | [(set_attr "type" "load_l")]) | |
293 | ||
b846c948 MM |
294 | ;; Use PTImode to get even/odd register pairs. |
295 | ;; Use a temporary register to force getting an even register for the | |
296 | ;; lqarx/stqcrx. instructions. Normal optimizations will eliminate this extra | |
297 | ;; copy on big endian systems. | |
298 | ||
299 | ;; On little endian systems where non-atomic quad word load/store instructions | |
300 | ;; are not used, the address can be register+offset, so make sure the address | |
301 | ;; is indexed or indirect before register allocation. | |
302 | ||
4b02c962 | 303 | (define_expand "load_lockedti" |
ad18eed2 SB |
304 | [(use (match_operand:TI 0 "quad_int_reg_operand")) |
305 | (use (match_operand:TI 1 "memory_operand"))] | |
4b02c962 MM |
306 | "TARGET_SYNC_TI" |
307 | { | |
b846c948 MM |
308 | rtx op0 = operands[0]; |
309 | rtx op1 = operands[1]; | |
4b02c962 | 310 | rtx pti = gen_reg_rtx (PTImode); |
b846c948 MM |
311 | |
312 | if (!indexed_or_indirect_operand (op1, TImode)) | |
313 | { | |
314 | rtx old_addr = XEXP (op1, 0); | |
315 | rtx new_addr = force_reg (Pmode, old_addr); | |
316 | operands[1] = op1 = change_address (op1, TImode, new_addr); | |
317 | } | |
318 | ||
319 | emit_insn (gen_load_lockedpti (pti, op1)); | |
320 | if (WORDS_BIG_ENDIAN) | |
321 | emit_move_insn (op0, gen_lowpart (TImode, pti)); | |
322 | else | |
323 | { | |
324 | emit_move_insn (gen_lowpart (DImode, op0), gen_highpart (DImode, pti)); | |
325 | emit_move_insn (gen_highpart (DImode, op0), gen_lowpart (DImode, pti)); | |
326 | } | |
4b02c962 MM |
327 | DONE; |
328 | }) | |
329 | ||
330 | (define_insn "load_lockedpti" | |
331 | [(set (match_operand:PTI 0 "quad_int_reg_operand" "=&r") | |
332 | (unspec_volatile:PTI | |
b846c948 | 333 | [(match_operand:TI 1 "indexed_or_indirect_operand" "Z")] UNSPECV_LL))] |
4b02c962 MM |
334 | "TARGET_SYNC_TI |
335 | && !reg_mentioned_p (operands[0], operands[1]) | |
336 | && quad_int_reg_operand (operands[0], PTImode)" | |
337 | "lqarx %0,%y1" | |
9a5a1e27 PH |
338 | [(set_attr "type" "load_l") |
339 | (set_attr "size" "128")]) | |
4b02c962 | 340 | |
2747a046 RH |
341 | (define_insn "store_conditional<mode>" |
342 | [(set (match_operand:CC 0 "cc_reg_operand" "=x") | |
343 | (unspec_volatile:CC [(const_int 0)] UNSPECV_SC)) | |
344 | (set (match_operand:ATOMIC 1 "memory_operand" "=Z") | |
4b02c962 | 345 | (match_operand:ATOMIC 2 "int_reg_operand" "r"))] |
a441dedb | 346 | "" |
2747a046 RH |
347 | "<stcx> %2,%y1" |
348 | [(set_attr "type" "store_c")]) | |
f565b0a1 | 349 | |
b846c948 MM |
350 | ;; Use a temporary register to force getting an even register for the |
351 | ;; lqarx/stqcrx. instructions. Normal optimizations will eliminate this extra | |
352 | ;; copy on big endian systems. | |
353 | ||
354 | ;; On little endian systems where non-atomic quad word load/store instructions | |
355 | ;; are not used, the address can be register+offset, so make sure the address | |
356 | ;; is indexed or indirect before register allocation. | |
357 | ||
4b02c962 | 358 | (define_expand "store_conditionalti" |
ad18eed2 SB |
359 | [(use (match_operand:CC 0 "cc_reg_operand")) |
360 | (use (match_operand:TI 1 "memory_operand")) | |
361 | (use (match_operand:TI 2 "quad_int_reg_operand"))] | |
4b02c962 MM |
362 | "TARGET_SYNC_TI" |
363 | { | |
364 | rtx op0 = operands[0]; | |
365 | rtx op1 = operands[1]; | |
366 | rtx op2 = operands[2]; | |
b846c948 MM |
367 | rtx addr = XEXP (op1, 0); |
368 | rtx pti_mem; | |
369 | rtx pti_reg; | |
370 | ||
371 | if (!indexed_or_indirect_operand (op1, TImode)) | |
372 | { | |
373 | rtx new_addr = force_reg (Pmode, addr); | |
374 | operands[1] = op1 = change_address (op1, TImode, new_addr); | |
375 | addr = new_addr; | |
376 | } | |
377 | ||
378 | pti_mem = change_address (op1, PTImode, addr); | |
379 | pti_reg = gen_reg_rtx (PTImode); | |
380 | ||
381 | if (WORDS_BIG_ENDIAN) | |
382 | emit_move_insn (pti_reg, gen_lowpart (PTImode, op2)); | |
383 | else | |
384 | { | |
385 | emit_move_insn (gen_lowpart (DImode, pti_reg), gen_highpart (DImode, op2)); | |
386 | emit_move_insn (gen_highpart (DImode, pti_reg), gen_lowpart (DImode, op2)); | |
387 | } | |
388 | ||
389 | emit_insn (gen_store_conditionalpti (op0, pti_mem, pti_reg)); | |
4b02c962 MM |
390 | DONE; |
391 | }) | |
392 | ||
393 | (define_insn "store_conditionalpti" | |
394 | [(set (match_operand:CC 0 "cc_reg_operand" "=x") | |
395 | (unspec_volatile:CC [(const_int 0)] UNSPECV_SC)) | |
b846c948 | 396 | (set (match_operand:PTI 1 "indexed_or_indirect_operand" "=Z") |
4b02c962 MM |
397 | (match_operand:PTI 2 "quad_int_reg_operand" "r"))] |
398 | "TARGET_SYNC_TI && quad_int_reg_operand (operands[2], PTImode)" | |
399 | "stqcx. %2,%y1" | |
9a5a1e27 PH |
400 | [(set_attr "type" "store_c") |
401 | (set_attr "size" "128")]) | |
4b02c962 | 402 | |
2747a046 | 403 | (define_expand "atomic_compare_and_swap<mode>" |
ad18eed2 SB |
404 | [(match_operand:SI 0 "int_reg_operand") ;; bool out |
405 | (match_operand:AINT 1 "int_reg_operand") ;; val out | |
406 | (match_operand:AINT 2 "memory_operand") ;; memory | |
407 | (match_operand:AINT 3 "reg_or_short_operand") ;; expected | |
408 | (match_operand:AINT 4 "int_reg_operand") ;; desired | |
409 | (match_operand:SI 5 "const_int_operand") ;; is_weak | |
410 | (match_operand:SI 6 "const_int_operand") ;; model succ | |
411 | (match_operand:SI 7 "const_int_operand")] ;; model fail | |
a441dedb | 412 | "" |
f565b0a1 | 413 | { |
2747a046 | 414 | rs6000_expand_atomic_compare_and_swap (operands); |
f565b0a1 | 415 | DONE; |
9f0076e5 | 416 | }) |
f565b0a1 | 417 | |
2747a046 | 418 | (define_expand "atomic_exchange<mode>" |
ad18eed2 SB |
419 | [(match_operand:AINT 0 "int_reg_operand") ;; output |
420 | (match_operand:AINT 1 "memory_operand") ;; memory | |
421 | (match_operand:AINT 2 "int_reg_operand") ;; input | |
422 | (match_operand:SI 3 "const_int_operand")] ;; model | |
a441dedb | 423 | "" |
f565b0a1 | 424 | { |
2747a046 | 425 | rs6000_expand_atomic_exchange (operands); |
f565b0a1 | 426 | DONE; |
9f0076e5 | 427 | }) |
f565b0a1 | 428 | |
2747a046 | 429 | (define_expand "atomic_<fetchop_name><mode>" |
ad18eed2 | 430 | [(match_operand:AINT 0 "memory_operand") ;; memory |
4b02c962 | 431 | (FETCHOP:AINT (match_dup 0) |
ad18eed2 SB |
432 | (match_operand:AINT 1 "<fetchop_pred>")) ;; operand |
433 | (match_operand:SI 2 "const_int_operand")] ;; model | |
a441dedb | 434 | "" |
f565b0a1 | 435 | { |
2747a046 RH |
436 | rs6000_expand_atomic_op (<CODE>, operands[0], operands[1], |
437 | NULL_RTX, NULL_RTX, operands[2]); | |
f565b0a1 | 438 | DONE; |
9f0076e5 | 439 | }) |
f565b0a1 | 440 | |
2747a046 | 441 | (define_expand "atomic_nand<mode>" |
ad18eed2 SB |
442 | [(match_operand:AINT 0 "memory_operand") ;; memory |
443 | (match_operand:AINT 1 "int_reg_operand") ;; operand | |
444 | (match_operand:SI 2 "const_int_operand")] ;; model | |
a441dedb | 445 | "" |
f565b0a1 | 446 | { |
2747a046 RH |
447 | rs6000_expand_atomic_op (NOT, operands[0], operands[1], |
448 | NULL_RTX, NULL_RTX, operands[2]); | |
f565b0a1 | 449 | DONE; |
9f0076e5 | 450 | }) |
f565b0a1 | 451 | |
2747a046 | 452 | (define_expand "atomic_fetch_<fetchop_name><mode>" |
ad18eed2 SB |
453 | [(match_operand:AINT 0 "int_reg_operand") ;; output |
454 | (match_operand:AINT 1 "memory_operand") ;; memory | |
4b02c962 | 455 | (FETCHOP:AINT (match_dup 1) |
ad18eed2 SB |
456 | (match_operand:AINT 2 "<fetchop_pred>")) ;; operand |
457 | (match_operand:SI 3 "const_int_operand")] ;; model | |
a441dedb | 458 | "" |
2747a046 RH |
459 | { |
460 | rs6000_expand_atomic_op (<CODE>, operands[1], operands[2], | |
461 | operands[0], NULL_RTX, operands[3]); | |
f565b0a1 | 462 | DONE; |
9f0076e5 | 463 | }) |
f565b0a1 | 464 | |
2747a046 | 465 | (define_expand "atomic_fetch_nand<mode>" |
ad18eed2 SB |
466 | [(match_operand:AINT 0 "int_reg_operand") ;; output |
467 | (match_operand:AINT 1 "memory_operand") ;; memory | |
468 | (match_operand:AINT 2 "int_reg_operand") ;; operand | |
469 | (match_operand:SI 3 "const_int_operand")] ;; model | |
a441dedb | 470 | "" |
f565b0a1 | 471 | { |
2747a046 RH |
472 | rs6000_expand_atomic_op (NOT, operands[1], operands[2], |
473 | operands[0], NULL_RTX, operands[3]); | |
474 | DONE; | |
475 | }) | |
f565b0a1 | 476 | |
2747a046 | 477 | (define_expand "atomic_<fetchop_name>_fetch<mode>" |
ad18eed2 SB |
478 | [(match_operand:AINT 0 "int_reg_operand") ;; output |
479 | (match_operand:AINT 1 "memory_operand") ;; memory | |
4b02c962 | 480 | (FETCHOP:AINT (match_dup 1) |
ad18eed2 SB |
481 | (match_operand:AINT 2 "<fetchop_pred>")) ;; operand |
482 | (match_operand:SI 3 "const_int_operand")] ;; model | |
a441dedb | 483 | "" |
f565b0a1 | 484 | { |
2747a046 RH |
485 | rs6000_expand_atomic_op (<CODE>, operands[1], operands[2], |
486 | NULL_RTX, operands[0], operands[3]); | |
f565b0a1 | 487 | DONE; |
9f0076e5 DE |
488 | }) |
489 | ||
2747a046 | 490 | (define_expand "atomic_nand_fetch<mode>" |
ad18eed2 SB |
491 | [(match_operand:AINT 0 "int_reg_operand") ;; output |
492 | (match_operand:AINT 1 "memory_operand") ;; memory | |
493 | (match_operand:AINT 2 "int_reg_operand") ;; operand | |
494 | (match_operand:SI 3 "const_int_operand")] ;; model | |
a441dedb | 495 | "" |
f565b0a1 | 496 | { |
2747a046 RH |
497 | rs6000_expand_atomic_op (NOT, operands[1], operands[2], |
498 | NULL_RTX, operands[0], operands[3]); | |
f565b0a1 | 499 | DONE; |
2747a046 | 500 | }) |