1 //
2 // Copyright (c) 2018, Red Hat, Inc. All rights reserved.
3 // DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 //
5 // This code is free software; you can redistribute it and/or modify it
6 // under the terms of the GNU General Public License version 2 only, as
7 // published by the Free Software Foundation.
8 //
9 // This code is distributed in the hope that it will be useful, but WITHOUT
10 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 // version 2 for more details (a copy is included in the LICENSE file that
13 // accompanied this code).
14 //
15 // You should have received a copy of the GNU General Public License version
16 // 2 along with this work; if not, write to the Free Software Foundation,
17 // Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 //
19 // Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 // or visit www.oracle.com if you need additional information or have any
21 // questions.
22 //
23 //
24
25 source %{
26 #include "gc/shenandoah/shenandoahBarrierSet.hpp"
27 #include "gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.hpp"
28 %}
29
30 // ---------------------------------- LOADS ---------------------------------------
31 //
32
33 instruct load_P_Normal_shenandoah(iRegPNoSp dst, memory8 mem, iRegPNoSp tmp, rFlagsReg cr)
34 %{
35 match(Set dst (LoadP mem));
36 predicate(UseShenandoahGC && !needs_acquiring_load(n) && n->as_Load()->barrier_data() != 0);
37 effect(TEMP_DEF dst, TEMP tmp, KILL cr);
38 // The main load is a candidate to implement implicit null checks.
39 ins_is_late_expanded_null_check_candidate(opnd_array(1)->opcode() == INDOFFL8);
40 format %{ "ldr $dst, $mem\t# ptr" %}
41 ins_encode %{
42 Address addr = mem2address($mem->opcode(), as_Register($mem$$base), $mem$$index, $mem$$scale, $mem$$disp);
43 if (addr.getMode() == Address::base_plus_offset) {
44 addr = __ legitimize_address(addr, /* size_in_memory */ 8, $tmp$$Register);
45 }
46 ShenandoahBarrierSet::assembler()->load_c2(this, masm,
47 $dst$$Register,
48 addr,
49 rscratch1,
50 rscratch2,
51 /* narrow = */ false,
52 /* acquire = */ false);
53 %}
54 ins_cost(3*INSN_COST);
55 ins_pipe(pipe_class_memory);
56 %}
57
58 instruct load_P_Volatile_shenandoah(iRegPNoSp dst, indirect mem, rFlagsReg cr)
59 %{
60 match(Set dst (LoadP mem));
61 predicate(UseShenandoahGC && needs_acquiring_load(n) && n->as_Load()->barrier_data() != 0);
62 effect(TEMP_DEF dst, KILL cr);
63 // The main load is a candidate to implement implicit null checks.
64 ins_is_late_expanded_null_check_candidate(true);
65 format %{ "ldar $dst, $mem\t# ptr" %}
66 ins_encode %{
67 ShenandoahBarrierSet::assembler()->load_c2(this, masm,
68 $dst$$Register,
69 Address($mem$$Register),
70 rscratch1,
71 rscratch2,
72 /* narrow = */ false,
73 /* acquire = */ true);
74 %}
75 ins_cost(3*INSN_COST);
76 ins_pipe(pipe_class_memory);
77 %}
78
79 instruct load_N_Normal_shenandoah(iRegNNoSp dst, memory4 mem, iRegPNoSp tmp, rFlagsReg cr)
80 %{
81 match(Set dst (LoadN mem));
82 predicate(UseShenandoahGC && !needs_acquiring_load(n) && n->as_Load()->barrier_data() != 0);
83 effect(TEMP_DEF dst, TEMP tmp, KILL cr);
84 // The main load is a candidate to implement implicit null checks.
85 ins_is_late_expanded_null_check_candidate(opnd_array(1)->opcode() == INDOFFL4);
86 format %{ "ldrw $dst, $mem\t# ptr" %}
87 ins_encode %{
88 Address addr = mem2address($mem->opcode(), as_Register($mem$$base), $mem$$index, $mem$$scale, $mem$$disp);
89 if (addr.getMode() == Address::base_plus_offset) {
90 addr = __ legitimize_address(addr, /* size_in_memory */ 4, $tmp$$Register);
91 }
92 ShenandoahBarrierSet::assembler()->load_c2(this, masm,
93 $dst$$Register,
94 addr,
95 rscratch1,
96 rscratch2,
97 /* narrow = */ true,
98 /* acquire = */ false);
99 %}
100 ins_cost(3*INSN_COST);
101 ins_pipe(pipe_class_memory);
102 %}
103
104 instruct load_N_Volatile_shenandoah(iRegNNoSp dst, indirect mem, rFlagsReg cr)
105 %{
106 match(Set dst (LoadN mem));
107 predicate(UseShenandoahGC && needs_acquiring_load(n) && n->as_Load()->barrier_data() != 0);
108 effect(TEMP_DEF dst, KILL cr);
109 // The main load is a candidate to implement implicit null checks.
110 ins_is_late_expanded_null_check_candidate(true);
111 format %{ "ldarw $dst, $mem\t# ptr" %}
112 ins_encode %{
113 ShenandoahBarrierSet::assembler()->load_c2(this, masm,
114 $dst$$Register,
115 Address($mem$$Register),
116 rscratch1,
117 rscratch2,
118 /* narrow = */ true,
119 /* acquire = */ true);
120 %}
121 ins_cost(VOLATILE_REF_COST);
122 ins_pipe(pipe_class_memory);
123 %}
124
125
126 // ---------------------------------- STORES ---------------------------------------
127 //
128
129 instruct store_P_Normal_shenandoah(memory8 mem, iRegP src, iRegPNoSp tmp1, iRegPNoSp tmp2, rFlagsReg cr)
130 %{
131 match(Set mem (StoreP mem src));
132 predicate(UseShenandoahGC && !needs_releasing_store(n) && n->as_Store()->barrier_data() != 0);
133 effect(TEMP tmp1, TEMP tmp2, KILL cr);
134 format %{ "str $src, $mem" %}
135 ins_encode %{
136 Address addr = mem2address($mem->opcode(), as_Register($mem$$base), $mem$$index, $mem$$scale, $mem$$disp);
137 if (addr.getMode() == Address::base_plus_offset) {
138 addr = __ legitimize_address(addr, /* size_in_memory */ 8, $tmp2$$Register);
139 }
140 ShenandoahBarrierSet::assembler()->store_c2(this, masm,
141 addr, /* dst_narrow = */ false,
142 $src$$Register, /* src_narrow = */ false,
143 $tmp1$$Register, rscratch1, rscratch2,
144 /* is_volatile = */ false);
145 %}
146 ins_cost(3*INSN_COST);
147 ins_pipe(pipe_class_memory);
148 %}
149
150 instruct store_P_Volatile_shenandoah(indirect mem, iRegP src, iRegPNoSp tmp, rFlagsReg cr)
151 %{
152 match(Set mem (StoreP mem src));
153 predicate(UseShenandoahGC && needs_releasing_store(n) && n->as_Store()->barrier_data() != 0);
154 effect(TEMP tmp, KILL cr);
155 format %{ "stlr $src, $mem" %}
156 ins_encode %{
157 ShenandoahBarrierSet::assembler()->store_c2(this, masm,
158 Address($mem$$Register), /* dst_narrow = */ false,
159 $src$$Register, /* src_narrow = */ false,
160 $tmp$$Register, rscratch1, rscratch2,
161 /* is_volatile = */ true);
162 %}
163 ins_cost(VOLATILE_REF_COST);
164 ins_pipe(pipe_class_memory);
165 %}
166
167 instruct store_N_Normal_shenandoah(memory4 mem, iRegN src, iRegPNoSp tmp1, iRegPNoSp tmp2, rFlagsReg cr)
168 %{
169 match(Set mem (StoreN mem src));
170 predicate(UseShenandoahGC && !needs_releasing_store(n) && n->as_Store()->barrier_data() != 0);
171 effect(TEMP tmp1, TEMP tmp2, KILL cr);
172 format %{ "strw $src, $mem" %}
173 ins_encode %{
174 Address addr = mem2address($mem->opcode(), as_Register($mem$$base), $mem$$index, $mem$$scale, $mem$$disp);
175 if (addr.getMode() == Address::base_plus_offset) {
176 addr = __ legitimize_address(addr, /* size_in_memory */ 4, $tmp2$$Register);
177 }
178 ShenandoahBarrierSet::assembler()->store_c2(this, masm,
179 addr, /* dst_narrow = */ true,
180 $src$$Register, /* src_narrow = */ true,
181 $tmp1$$Register, rscratch1, rscratch2,
182 /* is_volatile = */ false);
183 %}
184 ins_cost(3*INSN_COST);
185 ins_pipe(pipe_class_memory);
186 %}
187
188 instruct store_N_Volatile_shenandoah(indirect mem, iRegN src, iRegPNoSp tmp, rFlagsReg cr)
189 %{
190 match(Set mem (StoreN mem src));
191 predicate(UseShenandoahGC && needs_releasing_store(n) && n->as_Store()->barrier_data() != 0);
192 effect(TEMP tmp, KILL cr);
193 format %{ "stlrw $src, $mem" %}
194 ins_encode %{
195 ShenandoahBarrierSet::assembler()->store_c2(this, masm,
196 Address($mem$$Register), /* dst_narrow = */ true,
197 $src$$Register, /* src_narrow = */ true,
198 $tmp$$Register, rscratch1, rscratch2,
199 /* is_volatile = */ true);
200 %}
201 ins_cost(VOLATILE_REF_COST);
202 ins_pipe(pipe_class_memory);
203 %}
204
205 instruct encodePAndStoreN_Normal_shenandoah(memory4 mem, iRegP src, iRegPNoSp tmp1, iRegPNoSp tmp2, rFlagsReg cr)
206 %{
207 match(Set mem (StoreN mem (EncodeP src)));
208 predicate(UseShenandoahGC && !needs_releasing_store(n) && n->as_Store()->barrier_data() != 0);
209 effect(TEMP tmp1, TEMP tmp2, KILL cr);
210 format %{ "encode_heap_oop tmp, $src\n\t"
211 "str tmp, $mem\t# compressed ptr" %}
212 ins_encode %{
213 Address addr = mem2address($mem->opcode(), as_Register($mem$$base), $mem$$index, $mem$$scale, $mem$$disp);
214 if (addr.getMode() == Address::base_plus_offset) {
215 addr = __ legitimize_address(addr, /* size_in_memory */ 4, $tmp2$$Register);
216 }
217 ShenandoahBarrierSet::assembler()->store_c2(this, masm,
218 addr, /* dst_narrow = */ true,
219 $src$$Register, /* src_narrow = */ false,
220 $tmp1$$Register, rscratch1, rscratch2,
221 /* is_volatile = */ false);
222 %}
223 ins_cost(4*INSN_COST);
224 ins_pipe(pipe_class_memory);
225 %}
226
227 instruct encodePAndStoreN_Volatile_shenandoah(indirect mem, iRegP src, iRegPNoSp tmp, rFlagsReg cr)
228 %{
229 match(Set mem (StoreN mem (EncodeP src)));
230 predicate(UseShenandoahGC && needs_releasing_store(n) && n->as_Store()->barrier_data() != 0);
231 effect(TEMP tmp, KILL cr);
232 format %{ "encode_heap_oop tmp, $src\n\t"
233 "stlrw tmp, $mem\t# compressed ptr" %}
234 ins_encode %{
235 ShenandoahBarrierSet::assembler()->store_c2(this, masm,
236 Address($mem$$Register), /* dst_narrow = */ true,
237 $src$$Register, /* src_narrow = */ false,
238 $tmp$$Register, rscratch1, rscratch2,
239 /* is_volatile = */ true);
240 %}
241 ins_cost(4*INSN_COST);
242 ins_pipe(pipe_class_memory);
243 %}
244
245
246 // ---------------------- LOAD-STORES -----------------------------------
247 //
248
249 instruct compareAndSwap_P_shenandoah(iRegINoSp res, indirect mem, iRegPNoSp oldval, iRegP newval, iRegPNoSp tmp, rFlagsReg cr)
250 %{
251 match(Set res (CompareAndSwapP mem (Binary oldval newval)));
252 predicate(UseShenandoahGC && !needs_acquiring_load_exclusive(n) && n->as_LoadStore()->barrier_data() != 0);
253 effect(TEMP_DEF res, TEMP tmp, KILL cr);
254 format %{
255 "cmpxchg_P_shenandoah $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval"
256 %}
257 ins_encode %{
258 assert($mem$$index == -1 && $mem$$disp == 0, "impossible encoding");
259
260 ShenandoahBarrierSet::assembler()->compare_and_set_c2(this, masm,
261 $res$$Register,
262 $mem$$base$$Register,
263 $oldval$$Register,
264 $newval$$Register,
265 $tmp$$Register,
266 rscratch1,
267 rscratch2,
268 /* exchange = */ false,
269 /* narrow = */ false,
270 /* weak = */ false,
271 /* acquire = */ false);
272 %}
273 ins_cost(VOLATILE_REF_COST);
274 ins_pipe(pipe_slow);
275 %}
276
277 instruct compareAndSwap_P_A_shenandoah(iRegINoSp res, indirect mem, iRegPNoSp oldval, iRegP newval, iRegPNoSp tmp, rFlagsReg cr)
278 %{
279 match(Set res (CompareAndSwapP mem (Binary oldval newval)));
280 predicate(UseShenandoahGC && needs_acquiring_load_exclusive(n) && n->as_LoadStore()->barrier_data() != 0);
281 effect(TEMP_DEF res, TEMP tmp, KILL cr);
282 format %{
283 "cmpxchg_acq_shenandoah_oop $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval"
284 %}
285 ins_encode %{
286 assert($mem$$index == -1 && $mem$$disp == 0, "impossible encoding");
287
288 ShenandoahBarrierSet::assembler()->compare_and_set_c2(this, masm,
289 $res$$Register,
290 $mem$$base$$Register,
291 $oldval$$Register,
292 $newval$$Register,
293 $tmp$$Register,
294 rscratch1,
295 rscratch2,
296 /* exchange = */ false,
297 /* narrow = */ false,
298 /* weak = */ false,
299 /* acquire = */ true);
300 %}
301 ins_cost(VOLATILE_REF_COST);
302 ins_pipe(pipe_slow);
303 %}
304
305 instruct compareAndSwap_N_shenandoah(iRegINoSp res, indirect mem, iRegNNoSp oldval, iRegN newval, iRegPNoSp tmp, rFlagsReg cr)
306 %{
307 match(Set res (CompareAndSwapN mem (Binary oldval newval)));
308 predicate(UseShenandoahGC && !needs_acquiring_load_exclusive(n) && n->as_LoadStore()->barrier_data() != 0);
309 effect(TEMP_DEF res, TEMP tmp, KILL cr);
310 format %{
311 "cmpxchg_N_shenandoah $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval"
312 %}
313 ins_encode %{
314 assert($mem$$index == -1 && $mem$$disp == 0, "impossible encoding");
315
316 ShenandoahBarrierSet::assembler()->compare_and_set_c2(this, masm,
317 $res$$Register,
318 $mem$$base$$Register,
319 $oldval$$Register,
320 $newval$$Register,
321 $tmp$$Register,
322 rscratch1,
323 rscratch2,
324 /* exchange = */ false,
325 /* narrow = */ true,
326 /* weak = */ false,
327 /* acquire = */ false);
328 %}
329 ins_cost(VOLATILE_REF_COST);
330 ins_pipe(pipe_slow);
331 %}
332
333 instruct compareAndSwap_N_A_shenandoah(iRegINoSp res, indirect mem, iRegNNoSp oldval, iRegN newval, iRegPNoSp tmp, rFlagsReg cr)
334 %{
335 match(Set res (CompareAndSwapN mem (Binary oldval newval)));
336 predicate(UseShenandoahGC && needs_acquiring_load_exclusive(n) && n->as_LoadStore()->barrier_data() != 0);
337 effect(TEMP_DEF res, TEMP tmp, KILL cr);
338 format %{
339 "cmpxchgw_acq_shenandoah_narrow_oop $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval"
340 %}
341 ins_encode %{
342 assert($mem$$index == -1 && $mem$$disp == 0, "impossible encoding");
343
344 ShenandoahBarrierSet::assembler()->compare_and_set_c2(this, masm,
345 $res$$Register,
346 $mem$$base$$Register,
347 $oldval$$Register,
348 $newval$$Register,
349 $tmp$$Register,
350 rscratch1,
351 rscratch2,
352 /* exchange = */ false,
353 /* narrow = */ true,
354 /* weak = */ false,
355 /* acquire = */ true);
356 %}
357 ins_cost(VOLATILE_REF_COST);
358 ins_pipe(pipe_slow);
359 %}
360
361 instruct compareAndExchange_N_shenandoah(iRegNNoSp res, indirect mem, iRegN oldval, iRegN newval, iRegPNoSp tmp, rFlagsReg cr)
362 %{
363 match(Set res (CompareAndExchangeN mem (Binary oldval newval)));
364 predicate(UseShenandoahGC && !needs_acquiring_load_exclusive(n) && n->as_LoadStore()->barrier_data() != 0);
365 effect(TEMP_DEF res, TEMP tmp, KILL cr);
366 format %{
367 "cmpxchgw_shenandoah $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval"
368 %}
369 ins_encode %{
370 assert($mem$$index == -1 && $mem$$disp == 0, "impossible encoding");
371
372 ShenandoahBarrierSet::assembler()->compare_and_set_c2(this, masm,
373 $res$$Register,
374 $mem$$base$$Register,
375 $oldval$$Register,
376 $newval$$Register,
377 $tmp$$Register,
378 rscratch1,
379 rscratch2,
380 /* exchange = */ true,
381 /* narrow = */ true,
382 /* weak = */ false,
383 /* acquire = */ false);
384 %}
385 ins_cost(2*VOLATILE_REF_COST);
386 ins_pipe(pipe_slow);
387 %}
388
389 instruct compareAndExchange_N_A_shenandoah(iRegNNoSp res, indirect mem, iRegN oldval, iRegN newval, iRegPNoSp tmp, rFlagsReg cr)
390 %{
391 match(Set res (CompareAndExchangeN mem (Binary oldval newval)));
392 predicate(UseShenandoahGC && needs_acquiring_load_exclusive(n) && n->as_LoadStore()->barrier_data() != 0);
393 effect(TEMP_DEF res, TEMP tmp, KILL cr);
394 format %{
395 "cmpxchgw_acq_shenandoah $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval"
396 %}
397 ins_encode %{
398 assert($mem$$index == -1 && $mem$$disp == 0, "impossible encoding");
399
400 ShenandoahBarrierSet::assembler()->compare_and_set_c2(this, masm,
401 $res$$Register,
402 $mem$$base$$Register,
403 $oldval$$Register,
404 $newval$$Register,
405 $tmp$$Register,
406 rscratch1,
407 rscratch2,
408 /* exchange = */ true,
409 /* narrow = */ true,
410 /* weak = */ false,
411 /* acquire = */ true);
412 %}
413 ins_cost(2*VOLATILE_REF_COST);
414 ins_pipe(pipe_slow);
415 %}
416
417 instruct compareAndExchange_P_shenandoah(iRegPNoSp res, indirect mem, iRegP oldval, iRegP newval, iRegPNoSp tmp, rFlagsReg cr)
418 %{
419 match(Set res (CompareAndExchangeP mem (Binary oldval newval)));
420 predicate(UseShenandoahGC && !needs_acquiring_load_exclusive(n) && n->as_LoadStore()->barrier_data() != 0);
421 effect(TEMP_DEF res, TEMP tmp, KILL cr);
422 format %{
423 "cmpxchg_shenandoah $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval"
424 %}
425 ins_encode %{
426 assert($mem$$index == -1 && $mem$$disp == 0, "impossible encoding");
427
428 ShenandoahBarrierSet::assembler()->compare_and_set_c2(this, masm,
429 $res$$Register,
430 $mem$$base$$Register,
431 $oldval$$Register,
432 $newval$$Register,
433 $tmp$$Register,
434 rscratch1,
435 rscratch2,
436 /* exchange = */ true,
437 /* narrow = */ false,
438 /* weak = */ false,
439 /* acquire = */ false);
440 %}
441 ins_cost(2*VOLATILE_REF_COST);
442 ins_pipe(pipe_slow);
443 %}
444
445 instruct compareAndExchange_P_A_shenandoah(iRegPNoSp res, indirect mem, iRegP oldval, iRegP newval, iRegPNoSp tmp, rFlagsReg cr)
446 %{
447 match(Set res (CompareAndExchangeP mem (Binary oldval newval)));
448 predicate(UseShenandoahGC && needs_acquiring_load_exclusive(n) && n->as_LoadStore()->barrier_data() != 0);
449 effect(TEMP_DEF res, TEMP tmp, KILL cr);
450 format %{
451 "cmpxchg_acq_shenandoah $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval"
452 %}
453 ins_encode %{
454 assert($mem$$index == -1 && $mem$$disp == 0, "impossible encoding");
455
456 ShenandoahBarrierSet::assembler()->compare_and_set_c2(this, masm,
457 $res$$Register,
458 $mem$$base$$Register,
459 $oldval$$Register,
460 $newval$$Register,
461 $tmp$$Register,
462 rscratch1,
463 rscratch2,
464 /* exchange = */ true,
465 /* narrow = */ false,
466 /* weak = */ false,
467 /* acquire = */ true);
468 %}
469 ins_cost(2*VOLATILE_REF_COST);
470 ins_pipe(pipe_slow);
471 %}
472
473 instruct weakCompareAndSwap_N_shenandoah(iRegINoSp res, indirect mem, iRegNNoSp oldval, iRegN newval, iRegPNoSp tmp, rFlagsReg cr)
474 %{
475 match(Set res (WeakCompareAndSwapN mem (Binary oldval newval)));
476 predicate(UseShenandoahGC && !needs_acquiring_load_exclusive(n) && n->as_LoadStore()->barrier_data() != 0);
477 effect(TEMP_DEF res, TEMP tmp, KILL cr);
478 format %{
479 "cmpxchgw_shenandoah $res = $mem, $oldval, $newval\t# (N, weak) if $mem == $oldval then $mem <-- $newval\n\t"
480 "csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)"
481 %}
482 ins_encode %{
483 assert($mem$$index == -1 && $mem$$disp == 0, "impossible encoding");
484
485 ShenandoahBarrierSet::assembler()->compare_and_set_c2(this, masm,
486 $res$$Register,
487 $mem$$base$$Register,
488 $oldval$$Register,
489 $newval$$Register,
490 $tmp$$Register,
491 rscratch1,
492 rscratch2,
493 /* exchange = */ false,
494 /* narrow = */ true,
495 /* weak = */ true,
496 /* acquire = */ false);
497 %}
498 ins_cost(VOLATILE_REF_COST);
499 ins_pipe(pipe_slow);
500 %}
501
502 instruct weakCompareAndSwap_N_A_shenandoah(iRegINoSp res, indirect mem, iRegNNoSp oldval, iRegN newval, iRegPNoSp tmp, rFlagsReg cr)
503 %{
504 match(Set res (WeakCompareAndSwapN mem (Binary oldval newval)));
505 predicate(UseShenandoahGC && needs_acquiring_load_exclusive(n) && n->as_LoadStore()->barrier_data() != 0);
506 effect(TEMP_DEF res, TEMP tmp, KILL cr);
507 format %{
508 "cmpxchgw_acq_shenandoah $res = $mem, $oldval, $newval\t# (N, weak) if $mem == $oldval then $mem <-- $newval\n\t"
509 "csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)"
510 %}
511 ins_encode %{
512 assert($mem$$index == -1 && $mem$$disp == 0, "impossible encoding");
513
514 ShenandoahBarrierSet::assembler()->compare_and_set_c2(this, masm,
515 $res$$Register,
516 $mem$$base$$Register,
517 $oldval$$Register,
518 $newval$$Register,
519 $tmp$$Register,
520 rscratch1,
521 rscratch2,
522 /* exchange = */ false,
523 /* narrow = */ true,
524 /* weak = */ true,
525 /* acquire = */ true);
526 %}
527 ins_cost(VOLATILE_REF_COST);
528 ins_pipe(pipe_slow);
529 %}
530
531 instruct weakCompareAndSwap_P_shenandoah(iRegINoSp res, indirect mem, iRegPNoSp oldval, iRegP newval, iRegPNoSp tmp, rFlagsReg cr)
532 %{
533 match(Set res (WeakCompareAndSwapP mem (Binary oldval newval)));
534 predicate(UseShenandoahGC && !needs_acquiring_load_exclusive(n) && n->as_LoadStore()->barrier_data() != 0);
535 effect(TEMP_DEF res, TEMP tmp, KILL cr);
536 format %{
537 "cmpxchg_shenandoah $res = $mem, $oldval, $newval\t# (P, weak) if $mem == $oldval then $mem <-- $newval\n\t"
538 "csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)"
539 %}
540 ins_encode %{
541 assert($mem$$index == -1 && $mem$$disp == 0, "impossible encoding");
542
543 ShenandoahBarrierSet::assembler()->compare_and_set_c2(this, masm,
544 $res$$Register,
545 $mem$$base$$Register,
546 $oldval$$Register,
547 $newval$$Register,
548 $tmp$$Register,
549 rscratch1,
550 rscratch2,
551 /* exchange = */ false,
552 /* narrow = */ false,
553 /* weak = */ true,
554 /* acquire = */ false);
555 %}
556 ins_cost(VOLATILE_REF_COST);
557 ins_pipe(pipe_slow);
558 %}
559
560 instruct weakCompareAndSwap_P_A_shenandoah(iRegINoSp res, indirect mem, iRegPNoSp oldval, iRegP newval, iRegPNoSp tmp, rFlagsReg cr)
561 %{
562 match(Set res (WeakCompareAndSwapP mem (Binary oldval newval)));
563 predicate(UseShenandoahGC && needs_acquiring_load_exclusive(n) && n->as_LoadStore()->barrier_data() != 0);
564 effect(TEMP_DEF res, TEMP tmp, KILL cr);
565 format %{
566 "cmpxchg_acq_shenandoah $res = $mem, $oldval, $newval\t# (P, weak) if $mem == $oldval then $mem <-- $newval\n\t"
567 "csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)"
568 %}
569 ins_encode %{
570 assert($mem$$index == -1 && $mem$$disp == 0, "impossible encoding");
571
572 ShenandoahBarrierSet::assembler()->compare_and_set_c2(this, masm,
573 $res$$Register,
574 $mem$$base$$Register,
575 $oldval$$Register,
576 $newval$$Register,
577 $tmp$$Register,
578 rscratch1,
579 rscratch2,
580 /* exchange = */ false,
581 /* narrow = */ false,
582 /* weak = */ true,
583 /* acquire */ true);
584 %}
585 ins_cost(VOLATILE_REF_COST);
586 ins_pipe(pipe_slow);
587 %}
588
589 instruct getAndSet_P_shenandoah(indirect mem, iRegP newval, iRegPNoSp preval, iRegPNoSp tmp, rFlagsReg cr)
590 %{
591 match(Set preval (GetAndSetP mem newval));
592 predicate(UseShenandoahGC && !needs_acquiring_load_exclusive(n) && n->as_LoadStore()->barrier_data() != 0);
593 effect(TEMP_DEF preval, TEMP tmp, KILL cr);
594 format %{ "atomic_xchg $preval, $newval, [$mem]" %}
595 ins_encode %{
596 ShenandoahBarrierSet::assembler()->get_and_set_c2(this, masm,
597 $preval$$Register,
598 $newval$$Register,
599 $mem$$Register,
600 $tmp$$Register,
601 rscratch1,
602 rscratch2,
603 /* acquire = */ false);
604 %}
605 ins_cost(2*VOLATILE_REF_COST);
606 ins_pipe(pipe_serial);
607 %}
608
609 instruct getAndSet_P_A_shenandoah(indirect mem, iRegP newval, iRegPNoSp preval, iRegPNoSp tmp, rFlagsReg cr)
610 %{
611 match(Set preval (GetAndSetP mem newval));
612 predicate(UseShenandoahGC && needs_acquiring_load_exclusive(n) && n->as_LoadStore()->barrier_data() != 0);
613 effect(TEMP_DEF preval, TEMP tmp, KILL cr);
614 format %{ "atomic_xchg_acq $preval, $newval, [$mem]" %}
615 ins_encode %{
616 ShenandoahBarrierSet::assembler()->get_and_set_c2(this, masm,
617 $preval$$Register,
618 $newval$$Register,
619 $mem$$Register,
620 $tmp$$Register,
621 rscratch1,
622 rscratch2,
623 /* acquire = */ true);
624 %}
625 ins_cost(2*VOLATILE_REF_COST);
626 ins_pipe(pipe_serial);
627 %}
628
629 instruct getAndSet_N_shenandoah(indirect mem, iRegN newval, iRegNNoSp preval, iRegPNoSp tmp, rFlagsReg cr)
630 %{
631 match(Set preval (GetAndSetN mem newval));
632 predicate(UseShenandoahGC && !needs_acquiring_load_exclusive(n) && n->as_LoadStore()->barrier_data() != 0);
633 effect(TEMP_DEF preval, TEMP tmp, KILL cr);
634 format %{ "atomic_xchgw $preval, $newval, [$mem]" %}
635 ins_encode %{
636 ShenandoahBarrierSet::assembler()->get_and_set_c2(this, masm,
637 $preval$$Register,
638 $newval$$Register,
639 $mem$$Register,
640 $tmp$$Register,
641 rscratch1,
642 rscratch2,
643 /* acquire = */ false);
644 %}
645 ins_cost(2*VOLATILE_REF_COST);
646 ins_pipe(pipe_serial);
647 %}
648
649 instruct getAndSet_N_A_shenandoah(indirect mem, iRegN newval, iRegNNoSp preval, iRegPNoSp tmp, rFlagsReg cr)
650 %{
651 match(Set preval (GetAndSetN mem newval));
652 predicate(UseShenandoahGC && needs_acquiring_load_exclusive(n) && n->as_LoadStore()->barrier_data() != 0);
653 effect(TEMP_DEF preval, TEMP tmp, KILL cr);
654 format %{ "atomic_xchgw_acq $preval, $newval, [$mem]" %}
655 ins_encode %{
656 ShenandoahBarrierSet::assembler()->get_and_set_c2(this, masm,
657 $preval$$Register,
658 $newval$$Register,
659 $mem$$Register,
660 $tmp$$Register,
661 rscratch1,
662 rscratch2,
663 /* acquire = */ true);
664 %}
665 ins_cost(2*VOLATILE_REF_COST);
666 ins_pipe(pipe_serial);
667 %}