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_hpp %{
  26 #include "gc/shenandoah/shenandoahBarrierSet.hpp"
  27 #include "gc/shenandoah/shenandoahBarrierSetAssembler.hpp"
  28 %}
  29 
  30 encode %{
  31   enc_class aarch64_enc_cmpxchg_oop_shenandoah(memory mem, iRegP oldval, iRegP newval, iRegPNoSp tmp, iRegINoSp res) %{
  32     MacroAssembler _masm(&cbuf);
  33     guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding");
  34     Register tmp = $tmp$$Register;
  35     __ mov(tmp, $oldval$$Register); // Must not clobber oldval.
  36     ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, $mem$$Register, tmp, $newval$$Register,
  37                                                    /*acquire*/ false, /*release*/ true, /*is_cae*/ false, $res$$Register);
  38   %}
  39 
  40   enc_class aarch64_enc_cmpxchg_acq_oop_shenandoah(memory mem, iRegP oldval, iRegP newval, iRegPNoSp tmp, iRegINoSp res) %{
  41     MacroAssembler _masm(&cbuf);
  42     guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding");
  43     Register tmp = $tmp$$Register;
  44     __ mov(tmp, $oldval$$Register); // Must not clobber oldval.
  45     ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, $mem$$Register, tmp, $newval$$Register,
  46                                                    /*acquire*/ true, /*release*/ true, /*is_cae*/ false, $res$$Register);
  47   %}
  48 %}
  49 
  50 instruct compareAndSwapP_shenandoah(iRegINoSp res, indirect mem, iRegP oldval, iRegP newval, iRegPNoSp tmp, rFlagsReg cr) %{
  51 
  52   match(Set res (ShenandoahCompareAndSwapP mem (Binary oldval newval)));
  53   ins_cost(2 * VOLATILE_REF_COST);
  54 
  55   effect(TEMP tmp, KILL cr);
  56 
  57   format %{
  58     "cmpxchg_shenandoah $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval with temp $tmp"
  59   %}
  60 
  61   ins_encode(aarch64_enc_cmpxchg_oop_shenandoah(mem, oldval, newval, tmp, res));
  62 
  63   ins_pipe(pipe_slow);
  64 %}
  65 
  66 instruct compareAndSwapN_shenandoah(iRegINoSp res, indirect mem, iRegN oldval, iRegN newval, iRegNNoSp tmp, rFlagsReg cr) %{
  67 
  68   match(Set res (ShenandoahCompareAndSwapN mem (Binary oldval newval)));
  69   ins_cost(2 * VOLATILE_REF_COST);
  70 
  71   effect(TEMP tmp, KILL cr);
  72 
  73   format %{
  74     "cmpxchgw_shenandoah $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval with temp $tmp"
  75   %}
  76 
  77   ins_encode %{
  78     Register tmp = $tmp$$Register;
  79     __ mov(tmp, $oldval$$Register); // Must not clobber oldval.
  80     ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, $mem$$Register, tmp, $newval$$Register, /*acquire*/ false, /*release*/ true, /*is_cae*/ false, $res$$Register);
  81   %}
  82 
  83   ins_pipe(pipe_slow);
  84 %}
  85 
  86 instruct compareAndSwapPAcq_shenandoah(iRegINoSp res, indirect mem, iRegP oldval, iRegP newval, iRegPNoSp tmp, rFlagsReg cr) %{
  87 
  88   predicate(needs_acquiring_load_exclusive(n));
  89   match(Set res (ShenandoahCompareAndSwapP mem (Binary oldval newval)));
  90   ins_cost(VOLATILE_REF_COST);
  91 
  92   effect(TEMP tmp, KILL cr);
  93 
  94   format %{
  95     "cmpxchg_acq_shenandoah_oop $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval with temp $tmp"
  96   %}
  97 
  98   ins_encode(aarch64_enc_cmpxchg_acq_oop_shenandoah(mem, oldval, newval, tmp, res));
  99 
 100   ins_pipe(pipe_slow);
 101 %}
 102 
 103 instruct compareAndSwapNAcq_shenandoah(iRegINoSp res, indirect mem, iRegN oldval, iRegN newval, iRegNNoSp tmp, rFlagsReg cr) %{
 104 
 105   predicate(needs_acquiring_load_exclusive(n));
 106   match(Set res (ShenandoahCompareAndSwapN mem (Binary oldval newval)));
 107   ins_cost(VOLATILE_REF_COST);
 108 
 109   effect(TEMP tmp, KILL cr);
 110 
 111  format %{
 112     "cmpxchgw_acq_shenandoah_narrow_oop $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval with temp $tmp"
 113  %}
 114 
 115   ins_encode %{
 116     Register tmp = $tmp$$Register;
 117     __ mov(tmp, $oldval$$Register); // Must not clobber oldval.
 118     ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, $mem$$Register, tmp, $newval$$Register, /*acquire*/ true, /*release*/ true, /*is_cae*/ false, $res$$Register);
 119   %}
 120 
 121   ins_pipe(pipe_slow);
 122 %}
 123 
 124 instruct compareAndExchangeN_shenandoah(iRegNNoSp res, indirect mem, iRegN oldval, iRegN newval, iRegNNoSp tmp, rFlagsReg cr) %{
 125   match(Set res (ShenandoahCompareAndExchangeN mem (Binary oldval newval)));
 126   ins_cost(2 * VOLATILE_REF_COST);
 127   effect(TEMP_DEF res, TEMP tmp, KILL cr);
 128   format %{
 129     "cmpxchgw_shenandoah $res = $mem, $oldval, $newval\t# (narrow oop, weak) if $mem == $oldval then $mem <-- $newval"
 130   %}
 131   ins_encode %{
 132     Register tmp = $tmp$$Register;
 133     __ mov(tmp, $oldval$$Register); // Must not clobber oldval.
 134     ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, $mem$$Register, tmp, $newval$$Register,
 135                                                    /*acquire*/ false, /*release*/ true, /*is_cae*/ true, $res$$Register);
 136   %}
 137   ins_pipe(pipe_slow);
 138 %}
 139 
 140 instruct compareAndExchangeP_shenandoah(iRegPNoSp res, indirect mem, iRegP oldval, iRegP newval, iRegPNoSp tmp, rFlagsReg cr) %{
 141   match(Set res (ShenandoahCompareAndExchangeP mem (Binary oldval newval)));
 142   ins_cost(2 * VOLATILE_REF_COST);
 143   effect(TEMP_DEF res, TEMP tmp, KILL cr);
 144   format %{
 145     "cmpxchg_shenandoah $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval with temp $tmp"
 146   %}
 147   ins_encode %{
 148     Register tmp = $tmp$$Register;
 149     __ mov(tmp, $oldval$$Register); // Must not clobber oldval.
 150     ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, $mem$$Register, tmp, $newval$$Register,
 151                                                    /*acquire*/ false, /*release*/ true, /*is_cae*/ true, $res$$Register);
 152   %}
 153   ins_pipe(pipe_slow);
 154 %}
 155 
 156 instruct compareAndExchangeNAcq_shenandoah(iRegNNoSp res, indirect mem, iRegN oldval, iRegN newval, iRegNNoSp tmp, rFlagsReg cr) %{
 157   predicate(needs_acquiring_load_exclusive(n));
 158   match(Set res (ShenandoahCompareAndExchangeN mem (Binary oldval newval)));
 159   ins_cost(VOLATILE_REF_COST);
 160   effect(TEMP_DEF res, TEMP tmp, KILL cr);
 161   format %{
 162     "cmpxchgw_acq_shenandoah $res = $mem, $oldval, $newval\t# (narrow oop, weak) if $mem == $oldval then $mem <-- $newval"
 163   %}
 164   ins_encode %{
 165     Register tmp = $tmp$$Register;
 166     __ mov(tmp, $oldval$$Register); // Must not clobber oldval.
 167     ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, $mem$$Register, tmp, $newval$$Register,
 168                                                    /*acquire*/ true, /*release*/ true, /*is_cae*/ true, $res$$Register);
 169   %}
 170   ins_pipe(pipe_slow);
 171 %}
 172 
 173 instruct compareAndExchangePAcq_shenandoah(iRegPNoSp res, indirect mem, iRegP oldval, iRegP newval, iRegPNoSp tmp, rFlagsReg cr) %{
 174   predicate(needs_acquiring_load_exclusive(n));
 175   match(Set res (ShenandoahCompareAndExchangeP mem (Binary oldval newval)));
 176   ins_cost(VOLATILE_REF_COST);
 177   effect(TEMP_DEF res, TEMP tmp, KILL cr);
 178   format %{
 179     "cmpxchg_acq_shenandoah $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval with temp $tmp"
 180   %}
 181   ins_encode %{
 182     Register tmp = $tmp$$Register;
 183     __ mov(tmp, $oldval$$Register); // Must not clobber oldval.
 184     ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, $mem$$Register, tmp, $newval$$Register,
 185                                                    /*acquire*/ true, /*release*/ true, /*is_cae*/ true, $res$$Register);
 186   %}
 187   ins_pipe(pipe_slow);
 188 %}
 189 
 190 instruct weakCompareAndSwapN_shenandoah(iRegINoSp res, indirect mem, iRegN oldval, iRegN newval, iRegNNoSp tmp, rFlagsReg cr) %{
 191   match(Set res (ShenandoahWeakCompareAndSwapN mem (Binary oldval newval)));
 192   ins_cost(2 * VOLATILE_REF_COST);
 193   effect(TEMP tmp, KILL cr);
 194   format %{
 195     "cmpxchgw_shenandoah $res = $mem, $oldval, $newval\t# (narrow oop, weak) if $mem == $oldval then $mem <-- $newval"
 196     "csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)"
 197   %}
 198   ins_encode %{
 199     Register tmp = $tmp$$Register;
 200     __ mov(tmp, $oldval$$Register); // Must not clobber oldval.
 201     // Weak is not currently supported by ShenandoahBarrierSet::cmpxchg_oop
 202     ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, $mem$$Register, tmp, $newval$$Register,
 203                                                    /*acquire*/ false, /*release*/ true, /*is_cae*/ false, $res$$Register);
 204   %}
 205   ins_pipe(pipe_slow);
 206 %}
 207 
 208 instruct weakCompareAndSwapP_shenandoah(iRegINoSp res, indirect mem, iRegP oldval, iRegP newval, iRegPNoSp tmp, rFlagsReg cr) %{
 209   match(Set res (ShenandoahWeakCompareAndSwapP mem (Binary oldval newval)));
 210   ins_cost(2 * VOLATILE_REF_COST);
 211   effect(TEMP tmp, KILL cr);
 212   format %{
 213     "cmpxchg_shenandoah $res = $mem, $oldval, $newval\t# (ptr, weak) if $mem == $oldval then $mem <-- $newval"
 214   %}
 215   ins_encode %{
 216     Register tmp = $tmp$$Register;
 217     __ mov(tmp, $oldval$$Register); // Must not clobber oldval.
 218     // Weak is not currently supported by ShenandoahBarrierSet::cmpxchg_oop
 219     ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, $mem$$Register, tmp, $newval$$Register,
 220                                                    /*acquire*/ false, /*release*/ true, /*is_cae*/ false, $res$$Register);
 221   %}
 222   ins_pipe(pipe_slow);
 223 %}
 224 
 225 instruct weakCompareAndSwapNAcq_shenandoah(iRegINoSp res, indirect mem, iRegN oldval, iRegN newval, iRegNNoSp tmp, rFlagsReg cr) %{
 226   predicate(needs_acquiring_load_exclusive(n));
 227   match(Set res (ShenandoahWeakCompareAndSwapN mem (Binary oldval newval)));
 228   ins_cost(VOLATILE_REF_COST);
 229   effect(TEMP tmp, KILL cr);
 230   format %{
 231     "cmpxchgw_acq_shenandoah $res = $mem, $oldval, $newval\t# (narrow oop, weak) if $mem == $oldval then $mem <-- $newval"
 232     "csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)"
 233   %}
 234   ins_encode %{
 235     Register tmp = $tmp$$Register;
 236     __ mov(tmp, $oldval$$Register); // Must not clobber oldval.
 237     // Weak is not currently supported by ShenandoahBarrierSet::cmpxchg_oop
 238     ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, $mem$$Register, tmp, $newval$$Register,
 239                                                    /*acquire*/ true, /*release*/ true, /*is_cae*/ false, $res$$Register);
 240   %}
 241   ins_pipe(pipe_slow);
 242 %}
 243 
 244 instruct weakCompareAndSwapPAcq_shenandoah(iRegINoSp res, indirect mem, iRegP oldval, iRegP newval, iRegPNoSp tmp, rFlagsReg cr) %{
 245   predicate(needs_acquiring_load_exclusive(n));
 246   match(Set res (ShenandoahWeakCompareAndSwapP mem (Binary oldval newval)));
 247   ins_cost(VOLATILE_REF_COST);
 248   effect(TEMP tmp, KILL cr);
 249   format %{
 250     "cmpxchg_acq_shenandoah $res = $mem, $oldval, $newval\t# (ptr, weak) if $mem == $oldval then $mem <-- $newval"
 251     "csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)"
 252   %}
 253   ins_encode %{
 254     Register tmp = $tmp$$Register;
 255     __ mov(tmp, $oldval$$Register); // Must not clobber oldval.
 256     // Weak is not currently supported by ShenandoahBarrierSet::cmpxchg_oop
 257     ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, $mem$$Register, tmp, $newval$$Register,
 258                                                    /*acquire*/ true, /*release*/ true, /*is_cae*/ false, $res$$Register);
 259   %}
 260   ins_pipe(pipe_slow);
 261 %}