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 #include "gc/shenandoah/c2/shenandoahBarrierSetC2.hpp"
 29 %}
 30 
 31 instruct store_P_Normal_shenandoah(memory8 mem, iRegP src, iRegPNoSp tmp, rFlagsReg cr)
 32 %{
 33   match(Set mem (StoreP mem src));
 34   predicate(UseShenandoahGC && !needs_releasing_store(n) && n->as_Store()->barrier_data() != 0);
 35   effect(TEMP tmp, KILL cr);
 36   format %{ "str $src, $mem" %}
 37   ins_encode %{
 38     const Address addr = mem2address($mem->opcode(), as_Register($mem$$base), $mem$$index, $mem$$scale, $mem$$disp);
 39     ShenandoahBarrierSet::assembler()->store_c2(this, masm,
 40       addr,           /* dst_narrow  = */ false,
 41       $src$$Register, /* src_narrow  = */ false,
 42       $tmp$$Register, /* is_volatile = */ false);
 43   %}
 44   ins_cost(3*INSN_COST);
 45   ins_pipe(pipe_class_memory);
 46 %}
 47 
 48 instruct store_P_Volatile_shenandoah(indirect mem, iRegP src, iRegPNoSp tmp, rFlagsReg cr)
 49 %{
 50   match(Set mem (StoreP mem src));
 51   predicate(UseShenandoahGC && needs_releasing_store(n) && n->as_Store()->barrier_data() != 0);
 52   effect(TEMP tmp, KILL cr);
 53   format %{ "str $src, $mem" %}
 54   ins_encode %{
 55     ShenandoahBarrierSet::assembler()->store_c2(this, masm,
 56       Address($mem$$Register),    /* dst_narrow  = */ false,
 57       $src$$Register,             /* src_narrow  = */ false,
 58       $tmp$$Register,             /* is_volatile = */ true);
 59   %}
 60   ins_cost(VOLATILE_REF_COST);
 61   ins_pipe(pipe_class_memory);
 62 %}
 63 
 64 instruct store_N_Normal_shenandoah(memory4 mem, iRegN src, iRegPNoSp tmp, rFlagsReg cr)
 65 %{
 66   match(Set mem (StoreN mem src));
 67   predicate(UseShenandoahGC && !needs_releasing_store(n) && n->as_Store()->barrier_data() != 0);
 68   effect(TEMP tmp, KILL cr);
 69   format %{ "str $src, $mem" %}
 70   ins_encode %{
 71     const Address addr = mem2address($mem->opcode(), as_Register($mem$$base), $mem$$index, $mem$$scale, $mem$$disp);
 72     ShenandoahBarrierSet::assembler()->store_c2(this, masm,
 73       addr,           /* dst_narrow  = */ true,
 74       $src$$Register, /* src_narrow  = */ true,
 75       $tmp$$Register, /* is_volatile = */ false);
 76   %}
 77   ins_cost(3*INSN_COST);
 78   ins_pipe(pipe_class_memory);
 79 %}
 80 
 81 instruct store_N_Volatile_shenandoah(indirect mem, iRegN src, iRegPNoSp tmp, rFlagsReg cr)
 82 %{
 83   match(Set mem (StoreN mem src));
 84   predicate(UseShenandoahGC && needs_releasing_store(n) && n->as_Store()->barrier_data() != 0);
 85   effect(TEMP tmp, KILL cr);
 86   format %{ "str $src, $mem" %}
 87   ins_encode %{
 88     ShenandoahBarrierSet::assembler()->store_c2(this, masm,
 89       Address($mem$$Register),    /* dst_narrow  = */ true,
 90       $src$$Register,             /* src_narrow  = */ true,
 91       $tmp$$Register,             /* is_volatile = */ true);
 92   %}
 93   ins_cost(VOLATILE_REF_COST);
 94   ins_pipe(pipe_class_memory);
 95 %}
 96 
 97 instruct encodePAndStoreN_Normal_shenandoah(memory4 mem, iRegP src, iRegPNoSp tmp, rFlagsReg cr)
 98 %{
 99   match(Set mem (StoreN mem (EncodeP src)));
100   predicate(UseShenandoahGC && !needs_releasing_store(n) && n->as_Store()->barrier_data() != 0);
101   effect(TEMP tmp, KILL cr);
102   format %{ "encode_heap_oop tmp, $src\n\t"
103             "str  tmp, $mem\t# compressed ptr" %}
104   ins_encode %{
105     const Address addr = mem2address($mem->opcode(), as_Register($mem$$base), $mem$$index, $mem$$scale, $mem$$disp);
106     ShenandoahBarrierSet::assembler()->store_c2(this, masm,
107       addr,                    /* dst_narrow  = */ true,
108       $src$$Register,          /* src_narrow  = */ false,
109       $tmp$$Register,          /* is_volatile = */ false);
110   %}
111   ins_cost(4*INSN_COST);
112   ins_pipe(pipe_class_memory);
113 %}
114 
115 instruct encodePAndStoreN_Volatile_shenandoah(indirect mem, iRegP src, iRegPNoSp tmp, rFlagsReg cr)
116 %{
117   match(Set mem (StoreN mem (EncodeP src)));
118   predicate(UseShenandoahGC && needs_releasing_store(n) && n->as_Store()->barrier_data() != 0);
119   effect(TEMP tmp, KILL cr);
120   format %{ "encode_heap_oop tmp, $src\n\t"
121             "str  tmp, $mem\t# compressed ptr" %}
122   ins_encode %{
123     ShenandoahBarrierSet::assembler()->store_c2(this, masm,
124       Address($mem$$Register), /* dst_narrow  = */ true,
125       $src$$Register,          /* src_narrow  = */ false,
126       $tmp$$Register,          /* is_volatile = */ true);
127   %}
128   ins_cost(4*INSN_COST);
129   ins_pipe(pipe_class_memory);
130 %}
131 
132 instruct compareAndSwap_P_shenandoah(iRegINoSp res, indirect mem, iRegPNoSp oldval, iRegP newval, iRegPNoSp tmp, rFlagsReg cr)
133 %{
134   match(Set res (CompareAndSwapP mem (Binary oldval newval)));
135   predicate(UseShenandoahGC && !needs_acquiring_load_exclusive(n) && n->as_LoadStore()->barrier_data() != 0);
136   effect(TEMP_DEF res, TEMP tmp, KILL cr);
137   format %{
138     "cmpxchg_P_shenandoah $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval"
139   %}
140   ins_encode %{
141     guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding");
142 
143     ShenandoahBarrierSet::assembler()->compare_and_set_c2(this, masm,
144       $res$$Register,
145       $mem$$base$$Register,
146       $oldval$$Register,
147       $newval$$Register,
148       $tmp$$Register,
149       /* exchange */ false,
150       /* is_narrow */ false,
151       /* weak */ false,
152       /* acquire */ false);
153   %}
154   ins_cost(VOLATILE_REF_COST);
155   ins_pipe(pipe_slow);
156 %}
157 
158 instruct compareAndSwap_P_A_shenandoah(iRegINoSp res, indirect mem, iRegPNoSp oldval, iRegP newval, iRegPNoSp tmp, rFlagsReg cr)
159 %{
160   match(Set res (CompareAndSwapP mem (Binary oldval newval)));
161   predicate(UseShenandoahGC && needs_acquiring_load_exclusive(n) && n->as_LoadStore()->barrier_data() != 0);
162   effect(TEMP_DEF res, TEMP tmp, KILL cr);
163   format %{
164     "cmpxchg_P_shenandoah $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval"
165   %}
166   ins_encode %{
167     guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding");
168 
169     ShenandoahBarrierSet::assembler()->compare_and_set_c2(this, masm,
170       $res$$Register,
171       $mem$$base$$Register,
172       $oldval$$Register,
173       $newval$$Register,
174       $tmp$$Register,
175       /* exchange */ false,
176       /* is_narrow */ false,
177       /* weak */ false,
178       /* acquire */ true);
179   %}
180   ins_cost(VOLATILE_REF_COST);
181   ins_pipe(pipe_slow);
182 %}
183 
184 instruct compareAndSwap_N_shenandoah(iRegINoSp res, indirect mem, iRegNNoSp oldval, iRegN newval, iRegPNoSp tmp, rFlagsReg cr)
185 %{
186   match(Set res (CompareAndSwapN mem (Binary oldval newval)));
187   predicate(UseShenandoahGC && !needs_acquiring_load_exclusive(n) && n->as_LoadStore()->barrier_data() != 0);
188   effect(TEMP_DEF res, TEMP tmp, KILL cr);
189   format %{
190     "cmpxchg_N_shenandoah $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval"
191   %}
192   ins_encode %{
193     guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding");
194 
195     ShenandoahBarrierSet::assembler()->compare_and_set_c2(this, masm,
196       $res$$Register,
197       $mem$$base$$Register,
198       $oldval$$Register,
199       $newval$$Register,
200       $tmp$$Register,
201       /* exchange */ false,
202       /* is_narrow */ true,
203       /* weak */ false,
204       /* acquire */ false);
205   %}
206   ins_cost(VOLATILE_REF_COST);
207   ins_pipe(pipe_slow);
208 %}
209 
210 instruct compareAndSwap_N_A_shenandoah(iRegINoSp res, indirect mem, iRegNNoSp oldval, iRegN newval, iRegPNoSp tmp, rFlagsReg cr)
211 %{
212   match(Set res (CompareAndSwapN mem (Binary oldval newval)));
213   predicate(UseShenandoahGC && needs_acquiring_load_exclusive(n) && n->as_LoadStore()->barrier_data() != 0);
214   effect(TEMP_DEF res, TEMP tmp, KILL cr);
215   format %{
216     "cmpxchg_N_shenandoah $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval"
217   %}
218   ins_encode %{
219     guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding");
220 
221     ShenandoahBarrierSet::assembler()->compare_and_set_c2(this, masm,
222       $res$$Register,
223       $mem$$base$$Register,
224       $oldval$$Register,
225       $newval$$Register,
226       $tmp$$Register,
227       /* exchange */ false,
228       /* is_narrow */ true,
229       /* weak */ false,
230       /* acquire */ true);
231   %}
232   ins_cost(VOLATILE_REF_COST);
233   ins_pipe(pipe_slow);
234 %}
235 
236 instruct compareAndExchange_N_shenandoah(iRegNNoSp res, indirect mem, iRegN oldval, iRegN newval, iRegPNoSp tmp, rFlagsReg cr)
237 %{
238   match(Set res (CompareAndExchangeN mem (Binary oldval newval)));
239   predicate(UseShenandoahGC && !needs_acquiring_load_exclusive(n) && n->as_LoadStore()->barrier_data() != 0);
240   effect(TEMP_DEF res, TEMP tmp, KILL cr);
241   format %{
242     "cae_N_shenandoah $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval"
243   %}
244   ins_encode %{
245     guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding");
246 
247     ShenandoahBarrierSet::assembler()->compare_and_set_c2(this, masm,
248       $res$$Register,
249       $mem$$base$$Register,
250       $oldval$$Register,
251       $newval$$Register,
252       $tmp$$Register,
253       /* exchange */ true,
254       /* is_narrow */ true,
255       /* weak */ false,
256       /* acquire */ false);
257   %}
258   ins_cost(2*VOLATILE_REF_COST);
259   ins_pipe(pipe_slow);
260 %}
261 
262 instruct compareAndExchange_N_A_shenandoah(iRegNNoSp res, indirect mem, iRegN oldval, iRegN newval, iRegPNoSp tmp, rFlagsReg cr)
263 %{
264   match(Set res (CompareAndExchangeN mem (Binary oldval newval)));
265   predicate(UseShenandoahGC && needs_acquiring_load_exclusive(n) && n->as_LoadStore()->barrier_data() != 0);
266   effect(TEMP_DEF res, TEMP tmp, KILL cr);
267   format %{
268     "cae_N_shenandoah $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval"
269   %}
270   ins_encode %{
271     guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding");
272 
273     ShenandoahBarrierSet::assembler()->compare_and_set_c2(this, masm,
274       $res$$Register,
275       $mem$$base$$Register,
276       $oldval$$Register,
277       $newval$$Register,
278       $tmp$$Register,
279       /* exchange */ true,
280       /* is_narrow */ true,
281       /* weak */ false,
282       /* acquire */ true);
283   %}
284   ins_cost(2*VOLATILE_REF_COST);
285   ins_pipe(pipe_slow);
286 %}
287 
288 instruct compareAndExchange_P_shenandoah(iRegPNoSp res, indirect mem, iRegP oldval, iRegP newval, iRegPNoSp tmp, rFlagsReg cr)
289 %{
290   match(Set res (CompareAndExchangeP mem (Binary oldval newval)));
291   predicate(UseShenandoahGC && !needs_acquiring_load_exclusive(n) && n->as_LoadStore()->barrier_data() != 0);
292   effect(TEMP_DEF res, TEMP tmp, KILL cr);
293   format %{
294     "cae_P_shenandoah $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval"
295   %}
296   ins_encode %{
297     guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding");
298 
299     ShenandoahBarrierSet::assembler()->compare_and_set_c2(this, masm,
300       $res$$Register,
301       $mem$$base$$Register,
302       $oldval$$Register,
303       $newval$$Register,
304       $tmp$$Register,
305       /* exchange */ true,
306       /* is_narrow */ false,
307       /* weak */ false,
308       /* acquire */ false);
309   %}
310   ins_cost(2*VOLATILE_REF_COST);
311   ins_pipe(pipe_slow);
312 %}
313 
314 instruct compareAndExchange_P_A_shenandoah(iRegPNoSp res, indirect mem, iRegP oldval, iRegP newval, iRegPNoSp tmp, rFlagsReg cr)
315 %{
316   match(Set res (CompareAndExchangeP mem (Binary oldval newval)));
317   predicate(UseShenandoahGC && needs_acquiring_load_exclusive(n) && n->as_LoadStore()->barrier_data() != 0);
318   effect(TEMP_DEF res, TEMP tmp, KILL cr);
319   format %{
320     "cae_P_shenandoah $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval"
321   %}
322   ins_encode %{
323     guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding");
324 
325     ShenandoahBarrierSet::assembler()->compare_and_set_c2(this, masm,
326       $res$$Register,
327       $mem$$base$$Register,
328       $oldval$$Register,
329       $newval$$Register,
330       $tmp$$Register,
331       /* exchange */ true,
332       /* is_narrow */ false,
333       /* weak */ false,
334       /* acquire */ true);
335   %}
336   ins_cost(2*VOLATILE_REF_COST);
337   ins_pipe(pipe_slow);
338 %}
339 
340 instruct weakCompareAndSwap_N_shenandoah(iRegINoSp res, indirect mem, iRegNNoSp oldval, iRegN newval, iRegPNoSp tmp, rFlagsReg cr)
341 %{
342   match(Set res (WeakCompareAndSwapN mem (Binary oldval newval)));
343   predicate(UseShenandoahGC && !needs_acquiring_load_exclusive(n) && n->as_LoadStore()->barrier_data() != 0);
344   effect(TEMP_DEF res, TEMP tmp, KILL cr);
345   format %{
346     "cae_N_weak_shenandoah $res = $mem, $oldval, $newval\t# (N, weak) if $mem == $oldval then $mem <-- $newval\n\t"
347     "csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)"
348   %}
349   ins_encode %{
350     guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding");
351 
352     ShenandoahBarrierSet::assembler()->compare_and_set_c2(this, masm,
353       $res$$Register,
354       $mem$$base$$Register,
355       $oldval$$Register,
356       $newval$$Register,
357       $tmp$$Register,
358       /* exchange */ false,
359       /* is_narrow */ true,
360       /* weak */ true,
361       /* acquire */ false);
362   %}
363   ins_cost(VOLATILE_REF_COST);
364   ins_pipe(pipe_slow);
365 %}
366 
367 instruct weakCompareAndSwap_N_A_shenandoah(iRegINoSp res, indirect mem, iRegNNoSp oldval, iRegN newval, iRegPNoSp tmp, rFlagsReg cr)
368 %{
369   match(Set res (WeakCompareAndSwapN mem (Binary oldval newval)));
370   predicate(UseShenandoahGC && needs_acquiring_load_exclusive(n) && n->as_LoadStore()->barrier_data() != 0);
371   effect(TEMP_DEF res, TEMP tmp, KILL cr);
372   format %{
373     "cae_N_weak_shenandoah $res = $mem, $oldval, $newval\t# (N, weak) if $mem == $oldval then $mem <-- $newval\n\t"
374     "csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)"
375   %}
376   ins_encode %{
377     guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding");
378 
379     ShenandoahBarrierSet::assembler()->compare_and_set_c2(this, masm,
380       $res$$Register,
381       $mem$$base$$Register,
382       $oldval$$Register,
383       $newval$$Register,
384       $tmp$$Register,
385       /* exchange */ false,
386       /* is_narrow */ true,
387       /* weak */ true,
388       /* acquire */ true);
389   %}
390   ins_cost(VOLATILE_REF_COST);
391   ins_pipe(pipe_slow);
392 %}
393 
394 instruct weakCompareAndSwap_P_shenandoah(iRegINoSp res, indirect mem, iRegPNoSp oldval, iRegP newval, iRegPNoSp tmp, rFlagsReg cr)
395 %{
396   match(Set res (WeakCompareAndSwapP mem (Binary oldval newval)));
397   predicate(UseShenandoahGC && !needs_acquiring_load_exclusive(n) && n->as_LoadStore()->barrier_data() != 0);
398   effect(TEMP_DEF res, TEMP tmp, KILL cr);
399   format %{
400     "cae_P_weak_shenandoah $res = $mem, $oldval, $newval\t# (P, weak) if $mem == $oldval then $mem <-- $newval\n\t"
401     "csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)"
402   %}
403   ins_encode %{
404     guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding");
405 
406     ShenandoahBarrierSet::assembler()->compare_and_set_c2(this, masm,
407       $res$$Register,
408       $mem$$base$$Register,
409       $oldval$$Register,
410       $newval$$Register,
411       $tmp$$Register,
412       /* exchange */ false,
413       /* is_narrow */ false,
414       /* weak */ true,
415       /* acquire */ false);
416   %}
417   ins_cost(VOLATILE_REF_COST);
418   ins_pipe(pipe_slow);
419 %}
420 
421 instruct weakCompareAndSwap_P_A_shenandoah(iRegINoSp res, indirect mem, iRegPNoSp oldval, iRegP newval, iRegPNoSp tmp, rFlagsReg cr)
422 %{
423   match(Set res (WeakCompareAndSwapP mem (Binary oldval newval)));
424   predicate(UseShenandoahGC && needs_acquiring_load_exclusive(n) && n->as_LoadStore()->barrier_data() != 0);
425   effect(TEMP_DEF res, TEMP tmp, KILL cr);
426   format %{
427     "cae_P_weak_shenandoah $res = $mem, $oldval, $newval\t# (P, weak) if $mem == $oldval then $mem <-- $newval\n\t"
428     "csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)"
429   %}
430   ins_encode %{
431     guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding");
432 
433     ShenandoahBarrierSet::assembler()->compare_and_set_c2(this, masm,
434       $res$$Register,
435       $mem$$base$$Register,
436       $oldval$$Register,
437       $newval$$Register,
438       $tmp$$Register,
439       /* exchange */ false,
440       /* is_narrow */ false,
441       /* weak */ true,
442       /* acquire */ true);
443   %}
444   ins_cost(VOLATILE_REF_COST);
445   ins_pipe(pipe_slow);
446 %}
447 
448 instruct getAndSet_P_shenandoah(indirect mem, iRegP newval, iRegPNoSp preval, iRegPNoSp tmp,  rFlagsReg cr)
449 %{
450   match(Set preval (GetAndSetP mem newval));
451   predicate(UseShenandoahGC && !needs_acquiring_load_exclusive(n) && n->as_LoadStore()->barrier_data() != 0);
452   effect(TEMP_DEF preval, TEMP tmp, KILL cr);
453   format %{ "get_and_set_P $preval, $newval, [$mem]" %}
454   ins_encode %{
455     ShenandoahBarrierSet::assembler()->get_and_set_c2(this, masm,
456       $preval$$Register,
457       $newval$$Register,
458       $mem$$Register,
459       $tmp$$Register,
460       /* acquire */ false);
461   %}
462   ins_cost(2*VOLATILE_REF_COST);
463   ins_pipe(pipe_serial);
464 %}
465 
466 instruct getAndSet_P_A_shenandoah(indirect mem, iRegP newval, iRegPNoSp preval, iRegPNoSp tmp,  rFlagsReg cr)
467 %{
468   match(Set preval (GetAndSetP mem newval));
469   predicate(UseShenandoahGC && needs_acquiring_load_exclusive(n) && n->as_LoadStore()->barrier_data() != 0);
470   effect(TEMP_DEF preval, TEMP tmp, KILL cr);
471   format %{ "get_and_set_P $preval, $newval, [$mem]" %}
472   ins_encode %{
473     ShenandoahBarrierSet::assembler()->get_and_set_c2(this, masm,
474       $preval$$Register,
475       $newval$$Register,
476       $mem$$Register,
477       $tmp$$Register,
478       /* acquire */ true);
479   %}
480   ins_cost(2*VOLATILE_REF_COST);
481   ins_pipe(pipe_serial);
482 %}
483 
484 instruct getAndSet_N_shenandoah(indirect mem, iRegN newval, iRegNNoSp preval, iRegPNoSp tmp, rFlagsReg cr)
485 %{
486   match(Set preval (GetAndSetN mem newval));
487   predicate(UseShenandoahGC && !needs_acquiring_load_exclusive(n) && n->as_LoadStore()->barrier_data() != 0);
488   effect(TEMP_DEF preval, TEMP tmp, KILL cr);
489   format %{ "get_and_set_N $preval, $newval, [$mem]" %}
490   ins_encode %{
491     ShenandoahBarrierSet::assembler()->get_and_set_c2(this, masm,
492       $preval$$Register,
493       $newval$$Register,
494       $mem$$Register,
495       $tmp$$Register,
496       /* acquire */ false);
497   %}
498   ins_cost(2*VOLATILE_REF_COST);
499   ins_pipe(pipe_serial);
500 %}
501 
502 instruct getAndSet_N_A_shenandoah(indirect mem, iRegN newval, iRegNNoSp preval, iRegPNoSp tmp, rFlagsReg cr)
503 %{
504   match(Set preval (GetAndSetN mem newval));
505   predicate(UseShenandoahGC && needs_acquiring_load_exclusive(n) && n->as_LoadStore()->barrier_data() != 0);
506   effect(TEMP_DEF preval, TEMP tmp, KILL cr);
507   format %{ "get_and_set_N $preval, $newval, [$mem]" %}
508   ins_encode %{
509     ShenandoahBarrierSet::assembler()->get_and_set_c2(this, masm,
510       $preval$$Register,
511       $newval$$Register,
512       $mem$$Register,
513       $tmp$$Register,
514       /* acquire */ true);
515   %}
516   ins_cost(2*VOLATILE_REF_COST);
517   ins_pipe(pipe_serial);
518 %}
519 
520 instruct load_P_Normal_shenandoah(iRegPNoSp dst, memory8 mem, iRegPNoSp tmp, rFlagsReg cr)
521 %{
522   match(Set dst (LoadP mem));
523   predicate(UseShenandoahGC && !needs_acquiring_load(n) && n->as_Load()->barrier_data() != 0);
524   effect(TEMP_DEF dst, TEMP tmp, KILL cr);
525   // The main load is a candidate to implement implicit null checks.
526   ins_is_late_expanded_null_check_candidate(true);
527   format %{ "ldr  $dst, $mem\t# ptr" %}
528   ins_encode %{
529     Address addr = mem2address($mem->opcode(), as_Register($mem$$base), $mem$$index, $mem$$scale, $mem$$disp);
530     if (addr.getMode() == Address::base_plus_offset) {
531       addr = __ legitimize_address(addr, /* size_in_memory */ 8, $tmp$$Register);
532     }
533     ShenandoahBarrierSet::assembler()->load_c2(this, masm, $dst$$Register, addr, /* is_narrow */ false, /* is_acquire */ false);
534   %}
535   ins_cost(3*INSN_COST);
536   ins_pipe(pipe_class_memory);
537 %}
538 
539 instruct load_P_Volatile_shenandoah(iRegPNoSp dst, indirect mem, rFlagsReg cr)
540 %{
541   match(Set dst (LoadP mem));
542   predicate(UseShenandoahGC && needs_acquiring_load(n) && n->as_Load()->barrier_data() != 0);
543   effect(TEMP_DEF dst, KILL cr);
544   // The main load is a candidate to implement implicit null checks.
545   ins_is_late_expanded_null_check_candidate(true);
546   format %{ "ldr  $dst, $mem\t# ptr" %}
547   ins_encode %{
548     ShenandoahBarrierSet::assembler()->load_c2(this, masm, $dst$$Register, Address($mem$$Register), /* is_narrow */ false, /* is_acquire */ true);
549   %}
550   ins_cost(3*INSN_COST);
551   ins_pipe(pipe_class_memory);
552 %}
553 
554 instruct load_N_Normal_shenandoah(iRegNNoSp dst, memory4 mem, iRegPNoSp tmp, rFlagsReg cr)
555 %{
556   match(Set dst (LoadN mem));
557   predicate(UseShenandoahGC && !needs_acquiring_load(n) && n->as_Load()->barrier_data() != 0);
558   effect(TEMP_DEF dst, TEMP tmp, KILL cr);
559   // The main load is a candidate to implement implicit null checks.
560   ins_is_late_expanded_null_check_candidate(true);
561   format %{ "ldrw  $dst, $mem\t# ptr" %}
562   ins_encode %{
563     Address addr = mem2address($mem->opcode(), as_Register($mem$$base), $mem$$index, $mem$$scale, $mem$$disp);
564     if (addr.getMode() == Address::base_plus_offset) {
565       addr = __ legitimize_address(addr, /* size_in_memory */ 4, $tmp$$Register);
566     }
567     ShenandoahBarrierSet::assembler()->load_c2(this, masm, $dst$$Register, addr, /* is_narrow */ true, /* is_acquire */ false);
568   %}
569   ins_cost(3*INSN_COST);
570   ins_pipe(pipe_class_memory);
571 %}
572 
573 instruct load_N_Volatile_shenandoah(iRegNNoSp dst, indirect mem, rFlagsReg cr)
574 %{
575   match(Set dst (LoadN mem));
576   predicate(UseShenandoahGC && needs_acquiring_load(n) && n->as_Load()->barrier_data() != 0);
577   effect(TEMP_DEF dst, KILL cr);
578   // The main load is a candidate to implement implicit null checks.
579   ins_is_late_expanded_null_check_candidate(true);
580   format %{ "ldrw  $dst, $mem\t# ptr" %}
581   ins_encode %{
582     ShenandoahBarrierSet::assembler()->load_c2(this, masm, $dst$$Register, Address($mem$$Register), /* is_narrow */ true, /* is_acquire */ true);
583   %}
584   ins_cost(VOLATILE_REF_COST);
585   ins_pipe(pipe_class_memory);
586 %}
587