1 //
2 // Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved.
3 // DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 //
5 // This code is free software; you can redistribute it and/or modify it
6 // under the terms of the GNU General Public License version 2 only, as
7 // published by the Free Software Foundation.
8 //
9 // This code is distributed in the hope that it will be useful, but WITHOUT
10 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 // version 2 for more details (a copy is included in the LICENSE file that
13 // accompanied this code).
14 //
15 // You should have received a copy of the GNU General Public License version
16 // 2 along with this work; if not, write to the Free Software Foundation,
17 // Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 //
19 // Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 // or visit www.oracle.com if you need additional information or have any
21 // questions.
22 //
23 //
24
25 // AMD64 Architecture Description File
26
27 //----------REGISTER DEFINITION BLOCK------------------------------------------
28 // This information is used by the matcher and the register allocator to
29 // describe individual registers and classes of registers within the target
30 // architecture.
31
32 register %{
33 //----------Architecture Description Register Definitions----------------------
34 // General Registers
35 // "reg_def" name ( register save type, C convention save type,
36 // ideal register type, encoding );
37 // Register Save Types:
38 //
39 // NS = No-Save: The register allocator assumes that these registers
40 // can be used without saving upon entry to the method, &
41 // that they do not need to be saved at call sites.
42 //
43 // SOC = Save-On-Call: The register allocator assumes that these registers
44 // can be used without saving upon entry to the method,
45 // but that they must be saved at call sites.
46 //
47 // SOE = Save-On-Entry: The register allocator assumes that these registers
48 // must be saved before using them upon entry to the
49 // method, but they do not need to be saved at call
50 // sites.
51 //
52 // AS = Always-Save: The register allocator assumes that these registers
53 // must be saved before using them upon entry to the
54 // method, & that they must be saved at call sites.
55 //
56 // Ideal Register Type is used to determine how to save & restore a
57 // register. Op_RegI will get spilled with LoadI/StoreI, Op_RegP will get
58 // spilled with LoadP/StoreP. If the register supports both, use Op_RegI.
59 //
60 // The encoding number is the actual bit-pattern placed into the opcodes.
61
62 // General Registers
63 // R8-R15 must be encoded with REX. (RSP, RBP, RSI, RDI need REX when
64 // used as byte registers)
65
66 // Previously set RBX, RSI, and RDI as save-on-entry for java code
67 // Turn off SOE in java-code due to frequent use of uncommon-traps.
68 // Now that allocator is better, turn on RSI and RDI as SOE registers.
69
70 reg_def RAX (SOC, SOC, Op_RegI, 0, rax->as_VMReg());
71 reg_def RAX_H(SOC, SOC, Op_RegI, 0, rax->as_VMReg()->next());
72
73 reg_def RCX (SOC, SOC, Op_RegI, 1, rcx->as_VMReg());
74 reg_def RCX_H(SOC, SOC, Op_RegI, 1, rcx->as_VMReg()->next());
75
76 reg_def RDX (SOC, SOC, Op_RegI, 2, rdx->as_VMReg());
77 reg_def RDX_H(SOC, SOC, Op_RegI, 2, rdx->as_VMReg()->next());
78
79 reg_def RBX (SOC, SOE, Op_RegI, 3, rbx->as_VMReg());
80 reg_def RBX_H(SOC, SOE, Op_RegI, 3, rbx->as_VMReg()->next());
81
82 reg_def RSP (NS, NS, Op_RegI, 4, rsp->as_VMReg());
83 reg_def RSP_H(NS, NS, Op_RegI, 4, rsp->as_VMReg()->next());
84
85 // now that adapter frames are gone RBP is always saved and restored by the prolog/epilog code
86 reg_def RBP (NS, SOE, Op_RegI, 5, rbp->as_VMReg());
87 reg_def RBP_H(NS, SOE, Op_RegI, 5, rbp->as_VMReg()->next());
88
89 #ifdef _WIN64
90
91 reg_def RSI (SOC, SOE, Op_RegI, 6, rsi->as_VMReg());
92 reg_def RSI_H(SOC, SOE, Op_RegI, 6, rsi->as_VMReg()->next());
93
94 reg_def RDI (SOC, SOE, Op_RegI, 7, rdi->as_VMReg());
95 reg_def RDI_H(SOC, SOE, Op_RegI, 7, rdi->as_VMReg()->next());
96
97 #else
98
99 reg_def RSI (SOC, SOC, Op_RegI, 6, rsi->as_VMReg());
100 reg_def RSI_H(SOC, SOC, Op_RegI, 6, rsi->as_VMReg()->next());
101
102 reg_def RDI (SOC, SOC, Op_RegI, 7, rdi->as_VMReg());
103 reg_def RDI_H(SOC, SOC, Op_RegI, 7, rdi->as_VMReg()->next());
104
105 #endif
106
107 reg_def R8 (SOC, SOC, Op_RegI, 8, r8->as_VMReg());
108 reg_def R8_H (SOC, SOC, Op_RegI, 8, r8->as_VMReg()->next());
109
110 reg_def R9 (SOC, SOC, Op_RegI, 9, r9->as_VMReg());
111 reg_def R9_H (SOC, SOC, Op_RegI, 9, r9->as_VMReg()->next());
112
113 reg_def R10 (SOC, SOC, Op_RegI, 10, r10->as_VMReg());
114 reg_def R10_H(SOC, SOC, Op_RegI, 10, r10->as_VMReg()->next());
115
116 reg_def R11 (SOC, SOC, Op_RegI, 11, r11->as_VMReg());
117 reg_def R11_H(SOC, SOC, Op_RegI, 11, r11->as_VMReg()->next());
118
119 reg_def R12 (SOC, SOE, Op_RegI, 12, r12->as_VMReg());
120 reg_def R12_H(SOC, SOE, Op_RegI, 12, r12->as_VMReg()->next());
121
122 reg_def R13 (SOC, SOE, Op_RegI, 13, r13->as_VMReg());
123 reg_def R13_H(SOC, SOE, Op_RegI, 13, r13->as_VMReg()->next());
124
125 reg_def R14 (SOC, SOE, Op_RegI, 14, r14->as_VMReg());
126 reg_def R14_H(SOC, SOE, Op_RegI, 14, r14->as_VMReg()->next());
127
128 reg_def R15 (SOC, SOE, Op_RegI, 15, r15->as_VMReg());
129 reg_def R15_H(SOC, SOE, Op_RegI, 15, r15->as_VMReg()->next());
130
131 reg_def R16 (SOC, SOC, Op_RegI, 16, r16->as_VMReg());
132 reg_def R16_H(SOC, SOC, Op_RegI, 16, r16->as_VMReg()->next());
133
134 reg_def R17 (SOC, SOC, Op_RegI, 17, r17->as_VMReg());
135 reg_def R17_H(SOC, SOC, Op_RegI, 17, r17->as_VMReg()->next());
136
137 reg_def R18 (SOC, SOC, Op_RegI, 18, r18->as_VMReg());
138 reg_def R18_H(SOC, SOC, Op_RegI, 18, r18->as_VMReg()->next());
139
140 reg_def R19 (SOC, SOC, Op_RegI, 19, r19->as_VMReg());
141 reg_def R19_H(SOC, SOC, Op_RegI, 19, r19->as_VMReg()->next());
142
143 reg_def R20 (SOC, SOC, Op_RegI, 20, r20->as_VMReg());
144 reg_def R20_H(SOC, SOC, Op_RegI, 20, r20->as_VMReg()->next());
145
146 reg_def R21 (SOC, SOC, Op_RegI, 21, r21->as_VMReg());
147 reg_def R21_H(SOC, SOC, Op_RegI, 21, r21->as_VMReg()->next());
148
149 reg_def R22 (SOC, SOC, Op_RegI, 22, r22->as_VMReg());
150 reg_def R22_H(SOC, SOC, Op_RegI, 22, r22->as_VMReg()->next());
151
152 reg_def R23 (SOC, SOC, Op_RegI, 23, r23->as_VMReg());
153 reg_def R23_H(SOC, SOC, Op_RegI, 23, r23->as_VMReg()->next());
154
155 reg_def R24 (SOC, SOC, Op_RegI, 24, r24->as_VMReg());
156 reg_def R24_H(SOC, SOC, Op_RegI, 24, r24->as_VMReg()->next());
157
158 reg_def R25 (SOC, SOC, Op_RegI, 25, r25->as_VMReg());
159 reg_def R25_H(SOC, SOC, Op_RegI, 25, r25->as_VMReg()->next());
160
161 reg_def R26 (SOC, SOC, Op_RegI, 26, r26->as_VMReg());
162 reg_def R26_H(SOC, SOC, Op_RegI, 26, r26->as_VMReg()->next());
163
164 reg_def R27 (SOC, SOC, Op_RegI, 27, r27->as_VMReg());
165 reg_def R27_H(SOC, SOC, Op_RegI, 27, r27->as_VMReg()->next());
166
167 reg_def R28 (SOC, SOC, Op_RegI, 28, r28->as_VMReg());
168 reg_def R28_H(SOC, SOC, Op_RegI, 28, r28->as_VMReg()->next());
169
170 reg_def R29 (SOC, SOC, Op_RegI, 29, r29->as_VMReg());
171 reg_def R29_H(SOC, SOC, Op_RegI, 29, r29->as_VMReg()->next());
172
173 reg_def R30 (SOC, SOC, Op_RegI, 30, r30->as_VMReg());
174 reg_def R30_H(SOC, SOC, Op_RegI, 30, r30->as_VMReg()->next());
175
176 reg_def R31 (SOC, SOC, Op_RegI, 31, r31->as_VMReg());
177 reg_def R31_H(SOC, SOC, Op_RegI, 31, r31->as_VMReg()->next());
178
179 // Floating Point Registers
180
181 // Specify priority of register selection within phases of register
182 // allocation. Highest priority is first. A useful heuristic is to
183 // give registers a low priority when they are required by machine
184 // instructions, like EAX and EDX on I486, and choose no-save registers
185 // before save-on-call, & save-on-call before save-on-entry. Registers
186 // which participate in fixed calling sequences should come last.
187 // Registers which are used as pairs must fall on an even boundary.
188
189 alloc_class chunk0(R10, R10_H,
190 R11, R11_H,
191 R8, R8_H,
192 R9, R9_H,
193 R12, R12_H,
194 RCX, RCX_H,
195 RBX, RBX_H,
196 RDI, RDI_H,
197 RDX, RDX_H,
198 RSI, RSI_H,
199 RAX, RAX_H,
200 RBP, RBP_H,
201 R13, R13_H,
202 R14, R14_H,
203 R15, R15_H,
204 R16, R16_H,
205 R17, R17_H,
206 R18, R18_H,
207 R19, R19_H,
208 R20, R20_H,
209 R21, R21_H,
210 R22, R22_H,
211 R23, R23_H,
212 R24, R24_H,
213 R25, R25_H,
214 R26, R26_H,
215 R27, R27_H,
216 R28, R28_H,
217 R29, R29_H,
218 R30, R30_H,
219 R31, R31_H,
220 RSP, RSP_H);
221
222
223 //----------Architecture Description Register Classes--------------------------
224 // Several register classes are automatically defined based upon information in
225 // this architecture description.
226 // 1) reg_class inline_cache_reg ( /* as def'd in frame section */ )
227 // 2) reg_class stack_slots( /* one chunk of stack-based "registers" */ )
228 //
229
230 // Empty register class.
231 reg_class no_reg();
232
233 // Class for all pointer/long registers including APX extended GPRs.
234 reg_class all_reg(RAX, RAX_H,
235 RDX, RDX_H,
236 RBP, RBP_H,
237 RDI, RDI_H,
238 RSI, RSI_H,
239 RCX, RCX_H,
240 RBX, RBX_H,
241 RSP, RSP_H,
242 R8, R8_H,
243 R9, R9_H,
244 R10, R10_H,
245 R11, R11_H,
246 R12, R12_H,
247 R13, R13_H,
248 R14, R14_H,
249 R15, R15_H,
250 R16, R16_H,
251 R17, R17_H,
252 R18, R18_H,
253 R19, R19_H,
254 R20, R20_H,
255 R21, R21_H,
256 R22, R22_H,
257 R23, R23_H,
258 R24, R24_H,
259 R25, R25_H,
260 R26, R26_H,
261 R27, R27_H,
262 R28, R28_H,
263 R29, R29_H,
264 R30, R30_H,
265 R31, R31_H);
266
267 // Class for all int registers including APX extended GPRs.
268 reg_class all_int_reg(RAX
269 RDX,
270 RBP,
271 RDI,
272 RSI,
273 RCX,
274 RBX,
275 R8,
276 R9,
277 R10,
278 R11,
279 R12,
280 R13,
281 R14,
282 R16,
283 R17,
284 R18,
285 R19,
286 R20,
287 R21,
288 R22,
289 R23,
290 R24,
291 R25,
292 R26,
293 R27,
294 R28,
295 R29,
296 R30,
297 R31);
298
299 // Class for all pointer registers
300 reg_class any_reg %{
301 return _ANY_REG_mask;
302 %}
303
304 // Class for all pointer registers (excluding RSP)
305 reg_class ptr_reg %{
306 return _PTR_REG_mask;
307 %}
308
309 // Class for all pointer registers (excluding RSP and RBP)
310 reg_class ptr_reg_no_rbp %{
311 return _PTR_REG_NO_RBP_mask;
312 %}
313
314 // Class for all pointer registers (excluding RAX and RSP)
315 reg_class ptr_no_rax_reg %{
316 return _PTR_NO_RAX_REG_mask;
317 %}
318
319 // Class for all pointer registers (excluding RAX, RBX, and RSP)
320 reg_class ptr_no_rax_rbx_reg %{
321 return _PTR_NO_RAX_RBX_REG_mask;
322 %}
323
324 // Class for all long registers (excluding RSP)
325 reg_class long_reg %{
326 return _LONG_REG_mask;
327 %}
328
329 // Class for all long registers (excluding RAX, RDX and RSP)
330 reg_class long_no_rax_rdx_reg %{
331 return _LONG_NO_RAX_RDX_REG_mask;
332 %}
333
334 // Class for all long registers (excluding RCX and RSP)
335 reg_class long_no_rcx_reg %{
336 return _LONG_NO_RCX_REG_mask;
337 %}
338
339 // Class for all long registers (excluding RBP and R13)
340 reg_class long_no_rbp_r13_reg %{
341 return _LONG_NO_RBP_R13_REG_mask;
342 %}
343
344 // Class for all int registers (excluding RSP)
345 reg_class int_reg %{
346 return _INT_REG_mask;
347 %}
348
349 // Class for all int registers (excluding RAX, RDX, and RSP)
350 reg_class int_no_rax_rdx_reg %{
351 return _INT_NO_RAX_RDX_REG_mask;
352 %}
353
354 // Class for all int registers (excluding RCX and RSP)
355 reg_class int_no_rcx_reg %{
356 return _INT_NO_RCX_REG_mask;
357 %}
358
359 // Class for all int registers (excluding RBP and R13)
360 reg_class int_no_rbp_r13_reg %{
361 return _INT_NO_RBP_R13_REG_mask;
362 %}
363
364 // Singleton class for RAX pointer register
365 reg_class ptr_rax_reg(RAX, RAX_H);
366
367 // Singleton class for RBX pointer register
368 reg_class ptr_rbx_reg(RBX, RBX_H);
369
370 // Singleton class for RSI pointer register
371 reg_class ptr_rsi_reg(RSI, RSI_H);
372
373 // Singleton class for RBP pointer register
374 reg_class ptr_rbp_reg(RBP, RBP_H);
375
376 // Singleton class for RDI pointer register
377 reg_class ptr_rdi_reg(RDI, RDI_H);
378
379 // Singleton class for stack pointer
380 reg_class ptr_rsp_reg(RSP, RSP_H);
381
382 // Singleton class for TLS pointer
383 reg_class ptr_r15_reg(R15, R15_H);
384
385 // Singleton class for RAX long register
386 reg_class long_rax_reg(RAX, RAX_H);
387
388 // Singleton class for RCX long register
389 reg_class long_rcx_reg(RCX, RCX_H);
390
391 // Singleton class for RDX long register
392 reg_class long_rdx_reg(RDX, RDX_H);
393
394 // Singleton class for R11 long register
395 reg_class long_r11_reg(R11, R11_H);
396
397 // Singleton class for RAX int register
398 reg_class int_rax_reg(RAX);
399
400 // Singleton class for RBX int register
401 reg_class int_rbx_reg(RBX);
402
403 // Singleton class for RCX int register
404 reg_class int_rcx_reg(RCX);
405
406 // Singleton class for RDX int register
407 reg_class int_rdx_reg(RDX);
408
409 // Singleton class for RDI int register
410 reg_class int_rdi_reg(RDI);
411
412 // Singleton class for instruction pointer
413 // reg_class ip_reg(RIP);
414
415 %}
416
417 //----------SOURCE BLOCK-------------------------------------------------------
418 // This is a block of C++ code which provides values, functions, and
419 // definitions necessary in the rest of the architecture description
420
421 source_hpp %{
422
423 #include "peephole_x86_64.hpp"
424
425 bool castLL_is_imm32(const Node* n);
426
427 %}
428
429 source %{
430
431 bool castLL_is_imm32(const Node* n) {
432 assert(n->is_CastLL(), "must be a CastLL");
433 const TypeLong* t = n->bottom_type()->is_long();
434 return (t->_lo == min_jlong || Assembler::is_simm32(t->_lo)) && (t->_hi == max_jlong || Assembler::is_simm32(t->_hi));
435 }
436
437 %}
438
439 // Register masks
440 source_hpp %{
441
442 extern RegMask _ANY_REG_mask;
443 extern RegMask _PTR_REG_mask;
444 extern RegMask _PTR_REG_NO_RBP_mask;
445 extern RegMask _PTR_NO_RAX_REG_mask;
446 extern RegMask _PTR_NO_RAX_RBX_REG_mask;
447 extern RegMask _LONG_REG_mask;
448 extern RegMask _LONG_NO_RAX_RDX_REG_mask;
449 extern RegMask _LONG_NO_RCX_REG_mask;
450 extern RegMask _LONG_NO_RBP_R13_REG_mask;
451 extern RegMask _INT_REG_mask;
452 extern RegMask _INT_NO_RAX_RDX_REG_mask;
453 extern RegMask _INT_NO_RCX_REG_mask;
454 extern RegMask _INT_NO_RBP_R13_REG_mask;
455 extern RegMask _FLOAT_REG_mask;
456
457 extern RegMask _STACK_OR_PTR_REG_mask;
458 extern RegMask _STACK_OR_LONG_REG_mask;
459 extern RegMask _STACK_OR_INT_REG_mask;
460
461 inline const RegMask& STACK_OR_PTR_REG_mask() { return _STACK_OR_PTR_REG_mask; }
462 inline const RegMask& STACK_OR_LONG_REG_mask() { return _STACK_OR_LONG_REG_mask; }
463 inline const RegMask& STACK_OR_INT_REG_mask() { return _STACK_OR_INT_REG_mask; }
464
465 %}
466
467 source %{
468 #define RELOC_IMM64 Assembler::imm_operand
469 #define RELOC_DISP32 Assembler::disp32_operand
470
471 #define __ masm->
472
473 RegMask _ANY_REG_mask;
474 RegMask _PTR_REG_mask;
475 RegMask _PTR_REG_NO_RBP_mask;
476 RegMask _PTR_NO_RAX_REG_mask;
477 RegMask _PTR_NO_RAX_RBX_REG_mask;
478 RegMask _LONG_REG_mask;
479 RegMask _LONG_NO_RAX_RDX_REG_mask;
480 RegMask _LONG_NO_RCX_REG_mask;
481 RegMask _LONG_NO_RBP_R13_REG_mask;
482 RegMask _INT_REG_mask;
483 RegMask _INT_NO_RAX_RDX_REG_mask;
484 RegMask _INT_NO_RCX_REG_mask;
485 RegMask _INT_NO_RBP_R13_REG_mask;
486 RegMask _FLOAT_REG_mask;
487 RegMask _STACK_OR_PTR_REG_mask;
488 RegMask _STACK_OR_LONG_REG_mask;
489 RegMask _STACK_OR_INT_REG_mask;
490
491 static bool need_r12_heapbase() {
492 return UseCompressedOops;
493 }
494
495 void reg_mask_init() {
496 constexpr Register egprs[] = {r16, r17, r18, r19, r20, r21, r22, r23, r24, r25, r26, r27, r28, r29, r30, r31};
497
498 // _ALL_REG_mask is generated by adlc from the all_reg register class below.
499 // We derive a number of subsets from it.
500 _ANY_REG_mask = _ALL_REG_mask;
501
502 if (PreserveFramePointer) {
503 _ANY_REG_mask.Remove(OptoReg::as_OptoReg(rbp->as_VMReg()));
504 _ANY_REG_mask.Remove(OptoReg::as_OptoReg(rbp->as_VMReg()->next()));
505 }
506 if (need_r12_heapbase()) {
507 _ANY_REG_mask.Remove(OptoReg::as_OptoReg(r12->as_VMReg()));
508 _ANY_REG_mask.Remove(OptoReg::as_OptoReg(r12->as_VMReg()->next()));
509 }
510
511 _PTR_REG_mask = _ANY_REG_mask;
512 _PTR_REG_mask.Remove(OptoReg::as_OptoReg(rsp->as_VMReg()));
513 _PTR_REG_mask.Remove(OptoReg::as_OptoReg(rsp->as_VMReg()->next()));
514 _PTR_REG_mask.Remove(OptoReg::as_OptoReg(r15->as_VMReg()));
515 _PTR_REG_mask.Remove(OptoReg::as_OptoReg(r15->as_VMReg()->next()));
516 if (!UseAPX) {
517 for (uint i = 0; i < sizeof(egprs)/sizeof(Register); i++) {
518 _PTR_REG_mask.Remove(OptoReg::as_OptoReg(egprs[i]->as_VMReg()));
519 _PTR_REG_mask.Remove(OptoReg::as_OptoReg(egprs[i]->as_VMReg()->next()));
520 }
521 }
522
523 _STACK_OR_PTR_REG_mask = _PTR_REG_mask;
524 _STACK_OR_PTR_REG_mask.OR(STACK_OR_STACK_SLOTS_mask());
525
526 _PTR_REG_NO_RBP_mask = _PTR_REG_mask;
527 _PTR_REG_NO_RBP_mask.Remove(OptoReg::as_OptoReg(rbp->as_VMReg()));
528 _PTR_REG_NO_RBP_mask.Remove(OptoReg::as_OptoReg(rbp->as_VMReg()->next()));
529
530 _PTR_NO_RAX_REG_mask = _PTR_REG_mask;
531 _PTR_NO_RAX_REG_mask.Remove(OptoReg::as_OptoReg(rax->as_VMReg()));
532 _PTR_NO_RAX_REG_mask.Remove(OptoReg::as_OptoReg(rax->as_VMReg()->next()));
533
534 _PTR_NO_RAX_RBX_REG_mask = _PTR_NO_RAX_REG_mask;
535 _PTR_NO_RAX_RBX_REG_mask.Remove(OptoReg::as_OptoReg(rbx->as_VMReg()));
536 _PTR_NO_RAX_RBX_REG_mask.Remove(OptoReg::as_OptoReg(rbx->as_VMReg()->next()));
537
538
539 _LONG_REG_mask = _PTR_REG_mask;
540 _STACK_OR_LONG_REG_mask = _LONG_REG_mask;
541 _STACK_OR_LONG_REG_mask.OR(STACK_OR_STACK_SLOTS_mask());
542
543 _LONG_NO_RAX_RDX_REG_mask = _LONG_REG_mask;
544 _LONG_NO_RAX_RDX_REG_mask.Remove(OptoReg::as_OptoReg(rax->as_VMReg()));
545 _LONG_NO_RAX_RDX_REG_mask.Remove(OptoReg::as_OptoReg(rax->as_VMReg()->next()));
546 _LONG_NO_RAX_RDX_REG_mask.Remove(OptoReg::as_OptoReg(rdx->as_VMReg()));
547 _LONG_NO_RAX_RDX_REG_mask.Remove(OptoReg::as_OptoReg(rdx->as_VMReg()->next()));
548
549 _LONG_NO_RCX_REG_mask = _LONG_REG_mask;
550 _LONG_NO_RCX_REG_mask.Remove(OptoReg::as_OptoReg(rcx->as_VMReg()));
551 _LONG_NO_RCX_REG_mask.Remove(OptoReg::as_OptoReg(rcx->as_VMReg()->next()));
552
553 _LONG_NO_RBP_R13_REG_mask = _LONG_REG_mask;
554 _LONG_NO_RBP_R13_REG_mask.Remove(OptoReg::as_OptoReg(rbp->as_VMReg()));
555 _LONG_NO_RBP_R13_REG_mask.Remove(OptoReg::as_OptoReg(rbp->as_VMReg()->next()));
556 _LONG_NO_RBP_R13_REG_mask.Remove(OptoReg::as_OptoReg(r13->as_VMReg()));
557 _LONG_NO_RBP_R13_REG_mask.Remove(OptoReg::as_OptoReg(r13->as_VMReg()->next()));
558
559 _INT_REG_mask = _ALL_INT_REG_mask;
560 if (!UseAPX) {
561 for (uint i = 0; i < sizeof(egprs)/sizeof(Register); i++) {
562 _INT_REG_mask.Remove(OptoReg::as_OptoReg(egprs[i]->as_VMReg()));
563 }
564 }
565
566 if (PreserveFramePointer) {
567 _INT_REG_mask.Remove(OptoReg::as_OptoReg(rbp->as_VMReg()));
568 }
569 if (need_r12_heapbase()) {
570 _INT_REG_mask.Remove(OptoReg::as_OptoReg(r12->as_VMReg()));
571 }
572
573 _STACK_OR_INT_REG_mask = _INT_REG_mask;
574 _STACK_OR_INT_REG_mask.OR(STACK_OR_STACK_SLOTS_mask());
575
576 _INT_NO_RAX_RDX_REG_mask = _INT_REG_mask;
577 _INT_NO_RAX_RDX_REG_mask.Remove(OptoReg::as_OptoReg(rax->as_VMReg()));
578 _INT_NO_RAX_RDX_REG_mask.Remove(OptoReg::as_OptoReg(rdx->as_VMReg()));
579
580 _INT_NO_RCX_REG_mask = _INT_REG_mask;
581 _INT_NO_RCX_REG_mask.Remove(OptoReg::as_OptoReg(rcx->as_VMReg()));
582
583 _INT_NO_RBP_R13_REG_mask = _INT_REG_mask;
584 _INT_NO_RBP_R13_REG_mask.Remove(OptoReg::as_OptoReg(rbp->as_VMReg()));
585 _INT_NO_RBP_R13_REG_mask.Remove(OptoReg::as_OptoReg(r13->as_VMReg()));
586
587 // _FLOAT_REG_LEGACY_mask/_FLOAT_REG_EVEX_mask is generated by adlc
588 // from the float_reg_legacy/float_reg_evex register class.
589 _FLOAT_REG_mask = VM_Version::supports_evex() ? _FLOAT_REG_EVEX_mask : _FLOAT_REG_LEGACY_mask;
590 }
591
592 static bool generate_vzeroupper(Compile* C) {
593 return (VM_Version::supports_vzeroupper() && (C->max_vector_size() > 16 || C->clear_upper_avx() == true)) ? true: false; // Generate vzeroupper
594 }
595
596 static int clear_avx_size() {
597 return generate_vzeroupper(Compile::current()) ? 3: 0; // vzeroupper
598 }
599
600 // !!!!! Special hack to get all types of calls to specify the byte offset
601 // from the start of the call to the point where the return address
602 // will point.
603 int MachCallStaticJavaNode::ret_addr_offset()
604 {
605 int offset = 5; // 5 bytes from start of call to where return address points
606 offset += clear_avx_size();
607 return offset;
608 }
609
610 int MachCallDynamicJavaNode::ret_addr_offset()
611 {
612 int offset = 15; // 15 bytes from start of call to where return address points
613 offset += clear_avx_size();
614 return offset;
615 }
616
617 int MachCallRuntimeNode::ret_addr_offset() {
618 if (_entry_point == nullptr) {
619 // CallLeafNoFPInDirect
620 return 3; // callq (register)
621 }
622 int offset = 13; // movq r10,#addr; callq (r10)
623 if (this->ideal_Opcode() != Op_CallLeafVector) {
624 offset += clear_avx_size();
625 }
626 return offset;
627 }
628
629 //
630 // Compute padding required for nodes which need alignment
631 //
632
633 // The address of the call instruction needs to be 4-byte aligned to
634 // ensure that it does not span a cache line so that it can be patched.
635 int CallStaticJavaDirectNode::compute_padding(int current_offset) const
636 {
637 current_offset += clear_avx_size(); // skip vzeroupper
638 current_offset += 1; // skip call opcode byte
639 return align_up(current_offset, alignment_required()) - current_offset;
640 }
641
642 // The address of the call instruction needs to be 4-byte aligned to
643 // ensure that it does not span a cache line so that it can be patched.
644 int CallDynamicJavaDirectNode::compute_padding(int current_offset) const
645 {
646 current_offset += clear_avx_size(); // skip vzeroupper
647 current_offset += 11; // skip movq instruction + call opcode byte
648 return align_up(current_offset, alignment_required()) - current_offset;
649 }
650
651 // This could be in MacroAssembler but it's fairly C2 specific
652 static void emit_cmpfp_fixup(MacroAssembler* masm) {
653 Label exit;
654 __ jccb(Assembler::noParity, exit);
655 __ pushf();
656 //
657 // comiss/ucomiss instructions set ZF,PF,CF flags and
658 // zero OF,AF,SF for NaN values.
659 // Fixup flags by zeroing ZF,PF so that compare of NaN
660 // values returns 'less than' result (CF is set).
661 // Leave the rest of flags unchanged.
662 //
663 // 7 6 5 4 3 2 1 0
664 // |S|Z|r|A|r|P|r|C| (r - reserved bit)
665 // 0 0 1 0 1 0 1 1 (0x2B)
666 //
667 __ andq(Address(rsp, 0), 0xffffff2b);
668 __ popf();
669 __ bind(exit);
670 }
671
672 static void emit_cmpfp3(MacroAssembler* masm, Register dst) {
673 Label done;
674 __ movl(dst, -1);
675 __ jcc(Assembler::parity, done);
676 __ jcc(Assembler::below, done);
677 __ setcc(Assembler::notEqual, dst);
678 __ bind(done);
679 }
680
681 // Math.min() # Math.max()
682 // --------------------------
683 // ucomis[s/d] #
684 // ja -> b # a
685 // jp -> NaN # NaN
686 // jb -> a # b
687 // je #
688 // |-jz -> a | b # a & b
689 // | -> a #
690 static void emit_fp_min_max(MacroAssembler* masm, XMMRegister dst,
691 XMMRegister a, XMMRegister b,
692 XMMRegister xmmt, Register rt,
693 bool min, bool single) {
694
695 Label nan, zero, below, above, done;
696
697 if (single)
698 __ ucomiss(a, b);
699 else
700 __ ucomisd(a, b);
701
702 if (dst->encoding() != (min ? b : a)->encoding())
703 __ jccb(Assembler::above, above); // CF=0 & ZF=0
704 else
705 __ jccb(Assembler::above, done);
706
707 __ jccb(Assembler::parity, nan); // PF=1
708 __ jccb(Assembler::below, below); // CF=1
709
710 // equal
711 __ vpxor(xmmt, xmmt, xmmt, Assembler::AVX_128bit);
712 if (single) {
713 __ ucomiss(a, xmmt);
714 __ jccb(Assembler::equal, zero);
715
716 __ movflt(dst, a);
717 __ jmp(done);
718 }
719 else {
720 __ ucomisd(a, xmmt);
721 __ jccb(Assembler::equal, zero);
722
723 __ movdbl(dst, a);
724 __ jmp(done);
725 }
726
727 __ bind(zero);
728 if (min)
729 __ vpor(dst, a, b, Assembler::AVX_128bit);
730 else
731 __ vpand(dst, a, b, Assembler::AVX_128bit);
732
733 __ jmp(done);
734
735 __ bind(above);
736 if (single)
737 __ movflt(dst, min ? b : a);
738 else
739 __ movdbl(dst, min ? b : a);
740
741 __ jmp(done);
742
743 __ bind(nan);
744 if (single) {
745 __ movl(rt, 0x7fc00000); // Float.NaN
746 __ movdl(dst, rt);
747 }
748 else {
749 __ mov64(rt, 0x7ff8000000000000L); // Double.NaN
750 __ movdq(dst, rt);
751 }
752 __ jmp(done);
753
754 __ bind(below);
755 if (single)
756 __ movflt(dst, min ? a : b);
757 else
758 __ movdbl(dst, min ? a : b);
759
760 __ bind(done);
761 }
762
763 //=============================================================================
764 const RegMask& MachConstantBaseNode::_out_RegMask = RegMask::Empty;
765
766 int ConstantTable::calculate_table_base_offset() const {
767 return 0; // absolute addressing, no offset
768 }
769
770 bool MachConstantBaseNode::requires_postalloc_expand() const { return false; }
771 void MachConstantBaseNode::postalloc_expand(GrowableArray <Node *> *nodes, PhaseRegAlloc *ra_) {
772 ShouldNotReachHere();
773 }
774
775 void MachConstantBaseNode::emit(C2_MacroAssembler* masm, PhaseRegAlloc* ra_) const {
776 // Empty encoding
777 }
778
779 uint MachConstantBaseNode::size(PhaseRegAlloc* ra_) const {
780 return 0;
781 }
782
783 #ifndef PRODUCT
784 void MachConstantBaseNode::format(PhaseRegAlloc* ra_, outputStream* st) const {
785 st->print("# MachConstantBaseNode (empty encoding)");
786 }
787 #endif
788
789
790 //=============================================================================
791 #ifndef PRODUCT
792 void MachPrologNode::format(PhaseRegAlloc* ra_, outputStream* st) const {
793 Compile* C = ra_->C;
794
795 int framesize = C->output()->frame_size_in_bytes();
796 int bangsize = C->output()->bang_size_in_bytes();
797 assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned");
798 // Remove wordSize for return addr which is already pushed.
799 framesize -= wordSize;
800
801 if (C->output()->need_stack_bang(bangsize)) {
802 framesize -= wordSize;
803 st->print("# stack bang (%d bytes)", bangsize);
804 st->print("\n\t");
805 st->print("pushq rbp\t# Save rbp");
806 if (PreserveFramePointer) {
807 st->print("\n\t");
808 st->print("movq rbp, rsp\t# Save the caller's SP into rbp");
809 }
810 if (framesize) {
811 st->print("\n\t");
812 st->print("subq rsp, #%d\t# Create frame",framesize);
813 }
814 } else {
815 st->print("subq rsp, #%d\t# Create frame",framesize);
816 st->print("\n\t");
817 framesize -= wordSize;
818 st->print("movq [rsp + #%d], rbp\t# Save rbp",framesize);
819 if (PreserveFramePointer) {
820 st->print("\n\t");
821 st->print("movq rbp, rsp\t# Save the caller's SP into rbp");
822 if (framesize > 0) {
823 st->print("\n\t");
824 st->print("addq rbp, #%d", framesize);
825 }
826 }
827 }
828
829 if (VerifyStackAtCalls) {
830 st->print("\n\t");
831 framesize -= wordSize;
832 st->print("movq [rsp + #%d], 0xbadb100d\t# Majik cookie for stack depth check",framesize);
833 #ifdef ASSERT
834 st->print("\n\t");
835 st->print("# stack alignment check");
836 #endif
837 }
838 if (C->stub_function() != nullptr) {
839 st->print("\n\t");
840 st->print("cmpl [r15_thread + #disarmed_guard_value_offset], #disarmed_guard_value\t");
841 st->print("\n\t");
842 st->print("je fast_entry\t");
843 st->print("\n\t");
844 st->print("call #nmethod_entry_barrier_stub\t");
845 st->print("\n\tfast_entry:");
846 }
847 st->cr();
848 }
849 #endif
850
851 void MachPrologNode::emit(C2_MacroAssembler *masm, PhaseRegAlloc *ra_) const {
852 Compile* C = ra_->C;
853
854 __ verified_entry(C);
855
856 if (ra_->C->stub_function() == nullptr) {
857 __ entry_barrier();
858 }
859
860 if (!Compile::current()->output()->in_scratch_emit_size()) {
861 __ bind(*_verified_entry);
862 }
863
864 C->output()->set_frame_complete(__ offset());
865
866 if (C->has_mach_constant_base_node()) {
867 // NOTE: We set the table base offset here because users might be
868 // emitted before MachConstantBaseNode.
869 ConstantTable& constant_table = C->output()->constant_table();
870 constant_table.set_table_base_offset(constant_table.calculate_table_base_offset());
871 }
872 }
873
874 int MachPrologNode::reloc() const
875 {
876 return 0; // a large enough number
877 }
878
879 //=============================================================================
880 #ifndef PRODUCT
881 void MachEpilogNode::format(PhaseRegAlloc* ra_, outputStream* st) const
882 {
883 Compile* C = ra_->C;
884 if (generate_vzeroupper(C)) {
885 st->print("vzeroupper");
886 st->cr(); st->print("\t");
887 }
888
889 int framesize = C->output()->frame_size_in_bytes();
890 assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned");
891 // Remove word for return adr already pushed
892 // and RBP
893 framesize -= 2*wordSize;
894
895 if (framesize) {
896 st->print_cr("addq rsp, %d\t# Destroy frame", framesize);
897 st->print("\t");
898 }
899
900 st->print_cr("popq rbp");
901 if (do_polling() && C->is_method_compilation()) {
902 st->print("\t");
903 st->print_cr("cmpq rsp, poll_offset[r15_thread] \n\t"
904 "ja #safepoint_stub\t"
905 "# Safepoint: poll for GC");
906 }
907 }
908 #endif
909
910 void MachEpilogNode::emit(C2_MacroAssembler* masm, PhaseRegAlloc* ra_) const
911 {
912 Compile* C = ra_->C;
913
914 if (generate_vzeroupper(C)) {
915 // Clear upper bits of YMM registers when current compiled code uses
916 // wide vectors to avoid AVX <-> SSE transition penalty during call.
917 __ vzeroupper();
918 }
919
920 // Subtract two words to account for return address and rbp
921 int initial_framesize = C->output()->frame_size_in_bytes() - 2*wordSize;
922 __ remove_frame(initial_framesize, C->needs_stack_repair());
923
924 if (StackReservedPages > 0 && C->has_reserved_stack_access()) {
925 __ reserved_stack_check();
926 }
927
928 if (do_polling() && C->is_method_compilation()) {
929 Label dummy_label;
930 Label* code_stub = &dummy_label;
931 if (!C->output()->in_scratch_emit_size()) {
932 C2SafepointPollStub* stub = new (C->comp_arena()) C2SafepointPollStub(__ offset());
933 C->output()->add_stub(stub);
934 code_stub = &stub->entry();
935 }
936 __ relocate(relocInfo::poll_return_type);
937 __ safepoint_poll(*code_stub, true /* at_return */, true /* in_nmethod */);
938 }
939 }
940
941 int MachEpilogNode::reloc() const
942 {
943 return 2; // a large enough number
944 }
945
946 const Pipeline* MachEpilogNode::pipeline() const
947 {
948 return MachNode::pipeline_class();
949 }
950
951 //=============================================================================
952
953 enum RC {
954 rc_bad,
955 rc_int,
956 rc_kreg,
957 rc_float,
958 rc_stack
959 };
960
961 static enum RC rc_class(OptoReg::Name reg)
962 {
963 if( !OptoReg::is_valid(reg) ) return rc_bad;
964
965 if (OptoReg::is_stack(reg)) return rc_stack;
966
967 VMReg r = OptoReg::as_VMReg(reg);
968
969 if (r->is_Register()) return rc_int;
970
971 if (r->is_KRegister()) return rc_kreg;
972
973 assert(r->is_XMMRegister(), "must be");
974 return rc_float;
975 }
976
977 // Next two methods are shared by 32- and 64-bit VM. They are defined in x86.ad.
978 static void vec_mov_helper(C2_MacroAssembler *masm, int src_lo, int dst_lo,
979 int src_hi, int dst_hi, uint ireg, outputStream* st);
980
981 void vec_spill_helper(C2_MacroAssembler *masm, bool is_load,
982 int stack_offset, int reg, uint ireg, outputStream* st);
983
984 static void vec_stack_to_stack_helper(C2_MacroAssembler *masm, int src_offset,
985 int dst_offset, uint ireg, outputStream* st) {
986 if (masm) {
987 switch (ireg) {
988 case Op_VecS:
989 __ movq(Address(rsp, -8), rax);
990 __ movl(rax, Address(rsp, src_offset));
991 __ movl(Address(rsp, dst_offset), rax);
992 __ movq(rax, Address(rsp, -8));
993 break;
994 case Op_VecD:
995 __ pushq(Address(rsp, src_offset));
996 __ popq (Address(rsp, dst_offset));
997 break;
998 case Op_VecX:
999 __ pushq(Address(rsp, src_offset));
1000 __ popq (Address(rsp, dst_offset));
1001 __ pushq(Address(rsp, src_offset+8));
1002 __ popq (Address(rsp, dst_offset+8));
1003 break;
1004 case Op_VecY:
1005 __ vmovdqu(Address(rsp, -32), xmm0);
1006 __ vmovdqu(xmm0, Address(rsp, src_offset));
1007 __ vmovdqu(Address(rsp, dst_offset), xmm0);
1008 __ vmovdqu(xmm0, Address(rsp, -32));
1009 break;
1010 case Op_VecZ:
1011 __ evmovdquq(Address(rsp, -64), xmm0, 2);
1012 __ evmovdquq(xmm0, Address(rsp, src_offset), 2);
1013 __ evmovdquq(Address(rsp, dst_offset), xmm0, 2);
1014 __ evmovdquq(xmm0, Address(rsp, -64), 2);
1015 break;
1016 default:
1017 ShouldNotReachHere();
1018 }
1019 #ifndef PRODUCT
1020 } else {
1021 switch (ireg) {
1022 case Op_VecS:
1023 st->print("movq [rsp - #8], rax\t# 32-bit mem-mem spill\n\t"
1024 "movl rax, [rsp + #%d]\n\t"
1025 "movl [rsp + #%d], rax\n\t"
1026 "movq rax, [rsp - #8]",
1027 src_offset, dst_offset);
1028 break;
1029 case Op_VecD:
1030 st->print("pushq [rsp + #%d]\t# 64-bit mem-mem spill\n\t"
1031 "popq [rsp + #%d]",
1032 src_offset, dst_offset);
1033 break;
1034 case Op_VecX:
1035 st->print("pushq [rsp + #%d]\t# 128-bit mem-mem spill\n\t"
1036 "popq [rsp + #%d]\n\t"
1037 "pushq [rsp + #%d]\n\t"
1038 "popq [rsp + #%d]",
1039 src_offset, dst_offset, src_offset+8, dst_offset+8);
1040 break;
1041 case Op_VecY:
1042 st->print("vmovdqu [rsp - #32], xmm0\t# 256-bit mem-mem spill\n\t"
1043 "vmovdqu xmm0, [rsp + #%d]\n\t"
1044 "vmovdqu [rsp + #%d], xmm0\n\t"
1045 "vmovdqu xmm0, [rsp - #32]",
1046 src_offset, dst_offset);
1047 break;
1048 case Op_VecZ:
1049 st->print("vmovdqu [rsp - #64], xmm0\t# 512-bit mem-mem spill\n\t"
1050 "vmovdqu xmm0, [rsp + #%d]\n\t"
1051 "vmovdqu [rsp + #%d], xmm0\n\t"
1052 "vmovdqu xmm0, [rsp - #64]",
1053 src_offset, dst_offset);
1054 break;
1055 default:
1056 ShouldNotReachHere();
1057 }
1058 #endif
1059 }
1060 }
1061
1062 uint MachSpillCopyNode::implementation(C2_MacroAssembler* masm,
1063 PhaseRegAlloc* ra_,
1064 bool do_size,
1065 outputStream* st) const {
1066 assert(masm != nullptr || st != nullptr, "sanity");
1067 // Get registers to move
1068 OptoReg::Name src_second = ra_->get_reg_second(in(1));
1069 OptoReg::Name src_first = ra_->get_reg_first(in(1));
1070 OptoReg::Name dst_second = ra_->get_reg_second(this);
1071 OptoReg::Name dst_first = ra_->get_reg_first(this);
1072
1073 enum RC src_second_rc = rc_class(src_second);
1074 enum RC src_first_rc = rc_class(src_first);
1075 enum RC dst_second_rc = rc_class(dst_second);
1076 enum RC dst_first_rc = rc_class(dst_first);
1077
1078 assert(OptoReg::is_valid(src_first) && OptoReg::is_valid(dst_first),
1079 "must move at least 1 register" );
1080
1081 if (src_first == dst_first && src_second == dst_second) {
1082 // Self copy, no move
1083 return 0;
1084 }
1085 if (bottom_type()->isa_vect() != nullptr && bottom_type()->isa_vectmask() == nullptr) {
1086 uint ireg = ideal_reg();
1087 assert((src_first_rc != rc_int && dst_first_rc != rc_int), "sanity");
1088 assert((ireg == Op_VecS || ireg == Op_VecD || ireg == Op_VecX || ireg == Op_VecY || ireg == Op_VecZ ), "sanity");
1089 if( src_first_rc == rc_stack && dst_first_rc == rc_stack ) {
1090 // mem -> mem
1091 int src_offset = ra_->reg2offset(src_first);
1092 int dst_offset = ra_->reg2offset(dst_first);
1093 vec_stack_to_stack_helper(masm, src_offset, dst_offset, ireg, st);
1094 } else if (src_first_rc == rc_float && dst_first_rc == rc_float ) {
1095 vec_mov_helper(masm, src_first, dst_first, src_second, dst_second, ireg, st);
1096 } else if (src_first_rc == rc_float && dst_first_rc == rc_stack ) {
1097 int stack_offset = ra_->reg2offset(dst_first);
1098 vec_spill_helper(masm, false, stack_offset, src_first, ireg, st);
1099 } else if (src_first_rc == rc_stack && dst_first_rc == rc_float ) {
1100 int stack_offset = ra_->reg2offset(src_first);
1101 vec_spill_helper(masm, true, stack_offset, dst_first, ireg, st);
1102 } else {
1103 ShouldNotReachHere();
1104 }
1105 return 0;
1106 }
1107 if (src_first_rc == rc_stack) {
1108 // mem ->
1109 if (dst_first_rc == rc_stack) {
1110 // mem -> mem
1111 assert(src_second != dst_first, "overlap");
1112 if ((src_first & 1) == 0 && src_first + 1 == src_second &&
1113 (dst_first & 1) == 0 && dst_first + 1 == dst_second) {
1114 // 64-bit
1115 int src_offset = ra_->reg2offset(src_first);
1116 int dst_offset = ra_->reg2offset(dst_first);
1117 if (masm) {
1118 __ pushq(Address(rsp, src_offset));
1119 __ popq (Address(rsp, dst_offset));
1120 #ifndef PRODUCT
1121 } else {
1122 st->print("pushq [rsp + #%d]\t# 64-bit mem-mem spill\n\t"
1123 "popq [rsp + #%d]",
1124 src_offset, dst_offset);
1125 #endif
1126 }
1127 } else {
1128 // 32-bit
1129 assert(!((src_first & 1) == 0 && src_first + 1 == src_second), "no transform");
1130 assert(!((dst_first & 1) == 0 && dst_first + 1 == dst_second), "no transform");
1131 // No pushl/popl, so:
1132 int src_offset = ra_->reg2offset(src_first);
1133 int dst_offset = ra_->reg2offset(dst_first);
1134 if (masm) {
1135 __ movq(Address(rsp, -8), rax);
1136 __ movl(rax, Address(rsp, src_offset));
1137 __ movl(Address(rsp, dst_offset), rax);
1138 __ movq(rax, Address(rsp, -8));
1139 #ifndef PRODUCT
1140 } else {
1141 st->print("movq [rsp - #8], rax\t# 32-bit mem-mem spill\n\t"
1142 "movl rax, [rsp + #%d]\n\t"
1143 "movl [rsp + #%d], rax\n\t"
1144 "movq rax, [rsp - #8]",
1145 src_offset, dst_offset);
1146 #endif
1147 }
1148 }
1149 return 0;
1150 } else if (dst_first_rc == rc_int) {
1151 // mem -> gpr
1152 if ((src_first & 1) == 0 && src_first + 1 == src_second &&
1153 (dst_first & 1) == 0 && dst_first + 1 == dst_second) {
1154 // 64-bit
1155 int offset = ra_->reg2offset(src_first);
1156 if (masm) {
1157 __ movq(as_Register(Matcher::_regEncode[dst_first]), Address(rsp, offset));
1158 #ifndef PRODUCT
1159 } else {
1160 st->print("movq %s, [rsp + #%d]\t# spill",
1161 Matcher::regName[dst_first],
1162 offset);
1163 #endif
1164 }
1165 } else {
1166 // 32-bit
1167 assert(!((src_first & 1) == 0 && src_first + 1 == src_second), "no transform");
1168 assert(!((dst_first & 1) == 0 && dst_first + 1 == dst_second), "no transform");
1169 int offset = ra_->reg2offset(src_first);
1170 if (masm) {
1171 __ movl(as_Register(Matcher::_regEncode[dst_first]), Address(rsp, offset));
1172 #ifndef PRODUCT
1173 } else {
1174 st->print("movl %s, [rsp + #%d]\t# spill",
1175 Matcher::regName[dst_first],
1176 offset);
1177 #endif
1178 }
1179 }
1180 return 0;
1181 } else if (dst_first_rc == rc_float) {
1182 // mem-> xmm
1183 if ((src_first & 1) == 0 && src_first + 1 == src_second &&
1184 (dst_first & 1) == 0 && dst_first + 1 == dst_second) {
1185 // 64-bit
1186 int offset = ra_->reg2offset(src_first);
1187 if (masm) {
1188 __ movdbl( as_XMMRegister(Matcher::_regEncode[dst_first]), Address(rsp, offset));
1189 #ifndef PRODUCT
1190 } else {
1191 st->print("%s %s, [rsp + #%d]\t# spill",
1192 UseXmmLoadAndClearUpper ? "movsd " : "movlpd",
1193 Matcher::regName[dst_first],
1194 offset);
1195 #endif
1196 }
1197 } else {
1198 // 32-bit
1199 assert(!((src_first & 1) == 0 && src_first + 1 == src_second), "no transform");
1200 assert(!((dst_first & 1) == 0 && dst_first + 1 == dst_second), "no transform");
1201 int offset = ra_->reg2offset(src_first);
1202 if (masm) {
1203 __ movflt( as_XMMRegister(Matcher::_regEncode[dst_first]), Address(rsp, offset));
1204 #ifndef PRODUCT
1205 } else {
1206 st->print("movss %s, [rsp + #%d]\t# spill",
1207 Matcher::regName[dst_first],
1208 offset);
1209 #endif
1210 }
1211 }
1212 return 0;
1213 } else if (dst_first_rc == rc_kreg) {
1214 // mem -> kreg
1215 if ((src_first & 1) == 0 && src_first + 1 == src_second &&
1216 (dst_first & 1) == 0 && dst_first + 1 == dst_second) {
1217 // 64-bit
1218 int offset = ra_->reg2offset(src_first);
1219 if (masm) {
1220 __ kmov(as_KRegister(Matcher::_regEncode[dst_first]), Address(rsp, offset));
1221 #ifndef PRODUCT
1222 } else {
1223 st->print("kmovq %s, [rsp + #%d]\t# spill",
1224 Matcher::regName[dst_first],
1225 offset);
1226 #endif
1227 }
1228 }
1229 return 0;
1230 }
1231 } else if (src_first_rc == rc_int) {
1232 // gpr ->
1233 if (dst_first_rc == rc_stack) {
1234 // gpr -> mem
1235 if ((src_first & 1) == 0 && src_first + 1 == src_second &&
1236 (dst_first & 1) == 0 && dst_first + 1 == dst_second) {
1237 // 64-bit
1238 int offset = ra_->reg2offset(dst_first);
1239 if (masm) {
1240 __ movq(Address(rsp, offset), as_Register(Matcher::_regEncode[src_first]));
1241 #ifndef PRODUCT
1242 } else {
1243 st->print("movq [rsp + #%d], %s\t# spill",
1244 offset,
1245 Matcher::regName[src_first]);
1246 #endif
1247 }
1248 } else {
1249 // 32-bit
1250 assert(!((src_first & 1) == 0 && src_first + 1 == src_second), "no transform");
1251 assert(!((dst_first & 1) == 0 && dst_first + 1 == dst_second), "no transform");
1252 int offset = ra_->reg2offset(dst_first);
1253 if (masm) {
1254 __ movl(Address(rsp, offset), as_Register(Matcher::_regEncode[src_first]));
1255 #ifndef PRODUCT
1256 } else {
1257 st->print("movl [rsp + #%d], %s\t# spill",
1258 offset,
1259 Matcher::regName[src_first]);
1260 #endif
1261 }
1262 }
1263 return 0;
1264 } else if (dst_first_rc == rc_int) {
1265 // gpr -> gpr
1266 if ((src_first & 1) == 0 && src_first + 1 == src_second &&
1267 (dst_first & 1) == 0 && dst_first + 1 == dst_second) {
1268 // 64-bit
1269 if (masm) {
1270 __ movq(as_Register(Matcher::_regEncode[dst_first]),
1271 as_Register(Matcher::_regEncode[src_first]));
1272 #ifndef PRODUCT
1273 } else {
1274 st->print("movq %s, %s\t# spill",
1275 Matcher::regName[dst_first],
1276 Matcher::regName[src_first]);
1277 #endif
1278 }
1279 return 0;
1280 } else {
1281 // 32-bit
1282 assert(!((src_first & 1) == 0 && src_first + 1 == src_second), "no transform");
1283 assert(!((dst_first & 1) == 0 && dst_first + 1 == dst_second), "no transform");
1284 if (masm) {
1285 __ movl(as_Register(Matcher::_regEncode[dst_first]),
1286 as_Register(Matcher::_regEncode[src_first]));
1287 #ifndef PRODUCT
1288 } else {
1289 st->print("movl %s, %s\t# spill",
1290 Matcher::regName[dst_first],
1291 Matcher::regName[src_first]);
1292 #endif
1293 }
1294 return 0;
1295 }
1296 } else if (dst_first_rc == rc_float) {
1297 // gpr -> xmm
1298 if ((src_first & 1) == 0 && src_first + 1 == src_second &&
1299 (dst_first & 1) == 0 && dst_first + 1 == dst_second) {
1300 // 64-bit
1301 if (masm) {
1302 __ movdq( as_XMMRegister(Matcher::_regEncode[dst_first]), as_Register(Matcher::_regEncode[src_first]));
1303 #ifndef PRODUCT
1304 } else {
1305 st->print("movdq %s, %s\t# spill",
1306 Matcher::regName[dst_first],
1307 Matcher::regName[src_first]);
1308 #endif
1309 }
1310 } else {
1311 // 32-bit
1312 assert(!((src_first & 1) == 0 && src_first + 1 == src_second), "no transform");
1313 assert(!((dst_first & 1) == 0 && dst_first + 1 == dst_second), "no transform");
1314 if (masm) {
1315 __ movdl( as_XMMRegister(Matcher::_regEncode[dst_first]), as_Register(Matcher::_regEncode[src_first]));
1316 #ifndef PRODUCT
1317 } else {
1318 st->print("movdl %s, %s\t# spill",
1319 Matcher::regName[dst_first],
1320 Matcher::regName[src_first]);
1321 #endif
1322 }
1323 }
1324 return 0;
1325 } else if (dst_first_rc == rc_kreg) {
1326 if ((src_first & 1) == 0 && src_first + 1 == src_second &&
1327 (dst_first & 1) == 0 && dst_first + 1 == dst_second) {
1328 // 64-bit
1329 if (masm) {
1330 __ kmov(as_KRegister(Matcher::_regEncode[dst_first]), as_Register(Matcher::_regEncode[src_first]));
1331 #ifndef PRODUCT
1332 } else {
1333 st->print("kmovq %s, %s\t# spill",
1334 Matcher::regName[dst_first],
1335 Matcher::regName[src_first]);
1336 #endif
1337 }
1338 }
1339 Unimplemented();
1340 return 0;
1341 }
1342 } else if (src_first_rc == rc_float) {
1343 // xmm ->
1344 if (dst_first_rc == rc_stack) {
1345 // xmm -> mem
1346 if ((src_first & 1) == 0 && src_first + 1 == src_second &&
1347 (dst_first & 1) == 0 && dst_first + 1 == dst_second) {
1348 // 64-bit
1349 int offset = ra_->reg2offset(dst_first);
1350 if (masm) {
1351 __ movdbl( Address(rsp, offset), as_XMMRegister(Matcher::_regEncode[src_first]));
1352 #ifndef PRODUCT
1353 } else {
1354 st->print("movsd [rsp + #%d], %s\t# spill",
1355 offset,
1356 Matcher::regName[src_first]);
1357 #endif
1358 }
1359 } else {
1360 // 32-bit
1361 assert(!((src_first & 1) == 0 && src_first + 1 == src_second), "no transform");
1362 assert(!((dst_first & 1) == 0 && dst_first + 1 == dst_second), "no transform");
1363 int offset = ra_->reg2offset(dst_first);
1364 if (masm) {
1365 __ movflt(Address(rsp, offset), as_XMMRegister(Matcher::_regEncode[src_first]));
1366 #ifndef PRODUCT
1367 } else {
1368 st->print("movss [rsp + #%d], %s\t# spill",
1369 offset,
1370 Matcher::regName[src_first]);
1371 #endif
1372 }
1373 }
1374 return 0;
1375 } else if (dst_first_rc == rc_int) {
1376 // xmm -> gpr
1377 if ((src_first & 1) == 0 && src_first + 1 == src_second &&
1378 (dst_first & 1) == 0 && dst_first + 1 == dst_second) {
1379 // 64-bit
1380 if (masm) {
1381 __ movdq( as_Register(Matcher::_regEncode[dst_first]), as_XMMRegister(Matcher::_regEncode[src_first]));
1382 #ifndef PRODUCT
1383 } else {
1384 st->print("movdq %s, %s\t# spill",
1385 Matcher::regName[dst_first],
1386 Matcher::regName[src_first]);
1387 #endif
1388 }
1389 } else {
1390 // 32-bit
1391 assert(!((src_first & 1) == 0 && src_first + 1 == src_second), "no transform");
1392 assert(!((dst_first & 1) == 0 && dst_first + 1 == dst_second), "no transform");
1393 if (masm) {
1394 __ movdl( as_Register(Matcher::_regEncode[dst_first]), as_XMMRegister(Matcher::_regEncode[src_first]));
1395 #ifndef PRODUCT
1396 } else {
1397 st->print("movdl %s, %s\t# spill",
1398 Matcher::regName[dst_first],
1399 Matcher::regName[src_first]);
1400 #endif
1401 }
1402 }
1403 return 0;
1404 } else if (dst_first_rc == rc_float) {
1405 // xmm -> xmm
1406 if ((src_first & 1) == 0 && src_first + 1 == src_second &&
1407 (dst_first & 1) == 0 && dst_first + 1 == dst_second) {
1408 // 64-bit
1409 if (masm) {
1410 __ movdbl( as_XMMRegister(Matcher::_regEncode[dst_first]), as_XMMRegister(Matcher::_regEncode[src_first]));
1411 #ifndef PRODUCT
1412 } else {
1413 st->print("%s %s, %s\t# spill",
1414 UseXmmRegToRegMoveAll ? "movapd" : "movsd ",
1415 Matcher::regName[dst_first],
1416 Matcher::regName[src_first]);
1417 #endif
1418 }
1419 } else {
1420 // 32-bit
1421 assert(!((src_first & 1) == 0 && src_first + 1 == src_second), "no transform");
1422 assert(!((dst_first & 1) == 0 && dst_first + 1 == dst_second), "no transform");
1423 if (masm) {
1424 __ movflt( as_XMMRegister(Matcher::_regEncode[dst_first]), as_XMMRegister(Matcher::_regEncode[src_first]));
1425 #ifndef PRODUCT
1426 } else {
1427 st->print("%s %s, %s\t# spill",
1428 UseXmmRegToRegMoveAll ? "movaps" : "movss ",
1429 Matcher::regName[dst_first],
1430 Matcher::regName[src_first]);
1431 #endif
1432 }
1433 }
1434 return 0;
1435 } else if (dst_first_rc == rc_kreg) {
1436 assert(false, "Illegal spilling");
1437 return 0;
1438 }
1439 } else if (src_first_rc == rc_kreg) {
1440 if (dst_first_rc == rc_stack) {
1441 // mem -> kreg
1442 if ((src_first & 1) == 0 && src_first + 1 == src_second &&
1443 (dst_first & 1) == 0 && dst_first + 1 == dst_second) {
1444 // 64-bit
1445 int offset = ra_->reg2offset(dst_first);
1446 if (masm) {
1447 __ kmov(Address(rsp, offset), as_KRegister(Matcher::_regEncode[src_first]));
1448 #ifndef PRODUCT
1449 } else {
1450 st->print("kmovq [rsp + #%d] , %s\t# spill",
1451 offset,
1452 Matcher::regName[src_first]);
1453 #endif
1454 }
1455 }
1456 return 0;
1457 } else if (dst_first_rc == rc_int) {
1458 if ((src_first & 1) == 0 && src_first + 1 == src_second &&
1459 (dst_first & 1) == 0 && dst_first + 1 == dst_second) {
1460 // 64-bit
1461 if (masm) {
1462 __ kmov(as_Register(Matcher::_regEncode[dst_first]), as_KRegister(Matcher::_regEncode[src_first]));
1463 #ifndef PRODUCT
1464 } else {
1465 st->print("kmovq %s, %s\t# spill",
1466 Matcher::regName[dst_first],
1467 Matcher::regName[src_first]);
1468 #endif
1469 }
1470 }
1471 Unimplemented();
1472 return 0;
1473 } else if (dst_first_rc == rc_kreg) {
1474 if ((src_first & 1) == 0 && src_first + 1 == src_second &&
1475 (dst_first & 1) == 0 && dst_first + 1 == dst_second) {
1476 // 64-bit
1477 if (masm) {
1478 __ kmov(as_KRegister(Matcher::_regEncode[dst_first]), as_KRegister(Matcher::_regEncode[src_first]));
1479 #ifndef PRODUCT
1480 } else {
1481 st->print("kmovq %s, %s\t# spill",
1482 Matcher::regName[dst_first],
1483 Matcher::regName[src_first]);
1484 #endif
1485 }
1486 }
1487 return 0;
1488 } else if (dst_first_rc == rc_float) {
1489 assert(false, "Illegal spill");
1490 return 0;
1491 }
1492 }
1493
1494 assert(0," foo ");
1495 Unimplemented();
1496 return 0;
1497 }
1498
1499 #ifndef PRODUCT
1500 void MachSpillCopyNode::format(PhaseRegAlloc *ra_, outputStream* st) const {
1501 implementation(nullptr, ra_, false, st);
1502 }
1503 #endif
1504
1505 void MachSpillCopyNode::emit(C2_MacroAssembler *masm, PhaseRegAlloc *ra_) const {
1506 implementation(masm, ra_, false, nullptr);
1507 }
1508
1509 uint MachSpillCopyNode::size(PhaseRegAlloc *ra_) const {
1510 return MachNode::size(ra_);
1511 }
1512
1513 //=============================================================================
1514 #ifndef PRODUCT
1515 void BoxLockNode::format(PhaseRegAlloc* ra_, outputStream* st) const
1516 {
1517 int offset = ra_->reg2offset(in_RegMask(0).find_first_elem());
1518 int reg = ra_->get_reg_first(this);
1519 st->print("leaq %s, [rsp + #%d]\t# box lock",
1520 Matcher::regName[reg], offset);
1521 }
1522 #endif
1523
1524 void BoxLockNode::emit(C2_MacroAssembler* masm, PhaseRegAlloc* ra_) const
1525 {
1526 int offset = ra_->reg2offset(in_RegMask(0).find_first_elem());
1527 int reg = ra_->get_encode(this);
1528
1529 __ lea(as_Register(reg), Address(rsp, offset));
1530 }
1531
1532 uint BoxLockNode::size(PhaseRegAlloc *ra_) const
1533 {
1534 int offset = ra_->reg2offset(in_RegMask(0).find_first_elem());
1535 if (ra_->get_encode(this) > 15) {
1536 return (offset < 0x80) ? 6 : 9; // REX2
1537 } else {
1538 return (offset < 0x80) ? 5 : 8; // REX
1539 }
1540 }
1541
1542 //=============================================================================
1543 #ifndef PRODUCT
1544 void MachVEPNode::format(PhaseRegAlloc* ra_, outputStream* st) const
1545 {
1546 st->print_cr("MachVEPNode");
1547 }
1548 #endif
1549
1550 void MachVEPNode::emit(C2_MacroAssembler* masm, PhaseRegAlloc* ra_) const
1551 {
1552 CodeBuffer* cbuf = masm->code();
1553 uint insts_size = cbuf->insts_size();
1554 if (!_verified) {
1555 __ ic_check(1);
1556 } else {
1557 // TODO 8284443 Avoid creation of temporary frame
1558 if (ra_->C->stub_function() == nullptr) {
1559 __ verified_entry(ra_->C, 0);
1560 __ entry_barrier();
1561 int initial_framesize = ra_->C->output()->frame_size_in_bytes() - 2*wordSize;
1562 __ remove_frame(initial_framesize, false);
1563 }
1564 // Unpack inline type args passed as oop and then jump to
1565 // the verified entry point (skipping the unverified entry).
1566 int sp_inc = __ unpack_inline_args(ra_->C, _receiver_only);
1567 // Emit code for verified entry and save increment for stack repair on return
1568 __ verified_entry(ra_->C, sp_inc);
1569 if (Compile::current()->output()->in_scratch_emit_size()) {
1570 Label dummy_verified_entry;
1571 __ jmp(dummy_verified_entry);
1572 } else {
1573 __ jmp(*_verified_entry);
1574 }
1575 }
1576 /* WARNING these NOPs are critical so that verified entry point is properly
1577 4 bytes aligned for patching by NativeJump::patch_verified_entry() */
1578 int nops_cnt = 4 - ((cbuf->insts_size() - insts_size) & 0x3);
1579 nops_cnt &= 0x3; // Do not add nops if code is aligned.
1580 if (nops_cnt > 0) {
1581 __ nop(nops_cnt);
1582 }
1583 }
1584
1585 //=============================================================================
1586 #ifndef PRODUCT
1587 void MachUEPNode::format(PhaseRegAlloc* ra_, outputStream* st) const
1588 {
1589 if (UseCompressedClassPointers) {
1590 st->print_cr("movl rscratch1, [j_rarg0 + oopDesc::klass_offset_in_bytes()]\t# compressed klass");
1591 st->print_cr("\tcmpl rscratch1, [rax + CompiledICData::speculated_klass_offset()]\t # Inline cache check");
1592 } else {
1593 st->print_cr("movq rscratch1, [j_rarg0 + oopDesc::klass_offset_in_bytes()]\t# compressed klass");
1594 st->print_cr("\tcmpq rscratch1, [rax + CompiledICData::speculated_klass_offset()]\t # Inline cache check");
1595 }
1596 st->print_cr("\tjne SharedRuntime::_ic_miss_stub");
1597 }
1598 #endif
1599
1600 void MachUEPNode::emit(C2_MacroAssembler* masm, PhaseRegAlloc* ra_) const
1601 {
1602 __ ic_check(InteriorEntryAlignment);
1603 }
1604
1605 //=============================================================================
1606
1607 bool Matcher::supports_vector_calling_convention(void) {
1608 return EnableVectorSupport;
1609 }
1610
1611 OptoRegPair Matcher::vector_return_value(uint ideal_reg) {
1612 assert(EnableVectorSupport, "sanity");
1613 int lo = XMM0_num;
1614 int hi = XMM0b_num;
1615 if (ideal_reg == Op_VecX) hi = XMM0d_num;
1616 else if (ideal_reg == Op_VecY) hi = XMM0h_num;
1617 else if (ideal_reg == Op_VecZ) hi = XMM0p_num;
1618 return OptoRegPair(hi, lo);
1619 }
1620
1621 // Is this branch offset short enough that a short branch can be used?
1622 //
1623 // NOTE: If the platform does not provide any short branch variants, then
1624 // this method should return false for offset 0.
1625 bool Matcher::is_short_branch_offset(int rule, int br_size, int offset) {
1626 // The passed offset is relative to address of the branch.
1627 // On 86 a branch displacement is calculated relative to address
1628 // of a next instruction.
1629 offset -= br_size;
1630
1631 // the short version of jmpConUCF2 contains multiple branches,
1632 // making the reach slightly less
1633 if (rule == jmpConUCF2_rule)
1634 return (-126 <= offset && offset <= 125);
1635 return (-128 <= offset && offset <= 127);
1636 }
1637
1638 // Return whether or not this register is ever used as an argument.
1639 // This function is used on startup to build the trampoline stubs in
1640 // generateOptoStub. Registers not mentioned will be killed by the VM
1641 // call in the trampoline, and arguments in those registers not be
1642 // available to the callee.
1643 bool Matcher::can_be_java_arg(int reg)
1644 {
1645 return
1646 reg == RDI_num || reg == RDI_H_num ||
1647 reg == RSI_num || reg == RSI_H_num ||
1648 reg == RDX_num || reg == RDX_H_num ||
1649 reg == RCX_num || reg == RCX_H_num ||
1650 reg == R8_num || reg == R8_H_num ||
1651 reg == R9_num || reg == R9_H_num ||
1652 reg == R12_num || reg == R12_H_num ||
1653 reg == XMM0_num || reg == XMM0b_num ||
1654 reg == XMM1_num || reg == XMM1b_num ||
1655 reg == XMM2_num || reg == XMM2b_num ||
1656 reg == XMM3_num || reg == XMM3b_num ||
1657 reg == XMM4_num || reg == XMM4b_num ||
1658 reg == XMM5_num || reg == XMM5b_num ||
1659 reg == XMM6_num || reg == XMM6b_num ||
1660 reg == XMM7_num || reg == XMM7b_num;
1661 }
1662
1663 bool Matcher::is_spillable_arg(int reg)
1664 {
1665 return can_be_java_arg(reg);
1666 }
1667
1668 uint Matcher::int_pressure_limit()
1669 {
1670 return (INTPRESSURE == -1) ? _INT_REG_mask.Size() : INTPRESSURE;
1671 }
1672
1673 uint Matcher::float_pressure_limit()
1674 {
1675 // After experiment around with different values, the following default threshold
1676 // works best for LCM's register pressure scheduling on x64.
1677 uint dec_count = VM_Version::supports_evex() ? 4 : 2;
1678 uint default_float_pressure_threshold = _FLOAT_REG_mask.Size() - dec_count;
1679 return (FLOATPRESSURE == -1) ? default_float_pressure_threshold : FLOATPRESSURE;
1680 }
1681
1682 bool Matcher::use_asm_for_ldiv_by_con( jlong divisor ) {
1683 // In 64 bit mode a code which use multiply when
1684 // devisor is constant is faster than hardware
1685 // DIV instruction (it uses MulHiL).
1686 return false;
1687 }
1688
1689 // Register for DIVI projection of divmodI
1690 RegMask Matcher::divI_proj_mask() {
1691 return INT_RAX_REG_mask();
1692 }
1693
1694 // Register for MODI projection of divmodI
1695 RegMask Matcher::modI_proj_mask() {
1696 return INT_RDX_REG_mask();
1697 }
1698
1699 // Register for DIVL projection of divmodL
1700 RegMask Matcher::divL_proj_mask() {
1701 return LONG_RAX_REG_mask();
1702 }
1703
1704 // Register for MODL projection of divmodL
1705 RegMask Matcher::modL_proj_mask() {
1706 return LONG_RDX_REG_mask();
1707 }
1708
1709 %}
1710
1711 //----------ENCODING BLOCK-----------------------------------------------------
1712 // This block specifies the encoding classes used by the compiler to
1713 // output byte streams. Encoding classes are parameterized macros
1714 // used by Machine Instruction Nodes in order to generate the bit
1715 // encoding of the instruction. Operands specify their base encoding
1716 // interface with the interface keyword. There are currently
1717 // supported four interfaces, REG_INTER, CONST_INTER, MEMORY_INTER, &
1718 // COND_INTER. REG_INTER causes an operand to generate a function
1719 // which returns its register number when queried. CONST_INTER causes
1720 // an operand to generate a function which returns the value of the
1721 // constant when queried. MEMORY_INTER causes an operand to generate
1722 // four functions which return the Base Register, the Index Register,
1723 // the Scale Value, and the Offset Value of the operand when queried.
1724 // COND_INTER causes an operand to generate six functions which return
1725 // the encoding code (ie - encoding bits for the instruction)
1726 // associated with each basic boolean condition for a conditional
1727 // instruction.
1728 //
1729 // Instructions specify two basic values for encoding. Again, a
1730 // function is available to check if the constant displacement is an
1731 // oop. They use the ins_encode keyword to specify their encoding
1732 // classes (which must be a sequence of enc_class names, and their
1733 // parameters, specified in the encoding block), and they use the
1734 // opcode keyword to specify, in order, their primary, secondary, and
1735 // tertiary opcode. Only the opcode sections which a particular
1736 // instruction needs for encoding need to be specified.
1737 encode %{
1738 enc_class cdql_enc(no_rax_rdx_RegI div)
1739 %{
1740 // Full implementation of Java idiv and irem; checks for
1741 // special case as described in JVM spec., p.243 & p.271.
1742 //
1743 // normal case special case
1744 //
1745 // input : rax: dividend min_int
1746 // reg: divisor -1
1747 //
1748 // output: rax: quotient (= rax idiv reg) min_int
1749 // rdx: remainder (= rax irem reg) 0
1750 //
1751 // Code sequnce:
1752 //
1753 // 0: 3d 00 00 00 80 cmp $0x80000000,%eax
1754 // 5: 75 07/08 jne e <normal>
1755 // 7: 33 d2 xor %edx,%edx
1756 // [div >= 8 -> offset + 1]
1757 // [REX_B]
1758 // 9: 83 f9 ff cmp $0xffffffffffffffff,$div
1759 // c: 74 03/04 je 11 <done>
1760 // 000000000000000e <normal>:
1761 // e: 99 cltd
1762 // [div >= 8 -> offset + 1]
1763 // [REX_B]
1764 // f: f7 f9 idiv $div
1765 // 0000000000000011 <done>:
1766 Label normal;
1767 Label done;
1768
1769 // cmp $0x80000000,%eax
1770 __ cmpl(as_Register(RAX_enc), 0x80000000);
1771
1772 // jne e <normal>
1773 __ jccb(Assembler::notEqual, normal);
1774
1775 // xor %edx,%edx
1776 __ xorl(as_Register(RDX_enc), as_Register(RDX_enc));
1777
1778 // cmp $0xffffffffffffffff,%ecx
1779 __ cmpl($div$$Register, -1);
1780
1781 // je 11 <done>
1782 __ jccb(Assembler::equal, done);
1783
1784 // <normal>
1785 // cltd
1786 __ bind(normal);
1787 __ cdql();
1788
1789 // idivl
1790 // <done>
1791 __ idivl($div$$Register);
1792 __ bind(done);
1793 %}
1794
1795 enc_class cdqq_enc(no_rax_rdx_RegL div)
1796 %{
1797 // Full implementation of Java ldiv and lrem; checks for
1798 // special case as described in JVM spec., p.243 & p.271.
1799 //
1800 // normal case special case
1801 //
1802 // input : rax: dividend min_long
1803 // reg: divisor -1
1804 //
1805 // output: rax: quotient (= rax idiv reg) min_long
1806 // rdx: remainder (= rax irem reg) 0
1807 //
1808 // Code sequnce:
1809 //
1810 // 0: 48 ba 00 00 00 00 00 mov $0x8000000000000000,%rdx
1811 // 7: 00 00 80
1812 // a: 48 39 d0 cmp %rdx,%rax
1813 // d: 75 08 jne 17 <normal>
1814 // f: 33 d2 xor %edx,%edx
1815 // 11: 48 83 f9 ff cmp $0xffffffffffffffff,$div
1816 // 15: 74 05 je 1c <done>
1817 // 0000000000000017 <normal>:
1818 // 17: 48 99 cqto
1819 // 19: 48 f7 f9 idiv $div
1820 // 000000000000001c <done>:
1821 Label normal;
1822 Label done;
1823
1824 // mov $0x8000000000000000,%rdx
1825 __ mov64(as_Register(RDX_enc), 0x8000000000000000);
1826
1827 // cmp %rdx,%rax
1828 __ cmpq(as_Register(RAX_enc), as_Register(RDX_enc));
1829
1830 // jne 17 <normal>
1831 __ jccb(Assembler::notEqual, normal);
1832
1833 // xor %edx,%edx
1834 __ xorl(as_Register(RDX_enc), as_Register(RDX_enc));
1835
1836 // cmp $0xffffffffffffffff,$div
1837 __ cmpq($div$$Register, -1);
1838
1839 // je 1e <done>
1840 __ jccb(Assembler::equal, done);
1841
1842 // <normal>
1843 // cqto
1844 __ bind(normal);
1845 __ cdqq();
1846
1847 // idivq (note: must be emitted by the user of this rule)
1848 // <done>
1849 __ idivq($div$$Register);
1850 __ bind(done);
1851 %}
1852
1853 enc_class clear_avx %{
1854 DEBUG_ONLY(int off0 = __ offset());
1855 if (generate_vzeroupper(Compile::current())) {
1856 // Clear upper bits of YMM registers to avoid AVX <-> SSE transition penalty
1857 // Clear upper bits of YMM registers when current compiled code uses
1858 // wide vectors to avoid AVX <-> SSE transition penalty during call.
1859 __ vzeroupper();
1860 }
1861 DEBUG_ONLY(int off1 = __ offset());
1862 assert(off1 - off0 == clear_avx_size(), "correct size prediction");
1863 %}
1864
1865 enc_class Java_To_Runtime(method meth) %{
1866 __ lea(r10, RuntimeAddress((address)$meth$$method));
1867 __ call(r10);
1868 __ post_call_nop();
1869 %}
1870
1871 enc_class Java_Static_Call(method meth)
1872 %{
1873 // JAVA STATIC CALL
1874 // CALL to fixup routine. Fixup routine uses ScopeDesc info to
1875 // determine who we intended to call.
1876 if (!_method) {
1877 __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, $meth$$method)));
1878 } else if (_method->intrinsic_id() == vmIntrinsicID::_ensureMaterializedForStackWalk) {
1879 // The NOP here is purely to ensure that eliding a call to
1880 // JVM_EnsureMaterializedForStackWalk doesn't change the code size.
1881 __ addr_nop_5();
1882 __ block_comment("call JVM_EnsureMaterializedForStackWalk (elided)");
1883 } else {
1884 int method_index = resolved_method_index(masm);
1885 RelocationHolder rspec = _optimized_virtual ? opt_virtual_call_Relocation::spec(method_index)
1886 : static_call_Relocation::spec(method_index);
1887 address mark = __ pc();
1888 int call_offset = __ offset();
1889 __ call(AddressLiteral(CAST_FROM_FN_PTR(address, $meth$$method), rspec));
1890 if (CodeBuffer::supports_shared_stubs() && _method->can_be_statically_bound()) {
1891 // Calls of the same statically bound method can share
1892 // a stub to the interpreter.
1893 __ code()->shared_stub_to_interp_for(_method, call_offset);
1894 } else {
1895 // Emit stubs for static call.
1896 address stub = CompiledDirectCall::emit_to_interp_stub(masm, mark);
1897 __ clear_inst_mark();
1898 if (stub == nullptr) {
1899 ciEnv::current()->record_failure("CodeCache is full");
1900 return;
1901 }
1902 }
1903 }
1904 __ post_call_nop();
1905 %}
1906
1907 enc_class Java_Dynamic_Call(method meth) %{
1908 __ ic_call((address)$meth$$method, resolved_method_index(masm));
1909 __ post_call_nop();
1910 %}
1911
1912 %}
1913
1914
1915
1916 //----------FRAME--------------------------------------------------------------
1917 // Definition of frame structure and management information.
1918 //
1919 // S T A C K L A Y O U T Allocators stack-slot number
1920 // | (to get allocators register number
1921 // G Owned by | | v add OptoReg::stack0())
1922 // r CALLER | |
1923 // o | +--------+ pad to even-align allocators stack-slot
1924 // w V | pad0 | numbers; owned by CALLER
1925 // t -----------+--------+----> Matcher::_in_arg_limit, unaligned
1926 // h ^ | in | 5
1927 // | | args | 4 Holes in incoming args owned by SELF
1928 // | | | | 3
1929 // | | +--------+
1930 // V | | old out| Empty on Intel, window on Sparc
1931 // | old |preserve| Must be even aligned.
1932 // | SP-+--------+----> Matcher::_old_SP, even aligned
1933 // | | in | 3 area for Intel ret address
1934 // Owned by |preserve| Empty on Sparc.
1935 // SELF +--------+
1936 // | | pad2 | 2 pad to align old SP
1937 // | +--------+ 1
1938 // | | locks | 0
1939 // | +--------+----> OptoReg::stack0(), even aligned
1940 // | | pad1 | 11 pad to align new SP
1941 // | +--------+
1942 // | | | 10
1943 // | | spills | 9 spills
1944 // V | | 8 (pad0 slot for callee)
1945 // -----------+--------+----> Matcher::_out_arg_limit, unaligned
1946 // ^ | out | 7
1947 // | | args | 6 Holes in outgoing args owned by CALLEE
1948 // Owned by +--------+
1949 // CALLEE | new out| 6 Empty on Intel, window on Sparc
1950 // | new |preserve| Must be even-aligned.
1951 // | SP-+--------+----> Matcher::_new_SP, even aligned
1952 // | | |
1953 //
1954 // Note 1: Only region 8-11 is determined by the allocator. Region 0-5 is
1955 // known from SELF's arguments and the Java calling convention.
1956 // Region 6-7 is determined per call site.
1957 // Note 2: If the calling convention leaves holes in the incoming argument
1958 // area, those holes are owned by SELF. Holes in the outgoing area
1959 // are owned by the CALLEE. Holes should not be necessary in the
1960 // incoming area, as the Java calling convention is completely under
1961 // the control of the AD file. Doubles can be sorted and packed to
1962 // avoid holes. Holes in the outgoing arguments may be necessary for
1963 // varargs C calling conventions.
1964 // Note 3: Region 0-3 is even aligned, with pad2 as needed. Region 3-5 is
1965 // even aligned with pad0 as needed.
1966 // Region 6 is even aligned. Region 6-7 is NOT even aligned;
1967 // region 6-11 is even aligned; it may be padded out more so that
1968 // the region from SP to FP meets the minimum stack alignment.
1969 // Note 4: For I2C adapters, the incoming FP may not meet the minimum stack
1970 // alignment. Region 11, pad1, may be dynamically extended so that
1971 // SP meets the minimum alignment.
1972
1973 frame
1974 %{
1975 // These three registers define part of the calling convention
1976 // between compiled code and the interpreter.
1977 inline_cache_reg(RAX); // Inline Cache Register
1978
1979 // Optional: name the operand used by cisc-spilling to access
1980 // [stack_pointer + offset]
1981 cisc_spilling_operand_name(indOffset32);
1982
1983 // Number of stack slots consumed by locking an object
1984 sync_stack_slots(2);
1985
1986 // Compiled code's Frame Pointer
1987 frame_pointer(RSP);
1988
1989 // Interpreter stores its frame pointer in a register which is
1990 // stored to the stack by I2CAdaptors.
1991 // I2CAdaptors convert from interpreted java to compiled java.
1992 interpreter_frame_pointer(RBP);
1993
1994 // Stack alignment requirement
1995 stack_alignment(StackAlignmentInBytes); // Alignment size in bytes (128-bit -> 16 bytes)
1996
1997 // Number of outgoing stack slots killed above the out_preserve_stack_slots
1998 // for calls to C. Supports the var-args backing area for register parms.
1999 varargs_C_out_slots_killed(frame::arg_reg_save_area_bytes/BytesPerInt);
2000
2001 // The after-PROLOG location of the return address. Location of
2002 // return address specifies a type (REG or STACK) and a number
2003 // representing the register number (i.e. - use a register name) or
2004 // stack slot.
2005 // Ret Addr is on stack in slot 0 if no locks or verification or alignment.
2006 // Otherwise, it is above the locks and verification slot and alignment word
2007 return_addr(STACK - 2 +
2008 align_up((Compile::current()->in_preserve_stack_slots() +
2009 Compile::current()->fixed_slots()),
2010 stack_alignment_in_slots()));
2011
2012 // Location of compiled Java return values. Same as C for now.
2013 return_value
2014 %{
2015 assert(ideal_reg >= Op_RegI && ideal_reg <= Op_RegL,
2016 "only return normal values");
2017
2018 static const int lo[Op_RegL + 1] = {
2019 0,
2020 0,
2021 RAX_num, // Op_RegN
2022 RAX_num, // Op_RegI
2023 RAX_num, // Op_RegP
2024 XMM0_num, // Op_RegF
2025 XMM0_num, // Op_RegD
2026 RAX_num // Op_RegL
2027 };
2028 static const int hi[Op_RegL + 1] = {
2029 0,
2030 0,
2031 OptoReg::Bad, // Op_RegN
2032 OptoReg::Bad, // Op_RegI
2033 RAX_H_num, // Op_RegP
2034 OptoReg::Bad, // Op_RegF
2035 XMM0b_num, // Op_RegD
2036 RAX_H_num // Op_RegL
2037 };
2038 // Excluded flags and vector registers.
2039 assert(ARRAY_SIZE(hi) == _last_machine_leaf - 8, "missing type");
2040 return OptoRegPair(hi[ideal_reg], lo[ideal_reg]);
2041 %}
2042 %}
2043
2044 //----------ATTRIBUTES---------------------------------------------------------
2045 //----------Operand Attributes-------------------------------------------------
2046 op_attrib op_cost(0); // Required cost attribute
2047
2048 //----------Instruction Attributes---------------------------------------------
2049 ins_attrib ins_cost(100); // Required cost attribute
2050 ins_attrib ins_size(8); // Required size attribute (in bits)
2051 ins_attrib ins_short_branch(0); // Required flag: is this instruction
2052 // a non-matching short branch variant
2053 // of some long branch?
2054 ins_attrib ins_alignment(1); // Required alignment attribute (must
2055 // be a power of 2) specifies the
2056 // alignment that some part of the
2057 // instruction (not necessarily the
2058 // start) requires. If > 1, a
2059 // compute_padding() function must be
2060 // provided for the instruction
2061
2062 // Whether this node is expanded during code emission into a sequence of
2063 // instructions and the first instruction can perform an implicit null check.
2064 ins_attrib ins_is_late_expanded_null_check_candidate(false);
2065
2066 //----------OPERANDS-----------------------------------------------------------
2067 // Operand definitions must precede instruction definitions for correct parsing
2068 // in the ADLC because operands constitute user defined types which are used in
2069 // instruction definitions.
2070
2071 //----------Simple Operands----------------------------------------------------
2072 // Immediate Operands
2073 // Integer Immediate
2074 operand immI()
2075 %{
2076 match(ConI);
2077
2078 op_cost(10);
2079 format %{ %}
2080 interface(CONST_INTER);
2081 %}
2082
2083 // Constant for test vs zero
2084 operand immI_0()
2085 %{
2086 predicate(n->get_int() == 0);
2087 match(ConI);
2088
2089 op_cost(0);
2090 format %{ %}
2091 interface(CONST_INTER);
2092 %}
2093
2094 // Constant for increment
2095 operand immI_1()
2096 %{
2097 predicate(n->get_int() == 1);
2098 match(ConI);
2099
2100 op_cost(0);
2101 format %{ %}
2102 interface(CONST_INTER);
2103 %}
2104
2105 // Constant for decrement
2106 operand immI_M1()
2107 %{
2108 predicate(n->get_int() == -1);
2109 match(ConI);
2110
2111 op_cost(0);
2112 format %{ %}
2113 interface(CONST_INTER);
2114 %}
2115
2116 operand immI_2()
2117 %{
2118 predicate(n->get_int() == 2);
2119 match(ConI);
2120
2121 op_cost(0);
2122 format %{ %}
2123 interface(CONST_INTER);
2124 %}
2125
2126 operand immI_4()
2127 %{
2128 predicate(n->get_int() == 4);
2129 match(ConI);
2130
2131 op_cost(0);
2132 format %{ %}
2133 interface(CONST_INTER);
2134 %}
2135
2136 operand immI_8()
2137 %{
2138 predicate(n->get_int() == 8);
2139 match(ConI);
2140
2141 op_cost(0);
2142 format %{ %}
2143 interface(CONST_INTER);
2144 %}
2145
2146 // Valid scale values for addressing modes
2147 operand immI2()
2148 %{
2149 predicate(0 <= n->get_int() && (n->get_int() <= 3));
2150 match(ConI);
2151
2152 format %{ %}
2153 interface(CONST_INTER);
2154 %}
2155
2156 operand immU7()
2157 %{
2158 predicate((0 <= n->get_int()) && (n->get_int() <= 0x7F));
2159 match(ConI);
2160
2161 op_cost(5);
2162 format %{ %}
2163 interface(CONST_INTER);
2164 %}
2165
2166 operand immI8()
2167 %{
2168 predicate((-0x80 <= n->get_int()) && (n->get_int() < 0x80));
2169 match(ConI);
2170
2171 op_cost(5);
2172 format %{ %}
2173 interface(CONST_INTER);
2174 %}
2175
2176 operand immU8()
2177 %{
2178 predicate((0 <= n->get_int()) && (n->get_int() <= 255));
2179 match(ConI);
2180
2181 op_cost(5);
2182 format %{ %}
2183 interface(CONST_INTER);
2184 %}
2185
2186 operand immI16()
2187 %{
2188 predicate((-32768 <= n->get_int()) && (n->get_int() <= 32767));
2189 match(ConI);
2190
2191 op_cost(10);
2192 format %{ %}
2193 interface(CONST_INTER);
2194 %}
2195
2196 // Int Immediate non-negative
2197 operand immU31()
2198 %{
2199 predicate(n->get_int() >= 0);
2200 match(ConI);
2201
2202 op_cost(0);
2203 format %{ %}
2204 interface(CONST_INTER);
2205 %}
2206
2207 // Pointer Immediate
2208 operand immP()
2209 %{
2210 match(ConP);
2211
2212 op_cost(10);
2213 format %{ %}
2214 interface(CONST_INTER);
2215 %}
2216
2217 // Null Pointer Immediate
2218 operand immP0()
2219 %{
2220 predicate(n->get_ptr() == 0);
2221 match(ConP);
2222
2223 op_cost(5);
2224 format %{ %}
2225 interface(CONST_INTER);
2226 %}
2227
2228 // Pointer Immediate
2229 operand immN() %{
2230 match(ConN);
2231
2232 op_cost(10);
2233 format %{ %}
2234 interface(CONST_INTER);
2235 %}
2236
2237 operand immNKlass() %{
2238 match(ConNKlass);
2239
2240 op_cost(10);
2241 format %{ %}
2242 interface(CONST_INTER);
2243 %}
2244
2245 // Null Pointer Immediate
2246 operand immN0() %{
2247 predicate(n->get_narrowcon() == 0);
2248 match(ConN);
2249
2250 op_cost(5);
2251 format %{ %}
2252 interface(CONST_INTER);
2253 %}
2254
2255 operand immP31()
2256 %{
2257 predicate(n->as_Type()->type()->reloc() == relocInfo::none
2258 && (n->get_ptr() >> 31) == 0);
2259 match(ConP);
2260
2261 op_cost(5);
2262 format %{ %}
2263 interface(CONST_INTER);
2264 %}
2265
2266
2267 // Long Immediate
2268 operand immL()
2269 %{
2270 match(ConL);
2271
2272 op_cost(20);
2273 format %{ %}
2274 interface(CONST_INTER);
2275 %}
2276
2277 // Long Immediate 8-bit
2278 operand immL8()
2279 %{
2280 predicate(-0x80L <= n->get_long() && n->get_long() < 0x80L);
2281 match(ConL);
2282
2283 op_cost(5);
2284 format %{ %}
2285 interface(CONST_INTER);
2286 %}
2287
2288 // Long Immediate 32-bit unsigned
2289 operand immUL32()
2290 %{
2291 predicate(n->get_long() == (unsigned int) (n->get_long()));
2292 match(ConL);
2293
2294 op_cost(10);
2295 format %{ %}
2296 interface(CONST_INTER);
2297 %}
2298
2299 // Long Immediate 32-bit signed
2300 operand immL32()
2301 %{
2302 predicate(n->get_long() == (int) (n->get_long()));
2303 match(ConL);
2304
2305 op_cost(15);
2306 format %{ %}
2307 interface(CONST_INTER);
2308 %}
2309
2310 operand immL_Pow2()
2311 %{
2312 predicate(is_power_of_2((julong)n->get_long()));
2313 match(ConL);
2314
2315 op_cost(15);
2316 format %{ %}
2317 interface(CONST_INTER);
2318 %}
2319
2320 operand immL_NotPow2()
2321 %{
2322 predicate(is_power_of_2((julong)~n->get_long()));
2323 match(ConL);
2324
2325 op_cost(15);
2326 format %{ %}
2327 interface(CONST_INTER);
2328 %}
2329
2330 // Long Immediate zero
2331 operand immL0()
2332 %{
2333 predicate(n->get_long() == 0L);
2334 match(ConL);
2335
2336 op_cost(10);
2337 format %{ %}
2338 interface(CONST_INTER);
2339 %}
2340
2341 // Constant for increment
2342 operand immL1()
2343 %{
2344 predicate(n->get_long() == 1);
2345 match(ConL);
2346
2347 format %{ %}
2348 interface(CONST_INTER);
2349 %}
2350
2351 // Constant for decrement
2352 operand immL_M1()
2353 %{
2354 predicate(n->get_long() == -1);
2355 match(ConL);
2356
2357 format %{ %}
2358 interface(CONST_INTER);
2359 %}
2360
2361 // Long Immediate: low 32-bit mask
2362 operand immL_32bits()
2363 %{
2364 predicate(n->get_long() == 0xFFFFFFFFL);
2365 match(ConL);
2366 op_cost(20);
2367
2368 format %{ %}
2369 interface(CONST_INTER);
2370 %}
2371
2372 // Int Immediate: 2^n-1, positive
2373 operand immI_Pow2M1()
2374 %{
2375 predicate((n->get_int() > 0)
2376 && is_power_of_2((juint)n->get_int() + 1));
2377 match(ConI);
2378
2379 op_cost(20);
2380 format %{ %}
2381 interface(CONST_INTER);
2382 %}
2383
2384 // Float Immediate zero
2385 operand immF0()
2386 %{
2387 predicate(jint_cast(n->getf()) == 0);
2388 match(ConF);
2389
2390 op_cost(5);
2391 format %{ %}
2392 interface(CONST_INTER);
2393 %}
2394
2395 // Float Immediate
2396 operand immF()
2397 %{
2398 match(ConF);
2399
2400 op_cost(15);
2401 format %{ %}
2402 interface(CONST_INTER);
2403 %}
2404
2405 // Half Float Immediate
2406 operand immH()
2407 %{
2408 match(ConH);
2409
2410 op_cost(15);
2411 format %{ %}
2412 interface(CONST_INTER);
2413 %}
2414
2415 // Double Immediate zero
2416 operand immD0()
2417 %{
2418 predicate(jlong_cast(n->getd()) == 0);
2419 match(ConD);
2420
2421 op_cost(5);
2422 format %{ %}
2423 interface(CONST_INTER);
2424 %}
2425
2426 // Double Immediate
2427 operand immD()
2428 %{
2429 match(ConD);
2430
2431 op_cost(15);
2432 format %{ %}
2433 interface(CONST_INTER);
2434 %}
2435
2436 // Immediates for special shifts (sign extend)
2437
2438 // Constants for increment
2439 operand immI_16()
2440 %{
2441 predicate(n->get_int() == 16);
2442 match(ConI);
2443
2444 format %{ %}
2445 interface(CONST_INTER);
2446 %}
2447
2448 operand immI_24()
2449 %{
2450 predicate(n->get_int() == 24);
2451 match(ConI);
2452
2453 format %{ %}
2454 interface(CONST_INTER);
2455 %}
2456
2457 // Constant for byte-wide masking
2458 operand immI_255()
2459 %{
2460 predicate(n->get_int() == 255);
2461 match(ConI);
2462
2463 format %{ %}
2464 interface(CONST_INTER);
2465 %}
2466
2467 // Constant for short-wide masking
2468 operand immI_65535()
2469 %{
2470 predicate(n->get_int() == 65535);
2471 match(ConI);
2472
2473 format %{ %}
2474 interface(CONST_INTER);
2475 %}
2476
2477 // Constant for byte-wide masking
2478 operand immL_255()
2479 %{
2480 predicate(n->get_long() == 255);
2481 match(ConL);
2482
2483 format %{ %}
2484 interface(CONST_INTER);
2485 %}
2486
2487 // Constant for short-wide masking
2488 operand immL_65535()
2489 %{
2490 predicate(n->get_long() == 65535);
2491 match(ConL);
2492
2493 format %{ %}
2494 interface(CONST_INTER);
2495 %}
2496
2497 operand kReg()
2498 %{
2499 constraint(ALLOC_IN_RC(vectmask_reg));
2500 match(RegVectMask);
2501 format %{%}
2502 interface(REG_INTER);
2503 %}
2504
2505 // Register Operands
2506 // Integer Register
2507 operand rRegI()
2508 %{
2509 constraint(ALLOC_IN_RC(int_reg));
2510 match(RegI);
2511
2512 match(rax_RegI);
2513 match(rbx_RegI);
2514 match(rcx_RegI);
2515 match(rdx_RegI);
2516 match(rdi_RegI);
2517
2518 format %{ %}
2519 interface(REG_INTER);
2520 %}
2521
2522 // Special Registers
2523 operand rax_RegI()
2524 %{
2525 constraint(ALLOC_IN_RC(int_rax_reg));
2526 match(RegI);
2527 match(rRegI);
2528
2529 format %{ "RAX" %}
2530 interface(REG_INTER);
2531 %}
2532
2533 // Special Registers
2534 operand rbx_RegI()
2535 %{
2536 constraint(ALLOC_IN_RC(int_rbx_reg));
2537 match(RegI);
2538 match(rRegI);
2539
2540 format %{ "RBX" %}
2541 interface(REG_INTER);
2542 %}
2543
2544 operand rcx_RegI()
2545 %{
2546 constraint(ALLOC_IN_RC(int_rcx_reg));
2547 match(RegI);
2548 match(rRegI);
2549
2550 format %{ "RCX" %}
2551 interface(REG_INTER);
2552 %}
2553
2554 operand rdx_RegI()
2555 %{
2556 constraint(ALLOC_IN_RC(int_rdx_reg));
2557 match(RegI);
2558 match(rRegI);
2559
2560 format %{ "RDX" %}
2561 interface(REG_INTER);
2562 %}
2563
2564 operand rdi_RegI()
2565 %{
2566 constraint(ALLOC_IN_RC(int_rdi_reg));
2567 match(RegI);
2568 match(rRegI);
2569
2570 format %{ "RDI" %}
2571 interface(REG_INTER);
2572 %}
2573
2574 operand no_rax_rdx_RegI()
2575 %{
2576 constraint(ALLOC_IN_RC(int_no_rax_rdx_reg));
2577 match(RegI);
2578 match(rbx_RegI);
2579 match(rcx_RegI);
2580 match(rdi_RegI);
2581
2582 format %{ %}
2583 interface(REG_INTER);
2584 %}
2585
2586 operand no_rbp_r13_RegI()
2587 %{
2588 constraint(ALLOC_IN_RC(int_no_rbp_r13_reg));
2589 match(RegI);
2590 match(rRegI);
2591 match(rax_RegI);
2592 match(rbx_RegI);
2593 match(rcx_RegI);
2594 match(rdx_RegI);
2595 match(rdi_RegI);
2596
2597 format %{ %}
2598 interface(REG_INTER);
2599 %}
2600
2601 // Pointer Register
2602 operand any_RegP()
2603 %{
2604 constraint(ALLOC_IN_RC(any_reg));
2605 match(RegP);
2606 match(rax_RegP);
2607 match(rbx_RegP);
2608 match(rdi_RegP);
2609 match(rsi_RegP);
2610 match(rbp_RegP);
2611 match(r15_RegP);
2612 match(rRegP);
2613
2614 format %{ %}
2615 interface(REG_INTER);
2616 %}
2617
2618 operand rRegP()
2619 %{
2620 constraint(ALLOC_IN_RC(ptr_reg));
2621 match(RegP);
2622 match(rax_RegP);
2623 match(rbx_RegP);
2624 match(rdi_RegP);
2625 match(rsi_RegP);
2626 match(rbp_RegP); // See Q&A below about
2627 match(r15_RegP); // r15_RegP and rbp_RegP.
2628
2629 format %{ %}
2630 interface(REG_INTER);
2631 %}
2632
2633 operand rRegN() %{
2634 constraint(ALLOC_IN_RC(int_reg));
2635 match(RegN);
2636
2637 format %{ %}
2638 interface(REG_INTER);
2639 %}
2640
2641 // Question: Why is r15_RegP (the read-only TLS register) a match for rRegP?
2642 // Answer: Operand match rules govern the DFA as it processes instruction inputs.
2643 // It's fine for an instruction input that expects rRegP to match a r15_RegP.
2644 // The output of an instruction is controlled by the allocator, which respects
2645 // register class masks, not match rules. Unless an instruction mentions
2646 // r15_RegP or any_RegP explicitly as its output, r15 will not be considered
2647 // by the allocator as an input.
2648 // The same logic applies to rbp_RegP being a match for rRegP: If PreserveFramePointer==true,
2649 // the RBP is used as a proper frame pointer and is not included in ptr_reg. As a
2650 // result, RBP is not included in the output of the instruction either.
2651
2652 // This operand is not allowed to use RBP even if
2653 // RBP is not used to hold the frame pointer.
2654 operand no_rbp_RegP()
2655 %{
2656 constraint(ALLOC_IN_RC(ptr_reg_no_rbp));
2657 match(RegP);
2658 match(rbx_RegP);
2659 match(rsi_RegP);
2660 match(rdi_RegP);
2661
2662 format %{ %}
2663 interface(REG_INTER);
2664 %}
2665
2666 // Special Registers
2667 // Return a pointer value
2668 operand rax_RegP()
2669 %{
2670 constraint(ALLOC_IN_RC(ptr_rax_reg));
2671 match(RegP);
2672 match(rRegP);
2673
2674 format %{ %}
2675 interface(REG_INTER);
2676 %}
2677
2678 // Special Registers
2679 // Return a compressed pointer value
2680 operand rax_RegN()
2681 %{
2682 constraint(ALLOC_IN_RC(int_rax_reg));
2683 match(RegN);
2684 match(rRegN);
2685
2686 format %{ %}
2687 interface(REG_INTER);
2688 %}
2689
2690 // Used in AtomicAdd
2691 operand rbx_RegP()
2692 %{
2693 constraint(ALLOC_IN_RC(ptr_rbx_reg));
2694 match(RegP);
2695 match(rRegP);
2696
2697 format %{ %}
2698 interface(REG_INTER);
2699 %}
2700
2701 operand rsi_RegP()
2702 %{
2703 constraint(ALLOC_IN_RC(ptr_rsi_reg));
2704 match(RegP);
2705 match(rRegP);
2706
2707 format %{ %}
2708 interface(REG_INTER);
2709 %}
2710
2711 operand rbp_RegP()
2712 %{
2713 constraint(ALLOC_IN_RC(ptr_rbp_reg));
2714 match(RegP);
2715 match(rRegP);
2716
2717 format %{ %}
2718 interface(REG_INTER);
2719 %}
2720
2721 // Used in rep stosq
2722 operand rdi_RegP()
2723 %{
2724 constraint(ALLOC_IN_RC(ptr_rdi_reg));
2725 match(RegP);
2726 match(rRegP);
2727
2728 format %{ %}
2729 interface(REG_INTER);
2730 %}
2731
2732 operand r15_RegP()
2733 %{
2734 constraint(ALLOC_IN_RC(ptr_r15_reg));
2735 match(RegP);
2736 match(rRegP);
2737
2738 format %{ %}
2739 interface(REG_INTER);
2740 %}
2741
2742 operand rRegL()
2743 %{
2744 constraint(ALLOC_IN_RC(long_reg));
2745 match(RegL);
2746 match(rax_RegL);
2747 match(rdx_RegL);
2748
2749 format %{ %}
2750 interface(REG_INTER);
2751 %}
2752
2753 // Special Registers
2754 operand no_rax_rdx_RegL()
2755 %{
2756 constraint(ALLOC_IN_RC(long_no_rax_rdx_reg));
2757 match(RegL);
2758 match(rRegL);
2759
2760 format %{ %}
2761 interface(REG_INTER);
2762 %}
2763
2764 operand rax_RegL()
2765 %{
2766 constraint(ALLOC_IN_RC(long_rax_reg));
2767 match(RegL);
2768 match(rRegL);
2769
2770 format %{ "RAX" %}
2771 interface(REG_INTER);
2772 %}
2773
2774 operand rcx_RegL()
2775 %{
2776 constraint(ALLOC_IN_RC(long_rcx_reg));
2777 match(RegL);
2778 match(rRegL);
2779
2780 format %{ %}
2781 interface(REG_INTER);
2782 %}
2783
2784 operand rdx_RegL()
2785 %{
2786 constraint(ALLOC_IN_RC(long_rdx_reg));
2787 match(RegL);
2788 match(rRegL);
2789
2790 format %{ %}
2791 interface(REG_INTER);
2792 %}
2793
2794 operand r11_RegL()
2795 %{
2796 constraint(ALLOC_IN_RC(long_r11_reg));
2797 match(RegL);
2798 match(rRegL);
2799
2800 format %{ %}
2801 interface(REG_INTER);
2802 %}
2803
2804 operand no_rbp_r13_RegL()
2805 %{
2806 constraint(ALLOC_IN_RC(long_no_rbp_r13_reg));
2807 match(RegL);
2808 match(rRegL);
2809 match(rax_RegL);
2810 match(rcx_RegL);
2811 match(rdx_RegL);
2812
2813 format %{ %}
2814 interface(REG_INTER);
2815 %}
2816
2817 // Flags register, used as output of compare instructions
2818 operand rFlagsReg()
2819 %{
2820 constraint(ALLOC_IN_RC(int_flags));
2821 match(RegFlags);
2822
2823 format %{ "RFLAGS" %}
2824 interface(REG_INTER);
2825 %}
2826
2827 // Flags register, used as output of FLOATING POINT compare instructions
2828 operand rFlagsRegU()
2829 %{
2830 constraint(ALLOC_IN_RC(int_flags));
2831 match(RegFlags);
2832
2833 format %{ "RFLAGS_U" %}
2834 interface(REG_INTER);
2835 %}
2836
2837 operand rFlagsRegUCF() %{
2838 constraint(ALLOC_IN_RC(int_flags));
2839 match(RegFlags);
2840 predicate(false);
2841
2842 format %{ "RFLAGS_U_CF" %}
2843 interface(REG_INTER);
2844 %}
2845
2846 // Float register operands
2847 operand regF() %{
2848 constraint(ALLOC_IN_RC(float_reg));
2849 match(RegF);
2850
2851 format %{ %}
2852 interface(REG_INTER);
2853 %}
2854
2855 // Float register operands
2856 operand legRegF() %{
2857 constraint(ALLOC_IN_RC(float_reg_legacy));
2858 match(RegF);
2859
2860 format %{ %}
2861 interface(REG_INTER);
2862 %}
2863
2864 // Float register operands
2865 operand vlRegF() %{
2866 constraint(ALLOC_IN_RC(float_reg_vl));
2867 match(RegF);
2868
2869 format %{ %}
2870 interface(REG_INTER);
2871 %}
2872
2873 // Double register operands
2874 operand regD() %{
2875 constraint(ALLOC_IN_RC(double_reg));
2876 match(RegD);
2877
2878 format %{ %}
2879 interface(REG_INTER);
2880 %}
2881
2882 // Double register operands
2883 operand legRegD() %{
2884 constraint(ALLOC_IN_RC(double_reg_legacy));
2885 match(RegD);
2886
2887 format %{ %}
2888 interface(REG_INTER);
2889 %}
2890
2891 // Double register operands
2892 operand vlRegD() %{
2893 constraint(ALLOC_IN_RC(double_reg_vl));
2894 match(RegD);
2895
2896 format %{ %}
2897 interface(REG_INTER);
2898 %}
2899
2900 //----------Memory Operands----------------------------------------------------
2901 // Direct Memory Operand
2902 // operand direct(immP addr)
2903 // %{
2904 // match(addr);
2905
2906 // format %{ "[$addr]" %}
2907 // interface(MEMORY_INTER) %{
2908 // base(0xFFFFFFFF);
2909 // index(0x4);
2910 // scale(0x0);
2911 // disp($addr);
2912 // %}
2913 // %}
2914
2915 // Indirect Memory Operand
2916 operand indirect(any_RegP reg)
2917 %{
2918 constraint(ALLOC_IN_RC(ptr_reg));
2919 match(reg);
2920
2921 format %{ "[$reg]" %}
2922 interface(MEMORY_INTER) %{
2923 base($reg);
2924 index(0x4);
2925 scale(0x0);
2926 disp(0x0);
2927 %}
2928 %}
2929
2930 // Indirect Memory Plus Short Offset Operand
2931 operand indOffset8(any_RegP reg, immL8 off)
2932 %{
2933 constraint(ALLOC_IN_RC(ptr_reg));
2934 match(AddP reg off);
2935
2936 format %{ "[$reg + $off (8-bit)]" %}
2937 interface(MEMORY_INTER) %{
2938 base($reg);
2939 index(0x4);
2940 scale(0x0);
2941 disp($off);
2942 %}
2943 %}
2944
2945 // Indirect Memory Plus Long Offset Operand
2946 operand indOffset32(any_RegP reg, immL32 off)
2947 %{
2948 constraint(ALLOC_IN_RC(ptr_reg));
2949 match(AddP reg off);
2950
2951 format %{ "[$reg + $off (32-bit)]" %}
2952 interface(MEMORY_INTER) %{
2953 base($reg);
2954 index(0x4);
2955 scale(0x0);
2956 disp($off);
2957 %}
2958 %}
2959
2960 // Indirect Memory Plus Index Register Plus Offset Operand
2961 operand indIndexOffset(any_RegP reg, rRegL lreg, immL32 off)
2962 %{
2963 constraint(ALLOC_IN_RC(ptr_reg));
2964 match(AddP (AddP reg lreg) off);
2965
2966 op_cost(10);
2967 format %{"[$reg + $off + $lreg]" %}
2968 interface(MEMORY_INTER) %{
2969 base($reg);
2970 index($lreg);
2971 scale(0x0);
2972 disp($off);
2973 %}
2974 %}
2975
2976 // Indirect Memory Plus Index Register Plus Offset Operand
2977 operand indIndex(any_RegP reg, rRegL lreg)
2978 %{
2979 constraint(ALLOC_IN_RC(ptr_reg));
2980 match(AddP reg lreg);
2981
2982 op_cost(10);
2983 format %{"[$reg + $lreg]" %}
2984 interface(MEMORY_INTER) %{
2985 base($reg);
2986 index($lreg);
2987 scale(0x0);
2988 disp(0x0);
2989 %}
2990 %}
2991
2992 // Indirect Memory Times Scale Plus Index Register
2993 operand indIndexScale(any_RegP reg, rRegL lreg, immI2 scale)
2994 %{
2995 constraint(ALLOC_IN_RC(ptr_reg));
2996 match(AddP reg (LShiftL lreg scale));
2997
2998 op_cost(10);
2999 format %{"[$reg + $lreg << $scale]" %}
3000 interface(MEMORY_INTER) %{
3001 base($reg);
3002 index($lreg);
3003 scale($scale);
3004 disp(0x0);
3005 %}
3006 %}
3007
3008 operand indPosIndexScale(any_RegP reg, rRegI idx, immI2 scale)
3009 %{
3010 constraint(ALLOC_IN_RC(ptr_reg));
3011 predicate(n->in(3)->in(1)->as_Type()->type()->is_long()->_lo >= 0);
3012 match(AddP reg (LShiftL (ConvI2L idx) scale));
3013
3014 op_cost(10);
3015 format %{"[$reg + pos $idx << $scale]" %}
3016 interface(MEMORY_INTER) %{
3017 base($reg);
3018 index($idx);
3019 scale($scale);
3020 disp(0x0);
3021 %}
3022 %}
3023
3024 // Indirect Memory Times Scale Plus Index Register Plus Offset Operand
3025 operand indIndexScaleOffset(any_RegP reg, immL32 off, rRegL lreg, immI2 scale)
3026 %{
3027 constraint(ALLOC_IN_RC(ptr_reg));
3028 match(AddP (AddP reg (LShiftL lreg scale)) off);
3029
3030 op_cost(10);
3031 format %{"[$reg + $off + $lreg << $scale]" %}
3032 interface(MEMORY_INTER) %{
3033 base($reg);
3034 index($lreg);
3035 scale($scale);
3036 disp($off);
3037 %}
3038 %}
3039
3040 // Indirect Memory Plus Positive Index Register Plus Offset Operand
3041 operand indPosIndexOffset(any_RegP reg, immL32 off, rRegI idx)
3042 %{
3043 constraint(ALLOC_IN_RC(ptr_reg));
3044 predicate(n->in(2)->in(3)->as_Type()->type()->is_long()->_lo >= 0);
3045 match(AddP (AddP reg (ConvI2L idx)) off);
3046
3047 op_cost(10);
3048 format %{"[$reg + $off + $idx]" %}
3049 interface(MEMORY_INTER) %{
3050 base($reg);
3051 index($idx);
3052 scale(0x0);
3053 disp($off);
3054 %}
3055 %}
3056
3057 // Indirect Memory Times Scale Plus Positive Index Register Plus Offset Operand
3058 operand indPosIndexScaleOffset(any_RegP reg, immL32 off, rRegI idx, immI2 scale)
3059 %{
3060 constraint(ALLOC_IN_RC(ptr_reg));
3061 predicate(n->in(2)->in(3)->in(1)->as_Type()->type()->is_long()->_lo >= 0);
3062 match(AddP (AddP reg (LShiftL (ConvI2L idx) scale)) off);
3063
3064 op_cost(10);
3065 format %{"[$reg + $off + $idx << $scale]" %}
3066 interface(MEMORY_INTER) %{
3067 base($reg);
3068 index($idx);
3069 scale($scale);
3070 disp($off);
3071 %}
3072 %}
3073
3074 // Indirect Narrow Oop Operand
3075 operand indCompressedOop(rRegN reg) %{
3076 predicate(UseCompressedOops && (CompressedOops::shift() == Address::times_8));
3077 constraint(ALLOC_IN_RC(ptr_reg));
3078 match(DecodeN reg);
3079
3080 op_cost(10);
3081 format %{"[R12 + $reg << 3] (compressed oop addressing)" %}
3082 interface(MEMORY_INTER) %{
3083 base(0xc); // R12
3084 index($reg);
3085 scale(0x3);
3086 disp(0x0);
3087 %}
3088 %}
3089
3090 // Indirect Narrow Oop Plus Offset Operand
3091 // Note: x86 architecture doesn't support "scale * index + offset" without a base
3092 // we can't free r12 even with CompressedOops::base() == nullptr.
3093 operand indCompressedOopOffset(rRegN reg, immL32 off) %{
3094 predicate(UseCompressedOops && (CompressedOops::shift() == Address::times_8));
3095 constraint(ALLOC_IN_RC(ptr_reg));
3096 match(AddP (DecodeN reg) off);
3097
3098 op_cost(10);
3099 format %{"[R12 + $reg << 3 + $off] (compressed oop addressing)" %}
3100 interface(MEMORY_INTER) %{
3101 base(0xc); // R12
3102 index($reg);
3103 scale(0x3);
3104 disp($off);
3105 %}
3106 %}
3107
3108 // Indirect Memory Operand
3109 operand indirectNarrow(rRegN reg)
3110 %{
3111 predicate(CompressedOops::shift() == 0);
3112 constraint(ALLOC_IN_RC(ptr_reg));
3113 match(DecodeN reg);
3114
3115 format %{ "[$reg]" %}
3116 interface(MEMORY_INTER) %{
3117 base($reg);
3118 index(0x4);
3119 scale(0x0);
3120 disp(0x0);
3121 %}
3122 %}
3123
3124 // Indirect Memory Plus Short Offset Operand
3125 operand indOffset8Narrow(rRegN reg, immL8 off)
3126 %{
3127 predicate(CompressedOops::shift() == 0);
3128 constraint(ALLOC_IN_RC(ptr_reg));
3129 match(AddP (DecodeN reg) off);
3130
3131 format %{ "[$reg + $off (8-bit)]" %}
3132 interface(MEMORY_INTER) %{
3133 base($reg);
3134 index(0x4);
3135 scale(0x0);
3136 disp($off);
3137 %}
3138 %}
3139
3140 // Indirect Memory Plus Long Offset Operand
3141 operand indOffset32Narrow(rRegN reg, immL32 off)
3142 %{
3143 predicate(CompressedOops::shift() == 0);
3144 constraint(ALLOC_IN_RC(ptr_reg));
3145 match(AddP (DecodeN reg) off);
3146
3147 format %{ "[$reg + $off (32-bit)]" %}
3148 interface(MEMORY_INTER) %{
3149 base($reg);
3150 index(0x4);
3151 scale(0x0);
3152 disp($off);
3153 %}
3154 %}
3155
3156 // Indirect Memory Plus Index Register Plus Offset Operand
3157 operand indIndexOffsetNarrow(rRegN reg, rRegL lreg, immL32 off)
3158 %{
3159 predicate(CompressedOops::shift() == 0);
3160 constraint(ALLOC_IN_RC(ptr_reg));
3161 match(AddP (AddP (DecodeN reg) lreg) off);
3162
3163 op_cost(10);
3164 format %{"[$reg + $off + $lreg]" %}
3165 interface(MEMORY_INTER) %{
3166 base($reg);
3167 index($lreg);
3168 scale(0x0);
3169 disp($off);
3170 %}
3171 %}
3172
3173 // Indirect Memory Plus Index Register Plus Offset Operand
3174 operand indIndexNarrow(rRegN reg, rRegL lreg)
3175 %{
3176 predicate(CompressedOops::shift() == 0);
3177 constraint(ALLOC_IN_RC(ptr_reg));
3178 match(AddP (DecodeN reg) lreg);
3179
3180 op_cost(10);
3181 format %{"[$reg + $lreg]" %}
3182 interface(MEMORY_INTER) %{
3183 base($reg);
3184 index($lreg);
3185 scale(0x0);
3186 disp(0x0);
3187 %}
3188 %}
3189
3190 // Indirect Memory Times Scale Plus Index Register
3191 operand indIndexScaleNarrow(rRegN reg, rRegL lreg, immI2 scale)
3192 %{
3193 predicate(CompressedOops::shift() == 0);
3194 constraint(ALLOC_IN_RC(ptr_reg));
3195 match(AddP (DecodeN reg) (LShiftL lreg scale));
3196
3197 op_cost(10);
3198 format %{"[$reg + $lreg << $scale]" %}
3199 interface(MEMORY_INTER) %{
3200 base($reg);
3201 index($lreg);
3202 scale($scale);
3203 disp(0x0);
3204 %}
3205 %}
3206
3207 // Indirect Memory Times Scale Plus Index Register Plus Offset Operand
3208 operand indIndexScaleOffsetNarrow(rRegN reg, immL32 off, rRegL lreg, immI2 scale)
3209 %{
3210 predicate(CompressedOops::shift() == 0);
3211 constraint(ALLOC_IN_RC(ptr_reg));
3212 match(AddP (AddP (DecodeN reg) (LShiftL lreg scale)) off);
3213
3214 op_cost(10);
3215 format %{"[$reg + $off + $lreg << $scale]" %}
3216 interface(MEMORY_INTER) %{
3217 base($reg);
3218 index($lreg);
3219 scale($scale);
3220 disp($off);
3221 %}
3222 %}
3223
3224 // Indirect Memory Times Plus Positive Index Register Plus Offset Operand
3225 operand indPosIndexOffsetNarrow(rRegN reg, immL32 off, rRegI idx)
3226 %{
3227 constraint(ALLOC_IN_RC(ptr_reg));
3228 predicate(CompressedOops::shift() == 0 && n->in(2)->in(3)->as_Type()->type()->is_long()->_lo >= 0);
3229 match(AddP (AddP (DecodeN reg) (ConvI2L idx)) off);
3230
3231 op_cost(10);
3232 format %{"[$reg + $off + $idx]" %}
3233 interface(MEMORY_INTER) %{
3234 base($reg);
3235 index($idx);
3236 scale(0x0);
3237 disp($off);
3238 %}
3239 %}
3240
3241 // Indirect Memory Times Scale Plus Positive Index Register Plus Offset Operand
3242 operand indPosIndexScaleOffsetNarrow(rRegN reg, immL32 off, rRegI idx, immI2 scale)
3243 %{
3244 constraint(ALLOC_IN_RC(ptr_reg));
3245 predicate(CompressedOops::shift() == 0 && n->in(2)->in(3)->in(1)->as_Type()->type()->is_long()->_lo >= 0);
3246 match(AddP (AddP (DecodeN reg) (LShiftL (ConvI2L idx) scale)) off);
3247
3248 op_cost(10);
3249 format %{"[$reg + $off + $idx << $scale]" %}
3250 interface(MEMORY_INTER) %{
3251 base($reg);
3252 index($idx);
3253 scale($scale);
3254 disp($off);
3255 %}
3256 %}
3257
3258 //----------Special Memory Operands--------------------------------------------
3259 // Stack Slot Operand - This operand is used for loading and storing temporary
3260 // values on the stack where a match requires a value to
3261 // flow through memory.
3262 operand stackSlotP(sRegP reg)
3263 %{
3264 constraint(ALLOC_IN_RC(stack_slots));
3265 // No match rule because this operand is only generated in matching
3266
3267 format %{ "[$reg]" %}
3268 interface(MEMORY_INTER) %{
3269 base(0x4); // RSP
3270 index(0x4); // No Index
3271 scale(0x0); // No Scale
3272 disp($reg); // Stack Offset
3273 %}
3274 %}
3275
3276 operand stackSlotI(sRegI reg)
3277 %{
3278 constraint(ALLOC_IN_RC(stack_slots));
3279 // No match rule because this operand is only generated in matching
3280
3281 format %{ "[$reg]" %}
3282 interface(MEMORY_INTER) %{
3283 base(0x4); // RSP
3284 index(0x4); // No Index
3285 scale(0x0); // No Scale
3286 disp($reg); // Stack Offset
3287 %}
3288 %}
3289
3290 operand stackSlotF(sRegF reg)
3291 %{
3292 constraint(ALLOC_IN_RC(stack_slots));
3293 // No match rule because this operand is only generated in matching
3294
3295 format %{ "[$reg]" %}
3296 interface(MEMORY_INTER) %{
3297 base(0x4); // RSP
3298 index(0x4); // No Index
3299 scale(0x0); // No Scale
3300 disp($reg); // Stack Offset
3301 %}
3302 %}
3303
3304 operand stackSlotD(sRegD reg)
3305 %{
3306 constraint(ALLOC_IN_RC(stack_slots));
3307 // No match rule because this operand is only generated in matching
3308
3309 format %{ "[$reg]" %}
3310 interface(MEMORY_INTER) %{
3311 base(0x4); // RSP
3312 index(0x4); // No Index
3313 scale(0x0); // No Scale
3314 disp($reg); // Stack Offset
3315 %}
3316 %}
3317 operand stackSlotL(sRegL reg)
3318 %{
3319 constraint(ALLOC_IN_RC(stack_slots));
3320 // No match rule because this operand is only generated in matching
3321
3322 format %{ "[$reg]" %}
3323 interface(MEMORY_INTER) %{
3324 base(0x4); // RSP
3325 index(0x4); // No Index
3326 scale(0x0); // No Scale
3327 disp($reg); // Stack Offset
3328 %}
3329 %}
3330
3331 //----------Conditional Branch Operands----------------------------------------
3332 // Comparison Op - This is the operation of the comparison, and is limited to
3333 // the following set of codes:
3334 // L (<), LE (<=), G (>), GE (>=), E (==), NE (!=)
3335 //
3336 // Other attributes of the comparison, such as unsignedness, are specified
3337 // by the comparison instruction that sets a condition code flags register.
3338 // That result is represented by a flags operand whose subtype is appropriate
3339 // to the unsignedness (etc.) of the comparison.
3340 //
3341 // Later, the instruction which matches both the Comparison Op (a Bool) and
3342 // the flags (produced by the Cmp) specifies the coding of the comparison op
3343 // by matching a specific subtype of Bool operand below, such as cmpOpU.
3344
3345 // Comparison Code
3346 operand cmpOp()
3347 %{
3348 match(Bool);
3349
3350 format %{ "" %}
3351 interface(COND_INTER) %{
3352 equal(0x4, "e");
3353 not_equal(0x5, "ne");
3354 less(0xC, "l");
3355 greater_equal(0xD, "ge");
3356 less_equal(0xE, "le");
3357 greater(0xF, "g");
3358 overflow(0x0, "o");
3359 no_overflow(0x1, "no");
3360 %}
3361 %}
3362
3363 // Comparison Code, unsigned compare. Used by FP also, with
3364 // C2 (unordered) turned into GT or LT already. The other bits
3365 // C0 and C3 are turned into Carry & Zero flags.
3366 operand cmpOpU()
3367 %{
3368 match(Bool);
3369
3370 format %{ "" %}
3371 interface(COND_INTER) %{
3372 equal(0x4, "e");
3373 not_equal(0x5, "ne");
3374 less(0x2, "b");
3375 greater_equal(0x3, "ae");
3376 less_equal(0x6, "be");
3377 greater(0x7, "a");
3378 overflow(0x0, "o");
3379 no_overflow(0x1, "no");
3380 %}
3381 %}
3382
3383
3384 // Floating comparisons that don't require any fixup for the unordered case,
3385 // If both inputs of the comparison are the same, ZF is always set so we
3386 // don't need to use cmpOpUCF2 for eq/ne
3387 operand cmpOpUCF() %{
3388 match(Bool);
3389 predicate(n->as_Bool()->_test._test == BoolTest::lt ||
3390 n->as_Bool()->_test._test == BoolTest::ge ||
3391 n->as_Bool()->_test._test == BoolTest::le ||
3392 n->as_Bool()->_test._test == BoolTest::gt ||
3393 n->in(1)->in(1) == n->in(1)->in(2));
3394 format %{ "" %}
3395 interface(COND_INTER) %{
3396 equal(0xb, "np");
3397 not_equal(0xa, "p");
3398 less(0x2, "b");
3399 greater_equal(0x3, "ae");
3400 less_equal(0x6, "be");
3401 greater(0x7, "a");
3402 overflow(0x0, "o");
3403 no_overflow(0x1, "no");
3404 %}
3405 %}
3406
3407
3408 // Floating comparisons that can be fixed up with extra conditional jumps
3409 operand cmpOpUCF2() %{
3410 match(Bool);
3411 predicate((n->as_Bool()->_test._test == BoolTest::ne ||
3412 n->as_Bool()->_test._test == BoolTest::eq) &&
3413 n->in(1)->in(1) != n->in(1)->in(2));
3414 format %{ "" %}
3415 interface(COND_INTER) %{
3416 equal(0x4, "e");
3417 not_equal(0x5, "ne");
3418 less(0x2, "b");
3419 greater_equal(0x3, "ae");
3420 less_equal(0x6, "be");
3421 greater(0x7, "a");
3422 overflow(0x0, "o");
3423 no_overflow(0x1, "no");
3424 %}
3425 %}
3426
3427 //----------OPERAND CLASSES----------------------------------------------------
3428 // Operand Classes are groups of operands that are used as to simplify
3429 // instruction definitions by not requiring the AD writer to specify separate
3430 // instructions for every form of operand when the instruction accepts
3431 // multiple operand types with the same basic encoding and format. The classic
3432 // case of this is memory operands.
3433
3434 opclass memory(indirect, indOffset8, indOffset32, indIndexOffset, indIndex,
3435 indIndexScale, indPosIndexScale, indIndexScaleOffset, indPosIndexOffset, indPosIndexScaleOffset,
3436 indCompressedOop, indCompressedOopOffset,
3437 indirectNarrow, indOffset8Narrow, indOffset32Narrow,
3438 indIndexOffsetNarrow, indIndexNarrow, indIndexScaleNarrow,
3439 indIndexScaleOffsetNarrow, indPosIndexOffsetNarrow, indPosIndexScaleOffsetNarrow);
3440
3441 //----------PIPELINE-----------------------------------------------------------
3442 // Rules which define the behavior of the target architectures pipeline.
3443 pipeline %{
3444
3445 //----------ATTRIBUTES---------------------------------------------------------
3446 attributes %{
3447 variable_size_instructions; // Fixed size instructions
3448 max_instructions_per_bundle = 3; // Up to 3 instructions per bundle
3449 instruction_unit_size = 1; // An instruction is 1 bytes long
3450 instruction_fetch_unit_size = 16; // The processor fetches one line
3451 instruction_fetch_units = 1; // of 16 bytes
3452 %}
3453
3454 //----------RESOURCES----------------------------------------------------------
3455 // Resources are the functional units available to the machine
3456
3457 // Generic P2/P3 pipeline
3458 // 3 decoders, only D0 handles big operands; a "bundle" is the limit of
3459 // 3 instructions decoded per cycle.
3460 // 2 load/store ops per cycle, 1 branch, 1 FPU,
3461 // 3 ALU op, only ALU0 handles mul instructions.
3462 resources( D0, D1, D2, DECODE = D0 | D1 | D2,
3463 MS0, MS1, MS2, MEM = MS0 | MS1 | MS2,
3464 BR, FPU,
3465 ALU0, ALU1, ALU2, ALU = ALU0 | ALU1 | ALU2);
3466
3467 //----------PIPELINE DESCRIPTION-----------------------------------------------
3468 // Pipeline Description specifies the stages in the machine's pipeline
3469
3470 // Generic P2/P3 pipeline
3471 pipe_desc(S0, S1, S2, S3, S4, S5);
3472
3473 //----------PIPELINE CLASSES---------------------------------------------------
3474 // Pipeline Classes describe the stages in which input and output are
3475 // referenced by the hardware pipeline.
3476
3477 // Naming convention: ialu or fpu
3478 // Then: _reg
3479 // Then: _reg if there is a 2nd register
3480 // Then: _long if it's a pair of instructions implementing a long
3481 // Then: _fat if it requires the big decoder
3482 // Or: _mem if it requires the big decoder and a memory unit.
3483
3484 // Integer ALU reg operation
3485 pipe_class ialu_reg(rRegI dst)
3486 %{
3487 single_instruction;
3488 dst : S4(write);
3489 dst : S3(read);
3490 DECODE : S0; // any decoder
3491 ALU : S3; // any alu
3492 %}
3493
3494 // Long ALU reg operation
3495 pipe_class ialu_reg_long(rRegL dst)
3496 %{
3497 instruction_count(2);
3498 dst : S4(write);
3499 dst : S3(read);
3500 DECODE : S0(2); // any 2 decoders
3501 ALU : S3(2); // both alus
3502 %}
3503
3504 // Integer ALU reg operation using big decoder
3505 pipe_class ialu_reg_fat(rRegI dst)
3506 %{
3507 single_instruction;
3508 dst : S4(write);
3509 dst : S3(read);
3510 D0 : S0; // big decoder only
3511 ALU : S3; // any alu
3512 %}
3513
3514 // Integer ALU reg-reg operation
3515 pipe_class ialu_reg_reg(rRegI dst, rRegI src)
3516 %{
3517 single_instruction;
3518 dst : S4(write);
3519 src : S3(read);
3520 DECODE : S0; // any decoder
3521 ALU : S3; // any alu
3522 %}
3523
3524 // Integer ALU reg-reg operation
3525 pipe_class ialu_reg_reg_fat(rRegI dst, memory src)
3526 %{
3527 single_instruction;
3528 dst : S4(write);
3529 src : S3(read);
3530 D0 : S0; // big decoder only
3531 ALU : S3; // any alu
3532 %}
3533
3534 // Integer ALU reg-mem operation
3535 pipe_class ialu_reg_mem(rRegI dst, memory mem)
3536 %{
3537 single_instruction;
3538 dst : S5(write);
3539 mem : S3(read);
3540 D0 : S0; // big decoder only
3541 ALU : S4; // any alu
3542 MEM : S3; // any mem
3543 %}
3544
3545 // Integer mem operation (prefetch)
3546 pipe_class ialu_mem(memory mem)
3547 %{
3548 single_instruction;
3549 mem : S3(read);
3550 D0 : S0; // big decoder only
3551 MEM : S3; // any mem
3552 %}
3553
3554 // Integer Store to Memory
3555 pipe_class ialu_mem_reg(memory mem, rRegI src)
3556 %{
3557 single_instruction;
3558 mem : S3(read);
3559 src : S5(read);
3560 D0 : S0; // big decoder only
3561 ALU : S4; // any alu
3562 MEM : S3;
3563 %}
3564
3565 // // Long Store to Memory
3566 // pipe_class ialu_mem_long_reg(memory mem, rRegL src)
3567 // %{
3568 // instruction_count(2);
3569 // mem : S3(read);
3570 // src : S5(read);
3571 // D0 : S0(2); // big decoder only; twice
3572 // ALU : S4(2); // any 2 alus
3573 // MEM : S3(2); // Both mems
3574 // %}
3575
3576 // Integer Store to Memory
3577 pipe_class ialu_mem_imm(memory mem)
3578 %{
3579 single_instruction;
3580 mem : S3(read);
3581 D0 : S0; // big decoder only
3582 ALU : S4; // any alu
3583 MEM : S3;
3584 %}
3585
3586 // Integer ALU0 reg-reg operation
3587 pipe_class ialu_reg_reg_alu0(rRegI dst, rRegI src)
3588 %{
3589 single_instruction;
3590 dst : S4(write);
3591 src : S3(read);
3592 D0 : S0; // Big decoder only
3593 ALU0 : S3; // only alu0
3594 %}
3595
3596 // Integer ALU0 reg-mem operation
3597 pipe_class ialu_reg_mem_alu0(rRegI dst, memory mem)
3598 %{
3599 single_instruction;
3600 dst : S5(write);
3601 mem : S3(read);
3602 D0 : S0; // big decoder only
3603 ALU0 : S4; // ALU0 only
3604 MEM : S3; // any mem
3605 %}
3606
3607 // Integer ALU reg-reg operation
3608 pipe_class ialu_cr_reg_reg(rFlagsReg cr, rRegI src1, rRegI src2)
3609 %{
3610 single_instruction;
3611 cr : S4(write);
3612 src1 : S3(read);
3613 src2 : S3(read);
3614 DECODE : S0; // any decoder
3615 ALU : S3; // any alu
3616 %}
3617
3618 // Integer ALU reg-imm operation
3619 pipe_class ialu_cr_reg_imm(rFlagsReg cr, rRegI src1)
3620 %{
3621 single_instruction;
3622 cr : S4(write);
3623 src1 : S3(read);
3624 DECODE : S0; // any decoder
3625 ALU : S3; // any alu
3626 %}
3627
3628 // Integer ALU reg-mem operation
3629 pipe_class ialu_cr_reg_mem(rFlagsReg cr, rRegI src1, memory src2)
3630 %{
3631 single_instruction;
3632 cr : S4(write);
3633 src1 : S3(read);
3634 src2 : S3(read);
3635 D0 : S0; // big decoder only
3636 ALU : S4; // any alu
3637 MEM : S3;
3638 %}
3639
3640 // Conditional move reg-reg
3641 pipe_class pipe_cmplt( rRegI p, rRegI q, rRegI y)
3642 %{
3643 instruction_count(4);
3644 y : S4(read);
3645 q : S3(read);
3646 p : S3(read);
3647 DECODE : S0(4); // any decoder
3648 %}
3649
3650 // Conditional move reg-reg
3651 pipe_class pipe_cmov_reg( rRegI dst, rRegI src, rFlagsReg cr)
3652 %{
3653 single_instruction;
3654 dst : S4(write);
3655 src : S3(read);
3656 cr : S3(read);
3657 DECODE : S0; // any decoder
3658 %}
3659
3660 // Conditional move reg-mem
3661 pipe_class pipe_cmov_mem( rFlagsReg cr, rRegI dst, memory src)
3662 %{
3663 single_instruction;
3664 dst : S4(write);
3665 src : S3(read);
3666 cr : S3(read);
3667 DECODE : S0; // any decoder
3668 MEM : S3;
3669 %}
3670
3671 // Conditional move reg-reg long
3672 pipe_class pipe_cmov_reg_long( rFlagsReg cr, rRegL dst, rRegL src)
3673 %{
3674 single_instruction;
3675 dst : S4(write);
3676 src : S3(read);
3677 cr : S3(read);
3678 DECODE : S0(2); // any 2 decoders
3679 %}
3680
3681 // Float reg-reg operation
3682 pipe_class fpu_reg(regD dst)
3683 %{
3684 instruction_count(2);
3685 dst : S3(read);
3686 DECODE : S0(2); // any 2 decoders
3687 FPU : S3;
3688 %}
3689
3690 // Float reg-reg operation
3691 pipe_class fpu_reg_reg(regD dst, regD src)
3692 %{
3693 instruction_count(2);
3694 dst : S4(write);
3695 src : S3(read);
3696 DECODE : S0(2); // any 2 decoders
3697 FPU : S3;
3698 %}
3699
3700 // Float reg-reg operation
3701 pipe_class fpu_reg_reg_reg(regD dst, regD src1, regD src2)
3702 %{
3703 instruction_count(3);
3704 dst : S4(write);
3705 src1 : S3(read);
3706 src2 : S3(read);
3707 DECODE : S0(3); // any 3 decoders
3708 FPU : S3(2);
3709 %}
3710
3711 // Float reg-reg operation
3712 pipe_class fpu_reg_reg_reg_reg(regD dst, regD src1, regD src2, regD src3)
3713 %{
3714 instruction_count(4);
3715 dst : S4(write);
3716 src1 : S3(read);
3717 src2 : S3(read);
3718 src3 : S3(read);
3719 DECODE : S0(4); // any 3 decoders
3720 FPU : S3(2);
3721 %}
3722
3723 // Float reg-reg operation
3724 pipe_class fpu_reg_mem_reg_reg(regD dst, memory src1, regD src2, regD src3)
3725 %{
3726 instruction_count(4);
3727 dst : S4(write);
3728 src1 : S3(read);
3729 src2 : S3(read);
3730 src3 : S3(read);
3731 DECODE : S1(3); // any 3 decoders
3732 D0 : S0; // Big decoder only
3733 FPU : S3(2);
3734 MEM : S3;
3735 %}
3736
3737 // Float reg-mem operation
3738 pipe_class fpu_reg_mem(regD dst, memory mem)
3739 %{
3740 instruction_count(2);
3741 dst : S5(write);
3742 mem : S3(read);
3743 D0 : S0; // big decoder only
3744 DECODE : S1; // any decoder for FPU POP
3745 FPU : S4;
3746 MEM : S3; // any mem
3747 %}
3748
3749 // Float reg-mem operation
3750 pipe_class fpu_reg_reg_mem(regD dst, regD src1, memory mem)
3751 %{
3752 instruction_count(3);
3753 dst : S5(write);
3754 src1 : S3(read);
3755 mem : S3(read);
3756 D0 : S0; // big decoder only
3757 DECODE : S1(2); // any decoder for FPU POP
3758 FPU : S4;
3759 MEM : S3; // any mem
3760 %}
3761
3762 // Float mem-reg operation
3763 pipe_class fpu_mem_reg(memory mem, regD src)
3764 %{
3765 instruction_count(2);
3766 src : S5(read);
3767 mem : S3(read);
3768 DECODE : S0; // any decoder for FPU PUSH
3769 D0 : S1; // big decoder only
3770 FPU : S4;
3771 MEM : S3; // any mem
3772 %}
3773
3774 pipe_class fpu_mem_reg_reg(memory mem, regD src1, regD src2)
3775 %{
3776 instruction_count(3);
3777 src1 : S3(read);
3778 src2 : S3(read);
3779 mem : S3(read);
3780 DECODE : S0(2); // any decoder for FPU PUSH
3781 D0 : S1; // big decoder only
3782 FPU : S4;
3783 MEM : S3; // any mem
3784 %}
3785
3786 pipe_class fpu_mem_reg_mem(memory mem, regD src1, memory src2)
3787 %{
3788 instruction_count(3);
3789 src1 : S3(read);
3790 src2 : S3(read);
3791 mem : S4(read);
3792 DECODE : S0; // any decoder for FPU PUSH
3793 D0 : S0(2); // big decoder only
3794 FPU : S4;
3795 MEM : S3(2); // any mem
3796 %}
3797
3798 pipe_class fpu_mem_mem(memory dst, memory src1)
3799 %{
3800 instruction_count(2);
3801 src1 : S3(read);
3802 dst : S4(read);
3803 D0 : S0(2); // big decoder only
3804 MEM : S3(2); // any mem
3805 %}
3806
3807 pipe_class fpu_mem_mem_mem(memory dst, memory src1, memory src2)
3808 %{
3809 instruction_count(3);
3810 src1 : S3(read);
3811 src2 : S3(read);
3812 dst : S4(read);
3813 D0 : S0(3); // big decoder only
3814 FPU : S4;
3815 MEM : S3(3); // any mem
3816 %}
3817
3818 pipe_class fpu_mem_reg_con(memory mem, regD src1)
3819 %{
3820 instruction_count(3);
3821 src1 : S4(read);
3822 mem : S4(read);
3823 DECODE : S0; // any decoder for FPU PUSH
3824 D0 : S0(2); // big decoder only
3825 FPU : S4;
3826 MEM : S3(2); // any mem
3827 %}
3828
3829 // Float load constant
3830 pipe_class fpu_reg_con(regD dst)
3831 %{
3832 instruction_count(2);
3833 dst : S5(write);
3834 D0 : S0; // big decoder only for the load
3835 DECODE : S1; // any decoder for FPU POP
3836 FPU : S4;
3837 MEM : S3; // any mem
3838 %}
3839
3840 // Float load constant
3841 pipe_class fpu_reg_reg_con(regD dst, regD src)
3842 %{
3843 instruction_count(3);
3844 dst : S5(write);
3845 src : S3(read);
3846 D0 : S0; // big decoder only for the load
3847 DECODE : S1(2); // any decoder for FPU POP
3848 FPU : S4;
3849 MEM : S3; // any mem
3850 %}
3851
3852 // UnConditional branch
3853 pipe_class pipe_jmp(label labl)
3854 %{
3855 single_instruction;
3856 BR : S3;
3857 %}
3858
3859 // Conditional branch
3860 pipe_class pipe_jcc(cmpOp cmp, rFlagsReg cr, label labl)
3861 %{
3862 single_instruction;
3863 cr : S1(read);
3864 BR : S3;
3865 %}
3866
3867 // Allocation idiom
3868 pipe_class pipe_cmpxchg(rRegP dst, rRegP heap_ptr)
3869 %{
3870 instruction_count(1); force_serialization;
3871 fixed_latency(6);
3872 heap_ptr : S3(read);
3873 DECODE : S0(3);
3874 D0 : S2;
3875 MEM : S3;
3876 ALU : S3(2);
3877 dst : S5(write);
3878 BR : S5;
3879 %}
3880
3881 // Generic big/slow expanded idiom
3882 pipe_class pipe_slow()
3883 %{
3884 instruction_count(10); multiple_bundles; force_serialization;
3885 fixed_latency(100);
3886 D0 : S0(2);
3887 MEM : S3(2);
3888 %}
3889
3890 // The real do-nothing guy
3891 pipe_class empty()
3892 %{
3893 instruction_count(0);
3894 %}
3895
3896 // Define the class for the Nop node
3897 define
3898 %{
3899 MachNop = empty;
3900 %}
3901
3902 %}
3903
3904 //----------INSTRUCTIONS-------------------------------------------------------
3905 //
3906 // match -- States which machine-independent subtree may be replaced
3907 // by this instruction.
3908 // ins_cost -- The estimated cost of this instruction is used by instruction
3909 // selection to identify a minimum cost tree of machine
3910 // instructions that matches a tree of machine-independent
3911 // instructions.
3912 // format -- A string providing the disassembly for this instruction.
3913 // The value of an instruction's operand may be inserted
3914 // by referring to it with a '$' prefix.
3915 // opcode -- Three instruction opcodes may be provided. These are referred
3916 // to within an encode class as $primary, $secondary, and $tertiary
3917 // rrspectively. The primary opcode is commonly used to
3918 // indicate the type of machine instruction, while secondary
3919 // and tertiary are often used for prefix options or addressing
3920 // modes.
3921 // ins_encode -- A list of encode classes with parameters. The encode class
3922 // name must have been defined in an 'enc_class' specification
3923 // in the encode section of the architecture description.
3924
3925 // Dummy reg-to-reg vector moves. Removed during post-selection cleanup.
3926 // Load Float
3927 instruct MoveF2VL(vlRegF dst, regF src) %{
3928 match(Set dst src);
3929 format %{ "movss $dst,$src\t! load float (4 bytes)" %}
3930 ins_encode %{
3931 ShouldNotReachHere();
3932 %}
3933 ins_pipe( fpu_reg_reg );
3934 %}
3935
3936 // Load Float
3937 instruct MoveF2LEG(legRegF dst, regF src) %{
3938 match(Set dst src);
3939 format %{ "movss $dst,$src\t# if src != dst load float (4 bytes)" %}
3940 ins_encode %{
3941 ShouldNotReachHere();
3942 %}
3943 ins_pipe( fpu_reg_reg );
3944 %}
3945
3946 // Load Float
3947 instruct MoveVL2F(regF dst, vlRegF src) %{
3948 match(Set dst src);
3949 format %{ "movss $dst,$src\t! load float (4 bytes)" %}
3950 ins_encode %{
3951 ShouldNotReachHere();
3952 %}
3953 ins_pipe( fpu_reg_reg );
3954 %}
3955
3956 // Load Float
3957 instruct MoveLEG2F(regF dst, legRegF src) %{
3958 match(Set dst src);
3959 format %{ "movss $dst,$src\t# if src != dst load float (4 bytes)" %}
3960 ins_encode %{
3961 ShouldNotReachHere();
3962 %}
3963 ins_pipe( fpu_reg_reg );
3964 %}
3965
3966 // Load Double
3967 instruct MoveD2VL(vlRegD dst, regD src) %{
3968 match(Set dst src);
3969 format %{ "movsd $dst,$src\t! load double (8 bytes)" %}
3970 ins_encode %{
3971 ShouldNotReachHere();
3972 %}
3973 ins_pipe( fpu_reg_reg );
3974 %}
3975
3976 // Load Double
3977 instruct MoveD2LEG(legRegD dst, regD src) %{
3978 match(Set dst src);
3979 format %{ "movsd $dst,$src\t# if src != dst load double (8 bytes)" %}
3980 ins_encode %{
3981 ShouldNotReachHere();
3982 %}
3983 ins_pipe( fpu_reg_reg );
3984 %}
3985
3986 // Load Double
3987 instruct MoveVL2D(regD dst, vlRegD src) %{
3988 match(Set dst src);
3989 format %{ "movsd $dst,$src\t! load double (8 bytes)" %}
3990 ins_encode %{
3991 ShouldNotReachHere();
3992 %}
3993 ins_pipe( fpu_reg_reg );
3994 %}
3995
3996 // Load Double
3997 instruct MoveLEG2D(regD dst, legRegD src) %{
3998 match(Set dst src);
3999 format %{ "movsd $dst,$src\t# if src != dst load double (8 bytes)" %}
4000 ins_encode %{
4001 ShouldNotReachHere();
4002 %}
4003 ins_pipe( fpu_reg_reg );
4004 %}
4005
4006 //----------Load/Store/Move Instructions---------------------------------------
4007 //----------Load Instructions--------------------------------------------------
4008
4009 // Load Byte (8 bit signed)
4010 instruct loadB(rRegI dst, memory mem)
4011 %{
4012 match(Set dst (LoadB mem));
4013
4014 ins_cost(125);
4015 format %{ "movsbl $dst, $mem\t# byte" %}
4016
4017 ins_encode %{
4018 __ movsbl($dst$$Register, $mem$$Address);
4019 %}
4020
4021 ins_pipe(ialu_reg_mem);
4022 %}
4023
4024 // Load Byte (8 bit signed) into Long Register
4025 instruct loadB2L(rRegL dst, memory mem)
4026 %{
4027 match(Set dst (ConvI2L (LoadB mem)));
4028
4029 ins_cost(125);
4030 format %{ "movsbq $dst, $mem\t# byte -> long" %}
4031
4032 ins_encode %{
4033 __ movsbq($dst$$Register, $mem$$Address);
4034 %}
4035
4036 ins_pipe(ialu_reg_mem);
4037 %}
4038
4039 // Load Unsigned Byte (8 bit UNsigned)
4040 instruct loadUB(rRegI dst, memory mem)
4041 %{
4042 match(Set dst (LoadUB mem));
4043
4044 ins_cost(125);
4045 format %{ "movzbl $dst, $mem\t# ubyte" %}
4046
4047 ins_encode %{
4048 __ movzbl($dst$$Register, $mem$$Address);
4049 %}
4050
4051 ins_pipe(ialu_reg_mem);
4052 %}
4053
4054 // Load Unsigned Byte (8 bit UNsigned) into Long Register
4055 instruct loadUB2L(rRegL dst, memory mem)
4056 %{
4057 match(Set dst (ConvI2L (LoadUB mem)));
4058
4059 ins_cost(125);
4060 format %{ "movzbq $dst, $mem\t# ubyte -> long" %}
4061
4062 ins_encode %{
4063 __ movzbq($dst$$Register, $mem$$Address);
4064 %}
4065
4066 ins_pipe(ialu_reg_mem);
4067 %}
4068
4069 // Load Unsigned Byte (8 bit UNsigned) with 32-bit mask into Long Register
4070 instruct loadUB2L_immI(rRegL dst, memory mem, immI mask, rFlagsReg cr) %{
4071 match(Set dst (ConvI2L (AndI (LoadUB mem) mask)));
4072 effect(KILL cr);
4073
4074 format %{ "movzbq $dst, $mem\t# ubyte & 32-bit mask -> long\n\t"
4075 "andl $dst, right_n_bits($mask, 8)" %}
4076 ins_encode %{
4077 Register Rdst = $dst$$Register;
4078 __ movzbq(Rdst, $mem$$Address);
4079 __ andl(Rdst, $mask$$constant & right_n_bits(8));
4080 %}
4081 ins_pipe(ialu_reg_mem);
4082 %}
4083
4084 // Load Short (16 bit signed)
4085 instruct loadS(rRegI dst, memory mem)
4086 %{
4087 match(Set dst (LoadS mem));
4088
4089 ins_cost(125);
4090 format %{ "movswl $dst, $mem\t# short" %}
4091
4092 ins_encode %{
4093 __ movswl($dst$$Register, $mem$$Address);
4094 %}
4095
4096 ins_pipe(ialu_reg_mem);
4097 %}
4098
4099 // Load Short (16 bit signed) to Byte (8 bit signed)
4100 instruct loadS2B(rRegI dst, memory mem, immI_24 twentyfour) %{
4101 match(Set dst (RShiftI (LShiftI (LoadS mem) twentyfour) twentyfour));
4102
4103 ins_cost(125);
4104 format %{ "movsbl $dst, $mem\t# short -> byte" %}
4105 ins_encode %{
4106 __ movsbl($dst$$Register, $mem$$Address);
4107 %}
4108 ins_pipe(ialu_reg_mem);
4109 %}
4110
4111 // Load Short (16 bit signed) into Long Register
4112 instruct loadS2L(rRegL dst, memory mem)
4113 %{
4114 match(Set dst (ConvI2L (LoadS mem)));
4115
4116 ins_cost(125);
4117 format %{ "movswq $dst, $mem\t# short -> long" %}
4118
4119 ins_encode %{
4120 __ movswq($dst$$Register, $mem$$Address);
4121 %}
4122
4123 ins_pipe(ialu_reg_mem);
4124 %}
4125
4126 // Load Unsigned Short/Char (16 bit UNsigned)
4127 instruct loadUS(rRegI dst, memory mem)
4128 %{
4129 match(Set dst (LoadUS mem));
4130
4131 ins_cost(125);
4132 format %{ "movzwl $dst, $mem\t# ushort/char" %}
4133
4134 ins_encode %{
4135 __ movzwl($dst$$Register, $mem$$Address);
4136 %}
4137
4138 ins_pipe(ialu_reg_mem);
4139 %}
4140
4141 // Load Unsigned Short/Char (16 bit UNsigned) to Byte (8 bit signed)
4142 instruct loadUS2B(rRegI dst, memory mem, immI_24 twentyfour) %{
4143 match(Set dst (RShiftI (LShiftI (LoadUS mem) twentyfour) twentyfour));
4144
4145 ins_cost(125);
4146 format %{ "movsbl $dst, $mem\t# ushort -> byte" %}
4147 ins_encode %{
4148 __ movsbl($dst$$Register, $mem$$Address);
4149 %}
4150 ins_pipe(ialu_reg_mem);
4151 %}
4152
4153 // Load Unsigned Short/Char (16 bit UNsigned) into Long Register
4154 instruct loadUS2L(rRegL dst, memory mem)
4155 %{
4156 match(Set dst (ConvI2L (LoadUS mem)));
4157
4158 ins_cost(125);
4159 format %{ "movzwq $dst, $mem\t# ushort/char -> long" %}
4160
4161 ins_encode %{
4162 __ movzwq($dst$$Register, $mem$$Address);
4163 %}
4164
4165 ins_pipe(ialu_reg_mem);
4166 %}
4167
4168 // Load Unsigned Short/Char (16 bit UNsigned) with mask 0xFF into Long Register
4169 instruct loadUS2L_immI_255(rRegL dst, memory mem, immI_255 mask) %{
4170 match(Set dst (ConvI2L (AndI (LoadUS mem) mask)));
4171
4172 format %{ "movzbq $dst, $mem\t# ushort/char & 0xFF -> long" %}
4173 ins_encode %{
4174 __ movzbq($dst$$Register, $mem$$Address);
4175 %}
4176 ins_pipe(ialu_reg_mem);
4177 %}
4178
4179 // Load Unsigned Short/Char (16 bit UNsigned) with 32-bit mask into Long Register
4180 instruct loadUS2L_immI(rRegL dst, memory mem, immI mask, rFlagsReg cr) %{
4181 match(Set dst (ConvI2L (AndI (LoadUS mem) mask)));
4182 effect(KILL cr);
4183
4184 format %{ "movzwq $dst, $mem\t# ushort/char & 32-bit mask -> long\n\t"
4185 "andl $dst, right_n_bits($mask, 16)" %}
4186 ins_encode %{
4187 Register Rdst = $dst$$Register;
4188 __ movzwq(Rdst, $mem$$Address);
4189 __ andl(Rdst, $mask$$constant & right_n_bits(16));
4190 %}
4191 ins_pipe(ialu_reg_mem);
4192 %}
4193
4194 // Load Integer
4195 instruct loadI(rRegI dst, memory mem)
4196 %{
4197 match(Set dst (LoadI mem));
4198
4199 ins_cost(125);
4200 format %{ "movl $dst, $mem\t# int" %}
4201
4202 ins_encode %{
4203 __ movl($dst$$Register, $mem$$Address);
4204 %}
4205
4206 ins_pipe(ialu_reg_mem);
4207 %}
4208
4209 // Load Integer (32 bit signed) to Byte (8 bit signed)
4210 instruct loadI2B(rRegI dst, memory mem, immI_24 twentyfour) %{
4211 match(Set dst (RShiftI (LShiftI (LoadI mem) twentyfour) twentyfour));
4212
4213 ins_cost(125);
4214 format %{ "movsbl $dst, $mem\t# int -> byte" %}
4215 ins_encode %{
4216 __ movsbl($dst$$Register, $mem$$Address);
4217 %}
4218 ins_pipe(ialu_reg_mem);
4219 %}
4220
4221 // Load Integer (32 bit signed) to Unsigned Byte (8 bit UNsigned)
4222 instruct loadI2UB(rRegI dst, memory mem, immI_255 mask) %{
4223 match(Set dst (AndI (LoadI mem) mask));
4224
4225 ins_cost(125);
4226 format %{ "movzbl $dst, $mem\t# int -> ubyte" %}
4227 ins_encode %{
4228 __ movzbl($dst$$Register, $mem$$Address);
4229 %}
4230 ins_pipe(ialu_reg_mem);
4231 %}
4232
4233 // Load Integer (32 bit signed) to Short (16 bit signed)
4234 instruct loadI2S(rRegI dst, memory mem, immI_16 sixteen) %{
4235 match(Set dst (RShiftI (LShiftI (LoadI mem) sixteen) sixteen));
4236
4237 ins_cost(125);
4238 format %{ "movswl $dst, $mem\t# int -> short" %}
4239 ins_encode %{
4240 __ movswl($dst$$Register, $mem$$Address);
4241 %}
4242 ins_pipe(ialu_reg_mem);
4243 %}
4244
4245 // Load Integer (32 bit signed) to Unsigned Short/Char (16 bit UNsigned)
4246 instruct loadI2US(rRegI dst, memory mem, immI_65535 mask) %{
4247 match(Set dst (AndI (LoadI mem) mask));
4248
4249 ins_cost(125);
4250 format %{ "movzwl $dst, $mem\t# int -> ushort/char" %}
4251 ins_encode %{
4252 __ movzwl($dst$$Register, $mem$$Address);
4253 %}
4254 ins_pipe(ialu_reg_mem);
4255 %}
4256
4257 // Load Integer into Long Register
4258 instruct loadI2L(rRegL dst, memory mem)
4259 %{
4260 match(Set dst (ConvI2L (LoadI mem)));
4261
4262 ins_cost(125);
4263 format %{ "movslq $dst, $mem\t# int -> long" %}
4264
4265 ins_encode %{
4266 __ movslq($dst$$Register, $mem$$Address);
4267 %}
4268
4269 ins_pipe(ialu_reg_mem);
4270 %}
4271
4272 // Load Integer with mask 0xFF into Long Register
4273 instruct loadI2L_immI_255(rRegL dst, memory mem, immI_255 mask) %{
4274 match(Set dst (ConvI2L (AndI (LoadI mem) mask)));
4275
4276 format %{ "movzbq $dst, $mem\t# int & 0xFF -> long" %}
4277 ins_encode %{
4278 __ movzbq($dst$$Register, $mem$$Address);
4279 %}
4280 ins_pipe(ialu_reg_mem);
4281 %}
4282
4283 // Load Integer with mask 0xFFFF into Long Register
4284 instruct loadI2L_immI_65535(rRegL dst, memory mem, immI_65535 mask) %{
4285 match(Set dst (ConvI2L (AndI (LoadI mem) mask)));
4286
4287 format %{ "movzwq $dst, $mem\t# int & 0xFFFF -> long" %}
4288 ins_encode %{
4289 __ movzwq($dst$$Register, $mem$$Address);
4290 %}
4291 ins_pipe(ialu_reg_mem);
4292 %}
4293
4294 // Load Integer with a 31-bit mask into Long Register
4295 instruct loadI2L_immU31(rRegL dst, memory mem, immU31 mask, rFlagsReg cr) %{
4296 match(Set dst (ConvI2L (AndI (LoadI mem) mask)));
4297 effect(KILL cr);
4298
4299 format %{ "movl $dst, $mem\t# int & 31-bit mask -> long\n\t"
4300 "andl $dst, $mask" %}
4301 ins_encode %{
4302 Register Rdst = $dst$$Register;
4303 __ movl(Rdst, $mem$$Address);
4304 __ andl(Rdst, $mask$$constant);
4305 %}
4306 ins_pipe(ialu_reg_mem);
4307 %}
4308
4309 // Load Unsigned Integer into Long Register
4310 instruct loadUI2L(rRegL dst, memory mem, immL_32bits mask)
4311 %{
4312 match(Set dst (AndL (ConvI2L (LoadI mem)) mask));
4313
4314 ins_cost(125);
4315 format %{ "movl $dst, $mem\t# uint -> long" %}
4316
4317 ins_encode %{
4318 __ movl($dst$$Register, $mem$$Address);
4319 %}
4320
4321 ins_pipe(ialu_reg_mem);
4322 %}
4323
4324 // Load Long
4325 instruct loadL(rRegL dst, memory mem)
4326 %{
4327 match(Set dst (LoadL mem));
4328
4329 ins_cost(125);
4330 format %{ "movq $dst, $mem\t# long" %}
4331
4332 ins_encode %{
4333 __ movq($dst$$Register, $mem$$Address);
4334 %}
4335
4336 ins_pipe(ialu_reg_mem); // XXX
4337 %}
4338
4339 // Load Range
4340 instruct loadRange(rRegI dst, memory mem)
4341 %{
4342 match(Set dst (LoadRange mem));
4343
4344 ins_cost(125); // XXX
4345 format %{ "movl $dst, $mem\t# range" %}
4346 ins_encode %{
4347 __ movl($dst$$Register, $mem$$Address);
4348 %}
4349 ins_pipe(ialu_reg_mem);
4350 %}
4351
4352 // Load Pointer
4353 instruct loadP(rRegP dst, memory mem)
4354 %{
4355 match(Set dst (LoadP mem));
4356 predicate(n->as_Load()->barrier_data() == 0);
4357
4358 ins_cost(125); // XXX
4359 format %{ "movq $dst, $mem\t# ptr" %}
4360 ins_encode %{
4361 __ movq($dst$$Register, $mem$$Address);
4362 %}
4363 ins_pipe(ialu_reg_mem); // XXX
4364 %}
4365
4366 // Load Compressed Pointer
4367 instruct loadN(rRegN dst, memory mem)
4368 %{
4369 predicate(n->as_Load()->barrier_data() == 0);
4370 match(Set dst (LoadN mem));
4371
4372 ins_cost(125); // XXX
4373 format %{ "movl $dst, $mem\t# compressed ptr" %}
4374 ins_encode %{
4375 __ movl($dst$$Register, $mem$$Address);
4376 %}
4377 ins_pipe(ialu_reg_mem); // XXX
4378 %}
4379
4380
4381 // Load Klass Pointer
4382 instruct loadKlass(rRegP dst, memory mem)
4383 %{
4384 match(Set dst (LoadKlass mem));
4385
4386 ins_cost(125); // XXX
4387 format %{ "movq $dst, $mem\t# class" %}
4388 ins_encode %{
4389 __ movq($dst$$Register, $mem$$Address);
4390 %}
4391 ins_pipe(ialu_reg_mem); // XXX
4392 %}
4393
4394 // Load narrow Klass Pointer
4395 instruct loadNKlass(rRegN dst, memory mem)
4396 %{
4397 predicate(!UseCompactObjectHeaders);
4398 match(Set dst (LoadNKlass mem));
4399
4400 ins_cost(125); // XXX
4401 format %{ "movl $dst, $mem\t# compressed klass ptr" %}
4402 ins_encode %{
4403 __ movl($dst$$Register, $mem$$Address);
4404 %}
4405 ins_pipe(ialu_reg_mem); // XXX
4406 %}
4407
4408 instruct loadNKlassCompactHeaders(rRegN dst, memory mem, rFlagsReg cr)
4409 %{
4410 predicate(UseCompactObjectHeaders);
4411 match(Set dst (LoadNKlass mem));
4412 effect(KILL cr);
4413 ins_cost(125);
4414 format %{
4415 "movl $dst, $mem\t# compressed klass ptr, shifted\n\t"
4416 "shrl $dst, markWord::klass_shift_at_offset"
4417 %}
4418 ins_encode %{
4419 if (UseAPX) {
4420 __ eshrl($dst$$Register, $mem$$Address, markWord::klass_shift_at_offset, false);
4421 }
4422 else {
4423 __ movl($dst$$Register, $mem$$Address);
4424 __ shrl($dst$$Register, markWord::klass_shift_at_offset);
4425 }
4426 %}
4427 ins_pipe(ialu_reg_mem);
4428 %}
4429
4430 // Load Float
4431 instruct loadF(regF dst, memory mem)
4432 %{
4433 match(Set dst (LoadF mem));
4434
4435 ins_cost(145); // XXX
4436 format %{ "movss $dst, $mem\t# float" %}
4437 ins_encode %{
4438 __ movflt($dst$$XMMRegister, $mem$$Address);
4439 %}
4440 ins_pipe(pipe_slow); // XXX
4441 %}
4442
4443 // Load Double
4444 instruct loadD_partial(regD dst, memory mem)
4445 %{
4446 predicate(!UseXmmLoadAndClearUpper);
4447 match(Set dst (LoadD mem));
4448
4449 ins_cost(145); // XXX
4450 format %{ "movlpd $dst, $mem\t# double" %}
4451 ins_encode %{
4452 __ movdbl($dst$$XMMRegister, $mem$$Address);
4453 %}
4454 ins_pipe(pipe_slow); // XXX
4455 %}
4456
4457 instruct loadD(regD dst, memory mem)
4458 %{
4459 predicate(UseXmmLoadAndClearUpper);
4460 match(Set dst (LoadD mem));
4461
4462 ins_cost(145); // XXX
4463 format %{ "movsd $dst, $mem\t# double" %}
4464 ins_encode %{
4465 __ movdbl($dst$$XMMRegister, $mem$$Address);
4466 %}
4467 ins_pipe(pipe_slow); // XXX
4468 %}
4469
4470 // max = java.lang.Math.max(float a, float b)
4471 instruct maxF_avx10_reg(regF dst, regF a, regF b) %{
4472 predicate(VM_Version::supports_avx10_2());
4473 match(Set dst (MaxF a b));
4474 format %{ "maxF $dst, $a, $b" %}
4475 ins_encode %{
4476 __ eminmaxss($dst$$XMMRegister, $a$$XMMRegister, $b$$XMMRegister, AVX10_MINMAX_MAX_COMPARE_SIGN);
4477 %}
4478 ins_pipe( pipe_slow );
4479 %}
4480
4481 // max = java.lang.Math.max(float a, float b)
4482 instruct maxF_reg(legRegF dst, legRegF a, legRegF b, legRegF tmp, legRegF atmp, legRegF btmp) %{
4483 predicate(!VM_Version::supports_avx10_2() && UseAVX > 0 && !VLoopReductions::is_reduction(n));
4484 match(Set dst (MaxF a b));
4485 effect(USE a, USE b, TEMP tmp, TEMP atmp, TEMP btmp);
4486 format %{ "maxF $dst, $a, $b \t! using $tmp, $atmp and $btmp as TEMP" %}
4487 ins_encode %{
4488 __ vminmax_fp(Op_MaxV, T_FLOAT, $dst$$XMMRegister, $a$$XMMRegister, $b$$XMMRegister, $tmp$$XMMRegister, $atmp$$XMMRegister, $btmp$$XMMRegister, Assembler::AVX_128bit);
4489 %}
4490 ins_pipe( pipe_slow );
4491 %}
4492
4493 instruct maxF_reduction_reg(legRegF dst, legRegF a, legRegF b, legRegF xtmp, rRegI rtmp, rFlagsReg cr) %{
4494 predicate(!VM_Version::supports_avx10_2() && UseAVX > 0 && VLoopReductions::is_reduction(n));
4495 match(Set dst (MaxF a b));
4496 effect(USE a, USE b, TEMP xtmp, TEMP rtmp, KILL cr);
4497
4498 format %{ "maxF_reduction $dst, $a, $b \t!using $xtmp and $rtmp as TEMP" %}
4499 ins_encode %{
4500 emit_fp_min_max(masm, $dst$$XMMRegister, $a$$XMMRegister, $b$$XMMRegister, $xtmp$$XMMRegister, $rtmp$$Register,
4501 false /*min*/, true /*single*/);
4502 %}
4503 ins_pipe( pipe_slow );
4504 %}
4505
4506 // max = java.lang.Math.max(double a, double b)
4507 instruct maxD_avx10_reg(regD dst, regD a, regD b) %{
4508 predicate(VM_Version::supports_avx10_2());
4509 match(Set dst (MaxD a b));
4510 format %{ "maxD $dst, $a, $b" %}
4511 ins_encode %{
4512 __ eminmaxsd($dst$$XMMRegister, $a$$XMMRegister, $b$$XMMRegister, AVX10_MINMAX_MAX_COMPARE_SIGN);
4513 %}
4514 ins_pipe( pipe_slow );
4515 %}
4516
4517 // max = java.lang.Math.max(double a, double b)
4518 instruct maxD_reg(legRegD dst, legRegD a, legRegD b, legRegD tmp, legRegD atmp, legRegD btmp) %{
4519 predicate(!VM_Version::supports_avx10_2() && UseAVX > 0 && !VLoopReductions::is_reduction(n));
4520 match(Set dst (MaxD a b));
4521 effect(USE a, USE b, TEMP atmp, TEMP btmp, TEMP tmp);
4522 format %{ "maxD $dst, $a, $b \t! using $tmp, $atmp and $btmp as TEMP" %}
4523 ins_encode %{
4524 __ vminmax_fp(Op_MaxV, T_DOUBLE, $dst$$XMMRegister, $a$$XMMRegister, $b$$XMMRegister, $tmp$$XMMRegister, $atmp$$XMMRegister, $btmp$$XMMRegister, Assembler::AVX_128bit);
4525 %}
4526 ins_pipe( pipe_slow );
4527 %}
4528
4529 instruct maxD_reduction_reg(legRegD dst, legRegD a, legRegD b, legRegD xtmp, rRegL rtmp, rFlagsReg cr) %{
4530 predicate(!VM_Version::supports_avx10_2() && UseAVX > 0 && VLoopReductions::is_reduction(n));
4531 match(Set dst (MaxD a b));
4532 effect(USE a, USE b, TEMP xtmp, TEMP rtmp, KILL cr);
4533
4534 format %{ "maxD_reduction $dst, $a, $b \t! using $xtmp and $rtmp as TEMP" %}
4535 ins_encode %{
4536 emit_fp_min_max(masm, $dst$$XMMRegister, $a$$XMMRegister, $b$$XMMRegister, $xtmp$$XMMRegister, $rtmp$$Register,
4537 false /*min*/, false /*single*/);
4538 %}
4539 ins_pipe( pipe_slow );
4540 %}
4541
4542 // max = java.lang.Math.min(float a, float b)
4543 instruct minF_avx10_reg(regF dst, regF a, regF b) %{
4544 predicate(VM_Version::supports_avx10_2());
4545 match(Set dst (MinF a b));
4546 format %{ "minF $dst, $a, $b" %}
4547 ins_encode %{
4548 __ eminmaxss($dst$$XMMRegister, $a$$XMMRegister, $b$$XMMRegister, AVX10_MINMAX_MIN_COMPARE_SIGN);
4549 %}
4550 ins_pipe( pipe_slow );
4551 %}
4552
4553 // min = java.lang.Math.min(float a, float b)
4554 instruct minF_reg(legRegF dst, legRegF a, legRegF b, legRegF tmp, legRegF atmp, legRegF btmp) %{
4555 predicate(!VM_Version::supports_avx10_2() && UseAVX > 0 && !VLoopReductions::is_reduction(n));
4556 match(Set dst (MinF a b));
4557 effect(USE a, USE b, TEMP tmp, TEMP atmp, TEMP btmp);
4558 format %{ "minF $dst, $a, $b \t! using $tmp, $atmp and $btmp as TEMP" %}
4559 ins_encode %{
4560 __ vminmax_fp(Op_MinV, T_FLOAT, $dst$$XMMRegister, $a$$XMMRegister, $b$$XMMRegister, $tmp$$XMMRegister, $atmp$$XMMRegister, $btmp$$XMMRegister, Assembler::AVX_128bit);
4561 %}
4562 ins_pipe( pipe_slow );
4563 %}
4564
4565 instruct minF_reduction_reg(legRegF dst, legRegF a, legRegF b, legRegF xtmp, rRegI rtmp, rFlagsReg cr) %{
4566 predicate(!VM_Version::supports_avx10_2() && UseAVX > 0 && VLoopReductions::is_reduction(n));
4567 match(Set dst (MinF a b));
4568 effect(USE a, USE b, TEMP xtmp, TEMP rtmp, KILL cr);
4569
4570 format %{ "minF_reduction $dst, $a, $b \t! using $xtmp and $rtmp as TEMP" %}
4571 ins_encode %{
4572 emit_fp_min_max(masm, $dst$$XMMRegister, $a$$XMMRegister, $b$$XMMRegister, $xtmp$$XMMRegister, $rtmp$$Register,
4573 true /*min*/, true /*single*/);
4574 %}
4575 ins_pipe( pipe_slow );
4576 %}
4577
4578 // max = java.lang.Math.min(double a, double b)
4579 instruct minD_avx10_reg(regD dst, regD a, regD b) %{
4580 predicate(VM_Version::supports_avx10_2());
4581 match(Set dst (MinD a b));
4582 format %{ "minD $dst, $a, $b" %}
4583 ins_encode %{
4584 __ eminmaxsd($dst$$XMMRegister, $a$$XMMRegister, $b$$XMMRegister, AVX10_MINMAX_MIN_COMPARE_SIGN);
4585 %}
4586 ins_pipe( pipe_slow );
4587 %}
4588
4589 // min = java.lang.Math.min(double a, double b)
4590 instruct minD_reg(legRegD dst, legRegD a, legRegD b, legRegD tmp, legRegD atmp, legRegD btmp) %{
4591 predicate(!VM_Version::supports_avx10_2() && UseAVX > 0 && !VLoopReductions::is_reduction(n));
4592 match(Set dst (MinD a b));
4593 effect(USE a, USE b, TEMP tmp, TEMP atmp, TEMP btmp);
4594 format %{ "minD $dst, $a, $b \t! using $tmp, $atmp and $btmp as TEMP" %}
4595 ins_encode %{
4596 __ vminmax_fp(Op_MinV, T_DOUBLE, $dst$$XMMRegister, $a$$XMMRegister, $b$$XMMRegister, $tmp$$XMMRegister, $atmp$$XMMRegister, $btmp$$XMMRegister, Assembler::AVX_128bit);
4597 %}
4598 ins_pipe( pipe_slow );
4599 %}
4600
4601 instruct minD_reduction_reg(legRegD dst, legRegD a, legRegD b, legRegD xtmp, rRegL rtmp, rFlagsReg cr) %{
4602 predicate(!VM_Version::supports_avx10_2() && UseAVX > 0 && VLoopReductions::is_reduction(n));
4603 match(Set dst (MinD a b));
4604 effect(USE a, USE b, TEMP xtmp, TEMP rtmp, KILL cr);
4605
4606 format %{ "maxD_reduction $dst, $a, $b \t! using $xtmp and $rtmp as TEMP" %}
4607 ins_encode %{
4608 emit_fp_min_max(masm, $dst$$XMMRegister, $a$$XMMRegister, $b$$XMMRegister, $xtmp$$XMMRegister, $rtmp$$Register,
4609 true /*min*/, false /*single*/);
4610 %}
4611 ins_pipe( pipe_slow );
4612 %}
4613
4614 // Load Effective Address
4615 instruct leaP8(rRegP dst, indOffset8 mem)
4616 %{
4617 match(Set dst mem);
4618
4619 ins_cost(110); // XXX
4620 format %{ "leaq $dst, $mem\t# ptr 8" %}
4621 ins_encode %{
4622 __ leaq($dst$$Register, $mem$$Address);
4623 %}
4624 ins_pipe(ialu_reg_reg_fat);
4625 %}
4626
4627 instruct leaP32(rRegP dst, indOffset32 mem)
4628 %{
4629 match(Set dst mem);
4630
4631 ins_cost(110);
4632 format %{ "leaq $dst, $mem\t# ptr 32" %}
4633 ins_encode %{
4634 __ leaq($dst$$Register, $mem$$Address);
4635 %}
4636 ins_pipe(ialu_reg_reg_fat);
4637 %}
4638
4639 instruct leaPIdxOff(rRegP dst, indIndexOffset mem)
4640 %{
4641 match(Set dst mem);
4642
4643 ins_cost(110);
4644 format %{ "leaq $dst, $mem\t# ptr idxoff" %}
4645 ins_encode %{
4646 __ leaq($dst$$Register, $mem$$Address);
4647 %}
4648 ins_pipe(ialu_reg_reg_fat);
4649 %}
4650
4651 instruct leaPIdxScale(rRegP dst, indIndexScale mem)
4652 %{
4653 match(Set dst mem);
4654
4655 ins_cost(110);
4656 format %{ "leaq $dst, $mem\t# ptr idxscale" %}
4657 ins_encode %{
4658 __ leaq($dst$$Register, $mem$$Address);
4659 %}
4660 ins_pipe(ialu_reg_reg_fat);
4661 %}
4662
4663 instruct leaPPosIdxScale(rRegP dst, indPosIndexScale mem)
4664 %{
4665 match(Set dst mem);
4666
4667 ins_cost(110);
4668 format %{ "leaq $dst, $mem\t# ptr idxscale" %}
4669 ins_encode %{
4670 __ leaq($dst$$Register, $mem$$Address);
4671 %}
4672 ins_pipe(ialu_reg_reg_fat);
4673 %}
4674
4675 instruct leaPIdxScaleOff(rRegP dst, indIndexScaleOffset mem)
4676 %{
4677 match(Set dst mem);
4678
4679 ins_cost(110);
4680 format %{ "leaq $dst, $mem\t# ptr idxscaleoff" %}
4681 ins_encode %{
4682 __ leaq($dst$$Register, $mem$$Address);
4683 %}
4684 ins_pipe(ialu_reg_reg_fat);
4685 %}
4686
4687 instruct leaPPosIdxOff(rRegP dst, indPosIndexOffset mem)
4688 %{
4689 match(Set dst mem);
4690
4691 ins_cost(110);
4692 format %{ "leaq $dst, $mem\t# ptr posidxoff" %}
4693 ins_encode %{
4694 __ leaq($dst$$Register, $mem$$Address);
4695 %}
4696 ins_pipe(ialu_reg_reg_fat);
4697 %}
4698
4699 instruct leaPPosIdxScaleOff(rRegP dst, indPosIndexScaleOffset mem)
4700 %{
4701 match(Set dst mem);
4702
4703 ins_cost(110);
4704 format %{ "leaq $dst, $mem\t# ptr posidxscaleoff" %}
4705 ins_encode %{
4706 __ leaq($dst$$Register, $mem$$Address);
4707 %}
4708 ins_pipe(ialu_reg_reg_fat);
4709 %}
4710
4711 // Load Effective Address which uses Narrow (32-bits) oop
4712 instruct leaPCompressedOopOffset(rRegP dst, indCompressedOopOffset mem)
4713 %{
4714 predicate(UseCompressedOops && (CompressedOops::shift() != 0));
4715 match(Set dst mem);
4716
4717 ins_cost(110);
4718 format %{ "leaq $dst, $mem\t# ptr compressedoopoff32" %}
4719 ins_encode %{
4720 __ leaq($dst$$Register, $mem$$Address);
4721 %}
4722 ins_pipe(ialu_reg_reg_fat);
4723 %}
4724
4725 instruct leaP8Narrow(rRegP dst, indOffset8Narrow mem)
4726 %{
4727 predicate(CompressedOops::shift() == 0);
4728 match(Set dst mem);
4729
4730 ins_cost(110); // XXX
4731 format %{ "leaq $dst, $mem\t# ptr off8narrow" %}
4732 ins_encode %{
4733 __ leaq($dst$$Register, $mem$$Address);
4734 %}
4735 ins_pipe(ialu_reg_reg_fat);
4736 %}
4737
4738 instruct leaP32Narrow(rRegP dst, indOffset32Narrow mem)
4739 %{
4740 predicate(CompressedOops::shift() == 0);
4741 match(Set dst mem);
4742
4743 ins_cost(110);
4744 format %{ "leaq $dst, $mem\t# ptr off32narrow" %}
4745 ins_encode %{
4746 __ leaq($dst$$Register, $mem$$Address);
4747 %}
4748 ins_pipe(ialu_reg_reg_fat);
4749 %}
4750
4751 instruct leaPIdxOffNarrow(rRegP dst, indIndexOffsetNarrow mem)
4752 %{
4753 predicate(CompressedOops::shift() == 0);
4754 match(Set dst mem);
4755
4756 ins_cost(110);
4757 format %{ "leaq $dst, $mem\t# ptr idxoffnarrow" %}
4758 ins_encode %{
4759 __ leaq($dst$$Register, $mem$$Address);
4760 %}
4761 ins_pipe(ialu_reg_reg_fat);
4762 %}
4763
4764 instruct leaPIdxScaleNarrow(rRegP dst, indIndexScaleNarrow mem)
4765 %{
4766 predicate(CompressedOops::shift() == 0);
4767 match(Set dst mem);
4768
4769 ins_cost(110);
4770 format %{ "leaq $dst, $mem\t# ptr idxscalenarrow" %}
4771 ins_encode %{
4772 __ leaq($dst$$Register, $mem$$Address);
4773 %}
4774 ins_pipe(ialu_reg_reg_fat);
4775 %}
4776
4777 instruct leaPIdxScaleOffNarrow(rRegP dst, indIndexScaleOffsetNarrow mem)
4778 %{
4779 predicate(CompressedOops::shift() == 0);
4780 match(Set dst mem);
4781
4782 ins_cost(110);
4783 format %{ "leaq $dst, $mem\t# ptr idxscaleoffnarrow" %}
4784 ins_encode %{
4785 __ leaq($dst$$Register, $mem$$Address);
4786 %}
4787 ins_pipe(ialu_reg_reg_fat);
4788 %}
4789
4790 instruct leaPPosIdxOffNarrow(rRegP dst, indPosIndexOffsetNarrow mem)
4791 %{
4792 predicate(CompressedOops::shift() == 0);
4793 match(Set dst mem);
4794
4795 ins_cost(110);
4796 format %{ "leaq $dst, $mem\t# ptr posidxoffnarrow" %}
4797 ins_encode %{
4798 __ leaq($dst$$Register, $mem$$Address);
4799 %}
4800 ins_pipe(ialu_reg_reg_fat);
4801 %}
4802
4803 instruct leaPPosIdxScaleOffNarrow(rRegP dst, indPosIndexScaleOffsetNarrow mem)
4804 %{
4805 predicate(CompressedOops::shift() == 0);
4806 match(Set dst mem);
4807
4808 ins_cost(110);
4809 format %{ "leaq $dst, $mem\t# ptr posidxscaleoffnarrow" %}
4810 ins_encode %{
4811 __ leaq($dst$$Register, $mem$$Address);
4812 %}
4813 ins_pipe(ialu_reg_reg_fat);
4814 %}
4815
4816 instruct loadConI(rRegI dst, immI src)
4817 %{
4818 match(Set dst src);
4819
4820 format %{ "movl $dst, $src\t# int" %}
4821 ins_encode %{
4822 __ movl($dst$$Register, $src$$constant);
4823 %}
4824 ins_pipe(ialu_reg_fat); // XXX
4825 %}
4826
4827 instruct loadConI0(rRegI dst, immI_0 src, rFlagsReg cr)
4828 %{
4829 match(Set dst src);
4830 effect(KILL cr);
4831
4832 ins_cost(50);
4833 format %{ "xorl $dst, $dst\t# int" %}
4834 ins_encode %{
4835 __ xorl($dst$$Register, $dst$$Register);
4836 %}
4837 ins_pipe(ialu_reg);
4838 %}
4839
4840 instruct loadConL(rRegL dst, immL src)
4841 %{
4842 match(Set dst src);
4843
4844 ins_cost(150);
4845 format %{ "movq $dst, $src\t# long" %}
4846 ins_encode %{
4847 __ mov64($dst$$Register, $src$$constant);
4848 %}
4849 ins_pipe(ialu_reg);
4850 %}
4851
4852 instruct loadConL0(rRegL dst, immL0 src, rFlagsReg cr)
4853 %{
4854 match(Set dst src);
4855 effect(KILL cr);
4856
4857 ins_cost(50);
4858 format %{ "xorl $dst, $dst\t# long" %}
4859 ins_encode %{
4860 __ xorl($dst$$Register, $dst$$Register);
4861 %}
4862 ins_pipe(ialu_reg); // XXX
4863 %}
4864
4865 instruct loadConUL32(rRegL dst, immUL32 src)
4866 %{
4867 match(Set dst src);
4868
4869 ins_cost(60);
4870 format %{ "movl $dst, $src\t# long (unsigned 32-bit)" %}
4871 ins_encode %{
4872 __ movl($dst$$Register, $src$$constant);
4873 %}
4874 ins_pipe(ialu_reg);
4875 %}
4876
4877 instruct loadConL32(rRegL dst, immL32 src)
4878 %{
4879 match(Set dst src);
4880
4881 ins_cost(70);
4882 format %{ "movq $dst, $src\t# long (32-bit)" %}
4883 ins_encode %{
4884 __ movq($dst$$Register, $src$$constant);
4885 %}
4886 ins_pipe(ialu_reg);
4887 %}
4888
4889 instruct loadConP(rRegP dst, immP con) %{
4890 match(Set dst con);
4891
4892 format %{ "movq $dst, $con\t# ptr" %}
4893 ins_encode %{
4894 __ mov64($dst$$Register, $con$$constant, $con->constant_reloc(), RELOC_IMM64);
4895 %}
4896 ins_pipe(ialu_reg_fat); // XXX
4897 %}
4898
4899 instruct loadConP0(rRegP dst, immP0 src, rFlagsReg cr)
4900 %{
4901 match(Set dst src);
4902 effect(KILL cr);
4903
4904 ins_cost(50);
4905 format %{ "xorl $dst, $dst\t# ptr" %}
4906 ins_encode %{
4907 __ xorl($dst$$Register, $dst$$Register);
4908 %}
4909 ins_pipe(ialu_reg);
4910 %}
4911
4912 instruct loadConP31(rRegP dst, immP31 src, rFlagsReg cr)
4913 %{
4914 match(Set dst src);
4915 effect(KILL cr);
4916
4917 ins_cost(60);
4918 format %{ "movl $dst, $src\t# ptr (positive 32-bit)" %}
4919 ins_encode %{
4920 __ movl($dst$$Register, $src$$constant);
4921 %}
4922 ins_pipe(ialu_reg);
4923 %}
4924
4925 instruct loadConF(regF dst, immF con) %{
4926 match(Set dst con);
4927 ins_cost(125);
4928 format %{ "movss $dst, [$constantaddress]\t# load from constant table: float=$con" %}
4929 ins_encode %{
4930 __ movflt($dst$$XMMRegister, $constantaddress($con));
4931 %}
4932 ins_pipe(pipe_slow);
4933 %}
4934
4935 instruct loadConH(regF dst, immH con) %{
4936 match(Set dst con);
4937 ins_cost(125);
4938 format %{ "movss $dst, [$constantaddress]\t# load from constant table: halffloat=$con" %}
4939 ins_encode %{
4940 __ movflt($dst$$XMMRegister, $constantaddress($con));
4941 %}
4942 ins_pipe(pipe_slow);
4943 %}
4944
4945 instruct loadConN0(rRegN dst, immN0 src, rFlagsReg cr) %{
4946 match(Set dst src);
4947 effect(KILL cr);
4948 format %{ "xorq $dst, $src\t# compressed null pointer" %}
4949 ins_encode %{
4950 __ xorq($dst$$Register, $dst$$Register);
4951 %}
4952 ins_pipe(ialu_reg);
4953 %}
4954
4955 instruct loadConN(rRegN dst, immN src) %{
4956 match(Set dst src);
4957
4958 ins_cost(125);
4959 format %{ "movl $dst, $src\t# compressed ptr" %}
4960 ins_encode %{
4961 address con = (address)$src$$constant;
4962 if (con == nullptr) {
4963 ShouldNotReachHere();
4964 } else {
4965 __ set_narrow_oop($dst$$Register, (jobject)$src$$constant);
4966 }
4967 %}
4968 ins_pipe(ialu_reg_fat); // XXX
4969 %}
4970
4971 instruct loadConNKlass(rRegN dst, immNKlass src) %{
4972 match(Set dst src);
4973
4974 ins_cost(125);
4975 format %{ "movl $dst, $src\t# compressed klass ptr" %}
4976 ins_encode %{
4977 address con = (address)$src$$constant;
4978 if (con == nullptr) {
4979 ShouldNotReachHere();
4980 } else {
4981 __ set_narrow_klass($dst$$Register, (Klass*)$src$$constant);
4982 }
4983 %}
4984 ins_pipe(ialu_reg_fat); // XXX
4985 %}
4986
4987 instruct loadConF0(regF dst, immF0 src)
4988 %{
4989 match(Set dst src);
4990 ins_cost(100);
4991
4992 format %{ "xorps $dst, $dst\t# float 0.0" %}
4993 ins_encode %{
4994 __ xorps($dst$$XMMRegister, $dst$$XMMRegister);
4995 %}
4996 ins_pipe(pipe_slow);
4997 %}
4998
4999 // Use the same format since predicate() can not be used here.
5000 instruct loadConD(regD dst, immD con) %{
5001 match(Set dst con);
5002 ins_cost(125);
5003 format %{ "movsd $dst, [$constantaddress]\t# load from constant table: double=$con" %}
5004 ins_encode %{
5005 __ movdbl($dst$$XMMRegister, $constantaddress($con));
5006 %}
5007 ins_pipe(pipe_slow);
5008 %}
5009
5010 instruct loadConD0(regD dst, immD0 src)
5011 %{
5012 match(Set dst src);
5013 ins_cost(100);
5014
5015 format %{ "xorpd $dst, $dst\t# double 0.0" %}
5016 ins_encode %{
5017 __ xorpd($dst$$XMMRegister, $dst$$XMMRegister);
5018 %}
5019 ins_pipe(pipe_slow);
5020 %}
5021
5022 instruct loadSSI(rRegI dst, stackSlotI src)
5023 %{
5024 match(Set dst src);
5025
5026 ins_cost(125);
5027 format %{ "movl $dst, $src\t# int stk" %}
5028 ins_encode %{
5029 __ movl($dst$$Register, $src$$Address);
5030 %}
5031 ins_pipe(ialu_reg_mem);
5032 %}
5033
5034 instruct loadSSL(rRegL dst, stackSlotL src)
5035 %{
5036 match(Set dst src);
5037
5038 ins_cost(125);
5039 format %{ "movq $dst, $src\t# long stk" %}
5040 ins_encode %{
5041 __ movq($dst$$Register, $src$$Address);
5042 %}
5043 ins_pipe(ialu_reg_mem);
5044 %}
5045
5046 instruct loadSSP(rRegP dst, stackSlotP src)
5047 %{
5048 match(Set dst src);
5049
5050 ins_cost(125);
5051 format %{ "movq $dst, $src\t# ptr stk" %}
5052 ins_encode %{
5053 __ movq($dst$$Register, $src$$Address);
5054 %}
5055 ins_pipe(ialu_reg_mem);
5056 %}
5057
5058 instruct loadSSF(regF dst, stackSlotF src)
5059 %{
5060 match(Set dst src);
5061
5062 ins_cost(125);
5063 format %{ "movss $dst, $src\t# float stk" %}
5064 ins_encode %{
5065 __ movflt($dst$$XMMRegister, Address(rsp, $src$$disp));
5066 %}
5067 ins_pipe(pipe_slow); // XXX
5068 %}
5069
5070 // Use the same format since predicate() can not be used here.
5071 instruct loadSSD(regD dst, stackSlotD src)
5072 %{
5073 match(Set dst src);
5074
5075 ins_cost(125);
5076 format %{ "movsd $dst, $src\t# double stk" %}
5077 ins_encode %{
5078 __ movdbl($dst$$XMMRegister, Address(rsp, $src$$disp));
5079 %}
5080 ins_pipe(pipe_slow); // XXX
5081 %}
5082
5083 // Prefetch instructions for allocation.
5084 // Must be safe to execute with invalid address (cannot fault).
5085
5086 instruct prefetchAlloc( memory mem ) %{
5087 predicate(AllocatePrefetchInstr==3);
5088 match(PrefetchAllocation mem);
5089 ins_cost(125);
5090
5091 format %{ "PREFETCHW $mem\t# Prefetch allocation into level 1 cache and mark modified" %}
5092 ins_encode %{
5093 __ prefetchw($mem$$Address);
5094 %}
5095 ins_pipe(ialu_mem);
5096 %}
5097
5098 instruct prefetchAllocNTA( memory mem ) %{
5099 predicate(AllocatePrefetchInstr==0);
5100 match(PrefetchAllocation mem);
5101 ins_cost(125);
5102
5103 format %{ "PREFETCHNTA $mem\t# Prefetch allocation to non-temporal cache for write" %}
5104 ins_encode %{
5105 __ prefetchnta($mem$$Address);
5106 %}
5107 ins_pipe(ialu_mem);
5108 %}
5109
5110 instruct prefetchAllocT0( memory mem ) %{
5111 predicate(AllocatePrefetchInstr==1);
5112 match(PrefetchAllocation mem);
5113 ins_cost(125);
5114
5115 format %{ "PREFETCHT0 $mem\t# Prefetch allocation to level 1 and 2 caches for write" %}
5116 ins_encode %{
5117 __ prefetcht0($mem$$Address);
5118 %}
5119 ins_pipe(ialu_mem);
5120 %}
5121
5122 instruct prefetchAllocT2( memory mem ) %{
5123 predicate(AllocatePrefetchInstr==2);
5124 match(PrefetchAllocation mem);
5125 ins_cost(125);
5126
5127 format %{ "PREFETCHT2 $mem\t# Prefetch allocation to level 2 cache for write" %}
5128 ins_encode %{
5129 __ prefetcht2($mem$$Address);
5130 %}
5131 ins_pipe(ialu_mem);
5132 %}
5133
5134 //----------Store Instructions-------------------------------------------------
5135
5136 // Store Byte
5137 instruct storeB(memory mem, rRegI src)
5138 %{
5139 match(Set mem (StoreB mem src));
5140
5141 ins_cost(125); // XXX
5142 format %{ "movb $mem, $src\t# byte" %}
5143 ins_encode %{
5144 __ movb($mem$$Address, $src$$Register);
5145 %}
5146 ins_pipe(ialu_mem_reg);
5147 %}
5148
5149 // Store Char/Short
5150 instruct storeC(memory mem, rRegI src)
5151 %{
5152 match(Set mem (StoreC mem src));
5153
5154 ins_cost(125); // XXX
5155 format %{ "movw $mem, $src\t# char/short" %}
5156 ins_encode %{
5157 __ movw($mem$$Address, $src$$Register);
5158 %}
5159 ins_pipe(ialu_mem_reg);
5160 %}
5161
5162 // Store Integer
5163 instruct storeI(memory mem, rRegI src)
5164 %{
5165 match(Set mem (StoreI mem src));
5166
5167 ins_cost(125); // XXX
5168 format %{ "movl $mem, $src\t# int" %}
5169 ins_encode %{
5170 __ movl($mem$$Address, $src$$Register);
5171 %}
5172 ins_pipe(ialu_mem_reg);
5173 %}
5174
5175 // Store Long
5176 instruct storeL(memory mem, rRegL src)
5177 %{
5178 match(Set mem (StoreL mem src));
5179
5180 ins_cost(125); // XXX
5181 format %{ "movq $mem, $src\t# long" %}
5182 ins_encode %{
5183 __ movq($mem$$Address, $src$$Register);
5184 %}
5185 ins_pipe(ialu_mem_reg); // XXX
5186 %}
5187
5188 // Store Pointer
5189 instruct storeP(memory mem, any_RegP src)
5190 %{
5191 predicate(n->as_Store()->barrier_data() == 0);
5192 match(Set mem (StoreP mem src));
5193
5194 ins_cost(125); // XXX
5195 format %{ "movq $mem, $src\t# ptr" %}
5196 ins_encode %{
5197 __ movq($mem$$Address, $src$$Register);
5198 %}
5199 ins_pipe(ialu_mem_reg);
5200 %}
5201
5202 instruct storeImmP0(memory mem, immP0 zero)
5203 %{
5204 predicate(UseCompressedOops && (CompressedOops::base() == nullptr) && n->as_Store()->barrier_data() == 0);
5205 match(Set mem (StoreP mem zero));
5206
5207 ins_cost(125); // XXX
5208 format %{ "movq $mem, R12\t# ptr (R12_heapbase==0)" %}
5209 ins_encode %{
5210 __ movq($mem$$Address, r12);
5211 %}
5212 ins_pipe(ialu_mem_reg);
5213 %}
5214
5215 // Store Null Pointer, mark word, or other simple pointer constant.
5216 instruct storeImmP(memory mem, immP31 src)
5217 %{
5218 predicate(n->as_Store()->barrier_data() == 0);
5219 match(Set mem (StoreP mem src));
5220
5221 ins_cost(150); // XXX
5222 format %{ "movq $mem, $src\t# ptr" %}
5223 ins_encode %{
5224 __ movq($mem$$Address, $src$$constant);
5225 %}
5226 ins_pipe(ialu_mem_imm);
5227 %}
5228
5229 // Store Compressed Pointer
5230 instruct storeN(memory mem, rRegN src)
5231 %{
5232 predicate(n->as_Store()->barrier_data() == 0);
5233 match(Set mem (StoreN mem src));
5234
5235 ins_cost(125); // XXX
5236 format %{ "movl $mem, $src\t# compressed ptr" %}
5237 ins_encode %{
5238 __ movl($mem$$Address, $src$$Register);
5239 %}
5240 ins_pipe(ialu_mem_reg);
5241 %}
5242
5243 instruct storeNKlass(memory mem, rRegN src)
5244 %{
5245 match(Set mem (StoreNKlass mem src));
5246
5247 ins_cost(125); // XXX
5248 format %{ "movl $mem, $src\t# compressed klass ptr" %}
5249 ins_encode %{
5250 __ movl($mem$$Address, $src$$Register);
5251 %}
5252 ins_pipe(ialu_mem_reg);
5253 %}
5254
5255 instruct storeImmN0(memory mem, immN0 zero)
5256 %{
5257 predicate(CompressedOops::base() == nullptr && n->as_Store()->barrier_data() == 0);
5258 match(Set mem (StoreN mem zero));
5259
5260 ins_cost(125); // XXX
5261 format %{ "movl $mem, R12\t# compressed ptr (R12_heapbase==0)" %}
5262 ins_encode %{
5263 __ movl($mem$$Address, r12);
5264 %}
5265 ins_pipe(ialu_mem_reg);
5266 %}
5267
5268 instruct storeImmN(memory mem, immN src)
5269 %{
5270 predicate(n->as_Store()->barrier_data() == 0);
5271 match(Set mem (StoreN mem src));
5272
5273 ins_cost(150); // XXX
5274 format %{ "movl $mem, $src\t# compressed ptr" %}
5275 ins_encode %{
5276 address con = (address)$src$$constant;
5277 if (con == nullptr) {
5278 __ movl($mem$$Address, 0);
5279 } else {
5280 __ set_narrow_oop($mem$$Address, (jobject)$src$$constant);
5281 }
5282 %}
5283 ins_pipe(ialu_mem_imm);
5284 %}
5285
5286 instruct storeImmNKlass(memory mem, immNKlass src)
5287 %{
5288 match(Set mem (StoreNKlass mem src));
5289
5290 ins_cost(150); // XXX
5291 format %{ "movl $mem, $src\t# compressed klass ptr" %}
5292 ins_encode %{
5293 __ set_narrow_klass($mem$$Address, (Klass*)$src$$constant);
5294 %}
5295 ins_pipe(ialu_mem_imm);
5296 %}
5297
5298 // Store Integer Immediate
5299 instruct storeImmI0(memory mem, immI_0 zero)
5300 %{
5301 predicate(UseCompressedOops && (CompressedOops::base() == nullptr));
5302 match(Set mem (StoreI mem zero));
5303
5304 ins_cost(125); // XXX
5305 format %{ "movl $mem, R12\t# int (R12_heapbase==0)" %}
5306 ins_encode %{
5307 __ movl($mem$$Address, r12);
5308 %}
5309 ins_pipe(ialu_mem_reg);
5310 %}
5311
5312 instruct storeImmI(memory mem, immI src)
5313 %{
5314 match(Set mem (StoreI mem src));
5315
5316 ins_cost(150);
5317 format %{ "movl $mem, $src\t# int" %}
5318 ins_encode %{
5319 __ movl($mem$$Address, $src$$constant);
5320 %}
5321 ins_pipe(ialu_mem_imm);
5322 %}
5323
5324 // Store Long Immediate
5325 instruct storeImmL0(memory mem, immL0 zero)
5326 %{
5327 predicate(UseCompressedOops && (CompressedOops::base() == nullptr));
5328 match(Set mem (StoreL mem zero));
5329
5330 ins_cost(125); // XXX
5331 format %{ "movq $mem, R12\t# long (R12_heapbase==0)" %}
5332 ins_encode %{
5333 __ movq($mem$$Address, r12);
5334 %}
5335 ins_pipe(ialu_mem_reg);
5336 %}
5337
5338 instruct storeImmL(memory mem, immL32 src)
5339 %{
5340 match(Set mem (StoreL mem src));
5341
5342 ins_cost(150);
5343 format %{ "movq $mem, $src\t# long" %}
5344 ins_encode %{
5345 __ movq($mem$$Address, $src$$constant);
5346 %}
5347 ins_pipe(ialu_mem_imm);
5348 %}
5349
5350 // Store Short/Char Immediate
5351 instruct storeImmC0(memory mem, immI_0 zero)
5352 %{
5353 predicate(UseCompressedOops && (CompressedOops::base() == nullptr));
5354 match(Set mem (StoreC mem zero));
5355
5356 ins_cost(125); // XXX
5357 format %{ "movw $mem, R12\t# short/char (R12_heapbase==0)" %}
5358 ins_encode %{
5359 __ movw($mem$$Address, r12);
5360 %}
5361 ins_pipe(ialu_mem_reg);
5362 %}
5363
5364 instruct storeImmI16(memory mem, immI16 src)
5365 %{
5366 predicate(UseStoreImmI16);
5367 match(Set mem (StoreC mem src));
5368
5369 ins_cost(150);
5370 format %{ "movw $mem, $src\t# short/char" %}
5371 ins_encode %{
5372 __ movw($mem$$Address, $src$$constant);
5373 %}
5374 ins_pipe(ialu_mem_imm);
5375 %}
5376
5377 // Store Byte Immediate
5378 instruct storeImmB0(memory mem, immI_0 zero)
5379 %{
5380 predicate(UseCompressedOops && (CompressedOops::base() == nullptr));
5381 match(Set mem (StoreB mem zero));
5382
5383 ins_cost(125); // XXX
5384 format %{ "movb $mem, R12\t# short/char (R12_heapbase==0)" %}
5385 ins_encode %{
5386 __ movb($mem$$Address, r12);
5387 %}
5388 ins_pipe(ialu_mem_reg);
5389 %}
5390
5391 instruct storeImmB(memory mem, immI8 src)
5392 %{
5393 match(Set mem (StoreB mem src));
5394
5395 ins_cost(150); // XXX
5396 format %{ "movb $mem, $src\t# byte" %}
5397 ins_encode %{
5398 __ movb($mem$$Address, $src$$constant);
5399 %}
5400 ins_pipe(ialu_mem_imm);
5401 %}
5402
5403 // Store Float
5404 instruct storeF(memory mem, regF src)
5405 %{
5406 match(Set mem (StoreF mem src));
5407
5408 ins_cost(95); // XXX
5409 format %{ "movss $mem, $src\t# float" %}
5410 ins_encode %{
5411 __ movflt($mem$$Address, $src$$XMMRegister);
5412 %}
5413 ins_pipe(pipe_slow); // XXX
5414 %}
5415
5416 // Store immediate Float value (it is faster than store from XMM register)
5417 instruct storeF0(memory mem, immF0 zero)
5418 %{
5419 predicate(UseCompressedOops && (CompressedOops::base() == nullptr));
5420 match(Set mem (StoreF mem zero));
5421
5422 ins_cost(25); // XXX
5423 format %{ "movl $mem, R12\t# float 0. (R12_heapbase==0)" %}
5424 ins_encode %{
5425 __ movl($mem$$Address, r12);
5426 %}
5427 ins_pipe(ialu_mem_reg);
5428 %}
5429
5430 instruct storeF_imm(memory mem, immF src)
5431 %{
5432 match(Set mem (StoreF mem src));
5433
5434 ins_cost(50);
5435 format %{ "movl $mem, $src\t# float" %}
5436 ins_encode %{
5437 __ movl($mem$$Address, jint_cast($src$$constant));
5438 %}
5439 ins_pipe(ialu_mem_imm);
5440 %}
5441
5442 // Store Double
5443 instruct storeD(memory mem, regD src)
5444 %{
5445 match(Set mem (StoreD mem src));
5446
5447 ins_cost(95); // XXX
5448 format %{ "movsd $mem, $src\t# double" %}
5449 ins_encode %{
5450 __ movdbl($mem$$Address, $src$$XMMRegister);
5451 %}
5452 ins_pipe(pipe_slow); // XXX
5453 %}
5454
5455 // Store immediate double 0.0 (it is faster than store from XMM register)
5456 instruct storeD0_imm(memory mem, immD0 src)
5457 %{
5458 predicate(!UseCompressedOops || (CompressedOops::base() != nullptr));
5459 match(Set mem (StoreD mem src));
5460
5461 ins_cost(50);
5462 format %{ "movq $mem, $src\t# double 0." %}
5463 ins_encode %{
5464 __ movq($mem$$Address, $src$$constant);
5465 %}
5466 ins_pipe(ialu_mem_imm);
5467 %}
5468
5469 instruct storeD0(memory mem, immD0 zero)
5470 %{
5471 predicate(UseCompressedOops && (CompressedOops::base() == nullptr));
5472 match(Set mem (StoreD mem zero));
5473
5474 ins_cost(25); // XXX
5475 format %{ "movq $mem, R12\t# double 0. (R12_heapbase==0)" %}
5476 ins_encode %{
5477 __ movq($mem$$Address, r12);
5478 %}
5479 ins_pipe(ialu_mem_reg);
5480 %}
5481
5482 instruct storeSSI(stackSlotI dst, rRegI src)
5483 %{
5484 match(Set dst src);
5485
5486 ins_cost(100);
5487 format %{ "movl $dst, $src\t# int stk" %}
5488 ins_encode %{
5489 __ movl($dst$$Address, $src$$Register);
5490 %}
5491 ins_pipe( ialu_mem_reg );
5492 %}
5493
5494 instruct storeSSL(stackSlotL dst, rRegL src)
5495 %{
5496 match(Set dst src);
5497
5498 ins_cost(100);
5499 format %{ "movq $dst, $src\t# long stk" %}
5500 ins_encode %{
5501 __ movq($dst$$Address, $src$$Register);
5502 %}
5503 ins_pipe(ialu_mem_reg);
5504 %}
5505
5506 instruct storeSSP(stackSlotP dst, rRegP src)
5507 %{
5508 match(Set dst src);
5509
5510 ins_cost(100);
5511 format %{ "movq $dst, $src\t# ptr stk" %}
5512 ins_encode %{
5513 __ movq($dst$$Address, $src$$Register);
5514 %}
5515 ins_pipe(ialu_mem_reg);
5516 %}
5517
5518 instruct storeSSF(stackSlotF dst, regF src)
5519 %{
5520 match(Set dst src);
5521
5522 ins_cost(95); // XXX
5523 format %{ "movss $dst, $src\t# float stk" %}
5524 ins_encode %{
5525 __ movflt(Address(rsp, $dst$$disp), $src$$XMMRegister);
5526 %}
5527 ins_pipe(pipe_slow); // XXX
5528 %}
5529
5530 instruct storeSSD(stackSlotD dst, regD src)
5531 %{
5532 match(Set dst src);
5533
5534 ins_cost(95); // XXX
5535 format %{ "movsd $dst, $src\t# double stk" %}
5536 ins_encode %{
5537 __ movdbl(Address(rsp, $dst$$disp), $src$$XMMRegister);
5538 %}
5539 ins_pipe(pipe_slow); // XXX
5540 %}
5541
5542 instruct cacheWB(indirect addr)
5543 %{
5544 predicate(VM_Version::supports_data_cache_line_flush());
5545 match(CacheWB addr);
5546
5547 ins_cost(100);
5548 format %{"cache wb $addr" %}
5549 ins_encode %{
5550 assert($addr->index_position() < 0, "should be");
5551 assert($addr$$disp == 0, "should be");
5552 __ cache_wb(Address($addr$$base$$Register, 0));
5553 %}
5554 ins_pipe(pipe_slow); // XXX
5555 %}
5556
5557 instruct cacheWBPreSync()
5558 %{
5559 predicate(VM_Version::supports_data_cache_line_flush());
5560 match(CacheWBPreSync);
5561
5562 ins_cost(100);
5563 format %{"cache wb presync" %}
5564 ins_encode %{
5565 __ cache_wbsync(true);
5566 %}
5567 ins_pipe(pipe_slow); // XXX
5568 %}
5569
5570 instruct cacheWBPostSync()
5571 %{
5572 predicate(VM_Version::supports_data_cache_line_flush());
5573 match(CacheWBPostSync);
5574
5575 ins_cost(100);
5576 format %{"cache wb postsync" %}
5577 ins_encode %{
5578 __ cache_wbsync(false);
5579 %}
5580 ins_pipe(pipe_slow); // XXX
5581 %}
5582
5583 //----------BSWAP Instructions-------------------------------------------------
5584 instruct bytes_reverse_int(rRegI dst) %{
5585 match(Set dst (ReverseBytesI dst));
5586
5587 format %{ "bswapl $dst" %}
5588 ins_encode %{
5589 __ bswapl($dst$$Register);
5590 %}
5591 ins_pipe( ialu_reg );
5592 %}
5593
5594 instruct bytes_reverse_long(rRegL dst) %{
5595 match(Set dst (ReverseBytesL dst));
5596
5597 format %{ "bswapq $dst" %}
5598 ins_encode %{
5599 __ bswapq($dst$$Register);
5600 %}
5601 ins_pipe( ialu_reg);
5602 %}
5603
5604 instruct bytes_reverse_unsigned_short(rRegI dst, rFlagsReg cr) %{
5605 match(Set dst (ReverseBytesUS dst));
5606 effect(KILL cr);
5607
5608 format %{ "bswapl $dst\n\t"
5609 "shrl $dst,16\n\t" %}
5610 ins_encode %{
5611 __ bswapl($dst$$Register);
5612 __ shrl($dst$$Register, 16);
5613 %}
5614 ins_pipe( ialu_reg );
5615 %}
5616
5617 instruct bytes_reverse_short(rRegI dst, rFlagsReg cr) %{
5618 match(Set dst (ReverseBytesS dst));
5619 effect(KILL cr);
5620
5621 format %{ "bswapl $dst\n\t"
5622 "sar $dst,16\n\t" %}
5623 ins_encode %{
5624 __ bswapl($dst$$Register);
5625 __ sarl($dst$$Register, 16);
5626 %}
5627 ins_pipe( ialu_reg );
5628 %}
5629
5630 //---------- Zeros Count Instructions ------------------------------------------
5631
5632 instruct countLeadingZerosI(rRegI dst, rRegI src, rFlagsReg cr) %{
5633 predicate(UseCountLeadingZerosInstruction);
5634 match(Set dst (CountLeadingZerosI src));
5635 effect(KILL cr);
5636
5637 format %{ "lzcntl $dst, $src\t# count leading zeros (int)" %}
5638 ins_encode %{
5639 __ lzcntl($dst$$Register, $src$$Register);
5640 %}
5641 ins_pipe(ialu_reg);
5642 %}
5643
5644 instruct countLeadingZerosI_mem(rRegI dst, memory src, rFlagsReg cr) %{
5645 predicate(UseCountLeadingZerosInstruction);
5646 match(Set dst (CountLeadingZerosI (LoadI src)));
5647 effect(KILL cr);
5648 ins_cost(175);
5649 format %{ "lzcntl $dst, $src\t# count leading zeros (int)" %}
5650 ins_encode %{
5651 __ lzcntl($dst$$Register, $src$$Address);
5652 %}
5653 ins_pipe(ialu_reg_mem);
5654 %}
5655
5656 instruct countLeadingZerosI_bsr(rRegI dst, rRegI src, rFlagsReg cr) %{
5657 predicate(!UseCountLeadingZerosInstruction);
5658 match(Set dst (CountLeadingZerosI src));
5659 effect(KILL cr);
5660
5661 format %{ "bsrl $dst, $src\t# count leading zeros (int)\n\t"
5662 "jnz skip\n\t"
5663 "movl $dst, -1\n"
5664 "skip:\n\t"
5665 "negl $dst\n\t"
5666 "addl $dst, 31" %}
5667 ins_encode %{
5668 Register Rdst = $dst$$Register;
5669 Register Rsrc = $src$$Register;
5670 Label skip;
5671 __ bsrl(Rdst, Rsrc);
5672 __ jccb(Assembler::notZero, skip);
5673 __ movl(Rdst, -1);
5674 __ bind(skip);
5675 __ negl(Rdst);
5676 __ addl(Rdst, BitsPerInt - 1);
5677 %}
5678 ins_pipe(ialu_reg);
5679 %}
5680
5681 instruct countLeadingZerosL(rRegI dst, rRegL src, rFlagsReg cr) %{
5682 predicate(UseCountLeadingZerosInstruction);
5683 match(Set dst (CountLeadingZerosL src));
5684 effect(KILL cr);
5685
5686 format %{ "lzcntq $dst, $src\t# count leading zeros (long)" %}
5687 ins_encode %{
5688 __ lzcntq($dst$$Register, $src$$Register);
5689 %}
5690 ins_pipe(ialu_reg);
5691 %}
5692
5693 instruct countLeadingZerosL_mem(rRegI dst, memory src, rFlagsReg cr) %{
5694 predicate(UseCountLeadingZerosInstruction);
5695 match(Set dst (CountLeadingZerosL (LoadL src)));
5696 effect(KILL cr);
5697 ins_cost(175);
5698 format %{ "lzcntq $dst, $src\t# count leading zeros (long)" %}
5699 ins_encode %{
5700 __ lzcntq($dst$$Register, $src$$Address);
5701 %}
5702 ins_pipe(ialu_reg_mem);
5703 %}
5704
5705 instruct countLeadingZerosL_bsr(rRegI dst, rRegL src, rFlagsReg cr) %{
5706 predicate(!UseCountLeadingZerosInstruction);
5707 match(Set dst (CountLeadingZerosL src));
5708 effect(KILL cr);
5709
5710 format %{ "bsrq $dst, $src\t# count leading zeros (long)\n\t"
5711 "jnz skip\n\t"
5712 "movl $dst, -1\n"
5713 "skip:\n\t"
5714 "negl $dst\n\t"
5715 "addl $dst, 63" %}
5716 ins_encode %{
5717 Register Rdst = $dst$$Register;
5718 Register Rsrc = $src$$Register;
5719 Label skip;
5720 __ bsrq(Rdst, Rsrc);
5721 __ jccb(Assembler::notZero, skip);
5722 __ movl(Rdst, -1);
5723 __ bind(skip);
5724 __ negl(Rdst);
5725 __ addl(Rdst, BitsPerLong - 1);
5726 %}
5727 ins_pipe(ialu_reg);
5728 %}
5729
5730 instruct countTrailingZerosI(rRegI dst, rRegI src, rFlagsReg cr) %{
5731 predicate(UseCountTrailingZerosInstruction);
5732 match(Set dst (CountTrailingZerosI src));
5733 effect(KILL cr);
5734
5735 format %{ "tzcntl $dst, $src\t# count trailing zeros (int)" %}
5736 ins_encode %{
5737 __ tzcntl($dst$$Register, $src$$Register);
5738 %}
5739 ins_pipe(ialu_reg);
5740 %}
5741
5742 instruct countTrailingZerosI_mem(rRegI dst, memory src, rFlagsReg cr) %{
5743 predicate(UseCountTrailingZerosInstruction);
5744 match(Set dst (CountTrailingZerosI (LoadI src)));
5745 effect(KILL cr);
5746 ins_cost(175);
5747 format %{ "tzcntl $dst, $src\t# count trailing zeros (int)" %}
5748 ins_encode %{
5749 __ tzcntl($dst$$Register, $src$$Address);
5750 %}
5751 ins_pipe(ialu_reg_mem);
5752 %}
5753
5754 instruct countTrailingZerosI_bsf(rRegI dst, rRegI src, rFlagsReg cr) %{
5755 predicate(!UseCountTrailingZerosInstruction);
5756 match(Set dst (CountTrailingZerosI src));
5757 effect(KILL cr);
5758
5759 format %{ "bsfl $dst, $src\t# count trailing zeros (int)\n\t"
5760 "jnz done\n\t"
5761 "movl $dst, 32\n"
5762 "done:" %}
5763 ins_encode %{
5764 Register Rdst = $dst$$Register;
5765 Label done;
5766 __ bsfl(Rdst, $src$$Register);
5767 __ jccb(Assembler::notZero, done);
5768 __ movl(Rdst, BitsPerInt);
5769 __ bind(done);
5770 %}
5771 ins_pipe(ialu_reg);
5772 %}
5773
5774 instruct countTrailingZerosL(rRegI dst, rRegL src, rFlagsReg cr) %{
5775 predicate(UseCountTrailingZerosInstruction);
5776 match(Set dst (CountTrailingZerosL src));
5777 effect(KILL cr);
5778
5779 format %{ "tzcntq $dst, $src\t# count trailing zeros (long)" %}
5780 ins_encode %{
5781 __ tzcntq($dst$$Register, $src$$Register);
5782 %}
5783 ins_pipe(ialu_reg);
5784 %}
5785
5786 instruct countTrailingZerosL_mem(rRegI dst, memory src, rFlagsReg cr) %{
5787 predicate(UseCountTrailingZerosInstruction);
5788 match(Set dst (CountTrailingZerosL (LoadL src)));
5789 effect(KILL cr);
5790 ins_cost(175);
5791 format %{ "tzcntq $dst, $src\t# count trailing zeros (long)" %}
5792 ins_encode %{
5793 __ tzcntq($dst$$Register, $src$$Address);
5794 %}
5795 ins_pipe(ialu_reg_mem);
5796 %}
5797
5798 instruct countTrailingZerosL_bsf(rRegI dst, rRegL src, rFlagsReg cr) %{
5799 predicate(!UseCountTrailingZerosInstruction);
5800 match(Set dst (CountTrailingZerosL src));
5801 effect(KILL cr);
5802
5803 format %{ "bsfq $dst, $src\t# count trailing zeros (long)\n\t"
5804 "jnz done\n\t"
5805 "movl $dst, 64\n"
5806 "done:" %}
5807 ins_encode %{
5808 Register Rdst = $dst$$Register;
5809 Label done;
5810 __ bsfq(Rdst, $src$$Register);
5811 __ jccb(Assembler::notZero, done);
5812 __ movl(Rdst, BitsPerLong);
5813 __ bind(done);
5814 %}
5815 ins_pipe(ialu_reg);
5816 %}
5817
5818 //--------------- Reverse Operation Instructions ----------------
5819 instruct bytes_reversebit_int(rRegI dst, rRegI src, rRegI rtmp, rFlagsReg cr) %{
5820 predicate(!VM_Version::supports_gfni());
5821 match(Set dst (ReverseI src));
5822 effect(TEMP dst, TEMP rtmp, KILL cr);
5823 format %{ "reverse_int $dst $src\t! using $rtmp as TEMP" %}
5824 ins_encode %{
5825 __ reverseI($dst$$Register, $src$$Register, xnoreg, xnoreg, $rtmp$$Register);
5826 %}
5827 ins_pipe( ialu_reg );
5828 %}
5829
5830 instruct bytes_reversebit_int_gfni(rRegI dst, rRegI src, vlRegF xtmp1, vlRegF xtmp2, rRegL rtmp, rFlagsReg cr) %{
5831 predicate(VM_Version::supports_gfni());
5832 match(Set dst (ReverseI src));
5833 effect(TEMP dst, TEMP xtmp1, TEMP xtmp2, TEMP rtmp, KILL cr);
5834 format %{ "reverse_int $dst $src\t! using $rtmp, $xtmp1 and $xtmp2 as TEMP" %}
5835 ins_encode %{
5836 __ reverseI($dst$$Register, $src$$Register, $xtmp1$$XMMRegister, $xtmp2$$XMMRegister, $rtmp$$Register);
5837 %}
5838 ins_pipe( ialu_reg );
5839 %}
5840
5841 instruct bytes_reversebit_long(rRegL dst, rRegL src, rRegL rtmp1, rRegL rtmp2, rFlagsReg cr) %{
5842 predicate(!VM_Version::supports_gfni());
5843 match(Set dst (ReverseL src));
5844 effect(TEMP dst, TEMP rtmp1, TEMP rtmp2, KILL cr);
5845 format %{ "reverse_long $dst $src\t! using $rtmp1 and $rtmp2 as TEMP" %}
5846 ins_encode %{
5847 __ reverseL($dst$$Register, $src$$Register, xnoreg, xnoreg, $rtmp1$$Register, $rtmp2$$Register);
5848 %}
5849 ins_pipe( ialu_reg );
5850 %}
5851
5852 instruct bytes_reversebit_long_gfni(rRegL dst, rRegL src, vlRegD xtmp1, vlRegD xtmp2, rRegL rtmp, rFlagsReg cr) %{
5853 predicate(VM_Version::supports_gfni());
5854 match(Set dst (ReverseL src));
5855 effect(TEMP dst, TEMP xtmp1, TEMP xtmp2, TEMP rtmp, KILL cr);
5856 format %{ "reverse_long $dst $src\t! using $rtmp, $xtmp1 and $xtmp2 as TEMP" %}
5857 ins_encode %{
5858 __ reverseL($dst$$Register, $src$$Register, $xtmp1$$XMMRegister, $xtmp2$$XMMRegister, $rtmp$$Register, noreg);
5859 %}
5860 ins_pipe( ialu_reg );
5861 %}
5862
5863 //---------- Population Count Instructions -------------------------------------
5864
5865 instruct popCountI(rRegI dst, rRegI src, rFlagsReg cr) %{
5866 predicate(UsePopCountInstruction);
5867 match(Set dst (PopCountI src));
5868 effect(KILL cr);
5869
5870 format %{ "popcnt $dst, $src" %}
5871 ins_encode %{
5872 __ popcntl($dst$$Register, $src$$Register);
5873 %}
5874 ins_pipe(ialu_reg);
5875 %}
5876
5877 instruct popCountI_mem(rRegI dst, memory mem, rFlagsReg cr) %{
5878 predicate(UsePopCountInstruction);
5879 match(Set dst (PopCountI (LoadI mem)));
5880 effect(KILL cr);
5881
5882 format %{ "popcnt $dst, $mem" %}
5883 ins_encode %{
5884 __ popcntl($dst$$Register, $mem$$Address);
5885 %}
5886 ins_pipe(ialu_reg);
5887 %}
5888
5889 // Note: Long.bitCount(long) returns an int.
5890 instruct popCountL(rRegI dst, rRegL src, rFlagsReg cr) %{
5891 predicate(UsePopCountInstruction);
5892 match(Set dst (PopCountL src));
5893 effect(KILL cr);
5894
5895 format %{ "popcnt $dst, $src" %}
5896 ins_encode %{
5897 __ popcntq($dst$$Register, $src$$Register);
5898 %}
5899 ins_pipe(ialu_reg);
5900 %}
5901
5902 // Note: Long.bitCount(long) returns an int.
5903 instruct popCountL_mem(rRegI dst, memory mem, rFlagsReg cr) %{
5904 predicate(UsePopCountInstruction);
5905 match(Set dst (PopCountL (LoadL mem)));
5906 effect(KILL cr);
5907
5908 format %{ "popcnt $dst, $mem" %}
5909 ins_encode %{
5910 __ popcntq($dst$$Register, $mem$$Address);
5911 %}
5912 ins_pipe(ialu_reg);
5913 %}
5914
5915
5916 //----------MemBar Instructions-----------------------------------------------
5917 // Memory barrier flavors
5918
5919 instruct membar_acquire()
5920 %{
5921 match(MemBarAcquire);
5922 match(LoadFence);
5923 ins_cost(0);
5924
5925 size(0);
5926 format %{ "MEMBAR-acquire ! (empty encoding)" %}
5927 ins_encode();
5928 ins_pipe(empty);
5929 %}
5930
5931 instruct membar_acquire_lock()
5932 %{
5933 match(MemBarAcquireLock);
5934 ins_cost(0);
5935
5936 size(0);
5937 format %{ "MEMBAR-acquire (prior CMPXCHG in FastLock so empty encoding)" %}
5938 ins_encode();
5939 ins_pipe(empty);
5940 %}
5941
5942 instruct membar_release()
5943 %{
5944 match(MemBarRelease);
5945 match(StoreFence);
5946 ins_cost(0);
5947
5948 size(0);
5949 format %{ "MEMBAR-release ! (empty encoding)" %}
5950 ins_encode();
5951 ins_pipe(empty);
5952 %}
5953
5954 instruct membar_release_lock()
5955 %{
5956 match(MemBarReleaseLock);
5957 ins_cost(0);
5958
5959 size(0);
5960 format %{ "MEMBAR-release (a FastUnlock follows so empty encoding)" %}
5961 ins_encode();
5962 ins_pipe(empty);
5963 %}
5964
5965 instruct membar_volatile(rFlagsReg cr) %{
5966 match(MemBarVolatile);
5967 effect(KILL cr);
5968 ins_cost(400);
5969
5970 format %{
5971 $$template
5972 $$emit$$"lock addl [rsp + #0], 0\t! membar_volatile"
5973 %}
5974 ins_encode %{
5975 __ membar(Assembler::StoreLoad);
5976 %}
5977 ins_pipe(pipe_slow);
5978 %}
5979
5980 instruct unnecessary_membar_volatile()
5981 %{
5982 match(MemBarVolatile);
5983 predicate(Matcher::post_store_load_barrier(n));
5984 ins_cost(0);
5985
5986 size(0);
5987 format %{ "MEMBAR-volatile (unnecessary so empty encoding)" %}
5988 ins_encode();
5989 ins_pipe(empty);
5990 %}
5991
5992 instruct membar_storestore() %{
5993 match(MemBarStoreStore);
5994 match(StoreStoreFence);
5995 ins_cost(0);
5996
5997 size(0);
5998 format %{ "MEMBAR-storestore (empty encoding)" %}
5999 ins_encode( );
6000 ins_pipe(empty);
6001 %}
6002
6003 //----------Move Instructions--------------------------------------------------
6004
6005 instruct castX2P(rRegP dst, rRegL src)
6006 %{
6007 match(Set dst (CastX2P src));
6008
6009 format %{ "movq $dst, $src\t# long->ptr" %}
6010 ins_encode %{
6011 if ($dst$$reg != $src$$reg) {
6012 __ movptr($dst$$Register, $src$$Register);
6013 }
6014 %}
6015 ins_pipe(ialu_reg_reg); // XXX
6016 %}
6017
6018 instruct castI2N(rRegN dst, rRegI src)
6019 %{
6020 match(Set dst (CastI2N src));
6021
6022 format %{ "movq $dst, $src\t# int -> narrow ptr" %}
6023 ins_encode %{
6024 if ($dst$$reg != $src$$reg) {
6025 __ movl($dst$$Register, $src$$Register);
6026 }
6027 %}
6028 ins_pipe(ialu_reg_reg); // XXX
6029 %}
6030
6031 instruct castN2X(rRegL dst, rRegN src)
6032 %{
6033 match(Set dst (CastP2X src));
6034
6035 format %{ "movq $dst, $src\t# ptr -> long" %}
6036 ins_encode %{
6037 if ($dst$$reg != $src$$reg) {
6038 __ movptr($dst$$Register, $src$$Register);
6039 }
6040 %}
6041 ins_pipe(ialu_reg_reg); // XXX
6042 %}
6043
6044 instruct castP2X(rRegL dst, rRegP src)
6045 %{
6046 match(Set dst (CastP2X src));
6047
6048 format %{ "movq $dst, $src\t# ptr -> long" %}
6049 ins_encode %{
6050 if ($dst$$reg != $src$$reg) {
6051 __ movptr($dst$$Register, $src$$Register);
6052 }
6053 %}
6054 ins_pipe(ialu_reg_reg); // XXX
6055 %}
6056
6057 // Convert oop into int for vectors alignment masking
6058 instruct convP2I(rRegI dst, rRegP src)
6059 %{
6060 match(Set dst (ConvL2I (CastP2X src)));
6061
6062 format %{ "movl $dst, $src\t# ptr -> int" %}
6063 ins_encode %{
6064 __ movl($dst$$Register, $src$$Register);
6065 %}
6066 ins_pipe(ialu_reg_reg); // XXX
6067 %}
6068
6069 // Convert compressed oop into int for vectors alignment masking
6070 // in case of 32bit oops (heap < 4Gb).
6071 instruct convN2I(rRegI dst, rRegN src)
6072 %{
6073 predicate(CompressedOops::shift() == 0);
6074 match(Set dst (ConvL2I (CastP2X (DecodeN src))));
6075
6076 format %{ "movl $dst, $src\t# compressed ptr -> int" %}
6077 ins_encode %{
6078 __ movl($dst$$Register, $src$$Register);
6079 %}
6080 ins_pipe(ialu_reg_reg); // XXX
6081 %}
6082
6083 // Convert oop pointer into compressed form
6084 instruct encodeHeapOop(rRegN dst, rRegP src, rFlagsReg cr) %{
6085 predicate(n->bottom_type()->make_ptr()->ptr() != TypePtr::NotNull);
6086 match(Set dst (EncodeP src));
6087 effect(KILL cr);
6088 format %{ "encode_heap_oop $dst,$src" %}
6089 ins_encode %{
6090 Register s = $src$$Register;
6091 Register d = $dst$$Register;
6092 if (s != d) {
6093 __ movq(d, s);
6094 }
6095 __ encode_heap_oop(d);
6096 %}
6097 ins_pipe(ialu_reg_long);
6098 %}
6099
6100 instruct encodeHeapOop_not_null(rRegN dst, rRegP src, rFlagsReg cr) %{
6101 predicate(n->bottom_type()->make_ptr()->ptr() == TypePtr::NotNull);
6102 match(Set dst (EncodeP src));
6103 effect(KILL cr);
6104 format %{ "encode_heap_oop_not_null $dst,$src" %}
6105 ins_encode %{
6106 __ encode_heap_oop_not_null($dst$$Register, $src$$Register);
6107 %}
6108 ins_pipe(ialu_reg_long);
6109 %}
6110
6111 instruct decodeHeapOop(rRegP dst, rRegN src, rFlagsReg cr) %{
6112 predicate(n->bottom_type()->is_ptr()->ptr() != TypePtr::NotNull &&
6113 n->bottom_type()->is_ptr()->ptr() != TypePtr::Constant);
6114 match(Set dst (DecodeN src));
6115 effect(KILL cr);
6116 format %{ "decode_heap_oop $dst,$src" %}
6117 ins_encode %{
6118 Register s = $src$$Register;
6119 Register d = $dst$$Register;
6120 if (s != d) {
6121 __ movq(d, s);
6122 }
6123 __ decode_heap_oop(d);
6124 %}
6125 ins_pipe(ialu_reg_long);
6126 %}
6127
6128 instruct decodeHeapOop_not_null(rRegP dst, rRegN src, rFlagsReg cr) %{
6129 predicate(n->bottom_type()->is_ptr()->ptr() == TypePtr::NotNull ||
6130 n->bottom_type()->is_ptr()->ptr() == TypePtr::Constant);
6131 match(Set dst (DecodeN src));
6132 effect(KILL cr);
6133 format %{ "decode_heap_oop_not_null $dst,$src" %}
6134 ins_encode %{
6135 Register s = $src$$Register;
6136 Register d = $dst$$Register;
6137 if (s != d) {
6138 __ decode_heap_oop_not_null(d, s);
6139 } else {
6140 __ decode_heap_oop_not_null(d);
6141 }
6142 %}
6143 ins_pipe(ialu_reg_long);
6144 %}
6145
6146 instruct encodeKlass_not_null(rRegN dst, rRegP src, rFlagsReg cr) %{
6147 match(Set dst (EncodePKlass src));
6148 effect(TEMP dst, KILL cr);
6149 format %{ "encode_and_move_klass_not_null $dst,$src" %}
6150 ins_encode %{
6151 __ encode_and_move_klass_not_null($dst$$Register, $src$$Register);
6152 %}
6153 ins_pipe(ialu_reg_long);
6154 %}
6155
6156 instruct decodeKlass_not_null(rRegP dst, rRegN src, rFlagsReg cr) %{
6157 match(Set dst (DecodeNKlass src));
6158 effect(TEMP dst, KILL cr);
6159 format %{ "decode_and_move_klass_not_null $dst,$src" %}
6160 ins_encode %{
6161 __ decode_and_move_klass_not_null($dst$$Register, $src$$Register);
6162 %}
6163 ins_pipe(ialu_reg_long);
6164 %}
6165
6166 //----------Conditional Move---------------------------------------------------
6167 // Jump
6168 // dummy instruction for generating temp registers
6169 instruct jumpXtnd_offset(rRegL switch_val, immI2 shift, rRegI dest) %{
6170 match(Jump (LShiftL switch_val shift));
6171 ins_cost(350);
6172 predicate(false);
6173 effect(TEMP dest);
6174
6175 format %{ "leaq $dest, [$constantaddress]\n\t"
6176 "jmp [$dest + $switch_val << $shift]\n\t" %}
6177 ins_encode %{
6178 // We could use jump(ArrayAddress) except that the macro assembler needs to use r10
6179 // to do that and the compiler is using that register as one it can allocate.
6180 // So we build it all by hand.
6181 // Address index(noreg, switch_reg, (Address::ScaleFactor)$shift$$constant);
6182 // ArrayAddress dispatch(table, index);
6183 Address dispatch($dest$$Register, $switch_val$$Register, (Address::ScaleFactor) $shift$$constant);
6184 __ lea($dest$$Register, $constantaddress);
6185 __ jmp(dispatch);
6186 %}
6187 ins_pipe(pipe_jmp);
6188 %}
6189
6190 instruct jumpXtnd_addr(rRegL switch_val, immI2 shift, immL32 offset, rRegI dest) %{
6191 match(Jump (AddL (LShiftL switch_val shift) offset));
6192 ins_cost(350);
6193 effect(TEMP dest);
6194
6195 format %{ "leaq $dest, [$constantaddress]\n\t"
6196 "jmp [$dest + $switch_val << $shift + $offset]\n\t" %}
6197 ins_encode %{
6198 // We could use jump(ArrayAddress) except that the macro assembler needs to use r10
6199 // to do that and the compiler is using that register as one it can allocate.
6200 // So we build it all by hand.
6201 // Address index(noreg, switch_reg, (Address::ScaleFactor) $shift$$constant, (int) $offset$$constant);
6202 // ArrayAddress dispatch(table, index);
6203 Address dispatch($dest$$Register, $switch_val$$Register, (Address::ScaleFactor) $shift$$constant, (int) $offset$$constant);
6204 __ lea($dest$$Register, $constantaddress);
6205 __ jmp(dispatch);
6206 %}
6207 ins_pipe(pipe_jmp);
6208 %}
6209
6210 instruct jumpXtnd(rRegL switch_val, rRegI dest) %{
6211 match(Jump switch_val);
6212 ins_cost(350);
6213 effect(TEMP dest);
6214
6215 format %{ "leaq $dest, [$constantaddress]\n\t"
6216 "jmp [$dest + $switch_val]\n\t" %}
6217 ins_encode %{
6218 // We could use jump(ArrayAddress) except that the macro assembler needs to use r10
6219 // to do that and the compiler is using that register as one it can allocate.
6220 // So we build it all by hand.
6221 // Address index(noreg, switch_reg, Address::times_1);
6222 // ArrayAddress dispatch(table, index);
6223 Address dispatch($dest$$Register, $switch_val$$Register, Address::times_1);
6224 __ lea($dest$$Register, $constantaddress);
6225 __ jmp(dispatch);
6226 %}
6227 ins_pipe(pipe_jmp);
6228 %}
6229
6230 // Conditional move
6231 instruct cmovI_imm_01(rRegI dst, immI_1 src, rFlagsReg cr, cmpOp cop)
6232 %{
6233 predicate(n->in(2)->in(2)->is_Con() && n->in(2)->in(2)->get_int() == 0);
6234 match(Set dst (CMoveI (Binary cop cr) (Binary src dst)));
6235
6236 ins_cost(100); // XXX
6237 format %{ "setbn$cop $dst\t# signed, int" %}
6238 ins_encode %{
6239 Assembler::Condition cond = (Assembler::Condition)($cop$$cmpcode);
6240 __ setb(MacroAssembler::negate_condition(cond), $dst$$Register);
6241 %}
6242 ins_pipe(ialu_reg);
6243 %}
6244
6245 instruct cmovI_reg(rRegI dst, rRegI src, rFlagsReg cr, cmpOp cop)
6246 %{
6247 predicate(!UseAPX);
6248 match(Set dst (CMoveI (Binary cop cr) (Binary dst src)));
6249
6250 ins_cost(200); // XXX
6251 format %{ "cmovl$cop $dst, $src\t# signed, int" %}
6252 ins_encode %{
6253 __ cmovl((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src$$Register);
6254 %}
6255 ins_pipe(pipe_cmov_reg);
6256 %}
6257
6258 instruct cmovI_reg_ndd(rRegI dst, rRegI src1, rRegI src2, rFlagsReg cr, cmpOp cop)
6259 %{
6260 predicate(UseAPX);
6261 match(Set dst (CMoveI (Binary cop cr) (Binary src1 src2)));
6262
6263 ins_cost(200);
6264 format %{ "ecmovl$cop $dst, $src1, $src2\t# signed, int ndd" %}
6265 ins_encode %{
6266 __ ecmovl((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src1$$Register, $src2$$Register);
6267 %}
6268 ins_pipe(pipe_cmov_reg);
6269 %}
6270
6271 instruct cmovI_imm_01U(rRegI dst, immI_1 src, rFlagsRegU cr, cmpOpU cop)
6272 %{
6273 predicate(n->in(2)->in(2)->is_Con() && n->in(2)->in(2)->get_int() == 0);
6274 match(Set dst (CMoveI (Binary cop cr) (Binary src dst)));
6275
6276 ins_cost(100); // XXX
6277 format %{ "setbn$cop $dst\t# unsigned, int" %}
6278 ins_encode %{
6279 Assembler::Condition cond = (Assembler::Condition)($cop$$cmpcode);
6280 __ setb(MacroAssembler::negate_condition(cond), $dst$$Register);
6281 %}
6282 ins_pipe(ialu_reg);
6283 %}
6284
6285 instruct cmovI_regU(cmpOpU cop, rFlagsRegU cr, rRegI dst, rRegI src) %{
6286 predicate(!UseAPX);
6287 match(Set dst (CMoveI (Binary cop cr) (Binary dst src)));
6288
6289 ins_cost(200); // XXX
6290 format %{ "cmovl$cop $dst, $src\t# unsigned, int" %}
6291 ins_encode %{
6292 __ cmovl((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src$$Register);
6293 %}
6294 ins_pipe(pipe_cmov_reg);
6295 %}
6296
6297 instruct cmovI_regU_ndd(rRegI dst, cmpOpU cop, rFlagsRegU cr, rRegI src1, rRegI src2) %{
6298 predicate(UseAPX);
6299 match(Set dst (CMoveI (Binary cop cr) (Binary src1 src2)));
6300
6301 ins_cost(200);
6302 format %{ "ecmovl$cop $dst, $src1, $src2\t# unsigned, int ndd" %}
6303 ins_encode %{
6304 __ ecmovl((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src1$$Register, $src2$$Register);
6305 %}
6306 ins_pipe(pipe_cmov_reg);
6307 %}
6308
6309 instruct cmovI_imm_01UCF(rRegI dst, immI_1 src, rFlagsRegUCF cr, cmpOpUCF cop)
6310 %{
6311 predicate(n->in(2)->in(2)->is_Con() && n->in(2)->in(2)->get_int() == 0);
6312 match(Set dst (CMoveI (Binary cop cr) (Binary src dst)));
6313
6314 ins_cost(100); // XXX
6315 format %{ "setbn$cop $dst\t# unsigned, int" %}
6316 ins_encode %{
6317 Assembler::Condition cond = (Assembler::Condition)($cop$$cmpcode);
6318 __ setb(MacroAssembler::negate_condition(cond), $dst$$Register);
6319 %}
6320 ins_pipe(ialu_reg);
6321 %}
6322
6323 instruct cmovI_regUCF(cmpOpUCF cop, rFlagsRegUCF cr, rRegI dst, rRegI src) %{
6324 predicate(!UseAPX);
6325 match(Set dst (CMoveI (Binary cop cr) (Binary dst src)));
6326 ins_cost(200);
6327 expand %{
6328 cmovI_regU(cop, cr, dst, src);
6329 %}
6330 %}
6331
6332 instruct cmovI_regUCF_ndd(rRegI dst, cmpOpUCF cop, rFlagsRegUCF cr, rRegI src1, rRegI src2) %{
6333 predicate(UseAPX);
6334 match(Set dst (CMoveI (Binary cop cr) (Binary src1 src2)));
6335 ins_cost(200);
6336 format %{ "ecmovl$cop $dst, $src1, $src2\t# unsigned, int ndd" %}
6337 ins_encode %{
6338 __ ecmovl((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src1$$Register, $src2$$Register);
6339 %}
6340 ins_pipe(pipe_cmov_reg);
6341 %}
6342
6343 instruct cmovI_regUCF2_ne(cmpOpUCF2 cop, rFlagsRegUCF cr, rRegI dst, rRegI src) %{
6344 predicate(!UseAPX && n->in(1)->in(1)->as_Bool()->_test._test == BoolTest::ne);
6345 match(Set dst (CMoveI (Binary cop cr) (Binary dst src)));
6346
6347 ins_cost(200); // XXX
6348 format %{ "cmovpl $dst, $src\n\t"
6349 "cmovnel $dst, $src" %}
6350 ins_encode %{
6351 __ cmovl(Assembler::parity, $dst$$Register, $src$$Register);
6352 __ cmovl(Assembler::notEqual, $dst$$Register, $src$$Register);
6353 %}
6354 ins_pipe(pipe_cmov_reg);
6355 %}
6356
6357 instruct cmovI_regUCF2_ne_ndd(cmpOpUCF2 cop, rFlagsRegUCF cr, rRegI dst, rRegI src1, rRegI src2) %{
6358 predicate(UseAPX && n->in(1)->in(1)->as_Bool()->_test._test == BoolTest::ne);
6359 match(Set dst (CMoveI (Binary cop cr) (Binary src1 src2)));
6360 effect(TEMP dst);
6361
6362 ins_cost(200);
6363 format %{ "ecmovpl $dst, $src1, $src2\n\t"
6364 "cmovnel $dst, $src2" %}
6365 ins_encode %{
6366 __ ecmovl(Assembler::parity, $dst$$Register, $src1$$Register, $src2$$Register);
6367 __ cmovl(Assembler::notEqual, $dst$$Register, $src2$$Register);
6368 %}
6369 ins_pipe(pipe_cmov_reg);
6370 %}
6371
6372 // Since (x == y) == !(x != y), we can flip the sense of the test by flipping the
6373 // inputs of the CMove
6374 instruct cmovI_regUCF2_eq(cmpOpUCF2 cop, rFlagsRegUCF cr, rRegI dst, rRegI src) %{
6375 predicate(!UseAPX && n->in(1)->in(1)->as_Bool()->_test._test == BoolTest::eq);
6376 match(Set dst (CMoveI (Binary cop cr) (Binary src dst)));
6377 effect(TEMP dst);
6378
6379 ins_cost(200); // XXX
6380 format %{ "cmovpl $dst, $src\n\t"
6381 "cmovnel $dst, $src" %}
6382 ins_encode %{
6383 __ cmovl(Assembler::parity, $dst$$Register, $src$$Register);
6384 __ cmovl(Assembler::notEqual, $dst$$Register, $src$$Register);
6385 %}
6386 ins_pipe(pipe_cmov_reg);
6387 %}
6388
6389 // We need this special handling for only eq / neq comparison since NaN == NaN is false,
6390 // and parity flag bit is set if any of the operand is a NaN.
6391 instruct cmovI_regUCF2_eq_ndd(cmpOpUCF2 cop, rFlagsRegUCF cr, rRegI dst, rRegI src1, rRegI src2) %{
6392 predicate(UseAPX && n->in(1)->in(1)->as_Bool()->_test._test == BoolTest::eq);
6393 match(Set dst (CMoveI (Binary cop cr) (Binary src2 src1)));
6394 effect(TEMP dst);
6395
6396 ins_cost(200);
6397 format %{ "ecmovpl $dst, $src1, $src2\n\t"
6398 "cmovnel $dst, $src2" %}
6399 ins_encode %{
6400 __ ecmovl(Assembler::parity, $dst$$Register, $src1$$Register, $src2$$Register);
6401 __ cmovl(Assembler::notEqual, $dst$$Register, $src2$$Register);
6402 %}
6403 ins_pipe(pipe_cmov_reg);
6404 %}
6405
6406 // Conditional move
6407 instruct cmovI_mem(cmpOp cop, rFlagsReg cr, rRegI dst, memory src) %{
6408 predicate(!UseAPX);
6409 match(Set dst (CMoveI (Binary cop cr) (Binary dst (LoadI src))));
6410
6411 ins_cost(250); // XXX
6412 format %{ "cmovl$cop $dst, $src\t# signed, int" %}
6413 ins_encode %{
6414 __ cmovl((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src$$Address);
6415 %}
6416 ins_pipe(pipe_cmov_mem);
6417 %}
6418
6419 // Conditional move
6420 instruct cmovI_rReg_rReg_mem_ndd(rRegI dst, cmpOp cop, rFlagsReg cr, rRegI src1, memory src2)
6421 %{
6422 predicate(UseAPX);
6423 match(Set dst (CMoveI (Binary cop cr) (Binary src1 (LoadI src2))));
6424
6425 ins_cost(250);
6426 format %{ "ecmovl$cop $dst, $src1, $src2\t# signed, int ndd" %}
6427 ins_encode %{
6428 __ ecmovl((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src1$$Register, $src2$$Address);
6429 %}
6430 ins_pipe(pipe_cmov_mem);
6431 %}
6432
6433 // Conditional move
6434 instruct cmovI_memU(cmpOpU cop, rFlagsRegU cr, rRegI dst, memory src)
6435 %{
6436 predicate(!UseAPX);
6437 match(Set dst (CMoveI (Binary cop cr) (Binary dst (LoadI src))));
6438
6439 ins_cost(250); // XXX
6440 format %{ "cmovl$cop $dst, $src\t# unsigned, int" %}
6441 ins_encode %{
6442 __ cmovl((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src$$Address);
6443 %}
6444 ins_pipe(pipe_cmov_mem);
6445 %}
6446
6447 instruct cmovI_memUCF(cmpOpUCF cop, rFlagsRegUCF cr, rRegI dst, memory src) %{
6448 predicate(!UseAPX);
6449 match(Set dst (CMoveI (Binary cop cr) (Binary dst (LoadI src))));
6450 ins_cost(250);
6451 expand %{
6452 cmovI_memU(cop, cr, dst, src);
6453 %}
6454 %}
6455
6456 instruct cmovI_rReg_rReg_memU_ndd(rRegI dst, cmpOpU cop, rFlagsRegU cr, rRegI src1, memory src2)
6457 %{
6458 predicate(UseAPX);
6459 match(Set dst (CMoveI (Binary cop cr) (Binary src1 (LoadI src2))));
6460
6461 ins_cost(250);
6462 format %{ "ecmovl$cop $dst, $src1, $src2\t# unsigned, int ndd" %}
6463 ins_encode %{
6464 __ ecmovl((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src1$$Register, $src2$$Address);
6465 %}
6466 ins_pipe(pipe_cmov_mem);
6467 %}
6468
6469 instruct cmovI_rReg_rReg_memUCF_ndd(rRegI dst, cmpOpUCF cop, rFlagsRegUCF cr, rRegI src1, memory src2)
6470 %{
6471 predicate(UseAPX);
6472 match(Set dst (CMoveI (Binary cop cr) (Binary src1 (LoadI src2))));
6473 ins_cost(250);
6474 format %{ "ecmovl$cop $dst, $src1, $src2\t# unsigned, int ndd" %}
6475 ins_encode %{
6476 __ ecmovl((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src1$$Register, $src2$$Address);
6477 %}
6478 ins_pipe(pipe_cmov_mem);
6479 %}
6480
6481 // Conditional move
6482 instruct cmovN_reg(rRegN dst, rRegN src, rFlagsReg cr, cmpOp cop)
6483 %{
6484 predicate(!UseAPX);
6485 match(Set dst (CMoveN (Binary cop cr) (Binary dst src)));
6486
6487 ins_cost(200); // XXX
6488 format %{ "cmovl$cop $dst, $src\t# signed, compressed ptr" %}
6489 ins_encode %{
6490 __ cmovl((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src$$Register);
6491 %}
6492 ins_pipe(pipe_cmov_reg);
6493 %}
6494
6495 // Conditional move ndd
6496 instruct cmovN_reg_ndd(rRegN dst, rRegN src1, rRegN src2, rFlagsReg cr, cmpOp cop)
6497 %{
6498 predicate(UseAPX);
6499 match(Set dst (CMoveN (Binary cop cr) (Binary src1 src2)));
6500
6501 ins_cost(200);
6502 format %{ "ecmovl$cop $dst, $src1, $src2\t# signed, compressed ptr ndd" %}
6503 ins_encode %{
6504 __ ecmovl((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src1$$Register, $src2$$Register);
6505 %}
6506 ins_pipe(pipe_cmov_reg);
6507 %}
6508
6509 // Conditional move
6510 instruct cmovN_regU(cmpOpU cop, rFlagsRegU cr, rRegN dst, rRegN src)
6511 %{
6512 predicate(!UseAPX);
6513 match(Set dst (CMoveN (Binary cop cr) (Binary dst src)));
6514
6515 ins_cost(200); // XXX
6516 format %{ "cmovl$cop $dst, $src\t# unsigned, compressed ptr" %}
6517 ins_encode %{
6518 __ cmovl((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src$$Register);
6519 %}
6520 ins_pipe(pipe_cmov_reg);
6521 %}
6522
6523 instruct cmovN_regUCF(cmpOpUCF cop, rFlagsRegUCF cr, rRegN dst, rRegN src) %{
6524 predicate(!UseAPX);
6525 match(Set dst (CMoveN (Binary cop cr) (Binary dst src)));
6526 ins_cost(200);
6527 expand %{
6528 cmovN_regU(cop, cr, dst, src);
6529 %}
6530 %}
6531
6532 // Conditional move ndd
6533 instruct cmovN_regU_ndd(rRegN dst, cmpOpU cop, rFlagsRegU cr, rRegN src1, rRegN src2)
6534 %{
6535 predicate(UseAPX);
6536 match(Set dst (CMoveN (Binary cop cr) (Binary src1 src2)));
6537
6538 ins_cost(200);
6539 format %{ "ecmovl$cop $dst, $src1, $src2\t# unsigned, compressed ptr ndd" %}
6540 ins_encode %{
6541 __ ecmovl((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src1$$Register, $src2$$Register);
6542 %}
6543 ins_pipe(pipe_cmov_reg);
6544 %}
6545
6546 instruct cmovN_regUCF_ndd(rRegN dst, cmpOpUCF cop, rFlagsRegUCF cr, rRegN src1, rRegN src2) %{
6547 predicate(UseAPX);
6548 match(Set dst (CMoveN (Binary cop cr) (Binary src1 src2)));
6549 ins_cost(200);
6550 format %{ "ecmovl$cop $dst, $src1, $src2\t# unsigned, compressed ptr ndd" %}
6551 ins_encode %{
6552 __ ecmovl((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src1$$Register, $src2$$Register);
6553 %}
6554 ins_pipe(pipe_cmov_reg);
6555 %}
6556
6557 instruct cmovN_regUCF2_ne(cmpOpUCF2 cop, rFlagsRegUCF cr, rRegN dst, rRegN src) %{
6558 predicate(n->in(1)->in(1)->as_Bool()->_test._test == BoolTest::ne);
6559 match(Set dst (CMoveN (Binary cop cr) (Binary dst src)));
6560
6561 ins_cost(200); // XXX
6562 format %{ "cmovpl $dst, $src\n\t"
6563 "cmovnel $dst, $src" %}
6564 ins_encode %{
6565 __ cmovl(Assembler::parity, $dst$$Register, $src$$Register);
6566 __ cmovl(Assembler::notEqual, $dst$$Register, $src$$Register);
6567 %}
6568 ins_pipe(pipe_cmov_reg);
6569 %}
6570
6571 // Since (x == y) == !(x != y), we can flip the sense of the test by flipping the
6572 // inputs of the CMove
6573 instruct cmovN_regUCF2_eq(cmpOpUCF2 cop, rFlagsRegUCF cr, rRegN dst, rRegN src) %{
6574 predicate(n->in(1)->in(1)->as_Bool()->_test._test == BoolTest::eq);
6575 match(Set dst (CMoveN (Binary cop cr) (Binary src dst)));
6576
6577 ins_cost(200); // XXX
6578 format %{ "cmovpl $dst, $src\n\t"
6579 "cmovnel $dst, $src" %}
6580 ins_encode %{
6581 __ cmovl(Assembler::parity, $dst$$Register, $src$$Register);
6582 __ cmovl(Assembler::notEqual, $dst$$Register, $src$$Register);
6583 %}
6584 ins_pipe(pipe_cmov_reg);
6585 %}
6586
6587 // Conditional move
6588 instruct cmovP_reg(rRegP dst, rRegP src, rFlagsReg cr, cmpOp cop)
6589 %{
6590 predicate(!UseAPX);
6591 match(Set dst (CMoveP (Binary cop cr) (Binary dst src)));
6592
6593 ins_cost(200); // XXX
6594 format %{ "cmovq$cop $dst, $src\t# signed, ptr" %}
6595 ins_encode %{
6596 __ cmovq((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src$$Register);
6597 %}
6598 ins_pipe(pipe_cmov_reg); // XXX
6599 %}
6600
6601 // Conditional move ndd
6602 instruct cmovP_reg_ndd(rRegP dst, rRegP src1, rRegP src2, rFlagsReg cr, cmpOp cop)
6603 %{
6604 predicate(UseAPX);
6605 match(Set dst (CMoveP (Binary cop cr) (Binary src1 src2)));
6606
6607 ins_cost(200);
6608 format %{ "ecmovq$cop $dst, $src1, $src2\t# signed, ptr ndd" %}
6609 ins_encode %{
6610 __ ecmovq((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src1$$Register, $src2$$Register);
6611 %}
6612 ins_pipe(pipe_cmov_reg);
6613 %}
6614
6615 // Conditional move
6616 instruct cmovP_regU(cmpOpU cop, rFlagsRegU cr, rRegP dst, rRegP src)
6617 %{
6618 predicate(!UseAPX);
6619 match(Set dst (CMoveP (Binary cop cr) (Binary dst src)));
6620
6621 ins_cost(200); // XXX
6622 format %{ "cmovq$cop $dst, $src\t# unsigned, ptr" %}
6623 ins_encode %{
6624 __ cmovq((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src$$Register);
6625 %}
6626 ins_pipe(pipe_cmov_reg); // XXX
6627 %}
6628
6629 // Conditional move ndd
6630 instruct cmovP_regU_ndd(rRegP dst, cmpOpU cop, rFlagsRegU cr, rRegP src1, rRegP src2)
6631 %{
6632 predicate(UseAPX);
6633 match(Set dst (CMoveP (Binary cop cr) (Binary src1 src2)));
6634
6635 ins_cost(200);
6636 format %{ "ecmovq$cop $dst, $src1, $src2\t# unsigned, ptr ndd" %}
6637 ins_encode %{
6638 __ ecmovq((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src1$$Register, $src2$$Register);
6639 %}
6640 ins_pipe(pipe_cmov_reg);
6641 %}
6642
6643 instruct cmovP_regUCF(cmpOpUCF cop, rFlagsRegUCF cr, rRegP dst, rRegP src) %{
6644 predicate(!UseAPX);
6645 match(Set dst (CMoveP (Binary cop cr) (Binary dst src)));
6646 ins_cost(200);
6647 expand %{
6648 cmovP_regU(cop, cr, dst, src);
6649 %}
6650 %}
6651
6652 instruct cmovP_regUCF_ndd(rRegP dst, cmpOpUCF cop, rFlagsRegUCF cr, rRegP src1, rRegP src2) %{
6653 predicate(UseAPX);
6654 match(Set dst (CMoveP (Binary cop cr) (Binary src1 src2)));
6655 ins_cost(200);
6656 format %{ "ecmovq$cop $dst, $src1, $src2\t# unsigned, ptr ndd" %}
6657 ins_encode %{
6658 __ ecmovq((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src1$$Register, $src2$$Register);
6659 %}
6660 ins_pipe(pipe_cmov_reg);
6661 %}
6662
6663 instruct cmovP_regUCF2_ne(cmpOpUCF2 cop, rFlagsRegUCF cr, rRegP dst, rRegP src) %{
6664 predicate(!UseAPX && n->in(1)->in(1)->as_Bool()->_test._test == BoolTest::ne);
6665 match(Set dst (CMoveP (Binary cop cr) (Binary dst src)));
6666
6667 ins_cost(200); // XXX
6668 format %{ "cmovpq $dst, $src\n\t"
6669 "cmovneq $dst, $src" %}
6670 ins_encode %{
6671 __ cmovq(Assembler::parity, $dst$$Register, $src$$Register);
6672 __ cmovq(Assembler::notEqual, $dst$$Register, $src$$Register);
6673 %}
6674 ins_pipe(pipe_cmov_reg);
6675 %}
6676
6677 instruct cmovP_regUCF2_ne_ndd(cmpOpUCF2 cop, rFlagsRegUCF cr, rRegP dst, rRegP src1, rRegP src2) %{
6678 predicate(UseAPX && n->in(1)->in(1)->as_Bool()->_test._test == BoolTest::ne);
6679 match(Set dst (CMoveP (Binary cop cr) (Binary src1 src2)));
6680 effect(TEMP dst);
6681
6682 ins_cost(200);
6683 format %{ "ecmovpq $dst, $src1, $src2\n\t"
6684 "cmovneq $dst, $src2" %}
6685 ins_encode %{
6686 __ ecmovq(Assembler::parity, $dst$$Register, $src1$$Register, $src2$$Register);
6687 __ cmovq(Assembler::notEqual, $dst$$Register, $src2$$Register);
6688 %}
6689 ins_pipe(pipe_cmov_reg);
6690 %}
6691
6692 // Since (x == y) == !(x != y), we can flip the sense of the test by flipping the
6693 // inputs of the CMove
6694 instruct cmovP_regUCF2_eq(cmpOpUCF2 cop, rFlagsRegUCF cr, rRegP dst, rRegP src) %{
6695 predicate(!UseAPX && n->in(1)->in(1)->as_Bool()->_test._test == BoolTest::eq);
6696 match(Set dst (CMoveP (Binary cop cr) (Binary src dst)));
6697
6698 ins_cost(200); // XXX
6699 format %{ "cmovpq $dst, $src\n\t"
6700 "cmovneq $dst, $src" %}
6701 ins_encode %{
6702 __ cmovq(Assembler::parity, $dst$$Register, $src$$Register);
6703 __ cmovq(Assembler::notEqual, $dst$$Register, $src$$Register);
6704 %}
6705 ins_pipe(pipe_cmov_reg);
6706 %}
6707
6708 instruct cmovP_regUCF2_eq_ndd(cmpOpUCF2 cop, rFlagsRegUCF cr, rRegP dst, rRegP src1, rRegP src2) %{
6709 predicate(UseAPX && n->in(1)->in(1)->as_Bool()->_test._test == BoolTest::eq);
6710 match(Set dst (CMoveP (Binary cop cr) (Binary src2 src1)));
6711 effect(TEMP dst);
6712
6713 ins_cost(200);
6714 format %{ "ecmovpq $dst, $src1, $src2\n\t"
6715 "cmovneq $dst, $src2" %}
6716 ins_encode %{
6717 __ ecmovq(Assembler::parity, $dst$$Register, $src1$$Register, $src2$$Register);
6718 __ cmovq(Assembler::notEqual, $dst$$Register, $src2$$Register);
6719 %}
6720 ins_pipe(pipe_cmov_reg);
6721 %}
6722
6723 instruct cmovL_imm_01(rRegL dst, immL1 src, rFlagsReg cr, cmpOp cop)
6724 %{
6725 predicate(n->in(2)->in(2)->is_Con() && n->in(2)->in(2)->get_long() == 0);
6726 match(Set dst (CMoveL (Binary cop cr) (Binary src dst)));
6727
6728 ins_cost(100); // XXX
6729 format %{ "setbn$cop $dst\t# signed, long" %}
6730 ins_encode %{
6731 Assembler::Condition cond = (Assembler::Condition)($cop$$cmpcode);
6732 __ setb(MacroAssembler::negate_condition(cond), $dst$$Register);
6733 %}
6734 ins_pipe(ialu_reg);
6735 %}
6736
6737 instruct cmovL_reg(cmpOp cop, rFlagsReg cr, rRegL dst, rRegL src)
6738 %{
6739 predicate(!UseAPX);
6740 match(Set dst (CMoveL (Binary cop cr) (Binary dst src)));
6741
6742 ins_cost(200); // XXX
6743 format %{ "cmovq$cop $dst, $src\t# signed, long" %}
6744 ins_encode %{
6745 __ cmovq((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src$$Register);
6746 %}
6747 ins_pipe(pipe_cmov_reg); // XXX
6748 %}
6749
6750 instruct cmovL_reg_ndd(rRegL dst, cmpOp cop, rFlagsReg cr, rRegL src1, rRegL src2)
6751 %{
6752 predicate(UseAPX);
6753 match(Set dst (CMoveL (Binary cop cr) (Binary src1 src2)));
6754
6755 ins_cost(200);
6756 format %{ "ecmovq$cop $dst, $src1, $src2\t# signed, long ndd" %}
6757 ins_encode %{
6758 __ ecmovq((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src1$$Register, $src2$$Register);
6759 %}
6760 ins_pipe(pipe_cmov_reg);
6761 %}
6762
6763 instruct cmovL_mem(cmpOp cop, rFlagsReg cr, rRegL dst, memory src)
6764 %{
6765 predicate(!UseAPX);
6766 match(Set dst (CMoveL (Binary cop cr) (Binary dst (LoadL src))));
6767
6768 ins_cost(200); // XXX
6769 format %{ "cmovq$cop $dst, $src\t# signed, long" %}
6770 ins_encode %{
6771 __ cmovq((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src$$Address);
6772 %}
6773 ins_pipe(pipe_cmov_mem); // XXX
6774 %}
6775
6776 instruct cmovL_rReg_rReg_mem_ndd(rRegL dst, cmpOp cop, rFlagsReg cr, rRegL src1, memory src2)
6777 %{
6778 predicate(UseAPX);
6779 match(Set dst (CMoveL (Binary cop cr) (Binary src1 (LoadL src2))));
6780
6781 ins_cost(200);
6782 format %{ "ecmovq$cop $dst, $src1, $src2\t# signed, long ndd" %}
6783 ins_encode %{
6784 __ ecmovq((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src1$$Register, $src2$$Address);
6785 %}
6786 ins_pipe(pipe_cmov_mem);
6787 %}
6788
6789 instruct cmovL_imm_01U(rRegL dst, immL1 src, rFlagsRegU cr, cmpOpU cop)
6790 %{
6791 predicate(n->in(2)->in(2)->is_Con() && n->in(2)->in(2)->get_long() == 0);
6792 match(Set dst (CMoveL (Binary cop cr) (Binary src dst)));
6793
6794 ins_cost(100); // XXX
6795 format %{ "setbn$cop $dst\t# unsigned, long" %}
6796 ins_encode %{
6797 Assembler::Condition cond = (Assembler::Condition)($cop$$cmpcode);
6798 __ setb(MacroAssembler::negate_condition(cond), $dst$$Register);
6799 %}
6800 ins_pipe(ialu_reg);
6801 %}
6802
6803 instruct cmovL_regU(cmpOpU cop, rFlagsRegU cr, rRegL dst, rRegL src)
6804 %{
6805 predicate(!UseAPX);
6806 match(Set dst (CMoveL (Binary cop cr) (Binary dst src)));
6807
6808 ins_cost(200); // XXX
6809 format %{ "cmovq$cop $dst, $src\t# unsigned, long" %}
6810 ins_encode %{
6811 __ cmovq((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src$$Register);
6812 %}
6813 ins_pipe(pipe_cmov_reg); // XXX
6814 %}
6815
6816 instruct cmovL_regU_ndd(rRegL dst, cmpOpU cop, rFlagsRegU cr, rRegL src1, rRegL src2)
6817 %{
6818 predicate(UseAPX);
6819 match(Set dst (CMoveL (Binary cop cr) (Binary src1 src2)));
6820
6821 ins_cost(200);
6822 format %{ "ecmovq$cop $dst, $src1, $src2\t# unsigned, long ndd" %}
6823 ins_encode %{
6824 __ ecmovq((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src1$$Register, $src2$$Register);
6825 %}
6826 ins_pipe(pipe_cmov_reg);
6827 %}
6828
6829 instruct cmovL_imm_01UCF(rRegL dst, immL1 src, rFlagsRegUCF cr, cmpOpUCF cop)
6830 %{
6831 predicate(n->in(2)->in(2)->is_Con() && n->in(2)->in(2)->get_long() == 0);
6832 match(Set dst (CMoveL (Binary cop cr) (Binary src dst)));
6833
6834 ins_cost(100); // XXX
6835 format %{ "setbn$cop $dst\t# unsigned, long" %}
6836 ins_encode %{
6837 Assembler::Condition cond = (Assembler::Condition)($cop$$cmpcode);
6838 __ setb(MacroAssembler::negate_condition(cond), $dst$$Register);
6839 %}
6840 ins_pipe(ialu_reg);
6841 %}
6842
6843 instruct cmovL_regUCF(cmpOpUCF cop, rFlagsRegUCF cr, rRegL dst, rRegL src) %{
6844 predicate(!UseAPX);
6845 match(Set dst (CMoveL (Binary cop cr) (Binary dst src)));
6846 ins_cost(200);
6847 expand %{
6848 cmovL_regU(cop, cr, dst, src);
6849 %}
6850 %}
6851
6852 instruct cmovL_regUCF_ndd(rRegL dst, cmpOpUCF cop, rFlagsRegUCF cr, rRegL src1, rRegL src2)
6853 %{
6854 predicate(UseAPX);
6855 match(Set dst (CMoveL (Binary cop cr) (Binary src1 src2)));
6856 ins_cost(200);
6857 format %{ "ecmovq$cop $dst, $src1, $src2\t# unsigned, long ndd" %}
6858 ins_encode %{
6859 __ ecmovq((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src1$$Register, $src2$$Register);
6860 %}
6861 ins_pipe(pipe_cmov_reg);
6862 %}
6863
6864 instruct cmovL_regUCF2_ne(cmpOpUCF2 cop, rFlagsRegUCF cr, rRegL dst, rRegL src) %{
6865 predicate(!UseAPX && n->in(1)->in(1)->as_Bool()->_test._test == BoolTest::ne);
6866 match(Set dst (CMoveL (Binary cop cr) (Binary dst src)));
6867
6868 ins_cost(200); // XXX
6869 format %{ "cmovpq $dst, $src\n\t"
6870 "cmovneq $dst, $src" %}
6871 ins_encode %{
6872 __ cmovq(Assembler::parity, $dst$$Register, $src$$Register);
6873 __ cmovq(Assembler::notEqual, $dst$$Register, $src$$Register);
6874 %}
6875 ins_pipe(pipe_cmov_reg);
6876 %}
6877
6878 instruct cmovL_regUCF2_ne_ndd(cmpOpUCF2 cop, rFlagsRegUCF cr, rRegL dst, rRegL src1, rRegL src2) %{
6879 predicate(UseAPX && n->in(1)->in(1)->as_Bool()->_test._test == BoolTest::ne);
6880 match(Set dst (CMoveL (Binary cop cr) (Binary src1 src2)));
6881 effect(TEMP dst);
6882
6883 ins_cost(200);
6884 format %{ "ecmovpq $dst, $src1, $src2\n\t"
6885 "cmovneq $dst, $src2" %}
6886 ins_encode %{
6887 __ ecmovq(Assembler::parity, $dst$$Register, $src1$$Register, $src2$$Register);
6888 __ cmovq(Assembler::notEqual, $dst$$Register, $src2$$Register);
6889 %}
6890 ins_pipe(pipe_cmov_reg);
6891 %}
6892
6893 // Since (x == y) == !(x != y), we can flip the sense of the test by flipping the
6894 // inputs of the CMove
6895 instruct cmovL_regUCF2_eq(cmpOpUCF2 cop, rFlagsRegUCF cr, rRegL dst, rRegL src) %{
6896 predicate(!UseAPX && n->in(1)->in(1)->as_Bool()->_test._test == BoolTest::eq);
6897 match(Set dst (CMoveL (Binary cop cr) (Binary src dst)));
6898
6899 ins_cost(200); // XXX
6900 format %{ "cmovpq $dst, $src\n\t"
6901 "cmovneq $dst, $src" %}
6902 ins_encode %{
6903 __ cmovq(Assembler::parity, $dst$$Register, $src$$Register);
6904 __ cmovq(Assembler::notEqual, $dst$$Register, $src$$Register);
6905 %}
6906 ins_pipe(pipe_cmov_reg);
6907 %}
6908
6909 instruct cmovL_regUCF2_eq_ndd(cmpOpUCF2 cop, rFlagsRegUCF cr, rRegL dst, rRegL src1, rRegL src2) %{
6910 predicate(UseAPX && n->in(1)->in(1)->as_Bool()->_test._test == BoolTest::eq);
6911 match(Set dst (CMoveL (Binary cop cr) (Binary src2 src1)));
6912 effect(TEMP dst);
6913
6914 ins_cost(200);
6915 format %{ "ecmovpq $dst, $src1, $src2\n\t"
6916 "cmovneq $dst, $src2" %}
6917 ins_encode %{
6918 __ ecmovq(Assembler::parity, $dst$$Register, $src1$$Register, $src2$$Register);
6919 __ cmovq(Assembler::notEqual, $dst$$Register, $src2$$Register);
6920 %}
6921 ins_pipe(pipe_cmov_reg);
6922 %}
6923
6924 instruct cmovL_memU(cmpOpU cop, rFlagsRegU cr, rRegL dst, memory src)
6925 %{
6926 predicate(!UseAPX);
6927 match(Set dst (CMoveL (Binary cop cr) (Binary dst (LoadL src))));
6928
6929 ins_cost(200); // XXX
6930 format %{ "cmovq$cop $dst, $src\t# unsigned, long" %}
6931 ins_encode %{
6932 __ cmovq((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src$$Address);
6933 %}
6934 ins_pipe(pipe_cmov_mem); // XXX
6935 %}
6936
6937 instruct cmovL_memUCF(cmpOpUCF cop, rFlagsRegUCF cr, rRegL dst, memory src) %{
6938 predicate(!UseAPX);
6939 match(Set dst (CMoveL (Binary cop cr) (Binary dst (LoadL src))));
6940 ins_cost(200);
6941 expand %{
6942 cmovL_memU(cop, cr, dst, src);
6943 %}
6944 %}
6945
6946 instruct cmovL_rReg_rReg_memU_ndd(rRegL dst, cmpOpU cop, rFlagsRegU cr, rRegL src1, memory src2)
6947 %{
6948 predicate(UseAPX);
6949 match(Set dst (CMoveL (Binary cop cr) (Binary src1 (LoadL src2))));
6950
6951 ins_cost(200);
6952 format %{ "ecmovq$cop $dst, $src1, $src2\t# unsigned, long ndd" %}
6953 ins_encode %{
6954 __ ecmovq((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src1$$Register, $src2$$Address);
6955 %}
6956 ins_pipe(pipe_cmov_mem);
6957 %}
6958
6959 instruct cmovL_rReg_rReg_memUCF_ndd(rRegL dst, cmpOpUCF cop, rFlagsRegUCF cr, rRegL src1, memory src2)
6960 %{
6961 predicate(UseAPX);
6962 match(Set dst (CMoveL (Binary cop cr) (Binary src1 (LoadL src2))));
6963 ins_cost(200);
6964 format %{ "ecmovq$cop $dst, $src1, $src2\t# unsigned, long ndd" %}
6965 ins_encode %{
6966 __ ecmovq((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src1$$Register, $src2$$Address);
6967 %}
6968 ins_pipe(pipe_cmov_mem);
6969 %}
6970
6971 instruct cmovF_reg(cmpOp cop, rFlagsReg cr, regF dst, regF src)
6972 %{
6973 match(Set dst (CMoveF (Binary cop cr) (Binary dst src)));
6974
6975 ins_cost(200); // XXX
6976 format %{ "jn$cop skip\t# signed cmove float\n\t"
6977 "movss $dst, $src\n"
6978 "skip:" %}
6979 ins_encode %{
6980 Label Lskip;
6981 // Invert sense of branch from sense of CMOV
6982 __ jccb((Assembler::Condition)($cop$$cmpcode^1), Lskip);
6983 __ movflt($dst$$XMMRegister, $src$$XMMRegister);
6984 __ bind(Lskip);
6985 %}
6986 ins_pipe(pipe_slow);
6987 %}
6988
6989 instruct cmovF_regU(cmpOpU cop, rFlagsRegU cr, regF dst, regF src)
6990 %{
6991 match(Set dst (CMoveF (Binary cop cr) (Binary dst src)));
6992
6993 ins_cost(200); // XXX
6994 format %{ "jn$cop skip\t# unsigned cmove float\n\t"
6995 "movss $dst, $src\n"
6996 "skip:" %}
6997 ins_encode %{
6998 Label Lskip;
6999 // Invert sense of branch from sense of CMOV
7000 __ jccb((Assembler::Condition)($cop$$cmpcode^1), Lskip);
7001 __ movflt($dst$$XMMRegister, $src$$XMMRegister);
7002 __ bind(Lskip);
7003 %}
7004 ins_pipe(pipe_slow);
7005 %}
7006
7007 instruct cmovF_regUCF(cmpOpUCF cop, rFlagsRegUCF cr, regF dst, regF src) %{
7008 match(Set dst (CMoveF (Binary cop cr) (Binary dst src)));
7009 ins_cost(200);
7010 expand %{
7011 cmovF_regU(cop, cr, dst, src);
7012 %}
7013 %}
7014
7015 instruct cmovD_reg(cmpOp cop, rFlagsReg cr, regD dst, regD src)
7016 %{
7017 match(Set dst (CMoveD (Binary cop cr) (Binary dst src)));
7018
7019 ins_cost(200); // XXX
7020 format %{ "jn$cop skip\t# signed cmove double\n\t"
7021 "movsd $dst, $src\n"
7022 "skip:" %}
7023 ins_encode %{
7024 Label Lskip;
7025 // Invert sense of branch from sense of CMOV
7026 __ jccb((Assembler::Condition)($cop$$cmpcode^1), Lskip);
7027 __ movdbl($dst$$XMMRegister, $src$$XMMRegister);
7028 __ bind(Lskip);
7029 %}
7030 ins_pipe(pipe_slow);
7031 %}
7032
7033 instruct cmovD_regU(cmpOpU cop, rFlagsRegU cr, regD dst, regD src)
7034 %{
7035 match(Set dst (CMoveD (Binary cop cr) (Binary dst src)));
7036
7037 ins_cost(200); // XXX
7038 format %{ "jn$cop skip\t# unsigned cmove double\n\t"
7039 "movsd $dst, $src\n"
7040 "skip:" %}
7041 ins_encode %{
7042 Label Lskip;
7043 // Invert sense of branch from sense of CMOV
7044 __ jccb((Assembler::Condition)($cop$$cmpcode^1), Lskip);
7045 __ movdbl($dst$$XMMRegister, $src$$XMMRegister);
7046 __ bind(Lskip);
7047 %}
7048 ins_pipe(pipe_slow);
7049 %}
7050
7051 instruct cmovD_regUCF(cmpOpUCF cop, rFlagsRegUCF cr, regD dst, regD src) %{
7052 match(Set dst (CMoveD (Binary cop cr) (Binary dst src)));
7053 ins_cost(200);
7054 expand %{
7055 cmovD_regU(cop, cr, dst, src);
7056 %}
7057 %}
7058
7059 //----------Arithmetic Instructions--------------------------------------------
7060 //----------Addition Instructions----------------------------------------------
7061
7062 instruct addI_rReg(rRegI dst, rRegI src, rFlagsReg cr)
7063 %{
7064 predicate(!UseAPX);
7065 match(Set dst (AddI dst src));
7066 effect(KILL cr);
7067 flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag);
7068 format %{ "addl $dst, $src\t# int" %}
7069 ins_encode %{
7070 __ addl($dst$$Register, $src$$Register);
7071 %}
7072 ins_pipe(ialu_reg_reg);
7073 %}
7074
7075 instruct addI_rReg_ndd(rRegI dst, rRegI src1, rRegI src2, rFlagsReg cr)
7076 %{
7077 predicate(UseAPX);
7078 match(Set dst (AddI src1 src2));
7079 effect(KILL cr);
7080 flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag);
7081
7082 format %{ "eaddl $dst, $src1, $src2\t# int ndd" %}
7083 ins_encode %{
7084 __ eaddl($dst$$Register, $src1$$Register, $src2$$Register, false);
7085 %}
7086 ins_pipe(ialu_reg_reg);
7087 %}
7088
7089 instruct addI_rReg_imm(rRegI dst, immI src, rFlagsReg cr)
7090 %{
7091 predicate(!UseAPX);
7092 match(Set dst (AddI dst src));
7093 effect(KILL cr);
7094 flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag);
7095
7096 format %{ "addl $dst, $src\t# int" %}
7097 ins_encode %{
7098 __ addl($dst$$Register, $src$$constant);
7099 %}
7100 ins_pipe( ialu_reg );
7101 %}
7102
7103 instruct addI_rReg_rReg_imm_ndd(rRegI dst, rRegI src1, immI src2, rFlagsReg cr)
7104 %{
7105 predicate(UseAPX);
7106 match(Set dst (AddI src1 src2));
7107 effect(KILL cr);
7108 flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag);
7109
7110 format %{ "eaddl $dst, $src1, $src2\t# int ndd" %}
7111 ins_encode %{
7112 __ eaddl($dst$$Register, $src1$$Register, $src2$$constant, false);
7113 %}
7114 ins_pipe( ialu_reg );
7115 %}
7116
7117 instruct addI_rReg_mem_imm_ndd(rRegI dst, memory src1, immI src2, rFlagsReg cr)
7118 %{
7119 predicate(UseAPX);
7120 match(Set dst (AddI (LoadI src1) src2));
7121 effect(KILL cr);
7122 flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag);
7123
7124 format %{ "eaddl $dst, $src1, $src2\t# int ndd" %}
7125 ins_encode %{
7126 __ eaddl($dst$$Register, $src1$$Address, $src2$$constant, false);
7127 %}
7128 ins_pipe( ialu_reg );
7129 %}
7130
7131 instruct addI_rReg_mem(rRegI dst, memory src, rFlagsReg cr)
7132 %{
7133 predicate(!UseAPX);
7134 match(Set dst (AddI dst (LoadI src)));
7135 effect(KILL cr);
7136 flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag);
7137
7138 ins_cost(150); // XXX
7139 format %{ "addl $dst, $src\t# int" %}
7140 ins_encode %{
7141 __ addl($dst$$Register, $src$$Address);
7142 %}
7143 ins_pipe(ialu_reg_mem);
7144 %}
7145
7146 instruct addI_rReg_rReg_mem_ndd(rRegI dst, rRegI src1, memory src2, rFlagsReg cr)
7147 %{
7148 predicate(UseAPX);
7149 match(Set dst (AddI src1 (LoadI src2)));
7150 effect(KILL cr);
7151 flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag);
7152
7153 ins_cost(150);
7154 format %{ "eaddl $dst, $src1, $src2\t# int ndd" %}
7155 ins_encode %{
7156 __ eaddl($dst$$Register, $src1$$Register, $src2$$Address, false);
7157 %}
7158 ins_pipe(ialu_reg_mem);
7159 %}
7160
7161 instruct addI_mem_rReg(memory dst, rRegI src, rFlagsReg cr)
7162 %{
7163 match(Set dst (StoreI dst (AddI (LoadI dst) src)));
7164 effect(KILL cr);
7165 flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag);
7166
7167 ins_cost(150); // XXX
7168 format %{ "addl $dst, $src\t# int" %}
7169 ins_encode %{
7170 __ addl($dst$$Address, $src$$Register);
7171 %}
7172 ins_pipe(ialu_mem_reg);
7173 %}
7174
7175 instruct addI_mem_imm(memory dst, immI src, rFlagsReg cr)
7176 %{
7177 match(Set dst (StoreI dst (AddI (LoadI dst) src)));
7178 effect(KILL cr);
7179 flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag);
7180
7181
7182 ins_cost(125); // XXX
7183 format %{ "addl $dst, $src\t# int" %}
7184 ins_encode %{
7185 __ addl($dst$$Address, $src$$constant);
7186 %}
7187 ins_pipe(ialu_mem_imm);
7188 %}
7189
7190 instruct incI_rReg(rRegI dst, immI_1 src, rFlagsReg cr)
7191 %{
7192 predicate(!UseAPX && UseIncDec);
7193 match(Set dst (AddI dst src));
7194 effect(KILL cr);
7195
7196 format %{ "incl $dst\t# int" %}
7197 ins_encode %{
7198 __ incrementl($dst$$Register);
7199 %}
7200 ins_pipe(ialu_reg);
7201 %}
7202
7203 instruct incI_rReg_ndd(rRegI dst, rRegI src, immI_1 val, rFlagsReg cr)
7204 %{
7205 predicate(UseAPX && UseIncDec);
7206 match(Set dst (AddI src val));
7207 effect(KILL cr);
7208
7209 format %{ "eincl $dst, $src\t# int ndd" %}
7210 ins_encode %{
7211 __ eincl($dst$$Register, $src$$Register, false);
7212 %}
7213 ins_pipe(ialu_reg);
7214 %}
7215
7216 instruct incI_rReg_mem_ndd(rRegI dst, memory src, immI_1 val, rFlagsReg cr)
7217 %{
7218 predicate(UseAPX && UseIncDec);
7219 match(Set dst (AddI (LoadI src) val));
7220 effect(KILL cr);
7221
7222 format %{ "eincl $dst, $src\t# int ndd" %}
7223 ins_encode %{
7224 __ eincl($dst$$Register, $src$$Address, false);
7225 %}
7226 ins_pipe(ialu_reg);
7227 %}
7228
7229 instruct incI_mem(memory dst, immI_1 src, rFlagsReg cr)
7230 %{
7231 predicate(UseIncDec);
7232 match(Set dst (StoreI dst (AddI (LoadI dst) src)));
7233 effect(KILL cr);
7234
7235 ins_cost(125); // XXX
7236 format %{ "incl $dst\t# int" %}
7237 ins_encode %{
7238 __ incrementl($dst$$Address);
7239 %}
7240 ins_pipe(ialu_mem_imm);
7241 %}
7242
7243 // XXX why does that use AddI
7244 instruct decI_rReg(rRegI dst, immI_M1 src, rFlagsReg cr)
7245 %{
7246 predicate(!UseAPX && UseIncDec);
7247 match(Set dst (AddI dst src));
7248 effect(KILL cr);
7249
7250 format %{ "decl $dst\t# int" %}
7251 ins_encode %{
7252 __ decrementl($dst$$Register);
7253 %}
7254 ins_pipe(ialu_reg);
7255 %}
7256
7257 instruct decI_rReg_ndd(rRegI dst, rRegI src, immI_M1 val, rFlagsReg cr)
7258 %{
7259 predicate(UseAPX && UseIncDec);
7260 match(Set dst (AddI src val));
7261 effect(KILL cr);
7262
7263 format %{ "edecl $dst, $src\t# int ndd" %}
7264 ins_encode %{
7265 __ edecl($dst$$Register, $src$$Register, false);
7266 %}
7267 ins_pipe(ialu_reg);
7268 %}
7269
7270 instruct decI_rReg_mem_ndd(rRegI dst, memory src, immI_M1 val, rFlagsReg cr)
7271 %{
7272 predicate(UseAPX && UseIncDec);
7273 match(Set dst (AddI (LoadI src) val));
7274 effect(KILL cr);
7275
7276 format %{ "edecl $dst, $src\t# int ndd" %}
7277 ins_encode %{
7278 __ edecl($dst$$Register, $src$$Address, false);
7279 %}
7280 ins_pipe(ialu_reg);
7281 %}
7282
7283 // XXX why does that use AddI
7284 instruct decI_mem(memory dst, immI_M1 src, rFlagsReg cr)
7285 %{
7286 predicate(UseIncDec);
7287 match(Set dst (StoreI dst (AddI (LoadI dst) src)));
7288 effect(KILL cr);
7289
7290 ins_cost(125); // XXX
7291 format %{ "decl $dst\t# int" %}
7292 ins_encode %{
7293 __ decrementl($dst$$Address);
7294 %}
7295 ins_pipe(ialu_mem_imm);
7296 %}
7297
7298 instruct leaI_rReg_immI2_immI(rRegI dst, rRegI index, immI2 scale, immI disp)
7299 %{
7300 predicate(VM_Version::supports_fast_2op_lea());
7301 match(Set dst (AddI (LShiftI index scale) disp));
7302
7303 format %{ "leal $dst, [$index << $scale + $disp]\t# int" %}
7304 ins_encode %{
7305 Address::ScaleFactor scale = static_cast<Address::ScaleFactor>($scale$$constant);
7306 __ leal($dst$$Register, Address(noreg, $index$$Register, scale, $disp$$constant));
7307 %}
7308 ins_pipe(ialu_reg_reg);
7309 %}
7310
7311 instruct leaI_rReg_rReg_immI(rRegI dst, rRegI base, rRegI index, immI disp)
7312 %{
7313 predicate(VM_Version::supports_fast_3op_lea());
7314 match(Set dst (AddI (AddI base index) disp));
7315
7316 format %{ "leal $dst, [$base + $index + $disp]\t# int" %}
7317 ins_encode %{
7318 __ leal($dst$$Register, Address($base$$Register, $index$$Register, Address::times_1, $disp$$constant));
7319 %}
7320 ins_pipe(ialu_reg_reg);
7321 %}
7322
7323 instruct leaI_rReg_rReg_immI2(rRegI dst, no_rbp_r13_RegI base, rRegI index, immI2 scale)
7324 %{
7325 predicate(VM_Version::supports_fast_2op_lea());
7326 match(Set dst (AddI base (LShiftI index scale)));
7327
7328 format %{ "leal $dst, [$base + $index << $scale]\t# int" %}
7329 ins_encode %{
7330 Address::ScaleFactor scale = static_cast<Address::ScaleFactor>($scale$$constant);
7331 __ leal($dst$$Register, Address($base$$Register, $index$$Register, scale));
7332 %}
7333 ins_pipe(ialu_reg_reg);
7334 %}
7335
7336 instruct leaI_rReg_rReg_immI2_immI(rRegI dst, rRegI base, rRegI index, immI2 scale, immI disp)
7337 %{
7338 predicate(VM_Version::supports_fast_3op_lea());
7339 match(Set dst (AddI (AddI base (LShiftI index scale)) disp));
7340
7341 format %{ "leal $dst, [$base + $index << $scale + $disp]\t# int" %}
7342 ins_encode %{
7343 Address::ScaleFactor scale = static_cast<Address::ScaleFactor>($scale$$constant);
7344 __ leal($dst$$Register, Address($base$$Register, $index$$Register, scale, $disp$$constant));
7345 %}
7346 ins_pipe(ialu_reg_reg);
7347 %}
7348
7349 instruct addL_rReg(rRegL dst, rRegL src, rFlagsReg cr)
7350 %{
7351 predicate(!UseAPX);
7352 match(Set dst (AddL dst src));
7353 effect(KILL cr);
7354 flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag);
7355
7356 format %{ "addq $dst, $src\t# long" %}
7357 ins_encode %{
7358 __ addq($dst$$Register, $src$$Register);
7359 %}
7360 ins_pipe(ialu_reg_reg);
7361 %}
7362
7363 instruct addL_rReg_ndd(rRegL dst, rRegL src1, rRegL src2, rFlagsReg cr)
7364 %{
7365 predicate(UseAPX);
7366 match(Set dst (AddL src1 src2));
7367 effect(KILL cr);
7368 flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag);
7369
7370 format %{ "eaddq $dst, $src1, $src2\t# long ndd" %}
7371 ins_encode %{
7372 __ eaddq($dst$$Register, $src1$$Register, $src2$$Register, false);
7373 %}
7374 ins_pipe(ialu_reg_reg);
7375 %}
7376
7377 instruct addL_rReg_imm(rRegL dst, immL32 src, rFlagsReg cr)
7378 %{
7379 predicate(!UseAPX);
7380 match(Set dst (AddL dst src));
7381 effect(KILL cr);
7382 flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag);
7383
7384 format %{ "addq $dst, $src\t# long" %}
7385 ins_encode %{
7386 __ addq($dst$$Register, $src$$constant);
7387 %}
7388 ins_pipe( ialu_reg );
7389 %}
7390
7391 instruct addL_rReg_rReg_imm_ndd(rRegL dst, rRegL src1, immL32 src2, rFlagsReg cr)
7392 %{
7393 predicate(UseAPX);
7394 match(Set dst (AddL src1 src2));
7395 effect(KILL cr);
7396 flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag);
7397
7398 format %{ "eaddq $dst, $src1, $src2\t# long ndd" %}
7399 ins_encode %{
7400 __ eaddq($dst$$Register, $src1$$Register, $src2$$constant, false);
7401 %}
7402 ins_pipe( ialu_reg );
7403 %}
7404
7405 instruct addL_rReg_mem_imm_ndd(rRegL dst, memory src1, immL32 src2, rFlagsReg cr)
7406 %{
7407 predicate(UseAPX);
7408 match(Set dst (AddL (LoadL src1) src2));
7409 effect(KILL cr);
7410 flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag);
7411
7412 format %{ "eaddq $dst, $src1, $src2\t# long ndd" %}
7413 ins_encode %{
7414 __ eaddq($dst$$Register, $src1$$Address, $src2$$constant, false);
7415 %}
7416 ins_pipe( ialu_reg );
7417 %}
7418
7419 instruct addL_rReg_mem(rRegL dst, memory src, rFlagsReg cr)
7420 %{
7421 predicate(!UseAPX);
7422 match(Set dst (AddL dst (LoadL src)));
7423 effect(KILL cr);
7424 flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag);
7425
7426 ins_cost(150); // XXX
7427 format %{ "addq $dst, $src\t# long" %}
7428 ins_encode %{
7429 __ addq($dst$$Register, $src$$Address);
7430 %}
7431 ins_pipe(ialu_reg_mem);
7432 %}
7433
7434 instruct addL_rReg_rReg_mem_ndd(rRegL dst, rRegL src1, memory src2, rFlagsReg cr)
7435 %{
7436 predicate(UseAPX);
7437 match(Set dst (AddL src1 (LoadL src2)));
7438 effect(KILL cr);
7439 flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag);
7440
7441 ins_cost(150);
7442 format %{ "eaddq $dst, $src1, $src2\t# long ndd" %}
7443 ins_encode %{
7444 __ eaddq($dst$$Register, $src1$$Register, $src2$$Address, false);
7445 %}
7446 ins_pipe(ialu_reg_mem);
7447 %}
7448
7449 instruct addL_mem_rReg(memory dst, rRegL src, rFlagsReg cr)
7450 %{
7451 match(Set dst (StoreL dst (AddL (LoadL dst) src)));
7452 effect(KILL cr);
7453 flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag);
7454
7455 ins_cost(150); // XXX
7456 format %{ "addq $dst, $src\t# long" %}
7457 ins_encode %{
7458 __ addq($dst$$Address, $src$$Register);
7459 %}
7460 ins_pipe(ialu_mem_reg);
7461 %}
7462
7463 instruct addL_mem_imm(memory dst, immL32 src, rFlagsReg cr)
7464 %{
7465 match(Set dst (StoreL dst (AddL (LoadL dst) src)));
7466 effect(KILL cr);
7467 flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag);
7468
7469 ins_cost(125); // XXX
7470 format %{ "addq $dst, $src\t# long" %}
7471 ins_encode %{
7472 __ addq($dst$$Address, $src$$constant);
7473 %}
7474 ins_pipe(ialu_mem_imm);
7475 %}
7476
7477 instruct incL_rReg(rRegL dst, immL1 src, rFlagsReg cr)
7478 %{
7479 predicate(!UseAPX && UseIncDec);
7480 match(Set dst (AddL dst src));
7481 effect(KILL cr);
7482
7483 format %{ "incq $dst\t# long" %}
7484 ins_encode %{
7485 __ incrementq($dst$$Register);
7486 %}
7487 ins_pipe(ialu_reg);
7488 %}
7489
7490 instruct incL_rReg_ndd(rRegL dst, rRegI src, immL1 val, rFlagsReg cr)
7491 %{
7492 predicate(UseAPX && UseIncDec);
7493 match(Set dst (AddL src val));
7494 effect(KILL cr);
7495
7496 format %{ "eincq $dst, $src\t# long ndd" %}
7497 ins_encode %{
7498 __ eincq($dst$$Register, $src$$Register, false);
7499 %}
7500 ins_pipe(ialu_reg);
7501 %}
7502
7503 instruct incL_rReg_mem_ndd(rRegL dst, memory src, immL1 val, rFlagsReg cr)
7504 %{
7505 predicate(UseAPX && UseIncDec);
7506 match(Set dst (AddL (LoadL src) val));
7507 effect(KILL cr);
7508
7509 format %{ "eincq $dst, $src\t# long ndd" %}
7510 ins_encode %{
7511 __ eincq($dst$$Register, $src$$Address, false);
7512 %}
7513 ins_pipe(ialu_reg);
7514 %}
7515
7516 instruct incL_mem(memory dst, immL1 src, rFlagsReg cr)
7517 %{
7518 predicate(UseIncDec);
7519 match(Set dst (StoreL dst (AddL (LoadL dst) src)));
7520 effect(KILL cr);
7521
7522 ins_cost(125); // XXX
7523 format %{ "incq $dst\t# long" %}
7524 ins_encode %{
7525 __ incrementq($dst$$Address);
7526 %}
7527 ins_pipe(ialu_mem_imm);
7528 %}
7529
7530 // XXX why does that use AddL
7531 instruct decL_rReg(rRegL dst, immL_M1 src, rFlagsReg cr)
7532 %{
7533 predicate(!UseAPX && UseIncDec);
7534 match(Set dst (AddL dst src));
7535 effect(KILL cr);
7536
7537 format %{ "decq $dst\t# long" %}
7538 ins_encode %{
7539 __ decrementq($dst$$Register);
7540 %}
7541 ins_pipe(ialu_reg);
7542 %}
7543
7544 instruct decL_rReg_ndd(rRegL dst, rRegL src, immL_M1 val, rFlagsReg cr)
7545 %{
7546 predicate(UseAPX && UseIncDec);
7547 match(Set dst (AddL src val));
7548 effect(KILL cr);
7549
7550 format %{ "edecq $dst, $src\t# long ndd" %}
7551 ins_encode %{
7552 __ edecq($dst$$Register, $src$$Register, false);
7553 %}
7554 ins_pipe(ialu_reg);
7555 %}
7556
7557 instruct decL_rReg_mem_ndd(rRegL dst, memory src, immL_M1 val, rFlagsReg cr)
7558 %{
7559 predicate(UseAPX && UseIncDec);
7560 match(Set dst (AddL (LoadL src) val));
7561 effect(KILL cr);
7562
7563 format %{ "edecq $dst, $src\t# long ndd" %}
7564 ins_encode %{
7565 __ edecq($dst$$Register, $src$$Address, false);
7566 %}
7567 ins_pipe(ialu_reg);
7568 %}
7569
7570 // XXX why does that use AddL
7571 instruct decL_mem(memory dst, immL_M1 src, rFlagsReg cr)
7572 %{
7573 predicate(UseIncDec);
7574 match(Set dst (StoreL dst (AddL (LoadL dst) src)));
7575 effect(KILL cr);
7576
7577 ins_cost(125); // XXX
7578 format %{ "decq $dst\t# long" %}
7579 ins_encode %{
7580 __ decrementq($dst$$Address);
7581 %}
7582 ins_pipe(ialu_mem_imm);
7583 %}
7584
7585 instruct leaL_rReg_immI2_immL32(rRegL dst, rRegL index, immI2 scale, immL32 disp)
7586 %{
7587 predicate(VM_Version::supports_fast_2op_lea());
7588 match(Set dst (AddL (LShiftL index scale) disp));
7589
7590 format %{ "leaq $dst, [$index << $scale + $disp]\t# long" %}
7591 ins_encode %{
7592 Address::ScaleFactor scale = static_cast<Address::ScaleFactor>($scale$$constant);
7593 __ leaq($dst$$Register, Address(noreg, $index$$Register, scale, $disp$$constant));
7594 %}
7595 ins_pipe(ialu_reg_reg);
7596 %}
7597
7598 instruct leaL_rReg_rReg_immL32(rRegL dst, rRegL base, rRegL index, immL32 disp)
7599 %{
7600 predicate(VM_Version::supports_fast_3op_lea());
7601 match(Set dst (AddL (AddL base index) disp));
7602
7603 format %{ "leaq $dst, [$base + $index + $disp]\t# long" %}
7604 ins_encode %{
7605 __ leaq($dst$$Register, Address($base$$Register, $index$$Register, Address::times_1, $disp$$constant));
7606 %}
7607 ins_pipe(ialu_reg_reg);
7608 %}
7609
7610 instruct leaL_rReg_rReg_immI2(rRegL dst, no_rbp_r13_RegL base, rRegL index, immI2 scale)
7611 %{
7612 predicate(VM_Version::supports_fast_2op_lea());
7613 match(Set dst (AddL base (LShiftL index scale)));
7614
7615 format %{ "leaq $dst, [$base + $index << $scale]\t# long" %}
7616 ins_encode %{
7617 Address::ScaleFactor scale = static_cast<Address::ScaleFactor>($scale$$constant);
7618 __ leaq($dst$$Register, Address($base$$Register, $index$$Register, scale));
7619 %}
7620 ins_pipe(ialu_reg_reg);
7621 %}
7622
7623 instruct leaL_rReg_rReg_immI2_immL32(rRegL dst, rRegL base, rRegL index, immI2 scale, immL32 disp)
7624 %{
7625 predicate(VM_Version::supports_fast_3op_lea());
7626 match(Set dst (AddL (AddL base (LShiftL index scale)) disp));
7627
7628 format %{ "leaq $dst, [$base + $index << $scale + $disp]\t# long" %}
7629 ins_encode %{
7630 Address::ScaleFactor scale = static_cast<Address::ScaleFactor>($scale$$constant);
7631 __ leaq($dst$$Register, Address($base$$Register, $index$$Register, scale, $disp$$constant));
7632 %}
7633 ins_pipe(ialu_reg_reg);
7634 %}
7635
7636 instruct addP_rReg(rRegP dst, rRegL src, rFlagsReg cr)
7637 %{
7638 match(Set dst (AddP dst src));
7639 effect(KILL cr);
7640 flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag);
7641
7642 format %{ "addq $dst, $src\t# ptr" %}
7643 ins_encode %{
7644 __ addq($dst$$Register, $src$$Register);
7645 %}
7646 ins_pipe(ialu_reg_reg);
7647 %}
7648
7649 instruct addP_rReg_imm(rRegP dst, immL32 src, rFlagsReg cr)
7650 %{
7651 match(Set dst (AddP dst src));
7652 effect(KILL cr);
7653 flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag);
7654
7655 format %{ "addq $dst, $src\t# ptr" %}
7656 ins_encode %{
7657 __ addq($dst$$Register, $src$$constant);
7658 %}
7659 ins_pipe( ialu_reg );
7660 %}
7661
7662 // XXX addP mem ops ????
7663
7664 instruct checkCastPP(rRegP dst)
7665 %{
7666 match(Set dst (CheckCastPP dst));
7667
7668 size(0);
7669 format %{ "# checkcastPP of $dst" %}
7670 ins_encode(/* empty encoding */);
7671 ins_pipe(empty);
7672 %}
7673
7674 instruct castPP(rRegP dst)
7675 %{
7676 match(Set dst (CastPP dst));
7677
7678 size(0);
7679 format %{ "# castPP of $dst" %}
7680 ins_encode(/* empty encoding */);
7681 ins_pipe(empty);
7682 %}
7683
7684 instruct castII(rRegI dst)
7685 %{
7686 predicate(VerifyConstraintCasts == 0);
7687 match(Set dst (CastII dst));
7688
7689 size(0);
7690 format %{ "# castII of $dst" %}
7691 ins_encode(/* empty encoding */);
7692 ins_cost(0);
7693 ins_pipe(empty);
7694 %}
7695
7696 instruct castII_checked(rRegI dst, rFlagsReg cr)
7697 %{
7698 predicate(VerifyConstraintCasts > 0);
7699 match(Set dst (CastII dst));
7700
7701 effect(KILL cr);
7702 format %{ "# cast_checked_II $dst" %}
7703 ins_encode %{
7704 __ verify_int_in_range(_idx, bottom_type()->is_int(), $dst$$Register);
7705 %}
7706 ins_pipe(pipe_slow);
7707 %}
7708
7709 instruct castLL(rRegL dst)
7710 %{
7711 predicate(VerifyConstraintCasts == 0);
7712 match(Set dst (CastLL dst));
7713
7714 size(0);
7715 format %{ "# castLL of $dst" %}
7716 ins_encode(/* empty encoding */);
7717 ins_cost(0);
7718 ins_pipe(empty);
7719 %}
7720
7721 instruct castLL_checked_L32(rRegL dst, rFlagsReg cr)
7722 %{
7723 predicate(VerifyConstraintCasts > 0 && castLL_is_imm32(n));
7724 match(Set dst (CastLL dst));
7725
7726 effect(KILL cr);
7727 format %{ "# cast_checked_LL $dst" %}
7728 ins_encode %{
7729 __ verify_long_in_range(_idx, bottom_type()->is_long(), $dst$$Register, noreg);
7730 %}
7731 ins_pipe(pipe_slow);
7732 %}
7733
7734 instruct castLL_checked(rRegL dst, rRegL tmp, rFlagsReg cr)
7735 %{
7736 predicate(VerifyConstraintCasts > 0 && !castLL_is_imm32(n));
7737 match(Set dst (CastLL dst));
7738
7739 effect(KILL cr, TEMP tmp);
7740 format %{ "# cast_checked_LL $dst\tusing $tmp as TEMP" %}
7741 ins_encode %{
7742 __ verify_long_in_range(_idx, bottom_type()->is_long(), $dst$$Register, $tmp$$Register);
7743 %}
7744 ins_pipe(pipe_slow);
7745 %}
7746
7747 instruct castFF(regF dst)
7748 %{
7749 match(Set dst (CastFF dst));
7750
7751 size(0);
7752 format %{ "# castFF of $dst" %}
7753 ins_encode(/* empty encoding */);
7754 ins_cost(0);
7755 ins_pipe(empty);
7756 %}
7757
7758 instruct castHH(regF dst)
7759 %{
7760 match(Set dst (CastHH dst));
7761
7762 size(0);
7763 format %{ "# castHH of $dst" %}
7764 ins_encode(/* empty encoding */);
7765 ins_cost(0);
7766 ins_pipe(empty);
7767 %}
7768
7769 instruct castDD(regD dst)
7770 %{
7771 match(Set dst (CastDD dst));
7772
7773 size(0);
7774 format %{ "# castDD of $dst" %}
7775 ins_encode(/* empty encoding */);
7776 ins_cost(0);
7777 ins_pipe(empty);
7778 %}
7779
7780 // XXX No flag versions for CompareAndSwap{P,I,L} because matcher can't match them
7781 instruct compareAndSwapP(rRegI res,
7782 memory mem_ptr,
7783 rax_RegP oldval, rRegP newval,
7784 rFlagsReg cr)
7785 %{
7786 predicate(n->as_LoadStore()->barrier_data() == 0);
7787 match(Set res (CompareAndSwapP mem_ptr (Binary oldval newval)));
7788 match(Set res (WeakCompareAndSwapP mem_ptr (Binary oldval newval)));
7789 effect(KILL cr, KILL oldval);
7790
7791 format %{ "cmpxchgq $mem_ptr,$newval\t# "
7792 "If rax == $mem_ptr then store $newval into $mem_ptr\n\t"
7793 "setcc $res \t# emits sete + movzbl or setzue for APX" %}
7794 ins_encode %{
7795 __ lock();
7796 __ cmpxchgq($newval$$Register, $mem_ptr$$Address);
7797 __ setcc(Assembler::equal, $res$$Register);
7798 %}
7799 ins_pipe( pipe_cmpxchg );
7800 %}
7801
7802 instruct compareAndSwapL(rRegI res,
7803 memory mem_ptr,
7804 rax_RegL oldval, rRegL newval,
7805 rFlagsReg cr)
7806 %{
7807 match(Set res (CompareAndSwapL mem_ptr (Binary oldval newval)));
7808 match(Set res (WeakCompareAndSwapL mem_ptr (Binary oldval newval)));
7809 effect(KILL cr, KILL oldval);
7810
7811 format %{ "cmpxchgq $mem_ptr,$newval\t# "
7812 "If rax == $mem_ptr then store $newval into $mem_ptr\n\t"
7813 "setcc $res \t# emits sete + movzbl or setzue for APX" %}
7814 ins_encode %{
7815 __ lock();
7816 __ cmpxchgq($newval$$Register, $mem_ptr$$Address);
7817 __ setcc(Assembler::equal, $res$$Register);
7818 %}
7819 ins_pipe( pipe_cmpxchg );
7820 %}
7821
7822 instruct compareAndSwapI(rRegI res,
7823 memory mem_ptr,
7824 rax_RegI oldval, rRegI newval,
7825 rFlagsReg cr)
7826 %{
7827 match(Set res (CompareAndSwapI mem_ptr (Binary oldval newval)));
7828 match(Set res (WeakCompareAndSwapI mem_ptr (Binary oldval newval)));
7829 effect(KILL cr, KILL oldval);
7830
7831 format %{ "cmpxchgl $mem_ptr,$newval\t# "
7832 "If rax == $mem_ptr then store $newval into $mem_ptr\n\t"
7833 "setcc $res \t# emits sete + movzbl or setzue for APX" %}
7834 ins_encode %{
7835 __ lock();
7836 __ cmpxchgl($newval$$Register, $mem_ptr$$Address);
7837 __ setcc(Assembler::equal, $res$$Register);
7838 %}
7839 ins_pipe( pipe_cmpxchg );
7840 %}
7841
7842 instruct compareAndSwapB(rRegI res,
7843 memory mem_ptr,
7844 rax_RegI oldval, rRegI newval,
7845 rFlagsReg cr)
7846 %{
7847 match(Set res (CompareAndSwapB mem_ptr (Binary oldval newval)));
7848 match(Set res (WeakCompareAndSwapB mem_ptr (Binary oldval newval)));
7849 effect(KILL cr, KILL oldval);
7850
7851 format %{ "cmpxchgb $mem_ptr,$newval\t# "
7852 "If rax == $mem_ptr then store $newval into $mem_ptr\n\t"
7853 "setcc $res \t# emits sete + movzbl or setzue for APX" %}
7854 ins_encode %{
7855 __ lock();
7856 __ cmpxchgb($newval$$Register, $mem_ptr$$Address);
7857 __ setcc(Assembler::equal, $res$$Register);
7858 %}
7859 ins_pipe( pipe_cmpxchg );
7860 %}
7861
7862 instruct compareAndSwapS(rRegI res,
7863 memory mem_ptr,
7864 rax_RegI oldval, rRegI newval,
7865 rFlagsReg cr)
7866 %{
7867 match(Set res (CompareAndSwapS mem_ptr (Binary oldval newval)));
7868 match(Set res (WeakCompareAndSwapS mem_ptr (Binary oldval newval)));
7869 effect(KILL cr, KILL oldval);
7870
7871 format %{ "cmpxchgw $mem_ptr,$newval\t# "
7872 "If rax == $mem_ptr then store $newval into $mem_ptr\n\t"
7873 "setcc $res \t# emits sete + movzbl or setzue for APX" %}
7874 ins_encode %{
7875 __ lock();
7876 __ cmpxchgw($newval$$Register, $mem_ptr$$Address);
7877 __ setcc(Assembler::equal, $res$$Register);
7878 %}
7879 ins_pipe( pipe_cmpxchg );
7880 %}
7881
7882 instruct compareAndSwapN(rRegI res,
7883 memory mem_ptr,
7884 rax_RegN oldval, rRegN newval,
7885 rFlagsReg cr) %{
7886 predicate(n->as_LoadStore()->barrier_data() == 0);
7887 match(Set res (CompareAndSwapN mem_ptr (Binary oldval newval)));
7888 match(Set res (WeakCompareAndSwapN mem_ptr (Binary oldval newval)));
7889 effect(KILL cr, KILL oldval);
7890
7891 format %{ "cmpxchgl $mem_ptr,$newval\t# "
7892 "If rax == $mem_ptr then store $newval into $mem_ptr\n\t"
7893 "setcc $res \t# emits sete + movzbl or setzue for APX" %}
7894 ins_encode %{
7895 __ lock();
7896 __ cmpxchgl($newval$$Register, $mem_ptr$$Address);
7897 __ setcc(Assembler::equal, $res$$Register);
7898 %}
7899 ins_pipe( pipe_cmpxchg );
7900 %}
7901
7902 instruct compareAndExchangeB(
7903 memory mem_ptr,
7904 rax_RegI oldval, rRegI newval,
7905 rFlagsReg cr)
7906 %{
7907 match(Set oldval (CompareAndExchangeB mem_ptr (Binary oldval newval)));
7908 effect(KILL cr);
7909
7910 format %{ "cmpxchgb $mem_ptr,$newval\t# "
7911 "If rax == $mem_ptr then store $newval into $mem_ptr\n\t" %}
7912 ins_encode %{
7913 __ lock();
7914 __ cmpxchgb($newval$$Register, $mem_ptr$$Address);
7915 %}
7916 ins_pipe( pipe_cmpxchg );
7917 %}
7918
7919 instruct compareAndExchangeS(
7920 memory mem_ptr,
7921 rax_RegI oldval, rRegI newval,
7922 rFlagsReg cr)
7923 %{
7924 match(Set oldval (CompareAndExchangeS mem_ptr (Binary oldval newval)));
7925 effect(KILL cr);
7926
7927 format %{ "cmpxchgw $mem_ptr,$newval\t# "
7928 "If rax == $mem_ptr then store $newval into $mem_ptr\n\t" %}
7929 ins_encode %{
7930 __ lock();
7931 __ cmpxchgw($newval$$Register, $mem_ptr$$Address);
7932 %}
7933 ins_pipe( pipe_cmpxchg );
7934 %}
7935
7936 instruct compareAndExchangeI(
7937 memory mem_ptr,
7938 rax_RegI oldval, rRegI newval,
7939 rFlagsReg cr)
7940 %{
7941 match(Set oldval (CompareAndExchangeI mem_ptr (Binary oldval newval)));
7942 effect(KILL cr);
7943
7944 format %{ "cmpxchgl $mem_ptr,$newval\t# "
7945 "If rax == $mem_ptr then store $newval into $mem_ptr\n\t" %}
7946 ins_encode %{
7947 __ lock();
7948 __ cmpxchgl($newval$$Register, $mem_ptr$$Address);
7949 %}
7950 ins_pipe( pipe_cmpxchg );
7951 %}
7952
7953 instruct compareAndExchangeL(
7954 memory mem_ptr,
7955 rax_RegL oldval, rRegL newval,
7956 rFlagsReg cr)
7957 %{
7958 match(Set oldval (CompareAndExchangeL mem_ptr (Binary oldval newval)));
7959 effect(KILL cr);
7960
7961 format %{ "cmpxchgq $mem_ptr,$newval\t# "
7962 "If rax == $mem_ptr then store $newval into $mem_ptr\n\t" %}
7963 ins_encode %{
7964 __ lock();
7965 __ cmpxchgq($newval$$Register, $mem_ptr$$Address);
7966 %}
7967 ins_pipe( pipe_cmpxchg );
7968 %}
7969
7970 instruct compareAndExchangeN(
7971 memory mem_ptr,
7972 rax_RegN oldval, rRegN newval,
7973 rFlagsReg cr) %{
7974 predicate(n->as_LoadStore()->barrier_data() == 0);
7975 match(Set oldval (CompareAndExchangeN mem_ptr (Binary oldval newval)));
7976 effect(KILL cr);
7977
7978 format %{ "cmpxchgl $mem_ptr,$newval\t# "
7979 "If rax == $mem_ptr then store $newval into $mem_ptr\n\t" %}
7980 ins_encode %{
7981 __ lock();
7982 __ cmpxchgl($newval$$Register, $mem_ptr$$Address);
7983 %}
7984 ins_pipe( pipe_cmpxchg );
7985 %}
7986
7987 instruct compareAndExchangeP(
7988 memory mem_ptr,
7989 rax_RegP oldval, rRegP newval,
7990 rFlagsReg cr)
7991 %{
7992 predicate(n->as_LoadStore()->barrier_data() == 0);
7993 match(Set oldval (CompareAndExchangeP mem_ptr (Binary oldval newval)));
7994 effect(KILL cr);
7995
7996 format %{ "cmpxchgq $mem_ptr,$newval\t# "
7997 "If rax == $mem_ptr then store $newval into $mem_ptr\n\t" %}
7998 ins_encode %{
7999 __ lock();
8000 __ cmpxchgq($newval$$Register, $mem_ptr$$Address);
8001 %}
8002 ins_pipe( pipe_cmpxchg );
8003 %}
8004
8005 instruct xaddB_reg_no_res(memory mem, Universe dummy, rRegI add, rFlagsReg cr) %{
8006 predicate(n->as_LoadStore()->result_not_used());
8007 match(Set dummy (GetAndAddB mem add));
8008 effect(KILL cr);
8009 format %{ "addb_lock $mem, $add" %}
8010 ins_encode %{
8011 __ lock();
8012 __ addb($mem$$Address, $add$$Register);
8013 %}
8014 ins_pipe(pipe_cmpxchg);
8015 %}
8016
8017 instruct xaddB_imm_no_res(memory mem, Universe dummy, immI add, rFlagsReg cr) %{
8018 predicate(n->as_LoadStore()->result_not_used());
8019 match(Set dummy (GetAndAddB mem add));
8020 effect(KILL cr);
8021 format %{ "addb_lock $mem, $add" %}
8022 ins_encode %{
8023 __ lock();
8024 __ addb($mem$$Address, $add$$constant);
8025 %}
8026 ins_pipe(pipe_cmpxchg);
8027 %}
8028
8029 instruct xaddB(memory mem, rRegI newval, rFlagsReg cr) %{
8030 predicate(!n->as_LoadStore()->result_not_used());
8031 match(Set newval (GetAndAddB mem newval));
8032 effect(KILL cr);
8033 format %{ "xaddb_lock $mem, $newval" %}
8034 ins_encode %{
8035 __ lock();
8036 __ xaddb($mem$$Address, $newval$$Register);
8037 %}
8038 ins_pipe(pipe_cmpxchg);
8039 %}
8040
8041 instruct xaddS_reg_no_res(memory mem, Universe dummy, rRegI add, rFlagsReg cr) %{
8042 predicate(n->as_LoadStore()->result_not_used());
8043 match(Set dummy (GetAndAddS mem add));
8044 effect(KILL cr);
8045 format %{ "addw_lock $mem, $add" %}
8046 ins_encode %{
8047 __ lock();
8048 __ addw($mem$$Address, $add$$Register);
8049 %}
8050 ins_pipe(pipe_cmpxchg);
8051 %}
8052
8053 instruct xaddS_imm_no_res(memory mem, Universe dummy, immI add, rFlagsReg cr) %{
8054 predicate(UseStoreImmI16 && n->as_LoadStore()->result_not_used());
8055 match(Set dummy (GetAndAddS mem add));
8056 effect(KILL cr);
8057 format %{ "addw_lock $mem, $add" %}
8058 ins_encode %{
8059 __ lock();
8060 __ addw($mem$$Address, $add$$constant);
8061 %}
8062 ins_pipe(pipe_cmpxchg);
8063 %}
8064
8065 instruct xaddS(memory mem, rRegI newval, rFlagsReg cr) %{
8066 predicate(!n->as_LoadStore()->result_not_used());
8067 match(Set newval (GetAndAddS mem newval));
8068 effect(KILL cr);
8069 format %{ "xaddw_lock $mem, $newval" %}
8070 ins_encode %{
8071 __ lock();
8072 __ xaddw($mem$$Address, $newval$$Register);
8073 %}
8074 ins_pipe(pipe_cmpxchg);
8075 %}
8076
8077 instruct xaddI_reg_no_res(memory mem, Universe dummy, rRegI add, rFlagsReg cr) %{
8078 predicate(n->as_LoadStore()->result_not_used());
8079 match(Set dummy (GetAndAddI mem add));
8080 effect(KILL cr);
8081 format %{ "addl_lock $mem, $add" %}
8082 ins_encode %{
8083 __ lock();
8084 __ addl($mem$$Address, $add$$Register);
8085 %}
8086 ins_pipe(pipe_cmpxchg);
8087 %}
8088
8089 instruct xaddI_imm_no_res(memory mem, Universe dummy, immI add, rFlagsReg cr) %{
8090 predicate(n->as_LoadStore()->result_not_used());
8091 match(Set dummy (GetAndAddI mem add));
8092 effect(KILL cr);
8093 format %{ "addl_lock $mem, $add" %}
8094 ins_encode %{
8095 __ lock();
8096 __ addl($mem$$Address, $add$$constant);
8097 %}
8098 ins_pipe(pipe_cmpxchg);
8099 %}
8100
8101 instruct xaddI(memory mem, rRegI newval, rFlagsReg cr) %{
8102 predicate(!n->as_LoadStore()->result_not_used());
8103 match(Set newval (GetAndAddI mem newval));
8104 effect(KILL cr);
8105 format %{ "xaddl_lock $mem, $newval" %}
8106 ins_encode %{
8107 __ lock();
8108 __ xaddl($mem$$Address, $newval$$Register);
8109 %}
8110 ins_pipe(pipe_cmpxchg);
8111 %}
8112
8113 instruct xaddL_reg_no_res(memory mem, Universe dummy, rRegL add, rFlagsReg cr) %{
8114 predicate(n->as_LoadStore()->result_not_used());
8115 match(Set dummy (GetAndAddL mem add));
8116 effect(KILL cr);
8117 format %{ "addq_lock $mem, $add" %}
8118 ins_encode %{
8119 __ lock();
8120 __ addq($mem$$Address, $add$$Register);
8121 %}
8122 ins_pipe(pipe_cmpxchg);
8123 %}
8124
8125 instruct xaddL_imm_no_res(memory mem, Universe dummy, immL32 add, rFlagsReg cr) %{
8126 predicate(n->as_LoadStore()->result_not_used());
8127 match(Set dummy (GetAndAddL mem add));
8128 effect(KILL cr);
8129 format %{ "addq_lock $mem, $add" %}
8130 ins_encode %{
8131 __ lock();
8132 __ addq($mem$$Address, $add$$constant);
8133 %}
8134 ins_pipe(pipe_cmpxchg);
8135 %}
8136
8137 instruct xaddL(memory mem, rRegL newval, rFlagsReg cr) %{
8138 predicate(!n->as_LoadStore()->result_not_used());
8139 match(Set newval (GetAndAddL mem newval));
8140 effect(KILL cr);
8141 format %{ "xaddq_lock $mem, $newval" %}
8142 ins_encode %{
8143 __ lock();
8144 __ xaddq($mem$$Address, $newval$$Register);
8145 %}
8146 ins_pipe(pipe_cmpxchg);
8147 %}
8148
8149 instruct xchgB( memory mem, rRegI newval) %{
8150 match(Set newval (GetAndSetB mem newval));
8151 format %{ "XCHGB $newval,[$mem]" %}
8152 ins_encode %{
8153 __ xchgb($newval$$Register, $mem$$Address);
8154 %}
8155 ins_pipe( pipe_cmpxchg );
8156 %}
8157
8158 instruct xchgS( memory mem, rRegI newval) %{
8159 match(Set newval (GetAndSetS mem newval));
8160 format %{ "XCHGW $newval,[$mem]" %}
8161 ins_encode %{
8162 __ xchgw($newval$$Register, $mem$$Address);
8163 %}
8164 ins_pipe( pipe_cmpxchg );
8165 %}
8166
8167 instruct xchgI( memory mem, rRegI newval) %{
8168 match(Set newval (GetAndSetI mem newval));
8169 format %{ "XCHGL $newval,[$mem]" %}
8170 ins_encode %{
8171 __ xchgl($newval$$Register, $mem$$Address);
8172 %}
8173 ins_pipe( pipe_cmpxchg );
8174 %}
8175
8176 instruct xchgL( memory mem, rRegL newval) %{
8177 match(Set newval (GetAndSetL mem newval));
8178 format %{ "XCHGL $newval,[$mem]" %}
8179 ins_encode %{
8180 __ xchgq($newval$$Register, $mem$$Address);
8181 %}
8182 ins_pipe( pipe_cmpxchg );
8183 %}
8184
8185 instruct xchgP( memory mem, rRegP newval) %{
8186 match(Set newval (GetAndSetP mem newval));
8187 predicate(n->as_LoadStore()->barrier_data() == 0);
8188 format %{ "XCHGQ $newval,[$mem]" %}
8189 ins_encode %{
8190 __ xchgq($newval$$Register, $mem$$Address);
8191 %}
8192 ins_pipe( pipe_cmpxchg );
8193 %}
8194
8195 instruct xchgN( memory mem, rRegN newval) %{
8196 predicate(n->as_LoadStore()->barrier_data() == 0);
8197 match(Set newval (GetAndSetN mem newval));
8198 format %{ "XCHGL $newval,$mem]" %}
8199 ins_encode %{
8200 __ xchgl($newval$$Register, $mem$$Address);
8201 %}
8202 ins_pipe( pipe_cmpxchg );
8203 %}
8204
8205 //----------Abs Instructions-------------------------------------------
8206
8207 // Integer Absolute Instructions
8208 instruct absI_rReg(rRegI dst, rRegI src, rFlagsReg cr)
8209 %{
8210 match(Set dst (AbsI src));
8211 effect(TEMP dst, KILL cr);
8212 format %{ "xorl $dst, $dst\t# abs int\n\t"
8213 "subl $dst, $src\n\t"
8214 "cmovll $dst, $src" %}
8215 ins_encode %{
8216 __ xorl($dst$$Register, $dst$$Register);
8217 __ subl($dst$$Register, $src$$Register);
8218 __ cmovl(Assembler::less, $dst$$Register, $src$$Register);
8219 %}
8220
8221 ins_pipe(ialu_reg_reg);
8222 %}
8223
8224 // Long Absolute Instructions
8225 instruct absL_rReg(rRegL dst, rRegL src, rFlagsReg cr)
8226 %{
8227 match(Set dst (AbsL src));
8228 effect(TEMP dst, KILL cr);
8229 format %{ "xorl $dst, $dst\t# abs long\n\t"
8230 "subq $dst, $src\n\t"
8231 "cmovlq $dst, $src" %}
8232 ins_encode %{
8233 __ xorl($dst$$Register, $dst$$Register);
8234 __ subq($dst$$Register, $src$$Register);
8235 __ cmovq(Assembler::less, $dst$$Register, $src$$Register);
8236 %}
8237
8238 ins_pipe(ialu_reg_reg);
8239 %}
8240
8241 //----------Subtraction Instructions-------------------------------------------
8242
8243 // Integer Subtraction Instructions
8244 instruct subI_rReg(rRegI dst, rRegI src, rFlagsReg cr)
8245 %{
8246 predicate(!UseAPX);
8247 match(Set dst (SubI dst src));
8248 effect(KILL cr);
8249 flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag);
8250
8251 format %{ "subl $dst, $src\t# int" %}
8252 ins_encode %{
8253 __ subl($dst$$Register, $src$$Register);
8254 %}
8255 ins_pipe(ialu_reg_reg);
8256 %}
8257
8258 instruct subI_rReg_ndd(rRegI dst, rRegI src1, rRegI src2, rFlagsReg cr)
8259 %{
8260 predicate(UseAPX);
8261 match(Set dst (SubI src1 src2));
8262 effect(KILL cr);
8263 flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag);
8264
8265 format %{ "esubl $dst, $src1, $src2\t# int ndd" %}
8266 ins_encode %{
8267 __ esubl($dst$$Register, $src1$$Register, $src2$$Register, false);
8268 %}
8269 ins_pipe(ialu_reg_reg);
8270 %}
8271
8272 instruct subI_rReg_rReg_imm_ndd(rRegI dst, rRegI src1, immI src2, rFlagsReg cr)
8273 %{
8274 predicate(UseAPX);
8275 match(Set dst (SubI src1 src2));
8276 effect(KILL cr);
8277 flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag);
8278
8279 format %{ "esubl $dst, $src1, $src2\t# int ndd" %}
8280 ins_encode %{
8281 __ esubl($dst$$Register, $src1$$Register, $src2$$constant, false);
8282 %}
8283 ins_pipe(ialu_reg_reg);
8284 %}
8285
8286 instruct subI_rReg_mem_imm_ndd(rRegI dst, memory src1, immI src2, rFlagsReg cr)
8287 %{
8288 predicate(UseAPX);
8289 match(Set dst (SubI (LoadI src1) src2));
8290 effect(KILL cr);
8291 flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag);
8292
8293 format %{ "esubl $dst, $src1, $src2\t# int ndd" %}
8294 ins_encode %{
8295 __ esubl($dst$$Register, $src1$$Address, $src2$$constant, false);
8296 %}
8297 ins_pipe(ialu_reg_reg);
8298 %}
8299
8300 instruct subI_rReg_mem(rRegI dst, memory src, rFlagsReg cr)
8301 %{
8302 predicate(!UseAPX);
8303 match(Set dst (SubI dst (LoadI src)));
8304 effect(KILL cr);
8305 flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag);
8306
8307 ins_cost(150);
8308 format %{ "subl $dst, $src\t# int" %}
8309 ins_encode %{
8310 __ subl($dst$$Register, $src$$Address);
8311 %}
8312 ins_pipe(ialu_reg_mem);
8313 %}
8314
8315 instruct subI_rReg_rReg_mem_ndd(rRegI dst, rRegI src1, memory src2, rFlagsReg cr)
8316 %{
8317 predicate(UseAPX);
8318 match(Set dst (SubI src1 (LoadI src2)));
8319 effect(KILL cr);
8320 flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag);
8321
8322 ins_cost(150);
8323 format %{ "esubl $dst, $src1, $src2\t# int ndd" %}
8324 ins_encode %{
8325 __ esubl($dst$$Register, $src1$$Register, $src2$$Address, false);
8326 %}
8327 ins_pipe(ialu_reg_mem);
8328 %}
8329
8330 instruct subI_rReg_mem_rReg_ndd(rRegI dst, memory src1, rRegI src2, rFlagsReg cr)
8331 %{
8332 predicate(UseAPX);
8333 match(Set dst (SubI (LoadI src1) src2));
8334 effect(KILL cr);
8335 flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag);
8336
8337 ins_cost(150);
8338 format %{ "esubl $dst, $src1, $src2\t# int ndd" %}
8339 ins_encode %{
8340 __ esubl($dst$$Register, $src1$$Address, $src2$$Register, false);
8341 %}
8342 ins_pipe(ialu_reg_mem);
8343 %}
8344
8345 instruct subI_mem_rReg(memory dst, rRegI src, rFlagsReg cr)
8346 %{
8347 match(Set dst (StoreI dst (SubI (LoadI dst) src)));
8348 effect(KILL cr);
8349 flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag);
8350
8351 ins_cost(150);
8352 format %{ "subl $dst, $src\t# int" %}
8353 ins_encode %{
8354 __ subl($dst$$Address, $src$$Register);
8355 %}
8356 ins_pipe(ialu_mem_reg);
8357 %}
8358
8359 instruct subL_rReg(rRegL dst, rRegL src, rFlagsReg cr)
8360 %{
8361 predicate(!UseAPX);
8362 match(Set dst (SubL dst src));
8363 effect(KILL cr);
8364 flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag);
8365
8366 format %{ "subq $dst, $src\t# long" %}
8367 ins_encode %{
8368 __ subq($dst$$Register, $src$$Register);
8369 %}
8370 ins_pipe(ialu_reg_reg);
8371 %}
8372
8373 instruct subL_rReg_ndd(rRegL dst, rRegL src1, rRegL src2, rFlagsReg cr)
8374 %{
8375 predicate(UseAPX);
8376 match(Set dst (SubL src1 src2));
8377 effect(KILL cr);
8378 flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag);
8379
8380 format %{ "esubq $dst, $src1, $src2\t# long ndd" %}
8381 ins_encode %{
8382 __ esubq($dst$$Register, $src1$$Register, $src2$$Register, false);
8383 %}
8384 ins_pipe(ialu_reg_reg);
8385 %}
8386
8387 instruct subL_rReg_rReg_imm_ndd(rRegL dst, rRegL src1, immL32 src2, rFlagsReg cr)
8388 %{
8389 predicate(UseAPX);
8390 match(Set dst (SubL src1 src2));
8391 effect(KILL cr);
8392 flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag);
8393
8394 format %{ "esubq $dst, $src1, $src2\t# long ndd" %}
8395 ins_encode %{
8396 __ esubq($dst$$Register, $src1$$Register, $src2$$constant, false);
8397 %}
8398 ins_pipe(ialu_reg_reg);
8399 %}
8400
8401 instruct subL_rReg_mem_imm_ndd(rRegL dst, memory src1, immL32 src2, rFlagsReg cr)
8402 %{
8403 predicate(UseAPX);
8404 match(Set dst (SubL (LoadL src1) src2));
8405 effect(KILL cr);
8406 flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag);
8407
8408 format %{ "esubq $dst, $src1, $src2\t# long ndd" %}
8409 ins_encode %{
8410 __ esubq($dst$$Register, $src1$$Address, $src2$$constant, false);
8411 %}
8412 ins_pipe(ialu_reg_reg);
8413 %}
8414
8415 instruct subL_rReg_mem(rRegL dst, memory src, rFlagsReg cr)
8416 %{
8417 predicate(!UseAPX);
8418 match(Set dst (SubL dst (LoadL src)));
8419 effect(KILL cr);
8420 flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag);
8421
8422 ins_cost(150);
8423 format %{ "subq $dst, $src\t# long" %}
8424 ins_encode %{
8425 __ subq($dst$$Register, $src$$Address);
8426 %}
8427 ins_pipe(ialu_reg_mem);
8428 %}
8429
8430 instruct subL_rReg_rReg_mem_ndd(rRegL dst, rRegL src1, memory src2, rFlagsReg cr)
8431 %{
8432 predicate(UseAPX);
8433 match(Set dst (SubL src1 (LoadL src2)));
8434 effect(KILL cr);
8435 flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag);
8436
8437 ins_cost(150);
8438 format %{ "esubq $dst, $src1, $src2\t# long ndd" %}
8439 ins_encode %{
8440 __ esubq($dst$$Register, $src1$$Register, $src2$$Address, false);
8441 %}
8442 ins_pipe(ialu_reg_mem);
8443 %}
8444
8445 instruct subL_rReg_mem_rReg_ndd(rRegL dst, memory src1, rRegL src2, rFlagsReg cr)
8446 %{
8447 predicate(UseAPX);
8448 match(Set dst (SubL (LoadL src1) src2));
8449 effect(KILL cr);
8450 flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag);
8451
8452 ins_cost(150);
8453 format %{ "esubq $dst, $src1, $src2\t# long ndd" %}
8454 ins_encode %{
8455 __ esubq($dst$$Register, $src1$$Address, $src2$$Register, false);
8456 %}
8457 ins_pipe(ialu_reg_mem);
8458 %}
8459
8460 instruct subL_mem_rReg(memory dst, rRegL src, rFlagsReg cr)
8461 %{
8462 match(Set dst (StoreL dst (SubL (LoadL dst) src)));
8463 effect(KILL cr);
8464 flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag);
8465
8466 ins_cost(150);
8467 format %{ "subq $dst, $src\t# long" %}
8468 ins_encode %{
8469 __ subq($dst$$Address, $src$$Register);
8470 %}
8471 ins_pipe(ialu_mem_reg);
8472 %}
8473
8474 // Subtract from a pointer
8475 // XXX hmpf???
8476 instruct subP_rReg(rRegP dst, rRegI src, immI_0 zero, rFlagsReg cr)
8477 %{
8478 match(Set dst (AddP dst (SubI zero src)));
8479 effect(KILL cr);
8480
8481 format %{ "subq $dst, $src\t# ptr - int" %}
8482 ins_encode %{
8483 __ subq($dst$$Register, $src$$Register);
8484 %}
8485 ins_pipe(ialu_reg_reg);
8486 %}
8487
8488 instruct negI_rReg(rRegI dst, immI_0 zero, rFlagsReg cr)
8489 %{
8490 predicate(!UseAPX);
8491 match(Set dst (SubI zero dst));
8492 effect(KILL cr);
8493 flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag);
8494
8495 format %{ "negl $dst\t# int" %}
8496 ins_encode %{
8497 __ negl($dst$$Register);
8498 %}
8499 ins_pipe(ialu_reg);
8500 %}
8501
8502 instruct negI_rReg_ndd(rRegI dst, rRegI src, immI_0 zero, rFlagsReg cr)
8503 %{
8504 predicate(UseAPX);
8505 match(Set dst (SubI zero src));
8506 effect(KILL cr);
8507 flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag);
8508
8509 format %{ "enegl $dst, $src\t# int ndd" %}
8510 ins_encode %{
8511 __ enegl($dst$$Register, $src$$Register, false);
8512 %}
8513 ins_pipe(ialu_reg);
8514 %}
8515
8516 instruct negI_rReg_2(rRegI dst, rFlagsReg cr)
8517 %{
8518 predicate(!UseAPX);
8519 match(Set dst (NegI dst));
8520 effect(KILL cr);
8521 flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag);
8522
8523 format %{ "negl $dst\t# int" %}
8524 ins_encode %{
8525 __ negl($dst$$Register);
8526 %}
8527 ins_pipe(ialu_reg);
8528 %}
8529
8530 instruct negI_rReg_2_ndd(rRegI dst, rRegI src, rFlagsReg cr)
8531 %{
8532 predicate(UseAPX);
8533 match(Set dst (NegI src));
8534 effect(KILL cr);
8535 flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag);
8536
8537 format %{ "enegl $dst, $src\t# int ndd" %}
8538 ins_encode %{
8539 __ enegl($dst$$Register, $src$$Register, false);
8540 %}
8541 ins_pipe(ialu_reg);
8542 %}
8543
8544 instruct negI_mem(memory dst, immI_0 zero, rFlagsReg cr)
8545 %{
8546 match(Set dst (StoreI dst (SubI zero (LoadI dst))));
8547 effect(KILL cr);
8548 flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag);
8549
8550 format %{ "negl $dst\t# int" %}
8551 ins_encode %{
8552 __ negl($dst$$Address);
8553 %}
8554 ins_pipe(ialu_reg);
8555 %}
8556
8557 instruct negL_rReg(rRegL dst, immL0 zero, rFlagsReg cr)
8558 %{
8559 predicate(!UseAPX);
8560 match(Set dst (SubL zero dst));
8561 effect(KILL cr);
8562 flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag);
8563
8564 format %{ "negq $dst\t# long" %}
8565 ins_encode %{
8566 __ negq($dst$$Register);
8567 %}
8568 ins_pipe(ialu_reg);
8569 %}
8570
8571 instruct negL_rReg_ndd(rRegL dst, rRegL src, immL0 zero, rFlagsReg cr)
8572 %{
8573 predicate(UseAPX);
8574 match(Set dst (SubL zero src));
8575 effect(KILL cr);
8576 flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag);
8577
8578 format %{ "enegq $dst, $src\t# long ndd" %}
8579 ins_encode %{
8580 __ enegq($dst$$Register, $src$$Register, false);
8581 %}
8582 ins_pipe(ialu_reg);
8583 %}
8584
8585 instruct negL_rReg_2(rRegL dst, rFlagsReg cr)
8586 %{
8587 predicate(!UseAPX);
8588 match(Set dst (NegL dst));
8589 effect(KILL cr);
8590 flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag);
8591
8592 format %{ "negq $dst\t# int" %}
8593 ins_encode %{
8594 __ negq($dst$$Register);
8595 %}
8596 ins_pipe(ialu_reg);
8597 %}
8598
8599 instruct negL_rReg_2_ndd(rRegL dst, rRegL src, rFlagsReg cr)
8600 %{
8601 predicate(UseAPX);
8602 match(Set dst (NegL src));
8603 effect(KILL cr);
8604 flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag);
8605
8606 format %{ "enegq $dst, $src\t# long ndd" %}
8607 ins_encode %{
8608 __ enegq($dst$$Register, $src$$Register, false);
8609 %}
8610 ins_pipe(ialu_reg);
8611 %}
8612
8613 instruct negL_mem(memory dst, immL0 zero, rFlagsReg cr)
8614 %{
8615 match(Set dst (StoreL dst (SubL zero (LoadL dst))));
8616 effect(KILL cr);
8617 flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag);
8618
8619 format %{ "negq $dst\t# long" %}
8620 ins_encode %{
8621 __ negq($dst$$Address);
8622 %}
8623 ins_pipe(ialu_reg);
8624 %}
8625
8626 //----------Multiplication/Division Instructions-------------------------------
8627 // Integer Multiplication Instructions
8628 // Multiply Register
8629
8630 instruct mulI_rReg(rRegI dst, rRegI src, rFlagsReg cr)
8631 %{
8632 predicate(!UseAPX);
8633 match(Set dst (MulI dst src));
8634 effect(KILL cr);
8635
8636 ins_cost(300);
8637 format %{ "imull $dst, $src\t# int" %}
8638 ins_encode %{
8639 __ imull($dst$$Register, $src$$Register);
8640 %}
8641 ins_pipe(ialu_reg_reg_alu0);
8642 %}
8643
8644 instruct mulI_rReg_ndd(rRegI dst, rRegI src1, rRegI src2, rFlagsReg cr)
8645 %{
8646 predicate(UseAPX);
8647 match(Set dst (MulI src1 src2));
8648 effect(KILL cr);
8649
8650 ins_cost(300);
8651 format %{ "eimull $dst, $src1, $src2\t# int ndd" %}
8652 ins_encode %{
8653 __ eimull($dst$$Register, $src1$$Register, $src2$$Register, false);
8654 %}
8655 ins_pipe(ialu_reg_reg_alu0);
8656 %}
8657
8658 instruct mulI_rReg_imm(rRegI dst, rRegI src, immI imm, rFlagsReg cr)
8659 %{
8660 match(Set dst (MulI src imm));
8661 effect(KILL cr);
8662
8663 ins_cost(300);
8664 format %{ "imull $dst, $src, $imm\t# int" %}
8665 ins_encode %{
8666 __ imull($dst$$Register, $src$$Register, $imm$$constant);
8667 %}
8668 ins_pipe(ialu_reg_reg_alu0);
8669 %}
8670
8671 instruct mulI_mem(rRegI dst, memory src, rFlagsReg cr)
8672 %{
8673 predicate(!UseAPX);
8674 match(Set dst (MulI dst (LoadI src)));
8675 effect(KILL cr);
8676
8677 ins_cost(350);
8678 format %{ "imull $dst, $src\t# int" %}
8679 ins_encode %{
8680 __ imull($dst$$Register, $src$$Address);
8681 %}
8682 ins_pipe(ialu_reg_mem_alu0);
8683 %}
8684
8685 instruct mulI_rReg_rReg_mem_ndd(rRegI dst, rRegI src1, memory src2, rFlagsReg cr)
8686 %{
8687 predicate(UseAPX);
8688 match(Set dst (MulI src1 (LoadI src2)));
8689 effect(KILL cr);
8690
8691 ins_cost(350);
8692 format %{ "eimull $dst, $src1, $src2\t# int ndd" %}
8693 ins_encode %{
8694 __ eimull($dst$$Register, $src1$$Register, $src2$$Address, false);
8695 %}
8696 ins_pipe(ialu_reg_mem_alu0);
8697 %}
8698
8699 instruct mulI_mem_imm(rRegI dst, memory src, immI imm, rFlagsReg cr)
8700 %{
8701 match(Set dst (MulI (LoadI src) imm));
8702 effect(KILL cr);
8703
8704 ins_cost(300);
8705 format %{ "imull $dst, $src, $imm\t# int" %}
8706 ins_encode %{
8707 __ imull($dst$$Register, $src$$Address, $imm$$constant);
8708 %}
8709 ins_pipe(ialu_reg_mem_alu0);
8710 %}
8711
8712 instruct mulAddS2I_rReg(rRegI dst, rRegI src1, rRegI src2, rRegI src3, rFlagsReg cr)
8713 %{
8714 match(Set dst (MulAddS2I (Binary dst src1) (Binary src2 src3)));
8715 effect(KILL cr, KILL src2);
8716
8717 expand %{ mulI_rReg(dst, src1, cr);
8718 mulI_rReg(src2, src3, cr);
8719 addI_rReg(dst, src2, cr); %}
8720 %}
8721
8722 instruct mulL_rReg(rRegL dst, rRegL src, rFlagsReg cr)
8723 %{
8724 predicate(!UseAPX);
8725 match(Set dst (MulL dst src));
8726 effect(KILL cr);
8727
8728 ins_cost(300);
8729 format %{ "imulq $dst, $src\t# long" %}
8730 ins_encode %{
8731 __ imulq($dst$$Register, $src$$Register);
8732 %}
8733 ins_pipe(ialu_reg_reg_alu0);
8734 %}
8735
8736 instruct mulL_rReg_ndd(rRegL dst, rRegL src1, rRegL src2, rFlagsReg cr)
8737 %{
8738 predicate(UseAPX);
8739 match(Set dst (MulL src1 src2));
8740 effect(KILL cr);
8741
8742 ins_cost(300);
8743 format %{ "eimulq $dst, $src1, $src2\t# long ndd" %}
8744 ins_encode %{
8745 __ eimulq($dst$$Register, $src1$$Register, $src2$$Register, false);
8746 %}
8747 ins_pipe(ialu_reg_reg_alu0);
8748 %}
8749
8750 instruct mulL_rReg_imm(rRegL dst, rRegL src, immL32 imm, rFlagsReg cr)
8751 %{
8752 match(Set dst (MulL src imm));
8753 effect(KILL cr);
8754
8755 ins_cost(300);
8756 format %{ "imulq $dst, $src, $imm\t# long" %}
8757 ins_encode %{
8758 __ imulq($dst$$Register, $src$$Register, $imm$$constant);
8759 %}
8760 ins_pipe(ialu_reg_reg_alu0);
8761 %}
8762
8763 instruct mulL_mem(rRegL dst, memory src, rFlagsReg cr)
8764 %{
8765 predicate(!UseAPX);
8766 match(Set dst (MulL dst (LoadL src)));
8767 effect(KILL cr);
8768
8769 ins_cost(350);
8770 format %{ "imulq $dst, $src\t# long" %}
8771 ins_encode %{
8772 __ imulq($dst$$Register, $src$$Address);
8773 %}
8774 ins_pipe(ialu_reg_mem_alu0);
8775 %}
8776
8777 instruct mulL_rReg_rReg_mem_ndd(rRegL dst, rRegL src1, memory src2, rFlagsReg cr)
8778 %{
8779 predicate(UseAPX);
8780 match(Set dst (MulL src1 (LoadL src2)));
8781 effect(KILL cr);
8782
8783 ins_cost(350);
8784 format %{ "eimulq $dst, $src1, $src2 \t# long" %}
8785 ins_encode %{
8786 __ eimulq($dst$$Register, $src1$$Register, $src2$$Address, false);
8787 %}
8788 ins_pipe(ialu_reg_mem_alu0);
8789 %}
8790
8791 instruct mulL_mem_imm(rRegL dst, memory src, immL32 imm, rFlagsReg cr)
8792 %{
8793 match(Set dst (MulL (LoadL src) imm));
8794 effect(KILL cr);
8795
8796 ins_cost(300);
8797 format %{ "imulq $dst, $src, $imm\t# long" %}
8798 ins_encode %{
8799 __ imulq($dst$$Register, $src$$Address, $imm$$constant);
8800 %}
8801 ins_pipe(ialu_reg_mem_alu0);
8802 %}
8803
8804 instruct mulHiL_rReg(rdx_RegL dst, rRegL src, rax_RegL rax, rFlagsReg cr)
8805 %{
8806 match(Set dst (MulHiL src rax));
8807 effect(USE_KILL rax, KILL cr);
8808
8809 ins_cost(300);
8810 format %{ "imulq RDX:RAX, RAX, $src\t# mulhi" %}
8811 ins_encode %{
8812 __ imulq($src$$Register);
8813 %}
8814 ins_pipe(ialu_reg_reg_alu0);
8815 %}
8816
8817 instruct umulHiL_rReg(rdx_RegL dst, rRegL src, rax_RegL rax, rFlagsReg cr)
8818 %{
8819 match(Set dst (UMulHiL src rax));
8820 effect(USE_KILL rax, KILL cr);
8821
8822 ins_cost(300);
8823 format %{ "mulq RDX:RAX, RAX, $src\t# umulhi" %}
8824 ins_encode %{
8825 __ mulq($src$$Register);
8826 %}
8827 ins_pipe(ialu_reg_reg_alu0);
8828 %}
8829
8830 instruct divI_rReg(rax_RegI rax, rdx_RegI rdx, no_rax_rdx_RegI div,
8831 rFlagsReg cr)
8832 %{
8833 match(Set rax (DivI rax div));
8834 effect(KILL rdx, KILL cr);
8835
8836 ins_cost(30*100+10*100); // XXX
8837 format %{ "cmpl rax, 0x80000000\t# idiv\n\t"
8838 "jne,s normal\n\t"
8839 "xorl rdx, rdx\n\t"
8840 "cmpl $div, -1\n\t"
8841 "je,s done\n"
8842 "normal: cdql\n\t"
8843 "idivl $div\n"
8844 "done:" %}
8845 ins_encode(cdql_enc(div));
8846 ins_pipe(ialu_reg_reg_alu0);
8847 %}
8848
8849 instruct divL_rReg(rax_RegL rax, rdx_RegL rdx, no_rax_rdx_RegL div,
8850 rFlagsReg cr)
8851 %{
8852 match(Set rax (DivL rax div));
8853 effect(KILL rdx, KILL cr);
8854
8855 ins_cost(30*100+10*100); // XXX
8856 format %{ "movq rdx, 0x8000000000000000\t# ldiv\n\t"
8857 "cmpq rax, rdx\n\t"
8858 "jne,s normal\n\t"
8859 "xorl rdx, rdx\n\t"
8860 "cmpq $div, -1\n\t"
8861 "je,s done\n"
8862 "normal: cdqq\n\t"
8863 "idivq $div\n"
8864 "done:" %}
8865 ins_encode(cdqq_enc(div));
8866 ins_pipe(ialu_reg_reg_alu0);
8867 %}
8868
8869 instruct udivI_rReg(rax_RegI rax, rdx_RegI rdx, no_rax_rdx_RegI div, rFlagsReg cr)
8870 %{
8871 match(Set rax (UDivI rax div));
8872 effect(KILL rdx, KILL cr);
8873
8874 ins_cost(300);
8875 format %{ "udivl $rax,$rax,$div\t# UDivI\n" %}
8876 ins_encode %{
8877 __ udivI($rax$$Register, $div$$Register, $rdx$$Register);
8878 %}
8879 ins_pipe(ialu_reg_reg_alu0);
8880 %}
8881
8882 instruct udivL_rReg(rax_RegL rax, rdx_RegL rdx, no_rax_rdx_RegL div, rFlagsReg cr)
8883 %{
8884 match(Set rax (UDivL rax div));
8885 effect(KILL rdx, KILL cr);
8886
8887 ins_cost(300);
8888 format %{ "udivq $rax,$rax,$div\t# UDivL\n" %}
8889 ins_encode %{
8890 __ udivL($rax$$Register, $div$$Register, $rdx$$Register);
8891 %}
8892 ins_pipe(ialu_reg_reg_alu0);
8893 %}
8894
8895 // Integer DIVMOD with Register, both quotient and mod results
8896 instruct divModI_rReg_divmod(rax_RegI rax, rdx_RegI rdx, no_rax_rdx_RegI div,
8897 rFlagsReg cr)
8898 %{
8899 match(DivModI rax div);
8900 effect(KILL cr);
8901
8902 ins_cost(30*100+10*100); // XXX
8903 format %{ "cmpl rax, 0x80000000\t# idiv\n\t"
8904 "jne,s normal\n\t"
8905 "xorl rdx, rdx\n\t"
8906 "cmpl $div, -1\n\t"
8907 "je,s done\n"
8908 "normal: cdql\n\t"
8909 "idivl $div\n"
8910 "done:" %}
8911 ins_encode(cdql_enc(div));
8912 ins_pipe(pipe_slow);
8913 %}
8914
8915 // Long DIVMOD with Register, both quotient and mod results
8916 instruct divModL_rReg_divmod(rax_RegL rax, rdx_RegL rdx, no_rax_rdx_RegL div,
8917 rFlagsReg cr)
8918 %{
8919 match(DivModL rax div);
8920 effect(KILL cr);
8921
8922 ins_cost(30*100+10*100); // XXX
8923 format %{ "movq rdx, 0x8000000000000000\t# ldiv\n\t"
8924 "cmpq rax, rdx\n\t"
8925 "jne,s normal\n\t"
8926 "xorl rdx, rdx\n\t"
8927 "cmpq $div, -1\n\t"
8928 "je,s done\n"
8929 "normal: cdqq\n\t"
8930 "idivq $div\n"
8931 "done:" %}
8932 ins_encode(cdqq_enc(div));
8933 ins_pipe(pipe_slow);
8934 %}
8935
8936 // Unsigned integer DIVMOD with Register, both quotient and mod results
8937 instruct udivModI_rReg_divmod(rax_RegI rax, no_rax_rdx_RegI tmp, rdx_RegI rdx,
8938 no_rax_rdx_RegI div, rFlagsReg cr)
8939 %{
8940 match(UDivModI rax div);
8941 effect(TEMP tmp, KILL cr);
8942
8943 ins_cost(300);
8944 format %{ "udivl $rax,$rax,$div\t# begin UDivModI\n\t"
8945 "umodl $rdx,$rax,$div\t! using $tmp as TEMP # end UDivModI\n"
8946 %}
8947 ins_encode %{
8948 __ udivmodI($rax$$Register, $div$$Register, $rdx$$Register, $tmp$$Register);
8949 %}
8950 ins_pipe(pipe_slow);
8951 %}
8952
8953 // Unsigned long DIVMOD with Register, both quotient and mod results
8954 instruct udivModL_rReg_divmod(rax_RegL rax, no_rax_rdx_RegL tmp, rdx_RegL rdx,
8955 no_rax_rdx_RegL div, rFlagsReg cr)
8956 %{
8957 match(UDivModL rax div);
8958 effect(TEMP tmp, KILL cr);
8959
8960 ins_cost(300);
8961 format %{ "udivq $rax,$rax,$div\t# begin UDivModL\n\t"
8962 "umodq $rdx,$rax,$div\t! using $tmp as TEMP # end UDivModL\n"
8963 %}
8964 ins_encode %{
8965 __ udivmodL($rax$$Register, $div$$Register, $rdx$$Register, $tmp$$Register);
8966 %}
8967 ins_pipe(pipe_slow);
8968 %}
8969
8970 instruct modI_rReg(rdx_RegI rdx, rax_RegI rax, no_rax_rdx_RegI div,
8971 rFlagsReg cr)
8972 %{
8973 match(Set rdx (ModI rax div));
8974 effect(KILL rax, KILL cr);
8975
8976 ins_cost(300); // XXX
8977 format %{ "cmpl rax, 0x80000000\t# irem\n\t"
8978 "jne,s normal\n\t"
8979 "xorl rdx, rdx\n\t"
8980 "cmpl $div, -1\n\t"
8981 "je,s done\n"
8982 "normal: cdql\n\t"
8983 "idivl $div\n"
8984 "done:" %}
8985 ins_encode(cdql_enc(div));
8986 ins_pipe(ialu_reg_reg_alu0);
8987 %}
8988
8989 instruct modL_rReg(rdx_RegL rdx, rax_RegL rax, no_rax_rdx_RegL div,
8990 rFlagsReg cr)
8991 %{
8992 match(Set rdx (ModL rax div));
8993 effect(KILL rax, KILL cr);
8994
8995 ins_cost(300); // XXX
8996 format %{ "movq rdx, 0x8000000000000000\t# lrem\n\t"
8997 "cmpq rax, rdx\n\t"
8998 "jne,s normal\n\t"
8999 "xorl rdx, rdx\n\t"
9000 "cmpq $div, -1\n\t"
9001 "je,s done\n"
9002 "normal: cdqq\n\t"
9003 "idivq $div\n"
9004 "done:" %}
9005 ins_encode(cdqq_enc(div));
9006 ins_pipe(ialu_reg_reg_alu0);
9007 %}
9008
9009 instruct umodI_rReg(rdx_RegI rdx, rax_RegI rax, no_rax_rdx_RegI div, rFlagsReg cr)
9010 %{
9011 match(Set rdx (UModI rax div));
9012 effect(KILL rax, KILL cr);
9013
9014 ins_cost(300);
9015 format %{ "umodl $rdx,$rax,$div\t# UModI\n" %}
9016 ins_encode %{
9017 __ umodI($rax$$Register, $div$$Register, $rdx$$Register);
9018 %}
9019 ins_pipe(ialu_reg_reg_alu0);
9020 %}
9021
9022 instruct umodL_rReg(rdx_RegL rdx, rax_RegL rax, no_rax_rdx_RegL div, rFlagsReg cr)
9023 %{
9024 match(Set rdx (UModL rax div));
9025 effect(KILL rax, KILL cr);
9026
9027 ins_cost(300);
9028 format %{ "umodq $rdx,$rax,$div\t# UModL\n" %}
9029 ins_encode %{
9030 __ umodL($rax$$Register, $div$$Register, $rdx$$Register);
9031 %}
9032 ins_pipe(ialu_reg_reg_alu0);
9033 %}
9034
9035 // Integer Shift Instructions
9036 // Shift Left by one, two, three
9037 instruct salI_rReg_immI2(rRegI dst, immI2 shift, rFlagsReg cr)
9038 %{
9039 predicate(!UseAPX);
9040 match(Set dst (LShiftI dst shift));
9041 effect(KILL cr);
9042
9043 format %{ "sall $dst, $shift" %}
9044 ins_encode %{
9045 __ sall($dst$$Register, $shift$$constant);
9046 %}
9047 ins_pipe(ialu_reg);
9048 %}
9049
9050 // Shift Left by one, two, three
9051 instruct salI_rReg_immI2_ndd(rRegI dst, rRegI src, immI2 shift, rFlagsReg cr)
9052 %{
9053 predicate(UseAPX);
9054 match(Set dst (LShiftI src shift));
9055 effect(KILL cr);
9056
9057 format %{ "esall $dst, $src, $shift\t# int(ndd)" %}
9058 ins_encode %{
9059 __ esall($dst$$Register, $src$$Register, $shift$$constant, false);
9060 %}
9061 ins_pipe(ialu_reg);
9062 %}
9063
9064 // Shift Left by 8-bit immediate
9065 instruct salI_rReg_imm(rRegI dst, immI8 shift, rFlagsReg cr)
9066 %{
9067 predicate(!UseAPX);
9068 match(Set dst (LShiftI dst shift));
9069 effect(KILL cr);
9070
9071 format %{ "sall $dst, $shift" %}
9072 ins_encode %{
9073 __ sall($dst$$Register, $shift$$constant);
9074 %}
9075 ins_pipe(ialu_reg);
9076 %}
9077
9078 // Shift Left by 8-bit immediate
9079 instruct salI_rReg_imm_ndd(rRegI dst, rRegI src, immI8 shift, rFlagsReg cr)
9080 %{
9081 predicate(UseAPX);
9082 match(Set dst (LShiftI src shift));
9083 effect(KILL cr);
9084
9085 format %{ "esall $dst, $src, $shift\t# int (ndd)" %}
9086 ins_encode %{
9087 __ esall($dst$$Register, $src$$Register, $shift$$constant, false);
9088 %}
9089 ins_pipe(ialu_reg);
9090 %}
9091
9092 instruct salI_rReg_mem_imm_ndd(rRegI dst, memory src, immI8 shift, rFlagsReg cr)
9093 %{
9094 predicate(UseAPX);
9095 match(Set dst (LShiftI (LoadI src) shift));
9096 effect(KILL cr);
9097
9098 format %{ "esall $dst, $src, $shift\t# int (ndd)" %}
9099 ins_encode %{
9100 __ esall($dst$$Register, $src$$Address, $shift$$constant, false);
9101 %}
9102 ins_pipe(ialu_reg);
9103 %}
9104
9105 // Shift Left by 8-bit immediate
9106 instruct salI_mem_imm(memory dst, immI8 shift, rFlagsReg cr)
9107 %{
9108 match(Set dst (StoreI dst (LShiftI (LoadI dst) shift)));
9109 effect(KILL cr);
9110
9111 format %{ "sall $dst, $shift" %}
9112 ins_encode %{
9113 __ sall($dst$$Address, $shift$$constant);
9114 %}
9115 ins_pipe(ialu_mem_imm);
9116 %}
9117
9118 // Shift Left by variable
9119 instruct salI_rReg_CL(rRegI dst, rcx_RegI shift, rFlagsReg cr)
9120 %{
9121 predicate(!VM_Version::supports_bmi2());
9122 match(Set dst (LShiftI dst shift));
9123 effect(KILL cr);
9124
9125 format %{ "sall $dst, $shift" %}
9126 ins_encode %{
9127 __ sall($dst$$Register);
9128 %}
9129 ins_pipe(ialu_reg_reg);
9130 %}
9131
9132 // Shift Left by variable
9133 instruct salI_mem_CL(memory dst, rcx_RegI shift, rFlagsReg cr)
9134 %{
9135 predicate(!VM_Version::supports_bmi2());
9136 match(Set dst (StoreI dst (LShiftI (LoadI dst) shift)));
9137 effect(KILL cr);
9138
9139 format %{ "sall $dst, $shift" %}
9140 ins_encode %{
9141 __ sall($dst$$Address);
9142 %}
9143 ins_pipe(ialu_mem_reg);
9144 %}
9145
9146 instruct salI_rReg_rReg(rRegI dst, rRegI src, rRegI shift)
9147 %{
9148 predicate(VM_Version::supports_bmi2());
9149 match(Set dst (LShiftI src shift));
9150
9151 format %{ "shlxl $dst, $src, $shift" %}
9152 ins_encode %{
9153 __ shlxl($dst$$Register, $src$$Register, $shift$$Register);
9154 %}
9155 ins_pipe(ialu_reg_reg);
9156 %}
9157
9158 instruct salI_mem_rReg(rRegI dst, memory src, rRegI shift)
9159 %{
9160 predicate(VM_Version::supports_bmi2());
9161 match(Set dst (LShiftI (LoadI src) shift));
9162 ins_cost(175);
9163 format %{ "shlxl $dst, $src, $shift" %}
9164 ins_encode %{
9165 __ shlxl($dst$$Register, $src$$Address, $shift$$Register);
9166 %}
9167 ins_pipe(ialu_reg_mem);
9168 %}
9169
9170 // Arithmetic Shift Right by 8-bit immediate
9171 instruct sarI_rReg_imm(rRegI dst, immI8 shift, rFlagsReg cr)
9172 %{
9173 predicate(!UseAPX);
9174 match(Set dst (RShiftI dst shift));
9175 effect(KILL cr);
9176
9177 format %{ "sarl $dst, $shift" %}
9178 ins_encode %{
9179 __ sarl($dst$$Register, $shift$$constant);
9180 %}
9181 ins_pipe(ialu_mem_imm);
9182 %}
9183
9184 // Arithmetic Shift Right by 8-bit immediate
9185 instruct sarI_rReg_imm_ndd(rRegI dst, rRegI src, immI8 shift, rFlagsReg cr)
9186 %{
9187 predicate(UseAPX);
9188 match(Set dst (RShiftI src shift));
9189 effect(KILL cr);
9190
9191 format %{ "esarl $dst, $src, $shift\t# int (ndd)" %}
9192 ins_encode %{
9193 __ esarl($dst$$Register, $src$$Register, $shift$$constant, false);
9194 %}
9195 ins_pipe(ialu_mem_imm);
9196 %}
9197
9198 instruct sarI_rReg_mem_imm_ndd(rRegI dst, memory src, immI8 shift, rFlagsReg cr)
9199 %{
9200 predicate(UseAPX);
9201 match(Set dst (RShiftI (LoadI src) shift));
9202 effect(KILL cr);
9203
9204 format %{ "esarl $dst, $src, $shift\t# int (ndd)" %}
9205 ins_encode %{
9206 __ esarl($dst$$Register, $src$$Address, $shift$$constant, false);
9207 %}
9208 ins_pipe(ialu_mem_imm);
9209 %}
9210
9211 // Arithmetic Shift Right by 8-bit immediate
9212 instruct sarI_mem_imm(memory dst, immI8 shift, rFlagsReg cr)
9213 %{
9214 match(Set dst (StoreI dst (RShiftI (LoadI dst) shift)));
9215 effect(KILL cr);
9216
9217 format %{ "sarl $dst, $shift" %}
9218 ins_encode %{
9219 __ sarl($dst$$Address, $shift$$constant);
9220 %}
9221 ins_pipe(ialu_mem_imm);
9222 %}
9223
9224 // Arithmetic Shift Right by variable
9225 instruct sarI_rReg_CL(rRegI dst, rcx_RegI shift, rFlagsReg cr)
9226 %{
9227 predicate(!VM_Version::supports_bmi2());
9228 match(Set dst (RShiftI dst shift));
9229 effect(KILL cr);
9230
9231 format %{ "sarl $dst, $shift" %}
9232 ins_encode %{
9233 __ sarl($dst$$Register);
9234 %}
9235 ins_pipe(ialu_reg_reg);
9236 %}
9237
9238 // Arithmetic Shift Right by variable
9239 instruct sarI_mem_CL(memory dst, rcx_RegI shift, rFlagsReg cr)
9240 %{
9241 predicate(!VM_Version::supports_bmi2());
9242 match(Set dst (StoreI dst (RShiftI (LoadI dst) shift)));
9243 effect(KILL cr);
9244
9245 format %{ "sarl $dst, $shift" %}
9246 ins_encode %{
9247 __ sarl($dst$$Address);
9248 %}
9249 ins_pipe(ialu_mem_reg);
9250 %}
9251
9252 instruct sarI_rReg_rReg(rRegI dst, rRegI src, rRegI shift)
9253 %{
9254 predicate(VM_Version::supports_bmi2());
9255 match(Set dst (RShiftI src shift));
9256
9257 format %{ "sarxl $dst, $src, $shift" %}
9258 ins_encode %{
9259 __ sarxl($dst$$Register, $src$$Register, $shift$$Register);
9260 %}
9261 ins_pipe(ialu_reg_reg);
9262 %}
9263
9264 instruct sarI_mem_rReg(rRegI dst, memory src, rRegI shift)
9265 %{
9266 predicate(VM_Version::supports_bmi2());
9267 match(Set dst (RShiftI (LoadI src) shift));
9268 ins_cost(175);
9269 format %{ "sarxl $dst, $src, $shift" %}
9270 ins_encode %{
9271 __ sarxl($dst$$Register, $src$$Address, $shift$$Register);
9272 %}
9273 ins_pipe(ialu_reg_mem);
9274 %}
9275
9276 // Logical Shift Right by 8-bit immediate
9277 instruct shrI_rReg_imm(rRegI dst, immI8 shift, rFlagsReg cr)
9278 %{
9279 predicate(!UseAPX);
9280 match(Set dst (URShiftI dst shift));
9281 effect(KILL cr);
9282
9283 format %{ "shrl $dst, $shift" %}
9284 ins_encode %{
9285 __ shrl($dst$$Register, $shift$$constant);
9286 %}
9287 ins_pipe(ialu_reg);
9288 %}
9289
9290 // Logical Shift Right by 8-bit immediate
9291 instruct shrI_rReg_imm_ndd(rRegI dst, rRegI src, immI8 shift, rFlagsReg cr)
9292 %{
9293 predicate(UseAPX);
9294 match(Set dst (URShiftI src shift));
9295 effect(KILL cr);
9296
9297 format %{ "eshrl $dst, $src, $shift\t # int (ndd)" %}
9298 ins_encode %{
9299 __ eshrl($dst$$Register, $src$$Register, $shift$$constant, false);
9300 %}
9301 ins_pipe(ialu_reg);
9302 %}
9303
9304 instruct shrI_rReg_mem_imm_ndd(rRegI dst, memory src, immI8 shift, rFlagsReg cr)
9305 %{
9306 predicate(UseAPX);
9307 match(Set dst (URShiftI (LoadI src) shift));
9308 effect(KILL cr);
9309
9310 format %{ "eshrl $dst, $src, $shift\t # int (ndd)" %}
9311 ins_encode %{
9312 __ eshrl($dst$$Register, $src$$Address, $shift$$constant, false);
9313 %}
9314 ins_pipe(ialu_reg);
9315 %}
9316
9317 // Logical Shift Right by 8-bit immediate
9318 instruct shrI_mem_imm(memory dst, immI8 shift, rFlagsReg cr)
9319 %{
9320 match(Set dst (StoreI dst (URShiftI (LoadI dst) shift)));
9321 effect(KILL cr);
9322
9323 format %{ "shrl $dst, $shift" %}
9324 ins_encode %{
9325 __ shrl($dst$$Address, $shift$$constant);
9326 %}
9327 ins_pipe(ialu_mem_imm);
9328 %}
9329
9330 // Logical Shift Right by variable
9331 instruct shrI_rReg_CL(rRegI dst, rcx_RegI shift, rFlagsReg cr)
9332 %{
9333 predicate(!VM_Version::supports_bmi2());
9334 match(Set dst (URShiftI dst shift));
9335 effect(KILL cr);
9336
9337 format %{ "shrl $dst, $shift" %}
9338 ins_encode %{
9339 __ shrl($dst$$Register);
9340 %}
9341 ins_pipe(ialu_reg_reg);
9342 %}
9343
9344 // Logical Shift Right by variable
9345 instruct shrI_mem_CL(memory dst, rcx_RegI shift, rFlagsReg cr)
9346 %{
9347 predicate(!VM_Version::supports_bmi2());
9348 match(Set dst (StoreI dst (URShiftI (LoadI dst) shift)));
9349 effect(KILL cr);
9350
9351 format %{ "shrl $dst, $shift" %}
9352 ins_encode %{
9353 __ shrl($dst$$Address);
9354 %}
9355 ins_pipe(ialu_mem_reg);
9356 %}
9357
9358 instruct shrI_rReg_rReg(rRegI dst, rRegI src, rRegI shift)
9359 %{
9360 predicate(VM_Version::supports_bmi2());
9361 match(Set dst (URShiftI src shift));
9362
9363 format %{ "shrxl $dst, $src, $shift" %}
9364 ins_encode %{
9365 __ shrxl($dst$$Register, $src$$Register, $shift$$Register);
9366 %}
9367 ins_pipe(ialu_reg_reg);
9368 %}
9369
9370 instruct shrI_mem_rReg(rRegI dst, memory src, rRegI shift)
9371 %{
9372 predicate(VM_Version::supports_bmi2());
9373 match(Set dst (URShiftI (LoadI src) shift));
9374 ins_cost(175);
9375 format %{ "shrxl $dst, $src, $shift" %}
9376 ins_encode %{
9377 __ shrxl($dst$$Register, $src$$Address, $shift$$Register);
9378 %}
9379 ins_pipe(ialu_reg_mem);
9380 %}
9381
9382 // Long Shift Instructions
9383 // Shift Left by one, two, three
9384 instruct salL_rReg_immI2(rRegL dst, immI2 shift, rFlagsReg cr)
9385 %{
9386 predicate(!UseAPX);
9387 match(Set dst (LShiftL dst shift));
9388 effect(KILL cr);
9389
9390 format %{ "salq $dst, $shift" %}
9391 ins_encode %{
9392 __ salq($dst$$Register, $shift$$constant);
9393 %}
9394 ins_pipe(ialu_reg);
9395 %}
9396
9397 // Shift Left by one, two, three
9398 instruct salL_rReg_immI2_ndd(rRegL dst, rRegL src, immI2 shift, rFlagsReg cr)
9399 %{
9400 predicate(UseAPX);
9401 match(Set dst (LShiftL src shift));
9402 effect(KILL cr);
9403
9404 format %{ "esalq $dst, $src, $shift\t# long (ndd)" %}
9405 ins_encode %{
9406 __ esalq($dst$$Register, $src$$Register, $shift$$constant, false);
9407 %}
9408 ins_pipe(ialu_reg);
9409 %}
9410
9411 // Shift Left by 8-bit immediate
9412 instruct salL_rReg_imm(rRegL dst, immI8 shift, rFlagsReg cr)
9413 %{
9414 predicate(!UseAPX);
9415 match(Set dst (LShiftL dst shift));
9416 effect(KILL cr);
9417
9418 format %{ "salq $dst, $shift" %}
9419 ins_encode %{
9420 __ salq($dst$$Register, $shift$$constant);
9421 %}
9422 ins_pipe(ialu_reg);
9423 %}
9424
9425 // Shift Left by 8-bit immediate
9426 instruct salL_rReg_imm_ndd(rRegL dst, rRegL src, immI8 shift, rFlagsReg cr)
9427 %{
9428 predicate(UseAPX);
9429 match(Set dst (LShiftL src shift));
9430 effect(KILL cr);
9431
9432 format %{ "esalq $dst, $src, $shift\t# long (ndd)" %}
9433 ins_encode %{
9434 __ esalq($dst$$Register, $src$$Register, $shift$$constant, false);
9435 %}
9436 ins_pipe(ialu_reg);
9437 %}
9438
9439 instruct salL_rReg_mem_imm_ndd(rRegL dst, memory src, immI8 shift, rFlagsReg cr)
9440 %{
9441 predicate(UseAPX);
9442 match(Set dst (LShiftL (LoadL src) shift));
9443 effect(KILL cr);
9444
9445 format %{ "esalq $dst, $src, $shift\t# long (ndd)" %}
9446 ins_encode %{
9447 __ esalq($dst$$Register, $src$$Address, $shift$$constant, false);
9448 %}
9449 ins_pipe(ialu_reg);
9450 %}
9451
9452 // Shift Left by 8-bit immediate
9453 instruct salL_mem_imm(memory dst, immI8 shift, rFlagsReg cr)
9454 %{
9455 match(Set dst (StoreL dst (LShiftL (LoadL dst) shift)));
9456 effect(KILL cr);
9457
9458 format %{ "salq $dst, $shift" %}
9459 ins_encode %{
9460 __ salq($dst$$Address, $shift$$constant);
9461 %}
9462 ins_pipe(ialu_mem_imm);
9463 %}
9464
9465 // Shift Left by variable
9466 instruct salL_rReg_CL(rRegL dst, rcx_RegI shift, rFlagsReg cr)
9467 %{
9468 predicate(!VM_Version::supports_bmi2());
9469 match(Set dst (LShiftL dst shift));
9470 effect(KILL cr);
9471
9472 format %{ "salq $dst, $shift" %}
9473 ins_encode %{
9474 __ salq($dst$$Register);
9475 %}
9476 ins_pipe(ialu_reg_reg);
9477 %}
9478
9479 // Shift Left by variable
9480 instruct salL_mem_CL(memory dst, rcx_RegI shift, rFlagsReg cr)
9481 %{
9482 predicate(!VM_Version::supports_bmi2());
9483 match(Set dst (StoreL dst (LShiftL (LoadL dst) shift)));
9484 effect(KILL cr);
9485
9486 format %{ "salq $dst, $shift" %}
9487 ins_encode %{
9488 __ salq($dst$$Address);
9489 %}
9490 ins_pipe(ialu_mem_reg);
9491 %}
9492
9493 instruct salL_rReg_rReg(rRegL dst, rRegL src, rRegI shift)
9494 %{
9495 predicate(VM_Version::supports_bmi2());
9496 match(Set dst (LShiftL src shift));
9497
9498 format %{ "shlxq $dst, $src, $shift" %}
9499 ins_encode %{
9500 __ shlxq($dst$$Register, $src$$Register, $shift$$Register);
9501 %}
9502 ins_pipe(ialu_reg_reg);
9503 %}
9504
9505 instruct salL_mem_rReg(rRegL dst, memory src, rRegI shift)
9506 %{
9507 predicate(VM_Version::supports_bmi2());
9508 match(Set dst (LShiftL (LoadL src) shift));
9509 ins_cost(175);
9510 format %{ "shlxq $dst, $src, $shift" %}
9511 ins_encode %{
9512 __ shlxq($dst$$Register, $src$$Address, $shift$$Register);
9513 %}
9514 ins_pipe(ialu_reg_mem);
9515 %}
9516
9517 // Arithmetic Shift Right by 8-bit immediate
9518 instruct sarL_rReg_imm(rRegL dst, immI shift, rFlagsReg cr)
9519 %{
9520 predicate(!UseAPX);
9521 match(Set dst (RShiftL dst shift));
9522 effect(KILL cr);
9523
9524 format %{ "sarq $dst, $shift" %}
9525 ins_encode %{
9526 __ sarq($dst$$Register, (unsigned char)($shift$$constant & 0x3F));
9527 %}
9528 ins_pipe(ialu_mem_imm);
9529 %}
9530
9531 // Arithmetic Shift Right by 8-bit immediate
9532 instruct sarL_rReg_imm_ndd(rRegL dst, rRegL src, immI shift, rFlagsReg cr)
9533 %{
9534 predicate(UseAPX);
9535 match(Set dst (RShiftL src shift));
9536 effect(KILL cr);
9537
9538 format %{ "esarq $dst, $src, $shift\t# long (ndd)" %}
9539 ins_encode %{
9540 __ esarq($dst$$Register, $src$$Register, (unsigned char)($shift$$constant & 0x3F), false);
9541 %}
9542 ins_pipe(ialu_mem_imm);
9543 %}
9544
9545 instruct sarL_rReg_mem_imm_ndd(rRegL dst, memory src, immI shift, rFlagsReg cr)
9546 %{
9547 predicate(UseAPX);
9548 match(Set dst (RShiftL (LoadL src) shift));
9549 effect(KILL cr);
9550
9551 format %{ "esarq $dst, $src, $shift\t# long (ndd)" %}
9552 ins_encode %{
9553 __ esarq($dst$$Register, $src$$Address, (unsigned char)($shift$$constant & 0x3F), false);
9554 %}
9555 ins_pipe(ialu_mem_imm);
9556 %}
9557
9558 // Arithmetic Shift Right by 8-bit immediate
9559 instruct sarL_mem_imm(memory dst, immI shift, rFlagsReg cr)
9560 %{
9561 match(Set dst (StoreL dst (RShiftL (LoadL dst) shift)));
9562 effect(KILL cr);
9563
9564 format %{ "sarq $dst, $shift" %}
9565 ins_encode %{
9566 __ sarq($dst$$Address, (unsigned char)($shift$$constant & 0x3F));
9567 %}
9568 ins_pipe(ialu_mem_imm);
9569 %}
9570
9571 // Arithmetic Shift Right by variable
9572 instruct sarL_rReg_CL(rRegL dst, rcx_RegI shift, rFlagsReg cr)
9573 %{
9574 predicate(!VM_Version::supports_bmi2());
9575 match(Set dst (RShiftL dst shift));
9576 effect(KILL cr);
9577
9578 format %{ "sarq $dst, $shift" %}
9579 ins_encode %{
9580 __ sarq($dst$$Register);
9581 %}
9582 ins_pipe(ialu_reg_reg);
9583 %}
9584
9585 // Arithmetic Shift Right by variable
9586 instruct sarL_mem_CL(memory dst, rcx_RegI shift, rFlagsReg cr)
9587 %{
9588 predicate(!VM_Version::supports_bmi2());
9589 match(Set dst (StoreL dst (RShiftL (LoadL dst) shift)));
9590 effect(KILL cr);
9591
9592 format %{ "sarq $dst, $shift" %}
9593 ins_encode %{
9594 __ sarq($dst$$Address);
9595 %}
9596 ins_pipe(ialu_mem_reg);
9597 %}
9598
9599 instruct sarL_rReg_rReg(rRegL dst, rRegL src, rRegI shift)
9600 %{
9601 predicate(VM_Version::supports_bmi2());
9602 match(Set dst (RShiftL src shift));
9603
9604 format %{ "sarxq $dst, $src, $shift" %}
9605 ins_encode %{
9606 __ sarxq($dst$$Register, $src$$Register, $shift$$Register);
9607 %}
9608 ins_pipe(ialu_reg_reg);
9609 %}
9610
9611 instruct sarL_mem_rReg(rRegL dst, memory src, rRegI shift)
9612 %{
9613 predicate(VM_Version::supports_bmi2());
9614 match(Set dst (RShiftL (LoadL src) shift));
9615 ins_cost(175);
9616 format %{ "sarxq $dst, $src, $shift" %}
9617 ins_encode %{
9618 __ sarxq($dst$$Register, $src$$Address, $shift$$Register);
9619 %}
9620 ins_pipe(ialu_reg_mem);
9621 %}
9622
9623 // Logical Shift Right by 8-bit immediate
9624 instruct shrL_rReg_imm(rRegL dst, immI8 shift, rFlagsReg cr)
9625 %{
9626 predicate(!UseAPX);
9627 match(Set dst (URShiftL dst shift));
9628 effect(KILL cr);
9629
9630 format %{ "shrq $dst, $shift" %}
9631 ins_encode %{
9632 __ shrq($dst$$Register, $shift$$constant);
9633 %}
9634 ins_pipe(ialu_reg);
9635 %}
9636
9637 // Logical Shift Right by 8-bit immediate
9638 instruct shrL_rReg_imm_ndd(rRegL dst, rRegL src, immI8 shift, rFlagsReg cr)
9639 %{
9640 predicate(UseAPX);
9641 match(Set dst (URShiftL src shift));
9642 effect(KILL cr);
9643
9644 format %{ "eshrq $dst, $src, $shift\t# long (ndd)" %}
9645 ins_encode %{
9646 __ eshrq($dst$$Register, $src$$Register, $shift$$constant, false);
9647 %}
9648 ins_pipe(ialu_reg);
9649 %}
9650
9651 instruct shrL_rReg_mem_imm_ndd(rRegL dst, memory src, immI8 shift, rFlagsReg cr)
9652 %{
9653 predicate(UseAPX);
9654 match(Set dst (URShiftL (LoadL src) shift));
9655 effect(KILL cr);
9656
9657 format %{ "eshrq $dst, $src, $shift\t# long (ndd)" %}
9658 ins_encode %{
9659 __ eshrq($dst$$Register, $src$$Address, $shift$$constant, false);
9660 %}
9661 ins_pipe(ialu_reg);
9662 %}
9663
9664 // Logical Shift Right by 8-bit immediate
9665 instruct shrL_mem_imm(memory dst, immI8 shift, rFlagsReg cr)
9666 %{
9667 match(Set dst (StoreL dst (URShiftL (LoadL dst) shift)));
9668 effect(KILL cr);
9669
9670 format %{ "shrq $dst, $shift" %}
9671 ins_encode %{
9672 __ shrq($dst$$Address, $shift$$constant);
9673 %}
9674 ins_pipe(ialu_mem_imm);
9675 %}
9676
9677 // Logical Shift Right by variable
9678 instruct shrL_rReg_CL(rRegL dst, rcx_RegI shift, rFlagsReg cr)
9679 %{
9680 predicate(!VM_Version::supports_bmi2());
9681 match(Set dst (URShiftL dst shift));
9682 effect(KILL cr);
9683
9684 format %{ "shrq $dst, $shift" %}
9685 ins_encode %{
9686 __ shrq($dst$$Register);
9687 %}
9688 ins_pipe(ialu_reg_reg);
9689 %}
9690
9691 // Logical Shift Right by variable
9692 instruct shrL_mem_CL(memory dst, rcx_RegI shift, rFlagsReg cr)
9693 %{
9694 predicate(!VM_Version::supports_bmi2());
9695 match(Set dst (StoreL dst (URShiftL (LoadL dst) shift)));
9696 effect(KILL cr);
9697
9698 format %{ "shrq $dst, $shift" %}
9699 ins_encode %{
9700 __ shrq($dst$$Address);
9701 %}
9702 ins_pipe(ialu_mem_reg);
9703 %}
9704
9705 instruct shrL_rReg_rReg(rRegL dst, rRegL src, rRegI shift)
9706 %{
9707 predicate(VM_Version::supports_bmi2());
9708 match(Set dst (URShiftL src shift));
9709
9710 format %{ "shrxq $dst, $src, $shift" %}
9711 ins_encode %{
9712 __ shrxq($dst$$Register, $src$$Register, $shift$$Register);
9713 %}
9714 ins_pipe(ialu_reg_reg);
9715 %}
9716
9717 instruct shrL_mem_rReg(rRegL dst, memory src, rRegI shift)
9718 %{
9719 predicate(VM_Version::supports_bmi2());
9720 match(Set dst (URShiftL (LoadL src) shift));
9721 ins_cost(175);
9722 format %{ "shrxq $dst, $src, $shift" %}
9723 ins_encode %{
9724 __ shrxq($dst$$Register, $src$$Address, $shift$$Register);
9725 %}
9726 ins_pipe(ialu_reg_mem);
9727 %}
9728
9729 // Logical Shift Right by 24, followed by Arithmetic Shift Left by 24.
9730 // This idiom is used by the compiler for the i2b bytecode.
9731 instruct i2b(rRegI dst, rRegI src, immI_24 twentyfour)
9732 %{
9733 match(Set dst (RShiftI (LShiftI src twentyfour) twentyfour));
9734
9735 format %{ "movsbl $dst, $src\t# i2b" %}
9736 ins_encode %{
9737 __ movsbl($dst$$Register, $src$$Register);
9738 %}
9739 ins_pipe(ialu_reg_reg);
9740 %}
9741
9742 // Logical Shift Right by 16, followed by Arithmetic Shift Left by 16.
9743 // This idiom is used by the compiler the i2s bytecode.
9744 instruct i2s(rRegI dst, rRegI src, immI_16 sixteen)
9745 %{
9746 match(Set dst (RShiftI (LShiftI src sixteen) sixteen));
9747
9748 format %{ "movswl $dst, $src\t# i2s" %}
9749 ins_encode %{
9750 __ movswl($dst$$Register, $src$$Register);
9751 %}
9752 ins_pipe(ialu_reg_reg);
9753 %}
9754
9755 // ROL/ROR instructions
9756
9757 // Rotate left by constant.
9758 instruct rolI_immI8_legacy(rRegI dst, immI8 shift, rFlagsReg cr)
9759 %{
9760 predicate(!VM_Version::supports_bmi2() && n->bottom_type()->basic_type() == T_INT);
9761 match(Set dst (RotateLeft dst shift));
9762 effect(KILL cr);
9763 format %{ "roll $dst, $shift" %}
9764 ins_encode %{
9765 __ roll($dst$$Register, $shift$$constant);
9766 %}
9767 ins_pipe(ialu_reg);
9768 %}
9769
9770 instruct rolI_immI8(rRegI dst, rRegI src, immI8 shift)
9771 %{
9772 predicate(!UseAPX && VM_Version::supports_bmi2() && n->bottom_type()->basic_type() == T_INT);
9773 match(Set dst (RotateLeft src shift));
9774 format %{ "rolxl $dst, $src, $shift" %}
9775 ins_encode %{
9776 int shift = 32 - ($shift$$constant & 31);
9777 __ rorxl($dst$$Register, $src$$Register, shift);
9778 %}
9779 ins_pipe(ialu_reg_reg);
9780 %}
9781
9782 instruct rolI_mem_immI8(rRegI dst, memory src, immI8 shift)
9783 %{
9784 predicate(VM_Version::supports_bmi2() && n->bottom_type()->basic_type() == T_INT);
9785 match(Set dst (RotateLeft (LoadI src) shift));
9786 ins_cost(175);
9787 format %{ "rolxl $dst, $src, $shift" %}
9788 ins_encode %{
9789 int shift = 32 - ($shift$$constant & 31);
9790 __ rorxl($dst$$Register, $src$$Address, shift);
9791 %}
9792 ins_pipe(ialu_reg_mem);
9793 %}
9794
9795 // Rotate Left by variable
9796 instruct rolI_rReg_Var(rRegI dst, rcx_RegI shift, rFlagsReg cr)
9797 %{
9798 predicate(!UseAPX && n->bottom_type()->basic_type() == T_INT);
9799 match(Set dst (RotateLeft dst shift));
9800 effect(KILL cr);
9801 format %{ "roll $dst, $shift" %}
9802 ins_encode %{
9803 __ roll($dst$$Register);
9804 %}
9805 ins_pipe(ialu_reg_reg);
9806 %}
9807
9808 // Rotate Left by variable
9809 instruct rolI_rReg_Var_ndd(rRegI dst, rRegI src, rcx_RegI shift, rFlagsReg cr)
9810 %{
9811 predicate(UseAPX && n->bottom_type()->basic_type() == T_INT);
9812 match(Set dst (RotateLeft src shift));
9813 effect(KILL cr);
9814
9815 format %{ "eroll $dst, $src, $shift\t# rotate left (int ndd)" %}
9816 ins_encode %{
9817 __ eroll($dst$$Register, $src$$Register, false);
9818 %}
9819 ins_pipe(ialu_reg_reg);
9820 %}
9821
9822 // Rotate Right by constant.
9823 instruct rorI_immI8_legacy(rRegI dst, immI8 shift, rFlagsReg cr)
9824 %{
9825 predicate(!VM_Version::supports_bmi2() && n->bottom_type()->basic_type() == T_INT);
9826 match(Set dst (RotateRight dst shift));
9827 effect(KILL cr);
9828 format %{ "rorl $dst, $shift" %}
9829 ins_encode %{
9830 __ rorl($dst$$Register, $shift$$constant);
9831 %}
9832 ins_pipe(ialu_reg);
9833 %}
9834
9835 // Rotate Right by constant.
9836 instruct rorI_immI8(rRegI dst, rRegI src, immI8 shift)
9837 %{
9838 predicate(!UseAPX && VM_Version::supports_bmi2() && n->bottom_type()->basic_type() == T_INT);
9839 match(Set dst (RotateRight src shift));
9840 format %{ "rorxl $dst, $src, $shift" %}
9841 ins_encode %{
9842 __ rorxl($dst$$Register, $src$$Register, $shift$$constant);
9843 %}
9844 ins_pipe(ialu_reg_reg);
9845 %}
9846
9847 instruct rorI_mem_immI8(rRegI dst, memory src, immI8 shift)
9848 %{
9849 predicate(VM_Version::supports_bmi2() && n->bottom_type()->basic_type() == T_INT);
9850 match(Set dst (RotateRight (LoadI src) shift));
9851 ins_cost(175);
9852 format %{ "rorxl $dst, $src, $shift" %}
9853 ins_encode %{
9854 __ rorxl($dst$$Register, $src$$Address, $shift$$constant);
9855 %}
9856 ins_pipe(ialu_reg_mem);
9857 %}
9858
9859 // Rotate Right by variable
9860 instruct rorI_rReg_Var(rRegI dst, rcx_RegI shift, rFlagsReg cr)
9861 %{
9862 predicate(!UseAPX && n->bottom_type()->basic_type() == T_INT);
9863 match(Set dst (RotateRight dst shift));
9864 effect(KILL cr);
9865 format %{ "rorl $dst, $shift" %}
9866 ins_encode %{
9867 __ rorl($dst$$Register);
9868 %}
9869 ins_pipe(ialu_reg_reg);
9870 %}
9871
9872 // Rotate Right by variable
9873 instruct rorI_rReg_Var_ndd(rRegI dst, rRegI src, rcx_RegI shift, rFlagsReg cr)
9874 %{
9875 predicate(UseAPX && n->bottom_type()->basic_type() == T_INT);
9876 match(Set dst (RotateRight src shift));
9877 effect(KILL cr);
9878
9879 format %{ "erorl $dst, $src, $shift\t# rotate right(int ndd)" %}
9880 ins_encode %{
9881 __ erorl($dst$$Register, $src$$Register, false);
9882 %}
9883 ins_pipe(ialu_reg_reg);
9884 %}
9885
9886 // Rotate Left by constant.
9887 instruct rolL_immI8_legacy(rRegL dst, immI8 shift, rFlagsReg cr)
9888 %{
9889 predicate(!VM_Version::supports_bmi2() && n->bottom_type()->basic_type() == T_LONG);
9890 match(Set dst (RotateLeft dst shift));
9891 effect(KILL cr);
9892 format %{ "rolq $dst, $shift" %}
9893 ins_encode %{
9894 __ rolq($dst$$Register, $shift$$constant);
9895 %}
9896 ins_pipe(ialu_reg);
9897 %}
9898
9899 instruct rolL_immI8(rRegL dst, rRegL src, immI8 shift)
9900 %{
9901 predicate(!UseAPX && VM_Version::supports_bmi2() && n->bottom_type()->basic_type() == T_LONG);
9902 match(Set dst (RotateLeft src shift));
9903 format %{ "rolxq $dst, $src, $shift" %}
9904 ins_encode %{
9905 int shift = 64 - ($shift$$constant & 63);
9906 __ rorxq($dst$$Register, $src$$Register, shift);
9907 %}
9908 ins_pipe(ialu_reg_reg);
9909 %}
9910
9911 instruct rolL_mem_immI8(rRegL dst, memory src, immI8 shift)
9912 %{
9913 predicate(VM_Version::supports_bmi2() && n->bottom_type()->basic_type() == T_LONG);
9914 match(Set dst (RotateLeft (LoadL src) shift));
9915 ins_cost(175);
9916 format %{ "rolxq $dst, $src, $shift" %}
9917 ins_encode %{
9918 int shift = 64 - ($shift$$constant & 63);
9919 __ rorxq($dst$$Register, $src$$Address, shift);
9920 %}
9921 ins_pipe(ialu_reg_mem);
9922 %}
9923
9924 // Rotate Left by variable
9925 instruct rolL_rReg_Var(rRegL dst, rcx_RegI shift, rFlagsReg cr)
9926 %{
9927 predicate(!UseAPX && n->bottom_type()->basic_type() == T_LONG);
9928 match(Set dst (RotateLeft dst shift));
9929 effect(KILL cr);
9930 format %{ "rolq $dst, $shift" %}
9931 ins_encode %{
9932 __ rolq($dst$$Register);
9933 %}
9934 ins_pipe(ialu_reg_reg);
9935 %}
9936
9937 // Rotate Left by variable
9938 instruct rolL_rReg_Var_ndd(rRegL dst, rRegL src, rcx_RegI shift, rFlagsReg cr)
9939 %{
9940 predicate(UseAPX && n->bottom_type()->basic_type() == T_LONG);
9941 match(Set dst (RotateLeft src shift));
9942 effect(KILL cr);
9943
9944 format %{ "erolq $dst, $src, $shift\t# rotate left(long ndd)" %}
9945 ins_encode %{
9946 __ erolq($dst$$Register, $src$$Register, false);
9947 %}
9948 ins_pipe(ialu_reg_reg);
9949 %}
9950
9951 // Rotate Right by constant.
9952 instruct rorL_immI8_legacy(rRegL dst, immI8 shift, rFlagsReg cr)
9953 %{
9954 predicate(!VM_Version::supports_bmi2() && n->bottom_type()->basic_type() == T_LONG);
9955 match(Set dst (RotateRight dst shift));
9956 effect(KILL cr);
9957 format %{ "rorq $dst, $shift" %}
9958 ins_encode %{
9959 __ rorq($dst$$Register, $shift$$constant);
9960 %}
9961 ins_pipe(ialu_reg);
9962 %}
9963
9964 // Rotate Right by constant
9965 instruct rorL_immI8(rRegL dst, rRegL src, immI8 shift)
9966 %{
9967 predicate(VM_Version::supports_bmi2() && n->bottom_type()->basic_type() == T_LONG);
9968 match(Set dst (RotateRight src shift));
9969 format %{ "rorxq $dst, $src, $shift" %}
9970 ins_encode %{
9971 __ rorxq($dst$$Register, $src$$Register, $shift$$constant);
9972 %}
9973 ins_pipe(ialu_reg_reg);
9974 %}
9975
9976 instruct rorL_mem_immI8(rRegL dst, memory src, immI8 shift)
9977 %{
9978 predicate(VM_Version::supports_bmi2() && n->bottom_type()->basic_type() == T_LONG);
9979 match(Set dst (RotateRight (LoadL src) shift));
9980 ins_cost(175);
9981 format %{ "rorxq $dst, $src, $shift" %}
9982 ins_encode %{
9983 __ rorxq($dst$$Register, $src$$Address, $shift$$constant);
9984 %}
9985 ins_pipe(ialu_reg_mem);
9986 %}
9987
9988 // Rotate Right by variable
9989 instruct rorL_rReg_Var(rRegL dst, rcx_RegI shift, rFlagsReg cr)
9990 %{
9991 predicate(!UseAPX && n->bottom_type()->basic_type() == T_LONG);
9992 match(Set dst (RotateRight dst shift));
9993 effect(KILL cr);
9994 format %{ "rorq $dst, $shift" %}
9995 ins_encode %{
9996 __ rorq($dst$$Register);
9997 %}
9998 ins_pipe(ialu_reg_reg);
9999 %}
10000
10001 // Rotate Right by variable
10002 instruct rorL_rReg_Var_ndd(rRegL dst, rRegL src, rcx_RegI shift, rFlagsReg cr)
10003 %{
10004 predicate(UseAPX && n->bottom_type()->basic_type() == T_LONG);
10005 match(Set dst (RotateRight src shift));
10006 effect(KILL cr);
10007
10008 format %{ "erorq $dst, $src, $shift\t# rotate right(long ndd)" %}
10009 ins_encode %{
10010 __ erorq($dst$$Register, $src$$Register, false);
10011 %}
10012 ins_pipe(ialu_reg_reg);
10013 %}
10014
10015 //----------------------------- CompressBits/ExpandBits ------------------------
10016
10017 instruct compressBitsL_reg(rRegL dst, rRegL src, rRegL mask) %{
10018 predicate(n->bottom_type()->isa_long());
10019 match(Set dst (CompressBits src mask));
10020 format %{ "pextq $dst, $src, $mask\t! parallel bit extract" %}
10021 ins_encode %{
10022 __ pextq($dst$$Register, $src$$Register, $mask$$Register);
10023 %}
10024 ins_pipe( pipe_slow );
10025 %}
10026
10027 instruct expandBitsL_reg(rRegL dst, rRegL src, rRegL mask) %{
10028 predicate(n->bottom_type()->isa_long());
10029 match(Set dst (ExpandBits src mask));
10030 format %{ "pdepq $dst, $src, $mask\t! parallel bit deposit" %}
10031 ins_encode %{
10032 __ pdepq($dst$$Register, $src$$Register, $mask$$Register);
10033 %}
10034 ins_pipe( pipe_slow );
10035 %}
10036
10037 instruct compressBitsL_mem(rRegL dst, rRegL src, memory mask) %{
10038 predicate(n->bottom_type()->isa_long());
10039 match(Set dst (CompressBits src (LoadL mask)));
10040 format %{ "pextq $dst, $src, $mask\t! parallel bit extract" %}
10041 ins_encode %{
10042 __ pextq($dst$$Register, $src$$Register, $mask$$Address);
10043 %}
10044 ins_pipe( pipe_slow );
10045 %}
10046
10047 instruct expandBitsL_mem(rRegL dst, rRegL src, memory mask) %{
10048 predicate(n->bottom_type()->isa_long());
10049 match(Set dst (ExpandBits src (LoadL mask)));
10050 format %{ "pdepq $dst, $src, $mask\t! parallel bit deposit" %}
10051 ins_encode %{
10052 __ pdepq($dst$$Register, $src$$Register, $mask$$Address);
10053 %}
10054 ins_pipe( pipe_slow );
10055 %}
10056
10057
10058 // Logical Instructions
10059
10060 // Integer Logical Instructions
10061
10062 // And Instructions
10063 // And Register with Register
10064 instruct andI_rReg(rRegI dst, rRegI src, rFlagsReg cr)
10065 %{
10066 predicate(!UseAPX);
10067 match(Set dst (AndI dst src));
10068 effect(KILL cr);
10069 flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
10070
10071 format %{ "andl $dst, $src\t# int" %}
10072 ins_encode %{
10073 __ andl($dst$$Register, $src$$Register);
10074 %}
10075 ins_pipe(ialu_reg_reg);
10076 %}
10077
10078 // And Register with Register using New Data Destination (NDD)
10079 instruct andI_rReg_ndd(rRegI dst, rRegI src1, rRegI src2, rFlagsReg cr)
10080 %{
10081 predicate(UseAPX);
10082 match(Set dst (AndI src1 src2));
10083 effect(KILL cr);
10084 flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
10085
10086 format %{ "eandl $dst, $src1, $src2\t# int ndd" %}
10087 ins_encode %{
10088 __ eandl($dst$$Register, $src1$$Register, $src2$$Register, false);
10089
10090 %}
10091 ins_pipe(ialu_reg_reg);
10092 %}
10093
10094 // And Register with Immediate 255
10095 instruct andI_rReg_imm255(rRegI dst, rRegI src, immI_255 mask)
10096 %{
10097 match(Set dst (AndI src mask));
10098
10099 format %{ "movzbl $dst, $src\t# int & 0xFF" %}
10100 ins_encode %{
10101 __ movzbl($dst$$Register, $src$$Register);
10102 %}
10103 ins_pipe(ialu_reg);
10104 %}
10105
10106 // And Register with Immediate 255 and promote to long
10107 instruct andI2L_rReg_imm255(rRegL dst, rRegI src, immI_255 mask)
10108 %{
10109 match(Set dst (ConvI2L (AndI src mask)));
10110
10111 format %{ "movzbl $dst, $src\t# int & 0xFF -> long" %}
10112 ins_encode %{
10113 __ movzbl($dst$$Register, $src$$Register);
10114 %}
10115 ins_pipe(ialu_reg);
10116 %}
10117
10118 // And Register with Immediate 65535
10119 instruct andI_rReg_imm65535(rRegI dst, rRegI src, immI_65535 mask)
10120 %{
10121 match(Set dst (AndI src mask));
10122
10123 format %{ "movzwl $dst, $src\t# int & 0xFFFF" %}
10124 ins_encode %{
10125 __ movzwl($dst$$Register, $src$$Register);
10126 %}
10127 ins_pipe(ialu_reg);
10128 %}
10129
10130 // And Register with Immediate 65535 and promote to long
10131 instruct andI2L_rReg_imm65535(rRegL dst, rRegI src, immI_65535 mask)
10132 %{
10133 match(Set dst (ConvI2L (AndI src mask)));
10134
10135 format %{ "movzwl $dst, $src\t# int & 0xFFFF -> long" %}
10136 ins_encode %{
10137 __ movzwl($dst$$Register, $src$$Register);
10138 %}
10139 ins_pipe(ialu_reg);
10140 %}
10141
10142 // Can skip int2long conversions after AND with small bitmask
10143 instruct convI2LAndI_reg_immIbitmask(rRegL dst, rRegI src, immI_Pow2M1 mask, rRegI tmp, rFlagsReg cr)
10144 %{
10145 predicate(VM_Version::supports_bmi2());
10146 ins_cost(125);
10147 effect(TEMP tmp, KILL cr);
10148 match(Set dst (ConvI2L (AndI src mask)));
10149 format %{ "bzhiq $dst, $src, $mask \t# using $tmp as TEMP, int & immI_Pow2M1 -> long" %}
10150 ins_encode %{
10151 __ movl($tmp$$Register, exact_log2($mask$$constant + 1));
10152 __ bzhiq($dst$$Register, $src$$Register, $tmp$$Register);
10153 %}
10154 ins_pipe(ialu_reg_reg);
10155 %}
10156
10157 // And Register with Immediate
10158 instruct andI_rReg_imm(rRegI dst, immI src, rFlagsReg cr)
10159 %{
10160 predicate(!UseAPX);
10161 match(Set dst (AndI dst src));
10162 effect(KILL cr);
10163 flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
10164
10165 format %{ "andl $dst, $src\t# int" %}
10166 ins_encode %{
10167 __ andl($dst$$Register, $src$$constant);
10168 %}
10169 ins_pipe(ialu_reg);
10170 %}
10171
10172 instruct andI_rReg_rReg_imm_ndd(rRegI dst, rRegI src1, immI src2, rFlagsReg cr)
10173 %{
10174 predicate(UseAPX);
10175 match(Set dst (AndI src1 src2));
10176 effect(KILL cr);
10177 flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
10178
10179 format %{ "eandl $dst, $src1, $src2\t# int ndd" %}
10180 ins_encode %{
10181 __ eandl($dst$$Register, $src1$$Register, $src2$$constant, false);
10182 %}
10183 ins_pipe(ialu_reg);
10184 %}
10185
10186 instruct andI_rReg_mem_imm_ndd(rRegI dst, memory src1, immI src2, rFlagsReg cr)
10187 %{
10188 predicate(UseAPX);
10189 match(Set dst (AndI (LoadI src1) src2));
10190 effect(KILL cr);
10191 flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
10192
10193 format %{ "eandl $dst, $src1, $src2\t# int ndd" %}
10194 ins_encode %{
10195 __ eandl($dst$$Register, $src1$$Address, $src2$$constant, false);
10196 %}
10197 ins_pipe(ialu_reg);
10198 %}
10199
10200 // And Register with Memory
10201 instruct andI_rReg_mem(rRegI dst, memory src, rFlagsReg cr)
10202 %{
10203 predicate(!UseAPX);
10204 match(Set dst (AndI dst (LoadI src)));
10205 effect(KILL cr);
10206 flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
10207
10208 ins_cost(150);
10209 format %{ "andl $dst, $src\t# int" %}
10210 ins_encode %{
10211 __ andl($dst$$Register, $src$$Address);
10212 %}
10213 ins_pipe(ialu_reg_mem);
10214 %}
10215
10216 instruct andI_rReg_rReg_mem_ndd(rRegI dst, rRegI src1, memory src2, rFlagsReg cr)
10217 %{
10218 predicate(UseAPX);
10219 match(Set dst (AndI src1 (LoadI src2)));
10220 effect(KILL cr);
10221 flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
10222
10223 ins_cost(150);
10224 format %{ "eandl $dst, $src1, $src2\t# int ndd" %}
10225 ins_encode %{
10226 __ eandl($dst$$Register, $src1$$Register, $src2$$Address, false);
10227 %}
10228 ins_pipe(ialu_reg_mem);
10229 %}
10230
10231 // And Memory with Register
10232 instruct andB_mem_rReg(memory dst, rRegI src, rFlagsReg cr)
10233 %{
10234 match(Set dst (StoreB dst (AndI (LoadB dst) src)));
10235 effect(KILL cr);
10236 flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
10237
10238 ins_cost(150);
10239 format %{ "andb $dst, $src\t# byte" %}
10240 ins_encode %{
10241 __ andb($dst$$Address, $src$$Register);
10242 %}
10243 ins_pipe(ialu_mem_reg);
10244 %}
10245
10246 instruct andI_mem_rReg(memory dst, rRegI src, rFlagsReg cr)
10247 %{
10248 match(Set dst (StoreI dst (AndI (LoadI dst) src)));
10249 effect(KILL cr);
10250 flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
10251
10252 ins_cost(150);
10253 format %{ "andl $dst, $src\t# int" %}
10254 ins_encode %{
10255 __ andl($dst$$Address, $src$$Register);
10256 %}
10257 ins_pipe(ialu_mem_reg);
10258 %}
10259
10260 // And Memory with Immediate
10261 instruct andI_mem_imm(memory dst, immI src, rFlagsReg cr)
10262 %{
10263 match(Set dst (StoreI dst (AndI (LoadI dst) src)));
10264 effect(KILL cr);
10265 flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
10266
10267 ins_cost(125);
10268 format %{ "andl $dst, $src\t# int" %}
10269 ins_encode %{
10270 __ andl($dst$$Address, $src$$constant);
10271 %}
10272 ins_pipe(ialu_mem_imm);
10273 %}
10274
10275 // BMI1 instructions
10276 instruct andnI_rReg_rReg_mem(rRegI dst, rRegI src1, memory src2, immI_M1 minus_1, rFlagsReg cr) %{
10277 match(Set dst (AndI (XorI src1 minus_1) (LoadI src2)));
10278 predicate(UseBMI1Instructions);
10279 effect(KILL cr);
10280 flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
10281
10282 ins_cost(125);
10283 format %{ "andnl $dst, $src1, $src2" %}
10284
10285 ins_encode %{
10286 __ andnl($dst$$Register, $src1$$Register, $src2$$Address);
10287 %}
10288 ins_pipe(ialu_reg_mem);
10289 %}
10290
10291 instruct andnI_rReg_rReg_rReg(rRegI dst, rRegI src1, rRegI src2, immI_M1 minus_1, rFlagsReg cr) %{
10292 match(Set dst (AndI (XorI src1 minus_1) src2));
10293 predicate(UseBMI1Instructions);
10294 effect(KILL cr);
10295 flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
10296
10297 format %{ "andnl $dst, $src1, $src2" %}
10298
10299 ins_encode %{
10300 __ andnl($dst$$Register, $src1$$Register, $src2$$Register);
10301 %}
10302 ins_pipe(ialu_reg);
10303 %}
10304
10305 instruct blsiI_rReg_rReg(rRegI dst, rRegI src, immI_0 imm_zero, rFlagsReg cr) %{
10306 match(Set dst (AndI (SubI imm_zero src) src));
10307 predicate(UseBMI1Instructions);
10308 effect(KILL cr);
10309 flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_clears_overflow_flag);
10310
10311 format %{ "blsil $dst, $src" %}
10312
10313 ins_encode %{
10314 __ blsil($dst$$Register, $src$$Register);
10315 %}
10316 ins_pipe(ialu_reg);
10317 %}
10318
10319 instruct blsiI_rReg_mem(rRegI dst, memory src, immI_0 imm_zero, rFlagsReg cr) %{
10320 match(Set dst (AndI (SubI imm_zero (LoadI src) ) (LoadI src) ));
10321 predicate(UseBMI1Instructions);
10322 effect(KILL cr);
10323 flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_clears_overflow_flag);
10324
10325 ins_cost(125);
10326 format %{ "blsil $dst, $src" %}
10327
10328 ins_encode %{
10329 __ blsil($dst$$Register, $src$$Address);
10330 %}
10331 ins_pipe(ialu_reg_mem);
10332 %}
10333
10334 instruct blsmskI_rReg_mem(rRegI dst, memory src, immI_M1 minus_1, rFlagsReg cr)
10335 %{
10336 match(Set dst (XorI (AddI (LoadI src) minus_1) (LoadI src) ) );
10337 predicate(UseBMI1Instructions);
10338 effect(KILL cr);
10339 flag(PD::Flag_sets_sign_flag, PD::Flag_clears_zero_flag, PD::Flag_clears_overflow_flag);
10340
10341 ins_cost(125);
10342 format %{ "blsmskl $dst, $src" %}
10343
10344 ins_encode %{
10345 __ blsmskl($dst$$Register, $src$$Address);
10346 %}
10347 ins_pipe(ialu_reg_mem);
10348 %}
10349
10350 instruct blsmskI_rReg_rReg(rRegI dst, rRegI src, immI_M1 minus_1, rFlagsReg cr)
10351 %{
10352 match(Set dst (XorI (AddI src minus_1) src));
10353 predicate(UseBMI1Instructions);
10354 effect(KILL cr);
10355 flag(PD::Flag_sets_sign_flag, PD::Flag_clears_zero_flag, PD::Flag_clears_overflow_flag);
10356
10357 format %{ "blsmskl $dst, $src" %}
10358
10359 ins_encode %{
10360 __ blsmskl($dst$$Register, $src$$Register);
10361 %}
10362
10363 ins_pipe(ialu_reg);
10364 %}
10365
10366 instruct blsrI_rReg_rReg(rRegI dst, rRegI src, immI_M1 minus_1, rFlagsReg cr)
10367 %{
10368 match(Set dst (AndI (AddI src minus_1) src) );
10369 predicate(UseBMI1Instructions);
10370 effect(KILL cr);
10371 flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_clears_overflow_flag);
10372
10373 format %{ "blsrl $dst, $src" %}
10374
10375 ins_encode %{
10376 __ blsrl($dst$$Register, $src$$Register);
10377 %}
10378
10379 ins_pipe(ialu_reg_mem);
10380 %}
10381
10382 instruct blsrI_rReg_mem(rRegI dst, memory src, immI_M1 minus_1, rFlagsReg cr)
10383 %{
10384 match(Set dst (AndI (AddI (LoadI src) minus_1) (LoadI src) ) );
10385 predicate(UseBMI1Instructions);
10386 effect(KILL cr);
10387 flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_clears_overflow_flag);
10388
10389 ins_cost(125);
10390 format %{ "blsrl $dst, $src" %}
10391
10392 ins_encode %{
10393 __ blsrl($dst$$Register, $src$$Address);
10394 %}
10395
10396 ins_pipe(ialu_reg);
10397 %}
10398
10399 // Or Instructions
10400 // Or Register with Register
10401 instruct orI_rReg(rRegI dst, rRegI src, rFlagsReg cr)
10402 %{
10403 predicate(!UseAPX);
10404 match(Set dst (OrI dst src));
10405 effect(KILL cr);
10406 flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
10407
10408 format %{ "orl $dst, $src\t# int" %}
10409 ins_encode %{
10410 __ orl($dst$$Register, $src$$Register);
10411 %}
10412 ins_pipe(ialu_reg_reg);
10413 %}
10414
10415 // Or Register with Register using New Data Destination (NDD)
10416 instruct orI_rReg_ndd(rRegI dst, rRegI src1, rRegI src2, rFlagsReg cr)
10417 %{
10418 predicate(UseAPX);
10419 match(Set dst (OrI src1 src2));
10420 effect(KILL cr);
10421 flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
10422
10423 format %{ "eorl $dst, $src1, $src2\t# int ndd" %}
10424 ins_encode %{
10425 __ eorl($dst$$Register, $src1$$Register, $src2$$Register, false);
10426 %}
10427 ins_pipe(ialu_reg_reg);
10428 %}
10429
10430 // Or Register with Immediate
10431 instruct orI_rReg_imm(rRegI dst, immI src, rFlagsReg cr)
10432 %{
10433 predicate(!UseAPX);
10434 match(Set dst (OrI dst src));
10435 effect(KILL cr);
10436 flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
10437
10438 format %{ "orl $dst, $src\t# int" %}
10439 ins_encode %{
10440 __ orl($dst$$Register, $src$$constant);
10441 %}
10442 ins_pipe(ialu_reg);
10443 %}
10444
10445 instruct orI_rReg_rReg_imm_ndd(rRegI dst, rRegI src1, immI src2, rFlagsReg cr)
10446 %{
10447 predicate(UseAPX);
10448 match(Set dst (OrI src1 src2));
10449 effect(KILL cr);
10450 flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
10451
10452 format %{ "eorl $dst, $src1, $src2\t# int ndd" %}
10453 ins_encode %{
10454 __ eorl($dst$$Register, $src1$$Register, $src2$$constant, false);
10455 %}
10456 ins_pipe(ialu_reg);
10457 %}
10458
10459 instruct orI_rReg_imm_rReg_ndd(rRegI dst, immI src1, rRegI src2, rFlagsReg cr)
10460 %{
10461 predicate(UseAPX);
10462 match(Set dst (OrI src1 src2));
10463 effect(KILL cr);
10464 flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
10465
10466 format %{ "eorl $dst, $src2, $src1\t# int ndd" %}
10467 ins_encode %{
10468 __ eorl($dst$$Register, $src2$$Register, $src1$$constant, false);
10469 %}
10470 ins_pipe(ialu_reg);
10471 %}
10472
10473 instruct orI_rReg_mem_imm_ndd(rRegI dst, memory src1, immI src2, rFlagsReg cr)
10474 %{
10475 predicate(UseAPX);
10476 match(Set dst (OrI (LoadI src1) src2));
10477 effect(KILL cr);
10478 flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
10479
10480 format %{ "eorl $dst, $src1, $src2\t# int ndd" %}
10481 ins_encode %{
10482 __ eorl($dst$$Register, $src1$$Address, $src2$$constant, false);
10483 %}
10484 ins_pipe(ialu_reg);
10485 %}
10486
10487 // Or Register with Memory
10488 instruct orI_rReg_mem(rRegI dst, memory src, rFlagsReg cr)
10489 %{
10490 predicate(!UseAPX);
10491 match(Set dst (OrI dst (LoadI src)));
10492 effect(KILL cr);
10493 flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
10494
10495 ins_cost(150);
10496 format %{ "orl $dst, $src\t# int" %}
10497 ins_encode %{
10498 __ orl($dst$$Register, $src$$Address);
10499 %}
10500 ins_pipe(ialu_reg_mem);
10501 %}
10502
10503 instruct orI_rReg_rReg_mem_ndd(rRegI dst, rRegI src1, memory src2, rFlagsReg cr)
10504 %{
10505 predicate(UseAPX);
10506 match(Set dst (OrI src1 (LoadI src2)));
10507 effect(KILL cr);
10508 flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
10509
10510 ins_cost(150);
10511 format %{ "eorl $dst, $src1, $src2\t# int ndd" %}
10512 ins_encode %{
10513 __ eorl($dst$$Register, $src1$$Register, $src2$$Address, false);
10514 %}
10515 ins_pipe(ialu_reg_mem);
10516 %}
10517
10518 // Or Memory with Register
10519 instruct orB_mem_rReg(memory dst, rRegI src, rFlagsReg cr)
10520 %{
10521 match(Set dst (StoreB dst (OrI (LoadB dst) src)));
10522 effect(KILL cr);
10523 flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
10524
10525 ins_cost(150);
10526 format %{ "orb $dst, $src\t# byte" %}
10527 ins_encode %{
10528 __ orb($dst$$Address, $src$$Register);
10529 %}
10530 ins_pipe(ialu_mem_reg);
10531 %}
10532
10533 instruct orI_mem_rReg(memory dst, rRegI src, rFlagsReg cr)
10534 %{
10535 match(Set dst (StoreI dst (OrI (LoadI dst) src)));
10536 effect(KILL cr);
10537 flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
10538
10539 ins_cost(150);
10540 format %{ "orl $dst, $src\t# int" %}
10541 ins_encode %{
10542 __ orl($dst$$Address, $src$$Register);
10543 %}
10544 ins_pipe(ialu_mem_reg);
10545 %}
10546
10547 // Or Memory with Immediate
10548 instruct orI_mem_imm(memory dst, immI src, rFlagsReg cr)
10549 %{
10550 match(Set dst (StoreI dst (OrI (LoadI dst) src)));
10551 effect(KILL cr);
10552 flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
10553
10554 ins_cost(125);
10555 format %{ "orl $dst, $src\t# int" %}
10556 ins_encode %{
10557 __ orl($dst$$Address, $src$$constant);
10558 %}
10559 ins_pipe(ialu_mem_imm);
10560 %}
10561
10562 // Xor Instructions
10563 // Xor Register with Register
10564 instruct xorI_rReg(rRegI dst, rRegI src, rFlagsReg cr)
10565 %{
10566 predicate(!UseAPX);
10567 match(Set dst (XorI dst src));
10568 effect(KILL cr);
10569 flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
10570
10571 format %{ "xorl $dst, $src\t# int" %}
10572 ins_encode %{
10573 __ xorl($dst$$Register, $src$$Register);
10574 %}
10575 ins_pipe(ialu_reg_reg);
10576 %}
10577
10578 // Xor Register with Register using New Data Destination (NDD)
10579 instruct xorI_rReg_ndd(rRegI dst, rRegI src1, rRegI src2, rFlagsReg cr)
10580 %{
10581 predicate(UseAPX);
10582 match(Set dst (XorI src1 src2));
10583 effect(KILL cr);
10584 flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
10585
10586 format %{ "exorl $dst, $src1, $src2\t# int ndd" %}
10587 ins_encode %{
10588 __ exorl($dst$$Register, $src1$$Register, $src2$$Register, false);
10589 %}
10590 ins_pipe(ialu_reg_reg);
10591 %}
10592
10593 // Xor Register with Immediate -1
10594 instruct xorI_rReg_im1(rRegI dst, immI_M1 imm)
10595 %{
10596 predicate(!UseAPX);
10597 match(Set dst (XorI dst imm));
10598
10599 format %{ "notl $dst" %}
10600 ins_encode %{
10601 __ notl($dst$$Register);
10602 %}
10603 ins_pipe(ialu_reg);
10604 %}
10605
10606 instruct xorI_rReg_im1_ndd(rRegI dst, rRegI src, immI_M1 imm)
10607 %{
10608 match(Set dst (XorI src imm));
10609 predicate(UseAPX);
10610
10611 format %{ "enotl $dst, $src" %}
10612 ins_encode %{
10613 __ enotl($dst$$Register, $src$$Register);
10614 %}
10615 ins_pipe(ialu_reg);
10616 %}
10617
10618 // Xor Register with Immediate
10619 instruct xorI_rReg_imm(rRegI dst, immI src, rFlagsReg cr)
10620 %{
10621 // Strict predicate check to make selection of xorI_rReg_im1 cost agnostic if immI src is -1.
10622 predicate(!UseAPX && n->in(2)->bottom_type()->is_int()->get_con() != -1);
10623 match(Set dst (XorI dst src));
10624 effect(KILL cr);
10625 flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
10626
10627 format %{ "xorl $dst, $src\t# int" %}
10628 ins_encode %{
10629 __ xorl($dst$$Register, $src$$constant);
10630 %}
10631 ins_pipe(ialu_reg);
10632 %}
10633
10634 instruct xorI_rReg_rReg_imm_ndd(rRegI dst, rRegI src1, immI src2, rFlagsReg cr)
10635 %{
10636 // Strict predicate check to make selection of xorI_rReg_im1_ndd cost agnostic if immI src2 is -1.
10637 predicate(UseAPX && n->in(2)->bottom_type()->is_int()->get_con() != -1);
10638 match(Set dst (XorI src1 src2));
10639 effect(KILL cr);
10640 flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
10641
10642 format %{ "exorl $dst, $src1, $src2\t# int ndd" %}
10643 ins_encode %{
10644 __ exorl($dst$$Register, $src1$$Register, $src2$$constant, false);
10645 %}
10646 ins_pipe(ialu_reg);
10647 %}
10648
10649 // Xor Memory with Immediate
10650 instruct xorI_rReg_mem_imm_ndd(rRegI dst, memory src1, immI src2, rFlagsReg cr)
10651 %{
10652 predicate(UseAPX);
10653 match(Set dst (XorI (LoadI src1) src2));
10654 effect(KILL cr);
10655 ins_cost(150);
10656 flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
10657
10658 format %{ "exorl $dst, $src1, $src2\t# int ndd" %}
10659 ins_encode %{
10660 __ exorl($dst$$Register, $src1$$Address, $src2$$constant, false);
10661 %}
10662 ins_pipe(ialu_reg);
10663 %}
10664
10665 // Xor Register with Memory
10666 instruct xorI_rReg_mem(rRegI dst, memory src, rFlagsReg cr)
10667 %{
10668 predicate(!UseAPX);
10669 match(Set dst (XorI dst (LoadI src)));
10670 effect(KILL cr);
10671 flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
10672
10673 ins_cost(150);
10674 format %{ "xorl $dst, $src\t# int" %}
10675 ins_encode %{
10676 __ xorl($dst$$Register, $src$$Address);
10677 %}
10678 ins_pipe(ialu_reg_mem);
10679 %}
10680
10681 instruct xorI_rReg_rReg_mem_ndd(rRegI dst, rRegI src1, memory src2, rFlagsReg cr)
10682 %{
10683 predicate(UseAPX);
10684 match(Set dst (XorI src1 (LoadI src2)));
10685 effect(KILL cr);
10686 flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
10687
10688 ins_cost(150);
10689 format %{ "exorl $dst, $src1, $src2\t# int ndd" %}
10690 ins_encode %{
10691 __ exorl($dst$$Register, $src1$$Register, $src2$$Address, false);
10692 %}
10693 ins_pipe(ialu_reg_mem);
10694 %}
10695
10696 // Xor Memory with Register
10697 instruct xorB_mem_rReg(memory dst, rRegI src, rFlagsReg cr)
10698 %{
10699 match(Set dst (StoreB dst (XorI (LoadB dst) src)));
10700 effect(KILL cr);
10701 flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
10702
10703 ins_cost(150);
10704 format %{ "xorb $dst, $src\t# byte" %}
10705 ins_encode %{
10706 __ xorb($dst$$Address, $src$$Register);
10707 %}
10708 ins_pipe(ialu_mem_reg);
10709 %}
10710
10711 instruct xorI_mem_rReg(memory dst, rRegI src, rFlagsReg cr)
10712 %{
10713 match(Set dst (StoreI dst (XorI (LoadI dst) src)));
10714 effect(KILL cr);
10715 flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
10716
10717 ins_cost(150);
10718 format %{ "xorl $dst, $src\t# int" %}
10719 ins_encode %{
10720 __ xorl($dst$$Address, $src$$Register);
10721 %}
10722 ins_pipe(ialu_mem_reg);
10723 %}
10724
10725 // Xor Memory with Immediate
10726 instruct xorI_mem_imm(memory dst, immI src, rFlagsReg cr)
10727 %{
10728 match(Set dst (StoreI dst (XorI (LoadI dst) src)));
10729 effect(KILL cr);
10730 flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
10731
10732 ins_cost(125);
10733 format %{ "xorl $dst, $src\t# int" %}
10734 ins_encode %{
10735 __ xorl($dst$$Address, $src$$constant);
10736 %}
10737 ins_pipe(ialu_mem_imm);
10738 %}
10739
10740
10741 // Long Logical Instructions
10742
10743 // And Instructions
10744 // And Register with Register
10745 instruct andL_rReg(rRegL dst, rRegL src, rFlagsReg cr)
10746 %{
10747 predicate(!UseAPX);
10748 match(Set dst (AndL dst src));
10749 effect(KILL cr);
10750 flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
10751
10752 format %{ "andq $dst, $src\t# long" %}
10753 ins_encode %{
10754 __ andq($dst$$Register, $src$$Register);
10755 %}
10756 ins_pipe(ialu_reg_reg);
10757 %}
10758
10759 // And Register with Register using New Data Destination (NDD)
10760 instruct andL_rReg_ndd(rRegL dst, rRegL src1, rRegL src2, rFlagsReg cr)
10761 %{
10762 predicate(UseAPX);
10763 match(Set dst (AndL src1 src2));
10764 effect(KILL cr);
10765 flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
10766
10767 format %{ "eandq $dst, $src1, $src2\t# long ndd" %}
10768 ins_encode %{
10769 __ eandq($dst$$Register, $src1$$Register, $src2$$Register, false);
10770
10771 %}
10772 ins_pipe(ialu_reg_reg);
10773 %}
10774
10775 // And Register with Immediate 255
10776 instruct andL_rReg_imm255(rRegL dst, rRegL src, immL_255 mask)
10777 %{
10778 match(Set dst (AndL src mask));
10779
10780 format %{ "movzbl $dst, $src\t# long & 0xFF" %}
10781 ins_encode %{
10782 // movzbl zeroes out the upper 32-bit and does not need REX.W
10783 __ movzbl($dst$$Register, $src$$Register);
10784 %}
10785 ins_pipe(ialu_reg);
10786 %}
10787
10788 // And Register with Immediate 65535
10789 instruct andL_rReg_imm65535(rRegL dst, rRegL src, immL_65535 mask)
10790 %{
10791 match(Set dst (AndL src mask));
10792
10793 format %{ "movzwl $dst, $src\t# long & 0xFFFF" %}
10794 ins_encode %{
10795 // movzwl zeroes out the upper 32-bit and does not need REX.W
10796 __ movzwl($dst$$Register, $src$$Register);
10797 %}
10798 ins_pipe(ialu_reg);
10799 %}
10800
10801 // And Register with Immediate
10802 instruct andL_rReg_imm(rRegL dst, immL32 src, rFlagsReg cr)
10803 %{
10804 predicate(!UseAPX);
10805 match(Set dst (AndL dst src));
10806 effect(KILL cr);
10807 flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
10808
10809 format %{ "andq $dst, $src\t# long" %}
10810 ins_encode %{
10811 __ andq($dst$$Register, $src$$constant);
10812 %}
10813 ins_pipe(ialu_reg);
10814 %}
10815
10816 instruct andL_rReg_rReg_imm_ndd(rRegL dst, rRegL src1, immL32 src2, rFlagsReg cr)
10817 %{
10818 predicate(UseAPX);
10819 match(Set dst (AndL src1 src2));
10820 effect(KILL cr);
10821 flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
10822
10823 format %{ "eandq $dst, $src1, $src2\t# long ndd" %}
10824 ins_encode %{
10825 __ eandq($dst$$Register, $src1$$Register, $src2$$constant, false);
10826 %}
10827 ins_pipe(ialu_reg);
10828 %}
10829
10830 instruct andL_rReg_mem_imm_ndd(rRegL dst, memory src1, immL32 src2, rFlagsReg cr)
10831 %{
10832 predicate(UseAPX);
10833 match(Set dst (AndL (LoadL src1) src2));
10834 effect(KILL cr);
10835 flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
10836
10837 format %{ "eandq $dst, $src1, $src2\t# long ndd" %}
10838 ins_encode %{
10839 __ eandq($dst$$Register, $src1$$Address, $src2$$constant, false);
10840 %}
10841 ins_pipe(ialu_reg);
10842 %}
10843
10844 // And Register with Memory
10845 instruct andL_rReg_mem(rRegL dst, memory src, rFlagsReg cr)
10846 %{
10847 predicate(!UseAPX);
10848 match(Set dst (AndL dst (LoadL src)));
10849 effect(KILL cr);
10850 flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
10851
10852 ins_cost(150);
10853 format %{ "andq $dst, $src\t# long" %}
10854 ins_encode %{
10855 __ andq($dst$$Register, $src$$Address);
10856 %}
10857 ins_pipe(ialu_reg_mem);
10858 %}
10859
10860 instruct andL_rReg_rReg_mem_ndd(rRegL dst, rRegL src1, memory src2, rFlagsReg cr)
10861 %{
10862 predicate(UseAPX);
10863 match(Set dst (AndL src1 (LoadL src2)));
10864 effect(KILL cr);
10865 flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
10866
10867 ins_cost(150);
10868 format %{ "eandq $dst, $src1, $src2\t# long ndd" %}
10869 ins_encode %{
10870 __ eandq($dst$$Register, $src1$$Register, $src2$$Address, false);
10871 %}
10872 ins_pipe(ialu_reg_mem);
10873 %}
10874
10875 // And Memory with Register
10876 instruct andL_mem_rReg(memory dst, rRegL src, rFlagsReg cr)
10877 %{
10878 match(Set dst (StoreL dst (AndL (LoadL dst) src)));
10879 effect(KILL cr);
10880 flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
10881
10882 ins_cost(150);
10883 format %{ "andq $dst, $src\t# long" %}
10884 ins_encode %{
10885 __ andq($dst$$Address, $src$$Register);
10886 %}
10887 ins_pipe(ialu_mem_reg);
10888 %}
10889
10890 // And Memory with Immediate
10891 instruct andL_mem_imm(memory dst, immL32 src, rFlagsReg cr)
10892 %{
10893 match(Set dst (StoreL dst (AndL (LoadL dst) src)));
10894 effect(KILL cr);
10895 flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
10896
10897 ins_cost(125);
10898 format %{ "andq $dst, $src\t# long" %}
10899 ins_encode %{
10900 __ andq($dst$$Address, $src$$constant);
10901 %}
10902 ins_pipe(ialu_mem_imm);
10903 %}
10904
10905 instruct btrL_mem_imm(memory dst, immL_NotPow2 con, rFlagsReg cr)
10906 %{
10907 // con should be a pure 64-bit immediate given that not(con) is a power of 2
10908 // because AND/OR works well enough for 8/32-bit values.
10909 predicate(log2i_graceful(~n->in(3)->in(2)->get_long()) > 30);
10910
10911 match(Set dst (StoreL dst (AndL (LoadL dst) con)));
10912 effect(KILL cr);
10913
10914 ins_cost(125);
10915 format %{ "btrq $dst, log2(not($con))\t# long" %}
10916 ins_encode %{
10917 __ btrq($dst$$Address, log2i_exact((julong)~$con$$constant));
10918 %}
10919 ins_pipe(ialu_mem_imm);
10920 %}
10921
10922 // BMI1 instructions
10923 instruct andnL_rReg_rReg_mem(rRegL dst, rRegL src1, memory src2, immL_M1 minus_1, rFlagsReg cr) %{
10924 match(Set dst (AndL (XorL src1 minus_1) (LoadL src2)));
10925 predicate(UseBMI1Instructions);
10926 effect(KILL cr);
10927 flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
10928
10929 ins_cost(125);
10930 format %{ "andnq $dst, $src1, $src2" %}
10931
10932 ins_encode %{
10933 __ andnq($dst$$Register, $src1$$Register, $src2$$Address);
10934 %}
10935 ins_pipe(ialu_reg_mem);
10936 %}
10937
10938 instruct andnL_rReg_rReg_rReg(rRegL dst, rRegL src1, rRegL src2, immL_M1 minus_1, rFlagsReg cr) %{
10939 match(Set dst (AndL (XorL src1 minus_1) src2));
10940 predicate(UseBMI1Instructions);
10941 effect(KILL cr);
10942 flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
10943
10944 format %{ "andnq $dst, $src1, $src2" %}
10945
10946 ins_encode %{
10947 __ andnq($dst$$Register, $src1$$Register, $src2$$Register);
10948 %}
10949 ins_pipe(ialu_reg_mem);
10950 %}
10951
10952 instruct blsiL_rReg_rReg(rRegL dst, rRegL src, immL0 imm_zero, rFlagsReg cr) %{
10953 match(Set dst (AndL (SubL imm_zero src) src));
10954 predicate(UseBMI1Instructions);
10955 effect(KILL cr);
10956 flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_clears_overflow_flag);
10957
10958 format %{ "blsiq $dst, $src" %}
10959
10960 ins_encode %{
10961 __ blsiq($dst$$Register, $src$$Register);
10962 %}
10963 ins_pipe(ialu_reg);
10964 %}
10965
10966 instruct blsiL_rReg_mem(rRegL dst, memory src, immL0 imm_zero, rFlagsReg cr) %{
10967 match(Set dst (AndL (SubL imm_zero (LoadL src) ) (LoadL src) ));
10968 predicate(UseBMI1Instructions);
10969 effect(KILL cr);
10970 flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_clears_overflow_flag);
10971
10972 ins_cost(125);
10973 format %{ "blsiq $dst, $src" %}
10974
10975 ins_encode %{
10976 __ blsiq($dst$$Register, $src$$Address);
10977 %}
10978 ins_pipe(ialu_reg_mem);
10979 %}
10980
10981 instruct blsmskL_rReg_mem(rRegL dst, memory src, immL_M1 minus_1, rFlagsReg cr)
10982 %{
10983 match(Set dst (XorL (AddL (LoadL src) minus_1) (LoadL src) ) );
10984 predicate(UseBMI1Instructions);
10985 effect(KILL cr);
10986 flag(PD::Flag_sets_sign_flag, PD::Flag_clears_zero_flag, PD::Flag_clears_overflow_flag);
10987
10988 ins_cost(125);
10989 format %{ "blsmskq $dst, $src" %}
10990
10991 ins_encode %{
10992 __ blsmskq($dst$$Register, $src$$Address);
10993 %}
10994 ins_pipe(ialu_reg_mem);
10995 %}
10996
10997 instruct blsmskL_rReg_rReg(rRegL dst, rRegL src, immL_M1 minus_1, rFlagsReg cr)
10998 %{
10999 match(Set dst (XorL (AddL src minus_1) src));
11000 predicate(UseBMI1Instructions);
11001 effect(KILL cr);
11002 flag(PD::Flag_sets_sign_flag, PD::Flag_clears_zero_flag, PD::Flag_clears_overflow_flag);
11003
11004 format %{ "blsmskq $dst, $src" %}
11005
11006 ins_encode %{
11007 __ blsmskq($dst$$Register, $src$$Register);
11008 %}
11009
11010 ins_pipe(ialu_reg);
11011 %}
11012
11013 instruct blsrL_rReg_rReg(rRegL dst, rRegL src, immL_M1 minus_1, rFlagsReg cr)
11014 %{
11015 match(Set dst (AndL (AddL src minus_1) src) );
11016 predicate(UseBMI1Instructions);
11017 effect(KILL cr);
11018 flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_clears_overflow_flag);
11019
11020 format %{ "blsrq $dst, $src" %}
11021
11022 ins_encode %{
11023 __ blsrq($dst$$Register, $src$$Register);
11024 %}
11025
11026 ins_pipe(ialu_reg);
11027 %}
11028
11029 instruct blsrL_rReg_mem(rRegL dst, memory src, immL_M1 minus_1, rFlagsReg cr)
11030 %{
11031 match(Set dst (AndL (AddL (LoadL src) minus_1) (LoadL src)) );
11032 predicate(UseBMI1Instructions);
11033 effect(KILL cr);
11034 flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_clears_overflow_flag);
11035
11036 ins_cost(125);
11037 format %{ "blsrq $dst, $src" %}
11038
11039 ins_encode %{
11040 __ blsrq($dst$$Register, $src$$Address);
11041 %}
11042
11043 ins_pipe(ialu_reg);
11044 %}
11045
11046 // Or Instructions
11047 // Or Register with Register
11048 instruct orL_rReg(rRegL dst, rRegL src, rFlagsReg cr)
11049 %{
11050 predicate(!UseAPX);
11051 match(Set dst (OrL dst src));
11052 effect(KILL cr);
11053 flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
11054
11055 format %{ "orq $dst, $src\t# long" %}
11056 ins_encode %{
11057 __ orq($dst$$Register, $src$$Register);
11058 %}
11059 ins_pipe(ialu_reg_reg);
11060 %}
11061
11062 // Or Register with Register using New Data Destination (NDD)
11063 instruct orL_rReg_ndd(rRegL dst, rRegL src1, rRegL src2, rFlagsReg cr)
11064 %{
11065 predicate(UseAPX);
11066 match(Set dst (OrL src1 src2));
11067 effect(KILL cr);
11068 flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
11069
11070 format %{ "eorq $dst, $src1, $src2\t# long ndd" %}
11071 ins_encode %{
11072 __ eorq($dst$$Register, $src1$$Register, $src2$$Register, false);
11073
11074 %}
11075 ins_pipe(ialu_reg_reg);
11076 %}
11077
11078 // Use any_RegP to match R15 (TLS register) without spilling.
11079 instruct orL_rReg_castP2X(rRegL dst, any_RegP src, rFlagsReg cr) %{
11080 match(Set dst (OrL dst (CastP2X src)));
11081 effect(KILL cr);
11082 flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
11083
11084 format %{ "orq $dst, $src\t# long" %}
11085 ins_encode %{
11086 __ orq($dst$$Register, $src$$Register);
11087 %}
11088 ins_pipe(ialu_reg_reg);
11089 %}
11090
11091 instruct orL_rReg_castP2X_ndd(rRegL dst, any_RegP src1, any_RegP src2, rFlagsReg cr) %{
11092 match(Set dst (OrL src1 (CastP2X src2)));
11093 effect(KILL cr);
11094 flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
11095
11096 format %{ "eorq $dst, $src1, $src2\t# long ndd" %}
11097 ins_encode %{
11098 __ eorq($dst$$Register, $src1$$Register, $src2$$Register, false);
11099 %}
11100 ins_pipe(ialu_reg_reg);
11101 %}
11102
11103 // Or Register with Immediate
11104 instruct orL_rReg_imm(rRegL dst, immL32 src, rFlagsReg cr)
11105 %{
11106 predicate(!UseAPX);
11107 match(Set dst (OrL dst src));
11108 effect(KILL cr);
11109 flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
11110
11111 format %{ "orq $dst, $src\t# long" %}
11112 ins_encode %{
11113 __ orq($dst$$Register, $src$$constant);
11114 %}
11115 ins_pipe(ialu_reg);
11116 %}
11117
11118 instruct orL_rReg_rReg_imm_ndd(rRegL dst, rRegL src1, immL32 src2, rFlagsReg cr)
11119 %{
11120 predicate(UseAPX);
11121 match(Set dst (OrL src1 src2));
11122 effect(KILL cr);
11123 flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
11124
11125 format %{ "eorq $dst, $src1, $src2\t# long ndd" %}
11126 ins_encode %{
11127 __ eorq($dst$$Register, $src1$$Register, $src2$$constant, false);
11128 %}
11129 ins_pipe(ialu_reg);
11130 %}
11131
11132 instruct orL_rReg_imm_rReg_ndd(rRegL dst, immL32 src1, rRegL src2, rFlagsReg cr)
11133 %{
11134 predicate(UseAPX);
11135 match(Set dst (OrL src1 src2));
11136 effect(KILL cr);
11137 flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
11138
11139 format %{ "eorq $dst, $src2, $src1\t# long ndd" %}
11140 ins_encode %{
11141 __ eorq($dst$$Register, $src2$$Register, $src1$$constant, false);
11142 %}
11143 ins_pipe(ialu_reg);
11144 %}
11145
11146 // Or Memory with Immediate
11147 instruct orL_rReg_mem_imm_ndd(rRegL dst, memory src1, immL32 src2, rFlagsReg cr)
11148 %{
11149 predicate(UseAPX);
11150 match(Set dst (OrL (LoadL src1) src2));
11151 effect(KILL cr);
11152 flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
11153
11154 format %{ "eorq $dst, $src1, $src2\t# long ndd" %}
11155 ins_encode %{
11156 __ eorq($dst$$Register, $src1$$Address, $src2$$constant, false);
11157 %}
11158 ins_pipe(ialu_reg);
11159 %}
11160
11161 // Or Register with Memory
11162 instruct orL_rReg_mem(rRegL dst, memory src, rFlagsReg cr)
11163 %{
11164 predicate(!UseAPX);
11165 match(Set dst (OrL dst (LoadL src)));
11166 effect(KILL cr);
11167 flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
11168
11169 ins_cost(150);
11170 format %{ "orq $dst, $src\t# long" %}
11171 ins_encode %{
11172 __ orq($dst$$Register, $src$$Address);
11173 %}
11174 ins_pipe(ialu_reg_mem);
11175 %}
11176
11177 instruct orL_rReg_rReg_mem_ndd(rRegL dst, rRegL src1, memory src2, rFlagsReg cr)
11178 %{
11179 predicate(UseAPX);
11180 match(Set dst (OrL src1 (LoadL src2)));
11181 effect(KILL cr);
11182 flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
11183
11184 ins_cost(150);
11185 format %{ "eorq $dst, $src1, $src2\t# long ndd" %}
11186 ins_encode %{
11187 __ eorq($dst$$Register, $src1$$Register, $src2$$Address, false);
11188 %}
11189 ins_pipe(ialu_reg_mem);
11190 %}
11191
11192 // Or Memory with Register
11193 instruct orL_mem_rReg(memory dst, rRegL src, rFlagsReg cr)
11194 %{
11195 match(Set dst (StoreL dst (OrL (LoadL dst) src)));
11196 effect(KILL cr);
11197 flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
11198
11199 ins_cost(150);
11200 format %{ "orq $dst, $src\t# long" %}
11201 ins_encode %{
11202 __ orq($dst$$Address, $src$$Register);
11203 %}
11204 ins_pipe(ialu_mem_reg);
11205 %}
11206
11207 // Or Memory with Immediate
11208 instruct orL_mem_imm(memory dst, immL32 src, rFlagsReg cr)
11209 %{
11210 match(Set dst (StoreL dst (OrL (LoadL dst) src)));
11211 effect(KILL cr);
11212 flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
11213
11214 ins_cost(125);
11215 format %{ "orq $dst, $src\t# long" %}
11216 ins_encode %{
11217 __ orq($dst$$Address, $src$$constant);
11218 %}
11219 ins_pipe(ialu_mem_imm);
11220 %}
11221
11222 instruct btsL_mem_imm(memory dst, immL_Pow2 con, rFlagsReg cr)
11223 %{
11224 // con should be a pure 64-bit power of 2 immediate
11225 // because AND/OR works well enough for 8/32-bit values.
11226 predicate(log2i_graceful(n->in(3)->in(2)->get_long()) > 31);
11227
11228 match(Set dst (StoreL dst (OrL (LoadL dst) con)));
11229 effect(KILL cr);
11230
11231 ins_cost(125);
11232 format %{ "btsq $dst, log2($con)\t# long" %}
11233 ins_encode %{
11234 __ btsq($dst$$Address, log2i_exact((julong)$con$$constant));
11235 %}
11236 ins_pipe(ialu_mem_imm);
11237 %}
11238
11239 // Xor Instructions
11240 // Xor Register with Register
11241 instruct xorL_rReg(rRegL dst, rRegL src, rFlagsReg cr)
11242 %{
11243 predicate(!UseAPX);
11244 match(Set dst (XorL dst src));
11245 effect(KILL cr);
11246 flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
11247
11248 format %{ "xorq $dst, $src\t# long" %}
11249 ins_encode %{
11250 __ xorq($dst$$Register, $src$$Register);
11251 %}
11252 ins_pipe(ialu_reg_reg);
11253 %}
11254
11255 // Xor Register with Register using New Data Destination (NDD)
11256 instruct xorL_rReg_ndd(rRegL dst, rRegL src1, rRegL src2, rFlagsReg cr)
11257 %{
11258 predicate(UseAPX);
11259 match(Set dst (XorL src1 src2));
11260 effect(KILL cr);
11261 flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
11262
11263 format %{ "exorq $dst, $src1, $src2\t# long ndd" %}
11264 ins_encode %{
11265 __ exorq($dst$$Register, $src1$$Register, $src2$$Register, false);
11266 %}
11267 ins_pipe(ialu_reg_reg);
11268 %}
11269
11270 // Xor Register with Immediate -1
11271 instruct xorL_rReg_im1(rRegL dst, immL_M1 imm)
11272 %{
11273 predicate(!UseAPX);
11274 match(Set dst (XorL dst imm));
11275
11276 format %{ "notq $dst" %}
11277 ins_encode %{
11278 __ notq($dst$$Register);
11279 %}
11280 ins_pipe(ialu_reg);
11281 %}
11282
11283 instruct xorL_rReg_im1_ndd(rRegL dst,rRegL src, immL_M1 imm)
11284 %{
11285 predicate(UseAPX);
11286 match(Set dst (XorL src imm));
11287
11288 format %{ "enotq $dst, $src" %}
11289 ins_encode %{
11290 __ enotq($dst$$Register, $src$$Register);
11291 %}
11292 ins_pipe(ialu_reg);
11293 %}
11294
11295 // Xor Register with Immediate
11296 instruct xorL_rReg_imm(rRegL dst, immL32 src, rFlagsReg cr)
11297 %{
11298 // Strict predicate check to make selection of xorL_rReg_im1 cost agnostic if immL32 src is -1.
11299 predicate(!UseAPX && n->in(2)->bottom_type()->is_long()->get_con() != -1L);
11300 match(Set dst (XorL dst src));
11301 effect(KILL cr);
11302 flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
11303
11304 format %{ "xorq $dst, $src\t# long" %}
11305 ins_encode %{
11306 __ xorq($dst$$Register, $src$$constant);
11307 %}
11308 ins_pipe(ialu_reg);
11309 %}
11310
11311 instruct xorL_rReg_rReg_imm(rRegL dst, rRegL src1, immL32 src2, rFlagsReg cr)
11312 %{
11313 // Strict predicate check to make selection of xorL_rReg_im1_ndd cost agnostic if immL32 src2 is -1.
11314 predicate(UseAPX && n->in(2)->bottom_type()->is_long()->get_con() != -1L);
11315 match(Set dst (XorL src1 src2));
11316 effect(KILL cr);
11317 flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
11318
11319 format %{ "exorq $dst, $src1, $src2\t# long ndd" %}
11320 ins_encode %{
11321 __ exorq($dst$$Register, $src1$$Register, $src2$$constant, false);
11322 %}
11323 ins_pipe(ialu_reg);
11324 %}
11325
11326 // Xor Memory with Immediate
11327 instruct xorL_rReg_mem_imm(rRegL dst, memory src1, immL32 src2, rFlagsReg cr)
11328 %{
11329 predicate(UseAPX);
11330 match(Set dst (XorL (LoadL src1) src2));
11331 effect(KILL cr);
11332 flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
11333 ins_cost(150);
11334
11335 format %{ "exorq $dst, $src1, $src2\t# long ndd" %}
11336 ins_encode %{
11337 __ exorq($dst$$Register, $src1$$Address, $src2$$constant, false);
11338 %}
11339 ins_pipe(ialu_reg);
11340 %}
11341
11342 // Xor Register with Memory
11343 instruct xorL_rReg_mem(rRegL dst, memory src, rFlagsReg cr)
11344 %{
11345 predicate(!UseAPX);
11346 match(Set dst (XorL dst (LoadL src)));
11347 effect(KILL cr);
11348 flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
11349
11350 ins_cost(150);
11351 format %{ "xorq $dst, $src\t# long" %}
11352 ins_encode %{
11353 __ xorq($dst$$Register, $src$$Address);
11354 %}
11355 ins_pipe(ialu_reg_mem);
11356 %}
11357
11358 instruct xorL_rReg_rReg_mem_ndd(rRegL dst, rRegL src1, memory src2, rFlagsReg cr)
11359 %{
11360 predicate(UseAPX);
11361 match(Set dst (XorL src1 (LoadL src2)));
11362 effect(KILL cr);
11363 flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
11364
11365 ins_cost(150);
11366 format %{ "exorq $dst, $src1, $src2\t# long ndd" %}
11367 ins_encode %{
11368 __ exorq($dst$$Register, $src1$$Register, $src2$$Address, false);
11369 %}
11370 ins_pipe(ialu_reg_mem);
11371 %}
11372
11373 // Xor Memory with Register
11374 instruct xorL_mem_rReg(memory dst, rRegL src, rFlagsReg cr)
11375 %{
11376 match(Set dst (StoreL dst (XorL (LoadL dst) src)));
11377 effect(KILL cr);
11378 flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
11379
11380 ins_cost(150);
11381 format %{ "xorq $dst, $src\t# long" %}
11382 ins_encode %{
11383 __ xorq($dst$$Address, $src$$Register);
11384 %}
11385 ins_pipe(ialu_mem_reg);
11386 %}
11387
11388 // Xor Memory with Immediate
11389 instruct xorL_mem_imm(memory dst, immL32 src, rFlagsReg cr)
11390 %{
11391 match(Set dst (StoreL dst (XorL (LoadL dst) src)));
11392 effect(KILL cr);
11393 flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
11394
11395 ins_cost(125);
11396 format %{ "xorq $dst, $src\t# long" %}
11397 ins_encode %{
11398 __ xorq($dst$$Address, $src$$constant);
11399 %}
11400 ins_pipe(ialu_mem_imm);
11401 %}
11402
11403 instruct cmpLTMask(rRegI dst, rRegI p, rRegI q, rFlagsReg cr)
11404 %{
11405 match(Set dst (CmpLTMask p q));
11406 effect(KILL cr);
11407
11408 ins_cost(400);
11409 format %{ "cmpl $p, $q\t# cmpLTMask\n\t"
11410 "setcc $dst \t# emits setlt + movzbl or setzul for APX"
11411 "negl $dst" %}
11412 ins_encode %{
11413 __ cmpl($p$$Register, $q$$Register);
11414 __ setcc(Assembler::less, $dst$$Register);
11415 __ negl($dst$$Register);
11416 %}
11417 ins_pipe(pipe_slow);
11418 %}
11419
11420 instruct cmpLTMask0(rRegI dst, immI_0 zero, rFlagsReg cr)
11421 %{
11422 match(Set dst (CmpLTMask dst zero));
11423 effect(KILL cr);
11424
11425 ins_cost(100);
11426 format %{ "sarl $dst, #31\t# cmpLTMask0" %}
11427 ins_encode %{
11428 __ sarl($dst$$Register, 31);
11429 %}
11430 ins_pipe(ialu_reg);
11431 %}
11432
11433 /* Better to save a register than avoid a branch */
11434 instruct cadd_cmpLTMask(rRegI p, rRegI q, rRegI y, rFlagsReg cr)
11435 %{
11436 match(Set p (AddI (AndI (CmpLTMask p q) y) (SubI p q)));
11437 effect(KILL cr);
11438 ins_cost(300);
11439 format %{ "subl $p,$q\t# cadd_cmpLTMask\n\t"
11440 "jge done\n\t"
11441 "addl $p,$y\n"
11442 "done: " %}
11443 ins_encode %{
11444 Register Rp = $p$$Register;
11445 Register Rq = $q$$Register;
11446 Register Ry = $y$$Register;
11447 Label done;
11448 __ subl(Rp, Rq);
11449 __ jccb(Assembler::greaterEqual, done);
11450 __ addl(Rp, Ry);
11451 __ bind(done);
11452 %}
11453 ins_pipe(pipe_cmplt);
11454 %}
11455
11456 /* Better to save a register than avoid a branch */
11457 instruct and_cmpLTMask(rRegI p, rRegI q, rRegI y, rFlagsReg cr)
11458 %{
11459 match(Set y (AndI (CmpLTMask p q) y));
11460 effect(KILL cr);
11461
11462 ins_cost(300);
11463
11464 format %{ "cmpl $p, $q\t# and_cmpLTMask\n\t"
11465 "jlt done\n\t"
11466 "xorl $y, $y\n"
11467 "done: " %}
11468 ins_encode %{
11469 Register Rp = $p$$Register;
11470 Register Rq = $q$$Register;
11471 Register Ry = $y$$Register;
11472 Label done;
11473 __ cmpl(Rp, Rq);
11474 __ jccb(Assembler::less, done);
11475 __ xorl(Ry, Ry);
11476 __ bind(done);
11477 %}
11478 ins_pipe(pipe_cmplt);
11479 %}
11480
11481
11482 //---------- FP Instructions------------------------------------------------
11483
11484 // Really expensive, avoid
11485 instruct cmpF_cc_reg(rFlagsRegU cr, regF src1, regF src2)
11486 %{
11487 match(Set cr (CmpF src1 src2));
11488
11489 ins_cost(500);
11490 format %{ "ucomiss $src1, $src2\n\t"
11491 "jnp,s exit\n\t"
11492 "pushfq\t# saw NaN, set CF\n\t"
11493 "andq [rsp], #0xffffff2b\n\t"
11494 "popfq\n"
11495 "exit:" %}
11496 ins_encode %{
11497 __ ucomiss($src1$$XMMRegister, $src2$$XMMRegister);
11498 emit_cmpfp_fixup(masm);
11499 %}
11500 ins_pipe(pipe_slow);
11501 %}
11502
11503 instruct cmpF_cc_reg_CF(rFlagsRegUCF cr, regF src1, regF src2) %{
11504 match(Set cr (CmpF src1 src2));
11505
11506 ins_cost(100);
11507 format %{ "ucomiss $src1, $src2" %}
11508 ins_encode %{
11509 __ ucomiss($src1$$XMMRegister, $src2$$XMMRegister);
11510 %}
11511 ins_pipe(pipe_slow);
11512 %}
11513
11514 instruct cmpF_cc_memCF(rFlagsRegUCF cr, regF src1, memory src2) %{
11515 match(Set cr (CmpF src1 (LoadF src2)));
11516
11517 ins_cost(100);
11518 format %{ "ucomiss $src1, $src2" %}
11519 ins_encode %{
11520 __ ucomiss($src1$$XMMRegister, $src2$$Address);
11521 %}
11522 ins_pipe(pipe_slow);
11523 %}
11524
11525 instruct cmpF_cc_immCF(rFlagsRegUCF cr, regF src, immF con) %{
11526 match(Set cr (CmpF src con));
11527 ins_cost(100);
11528 format %{ "ucomiss $src, [$constantaddress]\t# load from constant table: float=$con" %}
11529 ins_encode %{
11530 __ ucomiss($src$$XMMRegister, $constantaddress($con));
11531 %}
11532 ins_pipe(pipe_slow);
11533 %}
11534
11535 // Really expensive, avoid
11536 instruct cmpD_cc_reg(rFlagsRegU cr, regD src1, regD src2)
11537 %{
11538 match(Set cr (CmpD src1 src2));
11539
11540 ins_cost(500);
11541 format %{ "ucomisd $src1, $src2\n\t"
11542 "jnp,s exit\n\t"
11543 "pushfq\t# saw NaN, set CF\n\t"
11544 "andq [rsp], #0xffffff2b\n\t"
11545 "popfq\n"
11546 "exit:" %}
11547 ins_encode %{
11548 __ ucomisd($src1$$XMMRegister, $src2$$XMMRegister);
11549 emit_cmpfp_fixup(masm);
11550 %}
11551 ins_pipe(pipe_slow);
11552 %}
11553
11554 instruct cmpD_cc_reg_CF(rFlagsRegUCF cr, regD src1, regD src2) %{
11555 match(Set cr (CmpD src1 src2));
11556
11557 ins_cost(100);
11558 format %{ "ucomisd $src1, $src2 test" %}
11559 ins_encode %{
11560 __ ucomisd($src1$$XMMRegister, $src2$$XMMRegister);
11561 %}
11562 ins_pipe(pipe_slow);
11563 %}
11564
11565 instruct cmpD_cc_memCF(rFlagsRegUCF cr, regD src1, memory src2) %{
11566 match(Set cr (CmpD src1 (LoadD src2)));
11567
11568 ins_cost(100);
11569 format %{ "ucomisd $src1, $src2" %}
11570 ins_encode %{
11571 __ ucomisd($src1$$XMMRegister, $src2$$Address);
11572 %}
11573 ins_pipe(pipe_slow);
11574 %}
11575
11576 instruct cmpD_cc_immCF(rFlagsRegUCF cr, regD src, immD con) %{
11577 match(Set cr (CmpD src con));
11578 ins_cost(100);
11579 format %{ "ucomisd $src, [$constantaddress]\t# load from constant table: double=$con" %}
11580 ins_encode %{
11581 __ ucomisd($src$$XMMRegister, $constantaddress($con));
11582 %}
11583 ins_pipe(pipe_slow);
11584 %}
11585
11586 // Compare into -1,0,1
11587 instruct cmpF_reg(rRegI dst, regF src1, regF src2, rFlagsReg cr)
11588 %{
11589 match(Set dst (CmpF3 src1 src2));
11590 effect(KILL cr);
11591
11592 ins_cost(275);
11593 format %{ "ucomiss $src1, $src2\n\t"
11594 "movl $dst, #-1\n\t"
11595 "jp,s done\n\t"
11596 "jb,s done\n\t"
11597 "setne $dst\n\t"
11598 "movzbl $dst, $dst\n"
11599 "done:" %}
11600 ins_encode %{
11601 __ ucomiss($src1$$XMMRegister, $src2$$XMMRegister);
11602 emit_cmpfp3(masm, $dst$$Register);
11603 %}
11604 ins_pipe(pipe_slow);
11605 %}
11606
11607 // Compare into -1,0,1
11608 instruct cmpF_mem(rRegI dst, regF src1, memory src2, rFlagsReg cr)
11609 %{
11610 match(Set dst (CmpF3 src1 (LoadF src2)));
11611 effect(KILL cr);
11612
11613 ins_cost(275);
11614 format %{ "ucomiss $src1, $src2\n\t"
11615 "movl $dst, #-1\n\t"
11616 "jp,s done\n\t"
11617 "jb,s done\n\t"
11618 "setne $dst\n\t"
11619 "movzbl $dst, $dst\n"
11620 "done:" %}
11621 ins_encode %{
11622 __ ucomiss($src1$$XMMRegister, $src2$$Address);
11623 emit_cmpfp3(masm, $dst$$Register);
11624 %}
11625 ins_pipe(pipe_slow);
11626 %}
11627
11628 // Compare into -1,0,1
11629 instruct cmpF_imm(rRegI dst, regF src, immF con, rFlagsReg cr) %{
11630 match(Set dst (CmpF3 src con));
11631 effect(KILL cr);
11632
11633 ins_cost(275);
11634 format %{ "ucomiss $src, [$constantaddress]\t# load from constant table: float=$con\n\t"
11635 "movl $dst, #-1\n\t"
11636 "jp,s done\n\t"
11637 "jb,s done\n\t"
11638 "setne $dst\n\t"
11639 "movzbl $dst, $dst\n"
11640 "done:" %}
11641 ins_encode %{
11642 __ ucomiss($src$$XMMRegister, $constantaddress($con));
11643 emit_cmpfp3(masm, $dst$$Register);
11644 %}
11645 ins_pipe(pipe_slow);
11646 %}
11647
11648 // Compare into -1,0,1
11649 instruct cmpD_reg(rRegI dst, regD src1, regD src2, rFlagsReg cr)
11650 %{
11651 match(Set dst (CmpD3 src1 src2));
11652 effect(KILL cr);
11653
11654 ins_cost(275);
11655 format %{ "ucomisd $src1, $src2\n\t"
11656 "movl $dst, #-1\n\t"
11657 "jp,s done\n\t"
11658 "jb,s done\n\t"
11659 "setne $dst\n\t"
11660 "movzbl $dst, $dst\n"
11661 "done:" %}
11662 ins_encode %{
11663 __ ucomisd($src1$$XMMRegister, $src2$$XMMRegister);
11664 emit_cmpfp3(masm, $dst$$Register);
11665 %}
11666 ins_pipe(pipe_slow);
11667 %}
11668
11669 // Compare into -1,0,1
11670 instruct cmpD_mem(rRegI dst, regD src1, memory src2, rFlagsReg cr)
11671 %{
11672 match(Set dst (CmpD3 src1 (LoadD src2)));
11673 effect(KILL cr);
11674
11675 ins_cost(275);
11676 format %{ "ucomisd $src1, $src2\n\t"
11677 "movl $dst, #-1\n\t"
11678 "jp,s done\n\t"
11679 "jb,s done\n\t"
11680 "setne $dst\n\t"
11681 "movzbl $dst, $dst\n"
11682 "done:" %}
11683 ins_encode %{
11684 __ ucomisd($src1$$XMMRegister, $src2$$Address);
11685 emit_cmpfp3(masm, $dst$$Register);
11686 %}
11687 ins_pipe(pipe_slow);
11688 %}
11689
11690 // Compare into -1,0,1
11691 instruct cmpD_imm(rRegI dst, regD src, immD con, rFlagsReg cr) %{
11692 match(Set dst (CmpD3 src con));
11693 effect(KILL cr);
11694
11695 ins_cost(275);
11696 format %{ "ucomisd $src, [$constantaddress]\t# load from constant table: double=$con\n\t"
11697 "movl $dst, #-1\n\t"
11698 "jp,s done\n\t"
11699 "jb,s done\n\t"
11700 "setne $dst\n\t"
11701 "movzbl $dst, $dst\n"
11702 "done:" %}
11703 ins_encode %{
11704 __ ucomisd($src$$XMMRegister, $constantaddress($con));
11705 emit_cmpfp3(masm, $dst$$Register);
11706 %}
11707 ins_pipe(pipe_slow);
11708 %}
11709
11710 //----------Arithmetic Conversion Instructions---------------------------------
11711
11712 instruct convF2D_reg_reg(regD dst, regF src)
11713 %{
11714 match(Set dst (ConvF2D src));
11715
11716 format %{ "cvtss2sd $dst, $src" %}
11717 ins_encode %{
11718 __ cvtss2sd ($dst$$XMMRegister, $src$$XMMRegister);
11719 %}
11720 ins_pipe(pipe_slow); // XXX
11721 %}
11722
11723 instruct convF2D_reg_mem(regD dst, memory src)
11724 %{
11725 predicate(UseAVX == 0);
11726 match(Set dst (ConvF2D (LoadF src)));
11727
11728 format %{ "cvtss2sd $dst, $src" %}
11729 ins_encode %{
11730 __ cvtss2sd ($dst$$XMMRegister, $src$$Address);
11731 %}
11732 ins_pipe(pipe_slow); // XXX
11733 %}
11734
11735 instruct convD2F_reg_reg(regF dst, regD src)
11736 %{
11737 match(Set dst (ConvD2F src));
11738
11739 format %{ "cvtsd2ss $dst, $src" %}
11740 ins_encode %{
11741 __ cvtsd2ss ($dst$$XMMRegister, $src$$XMMRegister);
11742 %}
11743 ins_pipe(pipe_slow); // XXX
11744 %}
11745
11746 instruct convD2F_reg_mem(regF dst, memory src)
11747 %{
11748 predicate(UseAVX == 0);
11749 match(Set dst (ConvD2F (LoadD src)));
11750
11751 format %{ "cvtsd2ss $dst, $src" %}
11752 ins_encode %{
11753 __ cvtsd2ss ($dst$$XMMRegister, $src$$Address);
11754 %}
11755 ins_pipe(pipe_slow); // XXX
11756 %}
11757
11758 // XXX do mem variants
11759 instruct convF2I_reg_reg(rRegI dst, regF src, rFlagsReg cr)
11760 %{
11761 predicate(!VM_Version::supports_avx10_2());
11762 match(Set dst (ConvF2I src));
11763 effect(KILL cr);
11764 format %{ "convert_f2i $dst, $src" %}
11765 ins_encode %{
11766 __ convertF2I(T_INT, T_FLOAT, $dst$$Register, $src$$XMMRegister);
11767 %}
11768 ins_pipe(pipe_slow);
11769 %}
11770
11771 instruct convF2I_reg_reg_avx10(rRegI dst, regF src)
11772 %{
11773 predicate(VM_Version::supports_avx10_2());
11774 match(Set dst (ConvF2I src));
11775 format %{ "evcvttss2sisl $dst, $src" %}
11776 ins_encode %{
11777 __ evcvttss2sisl($dst$$Register, $src$$XMMRegister);
11778 %}
11779 ins_pipe(pipe_slow);
11780 %}
11781
11782 instruct convF2I_reg_mem_avx10(rRegI dst, memory src)
11783 %{
11784 predicate(VM_Version::supports_avx10_2());
11785 match(Set dst (ConvF2I (LoadF src)));
11786 format %{ "evcvttss2sisl $dst, $src" %}
11787 ins_encode %{
11788 __ evcvttss2sisl($dst$$Register, $src$$Address);
11789 %}
11790 ins_pipe(pipe_slow);
11791 %}
11792
11793 instruct convF2L_reg_reg(rRegL dst, regF src, rFlagsReg cr)
11794 %{
11795 predicate(!VM_Version::supports_avx10_2());
11796 match(Set dst (ConvF2L src));
11797 effect(KILL cr);
11798 format %{ "convert_f2l $dst, $src"%}
11799 ins_encode %{
11800 __ convertF2I(T_LONG, T_FLOAT, $dst$$Register, $src$$XMMRegister);
11801 %}
11802 ins_pipe(pipe_slow);
11803 %}
11804
11805 instruct convF2L_reg_reg_avx10(rRegL dst, regF src)
11806 %{
11807 predicate(VM_Version::supports_avx10_2());
11808 match(Set dst (ConvF2L src));
11809 format %{ "evcvttss2sisq $dst, $src" %}
11810 ins_encode %{
11811 __ evcvttss2sisq($dst$$Register, $src$$XMMRegister);
11812 %}
11813 ins_pipe(pipe_slow);
11814 %}
11815
11816 instruct convF2L_reg_mem_avx10(rRegL dst, memory src)
11817 %{
11818 predicate(VM_Version::supports_avx10_2());
11819 match(Set dst (ConvF2L (LoadF src)));
11820 format %{ "evcvttss2sisq $dst, $src" %}
11821 ins_encode %{
11822 __ evcvttss2sisq($dst$$Register, $src$$Address);
11823 %}
11824 ins_pipe(pipe_slow);
11825 %}
11826
11827 instruct convD2I_reg_reg(rRegI dst, regD src, rFlagsReg cr)
11828 %{
11829 predicate(!VM_Version::supports_avx10_2());
11830 match(Set dst (ConvD2I src));
11831 effect(KILL cr);
11832 format %{ "convert_d2i $dst, $src"%}
11833 ins_encode %{
11834 __ convertF2I(T_INT, T_DOUBLE, $dst$$Register, $src$$XMMRegister);
11835 %}
11836 ins_pipe(pipe_slow);
11837 %}
11838
11839 instruct convD2I_reg_reg_avx10(rRegI dst, regD src)
11840 %{
11841 predicate(VM_Version::supports_avx10_2());
11842 match(Set dst (ConvD2I src));
11843 format %{ "evcvttsd2sisl $dst, $src" %}
11844 ins_encode %{
11845 __ evcvttsd2sisl($dst$$Register, $src$$XMMRegister);
11846 %}
11847 ins_pipe(pipe_slow);
11848 %}
11849
11850 instruct convD2I_reg_mem_avx10(rRegI dst, memory src)
11851 %{
11852 predicate(VM_Version::supports_avx10_2());
11853 match(Set dst (ConvD2I (LoadD src)));
11854 format %{ "evcvttsd2sisl $dst, $src" %}
11855 ins_encode %{
11856 __ evcvttsd2sisl($dst$$Register, $src$$Address);
11857 %}
11858 ins_pipe(pipe_slow);
11859 %}
11860
11861 instruct convD2L_reg_reg(rRegL dst, regD src, rFlagsReg cr)
11862 %{
11863 predicate(!VM_Version::supports_avx10_2());
11864 match(Set dst (ConvD2L src));
11865 effect(KILL cr);
11866 format %{ "convert_d2l $dst, $src"%}
11867 ins_encode %{
11868 __ convertF2I(T_LONG, T_DOUBLE, $dst$$Register, $src$$XMMRegister);
11869 %}
11870 ins_pipe(pipe_slow);
11871 %}
11872
11873 instruct convD2L_reg_reg_avx10(rRegL dst, regD src)
11874 %{
11875 predicate(VM_Version::supports_avx10_2());
11876 match(Set dst (ConvD2L src));
11877 format %{ "evcvttsd2sisq $dst, $src" %}
11878 ins_encode %{
11879 __ evcvttsd2sisq($dst$$Register, $src$$XMMRegister);
11880 %}
11881 ins_pipe(pipe_slow);
11882 %}
11883
11884 instruct convD2L_reg_mem_avx10(rRegL dst, memory src)
11885 %{
11886 predicate(VM_Version::supports_avx10_2());
11887 match(Set dst (ConvD2L (LoadD src)));
11888 format %{ "evcvttsd2sisq $dst, $src" %}
11889 ins_encode %{
11890 __ evcvttsd2sisq($dst$$Register, $src$$Address);
11891 %}
11892 ins_pipe(pipe_slow);
11893 %}
11894
11895 instruct round_double_reg(rRegL dst, regD src, rRegL rtmp, rcx_RegL rcx, rFlagsReg cr)
11896 %{
11897 match(Set dst (RoundD src));
11898 effect(TEMP dst, TEMP rtmp, TEMP rcx, KILL cr);
11899 format %{ "round_double $dst,$src \t! using $rtmp and $rcx as TEMP"%}
11900 ins_encode %{
11901 __ round_double($dst$$Register, $src$$XMMRegister, $rtmp$$Register, $rcx$$Register);
11902 %}
11903 ins_pipe(pipe_slow);
11904 %}
11905
11906 instruct round_float_reg(rRegI dst, regF src, rRegL rtmp, rcx_RegL rcx, rFlagsReg cr)
11907 %{
11908 match(Set dst (RoundF src));
11909 effect(TEMP dst, TEMP rtmp, TEMP rcx, KILL cr);
11910 format %{ "round_float $dst,$src" %}
11911 ins_encode %{
11912 __ round_float($dst$$Register, $src$$XMMRegister, $rtmp$$Register, $rcx$$Register);
11913 %}
11914 ins_pipe(pipe_slow);
11915 %}
11916
11917 instruct convI2F_reg_reg(vlRegF dst, rRegI src)
11918 %{
11919 predicate(!UseXmmI2F);
11920 match(Set dst (ConvI2F src));
11921
11922 format %{ "cvtsi2ssl $dst, $src\t# i2f" %}
11923 ins_encode %{
11924 if (UseAVX > 0) {
11925 __ pxor($dst$$XMMRegister, $dst$$XMMRegister);
11926 }
11927 __ cvtsi2ssl ($dst$$XMMRegister, $src$$Register);
11928 %}
11929 ins_pipe(pipe_slow); // XXX
11930 %}
11931
11932 instruct convI2F_reg_mem(regF dst, memory src)
11933 %{
11934 predicate(UseAVX == 0);
11935 match(Set dst (ConvI2F (LoadI src)));
11936
11937 format %{ "cvtsi2ssl $dst, $src\t# i2f" %}
11938 ins_encode %{
11939 __ cvtsi2ssl ($dst$$XMMRegister, $src$$Address);
11940 %}
11941 ins_pipe(pipe_slow); // XXX
11942 %}
11943
11944 instruct convI2D_reg_reg(vlRegD dst, rRegI src)
11945 %{
11946 predicate(!UseXmmI2D);
11947 match(Set dst (ConvI2D src));
11948
11949 format %{ "cvtsi2sdl $dst, $src\t# i2d" %}
11950 ins_encode %{
11951 if (UseAVX > 0) {
11952 __ pxor($dst$$XMMRegister, $dst$$XMMRegister);
11953 }
11954 __ cvtsi2sdl ($dst$$XMMRegister, $src$$Register);
11955 %}
11956 ins_pipe(pipe_slow); // XXX
11957 %}
11958
11959 instruct convI2D_reg_mem(regD dst, memory src)
11960 %{
11961 predicate(UseAVX == 0);
11962 match(Set dst (ConvI2D (LoadI src)));
11963
11964 format %{ "cvtsi2sdl $dst, $src\t# i2d" %}
11965 ins_encode %{
11966 __ cvtsi2sdl ($dst$$XMMRegister, $src$$Address);
11967 %}
11968 ins_pipe(pipe_slow); // XXX
11969 %}
11970
11971 instruct convXI2F_reg(regF dst, rRegI src)
11972 %{
11973 predicate(UseXmmI2F);
11974 match(Set dst (ConvI2F src));
11975
11976 format %{ "movdl $dst, $src\n\t"
11977 "cvtdq2psl $dst, $dst\t# i2f" %}
11978 ins_encode %{
11979 __ movdl($dst$$XMMRegister, $src$$Register);
11980 __ cvtdq2ps($dst$$XMMRegister, $dst$$XMMRegister);
11981 %}
11982 ins_pipe(pipe_slow); // XXX
11983 %}
11984
11985 instruct convXI2D_reg(regD dst, rRegI src)
11986 %{
11987 predicate(UseXmmI2D);
11988 match(Set dst (ConvI2D src));
11989
11990 format %{ "movdl $dst, $src\n\t"
11991 "cvtdq2pdl $dst, $dst\t# i2d" %}
11992 ins_encode %{
11993 __ movdl($dst$$XMMRegister, $src$$Register);
11994 __ cvtdq2pd($dst$$XMMRegister, $dst$$XMMRegister);
11995 %}
11996 ins_pipe(pipe_slow); // XXX
11997 %}
11998
11999 instruct convL2F_reg_reg(vlRegF dst, rRegL src)
12000 %{
12001 match(Set dst (ConvL2F src));
12002
12003 format %{ "cvtsi2ssq $dst, $src\t# l2f" %}
12004 ins_encode %{
12005 if (UseAVX > 0) {
12006 __ pxor($dst$$XMMRegister, $dst$$XMMRegister);
12007 }
12008 __ cvtsi2ssq ($dst$$XMMRegister, $src$$Register);
12009 %}
12010 ins_pipe(pipe_slow); // XXX
12011 %}
12012
12013 instruct convL2F_reg_mem(regF dst, memory src)
12014 %{
12015 predicate(UseAVX == 0);
12016 match(Set dst (ConvL2F (LoadL src)));
12017
12018 format %{ "cvtsi2ssq $dst, $src\t# l2f" %}
12019 ins_encode %{
12020 __ cvtsi2ssq ($dst$$XMMRegister, $src$$Address);
12021 %}
12022 ins_pipe(pipe_slow); // XXX
12023 %}
12024
12025 instruct convL2D_reg_reg(vlRegD dst, rRegL src)
12026 %{
12027 match(Set dst (ConvL2D src));
12028
12029 format %{ "cvtsi2sdq $dst, $src\t# l2d" %}
12030 ins_encode %{
12031 if (UseAVX > 0) {
12032 __ pxor($dst$$XMMRegister, $dst$$XMMRegister);
12033 }
12034 __ cvtsi2sdq ($dst$$XMMRegister, $src$$Register);
12035 %}
12036 ins_pipe(pipe_slow); // XXX
12037 %}
12038
12039 instruct convL2D_reg_mem(regD dst, memory src)
12040 %{
12041 predicate(UseAVX == 0);
12042 match(Set dst (ConvL2D (LoadL src)));
12043
12044 format %{ "cvtsi2sdq $dst, $src\t# l2d" %}
12045 ins_encode %{
12046 __ cvtsi2sdq ($dst$$XMMRegister, $src$$Address);
12047 %}
12048 ins_pipe(pipe_slow); // XXX
12049 %}
12050
12051 instruct convI2L_reg_reg(rRegL dst, rRegI src)
12052 %{
12053 match(Set dst (ConvI2L src));
12054
12055 ins_cost(125);
12056 format %{ "movslq $dst, $src\t# i2l" %}
12057 ins_encode %{
12058 __ movslq($dst$$Register, $src$$Register);
12059 %}
12060 ins_pipe(ialu_reg_reg);
12061 %}
12062
12063 // Zero-extend convert int to long
12064 instruct convI2L_reg_reg_zex(rRegL dst, rRegI src, immL_32bits mask)
12065 %{
12066 match(Set dst (AndL (ConvI2L src) mask));
12067
12068 format %{ "movl $dst, $src\t# i2l zero-extend\n\t" %}
12069 ins_encode %{
12070 if ($dst$$reg != $src$$reg) {
12071 __ movl($dst$$Register, $src$$Register);
12072 }
12073 %}
12074 ins_pipe(ialu_reg_reg);
12075 %}
12076
12077 // Zero-extend convert int to long
12078 instruct convI2L_reg_mem_zex(rRegL dst, memory src, immL_32bits mask)
12079 %{
12080 match(Set dst (AndL (ConvI2L (LoadI src)) mask));
12081
12082 format %{ "movl $dst, $src\t# i2l zero-extend\n\t" %}
12083 ins_encode %{
12084 __ movl($dst$$Register, $src$$Address);
12085 %}
12086 ins_pipe(ialu_reg_mem);
12087 %}
12088
12089 instruct zerox_long_reg_reg(rRegL dst, rRegL src, immL_32bits mask)
12090 %{
12091 match(Set dst (AndL src mask));
12092
12093 format %{ "movl $dst, $src\t# zero-extend long" %}
12094 ins_encode %{
12095 __ movl($dst$$Register, $src$$Register);
12096 %}
12097 ins_pipe(ialu_reg_reg);
12098 %}
12099
12100 instruct convL2I_reg_reg(rRegI dst, rRegL src)
12101 %{
12102 match(Set dst (ConvL2I src));
12103
12104 format %{ "movl $dst, $src\t# l2i" %}
12105 ins_encode %{
12106 __ movl($dst$$Register, $src$$Register);
12107 %}
12108 ins_pipe(ialu_reg_reg);
12109 %}
12110
12111
12112 instruct MoveF2I_stack_reg(rRegI dst, stackSlotF src) %{
12113 match(Set dst (MoveF2I src));
12114 effect(DEF dst, USE src);
12115
12116 ins_cost(125);
12117 format %{ "movl $dst, $src\t# MoveF2I_stack_reg" %}
12118 ins_encode %{
12119 __ movl($dst$$Register, Address(rsp, $src$$disp));
12120 %}
12121 ins_pipe(ialu_reg_mem);
12122 %}
12123
12124 instruct MoveI2F_stack_reg(regF dst, stackSlotI src) %{
12125 match(Set dst (MoveI2F src));
12126 effect(DEF dst, USE src);
12127
12128 ins_cost(125);
12129 format %{ "movss $dst, $src\t# MoveI2F_stack_reg" %}
12130 ins_encode %{
12131 __ movflt($dst$$XMMRegister, Address(rsp, $src$$disp));
12132 %}
12133 ins_pipe(pipe_slow);
12134 %}
12135
12136 instruct MoveD2L_stack_reg(rRegL dst, stackSlotD src) %{
12137 match(Set dst (MoveD2L src));
12138 effect(DEF dst, USE src);
12139
12140 ins_cost(125);
12141 format %{ "movq $dst, $src\t# MoveD2L_stack_reg" %}
12142 ins_encode %{
12143 __ movq($dst$$Register, Address(rsp, $src$$disp));
12144 %}
12145 ins_pipe(ialu_reg_mem);
12146 %}
12147
12148 instruct MoveL2D_stack_reg_partial(regD dst, stackSlotL src) %{
12149 predicate(!UseXmmLoadAndClearUpper);
12150 match(Set dst (MoveL2D src));
12151 effect(DEF dst, USE src);
12152
12153 ins_cost(125);
12154 format %{ "movlpd $dst, $src\t# MoveL2D_stack_reg" %}
12155 ins_encode %{
12156 __ movdbl($dst$$XMMRegister, Address(rsp, $src$$disp));
12157 %}
12158 ins_pipe(pipe_slow);
12159 %}
12160
12161 instruct MoveL2D_stack_reg(regD dst, stackSlotL src) %{
12162 predicate(UseXmmLoadAndClearUpper);
12163 match(Set dst (MoveL2D src));
12164 effect(DEF dst, USE src);
12165
12166 ins_cost(125);
12167 format %{ "movsd $dst, $src\t# MoveL2D_stack_reg" %}
12168 ins_encode %{
12169 __ movdbl($dst$$XMMRegister, Address(rsp, $src$$disp));
12170 %}
12171 ins_pipe(pipe_slow);
12172 %}
12173
12174
12175 instruct MoveF2I_reg_stack(stackSlotI dst, regF src) %{
12176 match(Set dst (MoveF2I src));
12177 effect(DEF dst, USE src);
12178
12179 ins_cost(95); // XXX
12180 format %{ "movss $dst, $src\t# MoveF2I_reg_stack" %}
12181 ins_encode %{
12182 __ movflt(Address(rsp, $dst$$disp), $src$$XMMRegister);
12183 %}
12184 ins_pipe(pipe_slow);
12185 %}
12186
12187 instruct MoveI2F_reg_stack(stackSlotF dst, rRegI src) %{
12188 match(Set dst (MoveI2F src));
12189 effect(DEF dst, USE src);
12190
12191 ins_cost(100);
12192 format %{ "movl $dst, $src\t# MoveI2F_reg_stack" %}
12193 ins_encode %{
12194 __ movl(Address(rsp, $dst$$disp), $src$$Register);
12195 %}
12196 ins_pipe( ialu_mem_reg );
12197 %}
12198
12199 instruct MoveD2L_reg_stack(stackSlotL dst, regD src) %{
12200 match(Set dst (MoveD2L src));
12201 effect(DEF dst, USE src);
12202
12203 ins_cost(95); // XXX
12204 format %{ "movsd $dst, $src\t# MoveL2D_reg_stack" %}
12205 ins_encode %{
12206 __ movdbl(Address(rsp, $dst$$disp), $src$$XMMRegister);
12207 %}
12208 ins_pipe(pipe_slow);
12209 %}
12210
12211 instruct MoveL2D_reg_stack(stackSlotD dst, rRegL src) %{
12212 match(Set dst (MoveL2D src));
12213 effect(DEF dst, USE src);
12214
12215 ins_cost(100);
12216 format %{ "movq $dst, $src\t# MoveL2D_reg_stack" %}
12217 ins_encode %{
12218 __ movq(Address(rsp, $dst$$disp), $src$$Register);
12219 %}
12220 ins_pipe(ialu_mem_reg);
12221 %}
12222
12223 instruct MoveF2I_reg_reg(rRegI dst, regF src) %{
12224 match(Set dst (MoveF2I src));
12225 effect(DEF dst, USE src);
12226 ins_cost(85);
12227 format %{ "movd $dst,$src\t# MoveF2I" %}
12228 ins_encode %{
12229 __ movdl($dst$$Register, $src$$XMMRegister);
12230 %}
12231 ins_pipe( pipe_slow );
12232 %}
12233
12234 instruct MoveD2L_reg_reg(rRegL dst, regD src) %{
12235 match(Set dst (MoveD2L src));
12236 effect(DEF dst, USE src);
12237 ins_cost(85);
12238 format %{ "movd $dst,$src\t# MoveD2L" %}
12239 ins_encode %{
12240 __ movdq($dst$$Register, $src$$XMMRegister);
12241 %}
12242 ins_pipe( pipe_slow );
12243 %}
12244
12245 instruct MoveI2F_reg_reg(regF dst, rRegI src) %{
12246 match(Set dst (MoveI2F src));
12247 effect(DEF dst, USE src);
12248 ins_cost(100);
12249 format %{ "movd $dst,$src\t# MoveI2F" %}
12250 ins_encode %{
12251 __ movdl($dst$$XMMRegister, $src$$Register);
12252 %}
12253 ins_pipe( pipe_slow );
12254 %}
12255
12256 instruct MoveL2D_reg_reg(regD dst, rRegL src) %{
12257 match(Set dst (MoveL2D src));
12258 effect(DEF dst, USE src);
12259 ins_cost(100);
12260 format %{ "movd $dst,$src\t# MoveL2D" %}
12261 ins_encode %{
12262 __ movdq($dst$$XMMRegister, $src$$Register);
12263 %}
12264 ins_pipe( pipe_slow );
12265 %}
12266
12267
12268 // Fast clearing of an array
12269 // Small non-constant lenght ClearArray for non-AVX512 targets.
12270 instruct rep_stos(rcx_RegL cnt, rdi_RegP base, regD tmp, rax_RegL val,
12271 Universe dummy, rFlagsReg cr)
12272 %{
12273 predicate(!((ClearArrayNode*)n)->is_large() && !((ClearArrayNode*)n)->word_copy_only() && (UseAVX <= 2));
12274 match(Set dummy (ClearArray (Binary cnt base) val));
12275 effect(USE_KILL cnt, USE_KILL base, TEMP tmp, USE_KILL val, KILL cr);
12276
12277 format %{ $$template
12278 $$emit$$"cmp InitArrayShortSize,rcx\n\t"
12279 $$emit$$"jg LARGE\n\t"
12280 $$emit$$"dec rcx\n\t"
12281 $$emit$$"js DONE\t# Zero length\n\t"
12282 $$emit$$"mov rax,(rdi,rcx,8)\t# LOOP\n\t"
12283 $$emit$$"dec rcx\n\t"
12284 $$emit$$"jge LOOP\n\t"
12285 $$emit$$"jmp DONE\n\t"
12286 $$emit$$"# LARGE:\n\t"
12287 if (UseFastStosb) {
12288 $$emit$$"shlq rcx,3\t# Convert doublewords to bytes\n\t"
12289 $$emit$$"rep stosb\t# Store rax to *rdi++ while rcx--\n\t"
12290 } else if (UseXMMForObjInit) {
12291 $$emit$$"movdq $tmp, $val\n\t"
12292 $$emit$$"punpcklqdq $tmp, $tmp\n\t"
12293 $$emit$$"vinserti128_high $tmp, $tmp\n\t"
12294 $$emit$$"jmpq L_zero_64_bytes\n\t"
12295 $$emit$$"# L_loop:\t# 64-byte LOOP\n\t"
12296 $$emit$$"vmovdqu $tmp,(rax)\n\t"
12297 $$emit$$"vmovdqu $tmp,0x20(rax)\n\t"
12298 $$emit$$"add 0x40,rax\n\t"
12299 $$emit$$"# L_zero_64_bytes:\n\t"
12300 $$emit$$"sub 0x8,rcx\n\t"
12301 $$emit$$"jge L_loop\n\t"
12302 $$emit$$"add 0x4,rcx\n\t"
12303 $$emit$$"jl L_tail\n\t"
12304 $$emit$$"vmovdqu $tmp,(rax)\n\t"
12305 $$emit$$"add 0x20,rax\n\t"
12306 $$emit$$"sub 0x4,rcx\n\t"
12307 $$emit$$"# L_tail:\t# Clearing tail bytes\n\t"
12308 $$emit$$"add 0x4,rcx\n\t"
12309 $$emit$$"jle L_end\n\t"
12310 $$emit$$"dec rcx\n\t"
12311 $$emit$$"# L_sloop:\t# 8-byte short loop\n\t"
12312 $$emit$$"vmovq xmm0,(rax)\n\t"
12313 $$emit$$"add 0x8,rax\n\t"
12314 $$emit$$"dec rcx\n\t"
12315 $$emit$$"jge L_sloop\n\t"
12316 $$emit$$"# L_end:\n\t"
12317 } else {
12318 $$emit$$"rep stosq\t# Store rax to *rdi++ while rcx--\n\t"
12319 }
12320 $$emit$$"# DONE"
12321 %}
12322 ins_encode %{
12323 __ clear_mem($base$$Register, $cnt$$Register, $val$$Register,
12324 $tmp$$XMMRegister, false, false);
12325 %}
12326 ins_pipe(pipe_slow);
12327 %}
12328
12329 instruct rep_stos_word_copy(rcx_RegL cnt, rdi_RegP base, regD tmp, rax_RegL val,
12330 Universe dummy, rFlagsReg cr)
12331 %{
12332 predicate(!((ClearArrayNode*)n)->is_large() && ((ClearArrayNode*)n)->word_copy_only() && (UseAVX <= 2));
12333 match(Set dummy (ClearArray (Binary cnt base) val));
12334 effect(USE_KILL cnt, USE_KILL base, TEMP tmp, USE_KILL val, KILL cr);
12335
12336 format %{ $$template
12337 $$emit$$"cmp InitArrayShortSize,rcx\n\t"
12338 $$emit$$"jg LARGE\n\t"
12339 $$emit$$"dec rcx\n\t"
12340 $$emit$$"js DONE\t# Zero length\n\t"
12341 $$emit$$"mov rax,(rdi,rcx,8)\t# LOOP\n\t"
12342 $$emit$$"dec rcx\n\t"
12343 $$emit$$"jge LOOP\n\t"
12344 $$emit$$"jmp DONE\n\t"
12345 $$emit$$"# LARGE:\n\t"
12346 if (UseXMMForObjInit) {
12347 $$emit$$"movdq $tmp, $val\n\t"
12348 $$emit$$"punpcklqdq $tmp, $tmp\n\t"
12349 $$emit$$"vinserti128_high $tmp, $tmp\n\t"
12350 $$emit$$"jmpq L_zero_64_bytes\n\t"
12351 $$emit$$"# L_loop:\t# 64-byte LOOP\n\t"
12352 $$emit$$"vmovdqu $tmp,(rax)\n\t"
12353 $$emit$$"vmovdqu $tmp,0x20(rax)\n\t"
12354 $$emit$$"add 0x40,rax\n\t"
12355 $$emit$$"# L_zero_64_bytes:\n\t"
12356 $$emit$$"sub 0x8,rcx\n\t"
12357 $$emit$$"jge L_loop\n\t"
12358 $$emit$$"add 0x4,rcx\n\t"
12359 $$emit$$"jl L_tail\n\t"
12360 $$emit$$"vmovdqu $tmp,(rax)\n\t"
12361 $$emit$$"add 0x20,rax\n\t"
12362 $$emit$$"sub 0x4,rcx\n\t"
12363 $$emit$$"# L_tail:\t# Clearing tail bytes\n\t"
12364 $$emit$$"add 0x4,rcx\n\t"
12365 $$emit$$"jle L_end\n\t"
12366 $$emit$$"dec rcx\n\t"
12367 $$emit$$"# L_sloop:\t# 8-byte short loop\n\t"
12368 $$emit$$"vmovq xmm0,(rax)\n\t"
12369 $$emit$$"add 0x8,rax\n\t"
12370 $$emit$$"dec rcx\n\t"
12371 $$emit$$"jge L_sloop\n\t"
12372 $$emit$$"# L_end:\n\t"
12373 } else {
12374 $$emit$$"rep stosq\t# Store rax to *rdi++ while rcx--\n\t"
12375 }
12376 $$emit$$"# DONE"
12377 %}
12378 ins_encode %{
12379 __ clear_mem($base$$Register, $cnt$$Register, $val$$Register,
12380 $tmp$$XMMRegister, false, true);
12381 %}
12382 ins_pipe(pipe_slow);
12383 %}
12384
12385 // Small non-constant length ClearArray for AVX512 targets.
12386 instruct rep_stos_evex(rcx_RegL cnt, rdi_RegP base, legRegD tmp, kReg ktmp, rax_RegL val,
12387 Universe dummy, rFlagsReg cr)
12388 %{
12389 predicate(!((ClearArrayNode*)n)->is_large() && !((ClearArrayNode*)n)->word_copy_only() && (UseAVX > 2));
12390 match(Set dummy (ClearArray (Binary cnt base) val));
12391 ins_cost(125);
12392 effect(USE_KILL cnt, USE_KILL base, TEMP tmp, TEMP ktmp, USE_KILL val, KILL cr);
12393
12394 format %{ $$template
12395 $$emit$$"xorq rax, rax\t# ClearArray:\n\t"
12396 $$emit$$"cmp InitArrayShortSize,rcx\n\t"
12397 $$emit$$"jg LARGE\n\t"
12398 $$emit$$"dec rcx\n\t"
12399 $$emit$$"js DONE\t# Zero length\n\t"
12400 $$emit$$"mov rax,(rdi,rcx,8)\t# LOOP\n\t"
12401 $$emit$$"dec rcx\n\t"
12402 $$emit$$"jge LOOP\n\t"
12403 $$emit$$"jmp DONE\n\t"
12404 $$emit$$"# LARGE:\n\t"
12405 if (UseFastStosb) {
12406 $$emit$$"shlq rcx,3\t# Convert doublewords to bytes\n\t"
12407 $$emit$$"rep stosb\t# Store rax to *rdi++ while rcx--\n\t"
12408 } else if (UseXMMForObjInit) {
12409 $$emit$$"mov rdi,rax\n\t"
12410 $$emit$$"vpxor ymm0,ymm0,ymm0\n\t"
12411 $$emit$$"jmpq L_zero_64_bytes\n\t"
12412 $$emit$$"# L_loop:\t# 64-byte LOOP\n\t"
12413 $$emit$$"vmovdqu ymm0,(rax)\n\t"
12414 $$emit$$"vmovdqu ymm0,0x20(rax)\n\t"
12415 $$emit$$"add 0x40,rax\n\t"
12416 $$emit$$"# L_zero_64_bytes:\n\t"
12417 $$emit$$"sub 0x8,rcx\n\t"
12418 $$emit$$"jge L_loop\n\t"
12419 $$emit$$"add 0x4,rcx\n\t"
12420 $$emit$$"jl L_tail\n\t"
12421 $$emit$$"vmovdqu ymm0,(rax)\n\t"
12422 $$emit$$"add 0x20,rax\n\t"
12423 $$emit$$"sub 0x4,rcx\n\t"
12424 $$emit$$"# L_tail:\t# Clearing tail bytes\n\t"
12425 $$emit$$"add 0x4,rcx\n\t"
12426 $$emit$$"jle L_end\n\t"
12427 $$emit$$"dec rcx\n\t"
12428 $$emit$$"# L_sloop:\t# 8-byte short loop\n\t"
12429 $$emit$$"vmovq xmm0,(rax)\n\t"
12430 $$emit$$"add 0x8,rax\n\t"
12431 $$emit$$"dec rcx\n\t"
12432 $$emit$$"jge L_sloop\n\t"
12433 $$emit$$"# L_end:\n\t"
12434 } else {
12435 $$emit$$"rep stosq\t# Store rax to *rdi++ while rcx--\n\t"
12436 }
12437 $$emit$$"# DONE"
12438 %}
12439 ins_encode %{
12440 __ clear_mem($base$$Register, $cnt$$Register, $val$$Register,
12441 $tmp$$XMMRegister, false, false, $ktmp$$KRegister);
12442 %}
12443 ins_pipe(pipe_slow);
12444 %}
12445
12446 instruct rep_stos_evex_word_copy(rcx_RegL cnt, rdi_RegP base, legRegD tmp, kReg ktmp, rax_RegL val,
12447 Universe dummy, rFlagsReg cr)
12448 %{
12449 predicate(!((ClearArrayNode*)n)->is_large() && ((ClearArrayNode*)n)->word_copy_only() && (UseAVX > 2));
12450 match(Set dummy (ClearArray (Binary cnt base) val));
12451 ins_cost(125);
12452 effect(USE_KILL cnt, USE_KILL base, TEMP tmp, TEMP ktmp, USE_KILL val, KILL cr);
12453
12454 format %{ $$template
12455 $$emit$$"xorq rax, rax\t# ClearArray:\n\t"
12456 $$emit$$"cmp InitArrayShortSize,rcx\n\t"
12457 $$emit$$"jg LARGE\n\t"
12458 $$emit$$"dec rcx\n\t"
12459 $$emit$$"js DONE\t# Zero length\n\t"
12460 $$emit$$"mov rax,(rdi,rcx,8)\t# LOOP\n\t"
12461 $$emit$$"dec rcx\n\t"
12462 $$emit$$"jge LOOP\n\t"
12463 $$emit$$"jmp DONE\n\t"
12464 $$emit$$"# LARGE:\n\t"
12465 if (UseFastStosb) {
12466 $$emit$$"shlq rcx,3\t# Convert doublewords to bytes\n\t"
12467 $$emit$$"rep stosb\t# Store rax to *rdi++ while rcx--\n\t"
12468 } else if (UseXMMForObjInit) {
12469 $$emit$$"mov rdi,rax\n\t"
12470 $$emit$$"vpxor ymm0,ymm0,ymm0\n\t"
12471 $$emit$$"jmpq L_zero_64_bytes\n\t"
12472 $$emit$$"# L_loop:\t# 64-byte LOOP\n\t"
12473 $$emit$$"vmovdqu ymm0,(rax)\n\t"
12474 $$emit$$"vmovdqu ymm0,0x20(rax)\n\t"
12475 $$emit$$"add 0x40,rax\n\t"
12476 $$emit$$"# L_zero_64_bytes:\n\t"
12477 $$emit$$"sub 0x8,rcx\n\t"
12478 $$emit$$"jge L_loop\n\t"
12479 $$emit$$"add 0x4,rcx\n\t"
12480 $$emit$$"jl L_tail\n\t"
12481 $$emit$$"vmovdqu ymm0,(rax)\n\t"
12482 $$emit$$"add 0x20,rax\n\t"
12483 $$emit$$"sub 0x4,rcx\n\t"
12484 $$emit$$"# L_tail:\t# Clearing tail bytes\n\t"
12485 $$emit$$"add 0x4,rcx\n\t"
12486 $$emit$$"jle L_end\n\t"
12487 $$emit$$"dec rcx\n\t"
12488 $$emit$$"# L_sloop:\t# 8-byte short loop\n\t"
12489 $$emit$$"vmovq xmm0,(rax)\n\t"
12490 $$emit$$"add 0x8,rax\n\t"
12491 $$emit$$"dec rcx\n\t"
12492 $$emit$$"jge L_sloop\n\t"
12493 $$emit$$"# L_end:\n\t"
12494 } else {
12495 $$emit$$"rep stosq\t# Store rax to *rdi++ while rcx--\n\t"
12496 }
12497 $$emit$$"# DONE"
12498 %}
12499 ins_encode %{
12500 __ clear_mem($base$$Register, $cnt$$Register, $val$$Register,
12501 $tmp$$XMMRegister, false, true, $ktmp$$KRegister);
12502 %}
12503 ins_pipe(pipe_slow);
12504 %}
12505
12506 // Large non-constant length ClearArray for non-AVX512 targets.
12507 instruct rep_stos_large(rcx_RegL cnt, rdi_RegP base, regD tmp, rax_RegL val,
12508 Universe dummy, rFlagsReg cr)
12509 %{
12510 predicate(((ClearArrayNode*)n)->is_large() && !((ClearArrayNode*)n)->word_copy_only() && (UseAVX <= 2));
12511 match(Set dummy (ClearArray (Binary cnt base) val));
12512 effect(USE_KILL cnt, USE_KILL base, TEMP tmp, USE_KILL val, KILL cr);
12513
12514 format %{ $$template
12515 if (UseFastStosb) {
12516 $$emit$$"shlq rcx,3\t# Convert doublewords to bytes\n\t"
12517 $$emit$$"rep stosb\t# Store rax to *rdi++ while rcx--"
12518 } else if (UseXMMForObjInit) {
12519 $$emit$$"movdq $tmp, $val\n\t"
12520 $$emit$$"punpcklqdq $tmp, $tmp\n\t"
12521 $$emit$$"vinserti128_high $tmp, $tmp\n\t"
12522 $$emit$$"jmpq L_zero_64_bytes\n\t"
12523 $$emit$$"# L_loop:\t# 64-byte LOOP\n\t"
12524 $$emit$$"vmovdqu $tmp,(rax)\n\t"
12525 $$emit$$"vmovdqu $tmp,0x20(rax)\n\t"
12526 $$emit$$"add 0x40,rax\n\t"
12527 $$emit$$"# L_zero_64_bytes:\n\t"
12528 $$emit$$"sub 0x8,rcx\n\t"
12529 $$emit$$"jge L_loop\n\t"
12530 $$emit$$"add 0x4,rcx\n\t"
12531 $$emit$$"jl L_tail\n\t"
12532 $$emit$$"vmovdqu $tmp,(rax)\n\t"
12533 $$emit$$"add 0x20,rax\n\t"
12534 $$emit$$"sub 0x4,rcx\n\t"
12535 $$emit$$"# L_tail:\t# Clearing tail bytes\n\t"
12536 $$emit$$"add 0x4,rcx\n\t"
12537 $$emit$$"jle L_end\n\t"
12538 $$emit$$"dec rcx\n\t"
12539 $$emit$$"# L_sloop:\t# 8-byte short loop\n\t"
12540 $$emit$$"vmovq xmm0,(rax)\n\t"
12541 $$emit$$"add 0x8,rax\n\t"
12542 $$emit$$"dec rcx\n\t"
12543 $$emit$$"jge L_sloop\n\t"
12544 $$emit$$"# L_end:\n\t"
12545 } else {
12546 $$emit$$"rep stosq\t# Store rax to *rdi++ while rcx--"
12547 }
12548 %}
12549 ins_encode %{
12550 __ clear_mem($base$$Register, $cnt$$Register, $val$$Register,
12551 $tmp$$XMMRegister, true, false);
12552 %}
12553 ins_pipe(pipe_slow);
12554 %}
12555
12556 instruct rep_stos_large_word_copy(rcx_RegL cnt, rdi_RegP base, regD tmp, rax_RegL val,
12557 Universe dummy, rFlagsReg cr)
12558 %{
12559 predicate(((ClearArrayNode*)n)->is_large() && ((ClearArrayNode*)n)->word_copy_only() && (UseAVX <= 2));
12560 match(Set dummy (ClearArray (Binary cnt base) val));
12561 effect(USE_KILL cnt, USE_KILL base, TEMP tmp, USE_KILL val, KILL cr);
12562
12563 format %{ $$template
12564 if (UseXMMForObjInit) {
12565 $$emit$$"movdq $tmp, $val\n\t"
12566 $$emit$$"punpcklqdq $tmp, $tmp\n\t"
12567 $$emit$$"vinserti128_high $tmp, $tmp\n\t"
12568 $$emit$$"jmpq L_zero_64_bytes\n\t"
12569 $$emit$$"# L_loop:\t# 64-byte LOOP\n\t"
12570 $$emit$$"vmovdqu $tmp,(rax)\n\t"
12571 $$emit$$"vmovdqu $tmp,0x20(rax)\n\t"
12572 $$emit$$"add 0x40,rax\n\t"
12573 $$emit$$"# L_zero_64_bytes:\n\t"
12574 $$emit$$"sub 0x8,rcx\n\t"
12575 $$emit$$"jge L_loop\n\t"
12576 $$emit$$"add 0x4,rcx\n\t"
12577 $$emit$$"jl L_tail\n\t"
12578 $$emit$$"vmovdqu $tmp,(rax)\n\t"
12579 $$emit$$"add 0x20,rax\n\t"
12580 $$emit$$"sub 0x4,rcx\n\t"
12581 $$emit$$"# L_tail:\t# Clearing tail bytes\n\t"
12582 $$emit$$"add 0x4,rcx\n\t"
12583 $$emit$$"jle L_end\n\t"
12584 $$emit$$"dec rcx\n\t"
12585 $$emit$$"# L_sloop:\t# 8-byte short loop\n\t"
12586 $$emit$$"vmovq xmm0,(rax)\n\t"
12587 $$emit$$"add 0x8,rax\n\t"
12588 $$emit$$"dec rcx\n\t"
12589 $$emit$$"jge L_sloop\n\t"
12590 $$emit$$"# L_end:\n\t"
12591 } else {
12592 $$emit$$"rep stosq\t# Store rax to *rdi++ while rcx--"
12593 }
12594 %}
12595 ins_encode %{
12596 __ clear_mem($base$$Register, $cnt$$Register, $val$$Register,
12597 $tmp$$XMMRegister, true, true);
12598 %}
12599 ins_pipe(pipe_slow);
12600 %}
12601
12602 // Large non-constant length ClearArray for AVX512 targets.
12603 instruct rep_stos_large_evex(rcx_RegL cnt, rdi_RegP base, legRegD tmp, kReg ktmp, rax_RegL val,
12604 Universe dummy, rFlagsReg cr)
12605 %{
12606 predicate(((ClearArrayNode*)n)->is_large() && !((ClearArrayNode*)n)->word_copy_only() && (UseAVX > 2));
12607 match(Set dummy (ClearArray (Binary cnt base) val));
12608 effect(USE_KILL cnt, USE_KILL base, TEMP tmp, TEMP ktmp, USE_KILL val, KILL cr);
12609
12610 format %{ $$template
12611 if (UseFastStosb) {
12612 $$emit$$"xorq rax, rax\t# ClearArray:\n\t"
12613 $$emit$$"shlq rcx,3\t# Convert doublewords to bytes\n\t"
12614 $$emit$$"rep stosb\t# Store rax to *rdi++ while rcx--"
12615 } else if (UseXMMForObjInit) {
12616 $$emit$$"mov rdi,rax\t# ClearArray:\n\t"
12617 $$emit$$"vpxor ymm0,ymm0,ymm0\n\t"
12618 $$emit$$"jmpq L_zero_64_bytes\n\t"
12619 $$emit$$"# L_loop:\t# 64-byte LOOP\n\t"
12620 $$emit$$"vmovdqu ymm0,(rax)\n\t"
12621 $$emit$$"vmovdqu ymm0,0x20(rax)\n\t"
12622 $$emit$$"add 0x40,rax\n\t"
12623 $$emit$$"# L_zero_64_bytes:\n\t"
12624 $$emit$$"sub 0x8,rcx\n\t"
12625 $$emit$$"jge L_loop\n\t"
12626 $$emit$$"add 0x4,rcx\n\t"
12627 $$emit$$"jl L_tail\n\t"
12628 $$emit$$"vmovdqu ymm0,(rax)\n\t"
12629 $$emit$$"add 0x20,rax\n\t"
12630 $$emit$$"sub 0x4,rcx\n\t"
12631 $$emit$$"# L_tail:\t# Clearing tail bytes\n\t"
12632 $$emit$$"add 0x4,rcx\n\t"
12633 $$emit$$"jle L_end\n\t"
12634 $$emit$$"dec rcx\n\t"
12635 $$emit$$"# L_sloop:\t# 8-byte short loop\n\t"
12636 $$emit$$"vmovq xmm0,(rax)\n\t"
12637 $$emit$$"add 0x8,rax\n\t"
12638 $$emit$$"dec rcx\n\t"
12639 $$emit$$"jge L_sloop\n\t"
12640 $$emit$$"# L_end:\n\t"
12641 } else {
12642 $$emit$$"xorq rax, rax\t# ClearArray:\n\t"
12643 $$emit$$"rep stosq\t# Store rax to *rdi++ while rcx--"
12644 }
12645 %}
12646 ins_encode %{
12647 __ clear_mem($base$$Register, $cnt$$Register, $val$$Register,
12648 $tmp$$XMMRegister, true, false, $ktmp$$KRegister);
12649 %}
12650 ins_pipe(pipe_slow);
12651 %}
12652
12653 instruct rep_stos_large_evex_word_copy(rcx_RegL cnt, rdi_RegP base, legRegD tmp, kReg ktmp, rax_RegL val,
12654 Universe dummy, rFlagsReg cr)
12655 %{
12656 predicate(((ClearArrayNode*)n)->is_large() && ((ClearArrayNode*)n)->word_copy_only() && (UseAVX > 2));
12657 match(Set dummy (ClearArray (Binary cnt base) val));
12658 effect(USE_KILL cnt, USE_KILL base, TEMP tmp, TEMP ktmp, USE_KILL val, KILL cr);
12659
12660 format %{ $$template
12661 if (UseFastStosb) {
12662 $$emit$$"xorq rax, rax\t# ClearArray:\n\t"
12663 $$emit$$"shlq rcx,3\t# Convert doublewords to bytes\n\t"
12664 $$emit$$"rep stosb\t# Store rax to *rdi++ while rcx--"
12665 } else if (UseXMMForObjInit) {
12666 $$emit$$"mov rdi,rax\t# ClearArray:\n\t"
12667 $$emit$$"vpxor ymm0,ymm0,ymm0\n\t"
12668 $$emit$$"jmpq L_zero_64_bytes\n\t"
12669 $$emit$$"# L_loop:\t# 64-byte LOOP\n\t"
12670 $$emit$$"vmovdqu ymm0,(rax)\n\t"
12671 $$emit$$"vmovdqu ymm0,0x20(rax)\n\t"
12672 $$emit$$"add 0x40,rax\n\t"
12673 $$emit$$"# L_zero_64_bytes:\n\t"
12674 $$emit$$"sub 0x8,rcx\n\t"
12675 $$emit$$"jge L_loop\n\t"
12676 $$emit$$"add 0x4,rcx\n\t"
12677 $$emit$$"jl L_tail\n\t"
12678 $$emit$$"vmovdqu ymm0,(rax)\n\t"
12679 $$emit$$"add 0x20,rax\n\t"
12680 $$emit$$"sub 0x4,rcx\n\t"
12681 $$emit$$"# L_tail:\t# Clearing tail bytes\n\t"
12682 $$emit$$"add 0x4,rcx\n\t"
12683 $$emit$$"jle L_end\n\t"
12684 $$emit$$"dec rcx\n\t"
12685 $$emit$$"# L_sloop:\t# 8-byte short loop\n\t"
12686 $$emit$$"vmovq xmm0,(rax)\n\t"
12687 $$emit$$"add 0x8,rax\n\t"
12688 $$emit$$"dec rcx\n\t"
12689 $$emit$$"jge L_sloop\n\t"
12690 $$emit$$"# L_end:\n\t"
12691 } else {
12692 $$emit$$"xorq rax, rax\t# ClearArray:\n\t"
12693 $$emit$$"rep stosq\t# Store rax to *rdi++ while rcx--"
12694 }
12695 %}
12696 ins_encode %{
12697 __ clear_mem($base$$Register, $cnt$$Register, $val$$Register,
12698 $tmp$$XMMRegister, true, true, $ktmp$$KRegister);
12699 %}
12700 ins_pipe(pipe_slow);
12701 %}
12702
12703 // Small constant length ClearArray for AVX512 targets.
12704 instruct rep_stos_im(immL cnt, rRegP base, regD tmp, rax_RegL val, kReg ktmp, Universe dummy, rFlagsReg cr)
12705 %{
12706 predicate(!((ClearArrayNode*)n)->is_large() && !((ClearArrayNode*)n)->word_copy_only() &&
12707 ((MaxVectorSize >= 32) && VM_Version::supports_avx512vl()));
12708 match(Set dummy (ClearArray (Binary cnt base) val));
12709 ins_cost(100);
12710 effect(TEMP tmp, USE_KILL val, TEMP ktmp, KILL cr);
12711 format %{ "clear_mem_imm $base , $cnt \n\t" %}
12712 ins_encode %{
12713 __ clear_mem($base$$Register, $cnt$$constant, $val$$Register, $tmp$$XMMRegister, $ktmp$$KRegister);
12714 %}
12715 ins_pipe(pipe_slow);
12716 %}
12717
12718 instruct string_compareL(rdi_RegP str1, rcx_RegI cnt1, rsi_RegP str2, rdx_RegI cnt2,
12719 rax_RegI result, legRegD tmp1, rFlagsReg cr)
12720 %{
12721 predicate(!VM_Version::supports_avx512vlbw() && ((StrCompNode*)n)->encoding() == StrIntrinsicNode::LL);
12722 match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
12723 effect(TEMP tmp1, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr);
12724
12725 format %{ "String Compare byte[] $str1,$cnt1,$str2,$cnt2 -> $result // KILL $tmp1" %}
12726 ins_encode %{
12727 __ string_compare($str1$$Register, $str2$$Register,
12728 $cnt1$$Register, $cnt2$$Register, $result$$Register,
12729 $tmp1$$XMMRegister, StrIntrinsicNode::LL, knoreg);
12730 %}
12731 ins_pipe( pipe_slow );
12732 %}
12733
12734 instruct string_compareL_evex(rdi_RegP str1, rcx_RegI cnt1, rsi_RegP str2, rdx_RegI cnt2,
12735 rax_RegI result, legRegD tmp1, kReg ktmp, rFlagsReg cr)
12736 %{
12737 predicate(VM_Version::supports_avx512vlbw() && ((StrCompNode*)n)->encoding() == StrIntrinsicNode::LL);
12738 match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
12739 effect(TEMP tmp1, TEMP ktmp, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr);
12740
12741 format %{ "String Compare byte[] $str1,$cnt1,$str2,$cnt2 -> $result // KILL $tmp1" %}
12742 ins_encode %{
12743 __ string_compare($str1$$Register, $str2$$Register,
12744 $cnt1$$Register, $cnt2$$Register, $result$$Register,
12745 $tmp1$$XMMRegister, StrIntrinsicNode::LL, $ktmp$$KRegister);
12746 %}
12747 ins_pipe( pipe_slow );
12748 %}
12749
12750 instruct string_compareU(rdi_RegP str1, rcx_RegI cnt1, rsi_RegP str2, rdx_RegI cnt2,
12751 rax_RegI result, legRegD tmp1, rFlagsReg cr)
12752 %{
12753 predicate(!VM_Version::supports_avx512vlbw() && ((StrCompNode*)n)->encoding() == StrIntrinsicNode::UU);
12754 match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
12755 effect(TEMP tmp1, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr);
12756
12757 format %{ "String Compare char[] $str1,$cnt1,$str2,$cnt2 -> $result // KILL $tmp1" %}
12758 ins_encode %{
12759 __ string_compare($str1$$Register, $str2$$Register,
12760 $cnt1$$Register, $cnt2$$Register, $result$$Register,
12761 $tmp1$$XMMRegister, StrIntrinsicNode::UU, knoreg);
12762 %}
12763 ins_pipe( pipe_slow );
12764 %}
12765
12766 instruct string_compareU_evex(rdi_RegP str1, rcx_RegI cnt1, rsi_RegP str2, rdx_RegI cnt2,
12767 rax_RegI result, legRegD tmp1, kReg ktmp, rFlagsReg cr)
12768 %{
12769 predicate(VM_Version::supports_avx512vlbw() && ((StrCompNode*)n)->encoding() == StrIntrinsicNode::UU);
12770 match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
12771 effect(TEMP tmp1, TEMP ktmp, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr);
12772
12773 format %{ "String Compare char[] $str1,$cnt1,$str2,$cnt2 -> $result // KILL $tmp1" %}
12774 ins_encode %{
12775 __ string_compare($str1$$Register, $str2$$Register,
12776 $cnt1$$Register, $cnt2$$Register, $result$$Register,
12777 $tmp1$$XMMRegister, StrIntrinsicNode::UU, $ktmp$$KRegister);
12778 %}
12779 ins_pipe( pipe_slow );
12780 %}
12781
12782 instruct string_compareLU(rdi_RegP str1, rcx_RegI cnt1, rsi_RegP str2, rdx_RegI cnt2,
12783 rax_RegI result, legRegD tmp1, rFlagsReg cr)
12784 %{
12785 predicate(!VM_Version::supports_avx512vlbw() && ((StrCompNode*)n)->encoding() == StrIntrinsicNode::LU);
12786 match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
12787 effect(TEMP tmp1, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr);
12788
12789 format %{ "String Compare byte[] $str1,$cnt1,$str2,$cnt2 -> $result // KILL $tmp1" %}
12790 ins_encode %{
12791 __ string_compare($str1$$Register, $str2$$Register,
12792 $cnt1$$Register, $cnt2$$Register, $result$$Register,
12793 $tmp1$$XMMRegister, StrIntrinsicNode::LU, knoreg);
12794 %}
12795 ins_pipe( pipe_slow );
12796 %}
12797
12798 instruct string_compareLU_evex(rdi_RegP str1, rcx_RegI cnt1, rsi_RegP str2, rdx_RegI cnt2,
12799 rax_RegI result, legRegD tmp1, kReg ktmp, rFlagsReg cr)
12800 %{
12801 predicate(VM_Version::supports_avx512vlbw() && ((StrCompNode*)n)->encoding() == StrIntrinsicNode::LU);
12802 match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
12803 effect(TEMP tmp1, TEMP ktmp, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr);
12804
12805 format %{ "String Compare byte[] $str1,$cnt1,$str2,$cnt2 -> $result // KILL $tmp1" %}
12806 ins_encode %{
12807 __ string_compare($str1$$Register, $str2$$Register,
12808 $cnt1$$Register, $cnt2$$Register, $result$$Register,
12809 $tmp1$$XMMRegister, StrIntrinsicNode::LU, $ktmp$$KRegister);
12810 %}
12811 ins_pipe( pipe_slow );
12812 %}
12813
12814 instruct string_compareUL(rsi_RegP str1, rdx_RegI cnt1, rdi_RegP str2, rcx_RegI cnt2,
12815 rax_RegI result, legRegD tmp1, rFlagsReg cr)
12816 %{
12817 predicate(!VM_Version::supports_avx512vlbw() && ((StrCompNode*)n)->encoding() == StrIntrinsicNode::UL);
12818 match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
12819 effect(TEMP tmp1, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr);
12820
12821 format %{ "String Compare byte[] $str1,$cnt1,$str2,$cnt2 -> $result // KILL $tmp1" %}
12822 ins_encode %{
12823 __ string_compare($str2$$Register, $str1$$Register,
12824 $cnt2$$Register, $cnt1$$Register, $result$$Register,
12825 $tmp1$$XMMRegister, StrIntrinsicNode::UL, knoreg);
12826 %}
12827 ins_pipe( pipe_slow );
12828 %}
12829
12830 instruct string_compareUL_evex(rsi_RegP str1, rdx_RegI cnt1, rdi_RegP str2, rcx_RegI cnt2,
12831 rax_RegI result, legRegD tmp1, kReg ktmp, rFlagsReg cr)
12832 %{
12833 predicate(VM_Version::supports_avx512vlbw() && ((StrCompNode*)n)->encoding() == StrIntrinsicNode::UL);
12834 match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
12835 effect(TEMP tmp1, TEMP ktmp, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr);
12836
12837 format %{ "String Compare byte[] $str1,$cnt1,$str2,$cnt2 -> $result // KILL $tmp1" %}
12838 ins_encode %{
12839 __ string_compare($str2$$Register, $str1$$Register,
12840 $cnt2$$Register, $cnt1$$Register, $result$$Register,
12841 $tmp1$$XMMRegister, StrIntrinsicNode::UL, $ktmp$$KRegister);
12842 %}
12843 ins_pipe( pipe_slow );
12844 %}
12845
12846 // fast search of substring with known size.
12847 instruct string_indexof_conL(rdi_RegP str1, rdx_RegI cnt1, rsi_RegP str2, immI int_cnt2,
12848 rbx_RegI result, legRegD tmp_vec, rax_RegI cnt2, rcx_RegI tmp, rFlagsReg cr)
12849 %{
12850 predicate(UseSSE42Intrinsics && (((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::LL));
12851 match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 int_cnt2)));
12852 effect(TEMP tmp_vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, KILL cnt2, KILL tmp, KILL cr);
12853
12854 format %{ "String IndexOf byte[] $str1,$cnt1,$str2,$int_cnt2 -> $result // KILL $tmp_vec, $cnt1, $cnt2, $tmp" %}
12855 ins_encode %{
12856 int icnt2 = (int)$int_cnt2$$constant;
12857 if (icnt2 >= 16) {
12858 // IndexOf for constant substrings with size >= 16 elements
12859 // which don't need to be loaded through stack.
12860 __ string_indexofC8($str1$$Register, $str2$$Register,
12861 $cnt1$$Register, $cnt2$$Register,
12862 icnt2, $result$$Register,
12863 $tmp_vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::LL);
12864 } else {
12865 // Small strings are loaded through stack if they cross page boundary.
12866 __ string_indexof($str1$$Register, $str2$$Register,
12867 $cnt1$$Register, $cnt2$$Register,
12868 icnt2, $result$$Register,
12869 $tmp_vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::LL);
12870 }
12871 %}
12872 ins_pipe( pipe_slow );
12873 %}
12874
12875 // fast search of substring with known size.
12876 instruct string_indexof_conU(rdi_RegP str1, rdx_RegI cnt1, rsi_RegP str2, immI int_cnt2,
12877 rbx_RegI result, legRegD tmp_vec, rax_RegI cnt2, rcx_RegI tmp, rFlagsReg cr)
12878 %{
12879 predicate(UseSSE42Intrinsics && (((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UU));
12880 match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 int_cnt2)));
12881 effect(TEMP tmp_vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, KILL cnt2, KILL tmp, KILL cr);
12882
12883 format %{ "String IndexOf char[] $str1,$cnt1,$str2,$int_cnt2 -> $result // KILL $tmp_vec, $cnt1, $cnt2, $tmp" %}
12884 ins_encode %{
12885 int icnt2 = (int)$int_cnt2$$constant;
12886 if (icnt2 >= 8) {
12887 // IndexOf for constant substrings with size >= 8 elements
12888 // which don't need to be loaded through stack.
12889 __ string_indexofC8($str1$$Register, $str2$$Register,
12890 $cnt1$$Register, $cnt2$$Register,
12891 icnt2, $result$$Register,
12892 $tmp_vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UU);
12893 } else {
12894 // Small strings are loaded through stack if they cross page boundary.
12895 __ string_indexof($str1$$Register, $str2$$Register,
12896 $cnt1$$Register, $cnt2$$Register,
12897 icnt2, $result$$Register,
12898 $tmp_vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UU);
12899 }
12900 %}
12901 ins_pipe( pipe_slow );
12902 %}
12903
12904 // fast search of substring with known size.
12905 instruct string_indexof_conUL(rdi_RegP str1, rdx_RegI cnt1, rsi_RegP str2, immI int_cnt2,
12906 rbx_RegI result, legRegD tmp_vec, rax_RegI cnt2, rcx_RegI tmp, rFlagsReg cr)
12907 %{
12908 predicate(UseSSE42Intrinsics && (((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UL));
12909 match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 int_cnt2)));
12910 effect(TEMP tmp_vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, KILL cnt2, KILL tmp, KILL cr);
12911
12912 format %{ "String IndexOf char[] $str1,$cnt1,$str2,$int_cnt2 -> $result // KILL $tmp_vec, $cnt1, $cnt2, $tmp" %}
12913 ins_encode %{
12914 int icnt2 = (int)$int_cnt2$$constant;
12915 if (icnt2 >= 8) {
12916 // IndexOf for constant substrings with size >= 8 elements
12917 // which don't need to be loaded through stack.
12918 __ string_indexofC8($str1$$Register, $str2$$Register,
12919 $cnt1$$Register, $cnt2$$Register,
12920 icnt2, $result$$Register,
12921 $tmp_vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UL);
12922 } else {
12923 // Small strings are loaded through stack if they cross page boundary.
12924 __ string_indexof($str1$$Register, $str2$$Register,
12925 $cnt1$$Register, $cnt2$$Register,
12926 icnt2, $result$$Register,
12927 $tmp_vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UL);
12928 }
12929 %}
12930 ins_pipe( pipe_slow );
12931 %}
12932
12933 instruct string_indexofL(rdi_RegP str1, rdx_RegI cnt1, rsi_RegP str2, rax_RegI cnt2,
12934 rbx_RegI result, legRegD tmp_vec, rcx_RegI tmp, rFlagsReg cr)
12935 %{
12936 predicate(UseSSE42Intrinsics && (((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::LL));
12937 match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 cnt2)));
12938 effect(TEMP tmp_vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL tmp, KILL cr);
12939
12940 format %{ "String IndexOf byte[] $str1,$cnt1,$str2,$cnt2 -> $result // KILL all" %}
12941 ins_encode %{
12942 __ string_indexof($str1$$Register, $str2$$Register,
12943 $cnt1$$Register, $cnt2$$Register,
12944 (-1), $result$$Register,
12945 $tmp_vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::LL);
12946 %}
12947 ins_pipe( pipe_slow );
12948 %}
12949
12950 instruct string_indexofU(rdi_RegP str1, rdx_RegI cnt1, rsi_RegP str2, rax_RegI cnt2,
12951 rbx_RegI result, legRegD tmp_vec, rcx_RegI tmp, rFlagsReg cr)
12952 %{
12953 predicate(UseSSE42Intrinsics && (((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UU));
12954 match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 cnt2)));
12955 effect(TEMP tmp_vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL tmp, KILL cr);
12956
12957 format %{ "String IndexOf char[] $str1,$cnt1,$str2,$cnt2 -> $result // KILL all" %}
12958 ins_encode %{
12959 __ string_indexof($str1$$Register, $str2$$Register,
12960 $cnt1$$Register, $cnt2$$Register,
12961 (-1), $result$$Register,
12962 $tmp_vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UU);
12963 %}
12964 ins_pipe( pipe_slow );
12965 %}
12966
12967 instruct string_indexofUL(rdi_RegP str1, rdx_RegI cnt1, rsi_RegP str2, rax_RegI cnt2,
12968 rbx_RegI result, legRegD tmp_vec, rcx_RegI tmp, rFlagsReg cr)
12969 %{
12970 predicate(UseSSE42Intrinsics && (((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UL));
12971 match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 cnt2)));
12972 effect(TEMP tmp_vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL tmp, KILL cr);
12973
12974 format %{ "String IndexOf char[] $str1,$cnt1,$str2,$cnt2 -> $result // KILL all" %}
12975 ins_encode %{
12976 __ string_indexof($str1$$Register, $str2$$Register,
12977 $cnt1$$Register, $cnt2$$Register,
12978 (-1), $result$$Register,
12979 $tmp_vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UL);
12980 %}
12981 ins_pipe( pipe_slow );
12982 %}
12983
12984 instruct string_indexof_char(rdi_RegP str1, rdx_RegI cnt1, rax_RegI ch,
12985 rbx_RegI result, legRegD tmp_vec1, legRegD tmp_vec2, legRegD tmp_vec3, rcx_RegI tmp, rFlagsReg cr)
12986 %{
12987 predicate(UseSSE42Intrinsics && (((StrIndexOfCharNode*)n)->encoding() == StrIntrinsicNode::U));
12988 match(Set result (StrIndexOfChar (Binary str1 cnt1) ch));
12989 effect(TEMP tmp_vec1, TEMP tmp_vec2, TEMP tmp_vec3, USE_KILL str1, USE_KILL cnt1, USE_KILL ch, TEMP tmp, KILL cr);
12990 format %{ "StringUTF16 IndexOf char[] $str1,$cnt1,$ch -> $result // KILL all" %}
12991 ins_encode %{
12992 __ string_indexof_char($str1$$Register, $cnt1$$Register, $ch$$Register, $result$$Register,
12993 $tmp_vec1$$XMMRegister, $tmp_vec2$$XMMRegister, $tmp_vec3$$XMMRegister, $tmp$$Register);
12994 %}
12995 ins_pipe( pipe_slow );
12996 %}
12997
12998 instruct stringL_indexof_char(rdi_RegP str1, rdx_RegI cnt1, rax_RegI ch,
12999 rbx_RegI result, legRegD tmp_vec1, legRegD tmp_vec2, legRegD tmp_vec3, rcx_RegI tmp, rFlagsReg cr)
13000 %{
13001 predicate(UseSSE42Intrinsics && (((StrIndexOfCharNode*)n)->encoding() == StrIntrinsicNode::L));
13002 match(Set result (StrIndexOfChar (Binary str1 cnt1) ch));
13003 effect(TEMP tmp_vec1, TEMP tmp_vec2, TEMP tmp_vec3, USE_KILL str1, USE_KILL cnt1, USE_KILL ch, TEMP tmp, KILL cr);
13004 format %{ "StringLatin1 IndexOf char[] $str1,$cnt1,$ch -> $result // KILL all" %}
13005 ins_encode %{
13006 __ stringL_indexof_char($str1$$Register, $cnt1$$Register, $ch$$Register, $result$$Register,
13007 $tmp_vec1$$XMMRegister, $tmp_vec2$$XMMRegister, $tmp_vec3$$XMMRegister, $tmp$$Register);
13008 %}
13009 ins_pipe( pipe_slow );
13010 %}
13011
13012 // fast string equals
13013 instruct string_equals(rdi_RegP str1, rsi_RegP str2, rcx_RegI cnt, rax_RegI result,
13014 legRegD tmp1, legRegD tmp2, rbx_RegI tmp3, rFlagsReg cr)
13015 %{
13016 predicate(!VM_Version::supports_avx512vlbw());
13017 match(Set result (StrEquals (Binary str1 str2) cnt));
13018 effect(TEMP tmp1, TEMP tmp2, USE_KILL str1, USE_KILL str2, USE_KILL cnt, KILL tmp3, KILL cr);
13019
13020 format %{ "String Equals $str1,$str2,$cnt -> $result // KILL $tmp1, $tmp2, $tmp3" %}
13021 ins_encode %{
13022 __ arrays_equals(false, $str1$$Register, $str2$$Register,
13023 $cnt$$Register, $result$$Register, $tmp3$$Register,
13024 $tmp1$$XMMRegister, $tmp2$$XMMRegister, false /* char */, knoreg);
13025 %}
13026 ins_pipe( pipe_slow );
13027 %}
13028
13029 instruct string_equals_evex(rdi_RegP str1, rsi_RegP str2, rcx_RegI cnt, rax_RegI result,
13030 legRegD tmp1, legRegD tmp2, kReg ktmp, rbx_RegI tmp3, rFlagsReg cr)
13031 %{
13032 predicate(VM_Version::supports_avx512vlbw());
13033 match(Set result (StrEquals (Binary str1 str2) cnt));
13034 effect(TEMP tmp1, TEMP tmp2, TEMP ktmp, USE_KILL str1, USE_KILL str2, USE_KILL cnt, KILL tmp3, KILL cr);
13035
13036 format %{ "String Equals $str1,$str2,$cnt -> $result // KILL $tmp1, $tmp2, $tmp3" %}
13037 ins_encode %{
13038 __ arrays_equals(false, $str1$$Register, $str2$$Register,
13039 $cnt$$Register, $result$$Register, $tmp3$$Register,
13040 $tmp1$$XMMRegister, $tmp2$$XMMRegister, false /* char */, $ktmp$$KRegister);
13041 %}
13042 ins_pipe( pipe_slow );
13043 %}
13044
13045 // fast array equals
13046 instruct array_equalsB(rdi_RegP ary1, rsi_RegP ary2, rax_RegI result,
13047 legRegD tmp1, legRegD tmp2, rcx_RegI tmp3, rbx_RegI tmp4, rFlagsReg cr)
13048 %{
13049 predicate(!VM_Version::supports_avx512vlbw() && ((AryEqNode*)n)->encoding() == StrIntrinsicNode::LL);
13050 match(Set result (AryEq ary1 ary2));
13051 effect(TEMP tmp1, TEMP tmp2, USE_KILL ary1, USE_KILL ary2, KILL tmp3, KILL tmp4, KILL cr);
13052
13053 format %{ "Array Equals byte[] $ary1,$ary2 -> $result // KILL $tmp1, $tmp2, $tmp3, $tmp4" %}
13054 ins_encode %{
13055 __ arrays_equals(true, $ary1$$Register, $ary2$$Register,
13056 $tmp3$$Register, $result$$Register, $tmp4$$Register,
13057 $tmp1$$XMMRegister, $tmp2$$XMMRegister, false /* char */, knoreg);
13058 %}
13059 ins_pipe( pipe_slow );
13060 %}
13061
13062 instruct array_equalsB_evex(rdi_RegP ary1, rsi_RegP ary2, rax_RegI result,
13063 legRegD tmp1, legRegD tmp2, kReg ktmp, rcx_RegI tmp3, rbx_RegI tmp4, rFlagsReg cr)
13064 %{
13065 predicate(VM_Version::supports_avx512vlbw() && ((AryEqNode*)n)->encoding() == StrIntrinsicNode::LL);
13066 match(Set result (AryEq ary1 ary2));
13067 effect(TEMP tmp1, TEMP tmp2, TEMP ktmp, USE_KILL ary1, USE_KILL ary2, KILL tmp3, KILL tmp4, KILL cr);
13068
13069 format %{ "Array Equals byte[] $ary1,$ary2 -> $result // KILL $tmp1, $tmp2, $tmp3, $tmp4" %}
13070 ins_encode %{
13071 __ arrays_equals(true, $ary1$$Register, $ary2$$Register,
13072 $tmp3$$Register, $result$$Register, $tmp4$$Register,
13073 $tmp1$$XMMRegister, $tmp2$$XMMRegister, false /* char */, $ktmp$$KRegister);
13074 %}
13075 ins_pipe( pipe_slow );
13076 %}
13077
13078 instruct array_equalsC(rdi_RegP ary1, rsi_RegP ary2, rax_RegI result,
13079 legRegD tmp1, legRegD tmp2, rcx_RegI tmp3, rbx_RegI tmp4, rFlagsReg cr)
13080 %{
13081 predicate(!VM_Version::supports_avx512vlbw() && ((AryEqNode*)n)->encoding() == StrIntrinsicNode::UU);
13082 match(Set result (AryEq ary1 ary2));
13083 effect(TEMP tmp1, TEMP tmp2, USE_KILL ary1, USE_KILL ary2, KILL tmp3, KILL tmp4, KILL cr);
13084
13085 format %{ "Array Equals char[] $ary1,$ary2 -> $result // KILL $tmp1, $tmp2, $tmp3, $tmp4" %}
13086 ins_encode %{
13087 __ arrays_equals(true, $ary1$$Register, $ary2$$Register,
13088 $tmp3$$Register, $result$$Register, $tmp4$$Register,
13089 $tmp1$$XMMRegister, $tmp2$$XMMRegister, true /* char */, knoreg);
13090 %}
13091 ins_pipe( pipe_slow );
13092 %}
13093
13094 instruct array_equalsC_evex(rdi_RegP ary1, rsi_RegP ary2, rax_RegI result,
13095 legRegD tmp1, legRegD tmp2, kReg ktmp, rcx_RegI tmp3, rbx_RegI tmp4, rFlagsReg cr)
13096 %{
13097 predicate(VM_Version::supports_avx512vlbw() && ((AryEqNode*)n)->encoding() == StrIntrinsicNode::UU);
13098 match(Set result (AryEq ary1 ary2));
13099 effect(TEMP tmp1, TEMP tmp2, TEMP ktmp, USE_KILL ary1, USE_KILL ary2, KILL tmp3, KILL tmp4, KILL cr);
13100
13101 format %{ "Array Equals char[] $ary1,$ary2 -> $result // KILL $tmp1, $tmp2, $tmp3, $tmp4" %}
13102 ins_encode %{
13103 __ arrays_equals(true, $ary1$$Register, $ary2$$Register,
13104 $tmp3$$Register, $result$$Register, $tmp4$$Register,
13105 $tmp1$$XMMRegister, $tmp2$$XMMRegister, true /* char */, $ktmp$$KRegister);
13106 %}
13107 ins_pipe( pipe_slow );
13108 %}
13109
13110 instruct arrays_hashcode(rdi_RegP ary1, rdx_RegI cnt1, rbx_RegI result, immU8 basic_type,
13111 legRegD tmp_vec1, legRegD tmp_vec2, legRegD tmp_vec3, legRegD tmp_vec4,
13112 legRegD tmp_vec5, legRegD tmp_vec6, legRegD tmp_vec7, legRegD tmp_vec8,
13113 legRegD tmp_vec9, legRegD tmp_vec10, legRegD tmp_vec11, legRegD tmp_vec12,
13114 legRegD tmp_vec13, rRegI tmp1, rRegI tmp2, rRegI tmp3, rFlagsReg cr)
13115 %{
13116 predicate(UseAVX >= 2);
13117 match(Set result (VectorizedHashCode (Binary ary1 cnt1) (Binary result basic_type)));
13118 effect(TEMP tmp_vec1, TEMP tmp_vec2, TEMP tmp_vec3, TEMP tmp_vec4, TEMP tmp_vec5, TEMP tmp_vec6,
13119 TEMP tmp_vec7, TEMP tmp_vec8, TEMP tmp_vec9, TEMP tmp_vec10, TEMP tmp_vec11, TEMP tmp_vec12,
13120 TEMP tmp_vec13, TEMP tmp1, TEMP tmp2, TEMP tmp3, USE_KILL ary1, USE_KILL cnt1,
13121 USE basic_type, KILL cr);
13122
13123 format %{ "Array HashCode array[] $ary1,$cnt1,$result,$basic_type -> $result // KILL all" %}
13124 ins_encode %{
13125 __ arrays_hashcode($ary1$$Register, $cnt1$$Register, $result$$Register,
13126 $tmp1$$Register, $tmp2$$Register, $tmp3$$Register,
13127 $tmp_vec1$$XMMRegister, $tmp_vec2$$XMMRegister, $tmp_vec3$$XMMRegister,
13128 $tmp_vec4$$XMMRegister, $tmp_vec5$$XMMRegister, $tmp_vec6$$XMMRegister,
13129 $tmp_vec7$$XMMRegister, $tmp_vec8$$XMMRegister, $tmp_vec9$$XMMRegister,
13130 $tmp_vec10$$XMMRegister, $tmp_vec11$$XMMRegister, $tmp_vec12$$XMMRegister,
13131 $tmp_vec13$$XMMRegister, (BasicType)$basic_type$$constant);
13132 %}
13133 ins_pipe( pipe_slow );
13134 %}
13135
13136 instruct count_positives(rsi_RegP ary1, rcx_RegI len, rax_RegI result,
13137 legRegD tmp1, legRegD tmp2, rbx_RegI tmp3, rFlagsReg cr,)
13138 %{
13139 predicate(!VM_Version::supports_avx512vlbw() || !VM_Version::supports_bmi2());
13140 match(Set result (CountPositives ary1 len));
13141 effect(TEMP tmp1, TEMP tmp2, USE_KILL ary1, USE_KILL len, KILL tmp3, KILL cr);
13142
13143 format %{ "countPositives byte[] $ary1,$len -> $result // KILL $tmp1, $tmp2, $tmp3" %}
13144 ins_encode %{
13145 __ count_positives($ary1$$Register, $len$$Register,
13146 $result$$Register, $tmp3$$Register,
13147 $tmp1$$XMMRegister, $tmp2$$XMMRegister, knoreg, knoreg);
13148 %}
13149 ins_pipe( pipe_slow );
13150 %}
13151
13152 instruct count_positives_evex(rsi_RegP ary1, rcx_RegI len, rax_RegI result,
13153 legRegD tmp1, legRegD tmp2, kReg ktmp1, kReg ktmp2, rbx_RegI tmp3, rFlagsReg cr,)
13154 %{
13155 predicate(VM_Version::supports_avx512vlbw() && VM_Version::supports_bmi2());
13156 match(Set result (CountPositives ary1 len));
13157 effect(TEMP tmp1, TEMP tmp2, TEMP ktmp1, TEMP ktmp2, USE_KILL ary1, USE_KILL len, KILL tmp3, KILL cr);
13158
13159 format %{ "countPositives byte[] $ary1,$len -> $result // KILL $tmp1, $tmp2, $tmp3" %}
13160 ins_encode %{
13161 __ count_positives($ary1$$Register, $len$$Register,
13162 $result$$Register, $tmp3$$Register,
13163 $tmp1$$XMMRegister, $tmp2$$XMMRegister, $ktmp1$$KRegister, $ktmp2$$KRegister);
13164 %}
13165 ins_pipe( pipe_slow );
13166 %}
13167
13168 // fast char[] to byte[] compression
13169 instruct string_compress(rsi_RegP src, rdi_RegP dst, rdx_RegI len, legRegD tmp1, legRegD tmp2, legRegD tmp3,
13170 legRegD tmp4, rcx_RegI tmp5, rax_RegI result, rFlagsReg cr) %{
13171 predicate(!VM_Version::supports_avx512vlbw() || !VM_Version::supports_bmi2());
13172 match(Set result (StrCompressedCopy src (Binary dst len)));
13173 effect(TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, USE_KILL src, USE_KILL dst,
13174 USE_KILL len, KILL tmp5, KILL cr);
13175
13176 format %{ "String Compress $src,$dst -> $result // KILL RAX, RCX, RDX" %}
13177 ins_encode %{
13178 __ char_array_compress($src$$Register, $dst$$Register, $len$$Register,
13179 $tmp1$$XMMRegister, $tmp2$$XMMRegister, $tmp3$$XMMRegister,
13180 $tmp4$$XMMRegister, $tmp5$$Register, $result$$Register,
13181 knoreg, knoreg);
13182 %}
13183 ins_pipe( pipe_slow );
13184 %}
13185
13186 instruct string_compress_evex(rsi_RegP src, rdi_RegP dst, rdx_RegI len, legRegD tmp1, legRegD tmp2, legRegD tmp3,
13187 legRegD tmp4, kReg ktmp1, kReg ktmp2, rcx_RegI tmp5, rax_RegI result, rFlagsReg cr) %{
13188 predicate(VM_Version::supports_avx512vlbw() && VM_Version::supports_bmi2());
13189 match(Set result (StrCompressedCopy src (Binary dst len)));
13190 effect(TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, TEMP ktmp1, TEMP ktmp2, USE_KILL src, USE_KILL dst,
13191 USE_KILL len, KILL tmp5, KILL cr);
13192
13193 format %{ "String Compress $src,$dst -> $result // KILL RAX, RCX, RDX" %}
13194 ins_encode %{
13195 __ char_array_compress($src$$Register, $dst$$Register, $len$$Register,
13196 $tmp1$$XMMRegister, $tmp2$$XMMRegister, $tmp3$$XMMRegister,
13197 $tmp4$$XMMRegister, $tmp5$$Register, $result$$Register,
13198 $ktmp1$$KRegister, $ktmp2$$KRegister);
13199 %}
13200 ins_pipe( pipe_slow );
13201 %}
13202 // fast byte[] to char[] inflation
13203 instruct string_inflate(Universe dummy, rsi_RegP src, rdi_RegP dst, rdx_RegI len,
13204 legRegD tmp1, rcx_RegI tmp2, rFlagsReg cr) %{
13205 predicate(!VM_Version::supports_avx512vlbw() || !VM_Version::supports_bmi2());
13206 match(Set dummy (StrInflatedCopy src (Binary dst len)));
13207 effect(TEMP tmp1, TEMP tmp2, USE_KILL src, USE_KILL dst, USE_KILL len, KILL cr);
13208
13209 format %{ "String Inflate $src,$dst // KILL $tmp1, $tmp2" %}
13210 ins_encode %{
13211 __ byte_array_inflate($src$$Register, $dst$$Register, $len$$Register,
13212 $tmp1$$XMMRegister, $tmp2$$Register, knoreg);
13213 %}
13214 ins_pipe( pipe_slow );
13215 %}
13216
13217 instruct string_inflate_evex(Universe dummy, rsi_RegP src, rdi_RegP dst, rdx_RegI len,
13218 legRegD tmp1, kReg ktmp, rcx_RegI tmp2, rFlagsReg cr) %{
13219 predicate(VM_Version::supports_avx512vlbw() && VM_Version::supports_bmi2());
13220 match(Set dummy (StrInflatedCopy src (Binary dst len)));
13221 effect(TEMP tmp1, TEMP tmp2, TEMP ktmp, USE_KILL src, USE_KILL dst, USE_KILL len, KILL cr);
13222
13223 format %{ "String Inflate $src,$dst // KILL $tmp1, $tmp2" %}
13224 ins_encode %{
13225 __ byte_array_inflate($src$$Register, $dst$$Register, $len$$Register,
13226 $tmp1$$XMMRegister, $tmp2$$Register, $ktmp$$KRegister);
13227 %}
13228 ins_pipe( pipe_slow );
13229 %}
13230
13231 // encode char[] to byte[] in ISO_8859_1
13232 instruct encode_iso_array(rsi_RegP src, rdi_RegP dst, rdx_RegI len,
13233 legRegD tmp1, legRegD tmp2, legRegD tmp3, legRegD tmp4,
13234 rcx_RegI tmp5, rax_RegI result, rFlagsReg cr) %{
13235 predicate(!((EncodeISOArrayNode*)n)->is_ascii());
13236 match(Set result (EncodeISOArray src (Binary dst len)));
13237 effect(TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, USE_KILL src, USE_KILL dst, USE_KILL len, KILL tmp5, KILL cr);
13238
13239 format %{ "Encode iso array $src,$dst,$len -> $result // KILL RCX, RDX, $tmp1, $tmp2, $tmp3, $tmp4, RSI, RDI " %}
13240 ins_encode %{
13241 __ encode_iso_array($src$$Register, $dst$$Register, $len$$Register,
13242 $tmp1$$XMMRegister, $tmp2$$XMMRegister, $tmp3$$XMMRegister,
13243 $tmp4$$XMMRegister, $tmp5$$Register, $result$$Register, false);
13244 %}
13245 ins_pipe( pipe_slow );
13246 %}
13247
13248 // encode char[] to byte[] in ASCII
13249 instruct encode_ascii_array(rsi_RegP src, rdi_RegP dst, rdx_RegI len,
13250 legRegD tmp1, legRegD tmp2, legRegD tmp3, legRegD tmp4,
13251 rcx_RegI tmp5, rax_RegI result, rFlagsReg cr) %{
13252 predicate(((EncodeISOArrayNode*)n)->is_ascii());
13253 match(Set result (EncodeISOArray src (Binary dst len)));
13254 effect(TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, USE_KILL src, USE_KILL dst, USE_KILL len, KILL tmp5, KILL cr);
13255
13256 format %{ "Encode ascii array $src,$dst,$len -> $result // KILL RCX, RDX, $tmp1, $tmp2, $tmp3, $tmp4, RSI, RDI " %}
13257 ins_encode %{
13258 __ encode_iso_array($src$$Register, $dst$$Register, $len$$Register,
13259 $tmp1$$XMMRegister, $tmp2$$XMMRegister, $tmp3$$XMMRegister,
13260 $tmp4$$XMMRegister, $tmp5$$Register, $result$$Register, true);
13261 %}
13262 ins_pipe( pipe_slow );
13263 %}
13264
13265 //----------Overflow Math Instructions-----------------------------------------
13266
13267 instruct overflowAddI_rReg(rFlagsReg cr, rax_RegI op1, rRegI op2)
13268 %{
13269 match(Set cr (OverflowAddI op1 op2));
13270 effect(DEF cr, USE_KILL op1, USE op2);
13271
13272 format %{ "addl $op1, $op2\t# overflow check int" %}
13273
13274 ins_encode %{
13275 __ addl($op1$$Register, $op2$$Register);
13276 %}
13277 ins_pipe(ialu_reg_reg);
13278 %}
13279
13280 instruct overflowAddI_rReg_imm(rFlagsReg cr, rax_RegI op1, immI op2)
13281 %{
13282 match(Set cr (OverflowAddI op1 op2));
13283 effect(DEF cr, USE_KILL op1, USE op2);
13284
13285 format %{ "addl $op1, $op2\t# overflow check int" %}
13286
13287 ins_encode %{
13288 __ addl($op1$$Register, $op2$$constant);
13289 %}
13290 ins_pipe(ialu_reg_reg);
13291 %}
13292
13293 instruct overflowAddL_rReg(rFlagsReg cr, rax_RegL op1, rRegL op2)
13294 %{
13295 match(Set cr (OverflowAddL op1 op2));
13296 effect(DEF cr, USE_KILL op1, USE op2);
13297
13298 format %{ "addq $op1, $op2\t# overflow check long" %}
13299 ins_encode %{
13300 __ addq($op1$$Register, $op2$$Register);
13301 %}
13302 ins_pipe(ialu_reg_reg);
13303 %}
13304
13305 instruct overflowAddL_rReg_imm(rFlagsReg cr, rax_RegL op1, immL32 op2)
13306 %{
13307 match(Set cr (OverflowAddL op1 op2));
13308 effect(DEF cr, USE_KILL op1, USE op2);
13309
13310 format %{ "addq $op1, $op2\t# overflow check long" %}
13311 ins_encode %{
13312 __ addq($op1$$Register, $op2$$constant);
13313 %}
13314 ins_pipe(ialu_reg_reg);
13315 %}
13316
13317 instruct overflowSubI_rReg(rFlagsReg cr, rRegI op1, rRegI op2)
13318 %{
13319 match(Set cr (OverflowSubI op1 op2));
13320
13321 format %{ "cmpl $op1, $op2\t# overflow check int" %}
13322 ins_encode %{
13323 __ cmpl($op1$$Register, $op2$$Register);
13324 %}
13325 ins_pipe(ialu_reg_reg);
13326 %}
13327
13328 instruct overflowSubI_rReg_imm(rFlagsReg cr, rRegI op1, immI op2)
13329 %{
13330 match(Set cr (OverflowSubI op1 op2));
13331
13332 format %{ "cmpl $op1, $op2\t# overflow check int" %}
13333 ins_encode %{
13334 __ cmpl($op1$$Register, $op2$$constant);
13335 %}
13336 ins_pipe(ialu_reg_reg);
13337 %}
13338
13339 instruct overflowSubL_rReg(rFlagsReg cr, rRegL op1, rRegL op2)
13340 %{
13341 match(Set cr (OverflowSubL op1 op2));
13342
13343 format %{ "cmpq $op1, $op2\t# overflow check long" %}
13344 ins_encode %{
13345 __ cmpq($op1$$Register, $op2$$Register);
13346 %}
13347 ins_pipe(ialu_reg_reg);
13348 %}
13349
13350 instruct overflowSubL_rReg_imm(rFlagsReg cr, rRegL op1, immL32 op2)
13351 %{
13352 match(Set cr (OverflowSubL op1 op2));
13353
13354 format %{ "cmpq $op1, $op2\t# overflow check long" %}
13355 ins_encode %{
13356 __ cmpq($op1$$Register, $op2$$constant);
13357 %}
13358 ins_pipe(ialu_reg_reg);
13359 %}
13360
13361 instruct overflowNegI_rReg(rFlagsReg cr, immI_0 zero, rax_RegI op2)
13362 %{
13363 match(Set cr (OverflowSubI zero op2));
13364 effect(DEF cr, USE_KILL op2);
13365
13366 format %{ "negl $op2\t# overflow check int" %}
13367 ins_encode %{
13368 __ negl($op2$$Register);
13369 %}
13370 ins_pipe(ialu_reg_reg);
13371 %}
13372
13373 instruct overflowNegL_rReg(rFlagsReg cr, immL0 zero, rax_RegL op2)
13374 %{
13375 match(Set cr (OverflowSubL zero op2));
13376 effect(DEF cr, USE_KILL op2);
13377
13378 format %{ "negq $op2\t# overflow check long" %}
13379 ins_encode %{
13380 __ negq($op2$$Register);
13381 %}
13382 ins_pipe(ialu_reg_reg);
13383 %}
13384
13385 instruct overflowMulI_rReg(rFlagsReg cr, rax_RegI op1, rRegI op2)
13386 %{
13387 match(Set cr (OverflowMulI op1 op2));
13388 effect(DEF cr, USE_KILL op1, USE op2);
13389
13390 format %{ "imull $op1, $op2\t# overflow check int" %}
13391 ins_encode %{
13392 __ imull($op1$$Register, $op2$$Register);
13393 %}
13394 ins_pipe(ialu_reg_reg_alu0);
13395 %}
13396
13397 instruct overflowMulI_rReg_imm(rFlagsReg cr, rRegI op1, immI op2, rRegI tmp)
13398 %{
13399 match(Set cr (OverflowMulI op1 op2));
13400 effect(DEF cr, TEMP tmp, USE op1, USE op2);
13401
13402 format %{ "imull $tmp, $op1, $op2\t# overflow check int" %}
13403 ins_encode %{
13404 __ imull($tmp$$Register, $op1$$Register, $op2$$constant);
13405 %}
13406 ins_pipe(ialu_reg_reg_alu0);
13407 %}
13408
13409 instruct overflowMulL_rReg(rFlagsReg cr, rax_RegL op1, rRegL op2)
13410 %{
13411 match(Set cr (OverflowMulL op1 op2));
13412 effect(DEF cr, USE_KILL op1, USE op2);
13413
13414 format %{ "imulq $op1, $op2\t# overflow check long" %}
13415 ins_encode %{
13416 __ imulq($op1$$Register, $op2$$Register);
13417 %}
13418 ins_pipe(ialu_reg_reg_alu0);
13419 %}
13420
13421 instruct overflowMulL_rReg_imm(rFlagsReg cr, rRegL op1, immL32 op2, rRegL tmp)
13422 %{
13423 match(Set cr (OverflowMulL op1 op2));
13424 effect(DEF cr, TEMP tmp, USE op1, USE op2);
13425
13426 format %{ "imulq $tmp, $op1, $op2\t# overflow check long" %}
13427 ins_encode %{
13428 __ imulq($tmp$$Register, $op1$$Register, $op2$$constant);
13429 %}
13430 ins_pipe(ialu_reg_reg_alu0);
13431 %}
13432
13433
13434 //----------Control Flow Instructions------------------------------------------
13435 // Signed compare Instructions
13436
13437 // XXX more variants!!
13438 instruct compI_rReg(rFlagsReg cr, rRegI op1, rRegI op2)
13439 %{
13440 match(Set cr (CmpI op1 op2));
13441 effect(DEF cr, USE op1, USE op2);
13442
13443 format %{ "cmpl $op1, $op2" %}
13444 ins_encode %{
13445 __ cmpl($op1$$Register, $op2$$Register);
13446 %}
13447 ins_pipe(ialu_cr_reg_reg);
13448 %}
13449
13450 instruct compI_rReg_imm(rFlagsReg cr, rRegI op1, immI op2)
13451 %{
13452 match(Set cr (CmpI op1 op2));
13453
13454 format %{ "cmpl $op1, $op2" %}
13455 ins_encode %{
13456 __ cmpl($op1$$Register, $op2$$constant);
13457 %}
13458 ins_pipe(ialu_cr_reg_imm);
13459 %}
13460
13461 instruct compI_rReg_mem(rFlagsReg cr, rRegI op1, memory op2)
13462 %{
13463 match(Set cr (CmpI op1 (LoadI op2)));
13464
13465 ins_cost(500); // XXX
13466 format %{ "cmpl $op1, $op2" %}
13467 ins_encode %{
13468 __ cmpl($op1$$Register, $op2$$Address);
13469 %}
13470 ins_pipe(ialu_cr_reg_mem);
13471 %}
13472
13473 instruct testI_reg(rFlagsReg cr, rRegI src, immI_0 zero)
13474 %{
13475 match(Set cr (CmpI src zero));
13476
13477 format %{ "testl $src, $src" %}
13478 ins_encode %{
13479 __ testl($src$$Register, $src$$Register);
13480 %}
13481 ins_pipe(ialu_cr_reg_imm);
13482 %}
13483
13484 instruct testI_reg_imm(rFlagsReg cr, rRegI src, immI con, immI_0 zero)
13485 %{
13486 match(Set cr (CmpI (AndI src con) zero));
13487
13488 format %{ "testl $src, $con" %}
13489 ins_encode %{
13490 __ testl($src$$Register, $con$$constant);
13491 %}
13492 ins_pipe(ialu_cr_reg_imm);
13493 %}
13494
13495 instruct testI_reg_reg(rFlagsReg cr, rRegI src1, rRegI src2, immI_0 zero)
13496 %{
13497 match(Set cr (CmpI (AndI src1 src2) zero));
13498
13499 format %{ "testl $src1, $src2" %}
13500 ins_encode %{
13501 __ testl($src1$$Register, $src2$$Register);
13502 %}
13503 ins_pipe(ialu_cr_reg_imm);
13504 %}
13505
13506 instruct testI_reg_mem(rFlagsReg cr, rRegI src, memory mem, immI_0 zero)
13507 %{
13508 match(Set cr (CmpI (AndI src (LoadI mem)) zero));
13509
13510 format %{ "testl $src, $mem" %}
13511 ins_encode %{
13512 __ testl($src$$Register, $mem$$Address);
13513 %}
13514 ins_pipe(ialu_cr_reg_mem);
13515 %}
13516
13517 // Unsigned compare Instructions; really, same as signed except they
13518 // produce an rFlagsRegU instead of rFlagsReg.
13519 instruct compU_rReg(rFlagsRegU cr, rRegI op1, rRegI op2)
13520 %{
13521 match(Set cr (CmpU op1 op2));
13522
13523 format %{ "cmpl $op1, $op2\t# unsigned" %}
13524 ins_encode %{
13525 __ cmpl($op1$$Register, $op2$$Register);
13526 %}
13527 ins_pipe(ialu_cr_reg_reg);
13528 %}
13529
13530 instruct compU_rReg_imm(rFlagsRegU cr, rRegI op1, immI op2)
13531 %{
13532 match(Set cr (CmpU op1 op2));
13533
13534 format %{ "cmpl $op1, $op2\t# unsigned" %}
13535 ins_encode %{
13536 __ cmpl($op1$$Register, $op2$$constant);
13537 %}
13538 ins_pipe(ialu_cr_reg_imm);
13539 %}
13540
13541 instruct compU_rReg_mem(rFlagsRegU cr, rRegI op1, memory op2)
13542 %{
13543 match(Set cr (CmpU op1 (LoadI op2)));
13544
13545 ins_cost(500); // XXX
13546 format %{ "cmpl $op1, $op2\t# unsigned" %}
13547 ins_encode %{
13548 __ cmpl($op1$$Register, $op2$$Address);
13549 %}
13550 ins_pipe(ialu_cr_reg_mem);
13551 %}
13552
13553 instruct testU_reg(rFlagsRegU cr, rRegI src, immI_0 zero)
13554 %{
13555 match(Set cr (CmpU src zero));
13556
13557 format %{ "testl $src, $src\t# unsigned" %}
13558 ins_encode %{
13559 __ testl($src$$Register, $src$$Register);
13560 %}
13561 ins_pipe(ialu_cr_reg_imm);
13562 %}
13563
13564 instruct compP_rReg(rFlagsRegU cr, rRegP op1, rRegP op2)
13565 %{
13566 match(Set cr (CmpP op1 op2));
13567
13568 format %{ "cmpq $op1, $op2\t# ptr" %}
13569 ins_encode %{
13570 __ cmpq($op1$$Register, $op2$$Register);
13571 %}
13572 ins_pipe(ialu_cr_reg_reg);
13573 %}
13574
13575 instruct compP_rReg_mem(rFlagsRegU cr, rRegP op1, memory op2)
13576 %{
13577 match(Set cr (CmpP op1 (LoadP op2)));
13578 predicate(n->in(2)->as_Load()->barrier_data() == 0);
13579
13580 ins_cost(500); // XXX
13581 format %{ "cmpq $op1, $op2\t# ptr" %}
13582 ins_encode %{
13583 __ cmpq($op1$$Register, $op2$$Address);
13584 %}
13585 ins_pipe(ialu_cr_reg_mem);
13586 %}
13587
13588 // XXX this is generalized by compP_rReg_mem???
13589 // Compare raw pointer (used in out-of-heap check).
13590 // Only works because non-oop pointers must be raw pointers
13591 // and raw pointers have no anti-dependencies.
13592 instruct compP_mem_rReg(rFlagsRegU cr, rRegP op1, memory op2)
13593 %{
13594 predicate(n->in(2)->in(2)->bottom_type()->reloc() == relocInfo::none &&
13595 n->in(2)->as_Load()->barrier_data() == 0);
13596 match(Set cr (CmpP op1 (LoadP op2)));
13597
13598 format %{ "cmpq $op1, $op2\t# raw ptr" %}
13599 ins_encode %{
13600 __ cmpq($op1$$Register, $op2$$Address);
13601 %}
13602 ins_pipe(ialu_cr_reg_mem);
13603 %}
13604
13605 // This will generate a signed flags result. This should be OK since
13606 // any compare to a zero should be eq/neq.
13607 instruct testP_reg(rFlagsReg cr, rRegP src, immP0 zero)
13608 %{
13609 match(Set cr (CmpP src zero));
13610
13611 format %{ "testq $src, $src\t# ptr" %}
13612 ins_encode %{
13613 __ testq($src$$Register, $src$$Register);
13614 %}
13615 ins_pipe(ialu_cr_reg_imm);
13616 %}
13617
13618 // This will generate a signed flags result. This should be OK since
13619 // any compare to a zero should be eq/neq.
13620 instruct testP_mem(rFlagsReg cr, memory op, immP0 zero)
13621 %{
13622 predicate((!UseCompressedOops || (CompressedOops::base() != nullptr)) &&
13623 n->in(1)->as_Load()->barrier_data() == 0);
13624 match(Set cr (CmpP (LoadP op) zero));
13625
13626 ins_cost(500); // XXX
13627 format %{ "testq $op, 0xffffffffffffffff\t# ptr" %}
13628 ins_encode %{
13629 __ testq($op$$Address, 0xFFFFFFFF);
13630 %}
13631 ins_pipe(ialu_cr_reg_imm);
13632 %}
13633
13634 instruct testP_mem_reg0(rFlagsReg cr, memory mem, immP0 zero)
13635 %{
13636 predicate(UseCompressedOops && (CompressedOops::base() == nullptr) &&
13637 n->in(1)->as_Load()->barrier_data() == 0);
13638 match(Set cr (CmpP (LoadP mem) zero));
13639
13640 format %{ "cmpq R12, $mem\t# ptr (R12_heapbase==0)" %}
13641 ins_encode %{
13642 __ cmpq(r12, $mem$$Address);
13643 %}
13644 ins_pipe(ialu_cr_reg_mem);
13645 %}
13646
13647 instruct compN_rReg(rFlagsRegU cr, rRegN op1, rRegN op2)
13648 %{
13649 match(Set cr (CmpN op1 op2));
13650
13651 format %{ "cmpl $op1, $op2\t# compressed ptr" %}
13652 ins_encode %{ __ cmpl($op1$$Register, $op2$$Register); %}
13653 ins_pipe(ialu_cr_reg_reg);
13654 %}
13655
13656 instruct compN_rReg_mem(rFlagsRegU cr, rRegN src, memory mem)
13657 %{
13658 predicate(n->in(2)->as_Load()->barrier_data() == 0);
13659 match(Set cr (CmpN src (LoadN mem)));
13660
13661 format %{ "cmpl $src, $mem\t# compressed ptr" %}
13662 ins_encode %{
13663 __ cmpl($src$$Register, $mem$$Address);
13664 %}
13665 ins_pipe(ialu_cr_reg_mem);
13666 %}
13667
13668 instruct compN_rReg_imm(rFlagsRegU cr, rRegN op1, immN op2) %{
13669 match(Set cr (CmpN op1 op2));
13670
13671 format %{ "cmpl $op1, $op2\t# compressed ptr" %}
13672 ins_encode %{
13673 __ cmp_narrow_oop($op1$$Register, (jobject)$op2$$constant);
13674 %}
13675 ins_pipe(ialu_cr_reg_imm);
13676 %}
13677
13678 instruct compN_mem_imm(rFlagsRegU cr, memory mem, immN src)
13679 %{
13680 predicate(n->in(2)->as_Load()->barrier_data() == 0);
13681 match(Set cr (CmpN src (LoadN mem)));
13682
13683 format %{ "cmpl $mem, $src\t# compressed ptr" %}
13684 ins_encode %{
13685 __ cmp_narrow_oop($mem$$Address, (jobject)$src$$constant);
13686 %}
13687 ins_pipe(ialu_cr_reg_mem);
13688 %}
13689
13690 instruct compN_rReg_imm_klass(rFlagsRegU cr, rRegN op1, immNKlass op2) %{
13691 match(Set cr (CmpN op1 op2));
13692
13693 format %{ "cmpl $op1, $op2\t# compressed klass ptr" %}
13694 ins_encode %{
13695 __ cmp_narrow_klass($op1$$Register, (Klass*)$op2$$constant);
13696 %}
13697 ins_pipe(ialu_cr_reg_imm);
13698 %}
13699
13700 instruct compN_mem_imm_klass(rFlagsRegU cr, memory mem, immNKlass src)
13701 %{
13702 predicate(!UseCompactObjectHeaders);
13703 match(Set cr (CmpN src (LoadNKlass mem)));
13704
13705 format %{ "cmpl $mem, $src\t# compressed klass ptr" %}
13706 ins_encode %{
13707 __ cmp_narrow_klass($mem$$Address, (Klass*)$src$$constant);
13708 %}
13709 ins_pipe(ialu_cr_reg_mem);
13710 %}
13711
13712 instruct testN_reg(rFlagsReg cr, rRegN src, immN0 zero) %{
13713 match(Set cr (CmpN src zero));
13714
13715 format %{ "testl $src, $src\t# compressed ptr" %}
13716 ins_encode %{ __ testl($src$$Register, $src$$Register); %}
13717 ins_pipe(ialu_cr_reg_imm);
13718 %}
13719
13720 instruct testN_mem(rFlagsReg cr, memory mem, immN0 zero)
13721 %{
13722 predicate(CompressedOops::base() != nullptr &&
13723 n->in(1)->as_Load()->barrier_data() == 0);
13724 match(Set cr (CmpN (LoadN mem) zero));
13725
13726 ins_cost(500); // XXX
13727 format %{ "testl $mem, 0xffffffff\t# compressed ptr" %}
13728 ins_encode %{
13729 __ cmpl($mem$$Address, (int)0xFFFFFFFF);
13730 %}
13731 ins_pipe(ialu_cr_reg_mem);
13732 %}
13733
13734 instruct testN_mem_reg0(rFlagsReg cr, memory mem, immN0 zero)
13735 %{
13736 predicate(CompressedOops::base() == nullptr &&
13737 n->in(1)->as_Load()->barrier_data() == 0);
13738 match(Set cr (CmpN (LoadN mem) zero));
13739
13740 format %{ "cmpl R12, $mem\t# compressed ptr (R12_heapbase==0)" %}
13741 ins_encode %{
13742 __ cmpl(r12, $mem$$Address);
13743 %}
13744 ins_pipe(ialu_cr_reg_mem);
13745 %}
13746
13747 // Yanked all unsigned pointer compare operations.
13748 // Pointer compares are done with CmpP which is already unsigned.
13749
13750 instruct compL_rReg(rFlagsReg cr, rRegL op1, rRegL op2)
13751 %{
13752 match(Set cr (CmpL op1 op2));
13753
13754 format %{ "cmpq $op1, $op2" %}
13755 ins_encode %{
13756 __ cmpq($op1$$Register, $op2$$Register);
13757 %}
13758 ins_pipe(ialu_cr_reg_reg);
13759 %}
13760
13761 instruct compL_rReg_imm(rFlagsReg cr, rRegL op1, immL32 op2)
13762 %{
13763 match(Set cr (CmpL op1 op2));
13764
13765 format %{ "cmpq $op1, $op2" %}
13766 ins_encode %{
13767 __ cmpq($op1$$Register, $op2$$constant);
13768 %}
13769 ins_pipe(ialu_cr_reg_imm);
13770 %}
13771
13772 instruct compL_rReg_mem(rFlagsReg cr, rRegL op1, memory op2)
13773 %{
13774 match(Set cr (CmpL op1 (LoadL op2)));
13775
13776 format %{ "cmpq $op1, $op2" %}
13777 ins_encode %{
13778 __ cmpq($op1$$Register, $op2$$Address);
13779 %}
13780 ins_pipe(ialu_cr_reg_mem);
13781 %}
13782
13783 instruct testL_reg(rFlagsReg cr, rRegL src, immL0 zero)
13784 %{
13785 match(Set cr (CmpL src zero));
13786
13787 format %{ "testq $src, $src" %}
13788 ins_encode %{
13789 __ testq($src$$Register, $src$$Register);
13790 %}
13791 ins_pipe(ialu_cr_reg_imm);
13792 %}
13793
13794 instruct testL_reg_imm(rFlagsReg cr, rRegL src, immL32 con, immL0 zero)
13795 %{
13796 match(Set cr (CmpL (AndL src con) zero));
13797
13798 format %{ "testq $src, $con\t# long" %}
13799 ins_encode %{
13800 __ testq($src$$Register, $con$$constant);
13801 %}
13802 ins_pipe(ialu_cr_reg_imm);
13803 %}
13804
13805 instruct testL_reg_reg(rFlagsReg cr, rRegL src1, rRegL src2, immL0 zero)
13806 %{
13807 match(Set cr (CmpL (AndL src1 src2) zero));
13808
13809 format %{ "testq $src1, $src2\t# long" %}
13810 ins_encode %{
13811 __ testq($src1$$Register, $src2$$Register);
13812 %}
13813 ins_pipe(ialu_cr_reg_imm);
13814 %}
13815
13816 instruct testL_reg_mem(rFlagsReg cr, rRegL src, memory mem, immL0 zero)
13817 %{
13818 match(Set cr (CmpL (AndL src (LoadL mem)) zero));
13819
13820 format %{ "testq $src, $mem" %}
13821 ins_encode %{
13822 __ testq($src$$Register, $mem$$Address);
13823 %}
13824 ins_pipe(ialu_cr_reg_mem);
13825 %}
13826
13827 instruct testL_reg_mem2(rFlagsReg cr, rRegP src, memory mem, immL0 zero)
13828 %{
13829 match(Set cr (CmpL (AndL (CastP2X src) (LoadL mem)) zero));
13830
13831 format %{ "testq $src, $mem" %}
13832 ins_encode %{
13833 __ testq($src$$Register, $mem$$Address);
13834 %}
13835 ins_pipe(ialu_cr_reg_mem);
13836 %}
13837
13838 // Manifest a CmpU result in an integer register. Very painful.
13839 // This is the test to avoid.
13840 instruct cmpU3_reg_reg(rRegI dst, rRegI src1, rRegI src2, rFlagsReg flags)
13841 %{
13842 match(Set dst (CmpU3 src1 src2));
13843 effect(KILL flags);
13844
13845 ins_cost(275); // XXX
13846 format %{ "cmpl $src1, $src2\t# CmpL3\n\t"
13847 "movl $dst, -1\n\t"
13848 "jb,u done\n\t"
13849 "setcc $dst \t# emits setne + movzbl or setzune for APX"
13850 "done:" %}
13851 ins_encode %{
13852 Label done;
13853 __ cmpl($src1$$Register, $src2$$Register);
13854 __ movl($dst$$Register, -1);
13855 __ jccb(Assembler::below, done);
13856 __ setcc(Assembler::notZero, $dst$$Register);
13857 __ bind(done);
13858 %}
13859 ins_pipe(pipe_slow);
13860 %}
13861
13862 // Manifest a CmpL result in an integer register. Very painful.
13863 // This is the test to avoid.
13864 instruct cmpL3_reg_reg(rRegI dst, rRegL src1, rRegL src2, rFlagsReg flags)
13865 %{
13866 match(Set dst (CmpL3 src1 src2));
13867 effect(KILL flags);
13868
13869 ins_cost(275); // XXX
13870 format %{ "cmpq $src1, $src2\t# CmpL3\n\t"
13871 "movl $dst, -1\n\t"
13872 "jl,s done\n\t"
13873 "setcc $dst \t# emits setne + movzbl or setzune for APX"
13874 "done:" %}
13875 ins_encode %{
13876 Label done;
13877 __ cmpq($src1$$Register, $src2$$Register);
13878 __ movl($dst$$Register, -1);
13879 __ jccb(Assembler::less, done);
13880 __ setcc(Assembler::notZero, $dst$$Register);
13881 __ bind(done);
13882 %}
13883 ins_pipe(pipe_slow);
13884 %}
13885
13886 // Manifest a CmpUL result in an integer register. Very painful.
13887 // This is the test to avoid.
13888 instruct cmpUL3_reg_reg(rRegI dst, rRegL src1, rRegL src2, rFlagsReg flags)
13889 %{
13890 match(Set dst (CmpUL3 src1 src2));
13891 effect(KILL flags);
13892
13893 ins_cost(275); // XXX
13894 format %{ "cmpq $src1, $src2\t# CmpL3\n\t"
13895 "movl $dst, -1\n\t"
13896 "jb,u done\n\t"
13897 "setcc $dst \t# emits setne + movzbl or setzune for APX"
13898 "done:" %}
13899 ins_encode %{
13900 Label done;
13901 __ cmpq($src1$$Register, $src2$$Register);
13902 __ movl($dst$$Register, -1);
13903 __ jccb(Assembler::below, done);
13904 __ setcc(Assembler::notZero, $dst$$Register);
13905 __ bind(done);
13906 %}
13907 ins_pipe(pipe_slow);
13908 %}
13909
13910 // Unsigned long compare Instructions; really, same as signed long except they
13911 // produce an rFlagsRegU instead of rFlagsReg.
13912 instruct compUL_rReg(rFlagsRegU cr, rRegL op1, rRegL op2)
13913 %{
13914 match(Set cr (CmpUL op1 op2));
13915
13916 format %{ "cmpq $op1, $op2\t# unsigned" %}
13917 ins_encode %{
13918 __ cmpq($op1$$Register, $op2$$Register);
13919 %}
13920 ins_pipe(ialu_cr_reg_reg);
13921 %}
13922
13923 instruct compUL_rReg_imm(rFlagsRegU cr, rRegL op1, immL32 op2)
13924 %{
13925 match(Set cr (CmpUL op1 op2));
13926
13927 format %{ "cmpq $op1, $op2\t# unsigned" %}
13928 ins_encode %{
13929 __ cmpq($op1$$Register, $op2$$constant);
13930 %}
13931 ins_pipe(ialu_cr_reg_imm);
13932 %}
13933
13934 instruct compUL_rReg_mem(rFlagsRegU cr, rRegL op1, memory op2)
13935 %{
13936 match(Set cr (CmpUL op1 (LoadL op2)));
13937
13938 format %{ "cmpq $op1, $op2\t# unsigned" %}
13939 ins_encode %{
13940 __ cmpq($op1$$Register, $op2$$Address);
13941 %}
13942 ins_pipe(ialu_cr_reg_mem);
13943 %}
13944
13945 instruct testUL_reg(rFlagsRegU cr, rRegL src, immL0 zero)
13946 %{
13947 match(Set cr (CmpUL src zero));
13948
13949 format %{ "testq $src, $src\t# unsigned" %}
13950 ins_encode %{
13951 __ testq($src$$Register, $src$$Register);
13952 %}
13953 ins_pipe(ialu_cr_reg_imm);
13954 %}
13955
13956 instruct compB_mem_imm(rFlagsReg cr, memory mem, immI8 imm)
13957 %{
13958 match(Set cr (CmpI (LoadB mem) imm));
13959
13960 ins_cost(125);
13961 format %{ "cmpb $mem, $imm" %}
13962 ins_encode %{ __ cmpb($mem$$Address, $imm$$constant); %}
13963 ins_pipe(ialu_cr_reg_mem);
13964 %}
13965
13966 instruct testUB_mem_imm(rFlagsReg cr, memory mem, immU7 imm, immI_0 zero)
13967 %{
13968 match(Set cr (CmpI (AndI (LoadUB mem) imm) zero));
13969
13970 ins_cost(125);
13971 format %{ "testb $mem, $imm\t# ubyte" %}
13972 ins_encode %{ __ testb($mem$$Address, $imm$$constant); %}
13973 ins_pipe(ialu_cr_reg_mem);
13974 %}
13975
13976 instruct testB_mem_imm(rFlagsReg cr, memory mem, immI8 imm, immI_0 zero)
13977 %{
13978 match(Set cr (CmpI (AndI (LoadB mem) imm) zero));
13979
13980 ins_cost(125);
13981 format %{ "testb $mem, $imm\t# byte" %}
13982 ins_encode %{ __ testb($mem$$Address, $imm$$constant); %}
13983 ins_pipe(ialu_cr_reg_mem);
13984 %}
13985
13986 //----------Max and Min--------------------------------------------------------
13987 // Min Instructions
13988
13989 instruct cmovI_reg_g(rRegI dst, rRegI src, rFlagsReg cr)
13990 %{
13991 predicate(!UseAPX);
13992 effect(USE_DEF dst, USE src, USE cr);
13993
13994 format %{ "cmovlgt $dst, $src\t# min" %}
13995 ins_encode %{
13996 __ cmovl(Assembler::greater, $dst$$Register, $src$$Register);
13997 %}
13998 ins_pipe(pipe_cmov_reg);
13999 %}
14000
14001 instruct cmovI_reg_g_ndd(rRegI dst, rRegI src1, rRegI src2, rFlagsReg cr)
14002 %{
14003 predicate(UseAPX);
14004 effect(DEF dst, USE src1, USE src2, USE cr);
14005
14006 format %{ "ecmovlgt $dst, $src1, $src2\t# min ndd" %}
14007 ins_encode %{
14008 __ ecmovl(Assembler::greater, $dst$$Register, $src1$$Register, $src2$$Register);
14009 %}
14010 ins_pipe(pipe_cmov_reg);
14011 %}
14012
14013 instruct minI_rReg(rRegI dst, rRegI src)
14014 %{
14015 predicate(!UseAPX);
14016 match(Set dst (MinI dst src));
14017
14018 ins_cost(200);
14019 expand %{
14020 rFlagsReg cr;
14021 compI_rReg(cr, dst, src);
14022 cmovI_reg_g(dst, src, cr);
14023 %}
14024 %}
14025
14026 instruct minI_rReg_ndd(rRegI dst, rRegI src1, rRegI src2)
14027 %{
14028 predicate(UseAPX);
14029 match(Set dst (MinI src1 src2));
14030 effect(DEF dst, USE src1, USE src2);
14031
14032 ins_cost(200);
14033 expand %{
14034 rFlagsReg cr;
14035 compI_rReg(cr, src1, src2);
14036 cmovI_reg_g_ndd(dst, src1, src2, cr);
14037 %}
14038 %}
14039
14040 instruct cmovI_reg_l(rRegI dst, rRegI src, rFlagsReg cr)
14041 %{
14042 predicate(!UseAPX);
14043 effect(USE_DEF dst, USE src, USE cr);
14044
14045 format %{ "cmovllt $dst, $src\t# max" %}
14046 ins_encode %{
14047 __ cmovl(Assembler::less, $dst$$Register, $src$$Register);
14048 %}
14049 ins_pipe(pipe_cmov_reg);
14050 %}
14051
14052 instruct cmovI_reg_l_ndd(rRegI dst, rRegI src1, rRegI src2, rFlagsReg cr)
14053 %{
14054 predicate(UseAPX);
14055 effect(DEF dst, USE src1, USE src2, USE cr);
14056
14057 format %{ "ecmovllt $dst, $src1, $src2\t# max ndd" %}
14058 ins_encode %{
14059 __ ecmovl(Assembler::less, $dst$$Register, $src1$$Register, $src2$$Register);
14060 %}
14061 ins_pipe(pipe_cmov_reg);
14062 %}
14063
14064 instruct maxI_rReg(rRegI dst, rRegI src)
14065 %{
14066 predicate(!UseAPX);
14067 match(Set dst (MaxI dst src));
14068
14069 ins_cost(200);
14070 expand %{
14071 rFlagsReg cr;
14072 compI_rReg(cr, dst, src);
14073 cmovI_reg_l(dst, src, cr);
14074 %}
14075 %}
14076
14077 instruct maxI_rReg_ndd(rRegI dst, rRegI src1, rRegI src2)
14078 %{
14079 predicate(UseAPX);
14080 match(Set dst (MaxI src1 src2));
14081 effect(DEF dst, USE src1, USE src2);
14082
14083 ins_cost(200);
14084 expand %{
14085 rFlagsReg cr;
14086 compI_rReg(cr, src1, src2);
14087 cmovI_reg_l_ndd(dst, src1, src2, cr);
14088 %}
14089 %}
14090
14091 // ============================================================================
14092 // Branch Instructions
14093
14094 // Jump Direct - Label defines a relative address from JMP+1
14095 instruct jmpDir(label labl)
14096 %{
14097 match(Goto);
14098 effect(USE labl);
14099
14100 ins_cost(300);
14101 format %{ "jmp $labl" %}
14102 size(5);
14103 ins_encode %{
14104 Label* L = $labl$$label;
14105 __ jmp(*L, false); // Always long jump
14106 %}
14107 ins_pipe(pipe_jmp);
14108 %}
14109
14110 // Jump Direct Conditional - Label defines a relative address from Jcc+1
14111 instruct jmpCon(cmpOp cop, rFlagsReg cr, label labl)
14112 %{
14113 match(If cop cr);
14114 effect(USE labl);
14115
14116 ins_cost(300);
14117 format %{ "j$cop $labl" %}
14118 size(6);
14119 ins_encode %{
14120 Label* L = $labl$$label;
14121 __ jcc((Assembler::Condition)($cop$$cmpcode), *L, false); // Always long jump
14122 %}
14123 ins_pipe(pipe_jcc);
14124 %}
14125
14126 // Jump Direct Conditional - Label defines a relative address from Jcc+1
14127 instruct jmpLoopEnd(cmpOp cop, rFlagsReg cr, label labl)
14128 %{
14129 match(CountedLoopEnd cop cr);
14130 effect(USE labl);
14131
14132 ins_cost(300);
14133 format %{ "j$cop $labl\t# loop end" %}
14134 size(6);
14135 ins_encode %{
14136 Label* L = $labl$$label;
14137 __ jcc((Assembler::Condition)($cop$$cmpcode), *L, false); // Always long jump
14138 %}
14139 ins_pipe(pipe_jcc);
14140 %}
14141
14142 // Jump Direct Conditional - using unsigned comparison
14143 instruct jmpConU(cmpOpU cop, rFlagsRegU cmp, label labl) %{
14144 match(If cop cmp);
14145 effect(USE labl);
14146
14147 ins_cost(300);
14148 format %{ "j$cop,u $labl" %}
14149 size(6);
14150 ins_encode %{
14151 Label* L = $labl$$label;
14152 __ jcc((Assembler::Condition)($cop$$cmpcode), *L, false); // Always long jump
14153 %}
14154 ins_pipe(pipe_jcc);
14155 %}
14156
14157 instruct jmpConUCF(cmpOpUCF cop, rFlagsRegUCF cmp, label labl) %{
14158 match(If cop cmp);
14159 effect(USE labl);
14160
14161 ins_cost(200);
14162 format %{ "j$cop,u $labl" %}
14163 size(6);
14164 ins_encode %{
14165 Label* L = $labl$$label;
14166 __ jcc((Assembler::Condition)($cop$$cmpcode), *L, false); // Always long jump
14167 %}
14168 ins_pipe(pipe_jcc);
14169 %}
14170
14171 instruct jmpConUCF2(cmpOpUCF2 cop, rFlagsRegUCF cmp, label labl) %{
14172 match(If cop cmp);
14173 effect(USE labl);
14174
14175 ins_cost(200);
14176 format %{ $$template
14177 if ($cop$$cmpcode == Assembler::notEqual) {
14178 $$emit$$"jp,u $labl\n\t"
14179 $$emit$$"j$cop,u $labl"
14180 } else {
14181 $$emit$$"jp,u done\n\t"
14182 $$emit$$"j$cop,u $labl\n\t"
14183 $$emit$$"done:"
14184 }
14185 %}
14186 ins_encode %{
14187 Label* l = $labl$$label;
14188 if ($cop$$cmpcode == Assembler::notEqual) {
14189 __ jcc(Assembler::parity, *l, false);
14190 __ jcc(Assembler::notEqual, *l, false);
14191 } else if ($cop$$cmpcode == Assembler::equal) {
14192 Label done;
14193 __ jccb(Assembler::parity, done);
14194 __ jcc(Assembler::equal, *l, false);
14195 __ bind(done);
14196 } else {
14197 ShouldNotReachHere();
14198 }
14199 %}
14200 ins_pipe(pipe_jcc);
14201 %}
14202
14203 // ============================================================================
14204 // The 2nd slow-half of a subtype check. Scan the subklass's 2ndary
14205 // superklass array for an instance of the superklass. Set a hidden
14206 // internal cache on a hit (cache is checked with exposed code in
14207 // gen_subtype_check()). Return NZ for a miss or zero for a hit. The
14208 // encoding ALSO sets flags.
14209
14210 instruct partialSubtypeCheck(rdi_RegP result,
14211 rsi_RegP sub, rax_RegP super, rcx_RegI rcx,
14212 rFlagsReg cr)
14213 %{
14214 match(Set result (PartialSubtypeCheck sub super));
14215 predicate(!UseSecondarySupersTable);
14216 effect(KILL rcx, KILL cr);
14217
14218 ins_cost(1100); // slightly larger than the next version
14219 format %{ "movq rdi, [$sub + in_bytes(Klass::secondary_supers_offset())]\n\t"
14220 "movl rcx, [rdi + Array<Klass*>::length_offset_in_bytes()]\t# length to scan\n\t"
14221 "addq rdi, Array<Klass*>::base_offset_in_bytes()\t# Skip to start of data; set NZ in case count is zero\n\t"
14222 "repne scasq\t# Scan *rdi++ for a match with rax while rcx--\n\t"
14223 "jne,s miss\t\t# Missed: rdi not-zero\n\t"
14224 "movq [$sub + in_bytes(Klass::secondary_super_cache_offset())], $super\t# Hit: update cache\n\t"
14225 "xorq $result, $result\t\t Hit: rdi zero\n\t"
14226 "miss:\t" %}
14227
14228 ins_encode %{
14229 Label miss;
14230 // NB: Callers may assume that, when $result is a valid register,
14231 // check_klass_subtype_slow_path_linear sets it to a nonzero
14232 // value.
14233 __ check_klass_subtype_slow_path_linear($sub$$Register, $super$$Register,
14234 $rcx$$Register, $result$$Register,
14235 nullptr, &miss,
14236 /*set_cond_codes:*/ true);
14237 __ xorptr($result$$Register, $result$$Register);
14238 __ bind(miss);
14239 %}
14240
14241 ins_pipe(pipe_slow);
14242 %}
14243
14244 // ============================================================================
14245 // Two versions of hashtable-based partialSubtypeCheck, both used when
14246 // we need to search for a super class in the secondary supers array.
14247 // The first is used when we don't know _a priori_ the class being
14248 // searched for. The second, far more common, is used when we do know:
14249 // this is used for instanceof, checkcast, and any case where C2 can
14250 // determine it by constant propagation.
14251
14252 instruct partialSubtypeCheckVarSuper(rsi_RegP sub, rax_RegP super, rdi_RegP result,
14253 rdx_RegL temp1, rcx_RegL temp2, rbx_RegP temp3, r11_RegL temp4,
14254 rFlagsReg cr)
14255 %{
14256 match(Set result (PartialSubtypeCheck sub super));
14257 predicate(UseSecondarySupersTable);
14258 effect(KILL cr, TEMP temp1, TEMP temp2, TEMP temp3, TEMP temp4);
14259
14260 ins_cost(1000);
14261 format %{ "partialSubtypeCheck $result, $sub, $super" %}
14262
14263 ins_encode %{
14264 __ lookup_secondary_supers_table_var($sub$$Register, $super$$Register, $temp1$$Register, $temp2$$Register,
14265 $temp3$$Register, $temp4$$Register, $result$$Register);
14266 %}
14267
14268 ins_pipe(pipe_slow);
14269 %}
14270
14271 instruct partialSubtypeCheckConstSuper(rsi_RegP sub, rax_RegP super_reg, immP super_con, rdi_RegP result,
14272 rdx_RegL temp1, rcx_RegL temp2, rbx_RegP temp3, r11_RegL temp4,
14273 rFlagsReg cr)
14274 %{
14275 match(Set result (PartialSubtypeCheck sub (Binary super_reg super_con)));
14276 predicate(UseSecondarySupersTable);
14277 effect(KILL cr, TEMP temp1, TEMP temp2, TEMP temp3, TEMP temp4);
14278
14279 ins_cost(700); // smaller than the next version
14280 format %{ "partialSubtypeCheck $result, $sub, $super_reg, $super_con" %}
14281
14282 ins_encode %{
14283 u1 super_klass_slot = ((Klass*)$super_con$$constant)->hash_slot();
14284 if (InlineSecondarySupersTest) {
14285 __ lookup_secondary_supers_table_const($sub$$Register, $super_reg$$Register, $temp1$$Register, $temp2$$Register,
14286 $temp3$$Register, $temp4$$Register, $result$$Register,
14287 super_klass_slot);
14288 } else {
14289 __ call(RuntimeAddress(StubRoutines::lookup_secondary_supers_table_stub(super_klass_slot)));
14290 }
14291 %}
14292
14293 ins_pipe(pipe_slow);
14294 %}
14295
14296 // ============================================================================
14297 // Branch Instructions -- short offset versions
14298 //
14299 // These instructions are used to replace jumps of a long offset (the default
14300 // match) with jumps of a shorter offset. These instructions are all tagged
14301 // with the ins_short_branch attribute, which causes the ADLC to suppress the
14302 // match rules in general matching. Instead, the ADLC generates a conversion
14303 // method in the MachNode which can be used to do in-place replacement of the
14304 // long variant with the shorter variant. The compiler will determine if a
14305 // branch can be taken by the is_short_branch_offset() predicate in the machine
14306 // specific code section of the file.
14307
14308 // Jump Direct - Label defines a relative address from JMP+1
14309 instruct jmpDir_short(label labl) %{
14310 match(Goto);
14311 effect(USE labl);
14312
14313 ins_cost(300);
14314 format %{ "jmp,s $labl" %}
14315 size(2);
14316 ins_encode %{
14317 Label* L = $labl$$label;
14318 __ jmpb(*L);
14319 %}
14320 ins_pipe(pipe_jmp);
14321 ins_short_branch(1);
14322 %}
14323
14324 // Jump Direct Conditional - Label defines a relative address from Jcc+1
14325 instruct jmpCon_short(cmpOp cop, rFlagsReg cr, label labl) %{
14326 match(If cop cr);
14327 effect(USE labl);
14328
14329 ins_cost(300);
14330 format %{ "j$cop,s $labl" %}
14331 size(2);
14332 ins_encode %{
14333 Label* L = $labl$$label;
14334 __ jccb((Assembler::Condition)($cop$$cmpcode), *L);
14335 %}
14336 ins_pipe(pipe_jcc);
14337 ins_short_branch(1);
14338 %}
14339
14340 // Jump Direct Conditional - Label defines a relative address from Jcc+1
14341 instruct jmpLoopEnd_short(cmpOp cop, rFlagsReg cr, label labl) %{
14342 match(CountedLoopEnd cop cr);
14343 effect(USE labl);
14344
14345 ins_cost(300);
14346 format %{ "j$cop,s $labl\t# loop end" %}
14347 size(2);
14348 ins_encode %{
14349 Label* L = $labl$$label;
14350 __ jccb((Assembler::Condition)($cop$$cmpcode), *L);
14351 %}
14352 ins_pipe(pipe_jcc);
14353 ins_short_branch(1);
14354 %}
14355
14356 // Jump Direct Conditional - using unsigned comparison
14357 instruct jmpConU_short(cmpOpU cop, rFlagsRegU cmp, label labl) %{
14358 match(If cop cmp);
14359 effect(USE labl);
14360
14361 ins_cost(300);
14362 format %{ "j$cop,us $labl" %}
14363 size(2);
14364 ins_encode %{
14365 Label* L = $labl$$label;
14366 __ jccb((Assembler::Condition)($cop$$cmpcode), *L);
14367 %}
14368 ins_pipe(pipe_jcc);
14369 ins_short_branch(1);
14370 %}
14371
14372 instruct jmpConUCF_short(cmpOpUCF cop, rFlagsRegUCF cmp, label labl) %{
14373 match(If cop cmp);
14374 effect(USE labl);
14375
14376 ins_cost(300);
14377 format %{ "j$cop,us $labl" %}
14378 size(2);
14379 ins_encode %{
14380 Label* L = $labl$$label;
14381 __ jccb((Assembler::Condition)($cop$$cmpcode), *L);
14382 %}
14383 ins_pipe(pipe_jcc);
14384 ins_short_branch(1);
14385 %}
14386
14387 instruct jmpConUCF2_short(cmpOpUCF2 cop, rFlagsRegUCF cmp, label labl) %{
14388 match(If cop cmp);
14389 effect(USE labl);
14390
14391 ins_cost(300);
14392 format %{ $$template
14393 if ($cop$$cmpcode == Assembler::notEqual) {
14394 $$emit$$"jp,u,s $labl\n\t"
14395 $$emit$$"j$cop,u,s $labl"
14396 } else {
14397 $$emit$$"jp,u,s done\n\t"
14398 $$emit$$"j$cop,u,s $labl\n\t"
14399 $$emit$$"done:"
14400 }
14401 %}
14402 size(4);
14403 ins_encode %{
14404 Label* l = $labl$$label;
14405 if ($cop$$cmpcode == Assembler::notEqual) {
14406 __ jccb(Assembler::parity, *l);
14407 __ jccb(Assembler::notEqual, *l);
14408 } else if ($cop$$cmpcode == Assembler::equal) {
14409 Label done;
14410 __ jccb(Assembler::parity, done);
14411 __ jccb(Assembler::equal, *l);
14412 __ bind(done);
14413 } else {
14414 ShouldNotReachHere();
14415 }
14416 %}
14417 ins_pipe(pipe_jcc);
14418 ins_short_branch(1);
14419 %}
14420
14421 // ============================================================================
14422 // inlined locking and unlocking
14423
14424 instruct cmpFastLockLightweight(rFlagsReg cr, rRegP object, rbx_RegP box, rax_RegI rax_reg, rRegP tmp) %{
14425 match(Set cr (FastLock object box));
14426 effect(TEMP rax_reg, TEMP tmp, USE_KILL box);
14427 ins_cost(300);
14428 format %{ "fastlock $object,$box\t! kills $box,$rax_reg,$tmp" %}
14429 ins_encode %{
14430 __ fast_lock_lightweight($object$$Register, $box$$Register, $rax_reg$$Register, $tmp$$Register, r15_thread);
14431 %}
14432 ins_pipe(pipe_slow);
14433 %}
14434
14435 instruct cmpFastUnlockLightweight(rFlagsReg cr, rRegP object, rax_RegP rax_reg, rRegP tmp) %{
14436 match(Set cr (FastUnlock object rax_reg));
14437 effect(TEMP tmp, USE_KILL rax_reg);
14438 ins_cost(300);
14439 format %{ "fastunlock $object,$rax_reg\t! kills $rax_reg,$tmp" %}
14440 ins_encode %{
14441 __ fast_unlock_lightweight($object$$Register, $rax_reg$$Register, $tmp$$Register, r15_thread);
14442 %}
14443 ins_pipe(pipe_slow);
14444 %}
14445
14446
14447 // ============================================================================
14448 // Safepoint Instructions
14449 instruct safePoint_poll_tls(rFlagsReg cr, rRegP poll)
14450 %{
14451 match(SafePoint poll);
14452 effect(KILL cr, USE poll);
14453
14454 format %{ "testl rax, [$poll]\t"
14455 "# Safepoint: poll for GC" %}
14456 ins_cost(125);
14457 ins_encode %{
14458 __ relocate(relocInfo::poll_type);
14459 address pre_pc = __ pc();
14460 __ testl(rax, Address($poll$$Register, 0));
14461 assert(nativeInstruction_at(pre_pc)->is_safepoint_poll(), "must emit test %%eax [reg]");
14462 %}
14463 ins_pipe(ialu_reg_mem);
14464 %}
14465
14466 instruct mask_all_evexL(kReg dst, rRegL src) %{
14467 match(Set dst (MaskAll src));
14468 format %{ "mask_all_evexL $dst, $src \t! mask all operation" %}
14469 ins_encode %{
14470 int mask_len = Matcher::vector_length(this);
14471 __ vector_maskall_operation($dst$$KRegister, $src$$Register, mask_len);
14472 %}
14473 ins_pipe( pipe_slow );
14474 %}
14475
14476 instruct mask_all_evexI_GT32(kReg dst, rRegI src, rRegL tmp) %{
14477 predicate(Matcher::vector_length(n) > 32);
14478 match(Set dst (MaskAll src));
14479 effect(TEMP tmp);
14480 format %{ "mask_all_evexI_GT32 $dst, $src \t! using $tmp as TEMP" %}
14481 ins_encode %{
14482 int mask_len = Matcher::vector_length(this);
14483 __ movslq($tmp$$Register, $src$$Register);
14484 __ vector_maskall_operation($dst$$KRegister, $tmp$$Register, mask_len);
14485 %}
14486 ins_pipe( pipe_slow );
14487 %}
14488
14489 // ============================================================================
14490 // Procedure Call/Return Instructions
14491 // Call Java Static Instruction
14492 // Note: If this code changes, the corresponding ret_addr_offset() and
14493 // compute_padding() functions will have to be adjusted.
14494 instruct CallStaticJavaDirect(method meth) %{
14495 match(CallStaticJava);
14496 effect(USE meth);
14497
14498 ins_cost(300);
14499 format %{ "call,static " %}
14500 opcode(0xE8); /* E8 cd */
14501 ins_encode(clear_avx, Java_Static_Call(meth), call_epilog);
14502 ins_pipe(pipe_slow);
14503 ins_alignment(4);
14504 %}
14505
14506 // Call Java Dynamic Instruction
14507 // Note: If this code changes, the corresponding ret_addr_offset() and
14508 // compute_padding() functions will have to be adjusted.
14509 instruct CallDynamicJavaDirect(method meth)
14510 %{
14511 match(CallDynamicJava);
14512 effect(USE meth);
14513
14514 ins_cost(300);
14515 format %{ "movq rax, #Universe::non_oop_word()\n\t"
14516 "call,dynamic " %}
14517 ins_encode(clear_avx, Java_Dynamic_Call(meth), call_epilog);
14518 ins_pipe(pipe_slow);
14519 ins_alignment(4);
14520 %}
14521
14522 // Call Runtime Instruction
14523 instruct CallRuntimeDirect(method meth)
14524 %{
14525 match(CallRuntime);
14526 effect(USE meth);
14527
14528 ins_cost(300);
14529 format %{ "call,runtime " %}
14530 ins_encode(clear_avx, Java_To_Runtime(meth));
14531 ins_pipe(pipe_slow);
14532 %}
14533
14534 // Call runtime without safepoint
14535 instruct CallLeafDirect(method meth)
14536 %{
14537 match(CallLeaf);
14538 effect(USE meth);
14539
14540 ins_cost(300);
14541 format %{ "call_leaf,runtime " %}
14542 ins_encode(clear_avx, Java_To_Runtime(meth));
14543 ins_pipe(pipe_slow);
14544 %}
14545
14546 // Call runtime without safepoint and with vector arguments
14547 instruct CallLeafDirectVector(method meth)
14548 %{
14549 match(CallLeafVector);
14550 effect(USE meth);
14551
14552 ins_cost(300);
14553 format %{ "call_leaf,vector " %}
14554 ins_encode(Java_To_Runtime(meth));
14555 ins_pipe(pipe_slow);
14556 %}
14557
14558 // Call runtime without safepoint
14559 // entry point is null, target holds the address to call
14560 instruct CallLeafNoFPInDirect(rRegP target)
14561 %{
14562 predicate(n->as_Call()->entry_point() == nullptr);
14563 match(CallLeafNoFP target);
14564
14565 ins_cost(300);
14566 format %{ "call_leaf_nofp,runtime indirect " %}
14567 ins_encode %{
14568 __ call($target$$Register);
14569 %}
14570
14571 ins_pipe(pipe_slow);
14572 %}
14573
14574 instruct CallLeafNoFPDirect(method meth)
14575 %{
14576 predicate(n->as_Call()->entry_point() != nullptr);
14577 match(CallLeafNoFP);
14578 effect(USE meth);
14579
14580 ins_cost(300);
14581 format %{ "call_leaf_nofp,runtime " %}
14582 ins_encode(clear_avx, Java_To_Runtime(meth));
14583 ins_pipe(pipe_slow);
14584 %}
14585
14586 // Return Instruction
14587 // Remove the return address & jump to it.
14588 // Notice: We always emit a nop after a ret to make sure there is room
14589 // for safepoint patching
14590 instruct Ret()
14591 %{
14592 match(Return);
14593
14594 format %{ "ret" %}
14595 ins_encode %{
14596 __ ret(0);
14597 %}
14598 ins_pipe(pipe_jmp);
14599 %}
14600
14601 // Tail Call; Jump from runtime stub to Java code.
14602 // Also known as an 'interprocedural jump'.
14603 // Target of jump will eventually return to caller.
14604 // TailJump below removes the return address.
14605 // Don't use rbp for 'jump_target' because a MachEpilogNode has already been
14606 // emitted just above the TailCall which has reset rbp to the caller state.
14607 instruct TailCalljmpInd(no_rbp_RegP jump_target, rbx_RegP method_ptr)
14608 %{
14609 match(TailCall jump_target method_ptr);
14610
14611 ins_cost(300);
14612 format %{ "jmp $jump_target\t# rbx holds method" %}
14613 ins_encode %{
14614 __ jmp($jump_target$$Register);
14615 %}
14616 ins_pipe(pipe_jmp);
14617 %}
14618
14619 // Tail Jump; remove the return address; jump to target.
14620 // TailCall above leaves the return address around.
14621 instruct tailjmpInd(no_rbp_RegP jump_target, rax_RegP ex_oop)
14622 %{
14623 match(TailJump jump_target ex_oop);
14624
14625 ins_cost(300);
14626 format %{ "popq rdx\t# pop return address\n\t"
14627 "jmp $jump_target" %}
14628 ins_encode %{
14629 __ popq(as_Register(RDX_enc));
14630 __ jmp($jump_target$$Register);
14631 %}
14632 ins_pipe(pipe_jmp);
14633 %}
14634
14635 // Forward exception.
14636 instruct ForwardExceptionjmp()
14637 %{
14638 match(ForwardException);
14639
14640 format %{ "jmp forward_exception_stub" %}
14641 ins_encode %{
14642 __ jump(RuntimeAddress(StubRoutines::forward_exception_entry()), noreg);
14643 %}
14644 ins_pipe(pipe_jmp);
14645 %}
14646
14647 // Create exception oop: created by stack-crawling runtime code.
14648 // Created exception is now available to this handler, and is setup
14649 // just prior to jumping to this handler. No code emitted.
14650 instruct CreateException(rax_RegP ex_oop)
14651 %{
14652 match(Set ex_oop (CreateEx));
14653
14654 size(0);
14655 // use the following format syntax
14656 format %{ "# exception oop is in rax; no code emitted" %}
14657 ins_encode();
14658 ins_pipe(empty);
14659 %}
14660
14661 // Rethrow exception:
14662 // The exception oop will come in the first argument position.
14663 // Then JUMP (not call) to the rethrow stub code.
14664 instruct RethrowException()
14665 %{
14666 match(Rethrow);
14667
14668 // use the following format syntax
14669 format %{ "jmp rethrow_stub" %}
14670 ins_encode %{
14671 __ jump(RuntimeAddress(OptoRuntime::rethrow_stub()), noreg);
14672 %}
14673 ins_pipe(pipe_jmp);
14674 %}
14675
14676 // ============================================================================
14677 // This name is KNOWN by the ADLC and cannot be changed.
14678 // The ADLC forces a 'TypeRawPtr::BOTTOM' output type
14679 // for this guy.
14680 instruct tlsLoadP(r15_RegP dst) %{
14681 match(Set dst (ThreadLocal));
14682 effect(DEF dst);
14683
14684 size(0);
14685 format %{ "# TLS is in R15" %}
14686 ins_encode( /*empty encoding*/ );
14687 ins_pipe(ialu_reg_reg);
14688 %}
14689
14690
14691 //----------PEEPHOLE RULES-----------------------------------------------------
14692 // These must follow all instruction definitions as they use the names
14693 // defined in the instructions definitions.
14694 //
14695 // peeppredicate ( rule_predicate );
14696 // // the predicate unless which the peephole rule will be ignored
14697 //
14698 // peepmatch ( root_instr_name [preceding_instruction]* );
14699 //
14700 // peepprocedure ( procedure_name );
14701 // // provide a procedure name to perform the optimization, the procedure should
14702 // // reside in the architecture dependent peephole file, the method has the
14703 // // signature of MachNode* (Block*, int, PhaseRegAlloc*, (MachNode*)(*)(), int...)
14704 // // with the arguments being the basic block, the current node index inside the
14705 // // block, the register allocator, the functions upon invoked return a new node
14706 // // defined in peepreplace, and the rules of the nodes appearing in the
14707 // // corresponding peepmatch, the function return true if successful, else
14708 // // return false
14709 //
14710 // peepconstraint %{
14711 // (instruction_number.operand_name relational_op instruction_number.operand_name
14712 // [, ...] );
14713 // // instruction numbers are zero-based using left to right order in peepmatch
14714 //
14715 // peepreplace ( instr_name ( [instruction_number.operand_name]* ) );
14716 // // provide an instruction_number.operand_name for each operand that appears
14717 // // in the replacement instruction's match rule
14718 //
14719 // ---------VM FLAGS---------------------------------------------------------
14720 //
14721 // All peephole optimizations can be turned off using -XX:-OptoPeephole
14722 //
14723 // Each peephole rule is given an identifying number starting with zero and
14724 // increasing by one in the order seen by the parser. An individual peephole
14725 // can be enabled, and all others disabled, by using -XX:OptoPeepholeAt=#
14726 // on the command-line.
14727 //
14728 // ---------CURRENT LIMITATIONS----------------------------------------------
14729 //
14730 // Only transformations inside a basic block (do we need more for peephole)
14731 //
14732 // ---------EXAMPLE----------------------------------------------------------
14733 //
14734 // // pertinent parts of existing instructions in architecture description
14735 // instruct movI(rRegI dst, rRegI src)
14736 // %{
14737 // match(Set dst (CopyI src));
14738 // %}
14739 //
14740 // instruct incI_rReg(rRegI dst, immI_1 src, rFlagsReg cr)
14741 // %{
14742 // match(Set dst (AddI dst src));
14743 // effect(KILL cr);
14744 // %}
14745 //
14746 // instruct leaI_rReg_immI(rRegI dst, immI_1 src)
14747 // %{
14748 // match(Set dst (AddI dst src));
14749 // %}
14750 //
14751 // 1. Simple replacement
14752 // - Only match adjacent instructions in same basic block
14753 // - Only equality constraints
14754 // - Only constraints between operands, not (0.dest_reg == RAX_enc)
14755 // - Only one replacement instruction
14756 //
14757 // // Change (inc mov) to lea
14758 // peephole %{
14759 // // lea should only be emitted when beneficial
14760 // peeppredicate( VM_Version::supports_fast_2op_lea() );
14761 // // increment preceded by register-register move
14762 // peepmatch ( incI_rReg movI );
14763 // // require that the destination register of the increment
14764 // // match the destination register of the move
14765 // peepconstraint ( 0.dst == 1.dst );
14766 // // construct a replacement instruction that sets
14767 // // the destination to ( move's source register + one )
14768 // peepreplace ( leaI_rReg_immI( 0.dst 1.src 0.src ) );
14769 // %}
14770 //
14771 // 2. Procedural replacement
14772 // - More flexible finding relevent nodes
14773 // - More flexible constraints
14774 // - More flexible transformations
14775 // - May utilise architecture-dependent API more effectively
14776 // - Currently only one replacement instruction due to adlc parsing capabilities
14777 //
14778 // // Change (inc mov) to lea
14779 // peephole %{
14780 // // lea should only be emitted when beneficial
14781 // peeppredicate( VM_Version::supports_fast_2op_lea() );
14782 // // the rule numbers of these nodes inside are passed into the function below
14783 // peepmatch ( incI_rReg movI );
14784 // // the method that takes the responsibility of transformation
14785 // peepprocedure ( inc_mov_to_lea );
14786 // // the replacement is a leaI_rReg_immI, a lambda upon invoked creating this
14787 // // node is passed into the function above
14788 // peepreplace ( leaI_rReg_immI() );
14789 // %}
14790
14791 // These instructions is not matched by the matcher but used by the peephole
14792 instruct leaI_rReg_rReg_peep(rRegI dst, rRegI src1, rRegI src2)
14793 %{
14794 predicate(false);
14795 match(Set dst (AddI src1 src2));
14796 format %{ "leal $dst, [$src1 + $src2]" %}
14797 ins_encode %{
14798 Register dst = $dst$$Register;
14799 Register src1 = $src1$$Register;
14800 Register src2 = $src2$$Register;
14801 if (src1 != rbp && src1 != r13) {
14802 __ leal(dst, Address(src1, src2, Address::times_1));
14803 } else {
14804 assert(src2 != rbp && src2 != r13, "");
14805 __ leal(dst, Address(src2, src1, Address::times_1));
14806 }
14807 %}
14808 ins_pipe(ialu_reg_reg);
14809 %}
14810
14811 instruct leaI_rReg_immI_peep(rRegI dst, rRegI src1, immI src2)
14812 %{
14813 predicate(false);
14814 match(Set dst (AddI src1 src2));
14815 format %{ "leal $dst, [$src1 + $src2]" %}
14816 ins_encode %{
14817 __ leal($dst$$Register, Address($src1$$Register, $src2$$constant));
14818 %}
14819 ins_pipe(ialu_reg_reg);
14820 %}
14821
14822 instruct leaI_rReg_immI2_peep(rRegI dst, rRegI src, immI2 shift)
14823 %{
14824 predicate(false);
14825 match(Set dst (LShiftI src shift));
14826 format %{ "leal $dst, [$src << $shift]" %}
14827 ins_encode %{
14828 Address::ScaleFactor scale = static_cast<Address::ScaleFactor>($shift$$constant);
14829 Register src = $src$$Register;
14830 if (scale == Address::times_2 && src != rbp && src != r13) {
14831 __ leal($dst$$Register, Address(src, src, Address::times_1));
14832 } else {
14833 __ leal($dst$$Register, Address(noreg, src, scale));
14834 }
14835 %}
14836 ins_pipe(ialu_reg_reg);
14837 %}
14838
14839 instruct leaL_rReg_rReg_peep(rRegL dst, rRegL src1, rRegL src2)
14840 %{
14841 predicate(false);
14842 match(Set dst (AddL src1 src2));
14843 format %{ "leaq $dst, [$src1 + $src2]" %}
14844 ins_encode %{
14845 Register dst = $dst$$Register;
14846 Register src1 = $src1$$Register;
14847 Register src2 = $src2$$Register;
14848 if (src1 != rbp && src1 != r13) {
14849 __ leaq(dst, Address(src1, src2, Address::times_1));
14850 } else {
14851 assert(src2 != rbp && src2 != r13, "");
14852 __ leaq(dst, Address(src2, src1, Address::times_1));
14853 }
14854 %}
14855 ins_pipe(ialu_reg_reg);
14856 %}
14857
14858 instruct leaL_rReg_immL32_peep(rRegL dst, rRegL src1, immL32 src2)
14859 %{
14860 predicate(false);
14861 match(Set dst (AddL src1 src2));
14862 format %{ "leaq $dst, [$src1 + $src2]" %}
14863 ins_encode %{
14864 __ leaq($dst$$Register, Address($src1$$Register, $src2$$constant));
14865 %}
14866 ins_pipe(ialu_reg_reg);
14867 %}
14868
14869 instruct leaL_rReg_immI2_peep(rRegL dst, rRegL src, immI2 shift)
14870 %{
14871 predicate(false);
14872 match(Set dst (LShiftL src shift));
14873 format %{ "leaq $dst, [$src << $shift]" %}
14874 ins_encode %{
14875 Address::ScaleFactor scale = static_cast<Address::ScaleFactor>($shift$$constant);
14876 Register src = $src$$Register;
14877 if (scale == Address::times_2 && src != rbp && src != r13) {
14878 __ leaq($dst$$Register, Address(src, src, Address::times_1));
14879 } else {
14880 __ leaq($dst$$Register, Address(noreg, src, scale));
14881 }
14882 %}
14883 ins_pipe(ialu_reg_reg);
14884 %}
14885
14886 // These peephole rules replace mov + I pairs (where I is one of {add, inc, dec,
14887 // sal}) with lea instructions. The {add, sal} rules are beneficial in
14888 // processors with at least partial ALU support for lea
14889 // (supports_fast_2op_lea()), whereas the {inc, dec} rules are only generally
14890 // beneficial for processors with full ALU support
14891 // (VM_Version::supports_fast_3op_lea()) and Intel Cascade Lake.
14892
14893 peephole
14894 %{
14895 peeppredicate(VM_Version::supports_fast_2op_lea());
14896 peepmatch (addI_rReg);
14897 peepprocedure (lea_coalesce_reg);
14898 peepreplace (leaI_rReg_rReg_peep());
14899 %}
14900
14901 peephole
14902 %{
14903 peeppredicate(VM_Version::supports_fast_2op_lea());
14904 peepmatch (addI_rReg_imm);
14905 peepprocedure (lea_coalesce_imm);
14906 peepreplace (leaI_rReg_immI_peep());
14907 %}
14908
14909 peephole
14910 %{
14911 peeppredicate(VM_Version::supports_fast_3op_lea() ||
14912 VM_Version::is_intel_cascade_lake());
14913 peepmatch (incI_rReg);
14914 peepprocedure (lea_coalesce_imm);
14915 peepreplace (leaI_rReg_immI_peep());
14916 %}
14917
14918 peephole
14919 %{
14920 peeppredicate(VM_Version::supports_fast_3op_lea() ||
14921 VM_Version::is_intel_cascade_lake());
14922 peepmatch (decI_rReg);
14923 peepprocedure (lea_coalesce_imm);
14924 peepreplace (leaI_rReg_immI_peep());
14925 %}
14926
14927 peephole
14928 %{
14929 peeppredicate(VM_Version::supports_fast_2op_lea());
14930 peepmatch (salI_rReg_immI2);
14931 peepprocedure (lea_coalesce_imm);
14932 peepreplace (leaI_rReg_immI2_peep());
14933 %}
14934
14935 peephole
14936 %{
14937 peeppredicate(VM_Version::supports_fast_2op_lea());
14938 peepmatch (addL_rReg);
14939 peepprocedure (lea_coalesce_reg);
14940 peepreplace (leaL_rReg_rReg_peep());
14941 %}
14942
14943 peephole
14944 %{
14945 peeppredicate(VM_Version::supports_fast_2op_lea());
14946 peepmatch (addL_rReg_imm);
14947 peepprocedure (lea_coalesce_imm);
14948 peepreplace (leaL_rReg_immL32_peep());
14949 %}
14950
14951 peephole
14952 %{
14953 peeppredicate(VM_Version::supports_fast_3op_lea() ||
14954 VM_Version::is_intel_cascade_lake());
14955 peepmatch (incL_rReg);
14956 peepprocedure (lea_coalesce_imm);
14957 peepreplace (leaL_rReg_immL32_peep());
14958 %}
14959
14960 peephole
14961 %{
14962 peeppredicate(VM_Version::supports_fast_3op_lea() ||
14963 VM_Version::is_intel_cascade_lake());
14964 peepmatch (decL_rReg);
14965 peepprocedure (lea_coalesce_imm);
14966 peepreplace (leaL_rReg_immL32_peep());
14967 %}
14968
14969 peephole
14970 %{
14971 peeppredicate(VM_Version::supports_fast_2op_lea());
14972 peepmatch (salL_rReg_immI2);
14973 peepprocedure (lea_coalesce_imm);
14974 peepreplace (leaL_rReg_immI2_peep());
14975 %}
14976
14977 peephole
14978 %{
14979 peepmatch (leaPCompressedOopOffset);
14980 peepprocedure (lea_remove_redundant);
14981 %}
14982
14983 peephole
14984 %{
14985 peepmatch (leaP8Narrow);
14986 peepprocedure (lea_remove_redundant);
14987 %}
14988
14989 peephole
14990 %{
14991 peepmatch (leaP32Narrow);
14992 peepprocedure (lea_remove_redundant);
14993 %}
14994
14995 // These peephole rules matches instructions which set flags and are followed by a testI/L_reg
14996 // The test instruction is redudanent in case the downstream instuctions (like JCC or CMOV) only use flags that are already set by the previous instruction
14997
14998 //int variant
14999 peephole
15000 %{
15001 peepmatch (testI_reg);
15002 peepprocedure (test_may_remove);
15003 %}
15004
15005 //long variant
15006 peephole
15007 %{
15008 peepmatch (testL_reg);
15009 peepprocedure (test_may_remove);
15010 %}
15011
15012
15013 //----------SMARTSPILL RULES---------------------------------------------------
15014 // These must follow all instruction definitions as they use the names
15015 // defined in the instructions definitions.