0
|
1 ;; GCC machine description for Alpha synchronization instructions.
|
|
2 ;; Copyright (C) 2005, 2007, 2008, 2009 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 (match_dup 0)
|
|
32 (unspec:BLK [(match_dup 0)] UNSPEC_MB))]
|
|
33 ""
|
|
34 {
|
|
35 operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
|
|
36 MEM_VOLATILE_P (operands[0]) = 1;
|
|
37 })
|
|
38
|
|
39 (define_insn "*memory_barrier"
|
|
40 [(set (match_operand:BLK 0 "" "")
|
|
41 (unspec:BLK [(match_dup 0)] 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
|
36
|
65 ;; the lock is cleared by a TAKEN branch. This means that we can not
|
|
66 ;; expand a ll/sc sequence until after the final basic-block reordering pass.
|
0
|
67
|
|
68 (define_insn_and_split "sync_<fetchop_name><mode>"
|
|
69 [(set (match_operand:I48MODE 0 "memory_operand" "+m")
|
|
70 (unspec:I48MODE
|
|
71 [(FETCHOP:I48MODE (match_dup 0)
|
|
72 (match_operand:I48MODE 1 "<fetchop_pred>" "<fetchop_constr>"))]
|
|
73 UNSPEC_ATOMIC))
|
|
74 (clobber (match_scratch:I48MODE 2 "=&r"))]
|
|
75 ""
|
|
76 "#"
|
36
|
77 "epilogue_completed"
|
0
|
78 [(const_int 0)]
|
|
79 {
|
|
80 alpha_split_atomic_op (<CODE>, operands[0], operands[1],
|
|
81 NULL, NULL, operands[2]);
|
|
82 DONE;
|
|
83 }
|
|
84 [(set_attr "type" "multi")])
|
|
85
|
|
86 (define_insn_and_split "sync_nand<mode>"
|
|
87 [(set (match_operand:I48MODE 0 "memory_operand" "+m")
|
|
88 (unspec:I48MODE
|
|
89 [(not:I48MODE
|
|
90 (and:I48MODE (match_dup 0)
|
|
91 (match_operand:I48MODE 1 "register_operand" "r")))]
|
|
92 UNSPEC_ATOMIC))
|
|
93 (clobber (match_scratch:I48MODE 2 "=&r"))]
|
|
94 ""
|
|
95 "#"
|
36
|
96 "epilogue_completed"
|
0
|
97 [(const_int 0)]
|
|
98 {
|
|
99 alpha_split_atomic_op (NOT, operands[0], operands[1],
|
|
100 NULL, NULL, operands[2]);
|
|
101 DONE;
|
|
102 }
|
|
103 [(set_attr "type" "multi")])
|
|
104
|
|
105 (define_insn_and_split "sync_old_<fetchop_name><mode>"
|
|
106 [(set (match_operand:I48MODE 0 "register_operand" "=&r")
|
|
107 (match_operand:I48MODE 1 "memory_operand" "+m"))
|
|
108 (set (match_dup 1)
|
|
109 (unspec:I48MODE
|
|
110 [(FETCHOP:I48MODE (match_dup 1)
|
|
111 (match_operand:I48MODE 2 "<fetchop_pred>" "<fetchop_constr>"))]
|
|
112 UNSPEC_ATOMIC))
|
|
113 (clobber (match_scratch:I48MODE 3 "=&r"))]
|
|
114 ""
|
|
115 "#"
|
36
|
116 "epilogue_completed"
|
0
|
117 [(const_int 0)]
|
|
118 {
|
|
119 alpha_split_atomic_op (<CODE>, operands[1], operands[2],
|
|
120 operands[0], NULL, operands[3]);
|
|
121 DONE;
|
|
122 }
|
|
123 [(set_attr "type" "multi")])
|
|
124
|
|
125 (define_insn_and_split "sync_old_nand<mode>"
|
|
126 [(set (match_operand:I48MODE 0 "register_operand" "=&r")
|
|
127 (match_operand:I48MODE 1 "memory_operand" "+m"))
|
|
128 (set (match_dup 1)
|
|
129 (unspec:I48MODE
|
|
130 [(not:I48MODE
|
|
131 (and:I48MODE (match_dup 1)
|
|
132 (match_operand:I48MODE 2 "register_operand" "r")))]
|
|
133 UNSPEC_ATOMIC))
|
|
134 (clobber (match_scratch:I48MODE 3 "=&r"))]
|
|
135 ""
|
|
136 "#"
|
36
|
137 "epilogue_completed"
|
0
|
138 [(const_int 0)]
|
|
139 {
|
|
140 alpha_split_atomic_op (NOT, operands[1], operands[2],
|
|
141 operands[0], NULL, operands[3]);
|
|
142 DONE;
|
|
143 }
|
|
144 [(set_attr "type" "multi")])
|
|
145
|
|
146 (define_insn_and_split "sync_new_<fetchop_name><mode>"
|
|
147 [(set (match_operand:I48MODE 0 "register_operand" "=&r")
|
|
148 (FETCHOP:I48MODE
|
|
149 (match_operand:I48MODE 1 "memory_operand" "+m")
|
|
150 (match_operand:I48MODE 2 "<fetchop_pred>" "<fetchop_constr>")))
|
|
151 (set (match_dup 1)
|
|
152 (unspec:I48MODE
|
|
153 [(FETCHOP:I48MODE (match_dup 1) (match_dup 2))]
|
|
154 UNSPEC_ATOMIC))
|
|
155 (clobber (match_scratch:I48MODE 3 "=&r"))]
|
|
156 ""
|
|
157 "#"
|
36
|
158 "epilogue_completed"
|
0
|
159 [(const_int 0)]
|
|
160 {
|
|
161 alpha_split_atomic_op (<CODE>, operands[1], operands[2],
|
|
162 NULL, operands[0], operands[3]);
|
|
163 DONE;
|
|
164 }
|
|
165 [(set_attr "type" "multi")])
|
|
166
|
|
167 (define_insn_and_split "sync_new_nand<mode>"
|
|
168 [(set (match_operand:I48MODE 0 "register_operand" "=&r")
|
|
169 (not:I48MODE
|
|
170 (and:I48MODE (match_operand:I48MODE 1 "memory_operand" "+m")
|
|
171 (match_operand:I48MODE 2 "register_operand" "r"))))
|
|
172 (set (match_dup 1)
|
|
173 (unspec:I48MODE
|
|
174 [(not:I48MODE (and:I48MODE (match_dup 1) (match_dup 2)))]
|
|
175 UNSPEC_ATOMIC))
|
|
176 (clobber (match_scratch:I48MODE 3 "=&r"))]
|
|
177 ""
|
|
178 "#"
|
36
|
179 "epilogue_completed"
|
0
|
180 [(const_int 0)]
|
|
181 {
|
|
182 alpha_split_atomic_op (NOT, operands[1], operands[2],
|
|
183 NULL, operands[0], operands[3]);
|
|
184 DONE;
|
|
185 }
|
|
186 [(set_attr "type" "multi")])
|
|
187
|
|
188 (define_expand "sync_compare_and_swap<mode>"
|
|
189 [(match_operand:I12MODE 0 "register_operand" "")
|
|
190 (match_operand:I12MODE 1 "memory_operand" "")
|
|
191 (match_operand:I12MODE 2 "register_operand" "")
|
|
192 (match_operand:I12MODE 3 "add_operand" "")]
|
|
193 ""
|
|
194 {
|
|
195 alpha_expand_compare_and_swap_12 (operands[0], operands[1],
|
|
196 operands[2], operands[3]);
|
|
197 DONE;
|
|
198 })
|
|
199
|
|
200 (define_insn_and_split "sync_compare_and_swap<mode>_1"
|
|
201 [(set (match_operand:DI 0 "register_operand" "=&r,&r")
|
|
202 (zero_extend:DI
|
|
203 (mem:I12MODE (match_operand:DI 1 "register_operand" "r,r"))))
|
|
204 (set (mem:I12MODE (match_dup 1))
|
|
205 (unspec:I12MODE
|
|
206 [(match_operand:DI 2 "reg_or_8bit_operand" "J,rI")
|
|
207 (match_operand:DI 3 "register_operand" "r,r")
|
|
208 (match_operand:DI 4 "register_operand" "r,r")]
|
|
209 UNSPEC_CMPXCHG))
|
|
210 (clobber (match_scratch:DI 5 "=&r,&r"))
|
|
211 (clobber (match_scratch:DI 6 "=X,&r"))]
|
|
212 ""
|
|
213 "#"
|
36
|
214 "epilogue_completed"
|
0
|
215 [(const_int 0)]
|
|
216 {
|
|
217 alpha_split_compare_and_swap_12 (<MODE>mode, operands[0], operands[1],
|
|
218 operands[2], operands[3], operands[4],
|
|
219 operands[5], operands[6]);
|
|
220 DONE;
|
|
221 }
|
|
222 [(set_attr "type" "multi")])
|
|
223
|
|
224 (define_expand "sync_compare_and_swap<mode>"
|
|
225 [(parallel
|
|
226 [(set (match_operand:I48MODE 0 "register_operand" "")
|
|
227 (match_operand:I48MODE 1 "memory_operand" ""))
|
|
228 (set (match_dup 1)
|
|
229 (unspec:I48MODE
|
|
230 [(match_operand:I48MODE 2 "reg_or_8bit_operand" "")
|
|
231 (match_operand:I48MODE 3 "add_operand" "rKL")]
|
|
232 UNSPEC_CMPXCHG))
|
|
233 (clobber (match_scratch:I48MODE 4 "=&r"))])]
|
|
234 ""
|
|
235 {
|
|
236 if (<MODE>mode == SImode)
|
|
237 operands[2] = convert_modes (DImode, SImode, operands[2], 0);
|
|
238 })
|
|
239
|
|
240 (define_insn_and_split "*sync_compare_and_swap<mode>"
|
|
241 [(set (match_operand:I48MODE 0 "register_operand" "=&r")
|
|
242 (match_operand:I48MODE 1 "memory_operand" "+m"))
|
|
243 (set (match_dup 1)
|
|
244 (unspec:I48MODE
|
|
245 [(match_operand:DI 2 "reg_or_8bit_operand" "rI")
|
|
246 (match_operand:I48MODE 3 "add_operand" "rKL")]
|
|
247 UNSPEC_CMPXCHG))
|
|
248 (clobber (match_scratch:I48MODE 4 "=&r"))]
|
|
249 ""
|
|
250 "#"
|
36
|
251 "epilogue_completed"
|
0
|
252 [(const_int 0)]
|
|
253 {
|
|
254 alpha_split_compare_and_swap (operands[0], operands[1], operands[2],
|
|
255 operands[3], operands[4]);
|
|
256 DONE;
|
|
257 }
|
|
258 [(set_attr "type" "multi")])
|
|
259
|
|
260 (define_expand "sync_lock_test_and_set<mode>"
|
|
261 [(match_operand:I12MODE 0 "register_operand" "")
|
|
262 (match_operand:I12MODE 1 "memory_operand" "")
|
|
263 (match_operand:I12MODE 2 "register_operand" "")]
|
|
264 ""
|
|
265 {
|
|
266 alpha_expand_lock_test_and_set_12 (operands[0], operands[1], operands[2]);
|
|
267 DONE;
|
|
268 })
|
|
269
|
|
270 (define_insn_and_split "sync_lock_test_and_set<mode>_1"
|
|
271 [(set (match_operand:DI 0 "register_operand" "=&r")
|
|
272 (zero_extend:DI
|
|
273 (mem:I12MODE (match_operand:DI 1 "register_operand" "r"))))
|
|
274 (set (mem:I12MODE (match_dup 1))
|
|
275 (unspec:I12MODE
|
|
276 [(match_operand:DI 2 "reg_or_8bit_operand" "rI")
|
|
277 (match_operand:DI 3 "register_operand" "r")]
|
|
278 UNSPEC_XCHG))
|
|
279 (clobber (match_scratch:DI 4 "=&r"))]
|
|
280 ""
|
|
281 "#"
|
36
|
282 "epilogue_completed"
|
0
|
283 [(const_int 0)]
|
|
284 {
|
|
285 alpha_split_lock_test_and_set_12 (<MODE>mode, operands[0], operands[1],
|
|
286 operands[2], operands[3], operands[4]);
|
|
287 DONE;
|
|
288 }
|
|
289 [(set_attr "type" "multi")])
|
|
290
|
|
291 (define_insn_and_split "sync_lock_test_and_set<mode>"
|
|
292 [(set (match_operand:I48MODE 0 "register_operand" "=&r")
|
|
293 (match_operand:I48MODE 1 "memory_operand" "+m"))
|
|
294 (set (match_dup 1)
|
|
295 (unspec:I48MODE
|
|
296 [(match_operand:I48MODE 2 "add_operand" "rKL")]
|
|
297 UNSPEC_XCHG))
|
|
298 (clobber (match_scratch:I48MODE 3 "=&r"))]
|
|
299 ""
|
|
300 "#"
|
36
|
301 "epilogue_completed"
|
0
|
302 [(const_int 0)]
|
|
303 {
|
|
304 alpha_split_lock_test_and_set (operands[0], operands[1],
|
|
305 operands[2], operands[3]);
|
|
306 DONE;
|
|
307 }
|
|
308 [(set_attr "type" "multi")])
|