OSDN Git Service

PR middle-end/20983
[pf3gnuchains/gcc-fork.git] / gcc / config / alpha / sync.md
1 ;; GCC machine description for Alpha synchronization instructions.
2 ;; Copyright (C) 2005, 2007 Free Software Foundation, Inc.
3 ;;
4 ;; This file is part of GCC.
5 ;;
6 ;; GCC is free software; you can redistribute it and/or modify
7 ;; it under the terms of the GNU General Public License as published by
8 ;; the Free Software Foundation; either version 3, or (at your option)
9 ;; any later version.
10 ;;
11 ;; GCC is distributed in the hope that it will be useful,
12 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 ;; GNU General Public License for more details.
15 ;;
16 ;; You should have received a copy of the GNU General Public License
17 ;; along with GCC; see the file COPYING3.  If not see
18 ;; <http://www.gnu.org/licenses/>.
19
20 (define_code_iterator FETCHOP [plus minus ior xor and])
21 (define_code_attr fetchop_name
22   [(plus "add") (minus "sub") (ior "ior") (xor "xor") (and "and")])
23 (define_code_attr fetchop_pred
24   [(plus "add_operand") (minus "reg_or_8bit_operand")
25    (ior "or_operand") (xor "or_operand") (and "and_operand")])
26 (define_code_attr fetchop_constr
27   [(plus "rKL") (minus "rI") (ior "rIN") (xor "rIN") (and "riNHM")])
28
29
30 (define_expand "memory_barrier"
31   [(set (mem:BLK (match_dup 0))
32         (unspec:BLK [(mem:BLK (match_dup 0))] UNSPEC_MB))]
33   ""
34 {
35   operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (DImode));
36   MEM_VOLATILE_P (operands[0]) = 1;
37 })
38
39 (define_insn "*mb_internal"
40   [(set (match_operand:BLK 0 "" "")
41         (unspec:BLK [(match_operand:BLK 1 "" "")] UNSPEC_MB))]
42   ""
43   "mb"
44   [(set_attr "type" "mb")])
45
46 (define_insn "load_locked_<mode>"
47   [(set (match_operand:I48MODE 0 "register_operand" "=r")
48         (unspec_volatile:I48MODE
49           [(match_operand:I48MODE 1 "memory_operand" "m")]
50           UNSPECV_LL))]
51   ""
52   "ld<modesuffix>_l %0,%1"
53   [(set_attr "type" "ld_l")])
54
55 (define_insn "store_conditional_<mode>"
56   [(set (match_operand:DI 0 "register_operand" "=r")
57         (unspec_volatile:DI [(const_int 0)] UNSPECV_SC))
58    (set (match_operand:I48MODE 1 "memory_operand" "=m")
59         (match_operand:I48MODE 2 "reg_or_0_operand" "0"))]
60   ""
61   "st<modesuffix>_c %0,%1"
62   [(set_attr "type" "st_c")])
63
64 ;; The Alpha Architecture Handbook says that it is UNPREDICTABLE whether
65 ;; the lock is cleared by a TAKEN branch.  If we were to honor that, it
66 ;; would mean that we could not expand a ll/sc sequence until after the
67 ;; final basic-block reordering pass.  Fortunately, it appears that no
68 ;; Alpha implementation ever built actually clears the lock on branches,
69 ;; taken or not.
70
71 (define_insn_and_split "sync_<fetchop_name><mode>"
72   [(set (match_operand:I48MODE 0 "memory_operand" "+m")
73         (unspec:I48MODE
74           [(FETCHOP:I48MODE (match_dup 0)
75              (match_operand:I48MODE 1 "<fetchop_pred>" "<fetchop_constr>"))]
76           UNSPEC_ATOMIC))
77    (clobber (match_scratch:I48MODE 2 "=&r"))]
78   ""
79   "#"
80   "reload_completed"
81   [(const_int 0)]
82 {
83   alpha_split_atomic_op (<CODE>, operands[0], operands[1],
84                          NULL, NULL, operands[2]);
85   DONE;
86 }
87   [(set_attr "type" "multi")])
88
89 (define_insn_and_split "sync_nand<mode>"
90   [(set (match_operand:I48MODE 0 "memory_operand" "+m")
91         (unspec:I48MODE
92           [(and:I48MODE (not:I48MODE (match_dup 0))
93              (match_operand:I48MODE 1 "register_operand" "r"))]
94           UNSPEC_ATOMIC))
95    (clobber (match_scratch:I48MODE 2 "=&r"))]
96   ""
97   "#"
98   "reload_completed"
99   [(const_int 0)]
100 {
101   alpha_split_atomic_op (NOT, operands[0], operands[1],
102                          NULL, NULL, operands[2]);
103   DONE;
104 }
105   [(set_attr "type" "multi")])
106
107 (define_insn_and_split "sync_old_<fetchop_name><mode>"
108   [(set (match_operand:I48MODE 0 "register_operand" "=&r")
109         (match_operand:I48MODE 1 "memory_operand" "+m"))
110    (set (match_dup 1)
111         (unspec:I48MODE
112           [(FETCHOP:I48MODE (match_dup 1)
113              (match_operand:I48MODE 2 "<fetchop_pred>" "<fetchop_constr>"))]
114           UNSPEC_ATOMIC))
115    (clobber (match_scratch:I48MODE 3 "=&r"))]
116   ""
117   "#"
118   "reload_completed"
119   [(const_int 0)]
120 {
121   alpha_split_atomic_op (<CODE>, operands[1], operands[2],
122                          operands[0], NULL, operands[3]);
123   DONE;
124 }
125   [(set_attr "type" "multi")])
126
127 (define_insn_and_split "sync_old_nand<mode>"
128   [(set (match_operand:I48MODE 0 "register_operand" "=&r")
129         (match_operand:I48MODE 1 "memory_operand" "+m"))
130    (set (match_dup 1)
131         (unspec:I48MODE
132           [(and:I48MODE (not:I48MODE (match_dup 1))
133              (match_operand:I48MODE 2 "register_operand" "r"))]
134           UNSPEC_ATOMIC))
135    (clobber (match_scratch:I48MODE 3 "=&r"))]
136   ""
137   "#"
138   "reload_completed"
139   [(const_int 0)]
140 {
141   alpha_split_atomic_op (NOT, operands[1], operands[2],
142                          operands[0], NULL, operands[3]);
143   DONE;
144 }
145   [(set_attr "type" "multi")])
146
147 (define_insn_and_split "sync_new_<fetchop_name><mode>"
148   [(set (match_operand:I48MODE 0 "register_operand" "=&r")
149         (FETCHOP:I48MODE 
150           (match_operand:I48MODE 1 "memory_operand" "+m")
151           (match_operand:I48MODE 2 "<fetchop_pred>" "<fetchop_constr>")))
152    (set (match_dup 1)
153         (unspec:I48MODE
154           [(FETCHOP:I48MODE (match_dup 1) (match_dup 2))]
155           UNSPEC_ATOMIC))
156    (clobber (match_scratch:I48MODE 3 "=&r"))]
157   ""
158   "#"
159   "reload_completed"
160   [(const_int 0)]
161 {
162   alpha_split_atomic_op (<CODE>, operands[1], operands[2],
163                          NULL, operands[0], operands[3]);
164   DONE;
165 }
166   [(set_attr "type" "multi")])
167
168 (define_insn_and_split "sync_new_nand<mode>"
169   [(set (match_operand:I48MODE 0 "register_operand" "=&r")
170         (and:I48MODE 
171           (not:I48MODE (match_operand:I48MODE 1 "memory_operand" "+m"))
172           (match_operand:I48MODE 2 "register_operand" "r")))
173    (set (match_dup 1)
174         (unspec:I48MODE
175           [(and:I48MODE (not:I48MODE (match_dup 1)) (match_dup 2))]
176           UNSPEC_ATOMIC))
177    (clobber (match_scratch:I48MODE 3 "=&r"))]
178   ""
179   "#"
180   "reload_completed"
181   [(const_int 0)]
182 {
183   alpha_split_atomic_op (NOT, operands[1], operands[2],
184                          NULL, operands[0], operands[3]);
185   DONE;
186 }
187   [(set_attr "type" "multi")])
188
189 (define_expand "sync_compare_and_swap<mode>"
190   [(match_operand:I12MODE 0 "register_operand" "")
191    (match_operand:I12MODE 1 "memory_operand" "")
192    (match_operand:I12MODE 2 "register_operand" "")
193    (match_operand:I12MODE 3 "add_operand" "")]
194   ""
195 {
196   alpha_expand_compare_and_swap_12 (operands[0], operands[1],
197                                     operands[2], operands[3]);
198   DONE;
199 })
200
201 (define_insn_and_split "sync_compare_and_swap<mode>_1"
202   [(set (match_operand:DI 0 "register_operand" "=&r,&r")
203         (zero_extend:DI
204           (mem:I12MODE (match_operand:DI 1 "register_operand" "r,r"))))
205    (set (mem:I12MODE (match_dup 1))
206         (unspec:I12MODE
207           [(match_operand:DI 2 "reg_or_8bit_operand" "J,rI")
208            (match_operand:DI 3 "register_operand" "r,r")
209            (match_operand:DI 4 "register_operand" "r,r")]
210           UNSPEC_CMPXCHG))
211    (clobber (match_scratch:DI 5 "=&r,&r"))
212    (clobber (match_scratch:DI 6 "=X,&r"))]
213   ""
214   "#"
215   "reload_completed"
216   [(const_int 0)]
217 {
218   alpha_split_compare_and_swap_12 (<MODE>mode, operands[0], operands[1],
219                                    operands[2], operands[3], operands[4],
220                                    operands[5], operands[6]);
221   DONE;
222 }
223   [(set_attr "type" "multi")])
224
225 (define_expand "sync_compare_and_swap<mode>"
226   [(parallel
227      [(set (match_operand:I48MODE 0 "register_operand" "")
228            (match_operand:I48MODE 1 "memory_operand" ""))
229       (set (match_dup 1)
230            (unspec:I48MODE
231              [(match_operand:I48MODE 2 "reg_or_8bit_operand" "")
232               (match_operand:I48MODE 3 "add_operand" "rKL")]
233              UNSPEC_CMPXCHG))
234       (clobber (match_scratch:I48MODE 4 "=&r"))])]
235   ""
236 {
237   if (<MODE>mode == SImode)
238     operands[2] = convert_modes (DImode, SImode, operands[2], 0);
239 })
240
241 (define_insn_and_split "*sync_compare_and_swap<mode>"
242   [(set (match_operand:I48MODE 0 "register_operand" "=&r")
243         (match_operand:I48MODE 1 "memory_operand" "+m"))
244    (set (match_dup 1)
245         (unspec:I48MODE
246           [(match_operand:DI 2 "reg_or_8bit_operand" "rI")
247            (match_operand:I48MODE 3 "add_operand" "rKL")]
248           UNSPEC_CMPXCHG))
249    (clobber (match_scratch:I48MODE 4 "=&r"))]
250   ""
251   "#"
252   "reload_completed"
253   [(const_int 0)]
254 {
255   alpha_split_compare_and_swap (operands[0], operands[1], operands[2],
256                                 operands[3], operands[4]);
257   DONE;
258 }
259   [(set_attr "type" "multi")])
260
261 (define_expand "sync_lock_test_and_set<mode>"
262   [(match_operand:I12MODE 0 "register_operand" "")
263    (match_operand:I12MODE 1 "memory_operand" "")
264    (match_operand:I12MODE 2 "register_operand" "")]
265   ""
266 {
267   alpha_expand_lock_test_and_set_12 (operands[0], operands[1], operands[2]);
268   DONE;
269 })
270
271 (define_insn_and_split "sync_lock_test_and_set<mode>_1"
272   [(set (match_operand:DI 0 "register_operand" "=&r")
273         (zero_extend:DI
274           (mem:I12MODE (match_operand:DI 1 "register_operand" "r"))))
275    (set (mem:I12MODE (match_dup 1))
276         (unspec:I12MODE
277           [(match_operand:DI 2 "reg_or_8bit_operand" "rI")
278            (match_operand:DI 3 "register_operand" "r")]
279           UNSPEC_XCHG))
280    (clobber (match_scratch:DI 4 "=&r"))]
281   ""
282   "#"
283   "reload_completed"
284   [(const_int 0)]
285 {
286   alpha_split_lock_test_and_set_12 (<MODE>mode, operands[0], operands[1],
287                                     operands[2], operands[3], operands[4]);
288   DONE;
289 }
290   [(set_attr "type" "multi")])
291
292 (define_insn_and_split "sync_lock_test_and_set<mode>"
293   [(set (match_operand:I48MODE 0 "register_operand" "=&r")
294         (match_operand:I48MODE 1 "memory_operand" "+m"))
295    (set (match_dup 1)
296         (unspec:I48MODE
297           [(match_operand:I48MODE 2 "add_operand" "rKL")]
298           UNSPEC_XCHG))
299    (clobber (match_scratch:I48MODE 3 "=&r"))]
300   ""
301   "#"
302   "reload_completed"
303   [(const_int 0)]
304 {
305   alpha_split_lock_test_and_set (operands[0], operands[1],
306                                  operands[2], operands[3]);
307   DONE;
308 }
309   [(set_attr "type" "multi")])