1 //
2 // Copyright (c) 2003, 2026, Oracle and/or its affiliates. All rights reserved.
3 // Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved.
4 // Copyright (c) 2020, 2024, Huawei Technologies Co., Ltd. All rights reserved.
5 // DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 //
7 // This code is free software; you can redistribute it and/or modify it
8 // under the terms of the GNU General Public License version 2 only, as
9 // published by the Free Software Foundation.
10 //
11 // This code is distributed in the hope that it will be useful, but WITHOUT
12 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 // version 2 for more details (a copy is included in the LICENSE file that
15 // accompanied this code).
16 //
17 // You should have received a copy of the GNU General Public License version
18 // 2 along with this work; if not, write to the Free Software Foundation,
19 // Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 //
21 // Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 // or visit www.oracle.com if you need additional information or have any
23 // questions.
24 //
25 //
26
27 // RISCV Architecture Description File
28
29 //----------REGISTER DEFINITION BLOCK------------------------------------------
30 // This information is used by the matcher and the register allocator to
31 // describe individual registers and classes of registers within the target
32 // architecture.
33
34 register %{
35 //----------Architecture Description Register Definitions----------------------
36 // General Registers
37 // "reg_def" name ( register save type, C convention save type,
38 // ideal register type, encoding );
39 // Register Save Types:
40 //
41 // NS = No-Save: The register allocator assumes that these registers
42 // can be used without saving upon entry to the method, &
43 // that they do not need to be saved at call sites.
44 //
45 // SOC = Save-On-Call: The register allocator assumes that these registers
46 // can be used without saving upon entry to the method,
47 // but that they must be saved at call sites.
48 //
49 // SOE = Save-On-Entry: The register allocator assumes that these registers
50 // must be saved before using them upon entry to the
51 // method, but they do not need to be saved at call
52 // sites.
53 //
54 // AS = Always-Save: The register allocator assumes that these registers
55 // must be saved before using them upon entry to the
56 // method, & that they must be saved at call sites.
57 //
58 // Ideal Register Type is used to determine how to save & restore a
59 // register. Op_RegI will get spilled with LoadI/StoreI, Op_RegP will get
60 // spilled with LoadP/StoreP. If the register supports both, use Op_RegI.
61 //
62 // The encoding number is the actual bit-pattern placed into the opcodes.
63
64 // We must define the 64 bit int registers in two 32 bit halves, the
65 // real lower register and a virtual upper half register. upper halves
66 // are used by the register allocator but are not actually supplied as
67 // operands to memory ops.
68 //
69 // follow the C1 compiler in making registers
70 //
71 // x7, x9-x17, x27-x31 volatile (caller save)
72 // x0-x4, x8, x23 system (no save, no allocate)
73 // x5-x6 non-allocatable (so we can use them as temporary regs)
74
75 //
76 // as regards Java usage. we don't use any callee save registers
77 // because this makes it difficult to de-optimise a frame (see comment
78 // in x86 implementation of Deoptimization::unwind_callee_save_values)
79 //
80
81 // General Registers
82
83 reg_def R0 ( NS, NS, Op_RegI, 0, x0->as_VMReg() ); // zr
84 reg_def R0_H ( NS, NS, Op_RegI, 0, x0->as_VMReg()->next() );
85 reg_def R1 ( NS, SOC, Op_RegI, 1, x1->as_VMReg() ); // ra
86 reg_def R1_H ( NS, SOC, Op_RegI, 1, x1->as_VMReg()->next() );
87 reg_def R2 ( NS, NS, Op_RegI, 2, x2->as_VMReg() ); // sp
88 reg_def R2_H ( NS, NS, Op_RegI, 2, x2->as_VMReg()->next() );
89 reg_def R3 ( NS, NS, Op_RegI, 3, x3->as_VMReg() ); // gp
90 reg_def R3_H ( NS, NS, Op_RegI, 3, x3->as_VMReg()->next() );
91 reg_def R4 ( NS, NS, Op_RegI, 4, x4->as_VMReg() ); // tp
92 reg_def R4_H ( NS, NS, Op_RegI, 4, x4->as_VMReg()->next() );
93 reg_def R7 ( SOC, SOC, Op_RegI, 7, x7->as_VMReg() );
94 reg_def R7_H ( SOC, SOC, Op_RegI, 7, x7->as_VMReg()->next() );
95 reg_def R8 ( NS, SOE, Op_RegI, 8, x8->as_VMReg() ); // fp
96 reg_def R8_H ( NS, SOE, Op_RegI, 8, x8->as_VMReg()->next() );
97 reg_def R9 ( SOC, SOE, Op_RegI, 9, x9->as_VMReg() );
98 reg_def R9_H ( SOC, SOE, Op_RegI, 9, x9->as_VMReg()->next() );
99 reg_def R10 ( SOC, SOC, Op_RegI, 10, x10->as_VMReg() );
100 reg_def R10_H ( SOC, SOC, Op_RegI, 10, x10->as_VMReg()->next());
101 reg_def R11 ( SOC, SOC, Op_RegI, 11, x11->as_VMReg() );
102 reg_def R11_H ( SOC, SOC, Op_RegI, 11, x11->as_VMReg()->next());
103 reg_def R12 ( SOC, SOC, Op_RegI, 12, x12->as_VMReg() );
104 reg_def R12_H ( SOC, SOC, Op_RegI, 12, x12->as_VMReg()->next());
105 reg_def R13 ( SOC, SOC, Op_RegI, 13, x13->as_VMReg() );
106 reg_def R13_H ( SOC, SOC, Op_RegI, 13, x13->as_VMReg()->next());
107 reg_def R14 ( SOC, SOC, Op_RegI, 14, x14->as_VMReg() );
108 reg_def R14_H ( SOC, SOC, Op_RegI, 14, x14->as_VMReg()->next());
109 reg_def R15 ( SOC, SOC, Op_RegI, 15, x15->as_VMReg() );
110 reg_def R15_H ( SOC, SOC, Op_RegI, 15, x15->as_VMReg()->next());
111 reg_def R16 ( SOC, SOC, Op_RegI, 16, x16->as_VMReg() );
112 reg_def R16_H ( SOC, SOC, Op_RegI, 16, x16->as_VMReg()->next());
113 reg_def R17 ( SOC, SOC, Op_RegI, 17, x17->as_VMReg() );
114 reg_def R17_H ( SOC, SOC, Op_RegI, 17, x17->as_VMReg()->next());
115 reg_def R18 ( SOC, SOE, Op_RegI, 18, x18->as_VMReg() );
116 reg_def R18_H ( SOC, SOE, Op_RegI, 18, x18->as_VMReg()->next());
117 reg_def R19 ( SOC, SOE, Op_RegI, 19, x19->as_VMReg() );
118 reg_def R19_H ( SOC, SOE, Op_RegI, 19, x19->as_VMReg()->next());
119 reg_def R20 ( SOC, SOE, Op_RegI, 20, x20->as_VMReg() ); // caller esp
120 reg_def R20_H ( SOC, SOE, Op_RegI, 20, x20->as_VMReg()->next());
121 reg_def R21 ( SOC, SOE, Op_RegI, 21, x21->as_VMReg() );
122 reg_def R21_H ( SOC, SOE, Op_RegI, 21, x21->as_VMReg()->next());
123 reg_def R22 ( SOC, SOE, Op_RegI, 22, x22->as_VMReg() );
124 reg_def R22_H ( SOC, SOE, Op_RegI, 22, x22->as_VMReg()->next());
125 reg_def R23 ( NS, SOE, Op_RegI, 23, x23->as_VMReg() ); // java thread
126 reg_def R23_H ( NS, SOE, Op_RegI, 23, x23->as_VMReg()->next());
127 reg_def R24 ( SOC, SOE, Op_RegI, 24, x24->as_VMReg() );
128 reg_def R24_H ( SOC, SOE, Op_RegI, 24, x24->as_VMReg()->next());
129 reg_def R25 ( SOC, SOE, Op_RegI, 25, x25->as_VMReg() );
130 reg_def R25_H ( SOC, SOE, Op_RegI, 25, x25->as_VMReg()->next());
131 reg_def R26 ( SOC, SOE, Op_RegI, 26, x26->as_VMReg() );
132 reg_def R26_H ( SOC, SOE, Op_RegI, 26, x26->as_VMReg()->next());
133 reg_def R27 ( SOC, SOE, Op_RegI, 27, x27->as_VMReg() ); // heapbase
134 reg_def R27_H ( SOC, SOE, Op_RegI, 27, x27->as_VMReg()->next());
135 reg_def R28 ( SOC, SOC, Op_RegI, 28, x28->as_VMReg() );
136 reg_def R28_H ( SOC, SOC, Op_RegI, 28, x28->as_VMReg()->next());
137 reg_def R29 ( SOC, SOC, Op_RegI, 29, x29->as_VMReg() );
138 reg_def R29_H ( SOC, SOC, Op_RegI, 29, x29->as_VMReg()->next());
139 reg_def R30 ( SOC, SOC, Op_RegI, 30, x30->as_VMReg() );
140 reg_def R30_H ( SOC, SOC, Op_RegI, 30, x30->as_VMReg()->next());
141 reg_def R31 ( SOC, SOC, Op_RegI, 31, x31->as_VMReg() );
142 reg_def R31_H ( SOC, SOC, Op_RegI, 31, x31->as_VMReg()->next());
143
144 // ----------------------------
145 // Float/Double Registers
146 // ----------------------------
147
148 // Double Registers
149
150 // The rules of ADL require that double registers be defined in pairs.
151 // Each pair must be two 32-bit values, but not necessarily a pair of
152 // single float registers. In each pair, ADLC-assigned register numbers
153 // must be adjacent, with the lower number even. Finally, when the
154 // CPU stores such a register pair to memory, the word associated with
155 // the lower ADLC-assigned number must be stored to the lower address.
156
157 // RISCV has 32 floating-point registers. Each can store a single
158 // or double precision floating-point value.
159
160 // for Java use float registers f0-f31 are always save on call whereas
161 // the platform ABI treats f8-f9 and f18-f27 as callee save). Other
162 // float registers are SOC as per the platform spec
163
164 reg_def F0 ( SOC, SOC, Op_RegF, 0, f0->as_VMReg() );
165 reg_def F0_H ( SOC, SOC, Op_RegF, 0, f0->as_VMReg()->next() );
166 reg_def F1 ( SOC, SOC, Op_RegF, 1, f1->as_VMReg() );
167 reg_def F1_H ( SOC, SOC, Op_RegF, 1, f1->as_VMReg()->next() );
168 reg_def F2 ( SOC, SOC, Op_RegF, 2, f2->as_VMReg() );
169 reg_def F2_H ( SOC, SOC, Op_RegF, 2, f2->as_VMReg()->next() );
170 reg_def F3 ( SOC, SOC, Op_RegF, 3, f3->as_VMReg() );
171 reg_def F3_H ( SOC, SOC, Op_RegF, 3, f3->as_VMReg()->next() );
172 reg_def F4 ( SOC, SOC, Op_RegF, 4, f4->as_VMReg() );
173 reg_def F4_H ( SOC, SOC, Op_RegF, 4, f4->as_VMReg()->next() );
174 reg_def F5 ( SOC, SOC, Op_RegF, 5, f5->as_VMReg() );
175 reg_def F5_H ( SOC, SOC, Op_RegF, 5, f5->as_VMReg()->next() );
176 reg_def F6 ( SOC, SOC, Op_RegF, 6, f6->as_VMReg() );
177 reg_def F6_H ( SOC, SOC, Op_RegF, 6, f6->as_VMReg()->next() );
178 reg_def F7 ( SOC, SOC, Op_RegF, 7, f7->as_VMReg() );
179 reg_def F7_H ( SOC, SOC, Op_RegF, 7, f7->as_VMReg()->next() );
180 reg_def F8 ( SOC, SOE, Op_RegF, 8, f8->as_VMReg() );
181 reg_def F8_H ( SOC, SOE, Op_RegF, 8, f8->as_VMReg()->next() );
182 reg_def F9 ( SOC, SOE, Op_RegF, 9, f9->as_VMReg() );
183 reg_def F9_H ( SOC, SOE, Op_RegF, 9, f9->as_VMReg()->next() );
184 reg_def F10 ( SOC, SOC, Op_RegF, 10, f10->as_VMReg() );
185 reg_def F10_H ( SOC, SOC, Op_RegF, 10, f10->as_VMReg()->next() );
186 reg_def F11 ( SOC, SOC, Op_RegF, 11, f11->as_VMReg() );
187 reg_def F11_H ( SOC, SOC, Op_RegF, 11, f11->as_VMReg()->next() );
188 reg_def F12 ( SOC, SOC, Op_RegF, 12, f12->as_VMReg() );
189 reg_def F12_H ( SOC, SOC, Op_RegF, 12, f12->as_VMReg()->next() );
190 reg_def F13 ( SOC, SOC, Op_RegF, 13, f13->as_VMReg() );
191 reg_def F13_H ( SOC, SOC, Op_RegF, 13, f13->as_VMReg()->next() );
192 reg_def F14 ( SOC, SOC, Op_RegF, 14, f14->as_VMReg() );
193 reg_def F14_H ( SOC, SOC, Op_RegF, 14, f14->as_VMReg()->next() );
194 reg_def F15 ( SOC, SOC, Op_RegF, 15, f15->as_VMReg() );
195 reg_def F15_H ( SOC, SOC, Op_RegF, 15, f15->as_VMReg()->next() );
196 reg_def F16 ( SOC, SOC, Op_RegF, 16, f16->as_VMReg() );
197 reg_def F16_H ( SOC, SOC, Op_RegF, 16, f16->as_VMReg()->next() );
198 reg_def F17 ( SOC, SOC, Op_RegF, 17, f17->as_VMReg() );
199 reg_def F17_H ( SOC, SOC, Op_RegF, 17, f17->as_VMReg()->next() );
200 reg_def F18 ( SOC, SOE, Op_RegF, 18, f18->as_VMReg() );
201 reg_def F18_H ( SOC, SOE, Op_RegF, 18, f18->as_VMReg()->next() );
202 reg_def F19 ( SOC, SOE, Op_RegF, 19, f19->as_VMReg() );
203 reg_def F19_H ( SOC, SOE, Op_RegF, 19, f19->as_VMReg()->next() );
204 reg_def F20 ( SOC, SOE, Op_RegF, 20, f20->as_VMReg() );
205 reg_def F20_H ( SOC, SOE, Op_RegF, 20, f20->as_VMReg()->next() );
206 reg_def F21 ( SOC, SOE, Op_RegF, 21, f21->as_VMReg() );
207 reg_def F21_H ( SOC, SOE, Op_RegF, 21, f21->as_VMReg()->next() );
208 reg_def F22 ( SOC, SOE, Op_RegF, 22, f22->as_VMReg() );
209 reg_def F22_H ( SOC, SOE, Op_RegF, 22, f22->as_VMReg()->next() );
210 reg_def F23 ( SOC, SOE, Op_RegF, 23, f23->as_VMReg() );
211 reg_def F23_H ( SOC, SOE, Op_RegF, 23, f23->as_VMReg()->next() );
212 reg_def F24 ( SOC, SOE, Op_RegF, 24, f24->as_VMReg() );
213 reg_def F24_H ( SOC, SOE, Op_RegF, 24, f24->as_VMReg()->next() );
214 reg_def F25 ( SOC, SOE, Op_RegF, 25, f25->as_VMReg() );
215 reg_def F25_H ( SOC, SOE, Op_RegF, 25, f25->as_VMReg()->next() );
216 reg_def F26 ( SOC, SOE, Op_RegF, 26, f26->as_VMReg() );
217 reg_def F26_H ( SOC, SOE, Op_RegF, 26, f26->as_VMReg()->next() );
218 reg_def F27 ( SOC, SOE, Op_RegF, 27, f27->as_VMReg() );
219 reg_def F27_H ( SOC, SOE, Op_RegF, 27, f27->as_VMReg()->next() );
220 reg_def F28 ( SOC, SOC, Op_RegF, 28, f28->as_VMReg() );
221 reg_def F28_H ( SOC, SOC, Op_RegF, 28, f28->as_VMReg()->next() );
222 reg_def F29 ( SOC, SOC, Op_RegF, 29, f29->as_VMReg() );
223 reg_def F29_H ( SOC, SOC, Op_RegF, 29, f29->as_VMReg()->next() );
224 reg_def F30 ( SOC, SOC, Op_RegF, 30, f30->as_VMReg() );
225 reg_def F30_H ( SOC, SOC, Op_RegF, 30, f30->as_VMReg()->next() );
226 reg_def F31 ( SOC, SOC, Op_RegF, 31, f31->as_VMReg() );
227 reg_def F31_H ( SOC, SOC, Op_RegF, 31, f31->as_VMReg()->next() );
228
229 // ----------------------------
230 // Vector Registers
231 // ----------------------------
232
233 // For RVV vector registers, we simply extend vector register size to 4
234 // 'logical' slots. This is nominally 128 bits but it actually covers
235 // all possible 'physical' RVV vector register lengths from 128 ~ 1024
236 // bits. The 'physical' RVV vector register length is detected during
237 // startup, so the register allocator is able to identify the correct
238 // number of bytes needed for an RVV spill/unspill.
239
240 reg_def V0 ( SOC, SOC, Op_VecA, 0, v0->as_VMReg() );
241 reg_def V0_H ( SOC, SOC, Op_VecA, 0, v0->as_VMReg()->next() );
242 reg_def V0_J ( SOC, SOC, Op_VecA, 0, v0->as_VMReg()->next(2) );
243 reg_def V0_K ( SOC, SOC, Op_VecA, 0, v0->as_VMReg()->next(3) );
244
245 reg_def V1 ( SOC, SOC, Op_VecA, 1, v1->as_VMReg() );
246 reg_def V1_H ( SOC, SOC, Op_VecA, 1, v1->as_VMReg()->next() );
247 reg_def V1_J ( SOC, SOC, Op_VecA, 1, v1->as_VMReg()->next(2) );
248 reg_def V1_K ( SOC, SOC, Op_VecA, 1, v1->as_VMReg()->next(3) );
249
250 reg_def V2 ( SOC, SOC, Op_VecA, 2, v2->as_VMReg() );
251 reg_def V2_H ( SOC, SOC, Op_VecA, 2, v2->as_VMReg()->next() );
252 reg_def V2_J ( SOC, SOC, Op_VecA, 2, v2->as_VMReg()->next(2) );
253 reg_def V2_K ( SOC, SOC, Op_VecA, 2, v2->as_VMReg()->next(3) );
254
255 reg_def V3 ( SOC, SOC, Op_VecA, 3, v3->as_VMReg() );
256 reg_def V3_H ( SOC, SOC, Op_VecA, 3, v3->as_VMReg()->next() );
257 reg_def V3_J ( SOC, SOC, Op_VecA, 3, v3->as_VMReg()->next(2) );
258 reg_def V3_K ( SOC, SOC, Op_VecA, 3, v3->as_VMReg()->next(3) );
259
260 reg_def V4 ( SOC, SOC, Op_VecA, 4, v4->as_VMReg() );
261 reg_def V4_H ( SOC, SOC, Op_VecA, 4, v4->as_VMReg()->next() );
262 reg_def V4_J ( SOC, SOC, Op_VecA, 4, v4->as_VMReg()->next(2) );
263 reg_def V4_K ( SOC, SOC, Op_VecA, 4, v4->as_VMReg()->next(3) );
264
265 reg_def V5 ( SOC, SOC, Op_VecA, 5, v5->as_VMReg() );
266 reg_def V5_H ( SOC, SOC, Op_VecA, 5, v5->as_VMReg()->next() );
267 reg_def V5_J ( SOC, SOC, Op_VecA, 5, v5->as_VMReg()->next(2) );
268 reg_def V5_K ( SOC, SOC, Op_VecA, 5, v5->as_VMReg()->next(3) );
269
270 reg_def V6 ( SOC, SOC, Op_VecA, 6, v6->as_VMReg() );
271 reg_def V6_H ( SOC, SOC, Op_VecA, 6, v6->as_VMReg()->next() );
272 reg_def V6_J ( SOC, SOC, Op_VecA, 6, v6->as_VMReg()->next(2) );
273 reg_def V6_K ( SOC, SOC, Op_VecA, 6, v6->as_VMReg()->next(3) );
274
275 reg_def V7 ( SOC, SOC, Op_VecA, 7, v7->as_VMReg() );
276 reg_def V7_H ( SOC, SOC, Op_VecA, 7, v7->as_VMReg()->next() );
277 reg_def V7_J ( SOC, SOC, Op_VecA, 7, v7->as_VMReg()->next(2) );
278 reg_def V7_K ( SOC, SOC, Op_VecA, 7, v7->as_VMReg()->next(3) );
279
280 reg_def V8 ( SOC, SOC, Op_VecA, 8, v8->as_VMReg() );
281 reg_def V8_H ( SOC, SOC, Op_VecA, 8, v8->as_VMReg()->next() );
282 reg_def V8_J ( SOC, SOC, Op_VecA, 8, v8->as_VMReg()->next(2) );
283 reg_def V8_K ( SOC, SOC, Op_VecA, 8, v8->as_VMReg()->next(3) );
284
285 reg_def V9 ( SOC, SOC, Op_VecA, 9, v9->as_VMReg() );
286 reg_def V9_H ( SOC, SOC, Op_VecA, 9, v9->as_VMReg()->next() );
287 reg_def V9_J ( SOC, SOC, Op_VecA, 9, v9->as_VMReg()->next(2) );
288 reg_def V9_K ( SOC, SOC, Op_VecA, 9, v9->as_VMReg()->next(3) );
289
290 reg_def V10 ( SOC, SOC, Op_VecA, 10, v10->as_VMReg() );
291 reg_def V10_H ( SOC, SOC, Op_VecA, 10, v10->as_VMReg()->next() );
292 reg_def V10_J ( SOC, SOC, Op_VecA, 10, v10->as_VMReg()->next(2) );
293 reg_def V10_K ( SOC, SOC, Op_VecA, 10, v10->as_VMReg()->next(3) );
294
295 reg_def V11 ( SOC, SOC, Op_VecA, 11, v11->as_VMReg() );
296 reg_def V11_H ( SOC, SOC, Op_VecA, 11, v11->as_VMReg()->next() );
297 reg_def V11_J ( SOC, SOC, Op_VecA, 11, v11->as_VMReg()->next(2) );
298 reg_def V11_K ( SOC, SOC, Op_VecA, 11, v11->as_VMReg()->next(3) );
299
300 reg_def V12 ( SOC, SOC, Op_VecA, 12, v12->as_VMReg() );
301 reg_def V12_H ( SOC, SOC, Op_VecA, 12, v12->as_VMReg()->next() );
302 reg_def V12_J ( SOC, SOC, Op_VecA, 12, v12->as_VMReg()->next(2) );
303 reg_def V12_K ( SOC, SOC, Op_VecA, 12, v12->as_VMReg()->next(3) );
304
305 reg_def V13 ( SOC, SOC, Op_VecA, 13, v13->as_VMReg() );
306 reg_def V13_H ( SOC, SOC, Op_VecA, 13, v13->as_VMReg()->next() );
307 reg_def V13_J ( SOC, SOC, Op_VecA, 13, v13->as_VMReg()->next(2) );
308 reg_def V13_K ( SOC, SOC, Op_VecA, 13, v13->as_VMReg()->next(3) );
309
310 reg_def V14 ( SOC, SOC, Op_VecA, 14, v14->as_VMReg() );
311 reg_def V14_H ( SOC, SOC, Op_VecA, 14, v14->as_VMReg()->next() );
312 reg_def V14_J ( SOC, SOC, Op_VecA, 14, v14->as_VMReg()->next(2) );
313 reg_def V14_K ( SOC, SOC, Op_VecA, 14, v14->as_VMReg()->next(3) );
314
315 reg_def V15 ( SOC, SOC, Op_VecA, 15, v15->as_VMReg() );
316 reg_def V15_H ( SOC, SOC, Op_VecA, 15, v15->as_VMReg()->next() );
317 reg_def V15_J ( SOC, SOC, Op_VecA, 15, v15->as_VMReg()->next(2) );
318 reg_def V15_K ( SOC, SOC, Op_VecA, 15, v15->as_VMReg()->next(3) );
319
320 reg_def V16 ( SOC, SOC, Op_VecA, 16, v16->as_VMReg() );
321 reg_def V16_H ( SOC, SOC, Op_VecA, 16, v16->as_VMReg()->next() );
322 reg_def V16_J ( SOC, SOC, Op_VecA, 16, v16->as_VMReg()->next(2) );
323 reg_def V16_K ( SOC, SOC, Op_VecA, 16, v16->as_VMReg()->next(3) );
324
325 reg_def V17 ( SOC, SOC, Op_VecA, 17, v17->as_VMReg() );
326 reg_def V17_H ( SOC, SOC, Op_VecA, 17, v17->as_VMReg()->next() );
327 reg_def V17_J ( SOC, SOC, Op_VecA, 17, v17->as_VMReg()->next(2) );
328 reg_def V17_K ( SOC, SOC, Op_VecA, 17, v17->as_VMReg()->next(3) );
329
330 reg_def V18 ( SOC, SOC, Op_VecA, 18, v18->as_VMReg() );
331 reg_def V18_H ( SOC, SOC, Op_VecA, 18, v18->as_VMReg()->next() );
332 reg_def V18_J ( SOC, SOC, Op_VecA, 18, v18->as_VMReg()->next(2) );
333 reg_def V18_K ( SOC, SOC, Op_VecA, 18, v18->as_VMReg()->next(3) );
334
335 reg_def V19 ( SOC, SOC, Op_VecA, 19, v19->as_VMReg() );
336 reg_def V19_H ( SOC, SOC, Op_VecA, 19, v19->as_VMReg()->next() );
337 reg_def V19_J ( SOC, SOC, Op_VecA, 19, v19->as_VMReg()->next(2) );
338 reg_def V19_K ( SOC, SOC, Op_VecA, 19, v19->as_VMReg()->next(3) );
339
340 reg_def V20 ( SOC, SOC, Op_VecA, 20, v20->as_VMReg() );
341 reg_def V20_H ( SOC, SOC, Op_VecA, 20, v20->as_VMReg()->next() );
342 reg_def V20_J ( SOC, SOC, Op_VecA, 20, v20->as_VMReg()->next(2) );
343 reg_def V20_K ( SOC, SOC, Op_VecA, 20, v20->as_VMReg()->next(3) );
344
345 reg_def V21 ( SOC, SOC, Op_VecA, 21, v21->as_VMReg() );
346 reg_def V21_H ( SOC, SOC, Op_VecA, 21, v21->as_VMReg()->next() );
347 reg_def V21_J ( SOC, SOC, Op_VecA, 21, v21->as_VMReg()->next(2) );
348 reg_def V21_K ( SOC, SOC, Op_VecA, 21, v21->as_VMReg()->next(3) );
349
350 reg_def V22 ( SOC, SOC, Op_VecA, 22, v22->as_VMReg() );
351 reg_def V22_H ( SOC, SOC, Op_VecA, 22, v22->as_VMReg()->next() );
352 reg_def V22_J ( SOC, SOC, Op_VecA, 22, v22->as_VMReg()->next(2) );
353 reg_def V22_K ( SOC, SOC, Op_VecA, 22, v22->as_VMReg()->next(3) );
354
355 reg_def V23 ( SOC, SOC, Op_VecA, 23, v23->as_VMReg() );
356 reg_def V23_H ( SOC, SOC, Op_VecA, 23, v23->as_VMReg()->next() );
357 reg_def V23_J ( SOC, SOC, Op_VecA, 23, v23->as_VMReg()->next(2) );
358 reg_def V23_K ( SOC, SOC, Op_VecA, 23, v23->as_VMReg()->next(3) );
359
360 reg_def V24 ( SOC, SOC, Op_VecA, 24, v24->as_VMReg() );
361 reg_def V24_H ( SOC, SOC, Op_VecA, 24, v24->as_VMReg()->next() );
362 reg_def V24_J ( SOC, SOC, Op_VecA, 24, v24->as_VMReg()->next(2) );
363 reg_def V24_K ( SOC, SOC, Op_VecA, 24, v24->as_VMReg()->next(3) );
364
365 reg_def V25 ( SOC, SOC, Op_VecA, 25, v25->as_VMReg() );
366 reg_def V25_H ( SOC, SOC, Op_VecA, 25, v25->as_VMReg()->next() );
367 reg_def V25_J ( SOC, SOC, Op_VecA, 25, v25->as_VMReg()->next(2) );
368 reg_def V25_K ( SOC, SOC, Op_VecA, 25, v25->as_VMReg()->next(3) );
369
370 reg_def V26 ( SOC, SOC, Op_VecA, 26, v26->as_VMReg() );
371 reg_def V26_H ( SOC, SOC, Op_VecA, 26, v26->as_VMReg()->next() );
372 reg_def V26_J ( SOC, SOC, Op_VecA, 26, v26->as_VMReg()->next(2) );
373 reg_def V26_K ( SOC, SOC, Op_VecA, 26, v26->as_VMReg()->next(3) );
374
375 reg_def V27 ( SOC, SOC, Op_VecA, 27, v27->as_VMReg() );
376 reg_def V27_H ( SOC, SOC, Op_VecA, 27, v27->as_VMReg()->next() );
377 reg_def V27_J ( SOC, SOC, Op_VecA, 27, v27->as_VMReg()->next(2) );
378 reg_def V27_K ( SOC, SOC, Op_VecA, 27, v27->as_VMReg()->next(3) );
379
380 reg_def V28 ( SOC, SOC, Op_VecA, 28, v28->as_VMReg() );
381 reg_def V28_H ( SOC, SOC, Op_VecA, 28, v28->as_VMReg()->next() );
382 reg_def V28_J ( SOC, SOC, Op_VecA, 28, v28->as_VMReg()->next(2) );
383 reg_def V28_K ( SOC, SOC, Op_VecA, 28, v28->as_VMReg()->next(3) );
384
385 reg_def V29 ( SOC, SOC, Op_VecA, 29, v29->as_VMReg() );
386 reg_def V29_H ( SOC, SOC, Op_VecA, 29, v29->as_VMReg()->next() );
387 reg_def V29_J ( SOC, SOC, Op_VecA, 29, v29->as_VMReg()->next(2) );
388 reg_def V29_K ( SOC, SOC, Op_VecA, 29, v29->as_VMReg()->next(3) );
389
390 reg_def V30 ( SOC, SOC, Op_VecA, 30, v30->as_VMReg() );
391 reg_def V30_H ( SOC, SOC, Op_VecA, 30, v30->as_VMReg()->next() );
392 reg_def V30_J ( SOC, SOC, Op_VecA, 30, v30->as_VMReg()->next(2) );
393 reg_def V30_K ( SOC, SOC, Op_VecA, 30, v30->as_VMReg()->next(3) );
394
395 reg_def V31 ( SOC, SOC, Op_VecA, 31, v31->as_VMReg() );
396 reg_def V31_H ( SOC, SOC, Op_VecA, 31, v31->as_VMReg()->next() );
397 reg_def V31_J ( SOC, SOC, Op_VecA, 31, v31->as_VMReg()->next(2) );
398 reg_def V31_K ( SOC, SOC, Op_VecA, 31, v31->as_VMReg()->next(3) );
399
400 // ----------------------------
401 // Special Registers
402 // ----------------------------
403
404 // On riscv, the physical flag register is missing, so we use t1 instead,
405 // to bridge the RegFlag semantics in share/opto
406
407 reg_def RFLAGS (SOC, SOC, Op_RegFlags, 6, x6->as_VMReg() );
408
409 // Specify priority of register selection within phases of register
410 // allocation. Highest priority is first. A useful heuristic is to
411 // give registers a low priority when they are required by machine
412 // instructions, like EAX and EDX on I486, and choose no-save registers
413 // before save-on-call, & save-on-call before save-on-entry. Registers
414 // which participate in fixed calling sequences should come last.
415 // Registers which are used as pairs must fall on an even boundary.
416
417 alloc_class chunk0(
418 // volatiles
419 R7, R7_H,
420 R28, R28_H,
421 R29, R29_H,
422 R30, R30_H,
423 R31, R31_H,
424
425 // arg registers
426 R10, R10_H,
427 R11, R11_H,
428 R12, R12_H,
429 R13, R13_H,
430 R14, R14_H,
431 R15, R15_H,
432 R16, R16_H,
433 R17, R17_H,
434
435 // non-volatiles
436 R9, R9_H,
437 R18, R18_H,
438 R19, R19_H,
439 R20, R20_H,
440 R21, R21_H,
441 R22, R22_H,
442 R24, R24_H,
443 R25, R25_H,
444 R26, R26_H,
445
446 // non-allocatable registers
447 R23, R23_H, // java thread
448 R27, R27_H, // heapbase
449 R4, R4_H, // thread
450 R8, R8_H, // fp
451 R0, R0_H, // zero
452 R1, R1_H, // ra
453 R2, R2_H, // sp
454 R3, R3_H, // gp
455 );
456
457 alloc_class chunk1(
458
459 // no save
460 F0, F0_H,
461 F1, F1_H,
462 F2, F2_H,
463 F3, F3_H,
464 F4, F4_H,
465 F5, F5_H,
466 F6, F6_H,
467 F7, F7_H,
468 F28, F28_H,
469 F29, F29_H,
470 F30, F30_H,
471 F31, F31_H,
472
473 // arg registers
474 F10, F10_H,
475 F11, F11_H,
476 F12, F12_H,
477 F13, F13_H,
478 F14, F14_H,
479 F15, F15_H,
480 F16, F16_H,
481 F17, F17_H,
482
483 // non-volatiles
484 F8, F8_H,
485 F9, F9_H,
486 F18, F18_H,
487 F19, F19_H,
488 F20, F20_H,
489 F21, F21_H,
490 F22, F22_H,
491 F23, F23_H,
492 F24, F24_H,
493 F25, F25_H,
494 F26, F26_H,
495 F27, F27_H,
496 );
497
498 alloc_class chunk2(
499 V0, V0_H, V0_J, V0_K,
500 V1, V1_H, V1_J, V1_K,
501 V2, V2_H, V2_J, V2_K,
502 V3, V3_H, V3_J, V3_K,
503 V4, V4_H, V4_J, V4_K,
504 V5, V5_H, V5_J, V5_K,
505 V6, V6_H, V6_J, V6_K,
506 V7, V7_H, V7_J, V7_K,
507 V8, V8_H, V8_J, V8_K,
508 V9, V9_H, V9_J, V9_K,
509 V10, V10_H, V10_J, V10_K,
510 V11, V11_H, V11_J, V11_K,
511 V12, V12_H, V12_J, V12_K,
512 V13, V13_H, V13_J, V13_K,
513 V14, V14_H, V14_J, V14_K,
514 V15, V15_H, V15_J, V15_K,
515 V16, V16_H, V16_J, V16_K,
516 V17, V17_H, V17_J, V17_K,
517 V18, V18_H, V18_J, V18_K,
518 V19, V19_H, V19_J, V19_K,
519 V20, V20_H, V20_J, V20_K,
520 V21, V21_H, V21_J, V21_K,
521 V22, V22_H, V22_J, V22_K,
522 V23, V23_H, V23_J, V23_K,
523 V24, V24_H, V24_J, V24_K,
524 V25, V25_H, V25_J, V25_K,
525 V26, V26_H, V26_J, V26_K,
526 V27, V27_H, V27_J, V27_K,
527 V28, V28_H, V28_J, V28_K,
528 V29, V29_H, V29_J, V29_K,
529 V30, V30_H, V30_J, V30_K,
530 V31, V31_H, V31_J, V31_K,
531 );
532
533 alloc_class chunk3(RFLAGS);
534
535 //----------Architecture Description Register Classes--------------------------
536 // Several register classes are automatically defined based upon information in
537 // this architecture description.
538 // 1) reg_class inline_cache_reg ( /* as def'd in frame section */ )
539 // 2) reg_class stack_slots( /* one chunk of stack-based "registers" */ )
540 //
541
542 // Class for all 32 bit general purpose registers
543 reg_class all_reg32(
544 R0,
545 R1,
546 R2,
547 R3,
548 R4,
549 R7,
550 R8,
551 R9,
552 R10,
553 R11,
554 R12,
555 R13,
556 R14,
557 R15,
558 R16,
559 R17,
560 R18,
561 R19,
562 R20,
563 R21,
564 R22,
565 R23,
566 R24,
567 R25,
568 R26,
569 R27,
570 R28,
571 R29,
572 R30,
573 R31
574 );
575
576 // Class for any 32 bit integer registers (excluding zr)
577 reg_class any_reg32 %{
578 return _ANY_REG32_mask;
579 %}
580
581 // Singleton class for R10 int register
582 reg_class int_r10_reg(R10);
583
584 // Singleton class for R12 int register
585 reg_class int_r12_reg(R12);
586
587 // Singleton class for R13 int register
588 reg_class int_r13_reg(R13);
589
590 // Singleton class for R14 int register
591 reg_class int_r14_reg(R14);
592
593 // Class for all long integer registers
594 reg_class all_reg(
595 R0, R0_H,
596 R1, R1_H,
597 R2, R2_H,
598 R3, R3_H,
599 R4, R4_H,
600 R7, R7_H,
601 R8, R8_H,
602 R9, R9_H,
603 R10, R10_H,
604 R11, R11_H,
605 R12, R12_H,
606 R13, R13_H,
607 R14, R14_H,
608 R15, R15_H,
609 R16, R16_H,
610 R17, R17_H,
611 R18, R18_H,
612 R19, R19_H,
613 R20, R20_H,
614 R21, R21_H,
615 R22, R22_H,
616 R23, R23_H,
617 R24, R24_H,
618 R25, R25_H,
619 R26, R26_H,
620 R27, R27_H,
621 R28, R28_H,
622 R29, R29_H,
623 R30, R30_H,
624 R31, R31_H
625 );
626
627 // Class for all long integer registers (excluding zr)
628 reg_class any_reg %{
629 return _ANY_REG_mask;
630 %}
631
632 // Class for non-allocatable 32 bit registers
633 reg_class non_allocatable_reg32(
634 R0, // zr
635 R1, // ra
636 R2, // sp
637 R3, // gp
638 R4, // tp
639 R23 // java thread
640 );
641
642 // Class for non-allocatable 64 bit registers
643 reg_class non_allocatable_reg(
644 R0, R0_H, // zr
645 R1, R1_H, // ra
646 R2, R2_H, // sp
647 R3, R3_H, // gp
648 R4, R4_H, // tp
649 R23, R23_H // java thread
650 );
651
652 // Class for all non-special integer registers
653 reg_class no_special_reg32 %{
654 return _NO_SPECIAL_REG32_mask;
655 %}
656
657 // Class for all non-special long integer registers
658 reg_class no_special_reg %{
659 return _NO_SPECIAL_REG_mask;
660 %}
661
662 reg_class ptr_reg %{
663 return _PTR_REG_mask;
664 %}
665
666 // Class for all non_special pointer registers
667 reg_class no_special_ptr_reg %{
668 return _NO_SPECIAL_PTR_REG_mask;
669 %}
670
671 // Class for all non_special pointer registers (excluding fp)
672 reg_class no_special_no_fp_ptr_reg %{
673 return _NO_SPECIAL_NO_FP_PTR_REG_mask;
674 %}
675
676 // Class for 64 bit register r10
677 reg_class r10_reg(
678 R10, R10_H
679 );
680
681 // Class for 64 bit register r11
682 reg_class r11_reg(
683 R11, R11_H
684 );
685
686 // Class for 64 bit register r12
687 reg_class r12_reg(
688 R12, R12_H
689 );
690
691 // Class for 64 bit register r13
692 reg_class r13_reg(
693 R13, R13_H
694 );
695
696 // Class for 64 bit register r14
697 reg_class r14_reg(
698 R14, R14_H
699 );
700
701 // Class for 64 bit register r15
702 reg_class r15_reg(
703 R15, R15_H
704 );
705
706 // Class for 64 bit register r16
707 reg_class r16_reg(
708 R16, R16_H
709 );
710
711 // Class for method register
712 reg_class method_reg(
713 R31, R31_H
714 );
715
716 // Class for java thread register
717 reg_class java_thread_reg(
718 R23, R23_H
719 );
720
721 reg_class r28_reg(
722 R28, R28_H
723 );
724
725 reg_class r29_reg(
726 R29, R29_H
727 );
728
729 reg_class r30_reg(
730 R30, R30_H
731 );
732
733 reg_class r31_reg(
734 R31, R31_H
735 );
736
737 // Class for zero registesr
738 reg_class zr_reg(
739 R0, R0_H
740 );
741
742 // Class for thread register
743 reg_class thread_reg(
744 R4, R4_H
745 );
746
747 // Class for frame pointer register
748 reg_class fp_reg(
749 R8, R8_H
750 );
751
752 // Class for link register
753 reg_class ra_reg(
754 R1, R1_H
755 );
756
757 // Class for long sp register
758 reg_class sp_reg(
759 R2, R2_H
760 );
761
762 // Class for all float registers
763 reg_class float_reg(
764 F0,
765 F1,
766 F2,
767 F3,
768 F4,
769 F5,
770 F6,
771 F7,
772 F8,
773 F9,
774 F10,
775 F11,
776 F12,
777 F13,
778 F14,
779 F15,
780 F16,
781 F17,
782 F18,
783 F19,
784 F20,
785 F21,
786 F22,
787 F23,
788 F24,
789 F25,
790 F26,
791 F27,
792 F28,
793 F29,
794 F30,
795 F31
796 );
797
798 // Double precision float registers have virtual `high halves' that
799 // are needed by the allocator.
800 // Class for all double registers
801 reg_class double_reg(
802 F0, F0_H,
803 F1, F1_H,
804 F2, F2_H,
805 F3, F3_H,
806 F4, F4_H,
807 F5, F5_H,
808 F6, F6_H,
809 F7, F7_H,
810 F8, F8_H,
811 F9, F9_H,
812 F10, F10_H,
813 F11, F11_H,
814 F12, F12_H,
815 F13, F13_H,
816 F14, F14_H,
817 F15, F15_H,
818 F16, F16_H,
819 F17, F17_H,
820 F18, F18_H,
821 F19, F19_H,
822 F20, F20_H,
823 F21, F21_H,
824 F22, F22_H,
825 F23, F23_H,
826 F24, F24_H,
827 F25, F25_H,
828 F26, F26_H,
829 F27, F27_H,
830 F28, F28_H,
831 F29, F29_H,
832 F30, F30_H,
833 F31, F31_H
834 );
835
836 // Class for RVV vector registers
837 // Note: v0, v30 and v31 are used as mask registers.
838 reg_class vectora_reg(
839 V1, V1_H, V1_J, V1_K,
840 V2, V2_H, V2_J, V2_K,
841 V3, V3_H, V3_J, V3_K,
842 V4, V4_H, V4_J, V4_K,
843 V5, V5_H, V5_J, V5_K,
844 V6, V6_H, V6_J, V6_K,
845 V7, V7_H, V7_J, V7_K,
846 V8, V8_H, V8_J, V8_K,
847 V9, V9_H, V9_J, V9_K,
848 V10, V10_H, V10_J, V10_K,
849 V11, V11_H, V11_J, V11_K,
850 V12, V12_H, V12_J, V12_K,
851 V13, V13_H, V13_J, V13_K,
852 V14, V14_H, V14_J, V14_K,
853 V15, V15_H, V15_J, V15_K,
854 V16, V16_H, V16_J, V16_K,
855 V17, V17_H, V17_J, V17_K,
856 V18, V18_H, V18_J, V18_K,
857 V19, V19_H, V19_J, V19_K,
858 V20, V20_H, V20_J, V20_K,
859 V21, V21_H, V21_J, V21_K,
860 V22, V22_H, V22_J, V22_K,
861 V23, V23_H, V23_J, V23_K,
862 V24, V24_H, V24_J, V24_K,
863 V25, V25_H, V25_J, V25_K,
864 V26, V26_H, V26_J, V26_K,
865 V27, V27_H, V27_J, V27_K,
866 V28, V28_H, V28_J, V28_K,
867 V29, V29_H, V29_J, V29_K
868 );
869
870 // Class for 64 bit register f0
871 reg_class f0_reg(
872 F0, F0_H
873 );
874
875 // Class for 64 bit register f1
876 reg_class f1_reg(
877 F1, F1_H
878 );
879
880 // Class for 64 bit register f2
881 reg_class f2_reg(
882 F2, F2_H
883 );
884
885 // Class for 64 bit register f3
886 reg_class f3_reg(
887 F3, F3_H
888 );
889
890 // class for vector register v1
891 reg_class v1_reg(
892 V1, V1_H, V1_J, V1_K
893 );
894
895 // class for vector register v2
896 reg_class v2_reg(
897 V2, V2_H, V2_J, V2_K
898 );
899
900 // class for vector register v3
901 reg_class v3_reg(
902 V3, V3_H, V3_J, V3_K
903 );
904
905 // class for vector register v4
906 reg_class v4_reg(
907 V4, V4_H, V4_J, V4_K
908 );
909
910 // class for vector register v5
911 reg_class v5_reg(
912 V5, V5_H, V5_J, V5_K
913 );
914
915 // class for vector register v6
916 reg_class v6_reg(
917 V6, V6_H, V6_J, V6_K
918 );
919
920 // class for vector register v7
921 reg_class v7_reg(
922 V7, V7_H, V7_J, V7_K
923 );
924
925 // class for vector register v8
926 reg_class v8_reg(
927 V8, V8_H, V8_J, V8_K
928 );
929
930 // class for vector register v9
931 reg_class v9_reg(
932 V9, V9_H, V9_J, V9_K
933 );
934
935 // class for vector register v10
936 reg_class v10_reg(
937 V10, V10_H, V10_J, V10_K
938 );
939
940 // class for vector register v11
941 reg_class v11_reg(
942 V11, V11_H, V11_J, V11_K
943 );
944
945 // class for condition codes
946 reg_class reg_flags(RFLAGS);
947
948 // Class for RVV v0 mask register
949 // https://github.com/riscv/riscv-v-spec/blob/master/v-spec.adoc#53-vector-masking
950 // The mask value used to control execution of a masked vector
951 // instruction is always supplied by vector register v0.
952 reg_class vmask_reg_v0 (
953 V0
954 );
955
956 // Class for RVV mask registers
957 // We need two more vmask registers to do the vector mask logical ops,
958 // so define v30, v31 as mask register too.
959 reg_class vmask_reg (
960 V0,
961 V30,
962 V31
963 );
964 %}
965
966 //----------DEFINITION BLOCK---------------------------------------------------
967 // Define name --> value mappings to inform the ADLC of an integer valued name
968 // Current support includes integer values in the range [0, 0x7FFFFFFF]
969 // Format:
970 // int_def <name> ( <int_value>, <expression>);
971 // Generated Code in ad_<arch>.hpp
972 // #define <name> (<expression>)
973 // // value == <int_value>
974 // Generated code in ad_<arch>.cpp adlc_verification()
975 // assert( <name> == <int_value>, "Expect (<expression>) to equal <int_value>");
976 //
977
978 // we follow the ppc-aix port in using a simple cost model which ranks
979 // register operations as cheap, memory ops as more expensive and
980 // branches as most expensive. the first two have a low as well as a
981 // normal cost. huge cost appears to be a way of saying don't do
982 // something
983
984 definitions %{
985 // The default cost (of a register move instruction).
986 int_def DEFAULT_COST ( 100, 100);
987 int_def ALU_COST ( 100, 1 * DEFAULT_COST); // unknown, const, arith, shift, slt,
988 // multi, auipc, nop, logical, move
989 int_def LOAD_COST ( 300, 3 * DEFAULT_COST); // load, fpload
990 int_def STORE_COST ( 100, 1 * DEFAULT_COST); // store, fpstore
991 int_def XFER_COST ( 300, 3 * DEFAULT_COST); // mfc, mtc, fcvt, fmove, fcmp
992 int_def FMVX_COST ( 100, 1 * DEFAULT_COST); // shuffles with no conversion
993 int_def BRANCH_COST ( 200, 2 * DEFAULT_COST); // branch, jmp, call
994 int_def IMUL_COST ( 1000, 10 * DEFAULT_COST); // imul
995 int_def IDIVSI_COST ( 3400, 34 * DEFAULT_COST); // idivsi
996 int_def IDIVDI_COST ( 6600, 66 * DEFAULT_COST); // idivdi
997 int_def FMUL_SINGLE_COST ( 500, 5 * DEFAULT_COST); // fmul, fmadd
998 int_def FMUL_DOUBLE_COST ( 700, 7 * DEFAULT_COST); // fmul, fmadd
999 int_def FDIV_COST ( 2000, 20 * DEFAULT_COST); // fdiv
1000 int_def FSQRT_COST ( 2500, 25 * DEFAULT_COST); // fsqrt
1001 int_def VOLATILE_REF_COST ( 1000, 10 * DEFAULT_COST);
1002 int_def CACHE_MISS_COST ( 2000, 20 * DEFAULT_COST); // typicall cache miss penalty
1003 %}
1004
1005
1006
1007 //----------SOURCE BLOCK-------------------------------------------------------
1008 // This is a block of C++ code which provides values, functions, and
1009 // definitions necessary in the rest of the architecture description
1010
1011 source_hpp %{
1012
1013 #include "asm/macroAssembler.hpp"
1014 #include "gc/shared/barrierSetAssembler.hpp"
1015 #include "gc/shared/cardTable.hpp"
1016 #include "gc/shared/cardTableBarrierSet.hpp"
1017 #include "gc/shared/collectedHeap.hpp"
1018 #include "opto/addnode.hpp"
1019 #include "opto/convertnode.hpp"
1020 #include "runtime/objectMonitor.hpp"
1021
1022 extern RegMask _ANY_REG32_mask;
1023 extern RegMask _ANY_REG_mask;
1024 extern RegMask _PTR_REG_mask;
1025 extern RegMask _NO_SPECIAL_REG32_mask;
1026 extern RegMask _NO_SPECIAL_REG_mask;
1027 extern RegMask _NO_SPECIAL_PTR_REG_mask;
1028 extern RegMask _NO_SPECIAL_NO_FP_PTR_REG_mask;
1029
1030 class CallStubImpl {
1031
1032 //--------------------------------------------------------------
1033 //---< Used for optimization in Compile::shorten_branches >---
1034 //--------------------------------------------------------------
1035
1036 public:
1037 // Size of call trampoline stub.
1038 static uint size_call_trampoline() {
1039 return 0; // no call trampolines on this platform
1040 }
1041
1042 // number of relocations needed by a call trampoline stub
1043 static uint reloc_call_trampoline() {
1044 return 0; // no call trampolines on this platform
1045 }
1046 };
1047
1048 class HandlerImpl {
1049
1050 public:
1051
1052 static int emit_deopt_handler(C2_MacroAssembler* masm);
1053
1054 static uint size_deopt_handler() {
1055 // count far call + j
1056 return NativeInstruction::instruction_size + MacroAssembler::far_branch_size();
1057 }
1058 };
1059
1060 class Node::PD {
1061 public:
1062 enum NodeFlags {
1063 _last_flag = Node::_last_flag
1064 };
1065 };
1066
1067 bool is_CAS(int opcode, bool maybe_volatile);
1068
1069 // predicate controlling translation of CompareAndSwapX
1070 bool needs_acquiring_load_reserved(const Node *load);
1071
1072 // predicate controlling addressing modes
1073 bool size_fits_all_mem_uses(AddPNode* addp, int shift);
1074 %}
1075
1076 source %{
1077
1078 // Derived RegMask with conditionally allocatable registers
1079
1080 RegMask _ANY_REG32_mask;
1081 RegMask _ANY_REG_mask;
1082 RegMask _PTR_REG_mask;
1083 RegMask _NO_SPECIAL_REG32_mask;
1084 RegMask _NO_SPECIAL_REG_mask;
1085 RegMask _NO_SPECIAL_PTR_REG_mask;
1086 RegMask _NO_SPECIAL_NO_FP_PTR_REG_mask;
1087
1088 void reg_mask_init() {
1089
1090 _ANY_REG32_mask.assignFrom(_ALL_REG32_mask);
1091 _ANY_REG32_mask.remove(OptoReg::as_OptoReg(x0->as_VMReg()));
1092
1093 _ANY_REG_mask.assignFrom(_ALL_REG_mask);
1094 _ANY_REG_mask.subtract(_ZR_REG_mask);
1095
1096 _PTR_REG_mask.assignFrom(_ALL_REG_mask);
1097 _PTR_REG_mask.subtract(_ZR_REG_mask);
1098
1099 _NO_SPECIAL_REG32_mask.assignFrom(_ALL_REG32_mask);
1100 _NO_SPECIAL_REG32_mask.subtract(_NON_ALLOCATABLE_REG32_mask);
1101
1102 _NO_SPECIAL_REG_mask.assignFrom(_ALL_REG_mask);
1103 _NO_SPECIAL_REG_mask.subtract(_NON_ALLOCATABLE_REG_mask);
1104
1105 _NO_SPECIAL_PTR_REG_mask.assignFrom(_ALL_REG_mask);
1106 _NO_SPECIAL_PTR_REG_mask.subtract(_NON_ALLOCATABLE_REG_mask);
1107
1108 // x27 is not allocatable when compressed oops is on
1109 if (UseCompressedOops) {
1110 _NO_SPECIAL_REG32_mask.remove(OptoReg::as_OptoReg(x27->as_VMReg()));
1111 _NO_SPECIAL_REG_mask.remove(OptoReg::as_OptoReg(x27->as_VMReg()));
1112 _NO_SPECIAL_PTR_REG_mask.remove(OptoReg::as_OptoReg(x27->as_VMReg()));
1113 }
1114
1115 // x8 is not allocatable when PreserveFramePointer is on
1116 if (PreserveFramePointer) {
1117 _NO_SPECIAL_REG32_mask.remove(OptoReg::as_OptoReg(x8->as_VMReg()));
1118 _NO_SPECIAL_REG_mask.remove(OptoReg::as_OptoReg(x8->as_VMReg()));
1119 _NO_SPECIAL_PTR_REG_mask.remove(OptoReg::as_OptoReg(x8->as_VMReg()));
1120 }
1121
1122 _NO_SPECIAL_NO_FP_PTR_REG_mask.assignFrom(_NO_SPECIAL_PTR_REG_mask);
1123 _NO_SPECIAL_NO_FP_PTR_REG_mask.remove(OptoReg::as_OptoReg(x8->as_VMReg()));
1124 }
1125
1126 void PhaseOutput::pd_perform_mach_node_analysis() {
1127 }
1128
1129 int MachNode::pd_alignment_required() const {
1130 return 1;
1131 }
1132
1133 int MachNode::compute_padding(int current_offset) const {
1134 return 0;
1135 }
1136
1137 // is_CAS(int opcode, bool maybe_volatile)
1138 //
1139 // return true if opcode is one of the possible CompareAndSwapX
1140 // values otherwise false.
1141 bool is_CAS(int opcode, bool maybe_volatile)
1142 {
1143 switch (opcode) {
1144 // We handle these
1145 case Op_CompareAndSwapI:
1146 case Op_CompareAndSwapL:
1147 case Op_CompareAndSwapP:
1148 case Op_CompareAndSwapN:
1149 case Op_CompareAndSwapB:
1150 case Op_CompareAndSwapS:
1151 case Op_GetAndSetI:
1152 case Op_GetAndSetL:
1153 case Op_GetAndSetP:
1154 case Op_GetAndSetN:
1155 case Op_GetAndAddI:
1156 case Op_GetAndAddL:
1157 return true;
1158 case Op_CompareAndExchangeI:
1159 case Op_CompareAndExchangeN:
1160 case Op_CompareAndExchangeB:
1161 case Op_CompareAndExchangeS:
1162 case Op_CompareAndExchangeL:
1163 case Op_CompareAndExchangeP:
1164 case Op_WeakCompareAndSwapB:
1165 case Op_WeakCompareAndSwapS:
1166 case Op_WeakCompareAndSwapI:
1167 case Op_WeakCompareAndSwapL:
1168 case Op_WeakCompareAndSwapP:
1169 case Op_WeakCompareAndSwapN:
1170 return maybe_volatile;
1171 default:
1172 return false;
1173 }
1174 }
1175
1176 constexpr uint64_t MAJIK_DWORD = 0xabbaabbaabbaabbaull;
1177
1178 // predicate controlling translation of CAS
1179 //
1180 // returns true if CAS needs to use an acquiring load otherwise false
1181 bool needs_acquiring_load_reserved(const Node *n)
1182 {
1183 assert(n != nullptr && is_CAS(n->Opcode(), true), "expecting a compare and swap");
1184
1185 LoadStoreNode* ldst = n->as_LoadStore();
1186 if (n != nullptr && is_CAS(n->Opcode(), false)) {
1187 assert(ldst != nullptr && ldst->trailing_membar() != nullptr, "expected trailing membar");
1188 } else {
1189 return ldst != nullptr && ldst->trailing_membar() != nullptr;
1190 }
1191 // so we can just return true here
1192 return true;
1193 }
1194 #define __ masm->
1195
1196 // advance declarations for helper functions to convert register
1197 // indices to register objects
1198
1199 // the ad file has to provide implementations of certain methods
1200 // expected by the generic code
1201 //
1202 // REQUIRED FUNCTIONALITY
1203
1204 //=============================================================================
1205
1206 // !!!!! Special hack to get all types of calls to specify the byte offset
1207 // from the start of the call to the point where the return address
1208 // will point.
1209
1210 int MachCallStaticJavaNode::ret_addr_offset()
1211 {
1212 return 3 * NativeInstruction::instruction_size; // auipc + ld + jalr
1213 }
1214
1215 int MachCallDynamicJavaNode::ret_addr_offset()
1216 {
1217 return NativeMovConstReg::movptr2_instruction_size + (3 * NativeInstruction::instruction_size); // movptr2, auipc + ld + jal
1218 }
1219
1220 int MachCallRuntimeNode::ret_addr_offset() {
1221 // For address inside the code cache the call will be:
1222 // auipc + jalr
1223 // For real runtime callouts it will be 8 instructions
1224 // see riscv_enc_java_to_runtime
1225 // la(t0, retaddr) -> auipc + addi
1226 // sd(t0, Address(xthread, JavaThread::last_Java_pc_offset())) -> sd
1227 // movptr(t1, addr, offset, t0) -> lui + lui + slli + add
1228 // jalr(t1, offset) -> jalr
1229 if (CodeCache::contains(_entry_point)) {
1230 return 2 * NativeInstruction::instruction_size;
1231 } else {
1232 return 8 * NativeInstruction::instruction_size;
1233 }
1234 }
1235
1236 //
1237 // Compute padding required for nodes which need alignment
1238 //
1239
1240 // With RVC a call instruction may get 2-byte aligned.
1241 // The address of the call instruction needs to be 4-byte aligned to
1242 // ensure that it does not span a cache line so that it can be patched.
1243 int CallStaticJavaDirectNode::compute_padding(int current_offset) const
1244 {
1245 // to make sure the address of jal 4-byte aligned.
1246 return align_up(current_offset, alignment_required()) - current_offset;
1247 }
1248
1249 // With RVC a call instruction may get 2-byte aligned.
1250 // The address of the call instruction needs to be 4-byte aligned to
1251 // ensure that it does not span a cache line so that it can be patched.
1252 int CallDynamicJavaDirectNode::compute_padding(int current_offset) const
1253 {
1254 // skip the movptr2 in MacroAssembler::ic_call():
1255 // lui, lui, slli, add, addi
1256 // Though movptr2() has already 4-byte aligned with or without RVC,
1257 // We need to prevent from further changes by explicitly calculating the size.
1258 current_offset += NativeMovConstReg::movptr2_instruction_size;
1259 // to make sure the address of jal 4-byte aligned.
1260 return align_up(current_offset, alignment_required()) - current_offset;
1261 }
1262
1263 int CallRuntimeDirectNode::compute_padding(int current_offset) const
1264 {
1265 return align_up(current_offset, alignment_required()) - current_offset;
1266 }
1267
1268 int CallLeafDirectNode::compute_padding(int current_offset) const
1269 {
1270 return align_up(current_offset, alignment_required()) - current_offset;
1271 }
1272
1273 int CallLeafDirectVectorNode::compute_padding(int current_offset) const
1274 {
1275 return align_up(current_offset, alignment_required()) - current_offset;
1276 }
1277
1278 int CallLeafNoFPDirectNode::compute_padding(int current_offset) const
1279 {
1280 return align_up(current_offset, alignment_required()) - current_offset;
1281 }
1282
1283 //=============================================================================
1284
1285 #ifndef PRODUCT
1286 void MachBreakpointNode::format(PhaseRegAlloc *ra_, outputStream *st) const {
1287 assert_cond(st != nullptr);
1288 st->print("BREAKPOINT");
1289 }
1290 #endif
1291
1292 void MachBreakpointNode::emit(C2_MacroAssembler *masm, PhaseRegAlloc *ra_) const {
1293 __ ebreak();
1294 }
1295
1296 uint MachBreakpointNode::size(PhaseRegAlloc *ra_) const {
1297 return MachNode::size(ra_);
1298 }
1299
1300 //=============================================================================
1301
1302 #ifndef PRODUCT
1303 void MachNopNode::format(PhaseRegAlloc*, outputStream* st) const {
1304 st->print("nop \t# %d bytes pad for loops and calls", _count);
1305 }
1306 #endif
1307
1308 void MachNopNode::emit(C2_MacroAssembler *masm, PhaseRegAlloc*) const {
1309 Assembler::CompressibleScope scope(masm); // nops shall be 2-byte under RVC for alignment purposes.
1310 for (int i = 0; i < _count; i++) {
1311 __ nop();
1312 }
1313 }
1314
1315 uint MachNopNode::size(PhaseRegAlloc*) const {
1316 return _count * (UseRVC ? NativeInstruction::compressed_instruction_size : NativeInstruction::instruction_size);
1317 }
1318
1319 //=============================================================================
1320 const RegMask& MachConstantBaseNode::_out_RegMask = RegMask::EMPTY;
1321
1322 int ConstantTable::calculate_table_base_offset() const {
1323 return 0; // absolute addressing, no offset
1324 }
1325
1326 bool MachConstantBaseNode::requires_postalloc_expand() const { return false; }
1327 void MachConstantBaseNode::postalloc_expand(GrowableArray <Node *> *nodes, PhaseRegAlloc *ra_) {
1328 ShouldNotReachHere();
1329 }
1330
1331 void MachConstantBaseNode::emit(C2_MacroAssembler* masm, PhaseRegAlloc* ra_) const {
1332 // Empty encoding
1333 }
1334
1335 uint MachConstantBaseNode::size(PhaseRegAlloc* ra_) const {
1336 return 0;
1337 }
1338
1339 #ifndef PRODUCT
1340 void MachConstantBaseNode::format(PhaseRegAlloc* ra_, outputStream* st) const {
1341 assert_cond(st != nullptr);
1342 st->print("-- \t// MachConstantBaseNode (empty encoding)");
1343 }
1344 #endif
1345
1346 #ifndef PRODUCT
1347 void MachPrologNode::format(PhaseRegAlloc *ra_, outputStream *st) const {
1348 assert_cond(st != nullptr && ra_ != nullptr);
1349 Compile* C = ra_->C;
1350
1351 int framesize = C->output()->frame_slots() << LogBytesPerInt;
1352
1353 if (C->output()->need_stack_bang(framesize)) {
1354 st->print("# stack bang size=%d\n\t", framesize);
1355 }
1356
1357 st->print("sub sp, sp, #%d\n\t", framesize);
1358 st->print("sd fp, [sp, #%d]\n\t", framesize - 2 * wordSize);
1359 st->print("sd ra, [sp, #%d]\n\t", framesize - wordSize);
1360 if (PreserveFramePointer) { st->print("add fp, sp, #%d\n\t", framesize); }
1361
1362 if (VerifyStackAtCalls) {
1363 st->print("mv t2, %ld\n\t", MAJIK_DWORD);
1364 st->print("sd t2, [sp, #%d]\n\t", framesize - 3 * wordSize);
1365 }
1366
1367 if (C->stub_function() == nullptr) {
1368 st->print("ld t0, [guard]\n\t");
1369 st->print("membar LoadLoad\n\t");
1370 st->print("ld t1, [xthread, #thread_disarmed_guard_value_offset]\n\t");
1371 st->print("beq t0, t1, skip\n\t");
1372 st->print("jalr #nmethod_entry_barrier_stub\n\t");
1373 st->print("j skip\n\t");
1374 st->print("guard: int\n\t");
1375 st->print("skip:\n\t");
1376 }
1377 }
1378 #endif
1379
1380 void MachPrologNode::emit(C2_MacroAssembler *masm, PhaseRegAlloc *ra_) const {
1381 assert_cond(ra_ != nullptr);
1382 Compile* C = ra_->C;
1383
1384 // n.b. frame size includes space for return pc and fp
1385 const int framesize = C->output()->frame_size_in_bytes();
1386
1387 assert_cond(C != nullptr);
1388
1389 if (C->clinit_barrier_on_entry()) {
1390 assert(!C->method()->holder()->is_not_initialized(), "initialization should have been started");
1391
1392 Label L_skip_barrier;
1393
1394 __ mov_metadata(t1, C->method()->holder()->constant_encoding());
1395 __ clinit_barrier(t1, t0, &L_skip_barrier);
1396 __ far_jump(RuntimeAddress(SharedRuntime::get_handle_wrong_method_stub()));
1397 __ bind(L_skip_barrier);
1398 }
1399
1400 int bangsize = C->output()->bang_size_in_bytes();
1401 if (C->output()->need_stack_bang(bangsize)) {
1402 __ generate_stack_overflow_check(bangsize);
1403 }
1404
1405 __ build_frame(framesize);
1406
1407 if (VerifyStackAtCalls) {
1408 __ mv(t2, MAJIK_DWORD);
1409 __ sd(t2, Address(sp, framesize - 3 * wordSize));
1410 }
1411
1412 if (C->stub_function() == nullptr) {
1413 BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler();
1414 // Dummy labels for just measuring the code size
1415 Label dummy_slow_path;
1416 Label dummy_continuation;
1417 Label dummy_guard;
1418 Label* slow_path = &dummy_slow_path;
1419 Label* continuation = &dummy_continuation;
1420 Label* guard = &dummy_guard;
1421 if (!Compile::current()->output()->in_scratch_emit_size()) {
1422 // Use real labels from actual stub when not emitting code for purpose of measuring its size
1423 C2EntryBarrierStub* stub = new (Compile::current()->comp_arena()) C2EntryBarrierStub();
1424 Compile::current()->output()->add_stub(stub);
1425 slow_path = &stub->entry();
1426 continuation = &stub->continuation();
1427 guard = &stub->guard();
1428 }
1429 // In the C2 code, we move the non-hot part of nmethod entry barriers out-of-line to a stub.
1430 bs->nmethod_entry_barrier(masm, slow_path, continuation, guard);
1431 }
1432
1433 C->output()->set_frame_complete(__ offset());
1434
1435 if (C->has_mach_constant_base_node()) {
1436 // NOTE: We set the table base offset here because users might be
1437 // emitted before MachConstantBaseNode.
1438 ConstantTable& constant_table = C->output()->constant_table();
1439 constant_table.set_table_base_offset(constant_table.calculate_table_base_offset());
1440 }
1441 }
1442
1443 int MachPrologNode::reloc() const
1444 {
1445 return 0;
1446 }
1447
1448 //=============================================================================
1449
1450 #ifndef PRODUCT
1451 void MachEpilogNode::format(PhaseRegAlloc *ra_, outputStream *st) const {
1452 assert_cond(st != nullptr && ra_ != nullptr);
1453 Compile* C = ra_->C;
1454 assert_cond(C != nullptr);
1455 int framesize = C->output()->frame_size_in_bytes();
1456
1457 st->print("# pop frame %d\n\t", framesize);
1458
1459 if (framesize == 0) {
1460 st->print("ld ra, [sp,#%d]\n\t", (2 * wordSize));
1461 st->print("ld fp, [sp,#%d]\n\t", (3 * wordSize));
1462 st->print("add sp, sp, #%d\n\t", (2 * wordSize));
1463 } else {
1464 st->print("add sp, sp, #%d\n\t", framesize);
1465 st->print("ld ra, [sp,#%d]\n\t", - 2 * wordSize);
1466 st->print("ld fp, [sp,#%d]\n\t", - wordSize);
1467 }
1468
1469 if (do_polling() && C->is_method_compilation()) {
1470 st->print("# test polling word\n\t");
1471 st->print("ld t0, [xthread,#%d]\n\t", in_bytes(JavaThread::polling_word_offset()));
1472 st->print("bgtu sp, t0, #slow_path");
1473 }
1474 }
1475 #endif
1476
1477 void MachEpilogNode::emit(C2_MacroAssembler *masm, PhaseRegAlloc *ra_) const {
1478 assert_cond(ra_ != nullptr);
1479 Compile* C = ra_->C;
1480 assert_cond(C != nullptr);
1481 int framesize = C->output()->frame_size_in_bytes();
1482
1483 __ remove_frame(framesize);
1484
1485 if (StackReservedPages > 0 && C->has_reserved_stack_access()) {
1486 __ reserved_stack_check();
1487 }
1488
1489 if (do_polling() && C->is_method_compilation()) {
1490 Label dummy_label;
1491 Label* code_stub = &dummy_label;
1492 if (!C->output()->in_scratch_emit_size()) {
1493 C2SafepointPollStub* stub = new (C->comp_arena()) C2SafepointPollStub(__ offset());
1494 C->output()->add_stub(stub);
1495 code_stub = &stub->entry();
1496 }
1497 __ relocate(relocInfo::poll_return_type);
1498 __ safepoint_poll(*code_stub, true /* at_return */, true /* in_nmethod */);
1499 }
1500 }
1501
1502 int MachEpilogNode::reloc() const {
1503 // Return number of relocatable values contained in this instruction.
1504 return 1; // 1 for polling page.
1505 }
1506 const Pipeline * MachEpilogNode::pipeline() const {
1507 return MachNode::pipeline_class();
1508 }
1509
1510 //=============================================================================
1511
1512 // Figure out which register class each belongs in: rc_int, rc_float or
1513 // rc_stack.
1514 enum RC { rc_bad, rc_int, rc_float, rc_vector, rc_stack };
1515
1516 static enum RC rc_class(OptoReg::Name reg) {
1517
1518 if (reg == OptoReg::Bad) {
1519 return rc_bad;
1520 }
1521
1522 // we have 30 int registers * 2 halves
1523 // (t0 and t1 are omitted)
1524 int slots_of_int_registers = Register::max_slots_per_register * (Register::number_of_registers - 2);
1525 if (reg < slots_of_int_registers) {
1526 return rc_int;
1527 }
1528
1529 // we have 32 float register * 2 halves
1530 int slots_of_float_registers = FloatRegister::max_slots_per_register * FloatRegister::number_of_registers;
1531 if (reg < slots_of_int_registers + slots_of_float_registers) {
1532 return rc_float;
1533 }
1534
1535 // we have 32 vector register * 4 halves
1536 int slots_of_vector_registers = VectorRegister::max_slots_per_register * VectorRegister::number_of_registers;
1537 if (reg < slots_of_int_registers + slots_of_float_registers + slots_of_vector_registers) {
1538 return rc_vector;
1539 }
1540
1541 // Between vector regs & stack is the flags regs.
1542 assert(OptoReg::is_stack(reg), "blow up if spilling flags");
1543
1544 return rc_stack;
1545 }
1546
1547 uint MachSpillCopyNode::implementation(C2_MacroAssembler *masm, PhaseRegAlloc *ra_, bool do_size, outputStream *st) const {
1548 assert_cond(ra_ != nullptr);
1549 Compile* C = ra_->C;
1550
1551 // Get registers to move.
1552 OptoReg::Name src_hi = ra_->get_reg_second(in(1));
1553 OptoReg::Name src_lo = ra_->get_reg_first(in(1));
1554 OptoReg::Name dst_hi = ra_->get_reg_second(this);
1555 OptoReg::Name dst_lo = ra_->get_reg_first(this);
1556
1557 enum RC src_hi_rc = rc_class(src_hi);
1558 enum RC src_lo_rc = rc_class(src_lo);
1559 enum RC dst_hi_rc = rc_class(dst_hi);
1560 enum RC dst_lo_rc = rc_class(dst_lo);
1561
1562 assert(src_lo != OptoReg::Bad && dst_lo != OptoReg::Bad, "must move at least 1 register");
1563
1564 if (src_hi != OptoReg::Bad && !bottom_type()->isa_pvectmask()) {
1565 assert((src_lo & 1) == 0 && src_lo + 1 == src_hi &&
1566 (dst_lo & 1) == 0 && dst_lo + 1 == dst_hi,
1567 "expected aligned-adjacent pairs");
1568 }
1569
1570 if (src_lo == dst_lo && src_hi == dst_hi) {
1571 return 0; // Self copy, no move.
1572 }
1573
1574 bool is64 = (src_lo & 1) == 0 && src_lo + 1 == src_hi &&
1575 (dst_lo & 1) == 0 && dst_lo + 1 == dst_hi;
1576 int src_offset = ra_->reg2offset(src_lo);
1577 int dst_offset = ra_->reg2offset(dst_lo);
1578
1579 if (bottom_type()->isa_vect() != nullptr) {
1580 uint ireg = ideal_reg();
1581 if (ireg == Op_VecA && masm) {
1582 int vector_reg_size_in_bytes = Matcher::scalable_vector_reg_size(T_BYTE);
1583 if (src_lo_rc == rc_stack && dst_lo_rc == rc_stack) {
1584 // stack to stack
1585 __ spill_copy_vector_stack_to_stack(src_offset, dst_offset,
1586 vector_reg_size_in_bytes);
1587 } else if (src_lo_rc == rc_vector && dst_lo_rc == rc_stack) {
1588 // vpr to stack
1589 __ spill(as_VectorRegister(Matcher::_regEncode[src_lo]), ra_->reg2offset(dst_lo));
1590 } else if (src_lo_rc == rc_stack && dst_lo_rc == rc_vector) {
1591 // stack to vpr
1592 __ unspill(as_VectorRegister(Matcher::_regEncode[dst_lo]), ra_->reg2offset(src_lo));
1593 } else if (src_lo_rc == rc_vector && dst_lo_rc == rc_vector) {
1594 // vpr to vpr
1595 __ vsetvli_helper(T_BYTE, MaxVectorSize);
1596 __ vmv_v_v(as_VectorRegister(Matcher::_regEncode[dst_lo]), as_VectorRegister(Matcher::_regEncode[src_lo]));
1597 } else {
1598 ShouldNotReachHere();
1599 }
1600 } else if (bottom_type()->isa_pvectmask() && masm) {
1601 int vmask_size_in_bytes = Matcher::scalable_predicate_reg_slots() * 32 / 8;
1602 if (src_lo_rc == rc_stack && dst_lo_rc == rc_stack) {
1603 // stack to stack
1604 __ spill_copy_vmask_stack_to_stack(src_offset, dst_offset,
1605 vmask_size_in_bytes);
1606 } else if (src_lo_rc == rc_vector && dst_lo_rc == rc_stack) {
1607 // vmask to stack
1608 __ spill_vmask(as_VectorRegister(Matcher::_regEncode[src_lo]), ra_->reg2offset(dst_lo));
1609 } else if (src_lo_rc == rc_stack && dst_lo_rc == rc_vector) {
1610 // stack to vmask
1611 __ unspill_vmask(as_VectorRegister(Matcher::_regEncode[dst_lo]), ra_->reg2offset(src_lo));
1612 } else if (src_lo_rc == rc_vector && dst_lo_rc == rc_vector) {
1613 // vmask to vmask
1614 __ vsetvli_helper(T_BYTE, MaxVectorSize >> 3);
1615 __ vmv_v_v(as_VectorRegister(Matcher::_regEncode[dst_lo]), as_VectorRegister(Matcher::_regEncode[src_lo]));
1616 } else {
1617 ShouldNotReachHere();
1618 }
1619 }
1620 } else if (masm != nullptr) {
1621 switch (src_lo_rc) {
1622 case rc_int:
1623 if (dst_lo_rc == rc_int) { // gpr --> gpr copy
1624 if (!is64 && this->ideal_reg() != Op_RegI) { // zero extended for narrow oop or klass
1625 __ zext(as_Register(Matcher::_regEncode[dst_lo]), as_Register(Matcher::_regEncode[src_lo]), 32);
1626 } else {
1627 __ mv(as_Register(Matcher::_regEncode[dst_lo]), as_Register(Matcher::_regEncode[src_lo]));
1628 }
1629 } else if (dst_lo_rc == rc_float) { // gpr --> fpr copy
1630 if (is64) {
1631 __ fmv_d_x(as_FloatRegister(Matcher::_regEncode[dst_lo]),
1632 as_Register(Matcher::_regEncode[src_lo]));
1633 } else {
1634 __ fmv_w_x(as_FloatRegister(Matcher::_regEncode[dst_lo]),
1635 as_Register(Matcher::_regEncode[src_lo]));
1636 }
1637 } else { // gpr --> stack spill
1638 assert(dst_lo_rc == rc_stack, "spill to bad register class");
1639 __ spill(as_Register(Matcher::_regEncode[src_lo]), is64, dst_offset);
1640 }
1641 break;
1642 case rc_float:
1643 if (dst_lo_rc == rc_int) { // fpr --> gpr copy
1644 if (is64) {
1645 __ fmv_x_d(as_Register(Matcher::_regEncode[dst_lo]),
1646 as_FloatRegister(Matcher::_regEncode[src_lo]));
1647 } else {
1648 __ fmv_x_w(as_Register(Matcher::_regEncode[dst_lo]),
1649 as_FloatRegister(Matcher::_regEncode[src_lo]));
1650 }
1651 } else if (dst_lo_rc == rc_float) { // fpr --> fpr copy
1652 if (is64) {
1653 __ fmv_d(as_FloatRegister(Matcher::_regEncode[dst_lo]),
1654 as_FloatRegister(Matcher::_regEncode[src_lo]));
1655 } else {
1656 __ fmv_s(as_FloatRegister(Matcher::_regEncode[dst_lo]),
1657 as_FloatRegister(Matcher::_regEncode[src_lo]));
1658 }
1659 } else { // fpr --> stack spill
1660 assert(dst_lo_rc == rc_stack, "spill to bad register class");
1661 __ spill(as_FloatRegister(Matcher::_regEncode[src_lo]),
1662 is64, dst_offset);
1663 }
1664 break;
1665 case rc_stack:
1666 if (dst_lo_rc == rc_int) { // stack --> gpr load
1667 if (this->ideal_reg() == Op_RegI) {
1668 __ unspill(as_Register(Matcher::_regEncode[dst_lo]), is64, src_offset);
1669 } else { // // zero extended for narrow oop or klass
1670 __ unspillu(as_Register(Matcher::_regEncode[dst_lo]), is64, src_offset);
1671 }
1672 } else if (dst_lo_rc == rc_float) { // stack --> fpr load
1673 __ unspill(as_FloatRegister(Matcher::_regEncode[dst_lo]),
1674 is64, src_offset);
1675 } else { // stack --> stack copy
1676 assert(dst_lo_rc == rc_stack, "spill to bad register class");
1677 if (this->ideal_reg() == Op_RegI) {
1678 __ unspill(t0, is64, src_offset);
1679 } else { // zero extended for narrow oop or klass
1680 __ unspillu(t0, is64, src_offset);
1681 }
1682 __ spill(t0, is64, dst_offset);
1683 }
1684 break;
1685 default:
1686 ShouldNotReachHere();
1687 }
1688 }
1689
1690 if (st != nullptr) {
1691 st->print("spill ");
1692 if (src_lo_rc == rc_stack) {
1693 st->print("[sp, #%d] -> ", src_offset);
1694 } else {
1695 st->print("%s -> ", Matcher::regName[src_lo]);
1696 }
1697 if (dst_lo_rc == rc_stack) {
1698 st->print("[sp, #%d]", dst_offset);
1699 } else {
1700 st->print("%s", Matcher::regName[dst_lo]);
1701 }
1702 if (bottom_type()->isa_vect() && !bottom_type()->isa_pvectmask()) {
1703 int vsize = 0;
1704 if (ideal_reg() == Op_VecA) {
1705 vsize = Matcher::scalable_vector_reg_size(T_BYTE) * 8;
1706 } else {
1707 ShouldNotReachHere();
1708 }
1709 st->print("\t# vector spill size = %d", vsize);
1710 } else if (ideal_reg() == Op_RegVectMask) {
1711 assert(Matcher::supports_scalable_vector(), "bad register type for spill");
1712 int vsize = Matcher::scalable_predicate_reg_slots() * 32;
1713 st->print("\t# vmask spill size = %d", vsize);
1714 } else {
1715 st->print("\t# spill size = %d", is64 ? 64 : 32);
1716 }
1717 }
1718
1719 return 0;
1720 }
1721
1722 #ifndef PRODUCT
1723 void MachSpillCopyNode::format(PhaseRegAlloc *ra_, outputStream *st) const {
1724 if (ra_ == nullptr) {
1725 st->print("N%d = SpillCopy(N%d)", _idx, in(1)->_idx);
1726 } else {
1727 implementation(nullptr, ra_, false, st);
1728 }
1729 }
1730 #endif
1731
1732 void MachSpillCopyNode::emit(C2_MacroAssembler *masm, PhaseRegAlloc *ra_) const {
1733 implementation(masm, ra_, false, nullptr);
1734 }
1735
1736 uint MachSpillCopyNode::size(PhaseRegAlloc *ra_) const {
1737 return MachNode::size(ra_);
1738 }
1739
1740 //=============================================================================
1741
1742 #ifndef PRODUCT
1743 void BoxLockNode::format(PhaseRegAlloc *ra_, outputStream *st) const {
1744 assert_cond(ra_ != nullptr && st != nullptr);
1745 int offset = ra_->reg2offset(in_RegMask(0).find_first_elem());
1746 int reg = ra_->get_reg_first(this);
1747 st->print("add %s, sp, #%d\t# box lock",
1748 Matcher::regName[reg], offset);
1749 }
1750 #endif
1751
1752 void BoxLockNode::emit(C2_MacroAssembler *masm, PhaseRegAlloc *ra_) const {
1753 Assembler::IncompressibleScope scope(masm); // Fixed length: see BoxLockNode::size()
1754
1755 assert_cond(ra_ != nullptr);
1756 int offset = ra_->reg2offset(in_RegMask(0).find_first_elem());
1757 int reg = ra_->get_encode(this);
1758
1759 if (Assembler::is_simm12(offset)) {
1760 __ addi(as_Register(reg), sp, offset);
1761 } else {
1762 __ li32(t0, offset);
1763 __ add(as_Register(reg), sp, t0);
1764 }
1765 }
1766
1767 uint BoxLockNode::size(PhaseRegAlloc *ra_) const {
1768 // BoxLockNode is not a MachNode, so we can't just call MachNode::size(ra_).
1769 int offset = ra_->reg2offset(in_RegMask(0).find_first_elem());
1770
1771 if (Assembler::is_simm12(offset)) {
1772 return NativeInstruction::instruction_size;
1773 } else {
1774 return 3 * NativeInstruction::instruction_size; // lui + addiw + add;
1775 }
1776 }
1777
1778 //=============================================================================
1779
1780 #ifndef PRODUCT
1781 void MachVEPNode::format(PhaseRegAlloc* ra_, outputStream* st) const
1782 {
1783 Unimplemented();
1784 }
1785 #endif
1786
1787 void MachVEPNode::emit(C2_MacroAssembler *masm, PhaseRegAlloc* ra_) const
1788 {
1789 Unimplemented();
1790 }
1791
1792 #ifndef PRODUCT
1793 void MachUEPNode::format(PhaseRegAlloc* ra_, outputStream* st) const
1794 {
1795 assert_cond(st != nullptr);
1796 st->print_cr("# MachUEPNode");
1797 st->print_cr("\tlwu t1, [j_rarg0 + oopDesc::klass_offset_in_bytes()]\t# compressed klass");
1798 st->print_cr("\tlwu t2, [t0 + CompiledICData::speculated_klass_offset()]\t# compressed klass");
1799 st->print_cr("\tbeq t1, t2, ic_hit");
1800 st->print_cr("\tj, SharedRuntime::_ic_miss_stub\t # Inline cache check");
1801 st->print_cr("\tic_hit:");
1802 }
1803 #endif
1804
1805 void MachUEPNode::emit(C2_MacroAssembler* masm, PhaseRegAlloc* ra_) const
1806 {
1807 // This is the unverified entry point.
1808 __ ic_check(CodeEntryAlignment);
1809
1810 // ic_check() aligns to CodeEntryAlignment >= InteriorEntryAlignment(min 16) > NativeInstruction::instruction_size(4).
1811 assert(((__ offset()) % CodeEntryAlignment) == 0, "Misaligned verified entry point");
1812 }
1813
1814 // REQUIRED EMIT CODE
1815
1816 //=============================================================================
1817
1818 // Emit deopt handler code.
1819 int HandlerImpl::emit_deopt_handler(C2_MacroAssembler* masm)
1820 {
1821 address base = __ start_a_stub(size_deopt_handler());
1822 if (base == nullptr) {
1823 ciEnv::current()->record_failure("CodeCache is full");
1824 return 0; // CodeBuffer::expand failed
1825 }
1826 int offset = __ offset();
1827
1828 Label start;
1829 __ bind(start);
1830
1831 __ far_call(RuntimeAddress(SharedRuntime::deopt_blob()->unpack()));
1832
1833 int entry_offset = __ offset();
1834 __ j(start);
1835
1836 assert(__ offset() - offset <= (int) size_deopt_handler(), "overflow");
1837 assert(__ offset() - entry_offset >= NativePostCallNop::first_check_size,
1838 "out of bounds read in post-call NOP check");
1839 __ end_a_stub();
1840 return entry_offset;
1841
1842 }
1843 // REQUIRED MATCHER CODE
1844
1845 //=============================================================================
1846
1847 bool Matcher::match_rule_supported(int opcode) {
1848 if (!has_match_rule(opcode)) {
1849 return false;
1850 }
1851
1852 switch (opcode) {
1853 case Op_OnSpinWait:
1854 return VM_Version::supports_on_spin_wait();
1855 case Op_CacheWB: // fall through
1856 case Op_CacheWBPreSync: // fall through
1857 case Op_CacheWBPostSync:
1858 if (!VM_Version::supports_data_cache_line_flush()) {
1859 return false;
1860 }
1861 break;
1862
1863 case Op_StrCompressedCopy: // fall through
1864 case Op_StrInflatedCopy: // fall through
1865 case Op_CountPositives: // fall through
1866 case Op_EncodeISOArray:
1867 return UseRVV;
1868
1869 case Op_PopCountI:
1870 case Op_PopCountL:
1871 return UsePopCountInstruction;
1872
1873 case Op_ReverseI:
1874 case Op_ReverseL:
1875 return UseZbkb;
1876
1877 case Op_ReverseBytesI:
1878 case Op_ReverseBytesL:
1879 case Op_ReverseBytesS:
1880 case Op_ReverseBytesUS:
1881 case Op_RotateRight:
1882 case Op_RotateLeft:
1883 case Op_CountLeadingZerosI:
1884 case Op_CountLeadingZerosL:
1885 case Op_CountTrailingZerosI:
1886 case Op_CountTrailingZerosL:
1887 return UseZbb;
1888
1889 case Op_FmaF:
1890 case Op_FmaD:
1891 return UseFMA;
1892
1893 case Op_ConvHF2F:
1894 case Op_ConvF2HF:
1895 return VM_Version::supports_float16_float_conversion();
1896 case Op_ReinterpretS2HF:
1897 case Op_ReinterpretHF2S:
1898 return UseZfh || UseZfhmin;
1899 case Op_AddHF:
1900 case Op_DivHF:
1901 case Op_FmaHF:
1902 case Op_MaxHF:
1903 case Op_MinHF:
1904 case Op_MulHF:
1905 case Op_SqrtHF:
1906 case Op_SubHF:
1907 return UseZfh;
1908
1909 case Op_CMoveP:
1910 case Op_CMoveN:
1911 return false;
1912 }
1913
1914 return true; // Per default match rules are supported.
1915 }
1916
1917 const RegMask* Matcher::predicate_reg_mask(void) {
1918 return &_VMASK_REG_mask;
1919 }
1920
1921 // Vector calling convention not yet implemented.
1922 bool Matcher::supports_vector_calling_convention(void) {
1923 return EnableVectorSupport;
1924 }
1925
1926 OptoRegPair Matcher::vector_return_value(uint ideal_reg) {
1927 assert(EnableVectorSupport, "sanity");
1928 assert(ideal_reg == Op_VecA, "sanity");
1929 // check more info at https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-cc.adoc
1930 int lo = V8_num;
1931 int hi = V8_K_num;
1932 return OptoRegPair(hi, lo);
1933 }
1934
1935 // Is this branch offset short enough that a short branch can be used?
1936 //
1937 // NOTE: If the platform does not provide any short branch variants, then
1938 // this method should return false for offset 0.
1939 // |---label(L1)-----|
1940 // |-----------------|
1941 // |-----------------|----------eq: float-------------------
1942 // |-----------------| // far_cmpD_branch | cmpD_branch
1943 // |------- ---------| feq; | feq;
1944 // |-far_cmpD_branch-| beqz done; | bnez L;
1945 // |-----------------| j L; |
1946 // |-----------------| bind(done); |
1947 // |-----------------|--------------------------------------
1948 // |-----------------| // so shortBrSize = br_size - 4;
1949 // |-----------------| // so offs = offset - shortBrSize + 4;
1950 // |---label(L2)-----|
1951 bool Matcher::is_short_branch_offset(int rule, int br_size, int offset) {
1952 // The passed offset is relative to address of the branch.
1953 int shortBrSize = br_size - 4;
1954 int offs = offset - shortBrSize + 4;
1955 return (-4096 <= offs && offs < 4096);
1956 }
1957
1958 // Vector width in bytes.
1959 int Matcher::vector_width_in_bytes(BasicType bt) {
1960 if (UseRVV) {
1961 // The MaxVectorSize should have been set by detecting RVV max vector register size when check UseRVV.
1962 // MaxVectorSize == VM_Version::_initial_vector_length
1963 int size = MaxVectorSize;
1964 // Minimum 2 values in vector
1965 if (size < 2 * type2aelembytes(bt)) size = 0;
1966 // But never < 4
1967 if (size < 4) size = 0;
1968 return size;
1969 }
1970 return 0;
1971 }
1972
1973 // Limits on vector size (number of elements) loaded into vector.
1974 int Matcher::max_vector_size(const BasicType bt) {
1975 return vector_width_in_bytes(bt) / type2aelembytes(bt);
1976 }
1977
1978 int Matcher::min_vector_size(const BasicType bt) {
1979 int size;
1980 switch(bt) {
1981 case T_BOOLEAN:
1982 // Load/store a vector mask with only 2 elements for vector types
1983 // such as "2I/2F/2L/2D".
1984 size = 2;
1985 break;
1986 case T_BYTE:
1987 // Generate a "4B" vector, to support vector cast between "8B/16B"
1988 // and "4S/4I/4L/4F/4D".
1989 size = 4;
1990 break;
1991 case T_SHORT:
1992 // Generate a "2S" vector, to support vector cast between "4S/8S"
1993 // and "2I/2L/2F/2D".
1994 size = 2;
1995 break;
1996 default:
1997 // Limit the min vector length to 64-bit.
1998 size = 8 / type2aelembytes(bt);
1999 // The number of elements in a vector should be at least 2.
2000 size = MAX2(size, 2);
2001 }
2002
2003 int max_size = max_vector_size(bt);
2004 return MIN2(size, max_size);
2005 }
2006
2007 int Matcher::max_vector_size_auto_vectorization(const BasicType bt) {
2008 return Matcher::max_vector_size(bt);
2009 }
2010
2011 // Vector ideal reg.
2012 uint Matcher::vector_ideal_reg(int len) {
2013 assert(MaxVectorSize >= len, "");
2014 if (UseRVV) {
2015 return Op_VecA;
2016 }
2017
2018 ShouldNotReachHere();
2019 return 0;
2020 }
2021
2022 int Matcher::scalable_vector_reg_size(const BasicType bt) {
2023 return Matcher::max_vector_size(bt);
2024 }
2025
2026 MachOper* Matcher::pd_specialize_generic_vector_operand(MachOper* original_opnd, uint ideal_reg, bool is_temp) {
2027 ShouldNotReachHere(); // generic vector operands not supported
2028 return nullptr;
2029 }
2030
2031 bool Matcher::is_reg2reg_move(MachNode* m) {
2032 ShouldNotReachHere(); // generic vector operands not supported
2033 return false;
2034 }
2035
2036 bool Matcher::is_register_biasing_candidate(const MachNode* mdef, int oper_index) {
2037 return false;
2038 }
2039
2040 bool Matcher::is_generic_vector(MachOper* opnd) {
2041 ShouldNotReachHere(); // generic vector operands not supported
2042 return false;
2043 }
2044
2045 #ifdef ASSERT
2046 // Return whether or not this register is ever used as an argument.
2047 bool Matcher::can_be_java_arg(int reg)
2048 {
2049 return
2050 reg == R10_num || reg == R10_H_num ||
2051 reg == R11_num || reg == R11_H_num ||
2052 reg == R12_num || reg == R12_H_num ||
2053 reg == R13_num || reg == R13_H_num ||
2054 reg == R14_num || reg == R14_H_num ||
2055 reg == R15_num || reg == R15_H_num ||
2056 reg == R16_num || reg == R16_H_num ||
2057 reg == R17_num || reg == R17_H_num ||
2058 reg == F10_num || reg == F10_H_num ||
2059 reg == F11_num || reg == F11_H_num ||
2060 reg == F12_num || reg == F12_H_num ||
2061 reg == F13_num || reg == F13_H_num ||
2062 reg == F14_num || reg == F14_H_num ||
2063 reg == F15_num || reg == F15_H_num ||
2064 reg == F16_num || reg == F16_H_num ||
2065 reg == F17_num || reg == F17_H_num;
2066 }
2067 #endif
2068
2069 uint Matcher::int_pressure_limit()
2070 {
2071 // A derived pointer is live at CallNode and then is flagged by RA
2072 // as a spilled LRG. Spilling heuristics(Spill-USE) explicitly skip
2073 // derived pointers and lastly fail to spill after reaching maximum
2074 // number of iterations. Lowering the default pressure threshold to
2075 // (_NO_SPECIAL_REG32_mask.size() minus 1) forces CallNode to become
2076 // a high register pressure area of the code so that split_DEF can
2077 // generate DefinitionSpillCopy for the derived pointer.
2078 uint default_int_pressure_threshold = _NO_SPECIAL_REG32_mask.size() - 1;
2079 if (!PreserveFramePointer) {
2080 // When PreserveFramePointer is off, frame pointer is allocatable,
2081 // but different from other SOC registers, it is excluded from
2082 // fatproj's mask because its save type is No-Save. Decrease 1 to
2083 // ensure high pressure at fatproj when PreserveFramePointer is off.
2084 // See check_pressure_at_fatproj().
2085 default_int_pressure_threshold--;
2086 }
2087 return (INTPRESSURE == -1) ? default_int_pressure_threshold : INTPRESSURE;
2088 }
2089
2090 uint Matcher::float_pressure_limit()
2091 {
2092 // _FLOAT_REG_mask is generated by adlc from the float_reg register class.
2093 return (FLOATPRESSURE == -1) ? _FLOAT_REG_mask.size() : FLOATPRESSURE;
2094 }
2095
2096 const RegMask& Matcher::divI_proj_mask() {
2097 ShouldNotReachHere();
2098 return RegMask::EMPTY;
2099 }
2100
2101 // Register for MODI projection of divmodI.
2102 const RegMask& Matcher::modI_proj_mask() {
2103 ShouldNotReachHere();
2104 return RegMask::EMPTY;
2105 }
2106
2107 // Register for DIVL projection of divmodL.
2108 const RegMask& Matcher::divL_proj_mask() {
2109 ShouldNotReachHere();
2110 return RegMask::EMPTY;
2111 }
2112
2113 // Register for MODL projection of divmodL.
2114 const RegMask& Matcher::modL_proj_mask() {
2115 ShouldNotReachHere();
2116 return RegMask::EMPTY;
2117 }
2118
2119 bool size_fits_all_mem_uses(AddPNode* addp, int shift) {
2120 assert_cond(addp != nullptr);
2121 for (DUIterator_Fast imax, i = addp->fast_outs(imax); i < imax; i++) {
2122 Node* u = addp->fast_out(i);
2123 if (u != nullptr && u->is_Mem()) {
2124 int opsize = u->as_Mem()->memory_size();
2125 assert(opsize > 0, "unexpected memory operand size");
2126 if (u->as_Mem()->memory_size() != (1 << shift)) {
2127 return false;
2128 }
2129 }
2130 }
2131 return true;
2132 }
2133
2134 // Binary src (Replicate scalar/immediate)
2135 static bool is_vector_scalar_bitwise_pattern(Node* n, Node* m) {
2136 if (n == nullptr || m == nullptr) {
2137 return false;
2138 }
2139
2140 if (m->Opcode() != Op_Replicate) {
2141 return false;
2142 }
2143
2144 switch (n->Opcode()) {
2145 case Op_AndV:
2146 case Op_OrV:
2147 case Op_XorV:
2148 case Op_AddVB:
2149 case Op_AddVS:
2150 case Op_AddVI:
2151 case Op_AddVL:
2152 case Op_SubVB:
2153 case Op_SubVS:
2154 case Op_SubVI:
2155 case Op_SubVL:
2156 case Op_MulVB:
2157 case Op_MulVS:
2158 case Op_MulVI:
2159 case Op_MulVL: {
2160 return true;
2161 }
2162 default:
2163 return false;
2164 }
2165 }
2166
2167 // (XorV src (Replicate m1))
2168 // (XorVMask src (MaskAll m1))
2169 static bool is_vector_bitwise_not_pattern(Node* n, Node* m) {
2170 if (n != nullptr && m != nullptr) {
2171 return (n->Opcode() == Op_XorV || n->Opcode() == Op_XorVMask) &&
2172 VectorNode::is_all_ones_vector(m);
2173 }
2174 return false;
2175 }
2176
2177 // Should the Matcher clone input 'm' of node 'n'?
2178 bool Matcher::pd_clone_node(Node* n, Node* m, Matcher::MStack& mstack) {
2179 assert_cond(m != nullptr);
2180 if (is_vshift_con_pattern(n, m) || // ShiftV src (ShiftCntV con)
2181 is_vector_bitwise_not_pattern(n, m) ||
2182 is_vector_scalar_bitwise_pattern(n, m) ||
2183 is_encode_and_store_pattern(n, m)) {
2184 mstack.push(m, Visit);
2185 return true;
2186 }
2187 return false;
2188 }
2189
2190 // Should the Matcher clone shifts on addressing modes, expecting them
2191 // to be subsumed into complex addressing expressions or compute them
2192 // into registers?
2193 bool Matcher::pd_clone_address_expressions(AddPNode* m, Matcher::MStack& mstack, VectorSet& address_visited) {
2194 return clone_base_plus_offset_address(m, mstack, address_visited);
2195 }
2196
2197 %}
2198
2199
2200
2201 //----------ENCODING BLOCK-----------------------------------------------------
2202 // This block specifies the encoding classes used by the compiler to
2203 // output byte streams. Encoding classes are parameterized macros
2204 // used by Machine Instruction Nodes in order to generate the bit
2205 // encoding of the instruction. Operands specify their base encoding
2206 // interface with the interface keyword. There are currently
2207 // supported four interfaces, REG_INTER, CONST_INTER, MEMORY_INTER, &
2208 // COND_INTER. REG_INTER causes an operand to generate a function
2209 // which returns its register number when queried. CONST_INTER causes
2210 // an operand to generate a function which returns the value of the
2211 // constant when queried. MEMORY_INTER causes an operand to generate
2212 // four functions which return the Base Register, the Index Register,
2213 // the Scale Value, and the Offset Value of the operand when queried.
2214 // COND_INTER causes an operand to generate six functions which return
2215 // the encoding code (ie - encoding bits for the instruction)
2216 // associated with each basic boolean condition for a conditional
2217 // instruction.
2218 //
2219 // Instructions specify two basic values for encoding. Again, a
2220 // function is available to check if the constant displacement is an
2221 // oop. They use the ins_encode keyword to specify their encoding
2222 // classes (which must be a sequence of enc_class names, and their
2223 // parameters, specified in the encoding block), and they use the
2224 // opcode keyword to specify, in order, their primary, secondary, and
2225 // tertiary opcode. Only the opcode sections which a particular
2226 // instruction needs for encoding need to be specified.
2227 encode %{
2228 // BEGIN Non-volatile memory access
2229
2230 enc_class riscv_enc_mov_imm(iRegIorL dst, immIorL src) %{
2231 int64_t con = (int64_t)$src$$constant;
2232 Register dst_reg = as_Register($dst$$reg);
2233 __ mv(dst_reg, con);
2234 %}
2235
2236 enc_class riscv_enc_mov_p(iRegP dst, immP src) %{
2237 Register dst_reg = as_Register($dst$$reg);
2238 address con = (address)$src$$constant;
2239 if (con == nullptr || con == (address)1) {
2240 ShouldNotReachHere();
2241 } else {
2242 relocInfo::relocType rtype = $src->constant_reloc();
2243 if (rtype == relocInfo::oop_type) {
2244 __ movoop(dst_reg, (jobject)con);
2245 } else if (rtype == relocInfo::metadata_type) {
2246 __ mov_metadata(dst_reg, (Metadata*)con);
2247 } else {
2248 assert(rtype == relocInfo::none || rtype == relocInfo::external_word_type, "unexpected reloc type");
2249 __ mv(dst_reg, $src$$constant);
2250 }
2251 }
2252 %}
2253
2254 enc_class riscv_enc_mov_p1(iRegP dst) %{
2255 Register dst_reg = as_Register($dst$$reg);
2256 __ mv(dst_reg, 1);
2257 %}
2258
2259 enc_class riscv_enc_mov_n(iRegN dst, immN src) %{
2260 Register dst_reg = as_Register($dst$$reg);
2261 address con = (address)$src$$constant;
2262 if (con == nullptr) {
2263 ShouldNotReachHere();
2264 } else {
2265 relocInfo::relocType rtype = $src->constant_reloc();
2266 assert(rtype == relocInfo::oop_type, "unexpected reloc type");
2267 __ set_narrow_oop(dst_reg, (jobject)con);
2268 }
2269 %}
2270
2271 enc_class riscv_enc_mov_zero(iRegNorP dst) %{
2272 Register dst_reg = as_Register($dst$$reg);
2273 __ mv(dst_reg, zr);
2274 %}
2275
2276 enc_class riscv_enc_mov_nk(iRegN dst, immNKlass src) %{
2277 Register dst_reg = as_Register($dst$$reg);
2278 address con = (address)$src$$constant;
2279 if (con == nullptr) {
2280 ShouldNotReachHere();
2281 } else {
2282 relocInfo::relocType rtype = $src->constant_reloc();
2283 assert(rtype == relocInfo::metadata_type, "unexpected reloc type");
2284 __ set_narrow_klass(dst_reg, (Klass *)con);
2285 }
2286 %}
2287
2288 // compare and branch instruction encodings
2289
2290 enc_class riscv_enc_j(label lbl) %{
2291 Label* L = $lbl$$label;
2292 __ j(*L);
2293 %}
2294
2295 enc_class riscv_enc_far_cmpULtGe_imm0_branch(cmpOpULtGe cmp, iRegIorL op1, label lbl) %{
2296 Label* L = $lbl$$label;
2297 switch ($cmp$$cmpcode) {
2298 case(BoolTest::ge):
2299 __ j(*L);
2300 break;
2301 case(BoolTest::lt):
2302 break;
2303 default:
2304 Unimplemented();
2305 }
2306 %}
2307
2308 // call instruction encodings
2309
2310 enc_class riscv_enc_partial_subtype_check(iRegP sub, iRegP super, iRegP temp, iRegP result) %{
2311 Register sub_reg = as_Register($sub$$reg);
2312 Register super_reg = as_Register($super$$reg);
2313 Register temp_reg = as_Register($temp$$reg);
2314 Register result_reg = as_Register($result$$reg);
2315 Register cr_reg = t1;
2316
2317 Label miss;
2318 Label done;
2319 __ check_klass_subtype_slow_path(sub_reg, super_reg, temp_reg, result_reg,
2320 nullptr, &miss, /*set_cond_codes*/ true);
2321 if ($primary) {
2322 __ mv(result_reg, zr);
2323 } else {
2324 __ mv(cr_reg, zr);
2325 __ j(done);
2326 }
2327
2328 __ bind(miss);
2329 if (!$primary) {
2330 __ mv(cr_reg, 1);
2331 }
2332
2333 __ bind(done);
2334 %}
2335
2336 enc_class riscv_enc_java_static_call(method meth) %{
2337 Assembler::IncompressibleScope scope(masm); // Fixed length: see ret_addr_offset
2338
2339 address addr = (address)$meth$$method;
2340 address call = nullptr;
2341 assert_cond(addr != nullptr);
2342 if (!_method) {
2343 // A call to a runtime wrapper, e.g. new, new_typeArray_Java, uncommon_trap.
2344 call = __ reloc_call(Address(addr, relocInfo::runtime_call_type));
2345 if (call == nullptr) {
2346 ciEnv::current()->record_failure("CodeCache is full");
2347 return;
2348 }
2349 } else if (_method->intrinsic_id() == vmIntrinsicID::_ensureMaterializedForStackWalk) {
2350 // The NOP here is purely to ensure that eliding a call to
2351 // JVM_EnsureMaterializedForStackWalk doesn't change the code size.
2352 __ nop();
2353 __ nop();
2354 __ nop();
2355 __ block_comment("call JVM_EnsureMaterializedForStackWalk (elided)");
2356 } else {
2357 int method_index = resolved_method_index(masm);
2358 RelocationHolder rspec = _optimized_virtual ? opt_virtual_call_Relocation::spec(method_index)
2359 : static_call_Relocation::spec(method_index);
2360 call = __ reloc_call(Address(addr, rspec));
2361 if (call == nullptr) {
2362 ciEnv::current()->record_failure("CodeCache is full");
2363 return;
2364 }
2365
2366 if (CodeBuffer::supports_shared_stubs() && _method->can_be_statically_bound()) {
2367 // Calls of the same statically bound method can share
2368 // a stub to the interpreter.
2369 __ code()->shared_stub_to_interp_for(_method, call - (__ begin()));
2370 } else {
2371 // Emit stub for static call
2372 address stub = CompiledDirectCall::emit_to_interp_stub(masm, call);
2373 if (stub == nullptr) {
2374 ciEnv::current()->record_failure("CodeCache is full");
2375 return;
2376 }
2377 }
2378 }
2379
2380 __ post_call_nop();
2381 %}
2382
2383 enc_class riscv_enc_java_dynamic_call(method meth) %{
2384 Assembler::IncompressibleScope scope(masm); // Fixed length: see ret_addr_offset
2385 int method_index = resolved_method_index(masm);
2386 address call = __ ic_call((address)$meth$$method, method_index);
2387 if (call == nullptr) {
2388 ciEnv::current()->record_failure("CodeCache is full");
2389 return;
2390 }
2391
2392 __ post_call_nop();
2393 %}
2394
2395 enc_class riscv_enc_call_epilog() %{
2396 if (VerifyStackAtCalls) {
2397 // Check that stack depth is unchanged: find majik cookie on stack
2398 int framesize = ra_->reg2offset_unchecked(OptoReg::add(ra_->_matcher._old_SP, -3 * VMRegImpl::slots_per_word));
2399 Label stack_ok;
2400 __ ld(t1, Address(sp, framesize));
2401 __ mv(t2, MAJIK_DWORD);
2402 __ beq(t2, t1, stack_ok);
2403 __ stop("MAJIK_DWORD not found");
2404 __ bind(stack_ok);
2405 }
2406 %}
2407
2408 enc_class riscv_enc_java_to_runtime(method meth) %{
2409 Assembler::IncompressibleScope scope(masm); // Fixed length: see ret_addr_offset
2410
2411 // Some calls to generated routines (arraycopy code) are scheduled by C2
2412 // as runtime calls. if so we can call them using a far call (they will be
2413 // in the code cache, thus in a reachable segment) otherwise we have to use
2414 // a movptr+jalr pair which loads the absolute address into a register.
2415 address entry = (address)$meth$$method;
2416 if (CodeCache::contains(entry)) {
2417 __ far_call(Address(entry, relocInfo::runtime_call_type));
2418 __ post_call_nop();
2419 } else {
2420 Label retaddr;
2421 // Make the anchor frame walkable
2422 __ la(t0, retaddr);
2423 __ sd(t0, Address(xthread, JavaThread::last_Java_pc_offset()));
2424 int32_t offset = 0;
2425 // No relocation needed
2426 __ movptr(t1, entry, offset, t0); // lui + lui + slli + add
2427 __ jalr(t1, offset);
2428 __ bind(retaddr);
2429 __ post_call_nop();
2430 }
2431 %}
2432
2433 enc_class riscv_enc_tail_call(iRegP jump_target) %{
2434 Register target_reg = as_Register($jump_target$$reg);
2435 __ jr(target_reg);
2436 %}
2437
2438 enc_class riscv_enc_tail_jmp(iRegP jump_target) %{
2439 Register target_reg = as_Register($jump_target$$reg);
2440 // exception oop should be in x10
2441 // ret addr has been popped into ra
2442 // callee expects it in x13
2443 __ mv(x13, ra);
2444 __ jr(target_reg);
2445 %}
2446
2447 enc_class riscv_enc_rethrow() %{
2448 __ far_jump(RuntimeAddress(OptoRuntime::rethrow_stub()));
2449 %}
2450
2451 enc_class riscv_enc_ret() %{
2452 __ ret();
2453 %}
2454
2455 %}
2456
2457 //----------FRAME--------------------------------------------------------------
2458 // Definition of frame structure and management information.
2459 //
2460 // S T A C K L A Y O U T Allocators stack-slot number
2461 // | (to get allocators register number
2462 // G Owned by | | v add OptoReg::stack0())
2463 // r CALLER | |
2464 // o | +--------+ pad to even-align allocators stack-slot
2465 // w V | pad0 | numbers; owned by CALLER
2466 // t -----------+--------+----> Matcher::_in_arg_limit, unaligned
2467 // h ^ | in | 5
2468 // | | args | 4 Holes in incoming args owned by SELF
2469 // | | | | 3
2470 // | | +--------+
2471 // V | | old out| Empty on Intel, window on Sparc
2472 // | old |preserve| Must be even aligned.
2473 // | SP-+--------+----> Matcher::_old_SP, even aligned
2474 // | | in | 3 area for Intel ret address
2475 // Owned by |preserve| Empty on Sparc.
2476 // SELF +--------+
2477 // | | pad2 | 2 pad to align old SP
2478 // | +--------+ 1
2479 // | | locks | 0
2480 // | +--------+----> OptoReg::stack0(), even aligned
2481 // | | pad1 | 11 pad to align new SP
2482 // | +--------+
2483 // | | | 10
2484 // | | spills | 9 spills
2485 // V | | 8 (pad0 slot for callee)
2486 // -----------+--------+----> Matcher::_out_arg_limit, unaligned
2487 // ^ | out | 7
2488 // | | args | 6 Holes in outgoing args owned by CALLEE
2489 // Owned by +--------+
2490 // CALLEE | new out| 6 Empty on Intel, window on Sparc
2491 // | new |preserve| Must be even-aligned.
2492 // | SP-+--------+----> Matcher::_new_SP, even aligned
2493 // | | |
2494 //
2495 // Note 1: Only region 8-11 is determined by the allocator. Region 0-5 is
2496 // known from SELF's arguments and the Java calling convention.
2497 // Region 6-7 is determined per call site.
2498 // Note 2: If the calling convention leaves holes in the incoming argument
2499 // area, those holes are owned by SELF. Holes in the outgoing area
2500 // are owned by the CALLEE. Holes should not be necessary in the
2501 // incoming area, as the Java calling convention is completely under
2502 // the control of the AD file. Doubles can be sorted and packed to
2503 // avoid holes. Holes in the outgoing arguments may be necessary for
2504 // varargs C calling conventions.
2505 // Note 3: Region 0-3 is even aligned, with pad2 as needed. Region 3-5 is
2506 // even aligned with pad0 as needed.
2507 // Region 6 is even aligned. Region 6-7 is NOT even aligned;
2508 // (the latter is true on Intel but is it false on RISCV?)
2509 // region 6-11 is even aligned; it may be padded out more so that
2510 // the region from SP to FP meets the minimum stack alignment.
2511 // Note 4: For I2C adapters, the incoming FP may not meet the minimum stack
2512 // alignment. Region 11, pad1, may be dynamically extended so that
2513 // SP meets the minimum alignment.
2514
2515 frame %{
2516 // These three registers define part of the calling convention
2517 // between compiled code and the interpreter.
2518
2519 // Inline Cache Register or methodOop for I2C.
2520 inline_cache_reg(R31);
2521
2522 // Optional: name the operand used by cisc-spilling to access [stack_pointer + offset]
2523 cisc_spilling_operand_name(indOffset);
2524
2525 // Number of stack slots consumed by locking an object
2526 // generate Compile::sync_stack_slots
2527 // VMRegImpl::slots_per_word = wordSize / stack_slot_size = 8 / 4 = 2
2528 sync_stack_slots(1 * VMRegImpl::slots_per_word);
2529
2530 // Compiled code's Frame Pointer
2531 frame_pointer(R2);
2532
2533 // Stack alignment requirement
2534 stack_alignment(StackAlignmentInBytes); // Alignment size in bytes (128-bit -> 16 bytes)
2535
2536 // Number of outgoing stack slots killed above the out_preserve_stack_slots
2537 // for calls to C. Supports the var-args backing area for register parms.
2538 varargs_C_out_slots_killed(frame::arg_reg_save_area_bytes / BytesPerInt);
2539
2540 // The after-PROLOG location of the return address. Location of
2541 // return address specifies a type (REG or STACK) and a number
2542 // representing the register number (i.e. - use a register name) or
2543 // stack slot.
2544 // Ret Addr is on stack in slot 0 if no locks or verification or alignment.
2545 // Otherwise, it is above the locks and verification slot and alignment word
2546 // TODO this may well be correct but need to check why that - 2 is there
2547 // ppc port uses 0 but we definitely need to allow for fixed_slots
2548 // which folds in the space used for monitors
2549 return_addr(STACK - 2 +
2550 align_up((Compile::current()->in_preserve_stack_slots() +
2551 Compile::current()->fixed_slots()),
2552 stack_alignment_in_slots()));
2553
2554 // Location of compiled Java return values. Same as C for now.
2555 return_value
2556 %{
2557 assert(ideal_reg >= Op_RegI && ideal_reg <= Op_RegL,
2558 "only return normal values");
2559
2560 static const int lo[Op_RegL + 1] = { // enum name
2561 0, // Op_Node
2562 0, // Op_Set
2563 R10_num, // Op_RegN
2564 R10_num, // Op_RegI
2565 R10_num, // Op_RegP
2566 F10_num, // Op_RegF
2567 F10_num, // Op_RegD
2568 R10_num // Op_RegL
2569 };
2570
2571 static const int hi[Op_RegL + 1] = { // enum name
2572 0, // Op_Node
2573 0, // Op_Set
2574 OptoReg::Bad, // Op_RegN
2575 OptoReg::Bad, // Op_RegI
2576 R10_H_num, // Op_RegP
2577 OptoReg::Bad, // Op_RegF
2578 F10_H_num, // Op_RegD
2579 R10_H_num // Op_RegL
2580 };
2581
2582 return OptoRegPair(hi[ideal_reg], lo[ideal_reg]);
2583 %}
2584 %}
2585
2586 //----------ATTRIBUTES---------------------------------------------------------
2587 //----------Operand Attributes-------------------------------------------------
2588 op_attrib op_cost(1); // Required cost attribute
2589
2590 //----------Instruction Attributes---------------------------------------------
2591 ins_attrib ins_cost(DEFAULT_COST); // Required cost attribute
2592 ins_attrib ins_size(32); // Required size attribute (in bits)
2593 ins_attrib ins_short_branch(0); // Required flag: is this instruction
2594 // a non-matching short branch variant
2595 // of some long branch?
2596 ins_attrib ins_alignment(4); // Required alignment attribute (must
2597 // be a power of 2) specifies the
2598 // alignment that some part of the
2599 // instruction (not necessarily the
2600 // start) requires. If > 1, a
2601 // compute_padding() function must be
2602 // provided for the instruction
2603
2604 // Whether this node is expanded during code emission into a sequence of
2605 // instructions and the first instruction can perform an implicit null check.
2606 ins_attrib ins_is_late_expanded_null_check_candidate(false);
2607
2608 //----------OPERANDS-----------------------------------------------------------
2609 // Operand definitions must precede instruction definitions for correct parsing
2610 // in the ADLC because operands constitute user defined types which are used in
2611 // instruction definitions.
2612
2613 //----------Simple Operands----------------------------------------------------
2614
2615 // Integer operands 32 bit
2616 // 32 bit immediate
2617 operand immI()
2618 %{
2619 match(ConI);
2620
2621 op_cost(0);
2622 format %{ %}
2623 interface(CONST_INTER);
2624 %}
2625
2626 // 32 bit zero
2627 operand immI0()
2628 %{
2629 predicate(n->get_int() == 0);
2630 match(ConI);
2631
2632 op_cost(0);
2633 format %{ %}
2634 interface(CONST_INTER);
2635 %}
2636
2637 // 32 bit unit increment
2638 operand immI_1()
2639 %{
2640 predicate(n->get_int() == 1);
2641 match(ConI);
2642
2643 op_cost(0);
2644 format %{ %}
2645 interface(CONST_INTER);
2646 %}
2647
2648 // 32 bit unit decrement
2649 operand immI_M1()
2650 %{
2651 predicate(n->get_int() == -1);
2652 match(ConI);
2653
2654 op_cost(0);
2655 format %{ %}
2656 interface(CONST_INTER);
2657 %}
2658
2659 // Unsigned Integer Immediate: 6-bit int, greater than 32
2660 operand uimmI6_ge32() %{
2661 predicate(((unsigned int)(n->get_int()) < 64) && (n->get_int() >= 32));
2662 match(ConI);
2663 op_cost(0);
2664 format %{ %}
2665 interface(CONST_INTER);
2666 %}
2667
2668 operand immI_le_4()
2669 %{
2670 predicate(n->get_int() <= 4);
2671 match(ConI);
2672
2673 op_cost(0);
2674 format %{ %}
2675 interface(CONST_INTER);
2676 %}
2677
2678 operand immI_16()
2679 %{
2680 predicate(n->get_int() == 16);
2681 match(ConI);
2682 op_cost(0);
2683 format %{ %}
2684 interface(CONST_INTER);
2685 %}
2686
2687 operand immI_24()
2688 %{
2689 predicate(n->get_int() == 24);
2690 match(ConI);
2691 op_cost(0);
2692 format %{ %}
2693 interface(CONST_INTER);
2694 %}
2695
2696 operand immI_31()
2697 %{
2698 predicate(n->get_int() == 31);
2699 match(ConI);
2700
2701 op_cost(0);
2702 format %{ %}
2703 interface(CONST_INTER);
2704 %}
2705
2706 operand immI_63()
2707 %{
2708 predicate(n->get_int() == 63);
2709 match(ConI);
2710
2711 op_cost(0);
2712 format %{ %}
2713 interface(CONST_INTER);
2714 %}
2715
2716 // 32 bit integer valid for add immediate
2717 operand immIAdd()
2718 %{
2719 predicate(Assembler::is_simm12((int64_t)n->get_int()));
2720 match(ConI);
2721 op_cost(0);
2722 format %{ %}
2723 interface(CONST_INTER);
2724 %}
2725
2726 // 32 bit integer valid for sub immediate
2727 operand immISub()
2728 %{
2729 predicate(Assembler::is_simm12(-(int64_t)n->get_int()));
2730 match(ConI);
2731 op_cost(0);
2732 format %{ %}
2733 interface(CONST_INTER);
2734 %}
2735
2736 // 5 bit signed value.
2737 operand immI5()
2738 %{
2739 predicate(n->get_int() <= 15 && n->get_int() >= -16);
2740 match(ConI);
2741
2742 op_cost(0);
2743 format %{ %}
2744 interface(CONST_INTER);
2745 %}
2746
2747 // 5 bit signed value (simm5)
2748 operand immL5()
2749 %{
2750 predicate(n->get_long() <= 15 && n->get_long() >= -16);
2751 match(ConL);
2752
2753 op_cost(0);
2754 format %{ %}
2755 interface(CONST_INTER);
2756 %}
2757
2758 // Integer operands 64 bit
2759 // 64 bit immediate
2760 operand immL()
2761 %{
2762 match(ConL);
2763
2764 op_cost(0);
2765 format %{ %}
2766 interface(CONST_INTER);
2767 %}
2768
2769 // 64 bit zero
2770 operand immL0()
2771 %{
2772 predicate(n->get_long() == 0);
2773 match(ConL);
2774
2775 op_cost(0);
2776 format %{ %}
2777 interface(CONST_INTER);
2778 %}
2779
2780 // Pointer operands
2781 // Pointer Immediate
2782 operand immP()
2783 %{
2784 match(ConP);
2785
2786 op_cost(0);
2787 format %{ %}
2788 interface(CONST_INTER);
2789 %}
2790
2791 // Null Pointer Immediate
2792 operand immP0()
2793 %{
2794 predicate(n->get_ptr() == 0);
2795 match(ConP);
2796
2797 op_cost(0);
2798 format %{ %}
2799 interface(CONST_INTER);
2800 %}
2801
2802 // Pointer Immediate One
2803 // this is used in object initialization (initial object header)
2804 operand immP_1()
2805 %{
2806 predicate(n->get_ptr() == 1);
2807 match(ConP);
2808
2809 op_cost(0);
2810 format %{ %}
2811 interface(CONST_INTER);
2812 %}
2813
2814 // Int Immediate: low 16-bit mask
2815 operand immI_16bits()
2816 %{
2817 predicate(n->get_int() == 0xFFFF);
2818 match(ConI);
2819 op_cost(0);
2820 format %{ %}
2821 interface(CONST_INTER);
2822 %}
2823
2824 operand immIpowerOf2() %{
2825 predicate(is_power_of_2((juint)(n->get_int())));
2826 match(ConI);
2827 op_cost(0);
2828 format %{ %}
2829 interface(CONST_INTER);
2830 %}
2831
2832 // Long Immediate: low 32-bit mask
2833 operand immL_32bits()
2834 %{
2835 predicate(n->get_long() == 0xFFFFFFFFL);
2836 match(ConL);
2837 op_cost(0);
2838 format %{ %}
2839 interface(CONST_INTER);
2840 %}
2841
2842 // 64 bit unit decrement
2843 operand immL_M1()
2844 %{
2845 predicate(n->get_long() == -1);
2846 match(ConL);
2847
2848 op_cost(0);
2849 format %{ %}
2850 interface(CONST_INTER);
2851 %}
2852
2853
2854 // 64 bit integer valid for add immediate
2855 operand immLAdd()
2856 %{
2857 predicate(Assembler::is_simm12(n->get_long()));
2858 match(ConL);
2859 op_cost(0);
2860 format %{ %}
2861 interface(CONST_INTER);
2862 %}
2863
2864 // 64 bit integer valid for sub immediate
2865 operand immLSub()
2866 %{
2867 predicate(Assembler::is_simm12(-(n->get_long())));
2868 match(ConL);
2869 op_cost(0);
2870 format %{ %}
2871 interface(CONST_INTER);
2872 %}
2873
2874 // Narrow pointer operands
2875 // Narrow Pointer Immediate
2876 operand immN()
2877 %{
2878 match(ConN);
2879
2880 op_cost(0);
2881 format %{ %}
2882 interface(CONST_INTER);
2883 %}
2884
2885 // Narrow Null Pointer Immediate
2886 operand immN0()
2887 %{
2888 predicate(n->get_narrowcon() == 0);
2889 match(ConN);
2890
2891 op_cost(0);
2892 format %{ %}
2893 interface(CONST_INTER);
2894 %}
2895
2896 operand immNKlass()
2897 %{
2898 match(ConNKlass);
2899
2900 op_cost(0);
2901 format %{ %}
2902 interface(CONST_INTER);
2903 %}
2904
2905 // Float and Double operands
2906 // Double Immediate
2907 operand immD()
2908 %{
2909 match(ConD);
2910 op_cost(0);
2911 format %{ %}
2912 interface(CONST_INTER);
2913 %}
2914
2915 // Double Immediate: +0.0d
2916 operand immD0()
2917 %{
2918 predicate(jlong_cast(n->getd()) == 0);
2919 match(ConD);
2920
2921 op_cost(0);
2922 format %{ %}
2923 interface(CONST_INTER);
2924 %}
2925
2926 // Float Immediate
2927 operand immF()
2928 %{
2929 match(ConF);
2930 op_cost(0);
2931 format %{ %}
2932 interface(CONST_INTER);
2933 %}
2934
2935 // Float Immediate: +0.0f.
2936 operand immF0()
2937 %{
2938 predicate(jint_cast(n->getf()) == 0);
2939 match(ConF);
2940
2941 op_cost(0);
2942 format %{ %}
2943 interface(CONST_INTER);
2944 %}
2945
2946 // Half Float Immediate
2947 operand immH()
2948 %{
2949 match(ConH);
2950
2951 op_cost(0);
2952 format %{ %}
2953 interface(CONST_INTER);
2954 %}
2955
2956 // Half Float Immediate: +0.0f.
2957 operand immH0()
2958 %{
2959 predicate(jint_cast(n->geth()) == 0);
2960 match(ConH);
2961
2962 op_cost(0);
2963 format %{ %}
2964 interface(CONST_INTER);
2965 %}
2966
2967 operand immIOffset()
2968 %{
2969 predicate(Assembler::is_simm12(n->get_int()));
2970 match(ConI);
2971 op_cost(0);
2972 format %{ %}
2973 interface(CONST_INTER);
2974 %}
2975
2976 operand immLOffset()
2977 %{
2978 predicate(Assembler::is_simm12(n->get_long()));
2979 match(ConL);
2980 op_cost(0);
2981 format %{ %}
2982 interface(CONST_INTER);
2983 %}
2984
2985 // Scale values
2986 operand immIScale()
2987 %{
2988 predicate(1 <= n->get_int() && (n->get_int() <= 3));
2989 match(ConI);
2990
2991 op_cost(0);
2992 format %{ %}
2993 interface(CONST_INTER);
2994 %}
2995
2996 // Integer 32 bit Register Operands
2997 operand iRegI()
2998 %{
2999 constraint(ALLOC_IN_RC(any_reg32));
3000 match(RegI);
3001 match(iRegINoSp);
3002 op_cost(0);
3003 format %{ %}
3004 interface(REG_INTER);
3005 %}
3006
3007 // Integer 32 bit Register not Special
3008 operand iRegINoSp()
3009 %{
3010 constraint(ALLOC_IN_RC(no_special_reg32));
3011 match(RegI);
3012 op_cost(0);
3013 format %{ %}
3014 interface(REG_INTER);
3015 %}
3016
3017 // Register R10 only
3018 operand iRegI_R10()
3019 %{
3020 constraint(ALLOC_IN_RC(int_r10_reg));
3021 match(RegI);
3022 match(iRegINoSp);
3023 op_cost(0);
3024 format %{ %}
3025 interface(REG_INTER);
3026 %}
3027
3028 // Register R12 only
3029 operand iRegI_R12()
3030 %{
3031 constraint(ALLOC_IN_RC(int_r12_reg));
3032 match(RegI);
3033 match(iRegINoSp);
3034 op_cost(0);
3035 format %{ %}
3036 interface(REG_INTER);
3037 %}
3038
3039 // Register R13 only
3040 operand iRegI_R13()
3041 %{
3042 constraint(ALLOC_IN_RC(int_r13_reg));
3043 match(RegI);
3044 match(iRegINoSp);
3045 op_cost(0);
3046 format %{ %}
3047 interface(REG_INTER);
3048 %}
3049
3050 // Register R14 only
3051 operand iRegI_R14()
3052 %{
3053 constraint(ALLOC_IN_RC(int_r14_reg));
3054 match(RegI);
3055 match(iRegINoSp);
3056 op_cost(0);
3057 format %{ %}
3058 interface(REG_INTER);
3059 %}
3060
3061 // Integer 64 bit Register Operands
3062 operand iRegL()
3063 %{
3064 constraint(ALLOC_IN_RC(any_reg));
3065 match(RegL);
3066 match(iRegLNoSp);
3067 op_cost(0);
3068 format %{ %}
3069 interface(REG_INTER);
3070 %}
3071
3072 // Integer 64 bit Register not Special
3073 operand iRegLNoSp()
3074 %{
3075 constraint(ALLOC_IN_RC(no_special_reg));
3076 match(RegL);
3077 match(iRegL_R10);
3078 format %{ %}
3079 interface(REG_INTER);
3080 %}
3081
3082 // Long 64 bit Register R29 only
3083 operand iRegL_R29()
3084 %{
3085 constraint(ALLOC_IN_RC(r29_reg));
3086 match(RegL);
3087 match(iRegLNoSp);
3088 op_cost(0);
3089 format %{ %}
3090 interface(REG_INTER);
3091 %}
3092
3093 // Long 64 bit Register R30 only
3094 operand iRegL_R30()
3095 %{
3096 constraint(ALLOC_IN_RC(r30_reg));
3097 match(RegL);
3098 match(iRegLNoSp);
3099 op_cost(0);
3100 format %{ %}
3101 interface(REG_INTER);
3102 %}
3103
3104 // Pointer Register Operands
3105 // Pointer Register
3106 operand iRegP()
3107 %{
3108 constraint(ALLOC_IN_RC(ptr_reg));
3109 match(RegP);
3110 match(iRegPNoSp);
3111 match(iRegP_R10);
3112 match(iRegP_R15);
3113 match(javaThread_RegP);
3114 op_cost(0);
3115 format %{ %}
3116 interface(REG_INTER);
3117 %}
3118
3119 // Pointer 64 bit Register not Special
3120 operand iRegPNoSp()
3121 %{
3122 constraint(ALLOC_IN_RC(no_special_ptr_reg));
3123 match(RegP);
3124 op_cost(0);
3125 format %{ %}
3126 interface(REG_INTER);
3127 %}
3128
3129 // This operand is not allowed to use fp even if
3130 // fp is not used to hold the frame pointer.
3131 operand iRegPNoSpNoFp()
3132 %{
3133 constraint(ALLOC_IN_RC(no_special_no_fp_ptr_reg));
3134 match(RegP);
3135 match(iRegPNoSp);
3136 op_cost(0);
3137 format %{ %}
3138 interface(REG_INTER);
3139 %}
3140
3141 operand iRegP_R10()
3142 %{
3143 constraint(ALLOC_IN_RC(r10_reg));
3144 match(RegP);
3145 // match(iRegP);
3146 match(iRegPNoSp);
3147 op_cost(0);
3148 format %{ %}
3149 interface(REG_INTER);
3150 %}
3151
3152 // Pointer 64 bit Register R11 only
3153 operand iRegP_R11()
3154 %{
3155 constraint(ALLOC_IN_RC(r11_reg));
3156 match(RegP);
3157 match(iRegPNoSp);
3158 op_cost(0);
3159 format %{ %}
3160 interface(REG_INTER);
3161 %}
3162
3163 operand iRegP_R12()
3164 %{
3165 constraint(ALLOC_IN_RC(r12_reg));
3166 match(RegP);
3167 // match(iRegP);
3168 match(iRegPNoSp);
3169 op_cost(0);
3170 format %{ %}
3171 interface(REG_INTER);
3172 %}
3173
3174 // Pointer 64 bit Register R13 only
3175 operand iRegP_R13()
3176 %{
3177 constraint(ALLOC_IN_RC(r13_reg));
3178 match(RegP);
3179 match(iRegPNoSp);
3180 op_cost(0);
3181 format %{ %}
3182 interface(REG_INTER);
3183 %}
3184
3185 operand iRegP_R14()
3186 %{
3187 constraint(ALLOC_IN_RC(r14_reg));
3188 match(RegP);
3189 // match(iRegP);
3190 match(iRegPNoSp);
3191 op_cost(0);
3192 format %{ %}
3193 interface(REG_INTER);
3194 %}
3195
3196 operand iRegP_R15()
3197 %{
3198 constraint(ALLOC_IN_RC(r15_reg));
3199 match(RegP);
3200 // match(iRegP);
3201 match(iRegPNoSp);
3202 op_cost(0);
3203 format %{ %}
3204 interface(REG_INTER);
3205 %}
3206
3207 operand iRegP_R16()
3208 %{
3209 constraint(ALLOC_IN_RC(r16_reg));
3210 match(RegP);
3211 match(iRegPNoSp);
3212 op_cost(0);
3213 format %{ %}
3214 interface(REG_INTER);
3215 %}
3216
3217 // Pointer 64 bit Register R28 only
3218 operand iRegP_R28()
3219 %{
3220 constraint(ALLOC_IN_RC(r28_reg));
3221 match(RegP);
3222 match(iRegPNoSp);
3223 op_cost(0);
3224 format %{ %}
3225 interface(REG_INTER);
3226 %}
3227
3228 // Pointer 64 bit Register R30 only
3229 operand iRegP_R30()
3230 %{
3231 constraint(ALLOC_IN_RC(r30_reg));
3232 match(RegP);
3233 match(iRegPNoSp);
3234 op_cost(0);
3235 format %{ %}
3236 interface(REG_INTER);
3237 %}
3238
3239 // Pointer 64 bit Register R31 only
3240 operand iRegP_R31()
3241 %{
3242 constraint(ALLOC_IN_RC(r31_reg));
3243 match(RegP);
3244 match(iRegPNoSp);
3245 op_cost(0);
3246 format %{ %}
3247 interface(REG_INTER);
3248 %}
3249
3250 // Pointer Register Operands
3251 // Narrow Pointer Register
3252 operand iRegN()
3253 %{
3254 constraint(ALLOC_IN_RC(any_reg32));
3255 match(RegN);
3256 match(iRegNNoSp);
3257 op_cost(0);
3258 format %{ %}
3259 interface(REG_INTER);
3260 %}
3261
3262 // Integer 64 bit Register not Special
3263 operand iRegNNoSp()
3264 %{
3265 constraint(ALLOC_IN_RC(no_special_reg32));
3266 match(RegN);
3267 op_cost(0);
3268 format %{ %}
3269 interface(REG_INTER);
3270 %}
3271
3272 // Long 64 bit Register R10 only
3273 operand iRegL_R10()
3274 %{
3275 constraint(ALLOC_IN_RC(r10_reg));
3276 match(RegL);
3277 match(iRegLNoSp);
3278 op_cost(0);
3279 format %{ %}
3280 interface(REG_INTER);
3281 %}
3282
3283 // Float Register
3284 // Float register operands
3285 operand fRegF()
3286 %{
3287 constraint(ALLOC_IN_RC(float_reg));
3288 match(RegF);
3289
3290 op_cost(0);
3291 format %{ %}
3292 interface(REG_INTER);
3293 %}
3294
3295 // Double Register
3296 // Double register operands
3297 operand fRegD()
3298 %{
3299 constraint(ALLOC_IN_RC(double_reg));
3300 match(RegD);
3301
3302 op_cost(0);
3303 format %{ %}
3304 interface(REG_INTER);
3305 %}
3306
3307 // Generic vector class. This will be used for
3308 // all vector operands.
3309 operand vReg()
3310 %{
3311 constraint(ALLOC_IN_RC(vectora_reg));
3312 match(VecA);
3313 op_cost(0);
3314 format %{ %}
3315 interface(REG_INTER);
3316 %}
3317
3318 operand vReg_V1()
3319 %{
3320 constraint(ALLOC_IN_RC(v1_reg));
3321 match(VecA);
3322 match(vReg);
3323 op_cost(0);
3324 format %{ %}
3325 interface(REG_INTER);
3326 %}
3327
3328 operand vReg_V2()
3329 %{
3330 constraint(ALLOC_IN_RC(v2_reg));
3331 match(VecA);
3332 match(vReg);
3333 op_cost(0);
3334 format %{ %}
3335 interface(REG_INTER);
3336 %}
3337
3338 operand vReg_V3()
3339 %{
3340 constraint(ALLOC_IN_RC(v3_reg));
3341 match(VecA);
3342 match(vReg);
3343 op_cost(0);
3344 format %{ %}
3345 interface(REG_INTER);
3346 %}
3347
3348 operand vReg_V4()
3349 %{
3350 constraint(ALLOC_IN_RC(v4_reg));
3351 match(VecA);
3352 match(vReg);
3353 op_cost(0);
3354 format %{ %}
3355 interface(REG_INTER);
3356 %}
3357
3358 operand vReg_V5()
3359 %{
3360 constraint(ALLOC_IN_RC(v5_reg));
3361 match(VecA);
3362 match(vReg);
3363 op_cost(0);
3364 format %{ %}
3365 interface(REG_INTER);
3366 %}
3367
3368 operand vReg_V6()
3369 %{
3370 constraint(ALLOC_IN_RC(v6_reg));
3371 match(VecA);
3372 match(vReg);
3373 op_cost(0);
3374 format %{ %}
3375 interface(REG_INTER);
3376 %}
3377
3378 operand vReg_V7()
3379 %{
3380 constraint(ALLOC_IN_RC(v7_reg));
3381 match(VecA);
3382 match(vReg);
3383 op_cost(0);
3384 format %{ %}
3385 interface(REG_INTER);
3386 %}
3387
3388 operand vReg_V8()
3389 %{
3390 constraint(ALLOC_IN_RC(v8_reg));
3391 match(VecA);
3392 match(vReg);
3393 op_cost(0);
3394 format %{ %}
3395 interface(REG_INTER);
3396 %}
3397
3398 operand vReg_V9()
3399 %{
3400 constraint(ALLOC_IN_RC(v9_reg));
3401 match(VecA);
3402 match(vReg);
3403 op_cost(0);
3404 format %{ %}
3405 interface(REG_INTER);
3406 %}
3407
3408 operand vReg_V10()
3409 %{
3410 constraint(ALLOC_IN_RC(v10_reg));
3411 match(VecA);
3412 match(vReg);
3413 op_cost(0);
3414 format %{ %}
3415 interface(REG_INTER);
3416 %}
3417
3418 operand vReg_V11()
3419 %{
3420 constraint(ALLOC_IN_RC(v11_reg));
3421 match(VecA);
3422 match(vReg);
3423 op_cost(0);
3424 format %{ %}
3425 interface(REG_INTER);
3426 %}
3427
3428 operand vRegMask()
3429 %{
3430 constraint(ALLOC_IN_RC(vmask_reg));
3431 match(RegVectMask);
3432 match(vRegMask_V0);
3433 op_cost(0);
3434 format %{ %}
3435 interface(REG_INTER);
3436 %}
3437
3438 // The mask value used to control execution of a masked
3439 // vector instruction is always supplied by vector register v0.
3440 operand vRegMask_V0()
3441 %{
3442 constraint(ALLOC_IN_RC(vmask_reg_v0));
3443 match(RegVectMask);
3444 match(vRegMask);
3445 op_cost(0);
3446 format %{ %}
3447 interface(REG_INTER);
3448 %}
3449
3450 // Java Thread Register
3451 operand javaThread_RegP(iRegP reg)
3452 %{
3453 constraint(ALLOC_IN_RC(java_thread_reg)); // java_thread_reg
3454 match(reg);
3455 op_cost(0);
3456 format %{ %}
3457 interface(REG_INTER);
3458 %}
3459
3460 //----------Memory Operands----------------------------------------------------
3461 // RISCV has only base_plus_offset and literal address mode, so no need to use
3462 // index and scale. Here set index as 0xffffffff and scale as 0x0.
3463 operand indirect(iRegP reg)
3464 %{
3465 constraint(ALLOC_IN_RC(ptr_reg));
3466 match(reg);
3467 op_cost(0);
3468 format %{ "[$reg]" %}
3469 interface(MEMORY_INTER) %{
3470 base($reg);
3471 index(0xffffffff);
3472 scale(0x0);
3473 disp(0x0);
3474 %}
3475 %}
3476
3477 operand indOffI(iRegP reg, immIOffset off)
3478 %{
3479 constraint(ALLOC_IN_RC(ptr_reg));
3480 match(AddP reg off);
3481 op_cost(0);
3482 format %{ "[$reg, $off]" %}
3483 interface(MEMORY_INTER) %{
3484 base($reg);
3485 index(0xffffffff);
3486 scale(0x0);
3487 disp($off);
3488 %}
3489 %}
3490
3491 operand indOffL(iRegP reg, immLOffset off)
3492 %{
3493 constraint(ALLOC_IN_RC(ptr_reg));
3494 match(AddP reg off);
3495 op_cost(0);
3496 format %{ "[$reg, $off]" %}
3497 interface(MEMORY_INTER) %{
3498 base($reg);
3499 index(0xffffffff);
3500 scale(0x0);
3501 disp($off);
3502 %}
3503 %}
3504
3505 operand indirectN(iRegN reg)
3506 %{
3507 predicate(CompressedOops::shift() == 0);
3508 constraint(ALLOC_IN_RC(ptr_reg));
3509 match(DecodeN reg);
3510 op_cost(0);
3511 format %{ "[$reg]\t# narrow" %}
3512 interface(MEMORY_INTER) %{
3513 base($reg);
3514 index(0xffffffff);
3515 scale(0x0);
3516 disp(0x0);
3517 %}
3518 %}
3519
3520 operand indOffIN(iRegN reg, immIOffset off)
3521 %{
3522 predicate(CompressedOops::shift() == 0);
3523 constraint(ALLOC_IN_RC(ptr_reg));
3524 match(AddP (DecodeN reg) off);
3525 op_cost(0);
3526 format %{ "[$reg, $off]\t# narrow" %}
3527 interface(MEMORY_INTER) %{
3528 base($reg);
3529 index(0xffffffff);
3530 scale(0x0);
3531 disp($off);
3532 %}
3533 %}
3534
3535 operand indOffLN(iRegN reg, immLOffset off)
3536 %{
3537 predicate(CompressedOops::shift() == 0);
3538 constraint(ALLOC_IN_RC(ptr_reg));
3539 match(AddP (DecodeN reg) off);
3540 op_cost(0);
3541 format %{ "[$reg, $off]\t# narrow" %}
3542 interface(MEMORY_INTER) %{
3543 base($reg);
3544 index(0xffffffff);
3545 scale(0x0);
3546 disp($off);
3547 %}
3548 %}
3549
3550 //----------Special Memory Operands--------------------------------------------
3551 // Stack Slot Operand - This operand is used for loading and storing temporary
3552 // values on the stack where a match requires a value to
3553 // flow through memory.
3554 operand stackSlotI(sRegI reg)
3555 %{
3556 constraint(ALLOC_IN_RC(stack_slots));
3557 // No match rule because this operand is only generated in matching
3558 // match(RegI);
3559 format %{ "[$reg]" %}
3560 interface(MEMORY_INTER) %{
3561 base(0x02); // RSP
3562 index(0xffffffff); // No Index
3563 scale(0x0); // No Scale
3564 disp($reg); // Stack Offset
3565 %}
3566 %}
3567
3568 operand stackSlotF(sRegF reg)
3569 %{
3570 constraint(ALLOC_IN_RC(stack_slots));
3571 // No match rule because this operand is only generated in matching
3572 // match(RegF);
3573 format %{ "[$reg]" %}
3574 interface(MEMORY_INTER) %{
3575 base(0x02); // RSP
3576 index(0xffffffff); // No Index
3577 scale(0x0); // No Scale
3578 disp($reg); // Stack Offset
3579 %}
3580 %}
3581
3582 operand stackSlotD(sRegD reg)
3583 %{
3584 constraint(ALLOC_IN_RC(stack_slots));
3585 // No match rule because this operand is only generated in matching
3586 // match(RegD);
3587 format %{ "[$reg]" %}
3588 interface(MEMORY_INTER) %{
3589 base(0x02); // RSP
3590 index(0xffffffff); // No Index
3591 scale(0x0); // No Scale
3592 disp($reg); // Stack Offset
3593 %}
3594 %}
3595
3596 operand stackSlotL(sRegL reg)
3597 %{
3598 constraint(ALLOC_IN_RC(stack_slots));
3599 // No match rule because this operand is only generated in matching
3600 // match(RegL);
3601 format %{ "[$reg]" %}
3602 interface(MEMORY_INTER) %{
3603 base(0x02); // RSP
3604 index(0xffffffff); // No Index
3605 scale(0x0); // No Scale
3606 disp($reg); // Stack Offset
3607 %}
3608 %}
3609
3610 // Special operand allowing long args to int ops to be truncated for free
3611
3612 operand iRegL2I(iRegL reg) %{
3613
3614 op_cost(0);
3615
3616 match(ConvL2I reg);
3617
3618 format %{ "l2i($reg)" %}
3619
3620 interface(REG_INTER)
3621 %}
3622
3623
3624 // Comparison Operands
3625 // NOTE: Label is a predefined operand which should not be redefined in
3626 // the AD file. It is generically handled within the ADLC.
3627
3628 //----------Conditional Branch Operands----------------------------------------
3629 // Comparison Op - This is the operation of the comparison, and is limited to
3630 // the following set of codes:
3631 // L (<), LE (<=), G (>), GE (>=), E (==), NE (!=)
3632 //
3633 // Other attributes of the comparison, such as unsignedness, are specified
3634 // by the comparison instruction that sets a condition code flags register.
3635 // That result is represented by a flags operand whose subtype is appropriate
3636 // to the unsignedness (etc.) of the comparison.
3637 //
3638 // Later, the instruction which matches both the Comparison Op (a Bool) and
3639 // the flags (produced by the Cmp) specifies the coding of the comparison op
3640 // by matching a specific subtype of Bool operand below, such as cmpOpU.
3641
3642
3643 // used for signed integral comparisons and fp comparisons
3644 operand cmpOp()
3645 %{
3646 match(Bool);
3647
3648 format %{ "" %}
3649
3650 // the values in interface derives from struct BoolTest::mask
3651 interface(COND_INTER) %{
3652 equal(0x0, "eq");
3653 greater(0x1, "gt");
3654 overflow(0x2, "overflow");
3655 less(0x3, "lt");
3656 not_equal(0x4, "ne");
3657 less_equal(0x5, "le");
3658 no_overflow(0x6, "no_overflow");
3659 greater_equal(0x7, "ge");
3660 %}
3661 %}
3662
3663 // used for unsigned integral comparisons
3664 operand cmpOpU()
3665 %{
3666 match(Bool);
3667
3668 format %{ "" %}
3669 // the values in interface derives from struct BoolTest::mask
3670 interface(COND_INTER) %{
3671 equal(0x0, "eq");
3672 greater(0x1, "gtu");
3673 overflow(0x2, "overflow");
3674 less(0x3, "ltu");
3675 not_equal(0x4, "ne");
3676 less_equal(0x5, "leu");
3677 no_overflow(0x6, "no_overflow");
3678 greater_equal(0x7, "geu");
3679 %}
3680 %}
3681
3682 // used for certain integral comparisons which can be
3683 // converted to bxx instructions
3684 operand cmpOpEqNe()
3685 %{
3686 match(Bool);
3687 op_cost(0);
3688 predicate(n->as_Bool()->_test._test == BoolTest::ne ||
3689 n->as_Bool()->_test._test == BoolTest::eq);
3690
3691 format %{ "" %}
3692 interface(COND_INTER) %{
3693 equal(0x0, "eq");
3694 greater(0x1, "gt");
3695 overflow(0x2, "overflow");
3696 less(0x3, "lt");
3697 not_equal(0x4, "ne");
3698 less_equal(0x5, "le");
3699 no_overflow(0x6, "no_overflow");
3700 greater_equal(0x7, "ge");
3701 %}
3702 %}
3703
3704 operand cmpOpULtGe()
3705 %{
3706 match(Bool);
3707 op_cost(0);
3708 predicate(n->as_Bool()->_test._test == BoolTest::lt ||
3709 n->as_Bool()->_test._test == BoolTest::ge);
3710
3711 format %{ "" %}
3712 interface(COND_INTER) %{
3713 equal(0x0, "eq");
3714 greater(0x1, "gtu");
3715 overflow(0x2, "overflow");
3716 less(0x3, "ltu");
3717 not_equal(0x4, "ne");
3718 less_equal(0x5, "leu");
3719 no_overflow(0x6, "no_overflow");
3720 greater_equal(0x7, "geu");
3721 %}
3722 %}
3723
3724 operand cmpOpUEqNeLeGt()
3725 %{
3726 match(Bool);
3727 op_cost(0);
3728 predicate(n->as_Bool()->_test._test == BoolTest::ne ||
3729 n->as_Bool()->_test._test == BoolTest::eq ||
3730 n->as_Bool()->_test._test == BoolTest::le ||
3731 n->as_Bool()->_test._test == BoolTest::gt);
3732
3733 format %{ "" %}
3734 interface(COND_INTER) %{
3735 equal(0x0, "eq");
3736 greater(0x1, "gtu");
3737 overflow(0x2, "overflow");
3738 less(0x3, "ltu");
3739 not_equal(0x4, "ne");
3740 less_equal(0x5, "leu");
3741 no_overflow(0x6, "no_overflow");
3742 greater_equal(0x7, "geu");
3743 %}
3744 %}
3745
3746
3747 // Flags register, used as output of compare logic
3748 operand rFlagsReg()
3749 %{
3750 constraint(ALLOC_IN_RC(reg_flags));
3751 match(RegFlags);
3752
3753 op_cost(0);
3754 format %{ "RFLAGS" %}
3755 interface(REG_INTER);
3756 %}
3757
3758 // Special Registers
3759
3760 // Method Register
3761 operand inline_cache_RegP(iRegP reg)
3762 %{
3763 constraint(ALLOC_IN_RC(method_reg)); // inline_cache_reg
3764 match(reg);
3765 match(iRegPNoSp);
3766 op_cost(0);
3767 format %{ %}
3768 interface(REG_INTER);
3769 %}
3770
3771 //----------OPERAND CLASSES----------------------------------------------------
3772 // Operand Classes are groups of operands that are used as to simplify
3773 // instruction definitions by not requiring the AD writer to specify
3774 // separate instructions for every form of operand when the
3775 // instruction accepts multiple operand types with the same basic
3776 // encoding and format. The classic case of this is memory operands.
3777
3778 // memory is used to define read/write location for load/store
3779 // instruction defs. we can turn a memory op into an Address
3780
3781 opclass memory(indirect, indOffI, indOffL, indirectN, indOffIN, indOffLN);
3782
3783 // iRegIorL2I is used for src inputs in rules for 32 bit int (I)
3784 // operations. it allows the src to be either an iRegI or a (ConvL2I
3785 // iRegL). in the latter case the l2i normally planted for a ConvL2I
3786 // can be elided because the 32-bit instruction will just employ the
3787 // lower 32 bits anyway.
3788 //
3789 // n.b. this does not elide all L2I conversions. if the truncated
3790 // value is consumed by more than one operation then the ConvL2I
3791 // cannot be bundled into the consuming nodes so an l2i gets planted
3792 // (actually an addiw $dst, $src, 0) and the downstream instructions
3793 // consume the result of the L2I as an iRegI input. That's a shame since
3794 // the addiw is actually redundant but its not too costly.
3795
3796 opclass iRegIorL2I(iRegI, iRegL2I);
3797 opclass iRegIorL(iRegI, iRegL);
3798 opclass iRegNorP(iRegN, iRegP);
3799 opclass iRegILNP(iRegI, iRegL, iRegN, iRegP);
3800 opclass iRegILNPNoSp(iRegINoSp, iRegLNoSp, iRegNNoSp, iRegPNoSp);
3801 opclass immIorL(immI, immL);
3802
3803 //----------PIPELINE-----------------------------------------------------------
3804 // Rules which define the behavior of the target architectures pipeline.
3805
3806 // For specific pipelines, e.g. generic RISC-V, define the stages of that pipeline
3807 //pipe_desc(ID, EX, MEM, WR);
3808 #define ID S0
3809 #define EX S1
3810 #define MEM S2
3811 #define WR S3
3812
3813 // Integer ALU reg operation
3814 pipeline %{
3815
3816 attributes %{
3817 // RISC-V instructions are of length 2 or 4 bytes.
3818 variable_size_instructions;
3819 instruction_unit_size = 2;
3820
3821 // Up to 4 instructions per bundle
3822 max_instructions_per_bundle = 4;
3823
3824 // The RISC-V processor fetches 64 bytes...
3825 instruction_fetch_unit_size = 64;
3826
3827 // ...in one line.
3828 instruction_fetch_units = 1;
3829 %}
3830
3831 // We don't use an actual pipeline model so don't care about resources
3832 // or description. we do use pipeline classes to introduce fixed
3833 // latencies
3834
3835 //----------RESOURCES----------------------------------------------------------
3836 // Resources are the functional units available to the machine
3837
3838 // Generic RISC-V pipeline
3839 // 1 decoder
3840 // 1 instruction decoded per cycle
3841 // 1 load/store ops per cycle, 1 branch, 1 FPU
3842 // 1 mul, 1 div
3843
3844 resources ( DECODE,
3845 ALU,
3846 MUL,
3847 DIV,
3848 BRANCH,
3849 LDST,
3850 FPU);
3851
3852 //----------PIPELINE DESCRIPTION-----------------------------------------------
3853 // Pipeline Description specifies the stages in the machine's pipeline
3854
3855 // Define the pipeline as a generic 6 stage pipeline
3856 pipe_desc(S0, S1, S2, S3, S4, S5);
3857
3858 //----------PIPELINE CLASSES---------------------------------------------------
3859 // Pipeline Classes describe the stages in which input and output are
3860 // referenced by the hardware pipeline.
3861
3862 pipe_class fp_dop_reg_reg_s(fRegF dst, fRegF src1, fRegF src2)
3863 %{
3864 single_instruction;
3865 src1 : S1(read);
3866 src2 : S2(read);
3867 dst : S5(write);
3868 DECODE : ID;
3869 FPU : S5;
3870 %}
3871
3872 pipe_class fp_dop_reg_reg_d(fRegD dst, fRegD src1, fRegD src2)
3873 %{
3874 src1 : S1(read);
3875 src2 : S2(read);
3876 dst : S5(write);
3877 DECODE : ID;
3878 FPU : S5;
3879 %}
3880
3881 pipe_class fp_uop_s(fRegF dst, fRegF src)
3882 %{
3883 single_instruction;
3884 src : S1(read);
3885 dst : S5(write);
3886 DECODE : ID;
3887 FPU : S5;
3888 %}
3889
3890 pipe_class fp_uop_d(fRegD dst, fRegD src)
3891 %{
3892 single_instruction;
3893 src : S1(read);
3894 dst : S5(write);
3895 DECODE : ID;
3896 FPU : S5;
3897 %}
3898
3899 pipe_class fp_d2f(fRegF dst, fRegD src)
3900 %{
3901 single_instruction;
3902 src : S1(read);
3903 dst : S5(write);
3904 DECODE : ID;
3905 FPU : S5;
3906 %}
3907
3908 pipe_class fp_f2d(fRegD dst, fRegF src)
3909 %{
3910 single_instruction;
3911 src : S1(read);
3912 dst : S5(write);
3913 DECODE : ID;
3914 FPU : S5;
3915 %}
3916
3917 pipe_class fp_f2i(iRegINoSp dst, fRegF src)
3918 %{
3919 single_instruction;
3920 src : S1(read);
3921 dst : S5(write);
3922 DECODE : ID;
3923 FPU : S5;
3924 %}
3925
3926 pipe_class fp_f2l(iRegLNoSp dst, fRegF src)
3927 %{
3928 single_instruction;
3929 src : S1(read);
3930 dst : S5(write);
3931 DECODE : ID;
3932 FPU : S5;
3933 %}
3934
3935 pipe_class fp_i2f(fRegF dst, iRegIorL2I src)
3936 %{
3937 single_instruction;
3938 src : S1(read);
3939 dst : S5(write);
3940 DECODE : ID;
3941 FPU : S5;
3942 %}
3943
3944 pipe_class fp_l2f(fRegF dst, iRegL src)
3945 %{
3946 single_instruction;
3947 src : S1(read);
3948 dst : S5(write);
3949 DECODE : ID;
3950 FPU : S5;
3951 %}
3952
3953 pipe_class fp_d2i(iRegINoSp dst, fRegD src)
3954 %{
3955 single_instruction;
3956 src : S1(read);
3957 dst : S5(write);
3958 DECODE : ID;
3959 FPU : S5;
3960 %}
3961
3962 pipe_class fp_d2l(iRegLNoSp dst, fRegD src)
3963 %{
3964 single_instruction;
3965 src : S1(read);
3966 dst : S5(write);
3967 DECODE : ID;
3968 FPU : S5;
3969 %}
3970
3971 pipe_class fp_i2d(fRegD dst, iRegIorL2I src)
3972 %{
3973 single_instruction;
3974 src : S1(read);
3975 dst : S5(write);
3976 DECODE : ID;
3977 FPU : S5;
3978 %}
3979
3980 pipe_class fp_l2d(fRegD dst, iRegIorL2I src)
3981 %{
3982 single_instruction;
3983 src : S1(read);
3984 dst : S5(write);
3985 DECODE : ID;
3986 FPU : S5;
3987 %}
3988
3989 pipe_class fp_div_s(fRegF dst, fRegF src1, fRegF src2)
3990 %{
3991 single_instruction;
3992 src1 : S1(read);
3993 src2 : S2(read);
3994 dst : S5(write);
3995 DECODE : ID;
3996 FPU : S5;
3997 %}
3998
3999 pipe_class fp_div_d(fRegD dst, fRegD src1, fRegD src2)
4000 %{
4001 single_instruction;
4002 src1 : S1(read);
4003 src2 : S2(read);
4004 dst : S5(write);
4005 DECODE : ID;
4006 FPU : S5;
4007 %}
4008
4009 pipe_class fp_sqrt_s(fRegF dst, fRegF src)
4010 %{
4011 single_instruction;
4012 src : S1(read);
4013 dst : S5(write);
4014 DECODE : ID;
4015 FPU : S5;
4016 %}
4017
4018 pipe_class fp_sqrt_d(fRegD dst, fRegD src)
4019 %{
4020 single_instruction;
4021 src : S1(read);
4022 dst : S5(write);
4023 DECODE : ID;
4024 FPU : S5;
4025 %}
4026
4027 pipe_class fp_load_constant_s(fRegF dst)
4028 %{
4029 single_instruction;
4030 dst : S5(write);
4031 DECODE : ID;
4032 FPU : S5;
4033 %}
4034
4035 pipe_class fp_load_constant_d(fRegD dst)
4036 %{
4037 single_instruction;
4038 dst : S5(write);
4039 DECODE : ID;
4040 FPU : S5;
4041 %}
4042
4043 pipe_class fp_load_mem_s(fRegF dst, memory mem)
4044 %{
4045 single_instruction;
4046 mem : S1(read);
4047 dst : S5(write);
4048 DECODE : ID;
4049 LDST : MEM;
4050 %}
4051
4052 pipe_class fp_load_mem_d(fRegD dst, memory mem)
4053 %{
4054 single_instruction;
4055 mem : S1(read);
4056 dst : S5(write);
4057 DECODE : ID;
4058 LDST : MEM;
4059 %}
4060
4061 pipe_class fp_store_reg_s(fRegF src, memory mem)
4062 %{
4063 single_instruction;
4064 src : S1(read);
4065 mem : S5(write);
4066 DECODE : ID;
4067 LDST : MEM;
4068 %}
4069
4070 pipe_class fp_store_reg_d(fRegD src, memory mem)
4071 %{
4072 single_instruction;
4073 src : S1(read);
4074 mem : S5(write);
4075 DECODE : ID;
4076 LDST : MEM;
4077 %}
4078
4079 //------- Integer ALU operations --------------------------
4080
4081 // Integer ALU reg-reg operation
4082 // Operands needs in ID, result generated in EX
4083 // E.g. ADD Rd, Rs1, Rs2
4084 pipe_class ialu_reg_reg(iRegI dst, iRegI src1, iRegI src2)
4085 %{
4086 single_instruction;
4087 dst : EX(write);
4088 src1 : ID(read);
4089 src2 : ID(read);
4090 DECODE : ID;
4091 ALU : EX;
4092 %}
4093
4094 // Integer ALU reg operation with constant shift
4095 // E.g. SLLI Rd, Rs1, #shift
4096 pipe_class ialu_reg_shift(iRegI dst, iRegI src1)
4097 %{
4098 single_instruction;
4099 dst : EX(write);
4100 src1 : ID(read);
4101 DECODE : ID;
4102 ALU : EX;
4103 %}
4104
4105 // Integer ALU reg-reg operation with variable shift
4106 // both operands must be available in ID
4107 // E.g. SLL Rd, Rs1, Rs2
4108 pipe_class ialu_reg_reg_vshift(iRegI dst, iRegI src1, iRegI src2)
4109 %{
4110 single_instruction;
4111 dst : EX(write);
4112 src1 : ID(read);
4113 src2 : ID(read);
4114 DECODE : ID;
4115 ALU : EX;
4116 %}
4117
4118 // Integer ALU reg operation
4119 // E.g. NEG Rd, Rs2
4120 pipe_class ialu_reg(iRegI dst, iRegI src)
4121 %{
4122 single_instruction;
4123 dst : EX(write);
4124 src : ID(read);
4125 DECODE : ID;
4126 ALU : EX;
4127 %}
4128
4129 // Integer ALU reg immediate operation
4130 // E.g. ADDI Rd, Rs1, #imm
4131 pipe_class ialu_reg_imm(iRegI dst, iRegI src1)
4132 %{
4133 single_instruction;
4134 dst : EX(write);
4135 src1 : ID(read);
4136 DECODE : ID;
4137 ALU : EX;
4138 %}
4139
4140 // Integer ALU immediate operation (no source operands)
4141 // E.g. LI Rd, #imm
4142 pipe_class ialu_imm(iRegI dst)
4143 %{
4144 single_instruction;
4145 dst : EX(write);
4146 DECODE : ID;
4147 ALU : EX;
4148 %}
4149
4150 //------- Multiply pipeline operations --------------------
4151
4152 // Multiply reg-reg
4153 // E.g. MULW Rd, Rs1, Rs2
4154 pipe_class imul_reg_reg(iRegI dst, iRegI src1, iRegI src2)
4155 %{
4156 single_instruction;
4157 dst : WR(write);
4158 src1 : ID(read);
4159 src2 : ID(read);
4160 DECODE : ID;
4161 MUL : WR;
4162 %}
4163
4164 // E.g. MUL RD, Rs1, Rs2
4165 pipe_class lmul_reg_reg(iRegL dst, iRegL src1, iRegL src2)
4166 %{
4167 single_instruction;
4168 fixed_latency(3); // Maximum latency for 64 bit mul
4169 dst : WR(write);
4170 src1 : ID(read);
4171 src2 : ID(read);
4172 DECODE : ID;
4173 MUL : WR;
4174 %}
4175
4176 //------- Divide pipeline operations --------------------
4177
4178 // E.g. DIVW Rd, Rs1, Rs2
4179 pipe_class idiv_reg_reg(iRegI dst, iRegI src1, iRegI src2)
4180 %{
4181 single_instruction;
4182 fixed_latency(8); // Maximum latency for 32 bit divide
4183 dst : WR(write);
4184 src1 : ID(read);
4185 src2 : ID(read);
4186 DECODE : ID;
4187 DIV : WR;
4188 %}
4189
4190 // E.g. DIV RD, Rs1, Rs2
4191 pipe_class ldiv_reg_reg(iRegL dst, iRegL src1, iRegL src2)
4192 %{
4193 single_instruction;
4194 fixed_latency(16); // Maximum latency for 64 bit divide
4195 dst : WR(write);
4196 src1 : ID(read);
4197 src2 : ID(read);
4198 DECODE : ID;
4199 DIV : WR;
4200 %}
4201
4202 //------- Load pipeline operations ------------------------
4203
4204 // Load - prefetch
4205 // Eg. PREFETCH_W mem
4206 pipe_class iload_prefetch(memory mem)
4207 %{
4208 single_instruction;
4209 mem : ID(read);
4210 DECODE : ID;
4211 LDST : MEM;
4212 %}
4213
4214 // Load - reg, mem
4215 // E.g. LA Rd, mem
4216 pipe_class iload_reg_mem(iRegI dst, memory mem)
4217 %{
4218 single_instruction;
4219 dst : WR(write);
4220 mem : ID(read);
4221 DECODE : ID;
4222 LDST : MEM;
4223 %}
4224
4225 // Load - reg, reg
4226 // E.g. LD Rd, Rs
4227 pipe_class iload_reg_reg(iRegI dst, iRegI src)
4228 %{
4229 single_instruction;
4230 dst : WR(write);
4231 src : ID(read);
4232 DECODE : ID;
4233 LDST : MEM;
4234 %}
4235
4236 //------- Store pipeline operations -----------------------
4237
4238 // Store - zr, mem
4239 // E.g. SD zr, mem
4240 pipe_class istore_mem(memory mem)
4241 %{
4242 single_instruction;
4243 mem : ID(read);
4244 DECODE : ID;
4245 LDST : MEM;
4246 %}
4247
4248 // Store - reg, mem
4249 // E.g. SD Rs, mem
4250 pipe_class istore_reg_mem(iRegI src, memory mem)
4251 %{
4252 single_instruction;
4253 mem : ID(read);
4254 src : EX(read);
4255 DECODE : ID;
4256 LDST : MEM;
4257 %}
4258
4259 // Store - reg, reg
4260 // E.g. SD Rs2, Rs1
4261 pipe_class istore_reg_reg(iRegI dst, iRegI src)
4262 %{
4263 single_instruction;
4264 dst : ID(read);
4265 src : EX(read);
4266 DECODE : ID;
4267 LDST : MEM;
4268 %}
4269
4270 //------- Control transfer pipeline operations ------------
4271
4272 // Branch
4273 pipe_class pipe_branch()
4274 %{
4275 single_instruction;
4276 DECODE : ID;
4277 BRANCH : EX;
4278 %}
4279
4280 // Branch
4281 pipe_class pipe_branch_reg(iRegI src)
4282 %{
4283 single_instruction;
4284 src : ID(read);
4285 DECODE : ID;
4286 BRANCH : EX;
4287 %}
4288
4289 // Compare & Branch
4290 // E.g. BEQ Rs1, Rs2, L
4291 pipe_class pipe_cmp_branch(iRegI src1, iRegI src2)
4292 %{
4293 single_instruction;
4294 src1 : ID(read);
4295 src2 : ID(read);
4296 DECODE : ID;
4297 BRANCH : EX;
4298 %}
4299
4300 // E.g. BEQZ Rs, L
4301 pipe_class pipe_cmpz_branch(iRegI src)
4302 %{
4303 single_instruction;
4304 src : ID(read);
4305 DECODE : ID;
4306 BRANCH : EX;
4307 %}
4308
4309 //------- Synchronisation operations ----------------------
4310 // Any operation requiring serialization
4311 // E.g. FENCE/Atomic Ops/Load Acquire/Store Release
4312 pipe_class pipe_serial()
4313 %{
4314 single_instruction;
4315 force_serialization;
4316 fixed_latency(16);
4317 DECODE : ID;
4318 LDST : MEM;
4319 %}
4320
4321 pipe_class pipe_slow()
4322 %{
4323 instruction_count(10);
4324 multiple_bundles;
4325 force_serialization;
4326 fixed_latency(16);
4327 DECODE : ID;
4328 LDST : MEM;
4329 %}
4330
4331 // The real do-nothing guy
4332 pipe_class real_empty()
4333 %{
4334 instruction_count(0);
4335 %}
4336
4337 // Empty pipeline class
4338 pipe_class pipe_class_empty()
4339 %{
4340 single_instruction;
4341 fixed_latency(0);
4342 %}
4343
4344 // Default pipeline class.
4345 pipe_class pipe_class_default()
4346 %{
4347 single_instruction;
4348 fixed_latency(2);
4349 %}
4350
4351 // Pipeline class for compares.
4352 pipe_class pipe_class_compare()
4353 %{
4354 single_instruction;
4355 fixed_latency(16);
4356 %}
4357
4358 // Pipeline class for memory operations.
4359 pipe_class pipe_class_memory()
4360 %{
4361 single_instruction;
4362 fixed_latency(16);
4363 %}
4364
4365 // Pipeline class for call.
4366 pipe_class pipe_class_call()
4367 %{
4368 single_instruction;
4369 fixed_latency(100);
4370 %}
4371
4372 // Define the class for the Nop node.
4373 define %{
4374 MachNop = pipe_class_empty;
4375 %}
4376 %}
4377 //----------INSTRUCTIONS-------------------------------------------------------
4378 //
4379 // match -- States which machine-independent subtree may be replaced
4380 // by this instruction.
4381 // ins_cost -- The estimated cost of this instruction is used by instruction
4382 // selection to identify a minimum cost tree of machine
4383 // instructions that matches a tree of machine-independent
4384 // instructions.
4385 // format -- A string providing the disassembly for this instruction.
4386 // The value of an instruction's operand may be inserted
4387 // by referring to it with a '$' prefix.
4388 // opcode -- Three instruction opcodes may be provided. These are referred
4389 // to within an encode class as $primary, $secondary, and $tertiary
4390 // rrspectively. The primary opcode is commonly used to
4391 // indicate the type of machine instruction, while secondary
4392 // and tertiary are often used for prefix options or addressing
4393 // modes.
4394 // ins_encode -- A list of encode classes with parameters. The encode class
4395 // name must have been defined in an 'enc_class' specification
4396 // in the encode section of the architecture description.
4397
4398 // ============================================================================
4399 // Memory (Load/Store) Instructions
4400
4401 // Load Instructions
4402
4403 // Load Byte (8 bit signed)
4404 instruct loadB(iRegINoSp dst, memory mem)
4405 %{
4406 match(Set dst (LoadB mem));
4407
4408 ins_cost(LOAD_COST);
4409 format %{ "lb $dst, $mem\t# byte, #@loadB" %}
4410
4411 ins_encode %{
4412 __ lb(as_Register($dst$$reg), Address(as_Register($mem$$base), $mem$$disp));
4413 %}
4414
4415 ins_pipe(iload_reg_mem);
4416 %}
4417
4418 // Load Byte (8 bit signed) into long
4419 instruct loadB2L(iRegLNoSp dst, memory mem)
4420 %{
4421 match(Set dst (ConvI2L (LoadB mem)));
4422
4423 ins_cost(LOAD_COST);
4424 format %{ "lb $dst, $mem\t# byte, #@loadB2L" %}
4425
4426 ins_encode %{
4427 __ lb(as_Register($dst$$reg), Address(as_Register($mem$$base), $mem$$disp));
4428 %}
4429
4430 ins_pipe(iload_reg_mem);
4431 %}
4432
4433 // Load Byte (8 bit unsigned)
4434 instruct loadUB(iRegINoSp dst, memory mem)
4435 %{
4436 match(Set dst (LoadUB mem));
4437
4438 ins_cost(LOAD_COST);
4439 format %{ "lbu $dst, $mem\t# byte, #@loadUB" %}
4440
4441 ins_encode %{
4442 __ lbu(as_Register($dst$$reg), Address(as_Register($mem$$base), $mem$$disp));
4443 %}
4444
4445 ins_pipe(iload_reg_mem);
4446 %}
4447
4448 // Load Byte (8 bit unsigned) into long
4449 instruct loadUB2L(iRegLNoSp dst, memory mem)
4450 %{
4451 match(Set dst (ConvI2L (LoadUB mem)));
4452
4453 ins_cost(LOAD_COST);
4454 format %{ "lbu $dst, $mem\t# byte, #@loadUB2L" %}
4455
4456 ins_encode %{
4457 __ lbu(as_Register($dst$$reg), Address(as_Register($mem$$base), $mem$$disp));
4458 %}
4459
4460 ins_pipe(iload_reg_mem);
4461 %}
4462
4463 // Load Short (16 bit signed)
4464 instruct loadS(iRegINoSp dst, memory mem)
4465 %{
4466 match(Set dst (LoadS mem));
4467
4468 ins_cost(LOAD_COST);
4469 format %{ "lh $dst, $mem\t# short, #@loadS" %}
4470
4471 ins_encode %{
4472 __ lh(as_Register($dst$$reg), Address(as_Register($mem$$base), $mem$$disp));
4473 %}
4474
4475 ins_pipe(iload_reg_mem);
4476 %}
4477
4478 // Load Short (16 bit signed) into long
4479 instruct loadS2L(iRegLNoSp dst, memory mem)
4480 %{
4481 match(Set dst (ConvI2L (LoadS mem)));
4482
4483 ins_cost(LOAD_COST);
4484 format %{ "lh $dst, $mem\t# short, #@loadS2L" %}
4485
4486 ins_encode %{
4487 __ lh(as_Register($dst$$reg), Address(as_Register($mem$$base), $mem$$disp));
4488 %}
4489
4490 ins_pipe(iload_reg_mem);
4491 %}
4492
4493 // Load Char (16 bit unsigned)
4494 instruct loadUS(iRegINoSp dst, memory mem)
4495 %{
4496 match(Set dst (LoadUS mem));
4497
4498 ins_cost(LOAD_COST);
4499 format %{ "lhu $dst, $mem\t# short, #@loadUS" %}
4500
4501 ins_encode %{
4502 __ lhu(as_Register($dst$$reg), Address(as_Register($mem$$base), $mem$$disp));
4503 %}
4504
4505 ins_pipe(iload_reg_mem);
4506 %}
4507
4508 // Load Short/Char (16 bit unsigned) into long
4509 instruct loadUS2L(iRegLNoSp dst, memory mem)
4510 %{
4511 match(Set dst (ConvI2L (LoadUS mem)));
4512
4513 ins_cost(LOAD_COST);
4514 format %{ "lhu $dst, $mem\t# short, #@loadUS2L" %}
4515
4516 ins_encode %{
4517 __ lhu(as_Register($dst$$reg), Address(as_Register($mem$$base), $mem$$disp));
4518 %}
4519
4520 ins_pipe(iload_reg_mem);
4521 %}
4522
4523 // Load Integer (32 bit signed)
4524 instruct loadI(iRegINoSp dst, memory mem)
4525 %{
4526 match(Set dst (LoadI mem));
4527
4528 ins_cost(LOAD_COST);
4529 format %{ "lw $dst, $mem\t# int, #@loadI" %}
4530
4531 ins_encode %{
4532 __ lw(as_Register($dst$$reg), Address(as_Register($mem$$base), $mem$$disp));
4533 %}
4534
4535 ins_pipe(iload_reg_mem);
4536 %}
4537
4538 // Load Integer (32 bit signed) into long
4539 instruct loadI2L(iRegLNoSp dst, memory mem)
4540 %{
4541 match(Set dst (ConvI2L (LoadI mem)));
4542
4543 ins_cost(LOAD_COST);
4544 format %{ "lw $dst, $mem\t# int, #@loadI2L" %}
4545
4546 ins_encode %{
4547 __ lw(as_Register($dst$$reg), Address(as_Register($mem$$base), $mem$$disp));
4548 %}
4549
4550 ins_pipe(iload_reg_mem);
4551 %}
4552
4553 // Load Integer (32 bit unsigned) into long
4554 instruct loadUI2L(iRegLNoSp dst, memory mem, immL_32bits mask)
4555 %{
4556 match(Set dst (AndL (ConvI2L (LoadI mem)) mask));
4557
4558 ins_cost(LOAD_COST);
4559 format %{ "lwu $dst, $mem\t# int, #@loadUI2L" %}
4560
4561 ins_encode %{
4562 __ lwu(as_Register($dst$$reg), Address(as_Register($mem$$base), $mem$$disp));
4563 %}
4564
4565 ins_pipe(iload_reg_mem);
4566 %}
4567
4568 // Load Long (64 bit signed)
4569 instruct loadL(iRegLNoSp dst, memory mem)
4570 %{
4571 match(Set dst (LoadL mem));
4572
4573 ins_cost(LOAD_COST);
4574 format %{ "ld $dst, $mem\t# int, #@loadL" %}
4575
4576 ins_encode %{
4577 __ ld(as_Register($dst$$reg), Address(as_Register($mem$$base), $mem$$disp));
4578 %}
4579
4580 ins_pipe(iload_reg_mem);
4581 %}
4582
4583 // Load Range
4584 instruct loadRange(iRegINoSp dst, memory mem)
4585 %{
4586 match(Set dst (LoadRange mem));
4587
4588 ins_cost(LOAD_COST);
4589 format %{ "lwu $dst, $mem\t# range, #@loadRange" %}
4590
4591 ins_encode %{
4592 __ lwu(as_Register($dst$$reg), Address(as_Register($mem$$base), $mem$$disp));
4593 %}
4594
4595 ins_pipe(iload_reg_mem);
4596 %}
4597
4598 // Load Pointer
4599 instruct loadP(iRegPNoSp dst, memory mem)
4600 %{
4601 match(Set dst (LoadP mem));
4602 predicate(n->as_Load()->barrier_data() == 0);
4603
4604 ins_cost(LOAD_COST);
4605 format %{ "ld $dst, $mem\t# ptr, #@loadP" %}
4606
4607 ins_encode %{
4608 __ ld(as_Register($dst$$reg), Address(as_Register($mem$$base), $mem$$disp));
4609 %}
4610
4611 ins_pipe(iload_reg_mem);
4612 %}
4613
4614 // Load Compressed Pointer
4615 instruct loadN(iRegNNoSp dst, memory mem)
4616 %{
4617 predicate(n->as_Load()->barrier_data() == 0);
4618 match(Set dst (LoadN mem));
4619
4620 ins_cost(LOAD_COST);
4621 format %{ "lwu $dst, $mem\t# compressed ptr, #@loadN" %}
4622
4623 ins_encode %{
4624 __ lwu(as_Register($dst$$reg), Address(as_Register($mem$$base), $mem$$disp));
4625 %}
4626
4627 ins_pipe(iload_reg_mem);
4628 %}
4629
4630 // Load Klass Pointer
4631 instruct loadKlass(iRegPNoSp dst, memory mem)
4632 %{
4633 match(Set dst (LoadKlass mem));
4634
4635 ins_cost(LOAD_COST);
4636 format %{ "ld $dst, $mem\t# class, #@loadKlass" %}
4637
4638 ins_encode %{
4639 __ ld(as_Register($dst$$reg), Address(as_Register($mem$$base), $mem$$disp));
4640 %}
4641
4642 ins_pipe(iload_reg_mem);
4643 %}
4644
4645 // Load Narrow Klass Pointer
4646 instruct loadNKlass(iRegNNoSp dst, memory mem)
4647 %{
4648 predicate(!UseCompactObjectHeaders);
4649 match(Set dst (LoadNKlass mem));
4650
4651 ins_cost(LOAD_COST);
4652 format %{ "lwu $dst, $mem\t# compressed class ptr, #@loadNKlass" %}
4653
4654 ins_encode %{
4655 __ lwu(as_Register($dst$$reg), Address(as_Register($mem$$base), $mem$$disp));
4656 %}
4657
4658 ins_pipe(iload_reg_mem);
4659 %}
4660
4661 instruct loadNKlassCompactHeaders(iRegNNoSp dst, memory mem)
4662 %{
4663 predicate(UseCompactObjectHeaders);
4664 match(Set dst (LoadNKlass mem));
4665
4666 ins_cost(LOAD_COST);
4667 format %{
4668 "lwu $dst, $mem\t# compressed klass ptr, shifted\n\t"
4669 "srli $dst, $dst, markWord::klass_shift_at_offset"
4670 %}
4671
4672 ins_encode %{
4673 __ lwu(as_Register($dst$$reg), Address(as_Register($mem$$base), $mem$$disp));
4674 __ srli(as_Register($dst$$reg), as_Register($dst$$reg), (unsigned) markWord::klass_shift_at_offset);
4675 %}
4676
4677 ins_pipe(iload_reg_mem);
4678 %}
4679
4680 // Load Float
4681 instruct loadF(fRegF dst, memory mem)
4682 %{
4683 match(Set dst (LoadF mem));
4684
4685 ins_cost(LOAD_COST);
4686 format %{ "flw $dst, $mem\t# float, #@loadF" %}
4687
4688 ins_encode %{
4689 __ flw(as_FloatRegister($dst$$reg), Address(as_Register($mem$$base), $mem$$disp));
4690 %}
4691
4692 ins_pipe(fp_load_mem_s);
4693 %}
4694
4695 // Load Double
4696 instruct loadD(fRegD dst, memory mem)
4697 %{
4698 match(Set dst (LoadD mem));
4699
4700 ins_cost(LOAD_COST);
4701 format %{ "fld $dst, $mem\t# double, #@loadD" %}
4702
4703 ins_encode %{
4704 __ fld(as_FloatRegister($dst$$reg), Address(as_Register($mem$$base), $mem$$disp));
4705 %}
4706
4707 ins_pipe(fp_load_mem_d);
4708 %}
4709
4710 // Load Int Constant
4711 instruct loadConI(iRegINoSp dst, immI src)
4712 %{
4713 match(Set dst src);
4714
4715 ins_cost(ALU_COST);
4716 format %{ "mv $dst, $src\t# int, #@loadConI" %}
4717
4718 ins_encode(riscv_enc_mov_imm(dst, src));
4719
4720 ins_pipe(ialu_imm);
4721 %}
4722
4723 // Load Long Constant
4724 instruct loadConL(iRegLNoSp dst, immL src)
4725 %{
4726 match(Set dst src);
4727
4728 ins_cost(ALU_COST);
4729 format %{ "mv $dst, $src\t# long, #@loadConL" %}
4730
4731 ins_encode(riscv_enc_mov_imm(dst, src));
4732
4733 ins_pipe(ialu_imm);
4734 %}
4735
4736 // Load Pointer Constant
4737 instruct loadConP(iRegPNoSp dst, immP con)
4738 %{
4739 match(Set dst con);
4740
4741 ins_cost(ALU_COST);
4742 format %{ "mv $dst, $con\t# ptr, #@loadConP" %}
4743
4744 ins_encode(riscv_enc_mov_p(dst, con));
4745
4746 ins_pipe(ialu_imm);
4747 %}
4748
4749 // Load Null Pointer Constant
4750 instruct loadConP0(iRegPNoSp dst, immP0 con)
4751 %{
4752 match(Set dst con);
4753
4754 ins_cost(ALU_COST);
4755 format %{ "mv $dst, $con\t# null pointer, #@loadConP0" %}
4756
4757 ins_encode(riscv_enc_mov_zero(dst));
4758
4759 ins_pipe(ialu_imm);
4760 %}
4761
4762 // Load Pointer Constant One
4763 instruct loadConP1(iRegPNoSp dst, immP_1 con)
4764 %{
4765 match(Set dst con);
4766
4767 ins_cost(ALU_COST);
4768 format %{ "mv $dst, $con\t# load ptr constant one, #@loadConP1" %}
4769
4770 ins_encode(riscv_enc_mov_p1(dst));
4771
4772 ins_pipe(ialu_imm);
4773 %}
4774
4775 // Load Narrow Pointer Constant
4776 instruct loadConN(iRegNNoSp dst, immN con)
4777 %{
4778 match(Set dst con);
4779
4780 ins_cost(ALU_COST * 4);
4781 format %{ "mv $dst, $con\t# compressed ptr, #@loadConN" %}
4782
4783 ins_encode(riscv_enc_mov_n(dst, con));
4784
4785 ins_pipe(ialu_imm);
4786 %}
4787
4788 // Load Narrow Null Pointer Constant
4789 instruct loadConN0(iRegNNoSp dst, immN0 con)
4790 %{
4791 match(Set dst con);
4792
4793 ins_cost(ALU_COST);
4794 format %{ "mv $dst, $con\t# compressed null pointer, #@loadConN0" %}
4795
4796 ins_encode(riscv_enc_mov_zero(dst));
4797
4798 ins_pipe(ialu_imm);
4799 %}
4800
4801 // Load Narrow Klass Constant
4802 instruct loadConNKlass(iRegNNoSp dst, immNKlass con)
4803 %{
4804 match(Set dst con);
4805
4806 ins_cost(ALU_COST * 6);
4807 format %{ "mv $dst, $con\t# compressed klass ptr, #@loadConNKlass" %}
4808
4809 ins_encode(riscv_enc_mov_nk(dst, con));
4810
4811 ins_pipe(ialu_imm);
4812 %}
4813
4814 // Load Half Float Constant
4815 instruct loadConH(fRegF dst, immH con) %{
4816 match(Set dst con);
4817
4818 ins_cost(LOAD_COST);
4819 format %{
4820 "flh $dst, [$constantaddress]\t# load from constant table: float=$con, #@loadConH"
4821 %}
4822
4823 ins_encode %{
4824 assert(UseZfh || UseZfhmin, "must");
4825 if (MacroAssembler::can_hf_imm_load($con$$constant)) {
4826 __ fli_h(as_FloatRegister($dst$$reg), $con$$constant);
4827 } else {
4828 __ flh(as_FloatRegister($dst$$reg), $constantaddress($con));
4829 }
4830 %}
4831
4832 ins_pipe(fp_load_constant_s);
4833 %}
4834
4835 instruct loadConH0(fRegF dst, immH0 con) %{
4836 match(Set dst con);
4837
4838 ins_cost(XFER_COST);
4839
4840 format %{ "fmv.h.x $dst, zr\t# float, #@loadConH0" %}
4841
4842 ins_encode %{
4843 assert(UseZfh || UseZfhmin, "must");
4844 __ fmv_h_x(as_FloatRegister($dst$$reg), zr);
4845 %}
4846
4847 ins_pipe(fp_load_constant_s);
4848 %}
4849
4850 // Load Float Constant
4851 instruct loadConF(fRegF dst, immF con) %{
4852 match(Set dst con);
4853
4854 ins_cost(LOAD_COST);
4855 format %{
4856 "flw $dst, [$constantaddress]\t# load from constant table: float=$con, #@loadConF"
4857 %}
4858
4859 ins_encode %{
4860 if (MacroAssembler::can_fp_imm_load($con$$constant)) {
4861 __ fli_s(as_FloatRegister($dst$$reg), $con$$constant);
4862 } else {
4863 __ flw(as_FloatRegister($dst$$reg), $constantaddress($con));
4864 }
4865 %}
4866
4867 ins_pipe(fp_load_constant_s);
4868 %}
4869
4870 instruct loadConF0(fRegF dst, immF0 con) %{
4871 match(Set dst con);
4872
4873 ins_cost(XFER_COST);
4874
4875 format %{ "fmv.w.x $dst, zr\t# float, #@loadConF0" %}
4876
4877 ins_encode %{
4878 __ fmv_w_x(as_FloatRegister($dst$$reg), zr);
4879 %}
4880
4881 ins_pipe(fp_load_constant_s);
4882 %}
4883
4884 // Load Double Constant
4885 instruct loadConD(fRegD dst, immD con) %{
4886 match(Set dst con);
4887
4888 ins_cost(LOAD_COST);
4889 format %{
4890 "fld $dst, [$constantaddress]\t# load from constant table: double=$con, #@loadConD"
4891 %}
4892
4893 ins_encode %{
4894 if (MacroAssembler::can_dp_imm_load($con$$constant)) {
4895 __ fli_d(as_FloatRegister($dst$$reg), $con$$constant);
4896 } else {
4897 __ fld(as_FloatRegister($dst$$reg), $constantaddress($con));
4898 }
4899 %}
4900
4901 ins_pipe(fp_load_constant_d);
4902 %}
4903
4904 instruct loadConD0(fRegD dst, immD0 con) %{
4905 match(Set dst con);
4906
4907 ins_cost(XFER_COST);
4908
4909 format %{ "fmv.d.x $dst, zr\t# double, #@loadConD0" %}
4910
4911 ins_encode %{
4912 __ fmv_d_x(as_FloatRegister($dst$$reg), zr);
4913 %}
4914
4915 ins_pipe(fp_load_constant_d);
4916 %}
4917
4918 // Store Byte
4919 instruct storeB(iRegIorL2I src, memory mem)
4920 %{
4921 match(Set mem (StoreB mem src));
4922
4923 ins_cost(STORE_COST);
4924 format %{ "sb $src, $mem\t# byte, #@storeB" %}
4925
4926 ins_encode %{
4927 __ sb(as_Register($src$$reg), Address(as_Register($mem$$base), $mem$$disp));
4928 %}
4929
4930 ins_pipe(istore_reg_mem);
4931 %}
4932
4933 instruct storeimmB0(immI0 zero, memory mem)
4934 %{
4935 match(Set mem (StoreB mem zero));
4936
4937 ins_cost(STORE_COST);
4938 format %{ "sb zr, $mem\t# byte, #@storeimmB0" %}
4939
4940 ins_encode %{
4941 __ sb(zr, Address(as_Register($mem$$base), $mem$$disp));
4942 %}
4943
4944 ins_pipe(istore_mem);
4945 %}
4946
4947 // Store Char/Short
4948 instruct storeC(iRegIorL2I src, memory mem)
4949 %{
4950 match(Set mem (StoreC mem src));
4951
4952 ins_cost(STORE_COST);
4953 format %{ "sh $src, $mem\t# short, #@storeC" %}
4954
4955 ins_encode %{
4956 __ sh(as_Register($src$$reg), Address(as_Register($mem$$base), $mem$$disp));
4957 %}
4958
4959 ins_pipe(istore_reg_mem);
4960 %}
4961
4962 instruct storeimmC0(immI0 zero, memory mem)
4963 %{
4964 match(Set mem (StoreC mem zero));
4965
4966 ins_cost(STORE_COST);
4967 format %{ "sh zr, $mem\t# short, #@storeimmC0" %}
4968
4969 ins_encode %{
4970 __ sh(zr, Address(as_Register($mem$$base), $mem$$disp));
4971 %}
4972
4973 ins_pipe(istore_mem);
4974 %}
4975
4976 // Store Integer
4977 instruct storeI(iRegIorL2I src, memory mem)
4978 %{
4979 match(Set mem(StoreI mem src));
4980
4981 ins_cost(STORE_COST);
4982 format %{ "sw $src, $mem\t# int, #@storeI" %}
4983
4984 ins_encode %{
4985 __ sw(as_Register($src$$reg), Address(as_Register($mem$$base), $mem$$disp));
4986 %}
4987
4988 ins_pipe(istore_reg_mem);
4989 %}
4990
4991 instruct storeimmI0(immI0 zero, memory mem)
4992 %{
4993 match(Set mem(StoreI mem zero));
4994
4995 ins_cost(STORE_COST);
4996 format %{ "sw zr, $mem\t# int, #@storeimmI0" %}
4997
4998 ins_encode %{
4999 __ sw(zr, Address(as_Register($mem$$base), $mem$$disp));
5000 %}
5001
5002 ins_pipe(istore_mem);
5003 %}
5004
5005 // Store Long (64 bit signed)
5006 instruct storeL(iRegL src, memory mem)
5007 %{
5008 match(Set mem (StoreL mem src));
5009
5010 ins_cost(STORE_COST);
5011 format %{ "sd $src, $mem\t# long, #@storeL" %}
5012
5013 ins_encode %{
5014 __ sd(as_Register($src$$reg), Address(as_Register($mem$$base), $mem$$disp));
5015 %}
5016
5017 ins_pipe(istore_reg_mem);
5018 %}
5019
5020 // Store Long (64 bit signed)
5021 instruct storeimmL0(immL0 zero, memory mem)
5022 %{
5023 match(Set mem (StoreL mem zero));
5024
5025 ins_cost(STORE_COST);
5026 format %{ "sd zr, $mem\t# long, #@storeimmL0" %}
5027
5028 ins_encode %{
5029 __ sd(zr, Address(as_Register($mem$$base), $mem$$disp));
5030 %}
5031
5032 ins_pipe(istore_mem);
5033 %}
5034
5035 // Store Pointer
5036 instruct storeP(iRegP src, memory mem)
5037 %{
5038 match(Set mem (StoreP mem src));
5039 predicate(n->as_Store()->barrier_data() == 0);
5040
5041 ins_cost(STORE_COST);
5042 format %{ "sd $src, $mem\t# ptr, #@storeP" %}
5043
5044 ins_encode %{
5045 __ sd(as_Register($src$$reg), Address(as_Register($mem$$base), $mem$$disp));
5046 %}
5047
5048 ins_pipe(istore_reg_mem);
5049 %}
5050
5051 // Store Pointer
5052 instruct storeimmP0(immP0 zero, memory mem)
5053 %{
5054 match(Set mem (StoreP mem zero));
5055 predicate(n->as_Store()->barrier_data() == 0);
5056
5057 ins_cost(STORE_COST);
5058 format %{ "sd zr, $mem\t# ptr, #@storeimmP0" %}
5059
5060 ins_encode %{
5061 __ sd(zr, Address(as_Register($mem$$base), $mem$$disp));
5062 %}
5063
5064 ins_pipe(istore_mem);
5065 %}
5066
5067 // Store Compressed Pointer
5068 instruct storeN(iRegN src, memory mem)
5069 %{
5070 predicate(n->as_Store()->barrier_data() == 0);
5071 match(Set mem (StoreN mem src));
5072
5073 ins_cost(STORE_COST);
5074 format %{ "sw $src, $mem\t# compressed ptr, #@storeN" %}
5075
5076 ins_encode %{
5077 __ sw(as_Register($src$$reg), Address(as_Register($mem$$base), $mem$$disp));
5078 %}
5079
5080 ins_pipe(istore_reg_mem);
5081 %}
5082
5083 instruct storeImmN0(immN0 zero, memory mem)
5084 %{
5085 predicate(n->as_Store()->barrier_data() == 0);
5086 match(Set mem (StoreN mem zero));
5087
5088 ins_cost(STORE_COST);
5089 format %{ "sw zr, $mem\t# compressed ptr, #@storeImmN0" %}
5090
5091 ins_encode %{
5092 __ sw(zr, Address(as_Register($mem$$base), $mem$$disp));
5093 %}
5094
5095 ins_pipe(istore_reg_mem);
5096 %}
5097
5098 // Store Float
5099 instruct storeF(fRegF src, memory mem)
5100 %{
5101 match(Set mem (StoreF mem src));
5102
5103 ins_cost(STORE_COST);
5104 format %{ "fsw $src, $mem\t# float, #@storeF" %}
5105
5106 ins_encode %{
5107 __ fsw(as_FloatRegister($src$$reg), Address(as_Register($mem$$base), $mem$$disp));
5108 %}
5109
5110 ins_pipe(fp_store_reg_s);
5111 %}
5112
5113 // Store Double
5114 instruct storeD(fRegD src, memory mem)
5115 %{
5116 match(Set mem (StoreD mem src));
5117
5118 ins_cost(STORE_COST);
5119 format %{ "fsd $src, $mem\t# double, #@storeD" %}
5120
5121 ins_encode %{
5122 __ fsd(as_FloatRegister($src$$reg), Address(as_Register($mem$$base), $mem$$disp));
5123 %}
5124
5125 ins_pipe(fp_store_reg_d);
5126 %}
5127
5128 // Store Compressed Klass Pointer
5129 instruct storeNKlass(iRegN src, memory mem)
5130 %{
5131 match(Set mem (StoreNKlass mem src));
5132
5133 ins_cost(STORE_COST);
5134 format %{ "sw $src, $mem\t# compressed klass ptr, #@storeNKlass" %}
5135
5136 ins_encode %{
5137 __ sw(as_Register($src$$reg), Address(as_Register($mem$$base), $mem$$disp));
5138 %}
5139
5140 ins_pipe(istore_reg_mem);
5141 %}
5142
5143 // ============================================================================
5144 // Prefetch instructions
5145 // Must be safe to execute with invalid address (cannot fault).
5146
5147 instruct prefetchalloc( memory mem ) %{
5148 predicate(UseZicbop);
5149 match(PrefetchAllocation mem);
5150
5151 ins_cost(ALU_COST * 1);
5152 format %{ "prefetch_w $mem\t# Prefetch for write" %}
5153
5154 ins_encode %{
5155 if (Assembler::is_simm12($mem$$disp)) {
5156 if (($mem$$disp & 0x1f) == 0) {
5157 __ prefetch_w(as_Register($mem$$base), $mem$$disp);
5158 } else {
5159 __ addi(t0, as_Register($mem$$base), $mem$$disp);
5160 __ prefetch_w(t0, 0);
5161 }
5162 } else {
5163 __ mv(t0, $mem$$disp);
5164 __ add(t0, as_Register($mem$$base), t0);
5165 __ prefetch_w(t0, 0);
5166 }
5167 %}
5168
5169 ins_pipe(iload_prefetch);
5170 %}
5171
5172 // ============================================================================
5173 // Atomic operation instructions
5174 //
5175
5176 // standard CompareAndSwapX when we are using barriers
5177 // these have higher priority than the rules selected by a predicate
5178 instruct compareAndSwapB_narrow(iRegINoSp res, indirect mem, iRegI_R12 oldval, iRegI_R13 newval,
5179 iRegINoSp tmp1, iRegINoSp tmp2, iRegINoSp tmp3, rFlagsReg cr)
5180 %{
5181 predicate(!UseZabha || !UseZacas);
5182
5183 match(Set res (CompareAndSwapB mem (Binary oldval newval)));
5184
5185 ins_cost(2 * VOLATILE_REF_COST);
5186
5187 effect(TEMP_DEF res, USE_KILL oldval, USE_KILL newval, TEMP tmp1, TEMP tmp2, TEMP tmp3, KILL cr);
5188
5189 format %{
5190 "cmpxchg $mem, $oldval, $newval\t# (byte) if $mem == $oldval then $mem <-- $newval\n\t"
5191 "mv $res, $res == $oldval\t# $res <-- ($res == $oldval ? 1 : 0), #@compareAndSwapB_narrow"
5192 %}
5193
5194 ins_encode %{
5195 __ cmpxchg_narrow_value(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int8,
5196 Assembler::relaxed /* acquire */, Assembler::rl /* release */, $res$$Register,
5197 true /* result as bool */, $tmp1$$Register, $tmp2$$Register, $tmp3$$Register);
5198 %}
5199
5200 ins_pipe(pipe_slow);
5201 %}
5202
5203 instruct compareAndSwapB(iRegINoSp res, indirect mem, iRegI oldval, iRegI newval)
5204 %{
5205 predicate(UseZabha && UseZacas);
5206
5207 match(Set res (CompareAndSwapB mem (Binary oldval newval)));
5208
5209 ins_cost(2 * VOLATILE_REF_COST);
5210
5211 format %{
5212 "cmpxchg $mem, $oldval, $newval\t# (byte) if $mem == $oldval then $mem <-- $newval\n\t"
5213 "mv $res, $res == $oldval\t# $res <-- ($res == $oldval ? 1 : 0), #@compareAndSwapB"
5214 %}
5215
5216 ins_encode %{
5217 __ cmpxchg(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int8,
5218 Assembler::relaxed /* acquire */, Assembler::rl /* release */, $res$$Register,
5219 true /* result as bool */);
5220 %}
5221
5222 ins_pipe(pipe_slow);
5223 %}
5224
5225 instruct compareAndSwapS_narrow(iRegINoSp res, indirect mem, iRegI_R12 oldval, iRegI_R13 newval,
5226 iRegINoSp tmp1, iRegINoSp tmp2, iRegINoSp tmp3, rFlagsReg cr)
5227 %{
5228 predicate(!UseZabha || !UseZacas);
5229
5230 match(Set res (CompareAndSwapS mem (Binary oldval newval)));
5231
5232 ins_cost(2 * VOLATILE_REF_COST);
5233
5234 effect(TEMP_DEF res, USE_KILL oldval, USE_KILL newval, TEMP tmp1, TEMP tmp2, TEMP tmp3, KILL cr);
5235
5236 format %{
5237 "cmpxchg $mem, $oldval, $newval\t# (short) if $mem == $oldval then $mem <-- $newval\n\t"
5238 "mv $res, $res == $oldval\t# $res <-- ($res == $oldval ? 1 : 0), #@compareAndSwapS_narrow"
5239 %}
5240
5241 ins_encode %{
5242 __ cmpxchg_narrow_value(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int16,
5243 Assembler::relaxed /* acquire */, Assembler::rl /* release */, $res$$Register,
5244 true /* result as bool */, $tmp1$$Register, $tmp2$$Register, $tmp3$$Register);
5245 %}
5246
5247 ins_pipe(pipe_slow);
5248 %}
5249
5250 instruct compareAndSwapS(iRegINoSp res, indirect mem, iRegI oldval, iRegI newval)
5251 %{
5252 predicate(UseZabha && UseZacas);
5253
5254 match(Set res (CompareAndSwapS mem (Binary oldval newval)));
5255
5256 ins_cost(2 * VOLATILE_REF_COST);
5257
5258 format %{
5259 "cmpxchg $mem, $oldval, $newval\t# (short) if $mem == $oldval then $mem <-- $newval\n\t"
5260 "mv $res, $res == $oldval\t# $res <-- ($res == $oldval ? 1 : 0), #@compareAndSwapS"
5261 %}
5262
5263 ins_encode %{
5264 __ cmpxchg(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int16,
5265 Assembler::relaxed /* acquire */, Assembler::rl /* release */, $res$$Register,
5266 true /* result as bool */);
5267 %}
5268
5269 ins_pipe(pipe_slow);
5270 %}
5271
5272 instruct compareAndSwapI(iRegINoSp res, indirect mem, iRegI oldval, iRegI newval)
5273 %{
5274 match(Set res (CompareAndSwapI mem (Binary oldval newval)));
5275
5276 ins_cost(2 * VOLATILE_REF_COST);
5277
5278 format %{
5279 "cmpxchg $mem, $oldval, $newval\t# (int) if $mem == $oldval then $mem <-- $newval\n\t"
5280 "mv $res, $res == $oldval\t# $res <-- ($res == $oldval ? 1 : 0), #@compareAndSwapI"
5281 %}
5282
5283 ins_encode %{
5284 __ cmpxchg(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int32,
5285 /*acquire*/ Assembler::relaxed, /*release*/ Assembler::rl, $res$$Register,
5286 /*result as bool*/ true);
5287 %}
5288
5289 ins_pipe(pipe_slow);
5290 %}
5291
5292 instruct compareAndSwapL(iRegINoSp res, indirect mem, iRegL oldval, iRegL newval)
5293 %{
5294 match(Set res (CompareAndSwapL mem (Binary oldval newval)));
5295
5296 ins_cost(2 * VOLATILE_REF_COST);
5297
5298 format %{
5299 "cmpxchg $mem, $oldval, $newval\t# (long) if $mem == $oldval then $mem <-- $newval\n\t"
5300 "mv $res, $res == $oldval\t# $res <-- ($res == $oldval ? 1 : 0), #@compareAndSwapL"
5301 %}
5302
5303 ins_encode %{
5304 __ cmpxchg(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int64,
5305 /*acquire*/ Assembler::relaxed, /*release*/ Assembler::rl, $res$$Register,
5306 /*result as bool*/ true);
5307 %}
5308
5309 ins_pipe(pipe_slow);
5310 %}
5311
5312 instruct compareAndSwapP(iRegINoSp res, indirect mem, iRegP oldval, iRegP newval)
5313 %{
5314 predicate(n->as_LoadStore()->barrier_data() == 0);
5315
5316 match(Set res (CompareAndSwapP mem (Binary oldval newval)));
5317
5318 ins_cost(2 * VOLATILE_REF_COST);
5319
5320 format %{
5321 "cmpxchg $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval\n\t"
5322 "mv $res, $res == $oldval\t# $res <-- ($res == $oldval ? 1 : 0), #@compareAndSwapP"
5323 %}
5324
5325 ins_encode %{
5326 __ cmpxchg(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int64,
5327 /*acquire*/ Assembler::relaxed, /*release*/ Assembler::rl, $res$$Register,
5328 /*result as bool*/ true);
5329 %}
5330
5331 ins_pipe(pipe_slow);
5332 %}
5333
5334 instruct compareAndSwapN(iRegINoSp res, indirect mem, iRegN oldval, iRegN newval)
5335 %{
5336 predicate(n->as_LoadStore()->barrier_data() == 0);
5337
5338 match(Set res (CompareAndSwapN mem (Binary oldval newval)));
5339
5340 ins_cost(2 * VOLATILE_REF_COST);
5341
5342 format %{
5343 "cmpxchg $mem, $oldval, $newval\t# (narrow oop) if $mem == $oldval then $mem <-- $newval\n\t"
5344 "mv $res, $res == $oldval\t# $res <-- ($res == $oldval ? 1 : 0), #@compareAndSwapN"
5345 %}
5346
5347 ins_encode %{
5348 __ cmpxchg(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::uint32,
5349 /*acquire*/ Assembler::relaxed, /*release*/ Assembler::rl, $res$$Register,
5350 /*result as bool*/ true);
5351 %}
5352
5353 ins_pipe(pipe_slow);
5354 %}
5355
5356 // alternative CompareAndSwapX when we are eliding barriers
5357 instruct compareAndSwapBAcq_narrow(iRegINoSp res, indirect mem, iRegI_R12 oldval, iRegI_R13 newval,
5358 iRegINoSp tmp1, iRegINoSp tmp2, iRegINoSp tmp3, rFlagsReg cr)
5359 %{
5360 predicate((!UseZabha || !UseZacas) && needs_acquiring_load_reserved(n));
5361
5362 match(Set res (CompareAndSwapB mem (Binary oldval newval)));
5363
5364 ins_cost(2 * VOLATILE_REF_COST);
5365
5366 effect(TEMP_DEF res, KILL cr, USE_KILL oldval, USE_KILL newval, TEMP tmp1, TEMP tmp2, TEMP tmp3);
5367
5368 format %{
5369 "cmpxchg_acq $mem, $oldval, $newval\t# (byte) if $mem == $oldval then $mem <-- $newval\n\t"
5370 "mv $res, $res == $oldval\t# $res <-- ($res == $oldval ? 1 : 0), #@compareAndSwapBAcq_narrow"
5371 %}
5372
5373 ins_encode %{
5374 __ cmpxchg_narrow_value(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int8,
5375 Assembler::aq /* acquire */, Assembler::rl /* release */, $res$$Register,
5376 true /* result as bool */, $tmp1$$Register, $tmp2$$Register, $tmp3$$Register);
5377 %}
5378
5379 ins_pipe(pipe_slow);
5380 %}
5381
5382 instruct compareAndSwapBAcq(iRegINoSp res, indirect mem, iRegI oldval, iRegI newval)
5383 %{
5384 predicate((UseZabha && UseZacas) && needs_acquiring_load_reserved(n));
5385
5386 match(Set res (CompareAndSwapB mem (Binary oldval newval)));
5387
5388 ins_cost(2 * VOLATILE_REF_COST);
5389
5390 format %{
5391 "cmpxchg $mem, $oldval, $newval\t# (byte) if $mem == $oldval then $mem <-- $newval\n\t"
5392 "mv $res, $res == $oldval\t# $res <-- ($res == $oldval ? 1 : 0), #@compareAndSwapBAcq"
5393 %}
5394
5395 ins_encode %{
5396 __ cmpxchg(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int8,
5397 Assembler::aq /* acquire */, Assembler::rl /* release */, $res$$Register,
5398 true /* result as bool */);
5399 %}
5400
5401 ins_pipe(pipe_slow);
5402 %}
5403
5404 instruct compareAndSwapSAcq_narrow(iRegINoSp res, indirect mem, iRegI_R12 oldval, iRegI_R13 newval,
5405 iRegINoSp tmp1, iRegINoSp tmp2, iRegINoSp tmp3, rFlagsReg cr)
5406 %{
5407 predicate((!UseZabha || !UseZacas) && needs_acquiring_load_reserved(n));
5408
5409 match(Set res (CompareAndSwapS mem (Binary oldval newval)));
5410
5411 ins_cost(2 * VOLATILE_REF_COST);
5412
5413 effect(TEMP_DEF res, KILL cr, USE_KILL oldval, USE_KILL newval, TEMP tmp1, TEMP tmp2, TEMP tmp3);
5414
5415 format %{
5416 "cmpxchg_acq $mem, $oldval, $newval\t# (short) if $mem == $oldval then $mem <-- $newval\n\t"
5417 "mv $res, $res == $oldval\t# $res <-- ($res == $oldval ? 1 : 0), #@compareAndSwapSAcq_narrow"
5418 %}
5419
5420 ins_encode %{
5421 __ cmpxchg_narrow_value(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int16,
5422 Assembler::aq /* acquire */, Assembler::rl /* release */, $res$$Register,
5423 true /* result as bool */, $tmp1$$Register, $tmp2$$Register, $tmp3$$Register);
5424 %}
5425
5426 ins_pipe(pipe_slow);
5427 %}
5428
5429 instruct compareAndSwapSAcq(iRegINoSp res, indirect mem, iRegI oldval, iRegI newval)
5430 %{
5431 predicate((UseZabha && UseZacas) && needs_acquiring_load_reserved(n));
5432
5433 match(Set res (CompareAndSwapS mem (Binary oldval newval)));
5434
5435 ins_cost(2 * VOLATILE_REF_COST);
5436
5437 format %{
5438 "cmpxchg $mem, $oldval, $newval\t# (short) if $mem == $oldval then $mem <-- $newval\n\t"
5439 "mv $res, $res == $oldval\t# $res <-- ($res == $oldval ? 1 : 0), #@compareAndSwapSAcq"
5440 %}
5441
5442 ins_encode %{
5443 __ cmpxchg(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int16,
5444 Assembler::aq /* acquire */, Assembler::rl /* release */, $res$$Register,
5445 true /* result as bool */);
5446 %}
5447
5448 ins_pipe(pipe_slow);
5449 %}
5450
5451 instruct compareAndSwapIAcq(iRegINoSp res, indirect mem, iRegI oldval, iRegI newval)
5452 %{
5453 predicate(needs_acquiring_load_reserved(n));
5454
5455 match(Set res (CompareAndSwapI mem (Binary oldval newval)));
5456
5457 ins_cost(2 * VOLATILE_REF_COST);
5458
5459 format %{
5460 "cmpxchg_acq $mem, $oldval, $newval\t# (int) if $mem == $oldval then $mem <-- $newval\n\t"
5461 "mv $res, $res == $oldval\t# $res <-- ($res == $oldval ? 1 : 0), #@compareAndSwapIAcq"
5462 %}
5463
5464 ins_encode %{
5465 __ cmpxchg(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int32,
5466 /*acquire*/ Assembler::aq, /*release*/ Assembler::rl, $res$$Register,
5467 /*result as bool*/ true);
5468 %}
5469
5470 ins_pipe(pipe_slow);
5471 %}
5472
5473 instruct compareAndSwapLAcq(iRegINoSp res, indirect mem, iRegL oldval, iRegL newval)
5474 %{
5475 predicate(needs_acquiring_load_reserved(n));
5476
5477 match(Set res (CompareAndSwapL mem (Binary oldval newval)));
5478
5479 ins_cost(2 * VOLATILE_REF_COST);
5480
5481 format %{
5482 "cmpxchg_acq $mem, $oldval, $newval\t# (long) if $mem == $oldval then $mem <-- $newval\n\t"
5483 "mv $res, $res == $oldval\t# $res <-- ($res == $oldval ? 1 : 0), #@compareAndSwapLAcq"
5484 %}
5485
5486 ins_encode %{
5487 __ cmpxchg(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int64,
5488 /*acquire*/ Assembler::aq, /*release*/ Assembler::rl, $res$$Register,
5489 /*result as bool*/ true);
5490 %}
5491
5492 ins_pipe(pipe_slow);
5493 %}
5494
5495 instruct compareAndSwapPAcq(iRegINoSp res, indirect mem, iRegP oldval, iRegP newval)
5496 %{
5497 predicate(needs_acquiring_load_reserved(n) && (n->as_LoadStore()->barrier_data() == 0));
5498
5499 match(Set res (CompareAndSwapP mem (Binary oldval newval)));
5500
5501 ins_cost(2 * VOLATILE_REF_COST);
5502
5503 format %{
5504 "cmpxchg_acq $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval\n\t"
5505 "mv $res, $res == $oldval\t# $res <-- ($res == $oldval ? 1 : 0), #@compareAndSwapPAcq"
5506 %}
5507
5508 ins_encode %{
5509 __ cmpxchg(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int64,
5510 /*acquire*/ Assembler::aq, /*release*/ Assembler::rl, $res$$Register,
5511 /*result as bool*/ true);
5512 %}
5513
5514 ins_pipe(pipe_slow);
5515 %}
5516
5517 instruct compareAndSwapNAcq(iRegINoSp res, indirect mem, iRegN oldval, iRegN newval)
5518 %{
5519 predicate(needs_acquiring_load_reserved(n) && n->as_LoadStore()->barrier_data() == 0);
5520
5521 match(Set res (CompareAndSwapN mem (Binary oldval newval)));
5522
5523 ins_cost(2 * VOLATILE_REF_COST);
5524
5525 format %{
5526 "cmpxchg_acq $mem, $oldval, $newval\t# (narrow oop) if $mem == $oldval then $mem <-- $newval\n\t"
5527 "mv $res, $res == $oldval\t# $res <-- ($res == $oldval ? 1 : 0), #@compareAndSwapNAcq"
5528 %}
5529
5530 ins_encode %{
5531 __ cmpxchg(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::uint32,
5532 /*acquire*/ Assembler::aq, /*release*/ Assembler::rl, $res$$Register,
5533 /*result as bool*/ true);
5534 %}
5535
5536 ins_pipe(pipe_slow);
5537 %}
5538
5539 // Sundry CAS operations. Note that release is always true,
5540 // regardless of the memory ordering of the CAS. This is because we
5541 // need the volatile case to be sequentially consistent but there is
5542 // no trailing StoreLoad barrier emitted by C2. Unfortunately we
5543 // can't check the type of memory ordering here, so we always emit a
5544 // sc_d(w) with rl bit set.
5545 instruct compareAndExchangeB_narrow(iRegINoSp res, indirect mem, iRegI_R12 oldval, iRegI_R13 newval,
5546 iRegINoSp tmp1, iRegINoSp tmp2, iRegINoSp tmp3, rFlagsReg cr)
5547 %{
5548 predicate(!UseZabha || !UseZacas);
5549
5550 match(Set res (CompareAndExchangeB mem (Binary oldval newval)));
5551
5552 ins_cost(2 * VOLATILE_REF_COST);
5553
5554 effect(TEMP_DEF res, KILL cr, USE_KILL oldval, USE_KILL newval, TEMP tmp1, TEMP tmp2, TEMP tmp3);
5555
5556 format %{
5557 "cmpxchg $res = $mem, $oldval, $newval\t# (byte, weak) if $mem == $oldval then $mem <-- $newval, #@compareAndExchangeB_narrow"
5558 %}
5559
5560 ins_encode %{
5561 __ cmpxchg_narrow_value(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int8,
5562 /*acquire*/ Assembler::relaxed, /*release*/ Assembler::rl, $res$$Register,
5563 /*result_as_bool*/ false, $tmp1$$Register, $tmp2$$Register, $tmp3$$Register);
5564 %}
5565
5566 ins_pipe(pipe_slow);
5567 %}
5568
5569 instruct compareAndExchangeB(iRegINoSp res, indirect mem, iRegI oldval, iRegI newval)
5570 %{
5571 predicate(UseZabha && UseZacas);
5572
5573 match(Set res (CompareAndExchangeB mem (Binary oldval newval)));
5574
5575 ins_cost(2 * VOLATILE_REF_COST);
5576
5577 format %{
5578 "cmpxchg $res = $mem, $oldval, $newval\t# (byte, weak) if $mem == $oldval then $mem <-- $newval, #@compareAndExchangeB"
5579 %}
5580
5581 ins_encode %{
5582 __ cmpxchg(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int8,
5583 /*acquire*/ Assembler::relaxed, /*release*/ Assembler::rl, $res$$Register);
5584 %}
5585
5586 ins_pipe(pipe_slow);
5587 %}
5588
5589 instruct compareAndExchangeS_narrow(iRegINoSp res, indirect mem, iRegI_R12 oldval, iRegI_R13 newval,
5590 iRegINoSp tmp1, iRegINoSp tmp2, iRegINoSp tmp3, rFlagsReg cr)
5591 %{
5592 predicate(!UseZabha || !UseZacas);
5593
5594 match(Set res (CompareAndExchangeS mem (Binary oldval newval)));
5595
5596 ins_cost(2 * VOLATILE_REF_COST);
5597
5598 effect(TEMP_DEF res, KILL cr, USE_KILL oldval, USE_KILL newval, TEMP tmp1, TEMP tmp2, TEMP tmp3);
5599
5600 format %{
5601 "cmpxchg $res = $mem, $oldval, $newval\t# (short, weak) if $mem == $oldval then $mem <-- $newval, #@compareAndExchangeS_narrow"
5602 %}
5603
5604 ins_encode %{
5605 __ cmpxchg_narrow_value(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int16,
5606 /*acquire*/ Assembler::relaxed, /*release*/ Assembler::rl, $res$$Register,
5607 /*result_as_bool*/ false, $tmp1$$Register, $tmp2$$Register, $tmp3$$Register);
5608 %}
5609
5610 ins_pipe(pipe_slow);
5611 %}
5612
5613 instruct compareAndExchangeS(iRegINoSp res, indirect mem, iRegI oldval, iRegI newval)
5614 %{
5615 predicate(UseZabha && UseZacas);
5616
5617 match(Set res (CompareAndExchangeS mem (Binary oldval newval)));
5618
5619 ins_cost(2 * VOLATILE_REF_COST);
5620
5621 format %{
5622 "cmpxchg $res = $mem, $oldval, $newval\t# (short, weak) if $mem == $oldval then $mem <-- $newval, #@compareAndExchangeS"
5623 %}
5624
5625 ins_encode %{
5626 __ cmpxchg(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int16,
5627 /*acquire*/ Assembler::relaxed, /*release*/ Assembler::rl, $res$$Register);
5628 %}
5629
5630 ins_pipe(pipe_slow);
5631 %}
5632
5633 instruct compareAndExchangeI(iRegINoSp res, indirect mem, iRegI oldval, iRegI newval)
5634 %{
5635 match(Set res (CompareAndExchangeI mem (Binary oldval newval)));
5636
5637 ins_cost(2 * VOLATILE_REF_COST);
5638
5639 format %{
5640 "cmpxchg $res = $mem, $oldval, $newval\t# (int, weak) if $mem == $oldval then $mem <-- $newval, #@compareAndExchangeI"
5641 %}
5642
5643 ins_encode %{
5644 __ cmpxchg(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int32,
5645 /*acquire*/ Assembler::relaxed, /*release*/ Assembler::rl, $res$$Register);
5646 %}
5647
5648 ins_pipe(pipe_slow);
5649 %}
5650
5651 instruct compareAndExchangeL(iRegLNoSp res, indirect mem, iRegL oldval, iRegL newval)
5652 %{
5653 match(Set res (CompareAndExchangeL mem (Binary oldval newval)));
5654
5655 ins_cost(2 * VOLATILE_REF_COST);
5656
5657 format %{
5658 "cmpxchg $res = $mem, $oldval, $newval\t# (long, weak) if $mem == $oldval then $mem <-- $newval, #@compareAndExchangeL"
5659 %}
5660
5661 ins_encode %{
5662 __ cmpxchg(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int64,
5663 /*acquire*/ Assembler::relaxed, /*release*/ Assembler::rl, $res$$Register);
5664 %}
5665
5666 ins_pipe(pipe_slow);
5667 %}
5668
5669 instruct compareAndExchangeN(iRegNNoSp res, indirect mem, iRegN oldval, iRegN newval)
5670 %{
5671 predicate(n->as_LoadStore()->barrier_data() == 0);
5672
5673 match(Set res (CompareAndExchangeN mem (Binary oldval newval)));
5674
5675 ins_cost(2 * VOLATILE_REF_COST);
5676
5677 format %{
5678 "cmpxchg $res = $mem, $oldval, $newval\t# (narrow oop, weak) if $mem == $oldval then $mem <-- $newval, #@compareAndExchangeN"
5679 %}
5680
5681 ins_encode %{
5682 __ cmpxchg(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::uint32,
5683 /*acquire*/ Assembler::relaxed, /*release*/ Assembler::rl, $res$$Register);
5684 %}
5685
5686 ins_pipe(pipe_slow);
5687 %}
5688
5689 instruct compareAndExchangeP(iRegPNoSp res, indirect mem, iRegP oldval, iRegP newval)
5690 %{
5691 predicate(n->as_LoadStore()->barrier_data() == 0);
5692
5693 match(Set res (CompareAndExchangeP mem (Binary oldval newval)));
5694
5695 ins_cost(2 * VOLATILE_REF_COST);
5696
5697 format %{
5698 "cmpxchg $res = $mem, $oldval, $newval\t# (ptr, weak) if $mem == $oldval then $mem <-- $newval, #@compareAndExchangeP"
5699 %}
5700
5701 ins_encode %{
5702 __ cmpxchg(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int64,
5703 /*acquire*/ Assembler::relaxed, /*release*/ Assembler::rl, $res$$Register);
5704 %}
5705
5706 ins_pipe(pipe_slow);
5707 %}
5708
5709 instruct compareAndExchangeBAcq_narrow(iRegINoSp res, indirect mem, iRegI_R12 oldval, iRegI_R13 newval,
5710 iRegINoSp tmp1, iRegINoSp tmp2, iRegINoSp tmp3, rFlagsReg cr)
5711 %{
5712 predicate((!UseZabha || !UseZacas) && needs_acquiring_load_reserved(n));
5713
5714 match(Set res (CompareAndExchangeB mem (Binary oldval newval)));
5715
5716 ins_cost(2 * VOLATILE_REF_COST);
5717
5718 effect(TEMP_DEF res, KILL cr, USE_KILL oldval, USE_KILL newval, TEMP tmp1, TEMP tmp2, TEMP tmp3);
5719
5720 format %{
5721 "cmpxchg_acq $res = $mem, $oldval, $newval\t# (byte, weak) if $mem == $oldval then $mem <-- $newval, #@compareAndExchangeBAcq_narrow"
5722 %}
5723
5724 ins_encode %{
5725 __ cmpxchg_narrow_value(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int8,
5726 /*acquire*/ Assembler::aq, /*release*/ Assembler::rl, $res$$Register,
5727 /*result_as_bool*/ false, $tmp1$$Register, $tmp2$$Register, $tmp3$$Register);
5728 %}
5729
5730 ins_pipe(pipe_slow);
5731 %}
5732
5733 instruct compareAndExchangeBAcq(iRegINoSp res, indirect mem, iRegI oldval, iRegI newval)
5734 %{
5735 predicate((UseZabha && UseZacas) && needs_acquiring_load_reserved(n));
5736
5737 match(Set res (CompareAndExchangeB mem (Binary oldval newval)));
5738
5739 ins_cost(2 * VOLATILE_REF_COST);
5740
5741 format %{
5742 "cmpxchg_acq $res = $mem, $oldval, $newval\t# (byte, weak) if $mem == $oldval then $mem <-- $newval, #@compareAndExchangeBAcq"
5743 %}
5744
5745 ins_encode %{
5746 __ cmpxchg(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int8,
5747 /*acquire*/ Assembler::aq, /*release*/ Assembler::rl, $res$$Register);
5748 %}
5749
5750 ins_pipe(pipe_slow);
5751 %}
5752
5753 instruct compareAndExchangeSAcq_narrow(iRegINoSp res, indirect mem, iRegI_R12 oldval, iRegI_R13 newval,
5754 iRegINoSp tmp1, iRegINoSp tmp2, iRegINoSp tmp3, rFlagsReg cr)
5755 %{
5756 predicate((!UseZabha || !UseZacas) && needs_acquiring_load_reserved(n));
5757
5758 match(Set res (CompareAndExchangeS mem (Binary oldval newval)));
5759
5760 ins_cost(2 * VOLATILE_REF_COST);
5761
5762 effect(TEMP_DEF res, KILL cr, USE_KILL oldval, USE_KILL newval, TEMP tmp1, TEMP tmp2, TEMP tmp3);
5763
5764 format %{
5765 "cmpxchg_acq $res = $mem, $oldval, $newval\t# (short, weak) if $mem == $oldval then $mem <-- $newval, #@compareAndExchangeSAcq_narrow"
5766 %}
5767
5768 ins_encode %{
5769 __ cmpxchg_narrow_value(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int16,
5770 /*acquire*/ Assembler::aq, /*release*/ Assembler::rl, $res$$Register,
5771 /*result_as_bool*/ false, $tmp1$$Register, $tmp2$$Register, $tmp3$$Register);
5772 %}
5773
5774 ins_pipe(pipe_slow);
5775 %}
5776
5777 instruct compareAndExchangeSAcq(iRegINoSp res, indirect mem, iRegI oldval, iRegI newval)
5778 %{
5779 predicate((UseZabha && UseZacas) && needs_acquiring_load_reserved(n));
5780
5781 match(Set res (CompareAndExchangeS mem (Binary oldval newval)));
5782
5783 ins_cost(2 * VOLATILE_REF_COST);
5784
5785 format %{
5786 "cmpxchg_acq $res = $mem, $oldval, $newval\t# (short, weak) if $mem == $oldval then $mem <-- $newval, #@compareAndExchangeSAcq"
5787 %}
5788
5789 ins_encode %{
5790 __ cmpxchg(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int16,
5791 /*acquire*/ Assembler::aq, /*release*/ Assembler::rl, $res$$Register);
5792 %}
5793
5794 ins_pipe(pipe_slow);
5795 %}
5796
5797 instruct compareAndExchangeIAcq(iRegINoSp res, indirect mem, iRegI oldval, iRegI newval)
5798 %{
5799 predicate(needs_acquiring_load_reserved(n));
5800
5801 match(Set res (CompareAndExchangeI mem (Binary oldval newval)));
5802
5803 ins_cost(2 * VOLATILE_REF_COST);
5804
5805 format %{
5806 "cmpxchg_acq $res = $mem, $oldval, $newval\t# (int, weak) if $mem == $oldval then $mem <-- $newval, #@compareAndExchangeIAcq"
5807 %}
5808
5809 ins_encode %{
5810 __ cmpxchg(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int32,
5811 /*acquire*/ Assembler::aq, /*release*/ Assembler::rl, $res$$Register);
5812 %}
5813
5814 ins_pipe(pipe_slow);
5815 %}
5816
5817 instruct compareAndExchangeLAcq(iRegLNoSp res, indirect mem, iRegL oldval, iRegL newval)
5818 %{
5819 predicate(needs_acquiring_load_reserved(n));
5820
5821 match(Set res (CompareAndExchangeL mem (Binary oldval newval)));
5822
5823 ins_cost(2 * VOLATILE_REF_COST);
5824
5825 format %{
5826 "cmpxchg_acq $res = $mem, $oldval, $newval\t# (long, weak) if $mem == $oldval then $mem <-- $newval, #@compareAndExchangeLAcq"
5827 %}
5828
5829 ins_encode %{
5830 __ cmpxchg(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int64,
5831 /*acquire*/ Assembler::aq, /*release*/ Assembler::rl, $res$$Register);
5832 %}
5833
5834 ins_pipe(pipe_slow);
5835 %}
5836
5837 instruct compareAndExchangeNAcq(iRegNNoSp res, indirect mem, iRegN oldval, iRegN newval)
5838 %{
5839 predicate(needs_acquiring_load_reserved(n) && n->as_LoadStore()->barrier_data() == 0);
5840
5841 match(Set res (CompareAndExchangeN mem (Binary oldval newval)));
5842
5843 ins_cost(2 * VOLATILE_REF_COST);
5844
5845 format %{
5846 "cmpxchg_acq $res = $mem, $oldval, $newval\t# (narrow oop, weak) if $mem == $oldval then $mem <-- $newval, #@compareAndExchangeNAcq"
5847 %}
5848
5849 ins_encode %{
5850 __ cmpxchg(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::uint32,
5851 /*acquire*/ Assembler::aq, /*release*/ Assembler::rl, $res$$Register);
5852 %}
5853
5854 ins_pipe(pipe_slow);
5855 %}
5856
5857 instruct compareAndExchangePAcq(iRegPNoSp res, indirect mem, iRegP oldval, iRegP newval)
5858 %{
5859 predicate(needs_acquiring_load_reserved(n) && (n->as_LoadStore()->barrier_data() == 0));
5860
5861 match(Set res (CompareAndExchangeP mem (Binary oldval newval)));
5862
5863 ins_cost(2 * VOLATILE_REF_COST);
5864
5865 format %{
5866 "cmpxchg_acq $res = $mem, $oldval, $newval\t# (ptr, weak) if $mem == $oldval then $mem <-- $newval, #@compareAndExchangePAcq"
5867 %}
5868
5869 ins_encode %{
5870 __ cmpxchg(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int64,
5871 /*acquire*/ Assembler::aq, /*release*/ Assembler::rl, $res$$Register);
5872 %}
5873
5874 ins_pipe(pipe_slow);
5875 %}
5876
5877 instruct weakCompareAndSwapB_narrow(iRegINoSp res, indirect mem, iRegI_R12 oldval, iRegI_R13 newval,
5878 iRegINoSp tmp1, iRegINoSp tmp2, iRegINoSp tmp3, rFlagsReg cr)
5879 %{
5880 predicate(!UseZabha || !UseZacas);
5881
5882 match(Set res (WeakCompareAndSwapB mem (Binary oldval newval)));
5883
5884 ins_cost(2 * VOLATILE_REF_COST);
5885
5886 effect(TEMP_DEF res, KILL cr, USE_KILL oldval, USE_KILL newval, TEMP tmp1, TEMP tmp2, TEMP tmp3);
5887
5888 format %{
5889 "weak_cmpxchg $mem, $oldval, $newval\t# (byte, weak) if $mem == $oldval then $mem <-- $newval\n\t"
5890 "# $res == 1 when success, #@weakCompareAndSwapB_narrow"
5891 %}
5892
5893 ins_encode %{
5894 __ weak_cmpxchg_narrow_value(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int8,
5895 /*acquire*/ Assembler::relaxed, /*release*/ Assembler::rl, $res$$Register,
5896 $tmp1$$Register, $tmp2$$Register, $tmp3$$Register);
5897 %}
5898
5899 ins_pipe(pipe_slow);
5900 %}
5901
5902 instruct weakCompareAndSwapB(iRegINoSp res, indirect mem, iRegI oldval, iRegI newval)
5903 %{
5904 predicate(UseZabha && UseZacas);
5905
5906 match(Set res (WeakCompareAndSwapB mem (Binary oldval newval)));
5907
5908 ins_cost(2 * VOLATILE_REF_COST);
5909
5910 format %{
5911 "weak_cmpxchg $mem, $oldval, $newval\t# (byte, weak) if $mem == $oldval then $mem <-- $newval\n\t"
5912 "# $res == 1 when success, #@weakCompareAndSwapB"
5913 %}
5914
5915 ins_encode %{
5916 __ weak_cmpxchg(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int8,
5917 /*acquire*/ Assembler::relaxed, /*release*/ Assembler::rl, $res$$Register);
5918 %}
5919
5920 ins_pipe(pipe_slow);
5921 %}
5922
5923 instruct weakCompareAndSwapS_narrow(iRegINoSp res, indirect mem, iRegI_R12 oldval, iRegI_R13 newval,
5924 iRegINoSp tmp1, iRegINoSp tmp2, iRegINoSp tmp3, rFlagsReg cr)
5925 %{
5926 predicate(!UseZabha || !UseZacas);
5927
5928 match(Set res (WeakCompareAndSwapS mem (Binary oldval newval)));
5929
5930 ins_cost(2 * VOLATILE_REF_COST);
5931
5932 effect(TEMP_DEF res, KILL cr, USE_KILL oldval, USE_KILL newval, TEMP tmp1, TEMP tmp2, TEMP tmp3);
5933
5934 format %{
5935 "weak_cmpxchg $mem, $oldval, $newval\t# (short, weak) if $mem == $oldval then $mem <-- $newval\n\t"
5936 "# $res == 1 when success, #@weakCompareAndSwapS_narrow"
5937 %}
5938
5939 ins_encode %{
5940 __ weak_cmpxchg_narrow_value(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int16,
5941 /*acquire*/ Assembler::relaxed, /*release*/ Assembler::rl, $res$$Register,
5942 $tmp1$$Register, $tmp2$$Register, $tmp3$$Register);
5943 %}
5944
5945 ins_pipe(pipe_slow);
5946 %}
5947
5948 instruct weakCompareAndSwapS(iRegINoSp res, indirect mem, iRegI oldval, iRegI newval)
5949 %{
5950 predicate(UseZabha && UseZacas);
5951
5952 match(Set res (WeakCompareAndSwapS mem (Binary oldval newval)));
5953
5954 ins_cost(2 * VOLATILE_REF_COST);
5955
5956 format %{
5957 "weak_cmpxchg $mem, $oldval, $newval\t# (short, weak) if $mem == $oldval then $mem <-- $newval\n\t"
5958 "# $res == 1 when success, #@weakCompareAndSwapS"
5959 %}
5960
5961 ins_encode %{
5962 __ weak_cmpxchg(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int16,
5963 /*acquire*/ Assembler::relaxed, /*release*/ Assembler::rl, $res$$Register);
5964 %}
5965
5966 ins_pipe(pipe_slow);
5967 %}
5968
5969 instruct weakCompareAndSwapI(iRegINoSp res, indirect mem, iRegI oldval, iRegI newval)
5970 %{
5971 match(Set res (WeakCompareAndSwapI mem (Binary oldval newval)));
5972
5973 ins_cost(2 * VOLATILE_REF_COST);
5974
5975 format %{
5976 "weak_cmpxchg $mem, $oldval, $newval\t# (int, weak) if $mem == $oldval then $mem <-- $newval\n\t"
5977 "# $res == 1 when success, #@weakCompareAndSwapI"
5978 %}
5979
5980 ins_encode %{
5981 __ weak_cmpxchg(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int32,
5982 /*acquire*/ Assembler::relaxed, /*release*/ Assembler::rl, $res$$Register);
5983 %}
5984
5985 ins_pipe(pipe_slow);
5986 %}
5987
5988 instruct weakCompareAndSwapL(iRegINoSp res, indirect mem, iRegL oldval, iRegL newval)
5989 %{
5990 match(Set res (WeakCompareAndSwapL mem (Binary oldval newval)));
5991
5992 ins_cost(2 * VOLATILE_REF_COST);
5993
5994 format %{
5995 "weak_cmpxchg $mem, $oldval, $newval\t# (long, weak) if $mem == $oldval then $mem <-- $newval\n\t"
5996 "# $res == 1 when success, #@weakCompareAndSwapL"
5997 %}
5998
5999 ins_encode %{
6000 __ weak_cmpxchg(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int64,
6001 /*acquire*/ Assembler::relaxed, /*release*/ Assembler::rl, $res$$Register);
6002 %}
6003
6004 ins_pipe(pipe_slow);
6005 %}
6006
6007 instruct weakCompareAndSwapN(iRegINoSp res, indirect mem, iRegN oldval, iRegN newval)
6008 %{
6009 predicate(n->as_LoadStore()->barrier_data() == 0);
6010
6011 match(Set res (WeakCompareAndSwapN mem (Binary oldval newval)));
6012
6013 ins_cost(2 * VOLATILE_REF_COST);
6014
6015 format %{
6016 "weak_cmpxchg $mem, $oldval, $newval\t# (narrow oop, weak) if $mem == $oldval then $mem <-- $newval\n\t"
6017 "# $res == 1 when success, #@weakCompareAndSwapN"
6018 %}
6019
6020 ins_encode %{
6021 __ weak_cmpxchg(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::uint32,
6022 /*acquire*/ Assembler::relaxed, /*release*/ Assembler::rl, $res$$Register);
6023 %}
6024
6025 ins_pipe(pipe_slow);
6026 %}
6027
6028 instruct weakCompareAndSwapP(iRegINoSp res, indirect mem, iRegP oldval, iRegP newval)
6029 %{
6030 predicate(n->as_LoadStore()->barrier_data() == 0);
6031
6032 match(Set res (WeakCompareAndSwapP mem (Binary oldval newval)));
6033
6034 ins_cost(2 * VOLATILE_REF_COST);
6035
6036 format %{
6037 "weak_cmpxchg $mem, $oldval, $newval\t# (ptr, weak) if $mem == $oldval then $mem <-- $newval\n\t"
6038 "# $res == 1 when success, #@weakCompareAndSwapP"
6039 %}
6040
6041 ins_encode %{
6042 __ weak_cmpxchg(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int64,
6043 /*acquire*/ Assembler::relaxed, /*release*/ Assembler::rl, $res$$Register);
6044 %}
6045
6046 ins_pipe(pipe_slow);
6047 %}
6048
6049 instruct weakCompareAndSwapBAcq_narrow(iRegINoSp res, indirect mem, iRegI_R12 oldval, iRegI_R13 newval,
6050 iRegINoSp tmp1, iRegINoSp tmp2, iRegINoSp tmp3, rFlagsReg cr)
6051 %{
6052 predicate((!UseZabha || !UseZacas) && needs_acquiring_load_reserved(n));
6053
6054 match(Set res (WeakCompareAndSwapB mem (Binary oldval newval)));
6055
6056 ins_cost(2 * VOLATILE_REF_COST);
6057
6058 effect(TEMP_DEF res, KILL cr, USE_KILL oldval, USE_KILL newval, TEMP tmp1, TEMP tmp2, TEMP tmp3);
6059
6060 format %{
6061 "weak_cmpxchg_acq $mem, $oldval, $newval\t# (byte, weak) if $mem == $oldval then $mem <-- $newval\n\t"
6062 "# $res == 1 when success, #@weakCompareAndSwapBAcq_narrow"
6063 %}
6064
6065 ins_encode %{
6066 __ weak_cmpxchg_narrow_value(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int8,
6067 /*acquire*/ Assembler::aq, /*release*/ Assembler::rl, $res$$Register,
6068 $tmp1$$Register, $tmp2$$Register, $tmp3$$Register);
6069 %}
6070
6071 ins_pipe(pipe_slow);
6072 %}
6073
6074 instruct weakCompareAndSwapBAcq(iRegINoSp res, indirect mem, iRegI oldval, iRegI newval)
6075 %{
6076 predicate((UseZabha && UseZacas) && needs_acquiring_load_reserved(n));
6077
6078 match(Set res (WeakCompareAndSwapB mem (Binary oldval newval)));
6079
6080 ins_cost(2 * VOLATILE_REF_COST);
6081
6082 format %{
6083 "weak_cmpxchg_acq $mem, $oldval, $newval\t# (byte, weak) if $mem == $oldval then $mem <-- $newval\n\t"
6084 "# $res == 1 when success, #@weakCompareAndSwapBAcq"
6085 %}
6086
6087 ins_encode %{
6088 __ weak_cmpxchg(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int8,
6089 /*acquire*/ Assembler::aq, /*release*/ Assembler::rl, $res$$Register);
6090 %}
6091
6092 ins_pipe(pipe_slow);
6093 %}
6094
6095 instruct weakCompareAndSwapSAcq_narrow(iRegINoSp res, indirect mem, iRegI_R12 oldval, iRegI_R13 newval,
6096 iRegINoSp tmp1, iRegINoSp tmp2, iRegINoSp tmp3, rFlagsReg cr)
6097 %{
6098 predicate((!UseZabha || !UseZacas) && needs_acquiring_load_reserved(n));
6099
6100 match(Set res (WeakCompareAndSwapS mem (Binary oldval newval)));
6101
6102 ins_cost(2 * VOLATILE_REF_COST);
6103
6104 effect(TEMP_DEF res, KILL cr, USE_KILL oldval, USE_KILL newval, TEMP tmp1, TEMP tmp2, TEMP tmp3);
6105
6106 format %{
6107 "weak_cmpxchg_acq $mem, $oldval, $newval\t# (short, weak) if $mem == $oldval then $mem <-- $newval\n\t"
6108 "# $res == 1 when success, #@weakCompareAndSwapSAcq_narrow"
6109 %}
6110
6111 ins_encode %{
6112 __ weak_cmpxchg_narrow_value(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int16,
6113 /*acquire*/ Assembler::aq, /*release*/ Assembler::rl, $res$$Register,
6114 $tmp1$$Register, $tmp2$$Register, $tmp3$$Register);
6115 %}
6116
6117 ins_pipe(pipe_slow);
6118 %}
6119
6120 instruct weakCompareAndSwapSAcq(iRegINoSp res, indirect mem, iRegI oldval, iRegI newval)
6121 %{
6122 predicate((UseZabha && UseZacas) && needs_acquiring_load_reserved(n));
6123
6124 match(Set res (WeakCompareAndSwapS mem (Binary oldval newval)));
6125
6126 ins_cost(2 * VOLATILE_REF_COST);
6127
6128 format %{
6129 "weak_cmpxchg_acq $mem, $oldval, $newval\t# (short, weak) if $mem == $oldval then $mem <-- $newval\n\t"
6130 "# $res == 1 when success, #@weakCompareAndSwapSAcq"
6131 %}
6132
6133 ins_encode %{
6134 __ weak_cmpxchg(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int16,
6135 /*acquire*/ Assembler::aq, /*release*/ Assembler::rl, $res$$Register);
6136 %}
6137
6138 ins_pipe(pipe_slow);
6139 %}
6140
6141 instruct weakCompareAndSwapIAcq(iRegINoSp res, indirect mem, iRegI oldval, iRegI newval)
6142 %{
6143 predicate(needs_acquiring_load_reserved(n));
6144
6145 match(Set res (WeakCompareAndSwapI mem (Binary oldval newval)));
6146
6147 ins_cost(2 * VOLATILE_REF_COST);
6148
6149 format %{
6150 "weak_cmpxchg_acq $mem, $oldval, $newval\t# (int, weak) if $mem == $oldval then $mem <-- $newval\n\t"
6151 "# $res == 1 when success, #@weakCompareAndSwapIAcq"
6152 %}
6153
6154 ins_encode %{
6155 __ weak_cmpxchg(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int32,
6156 /*acquire*/ Assembler::aq, /*release*/ Assembler::rl, $res$$Register);
6157 %}
6158
6159 ins_pipe(pipe_slow);
6160 %}
6161
6162 instruct weakCompareAndSwapLAcq(iRegINoSp res, indirect mem, iRegL oldval, iRegL newval)
6163 %{
6164 predicate(needs_acquiring_load_reserved(n));
6165
6166 match(Set res (WeakCompareAndSwapL mem (Binary oldval newval)));
6167
6168 ins_cost(2 * VOLATILE_REF_COST);
6169
6170 format %{
6171 "weak_cmpxchg_acq $mem, $oldval, $newval\t# (long, weak) if $mem == $oldval then $mem <-- $newval\n\t"
6172 "# $res == 1 when success, #@weakCompareAndSwapLAcq"
6173 %}
6174
6175 ins_encode %{
6176 __ weak_cmpxchg(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int64,
6177 /*acquire*/ Assembler::aq, /*release*/ Assembler::rl, $res$$Register);
6178 %}
6179
6180 ins_pipe(pipe_slow);
6181 %}
6182
6183 instruct weakCompareAndSwapNAcq(iRegINoSp res, indirect mem, iRegN oldval, iRegN newval)
6184 %{
6185 predicate(needs_acquiring_load_reserved(n) && n->as_LoadStore()->barrier_data() == 0);
6186
6187 match(Set res (WeakCompareAndSwapN mem (Binary oldval newval)));
6188
6189 ins_cost(2 * VOLATILE_REF_COST);
6190
6191 format %{
6192 "weak_cmpxchg_acq $mem, $oldval, $newval\t# (narrow oop, weak) if $mem == $oldval then $mem <-- $newval\n\t"
6193 "# $res == 1 when success, #@weakCompareAndSwapNAcq"
6194 %}
6195
6196 ins_encode %{
6197 __ weak_cmpxchg(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::uint32,
6198 /*acquire*/ Assembler::aq, /*release*/ Assembler::rl, $res$$Register);
6199 %}
6200
6201 ins_pipe(pipe_slow);
6202 %}
6203
6204 instruct weakCompareAndSwapPAcq(iRegINoSp res, indirect mem, iRegP oldval, iRegP newval)
6205 %{
6206 predicate(needs_acquiring_load_reserved(n) && (n->as_LoadStore()->barrier_data() == 0));
6207
6208 match(Set res (WeakCompareAndSwapP mem (Binary oldval newval)));
6209
6210 ins_cost(2 * VOLATILE_REF_COST);
6211
6212 format %{
6213 "weak_cmpxchg_acq $mem, $oldval, $newval\t# (ptr, weak) if $mem == $oldval then $mem <-- $newval\n\t"
6214 "\t# $res == 1 when success, #@weakCompareAndSwapPAcq"
6215 %}
6216
6217 ins_encode %{
6218 __ weak_cmpxchg(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int64,
6219 /*acquire*/ Assembler::aq, /*release*/ Assembler::rl, $res$$Register);
6220 %}
6221
6222 ins_pipe(pipe_slow);
6223 %}
6224
6225 instruct get_and_setI(indirect mem, iRegI newv, iRegINoSp prev)
6226 %{
6227 match(Set prev (GetAndSetI mem newv));
6228
6229 ins_cost(ALU_COST);
6230
6231 format %{ "atomic_xchgw $prev, $newv, [$mem]\t#@get_and_setI" %}
6232
6233 ins_encode %{
6234 __ atomic_xchgw($prev$$Register, $newv$$Register, as_Register($mem$$base));
6235 %}
6236
6237 ins_pipe(pipe_serial);
6238 %}
6239
6240 instruct get_and_setL(indirect mem, iRegL newv, iRegLNoSp prev)
6241 %{
6242 match(Set prev (GetAndSetL mem newv));
6243
6244 ins_cost(ALU_COST);
6245
6246 format %{ "atomic_xchg $prev, $newv, [$mem]\t#@get_and_setL" %}
6247
6248 ins_encode %{
6249 __ atomic_xchg($prev$$Register, $newv$$Register, as_Register($mem$$base));
6250 %}
6251
6252 ins_pipe(pipe_serial);
6253 %}
6254
6255 instruct get_and_setN(indirect mem, iRegN newv, iRegINoSp prev)
6256 %{
6257 predicate(n->as_LoadStore()->barrier_data() == 0);
6258
6259 match(Set prev (GetAndSetN mem newv));
6260
6261 ins_cost(ALU_COST);
6262
6263 format %{ "atomic_xchgwu $prev, $newv, [$mem]\t#@get_and_setN" %}
6264
6265 ins_encode %{
6266 __ atomic_xchgwu($prev$$Register, $newv$$Register, as_Register($mem$$base));
6267 %}
6268
6269 ins_pipe(pipe_serial);
6270 %}
6271
6272 instruct get_and_setP(indirect mem, iRegP newv, iRegPNoSp prev)
6273 %{
6274 predicate(n->as_LoadStore()->barrier_data() == 0);
6275 match(Set prev (GetAndSetP mem newv));
6276
6277 ins_cost(ALU_COST);
6278
6279 format %{ "atomic_xchg $prev, $newv, [$mem]\t#@get_and_setP" %}
6280
6281 ins_encode %{
6282 __ atomic_xchg($prev$$Register, $newv$$Register, as_Register($mem$$base));
6283 %}
6284
6285 ins_pipe(pipe_serial);
6286 %}
6287
6288 instruct get_and_setIAcq(indirect mem, iRegI newv, iRegINoSp prev)
6289 %{
6290 predicate(needs_acquiring_load_reserved(n));
6291
6292 match(Set prev (GetAndSetI mem newv));
6293
6294 ins_cost(ALU_COST);
6295
6296 format %{ "atomic_xchgw_acq $prev, $newv, [$mem]\t#@get_and_setIAcq" %}
6297
6298 ins_encode %{
6299 __ atomic_xchgalw($prev$$Register, $newv$$Register, as_Register($mem$$base));
6300 %}
6301
6302 ins_pipe(pipe_serial);
6303 %}
6304
6305 instruct get_and_setLAcq(indirect mem, iRegL newv, iRegLNoSp prev)
6306 %{
6307 predicate(needs_acquiring_load_reserved(n));
6308
6309 match(Set prev (GetAndSetL mem newv));
6310
6311 ins_cost(ALU_COST);
6312
6313 format %{ "atomic_xchg_acq $prev, $newv, [$mem]\t#@get_and_setLAcq" %}
6314
6315 ins_encode %{
6316 __ atomic_xchgal($prev$$Register, $newv$$Register, as_Register($mem$$base));
6317 %}
6318
6319 ins_pipe(pipe_serial);
6320 %}
6321
6322 instruct get_and_setNAcq(indirect mem, iRegN newv, iRegINoSp prev)
6323 %{
6324 predicate(needs_acquiring_load_reserved(n) && n->as_LoadStore()->barrier_data() == 0);
6325
6326 match(Set prev (GetAndSetN mem newv));
6327
6328 ins_cost(ALU_COST);
6329
6330 format %{ "atomic_xchgwu_acq $prev, $newv, [$mem]\t#@get_and_setNAcq" %}
6331
6332 ins_encode %{
6333 __ atomic_xchgalwu($prev$$Register, $newv$$Register, as_Register($mem$$base));
6334 %}
6335
6336 ins_pipe(pipe_serial);
6337 %}
6338
6339 instruct get_and_setPAcq(indirect mem, iRegP newv, iRegPNoSp prev)
6340 %{
6341 predicate(needs_acquiring_load_reserved(n) && (n->as_LoadStore()->barrier_data() == 0));
6342
6343 match(Set prev (GetAndSetP mem newv));
6344
6345 ins_cost(ALU_COST);
6346
6347 format %{ "atomic_xchg_acq $prev, $newv, [$mem]\t#@get_and_setPAcq" %}
6348
6349 ins_encode %{
6350 __ atomic_xchgal($prev$$Register, $newv$$Register, as_Register($mem$$base));
6351 %}
6352
6353 ins_pipe(pipe_serial);
6354 %}
6355
6356 instruct get_and_addL(indirect mem, iRegLNoSp newval, iRegL incr)
6357 %{
6358 match(Set newval (GetAndAddL mem incr));
6359
6360 ins_cost(ALU_COST);
6361
6362 format %{ "get_and_addL $newval, [$mem], $incr\t#@get_and_addL" %}
6363
6364 ins_encode %{
6365 __ atomic_add($newval$$Register, $incr$$Register, as_Register($mem$$base));
6366 %}
6367
6368 ins_pipe(pipe_serial);
6369 %}
6370
6371 instruct get_and_addL_no_res(indirect mem, Universe dummy, iRegL incr)
6372 %{
6373 predicate(n->as_LoadStore()->result_not_used());
6374
6375 match(Set dummy (GetAndAddL mem incr));
6376
6377 ins_cost(ALU_COST);
6378
6379 format %{ "get_and_addL [$mem], $incr\t#@get_and_addL_no_res" %}
6380
6381 ins_encode %{
6382 __ atomic_add(noreg, $incr$$Register, as_Register($mem$$base));
6383 %}
6384
6385 ins_pipe(pipe_serial);
6386 %}
6387
6388 instruct get_and_addLi(indirect mem, iRegLNoSp newval, immLAdd incr)
6389 %{
6390 match(Set newval (GetAndAddL mem incr));
6391
6392 ins_cost(ALU_COST);
6393
6394 format %{ "get_and_addL $newval, [$mem], $incr\t#@get_and_addLi" %}
6395
6396 ins_encode %{
6397 __ atomic_add($newval$$Register, $incr$$constant, as_Register($mem$$base));
6398 %}
6399
6400 ins_pipe(pipe_serial);
6401 %}
6402
6403 instruct get_and_addLi_no_res(indirect mem, Universe dummy, immLAdd incr)
6404 %{
6405 predicate(n->as_LoadStore()->result_not_used());
6406
6407 match(Set dummy (GetAndAddL mem incr));
6408
6409 ins_cost(ALU_COST);
6410
6411 format %{ "get_and_addL [$mem], $incr\t#@get_and_addLi_no_res" %}
6412
6413 ins_encode %{
6414 __ atomic_add(noreg, $incr$$constant, as_Register($mem$$base));
6415 %}
6416
6417 ins_pipe(pipe_serial);
6418 %}
6419
6420 instruct get_and_addI(indirect mem, iRegINoSp newval, iRegIorL2I incr)
6421 %{
6422 match(Set newval (GetAndAddI mem incr));
6423
6424 ins_cost(ALU_COST);
6425
6426 format %{ "get_and_addI $newval, [$mem], $incr\t#@get_and_addI" %}
6427
6428 ins_encode %{
6429 __ atomic_addw($newval$$Register, $incr$$Register, as_Register($mem$$base));
6430 %}
6431
6432 ins_pipe(pipe_serial);
6433 %}
6434
6435 instruct get_and_addI_no_res(indirect mem, Universe dummy, iRegIorL2I incr)
6436 %{
6437 predicate(n->as_LoadStore()->result_not_used());
6438
6439 match(Set dummy (GetAndAddI mem incr));
6440
6441 ins_cost(ALU_COST);
6442
6443 format %{ "get_and_addI [$mem], $incr\t#@get_and_addI_no_res" %}
6444
6445 ins_encode %{
6446 __ atomic_addw(noreg, $incr$$Register, as_Register($mem$$base));
6447 %}
6448
6449 ins_pipe(pipe_serial);
6450 %}
6451
6452 instruct get_and_addIi(indirect mem, iRegINoSp newval, immIAdd incr)
6453 %{
6454 match(Set newval (GetAndAddI mem incr));
6455
6456 ins_cost(ALU_COST);
6457
6458 format %{ "get_and_addI $newval, [$mem], $incr\t#@get_and_addIi" %}
6459
6460 ins_encode %{
6461 __ atomic_addw($newval$$Register, $incr$$constant, as_Register($mem$$base));
6462 %}
6463
6464 ins_pipe(pipe_serial);
6465 %}
6466
6467 instruct get_and_addIi_no_res(indirect mem, Universe dummy, immIAdd incr)
6468 %{
6469 predicate(n->as_LoadStore()->result_not_used());
6470
6471 match(Set dummy (GetAndAddI mem incr));
6472
6473 ins_cost(ALU_COST);
6474
6475 format %{ "get_and_addI [$mem], $incr\t#@get_and_addIi_no_res" %}
6476
6477 ins_encode %{
6478 __ atomic_addw(noreg, $incr$$constant, as_Register($mem$$base));
6479 %}
6480
6481 ins_pipe(pipe_serial);
6482 %}
6483
6484 instruct get_and_addLAcq(indirect mem, iRegLNoSp newval, iRegL incr)
6485 %{
6486 predicate(needs_acquiring_load_reserved(n));
6487
6488 match(Set newval (GetAndAddL mem incr));
6489
6490 ins_cost(ALU_COST);
6491
6492 format %{ "get_and_addL_acq $newval, [$mem], $incr\t#@get_and_addLAcq" %}
6493
6494 ins_encode %{
6495 __ atomic_addal($newval$$Register, $incr$$Register, as_Register($mem$$base));
6496 %}
6497
6498 ins_pipe(pipe_serial);
6499 %}
6500
6501 instruct get_and_addL_no_resAcq(indirect mem, Universe dummy, iRegL incr) %{
6502 predicate(n->as_LoadStore()->result_not_used() && needs_acquiring_load_reserved(n));
6503
6504 match(Set dummy (GetAndAddL mem incr));
6505
6506 ins_cost(ALU_COST);
6507
6508 format %{ "get_and_addL_acq [$mem], $incr\t#@get_and_addL_no_resAcq" %}
6509
6510 ins_encode %{
6511 __ atomic_addal(noreg, $incr$$Register, as_Register($mem$$base));
6512 %}
6513
6514 ins_pipe(pipe_serial);
6515 %}
6516
6517 instruct get_and_addLiAcq(indirect mem, iRegLNoSp newval, immLAdd incr)
6518 %{
6519 predicate(needs_acquiring_load_reserved(n));
6520
6521 match(Set newval (GetAndAddL mem incr));
6522
6523 ins_cost(ALU_COST);
6524
6525 format %{ "get_and_addL_acq $newval, [$mem], $incr\t#@get_and_addLiAcq" %}
6526
6527 ins_encode %{
6528 __ atomic_addal($newval$$Register, $incr$$constant, as_Register($mem$$base));
6529 %}
6530
6531 ins_pipe(pipe_serial);
6532 %}
6533
6534 instruct get_and_addLi_no_resAcq(indirect mem, Universe dummy, immLAdd incr)
6535 %{
6536 predicate(n->as_LoadStore()->result_not_used() && needs_acquiring_load_reserved(n));
6537
6538 match(Set dummy (GetAndAddL mem incr));
6539
6540 ins_cost(ALU_COST);
6541
6542 format %{ "get_and_addL_acq [$mem], $incr\t#@get_and_addLi_no_resAcq" %}
6543
6544 ins_encode %{
6545 __ atomic_addal(noreg, $incr$$constant, as_Register($mem$$base));
6546 %}
6547
6548 ins_pipe(pipe_serial);
6549 %}
6550
6551 instruct get_and_addIAcq(indirect mem, iRegINoSp newval, iRegIorL2I incr)
6552 %{
6553 predicate(needs_acquiring_load_reserved(n));
6554
6555 match(Set newval (GetAndAddI mem incr));
6556
6557 ins_cost(ALU_COST);
6558
6559 format %{ "get_and_addI_acq $newval, [$mem], $incr\t#@get_and_addIAcq" %}
6560
6561 ins_encode %{
6562 __ atomic_addalw($newval$$Register, $incr$$Register, as_Register($mem$$base));
6563 %}
6564
6565 ins_pipe(pipe_serial);
6566 %}
6567
6568 instruct get_and_addI_no_resAcq(indirect mem, Universe dummy, iRegIorL2I incr)
6569 %{
6570 predicate(n->as_LoadStore()->result_not_used() && needs_acquiring_load_reserved(n));
6571
6572 match(Set dummy (GetAndAddI mem incr));
6573
6574 ins_cost(ALU_COST);
6575
6576 format %{ "get_and_addI_acq [$mem], $incr\t#@get_and_addI_no_resAcq" %}
6577
6578 ins_encode %{
6579 __ atomic_addalw(noreg, $incr$$Register, as_Register($mem$$base));
6580 %}
6581
6582 ins_pipe(pipe_serial);
6583 %}
6584
6585 instruct get_and_addIiAcq(indirect mem, iRegINoSp newval, immIAdd incr)
6586 %{
6587 predicate(needs_acquiring_load_reserved(n));
6588
6589 match(Set newval (GetAndAddI mem incr));
6590
6591 ins_cost(ALU_COST);
6592
6593 format %{ "get_and_addI_acq $newval, [$mem], $incr\t#@get_and_addIiAcq" %}
6594
6595 ins_encode %{
6596 __ atomic_addalw($newval$$Register, $incr$$constant, as_Register($mem$$base));
6597 %}
6598
6599 ins_pipe(pipe_serial);
6600 %}
6601
6602 instruct get_and_addIi_no_resAcq(indirect mem, Universe dummy, immIAdd incr)
6603 %{
6604 predicate(n->as_LoadStore()->result_not_used() && needs_acquiring_load_reserved(n));
6605
6606 match(Set dummy (GetAndAddI mem incr));
6607
6608 ins_cost(ALU_COST);
6609
6610 format %{ "get_and_addI_acq [$mem], $incr\t#@get_and_addIi_no_resAcq" %}
6611
6612 ins_encode %{
6613 __ atomic_addalw(noreg, $incr$$constant, as_Register($mem$$base));
6614 %}
6615
6616 ins_pipe(pipe_serial);
6617 %}
6618
6619 // ============================================================================
6620 // Arithmetic Instructions
6621 //
6622
6623 // Integer Addition
6624
6625 // TODO
6626 // these currently employ operations which do not set CR and hence are
6627 // not flagged as killing CR but we would like to isolate the cases
6628 // where we want to set flags from those where we don't. need to work
6629 // out how to do that.
6630 instruct addI_reg_reg(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2) %{
6631 match(Set dst (AddI src1 src2));
6632
6633 ins_cost(ALU_COST);
6634 format %{ "addw $dst, $src1, $src2\t#@addI_reg_reg" %}
6635
6636 ins_encode %{
6637 __ addw(as_Register($dst$$reg),
6638 as_Register($src1$$reg),
6639 as_Register($src2$$reg));
6640 %}
6641
6642 ins_pipe(ialu_reg_reg);
6643 %}
6644
6645 instruct addI_reg_imm(iRegINoSp dst, iRegIorL2I src1, immIAdd src2) %{
6646 match(Set dst (AddI src1 src2));
6647
6648 ins_cost(ALU_COST);
6649 format %{ "addiw $dst, $src1, $src2\t#@addI_reg_imm" %}
6650
6651 ins_encode %{
6652 __ addiw(as_Register($dst$$reg),
6653 as_Register($src1$$reg),
6654 $src2$$constant);
6655 %}
6656
6657 ins_pipe(ialu_reg_imm);
6658 %}
6659
6660 instruct addI_reg_imm_l2i(iRegINoSp dst, iRegL src1, immIAdd src2) %{
6661 match(Set dst (AddI (ConvL2I src1) src2));
6662
6663 ins_cost(ALU_COST);
6664 format %{ "addiw $dst, $src1, $src2\t#@addI_reg_imm_l2i" %}
6665
6666 ins_encode %{
6667 __ addiw(as_Register($dst$$reg),
6668 as_Register($src1$$reg),
6669 $src2$$constant);
6670 %}
6671
6672 ins_pipe(ialu_reg_imm);
6673 %}
6674
6675 // Pointer Addition
6676 instruct addP_reg_reg(iRegPNoSp dst, iRegP src1, iRegL src2) %{
6677 match(Set dst (AddP src1 src2));
6678
6679 ins_cost(ALU_COST);
6680 format %{ "add $dst, $src1, $src2\t# ptr, #@addP_reg_reg" %}
6681
6682 ins_encode %{
6683 __ add(as_Register($dst$$reg),
6684 as_Register($src1$$reg),
6685 as_Register($src2$$reg));
6686 %}
6687
6688 ins_pipe(ialu_reg_reg);
6689 %}
6690
6691 // If we shift more than 32 bits, we need not convert I2L.
6692 instruct lShiftL_regI_immGE32(iRegLNoSp dst, iRegI src, uimmI6_ge32 scale) %{
6693 match(Set dst (LShiftL (ConvI2L src) scale));
6694 ins_cost(ALU_COST);
6695 format %{ "slli $dst, $src, $scale & 63\t#@lShiftL_regI_immGE32" %}
6696
6697 ins_encode %{
6698 __ slli(as_Register($dst$$reg), as_Register($src$$reg), $scale$$constant & 63);
6699 %}
6700
6701 ins_pipe(ialu_reg_shift);
6702 %}
6703
6704 // Pointer Immediate Addition
6705 // n.b. this needs to be more expensive than using an indirect memory
6706 // operand
6707 instruct addP_reg_imm(iRegPNoSp dst, iRegP src1, immLAdd src2) %{
6708 match(Set dst (AddP src1 src2));
6709 ins_cost(ALU_COST);
6710 format %{ "addi $dst, $src1, $src2\t# ptr, #@addP_reg_imm" %}
6711
6712 ins_encode %{
6713 __ addi(as_Register($dst$$reg),
6714 as_Register($src1$$reg),
6715 $src2$$constant);
6716 %}
6717
6718 ins_pipe(ialu_reg_imm);
6719 %}
6720
6721 // Long Addition
6722 instruct addL_reg_reg(iRegLNoSp dst, iRegL src1, iRegL src2) %{
6723 match(Set dst (AddL src1 src2));
6724 ins_cost(ALU_COST);
6725 format %{ "add $dst, $src1, $src2\t#@addL_reg_reg" %}
6726
6727 ins_encode %{
6728 __ add(as_Register($dst$$reg),
6729 as_Register($src1$$reg),
6730 as_Register($src2$$reg));
6731 %}
6732
6733 ins_pipe(ialu_reg_reg);
6734 %}
6735
6736 // No constant pool entries requiredLong Immediate Addition.
6737 instruct addL_reg_imm(iRegLNoSp dst, iRegL src1, immLAdd src2) %{
6738 match(Set dst (AddL src1 src2));
6739 ins_cost(ALU_COST);
6740 format %{ "addi $dst, $src1, $src2\t#@addL_reg_imm" %}
6741
6742 ins_encode %{
6743 // src2 is imm, so actually call the addi
6744 __ addi(as_Register($dst$$reg),
6745 as_Register($src1$$reg),
6746 $src2$$constant);
6747 %}
6748
6749 ins_pipe(ialu_reg_imm);
6750 %}
6751
6752 // Integer Subtraction
6753 instruct subI_reg_reg(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2) %{
6754 match(Set dst (SubI src1 src2));
6755
6756 ins_cost(ALU_COST);
6757 format %{ "subw $dst, $src1, $src2\t#@subI_reg_reg" %}
6758
6759 ins_encode %{
6760 __ subw(as_Register($dst$$reg),
6761 as_Register($src1$$reg),
6762 as_Register($src2$$reg));
6763 %}
6764
6765 ins_pipe(ialu_reg_reg);
6766 %}
6767
6768 // Immediate Subtraction
6769 instruct subI_reg_imm(iRegINoSp dst, iRegIorL2I src1, immISub src2) %{
6770 match(Set dst (SubI src1 src2));
6771
6772 ins_cost(ALU_COST);
6773 format %{ "addiw $dst, $src1, -$src2\t#@subI_reg_imm" %}
6774
6775 ins_encode %{
6776 // src2 is imm, so actually call the addiw
6777 __ subiw(as_Register($dst$$reg),
6778 as_Register($src1$$reg),
6779 $src2$$constant);
6780 %}
6781
6782 ins_pipe(ialu_reg_imm);
6783 %}
6784
6785 // Long Subtraction
6786 instruct subL_reg_reg(iRegLNoSp dst, iRegL src1, iRegL src2) %{
6787 match(Set dst (SubL src1 src2));
6788 ins_cost(ALU_COST);
6789 format %{ "sub $dst, $src1, $src2\t#@subL_reg_reg" %}
6790
6791 ins_encode %{
6792 __ sub(as_Register($dst$$reg),
6793 as_Register($src1$$reg),
6794 as_Register($src2$$reg));
6795 %}
6796
6797 ins_pipe(ialu_reg_reg);
6798 %}
6799
6800 // No constant pool entries requiredLong Immediate Subtraction.
6801 instruct subL_reg_imm(iRegLNoSp dst, iRegL src1, immLSub src2) %{
6802 match(Set dst (SubL src1 src2));
6803 ins_cost(ALU_COST);
6804 format %{ "addi $dst, $src1, -$src2\t#@subL_reg_imm" %}
6805
6806 ins_encode %{
6807 // src2 is imm, so actually call the addi
6808 __ subi(as_Register($dst$$reg),
6809 as_Register($src1$$reg),
6810 $src2$$constant);
6811 %}
6812
6813 ins_pipe(ialu_reg_imm);
6814 %}
6815
6816 // Integer Negation (special case for sub)
6817
6818 instruct negI_reg(iRegINoSp dst, iRegIorL2I src, immI0 zero) %{
6819 match(Set dst (SubI zero src));
6820 ins_cost(ALU_COST);
6821 format %{ "subw $dst, x0, $src\t# int, #@negI_reg" %}
6822
6823 ins_encode %{
6824 // actually call the subw
6825 __ negw(as_Register($dst$$reg),
6826 as_Register($src$$reg));
6827 %}
6828
6829 ins_pipe(ialu_reg);
6830 %}
6831
6832 // Long Negation
6833
6834 instruct negL_reg(iRegLNoSp dst, iRegL src, immL0 zero) %{
6835 match(Set dst (SubL zero src));
6836 ins_cost(ALU_COST);
6837 format %{ "sub $dst, x0, $src\t# long, #@negL_reg" %}
6838
6839 ins_encode %{
6840 // actually call the sub
6841 __ neg(as_Register($dst$$reg),
6842 as_Register($src$$reg));
6843 %}
6844
6845 ins_pipe(ialu_reg);
6846 %}
6847
6848 // Integer Multiply
6849
6850 instruct mulI(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2) %{
6851 match(Set dst (MulI src1 src2));
6852 ins_cost(IMUL_COST);
6853 format %{ "mulw $dst, $src1, $src2\t#@mulI" %}
6854
6855 //this means 2 word multi, and no sign extend to 64 bits
6856 ins_encode %{
6857 // riscv64 mulw will sign-extension to high 32 bits in dst reg
6858 __ mulw(as_Register($dst$$reg),
6859 as_Register($src1$$reg),
6860 as_Register($src2$$reg));
6861 %}
6862
6863 ins_pipe(imul_reg_reg);
6864 %}
6865
6866 // Long Multiply
6867
6868 instruct mulL(iRegLNoSp dst, iRegL src1, iRegL src2) %{
6869 match(Set dst (MulL src1 src2));
6870 ins_cost(IMUL_COST);
6871 format %{ "mul $dst, $src1, $src2\t#@mulL" %}
6872
6873 ins_encode %{
6874 __ mul(as_Register($dst$$reg),
6875 as_Register($src1$$reg),
6876 as_Register($src2$$reg));
6877 %}
6878
6879 ins_pipe(lmul_reg_reg);
6880 %}
6881
6882 instruct mulHiL_rReg(iRegLNoSp dst, iRegL src1, iRegL src2)
6883 %{
6884 match(Set dst (MulHiL src1 src2));
6885 ins_cost(IMUL_COST);
6886 format %{ "mulh $dst, $src1, $src2\t# mulhi, #@mulHiL_rReg" %}
6887
6888 ins_encode %{
6889 __ mulh(as_Register($dst$$reg),
6890 as_Register($src1$$reg),
6891 as_Register($src2$$reg));
6892 %}
6893
6894 ins_pipe(lmul_reg_reg);
6895 %}
6896
6897 instruct umulHiL_rReg(iRegLNoSp dst, iRegL src1, iRegL src2)
6898 %{
6899 match(Set dst (UMulHiL src1 src2));
6900 ins_cost(IMUL_COST);
6901 format %{ "mulhu $dst, $src1, $src2\t# umulhi, #@umulHiL_rReg" %}
6902
6903 ins_encode %{
6904 __ mulhu(as_Register($dst$$reg),
6905 as_Register($src1$$reg),
6906 as_Register($src2$$reg));
6907 %}
6908
6909 ins_pipe(lmul_reg_reg);
6910 %}
6911
6912 // Integer Divide
6913
6914 instruct divI(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2) %{
6915 match(Set dst (DivI src1 src2));
6916 ins_cost(IDIVSI_COST);
6917 format %{ "divw $dst, $src1, $src2\t#@divI"%}
6918
6919 ins_encode %{
6920 __ divw(as_Register($dst$$reg), as_Register($src1$$reg), as_Register($src2$$reg));
6921 %}
6922 ins_pipe(idiv_reg_reg);
6923 %}
6924
6925 instruct UdivI(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2) %{
6926 match(Set dst (UDivI src1 src2));
6927 ins_cost(IDIVSI_COST);
6928 format %{ "divuw $dst, $src1, $src2\t#@UdivI"%}
6929
6930 ins_encode %{
6931 __ divuw(as_Register($dst$$reg), as_Register($src1$$reg), as_Register($src2$$reg));
6932 %}
6933 ins_pipe(idiv_reg_reg);
6934 %}
6935
6936 instruct signExtract(iRegINoSp dst, iRegIorL2I src1, immI_31 div1, immI_31 div2) %{
6937 match(Set dst (URShiftI (RShiftI src1 div1) div2));
6938 ins_cost(ALU_COST);
6939 format %{ "srliw $dst, $src1, $div1\t# int signExtract, #@signExtract" %}
6940
6941 ins_encode %{
6942 __ srliw(as_Register($dst$$reg), as_Register($src1$$reg), 31);
6943 %}
6944 ins_pipe(ialu_reg_shift);
6945 %}
6946
6947 // Long Divide
6948
6949 instruct divL(iRegLNoSp dst, iRegL src1, iRegL src2) %{
6950 match(Set dst (DivL src1 src2));
6951 ins_cost(IDIVDI_COST);
6952 format %{ "div $dst, $src1, $src2\t#@divL" %}
6953
6954 ins_encode %{
6955 __ div(as_Register($dst$$reg), as_Register($src1$$reg), as_Register($src2$$reg));
6956 %}
6957 ins_pipe(ldiv_reg_reg);
6958 %}
6959
6960 instruct UdivL(iRegLNoSp dst, iRegL src1, iRegL src2) %{
6961 match(Set dst (UDivL src1 src2));
6962 ins_cost(IDIVDI_COST);
6963
6964 format %{ "divu $dst, $src1, $src2\t#@UdivL" %}
6965
6966 ins_encode %{
6967 __ divu(as_Register($dst$$reg), as_Register($src1$$reg), as_Register($src2$$reg));
6968 %}
6969 ins_pipe(ldiv_reg_reg);
6970 %}
6971
6972 instruct signExtractL(iRegLNoSp dst, iRegL src1, immI_63 div1, immI_63 div2) %{
6973 match(Set dst (URShiftL (RShiftL src1 div1) div2));
6974 ins_cost(ALU_COST);
6975 format %{ "srli $dst, $src1, $div1\t# long signExtract, #@signExtractL" %}
6976
6977 ins_encode %{
6978 __ srli(as_Register($dst$$reg), as_Register($src1$$reg), 63);
6979 %}
6980 ins_pipe(ialu_reg_shift);
6981 %}
6982
6983 // Integer Remainder
6984
6985 instruct modI(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2) %{
6986 match(Set dst (ModI src1 src2));
6987 ins_cost(IDIVSI_COST);
6988 format %{ "remw $dst, $src1, $src2\t#@modI" %}
6989
6990 ins_encode %{
6991 __ remw(as_Register($dst$$reg), as_Register($src1$$reg), as_Register($src2$$reg));
6992 %}
6993 ins_pipe(ialu_reg_reg);
6994 %}
6995
6996 instruct UmodI(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2) %{
6997 match(Set dst (UModI src1 src2));
6998 ins_cost(IDIVSI_COST);
6999 format %{ "remuw $dst, $src1, $src2\t#@UmodI" %}
7000
7001 ins_encode %{
7002 __ remuw(as_Register($dst$$reg), as_Register($src1$$reg), as_Register($src2$$reg));
7003 %}
7004 ins_pipe(ialu_reg_reg);
7005 %}
7006
7007 // Long Remainder
7008
7009 instruct modL(iRegLNoSp dst, iRegL src1, iRegL src2) %{
7010 match(Set dst (ModL src1 src2));
7011 ins_cost(IDIVDI_COST);
7012 format %{ "rem $dst, $src1, $src2\t#@modL" %}
7013
7014 ins_encode %{
7015 __ rem(as_Register($dst$$reg), as_Register($src1$$reg), as_Register($src2$$reg));
7016 %}
7017 ins_pipe(ialu_reg_reg);
7018 %}
7019
7020 instruct UmodL(iRegLNoSp dst, iRegL src1, iRegL src2) %{
7021 match(Set dst (UModL src1 src2));
7022 ins_cost(IDIVDI_COST);
7023 format %{ "remu $dst, $src1, $src2\t#@UmodL" %}
7024
7025 ins_encode %{
7026 __ remu(as_Register($dst$$reg), as_Register($src1$$reg), as_Register($src2$$reg));
7027 %}
7028 ins_pipe(ialu_reg_reg);
7029 %}
7030
7031 // Integer Shifts
7032
7033 // Shift Left Register
7034 // Only the low 5 bits of src2 are considered for the shift amount, all other bits are ignored.
7035 instruct lShiftI_reg_reg(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2) %{
7036 match(Set dst (LShiftI src1 src2));
7037 ins_cost(ALU_COST);
7038 format %{ "sllw $dst, $src1, $src2\t#@lShiftI_reg_reg" %}
7039
7040 ins_encode %{
7041 __ sllw(as_Register($dst$$reg),
7042 as_Register($src1$$reg),
7043 as_Register($src2$$reg));
7044 %}
7045
7046 ins_pipe(ialu_reg_reg_vshift);
7047 %}
7048
7049 // Shift Left Immediate
7050 instruct lShiftI_reg_imm(iRegINoSp dst, iRegIorL2I src1, immI src2) %{
7051 match(Set dst (LShiftI src1 src2));
7052 ins_cost(ALU_COST);
7053 format %{ "slliw $dst, $src1, ($src2 & 0x1f)\t#@lShiftI_reg_imm" %}
7054
7055 ins_encode %{
7056 // the shift amount is encoded in the lower
7057 // 5 bits of the I-immediate field for RV32I
7058 __ slliw(as_Register($dst$$reg),
7059 as_Register($src1$$reg),
7060 (unsigned) $src2$$constant & 0x1f);
7061 %}
7062
7063 ins_pipe(ialu_reg_shift);
7064 %}
7065
7066 // Shift Right Logical Register
7067 // Only the low 5 bits of src2 are considered for the shift amount, all other bits are ignored.
7068 instruct urShiftI_reg_reg(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2) %{
7069 match(Set dst (URShiftI src1 src2));
7070 ins_cost(ALU_COST);
7071 format %{ "srlw $dst, $src1, $src2\t#@urShiftI_reg_reg" %}
7072
7073 ins_encode %{
7074 __ srlw(as_Register($dst$$reg),
7075 as_Register($src1$$reg),
7076 as_Register($src2$$reg));
7077 %}
7078
7079 ins_pipe(ialu_reg_reg_vshift);
7080 %}
7081
7082 // Shift Right Logical Immediate
7083 instruct urShiftI_reg_imm(iRegINoSp dst, iRegIorL2I src1, immI src2) %{
7084 match(Set dst (URShiftI src1 src2));
7085 ins_cost(ALU_COST);
7086 format %{ "srliw $dst, $src1, ($src2 & 0x1f)\t#@urShiftI_reg_imm" %}
7087
7088 ins_encode %{
7089 // the shift amount is encoded in the lower
7090 // 6 bits of the I-immediate field for RV64I
7091 __ srliw(as_Register($dst$$reg),
7092 as_Register($src1$$reg),
7093 (unsigned) $src2$$constant & 0x1f);
7094 %}
7095
7096 ins_pipe(ialu_reg_shift);
7097 %}
7098
7099 // Shift Right Arithmetic Register
7100 // Only the low 5 bits of src2 are considered for the shift amount, all other bits are ignored.
7101 instruct rShiftI_reg_reg(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2) %{
7102 match(Set dst (RShiftI src1 src2));
7103 ins_cost(ALU_COST);
7104 format %{ "sraw $dst, $src1, $src2\t#@rShiftI_reg_reg" %}
7105
7106 ins_encode %{
7107 // riscv will sign-ext dst high 32 bits
7108 __ sraw(as_Register($dst$$reg),
7109 as_Register($src1$$reg),
7110 as_Register($src2$$reg));
7111 %}
7112
7113 ins_pipe(ialu_reg_reg_vshift);
7114 %}
7115
7116 // Shift Right Arithmetic Immediate
7117 instruct rShiftI_reg_imm(iRegINoSp dst, iRegIorL2I src1, immI src2) %{
7118 match(Set dst (RShiftI src1 src2));
7119 ins_cost(ALU_COST);
7120 format %{ "sraiw $dst, $src1, ($src2 & 0x1f)\t#@rShiftI_reg_imm" %}
7121
7122 ins_encode %{
7123 // riscv will sign-ext dst high 32 bits
7124 __ sraiw(as_Register($dst$$reg),
7125 as_Register($src1$$reg),
7126 (unsigned) $src2$$constant & 0x1f);
7127 %}
7128
7129 ins_pipe(ialu_reg_shift);
7130 %}
7131
7132 // Long Shifts
7133
7134 // Shift Left Register
7135 // Only the low 6 bits of src2 are considered for the shift amount, all other bits are ignored.
7136 instruct lShiftL_reg_reg(iRegLNoSp dst, iRegL src1, iRegIorL2I src2) %{
7137 match(Set dst (LShiftL src1 src2));
7138
7139 ins_cost(ALU_COST);
7140 format %{ "sll $dst, $src1, $src2\t#@lShiftL_reg_reg" %}
7141
7142 ins_encode %{
7143 __ sll(as_Register($dst$$reg),
7144 as_Register($src1$$reg),
7145 as_Register($src2$$reg));
7146 %}
7147
7148 ins_pipe(ialu_reg_reg_vshift);
7149 %}
7150
7151 // Shift Left Immediate
7152 instruct lShiftL_reg_imm(iRegLNoSp dst, iRegL src1, immI src2) %{
7153 match(Set dst (LShiftL src1 src2));
7154
7155 ins_cost(ALU_COST);
7156 format %{ "slli $dst, $src1, ($src2 & 0x3f)\t#@lShiftL_reg_imm" %}
7157
7158 ins_encode %{
7159 // the shift amount is encoded in the lower
7160 // 6 bits of the I-immediate field for RV64I
7161 __ slli(as_Register($dst$$reg),
7162 as_Register($src1$$reg),
7163 (unsigned) $src2$$constant & 0x3f);
7164 %}
7165
7166 ins_pipe(ialu_reg_shift);
7167 %}
7168
7169 // Shift Right Logical Register
7170 // Only the low 6 bits of src2 are considered for the shift amount, all other bits are ignored.
7171 instruct urShiftL_reg_reg(iRegLNoSp dst, iRegL src1, iRegIorL2I src2) %{
7172 match(Set dst (URShiftL src1 src2));
7173
7174 ins_cost(ALU_COST);
7175 format %{ "srl $dst, $src1, $src2\t#@urShiftL_reg_reg" %}
7176
7177 ins_encode %{
7178 __ srl(as_Register($dst$$reg),
7179 as_Register($src1$$reg),
7180 as_Register($src2$$reg));
7181 %}
7182
7183 ins_pipe(ialu_reg_reg_vshift);
7184 %}
7185
7186 // Shift Right Logical Immediate
7187 instruct urShiftL_reg_imm(iRegLNoSp dst, iRegL src1, immI src2) %{
7188 match(Set dst (URShiftL src1 src2));
7189
7190 ins_cost(ALU_COST);
7191 format %{ "srli $dst, $src1, ($src2 & 0x3f)\t#@urShiftL_reg_imm" %}
7192
7193 ins_encode %{
7194 // the shift amount is encoded in the lower
7195 // 6 bits of the I-immediate field for RV64I
7196 __ srli(as_Register($dst$$reg),
7197 as_Register($src1$$reg),
7198 (unsigned) $src2$$constant & 0x3f);
7199 %}
7200
7201 ins_pipe(ialu_reg_shift);
7202 %}
7203
7204 // A special-case pattern for card table stores.
7205 instruct urShiftP_reg_imm(iRegLNoSp dst, iRegP src1, immI src2) %{
7206 match(Set dst (URShiftL (CastP2X src1) src2));
7207
7208 ins_cost(ALU_COST);
7209 format %{ "srli $dst, p2x($src1), ($src2 & 0x3f)\t#@urShiftP_reg_imm" %}
7210
7211 ins_encode %{
7212 // the shift amount is encoded in the lower
7213 // 6 bits of the I-immediate field for RV64I
7214 __ srli(as_Register($dst$$reg),
7215 as_Register($src1$$reg),
7216 (unsigned) $src2$$constant & 0x3f);
7217 %}
7218
7219 ins_pipe(ialu_reg_shift);
7220 %}
7221
7222 // Shift Right Arithmetic Register
7223 // Only the low 6 bits of src2 are considered for the shift amount, all other bits are ignored.
7224 instruct rShiftL_reg_reg(iRegLNoSp dst, iRegL src1, iRegIorL2I src2) %{
7225 match(Set dst (RShiftL src1 src2));
7226
7227 ins_cost(ALU_COST);
7228 format %{ "sra $dst, $src1, $src2\t#@rShiftL_reg_reg" %}
7229
7230 ins_encode %{
7231 __ sra(as_Register($dst$$reg),
7232 as_Register($src1$$reg),
7233 as_Register($src2$$reg));
7234 %}
7235
7236 ins_pipe(ialu_reg_reg_vshift);
7237 %}
7238
7239 // Shift Right Arithmetic Immediate
7240 instruct rShiftL_reg_imm(iRegLNoSp dst, iRegL src1, immI src2) %{
7241 match(Set dst (RShiftL src1 src2));
7242
7243 ins_cost(ALU_COST);
7244 format %{ "srai $dst, $src1, ($src2 & 0x3f)\t#@rShiftL_reg_imm" %}
7245
7246 ins_encode %{
7247 // the shift amount is encoded in the lower
7248 // 6 bits of the I-immediate field for RV64I
7249 __ srai(as_Register($dst$$reg),
7250 as_Register($src1$$reg),
7251 (unsigned) $src2$$constant & 0x3f);
7252 %}
7253
7254 ins_pipe(ialu_reg_shift);
7255 %}
7256
7257 instruct regI_not_reg(iRegINoSp dst, iRegI src1, immI_M1 m1) %{
7258 match(Set dst (XorI src1 m1));
7259 ins_cost(ALU_COST);
7260 format %{ "xori $dst, $src1, -1\t#@regI_not_reg" %}
7261
7262 ins_encode %{
7263 __ xori(as_Register($dst$$reg), as_Register($src1$$reg), -1);
7264 %}
7265
7266 ins_pipe(ialu_reg_imm);
7267 %}
7268
7269 instruct regL_not_reg(iRegLNoSp dst, iRegL src1, immL_M1 m1) %{
7270 match(Set dst (XorL src1 m1));
7271 ins_cost(ALU_COST);
7272 format %{ "xori $dst, $src1, -1\t#@regL_not_reg" %}
7273
7274 ins_encode %{
7275 __ xori(as_Register($dst$$reg), as_Register($src1$$reg), -1);
7276 %}
7277
7278 ins_pipe(ialu_reg_imm);
7279 %}
7280
7281
7282 // ============================================================================
7283 // Floating Point Arithmetic Instructions
7284
7285 instruct addF_reg_reg(fRegF dst, fRegF src1, fRegF src2) %{
7286 match(Set dst (AddF src1 src2));
7287
7288 ins_cost(DEFAULT_COST * 5);
7289 format %{ "fadd.s $dst, $src1, $src2\t#@addF_reg_reg" %}
7290
7291 ins_encode %{
7292 __ fadd_s(as_FloatRegister($dst$$reg),
7293 as_FloatRegister($src1$$reg),
7294 as_FloatRegister($src2$$reg));
7295 %}
7296
7297 ins_pipe(fp_dop_reg_reg_s);
7298 %}
7299
7300 instruct addD_reg_reg(fRegD dst, fRegD src1, fRegD src2) %{
7301 match(Set dst (AddD src1 src2));
7302
7303 ins_cost(DEFAULT_COST * 5);
7304 format %{ "fadd.d $dst, $src1, $src2\t#@addD_reg_reg" %}
7305
7306 ins_encode %{
7307 __ fadd_d(as_FloatRegister($dst$$reg),
7308 as_FloatRegister($src1$$reg),
7309 as_FloatRegister($src2$$reg));
7310 %}
7311
7312 ins_pipe(fp_dop_reg_reg_d);
7313 %}
7314
7315 instruct subF_reg_reg(fRegF dst, fRegF src1, fRegF src2) %{
7316 match(Set dst (SubF src1 src2));
7317
7318 ins_cost(DEFAULT_COST * 5);
7319 format %{ "fsub.s $dst, $src1, $src2\t#@subF_reg_reg" %}
7320
7321 ins_encode %{
7322 __ fsub_s(as_FloatRegister($dst$$reg),
7323 as_FloatRegister($src1$$reg),
7324 as_FloatRegister($src2$$reg));
7325 %}
7326
7327 ins_pipe(fp_dop_reg_reg_s);
7328 %}
7329
7330 instruct subD_reg_reg(fRegD dst, fRegD src1, fRegD src2) %{
7331 match(Set dst (SubD src1 src2));
7332
7333 ins_cost(DEFAULT_COST * 5);
7334 format %{ "fsub.d $dst, $src1, $src2\t#@subD_reg_reg" %}
7335
7336 ins_encode %{
7337 __ fsub_d(as_FloatRegister($dst$$reg),
7338 as_FloatRegister($src1$$reg),
7339 as_FloatRegister($src2$$reg));
7340 %}
7341
7342 ins_pipe(fp_dop_reg_reg_d);
7343 %}
7344
7345 instruct mulF_reg_reg(fRegF dst, fRegF src1, fRegF src2) %{
7346 match(Set dst (MulF src1 src2));
7347
7348 ins_cost(FMUL_SINGLE_COST);
7349 format %{ "fmul.s $dst, $src1, $src2\t#@mulF_reg_reg" %}
7350
7351 ins_encode %{
7352 __ fmul_s(as_FloatRegister($dst$$reg),
7353 as_FloatRegister($src1$$reg),
7354 as_FloatRegister($src2$$reg));
7355 %}
7356
7357 ins_pipe(fp_dop_reg_reg_s);
7358 %}
7359
7360 instruct mulD_reg_reg(fRegD dst, fRegD src1, fRegD src2) %{
7361 match(Set dst (MulD src1 src2));
7362
7363 ins_cost(FMUL_DOUBLE_COST);
7364 format %{ "fmul.d $dst, $src1, $src2\t#@mulD_reg_reg" %}
7365
7366 ins_encode %{
7367 __ fmul_d(as_FloatRegister($dst$$reg),
7368 as_FloatRegister($src1$$reg),
7369 as_FloatRegister($src2$$reg));
7370 %}
7371
7372 ins_pipe(fp_dop_reg_reg_d);
7373 %}
7374
7375 // src1 * src2 + src3
7376 instruct maddF_reg_reg(fRegF dst, fRegF src1, fRegF src2, fRegF src3) %{
7377 match(Set dst (FmaF src3 (Binary src1 src2)));
7378
7379 ins_cost(FMUL_SINGLE_COST);
7380 format %{ "fmadd.s $dst, $src1, $src2, $src3\t#@maddF_reg_reg" %}
7381
7382 ins_encode %{
7383 assert(UseFMA, "Needs FMA instructions support.");
7384 __ fmadd_s(as_FloatRegister($dst$$reg),
7385 as_FloatRegister($src1$$reg),
7386 as_FloatRegister($src2$$reg),
7387 as_FloatRegister($src3$$reg));
7388 %}
7389
7390 ins_pipe(pipe_class_default);
7391 %}
7392
7393 // src1 * src2 + src3
7394 instruct maddD_reg_reg(fRegD dst, fRegD src1, fRegD src2, fRegD src3) %{
7395 match(Set dst (FmaD src3 (Binary src1 src2)));
7396
7397 ins_cost(FMUL_DOUBLE_COST);
7398 format %{ "fmadd.d $dst, $src1, $src2, $src3\t#@maddD_reg_reg" %}
7399
7400 ins_encode %{
7401 assert(UseFMA, "Needs FMA instructions support.");
7402 __ fmadd_d(as_FloatRegister($dst$$reg),
7403 as_FloatRegister($src1$$reg),
7404 as_FloatRegister($src2$$reg),
7405 as_FloatRegister($src3$$reg));
7406 %}
7407
7408 ins_pipe(pipe_class_default);
7409 %}
7410
7411 // src1 * src2 - src3
7412 instruct msubF_reg_reg(fRegF dst, fRegF src1, fRegF src2, fRegF src3) %{
7413 match(Set dst (FmaF (NegF src3) (Binary src1 src2)));
7414
7415 ins_cost(FMUL_SINGLE_COST);
7416 format %{ "fmsub.s $dst, $src1, $src2, $src3\t#@msubF_reg_reg" %}
7417
7418 ins_encode %{
7419 assert(UseFMA, "Needs FMA instructions support.");
7420 __ fmsub_s(as_FloatRegister($dst$$reg),
7421 as_FloatRegister($src1$$reg),
7422 as_FloatRegister($src2$$reg),
7423 as_FloatRegister($src3$$reg));
7424 %}
7425
7426 ins_pipe(pipe_class_default);
7427 %}
7428
7429 // src1 * src2 - src3
7430 instruct msubD_reg_reg(fRegD dst, fRegD src1, fRegD src2, fRegD src3) %{
7431 match(Set dst (FmaD (NegD src3) (Binary src1 src2)));
7432
7433 ins_cost(FMUL_DOUBLE_COST);
7434 format %{ "fmsub.d $dst, $src1, $src2, $src3\t#@msubD_reg_reg" %}
7435
7436 ins_encode %{
7437 assert(UseFMA, "Needs FMA instructions support.");
7438 __ fmsub_d(as_FloatRegister($dst$$reg),
7439 as_FloatRegister($src1$$reg),
7440 as_FloatRegister($src2$$reg),
7441 as_FloatRegister($src3$$reg));
7442 %}
7443
7444 ins_pipe(pipe_class_default);
7445 %}
7446
7447 // src1 * (-src2) + src3
7448 // "(-src1) * src2 + src3" has been idealized to "src2 * (-src1) + src3"
7449 instruct nmsubF_reg_reg(fRegF dst, fRegF src1, fRegF src2, fRegF src3) %{
7450 match(Set dst (FmaF src3 (Binary src1 (NegF src2))));
7451
7452 ins_cost(FMUL_SINGLE_COST);
7453 format %{ "fnmsub.s $dst, $src1, $src2, $src3\t#@nmsubF_reg_reg" %}
7454
7455 ins_encode %{
7456 assert(UseFMA, "Needs FMA instructions support.");
7457 __ fnmsub_s(as_FloatRegister($dst$$reg),
7458 as_FloatRegister($src1$$reg),
7459 as_FloatRegister($src2$$reg),
7460 as_FloatRegister($src3$$reg));
7461 %}
7462
7463 ins_pipe(pipe_class_default);
7464 %}
7465
7466 // src1 * (-src2) + src3
7467 // "(-src1) * src2 + src3" has been idealized to "src2 * (-src1) + src3"
7468 instruct nmsubD_reg_reg(fRegD dst, fRegD src1, fRegD src2, fRegD src3) %{
7469 match(Set dst (FmaD src3 (Binary src1 (NegD src2))));
7470
7471 ins_cost(FMUL_DOUBLE_COST);
7472 format %{ "fnmsub.d $dst, $src1, $src2, $src3\t#@nmsubD_reg_reg" %}
7473
7474 ins_encode %{
7475 assert(UseFMA, "Needs FMA instructions support.");
7476 __ fnmsub_d(as_FloatRegister($dst$$reg),
7477 as_FloatRegister($src1$$reg),
7478 as_FloatRegister($src2$$reg),
7479 as_FloatRegister($src3$$reg));
7480 %}
7481
7482 ins_pipe(pipe_class_default);
7483 %}
7484
7485 // src1 * (-src2) - src3
7486 // "(-src1) * src2 - src3" has been idealized to "src2 * (-src1) - src3"
7487 instruct nmaddF_reg_reg(fRegF dst, fRegF src1, fRegF src2, fRegF src3) %{
7488 match(Set dst (FmaF (NegF src3) (Binary src1 (NegF src2))));
7489
7490 ins_cost(FMUL_SINGLE_COST);
7491 format %{ "fnmadd.s $dst, $src1, $src2, $src3\t#@nmaddF_reg_reg" %}
7492
7493 ins_encode %{
7494 assert(UseFMA, "Needs FMA instructions support.");
7495 __ fnmadd_s(as_FloatRegister($dst$$reg),
7496 as_FloatRegister($src1$$reg),
7497 as_FloatRegister($src2$$reg),
7498 as_FloatRegister($src3$$reg));
7499 %}
7500
7501 ins_pipe(pipe_class_default);
7502 %}
7503
7504 // src1 * (-src2) - src3
7505 // "(-src1) * src2 - src3" has been idealized to "src2 * (-src1) - src3"
7506 instruct nmaddD_reg_reg(fRegD dst, fRegD src1, fRegD src2, fRegD src3) %{
7507 match(Set dst (FmaD (NegD src3) (Binary src1 (NegD src2))));
7508
7509 ins_cost(FMUL_DOUBLE_COST);
7510 format %{ "fnmadd.d $dst, $src1, $src2, $src3\t#@nmaddD_reg_reg" %}
7511
7512 ins_encode %{
7513 assert(UseFMA, "Needs FMA instructions support.");
7514 __ fnmadd_d(as_FloatRegister($dst$$reg),
7515 as_FloatRegister($src1$$reg),
7516 as_FloatRegister($src2$$reg),
7517 as_FloatRegister($src3$$reg));
7518 %}
7519
7520 ins_pipe(pipe_class_default);
7521 %}
7522
7523 // Math.max(FF)F
7524 instruct maxF_reg_reg(fRegF dst, fRegF src1, fRegF src2, rFlagsReg cr) %{
7525 predicate(!UseZfa);
7526 match(Set dst (MaxF src1 src2));
7527 effect(KILL cr);
7528
7529 format %{ "maxF $dst, $src1, $src2" %}
7530
7531 ins_encode %{
7532 __ minmax_fp(as_FloatRegister($dst$$reg),
7533 as_FloatRegister($src1$$reg), as_FloatRegister($src2$$reg),
7534 __ FLOAT_TYPE::single_precision, false /* is_min */);
7535 %}
7536
7537 ins_pipe(pipe_class_default);
7538 %}
7539
7540 instruct maxF_reg_reg_zfa(fRegF dst, fRegF src1, fRegF src2) %{
7541 predicate(UseZfa);
7542 match(Set dst (MaxF src1 src2));
7543
7544 format %{ "maxF $dst, $src1, $src2" %}
7545
7546 ins_encode %{
7547 __ fmaxm_s(as_FloatRegister($dst$$reg),
7548 as_FloatRegister($src1$$reg), as_FloatRegister($src2$$reg));
7549 %}
7550
7551 ins_pipe(pipe_class_default);
7552 %}
7553
7554 // Math.min(FF)F
7555 instruct minF_reg_reg(fRegF dst, fRegF src1, fRegF src2, rFlagsReg cr) %{
7556 predicate(!UseZfa);
7557 match(Set dst (MinF src1 src2));
7558 effect(KILL cr);
7559
7560 format %{ "minF $dst, $src1, $src2" %}
7561
7562 ins_encode %{
7563 __ minmax_fp(as_FloatRegister($dst$$reg),
7564 as_FloatRegister($src1$$reg), as_FloatRegister($src2$$reg),
7565 __ FLOAT_TYPE::single_precision, true /* is_min */);
7566 %}
7567
7568 ins_pipe(pipe_class_default);
7569 %}
7570
7571 instruct minF_reg_reg_zfa(fRegF dst, fRegF src1, fRegF src2) %{
7572 predicate(UseZfa);
7573 match(Set dst (MinF src1 src2));
7574
7575 format %{ "minF $dst, $src1, $src2" %}
7576
7577 ins_encode %{
7578 __ fminm_s(as_FloatRegister($dst$$reg),
7579 as_FloatRegister($src1$$reg), as_FloatRegister($src2$$reg));
7580 %}
7581
7582 ins_pipe(pipe_class_default);
7583 %}
7584
7585 // Math.max(DD)D
7586 instruct maxD_reg_reg(fRegD dst, fRegD src1, fRegD src2, rFlagsReg cr) %{
7587 predicate(!UseZfa);
7588 match(Set dst (MaxD src1 src2));
7589 effect(KILL cr);
7590
7591 format %{ "maxD $dst, $src1, $src2" %}
7592
7593 ins_encode %{
7594 __ minmax_fp(as_FloatRegister($dst$$reg),
7595 as_FloatRegister($src1$$reg), as_FloatRegister($src2$$reg),
7596 __ FLOAT_TYPE::double_precision, false /* is_min */);
7597 %}
7598
7599 ins_pipe(pipe_class_default);
7600 %}
7601
7602 instruct maxD_reg_reg_zfa(fRegD dst, fRegD src1, fRegD src2) %{
7603 predicate(UseZfa);
7604 match(Set dst (MaxD src1 src2));
7605
7606 format %{ "maxD $dst, $src1, $src2" %}
7607
7608 ins_encode %{
7609 __ fmaxm_d(as_FloatRegister($dst$$reg),
7610 as_FloatRegister($src1$$reg), as_FloatRegister($src2$$reg));
7611 %}
7612
7613 ins_pipe(pipe_class_default);
7614 %}
7615
7616 // Math.min(DD)D
7617 instruct minD_reg_reg(fRegD dst, fRegD src1, fRegD src2, rFlagsReg cr) %{
7618 predicate(!UseZfa);
7619 match(Set dst (MinD src1 src2));
7620 effect(KILL cr);
7621
7622 format %{ "minD $dst, $src1, $src2" %}
7623
7624 ins_encode %{
7625 __ minmax_fp(as_FloatRegister($dst$$reg),
7626 as_FloatRegister($src1$$reg), as_FloatRegister($src2$$reg),
7627 __ FLOAT_TYPE::double_precision, true /* is_min */);
7628 %}
7629
7630 ins_pipe(pipe_class_default);
7631 %}
7632
7633 instruct minD_reg_reg_zfa(fRegD dst, fRegD src1, fRegD src2) %{
7634 predicate(UseZfa);
7635 match(Set dst (MinD src1 src2));
7636
7637 format %{ "minD $dst, $src1, $src2" %}
7638
7639 ins_encode %{
7640 __ fminm_d(as_FloatRegister($dst$$reg),
7641 as_FloatRegister($src1$$reg), as_FloatRegister($src2$$reg));
7642 %}
7643
7644 ins_pipe(pipe_class_default);
7645 %}
7646
7647 // Float.isInfinite
7648 instruct isInfiniteF_reg_reg(iRegINoSp dst, fRegF src)
7649 %{
7650 match(Set dst (IsInfiniteF src));
7651
7652 format %{ "isInfinite $dst, $src" %}
7653 ins_encode %{
7654 __ fclass_s(as_Register($dst$$reg), as_FloatRegister($src$$reg));
7655 __ andi(as_Register($dst$$reg), as_Register($dst$$reg), Assembler::FClassBits::inf);
7656 __ slt(as_Register($dst$$reg), zr, as_Register($dst$$reg));
7657 %}
7658
7659 ins_pipe(pipe_class_default);
7660 %}
7661
7662 // Double.isInfinite
7663 instruct isInfiniteD_reg_reg(iRegINoSp dst, fRegD src)
7664 %{
7665 match(Set dst (IsInfiniteD src));
7666
7667 format %{ "isInfinite $dst, $src" %}
7668 ins_encode %{
7669 __ fclass_d(as_Register($dst$$reg), as_FloatRegister($src$$reg));
7670 __ andi(as_Register($dst$$reg), as_Register($dst$$reg), Assembler::FClassBits::inf);
7671 __ slt(as_Register($dst$$reg), zr, as_Register($dst$$reg));
7672 %}
7673
7674 ins_pipe(pipe_class_default);
7675 %}
7676
7677 // Float.isFinite
7678 instruct isFiniteF_reg_reg(iRegINoSp dst, fRegF src)
7679 %{
7680 match(Set dst (IsFiniteF src));
7681
7682 format %{ "isFinite $dst, $src" %}
7683 ins_encode %{
7684 __ fclass_s(as_Register($dst$$reg), as_FloatRegister($src$$reg));
7685 __ andi(as_Register($dst$$reg), as_Register($dst$$reg), Assembler::FClassBits::finite);
7686 __ slt(as_Register($dst$$reg), zr, as_Register($dst$$reg));
7687 %}
7688
7689 ins_pipe(pipe_class_default);
7690 %}
7691
7692 // Double.isFinite
7693 instruct isFiniteD_reg_reg(iRegINoSp dst, fRegD src)
7694 %{
7695 match(Set dst (IsFiniteD src));
7696
7697 format %{ "isFinite $dst, $src" %}
7698 ins_encode %{
7699 __ fclass_d(as_Register($dst$$reg), as_FloatRegister($src$$reg));
7700 __ andi(as_Register($dst$$reg), as_Register($dst$$reg), Assembler::FClassBits::finite);
7701 __ slt(as_Register($dst$$reg), zr, as_Register($dst$$reg));
7702 %}
7703
7704 ins_pipe(pipe_class_default);
7705 %}
7706
7707 instruct divF_reg_reg(fRegF dst, fRegF src1, fRegF src2) %{
7708 match(Set dst (DivF src1 src2));
7709
7710 ins_cost(FDIV_COST);
7711 format %{ "fdiv.s $dst, $src1, $src2\t#@divF_reg_reg" %}
7712
7713 ins_encode %{
7714 __ fdiv_s(as_FloatRegister($dst$$reg),
7715 as_FloatRegister($src1$$reg),
7716 as_FloatRegister($src2$$reg));
7717 %}
7718
7719 ins_pipe(fp_div_s);
7720 %}
7721
7722 instruct divD_reg_reg(fRegD dst, fRegD src1, fRegD src2) %{
7723 match(Set dst (DivD src1 src2));
7724
7725 ins_cost(FDIV_COST);
7726 format %{ "fdiv.d $dst, $src1, $src2\t#@divD_reg_reg" %}
7727
7728 ins_encode %{
7729 __ fdiv_d(as_FloatRegister($dst$$reg),
7730 as_FloatRegister($src1$$reg),
7731 as_FloatRegister($src2$$reg));
7732 %}
7733
7734 ins_pipe(fp_div_d);
7735 %}
7736
7737 instruct negF_reg_reg(fRegF dst, fRegF src) %{
7738 match(Set dst (NegF src));
7739
7740 ins_cost(XFER_COST);
7741 format %{ "fsgnjn.s $dst, $src, $src\t#@negF_reg_reg" %}
7742
7743 ins_encode %{
7744 __ fneg_s(as_FloatRegister($dst$$reg),
7745 as_FloatRegister($src$$reg));
7746 %}
7747
7748 ins_pipe(fp_uop_s);
7749 %}
7750
7751 instruct negD_reg_reg(fRegD dst, fRegD src) %{
7752 match(Set dst (NegD src));
7753
7754 ins_cost(XFER_COST);
7755 format %{ "fsgnjn.d $dst, $src, $src\t#@negD_reg_reg" %}
7756
7757 ins_encode %{
7758 __ fneg_d(as_FloatRegister($dst$$reg),
7759 as_FloatRegister($src$$reg));
7760 %}
7761
7762 ins_pipe(fp_uop_d);
7763 %}
7764
7765 instruct absI_reg(iRegINoSp dst, iRegIorL2I src) %{
7766 match(Set dst (AbsI src));
7767
7768 ins_cost(ALU_COST * 3);
7769 format %{
7770 "sraiw t0, $src, 0x1f\n\t"
7771 "addw $dst, $src, t0\n\t"
7772 "xorr $dst, $dst, t0\t#@absI_reg"
7773 %}
7774
7775 ins_encode %{
7776 __ sraiw(t0, as_Register($src$$reg), 0x1f);
7777 __ addw(as_Register($dst$$reg), as_Register($src$$reg), t0);
7778 __ xorr(as_Register($dst$$reg), as_Register($dst$$reg), t0);
7779 %}
7780
7781 ins_pipe(pipe_class_default);
7782 %}
7783
7784 instruct absL_reg(iRegLNoSp dst, iRegL src) %{
7785 match(Set dst (AbsL src));
7786
7787 ins_cost(ALU_COST * 3);
7788 format %{
7789 "srai t0, $src, 0x3f\n\t"
7790 "add $dst, $src, t0\n\t"
7791 "xorr $dst, $dst, t0\t#@absL_reg"
7792 %}
7793
7794 ins_encode %{
7795 __ srai(t0, as_Register($src$$reg), 0x3f);
7796 __ add(as_Register($dst$$reg), as_Register($src$$reg), t0);
7797 __ xorr(as_Register($dst$$reg), as_Register($dst$$reg), t0);
7798 %}
7799
7800 ins_pipe(pipe_class_default);
7801 %}
7802
7803 instruct absF_reg(fRegF dst, fRegF src) %{
7804 match(Set dst (AbsF src));
7805
7806 ins_cost(XFER_COST);
7807 format %{ "fsgnjx.s $dst, $src, $src\t#@absF_reg" %}
7808 ins_encode %{
7809 __ fabs_s(as_FloatRegister($dst$$reg),
7810 as_FloatRegister($src$$reg));
7811 %}
7812
7813 ins_pipe(fp_uop_s);
7814 %}
7815
7816 instruct absD_reg(fRegD dst, fRegD src) %{
7817 match(Set dst (AbsD src));
7818
7819 ins_cost(XFER_COST);
7820 format %{ "fsgnjx.d $dst, $src, $src\t#@absD_reg" %}
7821 ins_encode %{
7822 __ fabs_d(as_FloatRegister($dst$$reg),
7823 as_FloatRegister($src$$reg));
7824 %}
7825
7826 ins_pipe(fp_uop_d);
7827 %}
7828
7829 instruct sqrtF_reg(fRegF dst, fRegF src) %{
7830 match(Set dst (SqrtF src));
7831
7832 ins_cost(FSQRT_COST);
7833 format %{ "fsqrt.s $dst, $src\t#@sqrtF_reg" %}
7834 ins_encode %{
7835 __ fsqrt_s(as_FloatRegister($dst$$reg),
7836 as_FloatRegister($src$$reg));
7837 %}
7838
7839 ins_pipe(fp_sqrt_s);
7840 %}
7841
7842 instruct sqrtD_reg(fRegD dst, fRegD src) %{
7843 match(Set dst (SqrtD src));
7844
7845 ins_cost(FSQRT_COST);
7846 format %{ "fsqrt.d $dst, $src\t#@sqrtD_reg" %}
7847 ins_encode %{
7848 __ fsqrt_d(as_FloatRegister($dst$$reg),
7849 as_FloatRegister($src$$reg));
7850 %}
7851
7852 ins_pipe(fp_sqrt_d);
7853 %}
7854
7855 // Round Instruction
7856 instruct roundD_reg(fRegD dst, fRegD src, immI rmode, iRegLNoSp tmp1, iRegLNoSp tmp2, iRegLNoSp tmp3) %{
7857 match(Set dst (RoundDoubleMode src rmode));
7858 ins_cost(2 * XFER_COST + BRANCH_COST);
7859 effect(TEMP_DEF dst, TEMP tmp1, TEMP tmp2, TEMP tmp3);
7860
7861 format %{ "RoundDoubleMode $src, $rmode" %}
7862 ins_encode %{
7863 __ round_double_mode(as_FloatRegister($dst$$reg),
7864 as_FloatRegister($src$$reg), $rmode$$constant, $tmp1$$Register, $tmp2$$Register, $tmp3$$Register);
7865 %}
7866 ins_pipe(pipe_class_default);
7867 %}
7868
7869 // Copysign and signum intrinsics
7870
7871 instruct copySignD_reg(fRegD dst, fRegD src1, fRegD src2, immD zero) %{
7872 match(Set dst (CopySignD src1 (Binary src2 zero)));
7873 format %{ "CopySignD $dst $src1 $src2" %}
7874 ins_encode %{
7875 FloatRegister dst = as_FloatRegister($dst$$reg),
7876 src1 = as_FloatRegister($src1$$reg),
7877 src2 = as_FloatRegister($src2$$reg);
7878 __ fsgnj_d(dst, src1, src2);
7879 %}
7880 ins_pipe(fp_dop_reg_reg_d);
7881 %}
7882
7883 instruct copySignF_reg(fRegF dst, fRegF src1, fRegF src2) %{
7884 match(Set dst (CopySignF src1 src2));
7885 format %{ "CopySignF $dst $src1 $src2" %}
7886 ins_encode %{
7887 FloatRegister dst = as_FloatRegister($dst$$reg),
7888 src1 = as_FloatRegister($src1$$reg),
7889 src2 = as_FloatRegister($src2$$reg);
7890 __ fsgnj_s(dst, src1, src2);
7891 %}
7892 ins_pipe(fp_dop_reg_reg_s);
7893 %}
7894
7895 instruct signumD_reg(fRegD dst, immD zero, fRegD one) %{
7896 match(Set dst (SignumD dst (Binary zero one)));
7897 format %{ "signumD $dst, $dst" %}
7898 ins_encode %{
7899 __ signum_fp(as_FloatRegister($dst$$reg), as_FloatRegister($one$$reg), true /* is_double */);
7900 %}
7901 ins_pipe(pipe_class_default);
7902 %}
7903
7904 instruct signumF_reg(fRegF dst, immF zero, fRegF one) %{
7905 match(Set dst (SignumF dst (Binary zero one)));
7906 format %{ "signumF $dst, $dst" %}
7907 ins_encode %{
7908 __ signum_fp(as_FloatRegister($dst$$reg), as_FloatRegister($one$$reg), false /* is_double */);
7909 %}
7910 ins_pipe(pipe_class_default);
7911 %}
7912
7913 // Arithmetic Instructions End
7914
7915 // ============================================================================
7916 // Logical Instructions
7917
7918 // Register And
7919 instruct andI_reg_reg(iRegINoSp dst, iRegI src1, iRegI src2) %{
7920 match(Set dst (AndI src1 src2));
7921
7922 format %{ "andr $dst, $src1, $src2\t#@andI_reg_reg" %}
7923
7924 ins_cost(ALU_COST);
7925 ins_encode %{
7926 __ andr(as_Register($dst$$reg),
7927 as_Register($src1$$reg),
7928 as_Register($src2$$reg));
7929 %}
7930
7931 ins_pipe(ialu_reg_reg);
7932 %}
7933
7934 // Immediate And
7935 instruct andI_reg_imm(iRegINoSp dst, iRegI src1, immIAdd src2) %{
7936 match(Set dst (AndI src1 src2));
7937
7938 format %{ "andi $dst, $src1, $src2\t#@andI_reg_imm" %}
7939
7940 ins_cost(ALU_COST);
7941 ins_encode %{
7942 __ andi(as_Register($dst$$reg),
7943 as_Register($src1$$reg),
7944 (int32_t)($src2$$constant));
7945 %}
7946
7947 ins_pipe(ialu_reg_imm);
7948 %}
7949
7950 // Register Or
7951 instruct orI_reg_reg(iRegINoSp dst, iRegI src1, iRegI src2) %{
7952 match(Set dst (OrI src1 src2));
7953
7954 format %{ "orr $dst, $src1, $src2\t#@orI_reg_reg" %}
7955
7956 ins_cost(ALU_COST);
7957 ins_encode %{
7958 __ orr(as_Register($dst$$reg),
7959 as_Register($src1$$reg),
7960 as_Register($src2$$reg));
7961 %}
7962
7963 ins_pipe(ialu_reg_reg);
7964 %}
7965
7966 // Immediate Or
7967 instruct orI_reg_imm(iRegINoSp dst, iRegI src1, immIAdd src2) %{
7968 match(Set dst (OrI src1 src2));
7969
7970 format %{ "ori $dst, $src1, $src2\t#@orI_reg_imm" %}
7971
7972 ins_cost(ALU_COST);
7973 ins_encode %{
7974 __ ori(as_Register($dst$$reg),
7975 as_Register($src1$$reg),
7976 (int32_t)($src2$$constant));
7977 %}
7978
7979 ins_pipe(ialu_reg_imm);
7980 %}
7981
7982 // Register Xor
7983 instruct xorI_reg_reg(iRegINoSp dst, iRegI src1, iRegI src2) %{
7984 match(Set dst (XorI src1 src2));
7985
7986 format %{ "xorr $dst, $src1, $src2\t#@xorI_reg_reg" %}
7987
7988 ins_cost(ALU_COST);
7989 ins_encode %{
7990 __ xorr(as_Register($dst$$reg),
7991 as_Register($src1$$reg),
7992 as_Register($src2$$reg));
7993 %}
7994
7995 ins_pipe(ialu_reg_reg);
7996 %}
7997
7998 // Immediate Xor
7999 instruct xorI_reg_imm(iRegINoSp dst, iRegI src1, immIAdd src2) %{
8000 match(Set dst (XorI src1 src2));
8001
8002 format %{ "xori $dst, $src1, $src2\t#@xorI_reg_imm" %}
8003
8004 ins_cost(ALU_COST);
8005 ins_encode %{
8006 __ xori(as_Register($dst$$reg),
8007 as_Register($src1$$reg),
8008 (int32_t)($src2$$constant));
8009 %}
8010
8011 ins_pipe(ialu_reg_imm);
8012 %}
8013
8014 // Register And Long
8015 instruct andL_reg_reg(iRegLNoSp dst, iRegL src1, iRegL src2) %{
8016 match(Set dst (AndL src1 src2));
8017
8018 format %{ "andr $dst, $src1, $src2\t#@andL_reg_reg" %}
8019
8020 ins_cost(ALU_COST);
8021 ins_encode %{
8022 __ andr(as_Register($dst$$reg),
8023 as_Register($src1$$reg),
8024 as_Register($src2$$reg));
8025 %}
8026
8027 ins_pipe(ialu_reg_reg);
8028 %}
8029
8030 // Immediate And Long
8031 instruct andL_reg_imm(iRegLNoSp dst, iRegL src1, immLAdd src2) %{
8032 match(Set dst (AndL src1 src2));
8033
8034 format %{ "andi $dst, $src1, $src2\t#@andL_reg_imm" %}
8035
8036 ins_cost(ALU_COST);
8037 ins_encode %{
8038 __ andi(as_Register($dst$$reg),
8039 as_Register($src1$$reg),
8040 (int32_t)($src2$$constant));
8041 %}
8042
8043 ins_pipe(ialu_reg_imm);
8044 %}
8045
8046 // Register Or Long
8047 instruct orL_reg_reg(iRegLNoSp dst, iRegL src1, iRegL src2) %{
8048 match(Set dst (OrL src1 src2));
8049
8050 format %{ "orr $dst, $src1, $src2\t#@orL_reg_reg" %}
8051
8052 ins_cost(ALU_COST);
8053 ins_encode %{
8054 __ orr(as_Register($dst$$reg),
8055 as_Register($src1$$reg),
8056 as_Register($src2$$reg));
8057 %}
8058
8059 ins_pipe(ialu_reg_reg);
8060 %}
8061
8062 // Immediate Or Long
8063 instruct orL_reg_imm(iRegLNoSp dst, iRegL src1, immLAdd src2) %{
8064 match(Set dst (OrL src1 src2));
8065
8066 format %{ "ori $dst, $src1, $src2\t#@orL_reg_imm" %}
8067
8068 ins_cost(ALU_COST);
8069 ins_encode %{
8070 __ ori(as_Register($dst$$reg),
8071 as_Register($src1$$reg),
8072 (int32_t)($src2$$constant));
8073 %}
8074
8075 ins_pipe(ialu_reg_imm);
8076 %}
8077
8078 // Register Xor Long
8079 instruct xorL_reg_reg(iRegLNoSp dst, iRegL src1, iRegL src2) %{
8080 match(Set dst (XorL src1 src2));
8081
8082 format %{ "xorr $dst, $src1, $src2\t#@xorL_reg_reg" %}
8083
8084 ins_cost(ALU_COST);
8085 ins_encode %{
8086 __ xorr(as_Register($dst$$reg),
8087 as_Register($src1$$reg),
8088 as_Register($src2$$reg));
8089 %}
8090
8091 ins_pipe(ialu_reg_reg);
8092 %}
8093
8094 // Immediate Xor Long
8095 instruct xorL_reg_imm(iRegLNoSp dst, iRegL src1, immLAdd src2) %{
8096 match(Set dst (XorL src1 src2));
8097
8098 ins_cost(ALU_COST);
8099 format %{ "xori $dst, $src1, $src2\t#@xorL_reg_imm" %}
8100
8101 ins_encode %{
8102 __ xori(as_Register($dst$$reg),
8103 as_Register($src1$$reg),
8104 (int32_t)($src2$$constant));
8105 %}
8106
8107 ins_pipe(ialu_reg_imm);
8108 %}
8109
8110 // ============================================================================
8111 // MemBar Instruction
8112
8113 // RVTSO
8114
8115 instruct unnecessary_membar_rvtso() %{
8116 predicate(UseZtso);
8117 match(LoadFence);
8118 match(StoreFence);
8119 match(StoreStoreFence);
8120 match(MemBarAcquire);
8121 match(MemBarRelease);
8122 match(MemBarStoreStore);
8123 match(MemBarAcquireLock);
8124 match(MemBarReleaseLock);
8125
8126 ins_cost(0);
8127
8128 size(0);
8129
8130 format %{ "#@unnecessary_membar_rvtso elided/tso (empty encoding)" %}
8131 ins_encode %{
8132 __ block_comment("unnecessary_membar_rvtso");
8133 %}
8134 ins_pipe(real_empty);
8135 %}
8136
8137 instruct membar_storeload_rvtso() %{
8138 predicate(UseZtso);
8139 match(MemBarStoreLoad);
8140 ins_cost(VOLATILE_REF_COST);
8141
8142 format %{ "#@membar_storeload_rvtso\n\t"
8143 "fence w, r"%}
8144
8145 ins_encode %{
8146 __ block_comment("membar_storeload_rvtso");
8147 __ membar(MacroAssembler::StoreLoad);
8148 %}
8149
8150 ins_pipe(pipe_slow);
8151 %}
8152
8153 instruct membar_volatile_rvtso() %{
8154 predicate(UseZtso);
8155 match(MemBarVolatile);
8156 ins_cost(VOLATILE_REF_COST);
8157
8158 format %{ "#@membar_volatile_rvtso\n\t"
8159 "fence w, r"%}
8160
8161 ins_encode %{
8162 __ block_comment("membar_volatile_rvtso");
8163 __ membar(MacroAssembler::StoreLoad);
8164 %}
8165
8166 ins_pipe(pipe_slow);
8167 %}
8168
8169 instruct unnecessary_membar_volatile_rvtso() %{
8170 predicate(UseZtso && Matcher::post_store_load_barrier(n));
8171 match(MemBarVolatile);
8172 ins_cost(0);
8173
8174 size(0);
8175
8176 format %{ "#@unnecessary_membar_volatile_rvtso (unnecessary so empty encoding)" %}
8177 ins_encode %{
8178 __ block_comment("unnecessary_membar_volatile_rvtso");
8179 %}
8180 ins_pipe(real_empty);
8181 %}
8182
8183 instruct membar_full_rvtso() %{
8184 predicate(UseZtso);
8185 match(MemBarFull);
8186 ins_cost(VOLATILE_REF_COST);
8187
8188 format %{ "#@membar_full_rvtso\n\t"
8189 "fence rw, rw" %}
8190
8191 ins_encode %{
8192 __ block_comment("membar_full_rvtso");
8193 __ membar(MacroAssembler::AnyAny);
8194 %}
8195
8196 ins_pipe(pipe_slow);
8197 %}
8198
8199 // RVWMO
8200
8201 instruct membar_aqcuire_rvwmo() %{
8202 predicate(!UseZtso);
8203 match(LoadFence);
8204 match(MemBarAcquire);
8205 ins_cost(VOLATILE_REF_COST);
8206
8207 format %{ "#@membar_aqcuire_rvwmo\n\t"
8208 "fence r, rw" %}
8209
8210 ins_encode %{
8211 __ block_comment("membar_aqcuire_rvwmo");
8212 __ membar(MacroAssembler::LoadLoad | MacroAssembler::LoadStore);
8213 %}
8214 ins_pipe(pipe_serial);
8215 %}
8216
8217 instruct membar_release_rvwmo() %{
8218 predicate(!UseZtso);
8219 match(StoreFence);
8220 match(MemBarRelease);
8221 ins_cost(VOLATILE_REF_COST);
8222
8223 format %{ "#@membar_release_rvwmo\n\t"
8224 "fence rw, w" %}
8225
8226 ins_encode %{
8227 __ block_comment("membar_release_rvwmo");
8228 __ membar(MacroAssembler::LoadStore | MacroAssembler::StoreStore);
8229 %}
8230 ins_pipe(pipe_serial);
8231 %}
8232
8233 instruct membar_storestore_rvwmo() %{
8234 predicate(!UseZtso);
8235 match(MemBarStoreStore);
8236 match(StoreStoreFence);
8237 ins_cost(VOLATILE_REF_COST);
8238
8239 format %{ "#@membar_storestore_rvwmo\n\t"
8240 "fence w, w" %}
8241
8242 ins_encode %{
8243 __ membar(MacroAssembler::StoreStore);
8244 %}
8245 ins_pipe(pipe_serial);
8246 %}
8247
8248 instruct membar_storeload_rvwmo() %{
8249 predicate(!UseZtso);
8250 match(MemBarStoreLoad);
8251 ins_cost(VOLATILE_REF_COST);
8252
8253 format %{ "#@membar_storeload_rvwmo\n\t"
8254 "fence w, r"%}
8255
8256 ins_encode %{
8257 __ block_comment("membar_storeload_rvwmo");
8258 __ membar(MacroAssembler::StoreLoad);
8259 %}
8260
8261 ins_pipe(pipe_serial);
8262 %}
8263
8264 instruct membar_volatile_rvwmo() %{
8265 predicate(!UseZtso);
8266 match(MemBarVolatile);
8267 ins_cost(VOLATILE_REF_COST);
8268
8269 format %{ "#@membar_volatile_rvwmo\n\t"
8270 "fence w, r"%}
8271
8272 ins_encode %{
8273 __ block_comment("membar_volatile_rvwmo");
8274 __ membar(MacroAssembler::StoreLoad);
8275 %}
8276
8277 ins_pipe(pipe_serial);
8278 %}
8279
8280 instruct membar_lock_rvwmo() %{
8281 predicate(!UseZtso);
8282 match(MemBarAcquireLock);
8283 match(MemBarReleaseLock);
8284 ins_cost(0);
8285
8286 format %{ "#@membar_lock_rvwmo (elided)" %}
8287
8288 ins_encode %{
8289 __ block_comment("membar_lock_rvwmo (elided)");
8290 %}
8291
8292 ins_pipe(pipe_serial);
8293 %}
8294
8295 instruct unnecessary_membar_volatile_rvwmo() %{
8296 predicate(!UseZtso && Matcher::post_store_load_barrier(n));
8297 match(MemBarVolatile);
8298 ins_cost(0);
8299
8300 size(0);
8301 format %{ "#@unnecessary_membar_volatile_rvwmo (unnecessary so empty encoding)" %}
8302 ins_encode %{
8303 __ block_comment("unnecessary_membar_volatile_rvwmo");
8304 %}
8305 ins_pipe(real_empty);
8306 %}
8307
8308 instruct membar_full_rvwmo() %{
8309 predicate(!UseZtso);
8310 match(MemBarFull);
8311 ins_cost(VOLATILE_REF_COST);
8312
8313 format %{ "#@membar_full_rvwmo\n\t"
8314 "fence rw, rw" %}
8315
8316 ins_encode %{
8317 __ block_comment("membar_full_rvwmo");
8318 __ membar(MacroAssembler::AnyAny);
8319 %}
8320
8321 ins_pipe(pipe_serial);
8322 %}
8323
8324 instruct spin_wait() %{
8325 predicate(UseZihintpause);
8326 match(OnSpinWait);
8327 ins_cost(CACHE_MISS_COST);
8328
8329 format %{ "spin_wait" %}
8330
8331 ins_encode %{
8332 __ pause();
8333 %}
8334
8335 ins_pipe(pipe_serial);
8336 %}
8337
8338 // ============================================================================
8339 // Cast Instructions (Java-level type cast)
8340
8341 instruct castX2P(iRegPNoSp dst, iRegL src) %{
8342 match(Set dst (CastX2P src));
8343
8344 ins_cost(ALU_COST);
8345 format %{ "mv $dst, $src\t# long -> ptr, #@castX2P" %}
8346
8347 ins_encode %{
8348 if ($dst$$reg != $src$$reg) {
8349 __ mv(as_Register($dst$$reg), as_Register($src$$reg));
8350 }
8351 %}
8352
8353 ins_pipe(ialu_reg);
8354 %}
8355
8356 instruct castP2X(iRegLNoSp dst, iRegP src) %{
8357 match(Set dst (CastP2X src));
8358
8359 ins_cost(ALU_COST);
8360 format %{ "mv $dst, $src\t# ptr -> long, #@castP2X" %}
8361
8362 ins_encode %{
8363 if ($dst$$reg != $src$$reg) {
8364 __ mv(as_Register($dst$$reg), as_Register($src$$reg));
8365 }
8366 %}
8367
8368 ins_pipe(ialu_reg);
8369 %}
8370
8371 instruct castPP(iRegPNoSp dst)
8372 %{
8373 match(Set dst (CastPP dst));
8374 ins_cost(0);
8375
8376 size(0);
8377 format %{ "# castPP of $dst, #@castPP" %}
8378 ins_encode(/* empty encoding */);
8379 ins_pipe(pipe_class_empty);
8380 %}
8381
8382 instruct castLL(iRegL dst)
8383 %{
8384 match(Set dst (CastLL dst));
8385
8386 size(0);
8387 format %{ "# castLL of $dst, #@castLL" %}
8388 ins_encode(/* empty encoding */);
8389 ins_cost(0);
8390 ins_pipe(pipe_class_empty);
8391 %}
8392
8393 instruct castII(iRegI dst)
8394 %{
8395 match(Set dst (CastII dst));
8396
8397 size(0);
8398 format %{ "# castII of $dst, #@castII" %}
8399 ins_encode(/* empty encoding */);
8400 ins_cost(0);
8401 ins_pipe(pipe_class_empty);
8402 %}
8403
8404 instruct checkCastPP(iRegPNoSp dst)
8405 %{
8406 match(Set dst (CheckCastPP dst));
8407
8408 size(0);
8409 ins_cost(0);
8410 format %{ "# checkcastPP of $dst, #@checkCastPP" %}
8411 ins_encode(/* empty encoding */);
8412 ins_pipe(pipe_class_empty);
8413 %}
8414
8415 instruct castHH(fRegF dst)
8416 %{
8417 match(Set dst (CastHH dst));
8418
8419 size(0);
8420 format %{ "# castHH of $dst" %}
8421 ins_encode(/* empty encoding */);
8422 ins_cost(0);
8423 ins_pipe(pipe_class_empty);
8424 %}
8425
8426 instruct castFF(fRegF dst)
8427 %{
8428 match(Set dst (CastFF dst));
8429
8430 size(0);
8431 format %{ "# castFF of $dst" %}
8432 ins_encode(/* empty encoding */);
8433 ins_cost(0);
8434 ins_pipe(pipe_class_empty);
8435 %}
8436
8437 instruct castDD(fRegD dst)
8438 %{
8439 match(Set dst (CastDD dst));
8440
8441 size(0);
8442 format %{ "# castDD of $dst" %}
8443 ins_encode(/* empty encoding */);
8444 ins_cost(0);
8445 ins_pipe(pipe_class_empty);
8446 %}
8447
8448 instruct castVV(vReg dst)
8449 %{
8450 match(Set dst (CastVV dst));
8451
8452 size(0);
8453 format %{ "# castVV of $dst" %}
8454 ins_encode(/* empty encoding */);
8455 ins_cost(0);
8456 ins_pipe(pipe_class_empty);
8457 %}
8458
8459 instruct castVVMask(vRegMask dst)
8460 %{
8461 match(Set dst (CastVV dst));
8462
8463 size(0);
8464 format %{ "# castVV of $dst" %}
8465 ins_encode(/* empty encoding */);
8466 ins_cost(0);
8467 ins_pipe(pipe_class_empty);
8468 %}
8469
8470 // ============================================================================
8471 // Convert Instructions
8472
8473 // int to bool
8474 instruct convI2Bool(iRegINoSp dst, iRegI src)
8475 %{
8476 match(Set dst (Conv2B src));
8477
8478 ins_cost(ALU_COST);
8479 format %{ "snez $dst, $src\t#@convI2Bool" %}
8480
8481 ins_encode %{
8482 __ snez(as_Register($dst$$reg), as_Register($src$$reg));
8483 %}
8484
8485 ins_pipe(ialu_reg);
8486 %}
8487
8488 // pointer to bool
8489 instruct convP2Bool(iRegINoSp dst, iRegP src)
8490 %{
8491 match(Set dst (Conv2B src));
8492
8493 ins_cost(ALU_COST);
8494 format %{ "snez $dst, $src\t#@convP2Bool" %}
8495
8496 ins_encode %{
8497 __ snez(as_Register($dst$$reg), as_Register($src$$reg));
8498 %}
8499
8500 ins_pipe(ialu_reg);
8501 %}
8502
8503 // int <-> long
8504
8505 instruct convI2L_reg_reg(iRegLNoSp dst, iRegIorL2I src)
8506 %{
8507 match(Set dst (ConvI2L src));
8508
8509 ins_cost(ALU_COST);
8510 format %{ "addw $dst, $src, zr\t#@convI2L_reg_reg" %}
8511 ins_encode %{
8512 __ sext(as_Register($dst$$reg), as_Register($src$$reg), 32);
8513 %}
8514 ins_pipe(ialu_reg);
8515 %}
8516
8517 instruct convL2I_reg(iRegINoSp dst, iRegL src) %{
8518 match(Set dst (ConvL2I src));
8519
8520 ins_cost(ALU_COST);
8521 format %{ "addw $dst, $src, zr\t#@convL2I_reg" %}
8522
8523 ins_encode %{
8524 __ sext(as_Register($dst$$reg), as_Register($src$$reg), 32);
8525 %}
8526
8527 ins_pipe(ialu_reg);
8528 %}
8529
8530 // int to unsigned long (Zero-extend)
8531 instruct convI2UL_reg_reg(iRegLNoSp dst, iRegIorL2I src, immL_32bits mask)
8532 %{
8533 match(Set dst (AndL (ConvI2L src) mask));
8534
8535 ins_cost(ALU_COST * 2);
8536 format %{ "zext $dst, $src, 32\t# i2ul, #@convI2UL_reg_reg" %}
8537
8538 ins_encode %{
8539 __ zext(as_Register($dst$$reg), as_Register($src$$reg), 32);
8540 %}
8541
8542 ins_pipe(ialu_reg_shift);
8543 %}
8544
8545 // float <-> double
8546
8547 instruct convF2D_reg(fRegD dst, fRegF src) %{
8548 match(Set dst (ConvF2D src));
8549
8550 ins_cost(XFER_COST);
8551 format %{ "fcvt.d.s $dst, $src\t#@convF2D_reg" %}
8552
8553 ins_encode %{
8554 __ fcvt_d_s(as_FloatRegister($dst$$reg), as_FloatRegister($src$$reg));
8555 %}
8556
8557 ins_pipe(fp_f2d);
8558 %}
8559
8560 instruct convD2F_reg(fRegF dst, fRegD src) %{
8561 match(Set dst (ConvD2F src));
8562
8563 ins_cost(XFER_COST);
8564 format %{ "fcvt.s.d $dst, $src\t#@convD2F_reg" %}
8565
8566 ins_encode %{
8567 __ fcvt_s_d(as_FloatRegister($dst$$reg), as_FloatRegister($src$$reg));
8568 %}
8569
8570 ins_pipe(fp_d2f);
8571 %}
8572
8573 // single <-> half precision
8574
8575 instruct convHF2F_reg_reg(fRegF dst, iRegIorL2I src, iRegINoSp tmp) %{
8576 match(Set dst (ConvHF2F src));
8577 effect(TEMP tmp);
8578 format %{ "fmv.h.x $dst, $src\t# move source from $src to $dst\n\t"
8579 "fcvt.s.h $dst, $dst\t# convert half to single precision"
8580 %}
8581 ins_encode %{
8582 __ float16_to_float($dst$$FloatRegister, $src$$Register, $tmp$$Register);
8583 %}
8584 ins_pipe(pipe_slow);
8585 %}
8586
8587 instruct convF2HF_reg_reg(iRegINoSp dst, fRegF src, fRegF ftmp, iRegINoSp xtmp) %{
8588 match(Set dst (ConvF2HF src));
8589 effect(TEMP_DEF dst, TEMP ftmp, TEMP xtmp);
8590 format %{ "fcvt.h.s $ftmp, $src\t# convert single precision to half\n\t"
8591 "fmv.x.h $dst, $ftmp\t# move result from $ftmp to $dst"
8592 %}
8593 ins_encode %{
8594 __ float_to_float16($dst$$Register, $src$$FloatRegister, $ftmp$$FloatRegister, $xtmp$$Register);
8595 %}
8596 ins_pipe(pipe_slow);
8597 %}
8598
8599 // half precision operations
8600
8601 instruct reinterpretS2HF(fRegF dst, iRegI src)
8602 %{
8603 match(Set dst (ReinterpretS2HF src));
8604 format %{ "fmv.h.x $dst, $src\t# reinterpretS2HF" %}
8605 ins_encode %{
8606 __ fmv_h_x($dst$$FloatRegister, $src$$Register);
8607 %}
8608 ins_pipe(fp_i2f);
8609 %}
8610
8611 instruct convF2HFAndS2HF(fRegF dst, fRegF src)
8612 %{
8613 match(Set dst (ReinterpretS2HF (ConvF2HF src)));
8614 format %{ "convF2HFAndS2HF $dst, $src" %}
8615 ins_encode %{
8616 __ fcvt_h_s($dst$$FloatRegister, $src$$FloatRegister);
8617 %}
8618 ins_pipe(fp_uop_s);
8619 %}
8620
8621 instruct reinterpretHF2S(iRegINoSp dst, fRegF src)
8622 %{
8623 match(Set dst (ReinterpretHF2S src));
8624 format %{ "fmv.x.h $dst, $src\t# reinterpretHF2S" %}
8625 ins_encode %{
8626 __ fmv_x_h($dst$$Register, $src$$FloatRegister);
8627 %}
8628 ins_pipe(fp_f2i);
8629 %}
8630
8631 instruct convHF2SAndHF2F(fRegF dst, fRegF src)
8632 %{
8633 match(Set dst (ConvHF2F (ReinterpretHF2S src)));
8634 format %{ "convHF2SAndHF2F $dst, $src" %}
8635 ins_encode %{
8636 __ fcvt_s_h($dst$$FloatRegister, $src$$FloatRegister);
8637 %}
8638 ins_pipe(fp_uop_s);
8639 %}
8640
8641 instruct sqrt_HF_reg(fRegF dst, fRegF src)
8642 %{
8643 match(Set dst (SqrtHF src));
8644 format %{ "fsqrt.h $dst, $src" %}
8645 ins_encode %{
8646 __ fsqrt_h($dst$$FloatRegister, $src$$FloatRegister);
8647 %}
8648 ins_pipe(fp_sqrt_s);
8649 %}
8650
8651 instruct binOps_HF_reg(fRegF dst, fRegF src1, fRegF src2)
8652 %{
8653 match(Set dst (AddHF src1 src2));
8654 match(Set dst (SubHF src1 src2));
8655 match(Set dst (MulHF src1 src2));
8656 match(Set dst (DivHF src1 src2));
8657 format %{ "binop_hf $dst, $src1, $src2" %}
8658 ins_encode %{
8659 int opcode = this->ideal_Opcode();
8660 switch(opcode) {
8661 case Op_AddHF: __ fadd_h($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister); break;
8662 case Op_SubHF: __ fsub_h($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister); break;
8663 case Op_MulHF: __ fmul_h($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister); break;
8664 case Op_DivHF: __ fdiv_h($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister); break;
8665 default: assert(false, "%s is not supported here", NodeClassNames[opcode]); break;
8666 }
8667 %}
8668 ins_pipe(fp_dop_reg_reg_s);
8669 %}
8670
8671 instruct min_HF_reg(fRegF dst, fRegF src1, fRegF src2, rFlagsReg cr)
8672 %{
8673 predicate(!UseZfa);
8674 match(Set dst (MinHF src1 src2));
8675 effect(KILL cr);
8676
8677 format %{ "min_hf $dst, $src1, $src2" %}
8678
8679 ins_encode %{
8680 __ minmax_fp($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
8681 __ FLOAT_TYPE::half_precision, true /* is_min */);
8682 %}
8683 ins_pipe(pipe_class_default);
8684 %}
8685
8686 instruct min_HF_reg_zfa(fRegF dst, fRegF src1, fRegF src2)
8687 %{
8688 predicate(UseZfa);
8689 match(Set dst (MinHF src1 src2));
8690
8691 format %{ "min_hf $dst, $src1, $src2" %}
8692
8693 ins_encode %{
8694 __ fminm_h(as_FloatRegister($dst$$reg),
8695 as_FloatRegister($src1$$reg), as_FloatRegister($src2$$reg));
8696 %}
8697
8698 ins_pipe(pipe_class_default);
8699 %}
8700
8701 instruct max_HF_reg(fRegF dst, fRegF src1, fRegF src2, rFlagsReg cr)
8702 %{
8703 predicate(!UseZfa);
8704 match(Set dst (MaxHF src1 src2));
8705 effect(KILL cr);
8706
8707 format %{ "max_hf $dst, $src1, $src2" %}
8708
8709 ins_encode %{
8710 __ minmax_fp($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
8711 __ FLOAT_TYPE::half_precision, false /* is_min */);
8712 %}
8713 ins_pipe(pipe_class_default);
8714 %}
8715
8716 instruct max_HF_reg_zfa(fRegF dst, fRegF src1, fRegF src2)
8717 %{
8718 predicate(UseZfa);
8719 match(Set dst (MaxHF src1 src2));
8720
8721 format %{ "max_hf $dst, $src1, $src2" %}
8722
8723 ins_encode %{
8724 __ fmaxm_h(as_FloatRegister($dst$$reg),
8725 as_FloatRegister($src1$$reg), as_FloatRegister($src2$$reg));
8726 %}
8727
8728 ins_pipe(pipe_class_default);
8729 %}
8730
8731 instruct fma_HF_reg(fRegF dst, fRegF src1, fRegF src2, fRegF src3)
8732 %{
8733 match(Set dst (FmaHF src3 (Binary src1 src2)));
8734 format %{ "fmadd.h $dst, $src1, $src2, $src3\t# $dst = $src1 * $src2 + $src3 fma packedH" %}
8735 ins_encode %{
8736 __ fmadd_h($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, $src3$$FloatRegister);
8737 %}
8738 ins_pipe(pipe_class_default);
8739 %}
8740
8741 // float <-> int
8742
8743 instruct convF2I_reg_reg(iRegINoSp dst, fRegF src) %{
8744 match(Set dst (ConvF2I src));
8745
8746 ins_cost(XFER_COST);
8747 format %{ "fcvt.w.s $dst, $src\t#@convF2I_reg_reg" %}
8748
8749 ins_encode %{
8750 __ fcvt_w_s_safe($dst$$Register, $src$$FloatRegister);
8751 %}
8752
8753 ins_pipe(fp_f2i);
8754 %}
8755
8756 instruct convI2F_reg_reg(fRegF dst, iRegIorL2I src) %{
8757 match(Set dst (ConvI2F src));
8758
8759 ins_cost(XFER_COST);
8760 format %{ "fcvt.s.w $dst, $src\t#@convI2F_reg_reg" %}
8761
8762 ins_encode %{
8763 __ fcvt_s_w(as_FloatRegister($dst$$reg), as_Register($src$$reg));
8764 %}
8765
8766 ins_pipe(fp_i2f);
8767 %}
8768
8769 // float <-> long
8770
8771 instruct convF2L_reg_reg(iRegLNoSp dst, fRegF src) %{
8772 match(Set dst (ConvF2L src));
8773
8774 ins_cost(XFER_COST);
8775 format %{ "fcvt.l.s $dst, $src\t#@convF2L_reg_reg" %}
8776
8777 ins_encode %{
8778 __ fcvt_l_s_safe($dst$$Register, $src$$FloatRegister);
8779 %}
8780
8781 ins_pipe(fp_f2l);
8782 %}
8783
8784 instruct convL2F_reg_reg(fRegF dst, iRegL src) %{
8785 match(Set dst (ConvL2F src));
8786
8787 ins_cost(XFER_COST);
8788 format %{ "fcvt.s.l $dst, $src\t#@convL2F_reg_reg" %}
8789
8790 ins_encode %{
8791 __ fcvt_s_l(as_FloatRegister($dst$$reg), as_Register($src$$reg));
8792 %}
8793
8794 ins_pipe(fp_l2f);
8795 %}
8796
8797 // double <-> int
8798
8799 instruct convD2I_reg_reg(iRegINoSp dst, fRegD src) %{
8800 match(Set dst (ConvD2I src));
8801
8802 ins_cost(XFER_COST);
8803 format %{ "fcvt.w.d $dst, $src\t#@convD2I_reg_reg" %}
8804
8805 ins_encode %{
8806 __ fcvt_w_d_safe($dst$$Register, $src$$FloatRegister);
8807 %}
8808
8809 ins_pipe(fp_d2i);
8810 %}
8811
8812 instruct convI2D_reg_reg(fRegD dst, iRegIorL2I src) %{
8813 match(Set dst (ConvI2D src));
8814
8815 ins_cost(XFER_COST);
8816 format %{ "fcvt.d.w $dst, $src\t#@convI2D_reg_reg" %}
8817
8818 ins_encode %{
8819 __ fcvt_d_w(as_FloatRegister($dst$$reg), as_Register($src$$reg));
8820 %}
8821
8822 ins_pipe(fp_i2d);
8823 %}
8824
8825 // double <-> long
8826
8827 instruct convD2L_reg_reg(iRegLNoSp dst, fRegD src) %{
8828 match(Set dst (ConvD2L src));
8829
8830 ins_cost(XFER_COST);
8831 format %{ "fcvt.l.d $dst, $src\t#@convD2L_reg_reg" %}
8832
8833 ins_encode %{
8834 __ fcvt_l_d_safe($dst$$Register, $src$$FloatRegister);
8835 %}
8836
8837 ins_pipe(fp_d2l);
8838 %}
8839
8840 instruct convL2D_reg_reg(fRegD dst, iRegL src) %{
8841 match(Set dst (ConvL2D src));
8842
8843 ins_cost(XFER_COST);
8844 format %{ "fcvt.d.l $dst, $src\t#@convL2D_reg_reg" %}
8845
8846 ins_encode %{
8847 __ fcvt_d_l(as_FloatRegister($dst$$reg), as_Register($src$$reg));
8848 %}
8849
8850 ins_pipe(fp_l2d);
8851 %}
8852
8853 // Convert oop into int for vectors alignment masking
8854 instruct convP2I(iRegINoSp dst, iRegP src) %{
8855 match(Set dst (ConvL2I (CastP2X src)));
8856
8857 ins_cost(ALU_COST * 2);
8858 format %{ "zext $dst, $src, 32\t# ptr -> int, #@convP2I" %}
8859
8860 ins_encode %{
8861 __ zext($dst$$Register, $src$$Register, 32);
8862 %}
8863
8864 ins_pipe(ialu_reg);
8865 %}
8866
8867 // Convert compressed oop into int for vectors alignment masking
8868 // in case of 32bit oops (heap < 4Gb).
8869 instruct convN2I(iRegINoSp dst, iRegN src)
8870 %{
8871 predicate(CompressedOops::shift() == 0);
8872 match(Set dst (ConvL2I (CastP2X (DecodeN src))));
8873
8874 ins_cost(ALU_COST);
8875 format %{ "mv $dst, $src\t# compressed ptr -> int, #@convN2I" %}
8876
8877 ins_encode %{
8878 __ mv($dst$$Register, $src$$Register);
8879 %}
8880
8881 ins_pipe(ialu_reg);
8882 %}
8883
8884 instruct round_double_reg(iRegLNoSp dst, fRegD src, fRegD ftmp) %{
8885 match(Set dst (RoundD src));
8886
8887 ins_cost(XFER_COST + BRANCH_COST);
8888 effect(TEMP ftmp);
8889 format %{ "java_round_double $dst, $src\t#@round_double_reg" %}
8890
8891 ins_encode %{
8892 __ java_round_double($dst$$Register, as_FloatRegister($src$$reg), as_FloatRegister($ftmp$$reg));
8893 %}
8894
8895 ins_pipe(pipe_slow);
8896 %}
8897
8898 instruct round_float_reg(iRegINoSp dst, fRegF src, fRegF ftmp) %{
8899 match(Set dst (RoundF src));
8900
8901 ins_cost(XFER_COST + BRANCH_COST);
8902 effect(TEMP ftmp);
8903 format %{ "java_round_float $dst, $src\t#@round_float_reg" %}
8904
8905 ins_encode %{
8906 __ java_round_float($dst$$Register, as_FloatRegister($src$$reg), as_FloatRegister($ftmp$$reg));
8907 %}
8908
8909 ins_pipe(pipe_slow);
8910 %}
8911
8912 // Convert oop pointer into compressed form
8913 instruct encodeHeapOop(iRegNNoSp dst, iRegP src) %{
8914 predicate(n->bottom_type()->make_ptr()->ptr() != TypePtr::NotNull);
8915 match(Set dst (EncodeP src));
8916 ins_cost(ALU_COST);
8917 format %{ "encode_heap_oop $dst, $src\t#@encodeHeapOop" %}
8918 ins_encode %{
8919 Register s = $src$$Register;
8920 Register d = $dst$$Register;
8921 __ encode_heap_oop(d, s);
8922 %}
8923 ins_pipe(pipe_class_default);
8924 %}
8925
8926 instruct encodeHeapOop_not_null(iRegNNoSp dst, iRegP src) %{
8927 predicate(n->bottom_type()->make_ptr()->ptr() == TypePtr::NotNull);
8928 match(Set dst (EncodeP src));
8929 ins_cost(ALU_COST);
8930 format %{ "encode_heap_oop_not_null $dst, $src\t#@encodeHeapOop_not_null" %}
8931 ins_encode %{
8932 __ encode_heap_oop_not_null($dst$$Register, $src$$Register);
8933 %}
8934 ins_pipe(pipe_class_default);
8935 %}
8936
8937 instruct decodeHeapOop(iRegPNoSp dst, iRegN src) %{
8938 predicate(n->bottom_type()->is_ptr()->ptr() != TypePtr::NotNull &&
8939 n->bottom_type()->is_ptr()->ptr() != TypePtr::Constant);
8940 match(Set dst (DecodeN src));
8941
8942 ins_cost(0);
8943 format %{ "decode_heap_oop $dst, $src\t#@decodeHeapOop" %}
8944 ins_encode %{
8945 Register s = $src$$Register;
8946 Register d = $dst$$Register;
8947 __ decode_heap_oop(d, s);
8948 %}
8949 ins_pipe(pipe_class_default);
8950 %}
8951
8952 instruct decodeHeapOop_not_null(iRegPNoSp dst, iRegN src) %{
8953 predicate(n->bottom_type()->is_ptr()->ptr() == TypePtr::NotNull ||
8954 n->bottom_type()->is_ptr()->ptr() == TypePtr::Constant);
8955 match(Set dst (DecodeN src));
8956
8957 ins_cost(0);
8958 format %{ "decode_heap_oop_not_null $dst, $src\t#@decodeHeapOop_not_null" %}
8959 ins_encode %{
8960 Register s = $src$$Register;
8961 Register d = $dst$$Register;
8962 __ decode_heap_oop_not_null(d, s);
8963 %}
8964 ins_pipe(pipe_class_default);
8965 %}
8966
8967 // Convert klass pointer into compressed form.
8968 instruct encodeKlass_not_null(iRegNNoSp dst, iRegP src) %{
8969 match(Set dst (EncodePKlass src));
8970
8971 ins_cost(ALU_COST);
8972 format %{ "encode_klass_not_null $dst, $src\t#@encodeKlass_not_null" %}
8973
8974 ins_encode %{
8975 Register src_reg = as_Register($src$$reg);
8976 Register dst_reg = as_Register($dst$$reg);
8977 __ encode_klass_not_null(dst_reg, src_reg, t0);
8978 %}
8979
8980 ins_pipe(pipe_class_default);
8981 %}
8982
8983 instruct decodeKlass_not_null(iRegPNoSp dst, iRegN src, iRegPNoSp tmp) %{
8984 match(Set dst (DecodeNKlass src));
8985
8986 effect(TEMP_DEF dst, TEMP tmp);
8987
8988 ins_cost(ALU_COST);
8989 format %{ "decode_klass_not_null $dst, $src\t#@decodeKlass_not_null" %}
8990
8991 ins_encode %{
8992 Register src_reg = as_Register($src$$reg);
8993 Register dst_reg = as_Register($dst$$reg);
8994 Register tmp_reg = as_Register($tmp$$reg);
8995 __ decode_klass_not_null(dst_reg, src_reg, tmp_reg);
8996 %}
8997
8998 ins_pipe(pipe_class_default);
8999 %}
9000
9001 // stack <-> reg and reg <-> reg shuffles with no conversion
9002
9003 instruct MoveF2I_stack_reg(iRegINoSp dst, stackSlotF src) %{
9004
9005 match(Set dst (MoveF2I src));
9006
9007 effect(DEF dst, USE src);
9008
9009 ins_cost(LOAD_COST);
9010
9011 format %{ "lw $dst, $src\t#@MoveF2I_stack_reg" %}
9012
9013 ins_encode %{
9014 __ lw(as_Register($dst$$reg), Address(sp, $src$$disp));
9015 %}
9016
9017 ins_pipe(iload_reg_reg);
9018
9019 %}
9020
9021 instruct MoveI2F_stack_reg(fRegF dst, stackSlotI src) %{
9022
9023 match(Set dst (MoveI2F src));
9024
9025 effect(DEF dst, USE src);
9026
9027 ins_cost(LOAD_COST);
9028
9029 format %{ "flw $dst, $src\t#@MoveI2F_stack_reg" %}
9030
9031 ins_encode %{
9032 __ flw(as_FloatRegister($dst$$reg), Address(sp, $src$$disp));
9033 %}
9034
9035 ins_pipe(fp_load_mem_s);
9036
9037 %}
9038
9039 instruct MoveD2L_stack_reg(iRegLNoSp dst, stackSlotD src) %{
9040
9041 match(Set dst (MoveD2L src));
9042
9043 effect(DEF dst, USE src);
9044
9045 ins_cost(LOAD_COST);
9046
9047 format %{ "ld $dst, $src\t#@MoveD2L_stack_reg" %}
9048
9049 ins_encode %{
9050 __ ld(as_Register($dst$$reg), Address(sp, $src$$disp));
9051 %}
9052
9053 ins_pipe(iload_reg_reg);
9054
9055 %}
9056
9057 instruct MoveL2D_stack_reg(fRegD dst, stackSlotL src) %{
9058
9059 match(Set dst (MoveL2D src));
9060
9061 effect(DEF dst, USE src);
9062
9063 ins_cost(LOAD_COST);
9064
9065 format %{ "fld $dst, $src\t#@MoveL2D_stack_reg" %}
9066
9067 ins_encode %{
9068 __ fld(as_FloatRegister($dst$$reg), Address(sp, $src$$disp));
9069 %}
9070
9071 ins_pipe(fp_load_mem_d);
9072
9073 %}
9074
9075 instruct MoveF2I_reg_stack(stackSlotI dst, fRegF src) %{
9076
9077 match(Set dst (MoveF2I src));
9078
9079 effect(DEF dst, USE src);
9080
9081 ins_cost(STORE_COST);
9082
9083 format %{ "fsw $src, $dst\t#@MoveF2I_reg_stack" %}
9084
9085 ins_encode %{
9086 __ fsw(as_FloatRegister($src$$reg), Address(sp, $dst$$disp));
9087 %}
9088
9089 ins_pipe(fp_store_reg_s);
9090
9091 %}
9092
9093 instruct MoveI2F_reg_stack(stackSlotF dst, iRegI src) %{
9094
9095 match(Set dst (MoveI2F src));
9096
9097 effect(DEF dst, USE src);
9098
9099 ins_cost(STORE_COST);
9100
9101 format %{ "sw $src, $dst\t#@MoveI2F_reg_stack" %}
9102
9103 ins_encode %{
9104 __ sw(as_Register($src$$reg), Address(sp, $dst$$disp));
9105 %}
9106
9107 ins_pipe(istore_reg_reg);
9108
9109 %}
9110
9111 instruct MoveD2L_reg_stack(stackSlotL dst, fRegD src) %{
9112
9113 match(Set dst (MoveD2L src));
9114
9115 effect(DEF dst, USE src);
9116
9117 ins_cost(STORE_COST);
9118
9119 format %{ "fsd $dst, $src\t#@MoveD2L_reg_stack" %}
9120
9121 ins_encode %{
9122 __ fsd(as_FloatRegister($src$$reg), Address(sp, $dst$$disp));
9123 %}
9124
9125 ins_pipe(fp_store_reg_d);
9126
9127 %}
9128
9129 instruct MoveL2D_reg_stack(stackSlotD dst, iRegL src) %{
9130
9131 match(Set dst (MoveL2D src));
9132
9133 effect(DEF dst, USE src);
9134
9135 ins_cost(STORE_COST);
9136
9137 format %{ "sd $src, $dst\t#@MoveL2D_reg_stack" %}
9138
9139 ins_encode %{
9140 __ sd(as_Register($src$$reg), Address(sp, $dst$$disp));
9141 %}
9142
9143 ins_pipe(istore_reg_reg);
9144
9145 %}
9146
9147 instruct MoveF2I_reg_reg(iRegINoSp dst, fRegF src) %{
9148
9149 match(Set dst (MoveF2I src));
9150
9151 effect(DEF dst, USE src);
9152
9153 ins_cost(FMVX_COST);
9154
9155 format %{ "fmv.x.w $dst, $src\t#@MoveF2I_reg_reg" %}
9156
9157 ins_encode %{
9158 __ fmv_x_w(as_Register($dst$$reg), as_FloatRegister($src$$reg));
9159 %}
9160
9161 ins_pipe(fp_f2i);
9162
9163 %}
9164
9165 instruct MoveI2F_reg_reg(fRegF dst, iRegI src) %{
9166
9167 match(Set dst (MoveI2F src));
9168
9169 effect(DEF dst, USE src);
9170
9171 ins_cost(FMVX_COST);
9172
9173 format %{ "fmv.w.x $dst, $src\t#@MoveI2F_reg_reg" %}
9174
9175 ins_encode %{
9176 __ fmv_w_x(as_FloatRegister($dst$$reg), as_Register($src$$reg));
9177 %}
9178
9179 ins_pipe(fp_i2f);
9180
9181 %}
9182
9183 instruct MoveD2L_reg_reg(iRegLNoSp dst, fRegD src) %{
9184
9185 match(Set dst (MoveD2L src));
9186
9187 effect(DEF dst, USE src);
9188
9189 ins_cost(FMVX_COST);
9190
9191 format %{ "fmv.x.d $dst, $src\t#@MoveD2L_reg_reg" %}
9192
9193 ins_encode %{
9194 __ fmv_x_d(as_Register($dst$$reg), as_FloatRegister($src$$reg));
9195 %}
9196
9197 ins_pipe(fp_d2l);
9198
9199 %}
9200
9201 instruct MoveL2D_reg_reg(fRegD dst, iRegL src) %{
9202
9203 match(Set dst (MoveL2D src));
9204
9205 effect(DEF dst, USE src);
9206
9207 ins_cost(FMVX_COST);
9208
9209 format %{ "fmv.d.x $dst, $src\t#@MoveL2D_reg_reg" %}
9210
9211 ins_encode %{
9212 __ fmv_d_x(as_FloatRegister($dst$$reg), as_Register($src$$reg));
9213 %}
9214
9215 ins_pipe(fp_l2d);
9216
9217 %}
9218
9219 // ============================================================================
9220 // Compare Instructions which set the result float comparisons in dest register.
9221
9222 instruct cmpF3_reg_reg(iRegINoSp dst, fRegF op1, fRegF op2)
9223 %{
9224 match(Set dst (CmpF3 op1 op2));
9225
9226 ins_cost(XFER_COST * 2 + BRANCH_COST + ALU_COST);
9227 format %{ "flt.s $dst, $op2, $op1\t#@cmpF3_reg_reg\n\t"
9228 "bgtz $dst, done\n\t"
9229 "feq.s $dst, $op1, $op2\n\t"
9230 "addi $dst, $dst, -1\n\t"
9231 "done:"
9232 %}
9233
9234 ins_encode %{
9235 // we want -1 for unordered or less than, 0 for equal and 1 for greater than.
9236 __ float_compare(as_Register($dst$$reg), as_FloatRegister($op1$$reg),
9237 as_FloatRegister($op2$$reg), -1 /*unordered_result < 0*/);
9238 %}
9239
9240 ins_pipe(pipe_class_default);
9241 %}
9242
9243 instruct cmpD3_reg_reg(iRegINoSp dst, fRegD op1, fRegD op2)
9244 %{
9245 match(Set dst (CmpD3 op1 op2));
9246
9247 ins_cost(XFER_COST * 2 + BRANCH_COST + ALU_COST);
9248 format %{ "flt.d $dst, $op2, $op1\t#@cmpD3_reg_reg\n\t"
9249 "bgtz $dst, done\n\t"
9250 "feq.d $dst, $op1, $op2\n\t"
9251 "addi $dst, $dst, -1\n\t"
9252 "done:"
9253 %}
9254
9255 ins_encode %{
9256 // we want -1 for unordered or less than, 0 for equal and 1 for greater than.
9257 __ double_compare(as_Register($dst$$reg), as_FloatRegister($op1$$reg), as_FloatRegister($op2$$reg), -1 /*unordered_result < 0*/);
9258 %}
9259
9260 ins_pipe(pipe_class_default);
9261 %}
9262
9263 instruct cmpL3_reg_reg(iRegINoSp dst, iRegL op1, iRegL op2)
9264 %{
9265 match(Set dst (CmpL3 op1 op2));
9266
9267 ins_cost(ALU_COST * 3 + BRANCH_COST);
9268 format %{ "slt $dst, $op2, $op1\t#@cmpL3_reg_reg\n\t"
9269 "bnez $dst, done\n\t"
9270 "slt $dst, $op1, $op2\n\t"
9271 "neg $dst, $dst\n\t"
9272 "done:"
9273 %}
9274 ins_encode %{
9275 __ cmp_l2i(t0, as_Register($op1$$reg), as_Register($op2$$reg));
9276 __ mv(as_Register($dst$$reg), t0);
9277 %}
9278
9279 ins_pipe(pipe_class_default);
9280 %}
9281
9282 instruct cmpUL3_reg_reg(iRegINoSp dst, iRegL op1, iRegL op2)
9283 %{
9284 match(Set dst (CmpUL3 op1 op2));
9285
9286 ins_cost(ALU_COST * 3 + BRANCH_COST);
9287 format %{ "sltu $dst, $op2, $op1\t#@cmpUL3_reg_reg\n\t"
9288 "bnez $dst, done\n\t"
9289 "sltu $dst, $op1, $op2\n\t"
9290 "neg $dst, $dst\n\t"
9291 "done:"
9292 %}
9293 ins_encode %{
9294 __ cmp_ul2i(t0, as_Register($op1$$reg), as_Register($op2$$reg));
9295 __ mv(as_Register($dst$$reg), t0);
9296 %}
9297
9298 ins_pipe(pipe_class_default);
9299 %}
9300
9301 instruct cmpU3_reg_reg(iRegINoSp dst, iRegI op1, iRegI op2)
9302 %{
9303 match(Set dst (CmpU3 op1 op2));
9304
9305 ins_cost(ALU_COST * 3 + BRANCH_COST);
9306 format %{ "sltu $dst, $op2, $op1\t#@cmpU3_reg_reg\n\t"
9307 "bnez $dst, done\n\t"
9308 "sltu $dst, $op1, $op2\n\t"
9309 "neg $dst, $dst\n\t"
9310 "done:"
9311 %}
9312 ins_encode %{
9313 __ cmp_uw2i(t0, as_Register($op1$$reg), as_Register($op2$$reg));
9314 __ mv(as_Register($dst$$reg), t0);
9315 %}
9316
9317 ins_pipe(pipe_class_default);
9318 %}
9319
9320 instruct cmpLTMask_reg_reg(iRegINoSp dst, iRegI p, iRegI q)
9321 %{
9322 match(Set dst (CmpLTMask p q));
9323
9324 ins_cost(2 * ALU_COST);
9325
9326 format %{ "slt $dst, $p, $q\t#@cmpLTMask_reg_reg\n\t"
9327 "subw $dst, zr, $dst\t#@cmpLTMask_reg_reg"
9328 %}
9329
9330 ins_encode %{
9331 __ slt(as_Register($dst$$reg), as_Register($p$$reg), as_Register($q$$reg));
9332 __ subw(as_Register($dst$$reg), zr, as_Register($dst$$reg));
9333 %}
9334
9335 ins_pipe(ialu_reg_reg);
9336 %}
9337
9338 instruct cmpLTMask_reg_zero(iRegINoSp dst, iRegIorL2I op, immI0 zero)
9339 %{
9340 match(Set dst (CmpLTMask op zero));
9341
9342 ins_cost(ALU_COST);
9343
9344 format %{ "sraiw $dst, $dst, 31\t#@cmpLTMask_reg_reg" %}
9345
9346 ins_encode %{
9347 __ sraiw(as_Register($dst$$reg), as_Register($op$$reg), 31);
9348 %}
9349
9350 ins_pipe(ialu_reg_shift);
9351 %}
9352
9353
9354 // ============================================================================
9355 // Max and Min
9356
9357 instruct minI_reg_reg(iRegINoSp dst, iRegI src)
9358 %{
9359 match(Set dst (MinI dst src));
9360
9361 ins_cost(BRANCH_COST + ALU_COST);
9362 format %{"minI_reg_reg $dst, $dst, $src\t#@minI_reg_reg\n\t"%}
9363
9364 ins_encode %{
9365 __ cmov_gt(as_Register($dst$$reg), as_Register($src$$reg),
9366 as_Register($dst$$reg), as_Register($src$$reg));
9367 %}
9368
9369 ins_pipe(pipe_class_compare);
9370 %}
9371
9372 instruct maxI_reg_reg(iRegINoSp dst, iRegI src)
9373 %{
9374 match(Set dst (MaxI dst src));
9375
9376 ins_cost(BRANCH_COST + ALU_COST);
9377 format %{"maxI_reg_reg $dst, $dst, $src\t#@maxI_reg_reg\n\t"%}
9378
9379 ins_encode %{
9380 __ cmov_lt(as_Register($dst$$reg), as_Register($src$$reg),
9381 as_Register($dst$$reg), as_Register($src$$reg));
9382 %}
9383
9384 ins_pipe(pipe_class_compare);
9385 %}
9386
9387 // special case for comparing with zero
9388 // n.b. this is selected in preference to the rule above because it
9389 // avoids loading constant 0 into a source register
9390
9391 instruct minI_reg_zero(iRegINoSp dst, immI0 zero)
9392 %{
9393 match(Set dst (MinI dst zero));
9394 match(Set dst (MinI zero dst));
9395
9396 ins_cost(BRANCH_COST + ALU_COST);
9397 format %{"minI_reg_zero $dst, $dst, zr\t#@minI_reg_zero\n\t"%}
9398
9399 ins_encode %{
9400 __ cmov_gt(as_Register($dst$$reg), zr,
9401 as_Register($dst$$reg), zr);
9402 %}
9403
9404 ins_pipe(pipe_class_compare);
9405 %}
9406
9407 instruct maxI_reg_zero(iRegINoSp dst, immI0 zero)
9408 %{
9409 match(Set dst (MaxI dst zero));
9410 match(Set dst (MaxI zero dst));
9411
9412 ins_cost(BRANCH_COST + ALU_COST);
9413 format %{"maxI_reg_zero $dst, $dst, zr\t#@maxI_reg_zero\n\t"%}
9414
9415 ins_encode %{
9416 __ cmov_lt(as_Register($dst$$reg), zr,
9417 as_Register($dst$$reg), zr);
9418 %}
9419
9420 ins_pipe(pipe_class_compare);
9421 %}
9422
9423 instruct minI_rReg(iRegINoSp dst, iRegI src1, iRegI src2)
9424 %{
9425 match(Set dst (MinI src1 src2));
9426
9427 effect(DEF dst, USE src1, USE src2);
9428
9429 ins_cost(BRANCH_COST + ALU_COST * 2);
9430 format %{"minI_rReg $dst, $src1, $src2\t#@minI_rReg\n\t"%}
9431
9432 ins_encode %{
9433 __ mv(as_Register($dst$$reg), as_Register($src1$$reg));
9434 __ cmov_gt(as_Register($src1$$reg), as_Register($src2$$reg),
9435 as_Register($dst$$reg), as_Register($src2$$reg));
9436 %}
9437
9438 ins_pipe(pipe_class_compare);
9439 %}
9440
9441 instruct maxI_rReg(iRegINoSp dst, iRegI src1, iRegI src2)
9442 %{
9443 match(Set dst (MaxI src1 src2));
9444
9445 effect(DEF dst, USE src1, USE src2);
9446
9447 ins_cost(BRANCH_COST + ALU_COST * 2);
9448 format %{"maxI_rReg $dst, $src1, $src2\t#@maxI_rReg\n\t"%}
9449
9450 ins_encode %{
9451 __ mv(as_Register($dst$$reg), as_Register($src1$$reg));
9452 __ cmov_lt(as_Register($src1$$reg), as_Register($src2$$reg),
9453 as_Register($dst$$reg), as_Register($src2$$reg));
9454 %}
9455
9456 ins_pipe(pipe_class_compare);
9457 %}
9458
9459 // ============================================================================
9460 // Branch Instructions
9461 // Direct Branch.
9462 instruct branch(label lbl)
9463 %{
9464 match(Goto);
9465
9466 effect(USE lbl);
9467
9468 ins_cost(BRANCH_COST);
9469 format %{ "j $lbl\t#@branch" %}
9470
9471 ins_encode(riscv_enc_j(lbl));
9472
9473 ins_pipe(pipe_branch);
9474 %}
9475
9476 // ============================================================================
9477 // Compare and Branch Instructions
9478
9479 // Patterns for short (< 12KiB) variants
9480
9481 // Compare flags and branch near instructions.
9482 instruct cmpFlag_branch(cmpOpEqNe cmp, rFlagsReg cr, label lbl) %{
9483 match(If cmp cr);
9484 effect(USE lbl);
9485
9486 ins_cost(BRANCH_COST);
9487 format %{ "b$cmp $cr, zr, $lbl\t#@cmpFlag_branch" %}
9488
9489 ins_encode %{
9490 __ enc_cmpEqNe_imm0_branch($cmp$$cmpcode, as_Register($cr$$reg), *($lbl$$label));
9491 %}
9492 ins_pipe(pipe_cmpz_branch);
9493 ins_short_branch(1);
9494 %}
9495
9496 // Compare signed int and branch near instructions
9497 instruct cmpI_branch(cmpOp cmp, iRegI op1, iRegI op2, label lbl)
9498 %{
9499 // Same match rule as `far_cmpI_branch'.
9500 match(If cmp (CmpI op1 op2));
9501
9502 effect(USE lbl);
9503
9504 ins_cost(BRANCH_COST);
9505
9506 format %{ "b$cmp $op1, $op2, $lbl\t#@cmpI_branch" %}
9507
9508 ins_encode %{
9509 __ cmp_branch($cmp$$cmpcode, as_Register($op1$$reg), as_Register($op2$$reg), *($lbl$$label));
9510 %}
9511
9512 ins_pipe(pipe_cmp_branch);
9513 ins_short_branch(1);
9514 %}
9515
9516 instruct cmpI_loop(cmpOp cmp, iRegI op1, iRegI op2, label lbl)
9517 %{
9518 // Same match rule as `far_cmpI_loop'.
9519 match(CountedLoopEnd cmp (CmpI op1 op2));
9520
9521 effect(USE lbl);
9522
9523 ins_cost(BRANCH_COST);
9524
9525 format %{ "b$cmp $op1, $op2, $lbl\t#@cmpI_loop" %}
9526
9527 ins_encode %{
9528 __ cmp_branch($cmp$$cmpcode, as_Register($op1$$reg), as_Register($op2$$reg), *($lbl$$label));
9529 %}
9530
9531 ins_pipe(pipe_cmp_branch);
9532 ins_short_branch(1);
9533 %}
9534
9535 // Compare unsigned int and branch near instructions
9536 instruct cmpU_branch(cmpOpU cmp, iRegI op1, iRegI op2, label lbl)
9537 %{
9538 // Same match rule as `far_cmpU_branch'.
9539 match(If cmp (CmpU op1 op2));
9540
9541 effect(USE lbl);
9542
9543 ins_cost(BRANCH_COST);
9544
9545 format %{ "b$cmp $op1, $op2, $lbl\t#@cmpU_branch" %}
9546
9547 ins_encode %{
9548 __ cmp_branch($cmp$$cmpcode | C2_MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg),
9549 as_Register($op2$$reg), *($lbl$$label));
9550 %}
9551
9552 ins_pipe(pipe_cmp_branch);
9553 ins_short_branch(1);
9554 %}
9555
9556 // Compare signed long and branch near instructions
9557 instruct cmpL_branch(cmpOp cmp, iRegL op1, iRegL op2, label lbl)
9558 %{
9559 // Same match rule as `far_cmpL_branch'.
9560 match(If cmp (CmpL op1 op2));
9561
9562 effect(USE lbl);
9563
9564 ins_cost(BRANCH_COST);
9565
9566 format %{ "b$cmp $op1, $op2, $lbl\t#@cmpL_branch" %}
9567
9568 ins_encode %{
9569 __ cmp_branch($cmp$$cmpcode, as_Register($op1$$reg), as_Register($op2$$reg), *($lbl$$label));
9570 %}
9571
9572 ins_pipe(pipe_cmp_branch);
9573 ins_short_branch(1);
9574 %}
9575
9576 instruct cmpL_loop(cmpOp cmp, iRegL op1, iRegL op2, label lbl)
9577 %{
9578 // Same match rule as `far_cmpL_loop'.
9579 match(CountedLoopEnd cmp (CmpL op1 op2));
9580
9581 effect(USE lbl);
9582
9583 ins_cost(BRANCH_COST);
9584
9585 format %{ "b$cmp $op1, $op2, $lbl\t#@cmpL_loop" %}
9586
9587 ins_encode %{
9588 __ cmp_branch($cmp$$cmpcode, as_Register($op1$$reg), as_Register($op2$$reg), *($lbl$$label));
9589 %}
9590
9591 ins_pipe(pipe_cmp_branch);
9592 ins_short_branch(1);
9593 %}
9594
9595 // Compare unsigned long and branch near instructions
9596 instruct cmpUL_branch(cmpOpU cmp, iRegL op1, iRegL op2, label lbl)
9597 %{
9598 // Same match rule as `far_cmpUL_branch'.
9599 match(If cmp (CmpUL op1 op2));
9600
9601 effect(USE lbl);
9602
9603 ins_cost(BRANCH_COST);
9604 format %{ "b$cmp $op1, $op2, $lbl\t#@cmpUL_branch" %}
9605
9606 ins_encode %{
9607 __ cmp_branch($cmp$$cmpcode | C2_MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg),
9608 as_Register($op2$$reg), *($lbl$$label));
9609 %}
9610
9611 ins_pipe(pipe_cmp_branch);
9612 ins_short_branch(1);
9613 %}
9614
9615 // Compare pointer and branch near instructions
9616 instruct cmpP_branch(cmpOpU cmp, iRegP op1, iRegP op2, label lbl)
9617 %{
9618 // Same match rule as `far_cmpP_branch'.
9619 match(If cmp (CmpP op1 op2));
9620
9621 effect(USE lbl);
9622
9623 ins_cost(BRANCH_COST);
9624
9625 format %{ "b$cmp $op1, $op2, $lbl\t#@cmpP_branch" %}
9626
9627 ins_encode %{
9628 __ cmp_branch($cmp$$cmpcode | C2_MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg),
9629 as_Register($op2$$reg), *($lbl$$label));
9630 %}
9631
9632 ins_pipe(pipe_cmp_branch);
9633 ins_short_branch(1);
9634 %}
9635
9636 // Compare narrow pointer and branch near instructions
9637 instruct cmpN_branch(cmpOpU cmp, iRegN op1, iRegN op2, label lbl)
9638 %{
9639 // Same match rule as `far_cmpN_branch'.
9640 match(If cmp (CmpN op1 op2));
9641
9642 effect(USE lbl);
9643
9644 ins_cost(BRANCH_COST);
9645
9646 format %{ "b$cmp $op1, $op2, $lbl\t#@cmpN_branch" %}
9647
9648 ins_encode %{
9649 __ cmp_branch($cmp$$cmpcode | C2_MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg),
9650 as_Register($op2$$reg), *($lbl$$label));
9651 %}
9652
9653 ins_pipe(pipe_cmp_branch);
9654 ins_short_branch(1);
9655 %}
9656
9657 // Compare float and branch near instructions
9658 instruct cmpF_branch(cmpOp cmp, fRegF op1, fRegF op2, label lbl)
9659 %{
9660 // Same match rule as `far_cmpF_branch'.
9661 match(If cmp (CmpF op1 op2));
9662
9663 effect(USE lbl);
9664
9665 ins_cost(XFER_COST + BRANCH_COST);
9666 format %{ "float_b$cmp $op1, $op2, $lbl \t#@cmpF_branch"%}
9667
9668 ins_encode %{
9669 __ float_cmp_branch($cmp$$cmpcode, as_FloatRegister($op1$$reg), as_FloatRegister($op2$$reg), *($lbl$$label));
9670 %}
9671
9672 ins_pipe(pipe_class_compare);
9673 ins_short_branch(1);
9674 %}
9675
9676 // Compare double and branch near instructions
9677 instruct cmpD_branch(cmpOp cmp, fRegD op1, fRegD op2, label lbl)
9678 %{
9679 // Same match rule as `far_cmpD_branch'.
9680 match(If cmp (CmpD op1 op2));
9681 effect(USE lbl);
9682
9683 ins_cost(XFER_COST + BRANCH_COST);
9684 format %{ "double_b$cmp $op1, $op2, $lbl\t#@cmpD_branch"%}
9685
9686 ins_encode %{
9687 __ float_cmp_branch($cmp$$cmpcode | C2_MacroAssembler::double_branch_mask, as_FloatRegister($op1$$reg),
9688 as_FloatRegister($op2$$reg), *($lbl$$label));
9689 %}
9690
9691 ins_pipe(pipe_class_compare);
9692 ins_short_branch(1);
9693 %}
9694
9695 // Compare signed int with zero and branch near instructions
9696 instruct cmpI_reg_imm0_branch(cmpOp cmp, iRegI op1, immI0 zero, label lbl)
9697 %{
9698 // Same match rule as `far_cmpI_reg_imm0_branch'.
9699 match(If cmp (CmpI op1 zero));
9700
9701 effect(USE op1, USE lbl);
9702
9703 ins_cost(BRANCH_COST);
9704 format %{ "b$cmp $op1, zr, $lbl\t#@cmpI_reg_imm0_branch" %}
9705
9706 ins_encode %{
9707 __ cmp_branch($cmp$$cmpcode, as_Register($op1$$reg), zr, *($lbl$$label));
9708 %}
9709
9710 ins_pipe(pipe_cmpz_branch);
9711 ins_short_branch(1);
9712 %}
9713
9714 instruct cmpI_reg_imm0_loop(cmpOp cmp, iRegI op1, immI0 zero, label lbl)
9715 %{
9716 // Same match rule as `far_cmpI_reg_imm0_loop'.
9717 match(CountedLoopEnd cmp (CmpI op1 zero));
9718
9719 effect(USE op1, USE lbl);
9720
9721 ins_cost(BRANCH_COST);
9722
9723 format %{ "b$cmp $op1, zr, $lbl\t#@cmpI_reg_imm0_loop" %}
9724
9725 ins_encode %{
9726 __ cmp_branch($cmp$$cmpcode, as_Register($op1$$reg), zr, *($lbl$$label));
9727 %}
9728
9729 ins_pipe(pipe_cmpz_branch);
9730 ins_short_branch(1);
9731 %}
9732
9733 // Compare unsigned int with zero and branch near instructions
9734 instruct cmpUEqNeLeGt_reg_imm0_branch(cmpOpUEqNeLeGt cmp, iRegI op1, immI0 zero, label lbl)
9735 %{
9736 // Same match rule as `far_cmpUEqNeLeGt_reg_imm0_branch'.
9737 match(If cmp (CmpU op1 zero));
9738
9739 effect(USE op1, USE lbl);
9740
9741 ins_cost(BRANCH_COST);
9742
9743 format %{ "b$cmp $op1, zr, $lbl\t#@cmpUEqNeLeGt_reg_imm0_branch" %}
9744
9745 ins_encode %{
9746 __ enc_cmpUEqNeLeGt_imm0_branch($cmp$$cmpcode, as_Register($op1$$reg), *($lbl$$label));
9747 %}
9748
9749 ins_pipe(pipe_cmpz_branch);
9750 ins_short_branch(1);
9751 %}
9752
9753 // Compare signed long with zero and branch near instructions
9754 instruct cmpL_reg_imm0_branch(cmpOp cmp, iRegL op1, immL0 zero, label lbl)
9755 %{
9756 // Same match rule as `far_cmpL_reg_imm0_branch'.
9757 match(If cmp (CmpL op1 zero));
9758
9759 effect(USE op1, USE lbl);
9760
9761 ins_cost(BRANCH_COST);
9762
9763 format %{ "b$cmp $op1, zr, $lbl\t#@cmpL_reg_imm0_branch" %}
9764
9765 ins_encode %{
9766 __ cmp_branch($cmp$$cmpcode, as_Register($op1$$reg), zr, *($lbl$$label));
9767 %}
9768
9769 ins_pipe(pipe_cmpz_branch);
9770 ins_short_branch(1);
9771 %}
9772
9773 instruct cmpL_reg_imm0_loop(cmpOp cmp, iRegL op1, immL0 zero, label lbl)
9774 %{
9775 // Same match rule as `far_cmpL_reg_imm0_loop'.
9776 match(CountedLoopEnd cmp (CmpL op1 zero));
9777
9778 effect(USE op1, USE lbl);
9779
9780 ins_cost(BRANCH_COST);
9781
9782 format %{ "b$cmp $op1, zr, $lbl\t#@cmpL_reg_imm0_loop" %}
9783
9784 ins_encode %{
9785 __ cmp_branch($cmp$$cmpcode, as_Register($op1$$reg), zr, *($lbl$$label));
9786 %}
9787
9788 ins_pipe(pipe_cmpz_branch);
9789 ins_short_branch(1);
9790 %}
9791
9792 // Compare unsigned long with zero and branch near instructions
9793 instruct cmpULEqNeLeGt_reg_imm0_branch(cmpOpUEqNeLeGt cmp, iRegL op1, immL0 zero, label lbl)
9794 %{
9795 // Same match rule as `far_cmpULEqNeLeGt_reg_imm0_branch'.
9796 match(If cmp (CmpUL op1 zero));
9797
9798 effect(USE op1, USE lbl);
9799
9800 ins_cost(BRANCH_COST);
9801
9802 format %{ "b$cmp $op1, zr, $lbl\t#@cmpULEqNeLeGt_reg_imm0_branch" %}
9803
9804 ins_encode %{
9805 __ enc_cmpUEqNeLeGt_imm0_branch($cmp$$cmpcode, as_Register($op1$$reg), *($lbl$$label));
9806 %}
9807
9808 ins_pipe(pipe_cmpz_branch);
9809 ins_short_branch(1);
9810 %}
9811
9812 // Compare pointer with zero and branch near instructions
9813 instruct cmpP_imm0_branch(cmpOpEqNe cmp, iRegP op1, immP0 zero, label lbl) %{
9814 // Same match rule as `far_cmpP_reg_imm0_branch'.
9815 match(If cmp (CmpP op1 zero));
9816 effect(USE lbl);
9817
9818 ins_cost(BRANCH_COST);
9819 format %{ "b$cmp $op1, zr, $lbl\t#@cmpP_imm0_branch" %}
9820
9821 ins_encode %{
9822 __ enc_cmpEqNe_imm0_branch($cmp$$cmpcode, as_Register($op1$$reg), *($lbl$$label));
9823 %}
9824
9825 ins_pipe(pipe_cmpz_branch);
9826 ins_short_branch(1);
9827 %}
9828
9829 // Compare narrow pointer with zero and branch near instructions
9830 instruct cmpN_imm0_branch(cmpOpEqNe cmp, iRegN op1, immN0 zero, label lbl) %{
9831 // Same match rule as `far_cmpN_reg_imm0_branch'.
9832 match(If cmp (CmpN op1 zero));
9833 effect(USE lbl);
9834
9835 ins_cost(BRANCH_COST);
9836
9837 format %{ "b$cmp $op1, zr, $lbl\t#@cmpN_imm0_branch" %}
9838
9839 ins_encode %{
9840 __ enc_cmpEqNe_imm0_branch($cmp$$cmpcode, as_Register($op1$$reg), *($lbl$$label));
9841 %}
9842
9843 ins_pipe(pipe_cmpz_branch);
9844 ins_short_branch(1);
9845 %}
9846
9847 // Compare narrow pointer with pointer zero and branch near instructions
9848 instruct cmpP_narrowOop_imm0_branch(cmpOpEqNe cmp, iRegN op1, immP0 zero, label lbl) %{
9849 // Same match rule as `far_cmpP_narrowOop_imm0_branch'.
9850 match(If cmp (CmpP (DecodeN op1) zero));
9851 effect(USE lbl);
9852
9853 ins_cost(BRANCH_COST);
9854 format %{ "b$cmp $op1, zr, $lbl\t#@cmpP_narrowOop_imm0_branch" %}
9855
9856 ins_encode %{
9857 __ enc_cmpEqNe_imm0_branch($cmp$$cmpcode, as_Register($op1$$reg), *($lbl$$label));
9858 %}
9859
9860 ins_pipe(pipe_cmpz_branch);
9861 ins_short_branch(1);
9862 %}
9863
9864 // Patterns for far (20KiB) variants
9865
9866 instruct far_cmpFlag_branch(cmpOp cmp, rFlagsReg cr, label lbl) %{
9867 match(If cmp cr);
9868 effect(USE lbl);
9869
9870 ins_cost(BRANCH_COST);
9871 format %{ "far_b$cmp $cr, zr, $lbl\t#@far_cmpFlag_branch"%}
9872
9873 ins_encode %{
9874 __ enc_cmpEqNe_imm0_branch($cmp$$cmpcode, as_Register($cr$$reg), *($lbl$$label), /* is_far */ true);
9875 %}
9876
9877 ins_pipe(pipe_cmpz_branch);
9878 %}
9879
9880 // Compare signed int and branch far instructions
9881 instruct far_cmpI_branch(cmpOp cmp, iRegI op1, iRegI op2, label lbl) %{
9882 match(If cmp (CmpI op1 op2));
9883 effect(USE lbl);
9884
9885 ins_cost(BRANCH_COST * 2);
9886
9887 // the format instruction [far_b$cmp] here is be used as two insructions
9888 // in macroassembler: b$not_cmp(op1, op2, done), j($lbl), bind(done)
9889 format %{ "far_b$cmp $op1, $op2, $lbl\t#@far_cmpI_branch" %}
9890
9891 ins_encode %{
9892 __ cmp_branch($cmp$$cmpcode, as_Register($op1$$reg), as_Register($op2$$reg), *($lbl$$label), /* is_far */ true);
9893 %}
9894
9895 ins_pipe(pipe_cmp_branch);
9896 %}
9897
9898 instruct far_cmpI_loop(cmpOp cmp, iRegI op1, iRegI op2, label lbl) %{
9899 match(CountedLoopEnd cmp (CmpI op1 op2));
9900 effect(USE lbl);
9901
9902 ins_cost(BRANCH_COST * 2);
9903 format %{ "far_b$cmp $op1, $op2, $lbl\t#@far_cmpI_loop" %}
9904
9905 ins_encode %{
9906 __ cmp_branch($cmp$$cmpcode, as_Register($op1$$reg), as_Register($op2$$reg), *($lbl$$label), /* is_far */ true);
9907 %}
9908
9909 ins_pipe(pipe_cmp_branch);
9910 %}
9911
9912 instruct far_cmpU_branch(cmpOpU cmp, iRegI op1, iRegI op2, label lbl) %{
9913 match(If cmp (CmpU op1 op2));
9914 effect(USE lbl);
9915
9916 ins_cost(BRANCH_COST * 2);
9917 format %{ "far_b$cmp $op1, $op2, $lbl\t#@far_cmpU_branch" %}
9918
9919 ins_encode %{
9920 __ cmp_branch($cmp$$cmpcode | C2_MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg),
9921 as_Register($op2$$reg), *($lbl$$label), /* is_far */ true);
9922 %}
9923
9924 ins_pipe(pipe_cmp_branch);
9925 %}
9926
9927 instruct far_cmpL_branch(cmpOp cmp, iRegL op1, iRegL op2, label lbl) %{
9928 match(If cmp (CmpL op1 op2));
9929 effect(USE lbl);
9930
9931 ins_cost(BRANCH_COST * 2);
9932 format %{ "far_b$cmp $op1, $op2, $lbl\t#@far_cmpL_branch" %}
9933
9934 ins_encode %{
9935 __ cmp_branch($cmp$$cmpcode, as_Register($op1$$reg), as_Register($op2$$reg), *($lbl$$label), /* is_far */ true);
9936 %}
9937
9938 ins_pipe(pipe_cmp_branch);
9939 %}
9940
9941 instruct far_cmpLloop(cmpOp cmp, iRegL op1, iRegL op2, label lbl) %{
9942 match(CountedLoopEnd cmp (CmpL op1 op2));
9943 effect(USE lbl);
9944
9945 ins_cost(BRANCH_COST * 2);
9946 format %{ "far_b$cmp $op1, $op2, $lbl\t#@far_cmpL_loop" %}
9947
9948 ins_encode %{
9949 __ cmp_branch($cmp$$cmpcode, as_Register($op1$$reg), as_Register($op2$$reg), *($lbl$$label), /* is_far */ true);
9950 %}
9951
9952 ins_pipe(pipe_cmp_branch);
9953 %}
9954
9955 instruct far_cmpUL_branch(cmpOpU cmp, iRegL op1, iRegL op2, label lbl) %{
9956 match(If cmp (CmpUL op1 op2));
9957 effect(USE lbl);
9958
9959 ins_cost(BRANCH_COST * 2);
9960 format %{ "far_b$cmp $op1, $op2, $lbl\t#@far_cmpUL_branch" %}
9961
9962 ins_encode %{
9963 __ cmp_branch($cmp$$cmpcode | C2_MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg),
9964 as_Register($op2$$reg), *($lbl$$label), /* is_far */ true);
9965 %}
9966
9967 ins_pipe(pipe_cmp_branch);
9968 %}
9969
9970 instruct far_cmpP_branch(cmpOpU cmp, iRegP op1, iRegP op2, label lbl)
9971 %{
9972 match(If cmp (CmpP op1 op2));
9973
9974 effect(USE lbl);
9975
9976 ins_cost(BRANCH_COST * 2);
9977
9978 format %{ "far_b$cmp $op1, $op2, $lbl\t#@far_cmpP_branch" %}
9979
9980 ins_encode %{
9981 __ cmp_branch($cmp$$cmpcode | C2_MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg),
9982 as_Register($op2$$reg), *($lbl$$label), /* is_far */ true);
9983 %}
9984
9985 ins_pipe(pipe_cmp_branch);
9986 %}
9987
9988 instruct far_cmpN_branch(cmpOpU cmp, iRegN op1, iRegN op2, label lbl)
9989 %{
9990 match(If cmp (CmpN op1 op2));
9991
9992 effect(USE lbl);
9993
9994 ins_cost(BRANCH_COST * 2);
9995
9996 format %{ "far_b$cmp $op1, $op2, $lbl\t#@far_cmpN_branch" %}
9997
9998 ins_encode %{
9999 __ cmp_branch($cmp$$cmpcode | C2_MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg),
10000 as_Register($op2$$reg), *($lbl$$label), /* is_far */ true);
10001 %}
10002
10003 ins_pipe(pipe_cmp_branch);
10004 %}
10005
10006 // Float compare and branch instructions
10007 instruct far_cmpF_branch(cmpOp cmp, fRegF op1, fRegF op2, label lbl)
10008 %{
10009 match(If cmp (CmpF op1 op2));
10010
10011 effect(USE lbl);
10012
10013 ins_cost(XFER_COST + BRANCH_COST * 2);
10014 format %{ "far_float_b$cmp $op1, $op2, $lbl\t#@far_cmpF_branch"%}
10015
10016 ins_encode %{
10017 __ float_cmp_branch($cmp$$cmpcode, as_FloatRegister($op1$$reg), as_FloatRegister($op2$$reg),
10018 *($lbl$$label), /* is_far */ true);
10019 %}
10020
10021 ins_pipe(pipe_class_compare);
10022 %}
10023
10024 // Double compare and branch instructions
10025 instruct far_cmpD_branch(cmpOp cmp, fRegD op1, fRegD op2, label lbl)
10026 %{
10027 match(If cmp (CmpD op1 op2));
10028 effect(USE lbl);
10029
10030 ins_cost(XFER_COST + BRANCH_COST * 2);
10031 format %{ "far_double_b$cmp $op1, $op2, $lbl\t#@far_cmpD_branch"%}
10032
10033 ins_encode %{
10034 __ float_cmp_branch($cmp$$cmpcode | C2_MacroAssembler::double_branch_mask, as_FloatRegister($op1$$reg),
10035 as_FloatRegister($op2$$reg), *($lbl$$label), /* is_far */ true);
10036 %}
10037
10038 ins_pipe(pipe_class_compare);
10039 %}
10040
10041 instruct far_cmpI_reg_imm0_branch(cmpOp cmp, iRegI op1, immI0 zero, label lbl)
10042 %{
10043 match(If cmp (CmpI op1 zero));
10044
10045 effect(USE op1, USE lbl);
10046
10047 ins_cost(BRANCH_COST * 2);
10048
10049 format %{ "far_b$cmp $op1, zr, $lbl\t#@far_cmpI_reg_imm0_branch" %}
10050
10051 ins_encode %{
10052 __ cmp_branch($cmp$$cmpcode, as_Register($op1$$reg), zr, *($lbl$$label), /* is_far */ true);
10053 %}
10054
10055 ins_pipe(pipe_cmpz_branch);
10056 %}
10057
10058 instruct far_cmpI_reg_imm0_loop(cmpOp cmp, iRegI op1, immI0 zero, label lbl)
10059 %{
10060 match(CountedLoopEnd cmp (CmpI op1 zero));
10061
10062 effect(USE op1, USE lbl);
10063
10064 ins_cost(BRANCH_COST * 2);
10065
10066 format %{ "far_b$cmp $op1, zr, $lbl\t#@far_cmpI_reg_imm0_loop" %}
10067
10068 ins_encode %{
10069 __ cmp_branch($cmp$$cmpcode, as_Register($op1$$reg), zr, *($lbl$$label), /* is_far */ true);
10070 %}
10071
10072 ins_pipe(pipe_cmpz_branch);
10073 %}
10074
10075 instruct far_cmpUEqNeLeGt_imm0_branch(cmpOpUEqNeLeGt cmp, iRegI op1, immI0 zero, label lbl)
10076 %{
10077 match(If cmp (CmpU op1 zero));
10078
10079 effect(USE op1, USE lbl);
10080
10081 ins_cost(BRANCH_COST * 2);
10082
10083 format %{ "far_b$cmp $op1, zr, $lbl\t#@far_cmpUEqNeLeGt_imm0_branch" %}
10084
10085 ins_encode %{
10086 __ enc_cmpUEqNeLeGt_imm0_branch($cmp$$cmpcode, as_Register($op1$$reg), *($lbl$$label), /* is_far */ true);
10087 %}
10088
10089 ins_pipe(pipe_cmpz_branch);
10090 %}
10091
10092 // compare lt/ge unsigned instructs has no short instruct with same match
10093 instruct far_cmpULtGe_reg_imm0_branch(cmpOpULtGe cmp, iRegI op1, immI0 zero, label lbl)
10094 %{
10095 match(If cmp (CmpU op1 zero));
10096
10097 effect(USE op1, USE lbl);
10098
10099 ins_cost(BRANCH_COST);
10100
10101 format %{ "j $lbl if $cmp == ge\t#@far_cmpULtGe_reg_imm0_branch" %}
10102
10103 ins_encode(riscv_enc_far_cmpULtGe_imm0_branch(cmp, op1, lbl));
10104
10105 ins_pipe(pipe_cmpz_branch);
10106 %}
10107
10108 instruct far_cmpL_reg_imm0_branch(cmpOp cmp, iRegL op1, immL0 zero, label lbl)
10109 %{
10110 match(If cmp (CmpL op1 zero));
10111
10112 effect(USE op1, USE lbl);
10113
10114 ins_cost(BRANCH_COST * 2);
10115
10116 format %{ "far_b$cmp $op1, zr, $lbl\t#@far_cmpL_reg_imm0_branch" %}
10117
10118 ins_encode %{
10119 __ cmp_branch($cmp$$cmpcode, as_Register($op1$$reg), zr, *($lbl$$label), /* is_far */ true);
10120 %}
10121
10122 ins_pipe(pipe_cmpz_branch);
10123 %}
10124
10125 instruct far_cmpL_reg_imm0_loop(cmpOp cmp, iRegL op1, immL0 zero, label lbl)
10126 %{
10127 match(CountedLoopEnd cmp (CmpL op1 zero));
10128
10129 effect(USE op1, USE lbl);
10130
10131 ins_cost(BRANCH_COST * 2);
10132
10133 format %{ "far_b$cmp $op1, zr, $lbl\t#@far_cmpL_reg_imm0_loop" %}
10134
10135 ins_encode %{
10136 __ cmp_branch($cmp$$cmpcode, as_Register($op1$$reg), zr, *($lbl$$label), /* is_far */ true);
10137 %}
10138
10139 ins_pipe(pipe_cmpz_branch);
10140 %}
10141
10142 instruct far_cmpULEqNeLeGt_reg_imm0_branch(cmpOpUEqNeLeGt cmp, iRegL op1, immL0 zero, label lbl)
10143 %{
10144 match(If cmp (CmpUL op1 zero));
10145
10146 effect(USE op1, USE lbl);
10147
10148 ins_cost(BRANCH_COST * 2);
10149
10150 format %{ "far_b$cmp $op1, zr, $lbl\t#@far_cmpULEqNeLeGt_reg_imm0_branch" %}
10151
10152 ins_encode %{
10153 __ enc_cmpUEqNeLeGt_imm0_branch($cmp$$cmpcode, as_Register($op1$$reg), *($lbl$$label), /* is_far */ true);
10154 %}
10155
10156 ins_pipe(pipe_cmpz_branch);
10157 %}
10158
10159 // compare lt/ge unsigned instructs has no short instruct with same match
10160 instruct far_cmpULLtGe_reg_imm0_branch(cmpOpULtGe cmp, iRegL op1, immL0 zero, label lbl)
10161 %{
10162 match(If cmp (CmpUL op1 zero));
10163
10164 effect(USE op1, USE lbl);
10165
10166 ins_cost(BRANCH_COST);
10167
10168 format %{ "j $lbl if $cmp == ge\t#@far_cmpULLtGe_reg_imm0_branch" %}
10169
10170 ins_encode(riscv_enc_far_cmpULtGe_imm0_branch(cmp, op1, lbl));
10171
10172 ins_pipe(pipe_cmpz_branch);
10173 %}
10174
10175 instruct far_cmpP_imm0_branch(cmpOpEqNe cmp, iRegP op1, immP0 zero, label lbl) %{
10176 match(If cmp (CmpP op1 zero));
10177 effect(USE lbl);
10178
10179 ins_cost(BRANCH_COST * 2);
10180 format %{ "far_b$cmp $op1, zr, $lbl\t#@far_cmpP_imm0_branch" %}
10181
10182 ins_encode %{
10183 __ enc_cmpEqNe_imm0_branch($cmp$$cmpcode, as_Register($op1$$reg), *($lbl$$label), /* is_far */ true);
10184 %}
10185
10186 ins_pipe(pipe_cmpz_branch);
10187 %}
10188
10189 instruct far_cmpN_imm0_branch(cmpOpEqNe cmp, iRegN op1, immN0 zero, label lbl) %{
10190 match(If cmp (CmpN op1 zero));
10191 effect(USE lbl);
10192
10193 ins_cost(BRANCH_COST * 2);
10194
10195 format %{ "far_b$cmp $op1, zr, $lbl\t#@far_cmpN_imm0_branch" %}
10196
10197 ins_encode %{
10198 __ enc_cmpEqNe_imm0_branch($cmp$$cmpcode, as_Register($op1$$reg), *($lbl$$label), /* is_far */ true);
10199 %}
10200
10201 ins_pipe(pipe_cmpz_branch);
10202 %}
10203
10204 instruct far_cmpP_narrowOop_imm0_branch(cmpOpEqNe cmp, iRegN op1, immP0 zero, label lbl) %{
10205 match(If cmp (CmpP (DecodeN op1) zero));
10206 effect(USE lbl);
10207
10208 ins_cost(BRANCH_COST * 2);
10209 format %{ "far_b$cmp $op1, zr, $lbl\t#@far_cmpP_narrowOop_imm0_branch" %}
10210
10211 ins_encode %{
10212 __ enc_cmpEqNe_imm0_branch($cmp$$cmpcode, as_Register($op1$$reg), *($lbl$$label), /* is_far */ true);
10213 %}
10214
10215 ins_pipe(pipe_cmpz_branch);
10216 %}
10217
10218 // ============================================================================
10219 // Conditional Move Instructions
10220
10221 // --------- CMoveI ---------
10222
10223 instruct cmovI_cmpI(iRegINoSp dst, iRegI src, iRegI op1, iRegI op2, cmpOp cop) %{
10224 match(Set dst (CMoveI (Binary cop (CmpI op1 op2)) (Binary dst src)));
10225 ins_cost(ALU_COST + BRANCH_COST);
10226
10227 format %{
10228 "CMoveI $dst, ($op1 $cop $op2), $dst, $src\t#@cmovI_cmpI\n\t"
10229 %}
10230
10231 ins_encode %{
10232 __ enc_cmove($cop$$cmpcode,
10233 as_Register($op1$$reg), as_Register($op2$$reg),
10234 as_Register($dst$$reg), as_Register($src$$reg));
10235 %}
10236
10237 ins_pipe(pipe_class_compare);
10238 %}
10239
10240 instruct cmovI_cmpU(iRegINoSp dst, iRegI src, iRegI op1, iRegI op2, cmpOpU cop) %{
10241 match(Set dst (CMoveI (Binary cop (CmpU op1 op2)) (Binary dst src)));
10242 ins_cost(ALU_COST + BRANCH_COST);
10243
10244 format %{
10245 "CMoveI $dst, ($op1 $cop $op2), $dst, $src\t#@cmovI_cmpU\n\t"
10246 %}
10247
10248 ins_encode %{
10249 __ enc_cmove($cop$$cmpcode | C2_MacroAssembler::unsigned_branch_mask,
10250 as_Register($op1$$reg), as_Register($op2$$reg),
10251 as_Register($dst$$reg), as_Register($src$$reg));
10252 %}
10253
10254 ins_pipe(pipe_class_compare);
10255 %}
10256
10257 instruct cmovI_cmpL(iRegINoSp dst, iRegI src, iRegL op1, iRegL op2, cmpOp cop) %{
10258 match(Set dst (CMoveI (Binary cop (CmpL op1 op2)) (Binary dst src)));
10259 ins_cost(ALU_COST + BRANCH_COST);
10260
10261 format %{
10262 "CMoveI $dst, ($op1 $cop $op2), $dst, $src\t#@cmovI_cmpL\n\t"
10263 %}
10264
10265 ins_encode %{
10266 __ enc_cmove($cop$$cmpcode,
10267 as_Register($op1$$reg), as_Register($op2$$reg),
10268 as_Register($dst$$reg), as_Register($src$$reg));
10269 %}
10270
10271 ins_pipe(pipe_class_compare);
10272 %}
10273
10274 instruct cmovI_cmpUL(iRegINoSp dst, iRegI src, iRegL op1, iRegL op2, cmpOpU cop) %{
10275 match(Set dst (CMoveI (Binary cop (CmpUL op1 op2)) (Binary dst src)));
10276 ins_cost(ALU_COST + BRANCH_COST);
10277
10278 format %{
10279 "CMoveI $dst, ($op1 $cop $op2), $dst, $src\t#@cmovI_cmpUL\n\t"
10280 %}
10281
10282 ins_encode %{
10283 __ enc_cmove($cop$$cmpcode | C2_MacroAssembler::unsigned_branch_mask,
10284 as_Register($op1$$reg), as_Register($op2$$reg),
10285 as_Register($dst$$reg), as_Register($src$$reg));
10286 %}
10287
10288 ins_pipe(pipe_class_compare);
10289 %}
10290
10291 instruct cmovI_cmpF(iRegINoSp dst, iRegI src, fRegF op1, fRegF op2, cmpOp cop) %{
10292 match(Set dst (CMoveI (Binary cop (CmpF op1 op2)) (Binary dst src)));
10293 ins_cost(ALU_COST + BRANCH_COST);
10294
10295 format %{
10296 "CMoveI $dst, ($op1 $cop $op2), $dst, $src\t#@cmovI_cmpF\n\t"
10297 %}
10298
10299 ins_encode %{
10300 __ enc_cmove_cmp_fp($cop$$cmpcode,
10301 as_FloatRegister($op1$$reg), as_FloatRegister($op2$$reg),
10302 as_Register($dst$$reg), as_Register($src$$reg), true /* is_single */);
10303 %}
10304
10305 ins_pipe(pipe_class_compare);
10306 %}
10307
10308 instruct cmovI_cmpD(iRegINoSp dst, iRegI src, fRegD op1, fRegD op2, cmpOp cop) %{
10309 match(Set dst (CMoveI (Binary cop (CmpD op1 op2)) (Binary dst src)));
10310 ins_cost(ALU_COST + BRANCH_COST);
10311
10312 format %{
10313 "CMoveI $dst, ($op1 $cop $op2), $dst, $src\t#@cmovI_cmpD\n\t"
10314 %}
10315
10316 ins_encode %{
10317 __ enc_cmove_cmp_fp($cop$$cmpcode | C2_MacroAssembler::double_branch_mask,
10318 as_FloatRegister($op1$$reg), as_FloatRegister($op2$$reg),
10319 as_Register($dst$$reg), as_Register($src$$reg), false /* is_single */);
10320 %}
10321
10322 ins_pipe(pipe_class_compare);
10323 %}
10324
10325 instruct cmovI_cmpN(iRegINoSp dst, iRegI src, iRegN op1, iRegN op2, cmpOpU cop) %{
10326 match(Set dst (CMoveI (Binary cop (CmpN op1 op2)) (Binary dst src)));
10327 ins_cost(ALU_COST + BRANCH_COST);
10328
10329 format %{
10330 "CMoveI $dst, ($op1 $cop $op2), $dst, $src\t#@cmovI_cmpN\n\t"
10331 %}
10332
10333 ins_encode %{
10334 __ enc_cmove($cop$$cmpcode | C2_MacroAssembler::unsigned_branch_mask,
10335 as_Register($op1$$reg), as_Register($op2$$reg),
10336 as_Register($dst$$reg), as_Register($src$$reg));
10337 %}
10338
10339 ins_pipe(pipe_class_compare);
10340 %}
10341
10342 instruct cmovI_cmpP(iRegINoSp dst, iRegI src, iRegP op1, iRegP op2, cmpOpU cop) %{
10343 match(Set dst (CMoveI (Binary cop (CmpP op1 op2)) (Binary dst src)));
10344 ins_cost(ALU_COST + BRANCH_COST);
10345
10346 format %{
10347 "CMoveI $dst, ($op1 $cop $op2), $dst, $src\t#@cmovI_cmpP\n\t"
10348 %}
10349
10350 ins_encode %{
10351 __ enc_cmove($cop$$cmpcode | C2_MacroAssembler::unsigned_branch_mask,
10352 as_Register($op1$$reg), as_Register($op2$$reg),
10353 as_Register($dst$$reg), as_Register($src$$reg));
10354 %}
10355
10356 ins_pipe(pipe_class_compare);
10357 %}
10358
10359 // --------- CMoveL ---------
10360
10361 instruct cmovL_cmpL(iRegLNoSp dst, iRegL src, iRegL op1, iRegL op2, cmpOp cop) %{
10362 match(Set dst (CMoveL (Binary cop (CmpL op1 op2)) (Binary dst src)));
10363 ins_cost(ALU_COST + BRANCH_COST);
10364
10365 format %{
10366 "CMoveL $dst, ($op1 $cop $op2), $dst, $src\t#@cmovL_cmpL\n\t"
10367 %}
10368
10369 ins_encode %{
10370 __ enc_cmove($cop$$cmpcode,
10371 as_Register($op1$$reg), as_Register($op2$$reg),
10372 as_Register($dst$$reg), as_Register($src$$reg));
10373 %}
10374
10375 ins_pipe(pipe_class_compare);
10376 %}
10377
10378 instruct cmovL_cmpUL(iRegLNoSp dst, iRegL src, iRegL op1, iRegL op2, cmpOpU cop) %{
10379 match(Set dst (CMoveL (Binary cop (CmpUL op1 op2)) (Binary dst src)));
10380 ins_cost(ALU_COST + BRANCH_COST);
10381
10382 format %{
10383 "CMoveL $dst, ($op1 $cop $op2), $dst, $src\t#@cmovL_cmpUL\n\t"
10384 %}
10385
10386 ins_encode %{
10387 __ enc_cmove($cop$$cmpcode | C2_MacroAssembler::unsigned_branch_mask,
10388 as_Register($op1$$reg), as_Register($op2$$reg),
10389 as_Register($dst$$reg), as_Register($src$$reg));
10390 %}
10391
10392 ins_pipe(pipe_class_compare);
10393 %}
10394
10395 instruct cmovL_cmpI(iRegLNoSp dst, iRegL src, iRegI op1, iRegI op2, cmpOp cop) %{
10396 match(Set dst (CMoveL (Binary cop (CmpI op1 op2)) (Binary dst src)));
10397 ins_cost(ALU_COST + BRANCH_COST);
10398
10399 format %{
10400 "CMoveL $dst, ($op1 $cop $op2), $dst, $src\t#@cmovL_cmpI\n\t"
10401 %}
10402
10403 ins_encode %{
10404 __ enc_cmove($cop$$cmpcode,
10405 as_Register($op1$$reg), as_Register($op2$$reg),
10406 as_Register($dst$$reg), as_Register($src$$reg));
10407 %}
10408
10409 ins_pipe(pipe_class_compare);
10410 %}
10411
10412 instruct cmovL_cmpU(iRegLNoSp dst, iRegL src, iRegI op1, iRegI op2, cmpOpU cop) %{
10413 match(Set dst (CMoveL (Binary cop (CmpU op1 op2)) (Binary dst src)));
10414 ins_cost(ALU_COST + BRANCH_COST);
10415
10416 format %{
10417 "CMoveL $dst, ($op1 $cop $op2), $dst, $src\t#@cmovL_cmpU\n\t"
10418 %}
10419
10420 ins_encode %{
10421 __ enc_cmove($cop$$cmpcode | C2_MacroAssembler::unsigned_branch_mask,
10422 as_Register($op1$$reg), as_Register($op2$$reg),
10423 as_Register($dst$$reg), as_Register($src$$reg));
10424 %}
10425
10426 ins_pipe(pipe_class_compare);
10427 %}
10428
10429 instruct cmovL_cmpF(iRegLNoSp dst, iRegL src, fRegF op1, fRegF op2, cmpOp cop) %{
10430 match(Set dst (CMoveL (Binary cop (CmpF op1 op2)) (Binary dst src)));
10431 ins_cost(ALU_COST + BRANCH_COST);
10432
10433 format %{
10434 "CMoveL $dst, ($op1 $cop $op2), $dst, $src\t#@cmovL_cmpF\n\t"
10435 %}
10436
10437 ins_encode %{
10438 __ enc_cmove_cmp_fp($cop$$cmpcode,
10439 as_FloatRegister($op1$$reg), as_FloatRegister($op2$$reg),
10440 as_Register($dst$$reg), as_Register($src$$reg), true /* is_single */);
10441 %}
10442
10443 ins_pipe(pipe_class_compare);
10444 %}
10445
10446 instruct cmovL_cmpD(iRegLNoSp dst, iRegL src, fRegD op1, fRegD op2, cmpOp cop) %{
10447 match(Set dst (CMoveL (Binary cop (CmpD op1 op2)) (Binary dst src)));
10448 ins_cost(ALU_COST + BRANCH_COST);
10449
10450 format %{
10451 "CMoveL $dst, ($op1 $cop $op2), $dst, $src\t#@cmovL_cmpD\n\t"
10452 %}
10453
10454 ins_encode %{
10455 __ enc_cmove_cmp_fp($cop$$cmpcode | C2_MacroAssembler::double_branch_mask,
10456 as_FloatRegister($op1$$reg), as_FloatRegister($op2$$reg),
10457 as_Register($dst$$reg), as_Register($src$$reg), false /* is_single */);
10458 %}
10459
10460 ins_pipe(pipe_class_compare);
10461 %}
10462
10463 instruct cmovL_cmpN(iRegLNoSp dst, iRegL src, iRegN op1, iRegN op2, cmpOpU cop) %{
10464 match(Set dst (CMoveL (Binary cop (CmpN op1 op2)) (Binary dst src)));
10465 ins_cost(ALU_COST + BRANCH_COST);
10466
10467 format %{
10468 "CMoveL $dst, ($op1 $cop $op2), $dst, $src\t#@cmovL_cmpN\n\t"
10469 %}
10470
10471 ins_encode %{
10472 __ enc_cmove($cop$$cmpcode | C2_MacroAssembler::unsigned_branch_mask,
10473 as_Register($op1$$reg), as_Register($op2$$reg),
10474 as_Register($dst$$reg), as_Register($src$$reg));
10475 %}
10476
10477 ins_pipe(pipe_class_compare);
10478 %}
10479
10480 instruct cmovL_cmpP(iRegLNoSp dst, iRegL src, iRegP op1, iRegP op2, cmpOpU cop) %{
10481 match(Set dst (CMoveL (Binary cop (CmpP op1 op2)) (Binary dst src)));
10482 ins_cost(ALU_COST + BRANCH_COST);
10483
10484 format %{
10485 "CMoveL $dst, ($op1 $cop $op2), $dst, $src\t#@cmovL_cmpP\n\t"
10486 %}
10487
10488 ins_encode %{
10489 __ enc_cmove($cop$$cmpcode | C2_MacroAssembler::unsigned_branch_mask,
10490 as_Register($op1$$reg), as_Register($op2$$reg),
10491 as_Register($dst$$reg), as_Register($src$$reg));
10492 %}
10493
10494 ins_pipe(pipe_class_compare);
10495 %}
10496
10497 // --------- CMoveF ---------
10498
10499 instruct cmovF_cmpI(fRegF dst, fRegF src, iRegI op1, iRegI op2, cmpOp cop) %{
10500 match(Set dst (CMoveF (Binary cop (CmpI op1 op2)) (Binary dst src)));
10501 ins_cost(ALU_COST + BRANCH_COST);
10502
10503 format %{
10504 "CMoveF $dst, ($op1 $cop $op2), $dst, $src\t#@cmovF_cmpI\n\t"
10505 %}
10506
10507 ins_encode %{
10508 __ enc_cmove_fp_cmp($cop$$cmpcode,
10509 as_Register($op1$$reg), as_Register($op2$$reg),
10510 as_FloatRegister($dst$$reg), as_FloatRegister($src$$reg), true /* is_single */);
10511 %}
10512
10513 ins_pipe(pipe_class_compare);
10514 %}
10515
10516 instruct cmovF_cmpU(fRegF dst, fRegF src, iRegI op1, iRegI op2, cmpOpU cop) %{
10517 match(Set dst (CMoveF (Binary cop (CmpU op1 op2)) (Binary dst src)));
10518 ins_cost(ALU_COST + BRANCH_COST);
10519
10520 format %{
10521 "CMoveF $dst, ($op1 $cop $op2), $dst, $src\t#@cmovF_cmpU\n\t"
10522 %}
10523
10524 ins_encode %{
10525 __ enc_cmove_fp_cmp($cop$$cmpcode | C2_MacroAssembler::unsigned_branch_mask,
10526 as_Register($op1$$reg), as_Register($op2$$reg),
10527 as_FloatRegister($dst$$reg), as_FloatRegister($src$$reg), true /* is_single */);
10528 %}
10529
10530 ins_pipe(pipe_class_compare);
10531 %}
10532
10533 instruct cmovF_cmpL(fRegF dst, fRegF src, iRegL op1, iRegL op2, cmpOp cop) %{
10534 match(Set dst (CMoveF (Binary cop (CmpL op1 op2)) (Binary dst src)));
10535 ins_cost(ALU_COST + BRANCH_COST);
10536
10537 format %{
10538 "CMoveF $dst, ($op1 $cop $op2), $dst, $src\t#@cmovF_cmpL\n\t"
10539 %}
10540
10541 ins_encode %{
10542 __ enc_cmove_fp_cmp($cop$$cmpcode,
10543 as_Register($op1$$reg), as_Register($op2$$reg),
10544 as_FloatRegister($dst$$reg), as_FloatRegister($src$$reg), true /* is_single */);
10545 %}
10546
10547 ins_pipe(pipe_class_compare);
10548 %}
10549
10550 instruct cmovF_cmpUL(fRegF dst, fRegF src, iRegL op1, iRegL op2, cmpOpU cop) %{
10551 match(Set dst (CMoveF (Binary cop (CmpUL op1 op2)) (Binary dst src)));
10552 ins_cost(ALU_COST + BRANCH_COST);
10553
10554 format %{
10555 "CMoveF $dst, ($op1 $cop $op2), $dst, $src\t#@cmovF_cmpUL\n\t"
10556 %}
10557
10558 ins_encode %{
10559 __ enc_cmove_fp_cmp($cop$$cmpcode | C2_MacroAssembler::unsigned_branch_mask,
10560 as_Register($op1$$reg), as_Register($op2$$reg),
10561 as_FloatRegister($dst$$reg), as_FloatRegister($src$$reg), true /* is_single */);
10562 %}
10563
10564 ins_pipe(pipe_class_compare);
10565 %}
10566
10567 instruct cmovF_cmpF(fRegF dst, fRegF src, fRegF op1, fRegF op2, cmpOp cop) %{
10568 match(Set dst (CMoveF (Binary cop (CmpF op1 op2)) (Binary dst src)));
10569 ins_cost(ALU_COST + BRANCH_COST);
10570
10571 format %{
10572 "CMoveF $dst, ($op1 $cop $op2), $dst, $src\t#@cmovF_cmpF\n\t"
10573 %}
10574
10575 ins_encode %{
10576 __ enc_cmove_fp_cmp_fp($cop$$cmpcode,
10577 as_FloatRegister($op1$$reg), as_FloatRegister($op2$$reg),
10578 as_FloatRegister($dst$$reg), as_FloatRegister($src$$reg),
10579 true /* cmp_single */, true /* cmov_single */);
10580 %}
10581
10582 ins_pipe(pipe_class_compare);
10583 %}
10584
10585 instruct cmovF_cmpD(fRegF dst, fRegF src, fRegD op1, fRegD op2, cmpOp cop) %{
10586 match(Set dst (CMoveF (Binary cop (CmpD op1 op2)) (Binary dst src)));
10587 ins_cost(ALU_COST + BRANCH_COST);
10588
10589 format %{
10590 "CMoveF $dst, ($op1 $cop $op2), $dst, $src\t#@cmovF_cmpD\n\t"
10591 %}
10592
10593 ins_encode %{
10594 __ enc_cmove_fp_cmp_fp($cop$$cmpcode | C2_MacroAssembler::double_branch_mask,
10595 as_FloatRegister($op1$$reg), as_FloatRegister($op2$$reg),
10596 as_FloatRegister($dst$$reg), as_FloatRegister($src$$reg),
10597 false /* cmp_single */, true /* cmov_single */);
10598 %}
10599
10600 ins_pipe(pipe_class_compare);
10601 %}
10602
10603 instruct cmovF_cmpN(fRegF dst, fRegF src, iRegN op1, iRegN op2, cmpOp cop) %{
10604 match(Set dst (CMoveF (Binary cop (CmpN op1 op2)) (Binary dst src)));
10605 ins_cost(ALU_COST + BRANCH_COST);
10606
10607 format %{
10608 "CMoveF $dst, ($op1 $cop $op2), $dst, $src\t#@cmovF_cmpN\n\t"
10609 %}
10610
10611 ins_encode %{
10612 __ enc_cmove_fp_cmp($cop$$cmpcode | C2_MacroAssembler::unsigned_branch_mask,
10613 as_Register($op1$$reg), as_Register($op2$$reg),
10614 as_FloatRegister($dst$$reg), as_FloatRegister($src$$reg), true /* is_single */);
10615 %}
10616
10617 ins_pipe(pipe_class_compare);
10618 %}
10619
10620 instruct cmovF_cmpP(fRegF dst, fRegF src, iRegP op1, iRegP op2, cmpOp cop) %{
10621 match(Set dst (CMoveF (Binary cop (CmpP op1 op2)) (Binary dst src)));
10622 ins_cost(ALU_COST + BRANCH_COST);
10623
10624 format %{
10625 "CMoveF $dst, ($op1 $cop $op2), $dst, $src\t#@cmovF_cmpP\n\t"
10626 %}
10627
10628 ins_encode %{
10629 __ enc_cmove_fp_cmp($cop$$cmpcode | C2_MacroAssembler::unsigned_branch_mask,
10630 as_Register($op1$$reg), as_Register($op2$$reg),
10631 as_FloatRegister($dst$$reg), as_FloatRegister($src$$reg), true /* is_single */);
10632 %}
10633
10634 ins_pipe(pipe_class_compare);
10635 %}
10636
10637 // --------- CMoveD ---------
10638
10639 instruct cmovD_cmpI(fRegD dst, fRegD src, iRegI op1, iRegI op2, cmpOp cop) %{
10640 match(Set dst (CMoveD (Binary cop (CmpI op1 op2)) (Binary dst src)));
10641 ins_cost(ALU_COST + BRANCH_COST);
10642
10643 format %{
10644 "CMoveD $dst, ($op1 $cop $op2), $dst, $src\t#@cmovD_cmpI\n\t"
10645 %}
10646
10647 ins_encode %{
10648 __ enc_cmove_fp_cmp($cop$$cmpcode,
10649 as_Register($op1$$reg), as_Register($op2$$reg),
10650 as_FloatRegister($dst$$reg), as_FloatRegister($src$$reg), false /* is_single */);
10651 %}
10652
10653 ins_pipe(pipe_class_compare);
10654 %}
10655
10656 instruct cmovD_cmpU(fRegD dst, fRegD src, iRegI op1, iRegI op2, cmpOpU cop) %{
10657 match(Set dst (CMoveD (Binary cop (CmpU op1 op2)) (Binary dst src)));
10658 ins_cost(ALU_COST + BRANCH_COST);
10659
10660 format %{
10661 "CMoveD $dst, ($op1 $cop $op2), $dst, $src\t#@cmovD_cmpU\n\t"
10662 %}
10663
10664 ins_encode %{
10665 __ enc_cmove_fp_cmp($cop$$cmpcode | C2_MacroAssembler::unsigned_branch_mask,
10666 as_Register($op1$$reg), as_Register($op2$$reg),
10667 as_FloatRegister($dst$$reg), as_FloatRegister($src$$reg), false /* is_single */);
10668 %}
10669
10670 ins_pipe(pipe_class_compare);
10671 %}
10672
10673 instruct cmovD_cmpL(fRegD dst, fRegD src, iRegL op1, iRegL op2, cmpOp cop) %{
10674 match(Set dst (CMoveD (Binary cop (CmpL op1 op2)) (Binary dst src)));
10675 ins_cost(ALU_COST + BRANCH_COST);
10676
10677 format %{
10678 "CMoveD $dst, ($op1 $cop $op2), $dst, $src\t#@cmovD_cmpL\n\t"
10679 %}
10680
10681 ins_encode %{
10682 __ enc_cmove_fp_cmp($cop$$cmpcode,
10683 as_Register($op1$$reg), as_Register($op2$$reg),
10684 as_FloatRegister($dst$$reg), as_FloatRegister($src$$reg), false /* is_single */);
10685 %}
10686
10687 ins_pipe(pipe_class_compare);
10688 %}
10689
10690 instruct cmovD_cmpUL(fRegD dst, fRegD src, iRegL op1, iRegL op2, cmpOpU cop) %{
10691 match(Set dst (CMoveD (Binary cop (CmpUL op1 op2)) (Binary dst src)));
10692 ins_cost(ALU_COST + BRANCH_COST);
10693
10694 format %{
10695 "CMoveD $dst, ($op1 $cop $op2), $dst, $src\t#@cmovD_cmpUL\n\t"
10696 %}
10697
10698 ins_encode %{
10699 __ enc_cmove_fp_cmp($cop$$cmpcode | C2_MacroAssembler::unsigned_branch_mask,
10700 as_Register($op1$$reg), as_Register($op2$$reg),
10701 as_FloatRegister($dst$$reg), as_FloatRegister($src$$reg), false /* is_single */);
10702 %}
10703
10704 ins_pipe(pipe_class_compare);
10705 %}
10706
10707 instruct cmovD_cmpF(fRegD dst, fRegD src, fRegF op1, fRegF op2, cmpOp cop) %{
10708 match(Set dst (CMoveD (Binary cop (CmpF op1 op2)) (Binary dst src)));
10709 ins_cost(ALU_COST + BRANCH_COST);
10710
10711 format %{
10712 "CMoveD $dst, ($op1 $cop $op2), $dst, $src\t#@cmovD_cmpF\n\t"
10713 %}
10714
10715 ins_encode %{
10716 __ enc_cmove_fp_cmp_fp($cop$$cmpcode,
10717 as_FloatRegister($op1$$reg), as_FloatRegister($op2$$reg),
10718 as_FloatRegister($dst$$reg), as_FloatRegister($src$$reg),
10719 true /* cmp_single */, false /* cmov_single */);
10720 %}
10721
10722 ins_pipe(pipe_class_compare);
10723 %}
10724
10725 instruct cmovD_cmpD(fRegD dst, fRegD src, fRegD op1, fRegD op2, cmpOp cop) %{
10726 match(Set dst (CMoveD (Binary cop (CmpD op1 op2)) (Binary dst src)));
10727 ins_cost(ALU_COST + BRANCH_COST);
10728
10729 format %{
10730 "CMoveD $dst, ($op1 $cop $op2), $dst, $src\t#@cmovD_cmpD\n\t"
10731 %}
10732
10733 ins_encode %{
10734 __ enc_cmove_fp_cmp_fp($cop$$cmpcode | C2_MacroAssembler::double_branch_mask,
10735 as_FloatRegister($op1$$reg), as_FloatRegister($op2$$reg),
10736 as_FloatRegister($dst$$reg), as_FloatRegister($src$$reg),
10737 false /* cmp_single */, false /* cmov_single */);
10738 %}
10739
10740 ins_pipe(pipe_class_compare);
10741 %}
10742
10743 instruct cmovD_cmpN(fRegD dst, fRegD src, iRegN op1, iRegN op2, cmpOp cop) %{
10744 match(Set dst (CMoveD (Binary cop (CmpN op1 op2)) (Binary dst src)));
10745 ins_cost(ALU_COST + BRANCH_COST);
10746
10747 format %{
10748 "CMoveD $dst, ($op1 $cop $op2), $dst, $src\t#@cmovD_cmpN\n\t"
10749 %}
10750
10751 ins_encode %{
10752 __ enc_cmove_fp_cmp($cop$$cmpcode | C2_MacroAssembler::unsigned_branch_mask,
10753 as_Register($op1$$reg), as_Register($op2$$reg),
10754 as_FloatRegister($dst$$reg), as_FloatRegister($src$$reg), false /* is_single */);
10755 %}
10756
10757 ins_pipe(pipe_class_compare);
10758 %}
10759
10760 instruct cmovD_cmpP(fRegD dst, fRegD src, iRegP op1, iRegP op2, cmpOp cop) %{
10761 match(Set dst (CMoveD (Binary cop (CmpP op1 op2)) (Binary dst src)));
10762 ins_cost(ALU_COST + BRANCH_COST);
10763
10764 format %{
10765 "CMoveD $dst, ($op1 $cop $op2), $dst, $src\t#@cmovD_cmpP\n\t"
10766 %}
10767
10768 ins_encode %{
10769 __ enc_cmove_fp_cmp($cop$$cmpcode | C2_MacroAssembler::unsigned_branch_mask,
10770 as_Register($op1$$reg), as_Register($op2$$reg),
10771 as_FloatRegister($dst$$reg), as_FloatRegister($src$$reg), false /* is_single */);
10772 %}
10773
10774 ins_pipe(pipe_class_compare);
10775 %}
10776
10777 // ============================================================================
10778 // Procedure Call/Return Instructions
10779
10780 // Call Java Static Instruction
10781 // Note: If this code changes, the corresponding ret_addr_offset() and
10782 // compute_padding() functions will have to be adjusted.
10783 instruct CallStaticJavaDirect(method meth)
10784 %{
10785 match(CallStaticJava);
10786
10787 effect(USE meth);
10788
10789 ins_cost(BRANCH_COST);
10790
10791 format %{ "CALL,static $meth\t#@CallStaticJavaDirect" %}
10792
10793 ins_encode(riscv_enc_java_static_call(meth),
10794 riscv_enc_call_epilog);
10795
10796 ins_pipe(pipe_class_call);
10797 ins_alignment(4);
10798 %}
10799
10800 // TO HERE
10801
10802 // Call Java Dynamic Instruction
10803 // Note: If this code changes, the corresponding ret_addr_offset() and
10804 // compute_padding() functions will have to be adjusted.
10805 instruct CallDynamicJavaDirect(method meth)
10806 %{
10807 match(CallDynamicJava);
10808
10809 effect(USE meth);
10810
10811 ins_cost(BRANCH_COST + ALU_COST * 5);
10812
10813 format %{ "CALL,dynamic $meth\t#@CallDynamicJavaDirect" %}
10814
10815 ins_encode(riscv_enc_java_dynamic_call(meth),
10816 riscv_enc_call_epilog);
10817
10818 ins_pipe(pipe_class_call);
10819 ins_alignment(4);
10820 %}
10821
10822 // Call Runtime Instruction
10823
10824 instruct CallRuntimeDirect(method meth)
10825 %{
10826 match(CallRuntime);
10827
10828 effect(USE meth);
10829
10830 ins_cost(BRANCH_COST);
10831
10832 format %{ "CALL, runtime $meth\t#@CallRuntimeDirect" %}
10833
10834 ins_encode(riscv_enc_java_to_runtime(meth));
10835
10836 ins_pipe(pipe_class_call);
10837 ins_alignment(4);
10838 %}
10839
10840 // Call Runtime Instruction
10841
10842 instruct CallLeafDirect(method meth)
10843 %{
10844 match(CallLeaf);
10845
10846 effect(USE meth);
10847
10848 ins_cost(BRANCH_COST);
10849
10850 format %{ "CALL, runtime leaf $meth\t#@CallLeafDirect" %}
10851
10852 ins_encode(riscv_enc_java_to_runtime(meth));
10853
10854 ins_pipe(pipe_class_call);
10855 ins_alignment(4);
10856 %}
10857
10858 // Call Runtime Instruction without safepoint and with vector arguments
10859
10860 instruct CallLeafDirectVector(method meth)
10861 %{
10862 match(CallLeafVector);
10863
10864 effect(USE meth);
10865
10866 ins_cost(BRANCH_COST);
10867
10868 format %{ "CALL, runtime leaf vector $meth" %}
10869
10870 ins_encode(riscv_enc_java_to_runtime(meth));
10871
10872 ins_pipe(pipe_class_call);
10873 ins_alignment(4);
10874 %}
10875
10876 // Call Runtime Instruction
10877
10878 instruct CallLeafNoFPDirect(method meth)
10879 %{
10880 match(CallLeafNoFP);
10881
10882 effect(USE meth);
10883
10884 ins_cost(BRANCH_COST);
10885
10886 format %{ "CALL, runtime leaf nofp $meth\t#@CallLeafNoFPDirect" %}
10887
10888 ins_encode(riscv_enc_java_to_runtime(meth));
10889
10890 ins_pipe(pipe_class_call);
10891 ins_alignment(4);
10892 %}
10893
10894 // ============================================================================
10895 // Partial Subtype Check
10896 //
10897 // superklass array for an instance of the superklass. Set a hidden
10898 // internal cache on a hit (cache is checked with exposed code in
10899 // gen_subtype_check()). Return zero for a hit. The encoding
10900 // ALSO sets flags.
10901
10902 instruct partialSubtypeCheck(iRegP_R15 result, iRegP_R14 sub, iRegP_R10 super, iRegP_R12 tmp, rFlagsReg cr)
10903 %{
10904 predicate(!UseSecondarySupersTable);
10905 match(Set result (PartialSubtypeCheck sub super));
10906 effect(KILL tmp, KILL cr);
10907
10908 ins_cost(20 * DEFAULT_COST);
10909 format %{ "partialSubtypeCheck $result, $sub, $super\t#@partialSubtypeCheck" %}
10910
10911 ins_encode(riscv_enc_partial_subtype_check(sub, super, tmp, result));
10912
10913 opcode(0x1); // Force zero of result reg on hit
10914
10915 ins_pipe(pipe_class_memory);
10916 %}
10917
10918 // Two versions of partialSubtypeCheck, both used when we need to
10919 // search for a super class in the secondary supers array. The first
10920 // is used when we don't know _a priori_ the class being searched
10921 // for. The second, far more common, is used when we do know: this is
10922 // used for instanceof, checkcast, and any case where C2 can determine
10923 // it by constant propagation.
10924
10925 instruct partialSubtypeCheckVarSuper(iRegP_R14 sub, iRegP_R10 super, iRegP_R15 result,
10926 iRegP_R11 tmpR11, iRegP_R12 tmpR12, iRegP_R13 tmpR13,
10927 iRegP_R16 tmpR16, rFlagsReg cr)
10928 %{
10929 predicate(UseSecondarySupersTable);
10930 match(Set result (PartialSubtypeCheck sub super));
10931 effect(TEMP tmpR11, TEMP tmpR12, TEMP tmpR13, TEMP tmpR16, KILL cr);
10932
10933 ins_cost(10 * DEFAULT_COST); // slightly larger than the next version
10934 format %{ "partialSubtypeCheck $result, $sub, $super" %}
10935
10936 ins_encode %{
10937 __ lookup_secondary_supers_table_var($sub$$Register, $super$$Register, $result$$Register,
10938 $tmpR11$$Register, $tmpR12$$Register, $tmpR13$$Register,
10939 $tmpR16$$Register, nullptr /*L_success*/);
10940 %}
10941
10942 ins_pipe(pipe_class_memory);
10943 %}
10944
10945 instruct partialSubtypeCheckConstSuper(iRegP_R14 sub, iRegP_R10 super_reg, immP super_con, iRegP_R15 result,
10946 iRegP_R11 tmpR11, iRegP_R12 tmpR12, iRegP_R13 tmpR13, iRegP_R16 tmpR16, rFlagsReg cr)
10947 %{
10948 predicate(UseSecondarySupersTable);
10949 match(Set result (PartialSubtypeCheck sub (Binary super_reg super_con)));
10950 effect(TEMP tmpR11, TEMP tmpR12, TEMP tmpR13, TEMP tmpR16, KILL cr);
10951
10952 ins_cost(5 * DEFAULT_COST); // needs to be less than competing nodes
10953 format %{ "partialSubtypeCheck $result, $sub, $super_reg, $super_con" %}
10954
10955 ins_encode %{
10956 bool success = false;
10957 u1 super_klass_slot = ((Klass*)$super_con$$constant)->hash_slot();
10958 if (InlineSecondarySupersTest) {
10959 success = __ lookup_secondary_supers_table_const($sub$$Register, $super_reg$$Register, $result$$Register,
10960 $tmpR11$$Register, $tmpR12$$Register, $tmpR13$$Register,
10961 $tmpR16$$Register, super_klass_slot);
10962 } else {
10963 address call = __ reloc_call(RuntimeAddress(StubRoutines::lookup_secondary_supers_table_stub(super_klass_slot)));
10964 success = (call != nullptr);
10965 }
10966 if (!success) {
10967 ciEnv::current()->record_failure("CodeCache is full");
10968 return;
10969 }
10970 %}
10971
10972 ins_pipe(pipe_class_memory);
10973 %}
10974
10975 instruct string_compareU(iRegP_R11 str1, iRegI_R12 cnt1, iRegP_R13 str2, iRegI_R14 cnt2,
10976 iRegI_R10 result, iRegP_R28 tmp1, iRegL_R29 tmp2, iRegL_R30 tmp3, rFlagsReg cr)
10977 %{
10978 predicate(!UseRVV && ((StrCompNode *)n)->encoding() == StrIntrinsicNode::UU);
10979 match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
10980 effect(KILL tmp1, KILL tmp2, KILL tmp3, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr);
10981
10982 format %{ "String Compare $str1, $cnt1, $str2, $cnt2 -> $result\t#@string_compareU" %}
10983 ins_encode %{
10984 // Count is in 8-bit bytes; non-Compact chars are 16 bits.
10985 __ string_compare($str1$$Register, $str2$$Register,
10986 $cnt1$$Register, $cnt2$$Register, $result$$Register,
10987 $tmp1$$Register, $tmp2$$Register, $tmp3$$Register,
10988 StrIntrinsicNode::UU);
10989 %}
10990 ins_pipe(pipe_class_memory);
10991 %}
10992
10993 instruct string_compareL(iRegP_R11 str1, iRegI_R12 cnt1, iRegP_R13 str2, iRegI_R14 cnt2,
10994 iRegI_R10 result, iRegP_R28 tmp1, iRegL_R29 tmp2, iRegL_R30 tmp3, rFlagsReg cr)
10995 %{
10996 predicate(!UseRVV && ((StrCompNode *)n)->encoding() == StrIntrinsicNode::LL);
10997 match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
10998 effect(KILL tmp1, KILL tmp2, KILL tmp3, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr);
10999
11000 format %{ "String Compare $str1, $cnt1, $str2, $cnt2 -> $result\t#@string_compareL" %}
11001 ins_encode %{
11002 __ string_compare($str1$$Register, $str2$$Register,
11003 $cnt1$$Register, $cnt2$$Register, $result$$Register,
11004 $tmp1$$Register, $tmp2$$Register, $tmp3$$Register,
11005 StrIntrinsicNode::LL);
11006 %}
11007 ins_pipe(pipe_class_memory);
11008 %}
11009
11010 instruct string_compareUL(iRegP_R11 str1, iRegI_R12 cnt1, iRegP_R13 str2, iRegI_R14 cnt2,
11011 iRegI_R10 result, iRegP_R28 tmp1, iRegL_R29 tmp2, iRegL_R30 tmp3, rFlagsReg cr)
11012 %{
11013 predicate(!UseRVV && ((StrCompNode *)n)->encoding() == StrIntrinsicNode::UL);
11014 match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
11015 effect(KILL tmp1, KILL tmp2, KILL tmp3, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr);
11016
11017 format %{"String Compare $str1, $cnt1, $str2, $cnt2 -> $result\t#@string_compareUL" %}
11018 ins_encode %{
11019 __ string_compare($str1$$Register, $str2$$Register,
11020 $cnt1$$Register, $cnt2$$Register, $result$$Register,
11021 $tmp1$$Register, $tmp2$$Register, $tmp3$$Register,
11022 StrIntrinsicNode::UL);
11023 %}
11024 ins_pipe(pipe_class_memory);
11025 %}
11026
11027 instruct string_compareLU(iRegP_R11 str1, iRegI_R12 cnt1, iRegP_R13 str2, iRegI_R14 cnt2,
11028 iRegI_R10 result, iRegP_R28 tmp1, iRegL_R29 tmp2, iRegL_R30 tmp3,
11029 rFlagsReg cr)
11030 %{
11031 predicate(!UseRVV && ((StrCompNode *)n)->encoding() == StrIntrinsicNode::LU);
11032 match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
11033 effect(KILL tmp1, KILL tmp2, KILL tmp3, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr);
11034
11035 format %{ "String Compare $str1, $cnt1, $str2, $cnt2 -> $result\t#@string_compareLU" %}
11036 ins_encode %{
11037 __ string_compare($str1$$Register, $str2$$Register,
11038 $cnt1$$Register, $cnt2$$Register, $result$$Register,
11039 $tmp1$$Register, $tmp2$$Register, $tmp3$$Register,
11040 StrIntrinsicNode::LU);
11041 %}
11042 ins_pipe(pipe_class_memory);
11043 %}
11044
11045 instruct string_indexofUU(iRegP_R11 str1, iRegI_R12 cnt1, iRegP_R13 str2, iRegI_R14 cnt2,
11046 iRegI_R10 result, iRegINoSp tmp1, iRegINoSp tmp2, iRegINoSp tmp3,
11047 iRegINoSp tmp4, iRegINoSp tmp5, iRegINoSp tmp6, rFlagsReg cr)
11048 %{
11049 predicate(((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UU);
11050 match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 cnt2)));
11051 effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, TEMP_DEF result,
11052 TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, TEMP tmp5, TEMP tmp6, KILL cr);
11053
11054 format %{ "String IndexOf $str1,$cnt1,$str2,$cnt2 -> $result (UU)" %}
11055 ins_encode %{
11056 __ string_indexof($str1$$Register, $str2$$Register,
11057 $cnt1$$Register, $cnt2$$Register,
11058 $tmp1$$Register, $tmp2$$Register,
11059 $tmp3$$Register, $tmp4$$Register,
11060 $tmp5$$Register, $tmp6$$Register,
11061 $result$$Register, StrIntrinsicNode::UU);
11062 %}
11063 ins_pipe(pipe_class_memory);
11064 %}
11065
11066 instruct string_indexofLL(iRegP_R11 str1, iRegI_R12 cnt1, iRegP_R13 str2, iRegI_R14 cnt2,
11067 iRegI_R10 result, iRegINoSp tmp1, iRegINoSp tmp2, iRegINoSp tmp3,
11068 iRegINoSp tmp4, iRegINoSp tmp5, iRegINoSp tmp6, rFlagsReg cr)
11069 %{
11070 predicate(((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::LL);
11071 match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 cnt2)));
11072 effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, TEMP_DEF result,
11073 TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, TEMP tmp5, TEMP tmp6, KILL cr);
11074
11075 format %{ "String IndexOf $str1,$cnt1,$str2,$cnt2 -> $result (LL)" %}
11076 ins_encode %{
11077 __ string_indexof($str1$$Register, $str2$$Register,
11078 $cnt1$$Register, $cnt2$$Register,
11079 $tmp1$$Register, $tmp2$$Register,
11080 $tmp3$$Register, $tmp4$$Register,
11081 $tmp5$$Register, $tmp6$$Register,
11082 $result$$Register, StrIntrinsicNode::LL);
11083 %}
11084 ins_pipe(pipe_class_memory);
11085 %}
11086
11087 instruct string_indexofUL(iRegP_R11 str1, iRegI_R12 cnt1, iRegP_R13 str2, iRegI_R14 cnt2,
11088 iRegI_R10 result, iRegINoSp tmp1, iRegINoSp tmp2, iRegINoSp tmp3,
11089 iRegINoSp tmp4, iRegINoSp tmp5, iRegINoSp tmp6, rFlagsReg cr)
11090 %{
11091 predicate(((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UL);
11092 match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 cnt2)));
11093 effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, TEMP_DEF result,
11094 TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, TEMP tmp5, TEMP tmp6, KILL cr);
11095 format %{ "String IndexOf $str1,$cnt1,$str2,$cnt2 -> $result (UL)" %}
11096
11097 ins_encode %{
11098 __ string_indexof($str1$$Register, $str2$$Register,
11099 $cnt1$$Register, $cnt2$$Register,
11100 $tmp1$$Register, $tmp2$$Register,
11101 $tmp3$$Register, $tmp4$$Register,
11102 $tmp5$$Register, $tmp6$$Register,
11103 $result$$Register, StrIntrinsicNode::UL);
11104 %}
11105 ins_pipe(pipe_class_memory);
11106 %}
11107
11108 instruct string_indexof_conUU(iRegP_R11 str1, iRegI_R12 cnt1, iRegP_R13 str2,
11109 immI_le_4 int_cnt2, iRegI_R10 result, iRegINoSp tmp1, iRegINoSp tmp2,
11110 iRegINoSp tmp3, iRegINoSp tmp4, rFlagsReg cr)
11111 %{
11112 predicate(((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UU);
11113 match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 int_cnt2)));
11114 effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt1, TEMP_DEF result,
11115 TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, KILL cr);
11116
11117 format %{ "String IndexOf $str1,$cnt1,$str2,$int_cnt2 -> $result (UU)" %}
11118
11119 ins_encode %{
11120 int icnt2 = (int)$int_cnt2$$constant;
11121 __ string_indexof_linearscan($str1$$Register, $str2$$Register,
11122 $cnt1$$Register, zr,
11123 $tmp1$$Register, $tmp2$$Register,
11124 $tmp3$$Register, $tmp4$$Register,
11125 icnt2, $result$$Register, StrIntrinsicNode::UU);
11126 %}
11127 ins_pipe(pipe_class_memory);
11128 %}
11129
11130 instruct string_indexof_conLL(iRegP_R11 str1, iRegI_R12 cnt1, iRegP_R13 str2,
11131 immI_le_4 int_cnt2, iRegI_R10 result, iRegINoSp tmp1, iRegINoSp tmp2,
11132 iRegINoSp tmp3, iRegINoSp tmp4, rFlagsReg cr)
11133 %{
11134 predicate(((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::LL);
11135 match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 int_cnt2)));
11136 effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt1, TEMP_DEF result,
11137 TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, KILL cr);
11138
11139 format %{ "String IndexOf $str1,$cnt1,$str2,$int_cnt2 -> $result (LL)" %}
11140 ins_encode %{
11141 int icnt2 = (int)$int_cnt2$$constant;
11142 __ string_indexof_linearscan($str1$$Register, $str2$$Register,
11143 $cnt1$$Register, zr,
11144 $tmp1$$Register, $tmp2$$Register,
11145 $tmp3$$Register, $tmp4$$Register,
11146 icnt2, $result$$Register, StrIntrinsicNode::LL);
11147 %}
11148 ins_pipe(pipe_class_memory);
11149 %}
11150
11151 instruct string_indexof_conUL(iRegP_R11 str1, iRegI_R12 cnt1, iRegP_R13 str2,
11152 immI_1 int_cnt2, iRegI_R10 result, iRegINoSp tmp1, iRegINoSp tmp2,
11153 iRegINoSp tmp3, iRegINoSp tmp4, rFlagsReg cr)
11154 %{
11155 predicate(((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UL);
11156 match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 int_cnt2)));
11157 effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt1, TEMP_DEF result,
11158 TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, KILL cr);
11159
11160 format %{ "String IndexOf $str1,$cnt1,$str2,$int_cnt2 -> $result (UL)" %}
11161 ins_encode %{
11162 int icnt2 = (int)$int_cnt2$$constant;
11163 __ string_indexof_linearscan($str1$$Register, $str2$$Register,
11164 $cnt1$$Register, zr,
11165 $tmp1$$Register, $tmp2$$Register,
11166 $tmp3$$Register, $tmp4$$Register,
11167 icnt2, $result$$Register, StrIntrinsicNode::UL);
11168 %}
11169 ins_pipe(pipe_class_memory);
11170 %}
11171
11172 instruct stringU_indexof_char(iRegP_R11 str1, iRegI_R12 cnt1, iRegI_R13 ch,
11173 iRegI_R10 result, iRegINoSp tmp1, iRegINoSp tmp2,
11174 iRegINoSp tmp3, iRegINoSp tmp4, rFlagsReg cr)
11175 %{
11176 match(Set result (StrIndexOfChar (Binary str1 cnt1) ch));
11177 predicate(!UseRVV && (((StrIndexOfCharNode*)n)->encoding() == StrIntrinsicNode::U));
11178 effect(USE_KILL str1, USE_KILL cnt1, USE_KILL ch, TEMP_DEF result,
11179 TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, KILL cr);
11180
11181 format %{ "StringUTF16 IndexOf char[] $str1, $cnt1, $ch -> $result" %}
11182 ins_encode %{
11183 __ string_indexof_char($str1$$Register, $cnt1$$Register, $ch$$Register,
11184 $result$$Register, $tmp1$$Register, $tmp2$$Register,
11185 $tmp3$$Register, $tmp4$$Register, false /* isU */);
11186 %}
11187 ins_pipe(pipe_class_memory);
11188 %}
11189
11190
11191 instruct stringL_indexof_char(iRegP_R11 str1, iRegI_R12 cnt1, iRegI_R13 ch,
11192 iRegI_R10 result, iRegINoSp tmp1, iRegINoSp tmp2,
11193 iRegINoSp tmp3, iRegINoSp tmp4, rFlagsReg cr)
11194 %{
11195 match(Set result (StrIndexOfChar (Binary str1 cnt1) ch));
11196 predicate(!UseRVV && (((StrIndexOfCharNode*)n)->encoding() == StrIntrinsicNode::L));
11197 effect(USE_KILL str1, USE_KILL cnt1, USE_KILL ch, TEMP_DEF result,
11198 TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, KILL cr);
11199
11200 format %{ "StringLatin1 IndexOf char[] $str1, $cnt1, $ch -> $result" %}
11201 ins_encode %{
11202 __ string_indexof_char($str1$$Register, $cnt1$$Register, $ch$$Register,
11203 $result$$Register, $tmp1$$Register, $tmp2$$Register,
11204 $tmp3$$Register, $tmp4$$Register, true /* isL */);
11205 %}
11206 ins_pipe(pipe_class_memory);
11207 %}
11208
11209 // clearing of an array
11210 instruct clearArray_reg_reg(iRegL_R29 cnt, iRegP_R28 base, iRegP_R30 tmp1,
11211 iRegP_R31 tmp2, rFlagsReg cr, Universe dummy)
11212 %{
11213 // temp registers must match the one used in StubGenerator::generate_zero_blocks()
11214 predicate(UseBlockZeroing || !UseRVV);
11215 match(Set dummy (ClearArray cnt base));
11216 effect(USE_KILL cnt, USE_KILL base, TEMP tmp1, TEMP tmp2, KILL cr);
11217
11218 ins_cost(4 * DEFAULT_COST);
11219 format %{ "ClearArray $cnt, $base\t#@clearArray_reg_reg" %}
11220
11221 ins_encode %{
11222 address tpc = __ zero_words($base$$Register, $cnt$$Register);
11223 if (tpc == nullptr) {
11224 ciEnv::current()->record_failure("CodeCache is full");
11225 return;
11226 }
11227 %}
11228
11229 ins_pipe(pipe_class_memory);
11230 %}
11231
11232 instruct clearArray_imm_reg(immL cnt, iRegP_R28 base, Universe dummy, rFlagsReg cr)
11233 %{
11234 predicate(!UseRVV && (uint64_t)n->in(2)->get_long()
11235 < (uint64_t)(BlockZeroingLowLimit >> LogBytesPerWord));
11236 match(Set dummy (ClearArray cnt base));
11237 effect(USE_KILL base, KILL cr);
11238
11239 ins_cost(4 * DEFAULT_COST);
11240 format %{ "ClearArray $cnt, $base\t#@clearArray_imm_reg" %}
11241
11242 ins_encode %{
11243 __ zero_words($base$$Register, (uint64_t)$cnt$$constant);
11244 %}
11245
11246 ins_pipe(pipe_class_memory);
11247 %}
11248
11249 instruct string_equalsL(iRegP_R11 str1, iRegP_R13 str2, iRegI_R14 cnt,
11250 iRegI_R10 result, rFlagsReg cr)
11251 %{
11252 predicate(!UseRVV && ((StrEqualsNode*)n)->encoding() == StrIntrinsicNode::LL);
11253 match(Set result (StrEquals (Binary str1 str2) cnt));
11254 effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt, KILL cr);
11255
11256 format %{ "String Equals $str1, $str2, $cnt -> $result\t#@string_equalsL" %}
11257 ins_encode %{
11258 // Count is in 8-bit bytes; non-Compact chars are 16 bits.
11259 __ string_equals($str1$$Register, $str2$$Register,
11260 $result$$Register, $cnt$$Register);
11261 %}
11262 ins_pipe(pipe_class_memory);
11263 %}
11264
11265 instruct array_equalsB(iRegP_R11 ary1, iRegP_R12 ary2, iRegI_R10 result,
11266 iRegP_R13 tmp1, iRegP_R14 tmp2, iRegP_R15 tmp3)
11267 %{
11268 predicate(!UseRVV && ((AryEqNode*)n)->encoding() == StrIntrinsicNode::LL);
11269 match(Set result (AryEq ary1 ary2));
11270 effect(USE_KILL ary1, USE_KILL ary2, TEMP tmp1, TEMP tmp2, TEMP tmp3);
11271
11272 format %{ "Array Equals $ary1, $ary2 -> $result\t#@array_equalsB // KILL all" %}
11273 ins_encode %{
11274 __ arrays_equals($ary1$$Register, $ary2$$Register,
11275 $tmp1$$Register, $tmp2$$Register, $tmp3$$Register,
11276 $result$$Register, 1);
11277 %}
11278 ins_pipe(pipe_class_memory);
11279 %}
11280
11281 instruct array_equalsC(iRegP_R11 ary1, iRegP_R12 ary2, iRegI_R10 result,
11282 iRegP_R13 tmp1, iRegP_R14 tmp2, iRegP_R15 tmp3)
11283 %{
11284 predicate(!UseRVV && ((AryEqNode*)n)->encoding() == StrIntrinsicNode::UU);
11285 match(Set result (AryEq ary1 ary2));
11286 effect(USE_KILL ary1, USE_KILL ary2, TEMP tmp1, TEMP tmp2, TEMP tmp3);
11287
11288 format %{ "Array Equals $ary1, $ary2 -> $result\t#@array_equalsC // KILL all" %}
11289 ins_encode %{
11290 __ arrays_equals($ary1$$Register, $ary2$$Register,
11291 $tmp1$$Register, $tmp2$$Register, $tmp3$$Register,
11292 $result$$Register, 2);
11293 %}
11294 ins_pipe(pipe_class_memory);
11295 %}
11296
11297 // fast ArraysSupport.vectorizedHashCode
11298 instruct arrays_hashcode(iRegP_R11 ary, iRegI_R12 cnt, iRegI_R10 result, immI basic_type,
11299 iRegLNoSp tmp1, iRegLNoSp tmp2,
11300 iRegLNoSp tmp3, iRegLNoSp tmp4,
11301 iRegLNoSp tmp5, iRegLNoSp tmp6, rFlagsReg cr)
11302 %{
11303 predicate(!UseRVV);
11304 match(Set result (VectorizedHashCode (Binary ary cnt) (Binary result basic_type)));
11305 effect(TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, TEMP tmp5, TEMP tmp6,
11306 USE_KILL ary, USE_KILL cnt, USE basic_type, KILL cr);
11307
11308 format %{ "Array HashCode array[] $ary,$cnt,$result,$basic_type -> $result // KILL all" %}
11309 ins_encode %{
11310 __ arrays_hashcode($ary$$Register, $cnt$$Register, $result$$Register,
11311 $tmp1$$Register, $tmp2$$Register, $tmp3$$Register,
11312 $tmp4$$Register, $tmp5$$Register, $tmp6$$Register,
11313 (BasicType)$basic_type$$constant);
11314 %}
11315 ins_pipe(pipe_class_memory);
11316 %}
11317
11318 // ============================================================================
11319 // Safepoint Instructions
11320
11321 instruct safePoint(iRegP poll)
11322 %{
11323 match(SafePoint poll);
11324
11325 ins_cost(2 * LOAD_COST);
11326 format %{
11327 "lwu zr, [$poll]\t# Safepoint: poll for GC, #@safePoint"
11328 %}
11329 ins_encode %{
11330 __ read_polling_page(as_Register($poll$$reg), 0, relocInfo::poll_type);
11331 %}
11332 ins_pipe(pipe_serial); // ins_pipe(iload_reg_mem);
11333 %}
11334
11335 // ============================================================================
11336 // This name is KNOWN by the ADLC and cannot be changed.
11337 // The ADLC forces a 'TypeRawPtr::BOTTOM' output type
11338 // for this guy.
11339 instruct tlsLoadP(javaThread_RegP dst)
11340 %{
11341 match(Set dst (ThreadLocal));
11342
11343 ins_cost(0);
11344
11345 format %{ " -- \t// $dst=Thread::current(), empty, #@tlsLoadP" %}
11346
11347 size(0);
11348
11349 ins_encode( /*empty*/ );
11350
11351 ins_pipe(pipe_class_empty);
11352 %}
11353
11354 // inlined locking and unlocking
11355 // using t1 as the 'flag' register to bridge the BoolNode producers and consumers
11356 instruct cmpFastLock(rFlagsReg cr, iRegP object, iRegP box,
11357 iRegPNoSp tmp1, iRegPNoSp tmp2, iRegPNoSp tmp3, iRegPNoSp tmp4)
11358 %{
11359 match(Set cr (FastLock object box));
11360 effect(TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4);
11361
11362 ins_cost(10 * DEFAULT_COST);
11363 format %{ "fastlock $object,$box\t! kills $tmp1,$tmp2,$tmp3,$tmp4 #@cmpFastLock" %}
11364
11365 ins_encode %{
11366 __ fast_lock($object$$Register, $box$$Register,
11367 $tmp1$$Register, $tmp2$$Register, $tmp3$$Register, $tmp4$$Register);
11368 %}
11369
11370 ins_pipe(pipe_serial);
11371 %}
11372
11373 // using t1 as the 'flag' register to bridge the BoolNode producers and consumers
11374 instruct cmpFastUnlock(rFlagsReg cr, iRegP object, iRegP box,
11375 iRegPNoSp tmp1, iRegPNoSp tmp2, iRegPNoSp tmp3)
11376 %{
11377 match(Set cr (FastUnlock object box));
11378 effect(TEMP tmp1, TEMP tmp2, TEMP tmp3);
11379
11380 ins_cost(10 * DEFAULT_COST);
11381 format %{ "fastunlock $object,$box\t! kills $tmp1,$tmp2,$tmp3 #@cmpFastUnlock" %}
11382
11383 ins_encode %{
11384 __ fast_unlock($object$$Register, $box$$Register,
11385 $tmp1$$Register, $tmp2$$Register, $tmp3$$Register);
11386 %}
11387
11388 ins_pipe(pipe_serial);
11389 %}
11390
11391 // Tail Call; Jump from runtime stub to Java code.
11392 // Also known as an 'interprocedural jump'.
11393 // Target of jump will eventually return to caller.
11394 // TailJump below removes the return address.
11395 // Don't use fp for 'jump_target' because a MachEpilogNode has already been
11396 // emitted just above the TailCall which has reset fp to the caller state.
11397 instruct TailCalljmpInd(iRegPNoSpNoFp jump_target, inline_cache_RegP method_oop)
11398 %{
11399 match(TailCall jump_target method_oop);
11400
11401 ins_cost(BRANCH_COST);
11402
11403 format %{ "jalr $jump_target\t# $method_oop holds method oop, #@TailCalljmpInd." %}
11404
11405 ins_encode(riscv_enc_tail_call(jump_target));
11406
11407 ins_pipe(pipe_class_call);
11408 %}
11409
11410 instruct TailjmpInd(iRegPNoSpNoFp jump_target, iRegP_R10 ex_oop)
11411 %{
11412 match(TailJump jump_target ex_oop);
11413
11414 ins_cost(ALU_COST + BRANCH_COST);
11415
11416 format %{ "jalr $jump_target\t# $ex_oop holds exception oop, #@TailjmpInd." %}
11417
11418 ins_encode(riscv_enc_tail_jmp(jump_target));
11419
11420 ins_pipe(pipe_class_call);
11421 %}
11422
11423 // Forward exception.
11424 instruct ForwardExceptionjmp()
11425 %{
11426 match(ForwardException);
11427
11428 ins_cost(BRANCH_COST);
11429
11430 format %{ "j forward_exception_stub\t#@ForwardException" %}
11431
11432 ins_encode %{
11433 __ far_jump(RuntimeAddress(StubRoutines::forward_exception_entry()));
11434 %}
11435
11436 ins_pipe(pipe_class_call);
11437 %}
11438
11439 // Create exception oop: created by stack-crawling runtime code.
11440 // Created exception is now available to this handler, and is setup
11441 // just prior to jumping to this handler. No code emitted.
11442 instruct CreateException(iRegP_R10 ex_oop)
11443 %{
11444 match(Set ex_oop (CreateEx));
11445
11446 ins_cost(0);
11447 format %{ " -- \t// exception oop; no code emitted, #@CreateException" %}
11448
11449 size(0);
11450
11451 ins_encode( /*empty*/ );
11452
11453 ins_pipe(pipe_class_empty);
11454 %}
11455
11456 // Rethrow exception: The exception oop will come in the first
11457 // argument position. Then JUMP (not call) to the rethrow stub code.
11458 instruct RethrowException()
11459 %{
11460 match(Rethrow);
11461
11462 ins_cost(BRANCH_COST);
11463
11464 format %{ "j rethrow_stub\t#@RethrowException" %}
11465
11466 ins_encode(riscv_enc_rethrow());
11467
11468 ins_pipe(pipe_class_call);
11469 %}
11470
11471 // Return Instruction
11472 // epilog node loads ret address into ra as part of frame pop
11473 instruct Ret()
11474 %{
11475 match(Return);
11476
11477 ins_cost(BRANCH_COST);
11478 format %{ "ret\t// return register, #@Ret" %}
11479
11480 ins_encode(riscv_enc_ret());
11481
11482 ins_pipe(pipe_branch);
11483 %}
11484
11485 // Die now.
11486 instruct ShouldNotReachHere() %{
11487 match(Halt);
11488
11489 ins_cost(BRANCH_COST);
11490
11491 format %{ "#@ShouldNotReachHere" %}
11492
11493 ins_encode %{
11494 if (is_reachable()) {
11495 const char* str = __ code_string(_halt_reason);
11496 __ stop(str);
11497 }
11498 %}
11499
11500 ins_pipe(pipe_class_default);
11501 %}
11502
11503
11504 //----------PEEPHOLE RULES-----------------------------------------------------
11505 // These must follow all instruction definitions as they use the names
11506 // defined in the instructions definitions.
11507 //
11508 // peepmatch ( root_instr_name [preceding_instruction]* );
11509 //
11510 // peepconstraint %{
11511 // (instruction_number.operand_name relational_op instruction_number.operand_name
11512 // [, ...] );
11513 // // instruction numbers are zero-based using left to right order in peepmatch
11514 //
11515 // peepreplace ( instr_name ( [instruction_number.operand_name]* ) );
11516 // // provide an instruction_number.operand_name for each operand that appears
11517 // // in the replacement instruction's match rule
11518 //
11519 // ---------VM FLAGS---------------------------------------------------------
11520 //
11521 // All peephole optimizations can be turned off using -XX:-OptoPeephole
11522 //
11523 // Each peephole rule is given an identifying number starting with zero and
11524 // increasing by one in the order seen by the parser. An individual peephole
11525 // can be enabled, and all others disabled, by using -XX:OptoPeepholeAt=#
11526 // on the command-line.
11527 //
11528 // ---------CURRENT LIMITATIONS----------------------------------------------
11529 //
11530 // Only match adjacent instructions in same basic block
11531 // Only equality constraints
11532 // Only constraints between operands, not (0.dest_reg == RAX_enc)
11533 // Only one replacement instruction
11534 //
11535 //----------SMARTSPILL RULES---------------------------------------------------
11536 // These must follow all instruction definitions as they use the names
11537 // defined in the instructions definitions.
11538
11539 // Local Variables:
11540 // mode: c++
11541 // End: