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