re PR debug/55094 (ICE in maybe_record_trace_start, at dwarf2cfi.c:2224)
[official-gcc.git] / gcc / config / aarch64 / sync.md
blob61f1f1b78b8e08065026386f222ff4710f634fbb
1 ;; Machine description for AArch64 processor synchronization primitives.
2 ;; Copyright (C) 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
3 ;; Contributed by ARM Ltd.
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 (define_c_enum "unspecv"
22  [
23     UNSPECV_SYNC_COMPARE_AND_SWAP       ; Represent a sync_compare_and_swap.
24     UNSPECV_SYNC_LOCK                   ; Represent a sync_lock_test_and_set.
25     UNSPECV_SYNC_LOCK_RELEASE           ; Represent a sync_lock_release.
26     UNSPECV_SYNC_OP                     ; Represent a sync_<op>
27     UNSPECV_SYNC_NEW_OP                 ; Represent a sync_new_<op>
28     UNSPECV_SYNC_OLD_OP                 ; Represent a sync_old_<op>
31 (define_expand "sync_compare_and_swap<mode>"
32   [(set (match_operand:ALLI 0 "register_operand")
33         (unspec_volatile:ALLI [(match_operand:ALLI 1 "memory_operand")
34                                (match_operand:ALLI 2 "register_operand")
35                                (match_operand:ALLI 3 "register_operand")]
36                                UNSPECV_SYNC_COMPARE_AND_SWAP))]
37   ""
38   {
39     struct aarch64_sync_generator generator;
40     generator.op = aarch64_sync_generator_omrn;
41     generator.u.omrn = gen_aarch64_sync_compare_and_swap<mode>;
42     aarch64_expand_sync (<MODE>mode, &generator, operands[0], operands[1],
43                          operands[2], operands[3]);
44     DONE;
45   })
47 (define_expand "sync_lock_test_and_set<mode>"
48   [(match_operand:ALLI 0 "register_operand")
49    (match_operand:ALLI 1 "memory_operand")
50    (match_operand:ALLI 2 "register_operand")]
51   ""
52   {
53     struct aarch64_sync_generator generator;
54     generator.op = aarch64_sync_generator_omn;
55     generator.u.omn = gen_aarch64_sync_lock_test_and_set<mode>;
56     aarch64_expand_sync (<MODE>mode, &generator, operands[0], operands[1],
57                          NULL, operands[2]);
58     DONE;
59   })
61 (define_expand "sync_<optab><mode>"
62   [(match_operand:ALLI 0 "memory_operand")
63    (match_operand:ALLI 1 "register_operand")
64    (syncop:ALLI (match_dup 0) (match_dup 1))]
65   ""
66   {
67     struct aarch64_sync_generator generator;
68     generator.op = aarch64_sync_generator_omn;
69     generator.u.omn = gen_aarch64_sync_new_<optab><mode>;
70     aarch64_expand_sync (<MODE>mode, &generator, NULL, operands[0], NULL,
71                          operands[1]);
72     DONE;
73   })
75 (define_expand "sync_nand<mode>"
76   [(match_operand:ALLI 0 "memory_operand")
77    (match_operand:ALLI 1 "register_operand")
78    (not:ALLI (and:ALLI (match_dup 0) (match_dup 1)))]
79   ""
80   {
81     struct aarch64_sync_generator generator;
82     generator.op = aarch64_sync_generator_omn;
83     generator.u.omn = gen_aarch64_sync_new_nand<mode>;
84     aarch64_expand_sync (<MODE>mode, &generator, NULL, operands[0], NULL,
85                          operands[1]);
86     DONE;
87   })
89 (define_expand "sync_new_<optab><mode>"
90   [(match_operand:ALLI 0 "register_operand")
91    (match_operand:ALLI 1 "memory_operand")
92    (match_operand:ALLI 2 "register_operand")
93    (syncop:ALLI (match_dup 1) (match_dup 2))]
94   ""
95   {
96     struct aarch64_sync_generator generator;
97     generator.op = aarch64_sync_generator_omn;
98     generator.u.omn = gen_aarch64_sync_new_<optab><mode>;
99     aarch64_expand_sync (<MODE>mode, &generator, operands[0], operands[1],
100                          NULL, operands[2]);
101     DONE;
102   })
104 (define_expand "sync_new_nand<mode>"
105   [(match_operand:ALLI 0 "register_operand")
106    (match_operand:ALLI 1 "memory_operand")
107    (match_operand:ALLI 2 "register_operand")
108    (not:ALLI (and:ALLI (match_dup 1) (match_dup 2)))]
109   ""
110   {
111     struct aarch64_sync_generator generator;
112     generator.op = aarch64_sync_generator_omn;
113     generator.u.omn = gen_aarch64_sync_new_nand<mode>;
114     aarch64_expand_sync (<MODE>mode, &generator, operands[0], operands[1],
115                          NULL, operands[2]);
116     DONE;
117   });
119 (define_expand "sync_old_<optab><mode>"
120   [(match_operand:ALLI 0 "register_operand")
121    (match_operand:ALLI 1 "memory_operand")
122    (match_operand:ALLI 2 "register_operand")
123    (syncop:ALLI (match_dup 1) (match_dup 2))]
124   ""
125   {
126     struct aarch64_sync_generator generator;
127     generator.op = aarch64_sync_generator_omn;
128     generator.u.omn = gen_aarch64_sync_old_<optab><mode>;
129     aarch64_expand_sync (<MODE>mode, &generator, operands[0], operands[1],
130                          NULL, operands[2]);
131     DONE;
132   })
134 (define_expand "sync_old_nand<mode>"
135   [(match_operand:ALLI 0 "register_operand")
136    (match_operand:ALLI 1 "memory_operand")
137    (match_operand:ALLI 2 "register_operand")
138    (not:ALLI (and:ALLI (match_dup 1) (match_dup 2)))]
139   ""
140   {
141     struct aarch64_sync_generator generator;
142     generator.op = aarch64_sync_generator_omn;
143     generator.u.omn = gen_aarch64_sync_old_nand<mode>;
144     aarch64_expand_sync (<MODE>mode, &generator, operands[0], operands[1],
145                          NULL, operands[2]);
146     DONE;
147   })
149 (define_expand "memory_barrier"
150   [(set (match_dup 0) (unspec:BLK [(match_dup 0)] UNSPEC_MB))]
151   ""
153   operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
154   MEM_VOLATILE_P (operands[0]) = 1;
157 (define_insn "aarch64_sync_compare_and_swap<mode>"
158   [(set (match_operand:GPI 0 "register_operand" "=&r")
159         (unspec_volatile:GPI
160           [(match_operand:GPI 1 "aarch64_sync_memory_operand" "+Q")
161            (match_operand:GPI 2 "register_operand" "r")
162            (match_operand:GPI 3 "register_operand" "r")]
163           UNSPECV_SYNC_COMPARE_AND_SWAP))
164    (set (match_dup 1) (unspec_volatile:GPI [(match_dup 2)]
165                                           UNSPECV_SYNC_COMPARE_AND_SWAP))
166    (clobber:GPI (match_scratch:GPI 4 "=&r"))
167    (set (reg:CC CC_REGNUM) (unspec_volatile:CC [(match_dup 1)]
168                                                 UNSPECV_SYNC_COMPARE_AND_SWAP))
169    ]
170   ""
171   {
172     return aarch64_output_sync_insn (insn, operands);
173   }
174   [(set_attr "sync_result"          "0")
175    (set_attr "sync_memory"          "1")
176    (set_attr "sync_required_value"  "2")
177    (set_attr "sync_new_value"       "3")
178    (set_attr "sync_t1"              "0")
179    (set_attr "sync_t2"              "4")
180    ])
182 (define_insn "aarch64_sync_compare_and_swap<mode>"
183   [(set (match_operand:SI 0 "register_operand" "=&r")
184         (zero_extend:SI
185           (unspec_volatile:SHORT
186             [(match_operand:SHORT 1 "aarch64_sync_memory_operand" "+Q")
187              (match_operand:SI 2 "register_operand" "r")
188              (match_operand:SI 3 "register_operand" "r")]
189             UNSPECV_SYNC_COMPARE_AND_SWAP)))
190    (set (match_dup 1) (unspec_volatile:SHORT [(match_dup 2)]
191                                              UNSPECV_SYNC_COMPARE_AND_SWAP))
192    (clobber:SI (match_scratch:SI 4 "=&r"))
193    (set (reg:CC CC_REGNUM) (unspec_volatile:CC [(match_dup 1)]
194                                                 UNSPECV_SYNC_COMPARE_AND_SWAP))
195    ]
196   ""
197   {
198     return aarch64_output_sync_insn (insn, operands);
199   }
200   [(set_attr "sync_result"          "0")
201    (set_attr "sync_memory"          "1")
202    (set_attr "sync_required_value"  "2")
203    (set_attr "sync_new_value"       "3")
204    (set_attr "sync_t1"              "0")
205    (set_attr "sync_t2"              "4")
206    ])
208 (define_insn "aarch64_sync_lock_test_and_set<mode>"
209   [(set (match_operand:GPI 0 "register_operand" "=&r")
210         (match_operand:GPI 1 "aarch64_sync_memory_operand" "+Q"))
211    (set (match_dup 1)
212         (unspec_volatile:GPI [(match_operand:GPI 2 "register_operand" "r")]
213                              UNSPECV_SYNC_LOCK))
214    (clobber (reg:CC CC_REGNUM))
215    (clobber (match_scratch:GPI 3 "=&r"))]
216   ""
217   {
218     return aarch64_output_sync_insn (insn, operands);
219   }
220   [(set_attr "sync_release_barrier" "no")
221    (set_attr "sync_result"          "0")
222    (set_attr "sync_memory"          "1")
223    (set_attr "sync_new_value"       "2")
224    (set_attr "sync_t1"              "0")
225    (set_attr "sync_t2"              "3")
226    ])
228 (define_insn "aarch64_sync_lock_test_and_set<mode>"
229   [(set (match_operand:SI 0 "register_operand" "=&r")
230         (zero_extend:SI (match_operand:SHORT 1
231                           "aarch64_sync_memory_operand" "+Q")))
232    (set (match_dup 1)
233         (unspec_volatile:SHORT [(match_operand:SI 2 "register_operand" "r")]
234                                UNSPECV_SYNC_LOCK))
235    (clobber (reg:CC CC_REGNUM))
236    (clobber (match_scratch:SI 3 "=&r"))]
237   ""
238   {
239     return aarch64_output_sync_insn (insn, operands);
240   }
241   [(set_attr "sync_release_barrier" "no")
242    (set_attr "sync_result"          "0")
243    (set_attr "sync_memory"          "1")
244    (set_attr "sync_new_value"       "2")
245    (set_attr "sync_t1"              "0")
246    (set_attr "sync_t2"              "3")
247    ])
249 (define_insn "aarch64_sync_new_<optab><mode>"
250   [(set (match_operand:GPI 0 "register_operand" "=&r")
251         (unspec_volatile:GPI
252           [(syncop:GPI
253              (match_operand:GPI 1 "aarch64_sync_memory_operand" "+Q")
254              (match_operand:GPI 2 "register_operand" "r"))]
255            UNSPECV_SYNC_NEW_OP))
256    (set (match_dup 1)
257         (unspec_volatile:GPI [(match_dup 1) (match_dup 2)]
258                             UNSPECV_SYNC_NEW_OP))
259    (clobber (reg:CC CC_REGNUM))
260    (clobber (match_scratch:GPI 3 "=&r"))]
261   ""
262   {
263     return aarch64_output_sync_insn (insn, operands);
264   }
265   [(set_attr "sync_result"          "0")
266    (set_attr "sync_memory"          "1")
267    (set_attr "sync_new_value"       "2")
268    (set_attr "sync_t1"              "0")
269    (set_attr "sync_t2"              "3")
270    (set_attr "sync_op"              "<optab>")
271    ])
273 (define_insn "aarch64_sync_new_nand<mode>"
274   [(set (match_operand:GPI 0 "register_operand" "=&r")
275         (unspec_volatile:GPI
276           [(not:GPI (and:GPI
277                      (match_operand:GPI 1 "aarch64_sync_memory_operand" "+Q")
278                      (match_operand:GPI 2 "register_operand" "r")))]
279           UNSPECV_SYNC_NEW_OP))
280    (set (match_dup 1)
281         (unspec_volatile:GPI [(match_dup 1) (match_dup 2)]
282                             UNSPECV_SYNC_NEW_OP))
283    (clobber (reg:CC CC_REGNUM))
284    (clobber (match_scratch:GPI 3 "=&r"))]
285   ""
286   {
287     return aarch64_output_sync_insn (insn, operands);
288   }
289   [(set_attr "sync_result"          "0")
290    (set_attr "sync_memory"          "1")
291    (set_attr "sync_new_value"       "2")
292    (set_attr "sync_t1"              "0")
293    (set_attr "sync_t2"              "3")
294    (set_attr "sync_op"              "nand")
295    ])
297 (define_insn "aarch64_sync_new_<optab><mode>"
298   [(set (match_operand:SI 0 "register_operand" "=&r")
299         (unspec_volatile:SI
300           [(syncop:SI
301              (zero_extend:SI
302                (match_operand:SHORT 1 "aarch64_sync_memory_operand" "+Q"))
303                (match_operand:SI 2 "register_operand" "r"))]
304           UNSPECV_SYNC_NEW_OP))
305    (set (match_dup 1)
306         (unspec_volatile:SHORT [(match_dup 1) (match_dup 2)]
307                                UNSPECV_SYNC_NEW_OP))
308    (clobber (reg:CC CC_REGNUM))
309    (clobber (match_scratch:SI 3 "=&r"))]
310   ""
311   {
312     return aarch64_output_sync_insn (insn, operands);
313   }
314   [(set_attr "sync_result"          "0")
315    (set_attr "sync_memory"          "1")
316    (set_attr "sync_new_value"       "2")
317    (set_attr "sync_t1"              "0")
318    (set_attr "sync_t2"              "3")
319    (set_attr "sync_op"              "<optab>")
320    ])
322 (define_insn "aarch64_sync_new_nand<mode>"
323   [(set (match_operand:SI 0 "register_operand" "=&r")
324         (unspec_volatile:SI
325           [(not:SI
326              (and:SI
327                (zero_extend:SI
328                  (match_operand:SHORT 1 "aarch64_sync_memory_operand" "+Q"))
329                (match_operand:SI 2 "register_operand" "r")))
330           ] UNSPECV_SYNC_NEW_OP))
331    (set (match_dup 1)
332         (unspec_volatile:SHORT [(match_dup 1) (match_dup 2)]
333                                UNSPECV_SYNC_NEW_OP))
334    (clobber (reg:CC CC_REGNUM))
335    (clobber (match_scratch:SI 3 "=&r"))]
336   ""
337   {
338     return aarch64_output_sync_insn (insn, operands);
339   }
340   [(set_attr "sync_result"          "0")
341    (set_attr "sync_memory"          "1")
342    (set_attr "sync_new_value"       "2")
343    (set_attr "sync_t1"              "0")
344    (set_attr "sync_t2"              "3")
345    (set_attr "sync_op"              "nand")
346    ])
348 (define_insn "aarch64_sync_old_<optab><mode>"
349   [(set (match_operand:GPI 0 "register_operand" "=&r")
350         (unspec_volatile:GPI
351           [(syncop:GPI
352              (match_operand:GPI 1 "aarch64_sync_memory_operand" "+Q")
353              (match_operand:GPI 2 "register_operand" "r"))]
354           UNSPECV_SYNC_OLD_OP))
355    (set (match_dup 1)
356         (unspec_volatile:GPI [(match_dup 1) (match_dup 2)]
357                              UNSPECV_SYNC_OLD_OP))
358    (clobber (reg:CC CC_REGNUM))
359    (clobber (match_scratch:GPI 3 "=&r"))
360    (clobber (match_scratch:GPI 4 "=&r"))]
361   ""
362   {
363     return aarch64_output_sync_insn (insn, operands);
364   }
365   [(set_attr "sync_result"          "0")
366    (set_attr "sync_memory"          "1")
367    (set_attr "sync_new_value"       "2")
368    (set_attr "sync_t1"              "3")
369    (set_attr "sync_t2"              "4")
370    (set_attr "sync_op"              "<optab>")
371    ])
373 (define_insn "aarch64_sync_old_nand<mode>"
374   [(set (match_operand:GPI 0 "register_operand" "=&r")
375         (unspec_volatile:GPI
376           [(not:GPI (and:GPI
377                      (match_operand:GPI 1 "aarch64_sync_memory_operand" "+Q")
378                      (match_operand:GPI 2 "register_operand" "r")))]
379           UNSPECV_SYNC_OLD_OP))
380    (set (match_dup 1)
381         (unspec_volatile:GPI [(match_dup 1) (match_dup 2)]
382                              UNSPECV_SYNC_OLD_OP))
383    (clobber (reg:CC CC_REGNUM))
384    (clobber (match_scratch:GPI 3 "=&r"))
385    (clobber (match_scratch:GPI 4 "=&r"))]
386   ""
387   {
388     return aarch64_output_sync_insn (insn, operands);
389   }
390   [(set_attr "sync_result"          "0")
391    (set_attr "sync_memory"          "1")
392    (set_attr "sync_new_value"       "2")
393    (set_attr "sync_t1"              "3")
394    (set_attr "sync_t2"              "4")
395    (set_attr "sync_op"              "nand")
396    ])
398 (define_insn "aarch64_sync_old_<optab><mode>"
399   [(set (match_operand:SI 0 "register_operand" "=&r")
400         (unspec_volatile:SI
401           [(syncop:SI
402              (zero_extend:SI
403                (match_operand:SHORT 1 "aarch64_sync_memory_operand" "+Q"))
404                (match_operand:SI 2 "register_operand" "r"))]
405            UNSPECV_SYNC_OLD_OP))
406    (set (match_dup 1)
407         (unspec_volatile:SHORT [(match_dup 1) (match_dup 2)]
408                                UNSPECV_SYNC_OLD_OP))
409    (clobber (reg:CC CC_REGNUM))
410    (clobber (match_scratch:SI 3 "=&r"))
411    (clobber (match_scratch:SI 4 "=&r"))]
412   ""
413   {
414     return aarch64_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"              "3")
420    (set_attr "sync_t2"              "4")
421    (set_attr "sync_op"              "<optab>")
422    ])
424 (define_insn "aarch64_sync_old_nand<mode>"
425   [(set (match_operand:SI 0 "register_operand" "=&r")
426         (unspec_volatile:SI
427           [(not:SI
428              (and:SI
429                (zero_extend:SI
430                  (match_operand:SHORT 1 "aarch64_sync_memory_operand" "+Q"))
431                  (match_operand:SI 2 "register_operand" "r")))]
432           UNSPECV_SYNC_OLD_OP))
433    (set (match_dup 1)
434         (unspec_volatile:SHORT [(match_dup 1) (match_dup 2)]
435                                UNSPECV_SYNC_OLD_OP))
436    (clobber (reg:CC CC_REGNUM))
437    (clobber (match_scratch:SI 3 "=&r"))
438    (clobber (match_scratch:SI 4 "=&r"))]
439   ""
440   {
441     return aarch64_output_sync_insn (insn, operands);
442   }
443   [(set_attr "sync_result"          "0")
444    (set_attr "sync_memory"          "1")
445    (set_attr "sync_new_value"       "2")
446    (set_attr "sync_t1"              "3")
447    (set_attr "sync_t2"              "4")
448    (set_attr "sync_op"              "nand")
449    ])
451 (define_insn "*memory_barrier"
452   [(set (match_operand:BLK 0 "" "")
453         (unspec:BLK [(match_dup 0)] UNSPEC_MB))]
454   ""
455   "dmb\\tish"
458 (define_insn "sync_lock_release<mode>"
459   [(set (match_operand:ALLI 0 "memory_operand" "+Q")
460         (unspec_volatile:ALLI [(match_operand:ALLI 1 "register_operand" "r")]
461                               UNSPECV_SYNC_LOCK_RELEASE))]
463   ""
464   {
465     return aarch64_output_sync_lock_release (operands[1], operands[0]);
466   })