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