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_NOT_NOP)));
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_NOT_NOP,
168 MIPS_SYNC_OLD_OP_12_NOT_NOP_REG)));
170 [(set_attr "length" "40")])
172 (define_expand "sync_new_<optab><mode>"
174 (set (match_operand:SHORT 0 "register_operand")
175 (unspec_volatile:SHORT [(atomic_hiqi_op:SHORT
176 (match_operand:SHORT 1 "memory_operand")
177 (match_operand:SHORT 2 "general_operand"))]
180 (unspec_volatile:SHORT [(match_dup 1) (match_dup 2)]
181 UNSPEC_SYNC_NEW_OP))])]
184 union mips_gen_fn_ptrs generator;
185 generator.fn_5 = gen_sync_new_<optab>_12;
186 mips_expand_atomic_qihi (generator,
187 operands[0], operands[1], operands[2], NULL);
191 ;; Helper insn for sync_new_<optab><mode>
192 (define_insn "sync_new_<optab>_12"
193 [(set (match_operand:SI 0 "register_operand" "=&d")
195 [(match_operand:SI 1 "memory_operand" "+R")
196 (match_operand:SI 2 "register_operand" "d")
197 (match_operand:SI 3 "register_operand" "d")
198 (atomic_hiqi_op:SI (match_dup 0)
199 (match_operand:SI 4 "register_operand" "dJ"))]
200 UNSPEC_SYNC_NEW_OP_12))
206 (match_dup 4)] UNSPEC_SYNC_NEW_OP_12))]
209 return (mips_output_sync_loop
210 (MIPS_SYNC_NEW_OP_12 ("<insn>", MIPS_SYNC_NEW_OP_12_NOT_NOP)));
212 [(set_attr "length" "40")])
214 (define_expand "sync_nand<mode>"
215 [(set (match_operand:SHORT 0 "memory_operand")
216 (unspec_volatile:SHORT
218 (match_operand:SHORT 1 "general_operand")]
219 UNSPEC_SYNC_OLD_OP))]
222 union mips_gen_fn_ptrs generator;
223 generator.fn_4 = gen_sync_nand_12;
224 mips_expand_atomic_qihi (generator,
225 NULL, operands[0], operands[1], NULL);
229 ;; Helper insn for sync_nand<mode>
230 (define_insn "sync_nand_12"
231 [(set (match_operand:SI 0 "memory_operand" "+R")
233 [(match_operand:SI 1 "register_operand" "d")
234 (match_operand:SI 2 "register_operand" "d")
236 (match_operand:SI 3 "register_operand" "dJ")]
237 UNSPEC_SYNC_OLD_OP_12))
238 (clobber (match_scratch:SI 4 "=&d"))]
241 return (mips_output_sync_loop
242 (MIPS_SYNC_OP_12 ("and", MIPS_SYNC_OP_12_NOT_NOT)));
244 [(set_attr "length" "44")])
246 (define_expand "sync_old_nand<mode>"
248 (set (match_operand:SHORT 0 "register_operand")
249 (match_operand:SHORT 1 "memory_operand"))
251 (unspec_volatile:SHORT [(match_dup 1)
252 (match_operand:SHORT 2 "general_operand")]
253 UNSPEC_SYNC_OLD_OP))])]
256 union mips_gen_fn_ptrs generator;
257 generator.fn_5 = gen_sync_old_nand_12;
258 mips_expand_atomic_qihi (generator,
259 operands[0], operands[1], operands[2], NULL);
263 ;; Helper insn for sync_old_nand<mode>
264 (define_insn "sync_old_nand_12"
265 [(set (match_operand:SI 0 "register_operand" "=&d")
266 (match_operand:SI 1 "memory_operand" "+R"))
269 [(match_operand:SI 2 "register_operand" "d")
270 (match_operand:SI 3 "register_operand" "d")
271 (match_operand:SI 4 "register_operand" "dJ")]
272 UNSPEC_SYNC_OLD_OP_12))
273 (clobber (match_scratch:SI 5 "=&d"))]
276 return (mips_output_sync_loop
277 (MIPS_SYNC_OLD_OP_12 ("and", MIPS_SYNC_OLD_OP_12_NOT_NOT,
278 MIPS_SYNC_OLD_OP_12_NOT_NOT_REG)));
280 [(set_attr "length" "44")])
282 (define_expand "sync_new_nand<mode>"
284 (set (match_operand:SHORT 0 "register_operand")
285 (unspec_volatile:SHORT [(match_operand:SHORT 1 "memory_operand")
286 (match_operand:SHORT 2 "general_operand")]
289 (unspec_volatile:SHORT [(match_dup 1) (match_dup 2)]
290 UNSPEC_SYNC_NEW_OP))])]
293 union mips_gen_fn_ptrs generator;
294 generator.fn_5 = gen_sync_new_nand_12;
295 mips_expand_atomic_qihi (generator,
296 operands[0], operands[1], operands[2], NULL);
300 ;; Helper insn for sync_new_nand<mode>
301 (define_insn "sync_new_nand_12"
302 [(set (match_operand:SI 0 "register_operand" "=&d")
304 [(match_operand:SI 1 "memory_operand" "+R")
305 (match_operand:SI 2 "register_operand" "d")
306 (match_operand:SI 3 "register_operand" "d")
307 (match_operand:SI 4 "register_operand" "dJ")]
308 UNSPEC_SYNC_NEW_OP_12))
314 (match_dup 4)] UNSPEC_SYNC_NEW_OP_12))]
317 return (mips_output_sync_loop
318 (MIPS_SYNC_NEW_OP_12 ("and", MIPS_SYNC_NEW_OP_12_NOT_NOT)));
320 [(set_attr "length" "40")])
322 (define_insn "sync_sub<mode>"
323 [(set (match_operand:GPR 0 "memory_operand" "+R")
325 [(minus:GPR (match_dup 0)
326 (match_operand:GPR 1 "register_operand" "d"))]
327 UNSPEC_SYNC_OLD_OP))]
330 return mips_output_sync_loop (MIPS_SYNC_OP ("<d>", "<d>subu"));
332 [(set_attr "length" "28")])
334 (define_insn "sync_old_add<mode>"
335 [(set (match_operand:GPR 0 "register_operand" "=&d,&d")
336 (match_operand:GPR 1 "memory_operand" "+R,R"))
339 [(plus:GPR (match_dup 1)
340 (match_operand:GPR 2 "arith_operand" "I,d"))]
341 UNSPEC_SYNC_OLD_OP))]
344 if (which_alternative == 0)
345 return mips_output_sync_loop (MIPS_SYNC_OLD_OP ("<d>", "<d>addiu"));
347 return mips_output_sync_loop (MIPS_SYNC_OLD_OP ("<d>", "<d>addu"));
349 [(set_attr "length" "28")])
351 (define_insn "sync_old_sub<mode>"
352 [(set (match_operand:GPR 0 "register_operand" "=&d")
353 (match_operand:GPR 1 "memory_operand" "+R"))
356 [(minus:GPR (match_dup 1)
357 (match_operand:GPR 2 "register_operand" "d"))]
358 UNSPEC_SYNC_OLD_OP))]
361 return mips_output_sync_loop (MIPS_SYNC_OLD_OP ("<d>", "<d>subu"));
363 [(set_attr "length" "28")])
365 (define_insn "sync_new_add<mode>"
366 [(set (match_operand:GPR 0 "register_operand" "=&d,&d")
367 (plus:GPR (match_operand:GPR 1 "memory_operand" "+R,R")
368 (match_operand:GPR 2 "arith_operand" "I,d")))
371 [(plus:GPR (match_dup 1) (match_dup 2))]
372 UNSPEC_SYNC_NEW_OP))]
375 if (which_alternative == 0)
376 return mips_output_sync_loop (MIPS_SYNC_NEW_OP ("<d>", "<d>addiu"));
378 return mips_output_sync_loop (MIPS_SYNC_NEW_OP ("<d>", "<d>addu"));
380 [(set_attr "length" "28")])
382 (define_insn "sync_new_sub<mode>"
383 [(set (match_operand:GPR 0 "register_operand" "=&d")
384 (minus:GPR (match_operand:GPR 1 "memory_operand" "+R")
385 (match_operand:GPR 2 "register_operand" "d")))
388 [(minus:GPR (match_dup 1) (match_dup 2))]
389 UNSPEC_SYNC_NEW_OP))]
392 return mips_output_sync_loop (MIPS_SYNC_NEW_OP ("<d>", "<d>subu"));
394 [(set_attr "length" "28")])
396 (define_insn "sync_<optab><mode>"
397 [(set (match_operand:GPR 0 "memory_operand" "+R,R")
399 [(fetchop_bit:GPR (match_operand:GPR 1 "uns_arith_operand" "K,d")
401 UNSPEC_SYNC_OLD_OP))]
404 if (which_alternative == 0)
405 return mips_output_sync_loop (MIPS_SYNC_OP ("<d>", "<immediate_insn>"));
407 return mips_output_sync_loop (MIPS_SYNC_OP ("<d>", "<insn>"));
409 [(set_attr "length" "28")])
411 (define_insn "sync_old_<optab><mode>"
412 [(set (match_operand:GPR 0 "register_operand" "=&d,&d")
413 (match_operand:GPR 1 "memory_operand" "+R,R"))
416 [(fetchop_bit:GPR (match_operand:GPR 2 "uns_arith_operand" "K,d")
418 UNSPEC_SYNC_OLD_OP))]
421 if (which_alternative == 0)
422 return (mips_output_sync_loop
423 (MIPS_SYNC_OLD_OP ("<d>", "<immediate_insn>")));
425 return mips_output_sync_loop (MIPS_SYNC_OLD_OP ("<d>", "<insn>"));
427 [(set_attr "length" "28")])
429 (define_insn "sync_new_<optab><mode>"
430 [(set (match_operand:GPR 0 "register_operand" "=&d,&d")
431 (match_operand:GPR 1 "memory_operand" "+R,R"))
434 [(fetchop_bit:GPR (match_operand:GPR 2 "uns_arith_operand" "K,d")
436 UNSPEC_SYNC_NEW_OP))]
439 if (which_alternative == 0)
440 return (mips_output_sync_loop
441 (MIPS_SYNC_NEW_OP ("<d>", "<immediate_insn>")));
443 return mips_output_sync_loop (MIPS_SYNC_NEW_OP ("<d>", "<insn>"));
445 [(set_attr "length" "28")])
447 (define_insn "sync_nand<mode>"
448 [(set (match_operand:GPR 0 "memory_operand" "+R,R")
449 (unspec_volatile:GPR [(match_operand:GPR 1 "uns_arith_operand" "K,d")]
450 UNSPEC_SYNC_OLD_OP))]
453 if (which_alternative == 0)
454 return mips_output_sync_loop (MIPS_SYNC_NAND ("<d>", "andi"));
456 return mips_output_sync_loop (MIPS_SYNC_NAND ("<d>", "and"));
458 [(set_attr "length" "32")])
460 (define_insn "sync_old_nand<mode>"
461 [(set (match_operand:GPR 0 "register_operand" "=&d,&d")
462 (match_operand:GPR 1 "memory_operand" "+R,R"))
464 (unspec_volatile:GPR [(match_operand:GPR 2 "uns_arith_operand" "K,d")]
465 UNSPEC_SYNC_OLD_OP))]
468 if (which_alternative == 0)
469 return mips_output_sync_loop (MIPS_SYNC_OLD_NAND ("<d>", "andi"));
471 return mips_output_sync_loop (MIPS_SYNC_OLD_NAND ("<d>", "and"));
473 [(set_attr "length" "32")])
475 (define_insn "sync_new_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_NEW_OP))]
483 if (which_alternative == 0)
484 return mips_output_sync_loop (MIPS_SYNC_NEW_NAND ("<d>", "andi"));
486 return mips_output_sync_loop (MIPS_SYNC_NEW_NAND ("<d>", "and"));
488 [(set_attr "length" "32")])
490 (define_insn "sync_lock_test_and_set<mode>"
491 [(set (match_operand:GPR 0 "register_operand" "=&d,&d")
492 (match_operand:GPR 1 "memory_operand" "+R,R"))
494 (unspec_volatile:GPR [(match_operand:GPR 2 "arith_operand" "I,d")]
495 UNSPEC_SYNC_EXCHANGE))]
498 if (which_alternative == 0)
499 return mips_output_sync_loop (MIPS_SYNC_EXCHANGE ("<d>", "li"));
501 return mips_output_sync_loop (MIPS_SYNC_EXCHANGE ("<d>", "move"));
503 [(set_attr "length" "24")])
505 (define_expand "sync_lock_test_and_set<mode>"
506 [(match_operand:SHORT 0 "register_operand")
507 (match_operand:SHORT 1 "memory_operand")
508 (match_operand:SHORT 2 "general_operand")]
511 union mips_gen_fn_ptrs generator;
512 generator.fn_5 = gen_test_and_set_12;
513 mips_expand_atomic_qihi (generator,
514 operands[0], operands[1], operands[2], NULL);
518 (define_insn "test_and_set_12"
519 [(set (match_operand:SI 0 "register_operand" "=&d,&d")
520 (match_operand:SI 1 "memory_operand" "+R,R"))
522 (unspec_volatile:SI [(match_operand:SI 2 "register_operand" "d,d")
523 (match_operand:SI 3 "register_operand" "d,d")
524 (match_operand:SI 4 "arith_operand" "d,J")]
525 UNSPEC_SYNC_EXCHANGE_12))]
528 if (which_alternative == 0)
529 return (mips_output_sync_loop
530 (MIPS_SYNC_EXCHANGE_12 (MIPS_SYNC_EXCHANGE_12_NONZERO_OP)));
532 return (mips_output_sync_loop
533 (MIPS_SYNC_EXCHANGE_12 (MIPS_SYNC_EXCHANGE_12_ZERO_OP)));
535 [(set_attr "length" "28,24")])