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