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