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
25source_hpp %{
26#include "gc/shenandoah/shenandoahBarrierSet.hpp"
27#include "gc/shenandoah/shenandoahBarrierSetAssembler.hpp"
28%}
29
30encode %{
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
50instruct 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
66instruct 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
86instruct 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
103instruct 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
124instruct 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
140instruct 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
156instruct 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
173instruct 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
190instruct 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
208instruct 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
225instruct 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
244instruct 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%}
262