re PR debug/55094 (ICE in maybe_record_trace_start, at dwarf2cfi.c:2224)
[gcc.git] / gcc / config / aarch64 / sync.md
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.
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 (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>
29 ])
30
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 })
46
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 })
60
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 })
74
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 })
88
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 })
103
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 });
118
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 })
133
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 })
148
149 (define_expand "memory_barrier"
150 [(set (match_dup 0) (unspec:BLK [(match_dup 0)] UNSPEC_MB))]
151 ""
152 {
153 operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
154 MEM_VOLATILE_P (operands[0]) = 1;
155 })
156
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 ])
181
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 ])
207
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 ])
227
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 ])
248
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 ])
272
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 ])
296
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 ])
321
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 ])
347
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 ])
372
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 ])
397
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 ])
423
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 ])
450
451 (define_insn "*memory_barrier"
452 [(set (match_operand:BLK 0 "" "")
453 (unspec:BLK [(match_dup 0)] UNSPEC_MB))]
454 ""
455 "dmb\\tish"
456 )
457
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))]
462
463 ""
464 {
465 return aarch64_output_sync_lock_release (operands[1], operands[0]);
466 })
467