1 //
   2 // Copyright (c) 2019, Oracle and/or its affiliates. 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 source_hpp %{
  25 
  26 #include "gc/z/c2/zBarrierSetC2.hpp"
  27 
  28 %}
  29 
  30 source %{
  31 
  32 #include "gc/z/zBarrierSetAssembler.hpp"
  33 
  34 static void z_load_barrier_slow_reg(MacroAssembler& _masm, Register dst, 
  35                                     Register base, int index, int scale, 
  36                                     int disp, bool weak) {
  37   const address stub = weak ? ZBarrierSet::assembler()->load_barrier_weak_slow_stub(dst)
  38                             : ZBarrierSet::assembler()->load_barrier_slow_stub(dst);
  39 
  40   if (index == -1) {
  41     if (disp != 0) {
  42       __ lea(dst, Address(base, disp));
  43     } else {
  44        __ mov(dst, base);
  45     }
  46   } else {
  47     Register index_reg = as_Register(index);
  48     if (disp == 0) {
  49       __ lea(dst, Address(base, index_reg, Address::lsl(scale)));
  50     } else {
  51       __ lea(dst, Address(base, disp));
  52       __ lea(dst, Address(dst, index_reg, Address::lsl(scale)));
  53     }
  54   }
  55 
  56   __ far_call(RuntimeAddress(stub));
  57 }
  58 
  59 %}
  60 
  61 //
  62 // Execute ZGC load barrier (strong) slow path
  63 //
  64 instruct loadBarrierSlowReg(iRegP dst, memory src, rFlagsReg cr,
  65     vRegD_V0 v0, vRegD_V1 v1, vRegD_V2 v2, vRegD_V3 v3, vRegD_V4 v4,
  66     vRegD_V5 v5, vRegD_V6 v6, vRegD_V7 v7, vRegD_V8 v8, vRegD_V9 v9,
  67     vRegD_V10 v10, vRegD_V11 v11, vRegD_V12 v12, vRegD_V13 v13, vRegD_V14 v14,
  68     vRegD_V15 v15, vRegD_V16 v16, vRegD_V17 v17, vRegD_V18 v18, vRegD_V19 v19,
  69     vRegD_V20 v20, vRegD_V21 v21, vRegD_V22 v22, vRegD_V23 v23, vRegD_V24 v24,
  70     vRegD_V25 v25, vRegD_V26 v26, vRegD_V27 v27, vRegD_V28 v28, vRegD_V29 v29,
  71     vRegD_V30 v30, vRegD_V31 v31) %{
  72   match(Set dst (LoadBarrierSlowReg src dst));
  73   predicate(!n->as_LoadBarrierSlowReg()->is_weak());
  74 
  75   effect(KILL cr,
  76      KILL v0, KILL v1, KILL v2, KILL v3, KILL v4, KILL v5, KILL v6, KILL v7,
  77      KILL v8, KILL v9, KILL v10, KILL v11, KILL v12, KILL v13, KILL v14,
  78      KILL v15, KILL v16, KILL v17, KILL v18, KILL v19, KILL v20, KILL v21,
  79      KILL v22, KILL v23, KILL v24, KILL v25, KILL v26, KILL v27, KILL v28,
  80      KILL v29, KILL v30, KILL v31);
  81 
  82   format %{ "lea $dst, $src\n\t"
  83             "call #ZLoadBarrierSlowPath" %}
  84 
  85   ins_encode %{
  86     z_load_barrier_slow_reg(_masm, $dst$$Register, $src$$base$$Register,
  87                             $src$$index, $src$$scale, $src$$disp, false);
  88   %}
  89   ins_pipe(pipe_slow);
  90 %}
  91 
  92 //
  93 // Execute ZGC load barrier (weak) slow path
  94 //
  95 instruct loadBarrierWeakSlowReg(iRegP dst, memory src, rFlagsReg cr,
  96     vRegD_V0 v0, vRegD_V1 v1, vRegD_V2 v2, vRegD_V3 v3, vRegD_V4 v4,
  97     vRegD_V5 v5, vRegD_V6 v6, vRegD_V7 v7, vRegD_V8 v8, vRegD_V9 v9,
  98     vRegD_V10 v10, vRegD_V11 v11, vRegD_V12 v12, vRegD_V13 v13, vRegD_V14 v14,
  99     vRegD_V15 v15, vRegD_V16 v16, vRegD_V17 v17, vRegD_V18 v18, vRegD_V19 v19,
 100     vRegD_V20 v20, vRegD_V21 v21, vRegD_V22 v22, vRegD_V23 v23, vRegD_V24 v24,
 101     vRegD_V25 v25, vRegD_V26 v26, vRegD_V27 v27, vRegD_V28 v28, vRegD_V29 v29,
 102     vRegD_V30 v30, vRegD_V31 v31) %{
 103   match(Set dst (LoadBarrierSlowReg src dst));
 104   predicate(n->as_LoadBarrierSlowReg()->is_weak());
 105 
 106   effect(KILL cr,
 107      KILL v0, KILL v1, KILL v2, KILL v3, KILL v4, KILL v5, KILL v6, KILL v7,
 108      KILL v8, KILL v9, KILL v10, KILL v11, KILL v12, KILL v13, KILL v14,
 109      KILL v15, KILL v16, KILL v17, KILL v18, KILL v19, KILL v20, KILL v21,
 110      KILL v22, KILL v23, KILL v24, KILL v25, KILL v26, KILL v27, KILL v28,
 111      KILL v29, KILL v30, KILL v31);
 112 
 113   format %{ "lea $dst, $src\n\t"
 114             "call #ZLoadBarrierSlowPath" %}
 115 
 116   ins_encode %{
 117     z_load_barrier_slow_reg(_masm, $dst$$Register, $src$$base$$Register,
 118                             $src$$index, $src$$scale, $src$$disp, true);
 119   %}
 120   ins_pipe(pipe_slow);
 121 %}
 122 
 123 
 124 // Specialized versions of compareAndExchangeP that adds a keepalive that is consumed
 125 // but doesn't affect output.
 126 
 127 instruct z_compareAndExchangeP(iRegPNoSp res, indirect mem,
 128                                iRegP oldval, iRegP newval, iRegP keepalive,
 129                                rFlagsReg cr) %{
 130   match(Set res (ZCompareAndExchangeP (Binary mem keepalive) (Binary oldval newval)));
 131   ins_cost(2 * VOLATILE_REF_COST);
 132   effect(TEMP_DEF res, KILL cr);
 133   format %{
 134     "cmpxchg $res = $mem, $oldval, $newval\t# (ptr, weak) if $mem == $oldval then $mem <-- $newval"
 135   %}
 136   ins_encode %{
 137     __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register,
 138                Assembler::xword, /*acquire*/ false, /*release*/ true,
 139                /*weak*/ false, $res$$Register);
 140   %}
 141   ins_pipe(pipe_slow);
 142 %}
 143 
 144 instruct z_compareAndSwapP(iRegINoSp res,
 145                            indirect mem,
 146                            iRegP oldval, iRegP newval, iRegP keepalive,
 147                             rFlagsReg cr) %{
 148 
 149   match(Set res (ZCompareAndSwapP (Binary mem keepalive) (Binary oldval newval)));
 150   match(Set res (ZWeakCompareAndSwapP (Binary mem keepalive) (Binary oldval newval)));
 151 
 152   ins_cost(2 * VOLATILE_REF_COST);
 153 
 154   effect(KILL cr);
 155 
 156  format %{
 157     "cmpxchg $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval"
 158     "cset $res, EQ\t# $res <-- (EQ ? 1 : 0)"
 159  %}
 160 
 161  ins_encode(aarch64_enc_cmpxchg(mem, oldval, newval),
 162             aarch64_enc_cset_eq(res));
 163 
 164   ins_pipe(pipe_slow);
 165 %}
 166 
 167 
 168 instruct z_get_and_setP(indirect mem, iRegP newv, iRegPNoSp prev,
 169                         iRegP keepalive) %{
 170   match(Set prev (ZGetAndSetP mem (Binary newv keepalive)));
 171 
 172   ins_cost(2 * VOLATILE_REF_COST);
 173   format %{ "atomic_xchg  $prev, $newv, [$mem]" %}
 174   ins_encode %{
 175     __ atomic_xchg($prev$$Register, $newv$$Register, as_Register($mem$$base));
 176   %}
 177   ins_pipe(pipe_serial);
 178 %}