sync.md revision 169689
1187938Semax;; Machine description for PowerPC synchronization instructions.
2187938Semax;; Copyright (C) 2005 Free Software Foundation, Inc.
3187938Semax;; Contributed by Geoffrey Keating.
4187938Semax
5187938Semax;; This file is part of GCC.
6187938Semax
7187938Semax;; GCC is free software; you can redistribute it and/or modify it
8187938Semax;; under the terms of the GNU General Public License as published
9187938Semax;; by the Free Software Foundation; either version 2, or (at your
10187938Semax;; option) any later version.
11187938Semax
12187938Semax;; GCC is distributed in the hope that it will be useful, but WITHOUT
13187938Semax;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14187938Semax;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
15187938Semax;; License for more details.
16187938Semax
17187938Semax;; You should have received a copy of the GNU General Public License
18187938Semax;; along with GCC; see the file COPYING.  If not, write to the
19187938Semax;; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
20187938Semax;; MA 02110-1301, USA.
21187938Semax
22187938Semax(define_mode_attr larx [(SI "lwarx") (DI "ldarx")])
23187938Semax(define_mode_attr stcx [(SI "stwcx.") (DI "stdcx.")])
24187938Semax
25187938Semax(define_code_macro FETCHOP [plus minus ior xor and])
26187938Semax(define_code_attr fetchop_name
27187938Semax  [(plus "add") (minus "sub") (ior "ior") (xor "xor") (and "and")])
28187938Semax(define_code_attr fetchop_pred
29187938Semax  [(plus "add_operand") (minus "gpc_reg_operand")
30187938Semax   (ior "logical_operand") (xor "logical_operand") (and "and_operand")])
31187938Semax(define_code_attr fetchopsi_constr
32187938Semax  [(plus "rIL") (minus "r") (ior "rKL") (xor "rKL") (and "rTKL")])
33187938Semax(define_code_attr fetchopdi_constr
34187938Semax  [(plus "rIL") (minus "r") (ior "rKJF") (xor "rKJF") (and "rSTKJ")])
35187938Semax
36187938Semax(define_expand "memory_barrier"
37187938Semax  [(set (mem:BLK (match_dup 0))
38187938Semax	(unspec:BLK [(mem:BLK (match_dup 0))] UNSPEC_SYNC))]
39187938Semax  ""
40187938Semax{
41187938Semax  operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
42187938Semax  MEM_VOLATILE_P (operands[0]) = 1;
43187938Semax})
44187938Semax
45187938Semax(define_insn "*sync_internal"
46187938Semax  [(set (match_operand:BLK 0 "" "")
47187938Semax	(unspec:BLK [(match_operand:BLK 1 "" "")] UNSPEC_SYNC))]
48187938Semax  ""
49187938Semax  "{dcs|sync}"
50241699Semax  [(set_attr "type" "sync")])
51187938Semax
52187938Semax(define_insn "load_locked_<mode>"
53187938Semax  [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
54187938Semax	(unspec_volatile:GPR
55187938Semax	  [(match_operand:GPR 1 "memory_operand" "Z")] UNSPECV_LL))]
56187938Semax  "TARGET_POWERPC"
57187938Semax  "<larx> %0,%y1"
58187938Semax  [(set_attr "type" "load_l")])
59187938Semax
60187938Semax(define_insn "store_conditional_<mode>"
61187938Semax  [(set (match_operand:CC 0 "cc_reg_operand" "=x")
62187938Semax	(unspec_volatile:CC [(const_int 0)] UNSPECV_SC))
63187938Semax   (set (match_operand:GPR 1 "memory_operand" "=Z")
64187938Semax	(match_operand:GPR 2 "gpc_reg_operand" "r"))]
65187938Semax  "TARGET_POWERPC"
66187938Semax  "<stcx> %2,%y1"
67187938Semax  [(set_attr "type" "store_c")])
68187938Semax
69187938Semax(define_insn_and_split "sync_compare_and_swap<mode>"
70187938Semax  [(set (match_operand:GPR 0 "gpc_reg_operand" "=&r")
71187938Semax	(match_operand:GPR 1 "memory_operand" "+Z"))
72187938Semax   (set (match_dup 1)
73187938Semax	(unspec:GPR
74187938Semax	  [(match_operand:GPR 2 "reg_or_short_operand" "rI")
75187938Semax	   (match_operand:GPR 3 "gpc_reg_operand" "r")]
76187938Semax	  UNSPEC_CMPXCHG))
77187938Semax   (clobber (match_scratch:GPR 4 "=&r"))
78187938Semax   (clobber (match_scratch:CC 5 "=&x"))]
79187938Semax  "TARGET_POWERPC"
80187938Semax  "#"
81187938Semax  "&& reload_completed"
82187938Semax  [(const_int 0)]
83187938Semax{
84187938Semax  rs6000_split_compare_and_swap (operands[0], operands[1], operands[2],
85187938Semax				 operands[3], operands[4]);
86187938Semax  DONE;
87187938Semax})
88187938Semax
89187938Semax(define_expand "sync_compare_and_swaphi"
90187938Semax  [(match_operand:HI 0 "gpc_reg_operand" "")
91187938Semax   (match_operand:HI 1 "memory_operand" "")
92187938Semax   (match_operand:HI 2 "gpc_reg_operand" "")
93187938Semax   (match_operand:HI 3 "gpc_reg_operand" "")]
94187938Semax  "TARGET_POWERPC"
95187938Semax{
96187938Semax  rs6000_expand_compare_and_swapqhi (operands[0], operands[1],
97187938Semax				     operands[2], operands[3]);
98187938Semax  DONE;
99187938Semax})
100241699Semax
101241699Semax(define_expand "sync_compare_and_swapqi"
102241699Semax  [(match_operand:QI 0 "gpc_reg_operand" "")
103241699Semax   (match_operand:QI 1 "memory_operand" "")
104241699Semax   (match_operand:QI 2 "gpc_reg_operand" "")
105241699Semax   (match_operand:QI 3 "gpc_reg_operand" "")]
106241699Semax  "TARGET_POWERPC"
107241699Semax{
108241699Semax  rs6000_expand_compare_and_swapqhi (operands[0], operands[1],
109241699Semax				     operands[2], operands[3]);
110241699Semax  DONE;
111187938Semax})
112187938Semax
113187938Semax(define_insn_and_split "sync_compare_and_swapqhi_internal"
114187938Semax  [(set (match_operand:SI 0 "gpc_reg_operand" "=&r")
115187938Semax	(match_operand:SI 4 "memory_operand" "+Z"))
116187938Semax   (set (match_dup 4)
117187938Semax        (unspec:SI
118187938Semax          [(match_operand:SI 1 "gpc_reg_operand" "r")
119187938Semax           (match_operand:SI 2 "gpc_reg_operand" "r")
120187938Semax           (match_operand:SI 3 "gpc_reg_operand" "r")]
121241699Semax          UNSPEC_CMPXCHG))
122241699Semax   (clobber (match_scratch:SI 5 "=&r"))
123241699Semax   (clobber (match_scratch:CC 6 "=&x"))]
124241699Semax  "TARGET_POWERPC"
125241699Semax  "#"
126241699Semax  "&& reload_completed"
127241699Semax  [(const_int 0)]
128241699Semax{
129241699Semax  rs6000_split_compare_and_swapqhi (operands[0], operands[1],
130241699Semax				    operands[2], operands[3], operands[4],
131241699Semax				    operands[5]);
132241699Semax  DONE;
133241699Semax})
134241699Semax
135241699Semax(define_insn_and_split "sync_lock_test_and_set<mode>"
136241699Semax  [(set (match_operand:GPR 0 "gpc_reg_operand" "=&r")
137241699Semax	(match_operand:GPR 1 "memory_operand" "+Z"))
138241699Semax   (set (match_dup 1)
139241699Semax	(unspec:GPR
140241699Semax	  [(match_operand:GPR 2 "reg_or_short_operand" "rL")]
141241699Semax	  UNSPEC_XCHG))
142187938Semax   (clobber (match_scratch:GPR 3 "=&r"))
143187938Semax   (clobber (match_scratch:CC 4 "=&x"))]
144187938Semax  "TARGET_POWERPC"
145187938Semax  "#"
146187938Semax  "&& reload_completed"
147187938Semax  [(const_int 0)]
148187938Semax{
149187938Semax  rs6000_split_lock_test_and_set (operands[0], operands[1], operands[2],
150187938Semax				  operands[3]);
151187938Semax  DONE;
152187938Semax})
153187938Semax
154187938Semax(define_expand "sync_<fetchop_name><mode>"
155187938Semax  [(parallel [(set (match_operand:INT1 0 "memory_operand" "")
156187938Semax		   (unspec:INT1
157187938Semax		     [(FETCHOP:INT1 (match_dup 0)
158187938Semax			(match_operand:INT1 1 "<fetchop_pred>" ""))]
159187938Semax		     UNSPEC_ATOMIC))
160187938Semax	      (clobber (scratch:INT1))
161187938Semax	      (clobber (scratch:CC))])]
162187938Semax  "TARGET_POWERPC"
163187938Semax  "
164187938Semax{
165187938Semax  if (<MODE>mode != SImode && <MODE>mode != DImode)
166187938Semax    {
167187938Semax      if (PPC405_ERRATUM77)
168187938Semax	FAIL;
169187938Semax      rs6000_emit_sync (<CODE>, <MODE>mode, operands[0], operands[1],
170187938Semax			NULL_RTX, NULL_RTX, true);
171187938Semax      DONE;
172187938Semax    }
173187938Semax}")
174187938Semax
175187938Semax(define_insn_and_split "*sync_<fetchop_name>si_internal"
176187938Semax  [(set (match_operand:SI 0 "memory_operand" "+Z")
177187938Semax	(unspec:SI
178187938Semax	  [(FETCHOP:SI (match_dup 0)
179187938Semax	     (match_operand:SI 1 "<fetchop_pred>" "<fetchopsi_constr>"))]
180187938Semax	  UNSPEC_ATOMIC))
181187938Semax   (clobber (match_scratch:SI 2 "=&b"))
182187938Semax   (clobber (match_scratch:CC 3 "=&x"))]
183187938Semax  "TARGET_POWERPC"
184187938Semax  "#"
185187938Semax  "&& reload_completed"
186187938Semax  [(const_int 0)]
187187938Semax{
188187938Semax  rs6000_split_atomic_op (<CODE>, operands[0], operands[1],
189187938Semax			  NULL_RTX, NULL_RTX, operands[2]);
190187938Semax  DONE;
191187938Semax})
192187938Semax
193187938Semax(define_insn_and_split "*sync_<fetchop_name>di_internal"
194187938Semax  [(set (match_operand:DI 0 "memory_operand" "+Z")
195187938Semax	(unspec:DI
196187938Semax	  [(FETCHOP:DI (match_dup 0)
197187938Semax	     (match_operand:DI 1 "<fetchop_pred>" "<fetchopdi_constr>"))]
198187938Semax	  UNSPEC_ATOMIC))
199187938Semax   (clobber (match_scratch:DI 2 "=&b"))
200187938Semax   (clobber (match_scratch:CC 3 "=&x"))]
201187938Semax  "TARGET_POWERPC"
202187938Semax  "#"
203187938Semax  "&& reload_completed"
204187938Semax  [(const_int 0)]
205187938Semax{
206187938Semax  rs6000_split_atomic_op (<CODE>, operands[0], operands[1],
207187938Semax			  NULL_RTX, NULL_RTX, operands[2]);
208187938Semax  DONE;
209187938Semax})
210187938Semax
211187938Semax(define_expand "sync_nand<mode>"
212187938Semax  [(parallel [(set (match_operand:INT1 0 "memory_operand" "")
213187938Semax	      (unspec:INT1
214187938Semax		[(and:INT1 (not:INT1 (match_dup 0))
215187938Semax		   (match_operand:INT1 1 "gpc_reg_operand" ""))]
216187938Semax		UNSPEC_ATOMIC))
217187938Semax	      (clobber (scratch:INT1))
218187938Semax	      (clobber (scratch:CC))])]
219187938Semax  "TARGET_POWERPC"
220187938Semax  "
221187938Semax{
222187938Semax  if (<MODE>mode != SImode && <MODE>mode != DImode)
223187938Semax    {
224187938Semax      if (PPC405_ERRATUM77)
225	FAIL;
226      rs6000_emit_sync (AND, <MODE>mode,
227			gen_rtx_NOT (<MODE>mode, operands[0]),
228			operands[1],
229			NULL_RTX, NULL_RTX, true);
230      DONE;
231    }
232}")
233
234(define_insn_and_split "*sync_nand<mode>_internal"
235  [(set (match_operand:GPR 0 "memory_operand" "+Z")
236	(unspec:GPR
237	  [(and:GPR (not:GPR (match_dup 0))
238	     (match_operand:GPR 1 "gpc_reg_operand" "r"))]
239	  UNSPEC_ATOMIC))
240   (clobber (match_scratch:GPR 2 "=&r"))
241   (clobber (match_scratch:CC 3 "=&x"))]
242  "TARGET_POWERPC"
243  "#"
244  "&& reload_completed"
245  [(const_int 0)]
246{
247  rs6000_split_atomic_op (NOT, operands[0], operands[1],
248			  NULL_RTX, NULL_RTX, operands[2]);
249  DONE;
250})
251
252(define_expand "sync_old_<fetchop_name><mode>"
253  [(parallel [(set (match_operand:INT1 0 "gpc_reg_operand" "")
254		   (match_operand:INT1 1 "memory_operand" ""))
255	      (set (match_dup 1)
256		   (unspec:INT1
257		     [(FETCHOP:INT1 (match_dup 1)
258			(match_operand:INT1 2 "<fetchop_pred>" ""))]
259		     UNSPEC_ATOMIC))
260	      (clobber (scratch:INT1))
261	      (clobber (scratch:CC))])]
262  "TARGET_POWERPC"
263  "
264{ 
265  if (<MODE>mode != SImode && <MODE>mode != DImode)
266    {
267      if (PPC405_ERRATUM77)
268	FAIL;
269      rs6000_emit_sync (<CODE>, <MODE>mode, operands[1], operands[2],
270			operands[0], NULL_RTX, true);
271      DONE;
272    }
273}")
274
275(define_insn_and_split "*sync_old_<fetchop_name>si_internal"
276  [(set (match_operand:SI 0 "gpc_reg_operand" "=&r")
277	(match_operand:SI 1 "memory_operand" "+Z"))
278   (set (match_dup 1)
279	(unspec:SI
280	  [(FETCHOP:SI (match_dup 1)
281	     (match_operand:SI 2 "<fetchop_pred>" "<fetchopsi_constr>"))]
282	  UNSPEC_ATOMIC))
283   (clobber (match_scratch:SI 3 "=&b"))
284   (clobber (match_scratch:CC 4 "=&x"))]
285  "TARGET_POWERPC"
286  "#"
287  "&& reload_completed"
288  [(const_int 0)]
289{
290  rs6000_split_atomic_op (<CODE>, operands[1], operands[2],
291			  operands[0], NULL_RTX, operands[3]);
292  DONE;
293})
294
295(define_insn_and_split "*sync_old_<fetchop_name>di_internal"
296  [(set (match_operand:DI 0 "gpc_reg_operand" "=&r")
297	(match_operand:DI 1 "memory_operand" "+Z"))
298   (set (match_dup 1)
299	(unspec:DI
300	  [(FETCHOP:DI (match_dup 1)
301	     (match_operand:DI 2 "<fetchop_pred>" "<fetchopdi_constr>"))]
302	  UNSPEC_ATOMIC))
303   (clobber (match_scratch:DI 3 "=&b"))
304   (clobber (match_scratch:CC 4 "=&x"))]
305  "TARGET_POWERPC"
306  "#"
307  "&& reload_completed"
308  [(const_int 0)]
309{
310  rs6000_split_atomic_op (<CODE>, operands[1], operands[2],
311			  operands[0], NULL_RTX, operands[3]);
312  DONE;
313})
314
315(define_expand "sync_old_nand<mode>"
316  [(parallel [(set (match_operand:INT1 0 "gpc_reg_operand" "")
317		   (match_operand:INT1 1 "memory_operand" ""))
318	      (set (match_dup 1)
319		   (unspec:INT1
320		     [(and:INT1 (not:INT1 (match_dup 1))
321			(match_operand:INT1 2 "gpc_reg_operand" ""))]
322		     UNSPEC_ATOMIC))
323	      (clobber (scratch:INT1))
324	      (clobber (scratch:CC))])]
325  "TARGET_POWERPC"
326  "
327{
328  if (<MODE>mode != SImode && <MODE>mode != DImode)
329    {
330      if (PPC405_ERRATUM77)
331	FAIL;
332      rs6000_emit_sync (AND, <MODE>mode,
333			gen_rtx_NOT (<MODE>mode, operands[1]),
334			operands[2],
335			operands[0], NULL_RTX, true);
336      DONE;
337    }
338}")
339
340(define_insn_and_split "*sync_old_nand<mode>_internal"
341  [(set (match_operand:GPR 0 "gpc_reg_operand" "=&r")
342	(match_operand:GPR 1 "memory_operand" "+Z"))
343   (set (match_dup 1)
344	(unspec:GPR
345	  [(and:GPR (not:GPR (match_dup 1))
346	     (match_operand:GPR 2 "gpc_reg_operand" "r"))]
347	  UNSPEC_ATOMIC))
348   (clobber (match_scratch:GPR 3 "=&r"))
349   (clobber (match_scratch:CC 4 "=&x"))]
350  "TARGET_POWERPC"
351  "#"
352  "&& reload_completed"
353  [(const_int 0)]
354{
355  rs6000_split_atomic_op (NOT, operands[1], operands[2],
356			  operands[0], NULL_RTX, operands[3]);
357  DONE;
358})
359
360(define_expand "sync_new_<fetchop_name><mode>"
361  [(parallel [(set (match_operand:INT1 0 "gpc_reg_operand" "")
362		   (FETCHOP:INT1
363		     (match_operand:INT1 1 "memory_operand" "")
364		     (match_operand:INT1 2 "<fetchop_pred>" "")))
365	      (set (match_dup 1)
366		   (unspec:INT1
367		     [(FETCHOP:INT1 (match_dup 1) (match_dup 2))]
368		     UNSPEC_ATOMIC))
369	      (clobber (scratch:INT1))
370	      (clobber (scratch:CC))])]
371  "TARGET_POWERPC"
372  "
373{
374  if (<MODE>mode != SImode && <MODE>mode != DImode)
375    {
376      if (PPC405_ERRATUM77)
377	FAIL;
378      rs6000_emit_sync (<CODE>, <MODE>mode, operands[1], operands[2],
379			NULL_RTX, operands[0], true);
380      DONE;
381    }
382}")
383
384(define_insn_and_split "*sync_new_<fetchop_name>si_internal"
385  [(set (match_operand:SI 0 "gpc_reg_operand" "=&r")
386	(FETCHOP:SI
387	  (match_operand:SI 1 "memory_operand" "+Z")
388	  (match_operand:SI 2 "<fetchop_pred>" "<fetchopsi_constr>")))
389   (set (match_dup 1)
390	(unspec:SI
391	  [(FETCHOP:SI (match_dup 1) (match_dup 2))]
392	  UNSPEC_ATOMIC))
393   (clobber (match_scratch:SI 3 "=&b"))
394   (clobber (match_scratch:CC 4 "=&x"))]
395  "TARGET_POWERPC"
396  "#"
397  "&& reload_completed"
398  [(const_int 0)]
399{
400  rs6000_split_atomic_op (<CODE>, operands[1], operands[2],
401			  NULL_RTX, operands[0], operands[3]);
402  DONE;
403})
404
405(define_insn_and_split "*sync_new_<fetchop_name>di_internal"
406  [(set (match_operand:DI 0 "gpc_reg_operand" "=&r")
407	(FETCHOP:DI
408	  (match_operand:DI 1 "memory_operand" "+Z")
409	  (match_operand:DI 2 "<fetchop_pred>" "<fetchopdi_constr>")))
410   (set (match_dup 1)
411	(unspec:DI
412	  [(FETCHOP:DI (match_dup 1) (match_dup 2))]
413	  UNSPEC_ATOMIC))
414   (clobber (match_scratch:DI 3 "=&b"))
415   (clobber (match_scratch:CC 4 "=&x"))]
416  "TARGET_POWERPC"
417  "#"
418  "&& reload_completed"
419  [(const_int 0)]
420{
421  rs6000_split_atomic_op (<CODE>, operands[1], operands[2],
422			  NULL_RTX, operands[0], operands[3]);
423  DONE;
424})
425
426(define_expand "sync_new_nand<mode>"
427  [(parallel [(set (match_operand:INT1 0 "gpc_reg_operand" "")
428		   (and:INT1
429		     (not:INT1 (match_operand:INT1 1 "memory_operand" ""))
430		     (match_operand:INT1 2 "gpc_reg_operand" "")))
431	      (set (match_dup 1)
432		   (unspec:INT1
433		     [(and:INT1 (not:INT1 (match_dup 1)) (match_dup 2))]
434		     UNSPEC_ATOMIC))
435	      (clobber (scratch:INT1))
436	      (clobber (scratch:CC))])]
437  "TARGET_POWERPC"
438  "
439{
440  if (<MODE>mode != SImode && <MODE>mode != DImode)
441    {
442      if (PPC405_ERRATUM77)
443	FAIL;
444      rs6000_emit_sync (AND, <MODE>mode,
445			gen_rtx_NOT (<MODE>mode, operands[1]),
446			operands[2],
447			NULL_RTX, operands[0], true);
448      DONE;
449    }
450}")
451
452(define_insn_and_split "*sync_new_nand<mode>_internal"
453  [(set (match_operand:GPR 0 "gpc_reg_operand" "=&r")
454	(and:GPR
455	  (not:GPR (match_operand:GPR 1 "memory_operand" "+Z"))
456	  (match_operand:GPR 2 "gpc_reg_operand" "r")))
457   (set (match_dup 1)
458	(unspec:GPR
459	  [(and:GPR (not:GPR (match_dup 1)) (match_dup 2))]
460	  UNSPEC_ATOMIC))
461   (clobber (match_scratch:GPR 3 "=&r"))
462   (clobber (match_scratch:CC 4 "=&x"))]
463  "TARGET_POWERPC"
464  "#"
465  "&& reload_completed"
466  [(const_int 0)]
467{
468  rs6000_split_atomic_op (NOT, operands[1], operands[2],
469			  NULL_RTX, operands[0], operands[3]);
470  DONE;
471})
472
473; and<mode> without cr0 clobber to avoid generation of additional clobber 
474; in atomic splitters causing internal consistency failure.
475; cr0 already clobbered by larx/stcx.
476(define_insn "*atomic_andsi"
477  [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r,r,r")
478	(unspec:SI [(match_operand:SI 1 "gpc_reg_operand" "%r,r,r,r")
479		    (match_operand:SI 2 "and_operand" "?r,T,K,L")]
480		    UNSPEC_AND))]
481  ""
482  "@
483   and %0,%1,%2
484   {rlinm|rlwinm} %0,%1,0,%m2,%M2
485   {andil.|andi.} %0,%1,%b2
486   {andiu.|andis.} %0,%1,%u2"
487  [(set_attr "type" "*,*,compare,compare")])
488
489(define_insn "*atomic_anddi"
490  [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r,r,r")
491	(unspec:DI [(match_operand:DI 1 "gpc_reg_operand" "%r,r,r,r,r")
492		    (match_operand:DI 2 "and_operand" "?r,S,T,K,J")]
493		    UNSPEC_AND))]
494  "TARGET_POWERPC64"
495  "@
496   and %0,%1,%2
497   rldic%B2 %0,%1,0,%S2
498   rlwinm %0,%1,0,%m2,%M2
499   andi. %0,%1,%b2
500   andis. %0,%1,%u2"
501  [(set_attr "type" "*,*,*,compare,compare")
502   (set_attr "length" "4,4,4,4,4")])
503
504; the sync_*_internal patterns all have these operands:
505; 0 - memory location
506; 1 - operand
507; 2 - value in memory after operation
508; 3 - value in memory immediately before operation
509
510(define_insn "*sync_addshort_internal"
511  [(set (match_operand:SI 2 "gpc_reg_operand" "=&r")
512	(ior:SI (and:SI (plus:SI (match_operand:SI 0 "memory_operand" "+Z")
513				 (match_operand:SI 1 "add_operand" "rI"))
514			(match_operand:SI 4 "gpc_reg_operand" "r"))
515		(and:SI (not:SI (match_dup 4)) (match_dup 0))))
516   (set (match_operand:SI 3 "gpc_reg_operand" "=&b") (match_dup 0))
517   (set (match_dup 0)
518	(unspec:SI [(ior:SI (and:SI (plus:SI (match_dup 0) (match_dup 1))
519				    (match_dup 4))
520			    (and:SI (not:SI (match_dup 4)) (match_dup 0)))]
521		   UNSPEC_SYNC_OP))
522   (clobber (match_scratch:CC 5 "=&x"))
523   (clobber (match_scratch:SI 6 "=&r"))]
524  "TARGET_POWERPC && !PPC405_ERRATUM77"
525  "lwarx %3,%y0\n\tadd%I1 %2,%3,%1\n\tandc %6,%3,%4\n\tand %2,%2,%4\n\tor %2,%2,%6\n\tstwcx. %2,%y0\n\tbne- $-24"
526  [(set_attr "length" "28")])
527
528(define_insn "*sync_subshort_internal"
529  [(set (match_operand:SI 2 "gpc_reg_operand" "=&r")
530	(ior:SI (and:SI (minus:SI (match_operand:SI 0 "memory_operand" "+Z")
531				  (match_operand:SI 1 "add_operand" "rI"))
532			(match_operand:SI 4 "gpc_reg_operand" "r"))
533		(and:SI (not:SI (match_dup 4)) (match_dup 0))))
534   (set (match_operand:SI 3 "gpc_reg_operand" "=&b") (match_dup 0))
535   (set (match_dup 0)
536	(unspec:SI [(ior:SI (and:SI (minus:SI (match_dup 0) (match_dup 1))
537				    (match_dup 4))
538			    (and:SI (not:SI (match_dup 4)) (match_dup 0)))]
539		   UNSPEC_SYNC_OP))
540   (clobber (match_scratch:CC 5 "=&x"))
541   (clobber (match_scratch:SI 6 "=&r"))]
542  "TARGET_POWERPC && !PPC405_ERRATUM77"
543  "lwarx %3,%y0\n\tsubf %2,%1,%3\n\tandc %6,%3,%4\n\tand %2,%2,%4\n\tor %2,%2,%6\n\tstwcx. %2,%y0\n\tbne- $-24"
544  [(set_attr "length" "28")])
545
546(define_insn "*sync_andsi_internal"
547  [(set (match_operand:SI 2 "gpc_reg_operand" "=&r,&r,&r,&r")
548	(and:SI (match_operand:SI 0 "memory_operand" "+Z,Z,Z,Z")
549		(match_operand:SI 1 "and_operand" "r,T,K,L")))
550   (set (match_operand:SI 3 "gpc_reg_operand" "=&b,&b,&b,&b") (match_dup 0))
551   (set (match_dup 0)
552	(unspec:SI [(and:SI (match_dup 0) (match_dup 1))]
553		   UNSPEC_SYNC_OP))
554   (clobber (match_scratch:CC 4 "=&x,&x,&x,&x"))]
555  "TARGET_POWERPC && !PPC405_ERRATUM77"
556  "@
557   lwarx %3,%y0\n\tand %2,%3,%1\n\tstwcx. %2,%y0\n\tbne- $-12
558   lwarx %3,%y0\n\trlwinm %2,%3,0,%m1,%M1\n\tstwcx. %2,%y0\n\tbne- $-12
559   lwarx %3,%y0\n\tandi. %2,%3,%b1\n\tstwcx. %2,%y0\n\tbne- $-12
560   lwarx %3,%y0\n\tandis. %2,%3,%u1\n\tstwcx. %2,%y0\n\tbne- $-12"
561  [(set_attr "length" "16,16,16,16")])
562
563(define_insn "*sync_boolsi_internal"
564  [(set (match_operand:SI 2 "gpc_reg_operand" "=&r,&r,&r")
565	(match_operator:SI 4 "boolean_or_operator"
566	 [(match_operand:SI 0 "memory_operand" "+Z,Z,Z")
567	  (match_operand:SI 1 "logical_operand" "r,K,L")]))
568   (set (match_operand:SI 3 "gpc_reg_operand" "=&b,&b,&b") (match_dup 0))
569   (set (match_dup 0) (unspec:SI [(match_dup 4)] UNSPEC_SYNC_OP))
570   (clobber (match_scratch:CC 5 "=&x,&x,&x"))]
571  "TARGET_POWERPC && !PPC405_ERRATUM77"
572  "@
573   lwarx %3,%y0\n\t%q4 %2,%3,%1\n\tstwcx. %2,%y0\n\tbne- $-12
574   lwarx %3,%y0\n\t%q4i %2,%3,%b1\n\tstwcx. %2,%y0\n\tbne- $-12
575   lwarx %3,%y0\n\t%q4is %2,%3,%u1\n\tstwcx. %2,%y0\n\tbne- $-12"
576  [(set_attr "length" "16,16,16")])
577
578; This pattern could also take immediate values of operand 1,
579; since the non-NOT version of the operator is used; but this is not
580; very useful, since in practice operand 1 is a full 32-bit value.
581; Likewise, operand 5 is in practice either <= 2^16 or it is a register.
582(define_insn "*sync_boolcshort_internal"
583  [(set (match_operand:SI 2 "gpc_reg_operand" "=&r")
584	(match_operator:SI 4 "boolean_operator"
585	 [(xor:SI (match_operand:SI 0 "memory_operand" "+Z")
586		  (match_operand:SI 5 "logical_operand" "rK"))
587	  (match_operand:SI 1 "gpc_reg_operand" "r")]))
588   (set (match_operand:SI 3 "gpc_reg_operand" "=&b") (match_dup 0))
589   (set (match_dup 0) (unspec:SI [(match_dup 4)] UNSPEC_SYNC_OP))
590   (clobber (match_scratch:CC 6 "=&x"))]
591  "TARGET_POWERPC && !PPC405_ERRATUM77"
592  "lwarx %3,%y0\n\txor%I2 %2,%3,%5\n\t%q4 %2,%2,%1\n\tstwcx. %2,%y0\n\tbne- $-16"
593  [(set_attr "length" "20")])
594
595(define_insn "isync"
596  [(set (mem:BLK (match_scratch 0 "X"))
597	(unspec_volatile:BLK [(mem:BLK (match_scratch 1 "X"))] UNSPEC_ISYNC))]
598  ""
599  "{ics|isync}"
600  [(set_attr "type" "isync")])
601
602(define_expand "sync_lock_release<mode>"
603  [(set (match_operand:INT 0 "memory_operand")
604	(match_operand:INT 1 "any_operand"))]
605  ""
606  "
607{
608  emit_insn (gen_lwsync ());
609  emit_move_insn (operands[0], operands[1]);
610  DONE;
611}")
612
613; Some AIX assemblers don't accept lwsync, so we use a .long.
614(define_insn "lwsync"
615  [(set (mem:BLK (match_scratch 0 "X"))
616	(unspec_volatile:BLK [(mem:BLK (match_scratch 1 "X"))] UNSPEC_LWSYNC))]
617  ""
618{
619  if (TARGET_NO_LWSYNC)
620    return "sync";
621  else
622    return ".long 0x7c2004ac";
623}
624  [(set_attr "type" "sync")])
625
626