OSDN Git Service

r383@cf-ppc-macosx: monabuilder | 2008-12-23 16:04:56 +0900
[pf3gnuchains/pf3gnuchains3x.git] / gcc / config / mips / sync.md
1 ;;  Machine Description for MIPS based processor synchronization
2 ;;  instructions.
3 ;;  Copyright (C) 2007, 2008
4 ;;  Free Software Foundation, Inc.
5
6 ;; This file is part of GCC.
7
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)
11 ;; any later version.
12
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.
17
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/>.
21
22 ;; Atomic fetch bitwise operations.
23 (define_code_iterator fetchop_bit [ior xor and])
24
25 ;; Atomic HI and QI operations
26 (define_code_iterator atomic_hiqi_op [plus minus ior xor and])
27
28 ;; Atomic memory operations.
29
30 (define_insn "memory_barrier"
31   [(set (mem:BLK (scratch))
32         (unspec:BLK [(const_int 0)] UNSPEC_MEMORY_BARRIER))]
33   "GENERATE_SYNC"
34   "%|sync%-")
35
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"))
39    (set (match_dup 1)
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))]
43   "GENERATE_LL_SC"
44 {
45   if (which_alternative == 0)
46     return mips_output_sync_loop (MIPS_COMPARE_AND_SWAP ("<d>", "li"));
47   else
48     return mips_output_sync_loop (MIPS_COMPARE_AND_SWAP ("<d>", "move"));
49 }
50   [(set_attr "length" "32")])
51
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")]
57   "GENERATE_LL_SC"
58 {
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]);
63   DONE;
64 })
65
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"))
70    (set (match_dup 1)
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))]
76   "GENERATE_LL_SC"
77 {
78   if (which_alternative == 0)
79     return (mips_output_sync_loop
80             (MIPS_COMPARE_AND_SWAP_12 (MIPS_COMPARE_AND_SWAP_12_NONZERO_OP)));
81   else
82     return (mips_output_sync_loop
83             (MIPS_COMPARE_AND_SWAP_12 (MIPS_COMPARE_AND_SWAP_12_ZERO_OP)));
84 }
85   [(set_attr "length" "40,36")])
86
87 (define_insn "sync_add<mode>"
88   [(set (match_operand:GPR 0 "memory_operand" "+R,R")
89         (unspec_volatile:GPR
90           [(plus:GPR (match_dup 0)
91                      (match_operand:GPR 1 "arith_operand" "I,d"))]
92           UNSPEC_SYNC_OLD_OP))]
93   "GENERATE_LL_SC"
94 {
95   if (which_alternative == 0)
96     return mips_output_sync_loop (MIPS_SYNC_OP ("<d>", "<d>addiu"));
97   else
98     return mips_output_sync_loop (MIPS_SYNC_OP ("<d>", "<d>addu"));
99 }
100   [(set_attr "length" "28")])
101
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))]
108   "GENERATE_LL_SC"
109 {
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);
114   DONE;
115 })
116
117 ;; Helper insn for sync_<optab><mode>
118 (define_insn "sync_<optab>_12"
119   [(set (match_operand:SI 0 "memory_operand" "+R")
120         (unspec_volatile:SI
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"))]
127   "GENERATE_LL_SC"
128 {
129     return (mips_output_sync_loop
130             (MIPS_SYNC_OP_12 ("<insn>", MIPS_SYNC_OP_12_AND)));
131 }
132   [(set_attr "length" "40")])
133
134 (define_expand "sync_old_<optab><mode>"
135   [(parallel [
136      (set (match_operand:SHORT 0 "register_operand")
137           (match_operand:SHORT 1 "memory_operand"))
138      (set (match_dup 1)
139           (unspec_volatile:SHORT [(atomic_hiqi_op:SHORT
140                                     (match_dup 1)
141                                     (match_operand:SHORT 2 "general_operand"))]
142             UNSPEC_SYNC_OLD_OP))])]
143   "GENERATE_LL_SC"
144 {
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);
149   DONE;
150 })
151
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"))
156    (set (match_dup 1)
157         (unspec_volatile:SI
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"))]
164   "GENERATE_LL_SC"
165 {
166     return (mips_output_sync_loop
167             (MIPS_SYNC_OLD_OP_12 ("<insn>", MIPS_SYNC_OLD_OP_12_AND)));
168 }
169   [(set_attr "length" "40")])
170
171 (define_expand "sync_new_<optab><mode>"
172   [(parallel [
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"))]
177             UNSPEC_SYNC_NEW_OP))
178      (set (match_dup 1)
179           (unspec_volatile:SHORT [(match_dup 1) (match_dup 2)]
180             UNSPEC_SYNC_NEW_OP))])]
181   "GENERATE_LL_SC"
182 {
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);
187   DONE;
188 })
189
190 ;; Helper insn for sync_new_<optab><mode>
191 (define_insn "sync_new_<optab>_12"
192   [(set (match_operand:SI 0 "register_operand" "=&d")
193         (unspec_volatile:SI
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))
200    (set (match_dup 1)
201         (unspec_volatile:SI
202           [(match_dup 1)
203            (match_dup 2)
204            (match_dup 3)
205            (match_dup 4)] UNSPEC_SYNC_NEW_OP_12))]
206   "GENERATE_LL_SC"
207 {
208     return (mips_output_sync_loop
209             (MIPS_SYNC_NEW_OP_12 ("<insn>", MIPS_SYNC_NEW_OP_12_AND)));
210 }
211   [(set_attr "length" "40")])
212
213 (define_expand "sync_nand<mode>"
214   [(set (match_operand:SHORT 0 "memory_operand")
215         (unspec_volatile:SHORT
216           [(match_dup 0)
217            (match_operand:SHORT 1 "general_operand")]
218           UNSPEC_SYNC_OLD_OP))]
219   "GENERATE_LL_SC"
220 {
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);
225   DONE;
226 })
227
228 ;; Helper insn for sync_nand<mode>
229 (define_insn "sync_nand_12"
230   [(set (match_operand:SI 0 "memory_operand" "+R")
231         (unspec_volatile:SI
232           [(match_operand:SI 1 "register_operand" "d")
233            (match_operand:SI 2 "register_operand" "d")
234            (match_dup 0)
235            (match_operand:SI 3 "register_operand" "dJ")]
236           UNSPEC_SYNC_OLD_OP_12))
237    (clobber (match_scratch:SI 4 "=&d"))]
238   "GENERATE_LL_SC"
239 {
240     return (mips_output_sync_loop
241             (MIPS_SYNC_OP_12 ("and", MIPS_SYNC_OP_12_XOR)));
242 }
243   [(set_attr "length" "40")])
244
245 (define_expand "sync_old_nand<mode>"
246   [(parallel [
247      (set (match_operand:SHORT 0 "register_operand")
248           (match_operand:SHORT 1 "memory_operand"))
249      (set (match_dup 1)
250           (unspec_volatile:SHORT [(match_dup 1)
251                                   (match_operand:SHORT 2 "general_operand")]
252             UNSPEC_SYNC_OLD_OP))])]
253   "GENERATE_LL_SC"
254 {
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);
259   DONE;
260 })
261
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"))
266    (set (match_dup 1)
267         (unspec_volatile:SI
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"))]
273   "GENERATE_LL_SC"
274 {
275     return (mips_output_sync_loop
276             (MIPS_SYNC_OLD_OP_12 ("and", MIPS_SYNC_OLD_OP_12_XOR)));
277 }
278   [(set_attr "length" "40")])
279
280 (define_expand "sync_new_nand<mode>"
281   [(parallel [
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")]
285             UNSPEC_SYNC_NEW_OP))
286      (set (match_dup 1)
287           (unspec_volatile:SHORT [(match_dup 1) (match_dup 2)]
288             UNSPEC_SYNC_NEW_OP))])]
289   "GENERATE_LL_SC"
290 {
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);
295   DONE;
296 })
297
298 ;; Helper insn for sync_new_nand<mode>
299 (define_insn "sync_new_nand_12"
300   [(set (match_operand:SI 0 "register_operand" "=&d")
301         (unspec_volatile:SI
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))
307    (set (match_dup 1)
308         (unspec_volatile:SI
309           [(match_dup 1)
310            (match_dup 2)
311            (match_dup 3)
312            (match_dup 4)] UNSPEC_SYNC_NEW_OP_12))]
313   "GENERATE_LL_SC"
314 {
315     return (mips_output_sync_loop
316             (MIPS_SYNC_NEW_OP_12 ("and", MIPS_SYNC_NEW_OP_12_XOR)));
317 }
318   [(set_attr "length" "40")])
319
320 (define_insn "sync_sub<mode>"
321   [(set (match_operand:GPR 0 "memory_operand" "+R")
322         (unspec_volatile:GPR
323           [(minus:GPR (match_dup 0)
324                               (match_operand:GPR 1 "register_operand" "d"))]
325          UNSPEC_SYNC_OLD_OP))]
326   "GENERATE_LL_SC"
327 {
328   return mips_output_sync_loop (MIPS_SYNC_OP ("<d>", "<d>subu"));
329 }
330   [(set_attr "length" "28")])
331
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"))
335    (set (match_dup 1)
336         (unspec_volatile:GPR
337           [(plus:GPR (match_dup 1)
338                      (match_operand:GPR 2 "arith_operand" "I,d"))]
339          UNSPEC_SYNC_OLD_OP))]
340   "GENERATE_LL_SC"
341 {
342   if (which_alternative == 0)
343     return mips_output_sync_loop (MIPS_SYNC_OLD_OP ("<d>", "<d>addiu"));
344   else
345     return mips_output_sync_loop (MIPS_SYNC_OLD_OP ("<d>", "<d>addu"));
346 }
347   [(set_attr "length" "28")])
348
349 (define_insn "sync_old_sub<mode>"
350   [(set (match_operand:GPR 0 "register_operand" "=&d")
351         (match_operand:GPR 1 "memory_operand" "+R"))
352    (set (match_dup 1)
353         (unspec_volatile:GPR
354           [(minus:GPR (match_dup 1)
355                       (match_operand:GPR 2 "register_operand" "d"))]
356          UNSPEC_SYNC_OLD_OP))]
357   "GENERATE_LL_SC"
358 {
359   return mips_output_sync_loop (MIPS_SYNC_OLD_OP ("<d>", "<d>subu"));
360 }
361   [(set_attr "length" "28")])
362
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")))
367    (set (match_dup 1)
368         (unspec_volatile:GPR
369           [(plus:GPR (match_dup 1) (match_dup 2))]
370          UNSPEC_SYNC_NEW_OP))]
371   "GENERATE_LL_SC"
372 {
373   if (which_alternative == 0)
374     return mips_output_sync_loop (MIPS_SYNC_NEW_OP ("<d>", "<d>addiu"));
375   else
376     return mips_output_sync_loop (MIPS_SYNC_NEW_OP ("<d>", "<d>addu"));
377 }
378   [(set_attr "length" "28")])
379
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")))
384    (set (match_dup 1)
385         (unspec_volatile:GPR
386           [(minus:GPR (match_dup 1) (match_dup 2))]
387          UNSPEC_SYNC_NEW_OP))]
388   "GENERATE_LL_SC"
389 {
390   return mips_output_sync_loop (MIPS_SYNC_NEW_OP ("<d>", "<d>subu"));
391 }
392   [(set_attr "length" "28")])
393
394 (define_insn "sync_<optab><mode>"
395   [(set (match_operand:GPR 0 "memory_operand" "+R,R")
396         (unspec_volatile:GPR
397           [(fetchop_bit:GPR (match_operand:GPR 1 "uns_arith_operand" "K,d")
398                               (match_dup 0))]
399          UNSPEC_SYNC_OLD_OP))]
400   "GENERATE_LL_SC"
401 {
402   if (which_alternative == 0)
403     return mips_output_sync_loop (MIPS_SYNC_OP ("<d>", "<immediate_insn>"));
404   else
405     return mips_output_sync_loop (MIPS_SYNC_OP ("<d>", "<insn>"));
406 }
407   [(set_attr "length" "28")])
408
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"))
412    (set (match_dup 1)
413         (unspec_volatile:GPR
414           [(fetchop_bit:GPR (match_operand:GPR 2 "uns_arith_operand" "K,d")
415                             (match_dup 1))]
416          UNSPEC_SYNC_OLD_OP))]
417   "GENERATE_LL_SC"
418 {
419   if (which_alternative == 0)
420     return (mips_output_sync_loop
421             (MIPS_SYNC_OLD_OP ("<d>", "<immediate_insn>")));
422   else
423     return mips_output_sync_loop (MIPS_SYNC_OLD_OP ("<d>", "<insn>"));
424 }
425   [(set_attr "length" "28")])
426
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"))
430    (set (match_dup 1)
431         (unspec_volatile:GPR
432           [(fetchop_bit:GPR (match_operand:GPR 2 "uns_arith_operand" "K,d")
433                             (match_dup 1))]
434          UNSPEC_SYNC_NEW_OP))]
435   "GENERATE_LL_SC"
436 {
437   if (which_alternative == 0)
438     return (mips_output_sync_loop
439             (MIPS_SYNC_NEW_OP ("<d>", "<immediate_insn>")));
440   else
441     return mips_output_sync_loop (MIPS_SYNC_NEW_OP ("<d>", "<insn>"));
442 }
443   [(set_attr "length" "28")])
444
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))]
449   "GENERATE_LL_SC"
450 {
451   if (which_alternative == 0)
452     return mips_output_sync_loop (MIPS_SYNC_NAND ("<d>", "andi"));
453   else
454     return mips_output_sync_loop (MIPS_SYNC_NAND ("<d>", "and"));
455 }
456   [(set_attr "length" "32")])
457
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"))
461    (set (match_dup 1)
462         (unspec_volatile:GPR [(match_operand:GPR 2 "uns_arith_operand" "K,d")]
463          UNSPEC_SYNC_OLD_OP))]
464   "GENERATE_LL_SC"
465 {
466   if (which_alternative == 0)
467     return mips_output_sync_loop (MIPS_SYNC_OLD_NAND ("<d>", "andi"));
468   else
469     return mips_output_sync_loop (MIPS_SYNC_OLD_NAND ("<d>", "and"));
470 }
471   [(set_attr "length" "32")])
472
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"))
476    (set (match_dup 1)
477         (unspec_volatile:GPR [(match_operand:GPR 2 "uns_arith_operand" "K,d")]
478          UNSPEC_SYNC_NEW_OP))]
479   "GENERATE_LL_SC"
480 {
481   if (which_alternative == 0)
482     return mips_output_sync_loop (MIPS_SYNC_NEW_NAND ("<d>", "andi"));
483   else
484     return mips_output_sync_loop (MIPS_SYNC_NEW_NAND ("<d>", "and"));
485 }
486   [(set_attr "length" "32")])
487
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"))
491    (set (match_dup 1)
492         (unspec_volatile:GPR [(match_operand:GPR 2 "arith_operand" "I,d")]
493          UNSPEC_SYNC_EXCHANGE))]
494   "GENERATE_LL_SC"
495 {
496   if (which_alternative == 0)
497     return mips_output_sync_loop (MIPS_SYNC_EXCHANGE ("<d>", "li"));
498   else
499     return mips_output_sync_loop (MIPS_SYNC_EXCHANGE ("<d>", "move"));
500 }
501   [(set_attr "length" "24")])
502
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")]
507   "GENERATE_LL_SC"
508 {
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);
513   DONE;
514 })
515
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"))
519    (set (match_dup 1)
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))]
524   "GENERATE_LL_SC"
525 {
526   if (which_alternative == 0)
527     return (mips_output_sync_loop
528             (MIPS_SYNC_EXCHANGE_12 (MIPS_SYNC_EXCHANGE_12_NONZERO_OP)));
529   else
530     return (mips_output_sync_loop
531             (MIPS_SYNC_EXCHANGE_12 (MIPS_SYNC_EXCHANGE_12_ZERO_OP)));
532 }
533   [(set_attr "length" "28,24")])