1 ;; Machine description for AArch64 processor synchronization primitives.
2 ;; Copyright (C) 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
3 ;; Contributed by ARM Ltd.
5 ;; This file is part of GCC.
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)
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"
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))]
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]);
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")]
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],
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))]
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,
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)))]
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,
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))]
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],
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)))]
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],
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))]
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],
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)))]
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],
149 (define_expand "memory_barrier"
150 [(set (match_dup 0) (unspec:BLK [(match_dup 0)] UNSPEC_MB))]
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")
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))
172 return aarch64_output_sync_insn (insn, operands);
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")
182 (define_insn "aarch64_sync_compare_and_swap<mode>"
183 [(set (match_operand:SI 0 "register_operand" "=&r")
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))
198 return aarch64_output_sync_insn (insn, operands);
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")
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"))
212 (unspec_volatile:GPI [(match_operand:GPI 2 "register_operand" "r")]
214 (clobber (reg:CC CC_REGNUM))
215 (clobber (match_scratch:GPI 3 "=&r"))]
218 return aarch64_output_sync_insn (insn, operands);
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")
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")))
233 (unspec_volatile:SHORT [(match_operand:SI 2 "register_operand" "r")]
235 (clobber (reg:CC CC_REGNUM))
236 (clobber (match_scratch:SI 3 "=&r"))]
239 return aarch64_output_sync_insn (insn, operands);
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")
249 (define_insn "aarch64_sync_new_<optab><mode>"
250 [(set (match_operand:GPI 0 "register_operand" "=&r")
253 (match_operand:GPI 1 "aarch64_sync_memory_operand" "+Q")
254 (match_operand:GPI 2 "register_operand" "r"))]
255 UNSPECV_SYNC_NEW_OP))
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"))]
263 return aarch64_output_sync_insn (insn, operands);
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>")
273 (define_insn "aarch64_sync_new_nand<mode>"
274 [(set (match_operand:GPI 0 "register_operand" "=&r")
277 (match_operand:GPI 1 "aarch64_sync_memory_operand" "+Q")
278 (match_operand:GPI 2 "register_operand" "r")))]
279 UNSPECV_SYNC_NEW_OP))
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"))]
287 return aarch64_output_sync_insn (insn, operands);
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")
297 (define_insn "aarch64_sync_new_<optab><mode>"
298 [(set (match_operand:SI 0 "register_operand" "=&r")
302 (match_operand:SHORT 1 "aarch64_sync_memory_operand" "+Q"))
303 (match_operand:SI 2 "register_operand" "r"))]
304 UNSPECV_SYNC_NEW_OP))
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"))]
312 return aarch64_output_sync_insn (insn, operands);
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>")
322 (define_insn "aarch64_sync_new_nand<mode>"
323 [(set (match_operand:SI 0 "register_operand" "=&r")
328 (match_operand:SHORT 1 "aarch64_sync_memory_operand" "+Q"))
329 (match_operand:SI 2 "register_operand" "r")))
330 ] UNSPECV_SYNC_NEW_OP))
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"))]
338 return aarch64_output_sync_insn (insn, operands);
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")
348 (define_insn "aarch64_sync_old_<optab><mode>"
349 [(set (match_operand:GPI 0 "register_operand" "=&r")
352 (match_operand:GPI 1 "aarch64_sync_memory_operand" "+Q")
353 (match_operand:GPI 2 "register_operand" "r"))]
354 UNSPECV_SYNC_OLD_OP))
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"))]
363 return aarch64_output_sync_insn (insn, operands);
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>")
373 (define_insn "aarch64_sync_old_nand<mode>"
374 [(set (match_operand:GPI 0 "register_operand" "=&r")
377 (match_operand:GPI 1 "aarch64_sync_memory_operand" "+Q")
378 (match_operand:GPI 2 "register_operand" "r")))]
379 UNSPECV_SYNC_OLD_OP))
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"))]
388 return aarch64_output_sync_insn (insn, operands);
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")
398 (define_insn "aarch64_sync_old_<optab><mode>"
399 [(set (match_operand:SI 0 "register_operand" "=&r")
403 (match_operand:SHORT 1 "aarch64_sync_memory_operand" "+Q"))
404 (match_operand:SI 2 "register_operand" "r"))]
405 UNSPECV_SYNC_OLD_OP))
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"))]
414 return aarch64_output_sync_insn (insn, operands);
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>")
424 (define_insn "aarch64_sync_old_nand<mode>"
425 [(set (match_operand:SI 0 "register_operand" "=&r")
430 (match_operand:SHORT 1 "aarch64_sync_memory_operand" "+Q"))
431 (match_operand:SI 2 "register_operand" "r")))]
432 UNSPECV_SYNC_OLD_OP))
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"))]
441 return aarch64_output_sync_insn (insn, operands);
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")
451 (define_insn "*memory_barrier"
452 [(set (match_operand:BLK 0 "" "")
453 (unspec:BLK [(match_dup 0)] UNSPEC_MB))]
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))]
465 return aarch64_output_sync_lock_release (operands[1], operands[0]);