]>
Commit | Line | Data |
---|---|---|
f565b0a1 | 1 | ;; Machine description for PowerPC synchronization instructions. |
2f83c7d6 | 2 | ;; Copyright (C) 2005, 2007 Free Software Foundation, Inc. |
f565b0a1 DE |
3 | ;; Contributed by Geoffrey Keating. |
4 | ||
5 | ;; This file is part of GCC. | |
6 | ||
7 | ;; GCC is free software; you can redistribute it and/or modify it | |
8 | ;; under the terms of the GNU General Public License as published | |
2f83c7d6 | 9 | ;; by the Free Software Foundation; either version 3, or (at your |
f565b0a1 DE |
10 | ;; option) any later version. |
11 | ||
12 | ;; GCC is distributed in the hope that it will be useful, but WITHOUT | |
13 | ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | |
14 | ;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public | |
15 | ;; License for more details. | |
16 | ||
17 | ;; You should have received a copy of the GNU General Public License | |
2f83c7d6 NC |
18 | ;; along with GCC; see the file COPYING3. If not see |
19 | ;; <http://www.gnu.org/licenses/>. | |
f565b0a1 DE |
20 | |
21 | (define_mode_attr larx [(SI "lwarx") (DI "ldarx")]) | |
22 | (define_mode_attr stcx [(SI "stwcx.") (DI "stdcx.")]) | |
23 | ||
9f0076e5 DE |
24 | (define_code_macro FETCHOP [plus minus ior xor and]) |
25 | (define_code_attr fetchop_name | |
26 | [(plus "add") (minus "sub") (ior "ior") (xor "xor") (and "and")]) | |
27 | (define_code_attr fetchop_pred | |
28 | [(plus "add_operand") (minus "gpc_reg_operand") | |
29 | (ior "logical_operand") (xor "logical_operand") (and "and_operand")]) | |
30 | (define_code_attr fetchopsi_constr | |
31 | [(plus "rIL") (minus "r") (ior "rKL") (xor "rKL") (and "rTKL")]) | |
32 | (define_code_attr fetchopdi_constr | |
33 | [(plus "rIL") (minus "r") (ior "rKJF") (xor "rKJF") (and "rSTKJ")]) | |
34 | ||
b52110d4 DE |
35 | (define_expand "memory_barrier" |
36 | [(set (mem:BLK (match_dup 0)) | |
9f0076e5 | 37 | (unspec:BLK [(mem:BLK (match_dup 0))] UNSPEC_SYNC))] |
f565b0a1 | 38 | "" |
b52110d4 DE |
39 | { |
40 | operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode)); | |
41 | MEM_VOLATILE_P (operands[0]) = 1; | |
42 | }) | |
43 | ||
44 | (define_insn "*sync_internal" | |
45 | [(set (match_operand:BLK 0 "" "") | |
9f0076e5 | 46 | (unspec:BLK [(match_operand:BLK 1 "" "")] UNSPEC_SYNC))] |
b52110d4 DE |
47 | "" |
48 | "{dcs|sync}" | |
49 | [(set_attr "type" "sync")]) | |
50 | ||
51 | (define_insn "load_locked_<mode>" | |
52 | [(set (match_operand:GPR 0 "gpc_reg_operand" "=r") | |
53 | (unspec_volatile:GPR | |
d54c47e1 | 54 | [(match_operand:GPR 1 "memory_operand" "Z")] UNSPECV_LL))] |
b52110d4 DE |
55 | "TARGET_POWERPC" |
56 | "<larx> %0,%y1" | |
57 | [(set_attr "type" "load_l")]) | |
58 | ||
59 | (define_insn "store_conditional_<mode>" | |
60 | [(set (match_operand:CC 0 "cc_reg_operand" "=x") | |
61 | (unspec_volatile:CC [(const_int 0)] UNSPECV_SC)) | |
d54c47e1 | 62 | (set (match_operand:GPR 1 "memory_operand" "=Z") |
b52110d4 DE |
63 | (match_operand:GPR 2 "gpc_reg_operand" "r"))] |
64 | "TARGET_POWERPC" | |
65 | "<stcx> %2,%y1" | |
66 | [(set_attr "type" "store_c")]) | |
67 | ||
68 | (define_insn_and_split "sync_compare_and_swap<mode>" | |
69 | [(set (match_operand:GPR 0 "gpc_reg_operand" "=&r") | |
d54c47e1 | 70 | (match_operand:GPR 1 "memory_operand" "+Z")) |
b52110d4 | 71 | (set (match_dup 1) |
9f0076e5 | 72 | (unspec:GPR |
b52110d4 DE |
73 | [(match_operand:GPR 2 "reg_or_short_operand" "rI") |
74 | (match_operand:GPR 3 "gpc_reg_operand" "r")] | |
9f0076e5 | 75 | UNSPEC_CMPXCHG)) |
b52110d4 DE |
76 | (clobber (match_scratch:GPR 4 "=&r")) |
77 | (clobber (match_scratch:CC 5 "=&x"))] | |
78 | "TARGET_POWERPC" | |
79 | "#" | |
80 | "&& reload_completed" | |
81 | [(const_int 0)] | |
82 | { | |
83 | rs6000_split_compare_and_swap (operands[0], operands[1], operands[2], | |
84 | operands[3], operands[4]); | |
85 | DONE; | |
86 | }) | |
f565b0a1 | 87 | |
9fc75b97 DE |
88 | (define_expand "sync_compare_and_swaphi" |
89 | [(match_operand:HI 0 "gpc_reg_operand" "") | |
90 | (match_operand:HI 1 "memory_operand" "") | |
91 | (match_operand:HI 2 "gpc_reg_operand" "") | |
92 | (match_operand:HI 3 "gpc_reg_operand" "")] | |
93 | "TARGET_POWERPC" | |
94 | { | |
95 | rs6000_expand_compare_and_swapqhi (operands[0], operands[1], | |
96 | operands[2], operands[3]); | |
97 | DONE; | |
98 | }) | |
99 | ||
100 | (define_expand "sync_compare_and_swapqi" | |
101 | [(match_operand:QI 0 "gpc_reg_operand" "") | |
102 | (match_operand:QI 1 "memory_operand" "") | |
103 | (match_operand:QI 2 "gpc_reg_operand" "") | |
104 | (match_operand:QI 3 "gpc_reg_operand" "")] | |
105 | "TARGET_POWERPC" | |
106 | { | |
107 | rs6000_expand_compare_and_swapqhi (operands[0], operands[1], | |
108 | operands[2], operands[3]); | |
109 | DONE; | |
110 | }) | |
111 | ||
112 | (define_insn_and_split "sync_compare_and_swapqhi_internal" | |
113 | [(set (match_operand:SI 0 "gpc_reg_operand" "=&r") | |
114 | (match_operand:SI 4 "memory_operand" "+Z")) | |
115 | (set (match_dup 4) | |
116 | (unspec:SI | |
117 | [(match_operand:SI 1 "gpc_reg_operand" "r") | |
118 | (match_operand:SI 2 "gpc_reg_operand" "r") | |
119 | (match_operand:SI 3 "gpc_reg_operand" "r")] | |
120 | UNSPEC_CMPXCHG)) | |
121 | (clobber (match_scratch:SI 5 "=&r")) | |
122 | (clobber (match_scratch:CC 6 "=&x"))] | |
123 | "TARGET_POWERPC" | |
124 | "#" | |
125 | "&& reload_completed" | |
126 | [(const_int 0)] | |
127 | { | |
128 | rs6000_split_compare_and_swapqhi (operands[0], operands[1], | |
129 | operands[2], operands[3], operands[4], | |
130 | operands[5]); | |
131 | DONE; | |
132 | }) | |
133 | ||
b52110d4 DE |
134 | (define_insn_and_split "sync_lock_test_and_set<mode>" |
135 | [(set (match_operand:GPR 0 "gpc_reg_operand" "=&r") | |
9f0076e5 | 136 | (match_operand:GPR 1 "memory_operand" "+Z")) |
b52110d4 | 137 | (set (match_dup 1) |
9f0076e5 | 138 | (unspec:GPR |
b52110d4 | 139 | [(match_operand:GPR 2 "reg_or_short_operand" "rL")] |
9f0076e5 | 140 | UNSPEC_XCHG)) |
b52110d4 | 141 | (clobber (match_scratch:GPR 3 "=&r")) |
f565b0a1 | 142 | (clobber (match_scratch:CC 4 "=&x"))] |
b52110d4 DE |
143 | "TARGET_POWERPC" |
144 | "#" | |
145 | "&& reload_completed" | |
146 | [(const_int 0)] | |
147 | { | |
148 | rs6000_split_lock_test_and_set (operands[0], operands[1], operands[2], | |
149 | operands[3]); | |
150 | DONE; | |
151 | }) | |
f565b0a1 | 152 | |
9f0076e5 DE |
153 | (define_expand "sync_<fetchop_name><mode>" |
154 | [(parallel [(set (match_operand:INT1 0 "memory_operand" "") | |
155 | (unspec:INT1 | |
156 | [(FETCHOP:INT1 (match_dup 0) | |
157 | (match_operand:INT1 1 "<fetchop_pred>" ""))] | |
158 | UNSPEC_ATOMIC)) | |
159 | (clobber (scratch:INT1)) | |
160 | (clobber (scratch:CC))])] | |
161 | "TARGET_POWERPC" | |
f565b0a1 DE |
162 | " |
163 | { | |
9f0076e5 DE |
164 | if (<MODE>mode != SImode && <MODE>mode != DImode) |
165 | { | |
166 | if (PPC405_ERRATUM77) | |
167 | FAIL; | |
168 | rs6000_emit_sync (<CODE>, <MODE>mode, operands[0], operands[1], | |
169 | NULL_RTX, NULL_RTX, true); | |
170 | DONE; | |
171 | } | |
f565b0a1 DE |
172 | }") |
173 | ||
9f0076e5 DE |
174 | (define_insn_and_split "*sync_<fetchop_name>si_internal" |
175 | [(set (match_operand:SI 0 "memory_operand" "+Z") | |
176 | (unspec:SI | |
177 | [(FETCHOP:SI (match_dup 0) | |
178 | (match_operand:SI 1 "<fetchop_pred>" "<fetchopsi_constr>"))] | |
179 | UNSPEC_ATOMIC)) | |
66684b7e | 180 | (clobber (match_scratch:SI 2 "=&b")) |
9f0076e5 DE |
181 | (clobber (match_scratch:CC 3 "=&x"))] |
182 | "TARGET_POWERPC" | |
183 | "#" | |
184 | "&& reload_completed" | |
185 | [(const_int 0)] | |
f565b0a1 | 186 | { |
9f0076e5 DE |
187 | rs6000_split_atomic_op (<CODE>, operands[0], operands[1], |
188 | NULL_RTX, NULL_RTX, operands[2]); | |
f565b0a1 | 189 | DONE; |
9f0076e5 | 190 | }) |
f565b0a1 | 191 | |
9f0076e5 DE |
192 | (define_insn_and_split "*sync_<fetchop_name>di_internal" |
193 | [(set (match_operand:DI 0 "memory_operand" "+Z") | |
194 | (unspec:DI | |
195 | [(FETCHOP:DI (match_dup 0) | |
196 | (match_operand:DI 1 "<fetchop_pred>" "<fetchopdi_constr>"))] | |
197 | UNSPEC_ATOMIC)) | |
66684b7e | 198 | (clobber (match_scratch:DI 2 "=&b")) |
9f0076e5 DE |
199 | (clobber (match_scratch:CC 3 "=&x"))] |
200 | "TARGET_POWERPC" | |
201 | "#" | |
202 | "&& reload_completed" | |
203 | [(const_int 0)] | |
f565b0a1 | 204 | { |
9f0076e5 DE |
205 | rs6000_split_atomic_op (<CODE>, operands[0], operands[1], |
206 | NULL_RTX, NULL_RTX, operands[2]); | |
f565b0a1 | 207 | DONE; |
9f0076e5 | 208 | }) |
f565b0a1 DE |
209 | |
210 | (define_expand "sync_nand<mode>" | |
9f0076e5 DE |
211 | [(parallel [(set (match_operand:INT1 0 "memory_operand" "") |
212 | (unspec:INT1 | |
213 | [(and:INT1 (not:INT1 (match_dup 0)) | |
214 | (match_operand:INT1 1 "gpc_reg_operand" ""))] | |
215 | UNSPEC_ATOMIC)) | |
216 | (clobber (scratch:INT1)) | |
217 | (clobber (scratch:CC))])] | |
218 | "TARGET_POWERPC" | |
f565b0a1 DE |
219 | " |
220 | { | |
9f0076e5 DE |
221 | if (<MODE>mode != SImode && <MODE>mode != DImode) |
222 | { | |
223 | if (PPC405_ERRATUM77) | |
224 | FAIL; | |
225 | rs6000_emit_sync (AND, <MODE>mode, | |
226 | gen_rtx_NOT (<MODE>mode, operands[0]), | |
227 | operands[1], | |
228 | NULL_RTX, NULL_RTX, true); | |
229 | DONE; | |
230 | } | |
f565b0a1 DE |
231 | }") |
232 | ||
9f0076e5 DE |
233 | (define_insn_and_split "*sync_nand<mode>_internal" |
234 | [(set (match_operand:GPR 0 "memory_operand" "+Z") | |
235 | (unspec:GPR | |
236 | [(and:GPR (not:GPR (match_dup 0)) | |
237 | (match_operand:GPR 1 "gpc_reg_operand" "r"))] | |
238 | UNSPEC_ATOMIC)) | |
239 | (clobber (match_scratch:GPR 2 "=&r")) | |
240 | (clobber (match_scratch:CC 3 "=&x"))] | |
241 | "TARGET_POWERPC" | |
242 | "#" | |
243 | "&& reload_completed" | |
244 | [(const_int 0)] | |
f565b0a1 | 245 | { |
9f0076e5 DE |
246 | rs6000_split_atomic_op (NOT, operands[0], operands[1], |
247 | NULL_RTX, NULL_RTX, operands[2]); | |
f565b0a1 | 248 | DONE; |
9f0076e5 | 249 | }) |
f565b0a1 | 250 | |
9f0076e5 DE |
251 | (define_expand "sync_old_<fetchop_name><mode>" |
252 | [(parallel [(set (match_operand:INT1 0 "gpc_reg_operand" "") | |
253 | (match_operand:INT1 1 "memory_operand" "")) | |
254 | (set (match_dup 1) | |
255 | (unspec:INT1 | |
256 | [(FETCHOP:INT1 (match_dup 1) | |
257 | (match_operand:INT1 2 "<fetchop_pred>" ""))] | |
258 | UNSPEC_ATOMIC)) | |
259 | (clobber (scratch:INT1)) | |
260 | (clobber (scratch:CC))])] | |
261 | "TARGET_POWERPC" | |
f565b0a1 | 262 | " |
9f0076e5 DE |
263 | { |
264 | if (<MODE>mode != SImode && <MODE>mode != DImode) | |
265 | { | |
266 | if (PPC405_ERRATUM77) | |
267 | FAIL; | |
268 | rs6000_emit_sync (<CODE>, <MODE>mode, operands[1], operands[2], | |
269 | operands[0], NULL_RTX, true); | |
270 | DONE; | |
271 | } | |
f565b0a1 DE |
272 | }") |
273 | ||
9f0076e5 DE |
274 | (define_insn_and_split "*sync_old_<fetchop_name>si_internal" |
275 | [(set (match_operand:SI 0 "gpc_reg_operand" "=&r") | |
276 | (match_operand:SI 1 "memory_operand" "+Z")) | |
277 | (set (match_dup 1) | |
278 | (unspec:SI | |
279 | [(FETCHOP:SI (match_dup 1) | |
280 | (match_operand:SI 2 "<fetchop_pred>" "<fetchopsi_constr>"))] | |
281 | UNSPEC_ATOMIC)) | |
66684b7e | 282 | (clobber (match_scratch:SI 3 "=&b")) |
9f0076e5 DE |
283 | (clobber (match_scratch:CC 4 "=&x"))] |
284 | "TARGET_POWERPC" | |
285 | "#" | |
286 | "&& reload_completed" | |
287 | [(const_int 0)] | |
f565b0a1 | 288 | { |
9f0076e5 DE |
289 | rs6000_split_atomic_op (<CODE>, operands[1], operands[2], |
290 | operands[0], NULL_RTX, operands[3]); | |
f565b0a1 | 291 | DONE; |
9f0076e5 | 292 | }) |
f565b0a1 | 293 | |
9f0076e5 DE |
294 | (define_insn_and_split "*sync_old_<fetchop_name>di_internal" |
295 | [(set (match_operand:DI 0 "gpc_reg_operand" "=&r") | |
296 | (match_operand:DI 1 "memory_operand" "+Z")) | |
297 | (set (match_dup 1) | |
298 | (unspec:DI | |
299 | [(FETCHOP:DI (match_dup 1) | |
300 | (match_operand:DI 2 "<fetchop_pred>" "<fetchopdi_constr>"))] | |
301 | UNSPEC_ATOMIC)) | |
66684b7e | 302 | (clobber (match_scratch:DI 3 "=&b")) |
9f0076e5 DE |
303 | (clobber (match_scratch:CC 4 "=&x"))] |
304 | "TARGET_POWERPC" | |
305 | "#" | |
306 | "&& reload_completed" | |
307 | [(const_int 0)] | |
f565b0a1 | 308 | { |
9f0076e5 DE |
309 | rs6000_split_atomic_op (<CODE>, operands[1], operands[2], |
310 | operands[0], NULL_RTX, operands[3]); | |
f565b0a1 | 311 | DONE; |
9f0076e5 | 312 | }) |
f565b0a1 DE |
313 | |
314 | (define_expand "sync_old_nand<mode>" | |
9f0076e5 DE |
315 | [(parallel [(set (match_operand:INT1 0 "gpc_reg_operand" "") |
316 | (match_operand:INT1 1 "memory_operand" "")) | |
317 | (set (match_dup 1) | |
318 | (unspec:INT1 | |
319 | [(and:INT1 (not:INT1 (match_dup 1)) | |
320 | (match_operand:INT1 2 "gpc_reg_operand" ""))] | |
321 | UNSPEC_ATOMIC)) | |
322 | (clobber (scratch:INT1)) | |
323 | (clobber (scratch:CC))])] | |
324 | "TARGET_POWERPC" | |
f565b0a1 DE |
325 | " |
326 | { | |
9f0076e5 DE |
327 | if (<MODE>mode != SImode && <MODE>mode != DImode) |
328 | { | |
329 | if (PPC405_ERRATUM77) | |
330 | FAIL; | |
331 | rs6000_emit_sync (AND, <MODE>mode, | |
332 | gen_rtx_NOT (<MODE>mode, operands[1]), | |
333 | operands[2], | |
334 | operands[0], NULL_RTX, true); | |
335 | DONE; | |
336 | } | |
f565b0a1 DE |
337 | }") |
338 | ||
9f0076e5 DE |
339 | (define_insn_and_split "*sync_old_nand<mode>_internal" |
340 | [(set (match_operand:GPR 0 "gpc_reg_operand" "=&r") | |
341 | (match_operand:GPR 1 "memory_operand" "+Z")) | |
342 | (set (match_dup 1) | |
343 | (unspec:GPR | |
344 | [(and:GPR (not:GPR (match_dup 1)) | |
345 | (match_operand:GPR 2 "gpc_reg_operand" "r"))] | |
346 | UNSPEC_ATOMIC)) | |
347 | (clobber (match_scratch:GPR 3 "=&r")) | |
348 | (clobber (match_scratch:CC 4 "=&x"))] | |
349 | "TARGET_POWERPC" | |
350 | "#" | |
351 | "&& reload_completed" | |
352 | [(const_int 0)] | |
f565b0a1 | 353 | { |
9f0076e5 DE |
354 | rs6000_split_atomic_op (NOT, operands[1], operands[2], |
355 | operands[0], NULL_RTX, operands[3]); | |
f565b0a1 | 356 | DONE; |
9f0076e5 | 357 | }) |
f565b0a1 | 358 | |
9f0076e5 DE |
359 | (define_expand "sync_new_<fetchop_name><mode>" |
360 | [(parallel [(set (match_operand:INT1 0 "gpc_reg_operand" "") | |
361 | (FETCHOP:INT1 | |
362 | (match_operand:INT1 1 "memory_operand" "") | |
363 | (match_operand:INT1 2 "<fetchop_pred>" ""))) | |
364 | (set (match_dup 1) | |
365 | (unspec:INT1 | |
366 | [(FETCHOP:INT1 (match_dup 1) (match_dup 2))] | |
367 | UNSPEC_ATOMIC)) | |
368 | (clobber (scratch:INT1)) | |
369 | (clobber (scratch:CC))])] | |
370 | "TARGET_POWERPC" | |
f565b0a1 DE |
371 | " |
372 | { | |
9f0076e5 DE |
373 | if (<MODE>mode != SImode && <MODE>mode != DImode) |
374 | { | |
375 | if (PPC405_ERRATUM77) | |
376 | FAIL; | |
377 | rs6000_emit_sync (<CODE>, <MODE>mode, operands[1], operands[2], | |
378 | NULL_RTX, operands[0], true); | |
379 | DONE; | |
380 | } | |
f565b0a1 DE |
381 | }") |
382 | ||
9f0076e5 DE |
383 | (define_insn_and_split "*sync_new_<fetchop_name>si_internal" |
384 | [(set (match_operand:SI 0 "gpc_reg_operand" "=&r") | |
385 | (FETCHOP:SI | |
386 | (match_operand:SI 1 "memory_operand" "+Z") | |
387 | (match_operand:SI 2 "<fetchop_pred>" "<fetchopsi_constr>"))) | |
388 | (set (match_dup 1) | |
389 | (unspec:SI | |
390 | [(FETCHOP:SI (match_dup 1) (match_dup 2))] | |
391 | UNSPEC_ATOMIC)) | |
66684b7e | 392 | (clobber (match_scratch:SI 3 "=&b")) |
9f0076e5 DE |
393 | (clobber (match_scratch:CC 4 "=&x"))] |
394 | "TARGET_POWERPC" | |
395 | "#" | |
396 | "&& reload_completed" | |
397 | [(const_int 0)] | |
f565b0a1 | 398 | { |
9f0076e5 DE |
399 | rs6000_split_atomic_op (<CODE>, operands[1], operands[2], |
400 | NULL_RTX, operands[0], operands[3]); | |
f565b0a1 | 401 | DONE; |
9f0076e5 | 402 | }) |
f565b0a1 | 403 | |
9f0076e5 DE |
404 | (define_insn_and_split "*sync_new_<fetchop_name>di_internal" |
405 | [(set (match_operand:DI 0 "gpc_reg_operand" "=&r") | |
406 | (FETCHOP:DI | |
407 | (match_operand:DI 1 "memory_operand" "+Z") | |
408 | (match_operand:DI 2 "<fetchop_pred>" "<fetchopdi_constr>"))) | |
409 | (set (match_dup 1) | |
410 | (unspec:DI | |
411 | [(FETCHOP:DI (match_dup 1) (match_dup 2))] | |
412 | UNSPEC_ATOMIC)) | |
66684b7e | 413 | (clobber (match_scratch:DI 3 "=&b")) |
9f0076e5 DE |
414 | (clobber (match_scratch:CC 4 "=&x"))] |
415 | "TARGET_POWERPC" | |
416 | "#" | |
417 | "&& reload_completed" | |
418 | [(const_int 0)] | |
f565b0a1 | 419 | { |
9f0076e5 DE |
420 | rs6000_split_atomic_op (<CODE>, operands[1], operands[2], |
421 | NULL_RTX, operands[0], operands[3]); | |
f565b0a1 | 422 | DONE; |
9f0076e5 | 423 | }) |
f565b0a1 | 424 | |
9f0076e5 DE |
425 | (define_expand "sync_new_nand<mode>" |
426 | [(parallel [(set (match_operand:INT1 0 "gpc_reg_operand" "") | |
427 | (and:INT1 | |
428 | (not:INT1 (match_operand:INT1 1 "memory_operand" "")) | |
429 | (match_operand:INT1 2 "gpc_reg_operand" ""))) | |
430 | (set (match_dup 1) | |
431 | (unspec:INT1 | |
432 | [(and:INT1 (not:INT1 (match_dup 1)) (match_dup 2))] | |
433 | UNSPEC_ATOMIC)) | |
434 | (clobber (scratch:INT1)) | |
435 | (clobber (scratch:CC))])] | |
436 | "TARGET_POWERPC" | |
f565b0a1 DE |
437 | " |
438 | { | |
9f0076e5 DE |
439 | if (<MODE>mode != SImode && <MODE>mode != DImode) |
440 | { | |
441 | if (PPC405_ERRATUM77) | |
442 | FAIL; | |
443 | rs6000_emit_sync (AND, <MODE>mode, | |
444 | gen_rtx_NOT (<MODE>mode, operands[1]), | |
445 | operands[2], | |
446 | NULL_RTX, operands[0], true); | |
447 | DONE; | |
448 | } | |
f565b0a1 DE |
449 | }") |
450 | ||
9f0076e5 DE |
451 | (define_insn_and_split "*sync_new_nand<mode>_internal" |
452 | [(set (match_operand:GPR 0 "gpc_reg_operand" "=&r") | |
453 | (and:GPR | |
454 | (not:GPR (match_operand:GPR 1 "memory_operand" "+Z")) | |
455 | (match_operand:GPR 2 "gpc_reg_operand" "r"))) | |
456 | (set (match_dup 1) | |
457 | (unspec:GPR | |
458 | [(and:GPR (not:GPR (match_dup 1)) (match_dup 2))] | |
459 | UNSPEC_ATOMIC)) | |
460 | (clobber (match_scratch:GPR 3 "=&r")) | |
461 | (clobber (match_scratch:CC 4 "=&x"))] | |
462 | "TARGET_POWERPC" | |
463 | "#" | |
464 | "&& reload_completed" | |
465 | [(const_int 0)] | |
f565b0a1 | 466 | { |
9f0076e5 DE |
467 | rs6000_split_atomic_op (NOT, operands[1], operands[2], |
468 | NULL_RTX, operands[0], operands[3]); | |
f565b0a1 | 469 | DONE; |
9f0076e5 DE |
470 | }) |
471 | ||
472 | ; and<mode> without cr0 clobber to avoid generation of additional clobber | |
473 | ; in atomic splitters causing internal consistency failure. | |
474 | ; cr0 already clobbered by larx/stcx. | |
475 | (define_insn "*atomic_andsi" | |
476 | [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r,r,r") | |
477 | (unspec:SI [(match_operand:SI 1 "gpc_reg_operand" "%r,r,r,r") | |
478 | (match_operand:SI 2 "and_operand" "?r,T,K,L")] | |
479 | UNSPEC_AND))] | |
480 | "" | |
481 | "@ | |
482 | and %0,%1,%2 | |
483 | {rlinm|rlwinm} %0,%1,0,%m2,%M2 | |
484 | {andil.|andi.} %0,%1,%b2 | |
485 | {andiu.|andis.} %0,%1,%u2" | |
486 | [(set_attr "type" "*,*,compare,compare")]) | |
487 | ||
488 | (define_insn "*atomic_anddi" | |
489 | [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r,r,r") | |
490 | (unspec:DI [(match_operand:DI 1 "gpc_reg_operand" "%r,r,r,r,r") | |
491 | (match_operand:DI 2 "and_operand" "?r,S,T,K,J")] | |
492 | UNSPEC_AND))] | |
493 | "TARGET_POWERPC64" | |
494 | "@ | |
495 | and %0,%1,%2 | |
496 | rldic%B2 %0,%1,0,%S2 | |
497 | rlwinm %0,%1,0,%m2,%M2 | |
498 | andi. %0,%1,%b2 | |
499 | andis. %0,%1,%u2" | |
500 | [(set_attr "type" "*,*,*,compare,compare") | |
501 | (set_attr "length" "4,4,4,4,4")]) | |
f565b0a1 DE |
502 | |
503 | ; the sync_*_internal patterns all have these operands: | |
504 | ; 0 - memory location | |
505 | ; 1 - operand | |
506 | ; 2 - value in memory after operation | |
507 | ; 3 - value in memory immediately before operation | |
508 | ||
f565b0a1 DE |
509 | (define_insn "*sync_addshort_internal" |
510 | [(set (match_operand:SI 2 "gpc_reg_operand" "=&r") | |
511 | (ior:SI (and:SI (plus:SI (match_operand:SI 0 "memory_operand" "+Z") | |
512 | (match_operand:SI 1 "add_operand" "rI")) | |
513 | (match_operand:SI 4 "gpc_reg_operand" "r")) | |
514 | (and:SI (not:SI (match_dup 4)) (match_dup 0)))) | |
515 | (set (match_operand:SI 3 "gpc_reg_operand" "=&b") (match_dup 0)) | |
9f0076e5 DE |
516 | (set (match_dup 0) |
517 | (unspec:SI [(ior:SI (and:SI (plus:SI (match_dup 0) (match_dup 1)) | |
f565b0a1 DE |
518 | (match_dup 4)) |
519 | (and:SI (not:SI (match_dup 4)) (match_dup 0)))] | |
9f0076e5 | 520 | UNSPEC_SYNC_OP)) |
f565b0a1 DE |
521 | (clobber (match_scratch:CC 5 "=&x")) |
522 | (clobber (match_scratch:SI 6 "=&r"))] | |
523 | "TARGET_POWERPC && !PPC405_ERRATUM77" | |
524 | "lwarx %3,%y0\n\tadd%I1 %2,%3,%1\n\tandc %6,%3,%4\n\tand %2,%2,%4\n\tor %2,%2,%6\n\tstwcx. %2,%y0\n\tbne- $-24" | |
525 | [(set_attr "length" "28")]) | |
526 | ||
9f0076e5 DE |
527 | (define_insn "*sync_subshort_internal" |
528 | [(set (match_operand:SI 2 "gpc_reg_operand" "=&r") | |
529 | (ior:SI (and:SI (minus:SI (match_operand:SI 0 "memory_operand" "+Z") | |
530 | (match_operand:SI 1 "add_operand" "rI")) | |
531 | (match_operand:SI 4 "gpc_reg_operand" "r")) | |
532 | (and:SI (not:SI (match_dup 4)) (match_dup 0)))) | |
533 | (set (match_operand:SI 3 "gpc_reg_operand" "=&b") (match_dup 0)) | |
534 | (set (match_dup 0) | |
535 | (unspec:SI [(ior:SI (and:SI (minus:SI (match_dup 0) (match_dup 1)) | |
536 | (match_dup 4)) | |
537 | (and:SI (not:SI (match_dup 4)) (match_dup 0)))] | |
538 | UNSPEC_SYNC_OP)) | |
539 | (clobber (match_scratch:CC 5 "=&x")) | |
540 | (clobber (match_scratch:SI 6 "=&r"))] | |
f565b0a1 | 541 | "TARGET_POWERPC && !PPC405_ERRATUM77" |
9f0076e5 DE |
542 | "lwarx %3,%y0\n\tsubf %2,%1,%3\n\tandc %6,%3,%4\n\tand %2,%2,%4\n\tor %2,%2,%6\n\tstwcx. %2,%y0\n\tbne- $-24" |
543 | [(set_attr "length" "28")]) | |
f565b0a1 DE |
544 | |
545 | (define_insn "*sync_andsi_internal" | |
546 | [(set (match_operand:SI 2 "gpc_reg_operand" "=&r,&r,&r,&r") | |
547 | (and:SI (match_operand:SI 0 "memory_operand" "+Z,Z,Z,Z") | |
548 | (match_operand:SI 1 "and_operand" "r,T,K,L"))) | |
549 | (set (match_operand:SI 3 "gpc_reg_operand" "=&b,&b,&b,&b") (match_dup 0)) | |
9f0076e5 DE |
550 | (set (match_dup 0) |
551 | (unspec:SI [(and:SI (match_dup 0) (match_dup 1))] | |
552 | UNSPEC_SYNC_OP)) | |
f565b0a1 DE |
553 | (clobber (match_scratch:CC 4 "=&x,&x,&x,&x"))] |
554 | "TARGET_POWERPC && !PPC405_ERRATUM77" | |
555 | "@ | |
556 | lwarx %3,%y0\n\tand %2,%3,%1\n\tstwcx. %2,%y0\n\tbne- $-12 | |
557 | lwarx %3,%y0\n\trlwinm %2,%3,0,%m1,%M1\n\tstwcx. %2,%y0\n\tbne- $-12 | |
558 | lwarx %3,%y0\n\tandi. %2,%3,%b1\n\tstwcx. %2,%y0\n\tbne- $-12 | |
559 | lwarx %3,%y0\n\tandis. %2,%3,%u1\n\tstwcx. %2,%y0\n\tbne- $-12" | |
560 | [(set_attr "length" "16,16,16,16")]) | |
561 | ||
f565b0a1 DE |
562 | (define_insn "*sync_boolsi_internal" |
563 | [(set (match_operand:SI 2 "gpc_reg_operand" "=&r,&r,&r") | |
564 | (match_operator:SI 4 "boolean_or_operator" | |
565 | [(match_operand:SI 0 "memory_operand" "+Z,Z,Z") | |
566 | (match_operand:SI 1 "logical_operand" "r,K,L")])) | |
567 | (set (match_operand:SI 3 "gpc_reg_operand" "=&b,&b,&b") (match_dup 0)) | |
9f0076e5 | 568 | (set (match_dup 0) (unspec:SI [(match_dup 4)] UNSPEC_SYNC_OP)) |
f565b0a1 DE |
569 | (clobber (match_scratch:CC 5 "=&x,&x,&x"))] |
570 | "TARGET_POWERPC && !PPC405_ERRATUM77" | |
571 | "@ | |
572 | lwarx %3,%y0\n\t%q4 %2,%3,%1\n\tstwcx. %2,%y0\n\tbne- $-12 | |
573 | lwarx %3,%y0\n\t%q4i %2,%3,%b1\n\tstwcx. %2,%y0\n\tbne- $-12 | |
574 | lwarx %3,%y0\n\t%q4is %2,%3,%u1\n\tstwcx. %2,%y0\n\tbne- $-12" | |
575 | [(set_attr "length" "16,16,16")]) | |
576 | ||
f565b0a1 DE |
577 | ; This pattern could also take immediate values of operand 1, |
578 | ; since the non-NOT version of the operator is used; but this is not | |
579 | ; very useful, since in practice operand 1 is a full 32-bit value. | |
580 | ; Likewise, operand 5 is in practice either <= 2^16 or it is a register. | |
581 | (define_insn "*sync_boolcshort_internal" | |
582 | [(set (match_operand:SI 2 "gpc_reg_operand" "=&r") | |
583 | (match_operator:SI 4 "boolean_operator" | |
584 | [(xor:SI (match_operand:SI 0 "memory_operand" "+Z") | |
585 | (match_operand:SI 5 "logical_operand" "rK")) | |
586 | (match_operand:SI 1 "gpc_reg_operand" "r")])) | |
587 | (set (match_operand:SI 3 "gpc_reg_operand" "=&b") (match_dup 0)) | |
9f0076e5 | 588 | (set (match_dup 0) (unspec:SI [(match_dup 4)] UNSPEC_SYNC_OP)) |
f565b0a1 DE |
589 | (clobber (match_scratch:CC 6 "=&x"))] |
590 | "TARGET_POWERPC && !PPC405_ERRATUM77" | |
591 | "lwarx %3,%y0\n\txor%I2 %2,%3,%5\n\t%q4 %2,%2,%1\n\tstwcx. %2,%y0\n\tbne- $-16" | |
592 | [(set_attr "length" "20")]) | |
593 | ||
f565b0a1 DE |
594 | (define_insn "isync" |
595 | [(set (mem:BLK (match_scratch 0 "X")) | |
9f0076e5 | 596 | (unspec_volatile:BLK [(mem:BLK (match_scratch 1 "X"))] UNSPEC_ISYNC))] |
b52110d4 DE |
597 | "" |
598 | "{ics|isync}" | |
599 | [(set_attr "type" "isync")]) | |
f565b0a1 DE |
600 | |
601 | (define_expand "sync_lock_release<mode>" | |
602 | [(set (match_operand:INT 0 "memory_operand") | |
603 | (match_operand:INT 1 "any_operand"))] | |
604 | "" | |
605 | " | |
606 | { | |
607 | emit_insn (gen_lwsync ()); | |
608 | emit_move_insn (operands[0], operands[1]); | |
609 | DONE; | |
610 | }") | |
611 | ||
612 | ; Some AIX assemblers don't accept lwsync, so we use a .long. | |
613 | (define_insn "lwsync" | |
614 | [(set (mem:BLK (match_scratch 0 "X")) | |
9f0076e5 | 615 | (unspec_volatile:BLK [(mem:BLK (match_scratch 1 "X"))] UNSPEC_LWSYNC))] |
f565b0a1 | 616 | "" |
86098753 JM |
617 | { |
618 | if (TARGET_NO_LWSYNC) | |
619 | return "sync"; | |
620 | else | |
621 | return ".long 0x7c2004ac"; | |
622 | } | |
b52110d4 | 623 | [(set_attr "type" "sync")]) |
f565b0a1 | 624 |