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_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 "*mb_internal"
40 [(set (match_operand:BLK 0 "" "")
41 (unspec:BLK [(match_dup 0)] UNSPEC_MEMORY_BARRIER))]
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))]
54 if (which_alternative == 0)
55 return mips_output_sync_loop (MIPS_COMPARE_AND_SWAP ("<d>", "li"));
57 return mips_output_sync_loop (MIPS_COMPARE_AND_SWAP ("<d>", "move"));
59 [(set_attr "length" "32")])
61 (define_expand "sync_compare_and_swap<mode>"
62 [(match_operand:SHORT 0 "register_operand")
63 (match_operand:SHORT 1 "memory_operand")
64 (match_operand:SHORT 2 "general_operand")
65 (match_operand:SHORT 3 "general_operand")]
68 union mips_gen_fn_ptrs generator;
69 generator.fn_6 = gen_compare_and_swap_12;
70 mips_expand_atomic_qihi (generator,
71 operands[0], operands[1], operands[2], operands[3]);
75 ;; Helper insn for mips_expand_atomic_qihi.
76 (define_insn "compare_and_swap_12"
77 [(set (match_operand:SI 0 "register_operand" "=&d,&d")
78 (match_operand:SI 1 "memory_operand" "+R,R"))
80 (unspec_volatile:SI [(match_operand:SI 2 "register_operand" "d,d")
81 (match_operand:SI 3 "register_operand" "d,d")
82 (match_operand:SI 4 "reg_or_0_operand" "dJ,dJ")
83 (match_operand:SI 5 "reg_or_0_operand" "d,J")]
84 UNSPEC_COMPARE_AND_SWAP_12))]
87 if (which_alternative == 0)
88 return (mips_output_sync_loop
89 (MIPS_COMPARE_AND_SWAP_12 (MIPS_COMPARE_AND_SWAP_12_NONZERO_OP)));
91 return (mips_output_sync_loop
92 (MIPS_COMPARE_AND_SWAP_12 (MIPS_COMPARE_AND_SWAP_12_ZERO_OP)));
94 [(set_attr "length" "40,36")])
96 (define_insn "sync_add<mode>"
97 [(set (match_operand:GPR 0 "memory_operand" "+R,R")
99 [(plus:GPR (match_dup 0)
100 (match_operand:GPR 1 "arith_operand" "I,d"))]
101 UNSPEC_SYNC_OLD_OP))]
104 if (which_alternative == 0)
105 return mips_output_sync_loop (MIPS_SYNC_OP ("<d>", "<d>addiu"));
107 return mips_output_sync_loop (MIPS_SYNC_OP ("<d>", "<d>addu"));
109 [(set_attr "length" "28")])
111 (define_expand "sync_<optab><mode>"
112 [(set (match_operand:SHORT 0 "memory_operand")
113 (unspec_volatile:SHORT
114 [(atomic_hiqi_op:SHORT (match_dup 0)
115 (match_operand:SHORT 1 "general_operand"))]
116 UNSPEC_SYNC_OLD_OP))]
119 union mips_gen_fn_ptrs generator;
120 generator.fn_4 = gen_sync_<optab>_12;
121 mips_expand_atomic_qihi (generator,
122 NULL, operands[0], operands[1], NULL);
126 ;; Helper insn for sync_<optab><mode>
127 (define_insn "sync_<optab>_12"
128 [(set (match_operand:SI 0 "memory_operand" "+R")
130 [(match_operand:SI 1 "register_operand" "d")
131 (match_operand:SI 2 "register_operand" "d")
132 (atomic_hiqi_op:SI (match_dup 0)
133 (match_operand:SI 3 "register_operand" "dJ"))]
134 UNSPEC_SYNC_OLD_OP_12))
135 (clobber (match_scratch:SI 4 "=&d"))]
138 return (mips_output_sync_loop
139 (MIPS_SYNC_OP_12 ("<insn>", MIPS_SYNC_OP_12_AND)));
141 [(set_attr "length" "40")])
143 (define_expand "sync_old_<optab><mode>"
145 (set (match_operand:SHORT 0 "register_operand")
146 (match_operand:SHORT 1 "memory_operand"))
148 (unspec_volatile:SHORT [(atomic_hiqi_op:SHORT
150 (match_operand:SHORT 2 "general_operand"))]
151 UNSPEC_SYNC_OLD_OP))])]
154 union mips_gen_fn_ptrs generator;
155 generator.fn_5 = gen_sync_old_<optab>_12;
156 mips_expand_atomic_qihi (generator,
157 operands[0], operands[1], operands[2], NULL);
161 ;; Helper insn for sync_old_<optab><mode>
162 (define_insn "sync_old_<optab>_12"
163 [(set (match_operand:SI 0 "register_operand" "=&d")
164 (match_operand:SI 1 "memory_operand" "+R"))
167 [(match_operand:SI 2 "register_operand" "d")
168 (match_operand:SI 3 "register_operand" "d")
169 (atomic_hiqi_op:SI (match_dup 0)
170 (match_operand:SI 4 "register_operand" "dJ"))]
171 UNSPEC_SYNC_OLD_OP_12))
172 (clobber (match_scratch:SI 5 "=&d"))]
175 return (mips_output_sync_loop
176 (MIPS_SYNC_OLD_OP_12 ("<insn>", MIPS_SYNC_OLD_OP_12_AND)));
178 [(set_attr "length" "40")])
180 (define_expand "sync_new_<optab><mode>"
182 (set (match_operand:SHORT 0 "register_operand")
183 (unspec_volatile:SHORT [(atomic_hiqi_op:SHORT
184 (match_operand:SHORT 1 "memory_operand")
185 (match_operand:SHORT 2 "general_operand"))]
188 (unspec_volatile:SHORT [(match_dup 1) (match_dup 2)]
189 UNSPEC_SYNC_NEW_OP))])]
192 union mips_gen_fn_ptrs generator;
193 generator.fn_5 = gen_sync_new_<optab>_12;
194 mips_expand_atomic_qihi (generator,
195 operands[0], operands[1], operands[2], NULL);
199 ;; Helper insn for sync_new_<optab><mode>
200 (define_insn "sync_new_<optab>_12"
201 [(set (match_operand:SI 0 "register_operand" "=&d")
203 [(match_operand:SI 1 "memory_operand" "+R")
204 (match_operand:SI 2 "register_operand" "d")
205 (match_operand:SI 3 "register_operand" "d")
206 (atomic_hiqi_op:SI (match_dup 0)
207 (match_operand:SI 4 "register_operand" "dJ"))]
208 UNSPEC_SYNC_NEW_OP_12))
214 (match_dup 4)] UNSPEC_SYNC_NEW_OP_12))]
217 return (mips_output_sync_loop
218 (MIPS_SYNC_NEW_OP_12 ("<insn>", MIPS_SYNC_NEW_OP_12_AND)));
220 [(set_attr "length" "40")])
222 (define_expand "sync_nand<mode>"
223 [(set (match_operand:SHORT 0 "memory_operand")
224 (unspec_volatile:SHORT
226 (match_operand:SHORT 1 "general_operand")]
227 UNSPEC_SYNC_OLD_OP))]
230 union mips_gen_fn_ptrs generator;
231 generator.fn_4 = gen_sync_nand_12;
232 mips_expand_atomic_qihi (generator,
233 NULL, operands[0], operands[1], NULL);
237 ;; Helper insn for sync_nand<mode>
238 (define_insn "sync_nand_12"
239 [(set (match_operand:SI 0 "memory_operand" "+R")
241 [(match_operand:SI 1 "register_operand" "d")
242 (match_operand:SI 2 "register_operand" "d")
244 (match_operand:SI 3 "register_operand" "dJ")]
245 UNSPEC_SYNC_OLD_OP_12))
246 (clobber (match_scratch:SI 4 "=&d"))]
249 return (mips_output_sync_loop
250 (MIPS_SYNC_OP_12 ("and", MIPS_SYNC_OP_12_XOR)));
252 [(set_attr "length" "40")])
254 (define_expand "sync_old_nand<mode>"
256 (set (match_operand:SHORT 0 "register_operand")
257 (match_operand:SHORT 1 "memory_operand"))
259 (unspec_volatile:SHORT [(match_dup 1)
260 (match_operand:SHORT 2 "general_operand")]
261 UNSPEC_SYNC_OLD_OP))])]
264 union mips_gen_fn_ptrs generator;
265 generator.fn_5 = gen_sync_old_nand_12;
266 mips_expand_atomic_qihi (generator,
267 operands[0], operands[1], operands[2], NULL);
271 ;; Helper insn for sync_old_nand<mode>
272 (define_insn "sync_old_nand_12"
273 [(set (match_operand:SI 0 "register_operand" "=&d")
274 (match_operand:SI 1 "memory_operand" "+R"))
277 [(match_operand:SI 2 "register_operand" "d")
278 (match_operand:SI 3 "register_operand" "d")
279 (match_operand:SI 4 "register_operand" "dJ")]
280 UNSPEC_SYNC_OLD_OP_12))
281 (clobber (match_scratch:SI 5 "=&d"))]
284 return (mips_output_sync_loop
285 (MIPS_SYNC_OLD_OP_12 ("and", MIPS_SYNC_OLD_OP_12_XOR)));
287 [(set_attr "length" "40")])
289 (define_expand "sync_new_nand<mode>"
291 (set (match_operand:SHORT 0 "register_operand")
292 (unspec_volatile:SHORT [(match_operand:SHORT 1 "memory_operand")
293 (match_operand:SHORT 2 "general_operand")]
296 (unspec_volatile:SHORT [(match_dup 1) (match_dup 2)]
297 UNSPEC_SYNC_NEW_OP))])]
300 union mips_gen_fn_ptrs generator;
301 generator.fn_5 = gen_sync_new_nand_12;
302 mips_expand_atomic_qihi (generator,
303 operands[0], operands[1], operands[2], NULL);
307 ;; Helper insn for sync_new_nand<mode>
308 (define_insn "sync_new_nand_12"
309 [(set (match_operand:SI 0 "register_operand" "=&d")
311 [(match_operand:SI 1 "memory_operand" "+R")
312 (match_operand:SI 2 "register_operand" "d")
313 (match_operand:SI 3 "register_operand" "d")
314 (match_operand:SI 4 "register_operand" "dJ")]
315 UNSPEC_SYNC_NEW_OP_12))
321 (match_dup 4)] UNSPEC_SYNC_NEW_OP_12))]
324 return (mips_output_sync_loop
325 (MIPS_SYNC_NEW_OP_12 ("and", MIPS_SYNC_NEW_OP_12_XOR)));
327 [(set_attr "length" "40")])
329 (define_insn "sync_sub<mode>"
330 [(set (match_operand:GPR 0 "memory_operand" "+R")
332 [(minus:GPR (match_dup 0)
333 (match_operand:GPR 1 "register_operand" "d"))]
334 UNSPEC_SYNC_OLD_OP))]
337 return mips_output_sync_loop (MIPS_SYNC_OP ("<d>", "<d>subu"));
339 [(set_attr "length" "28")])
341 (define_insn "sync_old_add<mode>"
342 [(set (match_operand:GPR 0 "register_operand" "=&d,&d")
343 (match_operand:GPR 1 "memory_operand" "+R,R"))
346 [(plus:GPR (match_dup 1)
347 (match_operand:GPR 2 "arith_operand" "I,d"))]
348 UNSPEC_SYNC_OLD_OP))]
351 if (which_alternative == 0)
352 return mips_output_sync_loop (MIPS_SYNC_OLD_OP ("<d>", "<d>addiu"));
354 return mips_output_sync_loop (MIPS_SYNC_OLD_OP ("<d>", "<d>addu"));
356 [(set_attr "length" "28")])
358 (define_insn "sync_old_sub<mode>"
359 [(set (match_operand:GPR 0 "register_operand" "=&d")
360 (match_operand:GPR 1 "memory_operand" "+R"))
363 [(minus:GPR (match_dup 1)
364 (match_operand:GPR 2 "register_operand" "d"))]
365 UNSPEC_SYNC_OLD_OP))]
368 return mips_output_sync_loop (MIPS_SYNC_OLD_OP ("<d>", "<d>subu"));
370 [(set_attr "length" "28")])
372 (define_insn "sync_new_add<mode>"
373 [(set (match_operand:GPR 0 "register_operand" "=&d,&d")
374 (plus:GPR (match_operand:GPR 1 "memory_operand" "+R,R")
375 (match_operand:GPR 2 "arith_operand" "I,d")))
378 [(plus:GPR (match_dup 1) (match_dup 2))]
379 UNSPEC_SYNC_NEW_OP))]
382 if (which_alternative == 0)
383 return mips_output_sync_loop (MIPS_SYNC_NEW_OP ("<d>", "<d>addiu"));
385 return mips_output_sync_loop (MIPS_SYNC_NEW_OP ("<d>", "<d>addu"));
387 [(set_attr "length" "28")])
389 (define_insn "sync_new_sub<mode>"
390 [(set (match_operand:GPR 0 "register_operand" "=&d")
391 (minus:GPR (match_operand:GPR 1 "memory_operand" "+R")
392 (match_operand:GPR 2 "register_operand" "d")))
395 [(minus:GPR (match_dup 1) (match_dup 2))]
396 UNSPEC_SYNC_NEW_OP))]
399 return mips_output_sync_loop (MIPS_SYNC_NEW_OP ("<d>", "<d>subu"));
401 [(set_attr "length" "28")])
403 (define_insn "sync_<optab><mode>"
404 [(set (match_operand:GPR 0 "memory_operand" "+R,R")
406 [(fetchop_bit:GPR (match_operand:GPR 1 "uns_arith_operand" "K,d")
408 UNSPEC_SYNC_OLD_OP))]
411 if (which_alternative == 0)
412 return mips_output_sync_loop (MIPS_SYNC_OP ("<d>", "<immediate_insn>"));
414 return mips_output_sync_loop (MIPS_SYNC_OP ("<d>", "<insn>"));
416 [(set_attr "length" "28")])
418 (define_insn "sync_old_<optab><mode>"
419 [(set (match_operand:GPR 0 "register_operand" "=&d,&d")
420 (match_operand:GPR 1 "memory_operand" "+R,R"))
423 [(fetchop_bit:GPR (match_operand:GPR 2 "uns_arith_operand" "K,d")
425 UNSPEC_SYNC_OLD_OP))]
428 if (which_alternative == 0)
429 return (mips_output_sync_loop
430 (MIPS_SYNC_OLD_OP ("<d>", "<immediate_insn>")));
432 return mips_output_sync_loop (MIPS_SYNC_OLD_OP ("<d>", "<insn>"));
434 [(set_attr "length" "28")])
436 (define_insn "sync_new_<optab><mode>"
437 [(set (match_operand:GPR 0 "register_operand" "=&d,&d")
438 (match_operand:GPR 1 "memory_operand" "+R,R"))
441 [(fetchop_bit:GPR (match_operand:GPR 2 "uns_arith_operand" "K,d")
443 UNSPEC_SYNC_NEW_OP))]
446 if (which_alternative == 0)
447 return (mips_output_sync_loop
448 (MIPS_SYNC_NEW_OP ("<d>", "<immediate_insn>")));
450 return mips_output_sync_loop (MIPS_SYNC_NEW_OP ("<d>", "<insn>"));
452 [(set_attr "length" "28")])
454 (define_insn "sync_nand<mode>"
455 [(set (match_operand:GPR 0 "memory_operand" "+R,R")
456 (unspec_volatile:GPR [(match_operand:GPR 1 "uns_arith_operand" "K,d")]
457 UNSPEC_SYNC_OLD_OP))]
460 if (which_alternative == 0)
461 return mips_output_sync_loop (MIPS_SYNC_NAND ("<d>", "andi"));
463 return mips_output_sync_loop (MIPS_SYNC_NAND ("<d>", "and"));
465 [(set_attr "length" "32")])
467 (define_insn "sync_old_nand<mode>"
468 [(set (match_operand:GPR 0 "register_operand" "=&d,&d")
469 (match_operand:GPR 1 "memory_operand" "+R,R"))
471 (unspec_volatile:GPR [(match_operand:GPR 2 "uns_arith_operand" "K,d")]
472 UNSPEC_SYNC_OLD_OP))]
475 if (which_alternative == 0)
476 return mips_output_sync_loop (MIPS_SYNC_OLD_NAND ("<d>", "andi"));
478 return mips_output_sync_loop (MIPS_SYNC_OLD_NAND ("<d>", "and"));
480 [(set_attr "length" "32")])
482 (define_insn "sync_new_nand<mode>"
483 [(set (match_operand:GPR 0 "register_operand" "=&d,&d")
484 (match_operand:GPR 1 "memory_operand" "+R,R"))
486 (unspec_volatile:GPR [(match_operand:GPR 2 "uns_arith_operand" "K,d")]
487 UNSPEC_SYNC_NEW_OP))]
490 if (which_alternative == 0)
491 return mips_output_sync_loop (MIPS_SYNC_NEW_NAND ("<d>", "andi"));
493 return mips_output_sync_loop (MIPS_SYNC_NEW_NAND ("<d>", "and"));
495 [(set_attr "length" "32")])
497 (define_insn "sync_lock_test_and_set<mode>"
498 [(set (match_operand:GPR 0 "register_operand" "=&d,&d")
499 (match_operand:GPR 1 "memory_operand" "+R,R"))
501 (unspec_volatile:GPR [(match_operand:GPR 2 "arith_operand" "I,d")]
502 UNSPEC_SYNC_EXCHANGE))]
505 if (which_alternative == 0)
506 return mips_output_sync_loop (MIPS_SYNC_EXCHANGE ("<d>", "li"));
508 return mips_output_sync_loop (MIPS_SYNC_EXCHANGE ("<d>", "move"));
510 [(set_attr "length" "24")])
512 (define_expand "sync_lock_test_and_set<mode>"
513 [(match_operand:SHORT 0 "register_operand")
514 (match_operand:SHORT 1 "memory_operand")
515 (match_operand:SHORT 2 "general_operand")]
518 union mips_gen_fn_ptrs generator;
519 generator.fn_5 = gen_test_and_set_12;
520 mips_expand_atomic_qihi (generator,
521 operands[0], operands[1], operands[2], NULL);
525 (define_insn "test_and_set_12"
526 [(set (match_operand:SI 0 "register_operand" "=&d,&d")
527 (match_operand:SI 1 "memory_operand" "+R,R"))
529 (unspec_volatile:SI [(match_operand:SI 2 "register_operand" "d,d")
530 (match_operand:SI 3 "register_operand" "d,d")
531 (match_operand:SI 4 "arith_operand" "d,J")]
532 UNSPEC_SYNC_EXCHANGE_12))]
535 if (which_alternative == 0)
536 return (mips_output_sync_loop
537 (MIPS_SYNC_EXCHANGE_12 (MIPS_SYNC_EXCHANGE_12_NONZERO_OP)));
539 return (mips_output_sync_loop
540 (MIPS_SYNC_EXCHANGE_12 (MIPS_SYNC_EXCHANGE_12_ZERO_OP)));
542 [(set_attr "length" "28,24")])