1 // 2 // Copyright (c) 2018, Red Hat, Inc. All rights reserved. 3 // 4 // This code is free software; you can redistribute it and/or modify it 5 // under the terms of the GNU General Public License version 2 only, as 6 // published by the Free Software Foundation. 7 // 8 // This code is distributed in the hope that it will be useful, but WITHOUT 9 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 11 // version 2 for more details (a copy is included in the LICENSE file that 12 // accompanied this code). 13 // 14 // You should have received a copy of the GNU General Public License version 15 // 2 along with this work; if not, write to the Free Software Foundation, 16 // Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 17 // 18 // Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 19 // or visit www.oracle.com if you need additional information or have any 20 // questions. 21 // 22 // 23 24 source_hpp %{ 25 #include "gc/shenandoah/shenandoahBarrierSetAssembler.hpp" 26 %} 27 28 encode %{ 29 enc_class aarch64_enc_cmpxchg_oop_shenandoah(memory mem, iRegP oldval, iRegP newval, iRegPNoSp tmp) %{ 30 MacroAssembler _masm(&cbuf); 31 guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding"); 32 Register tmp = $tmp$$Register; 33 __ mov(tmp, $oldval$$Register); // Must not clobber oldval. 34 ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, $mem$$Register, tmp, $newval$$Register, 35 /*acquire*/ false, /*release*/ true, /*weak*/ false, /*encode*/ false, noreg, noreg); 36 %} 37 38 enc_class aarch64_enc_cmpxchg_acq_oop_shenandoah(memory mem, iRegP oldval, iRegP newval, iRegPNoSp tmp) %{ 39 MacroAssembler _masm(&cbuf); 40 guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding"); 41 Register tmp = $tmp$$Register; 42 __ mov(tmp, $oldval$$Register); // Must not clobber oldval. 43 ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, $mem$$Register, tmp, $newval$$Register, 44 /*acquire*/ true, /*release*/ true, /*weak*/ false, /*encode*/ false, noreg, noreg); 45 %} 46 %} 47 48 instruct shenandoahRB(iRegPNoSp dst, iRegP src, rFlagsReg cr) %{ 49 match(Set dst (ShenandoahReadBarrier src)); 50 format %{ "shenandoah_rb $dst,$src" %} 51 ins_encode %{ 52 Register s = $src$$Register; 53 Register d = $dst$$Register; 54 __ ldr(d, Address(s, ShenandoahBrooksPointer::byte_offset())); 55 %} 56 ins_pipe(pipe_class_memory); 57 %} 58 59 60 instruct compareAndSwapP_shenandoah(iRegINoSp res, indirect mem, iRegP oldval, iRegP newval, iRegPNoSp tmp, rFlagsReg cr) %{ 61 62 match(Set res (ShenandoahCompareAndSwapP mem (Binary oldval newval))); 63 ins_cost(2 * VOLATILE_REF_COST); 64 65 effect(TEMP tmp, KILL cr); 66 67 format %{ 68 "cmpxchg_shenandoah $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval with temp $tmp" 69 "cset $res, EQ\t# $res <-- (EQ ? 1 : 0)" 70 %} 71 72 ins_encode(aarch64_enc_cmpxchg_oop_shenandoah(mem, oldval, newval, tmp), 73 aarch64_enc_cset_eq(res)); 74 75 ins_pipe(pipe_slow); 76 %} 77 78 instruct compareAndSwapN_shenandoah(iRegINoSp res, indirect mem, iRegN oldval, iRegN newval, iRegNNoSp tmp, rFlagsReg cr) %{ 79 80 match(Set res (ShenandoahCompareAndSwapN mem (Binary oldval newval))); 81 ins_cost(2 * VOLATILE_REF_COST); 82 83 effect(TEMP tmp, KILL cr); 84 85 format %{ 86 "cmpxchgw_shenandoah $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval with temp $tmp" 87 "cset $res, EQ\t# $res <-- (EQ ? 1 : 0)" 88 %} 89 90 ins_encode %{ 91 Register tmp = $tmp$$Register; 92 __ mov(tmp, $oldval$$Register); // Must not clobber oldval. 93 ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, $mem$$Register, tmp, $newval$$Register, /*acquire*/ false, /*release*/ true, /*weak*/ false, /*encode*/ false, noreg, noreg); 94 __ cset($res$$Register, Assembler::EQ); 95 %} 96 97 ins_pipe(pipe_slow); 98 %} 99 100 instruct compareAndSwapPAcq_shenandoah(iRegINoSp res, indirect mem, iRegP oldval, iRegP newval, iRegPNoSp tmp, rFlagsReg cr) %{ 101 102 predicate(needs_acquiring_load_exclusive(n)); 103 match(Set res (ShenandoahCompareAndSwapP mem (Binary oldval newval))); 104 ins_cost(VOLATILE_REF_COST); 105 106 effect(TEMP tmp, KILL cr); 107 108 format %{ 109 "cmpxchg_acq_shenandoah_oop $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval with temp $tmp" 110 "cset $res, EQ\t# $res <-- (EQ ? 1 : 0)" 111 %} 112 113 ins_encode(aarch64_enc_cmpxchg_acq_oop_shenandoah(mem, oldval, newval, tmp), 114 aarch64_enc_cset_eq(res)); 115 116 ins_pipe(pipe_slow); 117 %} 118 119 instruct compareAndSwapNAcq_shenandoah(iRegINoSp res, indirect mem, iRegN oldval, iRegN newval, iRegNNoSp tmp, rFlagsReg cr) %{ 120 121 predicate(needs_acquiring_load_exclusive(n)); 122 match(Set res (ShenandoahCompareAndSwapN mem (Binary oldval newval))); 123 ins_cost(VOLATILE_REF_COST); 124 125 effect(TEMP tmp, KILL cr); 126 127 format %{ 128 "cmpxchgw_acq_shenandoah_narrow_oop $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval with temp $tmp" 129 "cset $res, EQ\t# $res <-- (EQ ? 1 : 0)" 130 %} 131 132 ins_encode %{ 133 Register tmp = $tmp$$Register; 134 __ mov(tmp, $oldval$$Register); // Must not clobber oldval. 135 ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, $mem$$Register, tmp, $newval$$Register, /*acquire*/ true, /*release*/ true, /*weak*/ false, /*encode*/ false, noreg, noreg); 136 __ cset($res$$Register, Assembler::EQ); 137 %} 138 139 ins_pipe(pipe_slow); 140 %} 141 142 instruct compareAndExchangeN_shenandoah(iRegNNoSp res, indirect mem, iRegN oldval, iRegN newval, iRegNNoSp tmp, rFlagsReg cr) %{ 143 match(Set res (ShenandoahCompareAndExchangeN mem (Binary oldval newval))); 144 ins_cost(2 * VOLATILE_REF_COST); 145 effect(TEMP_DEF res, TEMP tmp, KILL cr); 146 format %{ 147 "cmpxchgw_shenandoah $res = $mem, $oldval, $newval\t# (narrow oop, weak) if $mem == $oldval then $mem <-- $newval" 148 %} 149 ins_encode %{ 150 Register tmp = $tmp$$Register; 151 __ mov(tmp, $oldval$$Register); // Must not clobber oldval. 152 ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, $mem$$Register, tmp, $newval$$Register, 153 /*acquire*/ false, /*release*/ true, /*weak*/ false, /* encode*/ false, noreg, noreg, rscratch2, $res$$Register); 154 %} 155 ins_pipe(pipe_slow); 156 %} 157 158 instruct compareAndExchangeP_shenandoah(iRegPNoSp res, indirect mem, iRegP oldval, iRegP newval, iRegPNoSp tmp, rFlagsReg cr) %{ 159 match(Set res (ShenandoahCompareAndExchangeP mem (Binary oldval newval))); 160 ins_cost(2 * VOLATILE_REF_COST); 161 effect(TEMP_DEF res, TEMP tmp, KILL cr); 162 format %{ 163 "cmpxchg_shenandoah $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval with temp $tmp" 164 %} 165 ins_encode %{ 166 Register tmp = $tmp$$Register; 167 __ mov(tmp, $oldval$$Register); // Must not clobber oldval. 168 ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, $mem$$Register, tmp, $newval$$Register, 169 /*acquire*/ false, /*release*/ true, /*weak*/ false, /*encode*/ false, noreg, noreg, rscratch2, $res$$Register); 170 %} 171 ins_pipe(pipe_slow); 172 %} 173 174 instruct compareAndExchangeNAcq_shenandoah(iRegNNoSp res, indirect mem, iRegN oldval, iRegN newval, iRegNNoSp tmp, rFlagsReg cr) %{ 175 predicate(needs_acquiring_load_exclusive(n)); 176 match(Set res (ShenandoahCompareAndExchangeN mem (Binary oldval newval))); 177 ins_cost(VOLATILE_REF_COST); 178 effect(TEMP_DEF res, TEMP tmp, KILL cr); 179 format %{ 180 "cmpxchgw_acq_shenandoah $res = $mem, $oldval, $newval\t# (narrow oop, weak) if $mem == $oldval then $mem <-- $newval" 181 %} 182 ins_encode %{ 183 Register tmp = $tmp$$Register; 184 __ mov(tmp, $oldval$$Register); // Must not clobber oldval. 185 ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, $mem$$Register, tmp, $newval$$Register, 186 /*acquire*/ true, /*release*/ true, /*weak*/ false, /* encode*/ false, noreg, noreg, rscratch2, $res$$Register); 187 %} 188 ins_pipe(pipe_slow); 189 %} 190 191 instruct compareAndExchangePAcq_shenandoah(iRegPNoSp res, indirect mem, iRegP oldval, iRegP newval, iRegPNoSp tmp, rFlagsReg cr) %{ 192 predicate(needs_acquiring_load_exclusive(n)); 193 match(Set res (ShenandoahCompareAndExchangeP mem (Binary oldval newval))); 194 ins_cost(VOLATILE_REF_COST); 195 effect(TEMP_DEF res, TEMP tmp, KILL cr); 196 format %{ 197 "cmpxchg_acq_shenandoah $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval with temp $tmp" 198 %} 199 ins_encode %{ 200 Register tmp = $tmp$$Register; 201 __ mov(tmp, $oldval$$Register); // Must not clobber oldval. 202 ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, $mem$$Register, tmp, $newval$$Register, 203 /*acquire*/ true, /*release*/ true, /*weak*/ false, /*encode*/ false, noreg, noreg, rscratch2, $res$$Register); 204 %} 205 ins_pipe(pipe_slow); 206 %} 207 208 instruct weakCompareAndSwapN_shenandoah(iRegINoSp res, indirect mem, iRegN oldval, iRegN newval, iRegNNoSp tmp, rFlagsReg cr) %{ 209 match(Set res (ShenandoahWeakCompareAndSwapN mem (Binary oldval newval))); 210 ins_cost(2 * VOLATILE_REF_COST); 211 effect(TEMP tmp, KILL cr); 212 format %{ 213 "cmpxchgw_shenandoah $res = $mem, $oldval, $newval\t# (narrow oop, weak) if $mem == $oldval then $mem <-- $newval" 214 "csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)" 215 %} 216 ins_encode %{ 217 Register tmp = $tmp$$Register; 218 __ mov(tmp, $oldval$$Register); // Must not clobber oldval. 219 ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, $mem$$Register, tmp, $newval$$Register, 220 /*acquire*/ false, /*release*/ true, /*weak*/ true, /*encode*/ false, noreg, noreg); 221 __ csetw($res$$Register, Assembler::EQ); 222 %} 223 ins_pipe(pipe_slow); 224 %} 225 226 instruct weakCompareAndSwapP_shenandoah(iRegINoSp res, indirect mem, iRegP oldval, iRegP newval, iRegPNoSp tmp, rFlagsReg cr) %{ 227 match(Set res (ShenandoahWeakCompareAndSwapP mem (Binary oldval newval))); 228 ins_cost(2 * VOLATILE_REF_COST); 229 effect(TEMP tmp, KILL cr); 230 format %{ 231 "cmpxchg_shenandoah $res = $mem, $oldval, $newval\t# (ptr, 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 ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, $mem$$Register, tmp, $newval$$Register, 238 /*acquire*/ false, /*release*/ true, /*weak*/ true, /*encode*/ false, noreg, noreg); 239 __ csetw($res$$Register, Assembler::EQ); 240 %} 241 ins_pipe(pipe_slow); 242 %} 243 244 instruct weakCompareAndSwapNAcq_shenandoah(iRegINoSp res, indirect mem, iRegN oldval, iRegN newval, iRegNNoSp tmp, rFlagsReg cr) %{ 245 predicate(needs_acquiring_load_exclusive(n)); 246 match(Set res (ShenandoahWeakCompareAndSwapN mem (Binary oldval newval))); 247 ins_cost(VOLATILE_REF_COST); 248 effect(TEMP tmp, KILL cr); 249 format %{ 250 "cmpxchgw_acq_shenandoah $res = $mem, $oldval, $newval\t# (narrow oop, 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 ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, $mem$$Register, tmp, $newval$$Register, 257 /*acquire*/ true, /*release*/ true, /*weak*/ true, /*encode*/ false, noreg, noreg); 258 __ csetw($res$$Register, Assembler::EQ); 259 %} 260 ins_pipe(pipe_slow); 261 %} 262 263 instruct weakCompareAndSwapPAcq_shenandoah(iRegINoSp res, indirect mem, iRegP oldval, iRegP newval, iRegPNoSp tmp, rFlagsReg cr) %{ 264 predicate(needs_acquiring_load_exclusive(n)); 265 match(Set res (ShenandoahWeakCompareAndSwapP mem (Binary oldval newval))); 266 ins_cost(VOLATILE_REF_COST); 267 effect(TEMP tmp, KILL cr); 268 format %{ 269 "cmpxchg_acq_shenandoah $res = $mem, $oldval, $newval\t# (ptr, weak) if $mem == $oldval then $mem <-- $newval" 270 "csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)" 271 %} 272 ins_encode %{ 273 Register tmp = $tmp$$Register; 274 __ mov(tmp, $oldval$$Register); // Must not clobber oldval. 275 ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, $mem$$Register, tmp, $newval$$Register, 276 /*acquire*/ true, /*release*/ true, /*weak*/ true, /*encode*/ false, noreg, noreg); 277 __ csetw($res$$Register, Assembler::EQ); 278 %} 279 ins_pipe(pipe_slow); 280 %} 281