1 ;; Machine Description for MIPS based processor synchronization
3 ;; Copyright (C) 2007, 2008
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_insn "memory_barrier"
31 [(set (mem:BLK (scratch))
32 (unspec:BLK [(const_int 0)] UNSPEC_MEMORY_BARRIER))]
36 (define_insn "sync_compare_and_swap<mode>"
37 [(set (match_operand:GPR 0 "register_operand" "=&d,&d")
38 (match_operand:GPR 1 "memory_operand" "+R,R"))
40 (unspec_volatile:GPR [(match_operand:GPR 2 "reg_or_0_operand" "dJ,dJ")
41 (match_operand:GPR 3 "arith_operand" "I,d")]
42 UNSPEC_COMPARE_AND_SWAP))]
45 if (which_alternative == 0)
46 return mips_output_sync_loop (MIPS_COMPARE_AND_SWAP ("<d>", "li"));
48 return mips_output_sync_loop (MIPS_COMPARE_AND_SWAP ("<d>", "move"));
50 [(set_attr "length" "32")])
52 (define_expand "sync_compare_and_swap<mode>"
53 [(match_operand:SHORT 0 "register_operand")
54 (match_operand:SHORT 1 "memory_operand")
55 (match_operand:SHORT 2 "general_operand")
56 (match_operand:SHORT 3 "general_operand")]
59 union mips_gen_fn_ptrs generator;
60 generator.fn_6 = gen_compare_and_swap_12;
61 mips_expand_atomic_qihi (generator,
62 operands[0], operands[1], operands[2], operands[3]);
66 ;; Helper insn for mips_expand_atomic_qihi.
67 (define_insn "compare_and_swap_12"
68 [(set (match_operand:SI 0 "register_operand" "=&d,&d")
69 (match_operand:SI 1 "memory_operand" "+R,R"))
71 (unspec_volatile:SI [(match_operand:SI 2 "register_operand" "d,d")
72 (match_operand:SI 3 "register_operand" "d,d")
73 (match_operand:SI 4 "reg_or_0_operand" "dJ,dJ")
74 (match_operand:SI 5 "reg_or_0_operand" "d,J")]
75 UNSPEC_COMPARE_AND_SWAP_12))]
78 if (which_alternative == 0)
79 return (mips_output_sync_loop
80 (MIPS_COMPARE_AND_SWAP_12 (MIPS_COMPARE_AND_SWAP_12_NONZERO_OP)));
82 return (mips_output_sync_loop
83 (MIPS_COMPARE_AND_SWAP_12 (MIPS_COMPARE_AND_SWAP_12_ZERO_OP)));
85 [(set_attr "length" "40,36")])
87 (define_insn "sync_add<mode>"
88 [(set (match_operand:GPR 0 "memory_operand" "+R,R")
90 [(plus:GPR (match_dup 0)
91 (match_operand:GPR 1 "arith_operand" "I,d"))]
95 if (which_alternative == 0)
96 return mips_output_sync_loop (MIPS_SYNC_OP ("<d>", "<d>addiu"));
98 return mips_output_sync_loop (MIPS_SYNC_OP ("<d>", "<d>addu"));
100 [(set_attr "length" "28")])
102 (define_expand "sync_<optab><mode>"
103 [(set (match_operand:SHORT 0 "memory_operand")
104 (unspec_volatile:SHORT
105 [(atomic_hiqi_op:SHORT (match_dup 0)
106 (match_operand:SHORT 1 "general_operand"))]
107 UNSPEC_SYNC_OLD_OP))]
110 union mips_gen_fn_ptrs generator;
111 generator.fn_4 = gen_sync_<optab>_12;
112 mips_expand_atomic_qihi (generator,
113 NULL, operands[0], operands[1], NULL);
117 ;; Helper insn for sync_<optab><mode>
118 (define_insn "sync_<optab>_12"
119 [(set (match_operand:SI 0 "memory_operand" "+R")
121 [(match_operand:SI 1 "register_operand" "d")
122 (match_operand:SI 2 "register_operand" "d")
123 (atomic_hiqi_op:SI (match_dup 0)
124 (match_operand:SI 3 "register_operand" "dJ"))]
125 UNSPEC_SYNC_OLD_OP_12))
126 (clobber (match_scratch:SI 4 "=&d"))]
129 return (mips_output_sync_loop
130 (MIPS_SYNC_OP_12 ("<insn>", MIPS_SYNC_OP_12_AND)));
132 [(set_attr "length" "40")])
134 (define_expand "sync_old_<optab><mode>"
136 (set (match_operand:SHORT 0 "register_operand")
137 (match_operand:SHORT 1 "memory_operand"))
139 (unspec_volatile:SHORT [(atomic_hiqi_op:SHORT
141 (match_operand:SHORT 2 "general_operand"))]
142 UNSPEC_SYNC_OLD_OP))])]
145 union mips_gen_fn_ptrs generator;
146 generator.fn_5 = gen_sync_old_<optab>_12;
147 mips_expand_atomic_qihi (generator,
148 operands[0], operands[1], operands[2], NULL);
152 ;; Helper insn for sync_old_<optab><mode>
153 (define_insn "sync_old_<optab>_12"
154 [(set (match_operand:SI 0 "register_operand" "=&d")
155 (match_operand:SI 1 "memory_operand" "+R"))
158 [(match_operand:SI 2 "register_operand" "d")
159 (match_operand:SI 3 "register_operand" "d")
160 (atomic_hiqi_op:SI (match_dup 0)
161 (match_operand:SI 4 "register_operand" "dJ"))]
162 UNSPEC_SYNC_OLD_OP_12))
163 (clobber (match_scratch:SI 5 "=&d"))]
166 return (mips_output_sync_loop
167 (MIPS_SYNC_OLD_OP_12 ("<insn>", MIPS_SYNC_OLD_OP_12_AND)));
169 [(set_attr "length" "40")])
171 (define_expand "sync_new_<optab><mode>"
173 (set (match_operand:SHORT 0 "register_operand")
174 (unspec_volatile:SHORT [(atomic_hiqi_op:SHORT
175 (match_operand:SHORT 1 "memory_operand")
176 (match_operand:SHORT 2 "general_operand"))]
179 (unspec_volatile:SHORT [(match_dup 1) (match_dup 2)]
180 UNSPEC_SYNC_NEW_OP))])]
183 union mips_gen_fn_ptrs generator;
184 generator.fn_5 = gen_sync_new_<optab>_12;
185 mips_expand_atomic_qihi (generator,
186 operands[0], operands[1], operands[2], NULL);
190 ;; Helper insn for sync_new_<optab><mode>
191 (define_insn "sync_new_<optab>_12"
192 [(set (match_operand:SI 0 "register_operand" "=&d")
194 [(match_operand:SI 1 "memory_operand" "+R")
195 (match_operand:SI 2 "register_operand" "d")
196 (match_operand:SI 3 "register_operand" "d")
197 (atomic_hiqi_op:SI (match_dup 0)
198 (match_operand:SI 4 "register_operand" "dJ"))]
199 UNSPEC_SYNC_NEW_OP_12))
205 (match_dup 4)] UNSPEC_SYNC_NEW_OP_12))]
208 return (mips_output_sync_loop
209 (MIPS_SYNC_NEW_OP_12 ("<insn>", MIPS_SYNC_NEW_OP_12_AND)));
211 [(set_attr "length" "40")])
213 (define_expand "sync_nand<mode>"
214 [(set (match_operand:SHORT 0 "memory_operand")
215 (unspec_volatile:SHORT
217 (match_operand:SHORT 1 "general_operand")]
218 UNSPEC_SYNC_OLD_OP))]
221 union mips_gen_fn_ptrs generator;
222 generator.fn_4 = gen_sync_nand_12;
223 mips_expand_atomic_qihi (generator,
224 NULL, operands[0], operands[1], NULL);
228 ;; Helper insn for sync_nand<mode>
229 (define_insn "sync_nand_12"
230 [(set (match_operand:SI 0 "memory_operand" "+R")
232 [(match_operand:SI 1 "register_operand" "d")
233 (match_operand:SI 2 "register_operand" "d")
235 (match_operand:SI 3 "register_operand" "dJ")]
236 UNSPEC_SYNC_OLD_OP_12))
237 (clobber (match_scratch:SI 4 "=&d"))]
240 return (mips_output_sync_loop
241 (MIPS_SYNC_OP_12 ("and", MIPS_SYNC_OP_12_XOR)));
243 [(set_attr "length" "40")])
245 (define_expand "sync_old_nand<mode>"
247 (set (match_operand:SHORT 0 "register_operand")
248 (match_operand:SHORT 1 "memory_operand"))
250 (unspec_volatile:SHORT [(match_dup 1)
251 (match_operand:SHORT 2 "general_operand")]
252 UNSPEC_SYNC_OLD_OP))])]
255 union mips_gen_fn_ptrs generator;
256 generator.fn_5 = gen_sync_old_nand_12;
257 mips_expand_atomic_qihi (generator,
258 operands[0], operands[1], operands[2], NULL);
262 ;; Helper insn for sync_old_nand<mode>
263 (define_insn "sync_old_nand_12"
264 [(set (match_operand:SI 0 "register_operand" "=&d")
265 (match_operand:SI 1 "memory_operand" "+R"))
268 [(match_operand:SI 2 "register_operand" "d")
269 (match_operand:SI 3 "register_operand" "d")
270 (match_operand:SI 4 "register_operand" "dJ")]
271 UNSPEC_SYNC_OLD_OP_12))
272 (clobber (match_scratch:SI 5 "=&d"))]
275 return (mips_output_sync_loop
276 (MIPS_SYNC_OLD_OP_12 ("and", MIPS_SYNC_OLD_OP_12_XOR)));
278 [(set_attr "length" "40")])
280 (define_expand "sync_new_nand<mode>"
282 (set (match_operand:SHORT 0 "register_operand")
283 (unspec_volatile:SHORT [(match_operand:SHORT 1 "memory_operand")
284 (match_operand:SHORT 2 "general_operand")]
287 (unspec_volatile:SHORT [(match_dup 1) (match_dup 2)]
288 UNSPEC_SYNC_NEW_OP))])]
291 union mips_gen_fn_ptrs generator;
292 generator.fn_5 = gen_sync_new_nand_12;
293 mips_expand_atomic_qihi (generator,
294 operands[0], operands[1], operands[2], NULL);
298 ;; Helper insn for sync_new_nand<mode>
299 (define_insn "sync_new_nand_12"
300 [(set (match_operand:SI 0 "register_operand" "=&d")
302 [(match_operand:SI 1 "memory_operand" "+R")
303 (match_operand:SI 2 "register_operand" "d")
304 (match_operand:SI 3 "register_operand" "d")
305 (match_operand:SI 4 "register_operand" "dJ")]
306 UNSPEC_SYNC_NEW_OP_12))
312 (match_dup 4)] UNSPEC_SYNC_NEW_OP_12))]
315 return (mips_output_sync_loop
316 (MIPS_SYNC_NEW_OP_12 ("and", MIPS_SYNC_NEW_OP_12_XOR)));
318 [(set_attr "length" "40")])
320 (define_insn "sync_sub<mode>"
321 [(set (match_operand:GPR 0 "memory_operand" "+R")
323 [(minus:GPR (match_dup 0)
324 (match_operand:GPR 1 "register_operand" "d"))]
325 UNSPEC_SYNC_OLD_OP))]
328 return mips_output_sync_loop (MIPS_SYNC_OP ("<d>", "<d>subu"));
330 [(set_attr "length" "28")])
332 (define_insn "sync_old_add<mode>"
333 [(set (match_operand:GPR 0 "register_operand" "=&d,&d")
334 (match_operand:GPR 1 "memory_operand" "+R,R"))
337 [(plus:GPR (match_dup 1)
338 (match_operand:GPR 2 "arith_operand" "I,d"))]
339 UNSPEC_SYNC_OLD_OP))]
342 if (which_alternative == 0)
343 return mips_output_sync_loop (MIPS_SYNC_OLD_OP ("<d>", "<d>addiu"));
345 return mips_output_sync_loop (MIPS_SYNC_OLD_OP ("<d>", "<d>addu"));
347 [(set_attr "length" "28")])
349 (define_insn "sync_old_sub<mode>"
350 [(set (match_operand:GPR 0 "register_operand" "=&d")
351 (match_operand:GPR 1 "memory_operand" "+R"))
354 [(minus:GPR (match_dup 1)
355 (match_operand:GPR 2 "register_operand" "d"))]
356 UNSPEC_SYNC_OLD_OP))]
359 return mips_output_sync_loop (MIPS_SYNC_OLD_OP ("<d>", "<d>subu"));
361 [(set_attr "length" "28")])
363 (define_insn "sync_new_add<mode>"
364 [(set (match_operand:GPR 0 "register_operand" "=&d,&d")
365 (plus:GPR (match_operand:GPR 1 "memory_operand" "+R,R")
366 (match_operand:GPR 2 "arith_operand" "I,d")))
369 [(plus:GPR (match_dup 1) (match_dup 2))]
370 UNSPEC_SYNC_NEW_OP))]
373 if (which_alternative == 0)
374 return mips_output_sync_loop (MIPS_SYNC_NEW_OP ("<d>", "<d>addiu"));
376 return mips_output_sync_loop (MIPS_SYNC_NEW_OP ("<d>", "<d>addu"));
378 [(set_attr "length" "28")])
380 (define_insn "sync_new_sub<mode>"
381 [(set (match_operand:GPR 0 "register_operand" "=&d")
382 (minus:GPR (match_operand:GPR 1 "memory_operand" "+R")
383 (match_operand:GPR 2 "register_operand" "d")))
386 [(minus:GPR (match_dup 1) (match_dup 2))]
387 UNSPEC_SYNC_NEW_OP))]
390 return mips_output_sync_loop (MIPS_SYNC_NEW_OP ("<d>", "<d>subu"));
392 [(set_attr "length" "28")])
394 (define_insn "sync_<optab><mode>"
395 [(set (match_operand:GPR 0 "memory_operand" "+R,R")
397 [(fetchop_bit:GPR (match_operand:GPR 1 "uns_arith_operand" "K,d")
399 UNSPEC_SYNC_OLD_OP))]
402 if (which_alternative == 0)
403 return mips_output_sync_loop (MIPS_SYNC_OP ("<d>", "<immediate_insn>"));
405 return mips_output_sync_loop (MIPS_SYNC_OP ("<d>", "<insn>"));
407 [(set_attr "length" "28")])
409 (define_insn "sync_old_<optab><mode>"
410 [(set (match_operand:GPR 0 "register_operand" "=&d,&d")
411 (match_operand:GPR 1 "memory_operand" "+R,R"))
414 [(fetchop_bit:GPR (match_operand:GPR 2 "uns_arith_operand" "K,d")
416 UNSPEC_SYNC_OLD_OP))]
419 if (which_alternative == 0)
420 return (mips_output_sync_loop
421 (MIPS_SYNC_OLD_OP ("<d>", "<immediate_insn>")));
423 return mips_output_sync_loop (MIPS_SYNC_OLD_OP ("<d>", "<insn>"));
425 [(set_attr "length" "28")])
427 (define_insn "sync_new_<optab><mode>"
428 [(set (match_operand:GPR 0 "register_operand" "=&d,&d")
429 (match_operand:GPR 1 "memory_operand" "+R,R"))
432 [(fetchop_bit:GPR (match_operand:GPR 2 "uns_arith_operand" "K,d")
434 UNSPEC_SYNC_NEW_OP))]
437 if (which_alternative == 0)
438 return (mips_output_sync_loop
439 (MIPS_SYNC_NEW_OP ("<d>", "<immediate_insn>")));
441 return mips_output_sync_loop (MIPS_SYNC_NEW_OP ("<d>", "<insn>"));
443 [(set_attr "length" "28")])
445 (define_insn "sync_nand<mode>"
446 [(set (match_operand:GPR 0 "memory_operand" "+R,R")
447 (unspec_volatile:GPR [(match_operand:GPR 1 "uns_arith_operand" "K,d")]
448 UNSPEC_SYNC_OLD_OP))]
451 if (which_alternative == 0)
452 return mips_output_sync_loop (MIPS_SYNC_NAND ("<d>", "andi"));
454 return mips_output_sync_loop (MIPS_SYNC_NAND ("<d>", "and"));
456 [(set_attr "length" "32")])
458 (define_insn "sync_old_nand<mode>"
459 [(set (match_operand:GPR 0 "register_operand" "=&d,&d")
460 (match_operand:GPR 1 "memory_operand" "+R,R"))
462 (unspec_volatile:GPR [(match_operand:GPR 2 "uns_arith_operand" "K,d")]
463 UNSPEC_SYNC_OLD_OP))]
466 if (which_alternative == 0)
467 return mips_output_sync_loop (MIPS_SYNC_OLD_NAND ("<d>", "andi"));
469 return mips_output_sync_loop (MIPS_SYNC_OLD_NAND ("<d>", "and"));
471 [(set_attr "length" "32")])
473 (define_insn "sync_new_nand<mode>"
474 [(set (match_operand:GPR 0 "register_operand" "=&d,&d")
475 (match_operand:GPR 1 "memory_operand" "+R,R"))
477 (unspec_volatile:GPR [(match_operand:GPR 2 "uns_arith_operand" "K,d")]
478 UNSPEC_SYNC_NEW_OP))]
481 if (which_alternative == 0)
482 return mips_output_sync_loop (MIPS_SYNC_NEW_NAND ("<d>", "andi"));
484 return mips_output_sync_loop (MIPS_SYNC_NEW_NAND ("<d>", "and"));
486 [(set_attr "length" "32")])
488 (define_insn "sync_lock_test_and_set<mode>"
489 [(set (match_operand:GPR 0 "register_operand" "=&d,&d")
490 (match_operand:GPR 1 "memory_operand" "+R,R"))
492 (unspec_volatile:GPR [(match_operand:GPR 2 "arith_operand" "I,d")]
493 UNSPEC_SYNC_EXCHANGE))]
496 if (which_alternative == 0)
497 return mips_output_sync_loop (MIPS_SYNC_EXCHANGE ("<d>", "li"));
499 return mips_output_sync_loop (MIPS_SYNC_EXCHANGE ("<d>", "move"));
501 [(set_attr "length" "24")])
503 (define_expand "sync_lock_test_and_set<mode>"
504 [(match_operand:SHORT 0 "register_operand")
505 (match_operand:SHORT 1 "memory_operand")
506 (match_operand:SHORT 2 "general_operand")]
509 union mips_gen_fn_ptrs generator;
510 generator.fn_5 = gen_test_and_set_12;
511 mips_expand_atomic_qihi (generator,
512 operands[0], operands[1], operands[2], NULL);
516 (define_insn "test_and_set_12"
517 [(set (match_operand:SI 0 "register_operand" "=&d,&d")
518 (match_operand:SI 1 "memory_operand" "+R,R"))
520 (unspec_volatile:SI [(match_operand:SI 2 "register_operand" "d,d")
521 (match_operand:SI 3 "register_operand" "d,d")
522 (match_operand:SI 4 "arith_operand" "d,J")]
523 UNSPEC_SYNC_EXCHANGE_12))]
526 if (which_alternative == 0)
527 return (mips_output_sync_loop
528 (MIPS_SYNC_EXCHANGE_12 (MIPS_SYNC_EXCHANGE_12_NONZERO_OP)));
530 return (mips_output_sync_loop
531 (MIPS_SYNC_EXCHANGE_12 (MIPS_SYNC_EXCHANGE_12_ZERO_OP)));
533 [(set_attr "length" "28,24")])