Mercurial > hg > CbC > CbC_gcc
comparison gcc/config/rs6000/sync.md @ 0:a06113de4d67
first commit
author | kent <kent@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Fri, 17 Jul 2009 14:47:48 +0900 |
parents | |
children | 77e2b8dfacca |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:a06113de4d67 |
---|---|
1 ;; Machine description for PowerPC synchronization instructions. | |
2 ;; Copyright (C) 2005, 2007, 2008, 2009 Free Software Foundation, Inc. | |
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 | |
9 ;; by the Free Software Foundation; either version 3, or (at your | |
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 | |
18 ;; along with GCC; see the file COPYING3. If not see | |
19 ;; <http://www.gnu.org/licenses/>. | |
20 | |
21 (define_mode_attr larx [(SI "lwarx") (DI "ldarx")]) | |
22 (define_mode_attr stcx [(SI "stwcx.") (DI "stdcx.")]) | |
23 | |
24 (define_code_iterator 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 | |
35 (define_expand "memory_barrier" | |
36 [(set (match_dup 0) | |
37 (unspec:BLK [(match_dup 0)] UNSPEC_SYNC))] | |
38 "" | |
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 "" "") | |
46 (unspec:BLK [(match_dup 0)] UNSPEC_SYNC))] | |
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 | |
54 [(match_operand:GPR 1 "memory_operand" "Z")] UNSPECV_LL))] | |
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)) | |
62 (set (match_operand:GPR 1 "memory_operand" "=Z") | |
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") | |
70 (match_operand:GPR 1 "memory_operand" "+Z")) | |
71 (set (match_dup 1) | |
72 (unspec:GPR | |
73 [(match_operand:GPR 2 "reg_or_short_operand" "rI") | |
74 (match_operand:GPR 3 "gpc_reg_operand" "r")] | |
75 UNSPEC_CMPXCHG)) | |
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 }) | |
87 | |
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 | |
134 (define_insn_and_split "sync_lock_test_and_set<mode>" | |
135 [(set (match_operand:GPR 0 "gpc_reg_operand" "=&r") | |
136 (match_operand:GPR 1 "memory_operand" "+Z")) | |
137 (set (match_dup 1) | |
138 (unspec:GPR | |
139 [(match_operand:GPR 2 "reg_or_short_operand" "rL")] | |
140 UNSPEC_XCHG)) | |
141 (clobber (match_scratch:GPR 3 "=&r")) | |
142 (clobber (match_scratch:CC 4 "=&x"))] | |
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 }) | |
152 | |
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" | |
162 " | |
163 { | |
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 } | |
172 }") | |
173 | |
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)) | |
180 (clobber (match_scratch:SI 2 "=&b")) | |
181 (clobber (match_scratch:CC 3 "=&x"))] | |
182 "TARGET_POWERPC" | |
183 "#" | |
184 "&& reload_completed" | |
185 [(const_int 0)] | |
186 { | |
187 rs6000_split_atomic_op (<CODE>, operands[0], operands[1], | |
188 NULL_RTX, NULL_RTX, operands[2]); | |
189 DONE; | |
190 }) | |
191 | |
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)) | |
198 (clobber (match_scratch:DI 2 "=&b")) | |
199 (clobber (match_scratch:CC 3 "=&x"))] | |
200 "TARGET_POWERPC" | |
201 "#" | |
202 "&& reload_completed" | |
203 [(const_int 0)] | |
204 { | |
205 rs6000_split_atomic_op (<CODE>, operands[0], operands[1], | |
206 NULL_RTX, NULL_RTX, operands[2]); | |
207 DONE; | |
208 }) | |
209 | |
210 (define_expand "sync_nand<mode>" | |
211 [(parallel [(set (match_operand:INT1 0 "memory_operand" "") | |
212 (unspec:INT1 | |
213 [(ior:INT1 (not:INT1 (match_dup 0)) | |
214 (not:INT1 (match_operand:INT1 1 "gpc_reg_operand" "")))] | |
215 UNSPEC_ATOMIC)) | |
216 (clobber (scratch:INT1)) | |
217 (clobber (scratch:CC))])] | |
218 "TARGET_POWERPC" | |
219 " | |
220 { | |
221 if (<MODE>mode != SImode && <MODE>mode != DImode) | |
222 { | |
223 FAIL; | |
224 if (PPC405_ERRATUM77) | |
225 FAIL; | |
226 rs6000_emit_sync (NOT, <MODE>mode, operands[0], operands[1], | |
227 NULL_RTX, NULL_RTX, true); | |
228 DONE; | |
229 } | |
230 }") | |
231 | |
232 (define_insn_and_split "*sync_nand<mode>_internal" | |
233 [(set (match_operand:GPR 0 "memory_operand" "+Z") | |
234 (unspec:GPR | |
235 [(ior:GPR (not:GPR (match_dup 0)) | |
236 (not:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")))] | |
237 UNSPEC_ATOMIC)) | |
238 (clobber (match_scratch:GPR 2 "=&r")) | |
239 (clobber (match_scratch:CC 3 "=&x"))] | |
240 "TARGET_POWERPC" | |
241 "#" | |
242 "&& reload_completed" | |
243 [(const_int 0)] | |
244 { | |
245 rs6000_split_atomic_op (NOT, operands[0], operands[1], | |
246 NULL_RTX, NULL_RTX, operands[2]); | |
247 DONE; | |
248 }) | |
249 | |
250 (define_expand "sync_old_<fetchop_name><mode>" | |
251 [(parallel [(set (match_operand:INT1 0 "gpc_reg_operand" "") | |
252 (match_operand:INT1 1 "memory_operand" "")) | |
253 (set (match_dup 1) | |
254 (unspec:INT1 | |
255 [(FETCHOP:INT1 (match_dup 1) | |
256 (match_operand:INT1 2 "<fetchop_pred>" ""))] | |
257 UNSPEC_ATOMIC)) | |
258 (clobber (scratch:INT1)) | |
259 (clobber (scratch:CC))])] | |
260 "TARGET_POWERPC" | |
261 " | |
262 { | |
263 if (<MODE>mode != SImode && <MODE>mode != DImode) | |
264 { | |
265 if (PPC405_ERRATUM77) | |
266 FAIL; | |
267 rs6000_emit_sync (<CODE>, <MODE>mode, operands[1], operands[2], | |
268 operands[0], NULL_RTX, true); | |
269 DONE; | |
270 } | |
271 }") | |
272 | |
273 (define_insn_and_split "*sync_old_<fetchop_name>si_internal" | |
274 [(set (match_operand:SI 0 "gpc_reg_operand" "=&r") | |
275 (match_operand:SI 1 "memory_operand" "+Z")) | |
276 (set (match_dup 1) | |
277 (unspec:SI | |
278 [(FETCHOP:SI (match_dup 1) | |
279 (match_operand:SI 2 "<fetchop_pred>" "<fetchopsi_constr>"))] | |
280 UNSPEC_ATOMIC)) | |
281 (clobber (match_scratch:SI 3 "=&b")) | |
282 (clobber (match_scratch:CC 4 "=&x"))] | |
283 "TARGET_POWERPC" | |
284 "#" | |
285 "&& reload_completed" | |
286 [(const_int 0)] | |
287 { | |
288 rs6000_split_atomic_op (<CODE>, operands[1], operands[2], | |
289 operands[0], NULL_RTX, operands[3]); | |
290 DONE; | |
291 }) | |
292 | |
293 (define_insn_and_split "*sync_old_<fetchop_name>di_internal" | |
294 [(set (match_operand:DI 0 "gpc_reg_operand" "=&r") | |
295 (match_operand:DI 1 "memory_operand" "+Z")) | |
296 (set (match_dup 1) | |
297 (unspec:DI | |
298 [(FETCHOP:DI (match_dup 1) | |
299 (match_operand:DI 2 "<fetchop_pred>" "<fetchopdi_constr>"))] | |
300 UNSPEC_ATOMIC)) | |
301 (clobber (match_scratch:DI 3 "=&b")) | |
302 (clobber (match_scratch:CC 4 "=&x"))] | |
303 "TARGET_POWERPC" | |
304 "#" | |
305 "&& reload_completed" | |
306 [(const_int 0)] | |
307 { | |
308 rs6000_split_atomic_op (<CODE>, operands[1], operands[2], | |
309 operands[0], NULL_RTX, operands[3]); | |
310 DONE; | |
311 }) | |
312 | |
313 (define_expand "sync_old_nand<mode>" | |
314 [(parallel [(set (match_operand:INT1 0 "gpc_reg_operand" "") | |
315 (match_operand:INT1 1 "memory_operand" "")) | |
316 (set (match_dup 1) | |
317 (unspec:INT1 | |
318 [(ior:INT1 (not:INT1 (match_dup 1)) | |
319 (not:INT1 (match_operand:INT1 2 "gpc_reg_operand" "")))] | |
320 UNSPEC_ATOMIC)) | |
321 (clobber (scratch:INT1)) | |
322 (clobber (scratch:CC))])] | |
323 "TARGET_POWERPC" | |
324 " | |
325 { | |
326 if (<MODE>mode != SImode && <MODE>mode != DImode) | |
327 { | |
328 FAIL; | |
329 if (PPC405_ERRATUM77) | |
330 FAIL; | |
331 rs6000_emit_sync (NOT, <MODE>mode, operands[1], operands[2], | |
332 operands[0], NULL_RTX, true); | |
333 DONE; | |
334 } | |
335 }") | |
336 | |
337 (define_insn_and_split "*sync_old_nand<mode>_internal" | |
338 [(set (match_operand:GPR 0 "gpc_reg_operand" "=&r") | |
339 (match_operand:GPR 1 "memory_operand" "+Z")) | |
340 (set (match_dup 1) | |
341 (unspec:GPR | |
342 [(ior:GPR (not:GPR (match_dup 1)) | |
343 (not:GPR (match_operand:GPR 2 "gpc_reg_operand" "r")))] | |
344 UNSPEC_ATOMIC)) | |
345 (clobber (match_scratch:GPR 3 "=&r")) | |
346 (clobber (match_scratch:CC 4 "=&x"))] | |
347 "TARGET_POWERPC" | |
348 "#" | |
349 "&& reload_completed" | |
350 [(const_int 0)] | |
351 { | |
352 rs6000_split_atomic_op (NOT, operands[1], operands[2], | |
353 operands[0], NULL_RTX, operands[3]); | |
354 DONE; | |
355 }) | |
356 | |
357 (define_expand "sync_new_<fetchop_name><mode>" | |
358 [(parallel [(set (match_operand:INT1 0 "gpc_reg_operand" "") | |
359 (FETCHOP:INT1 | |
360 (match_operand:INT1 1 "memory_operand" "") | |
361 (match_operand:INT1 2 "<fetchop_pred>" ""))) | |
362 (set (match_dup 1) | |
363 (unspec:INT1 | |
364 [(FETCHOP:INT1 (match_dup 1) (match_dup 2))] | |
365 UNSPEC_ATOMIC)) | |
366 (clobber (scratch:INT1)) | |
367 (clobber (scratch:CC))])] | |
368 "TARGET_POWERPC" | |
369 " | |
370 { | |
371 if (<MODE>mode != SImode && <MODE>mode != DImode) | |
372 { | |
373 if (PPC405_ERRATUM77) | |
374 FAIL; | |
375 rs6000_emit_sync (<CODE>, <MODE>mode, operands[1], operands[2], | |
376 NULL_RTX, operands[0], true); | |
377 DONE; | |
378 } | |
379 }") | |
380 | |
381 (define_insn_and_split "*sync_new_<fetchop_name>si_internal" | |
382 [(set (match_operand:SI 0 "gpc_reg_operand" "=&r") | |
383 (FETCHOP:SI | |
384 (match_operand:SI 1 "memory_operand" "+Z") | |
385 (match_operand:SI 2 "<fetchop_pred>" "<fetchopsi_constr>"))) | |
386 (set (match_dup 1) | |
387 (unspec:SI | |
388 [(FETCHOP:SI (match_dup 1) (match_dup 2))] | |
389 UNSPEC_ATOMIC)) | |
390 (clobber (match_scratch:SI 3 "=&b")) | |
391 (clobber (match_scratch:CC 4 "=&x"))] | |
392 "TARGET_POWERPC" | |
393 "#" | |
394 "&& reload_completed" | |
395 [(const_int 0)] | |
396 { | |
397 rs6000_split_atomic_op (<CODE>, operands[1], operands[2], | |
398 NULL_RTX, operands[0], operands[3]); | |
399 DONE; | |
400 }) | |
401 | |
402 (define_insn_and_split "*sync_new_<fetchop_name>di_internal" | |
403 [(set (match_operand:DI 0 "gpc_reg_operand" "=&r") | |
404 (FETCHOP:DI | |
405 (match_operand:DI 1 "memory_operand" "+Z") | |
406 (match_operand:DI 2 "<fetchop_pred>" "<fetchopdi_constr>"))) | |
407 (set (match_dup 1) | |
408 (unspec:DI | |
409 [(FETCHOP:DI (match_dup 1) (match_dup 2))] | |
410 UNSPEC_ATOMIC)) | |
411 (clobber (match_scratch:DI 3 "=&b")) | |
412 (clobber (match_scratch:CC 4 "=&x"))] | |
413 "TARGET_POWERPC" | |
414 "#" | |
415 "&& reload_completed" | |
416 [(const_int 0)] | |
417 { | |
418 rs6000_split_atomic_op (<CODE>, operands[1], operands[2], | |
419 NULL_RTX, operands[0], operands[3]); | |
420 DONE; | |
421 }) | |
422 | |
423 (define_expand "sync_new_nand<mode>" | |
424 [(parallel [(set (match_operand:INT1 0 "gpc_reg_operand" "") | |
425 (ior:INT1 | |
426 (not:INT1 (match_operand:INT1 1 "memory_operand" "")) | |
427 (not:INT1 (match_operand:INT1 2 "gpc_reg_operand" "")))) | |
428 (set (match_dup 1) | |
429 (unspec:INT1 | |
430 [(ior:INT1 (not:INT1 (match_dup 1)) | |
431 (not:INT1 (match_dup 2)))] | |
432 UNSPEC_ATOMIC)) | |
433 (clobber (scratch:INT1)) | |
434 (clobber (scratch:CC))])] | |
435 "TARGET_POWERPC" | |
436 " | |
437 { | |
438 if (<MODE>mode != SImode && <MODE>mode != DImode) | |
439 { | |
440 FAIL; | |
441 if (PPC405_ERRATUM77) | |
442 FAIL; | |
443 rs6000_emit_sync (NOT, <MODE>mode, operands[1], operands[2], | |
444 NULL_RTX, operands[0], true); | |
445 DONE; | |
446 } | |
447 }") | |
448 | |
449 (define_insn_and_split "*sync_new_nand<mode>_internal" | |
450 [(set (match_operand:GPR 0 "gpc_reg_operand" "=&r") | |
451 (ior:GPR | |
452 (not:GPR (match_operand:GPR 1 "memory_operand" "+Z")) | |
453 (not:GPR (match_operand:GPR 2 "gpc_reg_operand" "r")))) | |
454 (set (match_dup 1) | |
455 (unspec:GPR | |
456 [(ior:GPR (not:GPR (match_dup 1)) (not:GPR (match_dup 2)))] | |
457 UNSPEC_ATOMIC)) | |
458 (clobber (match_scratch:GPR 3 "=&r")) | |
459 (clobber (match_scratch:CC 4 "=&x"))] | |
460 "TARGET_POWERPC" | |
461 "#" | |
462 "&& reload_completed" | |
463 [(const_int 0)] | |
464 { | |
465 rs6000_split_atomic_op (NOT, operands[1], operands[2], | |
466 NULL_RTX, operands[0], operands[3]); | |
467 DONE; | |
468 }) | |
469 | |
470 ; and<mode> without cr0 clobber to avoid generation of additional clobber | |
471 ; in atomic splitters causing internal consistency failure. | |
472 ; cr0 already clobbered by larx/stcx. | |
473 (define_insn "*atomic_andsi" | |
474 [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r,r,r") | |
475 (unspec:SI [(match_operand:SI 1 "gpc_reg_operand" "%r,r,r,r") | |
476 (match_operand:SI 2 "and_operand" "?r,T,K,L")] | |
477 UNSPEC_AND))] | |
478 "" | |
479 "@ | |
480 and %0,%1,%2 | |
481 {rlinm|rlwinm} %0,%1,0,%m2,%M2 | |
482 {andil.|andi.} %0,%1,%b2 | |
483 {andiu.|andis.} %0,%1,%u2" | |
484 [(set_attr "type" "*,*,compare,compare")]) | |
485 | |
486 (define_insn "*atomic_anddi" | |
487 [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r,r,r") | |
488 (unspec:DI [(match_operand:DI 1 "gpc_reg_operand" "%r,r,r,r,r") | |
489 (match_operand:DI 2 "and_operand" "?r,S,T,K,J")] | |
490 UNSPEC_AND))] | |
491 "TARGET_POWERPC64" | |
492 "@ | |
493 and %0,%1,%2 | |
494 rldic%B2 %0,%1,0,%S2 | |
495 rlwinm %0,%1,0,%m2,%M2 | |
496 andi. %0,%1,%b2 | |
497 andis. %0,%1,%u2" | |
498 [(set_attr "type" "*,*,*,compare,compare") | |
499 (set_attr "length" "4,4,4,4,4")]) | |
500 | |
501 ; the sync_*_internal patterns all have these operands: | |
502 ; 0 - memory location | |
503 ; 1 - operand | |
504 ; 2 - value in memory after operation | |
505 ; 3 - value in memory immediately before operation | |
506 | |
507 (define_insn "*sync_addshort_internal" | |
508 [(set (match_operand:SI 2 "gpc_reg_operand" "=&r") | |
509 (ior:SI (and:SI (plus:SI (match_operand:SI 0 "memory_operand" "+Z") | |
510 (match_operand:SI 1 "add_operand" "rI")) | |
511 (match_operand:SI 4 "gpc_reg_operand" "r")) | |
512 (and:SI (not:SI (match_dup 4)) (match_dup 0)))) | |
513 (set (match_operand:SI 3 "gpc_reg_operand" "=&b") (match_dup 0)) | |
514 (set (match_dup 0) | |
515 (unspec:SI [(ior:SI (and:SI (plus:SI (match_dup 0) (match_dup 1)) | |
516 (match_dup 4)) | |
517 (and:SI (not:SI (match_dup 4)) (match_dup 0)))] | |
518 UNSPEC_SYNC_OP)) | |
519 (clobber (match_scratch:CC 5 "=&x")) | |
520 (clobber (match_scratch:SI 6 "=&r"))] | |
521 "TARGET_POWERPC && !PPC405_ERRATUM77" | |
522 "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" | |
523 [(set_attr "length" "28")]) | |
524 | |
525 (define_insn "*sync_subshort_internal" | |
526 [(set (match_operand:SI 2 "gpc_reg_operand" "=&r") | |
527 (ior:SI (and:SI (minus:SI (match_operand:SI 0 "memory_operand" "+Z") | |
528 (match_operand:SI 1 "add_operand" "rI")) | |
529 (match_operand:SI 4 "gpc_reg_operand" "r")) | |
530 (and:SI (not:SI (match_dup 4)) (match_dup 0)))) | |
531 (set (match_operand:SI 3 "gpc_reg_operand" "=&b") (match_dup 0)) | |
532 (set (match_dup 0) | |
533 (unspec:SI [(ior:SI (and:SI (minus:SI (match_dup 0) (match_dup 1)) | |
534 (match_dup 4)) | |
535 (and:SI (not:SI (match_dup 4)) (match_dup 0)))] | |
536 UNSPEC_SYNC_OP)) | |
537 (clobber (match_scratch:CC 5 "=&x")) | |
538 (clobber (match_scratch:SI 6 "=&r"))] | |
539 "TARGET_POWERPC && !PPC405_ERRATUM77" | |
540 "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" | |
541 [(set_attr "length" "28")]) | |
542 | |
543 (define_insn "*sync_andsi_internal" | |
544 [(set (match_operand:SI 2 "gpc_reg_operand" "=&r,&r,&r,&r") | |
545 (and:SI (match_operand:SI 0 "memory_operand" "+Z,Z,Z,Z") | |
546 (match_operand:SI 1 "and_operand" "r,T,K,L"))) | |
547 (set (match_operand:SI 3 "gpc_reg_operand" "=&b,&b,&b,&b") (match_dup 0)) | |
548 (set (match_dup 0) | |
549 (unspec:SI [(and:SI (match_dup 0) (match_dup 1))] | |
550 UNSPEC_SYNC_OP)) | |
551 (clobber (match_scratch:CC 4 "=&x,&x,&x,&x"))] | |
552 "TARGET_POWERPC && !PPC405_ERRATUM77" | |
553 "@ | |
554 lwarx %3,%y0\n\tand %2,%3,%1\n\tstwcx. %2,%y0\n\tbne- $-12 | |
555 lwarx %3,%y0\n\trlwinm %2,%3,0,%m1,%M1\n\tstwcx. %2,%y0\n\tbne- $-12 | |
556 lwarx %3,%y0\n\tandi. %2,%3,%b1\n\tstwcx. %2,%y0\n\tbne- $-12 | |
557 lwarx %3,%y0\n\tandis. %2,%3,%u1\n\tstwcx. %2,%y0\n\tbne- $-12" | |
558 [(set_attr "length" "16,16,16,16")]) | |
559 | |
560 (define_insn "*sync_boolsi_internal" | |
561 [(set (match_operand:SI 2 "gpc_reg_operand" "=&r,&r,&r") | |
562 (match_operator:SI 4 "boolean_or_operator" | |
563 [(match_operand:SI 0 "memory_operand" "+Z,Z,Z") | |
564 (match_operand:SI 1 "logical_operand" "r,K,L")])) | |
565 (set (match_operand:SI 3 "gpc_reg_operand" "=&b,&b,&b") (match_dup 0)) | |
566 (set (match_dup 0) (unspec:SI [(match_dup 4)] UNSPEC_SYNC_OP)) | |
567 (clobber (match_scratch:CC 5 "=&x,&x,&x"))] | |
568 "TARGET_POWERPC && !PPC405_ERRATUM77" | |
569 "@ | |
570 lwarx %3,%y0\n\t%q4 %2,%3,%1\n\tstwcx. %2,%y0\n\tbne- $-12 | |
571 lwarx %3,%y0\n\t%q4i %2,%3,%b1\n\tstwcx. %2,%y0\n\tbne- $-12 | |
572 lwarx %3,%y0\n\t%q4is %2,%3,%u1\n\tstwcx. %2,%y0\n\tbne- $-12" | |
573 [(set_attr "length" "16,16,16")]) | |
574 | |
575 ; This pattern could also take immediate values of operand 1, | |
576 ; since the non-NOT version of the operator is used; but this is not | |
577 ; very useful, since in practice operand 1 is a full 32-bit value. | |
578 ; Likewise, operand 5 is in practice either <= 2^16 or it is a register. | |
579 (define_insn "*sync_boolcshort_internal" | |
580 [(set (match_operand:SI 2 "gpc_reg_operand" "=&r") | |
581 (match_operator:SI 4 "boolean_or_operator" | |
582 [(xor:SI (not:SI (match_operand:SI 0 "memory_operand" "+Z")) | |
583 (not:SI (match_operand:SI 5 "logical_operand" "rK"))) | |
584 (match_operand:SI 1 "gpc_reg_operand" "r")])) | |
585 (set (match_operand:SI 3 "gpc_reg_operand" "=&b") (match_dup 0)) | |
586 (set (match_dup 0) (unspec:SI [(match_dup 4)] UNSPEC_SYNC_OP)) | |
587 (clobber (match_scratch:CC 6 "=&x"))] | |
588 "TARGET_POWERPC && !PPC405_ERRATUM77" | |
589 "lwarx %3,%y0\n\txor%I2 %2,%3,%5\n\t%q4 %2,%2,%1\n\tstwcx. %2,%y0\n\tbne- $-16" | |
590 [(set_attr "length" "20")]) | |
591 | |
592 (define_insn "isync" | |
593 [(set (mem:BLK (match_scratch 0 "X")) | |
594 (unspec_volatile:BLK [(mem:BLK (match_scratch 1 "X"))] UNSPEC_ISYNC))] | |
595 "" | |
596 "{ics|isync}" | |
597 [(set_attr "type" "isync")]) | |
598 | |
599 (define_expand "sync_lock_release<mode>" | |
600 [(set (match_operand:INT 0 "memory_operand") | |
601 (match_operand:INT 1 "any_operand"))] | |
602 "" | |
603 " | |
604 { | |
605 emit_insn (gen_lwsync ()); | |
606 emit_move_insn (operands[0], operands[1]); | |
607 DONE; | |
608 }") | |
609 | |
610 ; Some AIX assemblers don't accept lwsync, so we use a .long. | |
611 (define_insn "lwsync" | |
612 [(set (mem:BLK (match_scratch 0 "X")) | |
613 (unspec_volatile:BLK [(mem:BLK (match_scratch 1 "X"))] UNSPEC_LWSYNC))] | |
614 "" | |
615 { | |
616 if (TARGET_NO_LWSYNC) | |
617 return "sync"; | |
618 else | |
619 return ".long 0x7c2004ac"; | |
620 } | |
621 [(set_attr "type" "sync")]) | |
622 |