]>
Commit | Line | Data |
---|---|---|
0b196b18 | 1 | ;; GCC machine description for Alpha synchronization instructions. |
8d9254fc | 2 | ;; Copyright (C) 2005-2020 Free Software Foundation, Inc. |
0b196b18 RH |
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 | |
2f83c7d6 | 8 | ;; the Free Software Foundation; either version 3, or (at your option) |
0b196b18 RH |
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 | |
2f83c7d6 NC |
17 | ;; along with GCC; see the file COPYING3. If not see |
18 | ;; <http://www.gnu.org/licenses/>. | |
0b196b18 | 19 | |
3abcb3a7 | 20 | (define_code_iterator FETCHOP [plus minus ior xor and]) |
0b196b18 | 21 | (define_code_attr fetchop_name |
27dd0a95 | 22 | [(plus "add") (minus "sub") (ior "or") (xor "xor") (and "and")]) |
0b196b18 RH |
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 | |
00ca3ed2 | 27 | [(plus "rKL") (minus "rI") (ior "rIN") (xor "rIN") (and "rINM")]) |
0b196b18 RH |
28 | |
29 | ||
30 | (define_expand "memory_barrier" | |
dc701734 UB |
31 | [(set (match_dup 0) |
32 | (unspec:BLK [(match_dup 0)] UNSPEC_MB))] | |
0b196b18 RH |
33 | "" |
34 | { | |
dc701734 | 35 | operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode)); |
0b196b18 RH |
36 | MEM_VOLATILE_P (operands[0]) = 1; |
37 | }) | |
38 | ||
1a8c13b3 | 39 | (define_insn "*memory_barrier" |
7159e638 | 40 | [(set (match_operand:BLK 0) |
dc701734 | 41 | (unspec:BLK [(match_dup 0)] UNSPEC_MB))] |
0b196b18 RH |
42 | "" |
43 | "mb" | |
44 | [(set_attr "type" "mb")]) | |
45 | ||
145f748f | 46 | (define_insn "@load_locked_<mode>" |
0b196b18 RH |
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 | ||
145f748f | 55 | (define_insn "@store_conditional_<mode>" |
0b196b18 RH |
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 | |
2371d1a0 RH |
65 | ;; the lock is cleared by a normal load or store. This means we cannot |
66 | ;; expand a ll/sc sequence before reload, lest a register spill is | |
67 | ;; inserted inside the sequence. It is also UNPREDICTABLE whether the | |
67914693 | 68 | ;; lock is cleared by a TAKEN branch. This means that we cannot expand |
2371d1a0 RH |
69 | ;; a ll/sc sequence containing a branch (i.e. compare-and-swap) until after |
70 | ;; the final basic-block reordering pass. | |
0b196b18 | 71 | |
2371d1a0 RH |
72 | (define_expand "atomic_compare_and_swap<mode>" |
73 | [(parallel | |
7159e638 | 74 | [(set (match_operand:DI 0 "register_operand") ;; bool out |
2371d1a0 | 75 | (unspec_volatile:DI [(const_int 0)] UNSPECV_CMPXCHG)) |
7159e638 | 76 | (set (match_operand:I48MODE 1 "register_operand") ;; val out |
2371d1a0 | 77 | (unspec_volatile:I48MODE [(const_int 0)] UNSPECV_CMPXCHG)) |
7159e638 | 78 | (set (match_operand:I48MODE 2 "memory_operand") ;; memory |
2371d1a0 RH |
79 | (unspec_volatile:I48MODE |
80 | [(match_dup 2) | |
7159e638 UB |
81 | (match_operand:I48MODE 3 "reg_or_8bit_operand") ;; expected |
82 | (match_operand:I48MODE 4 "add_operand") ;; desired | |
83 | (match_operand:SI 5 "const_int_operand") ;; is_weak | |
84 | (match_operand:SI 6 "const_int_operand") ;; succ model | |
85 | (match_operand:SI 7 "const_int_operand")] ;; fail model | |
2371d1a0 RH |
86 | UNSPECV_CMPXCHG))])] |
87 | "" | |
88 | { | |
89 | if (<MODE>mode == SImode) | |
90 | { | |
91 | operands[3] = convert_modes (DImode, SImode, operands[3], 0); | |
92 | operands[4] = convert_modes (DImode, SImode, operands[4], 0); | |
93 | } | |
94 | }) | |
95 | ||
96 | (define_insn_and_split "*atomic_compare_and_swap<mode>" | |
97 | [(set (match_operand:DI 0 "register_operand" "=&r") ;; bool out | |
98 | (unspec_volatile:DI [(const_int 0)] UNSPECV_CMPXCHG)) | |
99 | (set (match_operand:I48MODE 1 "register_operand" "=&r") ;; val out | |
100 | (unspec_volatile:I48MODE [(const_int 0)] UNSPECV_CMPXCHG)) | |
101 | (set (match_operand:I48MODE 2 "memory_operand" "+m") ;; memory | |
102 | (unspec_volatile:I48MODE | |
103 | [(match_dup 2) | |
104 | (match_operand:DI 3 "reg_or_8bit_operand" "rI") ;; expected | |
105 | (match_operand:DI 4 "add_operand" "rKL") ;; desired | |
7159e638 UB |
106 | (match_operand:SI 5 "const_int_operand") ;; is_weak |
107 | (match_operand:SI 6 "const_int_operand") ;; succ model | |
108 | (match_operand:SI 7 "const_int_operand")] ;; fail model | |
2371d1a0 | 109 | UNSPECV_CMPXCHG))] |
0b196b18 RH |
110 | "" |
111 | "#" | |
7b3d1847 | 112 | "epilogue_completed" |
0b196b18 RH |
113 | [(const_int 0)] |
114 | { | |
2371d1a0 | 115 | alpha_split_compare_and_swap (operands); |
0b196b18 RH |
116 | DONE; |
117 | } | |
118 | [(set_attr "type" "multi")]) | |
119 | ||
2371d1a0 | 120 | (define_expand "atomic_compare_and_swap<mode>" |
7159e638 UB |
121 | [(match_operand:DI 0 "register_operand") ;; bool out |
122 | (match_operand:I12MODE 1 "register_operand") ;; val out | |
123 | (match_operand:I12MODE 2 "mem_noofs_operand") ;; memory | |
124 | (match_operand:I12MODE 3 "register_operand") ;; expected | |
125 | (match_operand:I12MODE 4 "add_operand") ;; desired | |
126 | (match_operand:SI 5 "const_int_operand") ;; is_weak | |
127 | (match_operand:SI 6 "const_int_operand") ;; succ model | |
128 | (match_operand:SI 7 "const_int_operand")] ;; fail model | |
2371d1a0 RH |
129 | "" |
130 | { | |
131 | alpha_expand_compare_and_swap_12 (operands); | |
132 | DONE; | |
133 | }) | |
134 | ||
145f748f | 135 | (define_insn_and_split "@atomic_compare_and_swap<mode>_1" |
2371d1a0 RH |
136 | [(set (match_operand:DI 0 "register_operand" "=&r") ;; bool out |
137 | (unspec_volatile:DI [(const_int 0)] UNSPECV_CMPXCHG)) | |
138 | (set (match_operand:DI 1 "register_operand" "=&r") ;; val out | |
139 | (zero_extend:DI | |
140 | (unspec_volatile:I12MODE [(const_int 0)] UNSPECV_CMPXCHG))) | |
141 | (set (match_operand:I12MODE 2 "mem_noofs_operand" "+w") ;; memory | |
142 | (unspec_volatile:I12MODE | |
143 | [(match_dup 2) | |
144 | (match_operand:DI 3 "reg_or_8bit_operand" "rI") ;; expected | |
145 | (match_operand:DI 4 "reg_or_0_operand" "rJ") ;; desired | |
146 | (match_operand:DI 5 "register_operand" "r") ;; align | |
7159e638 UB |
147 | (match_operand:SI 6 "const_int_operand") ;; is_weak |
148 | (match_operand:SI 7 "const_int_operand") ;; succ model | |
149 | (match_operand:SI 8 "const_int_operand")] ;; fail model | |
2371d1a0 RH |
150 | UNSPECV_CMPXCHG)) |
151 | (clobber (match_scratch:DI 9 "=&r"))] | |
0b196b18 RH |
152 | "" |
153 | "#" | |
7b3d1847 | 154 | "epilogue_completed" |
0b196b18 RH |
155 | [(const_int 0)] |
156 | { | |
2371d1a0 | 157 | alpha_split_compare_and_swap_12 (operands); |
0b196b18 RH |
158 | DONE; |
159 | } | |
160 | [(set_attr "type" "multi")]) | |
161 | ||
2371d1a0 RH |
162 | (define_insn_and_split "atomic_exchange<mode>" |
163 | [(set (match_operand:I48MODE 0 "register_operand" "=&r") ;; output | |
164 | (match_operand:I48MODE 1 "memory_operand" "+m")) ;; memory | |
0b196b18 | 165 | (set (match_dup 1) |
38f31687 | 166 | (unspec:I48MODE |
2371d1a0 | 167 | [(match_operand:I48MODE 2 "add_operand" "rKL") ;; input |
7159e638 | 168 | (match_operand:SI 3 "const_int_operand")] ;; model |
2371d1a0 RH |
169 | UNSPEC_XCHG)) |
170 | (clobber (match_scratch:I48MODE 4 "=&r"))] | |
0b196b18 RH |
171 | "" |
172 | "#" | |
7b3d1847 | 173 | "epilogue_completed" |
0b196b18 RH |
174 | [(const_int 0)] |
175 | { | |
2371d1a0 | 176 | alpha_split_atomic_exchange (operands); |
0b196b18 RH |
177 | DONE; |
178 | } | |
179 | [(set_attr "type" "multi")]) | |
180 | ||
2371d1a0 | 181 | (define_expand "atomic_exchange<mode>" |
7159e638 UB |
182 | [(match_operand:I12MODE 0 "register_operand") ;; output |
183 | (match_operand:I12MODE 1 "mem_noofs_operand") ;; memory | |
184 | (match_operand:I12MODE 2 "reg_or_0_operand") ;; input | |
185 | (match_operand:SI 3 "const_int_operand")] ;; model | |
2371d1a0 RH |
186 | "" |
187 | { | |
188 | alpha_expand_atomic_exchange_12 (operands); | |
189 | DONE; | |
190 | }) | |
191 | ||
145f748f | 192 | (define_insn_and_split "@atomic_exchange<mode>_1" |
2371d1a0 RH |
193 | [(set (match_operand:DI 0 "register_operand" "=&r") ;; output |
194 | (zero_extend:DI | |
195 | (match_operand:I12MODE 1 "mem_noofs_operand" "+w"))) ;; memory | |
0b196b18 | 196 | (set (match_dup 1) |
2371d1a0 RH |
197 | (unspec:I12MODE |
198 | [(match_operand:DI 2 "reg_or_8bit_operand" "rI") ;; input | |
199 | (match_operand:DI 3 "register_operand" "r") ;; align | |
7159e638 | 200 | (match_operand:SI 4 "const_int_operand")] ;; model |
2371d1a0 RH |
201 | UNSPEC_XCHG)) |
202 | (clobber (match_scratch:DI 5 "=&r"))] | |
0b196b18 RH |
203 | "" |
204 | "#" | |
7b3d1847 | 205 | "epilogue_completed" |
0b196b18 RH |
206 | [(const_int 0)] |
207 | { | |
2371d1a0 | 208 | alpha_split_atomic_exchange_12 (operands); |
0b196b18 RH |
209 | DONE; |
210 | } | |
211 | [(set_attr "type" "multi")]) | |
212 | ||
2371d1a0 RH |
213 | (define_insn_and_split "atomic_<fetchop_name><mode>" |
214 | [(set (match_operand:I48MODE 0 "memory_operand" "+m") | |
38f31687 | 215 | (unspec:I48MODE |
2371d1a0 RH |
216 | [(FETCHOP:I48MODE (match_dup 0) |
217 | (match_operand:I48MODE 1 "<fetchop_pred>" "<fetchop_constr>")) | |
7159e638 | 218 | (match_operand:SI 2 "const_int_operand")] |
38f31687 | 219 | UNSPEC_ATOMIC)) |
0b196b18 RH |
220 | (clobber (match_scratch:I48MODE 3 "=&r"))] |
221 | "" | |
222 | "#" | |
7b3d1847 | 223 | "epilogue_completed" |
0b196b18 RH |
224 | [(const_int 0)] |
225 | { | |
2371d1a0 RH |
226 | alpha_split_atomic_op (<CODE>, operands[0], operands[1], |
227 | NULL, NULL, operands[3], | |
228 | (enum memmodel) INTVAL (operands[2])); | |
0b196b18 RH |
229 | DONE; |
230 | } | |
231 | [(set_attr "type" "multi")]) | |
232 | ||
2371d1a0 RH |
233 | (define_insn_and_split "atomic_nand<mode>" |
234 | [(set (match_operand:I48MODE 0 "memory_operand" "+m") | |
38f31687 | 235 | (unspec:I48MODE |
2371d1a0 RH |
236 | [(not:I48MODE |
237 | (and:I48MODE (match_dup 0) | |
238 | (match_operand:I48MODE 1 "register_operand" "r"))) | |
7159e638 | 239 | (match_operand:SI 2 "const_int_operand")] |
38f31687 | 240 | UNSPEC_ATOMIC)) |
0b196b18 RH |
241 | (clobber (match_scratch:I48MODE 3 "=&r"))] |
242 | "" | |
243 | "#" | |
7b3d1847 | 244 | "epilogue_completed" |
0b196b18 RH |
245 | [(const_int 0)] |
246 | { | |
2371d1a0 RH |
247 | alpha_split_atomic_op (NOT, operands[0], operands[1], |
248 | NULL, NULL, operands[3], | |
249 | (enum memmodel) INTVAL (operands[2])); | |
0b196b18 RH |
250 | DONE; |
251 | } | |
252 | [(set_attr "type" "multi")]) | |
253 | ||
2371d1a0 RH |
254 | (define_insn_and_split "atomic_fetch_<fetchop_name><mode>" |
255 | [(set (match_operand:I48MODE 0 "register_operand" "=&r") | |
256 | (match_operand:I48MODE 1 "memory_operand" "+m")) | |
257 | (set (match_dup 1) | |
258 | (unspec:I48MODE | |
259 | [(FETCHOP:I48MODE (match_dup 1) | |
260 | (match_operand:I48MODE 2 "<fetchop_pred>" "<fetchop_constr>")) | |
7159e638 | 261 | (match_operand:SI 3 "const_int_operand")] |
2371d1a0 RH |
262 | UNSPEC_ATOMIC)) |
263 | (clobber (match_scratch:I48MODE 4 "=&r"))] | |
38f31687 RH |
264 | "" |
265 | "#" | |
7b3d1847 | 266 | "epilogue_completed" |
38f31687 RH |
267 | [(const_int 0)] |
268 | { | |
2371d1a0 RH |
269 | alpha_split_atomic_op (<CODE>, operands[1], operands[2], |
270 | operands[0], NULL, operands[4], | |
271 | (enum memmodel) INTVAL (operands[3])); | |
38f31687 RH |
272 | DONE; |
273 | } | |
274 | [(set_attr "type" "multi")]) | |
275 | ||
2371d1a0 | 276 | (define_insn_and_split "atomic_fetch_nand<mode>" |
0b196b18 RH |
277 | [(set (match_operand:I48MODE 0 "register_operand" "=&r") |
278 | (match_operand:I48MODE 1 "memory_operand" "+m")) | |
279 | (set (match_dup 1) | |
38f31687 | 280 | (unspec:I48MODE |
2371d1a0 RH |
281 | [(not:I48MODE |
282 | (and:I48MODE (match_dup 1) | |
283 | (match_operand:I48MODE 2 "register_operand" "r"))) | |
7159e638 | 284 | (match_operand:SI 3 "const_int_operand")] |
2371d1a0 | 285 | UNSPEC_ATOMIC)) |
0b196b18 RH |
286 | (clobber (match_scratch:I48MODE 4 "=&r"))] |
287 | "" | |
288 | "#" | |
7b3d1847 | 289 | "epilogue_completed" |
0b196b18 RH |
290 | [(const_int 0)] |
291 | { | |
2371d1a0 RH |
292 | alpha_split_atomic_op (NOT, operands[1], operands[2], |
293 | operands[0], NULL, operands[4], | |
294 | (enum memmodel) INTVAL (operands[3])); | |
0b196b18 RH |
295 | DONE; |
296 | } | |
297 | [(set_attr "type" "multi")]) | |
298 | ||
2371d1a0 RH |
299 | (define_insn_and_split "atomic_<fetchop_name>_fetch<mode>" |
300 | [(set (match_operand:I48MODE 0 "register_operand" "=&r") | |
301 | (FETCHOP:I48MODE | |
302 | (match_operand:I48MODE 1 "memory_operand" "+m") | |
303 | (match_operand:I48MODE 2 "<fetchop_pred>" "<fetchop_constr>"))) | |
304 | (set (match_dup 1) | |
305 | (unspec:I48MODE | |
306 | [(FETCHOP:I48MODE (match_dup 1) (match_dup 2)) | |
7159e638 | 307 | (match_operand:SI 3 "const_int_operand")] |
2371d1a0 RH |
308 | UNSPEC_ATOMIC)) |
309 | (clobber (match_scratch:I48MODE 4 "=&r"))] | |
38f31687 RH |
310 | "" |
311 | "#" | |
7b3d1847 | 312 | "epilogue_completed" |
38f31687 RH |
313 | [(const_int 0)] |
314 | { | |
2371d1a0 RH |
315 | alpha_split_atomic_op (<CODE>, operands[1], operands[2], |
316 | NULL, operands[0], operands[4], | |
317 | (enum memmodel) INTVAL (operands[3])); | |
38f31687 RH |
318 | DONE; |
319 | } | |
320 | [(set_attr "type" "multi")]) | |
321 | ||
2371d1a0 | 322 | (define_insn_and_split "atomic_nand_fetch<mode>" |
0b196b18 | 323 | [(set (match_operand:I48MODE 0 "register_operand" "=&r") |
2371d1a0 RH |
324 | (not:I48MODE |
325 | (and:I48MODE (match_operand:I48MODE 1 "memory_operand" "+m") | |
326 | (match_operand:I48MODE 2 "register_operand" "r")))) | |
0b196b18 | 327 | (set (match_dup 1) |
38f31687 | 328 | (unspec:I48MODE |
2371d1a0 | 329 | [(not:I48MODE (and:I48MODE (match_dup 1) (match_dup 2))) |
7159e638 | 330 | (match_operand:SI 3 "const_int_operand")] |
2371d1a0 RH |
331 | UNSPEC_ATOMIC)) |
332 | (clobber (match_scratch:I48MODE 4 "=&r"))] | |
0b196b18 RH |
333 | "" |
334 | "#" | |
7b3d1847 | 335 | "epilogue_completed" |
0b196b18 RH |
336 | [(const_int 0)] |
337 | { | |
2371d1a0 RH |
338 | alpha_split_atomic_op (NOT, operands[1], operands[2], |
339 | NULL, operands[0], operands[4], | |
340 | (enum memmodel) INTVAL (operands[3])); | |
0b196b18 RH |
341 | DONE; |
342 | } | |
343 | [(set_attr "type" "multi")]) |