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 %}