1 dnl Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
  2 dnl DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  3 dnl
  4 dnl This code is free software; you can redistribute it and/or modify it
  5 dnl under the terms of the GNU General Public License version 2 only, as
  6 dnl published by the Free Software Foundation.
  7 dnl
  8 dnl This code is distributed in the hope that it will be useful, but WITHOUT
  9 dnl ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 10 dnl FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 11 dnl version 2 for more details (a copy is included in the LICENSE file that
 12 dnl accompanied this code).
 13 dnl
 14 dnl You should have received a copy of the GNU General Public License version
 15 dnl 2 along with this work; if not, write to the Free Software Foundation,
 16 dnl Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 17 dnl
 18 dnl Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 19 dnl or visit www.oracle.com if you need additional information or have any
 20 dnl questions.
 21 dnl
 22 // BEGIN This section of the file is automatically generated from shenandoah_aarch64.m4.
 23 
 24 
 25 define(`STORE_INSN',
 26 `
 27 // This pattern is generated automatically from shenandoah_aarch64.m4.
 28 // DO NOT EDIT ANYTHING IN THIS SECTION OF THE FILE
 29 instruct store_$1_$2_shenandoah(indirect mem, iReg$1 src, iRegPNoSp tmp, rFlagsReg cr)
 30 %{
 31   match(Set mem (Store$1 mem src));
 32   predicate(UseShenandoahGC && ifelse($2,Volatile,'needs_releasing_store(n)`,'!needs_releasing_store(n)`) && n->as_Store()->barrier_data() != 0);
 33   effect(TEMP tmp, KILL cr);
 34   ins_cost(ifelse($2,Volatile,VOLATILE_REF_COST,3*INSN_COST));
 35   format %{ "str  $src, $mem" %}
 36   ins_encode %{
 37     ShenandoahBarrierSet::assembler()->store_c2(this, masm,
 38       $mem$$Register, /* dst_narrow  = */ ifelse($1,N,'true`,'false`),
 39       $src$$Register, /* src_narrow  = */ ifelse($1,N,'true`,'false`),
 40       $tmp$$Register, /* pre_val     = */ noreg,
 41                       /* is_volatile = */ ifelse($2,Volatile,'true`,'false`));
 42   %}
 43   ins_pipe(pipe_class_memory);
 44 %}')dnl
 45 STORE_INSN(P,Normal)
 46 STORE_INSN(P,Volatile)
 47 STORE_INSN(N,Normal)
 48 STORE_INSN(N,Volatile)
 49 
 50 
 51 
 52 
 53 
 54 
 55 
 56 
 57 
 58 define(`ENCODEP_AND_STORE_INSN',
 59 `
 60 // This pattern is generated automatically from shenandoah_aarch64.m4.
 61 // DO NOT EDIT ANYTHING IN THIS SECTION OF THE FILE
 62 instruct encodePAndStoreN_$1_shenandoah(indirect mem, iRegP src, iRegPNoSp tmp, rFlagsReg cr)
 63 %{
 64   match(Set mem (StoreN mem (EncodeP src)));
 65   predicate(UseShenandoahGC && ifelse($1,Volatile,'needs_releasing_store(n)`,'!needs_releasing_store(n)`) && n->as_Store()->barrier_data() != 0);
 66   effect(TEMP tmp, KILL cr);
 67   ins_cost(ifelse($1,Volatile,VOLATILE_REF_COST,4*INSN_COST));
 68   format %{ "encode_heap_oop $tmp, $src\n\t"
 69             "str  $tmp, $mem\t# compressed ptr" %}
 70   ins_encode %{
 71     ShenandoahBarrierSet::assembler()->store_c2(this, masm,
 72       $mem$$Register, /* dst_narrow  = */ true,
 73       $src$$Register, /* src_narrow  = */ false,
 74       $tmp$$Register, /* pre_val     = */ noreg,
 75                       /* is_volatile = */ ifelse($1,Volatile,'true`,'false`));
 76   %}
 77   ins_pipe(pipe_class_memory);
 78 %}')dnl
 79 ENCODEP_AND_STORE_INSN(Normal)
 80 ENCODEP_AND_STORE_INSN(Volatile)
 81 
 82 
 83 
 84 
 85 
 86 
 87 
 88 
 89 
 90 define(`CMPANDSWP_INSN',
 91 `
 92 // This pattern is generated automatically from shenandoah_aarch64.m4.
 93 // DO NOT EDIT ANYTHING IN THIS SECTION OF THE FILE
 94 instruct compareAndSwap_$1_$2_shenandoah(iRegINoSp res, indirect mem, iReg$1NoSp oldval, iReg$1 newval, iRegPNoSp tmp1, iRegPNoSp tmp2, rFlagsReg cr)
 95 %{
 96   match(Set res (CompareAndSwap$1 mem (Binary oldval newval)));
 97   predicate(UseShenandoahGC && ifelse($2,Volatile,'needs_acquiring_load_exclusive(n)`,'!needs_acquiring_load_exclusive(n)`) && n->as_LoadStore()->barrier_data() != 0);
 98   ins_cost(ifelse($2,Volatile,VOLATILE_REF_COST + 3*INSN_COST,VOLATILE_REF_COST));
 99   effect(TEMP_DEF res, TEMP tmp1, TEMP tmp2, KILL cr);
100   format %{
101     "cmpxchg_$1_$2_shenandoah $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval"
102   %}
103   ins_encode %{
104     assert_different_registers($tmp1$$Register, $tmp2$$Register);
105     guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding");
106 
107     ShenandoahBarrierSet::assembler()->cae_c2(this, masm,
108       $res$$Register,
109       $mem$$base$$Register,
110       $oldval$$Register,
111       $newval$$Register,
112       $tmp1$$Register,
113       $tmp2$$Register,
114       /* exchange */ false,
115       /* maybe_null */ false,
116       /* is_narrow */ ifelse($1,N,'true`,'false`),
117       /* acquire */ ifelse($2,Volatile,'true`,'false`),
118       /* release */ true,
119       /* weak */ false);
120   %}
121 
122   ins_pipe(pipe_slow);
123 %}')dnl
124 CMPANDSWP_INSN(P,Normal)
125 CMPANDSWP_INSN(N,Normal)
126 CMPANDSWP_INSN(P,Volatile)
127 CMPANDSWP_INSN(N,Volatile)
128 
129 
130 
131 
132 
133 define(`CMPANDXCGH_INSN',
134 `
135 // This pattern is generated automatically from shenandoah_aarch64.m4.
136 // DO NOT EDIT ANYTHING IN THIS SECTION OF THE FILE
137 instruct compareAndExchange_$1_$2_shenandoah(iReg$1NoSp res, indirect mem, iReg$1 oldval, iReg$1 newval, iRegPNoSp tmp1, iRegPNoSp tmp2, rFlagsReg cr)
138 %{
139   match(Set res (CompareAndExchange$1 mem (Binary oldval newval)));
140   predicate(UseShenandoahGC && ifelse($2,Volatile,'needs_acquiring_load_exclusive(n)`,'!needs_acquiring_load_exclusive(n)`) && n->as_LoadStore()->barrier_data() != 0);
141   ins_cost(ifelse($2,Volatile,VOLATILE_REF_COST + 3*INSN_COST,2*VOLATILE_REF_COST));
142   effect(TEMP_DEF res, TEMP tmp1, TEMP tmp2, KILL cr);
143   format %{
144     "cae_$1_$2_shenandoah $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval"
145   %}
146   ins_encode %{
147     assert_different_registers($tmp1$$Register, $tmp2$$Register);
148     guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding");
149 
150     ShenandoahBarrierSet::assembler()->cae_c2(this, masm,
151       $res$$Register,
152       $mem$$base$$Register,
153       $oldval$$Register,
154       $newval$$Register,
155       $tmp1$$Register,
156       $tmp2$$Register,
157       /* exchange */ true,
158       /* maybe_null */ (this->bottom_type()->make_ptr()->ptr() != TypePtr::NotNull),
159       /* is_narrow */ ifelse($1,N,'true`,'false`),
160       /* acquire */ ifelse($2,Volatile,'true`,'false`),
161       /* release */ true,
162       /* weak */ false);
163   %}
164   ins_pipe(pipe_slow);
165 %}')dnl
166 CMPANDXCGH_INSN(N,Normal)
167 CMPANDXCGH_INSN(P,Normal)
168 CMPANDXCGH_INSN(N,Volatile)
169 CMPANDXCGH_INSN(P,Volatile)
170 
171 
172 
173 
174 
175 
176 
177 define(`WEAKCMPANDSWAP_INSN',
178 `
179 // This pattern is generated automatically from shenandoah_aarch64.m4.
180 // DO NOT EDIT ANYTHING IN THIS SECTION OF THE FILE
181 instruct weakCompareAndSwap_$1_$2_shenandoah(iRegINoSp res, indirect mem, iReg$1NoSp oldval, iReg$1 newval, iRegPNoSp tmp1, iRegPNoSp tmp2, rFlagsReg cr)
182 %{
183   match(Set res (WeakCompareAndSwap$1 mem (Binary oldval newval)));
184   predicate(UseShenandoahGC && ifelse($2,Volatile,'needs_acquiring_load_exclusive(n)`,'!needs_acquiring_load_exclusive(n)`) && n->as_LoadStore()->barrier_data() != 0);
185   ins_cost(VOLATILE_REF_COST);
186   effect(TEMP_DEF res, TEMP tmp1, TEMP tmp2, KILL cr);
187   format %{
188     "cae_$1_$2_weak_shenandoah $res = $mem, $oldval, $newval\t# ($1, weak, $2) if $mem == $oldval then $mem <-- $newval\n\t"
189     "csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)"
190   %}
191   ins_encode %{
192     assert_different_registers($tmp1$$Register, $tmp2$$Register);
193     guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding");
194 
195     ShenandoahBarrierSet::assembler()->cae_c2(this, masm,
196       $res$$Register,
197       $mem$$base$$Register,
198       $oldval$$Register,
199       $newval$$Register,
200       $tmp1$$Register,
201       $tmp2$$Register,
202       /* exchange */ false,
203       /* maybe_null */ false,
204       /* is_narrow */ ifelse($1,N,'true`,'false`),
205       /* acquire */ ifelse($2,Volatile,'true`,'false`),
206       /* release */ true,
207       /* weak */ true);
208   %}
209   ins_pipe(pipe_slow);
210 %}')dnl
211 WEAKCMPANDSWAP_INSN(N,Normal)
212 WEAKCMPANDSWAP_INSN(P,Normal)
213 WEAKCMPANDSWAP_INSN(N,Volatile)
214 WEAKCMPANDSWAP_INSN(P,Volatile)
215 
216 
217 define(`GETANDSET_INSN',
218 `
219 // This pattern is generated automatically from shenandoah_aarch64.m4.
220 // DO NOT EDIT ANYTHING IN THIS SECTION OF THE FILE
221 instruct getAndSet_$1_$2_shenandoah(indirect mem, iReg$1 newval, iReg$1NoSp preval, rFlagsReg cr)
222 %{
223   match(Set preval (GetAndSet$1 mem newval));
224   predicate(UseShenandoahGC && ifelse($2,Volatile,'needs_acquiring_load_exclusive(n)`,'!needs_acquiring_load_exclusive(n)`) && n->as_LoadStore()->barrier_data() != 0);
225   effect(TEMP_DEF preval, KILL cr);
226   ins_cost(ifelse($2,Volatile,VOLATILE_REF_COST + 3*INSN_COST,2*VOLATILE_REF_COST));
227   format %{ "get_and_set_$1_$2 $preval, $newval, [$mem]" %}
228   ins_encode %{
229     ShenandoahBarrierSet::assembler()->get_and_set_c2(this, masm,
230       $preval$$Register,
231       $newval$$base$$Register,
232       $mem$$Register,
233       /* maybe_null */ (this->bottom_type()->make_ptr()->ptr() != TypePtr::NotNull),
234       /* is_narrow */ ifelse($1,N,'true`,'false`),
235       /* acquire */ ifelse($2,Volatile,'true`,'false`));
236   %}
237   ins_pipe(pipe_serial);
238 %}')dnl
239 GETANDSET_INSN(P,Normal)
240 GETANDSET_INSN(P,Volatile)
241 GETANDSET_INSN(N,Normal)
242 GETANDSET_INSN(N,Volatile)
243 
244 define(`LOAD_INSN',
245 `
246 // This pattern is generated automatically from shenandoah_aarch64.m4.
247 // DO NOT EDIT ANYTHING IN THIS SECTION OF THE FILE
248 instruct load_$1_$2_shenandoah(iReg$1NoSp dst, indirect mem, iRegPNoSp tmp, rFlagsReg cr)
249 %{
250   match(Set dst (Load$1 mem));
251   predicate(UseShenandoahGC && ifelse($2,Volatile,'needs_acquiring_load(n)`,'!needs_acquiring_load(n)`) && n->as_Load()->barrier_data() != 0);
252   effect(TEMP_DEF dst, TEMP tmp, KILL cr);
253   ins_cost(ifelse($2,Volatile,VOLATILE_REF_COST,3*INSN_COST));
254   format %{ "$3  $dst, $mem\t# ptr" %}
255   ins_encode %{
256     __ $3($dst$$Register, $mem$$Register);
257 
258     Address gcs_addr(rthread, in_bytes(ShenandoahThreadLocalData::gc_state_offset()));
259     __ ldrb($tmp$$Register, gcs_addr);
260 
261     bool is_narrow = ifelse($1,N,'true`,'false`);
262     ShenandoahBarrierSet::assembler()->satb_barrier_c2(this, masm,
263                                                         noreg            /* obj */,
264                                                         $dst$$Register   /* pre_val, in this case it will be only used in the slowpath as tmp. */,
265                                                         $tmp$$Register   /* gc_state */,
266                                                         is_narrow        /* encoded_preval */);
267 
268     bool maybe_null = (this->bottom_type()->make_ptr()->ptr() != TypePtr::NotNull);
269     ShenandoahBarrierSet::assembler()->load_ref_barrier_c2(this, masm,
270                                                         $dst$$Register /* obj */,
271                                                         $mem$$Register /* addr */,
272                                                         is_narrow      /* narrow */,
273                                                         maybe_null,
274                                                         $tmp$$Register /* gc_state */);
275   %}
276   ins_pipe(pipe_class_memory);
277 %}')dnl
278 LOAD_INSN(P,Normal,ldr)
279 LOAD_INSN(P,Volatile,ldar)
280 LOAD_INSN(N,Normal,ldrw)
281 LOAD_INSN(N,Volatile,ldarw)
282 
283 // END This section of the file is automatically generated from shenandoah_aarch64.m4.