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.