1169689Skan;; Machine description for PowerPC synchronization instructions.
2169689Skan;; Copyright (C) 2005 Free Software Foundation, Inc.
3169689Skan;; Contributed by Geoffrey Keating.
4169689Skan
5169689Skan;; This file is part of GCC.
6169689Skan
7169689Skan;; GCC is free software; you can redistribute it and/or modify it
8169689Skan;; under the terms of the GNU General Public License as published
9169689Skan;; by the Free Software Foundation; either version 2, or (at your
10169689Skan;; option) any later version.
11169689Skan
12169689Skan;; GCC is distributed in the hope that it will be useful, but WITHOUT
13169689Skan;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14169689Skan;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
15169689Skan;; License for more details.
16169689Skan
17169689Skan;; You should have received a copy of the GNU General Public License
18169689Skan;; along with GCC; see the file COPYING.  If not, write to the
19169689Skan;; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
20169689Skan;; MA 02110-1301, USA.
21169689Skan
22169689Skan(define_mode_attr larx [(SI "lwarx") (DI "ldarx")])
23169689Skan(define_mode_attr stcx [(SI "stwcx.") (DI "stdcx.")])
24169689Skan
25169689Skan(define_code_macro FETCHOP [plus minus ior xor and])
26169689Skan(define_code_attr fetchop_name
27169689Skan  [(plus "add") (minus "sub") (ior "ior") (xor "xor") (and "and")])
28169689Skan(define_code_attr fetchop_pred
29169689Skan  [(plus "add_operand") (minus "gpc_reg_operand")
30169689Skan   (ior "logical_operand") (xor "logical_operand") (and "and_operand")])
31169689Skan(define_code_attr fetchopsi_constr
32169689Skan  [(plus "rIL") (minus "r") (ior "rKL") (xor "rKL") (and "rTKL")])
33169689Skan(define_code_attr fetchopdi_constr
34169689Skan  [(plus "rIL") (minus "r") (ior "rKJF") (xor "rKJF") (and "rSTKJ")])
35169689Skan
36169689Skan(define_expand "memory_barrier"
37169689Skan  [(set (mem:BLK (match_dup 0))
38169689Skan	(unspec:BLK [(mem:BLK (match_dup 0))] UNSPEC_SYNC))]
39169689Skan  ""
40169689Skan{
41169689Skan  operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
42169689Skan  MEM_VOLATILE_P (operands[0]) = 1;
43169689Skan})
44169689Skan
45169689Skan(define_insn "*sync_internal"
46169689Skan  [(set (match_operand:BLK 0 "" "")
47169689Skan	(unspec:BLK [(match_operand:BLK 1 "" "")] UNSPEC_SYNC))]
48169689Skan  ""
49169689Skan  "{dcs|sync}"
50169689Skan  [(set_attr "type" "sync")])
51169689Skan
52169689Skan(define_insn "load_locked_<mode>"
53169689Skan  [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
54169689Skan	(unspec_volatile:GPR
55169689Skan	  [(match_operand:GPR 1 "memory_operand" "Z")] UNSPECV_LL))]
56169689Skan  "TARGET_POWERPC"
57169689Skan  "<larx> %0,%y1"
58169689Skan  [(set_attr "type" "load_l")])
59169689Skan
60169689Skan(define_insn "store_conditional_<mode>"
61169689Skan  [(set (match_operand:CC 0 "cc_reg_operand" "=x")
62169689Skan	(unspec_volatile:CC [(const_int 0)] UNSPECV_SC))
63169689Skan   (set (match_operand:GPR 1 "memory_operand" "=Z")
64169689Skan	(match_operand:GPR 2 "gpc_reg_operand" "r"))]
65169689Skan  "TARGET_POWERPC"
66169689Skan  "<stcx> %2,%y1"
67169689Skan  [(set_attr "type" "store_c")])
68169689Skan
69169689Skan(define_insn_and_split "sync_compare_and_swap<mode>"
70169689Skan  [(set (match_operand:GPR 0 "gpc_reg_operand" "=&r")
71169689Skan	(match_operand:GPR 1 "memory_operand" "+Z"))
72169689Skan   (set (match_dup 1)
73169689Skan	(unspec:GPR
74169689Skan	  [(match_operand:GPR 2 "reg_or_short_operand" "rI")
75169689Skan	   (match_operand:GPR 3 "gpc_reg_operand" "r")]
76169689Skan	  UNSPEC_CMPXCHG))
77169689Skan   (clobber (match_scratch:GPR 4 "=&r"))
78169689Skan   (clobber (match_scratch:CC 5 "=&x"))]
79169689Skan  "TARGET_POWERPC"
80169689Skan  "#"
81169689Skan  "&& reload_completed"
82169689Skan  [(const_int 0)]
83169689Skan{
84169689Skan  rs6000_split_compare_and_swap (operands[0], operands[1], operands[2],
85169689Skan				 operands[3], operands[4]);
86169689Skan  DONE;
87169689Skan})
88169689Skan
89169689Skan(define_expand "sync_compare_and_swaphi"
90169689Skan  [(match_operand:HI 0 "gpc_reg_operand" "")
91169689Skan   (match_operand:HI 1 "memory_operand" "")
92169689Skan   (match_operand:HI 2 "gpc_reg_operand" "")
93169689Skan   (match_operand:HI 3 "gpc_reg_operand" "")]
94169689Skan  "TARGET_POWERPC"
95169689Skan{
96169689Skan  rs6000_expand_compare_and_swapqhi (operands[0], operands[1],
97169689Skan				     operands[2], operands[3]);
98169689Skan  DONE;
99169689Skan})
100169689Skan
101169689Skan(define_expand "sync_compare_and_swapqi"
102169689Skan  [(match_operand:QI 0 "gpc_reg_operand" "")
103169689Skan   (match_operand:QI 1 "memory_operand" "")
104169689Skan   (match_operand:QI 2 "gpc_reg_operand" "")
105169689Skan   (match_operand:QI 3 "gpc_reg_operand" "")]
106169689Skan  "TARGET_POWERPC"
107169689Skan{
108169689Skan  rs6000_expand_compare_and_swapqhi (operands[0], operands[1],
109169689Skan				     operands[2], operands[3]);
110169689Skan  DONE;
111169689Skan})
112169689Skan
113169689Skan(define_insn_and_split "sync_compare_and_swapqhi_internal"
114169689Skan  [(set (match_operand:SI 0 "gpc_reg_operand" "=&r")
115169689Skan	(match_operand:SI 4 "memory_operand" "+Z"))
116169689Skan   (set (match_dup 4)
117169689Skan        (unspec:SI
118169689Skan          [(match_operand:SI 1 "gpc_reg_operand" "r")
119169689Skan           (match_operand:SI 2 "gpc_reg_operand" "r")
120169689Skan           (match_operand:SI 3 "gpc_reg_operand" "r")]
121169689Skan          UNSPEC_CMPXCHG))
122169689Skan   (clobber (match_scratch:SI 5 "=&r"))
123169689Skan   (clobber (match_scratch:CC 6 "=&x"))]
124169689Skan  "TARGET_POWERPC"
125169689Skan  "#"
126169689Skan  "&& reload_completed"
127169689Skan  [(const_int 0)]
128169689Skan{
129169689Skan  rs6000_split_compare_and_swapqhi (operands[0], operands[1],
130169689Skan				    operands[2], operands[3], operands[4],
131169689Skan				    operands[5]);
132169689Skan  DONE;
133169689Skan})
134169689Skan
135169689Skan(define_insn_and_split "sync_lock_test_and_set<mode>"
136169689Skan  [(set (match_operand:GPR 0 "gpc_reg_operand" "=&r")
137169689Skan	(match_operand:GPR 1 "memory_operand" "+Z"))
138169689Skan   (set (match_dup 1)
139169689Skan	(unspec:GPR
140169689Skan	  [(match_operand:GPR 2 "reg_or_short_operand" "rL")]
141169689Skan	  UNSPEC_XCHG))
142169689Skan   (clobber (match_scratch:GPR 3 "=&r"))
143169689Skan   (clobber (match_scratch:CC 4 "=&x"))]
144169689Skan  "TARGET_POWERPC"
145169689Skan  "#"
146169689Skan  "&& reload_completed"
147169689Skan  [(const_int 0)]
148169689Skan{
149169689Skan  rs6000_split_lock_test_and_set (operands[0], operands[1], operands[2],
150169689Skan				  operands[3]);
151169689Skan  DONE;
152169689Skan})
153169689Skan
154169689Skan(define_expand "sync_<fetchop_name><mode>"
155169689Skan  [(parallel [(set (match_operand:INT1 0 "memory_operand" "")
156169689Skan		   (unspec:INT1
157169689Skan		     [(FETCHOP:INT1 (match_dup 0)
158169689Skan			(match_operand:INT1 1 "<fetchop_pred>" ""))]
159169689Skan		     UNSPEC_ATOMIC))
160169689Skan	      (clobber (scratch:INT1))
161169689Skan	      (clobber (scratch:CC))])]
162169689Skan  "TARGET_POWERPC"
163169689Skan  "
164169689Skan{
165169689Skan  if (<MODE>mode != SImode && <MODE>mode != DImode)
166169689Skan    {
167169689Skan      if (PPC405_ERRATUM77)
168169689Skan	FAIL;
169169689Skan      rs6000_emit_sync (<CODE>, <MODE>mode, operands[0], operands[1],
170169689Skan			NULL_RTX, NULL_RTX, true);
171169689Skan      DONE;
172169689Skan    }
173169689Skan}")
174169689Skan
175169689Skan(define_insn_and_split "*sync_<fetchop_name>si_internal"
176169689Skan  [(set (match_operand:SI 0 "memory_operand" "+Z")
177169689Skan	(unspec:SI
178169689Skan	  [(FETCHOP:SI (match_dup 0)
179169689Skan	     (match_operand:SI 1 "<fetchop_pred>" "<fetchopsi_constr>"))]
180169689Skan	  UNSPEC_ATOMIC))
181169689Skan   (clobber (match_scratch:SI 2 "=&b"))
182169689Skan   (clobber (match_scratch:CC 3 "=&x"))]
183169689Skan  "TARGET_POWERPC"
184169689Skan  "#"
185169689Skan  "&& reload_completed"
186169689Skan  [(const_int 0)]
187169689Skan{
188169689Skan  rs6000_split_atomic_op (<CODE>, operands[0], operands[1],
189169689Skan			  NULL_RTX, NULL_RTX, operands[2]);
190169689Skan  DONE;
191169689Skan})
192169689Skan
193169689Skan(define_insn_and_split "*sync_<fetchop_name>di_internal"
194169689Skan  [(set (match_operand:DI 0 "memory_operand" "+Z")
195169689Skan	(unspec:DI
196169689Skan	  [(FETCHOP:DI (match_dup 0)
197169689Skan	     (match_operand:DI 1 "<fetchop_pred>" "<fetchopdi_constr>"))]
198169689Skan	  UNSPEC_ATOMIC))
199169689Skan   (clobber (match_scratch:DI 2 "=&b"))
200169689Skan   (clobber (match_scratch:CC 3 "=&x"))]
201169689Skan  "TARGET_POWERPC"
202169689Skan  "#"
203169689Skan  "&& reload_completed"
204169689Skan  [(const_int 0)]
205169689Skan{
206169689Skan  rs6000_split_atomic_op (<CODE>, operands[0], operands[1],
207169689Skan			  NULL_RTX, NULL_RTX, operands[2]);
208169689Skan  DONE;
209169689Skan})
210169689Skan
211169689Skan(define_expand "sync_nand<mode>"
212169689Skan  [(parallel [(set (match_operand:INT1 0 "memory_operand" "")
213169689Skan	      (unspec:INT1
214169689Skan		[(and:INT1 (not:INT1 (match_dup 0))
215169689Skan		   (match_operand:INT1 1 "gpc_reg_operand" ""))]
216169689Skan		UNSPEC_ATOMIC))
217169689Skan	      (clobber (scratch:INT1))
218169689Skan	      (clobber (scratch:CC))])]
219169689Skan  "TARGET_POWERPC"
220169689Skan  "
221169689Skan{
222169689Skan  if (<MODE>mode != SImode && <MODE>mode != DImode)
223169689Skan    {
224169689Skan      if (PPC405_ERRATUM77)
225169689Skan	FAIL;
226169689Skan      rs6000_emit_sync (AND, <MODE>mode,
227169689Skan			gen_rtx_NOT (<MODE>mode, operands[0]),
228169689Skan			operands[1],
229169689Skan			NULL_RTX, NULL_RTX, true);
230169689Skan      DONE;
231169689Skan    }
232169689Skan}")
233169689Skan
234169689Skan(define_insn_and_split "*sync_nand<mode>_internal"
235169689Skan  [(set (match_operand:GPR 0 "memory_operand" "+Z")
236169689Skan	(unspec:GPR
237169689Skan	  [(and:GPR (not:GPR (match_dup 0))
238169689Skan	     (match_operand:GPR 1 "gpc_reg_operand" "r"))]
239169689Skan	  UNSPEC_ATOMIC))
240169689Skan   (clobber (match_scratch:GPR 2 "=&r"))
241169689Skan   (clobber (match_scratch:CC 3 "=&x"))]
242169689Skan  "TARGET_POWERPC"
243169689Skan  "#"
244169689Skan  "&& reload_completed"
245169689Skan  [(const_int 0)]
246169689Skan{
247169689Skan  rs6000_split_atomic_op (NOT, operands[0], operands[1],
248169689Skan			  NULL_RTX, NULL_RTX, operands[2]);
249169689Skan  DONE;
250169689Skan})
251169689Skan
252169689Skan(define_expand "sync_old_<fetchop_name><mode>"
253169689Skan  [(parallel [(set (match_operand:INT1 0 "gpc_reg_operand" "")
254169689Skan		   (match_operand:INT1 1 "memory_operand" ""))
255169689Skan	      (set (match_dup 1)
256169689Skan		   (unspec:INT1
257169689Skan		     [(FETCHOP:INT1 (match_dup 1)
258169689Skan			(match_operand:INT1 2 "<fetchop_pred>" ""))]
259169689Skan		     UNSPEC_ATOMIC))
260169689Skan	      (clobber (scratch:INT1))
261169689Skan	      (clobber (scratch:CC))])]
262169689Skan  "TARGET_POWERPC"
263169689Skan  "
264169689Skan{ 
265169689Skan  if (<MODE>mode != SImode && <MODE>mode != DImode)
266169689Skan    {
267169689Skan      if (PPC405_ERRATUM77)
268169689Skan	FAIL;
269169689Skan      rs6000_emit_sync (<CODE>, <MODE>mode, operands[1], operands[2],
270169689Skan			operands[0], NULL_RTX, true);
271169689Skan      DONE;
272169689Skan    }
273169689Skan}")
274169689Skan
275169689Skan(define_insn_and_split "*sync_old_<fetchop_name>si_internal"
276169689Skan  [(set (match_operand:SI 0 "gpc_reg_operand" "=&r")
277169689Skan	(match_operand:SI 1 "memory_operand" "+Z"))
278169689Skan   (set (match_dup 1)
279169689Skan	(unspec:SI
280169689Skan	  [(FETCHOP:SI (match_dup 1)
281169689Skan	     (match_operand:SI 2 "<fetchop_pred>" "<fetchopsi_constr>"))]
282169689Skan	  UNSPEC_ATOMIC))
283169689Skan   (clobber (match_scratch:SI 3 "=&b"))
284169689Skan   (clobber (match_scratch:CC 4 "=&x"))]
285169689Skan  "TARGET_POWERPC"
286169689Skan  "#"
287169689Skan  "&& reload_completed"
288169689Skan  [(const_int 0)]
289169689Skan{
290169689Skan  rs6000_split_atomic_op (<CODE>, operands[1], operands[2],
291169689Skan			  operands[0], NULL_RTX, operands[3]);
292169689Skan  DONE;
293169689Skan})
294169689Skan
295169689Skan(define_insn_and_split "*sync_old_<fetchop_name>di_internal"
296169689Skan  [(set (match_operand:DI 0 "gpc_reg_operand" "=&r")
297169689Skan	(match_operand:DI 1 "memory_operand" "+Z"))
298169689Skan   (set (match_dup 1)
299169689Skan	(unspec:DI
300169689Skan	  [(FETCHOP:DI (match_dup 1)
301169689Skan	     (match_operand:DI 2 "<fetchop_pred>" "<fetchopdi_constr>"))]
302169689Skan	  UNSPEC_ATOMIC))
303169689Skan   (clobber (match_scratch:DI 3 "=&b"))
304169689Skan   (clobber (match_scratch:CC 4 "=&x"))]
305169689Skan  "TARGET_POWERPC"
306169689Skan  "#"
307169689Skan  "&& reload_completed"
308169689Skan  [(const_int 0)]
309169689Skan{
310169689Skan  rs6000_split_atomic_op (<CODE>, operands[1], operands[2],
311169689Skan			  operands[0], NULL_RTX, operands[3]);
312169689Skan  DONE;
313169689Skan})
314169689Skan
315169689Skan(define_expand "sync_old_nand<mode>"
316169689Skan  [(parallel [(set (match_operand:INT1 0 "gpc_reg_operand" "")
317169689Skan		   (match_operand:INT1 1 "memory_operand" ""))
318169689Skan	      (set (match_dup 1)
319169689Skan		   (unspec:INT1
320169689Skan		     [(and:INT1 (not:INT1 (match_dup 1))
321169689Skan			(match_operand:INT1 2 "gpc_reg_operand" ""))]
322169689Skan		     UNSPEC_ATOMIC))
323169689Skan	      (clobber (scratch:INT1))
324169689Skan	      (clobber (scratch:CC))])]
325169689Skan  "TARGET_POWERPC"
326169689Skan  "
327169689Skan{
328169689Skan  if (<MODE>mode != SImode && <MODE>mode != DImode)
329169689Skan    {
330169689Skan      if (PPC405_ERRATUM77)
331169689Skan	FAIL;
332169689Skan      rs6000_emit_sync (AND, <MODE>mode,
333169689Skan			gen_rtx_NOT (<MODE>mode, operands[1]),
334169689Skan			operands[2],
335169689Skan			operands[0], NULL_RTX, true);
336169689Skan      DONE;
337169689Skan    }
338169689Skan}")
339169689Skan
340169689Skan(define_insn_and_split "*sync_old_nand<mode>_internal"
341169689Skan  [(set (match_operand:GPR 0 "gpc_reg_operand" "=&r")
342169689Skan	(match_operand:GPR 1 "memory_operand" "+Z"))
343169689Skan   (set (match_dup 1)
344169689Skan	(unspec:GPR
345169689Skan	  [(and:GPR (not:GPR (match_dup 1))
346169689Skan	     (match_operand:GPR 2 "gpc_reg_operand" "r"))]
347169689Skan	  UNSPEC_ATOMIC))
348169689Skan   (clobber (match_scratch:GPR 3 "=&r"))
349169689Skan   (clobber (match_scratch:CC 4 "=&x"))]
350169689Skan  "TARGET_POWERPC"
351169689Skan  "#"
352169689Skan  "&& reload_completed"
353169689Skan  [(const_int 0)]
354169689Skan{
355169689Skan  rs6000_split_atomic_op (NOT, operands[1], operands[2],
356169689Skan			  operands[0], NULL_RTX, operands[3]);
357169689Skan  DONE;
358169689Skan})
359169689Skan
360169689Skan(define_expand "sync_new_<fetchop_name><mode>"
361169689Skan  [(parallel [(set (match_operand:INT1 0 "gpc_reg_operand" "")
362169689Skan		   (FETCHOP:INT1
363169689Skan		     (match_operand:INT1 1 "memory_operand" "")
364169689Skan		     (match_operand:INT1 2 "<fetchop_pred>" "")))
365169689Skan	      (set (match_dup 1)
366169689Skan		   (unspec:INT1
367169689Skan		     [(FETCHOP:INT1 (match_dup 1) (match_dup 2))]
368169689Skan		     UNSPEC_ATOMIC))
369169689Skan	      (clobber (scratch:INT1))
370169689Skan	      (clobber (scratch:CC))])]
371169689Skan  "TARGET_POWERPC"
372169689Skan  "
373169689Skan{
374169689Skan  if (<MODE>mode != SImode && <MODE>mode != DImode)
375169689Skan    {
376169689Skan      if (PPC405_ERRATUM77)
377169689Skan	FAIL;
378169689Skan      rs6000_emit_sync (<CODE>, <MODE>mode, operands[1], operands[2],
379169689Skan			NULL_RTX, operands[0], true);
380169689Skan      DONE;
381169689Skan    }
382169689Skan}")
383169689Skan
384169689Skan(define_insn_and_split "*sync_new_<fetchop_name>si_internal"
385169689Skan  [(set (match_operand:SI 0 "gpc_reg_operand" "=&r")
386169689Skan	(FETCHOP:SI
387169689Skan	  (match_operand:SI 1 "memory_operand" "+Z")
388169689Skan	  (match_operand:SI 2 "<fetchop_pred>" "<fetchopsi_constr>")))
389169689Skan   (set (match_dup 1)
390169689Skan	(unspec:SI
391169689Skan	  [(FETCHOP:SI (match_dup 1) (match_dup 2))]
392169689Skan	  UNSPEC_ATOMIC))
393169689Skan   (clobber (match_scratch:SI 3 "=&b"))
394169689Skan   (clobber (match_scratch:CC 4 "=&x"))]
395169689Skan  "TARGET_POWERPC"
396169689Skan  "#"
397169689Skan  "&& reload_completed"
398169689Skan  [(const_int 0)]
399169689Skan{
400169689Skan  rs6000_split_atomic_op (<CODE>, operands[1], operands[2],
401169689Skan			  NULL_RTX, operands[0], operands[3]);
402169689Skan  DONE;
403169689Skan})
404169689Skan
405169689Skan(define_insn_and_split "*sync_new_<fetchop_name>di_internal"
406169689Skan  [(set (match_operand:DI 0 "gpc_reg_operand" "=&r")
407169689Skan	(FETCHOP:DI
408169689Skan	  (match_operand:DI 1 "memory_operand" "+Z")
409169689Skan	  (match_operand:DI 2 "<fetchop_pred>" "<fetchopdi_constr>")))
410169689Skan   (set (match_dup 1)
411169689Skan	(unspec:DI
412169689Skan	  [(FETCHOP:DI (match_dup 1) (match_dup 2))]
413169689Skan	  UNSPEC_ATOMIC))
414169689Skan   (clobber (match_scratch:DI 3 "=&b"))
415169689Skan   (clobber (match_scratch:CC 4 "=&x"))]
416169689Skan  "TARGET_POWERPC"
417169689Skan  "#"
418169689Skan  "&& reload_completed"
419169689Skan  [(const_int 0)]
420169689Skan{
421169689Skan  rs6000_split_atomic_op (<CODE>, operands[1], operands[2],
422169689Skan			  NULL_RTX, operands[0], operands[3]);
423169689Skan  DONE;
424169689Skan})
425169689Skan
426169689Skan(define_expand "sync_new_nand<mode>"
427169689Skan  [(parallel [(set (match_operand:INT1 0 "gpc_reg_operand" "")
428169689Skan		   (and:INT1
429169689Skan		     (not:INT1 (match_operand:INT1 1 "memory_operand" ""))
430169689Skan		     (match_operand:INT1 2 "gpc_reg_operand" "")))
431169689Skan	      (set (match_dup 1)
432169689Skan		   (unspec:INT1
433169689Skan		     [(and:INT1 (not:INT1 (match_dup 1)) (match_dup 2))]
434169689Skan		     UNSPEC_ATOMIC))
435169689Skan	      (clobber (scratch:INT1))
436169689Skan	      (clobber (scratch:CC))])]
437169689Skan  "TARGET_POWERPC"
438169689Skan  "
439169689Skan{
440169689Skan  if (<MODE>mode != SImode && <MODE>mode != DImode)
441169689Skan    {
442169689Skan      if (PPC405_ERRATUM77)
443169689Skan	FAIL;
444169689Skan      rs6000_emit_sync (AND, <MODE>mode,
445169689Skan			gen_rtx_NOT (<MODE>mode, operands[1]),
446169689Skan			operands[2],
447169689Skan			NULL_RTX, operands[0], true);
448169689Skan      DONE;
449169689Skan    }
450169689Skan}")
451169689Skan
452169689Skan(define_insn_and_split "*sync_new_nand<mode>_internal"
453169689Skan  [(set (match_operand:GPR 0 "gpc_reg_operand" "=&r")
454169689Skan	(and:GPR
455169689Skan	  (not:GPR (match_operand:GPR 1 "memory_operand" "+Z"))
456169689Skan	  (match_operand:GPR 2 "gpc_reg_operand" "r")))
457169689Skan   (set (match_dup 1)
458169689Skan	(unspec:GPR
459169689Skan	  [(and:GPR (not:GPR (match_dup 1)) (match_dup 2))]
460169689Skan	  UNSPEC_ATOMIC))
461169689Skan   (clobber (match_scratch:GPR 3 "=&r"))
462169689Skan   (clobber (match_scratch:CC 4 "=&x"))]
463169689Skan  "TARGET_POWERPC"
464169689Skan  "#"
465169689Skan  "&& reload_completed"
466169689Skan  [(const_int 0)]
467169689Skan{
468169689Skan  rs6000_split_atomic_op (NOT, operands[1], operands[2],
469169689Skan			  NULL_RTX, operands[0], operands[3]);
470169689Skan  DONE;
471169689Skan})
472169689Skan
473169689Skan; and<mode> without cr0 clobber to avoid generation of additional clobber 
474169689Skan; in atomic splitters causing internal consistency failure.
475169689Skan; cr0 already clobbered by larx/stcx.
476169689Skan(define_insn "*atomic_andsi"
477169689Skan  [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r,r,r")
478169689Skan	(unspec:SI [(match_operand:SI 1 "gpc_reg_operand" "%r,r,r,r")
479169689Skan		    (match_operand:SI 2 "and_operand" "?r,T,K,L")]
480169689Skan		    UNSPEC_AND))]
481169689Skan  ""
482169689Skan  "@
483169689Skan   and %0,%1,%2
484169689Skan   {rlinm|rlwinm} %0,%1,0,%m2,%M2
485169689Skan   {andil.|andi.} %0,%1,%b2
486169689Skan   {andiu.|andis.} %0,%1,%u2"
487169689Skan  [(set_attr "type" "*,*,compare,compare")])
488169689Skan
489169689Skan(define_insn "*atomic_anddi"
490169689Skan  [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r,r,r")
491169689Skan	(unspec:DI [(match_operand:DI 1 "gpc_reg_operand" "%r,r,r,r,r")
492169689Skan		    (match_operand:DI 2 "and_operand" "?r,S,T,K,J")]
493169689Skan		    UNSPEC_AND))]
494169689Skan  "TARGET_POWERPC64"
495169689Skan  "@
496169689Skan   and %0,%1,%2
497169689Skan   rldic%B2 %0,%1,0,%S2
498169689Skan   rlwinm %0,%1,0,%m2,%M2
499169689Skan   andi. %0,%1,%b2
500169689Skan   andis. %0,%1,%u2"
501169689Skan  [(set_attr "type" "*,*,*,compare,compare")
502169689Skan   (set_attr "length" "4,4,4,4,4")])
503169689Skan
504169689Skan; the sync_*_internal patterns all have these operands:
505169689Skan; 0 - memory location
506169689Skan; 1 - operand
507169689Skan; 2 - value in memory after operation
508169689Skan; 3 - value in memory immediately before operation
509169689Skan
510169689Skan(define_insn "*sync_addshort_internal"
511169689Skan  [(set (match_operand:SI 2 "gpc_reg_operand" "=&r")
512169689Skan	(ior:SI (and:SI (plus:SI (match_operand:SI 0 "memory_operand" "+Z")
513169689Skan				 (match_operand:SI 1 "add_operand" "rI"))
514169689Skan			(match_operand:SI 4 "gpc_reg_operand" "r"))
515169689Skan		(and:SI (not:SI (match_dup 4)) (match_dup 0))))
516169689Skan   (set (match_operand:SI 3 "gpc_reg_operand" "=&b") (match_dup 0))
517169689Skan   (set (match_dup 0)
518169689Skan	(unspec:SI [(ior:SI (and:SI (plus:SI (match_dup 0) (match_dup 1))
519169689Skan				    (match_dup 4))
520169689Skan			    (and:SI (not:SI (match_dup 4)) (match_dup 0)))]
521169689Skan		   UNSPEC_SYNC_OP))
522169689Skan   (clobber (match_scratch:CC 5 "=&x"))
523169689Skan   (clobber (match_scratch:SI 6 "=&r"))]
524169689Skan  "TARGET_POWERPC && !PPC405_ERRATUM77"
525169689Skan  "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"
526169689Skan  [(set_attr "length" "28")])
527169689Skan
528169689Skan(define_insn "*sync_subshort_internal"
529169689Skan  [(set (match_operand:SI 2 "gpc_reg_operand" "=&r")
530169689Skan	(ior:SI (and:SI (minus:SI (match_operand:SI 0 "memory_operand" "+Z")
531169689Skan				  (match_operand:SI 1 "add_operand" "rI"))
532169689Skan			(match_operand:SI 4 "gpc_reg_operand" "r"))
533169689Skan		(and:SI (not:SI (match_dup 4)) (match_dup 0))))
534169689Skan   (set (match_operand:SI 3 "gpc_reg_operand" "=&b") (match_dup 0))
535169689Skan   (set (match_dup 0)
536169689Skan	(unspec:SI [(ior:SI (and:SI (minus:SI (match_dup 0) (match_dup 1))
537169689Skan				    (match_dup 4))
538169689Skan			    (and:SI (not:SI (match_dup 4)) (match_dup 0)))]
539169689Skan		   UNSPEC_SYNC_OP))
540169689Skan   (clobber (match_scratch:CC 5 "=&x"))
541169689Skan   (clobber (match_scratch:SI 6 "=&r"))]
542169689Skan  "TARGET_POWERPC && !PPC405_ERRATUM77"
543169689Skan  "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"
544169689Skan  [(set_attr "length" "28")])
545169689Skan
546169689Skan(define_insn "*sync_andsi_internal"
547169689Skan  [(set (match_operand:SI 2 "gpc_reg_operand" "=&r,&r,&r,&r")
548169689Skan	(and:SI (match_operand:SI 0 "memory_operand" "+Z,Z,Z,Z")
549169689Skan		(match_operand:SI 1 "and_operand" "r,T,K,L")))
550169689Skan   (set (match_operand:SI 3 "gpc_reg_operand" "=&b,&b,&b,&b") (match_dup 0))
551169689Skan   (set (match_dup 0)
552169689Skan	(unspec:SI [(and:SI (match_dup 0) (match_dup 1))]
553169689Skan		   UNSPEC_SYNC_OP))
554169689Skan   (clobber (match_scratch:CC 4 "=&x,&x,&x,&x"))]
555169689Skan  "TARGET_POWERPC && !PPC405_ERRATUM77"
556169689Skan  "@
557169689Skan   lwarx %3,%y0\n\tand %2,%3,%1\n\tstwcx. %2,%y0\n\tbne- $-12
558169689Skan   lwarx %3,%y0\n\trlwinm %2,%3,0,%m1,%M1\n\tstwcx. %2,%y0\n\tbne- $-12
559169689Skan   lwarx %3,%y0\n\tandi. %2,%3,%b1\n\tstwcx. %2,%y0\n\tbne- $-12
560169689Skan   lwarx %3,%y0\n\tandis. %2,%3,%u1\n\tstwcx. %2,%y0\n\tbne- $-12"
561169689Skan  [(set_attr "length" "16,16,16,16")])
562169689Skan
563169689Skan(define_insn "*sync_boolsi_internal"
564169689Skan  [(set (match_operand:SI 2 "gpc_reg_operand" "=&r,&r,&r")
565169689Skan	(match_operator:SI 4 "boolean_or_operator"
566169689Skan	 [(match_operand:SI 0 "memory_operand" "+Z,Z,Z")
567169689Skan	  (match_operand:SI 1 "logical_operand" "r,K,L")]))
568169689Skan   (set (match_operand:SI 3 "gpc_reg_operand" "=&b,&b,&b") (match_dup 0))
569169689Skan   (set (match_dup 0) (unspec:SI [(match_dup 4)] UNSPEC_SYNC_OP))
570169689Skan   (clobber (match_scratch:CC 5 "=&x,&x,&x"))]
571169689Skan  "TARGET_POWERPC && !PPC405_ERRATUM77"
572169689Skan  "@
573169689Skan   lwarx %3,%y0\n\t%q4 %2,%3,%1\n\tstwcx. %2,%y0\n\tbne- $-12
574169689Skan   lwarx %3,%y0\n\t%q4i %2,%3,%b1\n\tstwcx. %2,%y0\n\tbne- $-12
575169689Skan   lwarx %3,%y0\n\t%q4is %2,%3,%u1\n\tstwcx. %2,%y0\n\tbne- $-12"
576169689Skan  [(set_attr "length" "16,16,16")])
577169689Skan
578169689Skan; This pattern could also take immediate values of operand 1,
579169689Skan; since the non-NOT version of the operator is used; but this is not
580169689Skan; very useful, since in practice operand 1 is a full 32-bit value.
581169689Skan; Likewise, operand 5 is in practice either <= 2^16 or it is a register.
582169689Skan(define_insn "*sync_boolcshort_internal"
583169689Skan  [(set (match_operand:SI 2 "gpc_reg_operand" "=&r")
584169689Skan	(match_operator:SI 4 "boolean_operator"
585169689Skan	 [(xor:SI (match_operand:SI 0 "memory_operand" "+Z")
586169689Skan		  (match_operand:SI 5 "logical_operand" "rK"))
587169689Skan	  (match_operand:SI 1 "gpc_reg_operand" "r")]))
588169689Skan   (set (match_operand:SI 3 "gpc_reg_operand" "=&b") (match_dup 0))
589169689Skan   (set (match_dup 0) (unspec:SI [(match_dup 4)] UNSPEC_SYNC_OP))
590169689Skan   (clobber (match_scratch:CC 6 "=&x"))]
591169689Skan  "TARGET_POWERPC && !PPC405_ERRATUM77"
592169689Skan  "lwarx %3,%y0\n\txor%I2 %2,%3,%5\n\t%q4 %2,%2,%1\n\tstwcx. %2,%y0\n\tbne- $-16"
593169689Skan  [(set_attr "length" "20")])
594169689Skan
595169689Skan(define_insn "isync"
596169689Skan  [(set (mem:BLK (match_scratch 0 "X"))
597169689Skan	(unspec_volatile:BLK [(mem:BLK (match_scratch 1 "X"))] UNSPEC_ISYNC))]
598169689Skan  ""
599169689Skan  "{ics|isync}"
600169689Skan  [(set_attr "type" "isync")])
601169689Skan
602169689Skan(define_expand "sync_lock_release<mode>"
603169689Skan  [(set (match_operand:INT 0 "memory_operand")
604169689Skan	(match_operand:INT 1 "any_operand"))]
605169689Skan  ""
606169689Skan  "
607169689Skan{
608169689Skan  emit_insn (gen_lwsync ());
609169689Skan  emit_move_insn (operands[0], operands[1]);
610169689Skan  DONE;
611169689Skan}")
612169689Skan
613169689Skan; Some AIX assemblers don't accept lwsync, so we use a .long.
614169689Skan(define_insn "lwsync"
615169689Skan  [(set (mem:BLK (match_scratch 0 "X"))
616169689Skan	(unspec_volatile:BLK [(mem:BLK (match_scratch 1 "X"))] UNSPEC_LWSYNC))]
617169689Skan  ""
618169689Skan{
619169689Skan  if (TARGET_NO_LWSYNC)
620169689Skan    return "sync";
621169689Skan  else
622169689Skan    return ".long 0x7c2004ac";
623169689Skan}
624169689Skan  [(set_attr "type" "sync")])
625169689Skan
626