diff a/src/hotspot/cpu/riscv/gc/shenandoah/shenandoah_riscv.ad b/src/hotspot/cpu/riscv/gc/shenandoah/shenandoah_riscv.ad
--- a/src/hotspot/cpu/riscv/gc/shenandoah/shenandoah_riscv.ad
+++ b/src/hotspot/cpu/riscv/gc/shenandoah/shenandoah_riscv.ad
@@ -21,265 +21,314 @@
 // or visit www.oracle.com if you need additional information or have any
 // questions.
 //
 //
 
-source_hpp %{
+source %{
 #include "gc/shenandoah/shenandoahBarrierSet.hpp"
-#include "gc/shenandoah/shenandoahBarrierSetAssembler.hpp"
+#include "gc/shenandoah/shenandoahBarrierSetAssembler_riscv.hpp"
+#include "gc/shenandoah/c2/shenandoahBarrierSetC2.hpp"
 %}
 
-instruct compareAndSwapP_shenandoah(iRegINoSp res, indirect mem, iRegP oldval, iRegP newval, iRegPNoSp tmp, rFlagsReg cr) %{
-  match(Set res (ShenandoahCompareAndSwapP mem (Binary oldval newval)));
-  ins_cost(10 * DEFAULT_COST);
+// Load Pointer
+instruct loadP_shenandoah(iRegPNoSp dst, memory mem)
+%{
+  match(Set dst (LoadP mem));
+  predicate(UseShenandoahGC && n->as_Load()->barrier_data() != 0);
 
-  effect(TEMP tmp, KILL cr);
+  effect(TEMP_DEF dst);
+  ins_is_late_expanded_null_check_candidate(true);
 
-  format %{
-    "cmpxchg_shenandoah $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval with temp $tmp, #@compareAndSwapP_shenandoah"
+  ins_cost(3 * LOAD_COST);
+  format %{ "ld  $dst, $mem\t# ptr, shenandoah late-barrier, #@loadP_shenandoah" %}
+
+  ins_encode %{
+    ShenandoahBarrierSet::assembler()->load_c2(this, masm, as_Register($dst$$reg),
+                                               Address(as_Register($mem$$base), $mem$$disp));
   %}
 
+  ins_pipe(iload_reg_mem);
+%}
+
+// Load Compressed Pointer
+instruct loadN_shenandoah(iRegNNoSp dst, memory mem)
+%{
+  match(Set dst (LoadN mem));
+  predicate(UseShenandoahGC && n->as_Load()->barrier_data() != 0);
+
+  effect(TEMP_DEF dst);
+  ins_is_late_expanded_null_check_candidate(true);
+
+  ins_cost(3 * LOAD_COST);
+  format %{ "lwu  $dst, $mem\t# compressed ptr, shenandoah late-barrier, #@loadN_shenandoah" %}
+
   ins_encode %{
-    Register tmp = $tmp$$Register;
-    __ mv(tmp, $oldval$$Register); // Must not clobber oldval.
-    ShenandoahBarrierSet::assembler()->cmpxchg_oop(masm, $mem$$Register, tmp, $newval$$Register,
-                                                   Assembler::relaxed /* acquire */, Assembler::rl /* release */,
-                                                   false /* is_cae */, $res$$Register);
+    ShenandoahBarrierSet::assembler()->load_c2(this, masm, as_Register($dst$$reg),
+                                               Address(as_Register($mem$$base), $mem$$disp));
   %}
 
-  ins_pipe(pipe_slow);
+  ins_pipe(iload_reg_mem);
 %}
 
-instruct compareAndSwapN_shenandoah(iRegINoSp res, indirect mem, iRegN oldval, iRegN newval, iRegNNoSp tmp, rFlagsReg cr) %{
-  match(Set res (ShenandoahCompareAndSwapN mem (Binary oldval newval)));
-  ins_cost(10 * DEFAULT_COST);
+// Store Pointer
+instruct storeP_shenandoah(memory mem, iRegP src, iRegPNoSp tmp, rFlagsReg cr)
+%{
+  match(Set mem (StoreP mem src));
+  predicate(UseShenandoahGC && n->as_Store()->barrier_data() != 0);
 
   effect(TEMP tmp, KILL cr);
 
-  format %{
-    "cmpxchgw_shenandoah $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval with temp $tmp, #@compareAndSwapN_shenandoah"
-  %}
+  ins_cost(3 * STORE_COST);
+  format %{ "sd  $src, $mem\t# ptr, shenandoah late-barrier, #@storeP_shenandoah" %}
 
   ins_encode %{
-    Register tmp = $tmp$$Register;
-    __ mv(tmp, $oldval$$Register); // Must not clobber oldval.
-    ShenandoahBarrierSet::assembler()->cmpxchg_oop(masm, $mem$$Register, tmp, $newval$$Register,
-                                                   Assembler::relaxed /* acquire */, Assembler::rl /* release */,
-                                                   false /* is_cae */, $res$$Register);
+    ShenandoahBarrierSet::assembler()->store_c2(this, masm,
+                                                Address(as_Register($mem$$base), $mem$$disp),
+                                                /* dst_narrow = */ false,
+                                                as_Register($src$$reg),
+                                                /* src_narrow = */ false,
+                                                as_Register($tmp$$reg));
   %}
 
-  ins_pipe(pipe_slow);
+  ins_pipe(istore_reg_mem);
 %}
 
-instruct compareAndSwapPAcq_shenandoah(iRegINoSp res, indirect mem, iRegP oldval, iRegP newval, iRegPNoSp tmp, rFlagsReg cr) %{
-  predicate(needs_acquiring_load_reserved(n));
-  match(Set res (ShenandoahCompareAndSwapP mem (Binary oldval newval)));
-  ins_cost(10 * DEFAULT_COST);
+// Store Compressed Pointer
+instruct storeN_shenandoah(memory mem, iRegN src, iRegNNoSp tmp, rFlagsReg cr)
+%{
+  match(Set mem (StoreN mem src));
+  predicate(UseShenandoahGC && n->as_Store()->barrier_data() != 0);
 
   effect(TEMP tmp, KILL cr);
 
-  format %{
-    "cmpxchg_acq_shenandoah_oop $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval with temp $tmp, #@compareAndSwapPAcq_shenandoah"
-  %}
+  ins_cost(3 * STORE_COST);
+  format %{ "sw  $src, $mem\t# compressed ptr, shenandoah late-barrier, #@storeN_shenandoah" %}
 
   ins_encode %{
-    Register tmp = $tmp$$Register;
-    __ mv(tmp, $oldval$$Register); // Must not clobber oldval.
-    ShenandoahBarrierSet::assembler()->cmpxchg_oop(masm, $mem$$Register, tmp, $newval$$Register,
-                                                   Assembler::aq /* acquire */, Assembler::rl /* release */,
-                                                   false /* is_cae */, $res$$Register);
+    ShenandoahBarrierSet::assembler()->store_c2(this, masm,
+                                                Address(as_Register($mem$$base), $mem$$disp),
+                                                /* dst_narrow = */ true,
+                                                as_Register($src$$reg),
+                                                /* src_narrow = */ true,
+                                                as_Register($tmp$$reg));
   %}
 
-  ins_pipe(pipe_slow);
+  ins_pipe(istore_reg_mem);
 %}
 
-instruct compareAndSwapNAcq_shenandoah(iRegINoSp res, indirect mem, iRegN oldval, iRegN newval, iRegNNoSp tmp, rFlagsReg cr) %{
-  predicate(needs_acquiring_load_reserved(n));
-  match(Set res (ShenandoahCompareAndSwapN mem (Binary oldval newval)));
-  ins_cost(10 * DEFAULT_COST);
+// Encode and Store Compressed Pointer
+instruct encodePAndStoreN_shenandoah(memory mem, iRegP src, iRegPNoSp tmp, rFlagsReg cr)
+%{
+  match(Set mem (StoreN mem (EncodeP src)));
+  predicate(UseShenandoahGC && n->as_Store()->barrier_data() != 0);
 
   effect(TEMP tmp, KILL cr);
 
+  ins_cost(4 * STORE_COST);
   format %{
-    "cmpxchgw_acq_shenandoah_narrow_oop $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval with temp $tmp, #@compareAndSwapNAcq_shenandoah"
+    "encode_heap_oop $tmp, $src\n\t"
+    "sw  $tmp, $mem\t# compressed ptr, shenandoah late-barrier, #@encodePAndStoreN_shenandoah"
   %}
 
   ins_encode %{
-    Register tmp = $tmp$$Register;
-    __ mv(tmp, $oldval$$Register); // Must not clobber oldval.
-    ShenandoahBarrierSet::assembler()->cmpxchg_oop(masm, $mem$$Register, tmp, $newval$$Register,
-                                                   Assembler::aq /* acquire */, Assembler::rl /* release */,
-                                                   false /* is_cae */, $res$$Register);
+    ShenandoahBarrierSet::assembler()->store_c2(this, masm,
+                                                Address(as_Register($mem$$base), $mem$$disp),
+                                                /* dst_narrow = */ true,
+                                                as_Register($src$$reg),
+                                                /* src_narrow = */ false,
+                                                as_Register($tmp$$reg));
   %}
 
-  ins_pipe(pipe_slow);
+  ins_pipe(istore_reg_mem);
 %}
 
-instruct compareAndExchangeN_shenandoah(iRegNNoSp res, indirect mem, iRegN oldval, iRegN newval, iRegNNoSp tmp, rFlagsReg cr) %{
-  match(Set res (ShenandoahCompareAndExchangeN mem (Binary oldval newval)));
+instruct compareAndSwap_P_shenandoah(iRegINoSp res, indirect mem, iRegPNoSp oldval, iRegP newval, iRegPNoSp tmp, rFlagsReg cr) %{
+  match(Set res (CompareAndSwapP mem (Binary oldval newval)));
+  predicate(UseShenandoahGC && n->as_LoadStore()->barrier_data() != 0);
   ins_cost(10 * DEFAULT_COST);
+
   effect(TEMP_DEF res, TEMP tmp, KILL cr);
 
   format %{
-    "cmpxchgw_shenandoah $res = $mem, $oldval, $newval\t# (narrow oop, weak) if $mem == $oldval then $mem <-- $newval, #@compareAndExchangeN_shenandoah"
+    "cmpxchg_P_shenandoah $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval, #@compareAndSwap_P_shenandoah"
   %}
 
   ins_encode %{
-    Register tmp = $tmp$$Register;
-    __ mv(tmp, $oldval$$Register); // Must not clobber oldval.
-    ShenandoahBarrierSet::assembler()->cmpxchg_oop(masm, $mem$$Register, tmp, $newval$$Register,
-                                                   Assembler::relaxed /* acquire */, Assembler::rl /* release */,
-                                                   true /* is_cae */, $res$$Register);
+    ShenandoahBarrierSet::assembler()->compare_and_set_c2(this, masm,
+                                                          as_Register($res$$reg),
+                                                          as_Register($mem$$base),
+                                                          as_Register($oldval$$reg),
+                                                          as_Register($newval$$reg),
+                                                          as_Register($tmp$$reg),
+                                                          /* exchange */ false,
+                                                          /* maybe_null */ true,
+                                                          /* is_narrow */ false,
+                                                          /* weak */ false);
   %}
 
   ins_pipe(pipe_slow);
 %}
 
-instruct compareAndExchangeP_shenandoah(iRegPNoSp res, indirect mem, iRegP oldval, iRegP newval, iRegPNoSp tmp, rFlagsReg cr) %{
-  match(Set res (ShenandoahCompareAndExchangeP mem (Binary oldval newval)));
+instruct compareAndSwap_N_shenandoah(iRegINoSp res, indirect mem, iRegNNoSp oldval, iRegN newval, iRegNNoSp tmp, rFlagsReg cr) %{
+  match(Set res (CompareAndSwapN mem (Binary oldval newval)));
+  predicate(UseShenandoahGC && n->as_LoadStore()->barrier_data() != 0);
   ins_cost(10 * DEFAULT_COST);
 
   effect(TEMP_DEF res, TEMP tmp, KILL cr);
+
   format %{
-    "cmpxchg_shenandoah $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval with temp $tmp, #@compareAndExchangeP_shenandoah"
+    "cmpxchg_N_shenandoah $mem, $oldval, $newval\t# (narrow ptr) if $mem == $oldval then $mem <-- $newval, #@compareAndSwap_N_shenandoah"
   %}
 
   ins_encode %{
-    Register tmp = $tmp$$Register;
-    __ mv(tmp, $oldval$$Register); // Must not clobber oldval.
-    ShenandoahBarrierSet::assembler()->cmpxchg_oop(masm, $mem$$Register, tmp, $newval$$Register,
-                                                   Assembler::relaxed /* acquire */, Assembler::rl /* release */,
-                                                   true /* is_cae */, $res$$Register);
+    ShenandoahBarrierSet::assembler()->compare_and_set_c2(this, masm,
+                                                          as_Register($res$$reg),
+                                                          as_Register($mem$$base),
+                                                          as_Register($oldval$$reg),
+                                                          as_Register($newval$$reg),
+                                                          as_Register($tmp$$reg),
+                                                          /* exchange */ false,
+                                                          /* maybe_null */ true,
+                                                          /* is_narrow */ true,
+                                                          /* weak */ false);
   %}
 
   ins_pipe(pipe_slow);
 %}
 
-instruct weakCompareAndSwapN_shenandoah(iRegINoSp res, indirect mem, iRegN oldval, iRegN newval, iRegNNoSp tmp, rFlagsReg cr) %{
-  match(Set res (ShenandoahWeakCompareAndSwapN mem (Binary oldval newval)));
+instruct compareAndExchange_N_shenandoah(iRegNNoSp res, indirect mem, iRegN oldval, iRegN newval, iRegNNoSp tmp, rFlagsReg cr) %{
+  match(Set res (CompareAndExchangeN mem (Binary oldval newval)));
+  predicate(UseShenandoahGC && n->as_LoadStore()->barrier_data() != 0);
   ins_cost(10 * DEFAULT_COST);
+  effect(TEMP_DEF res, TEMP tmp, KILL cr);
 
-  effect(TEMP tmp, KILL cr);
   format %{
-    "cmpxchgw_shenandoah $res = $mem, $oldval, $newval\t# (narrow oop, weak) if $mem == $oldval then $mem <-- $newval, #@weakCompareAndSwapN_shenandoah"
-    "mv $res, EQ\t# $res <-- (EQ ? 1 : 0)"
+    "cae_N_shenandoah $res = $mem, $oldval, $newval\t# (narrow oop) if $mem == $oldval then $mem <-- $newval, #@compareAndExchange_N_shenandoah"
   %}
 
   ins_encode %{
-    Register tmp = $tmp$$Register;
-    __ mv(tmp, $oldval$$Register); // Must not clobber oldval.
-    // Weak is not current supported by ShenandoahBarrierSet::cmpxchg_oop
-    ShenandoahBarrierSet::assembler()->cmpxchg_oop(masm, $mem$$Register, tmp, $newval$$Register,
-                                                   Assembler::relaxed /* acquire */, Assembler::rl /* release */,
-                                                   false /* is_cae */, $res$$Register);
+    ShenandoahBarrierSet::assembler()->compare_and_set_c2(this, masm,
+                                                          as_Register($res$$reg),
+                                                          as_Register($mem$$base),
+                                                          as_Register($oldval$$reg),
+                                                          as_Register($newval$$reg),
+                                                          as_Register($tmp$$reg),
+                                                          /* exchange */ true,
+                                                          /* maybe_null */ (this->bottom_type()->make_ptr()->ptr() != TypePtr::NotNull),
+                                                          /* is_narrow */ true,
+                                                          /* weak */ false);
   %}
 
   ins_pipe(pipe_slow);
 %}
 
-instruct compareAndExchangeNAcq_shenandoah(iRegNNoSp res, indirect mem, iRegN oldval, iRegN newval, iRegNNoSp tmp, rFlagsReg cr) %{
-  predicate(needs_acquiring_load_reserved(n));
-  match(Set res (ShenandoahCompareAndExchangeN mem (Binary oldval newval)));
+instruct compareAndExchange_P_shenandoah(iRegPNoSp res, indirect mem, iRegP oldval, iRegP newval, iRegPNoSp tmp, rFlagsReg cr) %{
+  match(Set res (CompareAndExchangeP mem (Binary oldval newval)));
+  predicate(UseShenandoahGC && n->as_LoadStore()->barrier_data() != 0);
   ins_cost(10 * DEFAULT_COST);
 
   effect(TEMP_DEF res, TEMP tmp, KILL cr);
   format %{
-    "cmpxchgw_acq_shenandoah $res = $mem, $oldval, $newval\t# (narrow oop, weak) if $mem == $oldval then $mem <-- $newval, #@compareAndExchangeNAcq_shenandoah"
+    "cae_P_shenandoah $res = $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval, #@compareAndExchange_P_shenandoah"
   %}
 
   ins_encode %{
-    Register tmp = $tmp$$Register;
-    __ mv(tmp, $oldval$$Register);
-    ShenandoahBarrierSet::assembler()->cmpxchg_oop(masm, $mem$$Register, tmp, $newval$$Register,
-                                                   Assembler::aq /* acquire */, Assembler::rl /* release */,
-                                                   true /* is_cae */, $res$$Register);
+    ShenandoahBarrierSet::assembler()->compare_and_set_c2(this, masm,
+                                                          as_Register($res$$reg),
+                                                          as_Register($mem$$base),
+                                                          as_Register($oldval$$reg),
+                                                          as_Register($newval$$reg),
+                                                          as_Register($tmp$$reg),
+                                                          /* exchange */ true,
+                                                          /* maybe_null */ (this->bottom_type()->make_ptr()->ptr() != TypePtr::NotNull),
+                                                          /* is_narrow */ false,
+                                                          /* weak */ false);
   %}
 
   ins_pipe(pipe_slow);
 %}
 
-instruct compareAndExchangePAcq_shenandoah(iRegPNoSp res, indirect mem, iRegP oldval, iRegP newval, iRegPNoSp tmp, rFlagsReg cr) %{
-  predicate(needs_acquiring_load_reserved(n));
-  match(Set res (ShenandoahCompareAndExchangeP mem (Binary oldval newval)));
+instruct weakCompareAndSwap_N_shenandoah(iRegINoSp res, indirect mem, iRegNNoSp oldval, iRegN newval, iRegNNoSp tmp, rFlagsReg cr) %{
+  match(Set res (WeakCompareAndSwapN mem (Binary oldval newval)));
+  predicate(UseShenandoahGC && n->as_LoadStore()->barrier_data() != 0);
   ins_cost(10 * DEFAULT_COST);
 
   effect(TEMP_DEF res, TEMP tmp, KILL cr);
   format %{
-    "cmpxchg_acq_shenandoah $res = $mem, $oldval, $newval\t# (narrow oop, weak) if $mem == $oldval then $mem <-- $newval, #@compareAndExchangePAcq_shenandoah"
+    "cae_N_weak_shenandoah $res = $mem, $oldval, $newval\t# (N, weak) if $mem == $oldval then $mem <-- $newval, #@weakCompareAndSwap_N_shenandoah"
   %}
 
   ins_encode %{
-    Register tmp = $tmp$$Register;
-    __ mv(tmp, $oldval$$Register);
-    ShenandoahBarrierSet::assembler()->cmpxchg_oop(masm, $mem$$Register, tmp, $newval$$Register,
-                                                   Assembler::aq /* acquire */, Assembler::rl /* release */,
-                                                   true /* is_cae */, $res$$Register);
+    ShenandoahBarrierSet::assembler()->compare_and_set_c2(this, masm,
+                                                          as_Register($res$$reg),
+                                                          as_Register($mem$$base),
+                                                          as_Register($oldval$$reg),
+                                                          as_Register($newval$$reg),
+                                                          as_Register($tmp$$reg),
+                                                          /* exchange */ false,
+                                                          /* maybe_null */ true,
+                                                          /* is_narrow */ true,
+                                                          /* weak */ true);
   %}
 
   ins_pipe(pipe_slow);
 %}
 
-instruct weakCompareAndSwapP_shenandoah(iRegINoSp res, indirect mem, iRegP oldval, iRegP newval, iRegPNoSp tmp, rFlagsReg cr) %{
-  match(Set res (ShenandoahWeakCompareAndSwapP mem (Binary oldval newval)));
+instruct weakCompareAndSwap_P_shenandoah(iRegINoSp res, indirect mem, iRegPNoSp oldval, iRegP newval, iRegPNoSp tmp, rFlagsReg cr) %{
+  match(Set res (WeakCompareAndSwapP mem (Binary oldval newval)));
+  predicate(UseShenandoahGC && n->as_LoadStore()->barrier_data() != 0);
   ins_cost(10 * DEFAULT_COST);
 
-  effect(TEMP tmp, KILL cr);
+  effect(TEMP_DEF res, TEMP tmp, KILL cr);
   format %{
-    "cmpxchg_shenandoah $res = $mem, $oldval, $newval\t# (ptr, weak) if $mem == $oldval then $mem <-- $newval, #@weakCompareAndSwapP_shenandoah"
+    "cae_P_weak_shenandoah $res = $mem, $oldval, $newval\t# (P, weak) if $mem == $oldval then $mem <-- $newval, #@weakCompareAndSwap_P_shenandoah"
   %}
 
   ins_encode %{
-    Register tmp = $tmp$$Register;
-    __ mv(tmp, $oldval$$Register); // Must not clobber oldval.
-    ShenandoahBarrierSet::assembler()->cmpxchg_oop(masm, $mem$$Register, tmp, $newval$$Register,
-                                                   Assembler::relaxed /* acquire */, Assembler::rl /* release */,
-                                                   false /* is_cae */, $res$$Register);
+    ShenandoahBarrierSet::assembler()->compare_and_set_c2(this, masm,
+                                                          as_Register($res$$reg),
+                                                          as_Register($mem$$base),
+                                                          as_Register($oldval$$reg),
+                                                          as_Register($newval$$reg),
+                                                          as_Register($tmp$$reg),
+                                                          /* exchange */ false,
+                                                          /* maybe_null */ true,
+                                                          /* is_narrow */ false,
+                                                          /* weak */ true);
   %}
 
   ins_pipe(pipe_slow);
 %}
 
-instruct weakCompareAndSwapNAcq_shenandoah(iRegINoSp res, indirect mem, iRegN oldval, iRegN newval, iRegNNoSp tmp, rFlagsReg cr) %{
-  predicate(needs_acquiring_load_reserved(n));
-  match(Set res (ShenandoahWeakCompareAndSwapN mem (Binary oldval newval)));
+instruct getAndSet_P_shenandoah(indirect mem, iRegP newval, iRegPNoSp preval, iRegPNoSp tmp, rFlagsReg cr)
+%{
+  match(Set preval (GetAndSetP mem newval));
+  predicate(UseShenandoahGC && n->as_LoadStore()->barrier_data() != 0);
+  effect(TEMP_DEF preval, TEMP tmp, KILL cr);
   ins_cost(10 * DEFAULT_COST);
-
-  effect(TEMP tmp, KILL cr);
-  format %{
-    "cmpxchgw_acq_shenandoah $res = $mem, $oldval, $newval\t# (ptr, weak) if $mem == $oldval then $mem <-- $newval, #@weakCompareAndSwapNAcq_shenandoah"
-    "mv $res, EQ\t# $res <-- (EQ ? 1 : 0)"
-  %}
-
+  format %{ "get_and_set_P $preval, $newval, [$mem], #@getAndSet_P_shenandoah" %}
   ins_encode %{
-    Register tmp = $tmp$$Register;
-    __ mv(tmp, $oldval$$Register); // Must not clobber oldval.
-    // Weak is not current supported by ShenandoahBarrierSet::cmpxchg_oop
-    ShenandoahBarrierSet::assembler()->cmpxchg_oop(masm, $mem$$Register, tmp, $newval$$Register,
-                                                   Assembler::aq /* acquire */, Assembler::rl /* release */,
-                                                   false /* is_cae */, $res$$Register);
+    ShenandoahBarrierSet::assembler()->get_and_set_c2(this, masm,
+                                                      as_Register($preval$$reg),
+                                                      as_Register($newval$$reg),
+                                                      as_Register($mem$$base),
+                                                      as_Register($tmp$$reg));
   %}
-
   ins_pipe(pipe_slow);
 %}
 
-instruct weakCompareAndSwapPAcq_shenandoah(iRegINoSp res, indirect mem, iRegP oldval, iRegP newval, iRegPNoSp tmp, rFlagsReg cr) %{
-  predicate(needs_acquiring_load_reserved(n));
-  match(Set res (ShenandoahWeakCompareAndSwapP mem (Binary oldval newval)));
+instruct getAndSet_N_shenandoah(indirect mem, iRegN newval, iRegNNoSp preval, iRegNNoSp tmp, rFlagsReg cr)
+%{
+  match(Set preval (GetAndSetN mem newval));
+  predicate(UseShenandoahGC && n->as_LoadStore()->barrier_data() != 0);
+  effect(TEMP_DEF preval, TEMP tmp, KILL cr);
   ins_cost(10 * DEFAULT_COST);
-
-  effect(TEMP tmp, KILL cr);
-  format %{
-    "cmpxchg_acq_shenandoah $res = $mem, $oldval, $newval\t# (ptr, weak) if $mem == $oldval then $mem <-- $newval, #@weakCompareAndSwapPAcq_shenandoah"
-    "mv $res, EQ\t# $res <-- (EQ ? 1 : 0)"
-  %}
-
+  format %{ "get_and_set_N $preval, $newval, [$mem], #@getAndSet_N_shenandoah" %}
   ins_encode %{
-    Register tmp = $tmp$$Register;
-    __ mv(tmp, $oldval$$Register); // Must not clobber oldval.
-    // Weak is not current supported by ShenandoahBarrierSet::cmpxchg_oop
-    ShenandoahBarrierSet::assembler()->cmpxchg_oop(masm, $mem$$Register, tmp, $newval$$Register,
-                                                   Assembler::aq /* acquire */, Assembler::rl /* release */,
-                                                   false /* is_cae */, $res$$Register);
+    ShenandoahBarrierSet::assembler()->get_and_set_c2(this, masm,
+                                                      as_Register($preval$$reg),
+                                                      as_Register($newval$$reg),
+                                                      as_Register($mem$$base),
+                                                      as_Register($tmp$$reg));
   %}
-
   ins_pipe(pipe_slow);
 %}
