2011-03-21 Daniel Jacobowitz <dan@codesourcery.com>
[official-gcc.git] / gcc / config / arm / sync.md
blob689a235c16f5e141eedf4acd08956b2e2b6ca697
1 ;; Machine description for ARM processor synchronization primitives.
2 ;; Copyright (C) 2010 Free Software Foundation, Inc.
3 ;; Written by Marcus Shawcroft (marcus.shawcroft@arm.com)
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 by
9 ;; the Free Software Foundation; either version 3, or (at your option)
10 ;; any later version.
12 ;; GCC is distributed in the hope that it will be useful, but
13 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
14 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 ;; General Public License for more details.
17 ;; You should have received a copy of the GNU General Public License
18 ;; along with GCC; see the file COPYING3.  If not see
19 ;; <http://www.gnu.org/licenses/>.  */
21 ;; ARMV6 introduced ldrex and strex instruction. These instruction
22 ;; access SI width data. In order to implement synchronization
23 ;; primitives for the narrower QI and HI modes we insert appropriate
24 ;; AND/OR sequences into the synchronization loop to mask out the
25 ;; relevant component of an SI access.
27 (define_expand "memory_barrier"
28   [(set (match_dup 0)
29         (unspec:BLK [(match_dup 0)] UNSPEC_MEMORY_BARRIER))]
30   "TARGET_HAVE_MEMORY_BARRIER"
32   operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
33   MEM_VOLATILE_P (operands[0]) = 1;
36 (define_expand "sync_compare_and_swapsi"
37   [(set (match_operand:SI 0 "s_register_operand")
38         (unspec_volatile:SI [(match_operand:SI 1 "memory_operand")
39                              (match_operand:SI 2 "s_register_operand")
40                              (match_operand:SI 3 "s_register_operand")]
41                              VUNSPEC_SYNC_COMPARE_AND_SWAP))]
42   "TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER"
43   {
44     struct arm_sync_generator generator;
45     generator.op = arm_sync_generator_omrn;
46     generator.u.omrn = gen_arm_sync_compare_and_swapsi;
47     arm_expand_sync (SImode, &generator, operands[0], operands[1], operands[2],
48                      operands[3]);
49     DONE;
50   })
52 (define_mode_iterator NARROW [QI HI])
54 (define_expand "sync_compare_and_swap<mode>"
55   [(set (match_operand:NARROW 0 "s_register_operand")
56         (unspec_volatile:NARROW [(match_operand:NARROW 1 "memory_operand")
57                              (match_operand:NARROW 2 "s_register_operand")
58                              (match_operand:NARROW 3 "s_register_operand")]
59                              VUNSPEC_SYNC_COMPARE_AND_SWAP))]
60   "TARGET_HAVE_LDREXBHD && TARGET_HAVE_MEMORY_BARRIER"
61   {
62     struct arm_sync_generator generator;
63     generator.op = arm_sync_generator_omrn;
64     generator.u.omrn = gen_arm_sync_compare_and_swap<mode>;
65     arm_expand_sync (<MODE>mode, &generator, operands[0], operands[1],
66                      operands[2], operands[3]);
67     DONE;
68   })
70 (define_expand "sync_lock_test_and_setsi"
71   [(match_operand:SI 0 "s_register_operand")
72    (match_operand:SI 1 "memory_operand")
73    (match_operand:SI 2 "s_register_operand")]
74   "TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER"
75   {
76     struct arm_sync_generator generator;
77     generator.op = arm_sync_generator_omn;
78     generator.u.omn = gen_arm_sync_lock_test_and_setsi;
79     arm_expand_sync (SImode, &generator, operands[0], operands[1], NULL,
80                      operands[2]);
81     DONE;
82   })
84 (define_expand "sync_lock_test_and_set<mode>"
85   [(match_operand:NARROW 0 "s_register_operand")
86    (match_operand:NARROW 1 "memory_operand")
87    (match_operand:NARROW 2 "s_register_operand")]
88   "TARGET_HAVE_LDREXBHD && TARGET_HAVE_MEMORY_BARRIER"
89   {
90     struct arm_sync_generator generator;
91     generator.op = arm_sync_generator_omn;
92     generator.u.omn = gen_arm_sync_lock_test_and_set<mode>;
93     arm_expand_sync (<MODE>mode, &generator, operands[0], operands[1], NULL,
94                      operands[2]);
95     DONE;
96   })
98 (define_code_iterator syncop [plus minus ior xor and])
100 (define_code_attr sync_optab [(ior "ior")
101                               (xor "xor")
102                               (and "and")
103                               (plus "add")
104                               (minus "sub")])
106 (define_code_attr sync_clobber [(ior "=&r")
107                                 (and "=&r")
108                                 (xor "X")
109                                 (plus "X")
110                                 (minus "X")])
112 (define_code_attr sync_t2_reqd [(ior "4")
113                                 (and "4")
114                                 (xor "*")
115                                 (plus "*")
116                                 (minus "*")])
118 (define_expand "sync_<sync_optab>si"
119   [(match_operand:SI 0 "memory_operand")
120    (match_operand:SI 1 "s_register_operand")
121    (syncop:SI (match_dup 0) (match_dup 1))]
122   "TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER"
123   {
124     struct arm_sync_generator generator;
125     generator.op = arm_sync_generator_omn;
126     generator.u.omn = gen_arm_sync_new_<sync_optab>si;
127     arm_expand_sync (SImode, &generator, NULL, operands[0], NULL, operands[1]);
128     DONE;
129   })
131 (define_expand "sync_nandsi"
132   [(match_operand:SI 0 "memory_operand")
133    (match_operand:SI 1 "s_register_operand")
134    (not:SI (and:SI (match_dup 0) (match_dup 1)))]
135   "TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER"
136   {
137     struct arm_sync_generator generator;
138     generator.op = arm_sync_generator_omn;
139     generator.u.omn = gen_arm_sync_new_nandsi;
140     arm_expand_sync (SImode, &generator, NULL, operands[0], NULL, operands[1]);
141     DONE;
142   })
144 (define_expand "sync_<sync_optab><mode>"
145   [(match_operand:NARROW 0 "memory_operand")
146    (match_operand:NARROW 1 "s_register_operand")
147    (syncop:NARROW (match_dup 0) (match_dup 1))]
148   "TARGET_HAVE_LDREXBHD && TARGET_HAVE_MEMORY_BARRIER"
149   {
150     struct arm_sync_generator generator;
151     generator.op = arm_sync_generator_omn;
152     generator.u.omn = gen_arm_sync_new_<sync_optab><mode>;
153     arm_expand_sync (<MODE>mode, &generator, NULL, operands[0], NULL,
154                      operands[1]);
155     DONE;
156   })
158 (define_expand "sync_nand<mode>"
159   [(match_operand:NARROW 0 "memory_operand")
160    (match_operand:NARROW 1 "s_register_operand")
161    (not:NARROW (and:NARROW (match_dup 0) (match_dup 1)))]
162   "TARGET_HAVE_LDREXBHD && TARGET_HAVE_MEMORY_BARRIER"
163   {
164     struct arm_sync_generator generator;
165     generator.op = arm_sync_generator_omn;
166     generator.u.omn = gen_arm_sync_new_nand<mode>;
167     arm_expand_sync (<MODE>mode, &generator, NULL, operands[0], NULL,
168                      operands[1]);
169     DONE;
170   })
172 (define_expand "sync_new_<sync_optab>si"
173   [(match_operand:SI 0 "s_register_operand")
174    (match_operand:SI 1 "memory_operand")
175    (match_operand:SI 2 "s_register_operand")
176    (syncop:SI (match_dup 1) (match_dup 2))]
177   "TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER"
178   {
179     struct arm_sync_generator generator;
180     generator.op = arm_sync_generator_omn;
181     generator.u.omn = gen_arm_sync_new_<sync_optab>si;
182     arm_expand_sync (SImode, &generator, operands[0], operands[1], NULL,
183                      operands[2]);
184     DONE;
185   })
187 (define_expand "sync_new_nandsi"
188   [(match_operand:SI 0 "s_register_operand")
189    (match_operand:SI 1 "memory_operand")
190    (match_operand:SI 2 "s_register_operand")
191    (not:SI (and:SI (match_dup 1) (match_dup 2)))]
192   "TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER"
193   {
194     struct arm_sync_generator generator;
195     generator.op = arm_sync_generator_omn;
196     generator.u.omn = gen_arm_sync_new_nandsi;
197     arm_expand_sync (SImode, &generator, operands[0], operands[1], NULL,
198                      operands[2]);
199     DONE;
200   })
202 (define_expand "sync_new_<sync_optab><mode>"
203   [(match_operand:NARROW 0 "s_register_operand")
204    (match_operand:NARROW 1 "memory_operand")
205    (match_operand:NARROW 2 "s_register_operand")
206    (syncop:NARROW (match_dup 1) (match_dup 2))]
207   "TARGET_HAVE_LDREXBHD && TARGET_HAVE_MEMORY_BARRIER"
208   {
209     struct arm_sync_generator generator;
210     generator.op = arm_sync_generator_omn;
211     generator.u.omn = gen_arm_sync_new_<sync_optab><mode>;
212     arm_expand_sync (<MODE>mode, &generator, operands[0], operands[1],
213                      NULL, operands[2]);
214     DONE;
215   })
217 (define_expand "sync_new_nand<mode>"
218   [(match_operand:NARROW 0 "s_register_operand")
219    (match_operand:NARROW 1 "memory_operand")
220    (match_operand:NARROW 2 "s_register_operand")
221    (not:NARROW (and:NARROW (match_dup 1) (match_dup 2)))]
222   "TARGET_HAVE_LDREXBHD && TARGET_HAVE_MEMORY_BARRIER"
223   {
224     struct arm_sync_generator generator;
225     generator.op = arm_sync_generator_omn;
226     generator.u.omn = gen_arm_sync_new_nand<mode>;
227     arm_expand_sync (<MODE>mode, &generator, operands[0], operands[1],
228                      NULL, operands[2]);
229     DONE;
230   });
232 (define_expand "sync_old_<sync_optab>si"
233   [(match_operand:SI 0 "s_register_operand")
234    (match_operand:SI 1 "memory_operand")
235    (match_operand:SI 2 "s_register_operand")
236    (syncop:SI (match_dup 1) (match_dup 2))]
237   "TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER"
238   {
239     struct arm_sync_generator generator;
240     generator.op = arm_sync_generator_omn;
241     generator.u.omn = gen_arm_sync_old_<sync_optab>si;
242     arm_expand_sync (SImode, &generator, operands[0], operands[1], NULL,
243                      operands[2]);
244     DONE;
245   })
247 (define_expand "sync_old_nandsi"
248   [(match_operand:SI 0 "s_register_operand")
249    (match_operand:SI 1 "memory_operand")
250    (match_operand:SI 2 "s_register_operand")
251    (not:SI (and:SI (match_dup 1) (match_dup 2)))]
252   "TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER"
253   {
254     struct arm_sync_generator generator;
255     generator.op = arm_sync_generator_omn;
256     generator.u.omn = gen_arm_sync_old_nandsi;
257     arm_expand_sync (SImode, &generator, operands[0], operands[1], NULL,
258                      operands[2]);
259     DONE;
260   })
262 (define_expand "sync_old_<sync_optab><mode>"
263   [(match_operand:NARROW 0 "s_register_operand")
264    (match_operand:NARROW 1 "memory_operand")
265    (match_operand:NARROW 2 "s_register_operand")
266    (syncop:NARROW (match_dup 1) (match_dup 2))]
267   "TARGET_HAVE_LDREXBHD && TARGET_HAVE_MEMORY_BARRIER"
268   {
269     struct arm_sync_generator generator;
270     generator.op = arm_sync_generator_omn;
271     generator.u.omn = gen_arm_sync_old_<sync_optab><mode>;
272     arm_expand_sync (<MODE>mode, &generator, operands[0], operands[1],
273                      NULL, operands[2]);
274     DONE;
275   })
277 (define_expand "sync_old_nand<mode>"
278   [(match_operand:NARROW 0 "s_register_operand")
279    (match_operand:NARROW 1 "memory_operand")
280    (match_operand:NARROW 2 "s_register_operand")
281    (not:NARROW (and:NARROW (match_dup 1) (match_dup 2)))]
282   "TARGET_HAVE_LDREXBHD && TARGET_HAVE_MEMORY_BARRIER"
283   {
284     struct arm_sync_generator generator;
285     generator.op = arm_sync_generator_omn;
286     generator.u.omn = gen_arm_sync_old_nand<mode>;
287     arm_expand_sync (<MODE>mode, &generator, operands[0], operands[1],
288                      NULL, operands[2]);
289     DONE;
290   })
292 (define_insn "arm_sync_compare_and_swapsi"
293   [(set (match_operand:SI 0 "s_register_operand" "=&r")
294         (unspec_volatile:SI
295           [(match_operand:SI 1 "arm_sync_memory_operand" "+Q")
296            (match_operand:SI 2 "s_register_operand" "r")
297            (match_operand:SI 3 "s_register_operand" "r")]
298           VUNSPEC_SYNC_COMPARE_AND_SWAP))
299    (set (match_dup 1) (unspec_volatile:SI [(match_dup 2)]
300                                           VUNSPEC_SYNC_COMPARE_AND_SWAP))
301    (set (reg:CC CC_REGNUM) (unspec_volatile:CC [(match_dup 1)]
302                                                 VUNSPEC_SYNC_COMPARE_AND_SWAP))
303    ]
304   "TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER"
305   {
306     return arm_output_sync_insn (insn, operands);
307   } 
308   [(set_attr "sync_result"          "0")
309    (set_attr "sync_memory"          "1")
310    (set_attr "sync_required_value"  "2")
311    (set_attr "sync_new_value"       "3")
312    (set_attr "sync_t1"              "0")
313    (set_attr "conds" "clob")
314    (set_attr "predicable" "no")])
316 (define_insn "arm_sync_compare_and_swap<mode>"
317   [(set (match_operand:SI 0 "s_register_operand" "=&r")
318         (zero_extend:SI
319           (unspec_volatile:NARROW
320             [(match_operand:NARROW 1 "arm_sync_memory_operand" "+Q")
321              (match_operand:SI 2 "s_register_operand" "r")
322              (match_operand:SI 3 "s_register_operand" "r")]
323             VUNSPEC_SYNC_COMPARE_AND_SWAP)))
324    (set (match_dup 1) (unspec_volatile:NARROW [(match_dup 2)]
325                                           VUNSPEC_SYNC_COMPARE_AND_SWAP))
326    (set (reg:CC CC_REGNUM) (unspec_volatile:CC [(match_dup 1)]
327                                                 VUNSPEC_SYNC_COMPARE_AND_SWAP))
328    ]
329   "TARGET_HAVE_LDREXBHD && TARGET_HAVE_MEMORY_BARRIER"
330   {
331     return arm_output_sync_insn (insn, operands);
332   } 
333   [(set_attr "sync_result"          "0")
334    (set_attr "sync_memory"          "1")
335    (set_attr "sync_required_value"  "2")
336    (set_attr "sync_new_value"       "3")
337    (set_attr "sync_t1"              "0")
338    (set_attr "conds" "clob")
339    (set_attr "predicable" "no")])
341 (define_insn "arm_sync_lock_test_and_setsi"
342   [(set (match_operand:SI 0 "s_register_operand" "=&r")
343         (match_operand:SI 1 "arm_sync_memory_operand" "+Q"))
344    (set (match_dup 1)
345         (unspec_volatile:SI [(match_operand:SI 2 "s_register_operand" "r")]
346                             VUNSPEC_SYNC_LOCK))
347    (clobber (reg:CC CC_REGNUM))
348    (clobber (match_scratch:SI 3 "=&r"))]
349   "TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER"
350   {
351     return arm_output_sync_insn (insn, operands);
352   } 
353   [(set_attr "sync_release_barrier" "no")
354    (set_attr "sync_result"          "0")
355    (set_attr "sync_memory"          "1")
356    (set_attr "sync_new_value"       "2")
357    (set_attr "sync_t1"              "0")
358    (set_attr "sync_t2"              "3")
359    (set_attr "conds" "clob")
360    (set_attr "predicable" "no")])
362 (define_insn "arm_sync_lock_test_and_set<mode>"
363   [(set (match_operand:SI 0 "s_register_operand" "=&r")
364         (zero_extend:SI (match_operand:NARROW 1 "arm_sync_memory_operand" "+Q")))
365    (set (match_dup 1)
366         (unspec_volatile:NARROW [(match_operand:SI 2 "s_register_operand" "r")]
367                                 VUNSPEC_SYNC_LOCK))
368    (clobber (reg:CC CC_REGNUM))
369    (clobber (match_scratch:SI 3 "=&r"))]
370   "TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER"
371   {
372     return arm_output_sync_insn (insn, operands);
373   } 
374   [(set_attr "sync_release_barrier" "no")
375    (set_attr "sync_result"          "0")
376    (set_attr "sync_memory"          "1")
377    (set_attr "sync_new_value"       "2")
378    (set_attr "sync_t1"              "0")
379    (set_attr "sync_t2"              "3")
380    (set_attr "conds" "clob")
381    (set_attr "predicable" "no")])
383 (define_insn "arm_sync_new_<sync_optab>si"
384   [(set (match_operand:SI 0 "s_register_operand" "=&r")
385         (unspec_volatile:SI [(syncop:SI
386                                (match_operand:SI 1 "arm_sync_memory_operand" "+Q")
387                                (match_operand:SI 2 "s_register_operand" "r"))
388                             ]
389                             VUNSPEC_SYNC_NEW_OP))
390    (set (match_dup 1)
391         (unspec_volatile:SI [(match_dup 1) (match_dup 2)]
392                             VUNSPEC_SYNC_NEW_OP))
393    (clobber (reg:CC CC_REGNUM))
394    (clobber (match_scratch:SI 3 "=&r"))]
395   "TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER"
396   {
397     return arm_output_sync_insn (insn, operands);
398   } 
399   [(set_attr "sync_result"          "0")
400    (set_attr "sync_memory"          "1")
401    (set_attr "sync_new_value"       "2")
402    (set_attr "sync_t1"              "0")
403    (set_attr "sync_t2"              "3")
404    (set_attr "sync_op"              "<sync_optab>")
405    (set_attr "conds" "clob")
406    (set_attr "predicable" "no")])
408 (define_insn "arm_sync_new_nandsi"
409   [(set (match_operand:SI 0 "s_register_operand" "=&r")
410         (unspec_volatile:SI [(not:SI (and:SI
411                                (match_operand:SI 1 "arm_sync_memory_operand" "+Q")
412                                (match_operand:SI 2 "s_register_operand" "r")))
413                             ]
414                             VUNSPEC_SYNC_NEW_OP))
415    (set (match_dup 1)
416         (unspec_volatile:SI [(match_dup 1) (match_dup 2)]
417                             VUNSPEC_SYNC_NEW_OP))
418    (clobber (reg:CC CC_REGNUM))
419    (clobber (match_scratch:SI 3 "=&r"))]
420   "TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER"
421   {
422     return arm_output_sync_insn (insn, operands);
423   } 
424   [(set_attr "sync_result"          "0")
425    (set_attr "sync_memory"          "1")
426    (set_attr "sync_new_value"       "2")
427    (set_attr "sync_t1"              "0")
428    (set_attr "sync_t2"              "3")
429    (set_attr "sync_op"              "nand")
430    (set_attr "conds" "clob")
431    (set_attr "predicable" "no")])
433 (define_insn "arm_sync_new_<sync_optab><mode>"
434   [(set (match_operand:SI 0 "s_register_operand" "=&r")
435         (unspec_volatile:SI [(syncop:SI
436                                (zero_extend:SI
437                                  (match_operand:NARROW 1 "arm_sync_memory_operand" "+Q"))
438                                (match_operand:SI 2 "s_register_operand" "r"))
439                             ]
440                             VUNSPEC_SYNC_NEW_OP))
441    (set (match_dup 1)
442         (unspec_volatile:NARROW [(match_dup 1) (match_dup 2)]
443                                 VUNSPEC_SYNC_NEW_OP))
444    (clobber (reg:CC CC_REGNUM))
445    (clobber (match_scratch:SI 3 "=&r"))]
446   "TARGET_HAVE_LDREXBHD && TARGET_HAVE_MEMORY_BARRIER"
447   {
448     return arm_output_sync_insn (insn, operands);
449   } 
450   [(set_attr "sync_result"          "0")
451    (set_attr "sync_memory"          "1")
452    (set_attr "sync_new_value"       "2")
453    (set_attr "sync_t1"              "0")
454    (set_attr "sync_t2"              "3")
455    (set_attr "sync_op"              "<sync_optab>")
456    (set_attr "conds" "clob")
457    (set_attr "predicable" "no")])
459 (define_insn "arm_sync_new_nand<mode>"
460   [(set (match_operand:SI 0 "s_register_operand" "=&r")
461         (unspec_volatile:SI
462           [(not:SI
463              (and:SI
464                (zero_extend:SI    
465                  (match_operand:NARROW 1 "arm_sync_memory_operand" "+Q"))
466                (match_operand:SI 2 "s_register_operand" "r")))
467           ] VUNSPEC_SYNC_NEW_OP))
468    (set (match_dup 1)
469         (unspec_volatile:NARROW [(match_dup 1) (match_dup 2)]
470                                 VUNSPEC_SYNC_NEW_OP))
471    (clobber (reg:CC CC_REGNUM))
472    (clobber (match_scratch:SI 3 "=&r"))]
473   "TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER"
474   {
475     return arm_output_sync_insn (insn, operands);
476   } 
477   [(set_attr "sync_result"          "0")
478    (set_attr "sync_memory"          "1")
479    (set_attr "sync_new_value"       "2")
480    (set_attr "sync_t1"              "0")
481    (set_attr "sync_t2"              "3")
482    (set_attr "sync_op"              "nand")
483    (set_attr "conds" "clob")
484    (set_attr "predicable" "no")])
486 (define_insn "arm_sync_old_<sync_optab>si"
487   [(set (match_operand:SI 0 "s_register_operand" "=&r")
488         (unspec_volatile:SI [(syncop:SI
489                                (match_operand:SI 1 "arm_sync_memory_operand" "+Q")
490                                (match_operand:SI 2 "s_register_operand" "r"))
491                             ]
492                             VUNSPEC_SYNC_OLD_OP))
493    (set (match_dup 1)
494         (unspec_volatile:SI [(match_dup 1) (match_dup 2)]
495                             VUNSPEC_SYNC_OLD_OP))
496    (clobber (reg:CC CC_REGNUM))
497    (clobber (match_scratch:SI 3 "=&r"))
498    (clobber (match_scratch:SI 4 "<sync_clobber>"))]
499   "TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER"
500   {
501     return arm_output_sync_insn (insn, operands);
502   } 
503   [(set_attr "sync_result"          "0")
504    (set_attr "sync_memory"          "1")
505    (set_attr "sync_new_value"       "2")
506    (set_attr "sync_t1"              "3")
507    (set_attr "sync_t2"              "<sync_t2_reqd>")
508    (set_attr "sync_op"              "<sync_optab>")
509    (set_attr "conds" "clob")
510    (set_attr "predicable" "no")])
512 (define_insn "arm_sync_old_nandsi"
513   [(set (match_operand:SI 0 "s_register_operand" "=&r")
514         (unspec_volatile:SI [(not:SI (and:SI
515                                (match_operand:SI 1 "arm_sync_memory_operand" "+Q")
516                                (match_operand:SI 2 "s_register_operand" "r")))
517                             ]
518                             VUNSPEC_SYNC_OLD_OP))
519    (set (match_dup 1)
520         (unspec_volatile:SI [(match_dup 1) (match_dup 2)]
521                             VUNSPEC_SYNC_OLD_OP))
522    (clobber (reg:CC CC_REGNUM))
523    (clobber (match_scratch:SI 3 "=&r"))
524    (clobber (match_scratch:SI 4 "=&r"))]
525   "TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER"
526   {
527     return arm_output_sync_insn (insn, operands);
528   } 
529   [(set_attr "sync_result"          "0")
530    (set_attr "sync_memory"          "1")
531    (set_attr "sync_new_value"       "2")
532    (set_attr "sync_t1"              "3")
533    (set_attr "sync_t2"              "4")
534    (set_attr "sync_op"              "nand")
535    (set_attr "conds"                "clob")
536    (set_attr "predicable" "no")])
538 (define_insn "arm_sync_old_<sync_optab><mode>"
539   [(set (match_operand:SI 0 "s_register_operand" "=&r")
540         (unspec_volatile:SI [(syncop:SI
541                                (zero_extend:SI
542                                  (match_operand:NARROW 1 "arm_sync_memory_operand" "+Q"))
543                                (match_operand:SI 2 "s_register_operand" "r"))
544                             ]
545                             VUNSPEC_SYNC_OLD_OP))
546    (set (match_dup 1)
547         (unspec_volatile:NARROW [(match_dup 1) (match_dup 2)]
548                             VUNSPEC_SYNC_OLD_OP))
549    (clobber (reg:CC CC_REGNUM))
550    (clobber (match_scratch:SI 3 "=&r"))
551    (clobber (match_scratch:SI 4 "<sync_clobber>"))]
552   "TARGET_HAVE_LDREXBHD && TARGET_HAVE_MEMORY_BARRIER"
553   {
554     return arm_output_sync_insn (insn, operands);
555   } 
556   [(set_attr "sync_result"          "0")
557    (set_attr "sync_memory"          "1")
558    (set_attr "sync_new_value"       "2")
559    (set_attr "sync_t1"              "3")
560    (set_attr "sync_t2"              "<sync_t2_reqd>")
561    (set_attr "sync_op"              "<sync_optab>")
562    (set_attr "conds"                "clob")
563    (set_attr "predicable" "no")])
565 (define_insn "arm_sync_old_nand<mode>"
566   [(set (match_operand:SI 0 "s_register_operand" "=&r")
567         (unspec_volatile:SI [(not:SI (and:SI
568                                (zero_extend:SI
569                                  (match_operand:NARROW 1 "arm_sync_memory_operand" "+Q"))
570                                (match_operand:SI 2 "s_register_operand" "r")))
571                             ]
572                             VUNSPEC_SYNC_OLD_OP))
573    (set (match_dup 1)
574         (unspec_volatile:NARROW [(match_dup 1) (match_dup 2)]
575                             VUNSPEC_SYNC_OLD_OP))
576    (clobber (reg:CC CC_REGNUM))
577    (clobber (match_scratch:SI 3 "=&r"))
578    (clobber (match_scratch:SI 4 "=&r"))]
579   "TARGET_HAVE_LDREXBHD && TARGET_HAVE_MEMORY_BARRIER"
580   {
581     return arm_output_sync_insn (insn, operands);
582   } 
583   [(set_attr "sync_result"          "0")
584    (set_attr "sync_memory"          "1")
585    (set_attr "sync_new_value"       "2")
586    (set_attr "sync_t1"              "3")
587    (set_attr "sync_t2"              "4")
588    (set_attr "sync_op"              "nand")
589    (set_attr "conds"                "clob")
590    (set_attr "predicable" "no")])
592 (define_insn "*memory_barrier"
593   [(set (match_operand:BLK 0 "" "")
594         (unspec:BLK [(match_dup 0)] UNSPEC_MEMORY_BARRIER))]
595   "TARGET_HAVE_MEMORY_BARRIER"
596   {
597     return arm_output_memory_barrier (operands);
598   }
599   [(set_attr "length" "4")
600    (set_attr "conds" "unconditional")
601    (set_attr "predicable" "no")])