OSDN Git Service

fe8301f344b4a65be85bb6b83b03384b0c9834b4
[pf3gnuchains/pf3gnuchains3x.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           [(not:I48MODE
93              (and:I48MODE (match_dup 0)
94                (match_operand:I48MODE 1 "register_operand" "r")))]
95           UNSPEC_ATOMIC))
96    (clobber (match_scratch:I48MODE 2 "=&r"))]
97   ""
98   "#"
99   "reload_completed"
100   [(const_int 0)]
101 {
102   alpha_split_atomic_op (NOT, operands[0], operands[1],
103                          NULL, NULL, operands[2]);
104   DONE;
105 }
106   [(set_attr "type" "multi")])
107
108 (define_insn_and_split "sync_old_<fetchop_name><mode>"
109   [(set (match_operand:I48MODE 0 "register_operand" "=&r")
110         (match_operand:I48MODE 1 "memory_operand" "+m"))
111    (set (match_dup 1)
112         (unspec:I48MODE
113           [(FETCHOP:I48MODE (match_dup 1)
114              (match_operand:I48MODE 2 "<fetchop_pred>" "<fetchop_constr>"))]
115           UNSPEC_ATOMIC))
116    (clobber (match_scratch:I48MODE 3 "=&r"))]
117   ""
118   "#"
119   "reload_completed"
120   [(const_int 0)]
121 {
122   alpha_split_atomic_op (<CODE>, operands[1], operands[2],
123                          operands[0], NULL, operands[3]);
124   DONE;
125 }
126   [(set_attr "type" "multi")])
127
128 (define_insn_and_split "sync_old_nand<mode>"
129   [(set (match_operand:I48MODE 0 "register_operand" "=&r")
130         (match_operand:I48MODE 1 "memory_operand" "+m"))
131    (set (match_dup 1)
132         (unspec:I48MODE
133           [(not:I48MODE
134              (and:I48MODE (match_dup 1)
135                (match_operand:I48MODE 2 "register_operand" "r")))]
136           UNSPEC_ATOMIC))
137    (clobber (match_scratch:I48MODE 3 "=&r"))]
138   ""
139   "#"
140   "reload_completed"
141   [(const_int 0)]
142 {
143   alpha_split_atomic_op (NOT, operands[1], operands[2],
144                          operands[0], NULL, operands[3]);
145   DONE;
146 }
147   [(set_attr "type" "multi")])
148
149 (define_insn_and_split "sync_new_<fetchop_name><mode>"
150   [(set (match_operand:I48MODE 0 "register_operand" "=&r")
151         (FETCHOP:I48MODE 
152           (match_operand:I48MODE 1 "memory_operand" "+m")
153           (match_operand:I48MODE 2 "<fetchop_pred>" "<fetchop_constr>")))
154    (set (match_dup 1)
155         (unspec:I48MODE
156           [(FETCHOP:I48MODE (match_dup 1) (match_dup 2))]
157           UNSPEC_ATOMIC))
158    (clobber (match_scratch:I48MODE 3 "=&r"))]
159   ""
160   "#"
161   "reload_completed"
162   [(const_int 0)]
163 {
164   alpha_split_atomic_op (<CODE>, operands[1], operands[2],
165                          NULL, operands[0], operands[3]);
166   DONE;
167 }
168   [(set_attr "type" "multi")])
169
170 (define_insn_and_split "sync_new_nand<mode>"
171   [(set (match_operand:I48MODE 0 "register_operand" "=&r")
172         (not:I48MODE
173           (and:I48MODE (match_operand:I48MODE 1 "memory_operand" "+m")
174             (match_operand:I48MODE 2 "register_operand" "r"))))
175    (set (match_dup 1)
176         (unspec:I48MODE
177           [(not:I48MODE (and:I48MODE (match_dup 1) (match_dup 2)))]
178           UNSPEC_ATOMIC))
179    (clobber (match_scratch:I48MODE 3 "=&r"))]
180   ""
181   "#"
182   "reload_completed"
183   [(const_int 0)]
184 {
185   alpha_split_atomic_op (NOT, operands[1], operands[2],
186                          NULL, operands[0], operands[3]);
187   DONE;
188 }
189   [(set_attr "type" "multi")])
190
191 (define_expand "sync_compare_and_swap<mode>"
192   [(match_operand:I12MODE 0 "register_operand" "")
193    (match_operand:I12MODE 1 "memory_operand" "")
194    (match_operand:I12MODE 2 "register_operand" "")
195    (match_operand:I12MODE 3 "add_operand" "")]
196   ""
197 {
198   alpha_expand_compare_and_swap_12 (operands[0], operands[1],
199                                     operands[2], operands[3]);
200   DONE;
201 })
202
203 (define_insn_and_split "sync_compare_and_swap<mode>_1"
204   [(set (match_operand:DI 0 "register_operand" "=&r,&r")
205         (zero_extend:DI
206           (mem:I12MODE (match_operand:DI 1 "register_operand" "r,r"))))
207    (set (mem:I12MODE (match_dup 1))
208         (unspec:I12MODE
209           [(match_operand:DI 2 "reg_or_8bit_operand" "J,rI")
210            (match_operand:DI 3 "register_operand" "r,r")
211            (match_operand:DI 4 "register_operand" "r,r")]
212           UNSPEC_CMPXCHG))
213    (clobber (match_scratch:DI 5 "=&r,&r"))
214    (clobber (match_scratch:DI 6 "=X,&r"))]
215   ""
216   "#"
217   "reload_completed"
218   [(const_int 0)]
219 {
220   alpha_split_compare_and_swap_12 (<MODE>mode, operands[0], operands[1],
221                                    operands[2], operands[3], operands[4],
222                                    operands[5], operands[6]);
223   DONE;
224 }
225   [(set_attr "type" "multi")])
226
227 (define_expand "sync_compare_and_swap<mode>"
228   [(parallel
229      [(set (match_operand:I48MODE 0 "register_operand" "")
230            (match_operand:I48MODE 1 "memory_operand" ""))
231       (set (match_dup 1)
232            (unspec:I48MODE
233              [(match_operand:I48MODE 2 "reg_or_8bit_operand" "")
234               (match_operand:I48MODE 3 "add_operand" "rKL")]
235              UNSPEC_CMPXCHG))
236       (clobber (match_scratch:I48MODE 4 "=&r"))])]
237   ""
238 {
239   if (<MODE>mode == SImode)
240     operands[2] = convert_modes (DImode, SImode, operands[2], 0);
241 })
242
243 (define_insn_and_split "*sync_compare_and_swap<mode>"
244   [(set (match_operand:I48MODE 0 "register_operand" "=&r")
245         (match_operand:I48MODE 1 "memory_operand" "+m"))
246    (set (match_dup 1)
247         (unspec:I48MODE
248           [(match_operand:DI 2 "reg_or_8bit_operand" "rI")
249            (match_operand:I48MODE 3 "add_operand" "rKL")]
250           UNSPEC_CMPXCHG))
251    (clobber (match_scratch:I48MODE 4 "=&r"))]
252   ""
253   "#"
254   "reload_completed"
255   [(const_int 0)]
256 {
257   alpha_split_compare_and_swap (operands[0], operands[1], operands[2],
258                                 operands[3], operands[4]);
259   DONE;
260 }
261   [(set_attr "type" "multi")])
262
263 (define_expand "sync_lock_test_and_set<mode>"
264   [(match_operand:I12MODE 0 "register_operand" "")
265    (match_operand:I12MODE 1 "memory_operand" "")
266    (match_operand:I12MODE 2 "register_operand" "")]
267   ""
268 {
269   alpha_expand_lock_test_and_set_12 (operands[0], operands[1], operands[2]);
270   DONE;
271 })
272
273 (define_insn_and_split "sync_lock_test_and_set<mode>_1"
274   [(set (match_operand:DI 0 "register_operand" "=&r")
275         (zero_extend:DI
276           (mem:I12MODE (match_operand:DI 1 "register_operand" "r"))))
277    (set (mem:I12MODE (match_dup 1))
278         (unspec:I12MODE
279           [(match_operand:DI 2 "reg_or_8bit_operand" "rI")
280            (match_operand:DI 3 "register_operand" "r")]
281           UNSPEC_XCHG))
282    (clobber (match_scratch:DI 4 "=&r"))]
283   ""
284   "#"
285   "reload_completed"
286   [(const_int 0)]
287 {
288   alpha_split_lock_test_and_set_12 (<MODE>mode, operands[0], operands[1],
289                                     operands[2], operands[3], operands[4]);
290   DONE;
291 }
292   [(set_attr "type" "multi")])
293
294 (define_insn_and_split "sync_lock_test_and_set<mode>"
295   [(set (match_operand:I48MODE 0 "register_operand" "=&r")
296         (match_operand:I48MODE 1 "memory_operand" "+m"))
297    (set (match_dup 1)
298         (unspec:I48MODE
299           [(match_operand:I48MODE 2 "add_operand" "rKL")]
300           UNSPEC_XCHG))
301    (clobber (match_scratch:I48MODE 3 "=&r"))]
302   ""
303   "#"
304   "reload_completed"
305   [(const_int 0)]
306 {
307   alpha_split_lock_test_and_set (operands[0], operands[1],
308                                  operands[2], operands[3]);
309   DONE;
310 }
311   [(set_attr "type" "multi")])