OSDN Git Service

* config/alpha/freebsd.h (LINK_SPEC): Don't use
[pf3gnuchains/gcc-fork.git] / gcc / config / arm / sync.md
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.
11 ;;
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.
16 ;;
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/>.  */
20
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.
26
27 (define_expand "memory_barrier"
28   [(set (match_dup 0)
29         (unspec:BLK [(match_dup 0)] UNSPEC_MEMORY_BARRIER))]
30   "TARGET_HAVE_MEMORY_BARRIER"
31 {
32   operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
33   MEM_VOLATILE_P (operands[0]) = 1;
34 })
35
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   })
51
52 (define_mode_iterator NARROW [QI HI])
53
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   })
69
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   })
83
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   })
97
98 (define_code_iterator syncop [plus minus ior xor and])
99
100 (define_code_attr sync_optab [(ior "ior")
101                               (xor "xor")
102                               (and "and")
103                               (plus "add")
104                               (minus "sub")])
105
106 (define_expand "sync_<sync_optab>si"
107   [(match_operand:SI 0 "memory_operand")
108    (match_operand:SI 1 "s_register_operand")
109    (syncop:SI (match_dup 0) (match_dup 1))]
110   "TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER"
111   {
112     struct arm_sync_generator generator;
113     generator.op = arm_sync_generator_omn;
114     generator.u.omn = gen_arm_sync_new_<sync_optab>si;
115     arm_expand_sync (SImode, &generator, NULL, operands[0], NULL, operands[1]);
116     DONE;
117   })
118
119 (define_expand "sync_nandsi"
120   [(match_operand:SI 0 "memory_operand")
121    (match_operand:SI 1 "s_register_operand")
122    (not:SI (and:SI (match_dup 0) (match_dup 1)))]
123   "TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER"
124   {
125     struct arm_sync_generator generator;
126     generator.op = arm_sync_generator_omn;
127     generator.u.omn = gen_arm_sync_new_nandsi;
128     arm_expand_sync (SImode, &generator, NULL, operands[0], NULL, operands[1]);
129     DONE;
130   })
131
132 (define_expand "sync_<sync_optab><mode>"
133   [(match_operand:NARROW 0 "memory_operand")
134    (match_operand:NARROW 1 "s_register_operand")
135    (syncop:NARROW (match_dup 0) (match_dup 1))]
136   "TARGET_HAVE_LDREXBHD && TARGET_HAVE_MEMORY_BARRIER"
137   {
138     struct arm_sync_generator generator;
139     generator.op = arm_sync_generator_omn;
140     generator.u.omn = gen_arm_sync_new_<sync_optab><mode>;
141     arm_expand_sync (<MODE>mode, &generator, NULL, operands[0], NULL,
142                      operands[1]);
143     DONE;
144   })
145
146 (define_expand "sync_nand<mode>"
147   [(match_operand:NARROW 0 "memory_operand")
148    (match_operand:NARROW 1 "s_register_operand")
149    (not:NARROW (and:NARROW (match_dup 0) (match_dup 1)))]
150   "TARGET_HAVE_LDREXBHD && TARGET_HAVE_MEMORY_BARRIER"
151   {
152     struct arm_sync_generator generator;
153     generator.op = arm_sync_generator_omn;
154     generator.u.omn = gen_arm_sync_new_nand<mode>;
155     arm_expand_sync (<MODE>mode, &generator, NULL, operands[0], NULL,
156                      operands[1]);
157     DONE;
158   })
159
160 (define_expand "sync_new_<sync_optab>si"
161   [(match_operand:SI 0 "s_register_operand")
162    (match_operand:SI 1 "memory_operand")
163    (match_operand:SI 2 "s_register_operand")
164    (syncop:SI (match_dup 1) (match_dup 2))]
165   "TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER"
166   {
167     struct arm_sync_generator generator;
168     generator.op = arm_sync_generator_omn;
169     generator.u.omn = gen_arm_sync_new_<sync_optab>si;
170     arm_expand_sync (SImode, &generator, operands[0], operands[1], NULL,
171                      operands[2]);
172     DONE;
173   })
174
175 (define_expand "sync_new_nandsi"
176   [(match_operand:SI 0 "s_register_operand")
177    (match_operand:SI 1 "memory_operand")
178    (match_operand:SI 2 "s_register_operand")
179    (not:SI (and:SI (match_dup 1) (match_dup 2)))]
180   "TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER"
181   {
182     struct arm_sync_generator generator;
183     generator.op = arm_sync_generator_omn;
184     generator.u.omn = gen_arm_sync_new_nandsi;
185     arm_expand_sync (SImode, &generator, operands[0], operands[1], NULL,
186                      operands[2]);
187     DONE;
188   })
189
190 (define_expand "sync_new_<sync_optab><mode>"
191   [(match_operand:NARROW 0 "s_register_operand")
192    (match_operand:NARROW 1 "memory_operand")
193    (match_operand:NARROW 2 "s_register_operand")
194    (syncop:NARROW (match_dup 1) (match_dup 2))]
195   "TARGET_HAVE_LDREXBHD && TARGET_HAVE_MEMORY_BARRIER"
196   {
197     struct arm_sync_generator generator;
198     generator.op = arm_sync_generator_omn;
199     generator.u.omn = gen_arm_sync_new_<sync_optab><mode>;
200     arm_expand_sync (<MODE>mode, &generator, operands[0], operands[1],
201                      NULL, operands[2]);
202     DONE;
203   })
204
205 (define_expand "sync_new_nand<mode>"
206   [(match_operand:NARROW 0 "s_register_operand")
207    (match_operand:NARROW 1 "memory_operand")
208    (match_operand:NARROW 2 "s_register_operand")
209    (not:NARROW (and:NARROW (match_dup 1) (match_dup 2)))]
210   "TARGET_HAVE_LDREXBHD && TARGET_HAVE_MEMORY_BARRIER"
211   {
212     struct arm_sync_generator generator;
213     generator.op = arm_sync_generator_omn;
214     generator.u.omn = gen_arm_sync_new_nand<mode>;
215     arm_expand_sync (<MODE>mode, &generator, operands[0], operands[1],
216                      NULL, operands[2]);
217     DONE;
218   });
219
220 (define_expand "sync_old_<sync_optab>si"
221   [(match_operand:SI 0 "s_register_operand")
222    (match_operand:SI 1 "memory_operand")
223    (match_operand:SI 2 "s_register_operand")
224    (syncop:SI (match_dup 1) (match_dup 2))]
225   "TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER"
226   {
227     struct arm_sync_generator generator;
228     generator.op = arm_sync_generator_omn;
229     generator.u.omn = gen_arm_sync_old_<sync_optab>si;
230     arm_expand_sync (SImode, &generator, operands[0], operands[1], NULL,
231                      operands[2]);
232     DONE;
233   })
234
235 (define_expand "sync_old_nandsi"
236   [(match_operand:SI 0 "s_register_operand")
237    (match_operand:SI 1 "memory_operand")
238    (match_operand:SI 2 "s_register_operand")
239    (not:SI (and:SI (match_dup 1) (match_dup 2)))]
240   "TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER"
241   {
242     struct arm_sync_generator generator;
243     generator.op = arm_sync_generator_omn;
244     generator.u.omn = gen_arm_sync_old_nandsi;
245     arm_expand_sync (SImode, &generator, operands[0], operands[1], NULL,
246                      operands[2]);
247     DONE;
248   })
249
250 (define_expand "sync_old_<sync_optab><mode>"
251   [(match_operand:NARROW 0 "s_register_operand")
252    (match_operand:NARROW 1 "memory_operand")
253    (match_operand:NARROW 2 "s_register_operand")
254    (syncop:NARROW (match_dup 1) (match_dup 2))]
255   "TARGET_HAVE_LDREXBHD && TARGET_HAVE_MEMORY_BARRIER"
256   {
257     struct arm_sync_generator generator;
258     generator.op = arm_sync_generator_omn;
259     generator.u.omn = gen_arm_sync_old_<sync_optab><mode>;
260     arm_expand_sync (<MODE>mode, &generator, operands[0], operands[1],
261                      NULL, operands[2]);
262     DONE;
263   })
264
265 (define_expand "sync_old_nand<mode>"
266   [(match_operand:NARROW 0 "s_register_operand")
267    (match_operand:NARROW 1 "memory_operand")
268    (match_operand:NARROW 2 "s_register_operand")
269    (not:NARROW (and:NARROW (match_dup 1) (match_dup 2)))]
270   "TARGET_HAVE_LDREXBHD && TARGET_HAVE_MEMORY_BARRIER"
271   {
272     struct arm_sync_generator generator;
273     generator.op = arm_sync_generator_omn;
274     generator.u.omn = gen_arm_sync_old_nand<mode>;
275     arm_expand_sync (<MODE>mode, &generator, operands[0], operands[1],
276                      NULL, operands[2]);
277     DONE;
278   })
279
280 (define_insn "arm_sync_compare_and_swapsi"
281   [(set (match_operand:SI 0 "s_register_operand" "=&r")
282         (unspec_volatile:SI
283           [(match_operand:SI 1 "arm_sync_memory_operand" "+Q")
284            (match_operand:SI 2 "s_register_operand" "r")
285            (match_operand:SI 3 "s_register_operand" "r")]
286           VUNSPEC_SYNC_COMPARE_AND_SWAP))
287    (set (match_dup 1) (unspec_volatile:SI [(match_dup 2)]
288                                           VUNSPEC_SYNC_COMPARE_AND_SWAP))
289    (clobber:SI (match_scratch:SI 4 "=&r"))
290    (set (reg:CC CC_REGNUM) (unspec_volatile:CC [(match_dup 1)]
291                                                 VUNSPEC_SYNC_COMPARE_AND_SWAP))
292    ]
293   "TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER"
294   {
295     return arm_output_sync_insn (insn, operands);
296   } 
297   [(set_attr "sync_result"          "0")
298    (set_attr "sync_memory"          "1")
299    (set_attr "sync_required_value"  "2")
300    (set_attr "sync_new_value"       "3")
301    (set_attr "sync_t1"              "0")
302    (set_attr "sync_t2"              "4")
303    (set_attr "conds" "clob")
304    (set_attr "predicable" "no")])
305
306 (define_insn "arm_sync_compare_and_swap<mode>"
307   [(set (match_operand:SI 0 "s_register_operand" "=&r")
308         (zero_extend:SI
309           (unspec_volatile:NARROW
310             [(match_operand:NARROW 1 "arm_sync_memory_operand" "+Q")
311              (match_operand:SI 2 "s_register_operand" "r")
312              (match_operand:SI 3 "s_register_operand" "r")]
313             VUNSPEC_SYNC_COMPARE_AND_SWAP)))
314    (set (match_dup 1) (unspec_volatile:NARROW [(match_dup 2)]
315                                           VUNSPEC_SYNC_COMPARE_AND_SWAP))
316    (clobber:SI (match_scratch:SI 4 "=&r"))
317    (set (reg:CC CC_REGNUM) (unspec_volatile:CC [(match_dup 1)]
318                                                 VUNSPEC_SYNC_COMPARE_AND_SWAP))
319    ]
320   "TARGET_HAVE_LDREXBHD && TARGET_HAVE_MEMORY_BARRIER"
321   {
322     return arm_output_sync_insn (insn, operands);
323   } 
324   [(set_attr "sync_result"          "0")
325    (set_attr "sync_memory"          "1")
326    (set_attr "sync_required_value"  "2")
327    (set_attr "sync_new_value"       "3")
328    (set_attr "sync_t1"              "0")
329    (set_attr "sync_t2"              "4")
330    (set_attr "conds" "clob")
331    (set_attr "predicable" "no")])
332
333 (define_insn "arm_sync_lock_test_and_setsi"
334   [(set (match_operand:SI 0 "s_register_operand" "=&r")
335         (match_operand:SI 1 "arm_sync_memory_operand" "+Q"))
336    (set (match_dup 1)
337         (unspec_volatile:SI [(match_operand:SI 2 "s_register_operand" "r")]
338                             VUNSPEC_SYNC_LOCK))
339    (clobber (reg:CC CC_REGNUM))
340    (clobber (match_scratch:SI 3 "=&r"))]
341   "TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER"
342   {
343     return arm_output_sync_insn (insn, operands);
344   } 
345   [(set_attr "sync_release_barrier" "no")
346    (set_attr "sync_result"          "0")
347    (set_attr "sync_memory"          "1")
348    (set_attr "sync_new_value"       "2")
349    (set_attr "sync_t1"              "0")
350    (set_attr "sync_t2"              "3")
351    (set_attr "conds" "clob")
352    (set_attr "predicable" "no")])
353
354 (define_insn "arm_sync_lock_test_and_set<mode>"
355   [(set (match_operand:SI 0 "s_register_operand" "=&r")
356         (zero_extend:SI (match_operand:NARROW 1 "arm_sync_memory_operand" "+Q")))
357    (set (match_dup 1)
358         (unspec_volatile:NARROW [(match_operand:SI 2 "s_register_operand" "r")]
359                                 VUNSPEC_SYNC_LOCK))
360    (clobber (reg:CC CC_REGNUM))
361    (clobber (match_scratch:SI 3 "=&r"))]
362   "TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER"
363   {
364     return arm_output_sync_insn (insn, operands);
365   } 
366   [(set_attr "sync_release_barrier" "no")
367    (set_attr "sync_result"          "0")
368    (set_attr "sync_memory"          "1")
369    (set_attr "sync_new_value"       "2")
370    (set_attr "sync_t1"              "0")
371    (set_attr "sync_t2"              "3")
372    (set_attr "conds" "clob")
373    (set_attr "predicable" "no")])
374
375 (define_insn "arm_sync_new_<sync_optab>si"
376   [(set (match_operand:SI 0 "s_register_operand" "=&r")
377         (unspec_volatile:SI [(syncop:SI
378                                (match_operand:SI 1 "arm_sync_memory_operand" "+Q")
379                                (match_operand:SI 2 "s_register_operand" "r"))
380                             ]
381                             VUNSPEC_SYNC_NEW_OP))
382    (set (match_dup 1)
383         (unspec_volatile:SI [(match_dup 1) (match_dup 2)]
384                             VUNSPEC_SYNC_NEW_OP))
385    (clobber (reg:CC CC_REGNUM))
386    (clobber (match_scratch:SI 3 "=&r"))]
387   "TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER"
388   {
389     return arm_output_sync_insn (insn, operands);
390   } 
391   [(set_attr "sync_result"          "0")
392    (set_attr "sync_memory"          "1")
393    (set_attr "sync_new_value"       "2")
394    (set_attr "sync_t1"              "0")
395    (set_attr "sync_t2"              "3")
396    (set_attr "sync_op"              "<sync_optab>")
397    (set_attr "conds" "clob")
398    (set_attr "predicable" "no")])
399
400 (define_insn "arm_sync_new_nandsi"
401   [(set (match_operand:SI 0 "s_register_operand" "=&r")
402         (unspec_volatile:SI [(not:SI (and:SI
403                                (match_operand:SI 1 "arm_sync_memory_operand" "+Q")
404                                (match_operand:SI 2 "s_register_operand" "r")))
405                             ]
406                             VUNSPEC_SYNC_NEW_OP))
407    (set (match_dup 1)
408         (unspec_volatile:SI [(match_dup 1) (match_dup 2)]
409                             VUNSPEC_SYNC_NEW_OP))
410    (clobber (reg:CC CC_REGNUM))
411    (clobber (match_scratch:SI 3 "=&r"))]
412   "TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER"
413   {
414     return arm_output_sync_insn (insn, operands);
415   } 
416   [(set_attr "sync_result"          "0")
417    (set_attr "sync_memory"          "1")
418    (set_attr "sync_new_value"       "2")
419    (set_attr "sync_t1"              "0")
420    (set_attr "sync_t2"              "3")
421    (set_attr "sync_op"              "nand")
422    (set_attr "conds" "clob")
423    (set_attr "predicable" "no")])
424
425 (define_insn "arm_sync_new_<sync_optab><mode>"
426   [(set (match_operand:SI 0 "s_register_operand" "=&r")
427         (unspec_volatile:SI [(syncop:SI
428                                (zero_extend:SI
429                                  (match_operand:NARROW 1 "arm_sync_memory_operand" "+Q"))
430                                (match_operand:SI 2 "s_register_operand" "r"))
431                             ]
432                             VUNSPEC_SYNC_NEW_OP))
433    (set (match_dup 1)
434         (unspec_volatile:NARROW [(match_dup 1) (match_dup 2)]
435                                 VUNSPEC_SYNC_NEW_OP))
436    (clobber (reg:CC CC_REGNUM))
437    (clobber (match_scratch:SI 3 "=&r"))]
438   "TARGET_HAVE_LDREXBHD && TARGET_HAVE_MEMORY_BARRIER"
439   {
440     return arm_output_sync_insn (insn, operands);
441   } 
442   [(set_attr "sync_result"          "0")
443    (set_attr "sync_memory"          "1")
444    (set_attr "sync_new_value"       "2")
445    (set_attr "sync_t1"              "0")
446    (set_attr "sync_t2"              "3")
447    (set_attr "sync_op"              "<sync_optab>")
448    (set_attr "conds" "clob")
449    (set_attr "predicable" "no")])
450
451 (define_insn "arm_sync_new_nand<mode>"
452   [(set (match_operand:SI 0 "s_register_operand" "=&r")
453         (unspec_volatile:SI
454           [(not:SI
455              (and:SI
456                (zero_extend:SI    
457                  (match_operand:NARROW 1 "arm_sync_memory_operand" "+Q"))
458                (match_operand:SI 2 "s_register_operand" "r")))
459           ] VUNSPEC_SYNC_NEW_OP))
460    (set (match_dup 1)
461         (unspec_volatile:NARROW [(match_dup 1) (match_dup 2)]
462                                 VUNSPEC_SYNC_NEW_OP))
463    (clobber (reg:CC CC_REGNUM))
464    (clobber (match_scratch:SI 3 "=&r"))]
465   "TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER"
466   {
467     return arm_output_sync_insn (insn, operands);
468   } 
469   [(set_attr "sync_result"          "0")
470    (set_attr "sync_memory"          "1")
471    (set_attr "sync_new_value"       "2")
472    (set_attr "sync_t1"              "0")
473    (set_attr "sync_t2"              "3")
474    (set_attr "sync_op"              "nand")
475    (set_attr "conds" "clob")
476    (set_attr "predicable" "no")])
477
478 (define_insn "arm_sync_old_<sync_optab>si"
479   [(set (match_operand:SI 0 "s_register_operand" "=&r")
480         (unspec_volatile:SI [(syncop:SI
481                                (match_operand:SI 1 "arm_sync_memory_operand" "+Q")
482                                (match_operand:SI 2 "s_register_operand" "r"))
483                             ]
484                             VUNSPEC_SYNC_OLD_OP))
485    (set (match_dup 1)
486         (unspec_volatile:SI [(match_dup 1) (match_dup 2)]
487                             VUNSPEC_SYNC_OLD_OP))
488    (clobber (reg:CC CC_REGNUM))
489    (clobber (match_scratch:SI 3 "=&r"))
490    (clobber (match_scratch:SI 4 "=&r"))]
491   "TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER"
492   {
493     return arm_output_sync_insn (insn, operands);
494   } 
495   [(set_attr "sync_result"          "0")
496    (set_attr "sync_memory"          "1")
497    (set_attr "sync_new_value"       "2")
498    (set_attr "sync_t1"              "3")
499    (set_attr "sync_t2"              "4")
500    (set_attr "sync_op"              "<sync_optab>")
501    (set_attr "conds" "clob")
502    (set_attr "predicable" "no")])
503
504 (define_insn "arm_sync_old_nandsi"
505   [(set (match_operand:SI 0 "s_register_operand" "=&r")
506         (unspec_volatile:SI [(not:SI (and:SI
507                                (match_operand:SI 1 "arm_sync_memory_operand" "+Q")
508                                (match_operand:SI 2 "s_register_operand" "r")))
509                             ]
510                             VUNSPEC_SYNC_OLD_OP))
511    (set (match_dup 1)
512         (unspec_volatile:SI [(match_dup 1) (match_dup 2)]
513                             VUNSPEC_SYNC_OLD_OP))
514    (clobber (reg:CC CC_REGNUM))
515    (clobber (match_scratch:SI 3 "=&r"))
516    (clobber (match_scratch:SI 4 "=&r"))]
517   "TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER"
518   {
519     return arm_output_sync_insn (insn, operands);
520   } 
521   [(set_attr "sync_result"          "0")
522    (set_attr "sync_memory"          "1")
523    (set_attr "sync_new_value"       "2")
524    (set_attr "sync_t1"              "3")
525    (set_attr "sync_t2"              "4")
526    (set_attr "sync_op"              "nand")
527    (set_attr "conds"                "clob")
528    (set_attr "predicable" "no")])
529
530 (define_insn "arm_sync_old_<sync_optab><mode>"
531   [(set (match_operand:SI 0 "s_register_operand" "=&r")
532         (unspec_volatile:SI [(syncop:SI
533                                (zero_extend:SI
534                                  (match_operand:NARROW 1 "arm_sync_memory_operand" "+Q"))
535                                (match_operand:SI 2 "s_register_operand" "r"))
536                             ]
537                             VUNSPEC_SYNC_OLD_OP))
538    (set (match_dup 1)
539         (unspec_volatile:NARROW [(match_dup 1) (match_dup 2)]
540                             VUNSPEC_SYNC_OLD_OP))
541    (clobber (reg:CC CC_REGNUM))
542    (clobber (match_scratch:SI 3 "=&r"))
543    (clobber (match_scratch:SI 4 "=&r"))]
544   "TARGET_HAVE_LDREXBHD && TARGET_HAVE_MEMORY_BARRIER"
545   {
546     return arm_output_sync_insn (insn, operands);
547   } 
548   [(set_attr "sync_result"          "0")
549    (set_attr "sync_memory"          "1")
550    (set_attr "sync_new_value"       "2")
551    (set_attr "sync_t1"              "3")
552    (set_attr "sync_t2"              "4")
553    (set_attr "sync_op"              "<sync_optab>")
554    (set_attr "conds"                "clob")
555    (set_attr "predicable" "no")])
556
557 (define_insn "arm_sync_old_nand<mode>"
558   [(set (match_operand:SI 0 "s_register_operand" "=&r")
559         (unspec_volatile:SI [(not:SI (and:SI
560                                (zero_extend:SI
561                                  (match_operand:NARROW 1 "arm_sync_memory_operand" "+Q"))
562                                (match_operand:SI 2 "s_register_operand" "r")))
563                             ]
564                             VUNSPEC_SYNC_OLD_OP))
565    (set (match_dup 1)
566         (unspec_volatile:NARROW [(match_dup 1) (match_dup 2)]
567                             VUNSPEC_SYNC_OLD_OP))
568    (clobber (reg:CC CC_REGNUM))
569    (clobber (match_scratch:SI 3 "=&r"))
570    (clobber (match_scratch:SI 4 "=&r"))]
571   "TARGET_HAVE_LDREXBHD && TARGET_HAVE_MEMORY_BARRIER"
572   {
573     return arm_output_sync_insn (insn, operands);
574   } 
575   [(set_attr "sync_result"          "0")
576    (set_attr "sync_memory"          "1")
577    (set_attr "sync_new_value"       "2")
578    (set_attr "sync_t1"              "3")
579    (set_attr "sync_t2"              "4")
580    (set_attr "sync_op"              "nand")
581    (set_attr "conds"                "clob")
582    (set_attr "predicable" "no")])
583
584 (define_insn "*memory_barrier"
585   [(set (match_operand:BLK 0 "" "")
586         (unspec:BLK [(match_dup 0)] UNSPEC_MEMORY_BARRIER))]
587   "TARGET_HAVE_MEMORY_BARRIER"
588   {
589     return arm_output_memory_barrier (operands);
590   }
591   [(set_attr "length" "4")
592    (set_attr "conds" "unconditional")
593    (set_attr "predicable" "no")])
594