Make UNSPEC/UNSPECV constants use the enum; Fix 48192; Add test case for 48053
[official-gcc.git] / gcc / config / rs6000 / sync.md
blobc3fbd9ee0284b5225aab25d36b680a4650a7f9f7
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 "ior") (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")])
31 (define_code_attr fetchopsi_constr
32   [(plus "rIL") (minus "r") (ior "rKL") (xor "rKL") (and "rTKL")])
33 (define_code_attr fetchopdi_constr
34   [(plus "rIL") (minus "r") (ior "rKJF") (xor "rKJF") (and "rSTKJ")])
36 (define_expand "memory_barrier"
37   [(set (match_dup 0)
38         (unspec:BLK [(match_dup 0)] UNSPEC_SYNC))]
39   ""
41   operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
42   MEM_VOLATILE_P (operands[0]) = 1;
45 (define_insn "*sync_internal"
46   [(set (match_operand:BLK 0 "" "")
47         (unspec:BLK [(match_dup 0)] UNSPEC_SYNC))]
48   ""
49   "{dcs|sync}"
50   [(set_attr "type" "sync")])
52 (define_insn "load_locked_<mode>"
53   [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
54         (unspec_volatile:GPR
55           [(match_operand:GPR 1 "memory_operand" "Z")] UNSPECV_LL))]
56   "TARGET_POWERPC"
57   "<larx> %0,%y1"
58   [(set_attr "type" "load_l")])
60 (define_insn "store_conditional_<mode>"
61   [(set (match_operand:CC 0 "cc_reg_operand" "=x")
62         (unspec_volatile:CC [(const_int 0)] UNSPECV_SC))
63    (set (match_operand:GPR 1 "memory_operand" "=Z")
64         (match_operand:GPR 2 "gpc_reg_operand" "r"))]
65   "TARGET_POWERPC"
66   "<stcx> %2,%y1"
67   [(set_attr "type" "store_c")])
69 (define_insn_and_split "sync_compare_and_swap<mode>"
70   [(set (match_operand:GPR 0 "gpc_reg_operand" "=&r")
71         (match_operand:GPR 1 "memory_operand" "+Z"))
72    (set (match_dup 1)
73         (unspec:GPR
74           [(match_operand:GPR 2 "reg_or_short_operand" "rI")
75            (match_operand:GPR 3 "gpc_reg_operand" "r")]
76           UNSPEC_CMPXCHG))
77    (clobber (match_scratch:GPR 4 "=&r"))
78    (clobber (match_scratch:CC 5 "=&x"))]
79   "TARGET_POWERPC"
80   "#"
81   "&& reload_completed"
82   [(const_int 0)]
84   rs6000_split_compare_and_swap (operands[0], operands[1], operands[2],
85                                  operands[3], operands[4]);
86   DONE;
89 (define_expand "sync_compare_and_swaphi"
90   [(match_operand:HI 0 "gpc_reg_operand" "")
91    (match_operand:HI 1 "memory_operand" "")
92    (match_operand:HI 2 "gpc_reg_operand" "")
93    (match_operand:HI 3 "gpc_reg_operand" "")]
94   "TARGET_POWERPC"
96   rs6000_expand_compare_and_swapqhi (operands[0], operands[1],
97                                      operands[2], operands[3]);
98   DONE;
101 (define_expand "sync_compare_and_swapqi"
102   [(match_operand:QI 0 "gpc_reg_operand" "")
103    (match_operand:QI 1 "memory_operand" "")
104    (match_operand:QI 2 "gpc_reg_operand" "")
105    (match_operand:QI 3 "gpc_reg_operand" "")]
106   "TARGET_POWERPC"
108   rs6000_expand_compare_and_swapqhi (operands[0], operands[1],
109                                      operands[2], operands[3]);
110   DONE;
113 (define_insn_and_split "sync_compare_and_swapqhi_internal"
114   [(set (match_operand:SI 0 "gpc_reg_operand" "=&r")
115         (match_operand:SI 4 "memory_operand" "+Z"))
116    (set (match_dup 4)
117         (unspec:SI
118           [(match_operand:SI 1 "gpc_reg_operand" "r")
119            (match_operand:SI 2 "gpc_reg_operand" "r")
120            (match_operand:SI 3 "gpc_reg_operand" "r")]
121           UNSPEC_CMPXCHG))
122    (clobber (match_scratch:SI 5 "=&r"))
123    (clobber (match_scratch:CC 6 "=&x"))]
124   "TARGET_POWERPC"
125   "#"
126   "&& reload_completed"
127   [(const_int 0)]
129   rs6000_split_compare_and_swapqhi (operands[0], operands[1],
130                                     operands[2], operands[3], operands[4],
131                                     operands[5]);
132   DONE;
135 (define_insn_and_split "sync_lock_test_and_set<mode>"
136   [(set (match_operand:GPR 0 "gpc_reg_operand" "=&r")
137         (match_operand:GPR 1 "memory_operand" "+Z"))
138    (set (match_dup 1)
139         (unspec:GPR
140           [(match_operand:GPR 2 "reg_or_short_operand" "rL")]
141           UNSPEC_XCHG))
142    (clobber (match_scratch:GPR 3 "=&r"))
143    (clobber (match_scratch:CC 4 "=&x"))]
144   "TARGET_POWERPC"
145   "#"
146   "&& reload_completed"
147   [(const_int 0)]
149   rs6000_split_lock_test_and_set (operands[0], operands[1], operands[2],
150                                   operands[3]);
151   DONE;
154 (define_expand "sync_<fetchop_name><mode>"
155   [(parallel [(set (match_operand:INT1 0 "memory_operand" "")
156                    (unspec:INT1
157                      [(FETCHOP:INT1 (match_dup 0)
158                         (match_operand:INT1 1 "<fetchop_pred>" ""))]
159                      UNSPEC_ATOMIC))
160               (clobber (scratch:INT1))
161               (clobber (scratch:CC))])]
162   "TARGET_POWERPC"
163   "
165   if (<MODE>mode != SImode && <MODE>mode != DImode)
166     {
167       if (PPC405_ERRATUM77)
168         FAIL;
169       rs6000_emit_sync (<CODE>, <MODE>mode, operands[0], operands[1],
170                         NULL_RTX, NULL_RTX, true);
171       DONE;
172     }
175 (define_insn_and_split "*sync_<fetchop_name>si_internal"
176   [(set (match_operand:SI 0 "memory_operand" "+Z")
177         (unspec:SI
178           [(FETCHOP:SI (match_dup 0)
179              (match_operand:SI 1 "<fetchop_pred>" "<fetchopsi_constr>"))]
180           UNSPEC_ATOMIC))
181    (clobber (match_scratch:SI 2 "=&b"))
182    (clobber (match_scratch:CC 3 "=&x"))]
183   "TARGET_POWERPC"
184   "#"
185   "&& reload_completed"
186   [(const_int 0)]
188   rs6000_split_atomic_op (<CODE>, operands[0], operands[1],
189                           NULL_RTX, NULL_RTX, operands[2]);
190   DONE;
193 (define_insn_and_split "*sync_<fetchop_name>di_internal"
194   [(set (match_operand:DI 0 "memory_operand" "+Z")
195         (unspec:DI
196           [(FETCHOP:DI (match_dup 0)
197              (match_operand:DI 1 "<fetchop_pred>" "<fetchopdi_constr>"))]
198           UNSPEC_ATOMIC))
199    (clobber (match_scratch:DI 2 "=&b"))
200    (clobber (match_scratch:CC 3 "=&x"))]
201   "TARGET_POWERPC"
202   "#"
203   "&& reload_completed"
204   [(const_int 0)]
206   rs6000_split_atomic_op (<CODE>, operands[0], operands[1],
207                           NULL_RTX, NULL_RTX, operands[2]);
208   DONE;
211 (define_expand "sync_nand<mode>"
212   [(parallel [(set (match_operand:INT1 0 "memory_operand" "")
213               (unspec:INT1
214                 [(ior:INT1 (not:INT1 (match_dup 0))
215                            (not:INT1 (match_operand:INT1 1 "gpc_reg_operand" "")))]
216                 UNSPEC_ATOMIC))
217               (clobber (scratch:INT1))
218               (clobber (scratch:CC))])]
219   "TARGET_POWERPC"
220   "
222   if (<MODE>mode != SImode && <MODE>mode != DImode)
223     {
224       FAIL;
225       if (PPC405_ERRATUM77)
226         FAIL;
227       rs6000_emit_sync (NOT, <MODE>mode, operands[0], operands[1],
228                         NULL_RTX, NULL_RTX, true);
229       DONE;
230     }
233 (define_insn_and_split "*sync_nand<mode>_internal"
234   [(set (match_operand:GPR 0 "memory_operand" "+Z")
235         (unspec:GPR
236           [(ior:GPR (not:GPR (match_dup 0))
237                     (not:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")))]
238           UNSPEC_ATOMIC))
239    (clobber (match_scratch:GPR 2 "=&r"))
240    (clobber (match_scratch:CC 3 "=&x"))]
241   "TARGET_POWERPC"
242   "#"
243   "&& reload_completed"
244   [(const_int 0)]
246   rs6000_split_atomic_op (NOT, operands[0], operands[1],
247                           NULL_RTX, NULL_RTX, operands[2]);
248   DONE;
251 (define_expand "sync_old_<fetchop_name><mode>"
252   [(parallel [(set (match_operand:INT1 0 "gpc_reg_operand" "")
253                    (match_operand:INT1 1 "memory_operand" ""))
254               (set (match_dup 1)
255                    (unspec:INT1
256                      [(FETCHOP:INT1 (match_dup 1)
257                         (match_operand:INT1 2 "<fetchop_pred>" ""))]
258                      UNSPEC_ATOMIC))
259               (clobber (scratch:INT1))
260               (clobber (scratch:CC))])]
261   "TARGET_POWERPC"
262   "
264   if (<MODE>mode != SImode && <MODE>mode != DImode)
265     {
266       if (PPC405_ERRATUM77)
267         FAIL;
268       rs6000_emit_sync (<CODE>, <MODE>mode, operands[1], operands[2],
269                         operands[0], NULL_RTX, true);
270       DONE;
271     }
274 (define_insn_and_split "*sync_old_<fetchop_name>si_internal"
275   [(set (match_operand:SI 0 "gpc_reg_operand" "=&r")
276         (match_operand:SI 1 "memory_operand" "+Z"))
277    (set (match_dup 1)
278         (unspec:SI
279           [(FETCHOP:SI (match_dup 1)
280              (match_operand:SI 2 "<fetchop_pred>" "<fetchopsi_constr>"))]
281           UNSPEC_ATOMIC))
282    (clobber (match_scratch:SI 3 "=&b"))
283    (clobber (match_scratch:CC 4 "=&x"))]
284   "TARGET_POWERPC"
285   "#"
286   "&& reload_completed"
287   [(const_int 0)]
289   rs6000_split_atomic_op (<CODE>, operands[1], operands[2],
290                           operands[0], NULL_RTX, operands[3]);
291   DONE;
294 (define_insn_and_split "*sync_old_<fetchop_name>di_internal"
295   [(set (match_operand:DI 0 "gpc_reg_operand" "=&r")
296         (match_operand:DI 1 "memory_operand" "+Z"))
297    (set (match_dup 1)
298         (unspec:DI
299           [(FETCHOP:DI (match_dup 1)
300              (match_operand:DI 2 "<fetchop_pred>" "<fetchopdi_constr>"))]
301           UNSPEC_ATOMIC))
302    (clobber (match_scratch:DI 3 "=&b"))
303    (clobber (match_scratch:CC 4 "=&x"))]
304   "TARGET_POWERPC"
305   "#"
306   "&& reload_completed"
307   [(const_int 0)]
309   rs6000_split_atomic_op (<CODE>, operands[1], operands[2],
310                           operands[0], NULL_RTX, operands[3]);
311   DONE;
314 (define_expand "sync_old_nand<mode>"
315   [(parallel [(set (match_operand:INT1 0 "gpc_reg_operand" "")
316                    (match_operand:INT1 1 "memory_operand" ""))
317               (set (match_dup 1)
318                    (unspec:INT1
319                      [(ior:INT1 (not:INT1 (match_dup 1))
320                                 (not:INT1 (match_operand:INT1 2 "gpc_reg_operand" "")))]
321                      UNSPEC_ATOMIC))
322               (clobber (scratch:INT1))
323               (clobber (scratch:CC))])]
324   "TARGET_POWERPC"
325   "
327   if (<MODE>mode != SImode && <MODE>mode != DImode)
328     {
329       FAIL;
330       if (PPC405_ERRATUM77)
331         FAIL;
332       rs6000_emit_sync (NOT, <MODE>mode, operands[1], operands[2],
333                         operands[0], NULL_RTX, true);
334       DONE;
335     }
338 (define_insn_and_split "*sync_old_nand<mode>_internal"
339   [(set (match_operand:GPR 0 "gpc_reg_operand" "=&r")
340         (match_operand:GPR 1 "memory_operand" "+Z"))
341    (set (match_dup 1)
342         (unspec:GPR
343           [(ior:GPR (not:GPR (match_dup 1))
344                     (not:GPR (match_operand:GPR 2 "gpc_reg_operand" "r")))]
345           UNSPEC_ATOMIC))
346    (clobber (match_scratch:GPR 3 "=&r"))
347    (clobber (match_scratch:CC 4 "=&x"))]
348   "TARGET_POWERPC"
349   "#"
350   "&& reload_completed"
351   [(const_int 0)]
353   rs6000_split_atomic_op (NOT, operands[1], operands[2],
354                           operands[0], NULL_RTX, operands[3]);
355   DONE;
358 (define_expand "sync_new_<fetchop_name><mode>"
359   [(parallel [(set (match_operand:INT1 0 "gpc_reg_operand" "")
360                    (FETCHOP:INT1
361                      (match_operand:INT1 1 "memory_operand" "")
362                      (match_operand:INT1 2 "<fetchop_pred>" "")))
363               (set (match_dup 1)
364                    (unspec:INT1
365                      [(FETCHOP:INT1 (match_dup 1) (match_dup 2))]
366                      UNSPEC_ATOMIC))
367               (clobber (scratch:INT1))
368               (clobber (scratch:CC))])]
369   "TARGET_POWERPC"
370   "
372   if (<MODE>mode != SImode && <MODE>mode != DImode)
373     {
374       if (PPC405_ERRATUM77)
375         FAIL;
376       rs6000_emit_sync (<CODE>, <MODE>mode, operands[1], operands[2],
377                         NULL_RTX, operands[0], true);
378       DONE;
379     }
382 (define_insn_and_split "*sync_new_<fetchop_name>si_internal"
383   [(set (match_operand:SI 0 "gpc_reg_operand" "=&r")
384         (FETCHOP:SI
385           (match_operand:SI 1 "memory_operand" "+Z")
386           (match_operand:SI 2 "<fetchop_pred>" "<fetchopsi_constr>")))
387    (set (match_dup 1)
388         (unspec:SI
389           [(FETCHOP:SI (match_dup 1) (match_dup 2))]
390           UNSPEC_ATOMIC))
391    (clobber (match_scratch:SI 3 "=&b"))
392    (clobber (match_scratch:CC 4 "=&x"))]
393   "TARGET_POWERPC"
394   "#"
395   "&& reload_completed"
396   [(const_int 0)]
398   rs6000_split_atomic_op (<CODE>, operands[1], operands[2],
399                           NULL_RTX, operands[0], operands[3]);
400   DONE;
403 (define_insn_and_split "*sync_new_<fetchop_name>di_internal"
404   [(set (match_operand:DI 0 "gpc_reg_operand" "=&r")
405         (FETCHOP:DI
406           (match_operand:DI 1 "memory_operand" "+Z")
407           (match_operand:DI 2 "<fetchop_pred>" "<fetchopdi_constr>")))
408    (set (match_dup 1)
409         (unspec:DI
410           [(FETCHOP:DI (match_dup 1) (match_dup 2))]
411           UNSPEC_ATOMIC))
412    (clobber (match_scratch:DI 3 "=&b"))
413    (clobber (match_scratch:CC 4 "=&x"))]
414   "TARGET_POWERPC"
415   "#"
416   "&& reload_completed"
417   [(const_int 0)]
419   rs6000_split_atomic_op (<CODE>, operands[1], operands[2],
420                           NULL_RTX, operands[0], operands[3]);
421   DONE;
424 (define_expand "sync_new_nand<mode>"
425   [(parallel [(set (match_operand:INT1 0 "gpc_reg_operand" "")
426                    (ior:INT1
427                      (not:INT1 (match_operand:INT1 1 "memory_operand" ""))
428                      (not:INT1 (match_operand:INT1 2 "gpc_reg_operand" ""))))
429               (set (match_dup 1)
430                    (unspec:INT1
431                      [(ior:INT1 (not:INT1 (match_dup 1))
432                                 (not:INT1 (match_dup 2)))]
433                      UNSPEC_ATOMIC))
434               (clobber (scratch:INT1))
435               (clobber (scratch:CC))])]
436   "TARGET_POWERPC"
437   "
439   if (<MODE>mode != SImode && <MODE>mode != DImode)
440     {
441       FAIL;
442       if (PPC405_ERRATUM77)
443         FAIL;
444       rs6000_emit_sync (NOT, <MODE>mode, operands[1], operands[2],
445                         NULL_RTX, operands[0], true);
446       DONE;
447     }
450 (define_insn_and_split "*sync_new_nand<mode>_internal"
451   [(set (match_operand:GPR 0 "gpc_reg_operand" "=&r")
452         (ior:GPR
453           (not:GPR (match_operand:GPR 1 "memory_operand" "+Z"))
454           (not:GPR (match_operand:GPR 2 "gpc_reg_operand" "r"))))
455    (set (match_dup 1)
456         (unspec:GPR
457           [(ior:GPR (not:GPR (match_dup 1)) (not:GPR (match_dup 2)))]
458           UNSPEC_ATOMIC))
459    (clobber (match_scratch:GPR 3 "=&r"))
460    (clobber (match_scratch:CC 4 "=&x"))]
461   "TARGET_POWERPC"
462   "#"
463   "&& reload_completed"
464   [(const_int 0)]
466   rs6000_split_atomic_op (NOT, operands[1], operands[2],
467                           NULL_RTX, operands[0], operands[3]);
468   DONE;
471 ; and<mode> without cr0 clobber to avoid generation of additional clobber 
472 ; in atomic splitters causing internal consistency failure.
473 ; cr0 already clobbered by larx/stcx.
474 (define_insn "*atomic_andsi"
475   [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r,r,r")
476         (unspec:SI [(match_operand:SI 1 "gpc_reg_operand" "%r,r,r,r")
477                     (match_operand:SI 2 "and_operand" "?r,T,K,L")]
478                     UNSPEC_AND))]
479   ""
480   "@
481    and %0,%1,%2
482    {rlinm|rlwinm} %0,%1,0,%m2,%M2
483    {andil.|andi.} %0,%1,%b2
484    {andiu.|andis.} %0,%1,%u2"
485   [(set_attr "type" "*,*,compare,compare")])
487 (define_insn "*atomic_anddi"
488   [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r,r,r")
489         (unspec:DI [(match_operand:DI 1 "gpc_reg_operand" "%r,r,r,r,r")
490                     (match_operand:DI 2 "and_operand" "?r,S,T,K,J")]
491                     UNSPEC_AND))]
492   "TARGET_POWERPC64"
493   "@
494    and %0,%1,%2
495    rldic%B2 %0,%1,0,%S2
496    rlwinm %0,%1,0,%m2,%M2
497    andi. %0,%1,%b2
498    andis. %0,%1,%u2"
499   [(set_attr "type" "*,*,*,compare,compare")
500    (set_attr "length" "4,4,4,4,4")])
502 ; the sync_*_internal patterns all have these operands:
503 ; 0 - memory location
504 ; 1 - operand
505 ; 2 - value in memory after operation
506 ; 3 - value in memory immediately before operation
508 (define_insn "*sync_addshort_internal"
509   [(set (match_operand:SI 2 "gpc_reg_operand" "=&r")
510         (ior:SI (and:SI (plus:SI (match_operand:SI 0 "memory_operand" "+Z")
511                                  (match_operand:SI 1 "add_operand" "rI"))
512                         (match_operand:SI 4 "gpc_reg_operand" "r"))
513                 (and:SI (not:SI (match_dup 4)) (match_dup 0))))
514    (set (match_operand:SI 3 "gpc_reg_operand" "=&b") (match_dup 0))
515    (set (match_dup 0)
516         (unspec:SI [(ior:SI (and:SI (plus:SI (match_dup 0) (match_dup 1))
517                                     (match_dup 4))
518                             (and:SI (not:SI (match_dup 4)) (match_dup 0)))]
519                    UNSPEC_SYNC_OP))
520    (clobber (match_scratch:CC 5 "=&x"))
521    (clobber (match_scratch:SI 6 "=&r"))]
522   "TARGET_POWERPC && !PPC405_ERRATUM77"
523   "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"
524   [(set_attr "length" "28")])
526 (define_insn "*sync_subshort_internal"
527   [(set (match_operand:SI 2 "gpc_reg_operand" "=&r")
528         (ior:SI (and:SI (minus:SI (match_operand:SI 0 "memory_operand" "+Z")
529                                   (match_operand:SI 1 "add_operand" "rI"))
530                         (match_operand:SI 4 "gpc_reg_operand" "r"))
531                 (and:SI (not:SI (match_dup 4)) (match_dup 0))))
532    (set (match_operand:SI 3 "gpc_reg_operand" "=&b") (match_dup 0))
533    (set (match_dup 0)
534         (unspec:SI [(ior:SI (and:SI (minus:SI (match_dup 0) (match_dup 1))
535                                     (match_dup 4))
536                             (and:SI (not:SI (match_dup 4)) (match_dup 0)))]
537                    UNSPEC_SYNC_OP))
538    (clobber (match_scratch:CC 5 "=&x"))
539    (clobber (match_scratch:SI 6 "=&r"))]
540   "TARGET_POWERPC && !PPC405_ERRATUM77"
541   "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"
542   [(set_attr "length" "28")])
544 (define_insn "*sync_andsi_internal"
545   [(set (match_operand:SI 2 "gpc_reg_operand" "=&r,&r,&r,&r")
546         (and:SI (match_operand:SI 0 "memory_operand" "+Z,Z,Z,Z")
547                 (match_operand:SI 1 "and_operand" "r,T,K,L")))
548    (set (match_operand:SI 3 "gpc_reg_operand" "=&b,&b,&b,&b") (match_dup 0))
549    (set (match_dup 0)
550         (unspec:SI [(and:SI (match_dup 0) (match_dup 1))]
551                    UNSPEC_SYNC_OP))
552    (clobber (match_scratch:CC 4 "=&x,&x,&x,&x"))]
553   "TARGET_POWERPC && !PPC405_ERRATUM77"
554   "@
555    lwarx %3,%y0\n\tand %2,%3,%1\n\tstwcx. %2,%y0\n\tbne- $-12
556    lwarx %3,%y0\n\trlwinm %2,%3,0,%m1,%M1\n\tstwcx. %2,%y0\n\tbne- $-12
557    lwarx %3,%y0\n\tandi. %2,%3,%b1\n\tstwcx. %2,%y0\n\tbne- $-12
558    lwarx %3,%y0\n\tandis. %2,%3,%u1\n\tstwcx. %2,%y0\n\tbne- $-12"
559   [(set_attr "length" "16,16,16,16")])
561 (define_insn "*sync_boolsi_internal"
562   [(set (match_operand:SI 2 "gpc_reg_operand" "=&r,&r,&r")
563         (match_operator:SI 4 "boolean_or_operator"
564          [(match_operand:SI 0 "memory_operand" "+Z,Z,Z")
565           (match_operand:SI 1 "logical_operand" "r,K,L")]))
566    (set (match_operand:SI 3 "gpc_reg_operand" "=&b,&b,&b") (match_dup 0))
567    (set (match_dup 0) (unspec:SI [(match_dup 4)] UNSPEC_SYNC_OP))
568    (clobber (match_scratch:CC 5 "=&x,&x,&x"))]
569   "TARGET_POWERPC && !PPC405_ERRATUM77"
570   "@
571    lwarx %3,%y0\n\t%q4 %2,%3,%1\n\tstwcx. %2,%y0\n\tbne- $-12
572    lwarx %3,%y0\n\t%q4i %2,%3,%b1\n\tstwcx. %2,%y0\n\tbne- $-12
573    lwarx %3,%y0\n\t%q4is %2,%3,%u1\n\tstwcx. %2,%y0\n\tbne- $-12"
574   [(set_attr "length" "16,16,16")])
576 ; This pattern could also take immediate values of operand 1,
577 ; since the non-NOT version of the operator is used; but this is not
578 ; very useful, since in practice operand 1 is a full 32-bit value.
579 ; Likewise, operand 5 is in practice either <= 2^16 or it is a register.
580 (define_insn "*sync_boolcshort_internal"
581   [(set (match_operand:SI 2 "gpc_reg_operand" "=&r")
582         (match_operator:SI 4 "boolean_or_operator"
583          [(xor:SI (not:SI (match_operand:SI 0 "memory_operand" "+Z"))
584                   (not:SI (match_operand:SI 5 "logical_operand" "rK")))
585          (match_operand:SI 1 "gpc_reg_operand" "r")]))
586    (set (match_operand:SI 3 "gpc_reg_operand" "=&b") (match_dup 0))
587    (set (match_dup 0) (unspec:SI [(match_dup 4)] UNSPEC_SYNC_OP))
588    (clobber (match_scratch:CC 6 "=&x"))]
589   "TARGET_POWERPC && !PPC405_ERRATUM77"
590   "lwarx %3,%y0\n\txor%I2 %2,%3,%5\n\t%q4 %2,%2,%1\n\tstwcx. %2,%y0\n\tbne- $-16"
591   [(set_attr "length" "20")])
593 (define_insn "isync"
594   [(set (mem:BLK (match_scratch 0 "X"))
595         (unspec_volatile:BLK [(mem:BLK (match_scratch 1 "X"))] UNSPECV_ISYNC))]
596   ""
597   "{ics|isync}"
598   [(set_attr "type" "isync")])
600 (define_expand "sync_lock_release<mode>"
601   [(set (match_operand:INT 0 "memory_operand")
602         (match_operand:INT 1 "any_operand"))]
603   ""
604   "
606   emit_insn (gen_lwsync ());
607   emit_move_insn (operands[0], operands[1]);
608   DONE;
611 ; Some AIX assemblers don't accept lwsync, so we use a .long.
612 (define_insn "lwsync"
613   [(set (mem:BLK (match_scratch 0 "X"))
614         (unspec_volatile:BLK [(mem:BLK (match_scratch 1 "X"))] UNSPECV_LWSYNC))]
615   ""
617   if (TARGET_NO_LWSYNC)
618     return "sync";
619   else
620     return (TARGET_LWSYNC_INSTRUCTION) ? "lwsync" : ".long 0x7c2004ac";
622   [(set_attr "type" "sync")])