1 ;; Machine Description for MIPS based processor synchronization
3 ;; Copyright (C) 2007, 2008, 2009
4 ;; Free Software Foundation, Inc.
6 ;; This file is part of GCC.
8 ;; GCC is free software; you can redistribute it and/or modify
9 ;; it under the terms of the GNU General Public License as published by
10 ;; the Free Software Foundation; either version 3, or (at your option)
13 ;; GCC is distributed in the hope that it will be useful,
14 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
15 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 ;; GNU General Public License for more details.
18 ;; You should have received a copy of the GNU General Public License
19 ;; along with GCC; see the file COPYING3. If not see
20 ;; <http://www.gnu.org/licenses/>.
22 ;; Atomic fetch bitwise operations.
23 (define_code_iterator fetchop_bit [ior xor and])
25 ;; Atomic HI and QI operations
26 (define_code_iterator atomic_hiqi_op [plus minus ior xor and])
28 ;; Atomic memory operations.
30 (define_expand "memory_barrier"
32 (unspec:BLK [(match_dup 0)] UNSPEC_MEMORY_BARRIER))]
35 operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
36 MEM_VOLATILE_P (operands[0]) = 1;
39 (define_insn "*memory_barrier"
40 [(set (match_operand:BLK 0 "" "")
41 (unspec:BLK [(match_dup 0)] UNSPEC_MEMORY_BARRIER))]
43 { return mips_output_sync (); })
45 (define_insn "sync_compare_and_swap<mode>"
46 [(set (match_operand:GPR 0 "register_operand" "=&d,&d")
47 (match_operand:GPR 1 "memory_operand" "+R,R"))
49 (unspec_volatile:GPR [(match_operand:GPR 2 "reg_or_0_operand" "dJ,dJ")
50 (match_operand:GPR 3 "arith_operand" "I,d")]
51 UNSPEC_COMPARE_AND_SWAP))]
53 { return mips_output_sync_loop (insn, operands); }
54 [(set_attr "sync_insn1" "li,move")
55 (set_attr "sync_oldval" "0")
56 (set_attr "sync_mem" "1")
57 (set_attr "sync_required_oldval" "2")
58 (set_attr "sync_insn1_op2" "3")])
60 (define_expand "sync_compare_and_swap<mode>"
61 [(match_operand:SHORT 0 "register_operand")
62 (match_operand:SHORT 1 "memory_operand")
63 (match_operand:SHORT 2 "general_operand")
64 (match_operand:SHORT 3 "general_operand")]
67 union mips_gen_fn_ptrs generator;
68 generator.fn_6 = gen_compare_and_swap_12;
69 mips_expand_atomic_qihi (generator,
70 operands[0], operands[1], operands[2], operands[3]);
74 ;; Helper insn for mips_expand_atomic_qihi.
75 (define_insn "compare_and_swap_12"
76 [(set (match_operand:SI 0 "register_operand" "=&d,&d")
77 (match_operand:SI 1 "memory_operand" "+R,R"))
79 (unspec_volatile:SI [(match_operand:SI 2 "register_operand" "d,d")
80 (match_operand:SI 3 "register_operand" "d,d")
81 (match_operand:SI 4 "reg_or_0_operand" "dJ,dJ")
82 (match_operand:SI 5 "reg_or_0_operand" "d,J")]
83 UNSPEC_COMPARE_AND_SWAP_12))]
85 { return mips_output_sync_loop (insn, operands); }
86 [(set_attr "sync_oldval" "0")
87 (set_attr "sync_mem" "1")
88 (set_attr "sync_inclusive_mask" "2")
89 (set_attr "sync_exclusive_mask" "3")
90 (set_attr "sync_required_oldval" "4")
91 (set_attr "sync_insn1_op2" "5")])
93 (define_insn "sync_add<mode>"
94 [(set (match_operand:GPR 0 "memory_operand" "+R,R")
96 [(plus:GPR (match_dup 0)
97 (match_operand:GPR 1 "arith_operand" "I,d"))]
100 { return mips_output_sync_loop (insn, operands); }
101 [(set_attr "sync_insn1" "addiu,addu")
102 (set_attr "sync_mem" "0")
103 (set_attr "sync_insn1_op2" "1")])
105 (define_expand "sync_<optab><mode>"
106 [(set (match_operand:SHORT 0 "memory_operand")
107 (unspec_volatile:SHORT
108 [(atomic_hiqi_op:SHORT (match_dup 0)
109 (match_operand:SHORT 1 "general_operand"))]
110 UNSPEC_SYNC_OLD_OP))]
113 union mips_gen_fn_ptrs generator;
114 generator.fn_4 = gen_sync_<optab>_12;
115 mips_expand_atomic_qihi (generator,
116 NULL, operands[0], operands[1], NULL);
120 ;; Helper insn for sync_<optab><mode>
121 (define_insn "sync_<optab>_12"
122 [(set (match_operand:SI 0 "memory_operand" "+R")
124 [(match_operand:SI 1 "register_operand" "d")
125 (match_operand:SI 2 "register_operand" "d")
126 (atomic_hiqi_op:SI (match_dup 0)
127 (match_operand:SI 3 "register_operand" "dJ"))]
128 UNSPEC_SYNC_OLD_OP_12))
129 (clobber (match_scratch:SI 4 "=&d"))]
131 { return mips_output_sync_loop (insn, operands); }
132 [(set_attr "sync_insn1" "<insn>")
133 (set_attr "sync_insn2" "and")
134 (set_attr "sync_mem" "0")
135 (set_attr "sync_inclusive_mask" "1")
136 (set_attr "sync_exclusive_mask" "2")
137 (set_attr "sync_insn1_op2" "3")
138 (set_attr "sync_oldval" "4")
139 (set_attr "sync_newval" "4")])
141 (define_expand "sync_old_<optab><mode>"
143 (set (match_operand:SHORT 0 "register_operand")
144 (match_operand:SHORT 1 "memory_operand"))
146 (unspec_volatile:SHORT [(atomic_hiqi_op:SHORT
148 (match_operand:SHORT 2 "general_operand"))]
149 UNSPEC_SYNC_OLD_OP))])]
152 union mips_gen_fn_ptrs generator;
153 generator.fn_5 = gen_sync_old_<optab>_12;
154 mips_expand_atomic_qihi (generator,
155 operands[0], operands[1], operands[2], NULL);
159 ;; Helper insn for sync_old_<optab><mode>
160 (define_insn "sync_old_<optab>_12"
161 [(set (match_operand:SI 0 "register_operand" "=&d")
162 (match_operand:SI 1 "memory_operand" "+R"))
165 [(match_operand:SI 2 "register_operand" "d")
166 (match_operand:SI 3 "register_operand" "d")
167 (atomic_hiqi_op:SI (match_dup 0)
168 (match_operand:SI 4 "register_operand" "dJ"))]
169 UNSPEC_SYNC_OLD_OP_12))
170 (clobber (match_scratch:SI 5 "=&d"))]
172 { return mips_output_sync_loop (insn, operands); }
173 [(set_attr "sync_insn1" "<insn>")
174 (set_attr "sync_insn2" "and")
175 (set_attr "sync_oldval" "0")
176 (set_attr "sync_mem" "1")
177 (set_attr "sync_inclusive_mask" "2")
178 (set_attr "sync_exclusive_mask" "3")
179 (set_attr "sync_insn1_op2" "4")
180 (set_attr "sync_newval" "5")])
182 (define_expand "sync_new_<optab><mode>"
184 (set (match_operand:SHORT 0 "register_operand")
185 (unspec_volatile:SHORT [(atomic_hiqi_op:SHORT
186 (match_operand:SHORT 1 "memory_operand")
187 (match_operand:SHORT 2 "general_operand"))]
190 (unspec_volatile:SHORT [(match_dup 1) (match_dup 2)]
191 UNSPEC_SYNC_NEW_OP))])]
194 union mips_gen_fn_ptrs generator;
195 generator.fn_5 = gen_sync_new_<optab>_12;
196 mips_expand_atomic_qihi (generator,
197 operands[0], operands[1], operands[2], NULL);
201 ;; Helper insn for sync_new_<optab><mode>
202 (define_insn "sync_new_<optab>_12"
203 [(set (match_operand:SI 0 "register_operand" "=&d")
205 [(match_operand:SI 1 "memory_operand" "+R")
206 (match_operand:SI 2 "register_operand" "d")
207 (match_operand:SI 3 "register_operand" "d")
208 (atomic_hiqi_op:SI (match_dup 0)
209 (match_operand:SI 4 "register_operand" "dJ"))]
210 UNSPEC_SYNC_NEW_OP_12))
216 (match_dup 4)] UNSPEC_SYNC_NEW_OP_12))]
218 { return mips_output_sync_loop (insn, operands); }
219 [(set_attr "sync_insn1" "<insn>")
220 (set_attr "sync_insn2" "and")
221 (set_attr "sync_oldval" "0")
222 (set_attr "sync_newval" "0")
223 (set_attr "sync_mem" "1")
224 (set_attr "sync_inclusive_mask" "2")
225 (set_attr "sync_exclusive_mask" "3")
226 (set_attr "sync_insn1_op2" "4")])
228 (define_expand "sync_nand<mode>"
229 [(set (match_operand:SHORT 0 "memory_operand")
230 (unspec_volatile:SHORT
232 (match_operand:SHORT 1 "general_operand")]
233 UNSPEC_SYNC_OLD_OP))]
236 union mips_gen_fn_ptrs generator;
237 generator.fn_4 = gen_sync_nand_12;
238 mips_expand_atomic_qihi (generator,
239 NULL, operands[0], operands[1], NULL);
243 ;; Helper insn for sync_nand<mode>
244 (define_insn "sync_nand_12"
245 [(set (match_operand:SI 0 "memory_operand" "+R")
247 [(match_operand:SI 1 "register_operand" "d")
248 (match_operand:SI 2 "register_operand" "d")
250 (match_operand:SI 3 "register_operand" "dJ")]
251 UNSPEC_SYNC_OLD_OP_12))
252 (clobber (match_scratch:SI 4 "=&d"))]
254 { return mips_output_sync_loop (insn, operands); }
255 [(set_attr "sync_insn1" "and")
256 (set_attr "sync_insn2" "xor")
257 (set_attr "sync_mem" "0")
258 (set_attr "sync_inclusive_mask" "1")
259 (set_attr "sync_exclusive_mask" "2")
260 (set_attr "sync_insn1_op2" "3")
261 (set_attr "sync_oldval" "4")
262 (set_attr "sync_newval" "4")])
264 (define_expand "sync_old_nand<mode>"
266 (set (match_operand:SHORT 0 "register_operand")
267 (match_operand:SHORT 1 "memory_operand"))
269 (unspec_volatile:SHORT [(match_dup 1)
270 (match_operand:SHORT 2 "general_operand")]
271 UNSPEC_SYNC_OLD_OP))])]
274 union mips_gen_fn_ptrs generator;
275 generator.fn_5 = gen_sync_old_nand_12;
276 mips_expand_atomic_qihi (generator,
277 operands[0], operands[1], operands[2], NULL);
281 ;; Helper insn for sync_old_nand<mode>
282 (define_insn "sync_old_nand_12"
283 [(set (match_operand:SI 0 "register_operand" "=&d")
284 (match_operand:SI 1 "memory_operand" "+R"))
287 [(match_operand:SI 2 "register_operand" "d")
288 (match_operand:SI 3 "register_operand" "d")
289 (match_operand:SI 4 "register_operand" "dJ")]
290 UNSPEC_SYNC_OLD_OP_12))
291 (clobber (match_scratch:SI 5 "=&d"))]
293 { return mips_output_sync_loop (insn, operands); }
294 [(set_attr "sync_insn1" "and")
295 (set_attr "sync_insn2" "xor")
296 (set_attr "sync_oldval" "0")
297 (set_attr "sync_mem" "1")
298 (set_attr "sync_inclusive_mask" "2")
299 (set_attr "sync_exclusive_mask" "3")
300 (set_attr "sync_insn1_op2" "4")
301 (set_attr "sync_newval" "5")])
303 (define_expand "sync_new_nand<mode>"
305 (set (match_operand:SHORT 0 "register_operand")
306 (unspec_volatile:SHORT [(match_operand:SHORT 1 "memory_operand")
307 (match_operand:SHORT 2 "general_operand")]
310 (unspec_volatile:SHORT [(match_dup 1) (match_dup 2)]
311 UNSPEC_SYNC_NEW_OP))])]
314 union mips_gen_fn_ptrs generator;
315 generator.fn_5 = gen_sync_new_nand_12;
316 mips_expand_atomic_qihi (generator,
317 operands[0], operands[1], operands[2], NULL);
321 ;; Helper insn for sync_new_nand<mode>
322 (define_insn "sync_new_nand_12"
323 [(set (match_operand:SI 0 "register_operand" "=&d")
325 [(match_operand:SI 1 "memory_operand" "+R")
326 (match_operand:SI 2 "register_operand" "d")
327 (match_operand:SI 3 "register_operand" "d")
328 (match_operand:SI 4 "register_operand" "dJ")]
329 UNSPEC_SYNC_NEW_OP_12))
335 (match_dup 4)] UNSPEC_SYNC_NEW_OP_12))]
337 { return mips_output_sync_loop (insn, operands); }
338 [(set_attr "sync_insn1" "and")
339 (set_attr "sync_insn2" "xor")
340 (set_attr "sync_oldval" "0")
341 (set_attr "sync_newval" "0")
342 (set_attr "sync_mem" "1")
343 (set_attr "sync_inclusive_mask" "2")
344 (set_attr "sync_exclusive_mask" "3")
345 (set_attr "sync_insn1_op2" "4")])
347 (define_insn "sync_sub<mode>"
348 [(set (match_operand:GPR 0 "memory_operand" "+R")
350 [(minus:GPR (match_dup 0)
351 (match_operand:GPR 1 "register_operand" "d"))]
352 UNSPEC_SYNC_OLD_OP))]
354 { return mips_output_sync_loop (insn, operands); }
355 [(set_attr "sync_insn1" "subu")
356 (set_attr "sync_mem" "0")
357 (set_attr "sync_insn1_op2" "1")])
359 (define_insn "sync_old_add<mode>"
360 [(set (match_operand:GPR 0 "register_operand" "=&d,&d")
361 (match_operand:GPR 1 "memory_operand" "+R,R"))
364 [(plus:GPR (match_dup 1)
365 (match_operand:GPR 2 "arith_operand" "I,d"))]
366 UNSPEC_SYNC_OLD_OP))]
368 { return mips_output_sync_loop (insn, operands); }
369 [(set_attr "sync_insn1" "addiu,addu")
370 (set_attr "sync_oldval" "0")
371 (set_attr "sync_mem" "1")
372 (set_attr "sync_insn1_op2" "2")])
374 (define_insn "sync_old_sub<mode>"
375 [(set (match_operand:GPR 0 "register_operand" "=&d")
376 (match_operand:GPR 1 "memory_operand" "+R"))
379 [(minus:GPR (match_dup 1)
380 (match_operand:GPR 2 "register_operand" "d"))]
381 UNSPEC_SYNC_OLD_OP))]
383 { return mips_output_sync_loop (insn, operands); }
384 [(set_attr "sync_insn1" "subu")
385 (set_attr "sync_oldval" "0")
386 (set_attr "sync_mem" "1")
387 (set_attr "sync_insn1_op2" "2")])
389 (define_insn "sync_new_add<mode>"
390 [(set (match_operand:GPR 0 "register_operand" "=&d,&d")
391 (plus:GPR (match_operand:GPR 1 "memory_operand" "+R,R")
392 (match_operand:GPR 2 "arith_operand" "I,d")))
395 [(plus:GPR (match_dup 1) (match_dup 2))]
396 UNSPEC_SYNC_NEW_OP))]
398 { return mips_output_sync_loop (insn, operands); }
399 [(set_attr "sync_insn1" "addiu,addu")
400 (set_attr "sync_oldval" "0")
401 (set_attr "sync_newval" "0")
402 (set_attr "sync_mem" "1")
403 (set_attr "sync_insn1_op2" "2")])
405 (define_insn "sync_new_sub<mode>"
406 [(set (match_operand:GPR 0 "register_operand" "=&d")
407 (minus:GPR (match_operand:GPR 1 "memory_operand" "+R")
408 (match_operand:GPR 2 "register_operand" "d")))
411 [(minus:GPR (match_dup 1) (match_dup 2))]
412 UNSPEC_SYNC_NEW_OP))]
414 { return mips_output_sync_loop (insn, operands); }
415 [(set_attr "sync_insn1" "subu")
416 (set_attr "sync_oldval" "0")
417 (set_attr "sync_newval" "0")
418 (set_attr "sync_mem" "1")
419 (set_attr "sync_insn1_op2" "2")])
421 (define_insn "sync_<optab><mode>"
422 [(set (match_operand:GPR 0 "memory_operand" "+R,R")
424 [(fetchop_bit:GPR (match_operand:GPR 1 "uns_arith_operand" "K,d")
426 UNSPEC_SYNC_OLD_OP))]
428 { return mips_output_sync_loop (insn, operands); }
429 [(set_attr "sync_insn1" "<immediate_insn>,<insn>")
430 (set_attr "sync_mem" "0")
431 (set_attr "sync_insn1_op2" "1")])
433 (define_insn "sync_old_<optab><mode>"
434 [(set (match_operand:GPR 0 "register_operand" "=&d,&d")
435 (match_operand:GPR 1 "memory_operand" "+R,R"))
438 [(fetchop_bit:GPR (match_operand:GPR 2 "uns_arith_operand" "K,d")
440 UNSPEC_SYNC_OLD_OP))]
442 { return mips_output_sync_loop (insn, operands); }
443 [(set_attr "sync_insn1" "<immediate_insn>,<insn>")
444 (set_attr "sync_oldval" "0")
445 (set_attr "sync_mem" "1")
446 (set_attr "sync_insn1_op2" "2")])
448 (define_insn "sync_new_<optab><mode>"
449 [(set (match_operand:GPR 0 "register_operand" "=&d,&d")
450 (match_operand:GPR 1 "memory_operand" "+R,R"))
453 [(fetchop_bit:GPR (match_operand:GPR 2 "uns_arith_operand" "K,d")
455 UNSPEC_SYNC_NEW_OP))]
457 { return mips_output_sync_loop (insn, operands); }
458 [(set_attr "sync_insn1" "<immediate_insn>,<insn>")
459 (set_attr "sync_oldval" "0")
460 (set_attr "sync_newval" "0")
461 (set_attr "sync_mem" "1")
462 (set_attr "sync_insn1_op2" "2")])
464 (define_insn "sync_nand<mode>"
465 [(set (match_operand:GPR 0 "memory_operand" "+R,R")
466 (unspec_volatile:GPR [(match_operand:GPR 1 "uns_arith_operand" "K,d")]
467 UNSPEC_SYNC_OLD_OP))]
469 { return mips_output_sync_loop (insn, operands); }
470 [(set_attr "sync_insn1" "andi,and")
471 (set_attr "sync_insn2" "not")
472 (set_attr "sync_mem" "0")
473 (set_attr "sync_insn1_op2" "1")])
475 (define_insn "sync_old_nand<mode>"
476 [(set (match_operand:GPR 0 "register_operand" "=&d,&d")
477 (match_operand:GPR 1 "memory_operand" "+R,R"))
479 (unspec_volatile:GPR [(match_operand:GPR 2 "uns_arith_operand" "K,d")]
480 UNSPEC_SYNC_OLD_OP))]
482 { return mips_output_sync_loop (insn, operands); }
483 [(set_attr "sync_insn1" "andi,and")
484 (set_attr "sync_insn2" "not")
485 (set_attr "sync_oldval" "0")
486 (set_attr "sync_mem" "1")
487 (set_attr "sync_insn1_op2" "2")])
489 (define_insn "sync_new_nand<mode>"
490 [(set (match_operand:GPR 0 "register_operand" "=&d,&d")
491 (match_operand:GPR 1 "memory_operand" "+R,R"))
493 (unspec_volatile:GPR [(match_operand:GPR 2 "uns_arith_operand" "K,d")]
494 UNSPEC_SYNC_NEW_OP))]
496 { return mips_output_sync_loop (insn, operands); }
497 [(set_attr "sync_insn1" "andi,and")
498 (set_attr "sync_insn2" "not")
499 (set_attr "sync_oldval" "0")
500 (set_attr "sync_newval" "0")
501 (set_attr "sync_mem" "1")
502 (set_attr "sync_insn1_op2" "2")])
504 (define_insn "sync_lock_test_and_set<mode>"
505 [(set (match_operand:GPR 0 "register_operand" "=&d,&d")
506 (match_operand:GPR 1 "memory_operand" "+R,R"))
508 (unspec_volatile:GPR [(match_operand:GPR 2 "arith_operand" "I,d")]
509 UNSPEC_SYNC_EXCHANGE))]
511 { return mips_output_sync_loop (insn, operands); }
512 [(set_attr "sync_release_barrier" "no")
513 (set_attr "sync_insn1" "li,move")
514 (set_attr "sync_oldval" "0")
515 (set_attr "sync_mem" "1")
516 (set_attr "sync_insn1_op2" "2")])
518 (define_expand "sync_lock_test_and_set<mode>"
519 [(match_operand:SHORT 0 "register_operand")
520 (match_operand:SHORT 1 "memory_operand")
521 (match_operand:SHORT 2 "general_operand")]
524 union mips_gen_fn_ptrs generator;
525 generator.fn_5 = gen_test_and_set_12;
526 mips_expand_atomic_qihi (generator,
527 operands[0], operands[1], operands[2], NULL);
531 (define_insn "test_and_set_12"
532 [(set (match_operand:SI 0 "register_operand" "=&d")
533 (match_operand:SI 1 "memory_operand" "+R"))
535 (unspec_volatile:SI [(match_operand:SI 2 "register_operand" "d")
536 (match_operand:SI 3 "register_operand" "d")
537 (match_operand:SI 4 "arith_operand" "dJ")]
538 UNSPEC_SYNC_EXCHANGE_12))]
540 { return mips_output_sync_loop (insn, operands); }
541 [(set_attr "sync_release_barrier" "no")
542 (set_attr "sync_oldval" "0")
543 (set_attr "sync_mem" "1")
544 ;; Unused, but needed to give the number of operands expected by
546 (set_attr "sync_inclusive_mask" "2")
547 (set_attr "sync_exclusive_mask" "3")
548 (set_attr "sync_insn1_op2" "4")])