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 int offset = 13; // movq r10,#addr; callq (r10)
619 if (this->ideal_Opcode() != Op_CallLeafVector) {
620 offset += clear_avx_size();
621 }
622 return offset;
623 }
624 //
625 // Compute padding required for nodes which need alignment
626 //
627
628 // The address of the call instruction needs to be 4-byte aligned to
629 // ensure that it does not span a cache line so that it can be patched.
630 int CallStaticJavaDirectNode::compute_padding(int current_offset) const
631 {
632 current_offset += clear_avx_size(); // skip vzeroupper
633 current_offset += 1; // skip call opcode byte
634 return align_up(current_offset, alignment_required()) - current_offset;
635 }
636
637 // The address of the call instruction needs to be 4-byte aligned to
638 // ensure that it does not span a cache line so that it can be patched.
639 int CallDynamicJavaDirectNode::compute_padding(int current_offset) const
640 {
641 current_offset += clear_avx_size(); // skip vzeroupper
642 current_offset += 11; // skip movq instruction + call opcode byte
643 return align_up(current_offset, alignment_required()) - current_offset;
644 }
645
646 // This could be in MacroAssembler but it's fairly C2 specific
647 static void emit_cmpfp_fixup(MacroAssembler* masm) {
648 Label exit;
649 __ jccb(Assembler::noParity, exit);
650 __ pushf();
651 //
652 // comiss/ucomiss instructions set ZF,PF,CF flags and
653 // zero OF,AF,SF for NaN values.
654 // Fixup flags by zeroing ZF,PF so that compare of NaN
655 // values returns 'less than' result (CF is set).
656 // Leave the rest of flags unchanged.
657 //
658 // 7 6 5 4 3 2 1 0
659 // |S|Z|r|A|r|P|r|C| (r - reserved bit)
660 // 0 0 1 0 1 0 1 1 (0x2B)
661 //
662 __ andq(Address(rsp, 0), 0xffffff2b);
663 __ popf();
664 __ bind(exit);
665 }
666
667 static void emit_cmpfp3(MacroAssembler* masm, Register dst) {
668 Label done;
669 __ movl(dst, -1);
670 __ jcc(Assembler::parity, done);
671 __ jcc(Assembler::below, done);
672 __ setcc(Assembler::notEqual, dst);
673 __ bind(done);
674 }
675
676 // Math.min() # Math.max()
677 // --------------------------
678 // ucomis[s/d] #
679 // ja -> b # a
680 // jp -> NaN # NaN
681 // jb -> a # b
682 // je #
683 // |-jz -> a | b # a & b
684 // | -> a #
685 static void emit_fp_min_max(MacroAssembler* masm, XMMRegister dst,
686 XMMRegister a, XMMRegister b,
687 XMMRegister xmmt, Register rt,
688 bool min, bool single) {
689
690 Label nan, zero, below, above, done;
691
692 if (single)
693 __ ucomiss(a, b);
694 else
695 __ ucomisd(a, b);
696
697 if (dst->encoding() != (min ? b : a)->encoding())
698 __ jccb(Assembler::above, above); // CF=0 & ZF=0
699 else
700 __ jccb(Assembler::above, done);
701
702 __ jccb(Assembler::parity, nan); // PF=1
703 __ jccb(Assembler::below, below); // CF=1
704
705 // equal
706 __ vpxor(xmmt, xmmt, xmmt, Assembler::AVX_128bit);
707 if (single) {
708 __ ucomiss(a, xmmt);
709 __ jccb(Assembler::equal, zero);
710
711 __ movflt(dst, a);
712 __ jmp(done);
713 }
714 else {
715 __ ucomisd(a, xmmt);
716 __ jccb(Assembler::equal, zero);
717
718 __ movdbl(dst, a);
719 __ jmp(done);
720 }
721
722 __ bind(zero);
723 if (min)
724 __ vpor(dst, a, b, Assembler::AVX_128bit);
725 else
726 __ vpand(dst, a, b, Assembler::AVX_128bit);
727
728 __ jmp(done);
729
730 __ bind(above);
731 if (single)
732 __ movflt(dst, min ? b : a);
733 else
734 __ movdbl(dst, min ? b : a);
735
736 __ jmp(done);
737
738 __ bind(nan);
739 if (single) {
740 __ movl(rt, 0x7fc00000); // Float.NaN
741 __ movdl(dst, rt);
742 }
743 else {
744 __ mov64(rt, 0x7ff8000000000000L); // Double.NaN
745 __ movdq(dst, rt);
746 }
747 __ jmp(done);
748
749 __ bind(below);
750 if (single)
751 __ movflt(dst, min ? a : b);
752 else
753 __ movdbl(dst, min ? a : b);
754
755 __ bind(done);
756 }
757
758 //=============================================================================
759 const RegMask& MachConstantBaseNode::_out_RegMask = RegMask::Empty;
760
761 int ConstantTable::calculate_table_base_offset() const {
762 return 0; // absolute addressing, no offset
763 }
764
765 bool MachConstantBaseNode::requires_postalloc_expand() const { return false; }
766 void MachConstantBaseNode::postalloc_expand(GrowableArray <Node *> *nodes, PhaseRegAlloc *ra_) {
767 ShouldNotReachHere();
768 }
769
770 void MachConstantBaseNode::emit(C2_MacroAssembler* masm, PhaseRegAlloc* ra_) const {
771 // Empty encoding
772 }
773
774 uint MachConstantBaseNode::size(PhaseRegAlloc* ra_) const {
775 return 0;
776 }
777
778 #ifndef PRODUCT
779 void MachConstantBaseNode::format(PhaseRegAlloc* ra_, outputStream* st) const {
780 st->print("# MachConstantBaseNode (empty encoding)");
781 }
782 #endif
783
784
785 //=============================================================================
786 #ifndef PRODUCT
787 void MachPrologNode::format(PhaseRegAlloc* ra_, outputStream* st) const {
788 Compile* C = ra_->C;
789
790 int framesize = C->output()->frame_size_in_bytes();
791 int bangsize = C->output()->bang_size_in_bytes();
792 assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned");
793 // Remove wordSize for return addr which is already pushed.
794 framesize -= wordSize;
795
796 if (C->output()->need_stack_bang(bangsize)) {
797 framesize -= wordSize;
798 st->print("# stack bang (%d bytes)", bangsize);
799 st->print("\n\t");
800 st->print("pushq rbp\t# Save rbp");
801 if (PreserveFramePointer) {
802 st->print("\n\t");
803 st->print("movq rbp, rsp\t# Save the caller's SP into rbp");
804 }
805 if (framesize) {
806 st->print("\n\t");
807 st->print("subq rsp, #%d\t# Create frame",framesize);
808 }
809 } else {
810 st->print("subq rsp, #%d\t# Create frame",framesize);
811 st->print("\n\t");
812 framesize -= wordSize;
813 st->print("movq [rsp + #%d], rbp\t# Save rbp",framesize);
814 if (PreserveFramePointer) {
815 st->print("\n\t");
816 st->print("movq rbp, rsp\t# Save the caller's SP into rbp");
817 if (framesize > 0) {
818 st->print("\n\t");
819 st->print("addq rbp, #%d", framesize);
820 }
821 }
822 }
823
824 if (VerifyStackAtCalls) {
825 st->print("\n\t");
826 framesize -= wordSize;
827 st->print("movq [rsp + #%d], 0xbadb100d\t# Majik cookie for stack depth check",framesize);
828 #ifdef ASSERT
829 st->print("\n\t");
830 st->print("# stack alignment check");
831 #endif
832 }
833 if (C->stub_function() != nullptr) {
834 st->print("\n\t");
835 st->print("cmpl [r15_thread + #disarmed_guard_value_offset], #disarmed_guard_value\t");
836 st->print("\n\t");
837 st->print("je fast_entry\t");
838 st->print("\n\t");
839 st->print("call #nmethod_entry_barrier_stub\t");
840 st->print("\n\tfast_entry:");
841 }
842 st->cr();
843 }
844 #endif
845
846 void MachPrologNode::emit(C2_MacroAssembler *masm, PhaseRegAlloc *ra_) const {
847 Compile* C = ra_->C;
848
849 int framesize = C->output()->frame_size_in_bytes();
850 int bangsize = C->output()->bang_size_in_bytes();
851
852 if (C->clinit_barrier_on_entry()) {
853 assert(VM_Version::supports_fast_class_init_checks(), "sanity");
854 assert(!C->method()->holder()->is_not_initialized(), "initialization should have been started");
855
856 Label L_skip_barrier;
857 Register klass = rscratch1;
858
859 __ mov_metadata(klass, C->method()->holder()->constant_encoding());
860 __ clinit_barrier(klass, &L_skip_barrier /*L_fast_path*/);
861
862 __ jump(RuntimeAddress(SharedRuntime::get_handle_wrong_method_stub())); // slow path
863
864 __ bind(L_skip_barrier);
865 }
866
867 __ verified_entry(framesize, C->output()->need_stack_bang(bangsize)?bangsize:0, false, C->stub_function() != nullptr);
868
869 C->output()->set_frame_complete(__ offset());
870
871 if (C->has_mach_constant_base_node()) {
872 // NOTE: We set the table base offset here because users might be
873 // emitted before MachConstantBaseNode.
874 ConstantTable& constant_table = C->output()->constant_table();
875 constant_table.set_table_base_offset(constant_table.calculate_table_base_offset());
876 }
877 }
878
879 uint MachPrologNode::size(PhaseRegAlloc* ra_) const
880 {
881 return MachNode::size(ra_); // too many variables; just compute it
882 // the hard way
883 }
884
885 int MachPrologNode::reloc() const
886 {
887 return 0; // a large enough number
888 }
889
890 //=============================================================================
891 #ifndef PRODUCT
892 void MachEpilogNode::format(PhaseRegAlloc* ra_, outputStream* st) const
893 {
894 Compile* C = ra_->C;
895 if (generate_vzeroupper(C)) {
896 st->print("vzeroupper");
897 st->cr(); st->print("\t");
898 }
899
900 int framesize = C->output()->frame_size_in_bytes();
901 assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned");
902 // Remove word for return adr already pushed
903 // and RBP
904 framesize -= 2*wordSize;
905
906 if (framesize) {
907 st->print_cr("addq rsp, %d\t# Destroy frame", framesize);
908 st->print("\t");
909 }
910
911 st->print_cr("popq rbp");
912 if (do_polling() && C->is_method_compilation()) {
913 st->print("\t");
914 st->print_cr("cmpq rsp, poll_offset[r15_thread] \n\t"
915 "ja #safepoint_stub\t"
916 "# Safepoint: poll for GC");
917 }
918 }
919 #endif
920
921 void MachEpilogNode::emit(C2_MacroAssembler* masm, PhaseRegAlloc* ra_) const
922 {
923 Compile* C = ra_->C;
924
925 if (generate_vzeroupper(C)) {
926 // Clear upper bits of YMM registers when current compiled code uses
927 // wide vectors to avoid AVX <-> SSE transition penalty during call.
928 __ vzeroupper();
929 }
930
931 int framesize = C->output()->frame_size_in_bytes();
932 assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned");
933 // Remove word for return adr already pushed
934 // and RBP
935 framesize -= 2*wordSize;
936
937 // Note that VerifyStackAtCalls' Majik cookie does not change the frame size popped here
938
939 if (framesize) {
940 __ addq(rsp, framesize);
941 }
942
943 __ popq(rbp);
944
945 if (StackReservedPages > 0 && C->has_reserved_stack_access()) {
946 __ reserved_stack_check();
947 }
948
949 if (do_polling() && C->is_method_compilation()) {
950 Label dummy_label;
951 Label* code_stub = &dummy_label;
952 if (!C->output()->in_scratch_emit_size()) {
953 C2SafepointPollStub* stub = new (C->comp_arena()) C2SafepointPollStub(__ offset());
954 C->output()->add_stub(stub);
955 code_stub = &stub->entry();
956 }
957 __ relocate(relocInfo::poll_return_type);
958 __ safepoint_poll(*code_stub, true /* at_return */, true /* in_nmethod */);
959 }
960 }
961
962 uint MachEpilogNode::size(PhaseRegAlloc* ra_) const
963 {
964 return MachNode::size(ra_); // too many variables; just compute it
965 // the hard way
966 }
967
968 int MachEpilogNode::reloc() const
969 {
970 return 2; // a large enough number
971 }
972
973 const Pipeline* MachEpilogNode::pipeline() const
974 {
975 return MachNode::pipeline_class();
976 }
977
978 //=============================================================================
979
980 enum RC {
981 rc_bad,
982 rc_int,
983 rc_kreg,
984 rc_float,
985 rc_stack
986 };
987
988 static enum RC rc_class(OptoReg::Name reg)
989 {
990 if( !OptoReg::is_valid(reg) ) return rc_bad;
991
992 if (OptoReg::is_stack(reg)) return rc_stack;
993
994 VMReg r = OptoReg::as_VMReg(reg);
995
996 if (r->is_Register()) return rc_int;
997
998 if (r->is_KRegister()) return rc_kreg;
999
1000 assert(r->is_XMMRegister(), "must be");
1001 return rc_float;
1002 }
1003
1004 // Next two methods are shared by 32- and 64-bit VM. They are defined in x86.ad.
1005 static void vec_mov_helper(C2_MacroAssembler *masm, int src_lo, int dst_lo,
1006 int src_hi, int dst_hi, uint ireg, outputStream* st);
1007
1008 void vec_spill_helper(C2_MacroAssembler *masm, bool is_load,
1009 int stack_offset, int reg, uint ireg, outputStream* st);
1010
1011 static void vec_stack_to_stack_helper(C2_MacroAssembler *masm, int src_offset,
1012 int dst_offset, uint ireg, outputStream* st) {
1013 if (masm) {
1014 switch (ireg) {
1015 case Op_VecS:
1016 __ movq(Address(rsp, -8), rax);
1017 __ movl(rax, Address(rsp, src_offset));
1018 __ movl(Address(rsp, dst_offset), rax);
1019 __ movq(rax, Address(rsp, -8));
1020 break;
1021 case Op_VecD:
1022 __ pushq(Address(rsp, src_offset));
1023 __ popq (Address(rsp, dst_offset));
1024 break;
1025 case Op_VecX:
1026 __ pushq(Address(rsp, src_offset));
1027 __ popq (Address(rsp, dst_offset));
1028 __ pushq(Address(rsp, src_offset+8));
1029 __ popq (Address(rsp, dst_offset+8));
1030 break;
1031 case Op_VecY:
1032 __ vmovdqu(Address(rsp, -32), xmm0);
1033 __ vmovdqu(xmm0, Address(rsp, src_offset));
1034 __ vmovdqu(Address(rsp, dst_offset), xmm0);
1035 __ vmovdqu(xmm0, Address(rsp, -32));
1036 break;
1037 case Op_VecZ:
1038 __ evmovdquq(Address(rsp, -64), xmm0, 2);
1039 __ evmovdquq(xmm0, Address(rsp, src_offset), 2);
1040 __ evmovdquq(Address(rsp, dst_offset), xmm0, 2);
1041 __ evmovdquq(xmm0, Address(rsp, -64), 2);
1042 break;
1043 default:
1044 ShouldNotReachHere();
1045 }
1046 #ifndef PRODUCT
1047 } else {
1048 switch (ireg) {
1049 case Op_VecS:
1050 st->print("movq [rsp - #8], rax\t# 32-bit mem-mem spill\n\t"
1051 "movl rax, [rsp + #%d]\n\t"
1052 "movl [rsp + #%d], rax\n\t"
1053 "movq rax, [rsp - #8]",
1054 src_offset, dst_offset);
1055 break;
1056 case Op_VecD:
1057 st->print("pushq [rsp + #%d]\t# 64-bit mem-mem spill\n\t"
1058 "popq [rsp + #%d]",
1059 src_offset, dst_offset);
1060 break;
1061 case Op_VecX:
1062 st->print("pushq [rsp + #%d]\t# 128-bit mem-mem spill\n\t"
1063 "popq [rsp + #%d]\n\t"
1064 "pushq [rsp + #%d]\n\t"
1065 "popq [rsp + #%d]",
1066 src_offset, dst_offset, src_offset+8, dst_offset+8);
1067 break;
1068 case Op_VecY:
1069 st->print("vmovdqu [rsp - #32], xmm0\t# 256-bit mem-mem spill\n\t"
1070 "vmovdqu xmm0, [rsp + #%d]\n\t"
1071 "vmovdqu [rsp + #%d], xmm0\n\t"
1072 "vmovdqu xmm0, [rsp - #32]",
1073 src_offset, dst_offset);
1074 break;
1075 case Op_VecZ:
1076 st->print("vmovdqu [rsp - #64], xmm0\t# 512-bit mem-mem spill\n\t"
1077 "vmovdqu xmm0, [rsp + #%d]\n\t"
1078 "vmovdqu [rsp + #%d], xmm0\n\t"
1079 "vmovdqu xmm0, [rsp - #64]",
1080 src_offset, dst_offset);
1081 break;
1082 default:
1083 ShouldNotReachHere();
1084 }
1085 #endif
1086 }
1087 }
1088
1089 uint MachSpillCopyNode::implementation(C2_MacroAssembler* masm,
1090 PhaseRegAlloc* ra_,
1091 bool do_size,
1092 outputStream* st) const {
1093 assert(masm != nullptr || st != nullptr, "sanity");
1094 // Get registers to move
1095 OptoReg::Name src_second = ra_->get_reg_second(in(1));
1096 OptoReg::Name src_first = ra_->get_reg_first(in(1));
1097 OptoReg::Name dst_second = ra_->get_reg_second(this);
1098 OptoReg::Name dst_first = ra_->get_reg_first(this);
1099
1100 enum RC src_second_rc = rc_class(src_second);
1101 enum RC src_first_rc = rc_class(src_first);
1102 enum RC dst_second_rc = rc_class(dst_second);
1103 enum RC dst_first_rc = rc_class(dst_first);
1104
1105 assert(OptoReg::is_valid(src_first) && OptoReg::is_valid(dst_first),
1106 "must move at least 1 register" );
1107
1108 if (src_first == dst_first && src_second == dst_second) {
1109 // Self copy, no move
1110 return 0;
1111 }
1112 if (bottom_type()->isa_vect() != nullptr && bottom_type()->isa_vectmask() == nullptr) {
1113 uint ireg = ideal_reg();
1114 assert((src_first_rc != rc_int && dst_first_rc != rc_int), "sanity");
1115 assert((ireg == Op_VecS || ireg == Op_VecD || ireg == Op_VecX || ireg == Op_VecY || ireg == Op_VecZ ), "sanity");
1116 if( src_first_rc == rc_stack && dst_first_rc == rc_stack ) {
1117 // mem -> mem
1118 int src_offset = ra_->reg2offset(src_first);
1119 int dst_offset = ra_->reg2offset(dst_first);
1120 vec_stack_to_stack_helper(masm, src_offset, dst_offset, ireg, st);
1121 } else if (src_first_rc == rc_float && dst_first_rc == rc_float ) {
1122 vec_mov_helper(masm, src_first, dst_first, src_second, dst_second, ireg, st);
1123 } else if (src_first_rc == rc_float && dst_first_rc == rc_stack ) {
1124 int stack_offset = ra_->reg2offset(dst_first);
1125 vec_spill_helper(masm, false, stack_offset, src_first, ireg, st);
1126 } else if (src_first_rc == rc_stack && dst_first_rc == rc_float ) {
1127 int stack_offset = ra_->reg2offset(src_first);
1128 vec_spill_helper(masm, true, stack_offset, dst_first, ireg, st);
1129 } else {
1130 ShouldNotReachHere();
1131 }
1132 return 0;
1133 }
1134 if (src_first_rc == rc_stack) {
1135 // mem ->
1136 if (dst_first_rc == rc_stack) {
1137 // mem -> mem
1138 assert(src_second != dst_first, "overlap");
1139 if ((src_first & 1) == 0 && src_first + 1 == src_second &&
1140 (dst_first & 1) == 0 && dst_first + 1 == dst_second) {
1141 // 64-bit
1142 int src_offset = ra_->reg2offset(src_first);
1143 int dst_offset = ra_->reg2offset(dst_first);
1144 if (masm) {
1145 __ pushq(Address(rsp, src_offset));
1146 __ popq (Address(rsp, dst_offset));
1147 #ifndef PRODUCT
1148 } else {
1149 st->print("pushq [rsp + #%d]\t# 64-bit mem-mem spill\n\t"
1150 "popq [rsp + #%d]",
1151 src_offset, dst_offset);
1152 #endif
1153 }
1154 } else {
1155 // 32-bit
1156 assert(!((src_first & 1) == 0 && src_first + 1 == src_second), "no transform");
1157 assert(!((dst_first & 1) == 0 && dst_first + 1 == dst_second), "no transform");
1158 // No pushl/popl, so:
1159 int src_offset = ra_->reg2offset(src_first);
1160 int dst_offset = ra_->reg2offset(dst_first);
1161 if (masm) {
1162 __ movq(Address(rsp, -8), rax);
1163 __ movl(rax, Address(rsp, src_offset));
1164 __ movl(Address(rsp, dst_offset), rax);
1165 __ movq(rax, Address(rsp, -8));
1166 #ifndef PRODUCT
1167 } else {
1168 st->print("movq [rsp - #8], rax\t# 32-bit mem-mem spill\n\t"
1169 "movl rax, [rsp + #%d]\n\t"
1170 "movl [rsp + #%d], rax\n\t"
1171 "movq rax, [rsp - #8]",
1172 src_offset, dst_offset);
1173 #endif
1174 }
1175 }
1176 return 0;
1177 } else if (dst_first_rc == rc_int) {
1178 // mem -> gpr
1179 if ((src_first & 1) == 0 && src_first + 1 == src_second &&
1180 (dst_first & 1) == 0 && dst_first + 1 == dst_second) {
1181 // 64-bit
1182 int offset = ra_->reg2offset(src_first);
1183 if (masm) {
1184 __ movq(as_Register(Matcher::_regEncode[dst_first]), Address(rsp, offset));
1185 #ifndef PRODUCT
1186 } else {
1187 st->print("movq %s, [rsp + #%d]\t# spill",
1188 Matcher::regName[dst_first],
1189 offset);
1190 #endif
1191 }
1192 } else {
1193 // 32-bit
1194 assert(!((src_first & 1) == 0 && src_first + 1 == src_second), "no transform");
1195 assert(!((dst_first & 1) == 0 && dst_first + 1 == dst_second), "no transform");
1196 int offset = ra_->reg2offset(src_first);
1197 if (masm) {
1198 __ movl(as_Register(Matcher::_regEncode[dst_first]), Address(rsp, offset));
1199 #ifndef PRODUCT
1200 } else {
1201 st->print("movl %s, [rsp + #%d]\t# spill",
1202 Matcher::regName[dst_first],
1203 offset);
1204 #endif
1205 }
1206 }
1207 return 0;
1208 } else if (dst_first_rc == rc_float) {
1209 // mem-> xmm
1210 if ((src_first & 1) == 0 && src_first + 1 == src_second &&
1211 (dst_first & 1) == 0 && dst_first + 1 == dst_second) {
1212 // 64-bit
1213 int offset = ra_->reg2offset(src_first);
1214 if (masm) {
1215 __ movdbl( as_XMMRegister(Matcher::_regEncode[dst_first]), Address(rsp, offset));
1216 #ifndef PRODUCT
1217 } else {
1218 st->print("%s %s, [rsp + #%d]\t# spill",
1219 UseXmmLoadAndClearUpper ? "movsd " : "movlpd",
1220 Matcher::regName[dst_first],
1221 offset);
1222 #endif
1223 }
1224 } else {
1225 // 32-bit
1226 assert(!((src_first & 1) == 0 && src_first + 1 == src_second), "no transform");
1227 assert(!((dst_first & 1) == 0 && dst_first + 1 == dst_second), "no transform");
1228 int offset = ra_->reg2offset(src_first);
1229 if (masm) {
1230 __ movflt( as_XMMRegister(Matcher::_regEncode[dst_first]), Address(rsp, offset));
1231 #ifndef PRODUCT
1232 } else {
1233 st->print("movss %s, [rsp + #%d]\t# spill",
1234 Matcher::regName[dst_first],
1235 offset);
1236 #endif
1237 }
1238 }
1239 return 0;
1240 } else if (dst_first_rc == rc_kreg) {
1241 // mem -> kreg
1242 if ((src_first & 1) == 0 && src_first + 1 == src_second &&
1243 (dst_first & 1) == 0 && dst_first + 1 == dst_second) {
1244 // 64-bit
1245 int offset = ra_->reg2offset(src_first);
1246 if (masm) {
1247 __ kmov(as_KRegister(Matcher::_regEncode[dst_first]), Address(rsp, offset));
1248 #ifndef PRODUCT
1249 } else {
1250 st->print("kmovq %s, [rsp + #%d]\t# spill",
1251 Matcher::regName[dst_first],
1252 offset);
1253 #endif
1254 }
1255 }
1256 return 0;
1257 }
1258 } else if (src_first_rc == rc_int) {
1259 // gpr ->
1260 if (dst_first_rc == rc_stack) {
1261 // gpr -> mem
1262 if ((src_first & 1) == 0 && src_first + 1 == src_second &&
1263 (dst_first & 1) == 0 && dst_first + 1 == dst_second) {
1264 // 64-bit
1265 int offset = ra_->reg2offset(dst_first);
1266 if (masm) {
1267 __ movq(Address(rsp, offset), as_Register(Matcher::_regEncode[src_first]));
1268 #ifndef PRODUCT
1269 } else {
1270 st->print("movq [rsp + #%d], %s\t# spill",
1271 offset,
1272 Matcher::regName[src_first]);
1273 #endif
1274 }
1275 } else {
1276 // 32-bit
1277 assert(!((src_first & 1) == 0 && src_first + 1 == src_second), "no transform");
1278 assert(!((dst_first & 1) == 0 && dst_first + 1 == dst_second), "no transform");
1279 int offset = ra_->reg2offset(dst_first);
1280 if (masm) {
1281 __ movl(Address(rsp, offset), as_Register(Matcher::_regEncode[src_first]));
1282 #ifndef PRODUCT
1283 } else {
1284 st->print("movl [rsp + #%d], %s\t# spill",
1285 offset,
1286 Matcher::regName[src_first]);
1287 #endif
1288 }
1289 }
1290 return 0;
1291 } else if (dst_first_rc == rc_int) {
1292 // gpr -> gpr
1293 if ((src_first & 1) == 0 && src_first + 1 == src_second &&
1294 (dst_first & 1) == 0 && dst_first + 1 == dst_second) {
1295 // 64-bit
1296 if (masm) {
1297 __ movq(as_Register(Matcher::_regEncode[dst_first]),
1298 as_Register(Matcher::_regEncode[src_first]));
1299 #ifndef PRODUCT
1300 } else {
1301 st->print("movq %s, %s\t# spill",
1302 Matcher::regName[dst_first],
1303 Matcher::regName[src_first]);
1304 #endif
1305 }
1306 return 0;
1307 } else {
1308 // 32-bit
1309 assert(!((src_first & 1) == 0 && src_first + 1 == src_second), "no transform");
1310 assert(!((dst_first & 1) == 0 && dst_first + 1 == dst_second), "no transform");
1311 if (masm) {
1312 __ movl(as_Register(Matcher::_regEncode[dst_first]),
1313 as_Register(Matcher::_regEncode[src_first]));
1314 #ifndef PRODUCT
1315 } else {
1316 st->print("movl %s, %s\t# spill",
1317 Matcher::regName[dst_first],
1318 Matcher::regName[src_first]);
1319 #endif
1320 }
1321 return 0;
1322 }
1323 } else if (dst_first_rc == rc_float) {
1324 // gpr -> xmm
1325 if ((src_first & 1) == 0 && src_first + 1 == src_second &&
1326 (dst_first & 1) == 0 && dst_first + 1 == dst_second) {
1327 // 64-bit
1328 if (masm) {
1329 __ movdq( as_XMMRegister(Matcher::_regEncode[dst_first]), as_Register(Matcher::_regEncode[src_first]));
1330 #ifndef PRODUCT
1331 } else {
1332 st->print("movdq %s, %s\t# spill",
1333 Matcher::regName[dst_first],
1334 Matcher::regName[src_first]);
1335 #endif
1336 }
1337 } else {
1338 // 32-bit
1339 assert(!((src_first & 1) == 0 && src_first + 1 == src_second), "no transform");
1340 assert(!((dst_first & 1) == 0 && dst_first + 1 == dst_second), "no transform");
1341 if (masm) {
1342 __ movdl( as_XMMRegister(Matcher::_regEncode[dst_first]), as_Register(Matcher::_regEncode[src_first]));
1343 #ifndef PRODUCT
1344 } else {
1345 st->print("movdl %s, %s\t# spill",
1346 Matcher::regName[dst_first],
1347 Matcher::regName[src_first]);
1348 #endif
1349 }
1350 }
1351 return 0;
1352 } else if (dst_first_rc == rc_kreg) {
1353 if ((src_first & 1) == 0 && src_first + 1 == src_second &&
1354 (dst_first & 1) == 0 && dst_first + 1 == dst_second) {
1355 // 64-bit
1356 if (masm) {
1357 __ kmov(as_KRegister(Matcher::_regEncode[dst_first]), as_Register(Matcher::_regEncode[src_first]));
1358 #ifndef PRODUCT
1359 } else {
1360 st->print("kmovq %s, %s\t# spill",
1361 Matcher::regName[dst_first],
1362 Matcher::regName[src_first]);
1363 #endif
1364 }
1365 }
1366 Unimplemented();
1367 return 0;
1368 }
1369 } else if (src_first_rc == rc_float) {
1370 // xmm ->
1371 if (dst_first_rc == rc_stack) {
1372 // xmm -> mem
1373 if ((src_first & 1) == 0 && src_first + 1 == src_second &&
1374 (dst_first & 1) == 0 && dst_first + 1 == dst_second) {
1375 // 64-bit
1376 int offset = ra_->reg2offset(dst_first);
1377 if (masm) {
1378 __ movdbl( Address(rsp, offset), as_XMMRegister(Matcher::_regEncode[src_first]));
1379 #ifndef PRODUCT
1380 } else {
1381 st->print("movsd [rsp + #%d], %s\t# spill",
1382 offset,
1383 Matcher::regName[src_first]);
1384 #endif
1385 }
1386 } else {
1387 // 32-bit
1388 assert(!((src_first & 1) == 0 && src_first + 1 == src_second), "no transform");
1389 assert(!((dst_first & 1) == 0 && dst_first + 1 == dst_second), "no transform");
1390 int offset = ra_->reg2offset(dst_first);
1391 if (masm) {
1392 __ movflt(Address(rsp, offset), as_XMMRegister(Matcher::_regEncode[src_first]));
1393 #ifndef PRODUCT
1394 } else {
1395 st->print("movss [rsp + #%d], %s\t# spill",
1396 offset,
1397 Matcher::regName[src_first]);
1398 #endif
1399 }
1400 }
1401 return 0;
1402 } else if (dst_first_rc == rc_int) {
1403 // xmm -> gpr
1404 if ((src_first & 1) == 0 && src_first + 1 == src_second &&
1405 (dst_first & 1) == 0 && dst_first + 1 == dst_second) {
1406 // 64-bit
1407 if (masm) {
1408 __ movdq( as_Register(Matcher::_regEncode[dst_first]), as_XMMRegister(Matcher::_regEncode[src_first]));
1409 #ifndef PRODUCT
1410 } else {
1411 st->print("movdq %s, %s\t# spill",
1412 Matcher::regName[dst_first],
1413 Matcher::regName[src_first]);
1414 #endif
1415 }
1416 } else {
1417 // 32-bit
1418 assert(!((src_first & 1) == 0 && src_first + 1 == src_second), "no transform");
1419 assert(!((dst_first & 1) == 0 && dst_first + 1 == dst_second), "no transform");
1420 if (masm) {
1421 __ movdl( as_Register(Matcher::_regEncode[dst_first]), as_XMMRegister(Matcher::_regEncode[src_first]));
1422 #ifndef PRODUCT
1423 } else {
1424 st->print("movdl %s, %s\t# spill",
1425 Matcher::regName[dst_first],
1426 Matcher::regName[src_first]);
1427 #endif
1428 }
1429 }
1430 return 0;
1431 } else if (dst_first_rc == rc_float) {
1432 // xmm -> xmm
1433 if ((src_first & 1) == 0 && src_first + 1 == src_second &&
1434 (dst_first & 1) == 0 && dst_first + 1 == dst_second) {
1435 // 64-bit
1436 if (masm) {
1437 __ movdbl( as_XMMRegister(Matcher::_regEncode[dst_first]), as_XMMRegister(Matcher::_regEncode[src_first]));
1438 #ifndef PRODUCT
1439 } else {
1440 st->print("%s %s, %s\t# spill",
1441 UseXmmRegToRegMoveAll ? "movapd" : "movsd ",
1442 Matcher::regName[dst_first],
1443 Matcher::regName[src_first]);
1444 #endif
1445 }
1446 } else {
1447 // 32-bit
1448 assert(!((src_first & 1) == 0 && src_first + 1 == src_second), "no transform");
1449 assert(!((dst_first & 1) == 0 && dst_first + 1 == dst_second), "no transform");
1450 if (masm) {
1451 __ movflt( as_XMMRegister(Matcher::_regEncode[dst_first]), as_XMMRegister(Matcher::_regEncode[src_first]));
1452 #ifndef PRODUCT
1453 } else {
1454 st->print("%s %s, %s\t# spill",
1455 UseXmmRegToRegMoveAll ? "movaps" : "movss ",
1456 Matcher::regName[dst_first],
1457 Matcher::regName[src_first]);
1458 #endif
1459 }
1460 }
1461 return 0;
1462 } else if (dst_first_rc == rc_kreg) {
1463 assert(false, "Illegal spilling");
1464 return 0;
1465 }
1466 } else if (src_first_rc == rc_kreg) {
1467 if (dst_first_rc == rc_stack) {
1468 // mem -> kreg
1469 if ((src_first & 1) == 0 && src_first + 1 == src_second &&
1470 (dst_first & 1) == 0 && dst_first + 1 == dst_second) {
1471 // 64-bit
1472 int offset = ra_->reg2offset(dst_first);
1473 if (masm) {
1474 __ kmov(Address(rsp, offset), as_KRegister(Matcher::_regEncode[src_first]));
1475 #ifndef PRODUCT
1476 } else {
1477 st->print("kmovq [rsp + #%d] , %s\t# spill",
1478 offset,
1479 Matcher::regName[src_first]);
1480 #endif
1481 }
1482 }
1483 return 0;
1484 } else if (dst_first_rc == rc_int) {
1485 if ((src_first & 1) == 0 && src_first + 1 == src_second &&
1486 (dst_first & 1) == 0 && dst_first + 1 == dst_second) {
1487 // 64-bit
1488 if (masm) {
1489 __ kmov(as_Register(Matcher::_regEncode[dst_first]), as_KRegister(Matcher::_regEncode[src_first]));
1490 #ifndef PRODUCT
1491 } else {
1492 st->print("kmovq %s, %s\t# spill",
1493 Matcher::regName[dst_first],
1494 Matcher::regName[src_first]);
1495 #endif
1496 }
1497 }
1498 Unimplemented();
1499 return 0;
1500 } else if (dst_first_rc == rc_kreg) {
1501 if ((src_first & 1) == 0 && src_first + 1 == src_second &&
1502 (dst_first & 1) == 0 && dst_first + 1 == dst_second) {
1503 // 64-bit
1504 if (masm) {
1505 __ kmov(as_KRegister(Matcher::_regEncode[dst_first]), as_KRegister(Matcher::_regEncode[src_first]));
1506 #ifndef PRODUCT
1507 } else {
1508 st->print("kmovq %s, %s\t# spill",
1509 Matcher::regName[dst_first],
1510 Matcher::regName[src_first]);
1511 #endif
1512 }
1513 }
1514 return 0;
1515 } else if (dst_first_rc == rc_float) {
1516 assert(false, "Illegal spill");
1517 return 0;
1518 }
1519 }
1520
1521 assert(0," foo ");
1522 Unimplemented();
1523 return 0;
1524 }
1525
1526 #ifndef PRODUCT
1527 void MachSpillCopyNode::format(PhaseRegAlloc *ra_, outputStream* st) const {
1528 implementation(nullptr, ra_, false, st);
1529 }
1530 #endif
1531
1532 void MachSpillCopyNode::emit(C2_MacroAssembler *masm, PhaseRegAlloc *ra_) const {
1533 implementation(masm, ra_, false, nullptr);
1534 }
1535
1536 uint MachSpillCopyNode::size(PhaseRegAlloc *ra_) const {
1537 return MachNode::size(ra_);
1538 }
1539
1540 //=============================================================================
1541 #ifndef PRODUCT
1542 void BoxLockNode::format(PhaseRegAlloc* ra_, outputStream* st) const
1543 {
1544 int offset = ra_->reg2offset(in_RegMask(0).find_first_elem());
1545 int reg = ra_->get_reg_first(this);
1546 st->print("leaq %s, [rsp + #%d]\t# box lock",
1547 Matcher::regName[reg], offset);
1548 }
1549 #endif
1550
1551 void BoxLockNode::emit(C2_MacroAssembler* masm, PhaseRegAlloc* ra_) const
1552 {
1553 int offset = ra_->reg2offset(in_RegMask(0).find_first_elem());
1554 int reg = ra_->get_encode(this);
1555
1556 __ lea(as_Register(reg), Address(rsp, offset));
1557 }
1558
1559 uint BoxLockNode::size(PhaseRegAlloc *ra_) const
1560 {
1561 int offset = ra_->reg2offset(in_RegMask(0).find_first_elem());
1562 if (ra_->get_encode(this) > 15) {
1563 return (offset < 0x80) ? 6 : 9; // REX2
1564 } else {
1565 return (offset < 0x80) ? 5 : 8; // REX
1566 }
1567 }
1568
1569 //=============================================================================
1570 #ifndef PRODUCT
1571 void MachUEPNode::format(PhaseRegAlloc* ra_, outputStream* st) const
1572 {
1573 if (UseCompressedClassPointers) {
1574 st->print_cr("movl rscratch1, [j_rarg0 + oopDesc::klass_offset_in_bytes()]\t# compressed klass");
1575 st->print_cr("\tcmpl rscratch1, [rax + CompiledICData::speculated_klass_offset()]\t # Inline cache check");
1576 } else {
1577 st->print_cr("movq rscratch1, [j_rarg0 + oopDesc::klass_offset_in_bytes()]\t# compressed klass");
1578 st->print_cr("\tcmpq rscratch1, [rax + CompiledICData::speculated_klass_offset()]\t # Inline cache check");
1579 }
1580 st->print_cr("\tjne SharedRuntime::_ic_miss_stub");
1581 }
1582 #endif
1583
1584 void MachUEPNode::emit(C2_MacroAssembler* masm, PhaseRegAlloc* ra_) const
1585 {
1586 __ ic_check(InteriorEntryAlignment);
1587 }
1588
1589 uint MachUEPNode::size(PhaseRegAlloc* ra_) const
1590 {
1591 return MachNode::size(ra_); // too many variables; just compute it
1592 // the hard way
1593 }
1594
1595
1596 //=============================================================================
1597
1598 bool Matcher::supports_vector_calling_convention(void) {
1599 return EnableVectorSupport;
1600 }
1601
1602 OptoRegPair Matcher::vector_return_value(uint ideal_reg) {
1603 assert(EnableVectorSupport, "sanity");
1604 int lo = XMM0_num;
1605 int hi = XMM0b_num;
1606 if (ideal_reg == Op_VecX) hi = XMM0d_num;
1607 else if (ideal_reg == Op_VecY) hi = XMM0h_num;
1608 else if (ideal_reg == Op_VecZ) hi = XMM0p_num;
1609 return OptoRegPair(hi, lo);
1610 }
1611
1612 // Is this branch offset short enough that a short branch can be used?
1613 //
1614 // NOTE: If the platform does not provide any short branch variants, then
1615 // this method should return false for offset 0.
1616 bool Matcher::is_short_branch_offset(int rule, int br_size, int offset) {
1617 // The passed offset is relative to address of the branch.
1618 // On 86 a branch displacement is calculated relative to address
1619 // of a next instruction.
1620 offset -= br_size;
1621
1622 // the short version of jmpConUCF2 contains multiple branches,
1623 // making the reach slightly less
1624 if (rule == jmpConUCF2_rule)
1625 return (-126 <= offset && offset <= 125);
1626 return (-128 <= offset && offset <= 127);
1627 }
1628
1629 // Return whether or not this register is ever used as an argument.
1630 // This function is used on startup to build the trampoline stubs in
1631 // generateOptoStub. Registers not mentioned will be killed by the VM
1632 // call in the trampoline, and arguments in those registers not be
1633 // available to the callee.
1634 bool Matcher::can_be_java_arg(int reg)
1635 {
1636 return
1637 reg == RDI_num || reg == RDI_H_num ||
1638 reg == RSI_num || reg == RSI_H_num ||
1639 reg == RDX_num || reg == RDX_H_num ||
1640 reg == RCX_num || reg == RCX_H_num ||
1641 reg == R8_num || reg == R8_H_num ||
1642 reg == R9_num || reg == R9_H_num ||
1643 reg == R12_num || reg == R12_H_num ||
1644 reg == XMM0_num || reg == XMM0b_num ||
1645 reg == XMM1_num || reg == XMM1b_num ||
1646 reg == XMM2_num || reg == XMM2b_num ||
1647 reg == XMM3_num || reg == XMM3b_num ||
1648 reg == XMM4_num || reg == XMM4b_num ||
1649 reg == XMM5_num || reg == XMM5b_num ||
1650 reg == XMM6_num || reg == XMM6b_num ||
1651 reg == XMM7_num || reg == XMM7b_num;
1652 }
1653
1654 bool Matcher::is_spillable_arg(int reg)
1655 {
1656 return can_be_java_arg(reg);
1657 }
1658
1659 uint Matcher::int_pressure_limit()
1660 {
1661 return (INTPRESSURE == -1) ? _INT_REG_mask.Size() : INTPRESSURE;
1662 }
1663
1664 uint Matcher::float_pressure_limit()
1665 {
1666 // After experiment around with different values, the following default threshold
1667 // works best for LCM's register pressure scheduling on x64.
1668 uint dec_count = VM_Version::supports_evex() ? 4 : 2;
1669 uint default_float_pressure_threshold = _FLOAT_REG_mask.Size() - dec_count;
1670 return (FLOATPRESSURE == -1) ? default_float_pressure_threshold : FLOATPRESSURE;
1671 }
1672
1673 bool Matcher::use_asm_for_ldiv_by_con( jlong divisor ) {
1674 // In 64 bit mode a code which use multiply when
1675 // devisor is constant is faster than hardware
1676 // DIV instruction (it uses MulHiL).
1677 return false;
1678 }
1679
1680 // Register for DIVI projection of divmodI
1681 RegMask Matcher::divI_proj_mask() {
1682 return INT_RAX_REG_mask();
1683 }
1684
1685 // Register for MODI projection of divmodI
1686 RegMask Matcher::modI_proj_mask() {
1687 return INT_RDX_REG_mask();
1688 }
1689
1690 // Register for DIVL projection of divmodL
1691 RegMask Matcher::divL_proj_mask() {
1692 return LONG_RAX_REG_mask();
1693 }
1694
1695 // Register for MODL projection of divmodL
1696 RegMask Matcher::modL_proj_mask() {
1697 return LONG_RDX_REG_mask();
1698 }
1699
1700 %}
1701
1702 //----------ENCODING BLOCK-----------------------------------------------------
1703 // This block specifies the encoding classes used by the compiler to
1704 // output byte streams. Encoding classes are parameterized macros
1705 // used by Machine Instruction Nodes in order to generate the bit
1706 // encoding of the instruction. Operands specify their base encoding
1707 // interface with the interface keyword. There are currently
1708 // supported four interfaces, REG_INTER, CONST_INTER, MEMORY_INTER, &
1709 // COND_INTER. REG_INTER causes an operand to generate a function
1710 // which returns its register number when queried. CONST_INTER causes
1711 // an operand to generate a function which returns the value of the
1712 // constant when queried. MEMORY_INTER causes an operand to generate
1713 // four functions which return the Base Register, the Index Register,
1714 // the Scale Value, and the Offset Value of the operand when queried.
1715 // COND_INTER causes an operand to generate six functions which return
1716 // the encoding code (ie - encoding bits for the instruction)
1717 // associated with each basic boolean condition for a conditional
1718 // instruction.
1719 //
1720 // Instructions specify two basic values for encoding. Again, a
1721 // function is available to check if the constant displacement is an
1722 // oop. They use the ins_encode keyword to specify their encoding
1723 // classes (which must be a sequence of enc_class names, and their
1724 // parameters, specified in the encoding block), and they use the
1725 // opcode keyword to specify, in order, their primary, secondary, and
1726 // tertiary opcode. Only the opcode sections which a particular
1727 // instruction needs for encoding need to be specified.
1728 encode %{
1729 enc_class cdql_enc(no_rax_rdx_RegI div)
1730 %{
1731 // Full implementation of Java idiv and irem; checks for
1732 // special case as described in JVM spec., p.243 & p.271.
1733 //
1734 // normal case special case
1735 //
1736 // input : rax: dividend min_int
1737 // reg: divisor -1
1738 //
1739 // output: rax: quotient (= rax idiv reg) min_int
1740 // rdx: remainder (= rax irem reg) 0
1741 //
1742 // Code sequnce:
1743 //
1744 // 0: 3d 00 00 00 80 cmp $0x80000000,%eax
1745 // 5: 75 07/08 jne e <normal>
1746 // 7: 33 d2 xor %edx,%edx
1747 // [div >= 8 -> offset + 1]
1748 // [REX_B]
1749 // 9: 83 f9 ff cmp $0xffffffffffffffff,$div
1750 // c: 74 03/04 je 11 <done>
1751 // 000000000000000e <normal>:
1752 // e: 99 cltd
1753 // [div >= 8 -> offset + 1]
1754 // [REX_B]
1755 // f: f7 f9 idiv $div
1756 // 0000000000000011 <done>:
1757 Label normal;
1758 Label done;
1759
1760 // cmp $0x80000000,%eax
1761 __ cmpl(as_Register(RAX_enc), 0x80000000);
1762
1763 // jne e <normal>
1764 __ jccb(Assembler::notEqual, normal);
1765
1766 // xor %edx,%edx
1767 __ xorl(as_Register(RDX_enc), as_Register(RDX_enc));
1768
1769 // cmp $0xffffffffffffffff,%ecx
1770 __ cmpl($div$$Register, -1);
1771
1772 // je 11 <done>
1773 __ jccb(Assembler::equal, done);
1774
1775 // <normal>
1776 // cltd
1777 __ bind(normal);
1778 __ cdql();
1779
1780 // idivl
1781 // <done>
1782 __ idivl($div$$Register);
1783 __ bind(done);
1784 %}
1785
1786 enc_class cdqq_enc(no_rax_rdx_RegL div)
1787 %{
1788 // Full implementation of Java ldiv and lrem; checks for
1789 // special case as described in JVM spec., p.243 & p.271.
1790 //
1791 // normal case special case
1792 //
1793 // input : rax: dividend min_long
1794 // reg: divisor -1
1795 //
1796 // output: rax: quotient (= rax idiv reg) min_long
1797 // rdx: remainder (= rax irem reg) 0
1798 //
1799 // Code sequnce:
1800 //
1801 // 0: 48 ba 00 00 00 00 00 mov $0x8000000000000000,%rdx
1802 // 7: 00 00 80
1803 // a: 48 39 d0 cmp %rdx,%rax
1804 // d: 75 08 jne 17 <normal>
1805 // f: 33 d2 xor %edx,%edx
1806 // 11: 48 83 f9 ff cmp $0xffffffffffffffff,$div
1807 // 15: 74 05 je 1c <done>
1808 // 0000000000000017 <normal>:
1809 // 17: 48 99 cqto
1810 // 19: 48 f7 f9 idiv $div
1811 // 000000000000001c <done>:
1812 Label normal;
1813 Label done;
1814
1815 // mov $0x8000000000000000,%rdx
1816 __ mov64(as_Register(RDX_enc), 0x8000000000000000);
1817
1818 // cmp %rdx,%rax
1819 __ cmpq(as_Register(RAX_enc), as_Register(RDX_enc));
1820
1821 // jne 17 <normal>
1822 __ jccb(Assembler::notEqual, normal);
1823
1824 // xor %edx,%edx
1825 __ xorl(as_Register(RDX_enc), as_Register(RDX_enc));
1826
1827 // cmp $0xffffffffffffffff,$div
1828 __ cmpq($div$$Register, -1);
1829
1830 // je 1e <done>
1831 __ jccb(Assembler::equal, done);
1832
1833 // <normal>
1834 // cqto
1835 __ bind(normal);
1836 __ cdqq();
1837
1838 // idivq (note: must be emitted by the user of this rule)
1839 // <done>
1840 __ idivq($div$$Register);
1841 __ bind(done);
1842 %}
1843
1844 enc_class clear_avx %{
1845 DEBUG_ONLY(int off0 = __ offset());
1846 if (generate_vzeroupper(Compile::current())) {
1847 // Clear upper bits of YMM registers to avoid AVX <-> SSE transition penalty
1848 // Clear upper bits of YMM registers when current compiled code uses
1849 // wide vectors to avoid AVX <-> SSE transition penalty during call.
1850 __ vzeroupper();
1851 }
1852 DEBUG_ONLY(int off1 = __ offset());
1853 assert(off1 - off0 == clear_avx_size(), "correct size prediction");
1854 %}
1855
1856 enc_class Java_To_Runtime(method meth) %{
1857 __ lea(r10, RuntimeAddress((address)$meth$$method));
1858 __ call(r10);
1859 __ post_call_nop();
1860 %}
1861
1862 enc_class Java_Static_Call(method meth)
1863 %{
1864 // JAVA STATIC CALL
1865 // CALL to fixup routine. Fixup routine uses ScopeDesc info to
1866 // determine who we intended to call.
1867 if (!_method) {
1868 __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, $meth$$method)));
1869 } else if (_method->intrinsic_id() == vmIntrinsicID::_ensureMaterializedForStackWalk) {
1870 // The NOP here is purely to ensure that eliding a call to
1871 // JVM_EnsureMaterializedForStackWalk doesn't change the code size.
1872 __ addr_nop_5();
1873 __ block_comment("call JVM_EnsureMaterializedForStackWalk (elided)");
1874 } else {
1875 int method_index = resolved_method_index(masm);
1876 RelocationHolder rspec = _optimized_virtual ? opt_virtual_call_Relocation::spec(method_index)
1877 : static_call_Relocation::spec(method_index);
1878 address mark = __ pc();
1879 int call_offset = __ offset();
1880 __ call(AddressLiteral(CAST_FROM_FN_PTR(address, $meth$$method), rspec));
1881 if (CodeBuffer::supports_shared_stubs() && _method->can_be_statically_bound()) {
1882 // Calls of the same statically bound method can share
1883 // a stub to the interpreter.
1884 __ code()->shared_stub_to_interp_for(_method, call_offset);
1885 } else {
1886 // Emit stubs for static call.
1887 address stub = CompiledDirectCall::emit_to_interp_stub(masm, mark);
1888 __ clear_inst_mark();
1889 if (stub == nullptr) {
1890 ciEnv::current()->record_failure("CodeCache is full");
1891 return;
1892 }
1893 }
1894 }
1895 __ post_call_nop();
1896 %}
1897
1898 enc_class Java_Dynamic_Call(method meth) %{
1899 __ ic_call((address)$meth$$method, resolved_method_index(masm));
1900 __ post_call_nop();
1901 %}
1902
1903 %}
1904
1905
1906
1907 //----------FRAME--------------------------------------------------------------
1908 // Definition of frame structure and management information.
1909 //
1910 // S T A C K L A Y O U T Allocators stack-slot number
1911 // | (to get allocators register number
1912 // G Owned by | | v add OptoReg::stack0())
1913 // r CALLER | |
1914 // o | +--------+ pad to even-align allocators stack-slot
1915 // w V | pad0 | numbers; owned by CALLER
1916 // t -----------+--------+----> Matcher::_in_arg_limit, unaligned
1917 // h ^ | in | 5
1918 // | | args | 4 Holes in incoming args owned by SELF
1919 // | | | | 3
1920 // | | +--------+
1921 // V | | old out| Empty on Intel, window on Sparc
1922 // | old |preserve| Must be even aligned.
1923 // | SP-+--------+----> Matcher::_old_SP, even aligned
1924 // | | in | 3 area for Intel ret address
1925 // Owned by |preserve| Empty on Sparc.
1926 // SELF +--------+
1927 // | | pad2 | 2 pad to align old SP
1928 // | +--------+ 1
1929 // | | locks | 0
1930 // | +--------+----> OptoReg::stack0(), even aligned
1931 // | | pad1 | 11 pad to align new SP
1932 // | +--------+
1933 // | | | 10
1934 // | | spills | 9 spills
1935 // V | | 8 (pad0 slot for callee)
1936 // -----------+--------+----> Matcher::_out_arg_limit, unaligned
1937 // ^ | out | 7
1938 // | | args | 6 Holes in outgoing args owned by CALLEE
1939 // Owned by +--------+
1940 // CALLEE | new out| 6 Empty on Intel, window on Sparc
1941 // | new |preserve| Must be even-aligned.
1942 // | SP-+--------+----> Matcher::_new_SP, even aligned
1943 // | | |
1944 //
1945 // Note 1: Only region 8-11 is determined by the allocator. Region 0-5 is
1946 // known from SELF's arguments and the Java calling convention.
1947 // Region 6-7 is determined per call site.
1948 // Note 2: If the calling convention leaves holes in the incoming argument
1949 // area, those holes are owned by SELF. Holes in the outgoing area
1950 // are owned by the CALLEE. Holes should not be necessary in the
1951 // incoming area, as the Java calling convention is completely under
1952 // the control of the AD file. Doubles can be sorted and packed to
1953 // avoid holes. Holes in the outgoing arguments may be necessary for
1954 // varargs C calling conventions.
1955 // Note 3: Region 0-3 is even aligned, with pad2 as needed. Region 3-5 is
1956 // even aligned with pad0 as needed.
1957 // Region 6 is even aligned. Region 6-7 is NOT even aligned;
1958 // region 6-11 is even aligned; it may be padded out more so that
1959 // the region from SP to FP meets the minimum stack alignment.
1960 // Note 4: For I2C adapters, the incoming FP may not meet the minimum stack
1961 // alignment. Region 11, pad1, may be dynamically extended so that
1962 // SP meets the minimum alignment.
1963
1964 frame
1965 %{
1966 // These three registers define part of the calling convention
1967 // between compiled code and the interpreter.
1968 inline_cache_reg(RAX); // Inline Cache Register
1969
1970 // Optional: name the operand used by cisc-spilling to access
1971 // [stack_pointer + offset]
1972 cisc_spilling_operand_name(indOffset32);
1973
1974 // Number of stack slots consumed by locking an object
1975 sync_stack_slots(2);
1976
1977 // Compiled code's Frame Pointer
1978 frame_pointer(RSP);
1979
1980 // Interpreter stores its frame pointer in a register which is
1981 // stored to the stack by I2CAdaptors.
1982 // I2CAdaptors convert from interpreted java to compiled java.
1983 interpreter_frame_pointer(RBP);
1984
1985 // Stack alignment requirement
1986 stack_alignment(StackAlignmentInBytes); // Alignment size in bytes (128-bit -> 16 bytes)
1987
1988 // Number of outgoing stack slots killed above the out_preserve_stack_slots
1989 // for calls to C. Supports the var-args backing area for register parms.
1990 varargs_C_out_slots_killed(frame::arg_reg_save_area_bytes/BytesPerInt);
1991
1992 // The after-PROLOG location of the return address. Location of
1993 // return address specifies a type (REG or STACK) and a number
1994 // representing the register number (i.e. - use a register name) or
1995 // stack slot.
1996 // Ret Addr is on stack in slot 0 if no locks or verification or alignment.
1997 // Otherwise, it is above the locks and verification slot and alignment word
1998 return_addr(STACK - 2 +
1999 align_up((Compile::current()->in_preserve_stack_slots() +
2000 Compile::current()->fixed_slots()),
2001 stack_alignment_in_slots()));
2002
2003 // Location of compiled Java return values. Same as C for now.
2004 return_value
2005 %{
2006 assert(ideal_reg >= Op_RegI && ideal_reg <= Op_RegL,
2007 "only return normal values");
2008
2009 static const int lo[Op_RegL + 1] = {
2010 0,
2011 0,
2012 RAX_num, // Op_RegN
2013 RAX_num, // Op_RegI
2014 RAX_num, // Op_RegP
2015 XMM0_num, // Op_RegF
2016 XMM0_num, // Op_RegD
2017 RAX_num // Op_RegL
2018 };
2019 static const int hi[Op_RegL + 1] = {
2020 0,
2021 0,
2022 OptoReg::Bad, // Op_RegN
2023 OptoReg::Bad, // Op_RegI
2024 RAX_H_num, // Op_RegP
2025 OptoReg::Bad, // Op_RegF
2026 XMM0b_num, // Op_RegD
2027 RAX_H_num // Op_RegL
2028 };
2029 // Excluded flags and vector registers.
2030 assert(ARRAY_SIZE(hi) == _last_machine_leaf - 8, "missing type");
2031 return OptoRegPair(hi[ideal_reg], lo[ideal_reg]);
2032 %}
2033 %}
2034
2035 //----------ATTRIBUTES---------------------------------------------------------
2036 //----------Operand Attributes-------------------------------------------------
2037 op_attrib op_cost(0); // Required cost attribute
2038
2039 //----------Instruction Attributes---------------------------------------------
2040 ins_attrib ins_cost(100); // Required cost attribute
2041 ins_attrib ins_size(8); // Required size attribute (in bits)
2042 ins_attrib ins_short_branch(0); // Required flag: is this instruction
2043 // a non-matching short branch variant
2044 // of some long branch?
2045 ins_attrib ins_alignment(1); // Required alignment attribute (must
2046 // be a power of 2) specifies the
2047 // alignment that some part of the
2048 // instruction (not necessarily the
2049 // start) requires. If > 1, a
2050 // compute_padding() function must be
2051 // provided for the instruction
2052
2053 // Whether this node is expanded during code emission into a sequence of
2054 // instructions and the first instruction can perform an implicit null check.
2055 ins_attrib ins_is_late_expanded_null_check_candidate(false);
2056
2057 //----------OPERANDS-----------------------------------------------------------
2058 // Operand definitions must precede instruction definitions for correct parsing
2059 // in the ADLC because operands constitute user defined types which are used in
2060 // instruction definitions.
2061
2062 //----------Simple Operands----------------------------------------------------
2063 // Immediate Operands
2064 // Integer Immediate
2065 operand immI()
2066 %{
2067 match(ConI);
2068
2069 op_cost(10);
2070 format %{ %}
2071 interface(CONST_INTER);
2072 %}
2073
2074 // Constant for test vs zero
2075 operand immI_0()
2076 %{
2077 predicate(n->get_int() == 0);
2078 match(ConI);
2079
2080 op_cost(0);
2081 format %{ %}
2082 interface(CONST_INTER);
2083 %}
2084
2085 // Constant for increment
2086 operand immI_1()
2087 %{
2088 predicate(n->get_int() == 1);
2089 match(ConI);
2090
2091 op_cost(0);
2092 format %{ %}
2093 interface(CONST_INTER);
2094 %}
2095
2096 // Constant for decrement
2097 operand immI_M1()
2098 %{
2099 predicate(n->get_int() == -1);
2100 match(ConI);
2101
2102 op_cost(0);
2103 format %{ %}
2104 interface(CONST_INTER);
2105 %}
2106
2107 operand immI_2()
2108 %{
2109 predicate(n->get_int() == 2);
2110 match(ConI);
2111
2112 op_cost(0);
2113 format %{ %}
2114 interface(CONST_INTER);
2115 %}
2116
2117 operand immI_4()
2118 %{
2119 predicate(n->get_int() == 4);
2120 match(ConI);
2121
2122 op_cost(0);
2123 format %{ %}
2124 interface(CONST_INTER);
2125 %}
2126
2127 operand immI_8()
2128 %{
2129 predicate(n->get_int() == 8);
2130 match(ConI);
2131
2132 op_cost(0);
2133 format %{ %}
2134 interface(CONST_INTER);
2135 %}
2136
2137 // Valid scale values for addressing modes
2138 operand immI2()
2139 %{
2140 predicate(0 <= n->get_int() && (n->get_int() <= 3));
2141 match(ConI);
2142
2143 format %{ %}
2144 interface(CONST_INTER);
2145 %}
2146
2147 operand immU7()
2148 %{
2149 predicate((0 <= n->get_int()) && (n->get_int() <= 0x7F));
2150 match(ConI);
2151
2152 op_cost(5);
2153 format %{ %}
2154 interface(CONST_INTER);
2155 %}
2156
2157 operand immI8()
2158 %{
2159 predicate((-0x80 <= n->get_int()) && (n->get_int() < 0x80));
2160 match(ConI);
2161
2162 op_cost(5);
2163 format %{ %}
2164 interface(CONST_INTER);
2165 %}
2166
2167 operand immU8()
2168 %{
2169 predicate((0 <= n->get_int()) && (n->get_int() <= 255));
2170 match(ConI);
2171
2172 op_cost(5);
2173 format %{ %}
2174 interface(CONST_INTER);
2175 %}
2176
2177 operand immI16()
2178 %{
2179 predicate((-32768 <= n->get_int()) && (n->get_int() <= 32767));
2180 match(ConI);
2181
2182 op_cost(10);
2183 format %{ %}
2184 interface(CONST_INTER);
2185 %}
2186
2187 // Int Immediate non-negative
2188 operand immU31()
2189 %{
2190 predicate(n->get_int() >= 0);
2191 match(ConI);
2192
2193 op_cost(0);
2194 format %{ %}
2195 interface(CONST_INTER);
2196 %}
2197
2198 // Pointer Immediate
2199 operand immP()
2200 %{
2201 match(ConP);
2202
2203 op_cost(10);
2204 format %{ %}
2205 interface(CONST_INTER);
2206 %}
2207
2208 // Null Pointer Immediate
2209 operand immP0()
2210 %{
2211 predicate(n->get_ptr() == 0);
2212 match(ConP);
2213
2214 op_cost(5);
2215 format %{ %}
2216 interface(CONST_INTER);
2217 %}
2218
2219 // Pointer Immediate
2220 operand immN() %{
2221 match(ConN);
2222
2223 op_cost(10);
2224 format %{ %}
2225 interface(CONST_INTER);
2226 %}
2227
2228 operand immNKlass() %{
2229 match(ConNKlass);
2230
2231 op_cost(10);
2232 format %{ %}
2233 interface(CONST_INTER);
2234 %}
2235
2236 // Null Pointer Immediate
2237 operand immN0() %{
2238 predicate(n->get_narrowcon() == 0);
2239 match(ConN);
2240
2241 op_cost(5);
2242 format %{ %}
2243 interface(CONST_INTER);
2244 %}
2245
2246 operand immP31()
2247 %{
2248 predicate(n->as_Type()->type()->reloc() == relocInfo::none
2249 && (n->get_ptr() >> 31) == 0);
2250 match(ConP);
2251
2252 op_cost(5);
2253 format %{ %}
2254 interface(CONST_INTER);
2255 %}
2256
2257
2258 // Long Immediate
2259 operand immL()
2260 %{
2261 match(ConL);
2262
2263 op_cost(20);
2264 format %{ %}
2265 interface(CONST_INTER);
2266 %}
2267
2268 // Long Immediate 8-bit
2269 operand immL8()
2270 %{
2271 predicate(-0x80L <= n->get_long() && n->get_long() < 0x80L);
2272 match(ConL);
2273
2274 op_cost(5);
2275 format %{ %}
2276 interface(CONST_INTER);
2277 %}
2278
2279 // Long Immediate 32-bit unsigned
2280 operand immUL32()
2281 %{
2282 predicate(n->get_long() == (unsigned int) (n->get_long()));
2283 match(ConL);
2284
2285 op_cost(10);
2286 format %{ %}
2287 interface(CONST_INTER);
2288 %}
2289
2290 // Long Immediate 32-bit signed
2291 operand immL32()
2292 %{
2293 predicate(n->get_long() == (int) (n->get_long()));
2294 match(ConL);
2295
2296 op_cost(15);
2297 format %{ %}
2298 interface(CONST_INTER);
2299 %}
2300
2301 operand immL_Pow2()
2302 %{
2303 predicate(is_power_of_2((julong)n->get_long()));
2304 match(ConL);
2305
2306 op_cost(15);
2307 format %{ %}
2308 interface(CONST_INTER);
2309 %}
2310
2311 operand immL_NotPow2()
2312 %{
2313 predicate(is_power_of_2((julong)~n->get_long()));
2314 match(ConL);
2315
2316 op_cost(15);
2317 format %{ %}
2318 interface(CONST_INTER);
2319 %}
2320
2321 // Long Immediate zero
2322 operand immL0()
2323 %{
2324 predicate(n->get_long() == 0L);
2325 match(ConL);
2326
2327 op_cost(10);
2328 format %{ %}
2329 interface(CONST_INTER);
2330 %}
2331
2332 // Constant for increment
2333 operand immL1()
2334 %{
2335 predicate(n->get_long() == 1);
2336 match(ConL);
2337
2338 format %{ %}
2339 interface(CONST_INTER);
2340 %}
2341
2342 // Constant for decrement
2343 operand immL_M1()
2344 %{
2345 predicate(n->get_long() == -1);
2346 match(ConL);
2347
2348 format %{ %}
2349 interface(CONST_INTER);
2350 %}
2351
2352 // Long Immediate: low 32-bit mask
2353 operand immL_32bits()
2354 %{
2355 predicate(n->get_long() == 0xFFFFFFFFL);
2356 match(ConL);
2357 op_cost(20);
2358
2359 format %{ %}
2360 interface(CONST_INTER);
2361 %}
2362
2363 // Int Immediate: 2^n-1, positive
2364 operand immI_Pow2M1()
2365 %{
2366 predicate((n->get_int() > 0)
2367 && is_power_of_2((juint)n->get_int() + 1));
2368 match(ConI);
2369
2370 op_cost(20);
2371 format %{ %}
2372 interface(CONST_INTER);
2373 %}
2374
2375 // Float Immediate zero
2376 operand immF0()
2377 %{
2378 predicate(jint_cast(n->getf()) == 0);
2379 match(ConF);
2380
2381 op_cost(5);
2382 format %{ %}
2383 interface(CONST_INTER);
2384 %}
2385
2386 // Float Immediate
2387 operand immF()
2388 %{
2389 match(ConF);
2390
2391 op_cost(15);
2392 format %{ %}
2393 interface(CONST_INTER);
2394 %}
2395
2396 // Half Float Immediate
2397 operand immH()
2398 %{
2399 match(ConH);
2400
2401 op_cost(15);
2402 format %{ %}
2403 interface(CONST_INTER);
2404 %}
2405
2406 // Double Immediate zero
2407 operand immD0()
2408 %{
2409 predicate(jlong_cast(n->getd()) == 0);
2410 match(ConD);
2411
2412 op_cost(5);
2413 format %{ %}
2414 interface(CONST_INTER);
2415 %}
2416
2417 // Double Immediate
2418 operand immD()
2419 %{
2420 match(ConD);
2421
2422 op_cost(15);
2423 format %{ %}
2424 interface(CONST_INTER);
2425 %}
2426
2427 // Immediates for special shifts (sign extend)
2428
2429 // Constants for increment
2430 operand immI_16()
2431 %{
2432 predicate(n->get_int() == 16);
2433 match(ConI);
2434
2435 format %{ %}
2436 interface(CONST_INTER);
2437 %}
2438
2439 operand immI_24()
2440 %{
2441 predicate(n->get_int() == 24);
2442 match(ConI);
2443
2444 format %{ %}
2445 interface(CONST_INTER);
2446 %}
2447
2448 // Constant for byte-wide masking
2449 operand immI_255()
2450 %{
2451 predicate(n->get_int() == 255);
2452 match(ConI);
2453
2454 format %{ %}
2455 interface(CONST_INTER);
2456 %}
2457
2458 // Constant for short-wide masking
2459 operand immI_65535()
2460 %{
2461 predicate(n->get_int() == 65535);
2462 match(ConI);
2463
2464 format %{ %}
2465 interface(CONST_INTER);
2466 %}
2467
2468 // Constant for byte-wide masking
2469 operand immL_255()
2470 %{
2471 predicate(n->get_long() == 255);
2472 match(ConL);
2473
2474 format %{ %}
2475 interface(CONST_INTER);
2476 %}
2477
2478 // Constant for short-wide masking
2479 operand immL_65535()
2480 %{
2481 predicate(n->get_long() == 65535);
2482 match(ConL);
2483
2484 format %{ %}
2485 interface(CONST_INTER);
2486 %}
2487
2488 operand kReg()
2489 %{
2490 constraint(ALLOC_IN_RC(vectmask_reg));
2491 match(RegVectMask);
2492 format %{%}
2493 interface(REG_INTER);
2494 %}
2495
2496 // Register Operands
2497 // Integer Register
2498 operand rRegI()
2499 %{
2500 constraint(ALLOC_IN_RC(int_reg));
2501 match(RegI);
2502
2503 match(rax_RegI);
2504 match(rbx_RegI);
2505 match(rcx_RegI);
2506 match(rdx_RegI);
2507 match(rdi_RegI);
2508
2509 format %{ %}
2510 interface(REG_INTER);
2511 %}
2512
2513 // Special Registers
2514 operand rax_RegI()
2515 %{
2516 constraint(ALLOC_IN_RC(int_rax_reg));
2517 match(RegI);
2518 match(rRegI);
2519
2520 format %{ "RAX" %}
2521 interface(REG_INTER);
2522 %}
2523
2524 // Special Registers
2525 operand rbx_RegI()
2526 %{
2527 constraint(ALLOC_IN_RC(int_rbx_reg));
2528 match(RegI);
2529 match(rRegI);
2530
2531 format %{ "RBX" %}
2532 interface(REG_INTER);
2533 %}
2534
2535 operand rcx_RegI()
2536 %{
2537 constraint(ALLOC_IN_RC(int_rcx_reg));
2538 match(RegI);
2539 match(rRegI);
2540
2541 format %{ "RCX" %}
2542 interface(REG_INTER);
2543 %}
2544
2545 operand rdx_RegI()
2546 %{
2547 constraint(ALLOC_IN_RC(int_rdx_reg));
2548 match(RegI);
2549 match(rRegI);
2550
2551 format %{ "RDX" %}
2552 interface(REG_INTER);
2553 %}
2554
2555 operand rdi_RegI()
2556 %{
2557 constraint(ALLOC_IN_RC(int_rdi_reg));
2558 match(RegI);
2559 match(rRegI);
2560
2561 format %{ "RDI" %}
2562 interface(REG_INTER);
2563 %}
2564
2565 operand no_rax_rdx_RegI()
2566 %{
2567 constraint(ALLOC_IN_RC(int_no_rax_rdx_reg));
2568 match(RegI);
2569 match(rbx_RegI);
2570 match(rcx_RegI);
2571 match(rdi_RegI);
2572
2573 format %{ %}
2574 interface(REG_INTER);
2575 %}
2576
2577 operand no_rbp_r13_RegI()
2578 %{
2579 constraint(ALLOC_IN_RC(int_no_rbp_r13_reg));
2580 match(RegI);
2581 match(rRegI);
2582 match(rax_RegI);
2583 match(rbx_RegI);
2584 match(rcx_RegI);
2585 match(rdx_RegI);
2586 match(rdi_RegI);
2587
2588 format %{ %}
2589 interface(REG_INTER);
2590 %}
2591
2592 // Pointer Register
2593 operand any_RegP()
2594 %{
2595 constraint(ALLOC_IN_RC(any_reg));
2596 match(RegP);
2597 match(rax_RegP);
2598 match(rbx_RegP);
2599 match(rdi_RegP);
2600 match(rsi_RegP);
2601 match(rbp_RegP);
2602 match(r15_RegP);
2603 match(rRegP);
2604
2605 format %{ %}
2606 interface(REG_INTER);
2607 %}
2608
2609 operand rRegP()
2610 %{
2611 constraint(ALLOC_IN_RC(ptr_reg));
2612 match(RegP);
2613 match(rax_RegP);
2614 match(rbx_RegP);
2615 match(rdi_RegP);
2616 match(rsi_RegP);
2617 match(rbp_RegP); // See Q&A below about
2618 match(r15_RegP); // r15_RegP and rbp_RegP.
2619
2620 format %{ %}
2621 interface(REG_INTER);
2622 %}
2623
2624 operand rRegN() %{
2625 constraint(ALLOC_IN_RC(int_reg));
2626 match(RegN);
2627
2628 format %{ %}
2629 interface(REG_INTER);
2630 %}
2631
2632 // Question: Why is r15_RegP (the read-only TLS register) a match for rRegP?
2633 // Answer: Operand match rules govern the DFA as it processes instruction inputs.
2634 // It's fine for an instruction input that expects rRegP to match a r15_RegP.
2635 // The output of an instruction is controlled by the allocator, which respects
2636 // register class masks, not match rules. Unless an instruction mentions
2637 // r15_RegP or any_RegP explicitly as its output, r15 will not be considered
2638 // by the allocator as an input.
2639 // The same logic applies to rbp_RegP being a match for rRegP: If PreserveFramePointer==true,
2640 // the RBP is used as a proper frame pointer and is not included in ptr_reg. As a
2641 // result, RBP is not included in the output of the instruction either.
2642
2643 // This operand is not allowed to use RBP even if
2644 // RBP is not used to hold the frame pointer.
2645 operand no_rbp_RegP()
2646 %{
2647 constraint(ALLOC_IN_RC(ptr_reg_no_rbp));
2648 match(RegP);
2649 match(rbx_RegP);
2650 match(rsi_RegP);
2651 match(rdi_RegP);
2652
2653 format %{ %}
2654 interface(REG_INTER);
2655 %}
2656
2657 // Special Registers
2658 // Return a pointer value
2659 operand rax_RegP()
2660 %{
2661 constraint(ALLOC_IN_RC(ptr_rax_reg));
2662 match(RegP);
2663 match(rRegP);
2664
2665 format %{ %}
2666 interface(REG_INTER);
2667 %}
2668
2669 // Special Registers
2670 // Return a compressed pointer value
2671 operand rax_RegN()
2672 %{
2673 constraint(ALLOC_IN_RC(int_rax_reg));
2674 match(RegN);
2675 match(rRegN);
2676
2677 format %{ %}
2678 interface(REG_INTER);
2679 %}
2680
2681 // Used in AtomicAdd
2682 operand rbx_RegP()
2683 %{
2684 constraint(ALLOC_IN_RC(ptr_rbx_reg));
2685 match(RegP);
2686 match(rRegP);
2687
2688 format %{ %}
2689 interface(REG_INTER);
2690 %}
2691
2692 operand rsi_RegP()
2693 %{
2694 constraint(ALLOC_IN_RC(ptr_rsi_reg));
2695 match(RegP);
2696 match(rRegP);
2697
2698 format %{ %}
2699 interface(REG_INTER);
2700 %}
2701
2702 operand rbp_RegP()
2703 %{
2704 constraint(ALLOC_IN_RC(ptr_rbp_reg));
2705 match(RegP);
2706 match(rRegP);
2707
2708 format %{ %}
2709 interface(REG_INTER);
2710 %}
2711
2712 // Used in rep stosq
2713 operand rdi_RegP()
2714 %{
2715 constraint(ALLOC_IN_RC(ptr_rdi_reg));
2716 match(RegP);
2717 match(rRegP);
2718
2719 format %{ %}
2720 interface(REG_INTER);
2721 %}
2722
2723 operand r15_RegP()
2724 %{
2725 constraint(ALLOC_IN_RC(ptr_r15_reg));
2726 match(RegP);
2727 match(rRegP);
2728
2729 format %{ %}
2730 interface(REG_INTER);
2731 %}
2732
2733 operand rRegL()
2734 %{
2735 constraint(ALLOC_IN_RC(long_reg));
2736 match(RegL);
2737 match(rax_RegL);
2738 match(rdx_RegL);
2739
2740 format %{ %}
2741 interface(REG_INTER);
2742 %}
2743
2744 // Special Registers
2745 operand no_rax_rdx_RegL()
2746 %{
2747 constraint(ALLOC_IN_RC(long_no_rax_rdx_reg));
2748 match(RegL);
2749 match(rRegL);
2750
2751 format %{ %}
2752 interface(REG_INTER);
2753 %}
2754
2755 operand rax_RegL()
2756 %{
2757 constraint(ALLOC_IN_RC(long_rax_reg));
2758 match(RegL);
2759 match(rRegL);
2760
2761 format %{ "RAX" %}
2762 interface(REG_INTER);
2763 %}
2764
2765 operand rcx_RegL()
2766 %{
2767 constraint(ALLOC_IN_RC(long_rcx_reg));
2768 match(RegL);
2769 match(rRegL);
2770
2771 format %{ %}
2772 interface(REG_INTER);
2773 %}
2774
2775 operand rdx_RegL()
2776 %{
2777 constraint(ALLOC_IN_RC(long_rdx_reg));
2778 match(RegL);
2779 match(rRegL);
2780
2781 format %{ %}
2782 interface(REG_INTER);
2783 %}
2784
2785 operand r11_RegL()
2786 %{
2787 constraint(ALLOC_IN_RC(long_r11_reg));
2788 match(RegL);
2789 match(rRegL);
2790
2791 format %{ %}
2792 interface(REG_INTER);
2793 %}
2794
2795 operand no_rbp_r13_RegL()
2796 %{
2797 constraint(ALLOC_IN_RC(long_no_rbp_r13_reg));
2798 match(RegL);
2799 match(rRegL);
2800 match(rax_RegL);
2801 match(rcx_RegL);
2802 match(rdx_RegL);
2803
2804 format %{ %}
2805 interface(REG_INTER);
2806 %}
2807
2808 // Flags register, used as output of compare instructions
2809 operand rFlagsReg()
2810 %{
2811 constraint(ALLOC_IN_RC(int_flags));
2812 match(RegFlags);
2813
2814 format %{ "RFLAGS" %}
2815 interface(REG_INTER);
2816 %}
2817
2818 // Flags register, used as output of FLOATING POINT compare instructions
2819 operand rFlagsRegU()
2820 %{
2821 constraint(ALLOC_IN_RC(int_flags));
2822 match(RegFlags);
2823
2824 format %{ "RFLAGS_U" %}
2825 interface(REG_INTER);
2826 %}
2827
2828 operand rFlagsRegUCF() %{
2829 constraint(ALLOC_IN_RC(int_flags));
2830 match(RegFlags);
2831 predicate(false);
2832
2833 format %{ "RFLAGS_U_CF" %}
2834 interface(REG_INTER);
2835 %}
2836
2837 // Float register operands
2838 operand regF() %{
2839 constraint(ALLOC_IN_RC(float_reg));
2840 match(RegF);
2841
2842 format %{ %}
2843 interface(REG_INTER);
2844 %}
2845
2846 // Float register operands
2847 operand legRegF() %{
2848 constraint(ALLOC_IN_RC(float_reg_legacy));
2849 match(RegF);
2850
2851 format %{ %}
2852 interface(REG_INTER);
2853 %}
2854
2855 // Float register operands
2856 operand vlRegF() %{
2857 constraint(ALLOC_IN_RC(float_reg_vl));
2858 match(RegF);
2859
2860 format %{ %}
2861 interface(REG_INTER);
2862 %}
2863
2864 // Double register operands
2865 operand regD() %{
2866 constraint(ALLOC_IN_RC(double_reg));
2867 match(RegD);
2868
2869 format %{ %}
2870 interface(REG_INTER);
2871 %}
2872
2873 // Double register operands
2874 operand legRegD() %{
2875 constraint(ALLOC_IN_RC(double_reg_legacy));
2876 match(RegD);
2877
2878 format %{ %}
2879 interface(REG_INTER);
2880 %}
2881
2882 // Double register operands
2883 operand vlRegD() %{
2884 constraint(ALLOC_IN_RC(double_reg_vl));
2885 match(RegD);
2886
2887 format %{ %}
2888 interface(REG_INTER);
2889 %}
2890
2891 //----------Memory Operands----------------------------------------------------
2892 // Direct Memory Operand
2893 // operand direct(immP addr)
2894 // %{
2895 // match(addr);
2896
2897 // format %{ "[$addr]" %}
2898 // interface(MEMORY_INTER) %{
2899 // base(0xFFFFFFFF);
2900 // index(0x4);
2901 // scale(0x0);
2902 // disp($addr);
2903 // %}
2904 // %}
2905
2906 // Indirect Memory Operand
2907 operand indirect(any_RegP reg)
2908 %{
2909 constraint(ALLOC_IN_RC(ptr_reg));
2910 match(reg);
2911
2912 format %{ "[$reg]" %}
2913 interface(MEMORY_INTER) %{
2914 base($reg);
2915 index(0x4);
2916 scale(0x0);
2917 disp(0x0);
2918 %}
2919 %}
2920
2921 // Indirect Memory Plus Short Offset Operand
2922 operand indOffset8(any_RegP reg, immL8 off)
2923 %{
2924 constraint(ALLOC_IN_RC(ptr_reg));
2925 match(AddP reg off);
2926
2927 format %{ "[$reg + $off (8-bit)]" %}
2928 interface(MEMORY_INTER) %{
2929 base($reg);
2930 index(0x4);
2931 scale(0x0);
2932 disp($off);
2933 %}
2934 %}
2935
2936 // Indirect Memory Plus Long Offset Operand
2937 operand indOffset32(any_RegP reg, immL32 off)
2938 %{
2939 constraint(ALLOC_IN_RC(ptr_reg));
2940 match(AddP reg off);
2941
2942 format %{ "[$reg + $off (32-bit)]" %}
2943 interface(MEMORY_INTER) %{
2944 base($reg);
2945 index(0x4);
2946 scale(0x0);
2947 disp($off);
2948 %}
2949 %}
2950
2951 // Indirect Memory Plus Index Register Plus Offset Operand
2952 operand indIndexOffset(any_RegP reg, rRegL lreg, immL32 off)
2953 %{
2954 constraint(ALLOC_IN_RC(ptr_reg));
2955 match(AddP (AddP reg lreg) off);
2956
2957 op_cost(10);
2958 format %{"[$reg + $off + $lreg]" %}
2959 interface(MEMORY_INTER) %{
2960 base($reg);
2961 index($lreg);
2962 scale(0x0);
2963 disp($off);
2964 %}
2965 %}
2966
2967 // Indirect Memory Plus Index Register Plus Offset Operand
2968 operand indIndex(any_RegP reg, rRegL lreg)
2969 %{
2970 constraint(ALLOC_IN_RC(ptr_reg));
2971 match(AddP reg lreg);
2972
2973 op_cost(10);
2974 format %{"[$reg + $lreg]" %}
2975 interface(MEMORY_INTER) %{
2976 base($reg);
2977 index($lreg);
2978 scale(0x0);
2979 disp(0x0);
2980 %}
2981 %}
2982
2983 // Indirect Memory Times Scale Plus Index Register
2984 operand indIndexScale(any_RegP reg, rRegL lreg, immI2 scale)
2985 %{
2986 constraint(ALLOC_IN_RC(ptr_reg));
2987 match(AddP reg (LShiftL lreg scale));
2988
2989 op_cost(10);
2990 format %{"[$reg + $lreg << $scale]" %}
2991 interface(MEMORY_INTER) %{
2992 base($reg);
2993 index($lreg);
2994 scale($scale);
2995 disp(0x0);
2996 %}
2997 %}
2998
2999 operand indPosIndexScale(any_RegP reg, rRegI idx, immI2 scale)
3000 %{
3001 constraint(ALLOC_IN_RC(ptr_reg));
3002 predicate(n->in(3)->in(1)->as_Type()->type()->is_long()->_lo >= 0);
3003 match(AddP reg (LShiftL (ConvI2L idx) scale));
3004
3005 op_cost(10);
3006 format %{"[$reg + pos $idx << $scale]" %}
3007 interface(MEMORY_INTER) %{
3008 base($reg);
3009 index($idx);
3010 scale($scale);
3011 disp(0x0);
3012 %}
3013 %}
3014
3015 // Indirect Memory Times Scale Plus Index Register Plus Offset Operand
3016 operand indIndexScaleOffset(any_RegP reg, immL32 off, rRegL lreg, immI2 scale)
3017 %{
3018 constraint(ALLOC_IN_RC(ptr_reg));
3019 match(AddP (AddP reg (LShiftL lreg scale)) off);
3020
3021 op_cost(10);
3022 format %{"[$reg + $off + $lreg << $scale]" %}
3023 interface(MEMORY_INTER) %{
3024 base($reg);
3025 index($lreg);
3026 scale($scale);
3027 disp($off);
3028 %}
3029 %}
3030
3031 // Indirect Memory Plus Positive Index Register Plus Offset Operand
3032 operand indPosIndexOffset(any_RegP reg, immL32 off, rRegI idx)
3033 %{
3034 constraint(ALLOC_IN_RC(ptr_reg));
3035 predicate(n->in(2)->in(3)->as_Type()->type()->is_long()->_lo >= 0);
3036 match(AddP (AddP reg (ConvI2L idx)) off);
3037
3038 op_cost(10);
3039 format %{"[$reg + $off + $idx]" %}
3040 interface(MEMORY_INTER) %{
3041 base($reg);
3042 index($idx);
3043 scale(0x0);
3044 disp($off);
3045 %}
3046 %}
3047
3048 // Indirect Memory Times Scale Plus Positive Index Register Plus Offset Operand
3049 operand indPosIndexScaleOffset(any_RegP reg, immL32 off, rRegI idx, immI2 scale)
3050 %{
3051 constraint(ALLOC_IN_RC(ptr_reg));
3052 predicate(n->in(2)->in(3)->in(1)->as_Type()->type()->is_long()->_lo >= 0);
3053 match(AddP (AddP reg (LShiftL (ConvI2L idx) scale)) off);
3054
3055 op_cost(10);
3056 format %{"[$reg + $off + $idx << $scale]" %}
3057 interface(MEMORY_INTER) %{
3058 base($reg);
3059 index($idx);
3060 scale($scale);
3061 disp($off);
3062 %}
3063 %}
3064
3065 // Indirect Narrow Oop Plus Offset Operand
3066 // Note: x86 architecture doesn't support "scale * index + offset" without a base
3067 // we can't free r12 even with CompressedOops::base() == nullptr.
3068 operand indCompressedOopOffset(rRegN reg, immL32 off) %{
3069 predicate(UseCompressedOops && (CompressedOops::shift() == Address::times_8));
3070 constraint(ALLOC_IN_RC(ptr_reg));
3071 match(AddP (DecodeN reg) off);
3072
3073 op_cost(10);
3074 format %{"[R12 + $reg << 3 + $off] (compressed oop addressing)" %}
3075 interface(MEMORY_INTER) %{
3076 base(0xc); // R12
3077 index($reg);
3078 scale(0x3);
3079 disp($off);
3080 %}
3081 %}
3082
3083 // Indirect Memory Operand
3084 operand indirectNarrow(rRegN reg)
3085 %{
3086 predicate(CompressedOops::shift() == 0);
3087 constraint(ALLOC_IN_RC(ptr_reg));
3088 match(DecodeN reg);
3089
3090 format %{ "[$reg]" %}
3091 interface(MEMORY_INTER) %{
3092 base($reg);
3093 index(0x4);
3094 scale(0x0);
3095 disp(0x0);
3096 %}
3097 %}
3098
3099 // Indirect Memory Plus Short Offset Operand
3100 operand indOffset8Narrow(rRegN reg, immL8 off)
3101 %{
3102 predicate(CompressedOops::shift() == 0);
3103 constraint(ALLOC_IN_RC(ptr_reg));
3104 match(AddP (DecodeN reg) off);
3105
3106 format %{ "[$reg + $off (8-bit)]" %}
3107 interface(MEMORY_INTER) %{
3108 base($reg);
3109 index(0x4);
3110 scale(0x0);
3111 disp($off);
3112 %}
3113 %}
3114
3115 // Indirect Memory Plus Long Offset Operand
3116 operand indOffset32Narrow(rRegN reg, immL32 off)
3117 %{
3118 predicate(CompressedOops::shift() == 0);
3119 constraint(ALLOC_IN_RC(ptr_reg));
3120 match(AddP (DecodeN reg) off);
3121
3122 format %{ "[$reg + $off (32-bit)]" %}
3123 interface(MEMORY_INTER) %{
3124 base($reg);
3125 index(0x4);
3126 scale(0x0);
3127 disp($off);
3128 %}
3129 %}
3130
3131 // Indirect Memory Plus Index Register Plus Offset Operand
3132 operand indIndexOffsetNarrow(rRegN reg, rRegL lreg, immL32 off)
3133 %{
3134 predicate(CompressedOops::shift() == 0);
3135 constraint(ALLOC_IN_RC(ptr_reg));
3136 match(AddP (AddP (DecodeN reg) lreg) off);
3137
3138 op_cost(10);
3139 format %{"[$reg + $off + $lreg]" %}
3140 interface(MEMORY_INTER) %{
3141 base($reg);
3142 index($lreg);
3143 scale(0x0);
3144 disp($off);
3145 %}
3146 %}
3147
3148 // Indirect Memory Plus Index Register Plus Offset Operand
3149 operand indIndexNarrow(rRegN reg, rRegL lreg)
3150 %{
3151 predicate(CompressedOops::shift() == 0);
3152 constraint(ALLOC_IN_RC(ptr_reg));
3153 match(AddP (DecodeN reg) lreg);
3154
3155 op_cost(10);
3156 format %{"[$reg + $lreg]" %}
3157 interface(MEMORY_INTER) %{
3158 base($reg);
3159 index($lreg);
3160 scale(0x0);
3161 disp(0x0);
3162 %}
3163 %}
3164
3165 // Indirect Memory Times Scale Plus Index Register
3166 operand indIndexScaleNarrow(rRegN reg, rRegL lreg, immI2 scale)
3167 %{
3168 predicate(CompressedOops::shift() == 0);
3169 constraint(ALLOC_IN_RC(ptr_reg));
3170 match(AddP (DecodeN reg) (LShiftL lreg scale));
3171
3172 op_cost(10);
3173 format %{"[$reg + $lreg << $scale]" %}
3174 interface(MEMORY_INTER) %{
3175 base($reg);
3176 index($lreg);
3177 scale($scale);
3178 disp(0x0);
3179 %}
3180 %}
3181
3182 // Indirect Memory Times Scale Plus Index Register Plus Offset Operand
3183 operand indIndexScaleOffsetNarrow(rRegN reg, immL32 off, rRegL lreg, immI2 scale)
3184 %{
3185 predicate(CompressedOops::shift() == 0);
3186 constraint(ALLOC_IN_RC(ptr_reg));
3187 match(AddP (AddP (DecodeN reg) (LShiftL lreg scale)) off);
3188
3189 op_cost(10);
3190 format %{"[$reg + $off + $lreg << $scale]" %}
3191 interface(MEMORY_INTER) %{
3192 base($reg);
3193 index($lreg);
3194 scale($scale);
3195 disp($off);
3196 %}
3197 %}
3198
3199 // Indirect Memory Times Plus Positive Index Register Plus Offset Operand
3200 operand indPosIndexOffsetNarrow(rRegN reg, immL32 off, rRegI idx)
3201 %{
3202 constraint(ALLOC_IN_RC(ptr_reg));
3203 predicate(CompressedOops::shift() == 0 && n->in(2)->in(3)->as_Type()->type()->is_long()->_lo >= 0);
3204 match(AddP (AddP (DecodeN reg) (ConvI2L idx)) off);
3205
3206 op_cost(10);
3207 format %{"[$reg + $off + $idx]" %}
3208 interface(MEMORY_INTER) %{
3209 base($reg);
3210 index($idx);
3211 scale(0x0);
3212 disp($off);
3213 %}
3214 %}
3215
3216 // Indirect Memory Times Scale Plus Positive Index Register Plus Offset Operand
3217 operand indPosIndexScaleOffsetNarrow(rRegN reg, immL32 off, rRegI idx, immI2 scale)
3218 %{
3219 constraint(ALLOC_IN_RC(ptr_reg));
3220 predicate(CompressedOops::shift() == 0 && n->in(2)->in(3)->in(1)->as_Type()->type()->is_long()->_lo >= 0);
3221 match(AddP (AddP (DecodeN reg) (LShiftL (ConvI2L idx) scale)) off);
3222
3223 op_cost(10);
3224 format %{"[$reg + $off + $idx << $scale]" %}
3225 interface(MEMORY_INTER) %{
3226 base($reg);
3227 index($idx);
3228 scale($scale);
3229 disp($off);
3230 %}
3231 %}
3232
3233 //----------Special Memory Operands--------------------------------------------
3234 // Stack Slot Operand - This operand is used for loading and storing temporary
3235 // values on the stack where a match requires a value to
3236 // flow through memory.
3237 operand stackSlotP(sRegP reg)
3238 %{
3239 constraint(ALLOC_IN_RC(stack_slots));
3240 // No match rule because this operand is only generated in matching
3241
3242 format %{ "[$reg]" %}
3243 interface(MEMORY_INTER) %{
3244 base(0x4); // RSP
3245 index(0x4); // No Index
3246 scale(0x0); // No Scale
3247 disp($reg); // Stack Offset
3248 %}
3249 %}
3250
3251 operand stackSlotI(sRegI reg)
3252 %{
3253 constraint(ALLOC_IN_RC(stack_slots));
3254 // No match rule because this operand is only generated in matching
3255
3256 format %{ "[$reg]" %}
3257 interface(MEMORY_INTER) %{
3258 base(0x4); // RSP
3259 index(0x4); // No Index
3260 scale(0x0); // No Scale
3261 disp($reg); // Stack Offset
3262 %}
3263 %}
3264
3265 operand stackSlotF(sRegF reg)
3266 %{
3267 constraint(ALLOC_IN_RC(stack_slots));
3268 // No match rule because this operand is only generated in matching
3269
3270 format %{ "[$reg]" %}
3271 interface(MEMORY_INTER) %{
3272 base(0x4); // RSP
3273 index(0x4); // No Index
3274 scale(0x0); // No Scale
3275 disp($reg); // Stack Offset
3276 %}
3277 %}
3278
3279 operand stackSlotD(sRegD reg)
3280 %{
3281 constraint(ALLOC_IN_RC(stack_slots));
3282 // No match rule because this operand is only generated in matching
3283
3284 format %{ "[$reg]" %}
3285 interface(MEMORY_INTER) %{
3286 base(0x4); // RSP
3287 index(0x4); // No Index
3288 scale(0x0); // No Scale
3289 disp($reg); // Stack Offset
3290 %}
3291 %}
3292 operand stackSlotL(sRegL reg)
3293 %{
3294 constraint(ALLOC_IN_RC(stack_slots));
3295 // No match rule because this operand is only generated in matching
3296
3297 format %{ "[$reg]" %}
3298 interface(MEMORY_INTER) %{
3299 base(0x4); // RSP
3300 index(0x4); // No Index
3301 scale(0x0); // No Scale
3302 disp($reg); // Stack Offset
3303 %}
3304 %}
3305
3306 //----------Conditional Branch Operands----------------------------------------
3307 // Comparison Op - This is the operation of the comparison, and is limited to
3308 // the following set of codes:
3309 // L (<), LE (<=), G (>), GE (>=), E (==), NE (!=)
3310 //
3311 // Other attributes of the comparison, such as unsignedness, are specified
3312 // by the comparison instruction that sets a condition code flags register.
3313 // That result is represented by a flags operand whose subtype is appropriate
3314 // to the unsignedness (etc.) of the comparison.
3315 //
3316 // Later, the instruction which matches both the Comparison Op (a Bool) and
3317 // the flags (produced by the Cmp) specifies the coding of the comparison op
3318 // by matching a specific subtype of Bool operand below, such as cmpOpU.
3319
3320 // Comparison Code
3321 operand cmpOp()
3322 %{
3323 match(Bool);
3324
3325 format %{ "" %}
3326 interface(COND_INTER) %{
3327 equal(0x4, "e");
3328 not_equal(0x5, "ne");
3329 less(0xC, "l");
3330 greater_equal(0xD, "ge");
3331 less_equal(0xE, "le");
3332 greater(0xF, "g");
3333 overflow(0x0, "o");
3334 no_overflow(0x1, "no");
3335 %}
3336 %}
3337
3338 // Comparison Code, unsigned compare. Used by FP also, with
3339 // C2 (unordered) turned into GT or LT already. The other bits
3340 // C0 and C3 are turned into Carry & Zero flags.
3341 operand cmpOpU()
3342 %{
3343 match(Bool);
3344
3345 format %{ "" %}
3346 interface(COND_INTER) %{
3347 equal(0x4, "e");
3348 not_equal(0x5, "ne");
3349 less(0x2, "b");
3350 greater_equal(0x3, "ae");
3351 less_equal(0x6, "be");
3352 greater(0x7, "a");
3353 overflow(0x0, "o");
3354 no_overflow(0x1, "no");
3355 %}
3356 %}
3357
3358
3359 // Floating comparisons that don't require any fixup for the unordered case,
3360 // If both inputs of the comparison are the same, ZF is always set so we
3361 // don't need to use cmpOpUCF2 for eq/ne
3362 operand cmpOpUCF() %{
3363 match(Bool);
3364 predicate(n->as_Bool()->_test._test == BoolTest::lt ||
3365 n->as_Bool()->_test._test == BoolTest::ge ||
3366 n->as_Bool()->_test._test == BoolTest::le ||
3367 n->as_Bool()->_test._test == BoolTest::gt ||
3368 n->in(1)->in(1) == n->in(1)->in(2));
3369 format %{ "" %}
3370 interface(COND_INTER) %{
3371 equal(0xb, "np");
3372 not_equal(0xa, "p");
3373 less(0x2, "b");
3374 greater_equal(0x3, "ae");
3375 less_equal(0x6, "be");
3376 greater(0x7, "a");
3377 overflow(0x0, "o");
3378 no_overflow(0x1, "no");
3379 %}
3380 %}
3381
3382
3383 // Floating comparisons that can be fixed up with extra conditional jumps
3384 operand cmpOpUCF2() %{
3385 match(Bool);
3386 predicate((n->as_Bool()->_test._test == BoolTest::ne ||
3387 n->as_Bool()->_test._test == BoolTest::eq) &&
3388 n->in(1)->in(1) != n->in(1)->in(2));
3389 format %{ "" %}
3390 interface(COND_INTER) %{
3391 equal(0x4, "e");
3392 not_equal(0x5, "ne");
3393 less(0x2, "b");
3394 greater_equal(0x3, "ae");
3395 less_equal(0x6, "be");
3396 greater(0x7, "a");
3397 overflow(0x0, "o");
3398 no_overflow(0x1, "no");
3399 %}
3400 %}
3401
3402 //----------OPERAND CLASSES----------------------------------------------------
3403 // Operand Classes are groups of operands that are used as to simplify
3404 // instruction definitions by not requiring the AD writer to specify separate
3405 // instructions for every form of operand when the instruction accepts
3406 // multiple operand types with the same basic encoding and format. The classic
3407 // case of this is memory operands.
3408
3409 opclass memory(indirect, indOffset8, indOffset32, indIndexOffset, indIndex,
3410 indIndexScale, indPosIndexScale, indIndexScaleOffset, indPosIndexOffset, indPosIndexScaleOffset,
3411 indCompressedOopOffset,
3412 indirectNarrow, indOffset8Narrow, indOffset32Narrow,
3413 indIndexOffsetNarrow, indIndexNarrow, indIndexScaleNarrow,
3414 indIndexScaleOffsetNarrow, indPosIndexOffsetNarrow, indPosIndexScaleOffsetNarrow);
3415
3416 //----------PIPELINE-----------------------------------------------------------
3417 // Rules which define the behavior of the target architectures pipeline.
3418 pipeline %{
3419
3420 //----------ATTRIBUTES---------------------------------------------------------
3421 attributes %{
3422 variable_size_instructions; // Fixed size instructions
3423 max_instructions_per_bundle = 3; // Up to 3 instructions per bundle
3424 instruction_unit_size = 1; // An instruction is 1 bytes long
3425 instruction_fetch_unit_size = 16; // The processor fetches one line
3426 instruction_fetch_units = 1; // of 16 bytes
3427 %}
3428
3429 //----------RESOURCES----------------------------------------------------------
3430 // Resources are the functional units available to the machine
3431
3432 // Generic P2/P3 pipeline
3433 // 3 decoders, only D0 handles big operands; a "bundle" is the limit of
3434 // 3 instructions decoded per cycle.
3435 // 2 load/store ops per cycle, 1 branch, 1 FPU,
3436 // 3 ALU op, only ALU0 handles mul instructions.
3437 resources( D0, D1, D2, DECODE = D0 | D1 | D2,
3438 MS0, MS1, MS2, MEM = MS0 | MS1 | MS2,
3439 BR, FPU,
3440 ALU0, ALU1, ALU2, ALU = ALU0 | ALU1 | ALU2);
3441
3442 //----------PIPELINE DESCRIPTION-----------------------------------------------
3443 // Pipeline Description specifies the stages in the machine's pipeline
3444
3445 // Generic P2/P3 pipeline
3446 pipe_desc(S0, S1, S2, S3, S4, S5);
3447
3448 //----------PIPELINE CLASSES---------------------------------------------------
3449 // Pipeline Classes describe the stages in which input and output are
3450 // referenced by the hardware pipeline.
3451
3452 // Naming convention: ialu or fpu
3453 // Then: _reg
3454 // Then: _reg if there is a 2nd register
3455 // Then: _long if it's a pair of instructions implementing a long
3456 // Then: _fat if it requires the big decoder
3457 // Or: _mem if it requires the big decoder and a memory unit.
3458
3459 // Integer ALU reg operation
3460 pipe_class ialu_reg(rRegI dst)
3461 %{
3462 single_instruction;
3463 dst : S4(write);
3464 dst : S3(read);
3465 DECODE : S0; // any decoder
3466 ALU : S3; // any alu
3467 %}
3468
3469 // Long ALU reg operation
3470 pipe_class ialu_reg_long(rRegL dst)
3471 %{
3472 instruction_count(2);
3473 dst : S4(write);
3474 dst : S3(read);
3475 DECODE : S0(2); // any 2 decoders
3476 ALU : S3(2); // both alus
3477 %}
3478
3479 // Integer ALU reg operation using big decoder
3480 pipe_class ialu_reg_fat(rRegI dst)
3481 %{
3482 single_instruction;
3483 dst : S4(write);
3484 dst : S3(read);
3485 D0 : S0; // big decoder only
3486 ALU : S3; // any alu
3487 %}
3488
3489 // Integer ALU reg-reg operation
3490 pipe_class ialu_reg_reg(rRegI dst, rRegI src)
3491 %{
3492 single_instruction;
3493 dst : S4(write);
3494 src : S3(read);
3495 DECODE : S0; // any decoder
3496 ALU : S3; // any alu
3497 %}
3498
3499 // Integer ALU reg-reg operation
3500 pipe_class ialu_reg_reg_fat(rRegI dst, memory src)
3501 %{
3502 single_instruction;
3503 dst : S4(write);
3504 src : S3(read);
3505 D0 : S0; // big decoder only
3506 ALU : S3; // any alu
3507 %}
3508
3509 // Integer ALU reg-mem operation
3510 pipe_class ialu_reg_mem(rRegI dst, memory mem)
3511 %{
3512 single_instruction;
3513 dst : S5(write);
3514 mem : S3(read);
3515 D0 : S0; // big decoder only
3516 ALU : S4; // any alu
3517 MEM : S3; // any mem
3518 %}
3519
3520 // Integer mem operation (prefetch)
3521 pipe_class ialu_mem(memory mem)
3522 %{
3523 single_instruction;
3524 mem : S3(read);
3525 D0 : S0; // big decoder only
3526 MEM : S3; // any mem
3527 %}
3528
3529 // Integer Store to Memory
3530 pipe_class ialu_mem_reg(memory mem, rRegI src)
3531 %{
3532 single_instruction;
3533 mem : S3(read);
3534 src : S5(read);
3535 D0 : S0; // big decoder only
3536 ALU : S4; // any alu
3537 MEM : S3;
3538 %}
3539
3540 // // Long Store to Memory
3541 // pipe_class ialu_mem_long_reg(memory mem, rRegL src)
3542 // %{
3543 // instruction_count(2);
3544 // mem : S3(read);
3545 // src : S5(read);
3546 // D0 : S0(2); // big decoder only; twice
3547 // ALU : S4(2); // any 2 alus
3548 // MEM : S3(2); // Both mems
3549 // %}
3550
3551 // Integer Store to Memory
3552 pipe_class ialu_mem_imm(memory mem)
3553 %{
3554 single_instruction;
3555 mem : S3(read);
3556 D0 : S0; // big decoder only
3557 ALU : S4; // any alu
3558 MEM : S3;
3559 %}
3560
3561 // Integer ALU0 reg-reg operation
3562 pipe_class ialu_reg_reg_alu0(rRegI dst, rRegI src)
3563 %{
3564 single_instruction;
3565 dst : S4(write);
3566 src : S3(read);
3567 D0 : S0; // Big decoder only
3568 ALU0 : S3; // only alu0
3569 %}
3570
3571 // Integer ALU0 reg-mem operation
3572 pipe_class ialu_reg_mem_alu0(rRegI dst, memory mem)
3573 %{
3574 single_instruction;
3575 dst : S5(write);
3576 mem : S3(read);
3577 D0 : S0; // big decoder only
3578 ALU0 : S4; // ALU0 only
3579 MEM : S3; // any mem
3580 %}
3581
3582 // Integer ALU reg-reg operation
3583 pipe_class ialu_cr_reg_reg(rFlagsReg cr, rRegI src1, rRegI src2)
3584 %{
3585 single_instruction;
3586 cr : S4(write);
3587 src1 : S3(read);
3588 src2 : S3(read);
3589 DECODE : S0; // any decoder
3590 ALU : S3; // any alu
3591 %}
3592
3593 // Integer ALU reg-imm operation
3594 pipe_class ialu_cr_reg_imm(rFlagsReg cr, rRegI src1)
3595 %{
3596 single_instruction;
3597 cr : S4(write);
3598 src1 : S3(read);
3599 DECODE : S0; // any decoder
3600 ALU : S3; // any alu
3601 %}
3602
3603 // Integer ALU reg-mem operation
3604 pipe_class ialu_cr_reg_mem(rFlagsReg cr, rRegI src1, memory src2)
3605 %{
3606 single_instruction;
3607 cr : S4(write);
3608 src1 : S3(read);
3609 src2 : S3(read);
3610 D0 : S0; // big decoder only
3611 ALU : S4; // any alu
3612 MEM : S3;
3613 %}
3614
3615 // Conditional move reg-reg
3616 pipe_class pipe_cmplt( rRegI p, rRegI q, rRegI y)
3617 %{
3618 instruction_count(4);
3619 y : S4(read);
3620 q : S3(read);
3621 p : S3(read);
3622 DECODE : S0(4); // any decoder
3623 %}
3624
3625 // Conditional move reg-reg
3626 pipe_class pipe_cmov_reg( rRegI dst, rRegI src, rFlagsReg cr)
3627 %{
3628 single_instruction;
3629 dst : S4(write);
3630 src : S3(read);
3631 cr : S3(read);
3632 DECODE : S0; // any decoder
3633 %}
3634
3635 // Conditional move reg-mem
3636 pipe_class pipe_cmov_mem( rFlagsReg cr, rRegI dst, memory src)
3637 %{
3638 single_instruction;
3639 dst : S4(write);
3640 src : S3(read);
3641 cr : S3(read);
3642 DECODE : S0; // any decoder
3643 MEM : S3;
3644 %}
3645
3646 // Conditional move reg-reg long
3647 pipe_class pipe_cmov_reg_long( rFlagsReg cr, rRegL dst, rRegL src)
3648 %{
3649 single_instruction;
3650 dst : S4(write);
3651 src : S3(read);
3652 cr : S3(read);
3653 DECODE : S0(2); // any 2 decoders
3654 %}
3655
3656 // Float reg-reg operation
3657 pipe_class fpu_reg(regD dst)
3658 %{
3659 instruction_count(2);
3660 dst : S3(read);
3661 DECODE : S0(2); // any 2 decoders
3662 FPU : S3;
3663 %}
3664
3665 // Float reg-reg operation
3666 pipe_class fpu_reg_reg(regD dst, regD src)
3667 %{
3668 instruction_count(2);
3669 dst : S4(write);
3670 src : S3(read);
3671 DECODE : S0(2); // any 2 decoders
3672 FPU : S3;
3673 %}
3674
3675 // Float reg-reg operation
3676 pipe_class fpu_reg_reg_reg(regD dst, regD src1, regD src2)
3677 %{
3678 instruction_count(3);
3679 dst : S4(write);
3680 src1 : S3(read);
3681 src2 : S3(read);
3682 DECODE : S0(3); // any 3 decoders
3683 FPU : S3(2);
3684 %}
3685
3686 // Float reg-reg operation
3687 pipe_class fpu_reg_reg_reg_reg(regD dst, regD src1, regD src2, regD src3)
3688 %{
3689 instruction_count(4);
3690 dst : S4(write);
3691 src1 : S3(read);
3692 src2 : S3(read);
3693 src3 : S3(read);
3694 DECODE : S0(4); // any 3 decoders
3695 FPU : S3(2);
3696 %}
3697
3698 // Float reg-reg operation
3699 pipe_class fpu_reg_mem_reg_reg(regD dst, memory src1, regD src2, regD src3)
3700 %{
3701 instruction_count(4);
3702 dst : S4(write);
3703 src1 : S3(read);
3704 src2 : S3(read);
3705 src3 : S3(read);
3706 DECODE : S1(3); // any 3 decoders
3707 D0 : S0; // Big decoder only
3708 FPU : S3(2);
3709 MEM : S3;
3710 %}
3711
3712 // Float reg-mem operation
3713 pipe_class fpu_reg_mem(regD dst, memory mem)
3714 %{
3715 instruction_count(2);
3716 dst : S5(write);
3717 mem : S3(read);
3718 D0 : S0; // big decoder only
3719 DECODE : S1; // any decoder for FPU POP
3720 FPU : S4;
3721 MEM : S3; // any mem
3722 %}
3723
3724 // Float reg-mem operation
3725 pipe_class fpu_reg_reg_mem(regD dst, regD src1, memory mem)
3726 %{
3727 instruction_count(3);
3728 dst : S5(write);
3729 src1 : S3(read);
3730 mem : S3(read);
3731 D0 : S0; // big decoder only
3732 DECODE : S1(2); // any decoder for FPU POP
3733 FPU : S4;
3734 MEM : S3; // any mem
3735 %}
3736
3737 // Float mem-reg operation
3738 pipe_class fpu_mem_reg(memory mem, regD src)
3739 %{
3740 instruction_count(2);
3741 src : S5(read);
3742 mem : S3(read);
3743 DECODE : S0; // any decoder for FPU PUSH
3744 D0 : S1; // big decoder only
3745 FPU : S4;
3746 MEM : S3; // any mem
3747 %}
3748
3749 pipe_class fpu_mem_reg_reg(memory mem, regD src1, regD src2)
3750 %{
3751 instruction_count(3);
3752 src1 : S3(read);
3753 src2 : S3(read);
3754 mem : S3(read);
3755 DECODE : S0(2); // any decoder for FPU PUSH
3756 D0 : S1; // big decoder only
3757 FPU : S4;
3758 MEM : S3; // any mem
3759 %}
3760
3761 pipe_class fpu_mem_reg_mem(memory mem, regD src1, memory src2)
3762 %{
3763 instruction_count(3);
3764 src1 : S3(read);
3765 src2 : S3(read);
3766 mem : S4(read);
3767 DECODE : S0; // any decoder for FPU PUSH
3768 D0 : S0(2); // big decoder only
3769 FPU : S4;
3770 MEM : S3(2); // any mem
3771 %}
3772
3773 pipe_class fpu_mem_mem(memory dst, memory src1)
3774 %{
3775 instruction_count(2);
3776 src1 : S3(read);
3777 dst : S4(read);
3778 D0 : S0(2); // big decoder only
3779 MEM : S3(2); // any mem
3780 %}
3781
3782 pipe_class fpu_mem_mem_mem(memory dst, memory src1, memory src2)
3783 %{
3784 instruction_count(3);
3785 src1 : S3(read);
3786 src2 : S3(read);
3787 dst : S4(read);
3788 D0 : S0(3); // big decoder only
3789 FPU : S4;
3790 MEM : S3(3); // any mem
3791 %}
3792
3793 pipe_class fpu_mem_reg_con(memory mem, regD src1)
3794 %{
3795 instruction_count(3);
3796 src1 : S4(read);
3797 mem : S4(read);
3798 DECODE : S0; // any decoder for FPU PUSH
3799 D0 : S0(2); // big decoder only
3800 FPU : S4;
3801 MEM : S3(2); // any mem
3802 %}
3803
3804 // Float load constant
3805 pipe_class fpu_reg_con(regD dst)
3806 %{
3807 instruction_count(2);
3808 dst : S5(write);
3809 D0 : S0; // big decoder only for the load
3810 DECODE : S1; // any decoder for FPU POP
3811 FPU : S4;
3812 MEM : S3; // any mem
3813 %}
3814
3815 // Float load constant
3816 pipe_class fpu_reg_reg_con(regD dst, regD src)
3817 %{
3818 instruction_count(3);
3819 dst : S5(write);
3820 src : S3(read);
3821 D0 : S0; // big decoder only for the load
3822 DECODE : S1(2); // any decoder for FPU POP
3823 FPU : S4;
3824 MEM : S3; // any mem
3825 %}
3826
3827 // UnConditional branch
3828 pipe_class pipe_jmp(label labl)
3829 %{
3830 single_instruction;
3831 BR : S3;
3832 %}
3833
3834 // Conditional branch
3835 pipe_class pipe_jcc(cmpOp cmp, rFlagsReg cr, label labl)
3836 %{
3837 single_instruction;
3838 cr : S1(read);
3839 BR : S3;
3840 %}
3841
3842 // Allocation idiom
3843 pipe_class pipe_cmpxchg(rRegP dst, rRegP heap_ptr)
3844 %{
3845 instruction_count(1); force_serialization;
3846 fixed_latency(6);
3847 heap_ptr : S3(read);
3848 DECODE : S0(3);
3849 D0 : S2;
3850 MEM : S3;
3851 ALU : S3(2);
3852 dst : S5(write);
3853 BR : S5;
3854 %}
3855
3856 // Generic big/slow expanded idiom
3857 pipe_class pipe_slow()
3858 %{
3859 instruction_count(10); multiple_bundles; force_serialization;
3860 fixed_latency(100);
3861 D0 : S0(2);
3862 MEM : S3(2);
3863 %}
3864
3865 // The real do-nothing guy
3866 pipe_class empty()
3867 %{
3868 instruction_count(0);
3869 %}
3870
3871 // Define the class for the Nop node
3872 define
3873 %{
3874 MachNop = empty;
3875 %}
3876
3877 %}
3878
3879 //----------INSTRUCTIONS-------------------------------------------------------
3880 //
3881 // match -- States which machine-independent subtree may be replaced
3882 // by this instruction.
3883 // ins_cost -- The estimated cost of this instruction is used by instruction
3884 // selection to identify a minimum cost tree of machine
3885 // instructions that matches a tree of machine-independent
3886 // instructions.
3887 // format -- A string providing the disassembly for this instruction.
3888 // The value of an instruction's operand may be inserted
3889 // by referring to it with a '$' prefix.
3890 // opcode -- Three instruction opcodes may be provided. These are referred
3891 // to within an encode class as $primary, $secondary, and $tertiary
3892 // rrspectively. The primary opcode is commonly used to
3893 // indicate the type of machine instruction, while secondary
3894 // and tertiary are often used for prefix options or addressing
3895 // modes.
3896 // ins_encode -- A list of encode classes with parameters. The encode class
3897 // name must have been defined in an 'enc_class' specification
3898 // in the encode section of the architecture description.
3899
3900 // Dummy reg-to-reg vector moves. Removed during post-selection cleanup.
3901 // Load Float
3902 instruct MoveF2VL(vlRegF dst, regF src) %{
3903 match(Set dst src);
3904 format %{ "movss $dst,$src\t! load float (4 bytes)" %}
3905 ins_encode %{
3906 ShouldNotReachHere();
3907 %}
3908 ins_pipe( fpu_reg_reg );
3909 %}
3910
3911 // Load Float
3912 instruct MoveF2LEG(legRegF dst, regF src) %{
3913 match(Set dst src);
3914 format %{ "movss $dst,$src\t# if src != dst load float (4 bytes)" %}
3915 ins_encode %{
3916 ShouldNotReachHere();
3917 %}
3918 ins_pipe( fpu_reg_reg );
3919 %}
3920
3921 // Load Float
3922 instruct MoveVL2F(regF dst, vlRegF src) %{
3923 match(Set dst src);
3924 format %{ "movss $dst,$src\t! load float (4 bytes)" %}
3925 ins_encode %{
3926 ShouldNotReachHere();
3927 %}
3928 ins_pipe( fpu_reg_reg );
3929 %}
3930
3931 // Load Float
3932 instruct MoveLEG2F(regF dst, legRegF src) %{
3933 match(Set dst src);
3934 format %{ "movss $dst,$src\t# if src != dst load float (4 bytes)" %}
3935 ins_encode %{
3936 ShouldNotReachHere();
3937 %}
3938 ins_pipe( fpu_reg_reg );
3939 %}
3940
3941 // Load Double
3942 instruct MoveD2VL(vlRegD dst, regD src) %{
3943 match(Set dst src);
3944 format %{ "movsd $dst,$src\t! load double (8 bytes)" %}
3945 ins_encode %{
3946 ShouldNotReachHere();
3947 %}
3948 ins_pipe( fpu_reg_reg );
3949 %}
3950
3951 // Load Double
3952 instruct MoveD2LEG(legRegD dst, regD src) %{
3953 match(Set dst src);
3954 format %{ "movsd $dst,$src\t# if src != dst load double (8 bytes)" %}
3955 ins_encode %{
3956 ShouldNotReachHere();
3957 %}
3958 ins_pipe( fpu_reg_reg );
3959 %}
3960
3961 // Load Double
3962 instruct MoveVL2D(regD dst, vlRegD src) %{
3963 match(Set dst src);
3964 format %{ "movsd $dst,$src\t! load double (8 bytes)" %}
3965 ins_encode %{
3966 ShouldNotReachHere();
3967 %}
3968 ins_pipe( fpu_reg_reg );
3969 %}
3970
3971 // Load Double
3972 instruct MoveLEG2D(regD dst, legRegD src) %{
3973 match(Set dst src);
3974 format %{ "movsd $dst,$src\t# if src != dst load double (8 bytes)" %}
3975 ins_encode %{
3976 ShouldNotReachHere();
3977 %}
3978 ins_pipe( fpu_reg_reg );
3979 %}
3980
3981 //----------Load/Store/Move Instructions---------------------------------------
3982 //----------Load Instructions--------------------------------------------------
3983
3984 // Load Byte (8 bit signed)
3985 instruct loadB(rRegI dst, memory mem)
3986 %{
3987 match(Set dst (LoadB mem));
3988
3989 ins_cost(125);
3990 format %{ "movsbl $dst, $mem\t# byte" %}
3991
3992 ins_encode %{
3993 __ movsbl($dst$$Register, $mem$$Address);
3994 %}
3995
3996 ins_pipe(ialu_reg_mem);
3997 %}
3998
3999 // Load Byte (8 bit signed) into Long Register
4000 instruct loadB2L(rRegL dst, memory mem)
4001 %{
4002 match(Set dst (ConvI2L (LoadB mem)));
4003
4004 ins_cost(125);
4005 format %{ "movsbq $dst, $mem\t# byte -> long" %}
4006
4007 ins_encode %{
4008 __ movsbq($dst$$Register, $mem$$Address);
4009 %}
4010
4011 ins_pipe(ialu_reg_mem);
4012 %}
4013
4014 // Load Unsigned Byte (8 bit UNsigned)
4015 instruct loadUB(rRegI dst, memory mem)
4016 %{
4017 match(Set dst (LoadUB mem));
4018
4019 ins_cost(125);
4020 format %{ "movzbl $dst, $mem\t# ubyte" %}
4021
4022 ins_encode %{
4023 __ movzbl($dst$$Register, $mem$$Address);
4024 %}
4025
4026 ins_pipe(ialu_reg_mem);
4027 %}
4028
4029 // Load Unsigned Byte (8 bit UNsigned) into Long Register
4030 instruct loadUB2L(rRegL dst, memory mem)
4031 %{
4032 match(Set dst (ConvI2L (LoadUB mem)));
4033
4034 ins_cost(125);
4035 format %{ "movzbq $dst, $mem\t# ubyte -> long" %}
4036
4037 ins_encode %{
4038 __ movzbq($dst$$Register, $mem$$Address);
4039 %}
4040
4041 ins_pipe(ialu_reg_mem);
4042 %}
4043
4044 // Load Unsigned Byte (8 bit UNsigned) with 32-bit mask into Long Register
4045 instruct loadUB2L_immI(rRegL dst, memory mem, immI mask, rFlagsReg cr) %{
4046 match(Set dst (ConvI2L (AndI (LoadUB mem) mask)));
4047 effect(KILL cr);
4048
4049 format %{ "movzbq $dst, $mem\t# ubyte & 32-bit mask -> long\n\t"
4050 "andl $dst, right_n_bits($mask, 8)" %}
4051 ins_encode %{
4052 Register Rdst = $dst$$Register;
4053 __ movzbq(Rdst, $mem$$Address);
4054 __ andl(Rdst, $mask$$constant & right_n_bits(8));
4055 %}
4056 ins_pipe(ialu_reg_mem);
4057 %}
4058
4059 // Load Short (16 bit signed)
4060 instruct loadS(rRegI dst, memory mem)
4061 %{
4062 match(Set dst (LoadS mem));
4063
4064 ins_cost(125);
4065 format %{ "movswl $dst, $mem\t# short" %}
4066
4067 ins_encode %{
4068 __ movswl($dst$$Register, $mem$$Address);
4069 %}
4070
4071 ins_pipe(ialu_reg_mem);
4072 %}
4073
4074 // Load Short (16 bit signed) to Byte (8 bit signed)
4075 instruct loadS2B(rRegI dst, memory mem, immI_24 twentyfour) %{
4076 match(Set dst (RShiftI (LShiftI (LoadS mem) twentyfour) twentyfour));
4077
4078 ins_cost(125);
4079 format %{ "movsbl $dst, $mem\t# short -> byte" %}
4080 ins_encode %{
4081 __ movsbl($dst$$Register, $mem$$Address);
4082 %}
4083 ins_pipe(ialu_reg_mem);
4084 %}
4085
4086 // Load Short (16 bit signed) into Long Register
4087 instruct loadS2L(rRegL dst, memory mem)
4088 %{
4089 match(Set dst (ConvI2L (LoadS mem)));
4090
4091 ins_cost(125);
4092 format %{ "movswq $dst, $mem\t# short -> long" %}
4093
4094 ins_encode %{
4095 __ movswq($dst$$Register, $mem$$Address);
4096 %}
4097
4098 ins_pipe(ialu_reg_mem);
4099 %}
4100
4101 // Load Unsigned Short/Char (16 bit UNsigned)
4102 instruct loadUS(rRegI dst, memory mem)
4103 %{
4104 match(Set dst (LoadUS mem));
4105
4106 ins_cost(125);
4107 format %{ "movzwl $dst, $mem\t# ushort/char" %}
4108
4109 ins_encode %{
4110 __ movzwl($dst$$Register, $mem$$Address);
4111 %}
4112
4113 ins_pipe(ialu_reg_mem);
4114 %}
4115
4116 // Load Unsigned Short/Char (16 bit UNsigned) to Byte (8 bit signed)
4117 instruct loadUS2B(rRegI dst, memory mem, immI_24 twentyfour) %{
4118 match(Set dst (RShiftI (LShiftI (LoadUS mem) twentyfour) twentyfour));
4119
4120 ins_cost(125);
4121 format %{ "movsbl $dst, $mem\t# ushort -> byte" %}
4122 ins_encode %{
4123 __ movsbl($dst$$Register, $mem$$Address);
4124 %}
4125 ins_pipe(ialu_reg_mem);
4126 %}
4127
4128 // Load Unsigned Short/Char (16 bit UNsigned) into Long Register
4129 instruct loadUS2L(rRegL dst, memory mem)
4130 %{
4131 match(Set dst (ConvI2L (LoadUS mem)));
4132
4133 ins_cost(125);
4134 format %{ "movzwq $dst, $mem\t# ushort/char -> long" %}
4135
4136 ins_encode %{
4137 __ movzwq($dst$$Register, $mem$$Address);
4138 %}
4139
4140 ins_pipe(ialu_reg_mem);
4141 %}
4142
4143 // Load Unsigned Short/Char (16 bit UNsigned) with mask 0xFF into Long Register
4144 instruct loadUS2L_immI_255(rRegL dst, memory mem, immI_255 mask) %{
4145 match(Set dst (ConvI2L (AndI (LoadUS mem) mask)));
4146
4147 format %{ "movzbq $dst, $mem\t# ushort/char & 0xFF -> long" %}
4148 ins_encode %{
4149 __ movzbq($dst$$Register, $mem$$Address);
4150 %}
4151 ins_pipe(ialu_reg_mem);
4152 %}
4153
4154 // Load Unsigned Short/Char (16 bit UNsigned) with 32-bit mask into Long Register
4155 instruct loadUS2L_immI(rRegL dst, memory mem, immI mask, rFlagsReg cr) %{
4156 match(Set dst (ConvI2L (AndI (LoadUS mem) mask)));
4157 effect(KILL cr);
4158
4159 format %{ "movzwq $dst, $mem\t# ushort/char & 32-bit mask -> long\n\t"
4160 "andl $dst, right_n_bits($mask, 16)" %}
4161 ins_encode %{
4162 Register Rdst = $dst$$Register;
4163 __ movzwq(Rdst, $mem$$Address);
4164 __ andl(Rdst, $mask$$constant & right_n_bits(16));
4165 %}
4166 ins_pipe(ialu_reg_mem);
4167 %}
4168
4169 // Load Integer
4170 instruct loadI(rRegI dst, memory mem)
4171 %{
4172 match(Set dst (LoadI mem));
4173
4174 ins_cost(125);
4175 format %{ "movl $dst, $mem\t# int" %}
4176
4177 ins_encode %{
4178 __ movl($dst$$Register, $mem$$Address);
4179 %}
4180
4181 ins_pipe(ialu_reg_mem);
4182 %}
4183
4184 // Load Integer (32 bit signed) to Byte (8 bit signed)
4185 instruct loadI2B(rRegI dst, memory mem, immI_24 twentyfour) %{
4186 match(Set dst (RShiftI (LShiftI (LoadI mem) twentyfour) twentyfour));
4187
4188 ins_cost(125);
4189 format %{ "movsbl $dst, $mem\t# int -> byte" %}
4190 ins_encode %{
4191 __ movsbl($dst$$Register, $mem$$Address);
4192 %}
4193 ins_pipe(ialu_reg_mem);
4194 %}
4195
4196 // Load Integer (32 bit signed) to Unsigned Byte (8 bit UNsigned)
4197 instruct loadI2UB(rRegI dst, memory mem, immI_255 mask) %{
4198 match(Set dst (AndI (LoadI mem) mask));
4199
4200 ins_cost(125);
4201 format %{ "movzbl $dst, $mem\t# int -> ubyte" %}
4202 ins_encode %{
4203 __ movzbl($dst$$Register, $mem$$Address);
4204 %}
4205 ins_pipe(ialu_reg_mem);
4206 %}
4207
4208 // Load Integer (32 bit signed) to Short (16 bit signed)
4209 instruct loadI2S(rRegI dst, memory mem, immI_16 sixteen) %{
4210 match(Set dst (RShiftI (LShiftI (LoadI mem) sixteen) sixteen));
4211
4212 ins_cost(125);
4213 format %{ "movswl $dst, $mem\t# int -> short" %}
4214 ins_encode %{
4215 __ movswl($dst$$Register, $mem$$Address);
4216 %}
4217 ins_pipe(ialu_reg_mem);
4218 %}
4219
4220 // Load Integer (32 bit signed) to Unsigned Short/Char (16 bit UNsigned)
4221 instruct loadI2US(rRegI dst, memory mem, immI_65535 mask) %{
4222 match(Set dst (AndI (LoadI mem) mask));
4223
4224 ins_cost(125);
4225 format %{ "movzwl $dst, $mem\t# int -> ushort/char" %}
4226 ins_encode %{
4227 __ movzwl($dst$$Register, $mem$$Address);
4228 %}
4229 ins_pipe(ialu_reg_mem);
4230 %}
4231
4232 // Load Integer into Long Register
4233 instruct loadI2L(rRegL dst, memory mem)
4234 %{
4235 match(Set dst (ConvI2L (LoadI mem)));
4236
4237 ins_cost(125);
4238 format %{ "movslq $dst, $mem\t# int -> long" %}
4239
4240 ins_encode %{
4241 __ movslq($dst$$Register, $mem$$Address);
4242 %}
4243
4244 ins_pipe(ialu_reg_mem);
4245 %}
4246
4247 // Load Integer with mask 0xFF into Long Register
4248 instruct loadI2L_immI_255(rRegL dst, memory mem, immI_255 mask) %{
4249 match(Set dst (ConvI2L (AndI (LoadI mem) mask)));
4250
4251 format %{ "movzbq $dst, $mem\t# int & 0xFF -> long" %}
4252 ins_encode %{
4253 __ movzbq($dst$$Register, $mem$$Address);
4254 %}
4255 ins_pipe(ialu_reg_mem);
4256 %}
4257
4258 // Load Integer with mask 0xFFFF into Long Register
4259 instruct loadI2L_immI_65535(rRegL dst, memory mem, immI_65535 mask) %{
4260 match(Set dst (ConvI2L (AndI (LoadI mem) mask)));
4261
4262 format %{ "movzwq $dst, $mem\t# int & 0xFFFF -> long" %}
4263 ins_encode %{
4264 __ movzwq($dst$$Register, $mem$$Address);
4265 %}
4266 ins_pipe(ialu_reg_mem);
4267 %}
4268
4269 // Load Integer with a 31-bit mask into Long Register
4270 instruct loadI2L_immU31(rRegL dst, memory mem, immU31 mask, rFlagsReg cr) %{
4271 match(Set dst (ConvI2L (AndI (LoadI mem) mask)));
4272 effect(KILL cr);
4273
4274 format %{ "movl $dst, $mem\t# int & 31-bit mask -> long\n\t"
4275 "andl $dst, $mask" %}
4276 ins_encode %{
4277 Register Rdst = $dst$$Register;
4278 __ movl(Rdst, $mem$$Address);
4279 __ andl(Rdst, $mask$$constant);
4280 %}
4281 ins_pipe(ialu_reg_mem);
4282 %}
4283
4284 // Load Unsigned Integer into Long Register
4285 instruct loadUI2L(rRegL dst, memory mem, immL_32bits mask)
4286 %{
4287 match(Set dst (AndL (ConvI2L (LoadI mem)) mask));
4288
4289 ins_cost(125);
4290 format %{ "movl $dst, $mem\t# uint -> long" %}
4291
4292 ins_encode %{
4293 __ movl($dst$$Register, $mem$$Address);
4294 %}
4295
4296 ins_pipe(ialu_reg_mem);
4297 %}
4298
4299 // Load Long
4300 instruct loadL(rRegL dst, memory mem)
4301 %{
4302 match(Set dst (LoadL mem));
4303
4304 ins_cost(125);
4305 format %{ "movq $dst, $mem\t# long" %}
4306
4307 ins_encode %{
4308 __ movq($dst$$Register, $mem$$Address);
4309 %}
4310
4311 ins_pipe(ialu_reg_mem); // XXX
4312 %}
4313
4314 // Load Range
4315 instruct loadRange(rRegI dst, memory mem)
4316 %{
4317 match(Set dst (LoadRange mem));
4318
4319 ins_cost(125); // XXX
4320 format %{ "movl $dst, $mem\t# range" %}
4321 ins_encode %{
4322 __ movl($dst$$Register, $mem$$Address);
4323 %}
4324 ins_pipe(ialu_reg_mem);
4325 %}
4326
4327 // Load Pointer
4328 instruct loadP(rRegP dst, memory mem)
4329 %{
4330 match(Set dst (LoadP mem));
4331 predicate(n->as_Load()->barrier_data() == 0);
4332
4333 ins_cost(125); // XXX
4334 format %{ "movq $dst, $mem\t# ptr" %}
4335 ins_encode %{
4336 __ movq($dst$$Register, $mem$$Address);
4337 %}
4338 ins_pipe(ialu_reg_mem); // XXX
4339 %}
4340
4341 // Load Compressed Pointer
4342 instruct loadN(rRegN dst, memory mem)
4343 %{
4344 predicate(n->as_Load()->barrier_data() == 0);
4345 match(Set dst (LoadN mem));
4346
4347 ins_cost(125); // XXX
4348 format %{ "movl $dst, $mem\t# compressed ptr" %}
4349 ins_encode %{
4350 __ movl($dst$$Register, $mem$$Address);
4351 %}
4352 ins_pipe(ialu_reg_mem); // XXX
4353 %}
4354
4355
4356 // Load Klass Pointer
4357 instruct loadKlass(rRegP dst, memory mem)
4358 %{
4359 match(Set dst (LoadKlass mem));
4360
4361 ins_cost(125); // XXX
4362 format %{ "movq $dst, $mem\t# class" %}
4363 ins_encode %{
4364 __ movq($dst$$Register, $mem$$Address);
4365 %}
4366 ins_pipe(ialu_reg_mem); // XXX
4367 %}
4368
4369 // Load narrow Klass Pointer
4370 instruct loadNKlass(rRegN dst, memory mem)
4371 %{
4372 predicate(!UseCompactObjectHeaders);
4373 match(Set dst (LoadNKlass mem));
4374
4375 ins_cost(125); // XXX
4376 format %{ "movl $dst, $mem\t# compressed klass ptr" %}
4377 ins_encode %{
4378 __ movl($dst$$Register, $mem$$Address);
4379 %}
4380 ins_pipe(ialu_reg_mem); // XXX
4381 %}
4382
4383 instruct loadNKlassCompactHeaders(rRegN dst, memory mem, rFlagsReg cr)
4384 %{
4385 predicate(UseCompactObjectHeaders);
4386 match(Set dst (LoadNKlass mem));
4387 effect(KILL cr);
4388 ins_cost(125);
4389 format %{
4390 "movl $dst, $mem\t# compressed klass ptr, shifted\n\t"
4391 "shrl $dst, markWord::klass_shift_at_offset"
4392 %}
4393 ins_encode %{
4394 if (UseAPX) {
4395 __ eshrl($dst$$Register, $mem$$Address, markWord::klass_shift_at_offset, false);
4396 }
4397 else {
4398 __ movl($dst$$Register, $mem$$Address);
4399 __ shrl($dst$$Register, markWord::klass_shift_at_offset);
4400 }
4401 %}
4402 ins_pipe(ialu_reg_mem);
4403 %}
4404
4405 // Load Float
4406 instruct loadF(regF dst, memory mem)
4407 %{
4408 match(Set dst (LoadF mem));
4409
4410 ins_cost(145); // XXX
4411 format %{ "movss $dst, $mem\t# float" %}
4412 ins_encode %{
4413 __ movflt($dst$$XMMRegister, $mem$$Address);
4414 %}
4415 ins_pipe(pipe_slow); // XXX
4416 %}
4417
4418 // Load Double
4419 instruct loadD_partial(regD dst, memory mem)
4420 %{
4421 predicate(!UseXmmLoadAndClearUpper);
4422 match(Set dst (LoadD mem));
4423
4424 ins_cost(145); // XXX
4425 format %{ "movlpd $dst, $mem\t# double" %}
4426 ins_encode %{
4427 __ movdbl($dst$$XMMRegister, $mem$$Address);
4428 %}
4429 ins_pipe(pipe_slow); // XXX
4430 %}
4431
4432 instruct loadD(regD dst, memory mem)
4433 %{
4434 predicate(UseXmmLoadAndClearUpper);
4435 match(Set dst (LoadD mem));
4436
4437 ins_cost(145); // XXX
4438 format %{ "movsd $dst, $mem\t# double" %}
4439 ins_encode %{
4440 __ movdbl($dst$$XMMRegister, $mem$$Address);
4441 %}
4442 ins_pipe(pipe_slow); // XXX
4443 %}
4444
4445 // max = java.lang.Math.max(float a, float b)
4446 instruct maxF_avx10_reg(regF dst, regF a, regF b) %{
4447 predicate(VM_Version::supports_avx10_2());
4448 match(Set dst (MaxF a b));
4449 format %{ "maxF $dst, $a, $b" %}
4450 ins_encode %{
4451 __ eminmaxss($dst$$XMMRegister, $a$$XMMRegister, $b$$XMMRegister, AVX10_MINMAX_MAX_COMPARE_SIGN);
4452 %}
4453 ins_pipe( pipe_slow );
4454 %}
4455
4456 // max = java.lang.Math.max(float a, float b)
4457 instruct maxF_reg(legRegF dst, legRegF a, legRegF b, legRegF tmp, legRegF atmp, legRegF btmp) %{
4458 predicate(!VM_Version::supports_avx10_2() && UseAVX > 0 && !VLoopReductions::is_reduction(n));
4459 match(Set dst (MaxF a b));
4460 effect(USE a, USE b, TEMP tmp, TEMP atmp, TEMP btmp);
4461 format %{ "maxF $dst, $a, $b \t! using $tmp, $atmp and $btmp as TEMP" %}
4462 ins_encode %{
4463 __ vminmax_fp(Op_MaxV, T_FLOAT, $dst$$XMMRegister, $a$$XMMRegister, $b$$XMMRegister, $tmp$$XMMRegister, $atmp$$XMMRegister, $btmp$$XMMRegister, Assembler::AVX_128bit);
4464 %}
4465 ins_pipe( pipe_slow );
4466 %}
4467
4468 instruct maxF_reduction_reg(legRegF dst, legRegF a, legRegF b, legRegF xtmp, rRegI rtmp, rFlagsReg cr) %{
4469 predicate(!VM_Version::supports_avx10_2() && UseAVX > 0 && VLoopReductions::is_reduction(n));
4470 match(Set dst (MaxF a b));
4471 effect(USE a, USE b, TEMP xtmp, TEMP rtmp, KILL cr);
4472
4473 format %{ "maxF_reduction $dst, $a, $b \t!using $xtmp and $rtmp as TEMP" %}
4474 ins_encode %{
4475 emit_fp_min_max(masm, $dst$$XMMRegister, $a$$XMMRegister, $b$$XMMRegister, $xtmp$$XMMRegister, $rtmp$$Register,
4476 false /*min*/, true /*single*/);
4477 %}
4478 ins_pipe( pipe_slow );
4479 %}
4480
4481 // max = java.lang.Math.max(double a, double b)
4482 instruct maxD_avx10_reg(regD dst, regD a, regD b) %{
4483 predicate(VM_Version::supports_avx10_2());
4484 match(Set dst (MaxD a b));
4485 format %{ "maxD $dst, $a, $b" %}
4486 ins_encode %{
4487 __ eminmaxsd($dst$$XMMRegister, $a$$XMMRegister, $b$$XMMRegister, AVX10_MINMAX_MAX_COMPARE_SIGN);
4488 %}
4489 ins_pipe( pipe_slow );
4490 %}
4491
4492 // max = java.lang.Math.max(double a, double b)
4493 instruct maxD_reg(legRegD dst, legRegD a, legRegD b, legRegD tmp, legRegD atmp, legRegD btmp) %{
4494 predicate(!VM_Version::supports_avx10_2() && UseAVX > 0 && !VLoopReductions::is_reduction(n));
4495 match(Set dst (MaxD a b));
4496 effect(USE a, USE b, TEMP atmp, TEMP btmp, TEMP tmp);
4497 format %{ "maxD $dst, $a, $b \t! using $tmp, $atmp and $btmp as TEMP" %}
4498 ins_encode %{
4499 __ vminmax_fp(Op_MaxV, T_DOUBLE, $dst$$XMMRegister, $a$$XMMRegister, $b$$XMMRegister, $tmp$$XMMRegister, $atmp$$XMMRegister, $btmp$$XMMRegister, Assembler::AVX_128bit);
4500 %}
4501 ins_pipe( pipe_slow );
4502 %}
4503
4504 instruct maxD_reduction_reg(legRegD dst, legRegD a, legRegD b, legRegD xtmp, rRegL rtmp, rFlagsReg cr) %{
4505 predicate(!VM_Version::supports_avx10_2() && UseAVX > 0 && VLoopReductions::is_reduction(n));
4506 match(Set dst (MaxD a b));
4507 effect(USE a, USE b, TEMP xtmp, TEMP rtmp, KILL cr);
4508
4509 format %{ "maxD_reduction $dst, $a, $b \t! using $xtmp and $rtmp as TEMP" %}
4510 ins_encode %{
4511 emit_fp_min_max(masm, $dst$$XMMRegister, $a$$XMMRegister, $b$$XMMRegister, $xtmp$$XMMRegister, $rtmp$$Register,
4512 false /*min*/, false /*single*/);
4513 %}
4514 ins_pipe( pipe_slow );
4515 %}
4516
4517 // max = java.lang.Math.min(float a, float b)
4518 instruct minF_avx10_reg(regF dst, regF a, regF b) %{
4519 predicate(VM_Version::supports_avx10_2());
4520 match(Set dst (MinF a b));
4521 format %{ "minF $dst, $a, $b" %}
4522 ins_encode %{
4523 __ eminmaxss($dst$$XMMRegister, $a$$XMMRegister, $b$$XMMRegister, AVX10_MINMAX_MIN_COMPARE_SIGN);
4524 %}
4525 ins_pipe( pipe_slow );
4526 %}
4527
4528 // min = java.lang.Math.min(float a, float b)
4529 instruct minF_reg(legRegF dst, legRegF a, legRegF b, legRegF tmp, legRegF atmp, legRegF btmp) %{
4530 predicate(!VM_Version::supports_avx10_2() && UseAVX > 0 && !VLoopReductions::is_reduction(n));
4531 match(Set dst (MinF a b));
4532 effect(USE a, USE b, TEMP tmp, TEMP atmp, TEMP btmp);
4533 format %{ "minF $dst, $a, $b \t! using $tmp, $atmp and $btmp as TEMP" %}
4534 ins_encode %{
4535 __ vminmax_fp(Op_MinV, T_FLOAT, $dst$$XMMRegister, $a$$XMMRegister, $b$$XMMRegister, $tmp$$XMMRegister, $atmp$$XMMRegister, $btmp$$XMMRegister, Assembler::AVX_128bit);
4536 %}
4537 ins_pipe( pipe_slow );
4538 %}
4539
4540 instruct minF_reduction_reg(legRegF dst, legRegF a, legRegF b, legRegF xtmp, rRegI rtmp, rFlagsReg cr) %{
4541 predicate(!VM_Version::supports_avx10_2() && UseAVX > 0 && VLoopReductions::is_reduction(n));
4542 match(Set dst (MinF a b));
4543 effect(USE a, USE b, TEMP xtmp, TEMP rtmp, KILL cr);
4544
4545 format %{ "minF_reduction $dst, $a, $b \t! using $xtmp and $rtmp as TEMP" %}
4546 ins_encode %{
4547 emit_fp_min_max(masm, $dst$$XMMRegister, $a$$XMMRegister, $b$$XMMRegister, $xtmp$$XMMRegister, $rtmp$$Register,
4548 true /*min*/, true /*single*/);
4549 %}
4550 ins_pipe( pipe_slow );
4551 %}
4552
4553 // max = java.lang.Math.min(double a, double b)
4554 instruct minD_avx10_reg(regD dst, regD a, regD b) %{
4555 predicate(VM_Version::supports_avx10_2());
4556 match(Set dst (MinD a b));
4557 format %{ "minD $dst, $a, $b" %}
4558 ins_encode %{
4559 __ eminmaxsd($dst$$XMMRegister, $a$$XMMRegister, $b$$XMMRegister, AVX10_MINMAX_MIN_COMPARE_SIGN);
4560 %}
4561 ins_pipe( pipe_slow );
4562 %}
4563
4564 // min = java.lang.Math.min(double a, double b)
4565 instruct minD_reg(legRegD dst, legRegD a, legRegD b, legRegD tmp, legRegD atmp, legRegD btmp) %{
4566 predicate(!VM_Version::supports_avx10_2() && UseAVX > 0 && !VLoopReductions::is_reduction(n));
4567 match(Set dst (MinD a b));
4568 effect(USE a, USE b, TEMP tmp, TEMP atmp, TEMP btmp);
4569 format %{ "minD $dst, $a, $b \t! using $tmp, $atmp and $btmp as TEMP" %}
4570 ins_encode %{
4571 __ vminmax_fp(Op_MinV, T_DOUBLE, $dst$$XMMRegister, $a$$XMMRegister, $b$$XMMRegister, $tmp$$XMMRegister, $atmp$$XMMRegister, $btmp$$XMMRegister, Assembler::AVX_128bit);
4572 %}
4573 ins_pipe( pipe_slow );
4574 %}
4575
4576 instruct minD_reduction_reg(legRegD dst, legRegD a, legRegD b, legRegD xtmp, rRegL rtmp, rFlagsReg cr) %{
4577 predicate(!VM_Version::supports_avx10_2() && UseAVX > 0 && VLoopReductions::is_reduction(n));
4578 match(Set dst (MinD a b));
4579 effect(USE a, USE b, TEMP xtmp, TEMP rtmp, KILL cr);
4580
4581 format %{ "maxD_reduction $dst, $a, $b \t! using $xtmp and $rtmp as TEMP" %}
4582 ins_encode %{
4583 emit_fp_min_max(masm, $dst$$XMMRegister, $a$$XMMRegister, $b$$XMMRegister, $xtmp$$XMMRegister, $rtmp$$Register,
4584 true /*min*/, false /*single*/);
4585 %}
4586 ins_pipe( pipe_slow );
4587 %}
4588
4589 // Load Effective Address
4590 instruct leaP8(rRegP dst, indOffset8 mem)
4591 %{
4592 match(Set dst mem);
4593
4594 ins_cost(110); // XXX
4595 format %{ "leaq $dst, $mem\t# ptr 8" %}
4596 ins_encode %{
4597 __ leaq($dst$$Register, $mem$$Address);
4598 %}
4599 ins_pipe(ialu_reg_reg_fat);
4600 %}
4601
4602 instruct leaP32(rRegP dst, indOffset32 mem)
4603 %{
4604 match(Set dst mem);
4605
4606 ins_cost(110);
4607 format %{ "leaq $dst, $mem\t# ptr 32" %}
4608 ins_encode %{
4609 __ leaq($dst$$Register, $mem$$Address);
4610 %}
4611 ins_pipe(ialu_reg_reg_fat);
4612 %}
4613
4614 instruct leaPIdxOff(rRegP dst, indIndexOffset mem)
4615 %{
4616 match(Set dst mem);
4617
4618 ins_cost(110);
4619 format %{ "leaq $dst, $mem\t# ptr idxoff" %}
4620 ins_encode %{
4621 __ leaq($dst$$Register, $mem$$Address);
4622 %}
4623 ins_pipe(ialu_reg_reg_fat);
4624 %}
4625
4626 instruct leaPIdxScale(rRegP dst, indIndexScale mem)
4627 %{
4628 match(Set dst mem);
4629
4630 ins_cost(110);
4631 format %{ "leaq $dst, $mem\t# ptr idxscale" %}
4632 ins_encode %{
4633 __ leaq($dst$$Register, $mem$$Address);
4634 %}
4635 ins_pipe(ialu_reg_reg_fat);
4636 %}
4637
4638 instruct leaPPosIdxScale(rRegP dst, indPosIndexScale mem)
4639 %{
4640 match(Set dst mem);
4641
4642 ins_cost(110);
4643 format %{ "leaq $dst, $mem\t# ptr idxscale" %}
4644 ins_encode %{
4645 __ leaq($dst$$Register, $mem$$Address);
4646 %}
4647 ins_pipe(ialu_reg_reg_fat);
4648 %}
4649
4650 instruct leaPIdxScaleOff(rRegP dst, indIndexScaleOffset mem)
4651 %{
4652 match(Set dst mem);
4653
4654 ins_cost(110);
4655 format %{ "leaq $dst, $mem\t# ptr idxscaleoff" %}
4656 ins_encode %{
4657 __ leaq($dst$$Register, $mem$$Address);
4658 %}
4659 ins_pipe(ialu_reg_reg_fat);
4660 %}
4661
4662 instruct leaPPosIdxOff(rRegP dst, indPosIndexOffset mem)
4663 %{
4664 match(Set dst mem);
4665
4666 ins_cost(110);
4667 format %{ "leaq $dst, $mem\t# ptr posidxoff" %}
4668 ins_encode %{
4669 __ leaq($dst$$Register, $mem$$Address);
4670 %}
4671 ins_pipe(ialu_reg_reg_fat);
4672 %}
4673
4674 instruct leaPPosIdxScaleOff(rRegP dst, indPosIndexScaleOffset mem)
4675 %{
4676 match(Set dst mem);
4677
4678 ins_cost(110);
4679 format %{ "leaq $dst, $mem\t# ptr posidxscaleoff" %}
4680 ins_encode %{
4681 __ leaq($dst$$Register, $mem$$Address);
4682 %}
4683 ins_pipe(ialu_reg_reg_fat);
4684 %}
4685
4686 // Load Effective Address which uses Narrow (32-bits) oop
4687 instruct leaPCompressedOopOffset(rRegP dst, indCompressedOopOffset mem)
4688 %{
4689 predicate(UseCompressedOops && (CompressedOops::shift() != 0));
4690 match(Set dst mem);
4691
4692 ins_cost(110);
4693 format %{ "leaq $dst, $mem\t# ptr compressedoopoff32" %}
4694 ins_encode %{
4695 __ leaq($dst$$Register, $mem$$Address);
4696 %}
4697 ins_pipe(ialu_reg_reg_fat);
4698 %}
4699
4700 instruct leaP8Narrow(rRegP dst, indOffset8Narrow mem)
4701 %{
4702 predicate(CompressedOops::shift() == 0);
4703 match(Set dst mem);
4704
4705 ins_cost(110); // XXX
4706 format %{ "leaq $dst, $mem\t# ptr off8narrow" %}
4707 ins_encode %{
4708 __ leaq($dst$$Register, $mem$$Address);
4709 %}
4710 ins_pipe(ialu_reg_reg_fat);
4711 %}
4712
4713 instruct leaP32Narrow(rRegP dst, indOffset32Narrow mem)
4714 %{
4715 predicate(CompressedOops::shift() == 0);
4716 match(Set dst mem);
4717
4718 ins_cost(110);
4719 format %{ "leaq $dst, $mem\t# ptr off32narrow" %}
4720 ins_encode %{
4721 __ leaq($dst$$Register, $mem$$Address);
4722 %}
4723 ins_pipe(ialu_reg_reg_fat);
4724 %}
4725
4726 instruct leaPIdxOffNarrow(rRegP dst, indIndexOffsetNarrow mem)
4727 %{
4728 predicate(CompressedOops::shift() == 0);
4729 match(Set dst mem);
4730
4731 ins_cost(110);
4732 format %{ "leaq $dst, $mem\t# ptr idxoffnarrow" %}
4733 ins_encode %{
4734 __ leaq($dst$$Register, $mem$$Address);
4735 %}
4736 ins_pipe(ialu_reg_reg_fat);
4737 %}
4738
4739 instruct leaPIdxScaleNarrow(rRegP dst, indIndexScaleNarrow mem)
4740 %{
4741 predicate(CompressedOops::shift() == 0);
4742 match(Set dst mem);
4743
4744 ins_cost(110);
4745 format %{ "leaq $dst, $mem\t# ptr idxscalenarrow" %}
4746 ins_encode %{
4747 __ leaq($dst$$Register, $mem$$Address);
4748 %}
4749 ins_pipe(ialu_reg_reg_fat);
4750 %}
4751
4752 instruct leaPIdxScaleOffNarrow(rRegP dst, indIndexScaleOffsetNarrow mem)
4753 %{
4754 predicate(CompressedOops::shift() == 0);
4755 match(Set dst mem);
4756
4757 ins_cost(110);
4758 format %{ "leaq $dst, $mem\t# ptr idxscaleoffnarrow" %}
4759 ins_encode %{
4760 __ leaq($dst$$Register, $mem$$Address);
4761 %}
4762 ins_pipe(ialu_reg_reg_fat);
4763 %}
4764
4765 instruct leaPPosIdxOffNarrow(rRegP dst, indPosIndexOffsetNarrow mem)
4766 %{
4767 predicate(CompressedOops::shift() == 0);
4768 match(Set dst mem);
4769
4770 ins_cost(110);
4771 format %{ "leaq $dst, $mem\t# ptr posidxoffnarrow" %}
4772 ins_encode %{
4773 __ leaq($dst$$Register, $mem$$Address);
4774 %}
4775 ins_pipe(ialu_reg_reg_fat);
4776 %}
4777
4778 instruct leaPPosIdxScaleOffNarrow(rRegP dst, indPosIndexScaleOffsetNarrow mem)
4779 %{
4780 predicate(CompressedOops::shift() == 0);
4781 match(Set dst mem);
4782
4783 ins_cost(110);
4784 format %{ "leaq $dst, $mem\t# ptr posidxscaleoffnarrow" %}
4785 ins_encode %{
4786 __ leaq($dst$$Register, $mem$$Address);
4787 %}
4788 ins_pipe(ialu_reg_reg_fat);
4789 %}
4790
4791 instruct loadConI(rRegI dst, immI src)
4792 %{
4793 match(Set dst src);
4794
4795 format %{ "movl $dst, $src\t# int" %}
4796 ins_encode %{
4797 __ movl($dst$$Register, $src$$constant);
4798 %}
4799 ins_pipe(ialu_reg_fat); // XXX
4800 %}
4801
4802 instruct loadConI0(rRegI dst, immI_0 src, rFlagsReg cr)
4803 %{
4804 match(Set dst src);
4805 effect(KILL cr);
4806
4807 ins_cost(50);
4808 format %{ "xorl $dst, $dst\t# int" %}
4809 ins_encode %{
4810 __ xorl($dst$$Register, $dst$$Register);
4811 %}
4812 ins_pipe(ialu_reg);
4813 %}
4814
4815 instruct loadConL(rRegL dst, immL src)
4816 %{
4817 match(Set dst src);
4818
4819 ins_cost(150);
4820 format %{ "movq $dst, $src\t# long" %}
4821 ins_encode %{
4822 __ mov64($dst$$Register, $src$$constant);
4823 %}
4824 ins_pipe(ialu_reg);
4825 %}
4826
4827 instruct loadConL0(rRegL dst, immL0 src, rFlagsReg cr)
4828 %{
4829 match(Set dst src);
4830 effect(KILL cr);
4831
4832 ins_cost(50);
4833 format %{ "xorl $dst, $dst\t# long" %}
4834 ins_encode %{
4835 __ xorl($dst$$Register, $dst$$Register);
4836 %}
4837 ins_pipe(ialu_reg); // XXX
4838 %}
4839
4840 instruct loadConUL32(rRegL dst, immUL32 src)
4841 %{
4842 match(Set dst src);
4843
4844 ins_cost(60);
4845 format %{ "movl $dst, $src\t# long (unsigned 32-bit)" %}
4846 ins_encode %{
4847 __ movl($dst$$Register, $src$$constant);
4848 %}
4849 ins_pipe(ialu_reg);
4850 %}
4851
4852 instruct loadConL32(rRegL dst, immL32 src)
4853 %{
4854 match(Set dst src);
4855
4856 ins_cost(70);
4857 format %{ "movq $dst, $src\t# long (32-bit)" %}
4858 ins_encode %{
4859 __ movq($dst$$Register, $src$$constant);
4860 %}
4861 ins_pipe(ialu_reg);
4862 %}
4863
4864 instruct loadConP(rRegP dst, immP con) %{
4865 match(Set dst con);
4866
4867 format %{ "movq $dst, $con\t# ptr" %}
4868 ins_encode %{
4869 __ mov64($dst$$Register, $con$$constant, $con->constant_reloc(), RELOC_IMM64);
4870 %}
4871 ins_pipe(ialu_reg_fat); // XXX
4872 %}
4873
4874 instruct loadConP0(rRegP dst, immP0 src, rFlagsReg cr)
4875 %{
4876 match(Set dst src);
4877 effect(KILL cr);
4878
4879 ins_cost(50);
4880 format %{ "xorl $dst, $dst\t# ptr" %}
4881 ins_encode %{
4882 __ xorl($dst$$Register, $dst$$Register);
4883 %}
4884 ins_pipe(ialu_reg);
4885 %}
4886
4887 instruct loadConP31(rRegP dst, immP31 src, rFlagsReg cr)
4888 %{
4889 match(Set dst src);
4890 effect(KILL cr);
4891
4892 ins_cost(60);
4893 format %{ "movl $dst, $src\t# ptr (positive 32-bit)" %}
4894 ins_encode %{
4895 __ movl($dst$$Register, $src$$constant);
4896 %}
4897 ins_pipe(ialu_reg);
4898 %}
4899
4900 instruct loadConF(regF dst, immF con) %{
4901 match(Set dst con);
4902 ins_cost(125);
4903 format %{ "movss $dst, [$constantaddress]\t# load from constant table: float=$con" %}
4904 ins_encode %{
4905 __ movflt($dst$$XMMRegister, $constantaddress($con));
4906 %}
4907 ins_pipe(pipe_slow);
4908 %}
4909
4910 instruct loadConH(regF dst, immH con) %{
4911 match(Set dst con);
4912 ins_cost(125);
4913 format %{ "movss $dst, [$constantaddress]\t# load from constant table: halffloat=$con" %}
4914 ins_encode %{
4915 __ movflt($dst$$XMMRegister, $constantaddress($con));
4916 %}
4917 ins_pipe(pipe_slow);
4918 %}
4919
4920 instruct loadConN0(rRegN dst, immN0 src, rFlagsReg cr) %{
4921 match(Set dst src);
4922 effect(KILL cr);
4923 format %{ "xorq $dst, $src\t# compressed null pointer" %}
4924 ins_encode %{
4925 __ xorq($dst$$Register, $dst$$Register);
4926 %}
4927 ins_pipe(ialu_reg);
4928 %}
4929
4930 instruct loadConN(rRegN dst, immN src) %{
4931 match(Set dst src);
4932
4933 ins_cost(125);
4934 format %{ "movl $dst, $src\t# compressed ptr" %}
4935 ins_encode %{
4936 address con = (address)$src$$constant;
4937 if (con == nullptr) {
4938 ShouldNotReachHere();
4939 } else {
4940 __ set_narrow_oop($dst$$Register, (jobject)$src$$constant);
4941 }
4942 %}
4943 ins_pipe(ialu_reg_fat); // XXX
4944 %}
4945
4946 instruct loadConNKlass(rRegN dst, immNKlass src) %{
4947 match(Set dst src);
4948
4949 ins_cost(125);
4950 format %{ "movl $dst, $src\t# compressed klass ptr" %}
4951 ins_encode %{
4952 address con = (address)$src$$constant;
4953 if (con == nullptr) {
4954 ShouldNotReachHere();
4955 } else {
4956 __ set_narrow_klass($dst$$Register, (Klass*)$src$$constant);
4957 }
4958 %}
4959 ins_pipe(ialu_reg_fat); // XXX
4960 %}
4961
4962 instruct loadConF0(regF dst, immF0 src)
4963 %{
4964 match(Set dst src);
4965 ins_cost(100);
4966
4967 format %{ "xorps $dst, $dst\t# float 0.0" %}
4968 ins_encode %{
4969 __ xorps($dst$$XMMRegister, $dst$$XMMRegister);
4970 %}
4971 ins_pipe(pipe_slow);
4972 %}
4973
4974 // Use the same format since predicate() can not be used here.
4975 instruct loadConD(regD dst, immD con) %{
4976 match(Set dst con);
4977 ins_cost(125);
4978 format %{ "movsd $dst, [$constantaddress]\t# load from constant table: double=$con" %}
4979 ins_encode %{
4980 __ movdbl($dst$$XMMRegister, $constantaddress($con));
4981 %}
4982 ins_pipe(pipe_slow);
4983 %}
4984
4985 instruct loadConD0(regD dst, immD0 src)
4986 %{
4987 match(Set dst src);
4988 ins_cost(100);
4989
4990 format %{ "xorpd $dst, $dst\t# double 0.0" %}
4991 ins_encode %{
4992 __ xorpd($dst$$XMMRegister, $dst$$XMMRegister);
4993 %}
4994 ins_pipe(pipe_slow);
4995 %}
4996
4997 instruct loadSSI(rRegI dst, stackSlotI src)
4998 %{
4999 match(Set dst src);
5000
5001 ins_cost(125);
5002 format %{ "movl $dst, $src\t# int stk" %}
5003 ins_encode %{
5004 __ movl($dst$$Register, $src$$Address);
5005 %}
5006 ins_pipe(ialu_reg_mem);
5007 %}
5008
5009 instruct loadSSL(rRegL dst, stackSlotL src)
5010 %{
5011 match(Set dst src);
5012
5013 ins_cost(125);
5014 format %{ "movq $dst, $src\t# long stk" %}
5015 ins_encode %{
5016 __ movq($dst$$Register, $src$$Address);
5017 %}
5018 ins_pipe(ialu_reg_mem);
5019 %}
5020
5021 instruct loadSSP(rRegP dst, stackSlotP src)
5022 %{
5023 match(Set dst src);
5024
5025 ins_cost(125);
5026 format %{ "movq $dst, $src\t# ptr stk" %}
5027 ins_encode %{
5028 __ movq($dst$$Register, $src$$Address);
5029 %}
5030 ins_pipe(ialu_reg_mem);
5031 %}
5032
5033 instruct loadSSF(regF dst, stackSlotF src)
5034 %{
5035 match(Set dst src);
5036
5037 ins_cost(125);
5038 format %{ "movss $dst, $src\t# float stk" %}
5039 ins_encode %{
5040 __ movflt($dst$$XMMRegister, Address(rsp, $src$$disp));
5041 %}
5042 ins_pipe(pipe_slow); // XXX
5043 %}
5044
5045 // Use the same format since predicate() can not be used here.
5046 instruct loadSSD(regD dst, stackSlotD src)
5047 %{
5048 match(Set dst src);
5049
5050 ins_cost(125);
5051 format %{ "movsd $dst, $src\t# double stk" %}
5052 ins_encode %{
5053 __ movdbl($dst$$XMMRegister, Address(rsp, $src$$disp));
5054 %}
5055 ins_pipe(pipe_slow); // XXX
5056 %}
5057
5058 // Prefetch instructions for allocation.
5059 // Must be safe to execute with invalid address (cannot fault).
5060
5061 instruct prefetchAlloc( memory mem ) %{
5062 predicate(AllocatePrefetchInstr==3);
5063 match(PrefetchAllocation mem);
5064 ins_cost(125);
5065
5066 format %{ "PREFETCHW $mem\t# Prefetch allocation into level 1 cache and mark modified" %}
5067 ins_encode %{
5068 __ prefetchw($mem$$Address);
5069 %}
5070 ins_pipe(ialu_mem);
5071 %}
5072
5073 instruct prefetchAllocNTA( memory mem ) %{
5074 predicate(AllocatePrefetchInstr==0);
5075 match(PrefetchAllocation mem);
5076 ins_cost(125);
5077
5078 format %{ "PREFETCHNTA $mem\t# Prefetch allocation to non-temporal cache for write" %}
5079 ins_encode %{
5080 __ prefetchnta($mem$$Address);
5081 %}
5082 ins_pipe(ialu_mem);
5083 %}
5084
5085 instruct prefetchAllocT0( memory mem ) %{
5086 predicate(AllocatePrefetchInstr==1);
5087 match(PrefetchAllocation mem);
5088 ins_cost(125);
5089
5090 format %{ "PREFETCHT0 $mem\t# Prefetch allocation to level 1 and 2 caches for write" %}
5091 ins_encode %{
5092 __ prefetcht0($mem$$Address);
5093 %}
5094 ins_pipe(ialu_mem);
5095 %}
5096
5097 instruct prefetchAllocT2( memory mem ) %{
5098 predicate(AllocatePrefetchInstr==2);
5099 match(PrefetchAllocation mem);
5100 ins_cost(125);
5101
5102 format %{ "PREFETCHT2 $mem\t# Prefetch allocation to level 2 cache for write" %}
5103 ins_encode %{
5104 __ prefetcht2($mem$$Address);
5105 %}
5106 ins_pipe(ialu_mem);
5107 %}
5108
5109 //----------Store Instructions-------------------------------------------------
5110
5111 // Store Byte
5112 instruct storeB(memory mem, rRegI src)
5113 %{
5114 match(Set mem (StoreB mem src));
5115
5116 ins_cost(125); // XXX
5117 format %{ "movb $mem, $src\t# byte" %}
5118 ins_encode %{
5119 __ movb($mem$$Address, $src$$Register);
5120 %}
5121 ins_pipe(ialu_mem_reg);
5122 %}
5123
5124 // Store Char/Short
5125 instruct storeC(memory mem, rRegI src)
5126 %{
5127 match(Set mem (StoreC mem src));
5128
5129 ins_cost(125); // XXX
5130 format %{ "movw $mem, $src\t# char/short" %}
5131 ins_encode %{
5132 __ movw($mem$$Address, $src$$Register);
5133 %}
5134 ins_pipe(ialu_mem_reg);
5135 %}
5136
5137 // Store Integer
5138 instruct storeI(memory mem, rRegI src)
5139 %{
5140 match(Set mem (StoreI mem src));
5141
5142 ins_cost(125); // XXX
5143 format %{ "movl $mem, $src\t# int" %}
5144 ins_encode %{
5145 __ movl($mem$$Address, $src$$Register);
5146 %}
5147 ins_pipe(ialu_mem_reg);
5148 %}
5149
5150 // Store Long
5151 instruct storeL(memory mem, rRegL src)
5152 %{
5153 match(Set mem (StoreL mem src));
5154
5155 ins_cost(125); // XXX
5156 format %{ "movq $mem, $src\t# long" %}
5157 ins_encode %{
5158 __ movq($mem$$Address, $src$$Register);
5159 %}
5160 ins_pipe(ialu_mem_reg); // XXX
5161 %}
5162
5163 // Store Pointer
5164 instruct storeP(memory mem, any_RegP src)
5165 %{
5166 predicate(n->as_Store()->barrier_data() == 0);
5167 match(Set mem (StoreP mem src));
5168
5169 ins_cost(125); // XXX
5170 format %{ "movq $mem, $src\t# ptr" %}
5171 ins_encode %{
5172 __ movq($mem$$Address, $src$$Register);
5173 %}
5174 ins_pipe(ialu_mem_reg);
5175 %}
5176
5177 instruct storeImmP0(memory mem, immP0 zero)
5178 %{
5179 predicate(UseCompressedOops && (CompressedOops::base() == nullptr) && n->as_Store()->barrier_data() == 0);
5180 match(Set mem (StoreP mem zero));
5181
5182 ins_cost(125); // XXX
5183 format %{ "movq $mem, R12\t# ptr (R12_heapbase==0)" %}
5184 ins_encode %{
5185 __ movq($mem$$Address, r12);
5186 %}
5187 ins_pipe(ialu_mem_reg);
5188 %}
5189
5190 // Store Null Pointer, mark word, or other simple pointer constant.
5191 instruct storeImmP(memory mem, immP31 src)
5192 %{
5193 predicate(n->as_Store()->barrier_data() == 0);
5194 match(Set mem (StoreP mem src));
5195
5196 ins_cost(150); // XXX
5197 format %{ "movq $mem, $src\t# ptr" %}
5198 ins_encode %{
5199 __ movq($mem$$Address, $src$$constant);
5200 %}
5201 ins_pipe(ialu_mem_imm);
5202 %}
5203
5204 // Store Compressed Pointer
5205 instruct storeN(memory mem, rRegN src)
5206 %{
5207 predicate(n->as_Store()->barrier_data() == 0);
5208 match(Set mem (StoreN mem src));
5209
5210 ins_cost(125); // XXX
5211 format %{ "movl $mem, $src\t# compressed ptr" %}
5212 ins_encode %{
5213 __ movl($mem$$Address, $src$$Register);
5214 %}
5215 ins_pipe(ialu_mem_reg);
5216 %}
5217
5218 instruct storeNKlass(memory mem, rRegN src)
5219 %{
5220 match(Set mem (StoreNKlass mem src));
5221
5222 ins_cost(125); // XXX
5223 format %{ "movl $mem, $src\t# compressed klass ptr" %}
5224 ins_encode %{
5225 __ movl($mem$$Address, $src$$Register);
5226 %}
5227 ins_pipe(ialu_mem_reg);
5228 %}
5229
5230 instruct storeImmN0(memory mem, immN0 zero)
5231 %{
5232 predicate(CompressedOops::base() == nullptr && n->as_Store()->barrier_data() == 0);
5233 match(Set mem (StoreN mem zero));
5234
5235 ins_cost(125); // XXX
5236 format %{ "movl $mem, R12\t# compressed ptr (R12_heapbase==0)" %}
5237 ins_encode %{
5238 __ movl($mem$$Address, r12);
5239 %}
5240 ins_pipe(ialu_mem_reg);
5241 %}
5242
5243 instruct storeImmN(memory mem, immN src)
5244 %{
5245 predicate(n->as_Store()->barrier_data() == 0);
5246 match(Set mem (StoreN mem src));
5247
5248 ins_cost(150); // XXX
5249 format %{ "movl $mem, $src\t# compressed ptr" %}
5250 ins_encode %{
5251 address con = (address)$src$$constant;
5252 if (con == nullptr) {
5253 __ movl($mem$$Address, 0);
5254 } else {
5255 __ set_narrow_oop($mem$$Address, (jobject)$src$$constant);
5256 }
5257 %}
5258 ins_pipe(ialu_mem_imm);
5259 %}
5260
5261 instruct storeImmNKlass(memory mem, immNKlass src)
5262 %{
5263 match(Set mem (StoreNKlass mem src));
5264
5265 ins_cost(150); // XXX
5266 format %{ "movl $mem, $src\t# compressed klass ptr" %}
5267 ins_encode %{
5268 __ set_narrow_klass($mem$$Address, (Klass*)$src$$constant);
5269 %}
5270 ins_pipe(ialu_mem_imm);
5271 %}
5272
5273 // Store Integer Immediate
5274 instruct storeImmI0(memory mem, immI_0 zero)
5275 %{
5276 predicate(UseCompressedOops && (CompressedOops::base() == nullptr));
5277 match(Set mem (StoreI mem zero));
5278
5279 ins_cost(125); // XXX
5280 format %{ "movl $mem, R12\t# int (R12_heapbase==0)" %}
5281 ins_encode %{
5282 __ movl($mem$$Address, r12);
5283 %}
5284 ins_pipe(ialu_mem_reg);
5285 %}
5286
5287 instruct storeImmI(memory mem, immI src)
5288 %{
5289 match(Set mem (StoreI mem src));
5290
5291 ins_cost(150);
5292 format %{ "movl $mem, $src\t# int" %}
5293 ins_encode %{
5294 __ movl($mem$$Address, $src$$constant);
5295 %}
5296 ins_pipe(ialu_mem_imm);
5297 %}
5298
5299 // Store Long Immediate
5300 instruct storeImmL0(memory mem, immL0 zero)
5301 %{
5302 predicate(UseCompressedOops && (CompressedOops::base() == nullptr));
5303 match(Set mem (StoreL mem zero));
5304
5305 ins_cost(125); // XXX
5306 format %{ "movq $mem, R12\t# long (R12_heapbase==0)" %}
5307 ins_encode %{
5308 __ movq($mem$$Address, r12);
5309 %}
5310 ins_pipe(ialu_mem_reg);
5311 %}
5312
5313 instruct storeImmL(memory mem, immL32 src)
5314 %{
5315 match(Set mem (StoreL mem src));
5316
5317 ins_cost(150);
5318 format %{ "movq $mem, $src\t# long" %}
5319 ins_encode %{
5320 __ movq($mem$$Address, $src$$constant);
5321 %}
5322 ins_pipe(ialu_mem_imm);
5323 %}
5324
5325 // Store Short/Char Immediate
5326 instruct storeImmC0(memory mem, immI_0 zero)
5327 %{
5328 predicate(UseCompressedOops && (CompressedOops::base() == nullptr));
5329 match(Set mem (StoreC mem zero));
5330
5331 ins_cost(125); // XXX
5332 format %{ "movw $mem, R12\t# short/char (R12_heapbase==0)" %}
5333 ins_encode %{
5334 __ movw($mem$$Address, r12);
5335 %}
5336 ins_pipe(ialu_mem_reg);
5337 %}
5338
5339 instruct storeImmI16(memory mem, immI16 src)
5340 %{
5341 predicate(UseStoreImmI16);
5342 match(Set mem (StoreC mem src));
5343
5344 ins_cost(150);
5345 format %{ "movw $mem, $src\t# short/char" %}
5346 ins_encode %{
5347 __ movw($mem$$Address, $src$$constant);
5348 %}
5349 ins_pipe(ialu_mem_imm);
5350 %}
5351
5352 // Store Byte Immediate
5353 instruct storeImmB0(memory mem, immI_0 zero)
5354 %{
5355 predicate(UseCompressedOops && (CompressedOops::base() == nullptr));
5356 match(Set mem (StoreB mem zero));
5357
5358 ins_cost(125); // XXX
5359 format %{ "movb $mem, R12\t# short/char (R12_heapbase==0)" %}
5360 ins_encode %{
5361 __ movb($mem$$Address, r12);
5362 %}
5363 ins_pipe(ialu_mem_reg);
5364 %}
5365
5366 instruct storeImmB(memory mem, immI8 src)
5367 %{
5368 match(Set mem (StoreB mem src));
5369
5370 ins_cost(150); // XXX
5371 format %{ "movb $mem, $src\t# byte" %}
5372 ins_encode %{
5373 __ movb($mem$$Address, $src$$constant);
5374 %}
5375 ins_pipe(ialu_mem_imm);
5376 %}
5377
5378 // Store Float
5379 instruct storeF(memory mem, regF src)
5380 %{
5381 match(Set mem (StoreF mem src));
5382
5383 ins_cost(95); // XXX
5384 format %{ "movss $mem, $src\t# float" %}
5385 ins_encode %{
5386 __ movflt($mem$$Address, $src$$XMMRegister);
5387 %}
5388 ins_pipe(pipe_slow); // XXX
5389 %}
5390
5391 // Store immediate Float value (it is faster than store from XMM register)
5392 instruct storeF0(memory mem, immF0 zero)
5393 %{
5394 predicate(UseCompressedOops && (CompressedOops::base() == nullptr));
5395 match(Set mem (StoreF mem zero));
5396
5397 ins_cost(25); // XXX
5398 format %{ "movl $mem, R12\t# float 0. (R12_heapbase==0)" %}
5399 ins_encode %{
5400 __ movl($mem$$Address, r12);
5401 %}
5402 ins_pipe(ialu_mem_reg);
5403 %}
5404
5405 instruct storeF_imm(memory mem, immF src)
5406 %{
5407 match(Set mem (StoreF mem src));
5408
5409 ins_cost(50);
5410 format %{ "movl $mem, $src\t# float" %}
5411 ins_encode %{
5412 __ movl($mem$$Address, jint_cast($src$$constant));
5413 %}
5414 ins_pipe(ialu_mem_imm);
5415 %}
5416
5417 // Store Double
5418 instruct storeD(memory mem, regD src)
5419 %{
5420 match(Set mem (StoreD mem src));
5421
5422 ins_cost(95); // XXX
5423 format %{ "movsd $mem, $src\t# double" %}
5424 ins_encode %{
5425 __ movdbl($mem$$Address, $src$$XMMRegister);
5426 %}
5427 ins_pipe(pipe_slow); // XXX
5428 %}
5429
5430 // Store immediate double 0.0 (it is faster than store from XMM register)
5431 instruct storeD0_imm(memory mem, immD0 src)
5432 %{
5433 predicate(!UseCompressedOops || (CompressedOops::base() != nullptr));
5434 match(Set mem (StoreD mem src));
5435
5436 ins_cost(50);
5437 format %{ "movq $mem, $src\t# double 0." %}
5438 ins_encode %{
5439 __ movq($mem$$Address, $src$$constant);
5440 %}
5441 ins_pipe(ialu_mem_imm);
5442 %}
5443
5444 instruct storeD0(memory mem, immD0 zero)
5445 %{
5446 predicate(UseCompressedOops && (CompressedOops::base() == nullptr));
5447 match(Set mem (StoreD mem zero));
5448
5449 ins_cost(25); // XXX
5450 format %{ "movq $mem, R12\t# double 0. (R12_heapbase==0)" %}
5451 ins_encode %{
5452 __ movq($mem$$Address, r12);
5453 %}
5454 ins_pipe(ialu_mem_reg);
5455 %}
5456
5457 instruct storeSSI(stackSlotI dst, rRegI src)
5458 %{
5459 match(Set dst src);
5460
5461 ins_cost(100);
5462 format %{ "movl $dst, $src\t# int stk" %}
5463 ins_encode %{
5464 __ movl($dst$$Address, $src$$Register);
5465 %}
5466 ins_pipe( ialu_mem_reg );
5467 %}
5468
5469 instruct storeSSL(stackSlotL dst, rRegL src)
5470 %{
5471 match(Set dst src);
5472
5473 ins_cost(100);
5474 format %{ "movq $dst, $src\t# long stk" %}
5475 ins_encode %{
5476 __ movq($dst$$Address, $src$$Register);
5477 %}
5478 ins_pipe(ialu_mem_reg);
5479 %}
5480
5481 instruct storeSSP(stackSlotP dst, rRegP src)
5482 %{
5483 match(Set dst src);
5484
5485 ins_cost(100);
5486 format %{ "movq $dst, $src\t# ptr stk" %}
5487 ins_encode %{
5488 __ movq($dst$$Address, $src$$Register);
5489 %}
5490 ins_pipe(ialu_mem_reg);
5491 %}
5492
5493 instruct storeSSF(stackSlotF dst, regF src)
5494 %{
5495 match(Set dst src);
5496
5497 ins_cost(95); // XXX
5498 format %{ "movss $dst, $src\t# float stk" %}
5499 ins_encode %{
5500 __ movflt(Address(rsp, $dst$$disp), $src$$XMMRegister);
5501 %}
5502 ins_pipe(pipe_slow); // XXX
5503 %}
5504
5505 instruct storeSSD(stackSlotD dst, regD src)
5506 %{
5507 match(Set dst src);
5508
5509 ins_cost(95); // XXX
5510 format %{ "movsd $dst, $src\t# double stk" %}
5511 ins_encode %{
5512 __ movdbl(Address(rsp, $dst$$disp), $src$$XMMRegister);
5513 %}
5514 ins_pipe(pipe_slow); // XXX
5515 %}
5516
5517 instruct cacheWB(indirect addr)
5518 %{
5519 predicate(VM_Version::supports_data_cache_line_flush());
5520 match(CacheWB addr);
5521
5522 ins_cost(100);
5523 format %{"cache wb $addr" %}
5524 ins_encode %{
5525 assert($addr->index_position() < 0, "should be");
5526 assert($addr$$disp == 0, "should be");
5527 __ cache_wb(Address($addr$$base$$Register, 0));
5528 %}
5529 ins_pipe(pipe_slow); // XXX
5530 %}
5531
5532 instruct cacheWBPreSync()
5533 %{
5534 predicate(VM_Version::supports_data_cache_line_flush());
5535 match(CacheWBPreSync);
5536
5537 ins_cost(100);
5538 format %{"cache wb presync" %}
5539 ins_encode %{
5540 __ cache_wbsync(true);
5541 %}
5542 ins_pipe(pipe_slow); // XXX
5543 %}
5544
5545 instruct cacheWBPostSync()
5546 %{
5547 predicate(VM_Version::supports_data_cache_line_flush());
5548 match(CacheWBPostSync);
5549
5550 ins_cost(100);
5551 format %{"cache wb postsync" %}
5552 ins_encode %{
5553 __ cache_wbsync(false);
5554 %}
5555 ins_pipe(pipe_slow); // XXX
5556 %}
5557
5558 //----------BSWAP Instructions-------------------------------------------------
5559 instruct bytes_reverse_int(rRegI dst) %{
5560 match(Set dst (ReverseBytesI dst));
5561
5562 format %{ "bswapl $dst" %}
5563 ins_encode %{
5564 __ bswapl($dst$$Register);
5565 %}
5566 ins_pipe( ialu_reg );
5567 %}
5568
5569 instruct bytes_reverse_long(rRegL dst) %{
5570 match(Set dst (ReverseBytesL dst));
5571
5572 format %{ "bswapq $dst" %}
5573 ins_encode %{
5574 __ bswapq($dst$$Register);
5575 %}
5576 ins_pipe( ialu_reg);
5577 %}
5578
5579 instruct bytes_reverse_unsigned_short(rRegI dst, rFlagsReg cr) %{
5580 match(Set dst (ReverseBytesUS dst));
5581 effect(KILL cr);
5582
5583 format %{ "bswapl $dst\n\t"
5584 "shrl $dst,16\n\t" %}
5585 ins_encode %{
5586 __ bswapl($dst$$Register);
5587 __ shrl($dst$$Register, 16);
5588 %}
5589 ins_pipe( ialu_reg );
5590 %}
5591
5592 instruct bytes_reverse_short(rRegI dst, rFlagsReg cr) %{
5593 match(Set dst (ReverseBytesS dst));
5594 effect(KILL cr);
5595
5596 format %{ "bswapl $dst\n\t"
5597 "sar $dst,16\n\t" %}
5598 ins_encode %{
5599 __ bswapl($dst$$Register);
5600 __ sarl($dst$$Register, 16);
5601 %}
5602 ins_pipe( ialu_reg );
5603 %}
5604
5605 //---------- Zeros Count Instructions ------------------------------------------
5606
5607 instruct countLeadingZerosI(rRegI dst, rRegI src, rFlagsReg cr) %{
5608 predicate(UseCountLeadingZerosInstruction);
5609 match(Set dst (CountLeadingZerosI src));
5610 effect(KILL cr);
5611
5612 format %{ "lzcntl $dst, $src\t# count leading zeros (int)" %}
5613 ins_encode %{
5614 __ lzcntl($dst$$Register, $src$$Register);
5615 %}
5616 ins_pipe(ialu_reg);
5617 %}
5618
5619 instruct countLeadingZerosI_mem(rRegI dst, memory src, rFlagsReg cr) %{
5620 predicate(UseCountLeadingZerosInstruction);
5621 match(Set dst (CountLeadingZerosI (LoadI src)));
5622 effect(KILL cr);
5623 ins_cost(175);
5624 format %{ "lzcntl $dst, $src\t# count leading zeros (int)" %}
5625 ins_encode %{
5626 __ lzcntl($dst$$Register, $src$$Address);
5627 %}
5628 ins_pipe(ialu_reg_mem);
5629 %}
5630
5631 instruct countLeadingZerosI_bsr(rRegI dst, rRegI src, rFlagsReg cr) %{
5632 predicate(!UseCountLeadingZerosInstruction);
5633 match(Set dst (CountLeadingZerosI src));
5634 effect(KILL cr);
5635
5636 format %{ "bsrl $dst, $src\t# count leading zeros (int)\n\t"
5637 "jnz skip\n\t"
5638 "movl $dst, -1\n"
5639 "skip:\n\t"
5640 "negl $dst\n\t"
5641 "addl $dst, 31" %}
5642 ins_encode %{
5643 Register Rdst = $dst$$Register;
5644 Register Rsrc = $src$$Register;
5645 Label skip;
5646 __ bsrl(Rdst, Rsrc);
5647 __ jccb(Assembler::notZero, skip);
5648 __ movl(Rdst, -1);
5649 __ bind(skip);
5650 __ negl(Rdst);
5651 __ addl(Rdst, BitsPerInt - 1);
5652 %}
5653 ins_pipe(ialu_reg);
5654 %}
5655
5656 instruct countLeadingZerosL(rRegI dst, rRegL src, rFlagsReg cr) %{
5657 predicate(UseCountLeadingZerosInstruction);
5658 match(Set dst (CountLeadingZerosL src));
5659 effect(KILL cr);
5660
5661 format %{ "lzcntq $dst, $src\t# count leading zeros (long)" %}
5662 ins_encode %{
5663 __ lzcntq($dst$$Register, $src$$Register);
5664 %}
5665 ins_pipe(ialu_reg);
5666 %}
5667
5668 instruct countLeadingZerosL_mem(rRegI dst, memory src, rFlagsReg cr) %{
5669 predicate(UseCountLeadingZerosInstruction);
5670 match(Set dst (CountLeadingZerosL (LoadL src)));
5671 effect(KILL cr);
5672 ins_cost(175);
5673 format %{ "lzcntq $dst, $src\t# count leading zeros (long)" %}
5674 ins_encode %{
5675 __ lzcntq($dst$$Register, $src$$Address);
5676 %}
5677 ins_pipe(ialu_reg_mem);
5678 %}
5679
5680 instruct countLeadingZerosL_bsr(rRegI dst, rRegL src, rFlagsReg cr) %{
5681 predicate(!UseCountLeadingZerosInstruction);
5682 match(Set dst (CountLeadingZerosL src));
5683 effect(KILL cr);
5684
5685 format %{ "bsrq $dst, $src\t# count leading zeros (long)\n\t"
5686 "jnz skip\n\t"
5687 "movl $dst, -1\n"
5688 "skip:\n\t"
5689 "negl $dst\n\t"
5690 "addl $dst, 63" %}
5691 ins_encode %{
5692 Register Rdst = $dst$$Register;
5693 Register Rsrc = $src$$Register;
5694 Label skip;
5695 __ bsrq(Rdst, Rsrc);
5696 __ jccb(Assembler::notZero, skip);
5697 __ movl(Rdst, -1);
5698 __ bind(skip);
5699 __ negl(Rdst);
5700 __ addl(Rdst, BitsPerLong - 1);
5701 %}
5702 ins_pipe(ialu_reg);
5703 %}
5704
5705 instruct countTrailingZerosI(rRegI dst, rRegI src, rFlagsReg cr) %{
5706 predicate(UseCountTrailingZerosInstruction);
5707 match(Set dst (CountTrailingZerosI src));
5708 effect(KILL cr);
5709
5710 format %{ "tzcntl $dst, $src\t# count trailing zeros (int)" %}
5711 ins_encode %{
5712 __ tzcntl($dst$$Register, $src$$Register);
5713 %}
5714 ins_pipe(ialu_reg);
5715 %}
5716
5717 instruct countTrailingZerosI_mem(rRegI dst, memory src, rFlagsReg cr) %{
5718 predicate(UseCountTrailingZerosInstruction);
5719 match(Set dst (CountTrailingZerosI (LoadI src)));
5720 effect(KILL cr);
5721 ins_cost(175);
5722 format %{ "tzcntl $dst, $src\t# count trailing zeros (int)" %}
5723 ins_encode %{
5724 __ tzcntl($dst$$Register, $src$$Address);
5725 %}
5726 ins_pipe(ialu_reg_mem);
5727 %}
5728
5729 instruct countTrailingZerosI_bsf(rRegI dst, rRegI src, rFlagsReg cr) %{
5730 predicate(!UseCountTrailingZerosInstruction);
5731 match(Set dst (CountTrailingZerosI src));
5732 effect(KILL cr);
5733
5734 format %{ "bsfl $dst, $src\t# count trailing zeros (int)\n\t"
5735 "jnz done\n\t"
5736 "movl $dst, 32\n"
5737 "done:" %}
5738 ins_encode %{
5739 Register Rdst = $dst$$Register;
5740 Label done;
5741 __ bsfl(Rdst, $src$$Register);
5742 __ jccb(Assembler::notZero, done);
5743 __ movl(Rdst, BitsPerInt);
5744 __ bind(done);
5745 %}
5746 ins_pipe(ialu_reg);
5747 %}
5748
5749 instruct countTrailingZerosL(rRegI dst, rRegL src, rFlagsReg cr) %{
5750 predicate(UseCountTrailingZerosInstruction);
5751 match(Set dst (CountTrailingZerosL src));
5752 effect(KILL cr);
5753
5754 format %{ "tzcntq $dst, $src\t# count trailing zeros (long)" %}
5755 ins_encode %{
5756 __ tzcntq($dst$$Register, $src$$Register);
5757 %}
5758 ins_pipe(ialu_reg);
5759 %}
5760
5761 instruct countTrailingZerosL_mem(rRegI dst, memory src, rFlagsReg cr) %{
5762 predicate(UseCountTrailingZerosInstruction);
5763 match(Set dst (CountTrailingZerosL (LoadL src)));
5764 effect(KILL cr);
5765 ins_cost(175);
5766 format %{ "tzcntq $dst, $src\t# count trailing zeros (long)" %}
5767 ins_encode %{
5768 __ tzcntq($dst$$Register, $src$$Address);
5769 %}
5770 ins_pipe(ialu_reg_mem);
5771 %}
5772
5773 instruct countTrailingZerosL_bsf(rRegI dst, rRegL src, rFlagsReg cr) %{
5774 predicate(!UseCountTrailingZerosInstruction);
5775 match(Set dst (CountTrailingZerosL src));
5776 effect(KILL cr);
5777
5778 format %{ "bsfq $dst, $src\t# count trailing zeros (long)\n\t"
5779 "jnz done\n\t"
5780 "movl $dst, 64\n"
5781 "done:" %}
5782 ins_encode %{
5783 Register Rdst = $dst$$Register;
5784 Label done;
5785 __ bsfq(Rdst, $src$$Register);
5786 __ jccb(Assembler::notZero, done);
5787 __ movl(Rdst, BitsPerLong);
5788 __ bind(done);
5789 %}
5790 ins_pipe(ialu_reg);
5791 %}
5792
5793 //--------------- Reverse Operation Instructions ----------------
5794 instruct bytes_reversebit_int(rRegI dst, rRegI src, rRegI rtmp, rFlagsReg cr) %{
5795 predicate(!VM_Version::supports_gfni());
5796 match(Set dst (ReverseI src));
5797 effect(TEMP dst, TEMP rtmp, KILL cr);
5798 format %{ "reverse_int $dst $src\t! using $rtmp as TEMP" %}
5799 ins_encode %{
5800 __ reverseI($dst$$Register, $src$$Register, xnoreg, xnoreg, $rtmp$$Register);
5801 %}
5802 ins_pipe( ialu_reg );
5803 %}
5804
5805 instruct bytes_reversebit_int_gfni(rRegI dst, rRegI src, vlRegF xtmp1, vlRegF xtmp2, rRegL rtmp, rFlagsReg cr) %{
5806 predicate(VM_Version::supports_gfni());
5807 match(Set dst (ReverseI src));
5808 effect(TEMP dst, TEMP xtmp1, TEMP xtmp2, TEMP rtmp, KILL cr);
5809 format %{ "reverse_int $dst $src\t! using $rtmp, $xtmp1 and $xtmp2 as TEMP" %}
5810 ins_encode %{
5811 __ reverseI($dst$$Register, $src$$Register, $xtmp1$$XMMRegister, $xtmp2$$XMMRegister, $rtmp$$Register);
5812 %}
5813 ins_pipe( ialu_reg );
5814 %}
5815
5816 instruct bytes_reversebit_long(rRegL dst, rRegL src, rRegL rtmp1, rRegL rtmp2, rFlagsReg cr) %{
5817 predicate(!VM_Version::supports_gfni());
5818 match(Set dst (ReverseL src));
5819 effect(TEMP dst, TEMP rtmp1, TEMP rtmp2, KILL cr);
5820 format %{ "reverse_long $dst $src\t! using $rtmp1 and $rtmp2 as TEMP" %}
5821 ins_encode %{
5822 __ reverseL($dst$$Register, $src$$Register, xnoreg, xnoreg, $rtmp1$$Register, $rtmp2$$Register);
5823 %}
5824 ins_pipe( ialu_reg );
5825 %}
5826
5827 instruct bytes_reversebit_long_gfni(rRegL dst, rRegL src, vlRegD xtmp1, vlRegD xtmp2, rRegL rtmp, rFlagsReg cr) %{
5828 predicate(VM_Version::supports_gfni());
5829 match(Set dst (ReverseL src));
5830 effect(TEMP dst, TEMP xtmp1, TEMP xtmp2, TEMP rtmp, KILL cr);
5831 format %{ "reverse_long $dst $src\t! using $rtmp, $xtmp1 and $xtmp2 as TEMP" %}
5832 ins_encode %{
5833 __ reverseL($dst$$Register, $src$$Register, $xtmp1$$XMMRegister, $xtmp2$$XMMRegister, $rtmp$$Register, noreg);
5834 %}
5835 ins_pipe( ialu_reg );
5836 %}
5837
5838 //---------- Population Count Instructions -------------------------------------
5839
5840 instruct popCountI(rRegI dst, rRegI src, rFlagsReg cr) %{
5841 predicate(UsePopCountInstruction);
5842 match(Set dst (PopCountI src));
5843 effect(KILL cr);
5844
5845 format %{ "popcnt $dst, $src" %}
5846 ins_encode %{
5847 __ popcntl($dst$$Register, $src$$Register);
5848 %}
5849 ins_pipe(ialu_reg);
5850 %}
5851
5852 instruct popCountI_mem(rRegI dst, memory mem, rFlagsReg cr) %{
5853 predicate(UsePopCountInstruction);
5854 match(Set dst (PopCountI (LoadI mem)));
5855 effect(KILL cr);
5856
5857 format %{ "popcnt $dst, $mem" %}
5858 ins_encode %{
5859 __ popcntl($dst$$Register, $mem$$Address);
5860 %}
5861 ins_pipe(ialu_reg);
5862 %}
5863
5864 // Note: Long.bitCount(long) returns an int.
5865 instruct popCountL(rRegI dst, rRegL src, rFlagsReg cr) %{
5866 predicate(UsePopCountInstruction);
5867 match(Set dst (PopCountL src));
5868 effect(KILL cr);
5869
5870 format %{ "popcnt $dst, $src" %}
5871 ins_encode %{
5872 __ popcntq($dst$$Register, $src$$Register);
5873 %}
5874 ins_pipe(ialu_reg);
5875 %}
5876
5877 // Note: Long.bitCount(long) returns an int.
5878 instruct popCountL_mem(rRegI dst, memory mem, rFlagsReg cr) %{
5879 predicate(UsePopCountInstruction);
5880 match(Set dst (PopCountL (LoadL mem)));
5881 effect(KILL cr);
5882
5883 format %{ "popcnt $dst, $mem" %}
5884 ins_encode %{
5885 __ popcntq($dst$$Register, $mem$$Address);
5886 %}
5887 ins_pipe(ialu_reg);
5888 %}
5889
5890
5891 //----------MemBar Instructions-----------------------------------------------
5892 // Memory barrier flavors
5893
5894 instruct membar_acquire()
5895 %{
5896 match(MemBarAcquire);
5897 match(LoadFence);
5898 ins_cost(0);
5899
5900 size(0);
5901 format %{ "MEMBAR-acquire ! (empty encoding)" %}
5902 ins_encode();
5903 ins_pipe(empty);
5904 %}
5905
5906 instruct membar_acquire_lock()
5907 %{
5908 match(MemBarAcquireLock);
5909 ins_cost(0);
5910
5911 size(0);
5912 format %{ "MEMBAR-acquire (prior CMPXCHG in FastLock so empty encoding)" %}
5913 ins_encode();
5914 ins_pipe(empty);
5915 %}
5916
5917 instruct membar_release()
5918 %{
5919 match(MemBarRelease);
5920 match(StoreFence);
5921 ins_cost(0);
5922
5923 size(0);
5924 format %{ "MEMBAR-release ! (empty encoding)" %}
5925 ins_encode();
5926 ins_pipe(empty);
5927 %}
5928
5929 instruct membar_release_lock()
5930 %{
5931 match(MemBarReleaseLock);
5932 ins_cost(0);
5933
5934 size(0);
5935 format %{ "MEMBAR-release (a FastUnlock follows so empty encoding)" %}
5936 ins_encode();
5937 ins_pipe(empty);
5938 %}
5939
5940 instruct membar_volatile(rFlagsReg cr) %{
5941 match(MemBarVolatile);
5942 effect(KILL cr);
5943 ins_cost(400);
5944
5945 format %{
5946 $$template
5947 $$emit$$"lock addl [rsp + #0], 0\t! membar_volatile"
5948 %}
5949 ins_encode %{
5950 __ membar(Assembler::StoreLoad);
5951 %}
5952 ins_pipe(pipe_slow);
5953 %}
5954
5955 instruct unnecessary_membar_volatile()
5956 %{
5957 match(MemBarVolatile);
5958 predicate(Matcher::post_store_load_barrier(n));
5959 ins_cost(0);
5960
5961 size(0);
5962 format %{ "MEMBAR-volatile (unnecessary so empty encoding)" %}
5963 ins_encode();
5964 ins_pipe(empty);
5965 %}
5966
5967 instruct membar_storestore() %{
5968 match(MemBarStoreStore);
5969 match(StoreStoreFence);
5970 ins_cost(0);
5971
5972 size(0);
5973 format %{ "MEMBAR-storestore (empty encoding)" %}
5974 ins_encode( );
5975 ins_pipe(empty);
5976 %}
5977
5978 //----------Move Instructions--------------------------------------------------
5979
5980 instruct castX2P(rRegP dst, rRegL src)
5981 %{
5982 match(Set dst (CastX2P src));
5983
5984 format %{ "movq $dst, $src\t# long->ptr" %}
5985 ins_encode %{
5986 if ($dst$$reg != $src$$reg) {
5987 __ movptr($dst$$Register, $src$$Register);
5988 }
5989 %}
5990 ins_pipe(ialu_reg_reg); // XXX
5991 %}
5992
5993 instruct castP2X(rRegL dst, rRegP src)
5994 %{
5995 match(Set dst (CastP2X src));
5996
5997 format %{ "movq $dst, $src\t# ptr -> long" %}
5998 ins_encode %{
5999 if ($dst$$reg != $src$$reg) {
6000 __ movptr($dst$$Register, $src$$Register);
6001 }
6002 %}
6003 ins_pipe(ialu_reg_reg); // XXX
6004 %}
6005
6006 // Convert oop into int for vectors alignment masking
6007 instruct convP2I(rRegI dst, rRegP src)
6008 %{
6009 match(Set dst (ConvL2I (CastP2X src)));
6010
6011 format %{ "movl $dst, $src\t# ptr -> int" %}
6012 ins_encode %{
6013 __ movl($dst$$Register, $src$$Register);
6014 %}
6015 ins_pipe(ialu_reg_reg); // XXX
6016 %}
6017
6018 // Convert compressed oop into int for vectors alignment masking
6019 // in case of 32bit oops (heap < 4Gb).
6020 instruct convN2I(rRegI dst, rRegN src)
6021 %{
6022 predicate(CompressedOops::shift() == 0);
6023 match(Set dst (ConvL2I (CastP2X (DecodeN src))));
6024
6025 format %{ "movl $dst, $src\t# compressed ptr -> int" %}
6026 ins_encode %{
6027 __ movl($dst$$Register, $src$$Register);
6028 %}
6029 ins_pipe(ialu_reg_reg); // XXX
6030 %}
6031
6032 // Convert oop pointer into compressed form
6033 instruct encodeHeapOop(rRegN dst, rRegP src, rFlagsReg cr) %{
6034 predicate(n->bottom_type()->make_ptr()->ptr() != TypePtr::NotNull);
6035 match(Set dst (EncodeP src));
6036 effect(KILL cr);
6037 format %{ "encode_heap_oop $dst,$src" %}
6038 ins_encode %{
6039 Register s = $src$$Register;
6040 Register d = $dst$$Register;
6041 if (s != d) {
6042 __ movq(d, s);
6043 }
6044 __ encode_heap_oop(d);
6045 %}
6046 ins_pipe(ialu_reg_long);
6047 %}
6048
6049 instruct encodeHeapOop_not_null(rRegN dst, rRegP src, rFlagsReg cr) %{
6050 predicate(n->bottom_type()->make_ptr()->ptr() == TypePtr::NotNull);
6051 match(Set dst (EncodeP src));
6052 effect(KILL cr);
6053 format %{ "encode_heap_oop_not_null $dst,$src" %}
6054 ins_encode %{
6055 __ encode_heap_oop_not_null($dst$$Register, $src$$Register);
6056 %}
6057 ins_pipe(ialu_reg_long);
6058 %}
6059
6060 instruct decodeHeapOop(rRegP dst, rRegN src, rFlagsReg cr) %{
6061 predicate(n->bottom_type()->is_ptr()->ptr() != TypePtr::NotNull &&
6062 n->bottom_type()->is_ptr()->ptr() != TypePtr::Constant);
6063 match(Set dst (DecodeN src));
6064 effect(KILL cr);
6065 format %{ "decode_heap_oop $dst,$src" %}
6066 ins_encode %{
6067 Register s = $src$$Register;
6068 Register d = $dst$$Register;
6069 if (s != d) {
6070 __ movq(d, s);
6071 }
6072 __ decode_heap_oop(d);
6073 %}
6074 ins_pipe(ialu_reg_long);
6075 %}
6076
6077 instruct decodeHeapOop_not_null(rRegP dst, rRegN src, rFlagsReg cr) %{
6078 predicate(n->bottom_type()->is_ptr()->ptr() == TypePtr::NotNull ||
6079 n->bottom_type()->is_ptr()->ptr() == TypePtr::Constant);
6080 match(Set dst (DecodeN src));
6081 effect(KILL cr);
6082 format %{ "decode_heap_oop_not_null $dst,$src" %}
6083 ins_encode %{
6084 Register s = $src$$Register;
6085 Register d = $dst$$Register;
6086 if (s != d) {
6087 __ decode_heap_oop_not_null(d, s);
6088 } else {
6089 __ decode_heap_oop_not_null(d);
6090 }
6091 %}
6092 ins_pipe(ialu_reg_long);
6093 %}
6094
6095 instruct encodeKlass_not_null(rRegN dst, rRegP src, rFlagsReg cr) %{
6096 match(Set dst (EncodePKlass src));
6097 effect(TEMP dst, KILL cr);
6098 format %{ "encode_and_move_klass_not_null $dst,$src" %}
6099 ins_encode %{
6100 __ encode_and_move_klass_not_null($dst$$Register, $src$$Register);
6101 %}
6102 ins_pipe(ialu_reg_long);
6103 %}
6104
6105 instruct decodeKlass_not_null(rRegP dst, rRegN src, rFlagsReg cr) %{
6106 match(Set dst (DecodeNKlass src));
6107 effect(TEMP dst, KILL cr);
6108 format %{ "decode_and_move_klass_not_null $dst,$src" %}
6109 ins_encode %{
6110 __ decode_and_move_klass_not_null($dst$$Register, $src$$Register);
6111 %}
6112 ins_pipe(ialu_reg_long);
6113 %}
6114
6115 //----------Conditional Move---------------------------------------------------
6116 // Jump
6117 // dummy instruction for generating temp registers
6118 instruct jumpXtnd_offset(rRegL switch_val, immI2 shift, rRegI dest) %{
6119 match(Jump (LShiftL switch_val shift));
6120 ins_cost(350);
6121 predicate(false);
6122 effect(TEMP dest);
6123
6124 format %{ "leaq $dest, [$constantaddress]\n\t"
6125 "jmp [$dest + $switch_val << $shift]\n\t" %}
6126 ins_encode %{
6127 // We could use jump(ArrayAddress) except that the macro assembler needs to use r10
6128 // to do that and the compiler is using that register as one it can allocate.
6129 // So we build it all by hand.
6130 // Address index(noreg, switch_reg, (Address::ScaleFactor)$shift$$constant);
6131 // ArrayAddress dispatch(table, index);
6132 Address dispatch($dest$$Register, $switch_val$$Register, (Address::ScaleFactor) $shift$$constant);
6133 __ lea($dest$$Register, $constantaddress);
6134 __ jmp(dispatch);
6135 %}
6136 ins_pipe(pipe_jmp);
6137 %}
6138
6139 instruct jumpXtnd_addr(rRegL switch_val, immI2 shift, immL32 offset, rRegI dest) %{
6140 match(Jump (AddL (LShiftL switch_val shift) offset));
6141 ins_cost(350);
6142 effect(TEMP dest);
6143
6144 format %{ "leaq $dest, [$constantaddress]\n\t"
6145 "jmp [$dest + $switch_val << $shift + $offset]\n\t" %}
6146 ins_encode %{
6147 // We could use jump(ArrayAddress) except that the macro assembler needs to use r10
6148 // to do that and the compiler is using that register as one it can allocate.
6149 // So we build it all by hand.
6150 // Address index(noreg, switch_reg, (Address::ScaleFactor) $shift$$constant, (int) $offset$$constant);
6151 // ArrayAddress dispatch(table, index);
6152 Address dispatch($dest$$Register, $switch_val$$Register, (Address::ScaleFactor) $shift$$constant, (int) $offset$$constant);
6153 __ lea($dest$$Register, $constantaddress);
6154 __ jmp(dispatch);
6155 %}
6156 ins_pipe(pipe_jmp);
6157 %}
6158
6159 instruct jumpXtnd(rRegL switch_val, rRegI dest) %{
6160 match(Jump switch_val);
6161 ins_cost(350);
6162 effect(TEMP dest);
6163
6164 format %{ "leaq $dest, [$constantaddress]\n\t"
6165 "jmp [$dest + $switch_val]\n\t" %}
6166 ins_encode %{
6167 // We could use jump(ArrayAddress) except that the macro assembler needs to use r10
6168 // to do that and the compiler is using that register as one it can allocate.
6169 // So we build it all by hand.
6170 // Address index(noreg, switch_reg, Address::times_1);
6171 // ArrayAddress dispatch(table, index);
6172 Address dispatch($dest$$Register, $switch_val$$Register, Address::times_1);
6173 __ lea($dest$$Register, $constantaddress);
6174 __ jmp(dispatch);
6175 %}
6176 ins_pipe(pipe_jmp);
6177 %}
6178
6179 // Conditional move
6180 instruct cmovI_imm_01(rRegI dst, immI_1 src, rFlagsReg cr, cmpOp cop)
6181 %{
6182 predicate(n->in(2)->in(2)->is_Con() && n->in(2)->in(2)->get_int() == 0);
6183 match(Set dst (CMoveI (Binary cop cr) (Binary src dst)));
6184
6185 ins_cost(100); // XXX
6186 format %{ "setbn$cop $dst\t# signed, int" %}
6187 ins_encode %{
6188 Assembler::Condition cond = (Assembler::Condition)($cop$$cmpcode);
6189 __ setb(MacroAssembler::negate_condition(cond), $dst$$Register);
6190 %}
6191 ins_pipe(ialu_reg);
6192 %}
6193
6194 instruct cmovI_reg(rRegI dst, rRegI src, rFlagsReg cr, cmpOp cop)
6195 %{
6196 predicate(!UseAPX);
6197 match(Set dst (CMoveI (Binary cop cr) (Binary dst src)));
6198
6199 ins_cost(200); // XXX
6200 format %{ "cmovl$cop $dst, $src\t# signed, int" %}
6201 ins_encode %{
6202 __ cmovl((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src$$Register);
6203 %}
6204 ins_pipe(pipe_cmov_reg);
6205 %}
6206
6207 instruct cmovI_reg_ndd(rRegI dst, rRegI src1, rRegI src2, rFlagsReg cr, cmpOp cop)
6208 %{
6209 predicate(UseAPX);
6210 match(Set dst (CMoveI (Binary cop cr) (Binary src1 src2)));
6211
6212 ins_cost(200);
6213 format %{ "ecmovl$cop $dst, $src1, $src2\t# signed, int ndd" %}
6214 ins_encode %{
6215 __ ecmovl((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src1$$Register, $src2$$Register);
6216 %}
6217 ins_pipe(pipe_cmov_reg);
6218 %}
6219
6220 instruct cmovI_imm_01U(rRegI dst, immI_1 src, rFlagsRegU cr, cmpOpU cop)
6221 %{
6222 predicate(n->in(2)->in(2)->is_Con() && n->in(2)->in(2)->get_int() == 0);
6223 match(Set dst (CMoveI (Binary cop cr) (Binary src dst)));
6224
6225 ins_cost(100); // XXX
6226 format %{ "setbn$cop $dst\t# unsigned, int" %}
6227 ins_encode %{
6228 Assembler::Condition cond = (Assembler::Condition)($cop$$cmpcode);
6229 __ setb(MacroAssembler::negate_condition(cond), $dst$$Register);
6230 %}
6231 ins_pipe(ialu_reg);
6232 %}
6233
6234 instruct cmovI_regU(cmpOpU cop, rFlagsRegU cr, rRegI dst, rRegI src) %{
6235 predicate(!UseAPX);
6236 match(Set dst (CMoveI (Binary cop cr) (Binary dst src)));
6237
6238 ins_cost(200); // XXX
6239 format %{ "cmovl$cop $dst, $src\t# unsigned, int" %}
6240 ins_encode %{
6241 __ cmovl((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src$$Register);
6242 %}
6243 ins_pipe(pipe_cmov_reg);
6244 %}
6245
6246 instruct cmovI_regU_ndd(rRegI dst, cmpOpU cop, rFlagsRegU cr, rRegI src1, rRegI src2) %{
6247 predicate(UseAPX);
6248 match(Set dst (CMoveI (Binary cop cr) (Binary src1 src2)));
6249
6250 ins_cost(200);
6251 format %{ "ecmovl$cop $dst, $src1, $src2\t# unsigned, int ndd" %}
6252 ins_encode %{
6253 __ ecmovl((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src1$$Register, $src2$$Register);
6254 %}
6255 ins_pipe(pipe_cmov_reg);
6256 %}
6257
6258 instruct cmovI_imm_01UCF(rRegI dst, immI_1 src, rFlagsRegUCF cr, cmpOpUCF cop)
6259 %{
6260 predicate(n->in(2)->in(2)->is_Con() && n->in(2)->in(2)->get_int() == 0);
6261 match(Set dst (CMoveI (Binary cop cr) (Binary src dst)));
6262
6263 ins_cost(100); // XXX
6264 format %{ "setbn$cop $dst\t# unsigned, int" %}
6265 ins_encode %{
6266 Assembler::Condition cond = (Assembler::Condition)($cop$$cmpcode);
6267 __ setb(MacroAssembler::negate_condition(cond), $dst$$Register);
6268 %}
6269 ins_pipe(ialu_reg);
6270 %}
6271
6272 instruct cmovI_regUCF(cmpOpUCF cop, rFlagsRegUCF cr, rRegI dst, rRegI src) %{
6273 predicate(!UseAPX);
6274 match(Set dst (CMoveI (Binary cop cr) (Binary dst src)));
6275 ins_cost(200);
6276 expand %{
6277 cmovI_regU(cop, cr, dst, src);
6278 %}
6279 %}
6280
6281 instruct cmovI_regUCF_ndd(rRegI dst, cmpOpUCF cop, rFlagsRegUCF cr, rRegI src1, rRegI src2) %{
6282 predicate(UseAPX);
6283 match(Set dst (CMoveI (Binary cop cr) (Binary src1 src2)));
6284 ins_cost(200);
6285 format %{ "ecmovl$cop $dst, $src1, $src2\t# unsigned, int ndd" %}
6286 ins_encode %{
6287 __ ecmovl((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src1$$Register, $src2$$Register);
6288 %}
6289 ins_pipe(pipe_cmov_reg);
6290 %}
6291
6292 instruct cmovI_regUCF2_ne(cmpOpUCF2 cop, rFlagsRegUCF cr, rRegI dst, rRegI src) %{
6293 predicate(!UseAPX && n->in(1)->in(1)->as_Bool()->_test._test == BoolTest::ne);
6294 match(Set dst (CMoveI (Binary cop cr) (Binary dst src)));
6295
6296 ins_cost(200); // XXX
6297 format %{ "cmovpl $dst, $src\n\t"
6298 "cmovnel $dst, $src" %}
6299 ins_encode %{
6300 __ cmovl(Assembler::parity, $dst$$Register, $src$$Register);
6301 __ cmovl(Assembler::notEqual, $dst$$Register, $src$$Register);
6302 %}
6303 ins_pipe(pipe_cmov_reg);
6304 %}
6305
6306 instruct cmovI_regUCF2_ne_ndd(cmpOpUCF2 cop, rFlagsRegUCF cr, rRegI dst, rRegI src1, rRegI src2) %{
6307 predicate(UseAPX && n->in(1)->in(1)->as_Bool()->_test._test == BoolTest::ne);
6308 match(Set dst (CMoveI (Binary cop cr) (Binary src1 src2)));
6309 effect(TEMP dst);
6310
6311 ins_cost(200);
6312 format %{ "ecmovpl $dst, $src1, $src2\n\t"
6313 "cmovnel $dst, $src2" %}
6314 ins_encode %{
6315 __ ecmovl(Assembler::parity, $dst$$Register, $src1$$Register, $src2$$Register);
6316 __ cmovl(Assembler::notEqual, $dst$$Register, $src2$$Register);
6317 %}
6318 ins_pipe(pipe_cmov_reg);
6319 %}
6320
6321 // Since (x == y) == !(x != y), we can flip the sense of the test by flipping the
6322 // inputs of the CMove
6323 instruct cmovI_regUCF2_eq(cmpOpUCF2 cop, rFlagsRegUCF cr, rRegI dst, rRegI src) %{
6324 predicate(!UseAPX && n->in(1)->in(1)->as_Bool()->_test._test == BoolTest::eq);
6325 match(Set dst (CMoveI (Binary cop cr) (Binary src dst)));
6326 effect(TEMP dst);
6327
6328 ins_cost(200); // XXX
6329 format %{ "cmovpl $dst, $src\n\t"
6330 "cmovnel $dst, $src" %}
6331 ins_encode %{
6332 __ cmovl(Assembler::parity, $dst$$Register, $src$$Register);
6333 __ cmovl(Assembler::notEqual, $dst$$Register, $src$$Register);
6334 %}
6335 ins_pipe(pipe_cmov_reg);
6336 %}
6337
6338 // We need this special handling for only eq / neq comparison since NaN == NaN is false,
6339 // and parity flag bit is set if any of the operand is a NaN.
6340 instruct cmovI_regUCF2_eq_ndd(cmpOpUCF2 cop, rFlagsRegUCF cr, rRegI dst, rRegI src1, rRegI src2) %{
6341 predicate(UseAPX && n->in(1)->in(1)->as_Bool()->_test._test == BoolTest::eq);
6342 match(Set dst (CMoveI (Binary cop cr) (Binary src2 src1)));
6343 effect(TEMP dst);
6344
6345 ins_cost(200);
6346 format %{ "ecmovpl $dst, $src1, $src2\n\t"
6347 "cmovnel $dst, $src2" %}
6348 ins_encode %{
6349 __ ecmovl(Assembler::parity, $dst$$Register, $src1$$Register, $src2$$Register);
6350 __ cmovl(Assembler::notEqual, $dst$$Register, $src2$$Register);
6351 %}
6352 ins_pipe(pipe_cmov_reg);
6353 %}
6354
6355 // Conditional move
6356 instruct cmovI_mem(cmpOp cop, rFlagsReg cr, rRegI dst, memory src) %{
6357 predicate(!UseAPX);
6358 match(Set dst (CMoveI (Binary cop cr) (Binary dst (LoadI src))));
6359
6360 ins_cost(250); // XXX
6361 format %{ "cmovl$cop $dst, $src\t# signed, int" %}
6362 ins_encode %{
6363 __ cmovl((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src$$Address);
6364 %}
6365 ins_pipe(pipe_cmov_mem);
6366 %}
6367
6368 // Conditional move
6369 instruct cmovI_rReg_rReg_mem_ndd(rRegI dst, cmpOp cop, rFlagsReg cr, rRegI src1, memory src2)
6370 %{
6371 predicate(UseAPX);
6372 match(Set dst (CMoveI (Binary cop cr) (Binary src1 (LoadI src2))));
6373
6374 ins_cost(250);
6375 format %{ "ecmovl$cop $dst, $src1, $src2\t# signed, int ndd" %}
6376 ins_encode %{
6377 __ ecmovl((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src1$$Register, $src2$$Address);
6378 %}
6379 ins_pipe(pipe_cmov_mem);
6380 %}
6381
6382 // Conditional move
6383 instruct cmovI_memU(cmpOpU cop, rFlagsRegU cr, rRegI dst, memory src)
6384 %{
6385 predicate(!UseAPX);
6386 match(Set dst (CMoveI (Binary cop cr) (Binary dst (LoadI src))));
6387
6388 ins_cost(250); // XXX
6389 format %{ "cmovl$cop $dst, $src\t# unsigned, int" %}
6390 ins_encode %{
6391 __ cmovl((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src$$Address);
6392 %}
6393 ins_pipe(pipe_cmov_mem);
6394 %}
6395
6396 instruct cmovI_memUCF(cmpOpUCF cop, rFlagsRegUCF cr, rRegI dst, memory src) %{
6397 predicate(!UseAPX);
6398 match(Set dst (CMoveI (Binary cop cr) (Binary dst (LoadI src))));
6399 ins_cost(250);
6400 expand %{
6401 cmovI_memU(cop, cr, dst, src);
6402 %}
6403 %}
6404
6405 instruct cmovI_rReg_rReg_memU_ndd(rRegI dst, cmpOpU cop, rFlagsRegU cr, rRegI src1, memory src2)
6406 %{
6407 predicate(UseAPX);
6408 match(Set dst (CMoveI (Binary cop cr) (Binary src1 (LoadI src2))));
6409
6410 ins_cost(250);
6411 format %{ "ecmovl$cop $dst, $src1, $src2\t# unsigned, int ndd" %}
6412 ins_encode %{
6413 __ ecmovl((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src1$$Register, $src2$$Address);
6414 %}
6415 ins_pipe(pipe_cmov_mem);
6416 %}
6417
6418 instruct cmovI_rReg_rReg_memUCF_ndd(rRegI dst, cmpOpUCF cop, rFlagsRegUCF cr, rRegI src1, memory src2)
6419 %{
6420 predicate(UseAPX);
6421 match(Set dst (CMoveI (Binary cop cr) (Binary src1 (LoadI src2))));
6422 ins_cost(250);
6423 format %{ "ecmovl$cop $dst, $src1, $src2\t# unsigned, int ndd" %}
6424 ins_encode %{
6425 __ ecmovl((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src1$$Register, $src2$$Address);
6426 %}
6427 ins_pipe(pipe_cmov_mem);
6428 %}
6429
6430 // Conditional move
6431 instruct cmovN_reg(rRegN dst, rRegN src, rFlagsReg cr, cmpOp cop)
6432 %{
6433 predicate(!UseAPX);
6434 match(Set dst (CMoveN (Binary cop cr) (Binary dst src)));
6435
6436 ins_cost(200); // XXX
6437 format %{ "cmovl$cop $dst, $src\t# signed, compressed ptr" %}
6438 ins_encode %{
6439 __ cmovl((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src$$Register);
6440 %}
6441 ins_pipe(pipe_cmov_reg);
6442 %}
6443
6444 // Conditional move ndd
6445 instruct cmovN_reg_ndd(rRegN dst, rRegN src1, rRegN src2, rFlagsReg cr, cmpOp cop)
6446 %{
6447 predicate(UseAPX);
6448 match(Set dst (CMoveN (Binary cop cr) (Binary src1 src2)));
6449
6450 ins_cost(200);
6451 format %{ "ecmovl$cop $dst, $src1, $src2\t# signed, compressed ptr ndd" %}
6452 ins_encode %{
6453 __ ecmovl((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src1$$Register, $src2$$Register);
6454 %}
6455 ins_pipe(pipe_cmov_reg);
6456 %}
6457
6458 // Conditional move
6459 instruct cmovN_regU(cmpOpU cop, rFlagsRegU cr, rRegN dst, rRegN src)
6460 %{
6461 predicate(!UseAPX);
6462 match(Set dst (CMoveN (Binary cop cr) (Binary dst src)));
6463
6464 ins_cost(200); // XXX
6465 format %{ "cmovl$cop $dst, $src\t# unsigned, compressed ptr" %}
6466 ins_encode %{
6467 __ cmovl((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src$$Register);
6468 %}
6469 ins_pipe(pipe_cmov_reg);
6470 %}
6471
6472 instruct cmovN_regUCF(cmpOpUCF cop, rFlagsRegUCF cr, rRegN dst, rRegN src) %{
6473 predicate(!UseAPX);
6474 match(Set dst (CMoveN (Binary cop cr) (Binary dst src)));
6475 ins_cost(200);
6476 expand %{
6477 cmovN_regU(cop, cr, dst, src);
6478 %}
6479 %}
6480
6481 // Conditional move ndd
6482 instruct cmovN_regU_ndd(rRegN dst, cmpOpU cop, rFlagsRegU cr, rRegN src1, rRegN src2)
6483 %{
6484 predicate(UseAPX);
6485 match(Set dst (CMoveN (Binary cop cr) (Binary src1 src2)));
6486
6487 ins_cost(200);
6488 format %{ "ecmovl$cop $dst, $src1, $src2\t# unsigned, compressed ptr ndd" %}
6489 ins_encode %{
6490 __ ecmovl((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src1$$Register, $src2$$Register);
6491 %}
6492 ins_pipe(pipe_cmov_reg);
6493 %}
6494
6495 instruct cmovN_regUCF_ndd(rRegN dst, cmpOpUCF cop, rFlagsRegUCF cr, rRegN src1, rRegN src2) %{
6496 predicate(UseAPX);
6497 match(Set dst (CMoveN (Binary cop cr) (Binary src1 src2)));
6498 ins_cost(200);
6499 format %{ "ecmovl$cop $dst, $src1, $src2\t# unsigned, compressed ptr ndd" %}
6500 ins_encode %{
6501 __ ecmovl((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src1$$Register, $src2$$Register);
6502 %}
6503 ins_pipe(pipe_cmov_reg);
6504 %}
6505
6506 instruct cmovN_regUCF2_ne(cmpOpUCF2 cop, rFlagsRegUCF cr, rRegN dst, rRegN src) %{
6507 predicate(n->in(1)->in(1)->as_Bool()->_test._test == BoolTest::ne);
6508 match(Set dst (CMoveN (Binary cop cr) (Binary dst src)));
6509
6510 ins_cost(200); // XXX
6511 format %{ "cmovpl $dst, $src\n\t"
6512 "cmovnel $dst, $src" %}
6513 ins_encode %{
6514 __ cmovl(Assembler::parity, $dst$$Register, $src$$Register);
6515 __ cmovl(Assembler::notEqual, $dst$$Register, $src$$Register);
6516 %}
6517 ins_pipe(pipe_cmov_reg);
6518 %}
6519
6520 // Since (x == y) == !(x != y), we can flip the sense of the test by flipping the
6521 // inputs of the CMove
6522 instruct cmovN_regUCF2_eq(cmpOpUCF2 cop, rFlagsRegUCF cr, rRegN dst, rRegN src) %{
6523 predicate(n->in(1)->in(1)->as_Bool()->_test._test == BoolTest::eq);
6524 match(Set dst (CMoveN (Binary cop cr) (Binary src dst)));
6525
6526 ins_cost(200); // XXX
6527 format %{ "cmovpl $dst, $src\n\t"
6528 "cmovnel $dst, $src" %}
6529 ins_encode %{
6530 __ cmovl(Assembler::parity, $dst$$Register, $src$$Register);
6531 __ cmovl(Assembler::notEqual, $dst$$Register, $src$$Register);
6532 %}
6533 ins_pipe(pipe_cmov_reg);
6534 %}
6535
6536 // Conditional move
6537 instruct cmovP_reg(rRegP dst, rRegP src, rFlagsReg cr, cmpOp cop)
6538 %{
6539 predicate(!UseAPX);
6540 match(Set dst (CMoveP (Binary cop cr) (Binary dst src)));
6541
6542 ins_cost(200); // XXX
6543 format %{ "cmovq$cop $dst, $src\t# signed, ptr" %}
6544 ins_encode %{
6545 __ cmovq((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src$$Register);
6546 %}
6547 ins_pipe(pipe_cmov_reg); // XXX
6548 %}
6549
6550 // Conditional move ndd
6551 instruct cmovP_reg_ndd(rRegP dst, rRegP src1, rRegP src2, rFlagsReg cr, cmpOp cop)
6552 %{
6553 predicate(UseAPX);
6554 match(Set dst (CMoveP (Binary cop cr) (Binary src1 src2)));
6555
6556 ins_cost(200);
6557 format %{ "ecmovq$cop $dst, $src1, $src2\t# signed, ptr ndd" %}
6558 ins_encode %{
6559 __ ecmovq((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src1$$Register, $src2$$Register);
6560 %}
6561 ins_pipe(pipe_cmov_reg);
6562 %}
6563
6564 // Conditional move
6565 instruct cmovP_regU(cmpOpU cop, rFlagsRegU cr, rRegP dst, rRegP src)
6566 %{
6567 predicate(!UseAPX);
6568 match(Set dst (CMoveP (Binary cop cr) (Binary dst src)));
6569
6570 ins_cost(200); // XXX
6571 format %{ "cmovq$cop $dst, $src\t# unsigned, ptr" %}
6572 ins_encode %{
6573 __ cmovq((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src$$Register);
6574 %}
6575 ins_pipe(pipe_cmov_reg); // XXX
6576 %}
6577
6578 // Conditional move ndd
6579 instruct cmovP_regU_ndd(rRegP dst, cmpOpU cop, rFlagsRegU cr, rRegP src1, rRegP src2)
6580 %{
6581 predicate(UseAPX);
6582 match(Set dst (CMoveP (Binary cop cr) (Binary src1 src2)));
6583
6584 ins_cost(200);
6585 format %{ "ecmovq$cop $dst, $src1, $src2\t# unsigned, ptr ndd" %}
6586 ins_encode %{
6587 __ ecmovq((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src1$$Register, $src2$$Register);
6588 %}
6589 ins_pipe(pipe_cmov_reg);
6590 %}
6591
6592 instruct cmovP_regUCF(cmpOpUCF cop, rFlagsRegUCF cr, rRegP dst, rRegP src) %{
6593 predicate(!UseAPX);
6594 match(Set dst (CMoveP (Binary cop cr) (Binary dst src)));
6595 ins_cost(200);
6596 expand %{
6597 cmovP_regU(cop, cr, dst, src);
6598 %}
6599 %}
6600
6601 instruct cmovP_regUCF_ndd(rRegP dst, cmpOpUCF cop, rFlagsRegUCF cr, rRegP src1, rRegP src2) %{
6602 predicate(UseAPX);
6603 match(Set dst (CMoveP (Binary cop cr) (Binary src1 src2)));
6604 ins_cost(200);
6605 format %{ "ecmovq$cop $dst, $src1, $src2\t# unsigned, ptr ndd" %}
6606 ins_encode %{
6607 __ ecmovq((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src1$$Register, $src2$$Register);
6608 %}
6609 ins_pipe(pipe_cmov_reg);
6610 %}
6611
6612 instruct cmovP_regUCF2_ne(cmpOpUCF2 cop, rFlagsRegUCF cr, rRegP dst, rRegP src) %{
6613 predicate(!UseAPX && n->in(1)->in(1)->as_Bool()->_test._test == BoolTest::ne);
6614 match(Set dst (CMoveP (Binary cop cr) (Binary dst src)));
6615
6616 ins_cost(200); // XXX
6617 format %{ "cmovpq $dst, $src\n\t"
6618 "cmovneq $dst, $src" %}
6619 ins_encode %{
6620 __ cmovq(Assembler::parity, $dst$$Register, $src$$Register);
6621 __ cmovq(Assembler::notEqual, $dst$$Register, $src$$Register);
6622 %}
6623 ins_pipe(pipe_cmov_reg);
6624 %}
6625
6626 instruct cmovP_regUCF2_ne_ndd(cmpOpUCF2 cop, rFlagsRegUCF cr, rRegP dst, rRegP src1, rRegP src2) %{
6627 predicate(UseAPX && n->in(1)->in(1)->as_Bool()->_test._test == BoolTest::ne);
6628 match(Set dst (CMoveP (Binary cop cr) (Binary src1 src2)));
6629 effect(TEMP dst);
6630
6631 ins_cost(200);
6632 format %{ "ecmovpq $dst, $src1, $src2\n\t"
6633 "cmovneq $dst, $src2" %}
6634 ins_encode %{
6635 __ ecmovq(Assembler::parity, $dst$$Register, $src1$$Register, $src2$$Register);
6636 __ cmovq(Assembler::notEqual, $dst$$Register, $src2$$Register);
6637 %}
6638 ins_pipe(pipe_cmov_reg);
6639 %}
6640
6641 // Since (x == y) == !(x != y), we can flip the sense of the test by flipping the
6642 // inputs of the CMove
6643 instruct cmovP_regUCF2_eq(cmpOpUCF2 cop, rFlagsRegUCF cr, rRegP dst, rRegP src) %{
6644 predicate(!UseAPX && n->in(1)->in(1)->as_Bool()->_test._test == BoolTest::eq);
6645 match(Set dst (CMoveP (Binary cop cr) (Binary src dst)));
6646
6647 ins_cost(200); // XXX
6648 format %{ "cmovpq $dst, $src\n\t"
6649 "cmovneq $dst, $src" %}
6650 ins_encode %{
6651 __ cmovq(Assembler::parity, $dst$$Register, $src$$Register);
6652 __ cmovq(Assembler::notEqual, $dst$$Register, $src$$Register);
6653 %}
6654 ins_pipe(pipe_cmov_reg);
6655 %}
6656
6657 instruct cmovP_regUCF2_eq_ndd(cmpOpUCF2 cop, rFlagsRegUCF cr, rRegP dst, rRegP src1, rRegP src2) %{
6658 predicate(UseAPX && n->in(1)->in(1)->as_Bool()->_test._test == BoolTest::eq);
6659 match(Set dst (CMoveP (Binary cop cr) (Binary src2 src1)));
6660 effect(TEMP dst);
6661
6662 ins_cost(200);
6663 format %{ "ecmovpq $dst, $src1, $src2\n\t"
6664 "cmovneq $dst, $src2" %}
6665 ins_encode %{
6666 __ ecmovq(Assembler::parity, $dst$$Register, $src1$$Register, $src2$$Register);
6667 __ cmovq(Assembler::notEqual, $dst$$Register, $src2$$Register);
6668 %}
6669 ins_pipe(pipe_cmov_reg);
6670 %}
6671
6672 instruct cmovL_imm_01(rRegL dst, immL1 src, rFlagsReg cr, cmpOp cop)
6673 %{
6674 predicate(n->in(2)->in(2)->is_Con() && n->in(2)->in(2)->get_long() == 0);
6675 match(Set dst (CMoveL (Binary cop cr) (Binary src dst)));
6676
6677 ins_cost(100); // XXX
6678 format %{ "setbn$cop $dst\t# signed, long" %}
6679 ins_encode %{
6680 Assembler::Condition cond = (Assembler::Condition)($cop$$cmpcode);
6681 __ setb(MacroAssembler::negate_condition(cond), $dst$$Register);
6682 %}
6683 ins_pipe(ialu_reg);
6684 %}
6685
6686 instruct cmovL_reg(cmpOp cop, rFlagsReg cr, rRegL dst, rRegL src)
6687 %{
6688 predicate(!UseAPX);
6689 match(Set dst (CMoveL (Binary cop cr) (Binary dst src)));
6690
6691 ins_cost(200); // XXX
6692 format %{ "cmovq$cop $dst, $src\t# signed, long" %}
6693 ins_encode %{
6694 __ cmovq((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src$$Register);
6695 %}
6696 ins_pipe(pipe_cmov_reg); // XXX
6697 %}
6698
6699 instruct cmovL_reg_ndd(rRegL dst, cmpOp cop, rFlagsReg cr, rRegL src1, rRegL src2)
6700 %{
6701 predicate(UseAPX);
6702 match(Set dst (CMoveL (Binary cop cr) (Binary src1 src2)));
6703
6704 ins_cost(200);
6705 format %{ "ecmovq$cop $dst, $src1, $src2\t# signed, long ndd" %}
6706 ins_encode %{
6707 __ ecmovq((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src1$$Register, $src2$$Register);
6708 %}
6709 ins_pipe(pipe_cmov_reg);
6710 %}
6711
6712 instruct cmovL_mem(cmpOp cop, rFlagsReg cr, rRegL dst, memory src)
6713 %{
6714 predicate(!UseAPX);
6715 match(Set dst (CMoveL (Binary cop cr) (Binary dst (LoadL src))));
6716
6717 ins_cost(200); // XXX
6718 format %{ "cmovq$cop $dst, $src\t# signed, long" %}
6719 ins_encode %{
6720 __ cmovq((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src$$Address);
6721 %}
6722 ins_pipe(pipe_cmov_mem); // XXX
6723 %}
6724
6725 instruct cmovL_rReg_rReg_mem_ndd(rRegL dst, cmpOp cop, rFlagsReg cr, rRegL src1, memory src2)
6726 %{
6727 predicate(UseAPX);
6728 match(Set dst (CMoveL (Binary cop cr) (Binary src1 (LoadL src2))));
6729
6730 ins_cost(200);
6731 format %{ "ecmovq$cop $dst, $src1, $src2\t# signed, long ndd" %}
6732 ins_encode %{
6733 __ ecmovq((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src1$$Register, $src2$$Address);
6734 %}
6735 ins_pipe(pipe_cmov_mem);
6736 %}
6737
6738 instruct cmovL_imm_01U(rRegL dst, immL1 src, rFlagsRegU cr, cmpOpU cop)
6739 %{
6740 predicate(n->in(2)->in(2)->is_Con() && n->in(2)->in(2)->get_long() == 0);
6741 match(Set dst (CMoveL (Binary cop cr) (Binary src dst)));
6742
6743 ins_cost(100); // XXX
6744 format %{ "setbn$cop $dst\t# unsigned, long" %}
6745 ins_encode %{
6746 Assembler::Condition cond = (Assembler::Condition)($cop$$cmpcode);
6747 __ setb(MacroAssembler::negate_condition(cond), $dst$$Register);
6748 %}
6749 ins_pipe(ialu_reg);
6750 %}
6751
6752 instruct cmovL_regU(cmpOpU cop, rFlagsRegU cr, rRegL dst, rRegL src)
6753 %{
6754 predicate(!UseAPX);
6755 match(Set dst (CMoveL (Binary cop cr) (Binary dst src)));
6756
6757 ins_cost(200); // XXX
6758 format %{ "cmovq$cop $dst, $src\t# unsigned, long" %}
6759 ins_encode %{
6760 __ cmovq((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src$$Register);
6761 %}
6762 ins_pipe(pipe_cmov_reg); // XXX
6763 %}
6764
6765 instruct cmovL_regU_ndd(rRegL dst, cmpOpU cop, rFlagsRegU cr, rRegL src1, rRegL src2)
6766 %{
6767 predicate(UseAPX);
6768 match(Set dst (CMoveL (Binary cop cr) (Binary src1 src2)));
6769
6770 ins_cost(200);
6771 format %{ "ecmovq$cop $dst, $src1, $src2\t# unsigned, long ndd" %}
6772 ins_encode %{
6773 __ ecmovq((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src1$$Register, $src2$$Register);
6774 %}
6775 ins_pipe(pipe_cmov_reg);
6776 %}
6777
6778 instruct cmovL_imm_01UCF(rRegL dst, immL1 src, rFlagsRegUCF cr, cmpOpUCF cop)
6779 %{
6780 predicate(n->in(2)->in(2)->is_Con() && n->in(2)->in(2)->get_long() == 0);
6781 match(Set dst (CMoveL (Binary cop cr) (Binary src dst)));
6782
6783 ins_cost(100); // XXX
6784 format %{ "setbn$cop $dst\t# unsigned, long" %}
6785 ins_encode %{
6786 Assembler::Condition cond = (Assembler::Condition)($cop$$cmpcode);
6787 __ setb(MacroAssembler::negate_condition(cond), $dst$$Register);
6788 %}
6789 ins_pipe(ialu_reg);
6790 %}
6791
6792 instruct cmovL_regUCF(cmpOpUCF cop, rFlagsRegUCF cr, rRegL dst, rRegL src) %{
6793 predicate(!UseAPX);
6794 match(Set dst (CMoveL (Binary cop cr) (Binary dst src)));
6795 ins_cost(200);
6796 expand %{
6797 cmovL_regU(cop, cr, dst, src);
6798 %}
6799 %}
6800
6801 instruct cmovL_regUCF_ndd(rRegL dst, cmpOpUCF cop, rFlagsRegUCF cr, rRegL src1, rRegL src2)
6802 %{
6803 predicate(UseAPX);
6804 match(Set dst (CMoveL (Binary cop cr) (Binary src1 src2)));
6805 ins_cost(200);
6806 format %{ "ecmovq$cop $dst, $src1, $src2\t# unsigned, long ndd" %}
6807 ins_encode %{
6808 __ ecmovq((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src1$$Register, $src2$$Register);
6809 %}
6810 ins_pipe(pipe_cmov_reg);
6811 %}
6812
6813 instruct cmovL_regUCF2_ne(cmpOpUCF2 cop, rFlagsRegUCF cr, rRegL dst, rRegL src) %{
6814 predicate(!UseAPX && n->in(1)->in(1)->as_Bool()->_test._test == BoolTest::ne);
6815 match(Set dst (CMoveL (Binary cop cr) (Binary dst src)));
6816
6817 ins_cost(200); // XXX
6818 format %{ "cmovpq $dst, $src\n\t"
6819 "cmovneq $dst, $src" %}
6820 ins_encode %{
6821 __ cmovq(Assembler::parity, $dst$$Register, $src$$Register);
6822 __ cmovq(Assembler::notEqual, $dst$$Register, $src$$Register);
6823 %}
6824 ins_pipe(pipe_cmov_reg);
6825 %}
6826
6827 instruct cmovL_regUCF2_ne_ndd(cmpOpUCF2 cop, rFlagsRegUCF cr, rRegL dst, rRegL src1, rRegL src2) %{
6828 predicate(UseAPX && n->in(1)->in(1)->as_Bool()->_test._test == BoolTest::ne);
6829 match(Set dst (CMoveL (Binary cop cr) (Binary src1 src2)));
6830 effect(TEMP dst);
6831
6832 ins_cost(200);
6833 format %{ "ecmovpq $dst, $src1, $src2\n\t"
6834 "cmovneq $dst, $src2" %}
6835 ins_encode %{
6836 __ ecmovq(Assembler::parity, $dst$$Register, $src1$$Register, $src2$$Register);
6837 __ cmovq(Assembler::notEqual, $dst$$Register, $src2$$Register);
6838 %}
6839 ins_pipe(pipe_cmov_reg);
6840 %}
6841
6842 // Since (x == y) == !(x != y), we can flip the sense of the test by flipping the
6843 // inputs of the CMove
6844 instruct cmovL_regUCF2_eq(cmpOpUCF2 cop, rFlagsRegUCF cr, rRegL dst, rRegL src) %{
6845 predicate(!UseAPX && n->in(1)->in(1)->as_Bool()->_test._test == BoolTest::eq);
6846 match(Set dst (CMoveL (Binary cop cr) (Binary src dst)));
6847
6848 ins_cost(200); // XXX
6849 format %{ "cmovpq $dst, $src\n\t"
6850 "cmovneq $dst, $src" %}
6851 ins_encode %{
6852 __ cmovq(Assembler::parity, $dst$$Register, $src$$Register);
6853 __ cmovq(Assembler::notEqual, $dst$$Register, $src$$Register);
6854 %}
6855 ins_pipe(pipe_cmov_reg);
6856 %}
6857
6858 instruct cmovL_regUCF2_eq_ndd(cmpOpUCF2 cop, rFlagsRegUCF cr, rRegL dst, rRegL src1, rRegL src2) %{
6859 predicate(UseAPX && n->in(1)->in(1)->as_Bool()->_test._test == BoolTest::eq);
6860 match(Set dst (CMoveL (Binary cop cr) (Binary src2 src1)));
6861 effect(TEMP dst);
6862
6863 ins_cost(200);
6864 format %{ "ecmovpq $dst, $src1, $src2\n\t"
6865 "cmovneq $dst, $src2" %}
6866 ins_encode %{
6867 __ ecmovq(Assembler::parity, $dst$$Register, $src1$$Register, $src2$$Register);
6868 __ cmovq(Assembler::notEqual, $dst$$Register, $src2$$Register);
6869 %}
6870 ins_pipe(pipe_cmov_reg);
6871 %}
6872
6873 instruct cmovL_memU(cmpOpU cop, rFlagsRegU cr, rRegL dst, memory src)
6874 %{
6875 predicate(!UseAPX);
6876 match(Set dst (CMoveL (Binary cop cr) (Binary dst (LoadL src))));
6877
6878 ins_cost(200); // XXX
6879 format %{ "cmovq$cop $dst, $src\t# unsigned, long" %}
6880 ins_encode %{
6881 __ cmovq((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src$$Address);
6882 %}
6883 ins_pipe(pipe_cmov_mem); // XXX
6884 %}
6885
6886 instruct cmovL_memUCF(cmpOpUCF cop, rFlagsRegUCF cr, rRegL dst, memory src) %{
6887 predicate(!UseAPX);
6888 match(Set dst (CMoveL (Binary cop cr) (Binary dst (LoadL src))));
6889 ins_cost(200);
6890 expand %{
6891 cmovL_memU(cop, cr, dst, src);
6892 %}
6893 %}
6894
6895 instruct cmovL_rReg_rReg_memU_ndd(rRegL dst, cmpOpU cop, rFlagsRegU cr, rRegL src1, memory src2)
6896 %{
6897 predicate(UseAPX);
6898 match(Set dst (CMoveL (Binary cop cr) (Binary src1 (LoadL src2))));
6899
6900 ins_cost(200);
6901 format %{ "ecmovq$cop $dst, $src1, $src2\t# unsigned, long ndd" %}
6902 ins_encode %{
6903 __ ecmovq((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src1$$Register, $src2$$Address);
6904 %}
6905 ins_pipe(pipe_cmov_mem);
6906 %}
6907
6908 instruct cmovL_rReg_rReg_memUCF_ndd(rRegL dst, cmpOpUCF cop, rFlagsRegUCF cr, rRegL src1, memory src2)
6909 %{
6910 predicate(UseAPX);
6911 match(Set dst (CMoveL (Binary cop cr) (Binary src1 (LoadL src2))));
6912 ins_cost(200);
6913 format %{ "ecmovq$cop $dst, $src1, $src2\t# unsigned, long ndd" %}
6914 ins_encode %{
6915 __ ecmovq((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src1$$Register, $src2$$Address);
6916 %}
6917 ins_pipe(pipe_cmov_mem);
6918 %}
6919
6920 instruct cmovF_reg(cmpOp cop, rFlagsReg cr, regF dst, regF src)
6921 %{
6922 match(Set dst (CMoveF (Binary cop cr) (Binary dst src)));
6923
6924 ins_cost(200); // XXX
6925 format %{ "jn$cop skip\t# signed cmove float\n\t"
6926 "movss $dst, $src\n"
6927 "skip:" %}
6928 ins_encode %{
6929 Label Lskip;
6930 // Invert sense of branch from sense of CMOV
6931 __ jccb((Assembler::Condition)($cop$$cmpcode^1), Lskip);
6932 __ movflt($dst$$XMMRegister, $src$$XMMRegister);
6933 __ bind(Lskip);
6934 %}
6935 ins_pipe(pipe_slow);
6936 %}
6937
6938 instruct cmovF_regU(cmpOpU cop, rFlagsRegU cr, regF dst, regF src)
6939 %{
6940 match(Set dst (CMoveF (Binary cop cr) (Binary dst src)));
6941
6942 ins_cost(200); // XXX
6943 format %{ "jn$cop skip\t# unsigned cmove float\n\t"
6944 "movss $dst, $src\n"
6945 "skip:" %}
6946 ins_encode %{
6947 Label Lskip;
6948 // Invert sense of branch from sense of CMOV
6949 __ jccb((Assembler::Condition)($cop$$cmpcode^1), Lskip);
6950 __ movflt($dst$$XMMRegister, $src$$XMMRegister);
6951 __ bind(Lskip);
6952 %}
6953 ins_pipe(pipe_slow);
6954 %}
6955
6956 instruct cmovF_regUCF(cmpOpUCF cop, rFlagsRegUCF cr, regF dst, regF src) %{
6957 match(Set dst (CMoveF (Binary cop cr) (Binary dst src)));
6958 ins_cost(200);
6959 expand %{
6960 cmovF_regU(cop, cr, dst, src);
6961 %}
6962 %}
6963
6964 instruct cmovD_reg(cmpOp cop, rFlagsReg cr, regD dst, regD src)
6965 %{
6966 match(Set dst (CMoveD (Binary cop cr) (Binary dst src)));
6967
6968 ins_cost(200); // XXX
6969 format %{ "jn$cop skip\t# signed cmove double\n\t"
6970 "movsd $dst, $src\n"
6971 "skip:" %}
6972 ins_encode %{
6973 Label Lskip;
6974 // Invert sense of branch from sense of CMOV
6975 __ jccb((Assembler::Condition)($cop$$cmpcode^1), Lskip);
6976 __ movdbl($dst$$XMMRegister, $src$$XMMRegister);
6977 __ bind(Lskip);
6978 %}
6979 ins_pipe(pipe_slow);
6980 %}
6981
6982 instruct cmovD_regU(cmpOpU cop, rFlagsRegU cr, regD dst, regD src)
6983 %{
6984 match(Set dst (CMoveD (Binary cop cr) (Binary dst src)));
6985
6986 ins_cost(200); // XXX
6987 format %{ "jn$cop skip\t# unsigned cmove double\n\t"
6988 "movsd $dst, $src\n"
6989 "skip:" %}
6990 ins_encode %{
6991 Label Lskip;
6992 // Invert sense of branch from sense of CMOV
6993 __ jccb((Assembler::Condition)($cop$$cmpcode^1), Lskip);
6994 __ movdbl($dst$$XMMRegister, $src$$XMMRegister);
6995 __ bind(Lskip);
6996 %}
6997 ins_pipe(pipe_slow);
6998 %}
6999
7000 instruct cmovD_regUCF(cmpOpUCF cop, rFlagsRegUCF cr, regD dst, regD src) %{
7001 match(Set dst (CMoveD (Binary cop cr) (Binary dst src)));
7002 ins_cost(200);
7003 expand %{
7004 cmovD_regU(cop, cr, dst, src);
7005 %}
7006 %}
7007
7008 //----------Arithmetic Instructions--------------------------------------------
7009 //----------Addition Instructions----------------------------------------------
7010
7011 instruct addI_rReg(rRegI dst, rRegI src, rFlagsReg cr)
7012 %{
7013 predicate(!UseAPX);
7014 match(Set dst (AddI dst src));
7015 effect(KILL cr);
7016 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);
7017 format %{ "addl $dst, $src\t# int" %}
7018 ins_encode %{
7019 __ addl($dst$$Register, $src$$Register);
7020 %}
7021 ins_pipe(ialu_reg_reg);
7022 %}
7023
7024 instruct addI_rReg_ndd(rRegI dst, rRegI src1, rRegI src2, rFlagsReg cr)
7025 %{
7026 predicate(UseAPX);
7027 match(Set dst (AddI src1 src2));
7028 effect(KILL cr);
7029 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);
7030
7031 format %{ "eaddl $dst, $src1, $src2\t# int ndd" %}
7032 ins_encode %{
7033 __ eaddl($dst$$Register, $src1$$Register, $src2$$Register, false);
7034 %}
7035 ins_pipe(ialu_reg_reg);
7036 %}
7037
7038 instruct addI_rReg_imm(rRegI dst, immI src, rFlagsReg cr)
7039 %{
7040 predicate(!UseAPX);
7041 match(Set dst (AddI dst src));
7042 effect(KILL cr);
7043 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);
7044
7045 format %{ "addl $dst, $src\t# int" %}
7046 ins_encode %{
7047 __ addl($dst$$Register, $src$$constant);
7048 %}
7049 ins_pipe( ialu_reg );
7050 %}
7051
7052 instruct addI_rReg_rReg_imm_ndd(rRegI dst, rRegI src1, immI src2, rFlagsReg cr)
7053 %{
7054 predicate(UseAPX);
7055 match(Set dst (AddI src1 src2));
7056 effect(KILL cr);
7057 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);
7058
7059 format %{ "eaddl $dst, $src1, $src2\t# int ndd" %}
7060 ins_encode %{
7061 __ eaddl($dst$$Register, $src1$$Register, $src2$$constant, false);
7062 %}
7063 ins_pipe( ialu_reg );
7064 %}
7065
7066 instruct addI_rReg_mem_imm_ndd(rRegI dst, memory src1, immI src2, rFlagsReg cr)
7067 %{
7068 predicate(UseAPX);
7069 match(Set dst (AddI (LoadI src1) src2));
7070 effect(KILL cr);
7071 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);
7072
7073 format %{ "eaddl $dst, $src1, $src2\t# int ndd" %}
7074 ins_encode %{
7075 __ eaddl($dst$$Register, $src1$$Address, $src2$$constant, false);
7076 %}
7077 ins_pipe( ialu_reg );
7078 %}
7079
7080 instruct addI_rReg_mem(rRegI dst, memory src, rFlagsReg cr)
7081 %{
7082 predicate(!UseAPX);
7083 match(Set dst (AddI dst (LoadI src)));
7084 effect(KILL cr);
7085 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);
7086
7087 ins_cost(150); // XXX
7088 format %{ "addl $dst, $src\t# int" %}
7089 ins_encode %{
7090 __ addl($dst$$Register, $src$$Address);
7091 %}
7092 ins_pipe(ialu_reg_mem);
7093 %}
7094
7095 instruct addI_rReg_rReg_mem_ndd(rRegI dst, rRegI src1, memory src2, rFlagsReg cr)
7096 %{
7097 predicate(UseAPX);
7098 match(Set dst (AddI src1 (LoadI src2)));
7099 effect(KILL cr);
7100 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);
7101
7102 ins_cost(150);
7103 format %{ "eaddl $dst, $src1, $src2\t# int ndd" %}
7104 ins_encode %{
7105 __ eaddl($dst$$Register, $src1$$Register, $src2$$Address, false);
7106 %}
7107 ins_pipe(ialu_reg_mem);
7108 %}
7109
7110 instruct addI_mem_rReg(memory dst, rRegI src, rFlagsReg cr)
7111 %{
7112 match(Set dst (StoreI dst (AddI (LoadI dst) src)));
7113 effect(KILL cr);
7114 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);
7115
7116 ins_cost(150); // XXX
7117 format %{ "addl $dst, $src\t# int" %}
7118 ins_encode %{
7119 __ addl($dst$$Address, $src$$Register);
7120 %}
7121 ins_pipe(ialu_mem_reg);
7122 %}
7123
7124 instruct addI_mem_imm(memory dst, immI src, rFlagsReg cr)
7125 %{
7126 match(Set dst (StoreI dst (AddI (LoadI dst) src)));
7127 effect(KILL cr);
7128 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);
7129
7130
7131 ins_cost(125); // XXX
7132 format %{ "addl $dst, $src\t# int" %}
7133 ins_encode %{
7134 __ addl($dst$$Address, $src$$constant);
7135 %}
7136 ins_pipe(ialu_mem_imm);
7137 %}
7138
7139 instruct incI_rReg(rRegI dst, immI_1 src, rFlagsReg cr)
7140 %{
7141 predicate(!UseAPX && UseIncDec);
7142 match(Set dst (AddI dst src));
7143 effect(KILL cr);
7144
7145 format %{ "incl $dst\t# int" %}
7146 ins_encode %{
7147 __ incrementl($dst$$Register);
7148 %}
7149 ins_pipe(ialu_reg);
7150 %}
7151
7152 instruct incI_rReg_ndd(rRegI dst, rRegI src, immI_1 val, rFlagsReg cr)
7153 %{
7154 predicate(UseAPX && UseIncDec);
7155 match(Set dst (AddI src val));
7156 effect(KILL cr);
7157
7158 format %{ "eincl $dst, $src\t# int ndd" %}
7159 ins_encode %{
7160 __ eincl($dst$$Register, $src$$Register, false);
7161 %}
7162 ins_pipe(ialu_reg);
7163 %}
7164
7165 instruct incI_rReg_mem_ndd(rRegI dst, memory src, immI_1 val, rFlagsReg cr)
7166 %{
7167 predicate(UseAPX && UseIncDec);
7168 match(Set dst (AddI (LoadI src) val));
7169 effect(KILL cr);
7170
7171 format %{ "eincl $dst, $src\t# int ndd" %}
7172 ins_encode %{
7173 __ eincl($dst$$Register, $src$$Address, false);
7174 %}
7175 ins_pipe(ialu_reg);
7176 %}
7177
7178 instruct incI_mem(memory dst, immI_1 src, rFlagsReg cr)
7179 %{
7180 predicate(UseIncDec);
7181 match(Set dst (StoreI dst (AddI (LoadI dst) src)));
7182 effect(KILL cr);
7183
7184 ins_cost(125); // XXX
7185 format %{ "incl $dst\t# int" %}
7186 ins_encode %{
7187 __ incrementl($dst$$Address);
7188 %}
7189 ins_pipe(ialu_mem_imm);
7190 %}
7191
7192 // XXX why does that use AddI
7193 instruct decI_rReg(rRegI dst, immI_M1 src, rFlagsReg cr)
7194 %{
7195 predicate(!UseAPX && UseIncDec);
7196 match(Set dst (AddI dst src));
7197 effect(KILL cr);
7198
7199 format %{ "decl $dst\t# int" %}
7200 ins_encode %{
7201 __ decrementl($dst$$Register);
7202 %}
7203 ins_pipe(ialu_reg);
7204 %}
7205
7206 instruct decI_rReg_ndd(rRegI dst, rRegI src, immI_M1 val, rFlagsReg cr)
7207 %{
7208 predicate(UseAPX && UseIncDec);
7209 match(Set dst (AddI src val));
7210 effect(KILL cr);
7211
7212 format %{ "edecl $dst, $src\t# int ndd" %}
7213 ins_encode %{
7214 __ edecl($dst$$Register, $src$$Register, false);
7215 %}
7216 ins_pipe(ialu_reg);
7217 %}
7218
7219 instruct decI_rReg_mem_ndd(rRegI dst, memory src, immI_M1 val, rFlagsReg cr)
7220 %{
7221 predicate(UseAPX && UseIncDec);
7222 match(Set dst (AddI (LoadI src) val));
7223 effect(KILL cr);
7224
7225 format %{ "edecl $dst, $src\t# int ndd" %}
7226 ins_encode %{
7227 __ edecl($dst$$Register, $src$$Address, false);
7228 %}
7229 ins_pipe(ialu_reg);
7230 %}
7231
7232 // XXX why does that use AddI
7233 instruct decI_mem(memory dst, immI_M1 src, rFlagsReg cr)
7234 %{
7235 predicate(UseIncDec);
7236 match(Set dst (StoreI dst (AddI (LoadI dst) src)));
7237 effect(KILL cr);
7238
7239 ins_cost(125); // XXX
7240 format %{ "decl $dst\t# int" %}
7241 ins_encode %{
7242 __ decrementl($dst$$Address);
7243 %}
7244 ins_pipe(ialu_mem_imm);
7245 %}
7246
7247 instruct leaI_rReg_immI2_immI(rRegI dst, rRegI index, immI2 scale, immI disp)
7248 %{
7249 predicate(VM_Version::supports_fast_2op_lea());
7250 match(Set dst (AddI (LShiftI index scale) disp));
7251
7252 format %{ "leal $dst, [$index << $scale + $disp]\t# int" %}
7253 ins_encode %{
7254 Address::ScaleFactor scale = static_cast<Address::ScaleFactor>($scale$$constant);
7255 __ leal($dst$$Register, Address(noreg, $index$$Register, scale, $disp$$constant));
7256 %}
7257 ins_pipe(ialu_reg_reg);
7258 %}
7259
7260 instruct leaI_rReg_rReg_immI(rRegI dst, rRegI base, rRegI index, immI disp)
7261 %{
7262 predicate(VM_Version::supports_fast_3op_lea());
7263 match(Set dst (AddI (AddI base index) disp));
7264
7265 format %{ "leal $dst, [$base + $index + $disp]\t# int" %}
7266 ins_encode %{
7267 __ leal($dst$$Register, Address($base$$Register, $index$$Register, Address::times_1, $disp$$constant));
7268 %}
7269 ins_pipe(ialu_reg_reg);
7270 %}
7271
7272 instruct leaI_rReg_rReg_immI2(rRegI dst, no_rbp_r13_RegI base, rRegI index, immI2 scale)
7273 %{
7274 predicate(VM_Version::supports_fast_2op_lea());
7275 match(Set dst (AddI base (LShiftI index scale)));
7276
7277 format %{ "leal $dst, [$base + $index << $scale]\t# int" %}
7278 ins_encode %{
7279 Address::ScaleFactor scale = static_cast<Address::ScaleFactor>($scale$$constant);
7280 __ leal($dst$$Register, Address($base$$Register, $index$$Register, scale));
7281 %}
7282 ins_pipe(ialu_reg_reg);
7283 %}
7284
7285 instruct leaI_rReg_rReg_immI2_immI(rRegI dst, rRegI base, rRegI index, immI2 scale, immI disp)
7286 %{
7287 predicate(VM_Version::supports_fast_3op_lea());
7288 match(Set dst (AddI (AddI base (LShiftI index scale)) disp));
7289
7290 format %{ "leal $dst, [$base + $index << $scale + $disp]\t# int" %}
7291 ins_encode %{
7292 Address::ScaleFactor scale = static_cast<Address::ScaleFactor>($scale$$constant);
7293 __ leal($dst$$Register, Address($base$$Register, $index$$Register, scale, $disp$$constant));
7294 %}
7295 ins_pipe(ialu_reg_reg);
7296 %}
7297
7298 instruct addL_rReg(rRegL dst, rRegL src, rFlagsReg cr)
7299 %{
7300 predicate(!UseAPX);
7301 match(Set dst (AddL dst src));
7302 effect(KILL cr);
7303 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);
7304
7305 format %{ "addq $dst, $src\t# long" %}
7306 ins_encode %{
7307 __ addq($dst$$Register, $src$$Register);
7308 %}
7309 ins_pipe(ialu_reg_reg);
7310 %}
7311
7312 instruct addL_rReg_ndd(rRegL dst, rRegL src1, rRegL src2, rFlagsReg cr)
7313 %{
7314 predicate(UseAPX);
7315 match(Set dst (AddL src1 src2));
7316 effect(KILL cr);
7317 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);
7318
7319 format %{ "eaddq $dst, $src1, $src2\t# long ndd" %}
7320 ins_encode %{
7321 __ eaddq($dst$$Register, $src1$$Register, $src2$$Register, false);
7322 %}
7323 ins_pipe(ialu_reg_reg);
7324 %}
7325
7326 instruct addL_rReg_imm(rRegL dst, immL32 src, rFlagsReg cr)
7327 %{
7328 predicate(!UseAPX);
7329 match(Set dst (AddL dst src));
7330 effect(KILL cr);
7331 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);
7332
7333 format %{ "addq $dst, $src\t# long" %}
7334 ins_encode %{
7335 __ addq($dst$$Register, $src$$constant);
7336 %}
7337 ins_pipe( ialu_reg );
7338 %}
7339
7340 instruct addL_rReg_rReg_imm_ndd(rRegL dst, rRegL src1, immL32 src2, rFlagsReg cr)
7341 %{
7342 predicate(UseAPX);
7343 match(Set dst (AddL src1 src2));
7344 effect(KILL cr);
7345 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);
7346
7347 format %{ "eaddq $dst, $src1, $src2\t# long ndd" %}
7348 ins_encode %{
7349 __ eaddq($dst$$Register, $src1$$Register, $src2$$constant, false);
7350 %}
7351 ins_pipe( ialu_reg );
7352 %}
7353
7354 instruct addL_rReg_mem_imm_ndd(rRegL dst, memory src1, immL32 src2, rFlagsReg cr)
7355 %{
7356 predicate(UseAPX);
7357 match(Set dst (AddL (LoadL src1) src2));
7358 effect(KILL cr);
7359 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);
7360
7361 format %{ "eaddq $dst, $src1, $src2\t# long ndd" %}
7362 ins_encode %{
7363 __ eaddq($dst$$Register, $src1$$Address, $src2$$constant, false);
7364 %}
7365 ins_pipe( ialu_reg );
7366 %}
7367
7368 instruct addL_rReg_mem(rRegL dst, memory src, rFlagsReg cr)
7369 %{
7370 predicate(!UseAPX);
7371 match(Set dst (AddL dst (LoadL src)));
7372 effect(KILL cr);
7373 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);
7374
7375 ins_cost(150); // XXX
7376 format %{ "addq $dst, $src\t# long" %}
7377 ins_encode %{
7378 __ addq($dst$$Register, $src$$Address);
7379 %}
7380 ins_pipe(ialu_reg_mem);
7381 %}
7382
7383 instruct addL_rReg_rReg_mem_ndd(rRegL dst, rRegL src1, memory src2, rFlagsReg cr)
7384 %{
7385 predicate(UseAPX);
7386 match(Set dst (AddL src1 (LoadL src2)));
7387 effect(KILL cr);
7388 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);
7389
7390 ins_cost(150);
7391 format %{ "eaddq $dst, $src1, $src2\t# long ndd" %}
7392 ins_encode %{
7393 __ eaddq($dst$$Register, $src1$$Register, $src2$$Address, false);
7394 %}
7395 ins_pipe(ialu_reg_mem);
7396 %}
7397
7398 instruct addL_mem_rReg(memory dst, rRegL src, rFlagsReg cr)
7399 %{
7400 match(Set dst (StoreL dst (AddL (LoadL dst) src)));
7401 effect(KILL cr);
7402 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);
7403
7404 ins_cost(150); // XXX
7405 format %{ "addq $dst, $src\t# long" %}
7406 ins_encode %{
7407 __ addq($dst$$Address, $src$$Register);
7408 %}
7409 ins_pipe(ialu_mem_reg);
7410 %}
7411
7412 instruct addL_mem_imm(memory dst, immL32 src, rFlagsReg cr)
7413 %{
7414 match(Set dst (StoreL dst (AddL (LoadL dst) src)));
7415 effect(KILL cr);
7416 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);
7417
7418 ins_cost(125); // XXX
7419 format %{ "addq $dst, $src\t# long" %}
7420 ins_encode %{
7421 __ addq($dst$$Address, $src$$constant);
7422 %}
7423 ins_pipe(ialu_mem_imm);
7424 %}
7425
7426 instruct incL_rReg(rRegL dst, immL1 src, rFlagsReg cr)
7427 %{
7428 predicate(!UseAPX && UseIncDec);
7429 match(Set dst (AddL dst src));
7430 effect(KILL cr);
7431
7432 format %{ "incq $dst\t# long" %}
7433 ins_encode %{
7434 __ incrementq($dst$$Register);
7435 %}
7436 ins_pipe(ialu_reg);
7437 %}
7438
7439 instruct incL_rReg_ndd(rRegL dst, rRegI src, immL1 val, rFlagsReg cr)
7440 %{
7441 predicate(UseAPX && UseIncDec);
7442 match(Set dst (AddL src val));
7443 effect(KILL cr);
7444
7445 format %{ "eincq $dst, $src\t# long ndd" %}
7446 ins_encode %{
7447 __ eincq($dst$$Register, $src$$Register, false);
7448 %}
7449 ins_pipe(ialu_reg);
7450 %}
7451
7452 instruct incL_rReg_mem_ndd(rRegL dst, memory src, immL1 val, rFlagsReg cr)
7453 %{
7454 predicate(UseAPX && UseIncDec);
7455 match(Set dst (AddL (LoadL src) val));
7456 effect(KILL cr);
7457
7458 format %{ "eincq $dst, $src\t# long ndd" %}
7459 ins_encode %{
7460 __ eincq($dst$$Register, $src$$Address, false);
7461 %}
7462 ins_pipe(ialu_reg);
7463 %}
7464
7465 instruct incL_mem(memory dst, immL1 src, rFlagsReg cr)
7466 %{
7467 predicate(UseIncDec);
7468 match(Set dst (StoreL dst (AddL (LoadL dst) src)));
7469 effect(KILL cr);
7470
7471 ins_cost(125); // XXX
7472 format %{ "incq $dst\t# long" %}
7473 ins_encode %{
7474 __ incrementq($dst$$Address);
7475 %}
7476 ins_pipe(ialu_mem_imm);
7477 %}
7478
7479 // XXX why does that use AddL
7480 instruct decL_rReg(rRegL dst, immL_M1 src, rFlagsReg cr)
7481 %{
7482 predicate(!UseAPX && UseIncDec);
7483 match(Set dst (AddL dst src));
7484 effect(KILL cr);
7485
7486 format %{ "decq $dst\t# long" %}
7487 ins_encode %{
7488 __ decrementq($dst$$Register);
7489 %}
7490 ins_pipe(ialu_reg);
7491 %}
7492
7493 instruct decL_rReg_ndd(rRegL dst, rRegL src, immL_M1 val, rFlagsReg cr)
7494 %{
7495 predicate(UseAPX && UseIncDec);
7496 match(Set dst (AddL src val));
7497 effect(KILL cr);
7498
7499 format %{ "edecq $dst, $src\t# long ndd" %}
7500 ins_encode %{
7501 __ edecq($dst$$Register, $src$$Register, false);
7502 %}
7503 ins_pipe(ialu_reg);
7504 %}
7505
7506 instruct decL_rReg_mem_ndd(rRegL dst, memory src, immL_M1 val, rFlagsReg cr)
7507 %{
7508 predicate(UseAPX && UseIncDec);
7509 match(Set dst (AddL (LoadL src) val));
7510 effect(KILL cr);
7511
7512 format %{ "edecq $dst, $src\t# long ndd" %}
7513 ins_encode %{
7514 __ edecq($dst$$Register, $src$$Address, false);
7515 %}
7516 ins_pipe(ialu_reg);
7517 %}
7518
7519 // XXX why does that use AddL
7520 instruct decL_mem(memory dst, immL_M1 src, rFlagsReg cr)
7521 %{
7522 predicate(UseIncDec);
7523 match(Set dst (StoreL dst (AddL (LoadL dst) src)));
7524 effect(KILL cr);
7525
7526 ins_cost(125); // XXX
7527 format %{ "decq $dst\t# long" %}
7528 ins_encode %{
7529 __ decrementq($dst$$Address);
7530 %}
7531 ins_pipe(ialu_mem_imm);
7532 %}
7533
7534 instruct leaL_rReg_immI2_immL32(rRegL dst, rRegL index, immI2 scale, immL32 disp)
7535 %{
7536 predicate(VM_Version::supports_fast_2op_lea());
7537 match(Set dst (AddL (LShiftL index scale) disp));
7538
7539 format %{ "leaq $dst, [$index << $scale + $disp]\t# long" %}
7540 ins_encode %{
7541 Address::ScaleFactor scale = static_cast<Address::ScaleFactor>($scale$$constant);
7542 __ leaq($dst$$Register, Address(noreg, $index$$Register, scale, $disp$$constant));
7543 %}
7544 ins_pipe(ialu_reg_reg);
7545 %}
7546
7547 instruct leaL_rReg_rReg_immL32(rRegL dst, rRegL base, rRegL index, immL32 disp)
7548 %{
7549 predicate(VM_Version::supports_fast_3op_lea());
7550 match(Set dst (AddL (AddL base index) disp));
7551
7552 format %{ "leaq $dst, [$base + $index + $disp]\t# long" %}
7553 ins_encode %{
7554 __ leaq($dst$$Register, Address($base$$Register, $index$$Register, Address::times_1, $disp$$constant));
7555 %}
7556 ins_pipe(ialu_reg_reg);
7557 %}
7558
7559 instruct leaL_rReg_rReg_immI2(rRegL dst, no_rbp_r13_RegL base, rRegL index, immI2 scale)
7560 %{
7561 predicate(VM_Version::supports_fast_2op_lea());
7562 match(Set dst (AddL base (LShiftL index scale)));
7563
7564 format %{ "leaq $dst, [$base + $index << $scale]\t# long" %}
7565 ins_encode %{
7566 Address::ScaleFactor scale = static_cast<Address::ScaleFactor>($scale$$constant);
7567 __ leaq($dst$$Register, Address($base$$Register, $index$$Register, scale));
7568 %}
7569 ins_pipe(ialu_reg_reg);
7570 %}
7571
7572 instruct leaL_rReg_rReg_immI2_immL32(rRegL dst, rRegL base, rRegL index, immI2 scale, immL32 disp)
7573 %{
7574 predicate(VM_Version::supports_fast_3op_lea());
7575 match(Set dst (AddL (AddL base (LShiftL index scale)) disp));
7576
7577 format %{ "leaq $dst, [$base + $index << $scale + $disp]\t# long" %}
7578 ins_encode %{
7579 Address::ScaleFactor scale = static_cast<Address::ScaleFactor>($scale$$constant);
7580 __ leaq($dst$$Register, Address($base$$Register, $index$$Register, scale, $disp$$constant));
7581 %}
7582 ins_pipe(ialu_reg_reg);
7583 %}
7584
7585 instruct addP_rReg(rRegP dst, rRegL src, rFlagsReg cr)
7586 %{
7587 match(Set dst (AddP dst src));
7588 effect(KILL cr);
7589 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);
7590
7591 format %{ "addq $dst, $src\t# ptr" %}
7592 ins_encode %{
7593 __ addq($dst$$Register, $src$$Register);
7594 %}
7595 ins_pipe(ialu_reg_reg);
7596 %}
7597
7598 instruct addP_rReg_imm(rRegP dst, immL32 src, rFlagsReg cr)
7599 %{
7600 match(Set dst (AddP dst src));
7601 effect(KILL cr);
7602 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);
7603
7604 format %{ "addq $dst, $src\t# ptr" %}
7605 ins_encode %{
7606 __ addq($dst$$Register, $src$$constant);
7607 %}
7608 ins_pipe( ialu_reg );
7609 %}
7610
7611 // XXX addP mem ops ????
7612
7613 instruct checkCastPP(rRegP dst)
7614 %{
7615 match(Set dst (CheckCastPP dst));
7616
7617 size(0);
7618 format %{ "# checkcastPP of $dst" %}
7619 ins_encode(/* empty encoding */);
7620 ins_pipe(empty);
7621 %}
7622
7623 instruct castPP(rRegP dst)
7624 %{
7625 match(Set dst (CastPP dst));
7626
7627 size(0);
7628 format %{ "# castPP of $dst" %}
7629 ins_encode(/* empty encoding */);
7630 ins_pipe(empty);
7631 %}
7632
7633 instruct castII(rRegI dst)
7634 %{
7635 predicate(VerifyConstraintCasts == 0);
7636 match(Set dst (CastII dst));
7637
7638 size(0);
7639 format %{ "# castII of $dst" %}
7640 ins_encode(/* empty encoding */);
7641 ins_cost(0);
7642 ins_pipe(empty);
7643 %}
7644
7645 instruct castII_checked(rRegI dst, rFlagsReg cr)
7646 %{
7647 predicate(VerifyConstraintCasts > 0);
7648 match(Set dst (CastII dst));
7649
7650 effect(KILL cr);
7651 format %{ "# cast_checked_II $dst" %}
7652 ins_encode %{
7653 __ verify_int_in_range(_idx, bottom_type()->is_int(), $dst$$Register);
7654 %}
7655 ins_pipe(pipe_slow);
7656 %}
7657
7658 instruct castLL(rRegL dst)
7659 %{
7660 predicate(VerifyConstraintCasts == 0);
7661 match(Set dst (CastLL dst));
7662
7663 size(0);
7664 format %{ "# castLL of $dst" %}
7665 ins_encode(/* empty encoding */);
7666 ins_cost(0);
7667 ins_pipe(empty);
7668 %}
7669
7670 instruct castLL_checked_L32(rRegL dst, rFlagsReg cr)
7671 %{
7672 predicate(VerifyConstraintCasts > 0 && castLL_is_imm32(n));
7673 match(Set dst (CastLL dst));
7674
7675 effect(KILL cr);
7676 format %{ "# cast_checked_LL $dst" %}
7677 ins_encode %{
7678 __ verify_long_in_range(_idx, bottom_type()->is_long(), $dst$$Register, noreg);
7679 %}
7680 ins_pipe(pipe_slow);
7681 %}
7682
7683 instruct castLL_checked(rRegL dst, rRegL tmp, rFlagsReg cr)
7684 %{
7685 predicate(VerifyConstraintCasts > 0 && !castLL_is_imm32(n));
7686 match(Set dst (CastLL dst));
7687
7688 effect(KILL cr, TEMP tmp);
7689 format %{ "# cast_checked_LL $dst\tusing $tmp as TEMP" %}
7690 ins_encode %{
7691 __ verify_long_in_range(_idx, bottom_type()->is_long(), $dst$$Register, $tmp$$Register);
7692 %}
7693 ins_pipe(pipe_slow);
7694 %}
7695
7696 instruct castFF(regF dst)
7697 %{
7698 match(Set dst (CastFF dst));
7699
7700 size(0);
7701 format %{ "# castFF of $dst" %}
7702 ins_encode(/* empty encoding */);
7703 ins_cost(0);
7704 ins_pipe(empty);
7705 %}
7706
7707 instruct castHH(regF dst)
7708 %{
7709 match(Set dst (CastHH dst));
7710
7711 size(0);
7712 format %{ "# castHH of $dst" %}
7713 ins_encode(/* empty encoding */);
7714 ins_cost(0);
7715 ins_pipe(empty);
7716 %}
7717
7718 instruct castDD(regD dst)
7719 %{
7720 match(Set dst (CastDD dst));
7721
7722 size(0);
7723 format %{ "# castDD of $dst" %}
7724 ins_encode(/* empty encoding */);
7725 ins_cost(0);
7726 ins_pipe(empty);
7727 %}
7728
7729 // XXX No flag versions for CompareAndSwap{P,I,L} because matcher can't match them
7730 instruct compareAndSwapP(rRegI res,
7731 memory mem_ptr,
7732 rax_RegP oldval, rRegP newval,
7733 rFlagsReg cr)
7734 %{
7735 predicate(n->as_LoadStore()->barrier_data() == 0);
7736 match(Set res (CompareAndSwapP mem_ptr (Binary oldval newval)));
7737 match(Set res (WeakCompareAndSwapP mem_ptr (Binary oldval newval)));
7738 effect(KILL cr, KILL oldval);
7739
7740 format %{ "cmpxchgq $mem_ptr,$newval\t# "
7741 "If rax == $mem_ptr then store $newval into $mem_ptr\n\t"
7742 "setcc $res \t# emits sete + movzbl or setzue for APX" %}
7743 ins_encode %{
7744 __ lock();
7745 __ cmpxchgq($newval$$Register, $mem_ptr$$Address);
7746 __ setcc(Assembler::equal, $res$$Register);
7747 %}
7748 ins_pipe( pipe_cmpxchg );
7749 %}
7750
7751 instruct compareAndSwapL(rRegI res,
7752 memory mem_ptr,
7753 rax_RegL oldval, rRegL newval,
7754 rFlagsReg cr)
7755 %{
7756 match(Set res (CompareAndSwapL mem_ptr (Binary oldval newval)));
7757 match(Set res (WeakCompareAndSwapL mem_ptr (Binary oldval newval)));
7758 effect(KILL cr, KILL oldval);
7759
7760 format %{ "cmpxchgq $mem_ptr,$newval\t# "
7761 "If rax == $mem_ptr then store $newval into $mem_ptr\n\t"
7762 "setcc $res \t# emits sete + movzbl or setzue for APX" %}
7763 ins_encode %{
7764 __ lock();
7765 __ cmpxchgq($newval$$Register, $mem_ptr$$Address);
7766 __ setcc(Assembler::equal, $res$$Register);
7767 %}
7768 ins_pipe( pipe_cmpxchg );
7769 %}
7770
7771 instruct compareAndSwapI(rRegI res,
7772 memory mem_ptr,
7773 rax_RegI oldval, rRegI newval,
7774 rFlagsReg cr)
7775 %{
7776 match(Set res (CompareAndSwapI mem_ptr (Binary oldval newval)));
7777 match(Set res (WeakCompareAndSwapI mem_ptr (Binary oldval newval)));
7778 effect(KILL cr, KILL oldval);
7779
7780 format %{ "cmpxchgl $mem_ptr,$newval\t# "
7781 "If rax == $mem_ptr then store $newval into $mem_ptr\n\t"
7782 "setcc $res \t# emits sete + movzbl or setzue for APX" %}
7783 ins_encode %{
7784 __ lock();
7785 __ cmpxchgl($newval$$Register, $mem_ptr$$Address);
7786 __ setcc(Assembler::equal, $res$$Register);
7787 %}
7788 ins_pipe( pipe_cmpxchg );
7789 %}
7790
7791 instruct compareAndSwapB(rRegI res,
7792 memory mem_ptr,
7793 rax_RegI oldval, rRegI newval,
7794 rFlagsReg cr)
7795 %{
7796 match(Set res (CompareAndSwapB mem_ptr (Binary oldval newval)));
7797 match(Set res (WeakCompareAndSwapB mem_ptr (Binary oldval newval)));
7798 effect(KILL cr, KILL oldval);
7799
7800 format %{ "cmpxchgb $mem_ptr,$newval\t# "
7801 "If rax == $mem_ptr then store $newval into $mem_ptr\n\t"
7802 "setcc $res \t# emits sete + movzbl or setzue for APX" %}
7803 ins_encode %{
7804 __ lock();
7805 __ cmpxchgb($newval$$Register, $mem_ptr$$Address);
7806 __ setcc(Assembler::equal, $res$$Register);
7807 %}
7808 ins_pipe( pipe_cmpxchg );
7809 %}
7810
7811 instruct compareAndSwapS(rRegI res,
7812 memory mem_ptr,
7813 rax_RegI oldval, rRegI newval,
7814 rFlagsReg cr)
7815 %{
7816 match(Set res (CompareAndSwapS mem_ptr (Binary oldval newval)));
7817 match(Set res (WeakCompareAndSwapS mem_ptr (Binary oldval newval)));
7818 effect(KILL cr, KILL oldval);
7819
7820 format %{ "cmpxchgw $mem_ptr,$newval\t# "
7821 "If rax == $mem_ptr then store $newval into $mem_ptr\n\t"
7822 "setcc $res \t# emits sete + movzbl or setzue for APX" %}
7823 ins_encode %{
7824 __ lock();
7825 __ cmpxchgw($newval$$Register, $mem_ptr$$Address);
7826 __ setcc(Assembler::equal, $res$$Register);
7827 %}
7828 ins_pipe( pipe_cmpxchg );
7829 %}
7830
7831 instruct compareAndSwapN(rRegI res,
7832 memory mem_ptr,
7833 rax_RegN oldval, rRegN newval,
7834 rFlagsReg cr) %{
7835 predicate(n->as_LoadStore()->barrier_data() == 0);
7836 match(Set res (CompareAndSwapN mem_ptr (Binary oldval newval)));
7837 match(Set res (WeakCompareAndSwapN mem_ptr (Binary oldval newval)));
7838 effect(KILL cr, KILL oldval);
7839
7840 format %{ "cmpxchgl $mem_ptr,$newval\t# "
7841 "If rax == $mem_ptr then store $newval into $mem_ptr\n\t"
7842 "setcc $res \t# emits sete + movzbl or setzue for APX" %}
7843 ins_encode %{
7844 __ lock();
7845 __ cmpxchgl($newval$$Register, $mem_ptr$$Address);
7846 __ setcc(Assembler::equal, $res$$Register);
7847 %}
7848 ins_pipe( pipe_cmpxchg );
7849 %}
7850
7851 instruct compareAndExchangeB(
7852 memory mem_ptr,
7853 rax_RegI oldval, rRegI newval,
7854 rFlagsReg cr)
7855 %{
7856 match(Set oldval (CompareAndExchangeB mem_ptr (Binary oldval newval)));
7857 effect(KILL cr);
7858
7859 format %{ "cmpxchgb $mem_ptr,$newval\t# "
7860 "If rax == $mem_ptr then store $newval into $mem_ptr\n\t" %}
7861 ins_encode %{
7862 __ lock();
7863 __ cmpxchgb($newval$$Register, $mem_ptr$$Address);
7864 %}
7865 ins_pipe( pipe_cmpxchg );
7866 %}
7867
7868 instruct compareAndExchangeS(
7869 memory mem_ptr,
7870 rax_RegI oldval, rRegI newval,
7871 rFlagsReg cr)
7872 %{
7873 match(Set oldval (CompareAndExchangeS mem_ptr (Binary oldval newval)));
7874 effect(KILL cr);
7875
7876 format %{ "cmpxchgw $mem_ptr,$newval\t# "
7877 "If rax == $mem_ptr then store $newval into $mem_ptr\n\t" %}
7878 ins_encode %{
7879 __ lock();
7880 __ cmpxchgw($newval$$Register, $mem_ptr$$Address);
7881 %}
7882 ins_pipe( pipe_cmpxchg );
7883 %}
7884
7885 instruct compareAndExchangeI(
7886 memory mem_ptr,
7887 rax_RegI oldval, rRegI newval,
7888 rFlagsReg cr)
7889 %{
7890 match(Set oldval (CompareAndExchangeI mem_ptr (Binary oldval newval)));
7891 effect(KILL cr);
7892
7893 format %{ "cmpxchgl $mem_ptr,$newval\t# "
7894 "If rax == $mem_ptr then store $newval into $mem_ptr\n\t" %}
7895 ins_encode %{
7896 __ lock();
7897 __ cmpxchgl($newval$$Register, $mem_ptr$$Address);
7898 %}
7899 ins_pipe( pipe_cmpxchg );
7900 %}
7901
7902 instruct compareAndExchangeL(
7903 memory mem_ptr,
7904 rax_RegL oldval, rRegL newval,
7905 rFlagsReg cr)
7906 %{
7907 match(Set oldval (CompareAndExchangeL mem_ptr (Binary oldval newval)));
7908 effect(KILL cr);
7909
7910 format %{ "cmpxchgq $mem_ptr,$newval\t# "
7911 "If rax == $mem_ptr then store $newval into $mem_ptr\n\t" %}
7912 ins_encode %{
7913 __ lock();
7914 __ cmpxchgq($newval$$Register, $mem_ptr$$Address);
7915 %}
7916 ins_pipe( pipe_cmpxchg );
7917 %}
7918
7919 instruct compareAndExchangeN(
7920 memory mem_ptr,
7921 rax_RegN oldval, rRegN newval,
7922 rFlagsReg cr) %{
7923 predicate(n->as_LoadStore()->barrier_data() == 0);
7924 match(Set oldval (CompareAndExchangeN mem_ptr (Binary oldval newval)));
7925 effect(KILL cr);
7926
7927 format %{ "cmpxchgl $mem_ptr,$newval\t# "
7928 "If rax == $mem_ptr then store $newval into $mem_ptr\n\t" %}
7929 ins_encode %{
7930 __ lock();
7931 __ cmpxchgl($newval$$Register, $mem_ptr$$Address);
7932 %}
7933 ins_pipe( pipe_cmpxchg );
7934 %}
7935
7936 instruct compareAndExchangeP(
7937 memory mem_ptr,
7938 rax_RegP oldval, rRegP newval,
7939 rFlagsReg cr)
7940 %{
7941 predicate(n->as_LoadStore()->barrier_data() == 0);
7942 match(Set oldval (CompareAndExchangeP mem_ptr (Binary oldval newval)));
7943 effect(KILL cr);
7944
7945 format %{ "cmpxchgq $mem_ptr,$newval\t# "
7946 "If rax == $mem_ptr then store $newval into $mem_ptr\n\t" %}
7947 ins_encode %{
7948 __ lock();
7949 __ cmpxchgq($newval$$Register, $mem_ptr$$Address);
7950 %}
7951 ins_pipe( pipe_cmpxchg );
7952 %}
7953
7954 instruct xaddB_reg_no_res(memory mem, Universe dummy, rRegI add, rFlagsReg cr) %{
7955 predicate(n->as_LoadStore()->result_not_used());
7956 match(Set dummy (GetAndAddB mem add));
7957 effect(KILL cr);
7958 format %{ "addb_lock $mem, $add" %}
7959 ins_encode %{
7960 __ lock();
7961 __ addb($mem$$Address, $add$$Register);
7962 %}
7963 ins_pipe(pipe_cmpxchg);
7964 %}
7965
7966 instruct xaddB_imm_no_res(memory mem, Universe dummy, immI add, rFlagsReg cr) %{
7967 predicate(n->as_LoadStore()->result_not_used());
7968 match(Set dummy (GetAndAddB mem add));
7969 effect(KILL cr);
7970 format %{ "addb_lock $mem, $add" %}
7971 ins_encode %{
7972 __ lock();
7973 __ addb($mem$$Address, $add$$constant);
7974 %}
7975 ins_pipe(pipe_cmpxchg);
7976 %}
7977
7978 instruct xaddB(memory mem, rRegI newval, rFlagsReg cr) %{
7979 predicate(!n->as_LoadStore()->result_not_used());
7980 match(Set newval (GetAndAddB mem newval));
7981 effect(KILL cr);
7982 format %{ "xaddb_lock $mem, $newval" %}
7983 ins_encode %{
7984 __ lock();
7985 __ xaddb($mem$$Address, $newval$$Register);
7986 %}
7987 ins_pipe(pipe_cmpxchg);
7988 %}
7989
7990 instruct xaddS_reg_no_res(memory mem, Universe dummy, rRegI add, rFlagsReg cr) %{
7991 predicate(n->as_LoadStore()->result_not_used());
7992 match(Set dummy (GetAndAddS mem add));
7993 effect(KILL cr);
7994 format %{ "addw_lock $mem, $add" %}
7995 ins_encode %{
7996 __ lock();
7997 __ addw($mem$$Address, $add$$Register);
7998 %}
7999 ins_pipe(pipe_cmpxchg);
8000 %}
8001
8002 instruct xaddS_imm_no_res(memory mem, Universe dummy, immI add, rFlagsReg cr) %{
8003 predicate(UseStoreImmI16 && n->as_LoadStore()->result_not_used());
8004 match(Set dummy (GetAndAddS mem add));
8005 effect(KILL cr);
8006 format %{ "addw_lock $mem, $add" %}
8007 ins_encode %{
8008 __ lock();
8009 __ addw($mem$$Address, $add$$constant);
8010 %}
8011 ins_pipe(pipe_cmpxchg);
8012 %}
8013
8014 instruct xaddS(memory mem, rRegI newval, rFlagsReg cr) %{
8015 predicate(!n->as_LoadStore()->result_not_used());
8016 match(Set newval (GetAndAddS mem newval));
8017 effect(KILL cr);
8018 format %{ "xaddw_lock $mem, $newval" %}
8019 ins_encode %{
8020 __ lock();
8021 __ xaddw($mem$$Address, $newval$$Register);
8022 %}
8023 ins_pipe(pipe_cmpxchg);
8024 %}
8025
8026 instruct xaddI_reg_no_res(memory mem, Universe dummy, rRegI add, rFlagsReg cr) %{
8027 predicate(n->as_LoadStore()->result_not_used());
8028 match(Set dummy (GetAndAddI mem add));
8029 effect(KILL cr);
8030 format %{ "addl_lock $mem, $add" %}
8031 ins_encode %{
8032 __ lock();
8033 __ addl($mem$$Address, $add$$Register);
8034 %}
8035 ins_pipe(pipe_cmpxchg);
8036 %}
8037
8038 instruct xaddI_imm_no_res(memory mem, Universe dummy, immI add, rFlagsReg cr) %{
8039 predicate(n->as_LoadStore()->result_not_used());
8040 match(Set dummy (GetAndAddI mem add));
8041 effect(KILL cr);
8042 format %{ "addl_lock $mem, $add" %}
8043 ins_encode %{
8044 __ lock();
8045 __ addl($mem$$Address, $add$$constant);
8046 %}
8047 ins_pipe(pipe_cmpxchg);
8048 %}
8049
8050 instruct xaddI(memory mem, rRegI newval, rFlagsReg cr) %{
8051 predicate(!n->as_LoadStore()->result_not_used());
8052 match(Set newval (GetAndAddI mem newval));
8053 effect(KILL cr);
8054 format %{ "xaddl_lock $mem, $newval" %}
8055 ins_encode %{
8056 __ lock();
8057 __ xaddl($mem$$Address, $newval$$Register);
8058 %}
8059 ins_pipe(pipe_cmpxchg);
8060 %}
8061
8062 instruct xaddL_reg_no_res(memory mem, Universe dummy, rRegL add, rFlagsReg cr) %{
8063 predicate(n->as_LoadStore()->result_not_used());
8064 match(Set dummy (GetAndAddL mem add));
8065 effect(KILL cr);
8066 format %{ "addq_lock $mem, $add" %}
8067 ins_encode %{
8068 __ lock();
8069 __ addq($mem$$Address, $add$$Register);
8070 %}
8071 ins_pipe(pipe_cmpxchg);
8072 %}
8073
8074 instruct xaddL_imm_no_res(memory mem, Universe dummy, immL32 add, rFlagsReg cr) %{
8075 predicate(n->as_LoadStore()->result_not_used());
8076 match(Set dummy (GetAndAddL mem add));
8077 effect(KILL cr);
8078 format %{ "addq_lock $mem, $add" %}
8079 ins_encode %{
8080 __ lock();
8081 __ addq($mem$$Address, $add$$constant);
8082 %}
8083 ins_pipe(pipe_cmpxchg);
8084 %}
8085
8086 instruct xaddL(memory mem, rRegL newval, rFlagsReg cr) %{
8087 predicate(!n->as_LoadStore()->result_not_used());
8088 match(Set newval (GetAndAddL mem newval));
8089 effect(KILL cr);
8090 format %{ "xaddq_lock $mem, $newval" %}
8091 ins_encode %{
8092 __ lock();
8093 __ xaddq($mem$$Address, $newval$$Register);
8094 %}
8095 ins_pipe(pipe_cmpxchg);
8096 %}
8097
8098 instruct xchgB( memory mem, rRegI newval) %{
8099 match(Set newval (GetAndSetB mem newval));
8100 format %{ "XCHGB $newval,[$mem]" %}
8101 ins_encode %{
8102 __ xchgb($newval$$Register, $mem$$Address);
8103 %}
8104 ins_pipe( pipe_cmpxchg );
8105 %}
8106
8107 instruct xchgS( memory mem, rRegI newval) %{
8108 match(Set newval (GetAndSetS mem newval));
8109 format %{ "XCHGW $newval,[$mem]" %}
8110 ins_encode %{
8111 __ xchgw($newval$$Register, $mem$$Address);
8112 %}
8113 ins_pipe( pipe_cmpxchg );
8114 %}
8115
8116 instruct xchgI( memory mem, rRegI newval) %{
8117 match(Set newval (GetAndSetI mem newval));
8118 format %{ "XCHGL $newval,[$mem]" %}
8119 ins_encode %{
8120 __ xchgl($newval$$Register, $mem$$Address);
8121 %}
8122 ins_pipe( pipe_cmpxchg );
8123 %}
8124
8125 instruct xchgL( memory mem, rRegL newval) %{
8126 match(Set newval (GetAndSetL mem newval));
8127 format %{ "XCHGL $newval,[$mem]" %}
8128 ins_encode %{
8129 __ xchgq($newval$$Register, $mem$$Address);
8130 %}
8131 ins_pipe( pipe_cmpxchg );
8132 %}
8133
8134 instruct xchgP( memory mem, rRegP newval) %{
8135 match(Set newval (GetAndSetP mem newval));
8136 predicate(n->as_LoadStore()->barrier_data() == 0);
8137 format %{ "XCHGQ $newval,[$mem]" %}
8138 ins_encode %{
8139 __ xchgq($newval$$Register, $mem$$Address);
8140 %}
8141 ins_pipe( pipe_cmpxchg );
8142 %}
8143
8144 instruct xchgN( memory mem, rRegN newval) %{
8145 predicate(n->as_LoadStore()->barrier_data() == 0);
8146 match(Set newval (GetAndSetN mem newval));
8147 format %{ "XCHGL $newval,$mem]" %}
8148 ins_encode %{
8149 __ xchgl($newval$$Register, $mem$$Address);
8150 %}
8151 ins_pipe( pipe_cmpxchg );
8152 %}
8153
8154 //----------Abs Instructions-------------------------------------------
8155
8156 // Integer Absolute Instructions
8157 instruct absI_rReg(rRegI dst, rRegI src, rFlagsReg cr)
8158 %{
8159 match(Set dst (AbsI src));
8160 effect(TEMP dst, KILL cr);
8161 format %{ "xorl $dst, $dst\t# abs int\n\t"
8162 "subl $dst, $src\n\t"
8163 "cmovll $dst, $src" %}
8164 ins_encode %{
8165 __ xorl($dst$$Register, $dst$$Register);
8166 __ subl($dst$$Register, $src$$Register);
8167 __ cmovl(Assembler::less, $dst$$Register, $src$$Register);
8168 %}
8169
8170 ins_pipe(ialu_reg_reg);
8171 %}
8172
8173 // Long Absolute Instructions
8174 instruct absL_rReg(rRegL dst, rRegL src, rFlagsReg cr)
8175 %{
8176 match(Set dst (AbsL src));
8177 effect(TEMP dst, KILL cr);
8178 format %{ "xorl $dst, $dst\t# abs long\n\t"
8179 "subq $dst, $src\n\t"
8180 "cmovlq $dst, $src" %}
8181 ins_encode %{
8182 __ xorl($dst$$Register, $dst$$Register);
8183 __ subq($dst$$Register, $src$$Register);
8184 __ cmovq(Assembler::less, $dst$$Register, $src$$Register);
8185 %}
8186
8187 ins_pipe(ialu_reg_reg);
8188 %}
8189
8190 //----------Subtraction Instructions-------------------------------------------
8191
8192 // Integer Subtraction Instructions
8193 instruct subI_rReg(rRegI dst, rRegI src, rFlagsReg cr)
8194 %{
8195 predicate(!UseAPX);
8196 match(Set dst (SubI dst src));
8197 effect(KILL cr);
8198 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);
8199
8200 format %{ "subl $dst, $src\t# int" %}
8201 ins_encode %{
8202 __ subl($dst$$Register, $src$$Register);
8203 %}
8204 ins_pipe(ialu_reg_reg);
8205 %}
8206
8207 instruct subI_rReg_ndd(rRegI dst, rRegI src1, rRegI src2, rFlagsReg cr)
8208 %{
8209 predicate(UseAPX);
8210 match(Set dst (SubI src1 src2));
8211 effect(KILL cr);
8212 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);
8213
8214 format %{ "esubl $dst, $src1, $src2\t# int ndd" %}
8215 ins_encode %{
8216 __ esubl($dst$$Register, $src1$$Register, $src2$$Register, false);
8217 %}
8218 ins_pipe(ialu_reg_reg);
8219 %}
8220
8221 instruct subI_rReg_rReg_imm_ndd(rRegI dst, rRegI src1, immI src2, rFlagsReg cr)
8222 %{
8223 predicate(UseAPX);
8224 match(Set dst (SubI src1 src2));
8225 effect(KILL cr);
8226 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);
8227
8228 format %{ "esubl $dst, $src1, $src2\t# int ndd" %}
8229 ins_encode %{
8230 __ esubl($dst$$Register, $src1$$Register, $src2$$constant, false);
8231 %}
8232 ins_pipe(ialu_reg_reg);
8233 %}
8234
8235 instruct subI_rReg_mem_imm_ndd(rRegI dst, memory src1, immI src2, rFlagsReg cr)
8236 %{
8237 predicate(UseAPX);
8238 match(Set dst (SubI (LoadI src1) src2));
8239 effect(KILL cr);
8240 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);
8241
8242 format %{ "esubl $dst, $src1, $src2\t# int ndd" %}
8243 ins_encode %{
8244 __ esubl($dst$$Register, $src1$$Address, $src2$$constant, false);
8245 %}
8246 ins_pipe(ialu_reg_reg);
8247 %}
8248
8249 instruct subI_rReg_mem(rRegI dst, memory src, rFlagsReg cr)
8250 %{
8251 predicate(!UseAPX);
8252 match(Set dst (SubI dst (LoadI src)));
8253 effect(KILL cr);
8254 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);
8255
8256 ins_cost(150);
8257 format %{ "subl $dst, $src\t# int" %}
8258 ins_encode %{
8259 __ subl($dst$$Register, $src$$Address);
8260 %}
8261 ins_pipe(ialu_reg_mem);
8262 %}
8263
8264 instruct subI_rReg_rReg_mem_ndd(rRegI dst, rRegI src1, memory src2, rFlagsReg cr)
8265 %{
8266 predicate(UseAPX);
8267 match(Set dst (SubI src1 (LoadI src2)));
8268 effect(KILL cr);
8269 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);
8270
8271 ins_cost(150);
8272 format %{ "esubl $dst, $src1, $src2\t# int ndd" %}
8273 ins_encode %{
8274 __ esubl($dst$$Register, $src1$$Register, $src2$$Address, false);
8275 %}
8276 ins_pipe(ialu_reg_mem);
8277 %}
8278
8279 instruct subI_rReg_mem_rReg_ndd(rRegI dst, memory src1, rRegI src2, rFlagsReg cr)
8280 %{
8281 predicate(UseAPX);
8282 match(Set dst (SubI (LoadI src1) src2));
8283 effect(KILL cr);
8284 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);
8285
8286 ins_cost(150);
8287 format %{ "esubl $dst, $src1, $src2\t# int ndd" %}
8288 ins_encode %{
8289 __ esubl($dst$$Register, $src1$$Address, $src2$$Register, false);
8290 %}
8291 ins_pipe(ialu_reg_mem);
8292 %}
8293
8294 instruct subI_mem_rReg(memory dst, rRegI src, rFlagsReg cr)
8295 %{
8296 match(Set dst (StoreI dst (SubI (LoadI dst) src)));
8297 effect(KILL cr);
8298 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);
8299
8300 ins_cost(150);
8301 format %{ "subl $dst, $src\t# int" %}
8302 ins_encode %{
8303 __ subl($dst$$Address, $src$$Register);
8304 %}
8305 ins_pipe(ialu_mem_reg);
8306 %}
8307
8308 instruct subL_rReg(rRegL dst, rRegL src, rFlagsReg cr)
8309 %{
8310 predicate(!UseAPX);
8311 match(Set dst (SubL dst src));
8312 effect(KILL cr);
8313 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);
8314
8315 format %{ "subq $dst, $src\t# long" %}
8316 ins_encode %{
8317 __ subq($dst$$Register, $src$$Register);
8318 %}
8319 ins_pipe(ialu_reg_reg);
8320 %}
8321
8322 instruct subL_rReg_ndd(rRegL dst, rRegL src1, rRegL src2, rFlagsReg cr)
8323 %{
8324 predicate(UseAPX);
8325 match(Set dst (SubL src1 src2));
8326 effect(KILL cr);
8327 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);
8328
8329 format %{ "esubq $dst, $src1, $src2\t# long ndd" %}
8330 ins_encode %{
8331 __ esubq($dst$$Register, $src1$$Register, $src2$$Register, false);
8332 %}
8333 ins_pipe(ialu_reg_reg);
8334 %}
8335
8336 instruct subL_rReg_rReg_imm_ndd(rRegL dst, rRegL src1, immL32 src2, rFlagsReg cr)
8337 %{
8338 predicate(UseAPX);
8339 match(Set dst (SubL src1 src2));
8340 effect(KILL cr);
8341 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);
8342
8343 format %{ "esubq $dst, $src1, $src2\t# long ndd" %}
8344 ins_encode %{
8345 __ esubq($dst$$Register, $src1$$Register, $src2$$constant, false);
8346 %}
8347 ins_pipe(ialu_reg_reg);
8348 %}
8349
8350 instruct subL_rReg_mem_imm_ndd(rRegL dst, memory src1, immL32 src2, rFlagsReg cr)
8351 %{
8352 predicate(UseAPX);
8353 match(Set dst (SubL (LoadL src1) src2));
8354 effect(KILL cr);
8355 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);
8356
8357 format %{ "esubq $dst, $src1, $src2\t# long ndd" %}
8358 ins_encode %{
8359 __ esubq($dst$$Register, $src1$$Address, $src2$$constant, false);
8360 %}
8361 ins_pipe(ialu_reg_reg);
8362 %}
8363
8364 instruct subL_rReg_mem(rRegL dst, memory src, rFlagsReg cr)
8365 %{
8366 predicate(!UseAPX);
8367 match(Set dst (SubL dst (LoadL src)));
8368 effect(KILL cr);
8369 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);
8370
8371 ins_cost(150);
8372 format %{ "subq $dst, $src\t# long" %}
8373 ins_encode %{
8374 __ subq($dst$$Register, $src$$Address);
8375 %}
8376 ins_pipe(ialu_reg_mem);
8377 %}
8378
8379 instruct subL_rReg_rReg_mem_ndd(rRegL dst, rRegL src1, memory src2, rFlagsReg cr)
8380 %{
8381 predicate(UseAPX);
8382 match(Set dst (SubL src1 (LoadL src2)));
8383 effect(KILL cr);
8384 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);
8385
8386 ins_cost(150);
8387 format %{ "esubq $dst, $src1, $src2\t# long ndd" %}
8388 ins_encode %{
8389 __ esubq($dst$$Register, $src1$$Register, $src2$$Address, false);
8390 %}
8391 ins_pipe(ialu_reg_mem);
8392 %}
8393
8394 instruct subL_rReg_mem_rReg_ndd(rRegL dst, memory src1, rRegL src2, rFlagsReg cr)
8395 %{
8396 predicate(UseAPX);
8397 match(Set dst (SubL (LoadL src1) src2));
8398 effect(KILL cr);
8399 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);
8400
8401 ins_cost(150);
8402 format %{ "esubq $dst, $src1, $src2\t# long ndd" %}
8403 ins_encode %{
8404 __ esubq($dst$$Register, $src1$$Address, $src2$$Register, false);
8405 %}
8406 ins_pipe(ialu_reg_mem);
8407 %}
8408
8409 instruct subL_mem_rReg(memory dst, rRegL src, rFlagsReg cr)
8410 %{
8411 match(Set dst (StoreL dst (SubL (LoadL dst) src)));
8412 effect(KILL cr);
8413 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);
8414
8415 ins_cost(150);
8416 format %{ "subq $dst, $src\t# long" %}
8417 ins_encode %{
8418 __ subq($dst$$Address, $src$$Register);
8419 %}
8420 ins_pipe(ialu_mem_reg);
8421 %}
8422
8423 // Subtract from a pointer
8424 // XXX hmpf???
8425 instruct subP_rReg(rRegP dst, rRegI src, immI_0 zero, rFlagsReg cr)
8426 %{
8427 match(Set dst (AddP dst (SubI zero src)));
8428 effect(KILL cr);
8429
8430 format %{ "subq $dst, $src\t# ptr - int" %}
8431 ins_encode %{
8432 __ subq($dst$$Register, $src$$Register);
8433 %}
8434 ins_pipe(ialu_reg_reg);
8435 %}
8436
8437 instruct negI_rReg(rRegI dst, immI_0 zero, rFlagsReg cr)
8438 %{
8439 predicate(!UseAPX);
8440 match(Set dst (SubI zero dst));
8441 effect(KILL cr);
8442 flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag);
8443
8444 format %{ "negl $dst\t# int" %}
8445 ins_encode %{
8446 __ negl($dst$$Register);
8447 %}
8448 ins_pipe(ialu_reg);
8449 %}
8450
8451 instruct negI_rReg_ndd(rRegI dst, rRegI src, immI_0 zero, rFlagsReg cr)
8452 %{
8453 predicate(UseAPX);
8454 match(Set dst (SubI zero src));
8455 effect(KILL cr);
8456 flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag);
8457
8458 format %{ "enegl $dst, $src\t# int ndd" %}
8459 ins_encode %{
8460 __ enegl($dst$$Register, $src$$Register, false);
8461 %}
8462 ins_pipe(ialu_reg);
8463 %}
8464
8465 instruct negI_rReg_2(rRegI dst, rFlagsReg cr)
8466 %{
8467 predicate(!UseAPX);
8468 match(Set dst (NegI dst));
8469 effect(KILL cr);
8470 flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag);
8471
8472 format %{ "negl $dst\t# int" %}
8473 ins_encode %{
8474 __ negl($dst$$Register);
8475 %}
8476 ins_pipe(ialu_reg);
8477 %}
8478
8479 instruct negI_rReg_2_ndd(rRegI dst, rRegI src, rFlagsReg cr)
8480 %{
8481 predicate(UseAPX);
8482 match(Set dst (NegI src));
8483 effect(KILL cr);
8484 flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag);
8485
8486 format %{ "enegl $dst, $src\t# int ndd" %}
8487 ins_encode %{
8488 __ enegl($dst$$Register, $src$$Register, false);
8489 %}
8490 ins_pipe(ialu_reg);
8491 %}
8492
8493 instruct negI_mem(memory dst, immI_0 zero, rFlagsReg cr)
8494 %{
8495 match(Set dst (StoreI dst (SubI zero (LoadI dst))));
8496 effect(KILL cr);
8497 flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag);
8498
8499 format %{ "negl $dst\t# int" %}
8500 ins_encode %{
8501 __ negl($dst$$Address);
8502 %}
8503 ins_pipe(ialu_reg);
8504 %}
8505
8506 instruct negL_rReg(rRegL dst, immL0 zero, rFlagsReg cr)
8507 %{
8508 predicate(!UseAPX);
8509 match(Set dst (SubL zero dst));
8510 effect(KILL cr);
8511 flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag);
8512
8513 format %{ "negq $dst\t# long" %}
8514 ins_encode %{
8515 __ negq($dst$$Register);
8516 %}
8517 ins_pipe(ialu_reg);
8518 %}
8519
8520 instruct negL_rReg_ndd(rRegL dst, rRegL src, immL0 zero, rFlagsReg cr)
8521 %{
8522 predicate(UseAPX);
8523 match(Set dst (SubL zero src));
8524 effect(KILL cr);
8525 flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag);
8526
8527 format %{ "enegq $dst, $src\t# long ndd" %}
8528 ins_encode %{
8529 __ enegq($dst$$Register, $src$$Register, false);
8530 %}
8531 ins_pipe(ialu_reg);
8532 %}
8533
8534 instruct negL_rReg_2(rRegL dst, rFlagsReg cr)
8535 %{
8536 predicate(!UseAPX);
8537 match(Set dst (NegL dst));
8538 effect(KILL cr);
8539 flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag);
8540
8541 format %{ "negq $dst\t# int" %}
8542 ins_encode %{
8543 __ negq($dst$$Register);
8544 %}
8545 ins_pipe(ialu_reg);
8546 %}
8547
8548 instruct negL_rReg_2_ndd(rRegL dst, rRegL src, rFlagsReg cr)
8549 %{
8550 predicate(UseAPX);
8551 match(Set dst (NegL src));
8552 effect(KILL cr);
8553 flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag);
8554
8555 format %{ "enegq $dst, $src\t# long ndd" %}
8556 ins_encode %{
8557 __ enegq($dst$$Register, $src$$Register, false);
8558 %}
8559 ins_pipe(ialu_reg);
8560 %}
8561
8562 instruct negL_mem(memory dst, immL0 zero, rFlagsReg cr)
8563 %{
8564 match(Set dst (StoreL dst (SubL zero (LoadL dst))));
8565 effect(KILL cr);
8566 flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag);
8567
8568 format %{ "negq $dst\t# long" %}
8569 ins_encode %{
8570 __ negq($dst$$Address);
8571 %}
8572 ins_pipe(ialu_reg);
8573 %}
8574
8575 //----------Multiplication/Division Instructions-------------------------------
8576 // Integer Multiplication Instructions
8577 // Multiply Register
8578
8579 instruct mulI_rReg(rRegI dst, rRegI src, rFlagsReg cr)
8580 %{
8581 predicate(!UseAPX);
8582 match(Set dst (MulI dst src));
8583 effect(KILL cr);
8584
8585 ins_cost(300);
8586 format %{ "imull $dst, $src\t# int" %}
8587 ins_encode %{
8588 __ imull($dst$$Register, $src$$Register);
8589 %}
8590 ins_pipe(ialu_reg_reg_alu0);
8591 %}
8592
8593 instruct mulI_rReg_ndd(rRegI dst, rRegI src1, rRegI src2, rFlagsReg cr)
8594 %{
8595 predicate(UseAPX);
8596 match(Set dst (MulI src1 src2));
8597 effect(KILL cr);
8598
8599 ins_cost(300);
8600 format %{ "eimull $dst, $src1, $src2\t# int ndd" %}
8601 ins_encode %{
8602 __ eimull($dst$$Register, $src1$$Register, $src2$$Register, false);
8603 %}
8604 ins_pipe(ialu_reg_reg_alu0);
8605 %}
8606
8607 instruct mulI_rReg_imm(rRegI dst, rRegI src, immI imm, rFlagsReg cr)
8608 %{
8609 match(Set dst (MulI src imm));
8610 effect(KILL cr);
8611
8612 ins_cost(300);
8613 format %{ "imull $dst, $src, $imm\t# int" %}
8614 ins_encode %{
8615 __ imull($dst$$Register, $src$$Register, $imm$$constant);
8616 %}
8617 ins_pipe(ialu_reg_reg_alu0);
8618 %}
8619
8620 instruct mulI_mem(rRegI dst, memory src, rFlagsReg cr)
8621 %{
8622 predicate(!UseAPX);
8623 match(Set dst (MulI dst (LoadI src)));
8624 effect(KILL cr);
8625
8626 ins_cost(350);
8627 format %{ "imull $dst, $src\t# int" %}
8628 ins_encode %{
8629 __ imull($dst$$Register, $src$$Address);
8630 %}
8631 ins_pipe(ialu_reg_mem_alu0);
8632 %}
8633
8634 instruct mulI_rReg_rReg_mem_ndd(rRegI dst, rRegI src1, memory src2, rFlagsReg cr)
8635 %{
8636 predicate(UseAPX);
8637 match(Set dst (MulI src1 (LoadI src2)));
8638 effect(KILL cr);
8639
8640 ins_cost(350);
8641 format %{ "eimull $dst, $src1, $src2\t# int ndd" %}
8642 ins_encode %{
8643 __ eimull($dst$$Register, $src1$$Register, $src2$$Address, false);
8644 %}
8645 ins_pipe(ialu_reg_mem_alu0);
8646 %}
8647
8648 instruct mulI_mem_imm(rRegI dst, memory src, immI imm, rFlagsReg cr)
8649 %{
8650 match(Set dst (MulI (LoadI src) imm));
8651 effect(KILL cr);
8652
8653 ins_cost(300);
8654 format %{ "imull $dst, $src, $imm\t# int" %}
8655 ins_encode %{
8656 __ imull($dst$$Register, $src$$Address, $imm$$constant);
8657 %}
8658 ins_pipe(ialu_reg_mem_alu0);
8659 %}
8660
8661 instruct mulAddS2I_rReg(rRegI dst, rRegI src1, rRegI src2, rRegI src3, rFlagsReg cr)
8662 %{
8663 match(Set dst (MulAddS2I (Binary dst src1) (Binary src2 src3)));
8664 effect(KILL cr, KILL src2);
8665
8666 expand %{ mulI_rReg(dst, src1, cr);
8667 mulI_rReg(src2, src3, cr);
8668 addI_rReg(dst, src2, cr); %}
8669 %}
8670
8671 instruct mulL_rReg(rRegL dst, rRegL src, rFlagsReg cr)
8672 %{
8673 predicate(!UseAPX);
8674 match(Set dst (MulL dst src));
8675 effect(KILL cr);
8676
8677 ins_cost(300);
8678 format %{ "imulq $dst, $src\t# long" %}
8679 ins_encode %{
8680 __ imulq($dst$$Register, $src$$Register);
8681 %}
8682 ins_pipe(ialu_reg_reg_alu0);
8683 %}
8684
8685 instruct mulL_rReg_ndd(rRegL dst, rRegL src1, rRegL src2, rFlagsReg cr)
8686 %{
8687 predicate(UseAPX);
8688 match(Set dst (MulL src1 src2));
8689 effect(KILL cr);
8690
8691 ins_cost(300);
8692 format %{ "eimulq $dst, $src1, $src2\t# long ndd" %}
8693 ins_encode %{
8694 __ eimulq($dst$$Register, $src1$$Register, $src2$$Register, false);
8695 %}
8696 ins_pipe(ialu_reg_reg_alu0);
8697 %}
8698
8699 instruct mulL_rReg_imm(rRegL dst, rRegL src, immL32 imm, rFlagsReg cr)
8700 %{
8701 match(Set dst (MulL src imm));
8702 effect(KILL cr);
8703
8704 ins_cost(300);
8705 format %{ "imulq $dst, $src, $imm\t# long" %}
8706 ins_encode %{
8707 __ imulq($dst$$Register, $src$$Register, $imm$$constant);
8708 %}
8709 ins_pipe(ialu_reg_reg_alu0);
8710 %}
8711
8712 instruct mulL_mem(rRegL dst, memory src, rFlagsReg cr)
8713 %{
8714 predicate(!UseAPX);
8715 match(Set dst (MulL dst (LoadL src)));
8716 effect(KILL cr);
8717
8718 ins_cost(350);
8719 format %{ "imulq $dst, $src\t# long" %}
8720 ins_encode %{
8721 __ imulq($dst$$Register, $src$$Address);
8722 %}
8723 ins_pipe(ialu_reg_mem_alu0);
8724 %}
8725
8726 instruct mulL_rReg_rReg_mem_ndd(rRegL dst, rRegL src1, memory src2, rFlagsReg cr)
8727 %{
8728 predicate(UseAPX);
8729 match(Set dst (MulL src1 (LoadL src2)));
8730 effect(KILL cr);
8731
8732 ins_cost(350);
8733 format %{ "eimulq $dst, $src1, $src2 \t# long" %}
8734 ins_encode %{
8735 __ eimulq($dst$$Register, $src1$$Register, $src2$$Address, false);
8736 %}
8737 ins_pipe(ialu_reg_mem_alu0);
8738 %}
8739
8740 instruct mulL_mem_imm(rRegL dst, memory src, immL32 imm, rFlagsReg cr)
8741 %{
8742 match(Set dst (MulL (LoadL src) imm));
8743 effect(KILL cr);
8744
8745 ins_cost(300);
8746 format %{ "imulq $dst, $src, $imm\t# long" %}
8747 ins_encode %{
8748 __ imulq($dst$$Register, $src$$Address, $imm$$constant);
8749 %}
8750 ins_pipe(ialu_reg_mem_alu0);
8751 %}
8752
8753 instruct mulHiL_rReg(rdx_RegL dst, rRegL src, rax_RegL rax, rFlagsReg cr)
8754 %{
8755 match(Set dst (MulHiL src rax));
8756 effect(USE_KILL rax, KILL cr);
8757
8758 ins_cost(300);
8759 format %{ "imulq RDX:RAX, RAX, $src\t# mulhi" %}
8760 ins_encode %{
8761 __ imulq($src$$Register);
8762 %}
8763 ins_pipe(ialu_reg_reg_alu0);
8764 %}
8765
8766 instruct umulHiL_rReg(rdx_RegL dst, rRegL src, rax_RegL rax, rFlagsReg cr)
8767 %{
8768 match(Set dst (UMulHiL src rax));
8769 effect(USE_KILL rax, KILL cr);
8770
8771 ins_cost(300);
8772 format %{ "mulq RDX:RAX, RAX, $src\t# umulhi" %}
8773 ins_encode %{
8774 __ mulq($src$$Register);
8775 %}
8776 ins_pipe(ialu_reg_reg_alu0);
8777 %}
8778
8779 instruct divI_rReg(rax_RegI rax, rdx_RegI rdx, no_rax_rdx_RegI div,
8780 rFlagsReg cr)
8781 %{
8782 match(Set rax (DivI rax div));
8783 effect(KILL rdx, KILL cr);
8784
8785 ins_cost(30*100+10*100); // XXX
8786 format %{ "cmpl rax, 0x80000000\t# idiv\n\t"
8787 "jne,s normal\n\t"
8788 "xorl rdx, rdx\n\t"
8789 "cmpl $div, -1\n\t"
8790 "je,s done\n"
8791 "normal: cdql\n\t"
8792 "idivl $div\n"
8793 "done:" %}
8794 ins_encode(cdql_enc(div));
8795 ins_pipe(ialu_reg_reg_alu0);
8796 %}
8797
8798 instruct divL_rReg(rax_RegL rax, rdx_RegL rdx, no_rax_rdx_RegL div,
8799 rFlagsReg cr)
8800 %{
8801 match(Set rax (DivL rax div));
8802 effect(KILL rdx, KILL cr);
8803
8804 ins_cost(30*100+10*100); // XXX
8805 format %{ "movq rdx, 0x8000000000000000\t# ldiv\n\t"
8806 "cmpq rax, rdx\n\t"
8807 "jne,s normal\n\t"
8808 "xorl rdx, rdx\n\t"
8809 "cmpq $div, -1\n\t"
8810 "je,s done\n"
8811 "normal: cdqq\n\t"
8812 "idivq $div\n"
8813 "done:" %}
8814 ins_encode(cdqq_enc(div));
8815 ins_pipe(ialu_reg_reg_alu0);
8816 %}
8817
8818 instruct udivI_rReg(rax_RegI rax, rdx_RegI rdx, no_rax_rdx_RegI div, rFlagsReg cr)
8819 %{
8820 match(Set rax (UDivI rax div));
8821 effect(KILL rdx, KILL cr);
8822
8823 ins_cost(300);
8824 format %{ "udivl $rax,$rax,$div\t# UDivI\n" %}
8825 ins_encode %{
8826 __ udivI($rax$$Register, $div$$Register, $rdx$$Register);
8827 %}
8828 ins_pipe(ialu_reg_reg_alu0);
8829 %}
8830
8831 instruct udivL_rReg(rax_RegL rax, rdx_RegL rdx, no_rax_rdx_RegL div, rFlagsReg cr)
8832 %{
8833 match(Set rax (UDivL rax div));
8834 effect(KILL rdx, KILL cr);
8835
8836 ins_cost(300);
8837 format %{ "udivq $rax,$rax,$div\t# UDivL\n" %}
8838 ins_encode %{
8839 __ udivL($rax$$Register, $div$$Register, $rdx$$Register);
8840 %}
8841 ins_pipe(ialu_reg_reg_alu0);
8842 %}
8843
8844 // Integer DIVMOD with Register, both quotient and mod results
8845 instruct divModI_rReg_divmod(rax_RegI rax, rdx_RegI rdx, no_rax_rdx_RegI div,
8846 rFlagsReg cr)
8847 %{
8848 match(DivModI rax div);
8849 effect(KILL cr);
8850
8851 ins_cost(30*100+10*100); // XXX
8852 format %{ "cmpl rax, 0x80000000\t# idiv\n\t"
8853 "jne,s normal\n\t"
8854 "xorl rdx, rdx\n\t"
8855 "cmpl $div, -1\n\t"
8856 "je,s done\n"
8857 "normal: cdql\n\t"
8858 "idivl $div\n"
8859 "done:" %}
8860 ins_encode(cdql_enc(div));
8861 ins_pipe(pipe_slow);
8862 %}
8863
8864 // Long DIVMOD with Register, both quotient and mod results
8865 instruct divModL_rReg_divmod(rax_RegL rax, rdx_RegL rdx, no_rax_rdx_RegL div,
8866 rFlagsReg cr)
8867 %{
8868 match(DivModL rax div);
8869 effect(KILL cr);
8870
8871 ins_cost(30*100+10*100); // XXX
8872 format %{ "movq rdx, 0x8000000000000000\t# ldiv\n\t"
8873 "cmpq rax, rdx\n\t"
8874 "jne,s normal\n\t"
8875 "xorl rdx, rdx\n\t"
8876 "cmpq $div, -1\n\t"
8877 "je,s done\n"
8878 "normal: cdqq\n\t"
8879 "idivq $div\n"
8880 "done:" %}
8881 ins_encode(cdqq_enc(div));
8882 ins_pipe(pipe_slow);
8883 %}
8884
8885 // Unsigned integer DIVMOD with Register, both quotient and mod results
8886 instruct udivModI_rReg_divmod(rax_RegI rax, no_rax_rdx_RegI tmp, rdx_RegI rdx,
8887 no_rax_rdx_RegI div, rFlagsReg cr)
8888 %{
8889 match(UDivModI rax div);
8890 effect(TEMP tmp, KILL cr);
8891
8892 ins_cost(300);
8893 format %{ "udivl $rax,$rax,$div\t# begin UDivModI\n\t"
8894 "umodl $rdx,$rax,$div\t! using $tmp as TEMP # end UDivModI\n"
8895 %}
8896 ins_encode %{
8897 __ udivmodI($rax$$Register, $div$$Register, $rdx$$Register, $tmp$$Register);
8898 %}
8899 ins_pipe(pipe_slow);
8900 %}
8901
8902 // Unsigned long DIVMOD with Register, both quotient and mod results
8903 instruct udivModL_rReg_divmod(rax_RegL rax, no_rax_rdx_RegL tmp, rdx_RegL rdx,
8904 no_rax_rdx_RegL div, rFlagsReg cr)
8905 %{
8906 match(UDivModL rax div);
8907 effect(TEMP tmp, KILL cr);
8908
8909 ins_cost(300);
8910 format %{ "udivq $rax,$rax,$div\t# begin UDivModL\n\t"
8911 "umodq $rdx,$rax,$div\t! using $tmp as TEMP # end UDivModL\n"
8912 %}
8913 ins_encode %{
8914 __ udivmodL($rax$$Register, $div$$Register, $rdx$$Register, $tmp$$Register);
8915 %}
8916 ins_pipe(pipe_slow);
8917 %}
8918
8919 instruct modI_rReg(rdx_RegI rdx, rax_RegI rax, no_rax_rdx_RegI div,
8920 rFlagsReg cr)
8921 %{
8922 match(Set rdx (ModI rax div));
8923 effect(KILL rax, KILL cr);
8924
8925 ins_cost(300); // XXX
8926 format %{ "cmpl rax, 0x80000000\t# irem\n\t"
8927 "jne,s normal\n\t"
8928 "xorl rdx, rdx\n\t"
8929 "cmpl $div, -1\n\t"
8930 "je,s done\n"
8931 "normal: cdql\n\t"
8932 "idivl $div\n"
8933 "done:" %}
8934 ins_encode(cdql_enc(div));
8935 ins_pipe(ialu_reg_reg_alu0);
8936 %}
8937
8938 instruct modL_rReg(rdx_RegL rdx, rax_RegL rax, no_rax_rdx_RegL div,
8939 rFlagsReg cr)
8940 %{
8941 match(Set rdx (ModL rax div));
8942 effect(KILL rax, KILL cr);
8943
8944 ins_cost(300); // XXX
8945 format %{ "movq rdx, 0x8000000000000000\t# lrem\n\t"
8946 "cmpq rax, rdx\n\t"
8947 "jne,s normal\n\t"
8948 "xorl rdx, rdx\n\t"
8949 "cmpq $div, -1\n\t"
8950 "je,s done\n"
8951 "normal: cdqq\n\t"
8952 "idivq $div\n"
8953 "done:" %}
8954 ins_encode(cdqq_enc(div));
8955 ins_pipe(ialu_reg_reg_alu0);
8956 %}
8957
8958 instruct umodI_rReg(rdx_RegI rdx, rax_RegI rax, no_rax_rdx_RegI div, rFlagsReg cr)
8959 %{
8960 match(Set rdx (UModI rax div));
8961 effect(KILL rax, KILL cr);
8962
8963 ins_cost(300);
8964 format %{ "umodl $rdx,$rax,$div\t# UModI\n" %}
8965 ins_encode %{
8966 __ umodI($rax$$Register, $div$$Register, $rdx$$Register);
8967 %}
8968 ins_pipe(ialu_reg_reg_alu0);
8969 %}
8970
8971 instruct umodL_rReg(rdx_RegL rdx, rax_RegL rax, no_rax_rdx_RegL div, rFlagsReg cr)
8972 %{
8973 match(Set rdx (UModL rax div));
8974 effect(KILL rax, KILL cr);
8975
8976 ins_cost(300);
8977 format %{ "umodq $rdx,$rax,$div\t# UModL\n" %}
8978 ins_encode %{
8979 __ umodL($rax$$Register, $div$$Register, $rdx$$Register);
8980 %}
8981 ins_pipe(ialu_reg_reg_alu0);
8982 %}
8983
8984 // Integer Shift Instructions
8985 // Shift Left by one, two, three
8986 instruct salI_rReg_immI2(rRegI dst, immI2 shift, rFlagsReg cr)
8987 %{
8988 predicate(!UseAPX);
8989 match(Set dst (LShiftI dst shift));
8990 effect(KILL cr);
8991
8992 format %{ "sall $dst, $shift" %}
8993 ins_encode %{
8994 __ sall($dst$$Register, $shift$$constant);
8995 %}
8996 ins_pipe(ialu_reg);
8997 %}
8998
8999 // Shift Left by one, two, three
9000 instruct salI_rReg_immI2_ndd(rRegI dst, rRegI src, immI2 shift, rFlagsReg cr)
9001 %{
9002 predicate(UseAPX);
9003 match(Set dst (LShiftI src shift));
9004 effect(KILL cr);
9005
9006 format %{ "esall $dst, $src, $shift\t# int(ndd)" %}
9007 ins_encode %{
9008 __ esall($dst$$Register, $src$$Register, $shift$$constant, false);
9009 %}
9010 ins_pipe(ialu_reg);
9011 %}
9012
9013 // Shift Left by 8-bit immediate
9014 instruct salI_rReg_imm(rRegI dst, immI8 shift, rFlagsReg cr)
9015 %{
9016 predicate(!UseAPX);
9017 match(Set dst (LShiftI dst shift));
9018 effect(KILL cr);
9019
9020 format %{ "sall $dst, $shift" %}
9021 ins_encode %{
9022 __ sall($dst$$Register, $shift$$constant);
9023 %}
9024 ins_pipe(ialu_reg);
9025 %}
9026
9027 // Shift Left by 8-bit immediate
9028 instruct salI_rReg_imm_ndd(rRegI dst, rRegI src, immI8 shift, rFlagsReg cr)
9029 %{
9030 predicate(UseAPX);
9031 match(Set dst (LShiftI src shift));
9032 effect(KILL cr);
9033
9034 format %{ "esall $dst, $src, $shift\t# int (ndd)" %}
9035 ins_encode %{
9036 __ esall($dst$$Register, $src$$Register, $shift$$constant, false);
9037 %}
9038 ins_pipe(ialu_reg);
9039 %}
9040
9041 instruct salI_rReg_mem_imm_ndd(rRegI dst, memory src, immI8 shift, rFlagsReg cr)
9042 %{
9043 predicate(UseAPX);
9044 match(Set dst (LShiftI (LoadI src) shift));
9045 effect(KILL cr);
9046
9047 format %{ "esall $dst, $src, $shift\t# int (ndd)" %}
9048 ins_encode %{
9049 __ esall($dst$$Register, $src$$Address, $shift$$constant, false);
9050 %}
9051 ins_pipe(ialu_reg);
9052 %}
9053
9054 // Shift Left by 8-bit immediate
9055 instruct salI_mem_imm(memory dst, immI8 shift, rFlagsReg cr)
9056 %{
9057 match(Set dst (StoreI dst (LShiftI (LoadI dst) shift)));
9058 effect(KILL cr);
9059
9060 format %{ "sall $dst, $shift" %}
9061 ins_encode %{
9062 __ sall($dst$$Address, $shift$$constant);
9063 %}
9064 ins_pipe(ialu_mem_imm);
9065 %}
9066
9067 // Shift Left by variable
9068 instruct salI_rReg_CL(rRegI dst, rcx_RegI shift, rFlagsReg cr)
9069 %{
9070 predicate(!VM_Version::supports_bmi2());
9071 match(Set dst (LShiftI dst shift));
9072 effect(KILL cr);
9073
9074 format %{ "sall $dst, $shift" %}
9075 ins_encode %{
9076 __ sall($dst$$Register);
9077 %}
9078 ins_pipe(ialu_reg_reg);
9079 %}
9080
9081 // Shift Left by variable
9082 instruct salI_mem_CL(memory dst, rcx_RegI shift, rFlagsReg cr)
9083 %{
9084 predicate(!VM_Version::supports_bmi2());
9085 match(Set dst (StoreI dst (LShiftI (LoadI dst) shift)));
9086 effect(KILL cr);
9087
9088 format %{ "sall $dst, $shift" %}
9089 ins_encode %{
9090 __ sall($dst$$Address);
9091 %}
9092 ins_pipe(ialu_mem_reg);
9093 %}
9094
9095 instruct salI_rReg_rReg(rRegI dst, rRegI src, rRegI shift)
9096 %{
9097 predicate(VM_Version::supports_bmi2());
9098 match(Set dst (LShiftI src shift));
9099
9100 format %{ "shlxl $dst, $src, $shift" %}
9101 ins_encode %{
9102 __ shlxl($dst$$Register, $src$$Register, $shift$$Register);
9103 %}
9104 ins_pipe(ialu_reg_reg);
9105 %}
9106
9107 instruct salI_mem_rReg(rRegI dst, memory src, rRegI shift)
9108 %{
9109 predicate(VM_Version::supports_bmi2());
9110 match(Set dst (LShiftI (LoadI src) shift));
9111 ins_cost(175);
9112 format %{ "shlxl $dst, $src, $shift" %}
9113 ins_encode %{
9114 __ shlxl($dst$$Register, $src$$Address, $shift$$Register);
9115 %}
9116 ins_pipe(ialu_reg_mem);
9117 %}
9118
9119 // Arithmetic Shift Right by 8-bit immediate
9120 instruct sarI_rReg_imm(rRegI dst, immI8 shift, rFlagsReg cr)
9121 %{
9122 predicate(!UseAPX);
9123 match(Set dst (RShiftI dst shift));
9124 effect(KILL cr);
9125
9126 format %{ "sarl $dst, $shift" %}
9127 ins_encode %{
9128 __ sarl($dst$$Register, $shift$$constant);
9129 %}
9130 ins_pipe(ialu_mem_imm);
9131 %}
9132
9133 // Arithmetic Shift Right by 8-bit immediate
9134 instruct sarI_rReg_imm_ndd(rRegI dst, rRegI src, immI8 shift, rFlagsReg cr)
9135 %{
9136 predicate(UseAPX);
9137 match(Set dst (RShiftI src shift));
9138 effect(KILL cr);
9139
9140 format %{ "esarl $dst, $src, $shift\t# int (ndd)" %}
9141 ins_encode %{
9142 __ esarl($dst$$Register, $src$$Register, $shift$$constant, false);
9143 %}
9144 ins_pipe(ialu_mem_imm);
9145 %}
9146
9147 instruct sarI_rReg_mem_imm_ndd(rRegI dst, memory src, immI8 shift, rFlagsReg cr)
9148 %{
9149 predicate(UseAPX);
9150 match(Set dst (RShiftI (LoadI src) shift));
9151 effect(KILL cr);
9152
9153 format %{ "esarl $dst, $src, $shift\t# int (ndd)" %}
9154 ins_encode %{
9155 __ esarl($dst$$Register, $src$$Address, $shift$$constant, false);
9156 %}
9157 ins_pipe(ialu_mem_imm);
9158 %}
9159
9160 // Arithmetic Shift Right by 8-bit immediate
9161 instruct sarI_mem_imm(memory dst, immI8 shift, rFlagsReg cr)
9162 %{
9163 match(Set dst (StoreI dst (RShiftI (LoadI dst) shift)));
9164 effect(KILL cr);
9165
9166 format %{ "sarl $dst, $shift" %}
9167 ins_encode %{
9168 __ sarl($dst$$Address, $shift$$constant);
9169 %}
9170 ins_pipe(ialu_mem_imm);
9171 %}
9172
9173 // Arithmetic Shift Right by variable
9174 instruct sarI_rReg_CL(rRegI dst, rcx_RegI shift, rFlagsReg cr)
9175 %{
9176 predicate(!VM_Version::supports_bmi2());
9177 match(Set dst (RShiftI dst shift));
9178 effect(KILL cr);
9179
9180 format %{ "sarl $dst, $shift" %}
9181 ins_encode %{
9182 __ sarl($dst$$Register);
9183 %}
9184 ins_pipe(ialu_reg_reg);
9185 %}
9186
9187 // Arithmetic Shift Right by variable
9188 instruct sarI_mem_CL(memory dst, rcx_RegI shift, rFlagsReg cr)
9189 %{
9190 predicate(!VM_Version::supports_bmi2());
9191 match(Set dst (StoreI dst (RShiftI (LoadI dst) shift)));
9192 effect(KILL cr);
9193
9194 format %{ "sarl $dst, $shift" %}
9195 ins_encode %{
9196 __ sarl($dst$$Address);
9197 %}
9198 ins_pipe(ialu_mem_reg);
9199 %}
9200
9201 instruct sarI_rReg_rReg(rRegI dst, rRegI src, rRegI shift)
9202 %{
9203 predicate(VM_Version::supports_bmi2());
9204 match(Set dst (RShiftI src shift));
9205
9206 format %{ "sarxl $dst, $src, $shift" %}
9207 ins_encode %{
9208 __ sarxl($dst$$Register, $src$$Register, $shift$$Register);
9209 %}
9210 ins_pipe(ialu_reg_reg);
9211 %}
9212
9213 instruct sarI_mem_rReg(rRegI dst, memory src, rRegI shift)
9214 %{
9215 predicate(VM_Version::supports_bmi2());
9216 match(Set dst (RShiftI (LoadI src) shift));
9217 ins_cost(175);
9218 format %{ "sarxl $dst, $src, $shift" %}
9219 ins_encode %{
9220 __ sarxl($dst$$Register, $src$$Address, $shift$$Register);
9221 %}
9222 ins_pipe(ialu_reg_mem);
9223 %}
9224
9225 // Logical Shift Right by 8-bit immediate
9226 instruct shrI_rReg_imm(rRegI dst, immI8 shift, rFlagsReg cr)
9227 %{
9228 predicate(!UseAPX);
9229 match(Set dst (URShiftI dst shift));
9230 effect(KILL cr);
9231
9232 format %{ "shrl $dst, $shift" %}
9233 ins_encode %{
9234 __ shrl($dst$$Register, $shift$$constant);
9235 %}
9236 ins_pipe(ialu_reg);
9237 %}
9238
9239 // Logical Shift Right by 8-bit immediate
9240 instruct shrI_rReg_imm_ndd(rRegI dst, rRegI src, immI8 shift, rFlagsReg cr)
9241 %{
9242 predicate(UseAPX);
9243 match(Set dst (URShiftI src shift));
9244 effect(KILL cr);
9245
9246 format %{ "eshrl $dst, $src, $shift\t # int (ndd)" %}
9247 ins_encode %{
9248 __ eshrl($dst$$Register, $src$$Register, $shift$$constant, false);
9249 %}
9250 ins_pipe(ialu_reg);
9251 %}
9252
9253 instruct shrI_rReg_mem_imm_ndd(rRegI dst, memory src, immI8 shift, rFlagsReg cr)
9254 %{
9255 predicate(UseAPX);
9256 match(Set dst (URShiftI (LoadI src) shift));
9257 effect(KILL cr);
9258
9259 format %{ "eshrl $dst, $src, $shift\t # int (ndd)" %}
9260 ins_encode %{
9261 __ eshrl($dst$$Register, $src$$Address, $shift$$constant, false);
9262 %}
9263 ins_pipe(ialu_reg);
9264 %}
9265
9266 // Logical Shift Right by 8-bit immediate
9267 instruct shrI_mem_imm(memory dst, immI8 shift, rFlagsReg cr)
9268 %{
9269 match(Set dst (StoreI dst (URShiftI (LoadI dst) shift)));
9270 effect(KILL cr);
9271
9272 format %{ "shrl $dst, $shift" %}
9273 ins_encode %{
9274 __ shrl($dst$$Address, $shift$$constant);
9275 %}
9276 ins_pipe(ialu_mem_imm);
9277 %}
9278
9279 // Logical Shift Right by variable
9280 instruct shrI_rReg_CL(rRegI dst, rcx_RegI shift, rFlagsReg cr)
9281 %{
9282 predicate(!VM_Version::supports_bmi2());
9283 match(Set dst (URShiftI dst shift));
9284 effect(KILL cr);
9285
9286 format %{ "shrl $dst, $shift" %}
9287 ins_encode %{
9288 __ shrl($dst$$Register);
9289 %}
9290 ins_pipe(ialu_reg_reg);
9291 %}
9292
9293 // Logical Shift Right by variable
9294 instruct shrI_mem_CL(memory dst, rcx_RegI shift, rFlagsReg cr)
9295 %{
9296 predicate(!VM_Version::supports_bmi2());
9297 match(Set dst (StoreI dst (URShiftI (LoadI dst) shift)));
9298 effect(KILL cr);
9299
9300 format %{ "shrl $dst, $shift" %}
9301 ins_encode %{
9302 __ shrl($dst$$Address);
9303 %}
9304 ins_pipe(ialu_mem_reg);
9305 %}
9306
9307 instruct shrI_rReg_rReg(rRegI dst, rRegI src, rRegI shift)
9308 %{
9309 predicate(VM_Version::supports_bmi2());
9310 match(Set dst (URShiftI src shift));
9311
9312 format %{ "shrxl $dst, $src, $shift" %}
9313 ins_encode %{
9314 __ shrxl($dst$$Register, $src$$Register, $shift$$Register);
9315 %}
9316 ins_pipe(ialu_reg_reg);
9317 %}
9318
9319 instruct shrI_mem_rReg(rRegI dst, memory src, rRegI shift)
9320 %{
9321 predicate(VM_Version::supports_bmi2());
9322 match(Set dst (URShiftI (LoadI src) shift));
9323 ins_cost(175);
9324 format %{ "shrxl $dst, $src, $shift" %}
9325 ins_encode %{
9326 __ shrxl($dst$$Register, $src$$Address, $shift$$Register);
9327 %}
9328 ins_pipe(ialu_reg_mem);
9329 %}
9330
9331 // Long Shift Instructions
9332 // Shift Left by one, two, three
9333 instruct salL_rReg_immI2(rRegL dst, immI2 shift, rFlagsReg cr)
9334 %{
9335 predicate(!UseAPX);
9336 match(Set dst (LShiftL dst shift));
9337 effect(KILL cr);
9338
9339 format %{ "salq $dst, $shift" %}
9340 ins_encode %{
9341 __ salq($dst$$Register, $shift$$constant);
9342 %}
9343 ins_pipe(ialu_reg);
9344 %}
9345
9346 // Shift Left by one, two, three
9347 instruct salL_rReg_immI2_ndd(rRegL dst, rRegL src, immI2 shift, rFlagsReg cr)
9348 %{
9349 predicate(UseAPX);
9350 match(Set dst (LShiftL src shift));
9351 effect(KILL cr);
9352
9353 format %{ "esalq $dst, $src, $shift\t# long (ndd)" %}
9354 ins_encode %{
9355 __ esalq($dst$$Register, $src$$Register, $shift$$constant, false);
9356 %}
9357 ins_pipe(ialu_reg);
9358 %}
9359
9360 // Shift Left by 8-bit immediate
9361 instruct salL_rReg_imm(rRegL dst, immI8 shift, rFlagsReg cr)
9362 %{
9363 predicate(!UseAPX);
9364 match(Set dst (LShiftL dst shift));
9365 effect(KILL cr);
9366
9367 format %{ "salq $dst, $shift" %}
9368 ins_encode %{
9369 __ salq($dst$$Register, $shift$$constant);
9370 %}
9371 ins_pipe(ialu_reg);
9372 %}
9373
9374 // Shift Left by 8-bit immediate
9375 instruct salL_rReg_imm_ndd(rRegL dst, rRegL src, immI8 shift, rFlagsReg cr)
9376 %{
9377 predicate(UseAPX);
9378 match(Set dst (LShiftL src shift));
9379 effect(KILL cr);
9380
9381 format %{ "esalq $dst, $src, $shift\t# long (ndd)" %}
9382 ins_encode %{
9383 __ esalq($dst$$Register, $src$$Register, $shift$$constant, false);
9384 %}
9385 ins_pipe(ialu_reg);
9386 %}
9387
9388 instruct salL_rReg_mem_imm_ndd(rRegL dst, memory src, immI8 shift, rFlagsReg cr)
9389 %{
9390 predicate(UseAPX);
9391 match(Set dst (LShiftL (LoadL src) shift));
9392 effect(KILL cr);
9393
9394 format %{ "esalq $dst, $src, $shift\t# long (ndd)" %}
9395 ins_encode %{
9396 __ esalq($dst$$Register, $src$$Address, $shift$$constant, false);
9397 %}
9398 ins_pipe(ialu_reg);
9399 %}
9400
9401 // Shift Left by 8-bit immediate
9402 instruct salL_mem_imm(memory dst, immI8 shift, rFlagsReg cr)
9403 %{
9404 match(Set dst (StoreL dst (LShiftL (LoadL dst) shift)));
9405 effect(KILL cr);
9406
9407 format %{ "salq $dst, $shift" %}
9408 ins_encode %{
9409 __ salq($dst$$Address, $shift$$constant);
9410 %}
9411 ins_pipe(ialu_mem_imm);
9412 %}
9413
9414 // Shift Left by variable
9415 instruct salL_rReg_CL(rRegL dst, rcx_RegI shift, rFlagsReg cr)
9416 %{
9417 predicate(!VM_Version::supports_bmi2());
9418 match(Set dst (LShiftL dst shift));
9419 effect(KILL cr);
9420
9421 format %{ "salq $dst, $shift" %}
9422 ins_encode %{
9423 __ salq($dst$$Register);
9424 %}
9425 ins_pipe(ialu_reg_reg);
9426 %}
9427
9428 // Shift Left by variable
9429 instruct salL_mem_CL(memory dst, rcx_RegI shift, rFlagsReg cr)
9430 %{
9431 predicate(!VM_Version::supports_bmi2());
9432 match(Set dst (StoreL dst (LShiftL (LoadL dst) shift)));
9433 effect(KILL cr);
9434
9435 format %{ "salq $dst, $shift" %}
9436 ins_encode %{
9437 __ salq($dst$$Address);
9438 %}
9439 ins_pipe(ialu_mem_reg);
9440 %}
9441
9442 instruct salL_rReg_rReg(rRegL dst, rRegL src, rRegI shift)
9443 %{
9444 predicate(VM_Version::supports_bmi2());
9445 match(Set dst (LShiftL src shift));
9446
9447 format %{ "shlxq $dst, $src, $shift" %}
9448 ins_encode %{
9449 __ shlxq($dst$$Register, $src$$Register, $shift$$Register);
9450 %}
9451 ins_pipe(ialu_reg_reg);
9452 %}
9453
9454 instruct salL_mem_rReg(rRegL dst, memory src, rRegI shift)
9455 %{
9456 predicate(VM_Version::supports_bmi2());
9457 match(Set dst (LShiftL (LoadL src) shift));
9458 ins_cost(175);
9459 format %{ "shlxq $dst, $src, $shift" %}
9460 ins_encode %{
9461 __ shlxq($dst$$Register, $src$$Address, $shift$$Register);
9462 %}
9463 ins_pipe(ialu_reg_mem);
9464 %}
9465
9466 // Arithmetic Shift Right by 8-bit immediate
9467 instruct sarL_rReg_imm(rRegL dst, immI shift, rFlagsReg cr)
9468 %{
9469 predicate(!UseAPX);
9470 match(Set dst (RShiftL dst shift));
9471 effect(KILL cr);
9472
9473 format %{ "sarq $dst, $shift" %}
9474 ins_encode %{
9475 __ sarq($dst$$Register, (unsigned char)($shift$$constant & 0x3F));
9476 %}
9477 ins_pipe(ialu_mem_imm);
9478 %}
9479
9480 // Arithmetic Shift Right by 8-bit immediate
9481 instruct sarL_rReg_imm_ndd(rRegL dst, rRegL src, immI shift, rFlagsReg cr)
9482 %{
9483 predicate(UseAPX);
9484 match(Set dst (RShiftL src shift));
9485 effect(KILL cr);
9486
9487 format %{ "esarq $dst, $src, $shift\t# long (ndd)" %}
9488 ins_encode %{
9489 __ esarq($dst$$Register, $src$$Register, (unsigned char)($shift$$constant & 0x3F), false);
9490 %}
9491 ins_pipe(ialu_mem_imm);
9492 %}
9493
9494 instruct sarL_rReg_mem_imm_ndd(rRegL dst, memory src, immI shift, rFlagsReg cr)
9495 %{
9496 predicate(UseAPX);
9497 match(Set dst (RShiftL (LoadL src) shift));
9498 effect(KILL cr);
9499
9500 format %{ "esarq $dst, $src, $shift\t# long (ndd)" %}
9501 ins_encode %{
9502 __ esarq($dst$$Register, $src$$Address, (unsigned char)($shift$$constant & 0x3F), false);
9503 %}
9504 ins_pipe(ialu_mem_imm);
9505 %}
9506
9507 // Arithmetic Shift Right by 8-bit immediate
9508 instruct sarL_mem_imm(memory dst, immI shift, rFlagsReg cr)
9509 %{
9510 match(Set dst (StoreL dst (RShiftL (LoadL dst) shift)));
9511 effect(KILL cr);
9512
9513 format %{ "sarq $dst, $shift" %}
9514 ins_encode %{
9515 __ sarq($dst$$Address, (unsigned char)($shift$$constant & 0x3F));
9516 %}
9517 ins_pipe(ialu_mem_imm);
9518 %}
9519
9520 // Arithmetic Shift Right by variable
9521 instruct sarL_rReg_CL(rRegL dst, rcx_RegI shift, rFlagsReg cr)
9522 %{
9523 predicate(!VM_Version::supports_bmi2());
9524 match(Set dst (RShiftL dst shift));
9525 effect(KILL cr);
9526
9527 format %{ "sarq $dst, $shift" %}
9528 ins_encode %{
9529 __ sarq($dst$$Register);
9530 %}
9531 ins_pipe(ialu_reg_reg);
9532 %}
9533
9534 // Arithmetic Shift Right by variable
9535 instruct sarL_mem_CL(memory dst, rcx_RegI shift, rFlagsReg cr)
9536 %{
9537 predicate(!VM_Version::supports_bmi2());
9538 match(Set dst (StoreL dst (RShiftL (LoadL dst) shift)));
9539 effect(KILL cr);
9540
9541 format %{ "sarq $dst, $shift" %}
9542 ins_encode %{
9543 __ sarq($dst$$Address);
9544 %}
9545 ins_pipe(ialu_mem_reg);
9546 %}
9547
9548 instruct sarL_rReg_rReg(rRegL dst, rRegL src, rRegI shift)
9549 %{
9550 predicate(VM_Version::supports_bmi2());
9551 match(Set dst (RShiftL src shift));
9552
9553 format %{ "sarxq $dst, $src, $shift" %}
9554 ins_encode %{
9555 __ sarxq($dst$$Register, $src$$Register, $shift$$Register);
9556 %}
9557 ins_pipe(ialu_reg_reg);
9558 %}
9559
9560 instruct sarL_mem_rReg(rRegL dst, memory src, rRegI shift)
9561 %{
9562 predicate(VM_Version::supports_bmi2());
9563 match(Set dst (RShiftL (LoadL src) shift));
9564 ins_cost(175);
9565 format %{ "sarxq $dst, $src, $shift" %}
9566 ins_encode %{
9567 __ sarxq($dst$$Register, $src$$Address, $shift$$Register);
9568 %}
9569 ins_pipe(ialu_reg_mem);
9570 %}
9571
9572 // Logical Shift Right by 8-bit immediate
9573 instruct shrL_rReg_imm(rRegL dst, immI8 shift, rFlagsReg cr)
9574 %{
9575 predicate(!UseAPX);
9576 match(Set dst (URShiftL dst shift));
9577 effect(KILL cr);
9578
9579 format %{ "shrq $dst, $shift" %}
9580 ins_encode %{
9581 __ shrq($dst$$Register, $shift$$constant);
9582 %}
9583 ins_pipe(ialu_reg);
9584 %}
9585
9586 // Logical Shift Right by 8-bit immediate
9587 instruct shrL_rReg_imm_ndd(rRegL dst, rRegL src, immI8 shift, rFlagsReg cr)
9588 %{
9589 predicate(UseAPX);
9590 match(Set dst (URShiftL src shift));
9591 effect(KILL cr);
9592
9593 format %{ "eshrq $dst, $src, $shift\t# long (ndd)" %}
9594 ins_encode %{
9595 __ eshrq($dst$$Register, $src$$Register, $shift$$constant, false);
9596 %}
9597 ins_pipe(ialu_reg);
9598 %}
9599
9600 instruct shrL_rReg_mem_imm_ndd(rRegL dst, memory src, immI8 shift, rFlagsReg cr)
9601 %{
9602 predicate(UseAPX);
9603 match(Set dst (URShiftL (LoadL src) shift));
9604 effect(KILL cr);
9605
9606 format %{ "eshrq $dst, $src, $shift\t# long (ndd)" %}
9607 ins_encode %{
9608 __ eshrq($dst$$Register, $src$$Address, $shift$$constant, false);
9609 %}
9610 ins_pipe(ialu_reg);
9611 %}
9612
9613 // Logical Shift Right by 8-bit immediate
9614 instruct shrL_mem_imm(memory dst, immI8 shift, rFlagsReg cr)
9615 %{
9616 match(Set dst (StoreL dst (URShiftL (LoadL dst) shift)));
9617 effect(KILL cr);
9618
9619 format %{ "shrq $dst, $shift" %}
9620 ins_encode %{
9621 __ shrq($dst$$Address, $shift$$constant);
9622 %}
9623 ins_pipe(ialu_mem_imm);
9624 %}
9625
9626 // Logical Shift Right by variable
9627 instruct shrL_rReg_CL(rRegL dst, rcx_RegI shift, rFlagsReg cr)
9628 %{
9629 predicate(!VM_Version::supports_bmi2());
9630 match(Set dst (URShiftL dst shift));
9631 effect(KILL cr);
9632
9633 format %{ "shrq $dst, $shift" %}
9634 ins_encode %{
9635 __ shrq($dst$$Register);
9636 %}
9637 ins_pipe(ialu_reg_reg);
9638 %}
9639
9640 // Logical Shift Right by variable
9641 instruct shrL_mem_CL(memory dst, rcx_RegI shift, rFlagsReg cr)
9642 %{
9643 predicate(!VM_Version::supports_bmi2());
9644 match(Set dst (StoreL dst (URShiftL (LoadL dst) shift)));
9645 effect(KILL cr);
9646
9647 format %{ "shrq $dst, $shift" %}
9648 ins_encode %{
9649 __ shrq($dst$$Address);
9650 %}
9651 ins_pipe(ialu_mem_reg);
9652 %}
9653
9654 instruct shrL_rReg_rReg(rRegL dst, rRegL src, rRegI shift)
9655 %{
9656 predicate(VM_Version::supports_bmi2());
9657 match(Set dst (URShiftL src shift));
9658
9659 format %{ "shrxq $dst, $src, $shift" %}
9660 ins_encode %{
9661 __ shrxq($dst$$Register, $src$$Register, $shift$$Register);
9662 %}
9663 ins_pipe(ialu_reg_reg);
9664 %}
9665
9666 instruct shrL_mem_rReg(rRegL dst, memory src, rRegI shift)
9667 %{
9668 predicate(VM_Version::supports_bmi2());
9669 match(Set dst (URShiftL (LoadL src) shift));
9670 ins_cost(175);
9671 format %{ "shrxq $dst, $src, $shift" %}
9672 ins_encode %{
9673 __ shrxq($dst$$Register, $src$$Address, $shift$$Register);
9674 %}
9675 ins_pipe(ialu_reg_mem);
9676 %}
9677
9678 // Logical Shift Right by 24, followed by Arithmetic Shift Left by 24.
9679 // This idiom is used by the compiler for the i2b bytecode.
9680 instruct i2b(rRegI dst, rRegI src, immI_24 twentyfour)
9681 %{
9682 match(Set dst (RShiftI (LShiftI src twentyfour) twentyfour));
9683
9684 format %{ "movsbl $dst, $src\t# i2b" %}
9685 ins_encode %{
9686 __ movsbl($dst$$Register, $src$$Register);
9687 %}
9688 ins_pipe(ialu_reg_reg);
9689 %}
9690
9691 // Logical Shift Right by 16, followed by Arithmetic Shift Left by 16.
9692 // This idiom is used by the compiler the i2s bytecode.
9693 instruct i2s(rRegI dst, rRegI src, immI_16 sixteen)
9694 %{
9695 match(Set dst (RShiftI (LShiftI src sixteen) sixteen));
9696
9697 format %{ "movswl $dst, $src\t# i2s" %}
9698 ins_encode %{
9699 __ movswl($dst$$Register, $src$$Register);
9700 %}
9701 ins_pipe(ialu_reg_reg);
9702 %}
9703
9704 // ROL/ROR instructions
9705
9706 // Rotate left by constant.
9707 instruct rolI_immI8_legacy(rRegI dst, immI8 shift, rFlagsReg cr)
9708 %{
9709 predicate(!VM_Version::supports_bmi2() && n->bottom_type()->basic_type() == T_INT);
9710 match(Set dst (RotateLeft dst shift));
9711 effect(KILL cr);
9712 format %{ "roll $dst, $shift" %}
9713 ins_encode %{
9714 __ roll($dst$$Register, $shift$$constant);
9715 %}
9716 ins_pipe(ialu_reg);
9717 %}
9718
9719 instruct rolI_immI8(rRegI dst, rRegI src, immI8 shift)
9720 %{
9721 predicate(!UseAPX && VM_Version::supports_bmi2() && n->bottom_type()->basic_type() == T_INT);
9722 match(Set dst (RotateLeft src shift));
9723 format %{ "rolxl $dst, $src, $shift" %}
9724 ins_encode %{
9725 int shift = 32 - ($shift$$constant & 31);
9726 __ rorxl($dst$$Register, $src$$Register, shift);
9727 %}
9728 ins_pipe(ialu_reg_reg);
9729 %}
9730
9731 instruct rolI_mem_immI8(rRegI dst, memory src, immI8 shift)
9732 %{
9733 predicate(VM_Version::supports_bmi2() && n->bottom_type()->basic_type() == T_INT);
9734 match(Set dst (RotateLeft (LoadI src) shift));
9735 ins_cost(175);
9736 format %{ "rolxl $dst, $src, $shift" %}
9737 ins_encode %{
9738 int shift = 32 - ($shift$$constant & 31);
9739 __ rorxl($dst$$Register, $src$$Address, shift);
9740 %}
9741 ins_pipe(ialu_reg_mem);
9742 %}
9743
9744 // Rotate Left by variable
9745 instruct rolI_rReg_Var(rRegI dst, rcx_RegI shift, rFlagsReg cr)
9746 %{
9747 predicate(!UseAPX && n->bottom_type()->basic_type() == T_INT);
9748 match(Set dst (RotateLeft dst shift));
9749 effect(KILL cr);
9750 format %{ "roll $dst, $shift" %}
9751 ins_encode %{
9752 __ roll($dst$$Register);
9753 %}
9754 ins_pipe(ialu_reg_reg);
9755 %}
9756
9757 // Rotate Left by variable
9758 instruct rolI_rReg_Var_ndd(rRegI dst, rRegI src, rcx_RegI shift, rFlagsReg cr)
9759 %{
9760 predicate(UseAPX && n->bottom_type()->basic_type() == T_INT);
9761 match(Set dst (RotateLeft src shift));
9762 effect(KILL cr);
9763
9764 format %{ "eroll $dst, $src, $shift\t# rotate left (int ndd)" %}
9765 ins_encode %{
9766 __ eroll($dst$$Register, $src$$Register, false);
9767 %}
9768 ins_pipe(ialu_reg_reg);
9769 %}
9770
9771 // Rotate Right by constant.
9772 instruct rorI_immI8_legacy(rRegI dst, immI8 shift, rFlagsReg cr)
9773 %{
9774 predicate(!VM_Version::supports_bmi2() && n->bottom_type()->basic_type() == T_INT);
9775 match(Set dst (RotateRight dst shift));
9776 effect(KILL cr);
9777 format %{ "rorl $dst, $shift" %}
9778 ins_encode %{
9779 __ rorl($dst$$Register, $shift$$constant);
9780 %}
9781 ins_pipe(ialu_reg);
9782 %}
9783
9784 // Rotate Right by constant.
9785 instruct rorI_immI8(rRegI dst, rRegI src, immI8 shift)
9786 %{
9787 predicate(!UseAPX && VM_Version::supports_bmi2() && n->bottom_type()->basic_type() == T_INT);
9788 match(Set dst (RotateRight src shift));
9789 format %{ "rorxl $dst, $src, $shift" %}
9790 ins_encode %{
9791 __ rorxl($dst$$Register, $src$$Register, $shift$$constant);
9792 %}
9793 ins_pipe(ialu_reg_reg);
9794 %}
9795
9796 instruct rorI_mem_immI8(rRegI dst, memory src, immI8 shift)
9797 %{
9798 predicate(VM_Version::supports_bmi2() && n->bottom_type()->basic_type() == T_INT);
9799 match(Set dst (RotateRight (LoadI src) shift));
9800 ins_cost(175);
9801 format %{ "rorxl $dst, $src, $shift" %}
9802 ins_encode %{
9803 __ rorxl($dst$$Register, $src$$Address, $shift$$constant);
9804 %}
9805 ins_pipe(ialu_reg_mem);
9806 %}
9807
9808 // Rotate Right by variable
9809 instruct rorI_rReg_Var(rRegI dst, rcx_RegI shift, rFlagsReg cr)
9810 %{
9811 predicate(!UseAPX && n->bottom_type()->basic_type() == T_INT);
9812 match(Set dst (RotateRight dst shift));
9813 effect(KILL cr);
9814 format %{ "rorl $dst, $shift" %}
9815 ins_encode %{
9816 __ rorl($dst$$Register);
9817 %}
9818 ins_pipe(ialu_reg_reg);
9819 %}
9820
9821 // Rotate Right by variable
9822 instruct rorI_rReg_Var_ndd(rRegI dst, rRegI src, rcx_RegI shift, rFlagsReg cr)
9823 %{
9824 predicate(UseAPX && n->bottom_type()->basic_type() == T_INT);
9825 match(Set dst (RotateRight src shift));
9826 effect(KILL cr);
9827
9828 format %{ "erorl $dst, $src, $shift\t# rotate right(int ndd)" %}
9829 ins_encode %{
9830 __ erorl($dst$$Register, $src$$Register, false);
9831 %}
9832 ins_pipe(ialu_reg_reg);
9833 %}
9834
9835 // Rotate Left by constant.
9836 instruct rolL_immI8_legacy(rRegL dst, immI8 shift, rFlagsReg cr)
9837 %{
9838 predicate(!VM_Version::supports_bmi2() && n->bottom_type()->basic_type() == T_LONG);
9839 match(Set dst (RotateLeft dst shift));
9840 effect(KILL cr);
9841 format %{ "rolq $dst, $shift" %}
9842 ins_encode %{
9843 __ rolq($dst$$Register, $shift$$constant);
9844 %}
9845 ins_pipe(ialu_reg);
9846 %}
9847
9848 instruct rolL_immI8(rRegL dst, rRegL src, immI8 shift)
9849 %{
9850 predicate(!UseAPX && VM_Version::supports_bmi2() && n->bottom_type()->basic_type() == T_LONG);
9851 match(Set dst (RotateLeft src shift));
9852 format %{ "rolxq $dst, $src, $shift" %}
9853 ins_encode %{
9854 int shift = 64 - ($shift$$constant & 63);
9855 __ rorxq($dst$$Register, $src$$Register, shift);
9856 %}
9857 ins_pipe(ialu_reg_reg);
9858 %}
9859
9860 instruct rolL_mem_immI8(rRegL dst, memory src, immI8 shift)
9861 %{
9862 predicate(VM_Version::supports_bmi2() && n->bottom_type()->basic_type() == T_LONG);
9863 match(Set dst (RotateLeft (LoadL src) shift));
9864 ins_cost(175);
9865 format %{ "rolxq $dst, $src, $shift" %}
9866 ins_encode %{
9867 int shift = 64 - ($shift$$constant & 63);
9868 __ rorxq($dst$$Register, $src$$Address, shift);
9869 %}
9870 ins_pipe(ialu_reg_mem);
9871 %}
9872
9873 // Rotate Left by variable
9874 instruct rolL_rReg_Var(rRegL dst, rcx_RegI shift, rFlagsReg cr)
9875 %{
9876 predicate(!UseAPX && n->bottom_type()->basic_type() == T_LONG);
9877 match(Set dst (RotateLeft dst shift));
9878 effect(KILL cr);
9879 format %{ "rolq $dst, $shift" %}
9880 ins_encode %{
9881 __ rolq($dst$$Register);
9882 %}
9883 ins_pipe(ialu_reg_reg);
9884 %}
9885
9886 // Rotate Left by variable
9887 instruct rolL_rReg_Var_ndd(rRegL dst, rRegL src, rcx_RegI shift, rFlagsReg cr)
9888 %{
9889 predicate(UseAPX && n->bottom_type()->basic_type() == T_LONG);
9890 match(Set dst (RotateLeft src shift));
9891 effect(KILL cr);
9892
9893 format %{ "erolq $dst, $src, $shift\t# rotate left(long ndd)" %}
9894 ins_encode %{
9895 __ erolq($dst$$Register, $src$$Register, false);
9896 %}
9897 ins_pipe(ialu_reg_reg);
9898 %}
9899
9900 // Rotate Right by constant.
9901 instruct rorL_immI8_legacy(rRegL dst, immI8 shift, rFlagsReg cr)
9902 %{
9903 predicate(!VM_Version::supports_bmi2() && n->bottom_type()->basic_type() == T_LONG);
9904 match(Set dst (RotateRight dst shift));
9905 effect(KILL cr);
9906 format %{ "rorq $dst, $shift" %}
9907 ins_encode %{
9908 __ rorq($dst$$Register, $shift$$constant);
9909 %}
9910 ins_pipe(ialu_reg);
9911 %}
9912
9913 // Rotate Right by constant
9914 instruct rorL_immI8(rRegL dst, rRegL src, immI8 shift)
9915 %{
9916 predicate(VM_Version::supports_bmi2() && n->bottom_type()->basic_type() == T_LONG);
9917 match(Set dst (RotateRight src shift));
9918 format %{ "rorxq $dst, $src, $shift" %}
9919 ins_encode %{
9920 __ rorxq($dst$$Register, $src$$Register, $shift$$constant);
9921 %}
9922 ins_pipe(ialu_reg_reg);
9923 %}
9924
9925 instruct rorL_mem_immI8(rRegL dst, memory src, immI8 shift)
9926 %{
9927 predicate(VM_Version::supports_bmi2() && n->bottom_type()->basic_type() == T_LONG);
9928 match(Set dst (RotateRight (LoadL src) shift));
9929 ins_cost(175);
9930 format %{ "rorxq $dst, $src, $shift" %}
9931 ins_encode %{
9932 __ rorxq($dst$$Register, $src$$Address, $shift$$constant);
9933 %}
9934 ins_pipe(ialu_reg_mem);
9935 %}
9936
9937 // Rotate Right by variable
9938 instruct rorL_rReg_Var(rRegL dst, rcx_RegI shift, rFlagsReg cr)
9939 %{
9940 predicate(!UseAPX && n->bottom_type()->basic_type() == T_LONG);
9941 match(Set dst (RotateRight dst shift));
9942 effect(KILL cr);
9943 format %{ "rorq $dst, $shift" %}
9944 ins_encode %{
9945 __ rorq($dst$$Register);
9946 %}
9947 ins_pipe(ialu_reg_reg);
9948 %}
9949
9950 // Rotate Right by variable
9951 instruct rorL_rReg_Var_ndd(rRegL dst, rRegL src, rcx_RegI shift, rFlagsReg cr)
9952 %{
9953 predicate(UseAPX && n->bottom_type()->basic_type() == T_LONG);
9954 match(Set dst (RotateRight src shift));
9955 effect(KILL cr);
9956
9957 format %{ "erorq $dst, $src, $shift\t# rotate right(long ndd)" %}
9958 ins_encode %{
9959 __ erorq($dst$$Register, $src$$Register, false);
9960 %}
9961 ins_pipe(ialu_reg_reg);
9962 %}
9963
9964 //----------------------------- CompressBits/ExpandBits ------------------------
9965
9966 instruct compressBitsL_reg(rRegL dst, rRegL src, rRegL mask) %{
9967 predicate(n->bottom_type()->isa_long());
9968 match(Set dst (CompressBits src mask));
9969 format %{ "pextq $dst, $src, $mask\t! parallel bit extract" %}
9970 ins_encode %{
9971 __ pextq($dst$$Register, $src$$Register, $mask$$Register);
9972 %}
9973 ins_pipe( pipe_slow );
9974 %}
9975
9976 instruct expandBitsL_reg(rRegL dst, rRegL src, rRegL mask) %{
9977 predicate(n->bottom_type()->isa_long());
9978 match(Set dst (ExpandBits src mask));
9979 format %{ "pdepq $dst, $src, $mask\t! parallel bit deposit" %}
9980 ins_encode %{
9981 __ pdepq($dst$$Register, $src$$Register, $mask$$Register);
9982 %}
9983 ins_pipe( pipe_slow );
9984 %}
9985
9986 instruct compressBitsL_mem(rRegL dst, rRegL src, memory mask) %{
9987 predicate(n->bottom_type()->isa_long());
9988 match(Set dst (CompressBits src (LoadL mask)));
9989 format %{ "pextq $dst, $src, $mask\t! parallel bit extract" %}
9990 ins_encode %{
9991 __ pextq($dst$$Register, $src$$Register, $mask$$Address);
9992 %}
9993 ins_pipe( pipe_slow );
9994 %}
9995
9996 instruct expandBitsL_mem(rRegL dst, rRegL src, memory mask) %{
9997 predicate(n->bottom_type()->isa_long());
9998 match(Set dst (ExpandBits src (LoadL mask)));
9999 format %{ "pdepq $dst, $src, $mask\t! parallel bit deposit" %}
10000 ins_encode %{
10001 __ pdepq($dst$$Register, $src$$Register, $mask$$Address);
10002 %}
10003 ins_pipe( pipe_slow );
10004 %}
10005
10006
10007 // Logical Instructions
10008
10009 // Integer Logical Instructions
10010
10011 // And Instructions
10012 // And Register with Register
10013 instruct andI_rReg(rRegI dst, rRegI src, rFlagsReg cr)
10014 %{
10015 predicate(!UseAPX);
10016 match(Set dst (AndI dst src));
10017 effect(KILL cr);
10018 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);
10019
10020 format %{ "andl $dst, $src\t# int" %}
10021 ins_encode %{
10022 __ andl($dst$$Register, $src$$Register);
10023 %}
10024 ins_pipe(ialu_reg_reg);
10025 %}
10026
10027 // And Register with Register using New Data Destination (NDD)
10028 instruct andI_rReg_ndd(rRegI dst, rRegI src1, rRegI src2, rFlagsReg cr)
10029 %{
10030 predicate(UseAPX);
10031 match(Set dst (AndI src1 src2));
10032 effect(KILL cr);
10033 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);
10034
10035 format %{ "eandl $dst, $src1, $src2\t# int ndd" %}
10036 ins_encode %{
10037 __ eandl($dst$$Register, $src1$$Register, $src2$$Register, false);
10038
10039 %}
10040 ins_pipe(ialu_reg_reg);
10041 %}
10042
10043 // And Register with Immediate 255
10044 instruct andI_rReg_imm255(rRegI dst, rRegI src, immI_255 mask)
10045 %{
10046 match(Set dst (AndI src mask));
10047
10048 format %{ "movzbl $dst, $src\t# int & 0xFF" %}
10049 ins_encode %{
10050 __ movzbl($dst$$Register, $src$$Register);
10051 %}
10052 ins_pipe(ialu_reg);
10053 %}
10054
10055 // And Register with Immediate 255 and promote to long
10056 instruct andI2L_rReg_imm255(rRegL dst, rRegI src, immI_255 mask)
10057 %{
10058 match(Set dst (ConvI2L (AndI src mask)));
10059
10060 format %{ "movzbl $dst, $src\t# int & 0xFF -> long" %}
10061 ins_encode %{
10062 __ movzbl($dst$$Register, $src$$Register);
10063 %}
10064 ins_pipe(ialu_reg);
10065 %}
10066
10067 // And Register with Immediate 65535
10068 instruct andI_rReg_imm65535(rRegI dst, rRegI src, immI_65535 mask)
10069 %{
10070 match(Set dst (AndI src mask));
10071
10072 format %{ "movzwl $dst, $src\t# int & 0xFFFF" %}
10073 ins_encode %{
10074 __ movzwl($dst$$Register, $src$$Register);
10075 %}
10076 ins_pipe(ialu_reg);
10077 %}
10078
10079 // And Register with Immediate 65535 and promote to long
10080 instruct andI2L_rReg_imm65535(rRegL dst, rRegI src, immI_65535 mask)
10081 %{
10082 match(Set dst (ConvI2L (AndI src mask)));
10083
10084 format %{ "movzwl $dst, $src\t# int & 0xFFFF -> long" %}
10085 ins_encode %{
10086 __ movzwl($dst$$Register, $src$$Register);
10087 %}
10088 ins_pipe(ialu_reg);
10089 %}
10090
10091 // Can skip int2long conversions after AND with small bitmask
10092 instruct convI2LAndI_reg_immIbitmask(rRegL dst, rRegI src, immI_Pow2M1 mask, rRegI tmp, rFlagsReg cr)
10093 %{
10094 predicate(VM_Version::supports_bmi2());
10095 ins_cost(125);
10096 effect(TEMP tmp, KILL cr);
10097 match(Set dst (ConvI2L (AndI src mask)));
10098 format %{ "bzhiq $dst, $src, $mask \t# using $tmp as TEMP, int & immI_Pow2M1 -> long" %}
10099 ins_encode %{
10100 __ movl($tmp$$Register, exact_log2($mask$$constant + 1));
10101 __ bzhiq($dst$$Register, $src$$Register, $tmp$$Register);
10102 %}
10103 ins_pipe(ialu_reg_reg);
10104 %}
10105
10106 // And Register with Immediate
10107 instruct andI_rReg_imm(rRegI dst, immI src, rFlagsReg cr)
10108 %{
10109 predicate(!UseAPX);
10110 match(Set dst (AndI dst src));
10111 effect(KILL cr);
10112 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);
10113
10114 format %{ "andl $dst, $src\t# int" %}
10115 ins_encode %{
10116 __ andl($dst$$Register, $src$$constant);
10117 %}
10118 ins_pipe(ialu_reg);
10119 %}
10120
10121 instruct andI_rReg_rReg_imm_ndd(rRegI dst, rRegI src1, immI src2, rFlagsReg cr)
10122 %{
10123 predicate(UseAPX);
10124 match(Set dst (AndI src1 src2));
10125 effect(KILL cr);
10126 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);
10127
10128 format %{ "eandl $dst, $src1, $src2\t# int ndd" %}
10129 ins_encode %{
10130 __ eandl($dst$$Register, $src1$$Register, $src2$$constant, false);
10131 %}
10132 ins_pipe(ialu_reg);
10133 %}
10134
10135 instruct andI_rReg_mem_imm_ndd(rRegI dst, memory src1, immI src2, rFlagsReg cr)
10136 %{
10137 predicate(UseAPX);
10138 match(Set dst (AndI (LoadI src1) src2));
10139 effect(KILL cr);
10140 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);
10141
10142 format %{ "eandl $dst, $src1, $src2\t# int ndd" %}
10143 ins_encode %{
10144 __ eandl($dst$$Register, $src1$$Address, $src2$$constant, false);
10145 %}
10146 ins_pipe(ialu_reg);
10147 %}
10148
10149 // And Register with Memory
10150 instruct andI_rReg_mem(rRegI dst, memory src, rFlagsReg cr)
10151 %{
10152 predicate(!UseAPX);
10153 match(Set dst (AndI dst (LoadI src)));
10154 effect(KILL cr);
10155 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);
10156
10157 ins_cost(150);
10158 format %{ "andl $dst, $src\t# int" %}
10159 ins_encode %{
10160 __ andl($dst$$Register, $src$$Address);
10161 %}
10162 ins_pipe(ialu_reg_mem);
10163 %}
10164
10165 instruct andI_rReg_rReg_mem_ndd(rRegI dst, rRegI src1, memory src2, rFlagsReg cr)
10166 %{
10167 predicate(UseAPX);
10168 match(Set dst (AndI src1 (LoadI src2)));
10169 effect(KILL cr);
10170 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);
10171
10172 ins_cost(150);
10173 format %{ "eandl $dst, $src1, $src2\t# int ndd" %}
10174 ins_encode %{
10175 __ eandl($dst$$Register, $src1$$Register, $src2$$Address, false);
10176 %}
10177 ins_pipe(ialu_reg_mem);
10178 %}
10179
10180 // And Memory with Register
10181 instruct andB_mem_rReg(memory dst, rRegI src, rFlagsReg cr)
10182 %{
10183 match(Set dst (StoreB dst (AndI (LoadB dst) src)));
10184 effect(KILL cr);
10185 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);
10186
10187 ins_cost(150);
10188 format %{ "andb $dst, $src\t# byte" %}
10189 ins_encode %{
10190 __ andb($dst$$Address, $src$$Register);
10191 %}
10192 ins_pipe(ialu_mem_reg);
10193 %}
10194
10195 instruct andI_mem_rReg(memory dst, rRegI src, rFlagsReg cr)
10196 %{
10197 match(Set dst (StoreI dst (AndI (LoadI dst) src)));
10198 effect(KILL cr);
10199 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);
10200
10201 ins_cost(150);
10202 format %{ "andl $dst, $src\t# int" %}
10203 ins_encode %{
10204 __ andl($dst$$Address, $src$$Register);
10205 %}
10206 ins_pipe(ialu_mem_reg);
10207 %}
10208
10209 // And Memory with Immediate
10210 instruct andI_mem_imm(memory dst, immI src, rFlagsReg cr)
10211 %{
10212 match(Set dst (StoreI dst (AndI (LoadI dst) src)));
10213 effect(KILL cr);
10214 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);
10215
10216 ins_cost(125);
10217 format %{ "andl $dst, $src\t# int" %}
10218 ins_encode %{
10219 __ andl($dst$$Address, $src$$constant);
10220 %}
10221 ins_pipe(ialu_mem_imm);
10222 %}
10223
10224 // BMI1 instructions
10225 instruct andnI_rReg_rReg_mem(rRegI dst, rRegI src1, memory src2, immI_M1 minus_1, rFlagsReg cr) %{
10226 match(Set dst (AndI (XorI src1 minus_1) (LoadI src2)));
10227 predicate(UseBMI1Instructions);
10228 effect(KILL cr);
10229 flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
10230
10231 ins_cost(125);
10232 format %{ "andnl $dst, $src1, $src2" %}
10233
10234 ins_encode %{
10235 __ andnl($dst$$Register, $src1$$Register, $src2$$Address);
10236 %}
10237 ins_pipe(ialu_reg_mem);
10238 %}
10239
10240 instruct andnI_rReg_rReg_rReg(rRegI dst, rRegI src1, rRegI src2, immI_M1 minus_1, rFlagsReg cr) %{
10241 match(Set dst (AndI (XorI src1 minus_1) src2));
10242 predicate(UseBMI1Instructions);
10243 effect(KILL cr);
10244 flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
10245
10246 format %{ "andnl $dst, $src1, $src2" %}
10247
10248 ins_encode %{
10249 __ andnl($dst$$Register, $src1$$Register, $src2$$Register);
10250 %}
10251 ins_pipe(ialu_reg);
10252 %}
10253
10254 instruct blsiI_rReg_rReg(rRegI dst, rRegI src, immI_0 imm_zero, rFlagsReg cr) %{
10255 match(Set dst (AndI (SubI imm_zero src) src));
10256 predicate(UseBMI1Instructions);
10257 effect(KILL cr);
10258 flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_clears_overflow_flag);
10259
10260 format %{ "blsil $dst, $src" %}
10261
10262 ins_encode %{
10263 __ blsil($dst$$Register, $src$$Register);
10264 %}
10265 ins_pipe(ialu_reg);
10266 %}
10267
10268 instruct blsiI_rReg_mem(rRegI dst, memory src, immI_0 imm_zero, rFlagsReg cr) %{
10269 match(Set dst (AndI (SubI imm_zero (LoadI src) ) (LoadI src) ));
10270 predicate(UseBMI1Instructions);
10271 effect(KILL cr);
10272 flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_clears_overflow_flag);
10273
10274 ins_cost(125);
10275 format %{ "blsil $dst, $src" %}
10276
10277 ins_encode %{
10278 __ blsil($dst$$Register, $src$$Address);
10279 %}
10280 ins_pipe(ialu_reg_mem);
10281 %}
10282
10283 instruct blsmskI_rReg_mem(rRegI dst, memory src, immI_M1 minus_1, rFlagsReg cr)
10284 %{
10285 match(Set dst (XorI (AddI (LoadI src) minus_1) (LoadI src) ) );
10286 predicate(UseBMI1Instructions);
10287 effect(KILL cr);
10288 flag(PD::Flag_sets_sign_flag, PD::Flag_clears_zero_flag, PD::Flag_clears_overflow_flag);
10289
10290 ins_cost(125);
10291 format %{ "blsmskl $dst, $src" %}
10292
10293 ins_encode %{
10294 __ blsmskl($dst$$Register, $src$$Address);
10295 %}
10296 ins_pipe(ialu_reg_mem);
10297 %}
10298
10299 instruct blsmskI_rReg_rReg(rRegI dst, rRegI src, immI_M1 minus_1, rFlagsReg cr)
10300 %{
10301 match(Set dst (XorI (AddI src minus_1) src));
10302 predicate(UseBMI1Instructions);
10303 effect(KILL cr);
10304 flag(PD::Flag_sets_sign_flag, PD::Flag_clears_zero_flag, PD::Flag_clears_overflow_flag);
10305
10306 format %{ "blsmskl $dst, $src" %}
10307
10308 ins_encode %{
10309 __ blsmskl($dst$$Register, $src$$Register);
10310 %}
10311
10312 ins_pipe(ialu_reg);
10313 %}
10314
10315 instruct blsrI_rReg_rReg(rRegI dst, rRegI src, immI_M1 minus_1, rFlagsReg cr)
10316 %{
10317 match(Set dst (AndI (AddI src minus_1) src) );
10318 predicate(UseBMI1Instructions);
10319 effect(KILL cr);
10320 flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_clears_overflow_flag);
10321
10322 format %{ "blsrl $dst, $src" %}
10323
10324 ins_encode %{
10325 __ blsrl($dst$$Register, $src$$Register);
10326 %}
10327
10328 ins_pipe(ialu_reg_mem);
10329 %}
10330
10331 instruct blsrI_rReg_mem(rRegI dst, memory src, immI_M1 minus_1, rFlagsReg cr)
10332 %{
10333 match(Set dst (AndI (AddI (LoadI src) minus_1) (LoadI src) ) );
10334 predicate(UseBMI1Instructions);
10335 effect(KILL cr);
10336 flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_clears_overflow_flag);
10337
10338 ins_cost(125);
10339 format %{ "blsrl $dst, $src" %}
10340
10341 ins_encode %{
10342 __ blsrl($dst$$Register, $src$$Address);
10343 %}
10344
10345 ins_pipe(ialu_reg);
10346 %}
10347
10348 // Or Instructions
10349 // Or Register with Register
10350 instruct orI_rReg(rRegI dst, rRegI src, rFlagsReg cr)
10351 %{
10352 predicate(!UseAPX);
10353 match(Set dst (OrI dst src));
10354 effect(KILL cr);
10355 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);
10356
10357 format %{ "orl $dst, $src\t# int" %}
10358 ins_encode %{
10359 __ orl($dst$$Register, $src$$Register);
10360 %}
10361 ins_pipe(ialu_reg_reg);
10362 %}
10363
10364 // Or Register with Register using New Data Destination (NDD)
10365 instruct orI_rReg_ndd(rRegI dst, rRegI src1, rRegI src2, rFlagsReg cr)
10366 %{
10367 predicate(UseAPX);
10368 match(Set dst (OrI src1 src2));
10369 effect(KILL cr);
10370 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);
10371
10372 format %{ "eorl $dst, $src1, $src2\t# int ndd" %}
10373 ins_encode %{
10374 __ eorl($dst$$Register, $src1$$Register, $src2$$Register, false);
10375 %}
10376 ins_pipe(ialu_reg_reg);
10377 %}
10378
10379 // Or Register with Immediate
10380 instruct orI_rReg_imm(rRegI dst, immI src, rFlagsReg cr)
10381 %{
10382 predicate(!UseAPX);
10383 match(Set dst (OrI dst src));
10384 effect(KILL cr);
10385 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);
10386
10387 format %{ "orl $dst, $src\t# int" %}
10388 ins_encode %{
10389 __ orl($dst$$Register, $src$$constant);
10390 %}
10391 ins_pipe(ialu_reg);
10392 %}
10393
10394 instruct orI_rReg_rReg_imm_ndd(rRegI dst, rRegI src1, immI src2, rFlagsReg cr)
10395 %{
10396 predicate(UseAPX);
10397 match(Set dst (OrI src1 src2));
10398 effect(KILL cr);
10399 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);
10400
10401 format %{ "eorl $dst, $src1, $src2\t# int ndd" %}
10402 ins_encode %{
10403 __ eorl($dst$$Register, $src1$$Register, $src2$$constant, false);
10404 %}
10405 ins_pipe(ialu_reg);
10406 %}
10407
10408 instruct orI_rReg_imm_rReg_ndd(rRegI dst, immI src1, rRegI src2, rFlagsReg cr)
10409 %{
10410 predicate(UseAPX);
10411 match(Set dst (OrI src1 src2));
10412 effect(KILL cr);
10413 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);
10414
10415 format %{ "eorl $dst, $src2, $src1\t# int ndd" %}
10416 ins_encode %{
10417 __ eorl($dst$$Register, $src2$$Register, $src1$$constant, false);
10418 %}
10419 ins_pipe(ialu_reg);
10420 %}
10421
10422 instruct orI_rReg_mem_imm_ndd(rRegI dst, memory src1, immI src2, rFlagsReg cr)
10423 %{
10424 predicate(UseAPX);
10425 match(Set dst (OrI (LoadI src1) src2));
10426 effect(KILL cr);
10427 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);
10428
10429 format %{ "eorl $dst, $src1, $src2\t# int ndd" %}
10430 ins_encode %{
10431 __ eorl($dst$$Register, $src1$$Address, $src2$$constant, false);
10432 %}
10433 ins_pipe(ialu_reg);
10434 %}
10435
10436 // Or Register with Memory
10437 instruct orI_rReg_mem(rRegI dst, memory src, rFlagsReg cr)
10438 %{
10439 predicate(!UseAPX);
10440 match(Set dst (OrI dst (LoadI src)));
10441 effect(KILL cr);
10442 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);
10443
10444 ins_cost(150);
10445 format %{ "orl $dst, $src\t# int" %}
10446 ins_encode %{
10447 __ orl($dst$$Register, $src$$Address);
10448 %}
10449 ins_pipe(ialu_reg_mem);
10450 %}
10451
10452 instruct orI_rReg_rReg_mem_ndd(rRegI dst, rRegI src1, memory src2, rFlagsReg cr)
10453 %{
10454 predicate(UseAPX);
10455 match(Set dst (OrI src1 (LoadI src2)));
10456 effect(KILL cr);
10457 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);
10458
10459 ins_cost(150);
10460 format %{ "eorl $dst, $src1, $src2\t# int ndd" %}
10461 ins_encode %{
10462 __ eorl($dst$$Register, $src1$$Register, $src2$$Address, false);
10463 %}
10464 ins_pipe(ialu_reg_mem);
10465 %}
10466
10467 // Or Memory with Register
10468 instruct orB_mem_rReg(memory dst, rRegI src, rFlagsReg cr)
10469 %{
10470 match(Set dst (StoreB dst (OrI (LoadB dst) src)));
10471 effect(KILL cr);
10472 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);
10473
10474 ins_cost(150);
10475 format %{ "orb $dst, $src\t# byte" %}
10476 ins_encode %{
10477 __ orb($dst$$Address, $src$$Register);
10478 %}
10479 ins_pipe(ialu_mem_reg);
10480 %}
10481
10482 instruct orI_mem_rReg(memory dst, rRegI src, rFlagsReg cr)
10483 %{
10484 match(Set dst (StoreI dst (OrI (LoadI dst) src)));
10485 effect(KILL cr);
10486 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);
10487
10488 ins_cost(150);
10489 format %{ "orl $dst, $src\t# int" %}
10490 ins_encode %{
10491 __ orl($dst$$Address, $src$$Register);
10492 %}
10493 ins_pipe(ialu_mem_reg);
10494 %}
10495
10496 // Or Memory with Immediate
10497 instruct orI_mem_imm(memory dst, immI src, rFlagsReg cr)
10498 %{
10499 match(Set dst (StoreI dst (OrI (LoadI dst) src)));
10500 effect(KILL cr);
10501 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);
10502
10503 ins_cost(125);
10504 format %{ "orl $dst, $src\t# int" %}
10505 ins_encode %{
10506 __ orl($dst$$Address, $src$$constant);
10507 %}
10508 ins_pipe(ialu_mem_imm);
10509 %}
10510
10511 // Xor Instructions
10512 // Xor Register with Register
10513 instruct xorI_rReg(rRegI dst, rRegI src, rFlagsReg cr)
10514 %{
10515 predicate(!UseAPX);
10516 match(Set dst (XorI dst src));
10517 effect(KILL cr);
10518 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);
10519
10520 format %{ "xorl $dst, $src\t# int" %}
10521 ins_encode %{
10522 __ xorl($dst$$Register, $src$$Register);
10523 %}
10524 ins_pipe(ialu_reg_reg);
10525 %}
10526
10527 // Xor Register with Register using New Data Destination (NDD)
10528 instruct xorI_rReg_ndd(rRegI dst, rRegI src1, rRegI src2, rFlagsReg cr)
10529 %{
10530 predicate(UseAPX);
10531 match(Set dst (XorI src1 src2));
10532 effect(KILL cr);
10533 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);
10534
10535 format %{ "exorl $dst, $src1, $src2\t# int ndd" %}
10536 ins_encode %{
10537 __ exorl($dst$$Register, $src1$$Register, $src2$$Register, false);
10538 %}
10539 ins_pipe(ialu_reg_reg);
10540 %}
10541
10542 // Xor Register with Immediate -1
10543 instruct xorI_rReg_im1(rRegI dst, immI_M1 imm)
10544 %{
10545 predicate(!UseAPX);
10546 match(Set dst (XorI dst imm));
10547
10548 format %{ "notl $dst" %}
10549 ins_encode %{
10550 __ notl($dst$$Register);
10551 %}
10552 ins_pipe(ialu_reg);
10553 %}
10554
10555 instruct xorI_rReg_im1_ndd(rRegI dst, rRegI src, immI_M1 imm)
10556 %{
10557 match(Set dst (XorI src imm));
10558 predicate(UseAPX);
10559
10560 format %{ "enotl $dst, $src" %}
10561 ins_encode %{
10562 __ enotl($dst$$Register, $src$$Register);
10563 %}
10564 ins_pipe(ialu_reg);
10565 %}
10566
10567 // Xor Register with Immediate
10568 instruct xorI_rReg_imm(rRegI dst, immI src, rFlagsReg cr)
10569 %{
10570 // Strict predicate check to make selection of xorI_rReg_im1 cost agnostic if immI src is -1.
10571 predicate(!UseAPX && n->in(2)->bottom_type()->is_int()->get_con() != -1);
10572 match(Set dst (XorI dst src));
10573 effect(KILL cr);
10574 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);
10575
10576 format %{ "xorl $dst, $src\t# int" %}
10577 ins_encode %{
10578 __ xorl($dst$$Register, $src$$constant);
10579 %}
10580 ins_pipe(ialu_reg);
10581 %}
10582
10583 instruct xorI_rReg_rReg_imm_ndd(rRegI dst, rRegI src1, immI src2, rFlagsReg cr)
10584 %{
10585 // Strict predicate check to make selection of xorI_rReg_im1_ndd cost agnostic if immI src2 is -1.
10586 predicate(UseAPX && n->in(2)->bottom_type()->is_int()->get_con() != -1);
10587 match(Set dst (XorI src1 src2));
10588 effect(KILL cr);
10589 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);
10590
10591 format %{ "exorl $dst, $src1, $src2\t# int ndd" %}
10592 ins_encode %{
10593 __ exorl($dst$$Register, $src1$$Register, $src2$$constant, false);
10594 %}
10595 ins_pipe(ialu_reg);
10596 %}
10597
10598 // Xor Memory with Immediate
10599 instruct xorI_rReg_mem_imm_ndd(rRegI dst, memory src1, immI src2, rFlagsReg cr)
10600 %{
10601 predicate(UseAPX);
10602 match(Set dst (XorI (LoadI src1) src2));
10603 effect(KILL cr);
10604 ins_cost(150);
10605 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);
10606
10607 format %{ "exorl $dst, $src1, $src2\t# int ndd" %}
10608 ins_encode %{
10609 __ exorl($dst$$Register, $src1$$Address, $src2$$constant, false);
10610 %}
10611 ins_pipe(ialu_reg);
10612 %}
10613
10614 // Xor Register with Memory
10615 instruct xorI_rReg_mem(rRegI dst, memory src, rFlagsReg cr)
10616 %{
10617 predicate(!UseAPX);
10618 match(Set dst (XorI dst (LoadI src)));
10619 effect(KILL cr);
10620 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);
10621
10622 ins_cost(150);
10623 format %{ "xorl $dst, $src\t# int" %}
10624 ins_encode %{
10625 __ xorl($dst$$Register, $src$$Address);
10626 %}
10627 ins_pipe(ialu_reg_mem);
10628 %}
10629
10630 instruct xorI_rReg_rReg_mem_ndd(rRegI dst, rRegI src1, memory src2, rFlagsReg cr)
10631 %{
10632 predicate(UseAPX);
10633 match(Set dst (XorI src1 (LoadI src2)));
10634 effect(KILL cr);
10635 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);
10636
10637 ins_cost(150);
10638 format %{ "exorl $dst, $src1, $src2\t# int ndd" %}
10639 ins_encode %{
10640 __ exorl($dst$$Register, $src1$$Register, $src2$$Address, false);
10641 %}
10642 ins_pipe(ialu_reg_mem);
10643 %}
10644
10645 // Xor Memory with Register
10646 instruct xorB_mem_rReg(memory dst, rRegI src, rFlagsReg cr)
10647 %{
10648 match(Set dst (StoreB dst (XorI (LoadB dst) src)));
10649 effect(KILL cr);
10650 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);
10651
10652 ins_cost(150);
10653 format %{ "xorb $dst, $src\t# byte" %}
10654 ins_encode %{
10655 __ xorb($dst$$Address, $src$$Register);
10656 %}
10657 ins_pipe(ialu_mem_reg);
10658 %}
10659
10660 instruct xorI_mem_rReg(memory dst, rRegI src, rFlagsReg cr)
10661 %{
10662 match(Set dst (StoreI dst (XorI (LoadI dst) src)));
10663 effect(KILL cr);
10664 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);
10665
10666 ins_cost(150);
10667 format %{ "xorl $dst, $src\t# int" %}
10668 ins_encode %{
10669 __ xorl($dst$$Address, $src$$Register);
10670 %}
10671 ins_pipe(ialu_mem_reg);
10672 %}
10673
10674 // Xor Memory with Immediate
10675 instruct xorI_mem_imm(memory dst, immI src, rFlagsReg cr)
10676 %{
10677 match(Set dst (StoreI dst (XorI (LoadI dst) src)));
10678 effect(KILL cr);
10679 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);
10680
10681 ins_cost(125);
10682 format %{ "xorl $dst, $src\t# int" %}
10683 ins_encode %{
10684 __ xorl($dst$$Address, $src$$constant);
10685 %}
10686 ins_pipe(ialu_mem_imm);
10687 %}
10688
10689
10690 // Long Logical Instructions
10691
10692 // And Instructions
10693 // And Register with Register
10694 instruct andL_rReg(rRegL dst, rRegL src, rFlagsReg cr)
10695 %{
10696 predicate(!UseAPX);
10697 match(Set dst (AndL dst src));
10698 effect(KILL cr);
10699 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);
10700
10701 format %{ "andq $dst, $src\t# long" %}
10702 ins_encode %{
10703 __ andq($dst$$Register, $src$$Register);
10704 %}
10705 ins_pipe(ialu_reg_reg);
10706 %}
10707
10708 // And Register with Register using New Data Destination (NDD)
10709 instruct andL_rReg_ndd(rRegL dst, rRegL src1, rRegL src2, rFlagsReg cr)
10710 %{
10711 predicate(UseAPX);
10712 match(Set dst (AndL src1 src2));
10713 effect(KILL cr);
10714 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);
10715
10716 format %{ "eandq $dst, $src1, $src2\t# long ndd" %}
10717 ins_encode %{
10718 __ eandq($dst$$Register, $src1$$Register, $src2$$Register, false);
10719
10720 %}
10721 ins_pipe(ialu_reg_reg);
10722 %}
10723
10724 // And Register with Immediate 255
10725 instruct andL_rReg_imm255(rRegL dst, rRegL src, immL_255 mask)
10726 %{
10727 match(Set dst (AndL src mask));
10728
10729 format %{ "movzbl $dst, $src\t# long & 0xFF" %}
10730 ins_encode %{
10731 // movzbl zeroes out the upper 32-bit and does not need REX.W
10732 __ movzbl($dst$$Register, $src$$Register);
10733 %}
10734 ins_pipe(ialu_reg);
10735 %}
10736
10737 // And Register with Immediate 65535
10738 instruct andL_rReg_imm65535(rRegL dst, rRegL src, immL_65535 mask)
10739 %{
10740 match(Set dst (AndL src mask));
10741
10742 format %{ "movzwl $dst, $src\t# long & 0xFFFF" %}
10743 ins_encode %{
10744 // movzwl zeroes out the upper 32-bit and does not need REX.W
10745 __ movzwl($dst$$Register, $src$$Register);
10746 %}
10747 ins_pipe(ialu_reg);
10748 %}
10749
10750 // And Register with Immediate
10751 instruct andL_rReg_imm(rRegL dst, immL32 src, rFlagsReg cr)
10752 %{
10753 predicate(!UseAPX);
10754 match(Set dst (AndL dst src));
10755 effect(KILL cr);
10756 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);
10757
10758 format %{ "andq $dst, $src\t# long" %}
10759 ins_encode %{
10760 __ andq($dst$$Register, $src$$constant);
10761 %}
10762 ins_pipe(ialu_reg);
10763 %}
10764
10765 instruct andL_rReg_rReg_imm_ndd(rRegL dst, rRegL src1, immL32 src2, rFlagsReg cr)
10766 %{
10767 predicate(UseAPX);
10768 match(Set dst (AndL src1 src2));
10769 effect(KILL cr);
10770 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);
10771
10772 format %{ "eandq $dst, $src1, $src2\t# long ndd" %}
10773 ins_encode %{
10774 __ eandq($dst$$Register, $src1$$Register, $src2$$constant, false);
10775 %}
10776 ins_pipe(ialu_reg);
10777 %}
10778
10779 instruct andL_rReg_mem_imm_ndd(rRegL dst, memory src1, immL32 src2, rFlagsReg cr)
10780 %{
10781 predicate(UseAPX);
10782 match(Set dst (AndL (LoadL src1) src2));
10783 effect(KILL cr);
10784 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);
10785
10786 format %{ "eandq $dst, $src1, $src2\t# long ndd" %}
10787 ins_encode %{
10788 __ eandq($dst$$Register, $src1$$Address, $src2$$constant, false);
10789 %}
10790 ins_pipe(ialu_reg);
10791 %}
10792
10793 // And Register with Memory
10794 instruct andL_rReg_mem(rRegL dst, memory src, rFlagsReg cr)
10795 %{
10796 predicate(!UseAPX);
10797 match(Set dst (AndL dst (LoadL src)));
10798 effect(KILL cr);
10799 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);
10800
10801 ins_cost(150);
10802 format %{ "andq $dst, $src\t# long" %}
10803 ins_encode %{
10804 __ andq($dst$$Register, $src$$Address);
10805 %}
10806 ins_pipe(ialu_reg_mem);
10807 %}
10808
10809 instruct andL_rReg_rReg_mem_ndd(rRegL dst, rRegL src1, memory src2, rFlagsReg cr)
10810 %{
10811 predicate(UseAPX);
10812 match(Set dst (AndL src1 (LoadL src2)));
10813 effect(KILL cr);
10814 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);
10815
10816 ins_cost(150);
10817 format %{ "eandq $dst, $src1, $src2\t# long ndd" %}
10818 ins_encode %{
10819 __ eandq($dst$$Register, $src1$$Register, $src2$$Address, false);
10820 %}
10821 ins_pipe(ialu_reg_mem);
10822 %}
10823
10824 // And Memory with Register
10825 instruct andL_mem_rReg(memory dst, rRegL src, rFlagsReg cr)
10826 %{
10827 match(Set dst (StoreL dst (AndL (LoadL dst) src)));
10828 effect(KILL cr);
10829 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);
10830
10831 ins_cost(150);
10832 format %{ "andq $dst, $src\t# long" %}
10833 ins_encode %{
10834 __ andq($dst$$Address, $src$$Register);
10835 %}
10836 ins_pipe(ialu_mem_reg);
10837 %}
10838
10839 // And Memory with Immediate
10840 instruct andL_mem_imm(memory dst, immL32 src, rFlagsReg cr)
10841 %{
10842 match(Set dst (StoreL dst (AndL (LoadL dst) src)));
10843 effect(KILL cr);
10844 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);
10845
10846 ins_cost(125);
10847 format %{ "andq $dst, $src\t# long" %}
10848 ins_encode %{
10849 __ andq($dst$$Address, $src$$constant);
10850 %}
10851 ins_pipe(ialu_mem_imm);
10852 %}
10853
10854 instruct btrL_mem_imm(memory dst, immL_NotPow2 con, rFlagsReg cr)
10855 %{
10856 // con should be a pure 64-bit immediate given that not(con) is a power of 2
10857 // because AND/OR works well enough for 8/32-bit values.
10858 predicate(log2i_graceful(~n->in(3)->in(2)->get_long()) > 30);
10859
10860 match(Set dst (StoreL dst (AndL (LoadL dst) con)));
10861 effect(KILL cr);
10862
10863 ins_cost(125);
10864 format %{ "btrq $dst, log2(not($con))\t# long" %}
10865 ins_encode %{
10866 __ btrq($dst$$Address, log2i_exact((julong)~$con$$constant));
10867 %}
10868 ins_pipe(ialu_mem_imm);
10869 %}
10870
10871 // BMI1 instructions
10872 instruct andnL_rReg_rReg_mem(rRegL dst, rRegL src1, memory src2, immL_M1 minus_1, rFlagsReg cr) %{
10873 match(Set dst (AndL (XorL src1 minus_1) (LoadL src2)));
10874 predicate(UseBMI1Instructions);
10875 effect(KILL cr);
10876 flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
10877
10878 ins_cost(125);
10879 format %{ "andnq $dst, $src1, $src2" %}
10880
10881 ins_encode %{
10882 __ andnq($dst$$Register, $src1$$Register, $src2$$Address);
10883 %}
10884 ins_pipe(ialu_reg_mem);
10885 %}
10886
10887 instruct andnL_rReg_rReg_rReg(rRegL dst, rRegL src1, rRegL src2, immL_M1 minus_1, rFlagsReg cr) %{
10888 match(Set dst (AndL (XorL src1 minus_1) src2));
10889 predicate(UseBMI1Instructions);
10890 effect(KILL cr);
10891 flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
10892
10893 format %{ "andnq $dst, $src1, $src2" %}
10894
10895 ins_encode %{
10896 __ andnq($dst$$Register, $src1$$Register, $src2$$Register);
10897 %}
10898 ins_pipe(ialu_reg_mem);
10899 %}
10900
10901 instruct blsiL_rReg_rReg(rRegL dst, rRegL src, immL0 imm_zero, rFlagsReg cr) %{
10902 match(Set dst (AndL (SubL imm_zero src) src));
10903 predicate(UseBMI1Instructions);
10904 effect(KILL cr);
10905 flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_clears_overflow_flag);
10906
10907 format %{ "blsiq $dst, $src" %}
10908
10909 ins_encode %{
10910 __ blsiq($dst$$Register, $src$$Register);
10911 %}
10912 ins_pipe(ialu_reg);
10913 %}
10914
10915 instruct blsiL_rReg_mem(rRegL dst, memory src, immL0 imm_zero, rFlagsReg cr) %{
10916 match(Set dst (AndL (SubL imm_zero (LoadL src) ) (LoadL src) ));
10917 predicate(UseBMI1Instructions);
10918 effect(KILL cr);
10919 flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_clears_overflow_flag);
10920
10921 ins_cost(125);
10922 format %{ "blsiq $dst, $src" %}
10923
10924 ins_encode %{
10925 __ blsiq($dst$$Register, $src$$Address);
10926 %}
10927 ins_pipe(ialu_reg_mem);
10928 %}
10929
10930 instruct blsmskL_rReg_mem(rRegL dst, memory src, immL_M1 minus_1, rFlagsReg cr)
10931 %{
10932 match(Set dst (XorL (AddL (LoadL src) minus_1) (LoadL src) ) );
10933 predicate(UseBMI1Instructions);
10934 effect(KILL cr);
10935 flag(PD::Flag_sets_sign_flag, PD::Flag_clears_zero_flag, PD::Flag_clears_overflow_flag);
10936
10937 ins_cost(125);
10938 format %{ "blsmskq $dst, $src" %}
10939
10940 ins_encode %{
10941 __ blsmskq($dst$$Register, $src$$Address);
10942 %}
10943 ins_pipe(ialu_reg_mem);
10944 %}
10945
10946 instruct blsmskL_rReg_rReg(rRegL dst, rRegL src, immL_M1 minus_1, rFlagsReg cr)
10947 %{
10948 match(Set dst (XorL (AddL src minus_1) src));
10949 predicate(UseBMI1Instructions);
10950 effect(KILL cr);
10951 flag(PD::Flag_sets_sign_flag, PD::Flag_clears_zero_flag, PD::Flag_clears_overflow_flag);
10952
10953 format %{ "blsmskq $dst, $src" %}
10954
10955 ins_encode %{
10956 __ blsmskq($dst$$Register, $src$$Register);
10957 %}
10958
10959 ins_pipe(ialu_reg);
10960 %}
10961
10962 instruct blsrL_rReg_rReg(rRegL dst, rRegL src, immL_M1 minus_1, rFlagsReg cr)
10963 %{
10964 match(Set dst (AndL (AddL src minus_1) src) );
10965 predicate(UseBMI1Instructions);
10966 effect(KILL cr);
10967 flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_clears_overflow_flag);
10968
10969 format %{ "blsrq $dst, $src" %}
10970
10971 ins_encode %{
10972 __ blsrq($dst$$Register, $src$$Register);
10973 %}
10974
10975 ins_pipe(ialu_reg);
10976 %}
10977
10978 instruct blsrL_rReg_mem(rRegL dst, memory src, immL_M1 minus_1, rFlagsReg cr)
10979 %{
10980 match(Set dst (AndL (AddL (LoadL src) minus_1) (LoadL src)) );
10981 predicate(UseBMI1Instructions);
10982 effect(KILL cr);
10983 flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_clears_overflow_flag);
10984
10985 ins_cost(125);
10986 format %{ "blsrq $dst, $src" %}
10987
10988 ins_encode %{
10989 __ blsrq($dst$$Register, $src$$Address);
10990 %}
10991
10992 ins_pipe(ialu_reg);
10993 %}
10994
10995 // Or Instructions
10996 // Or Register with Register
10997 instruct orL_rReg(rRegL dst, rRegL src, rFlagsReg cr)
10998 %{
10999 predicate(!UseAPX);
11000 match(Set dst (OrL dst src));
11001 effect(KILL cr);
11002 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);
11003
11004 format %{ "orq $dst, $src\t# long" %}
11005 ins_encode %{
11006 __ orq($dst$$Register, $src$$Register);
11007 %}
11008 ins_pipe(ialu_reg_reg);
11009 %}
11010
11011 // Or Register with Register using New Data Destination (NDD)
11012 instruct orL_rReg_ndd(rRegL dst, rRegL src1, rRegL src2, rFlagsReg cr)
11013 %{
11014 predicate(UseAPX);
11015 match(Set dst (OrL src1 src2));
11016 effect(KILL cr);
11017 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);
11018
11019 format %{ "eorq $dst, $src1, $src2\t# long ndd" %}
11020 ins_encode %{
11021 __ eorq($dst$$Register, $src1$$Register, $src2$$Register, false);
11022
11023 %}
11024 ins_pipe(ialu_reg_reg);
11025 %}
11026
11027 // Use any_RegP to match R15 (TLS register) without spilling.
11028 instruct orL_rReg_castP2X(rRegL dst, any_RegP src, rFlagsReg cr) %{
11029 match(Set dst (OrL dst (CastP2X src)));
11030 effect(KILL cr);
11031 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);
11032
11033 format %{ "orq $dst, $src\t# long" %}
11034 ins_encode %{
11035 __ orq($dst$$Register, $src$$Register);
11036 %}
11037 ins_pipe(ialu_reg_reg);
11038 %}
11039
11040 instruct orL_rReg_castP2X_ndd(rRegL dst, any_RegP src1, any_RegP src2, rFlagsReg cr) %{
11041 match(Set dst (OrL src1 (CastP2X src2)));
11042 effect(KILL cr);
11043 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);
11044
11045 format %{ "eorq $dst, $src1, $src2\t# long ndd" %}
11046 ins_encode %{
11047 __ eorq($dst$$Register, $src1$$Register, $src2$$Register, false);
11048 %}
11049 ins_pipe(ialu_reg_reg);
11050 %}
11051
11052 // Or Register with Immediate
11053 instruct orL_rReg_imm(rRegL dst, immL32 src, rFlagsReg cr)
11054 %{
11055 predicate(!UseAPX);
11056 match(Set dst (OrL dst src));
11057 effect(KILL cr);
11058 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);
11059
11060 format %{ "orq $dst, $src\t# long" %}
11061 ins_encode %{
11062 __ orq($dst$$Register, $src$$constant);
11063 %}
11064 ins_pipe(ialu_reg);
11065 %}
11066
11067 instruct orL_rReg_rReg_imm_ndd(rRegL dst, rRegL src1, immL32 src2, rFlagsReg cr)
11068 %{
11069 predicate(UseAPX);
11070 match(Set dst (OrL src1 src2));
11071 effect(KILL cr);
11072 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);
11073
11074 format %{ "eorq $dst, $src1, $src2\t# long ndd" %}
11075 ins_encode %{
11076 __ eorq($dst$$Register, $src1$$Register, $src2$$constant, false);
11077 %}
11078 ins_pipe(ialu_reg);
11079 %}
11080
11081 instruct orL_rReg_imm_rReg_ndd(rRegL dst, immL32 src1, rRegL src2, rFlagsReg cr)
11082 %{
11083 predicate(UseAPX);
11084 match(Set dst (OrL src1 src2));
11085 effect(KILL cr);
11086 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);
11087
11088 format %{ "eorq $dst, $src2, $src1\t# long ndd" %}
11089 ins_encode %{
11090 __ eorq($dst$$Register, $src2$$Register, $src1$$constant, false);
11091 %}
11092 ins_pipe(ialu_reg);
11093 %}
11094
11095 // Or Memory with Immediate
11096 instruct orL_rReg_mem_imm_ndd(rRegL dst, memory src1, immL32 src2, rFlagsReg cr)
11097 %{
11098 predicate(UseAPX);
11099 match(Set dst (OrL (LoadL src1) src2));
11100 effect(KILL cr);
11101 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);
11102
11103 format %{ "eorq $dst, $src1, $src2\t# long ndd" %}
11104 ins_encode %{
11105 __ eorq($dst$$Register, $src1$$Address, $src2$$constant, false);
11106 %}
11107 ins_pipe(ialu_reg);
11108 %}
11109
11110 // Or Register with Memory
11111 instruct orL_rReg_mem(rRegL dst, memory src, rFlagsReg cr)
11112 %{
11113 predicate(!UseAPX);
11114 match(Set dst (OrL dst (LoadL src)));
11115 effect(KILL cr);
11116 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);
11117
11118 ins_cost(150);
11119 format %{ "orq $dst, $src\t# long" %}
11120 ins_encode %{
11121 __ orq($dst$$Register, $src$$Address);
11122 %}
11123 ins_pipe(ialu_reg_mem);
11124 %}
11125
11126 instruct orL_rReg_rReg_mem_ndd(rRegL dst, rRegL src1, memory src2, rFlagsReg cr)
11127 %{
11128 predicate(UseAPX);
11129 match(Set dst (OrL src1 (LoadL src2)));
11130 effect(KILL cr);
11131 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);
11132
11133 ins_cost(150);
11134 format %{ "eorq $dst, $src1, $src2\t# long ndd" %}
11135 ins_encode %{
11136 __ eorq($dst$$Register, $src1$$Register, $src2$$Address, false);
11137 %}
11138 ins_pipe(ialu_reg_mem);
11139 %}
11140
11141 // Or Memory with Register
11142 instruct orL_mem_rReg(memory dst, rRegL src, rFlagsReg cr)
11143 %{
11144 match(Set dst (StoreL dst (OrL (LoadL dst) src)));
11145 effect(KILL cr);
11146 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);
11147
11148 ins_cost(150);
11149 format %{ "orq $dst, $src\t# long" %}
11150 ins_encode %{
11151 __ orq($dst$$Address, $src$$Register);
11152 %}
11153 ins_pipe(ialu_mem_reg);
11154 %}
11155
11156 // Or Memory with Immediate
11157 instruct orL_mem_imm(memory dst, immL32 src, rFlagsReg cr)
11158 %{
11159 match(Set dst (StoreL dst (OrL (LoadL dst) src)));
11160 effect(KILL cr);
11161 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);
11162
11163 ins_cost(125);
11164 format %{ "orq $dst, $src\t# long" %}
11165 ins_encode %{
11166 __ orq($dst$$Address, $src$$constant);
11167 %}
11168 ins_pipe(ialu_mem_imm);
11169 %}
11170
11171 instruct btsL_mem_imm(memory dst, immL_Pow2 con, rFlagsReg cr)
11172 %{
11173 // con should be a pure 64-bit power of 2 immediate
11174 // because AND/OR works well enough for 8/32-bit values.
11175 predicate(log2i_graceful(n->in(3)->in(2)->get_long()) > 31);
11176
11177 match(Set dst (StoreL dst (OrL (LoadL dst) con)));
11178 effect(KILL cr);
11179
11180 ins_cost(125);
11181 format %{ "btsq $dst, log2($con)\t# long" %}
11182 ins_encode %{
11183 __ btsq($dst$$Address, log2i_exact((julong)$con$$constant));
11184 %}
11185 ins_pipe(ialu_mem_imm);
11186 %}
11187
11188 // Xor Instructions
11189 // Xor Register with Register
11190 instruct xorL_rReg(rRegL dst, rRegL src, rFlagsReg cr)
11191 %{
11192 predicate(!UseAPX);
11193 match(Set dst (XorL dst src));
11194 effect(KILL cr);
11195 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);
11196
11197 format %{ "xorq $dst, $src\t# long" %}
11198 ins_encode %{
11199 __ xorq($dst$$Register, $src$$Register);
11200 %}
11201 ins_pipe(ialu_reg_reg);
11202 %}
11203
11204 // Xor Register with Register using New Data Destination (NDD)
11205 instruct xorL_rReg_ndd(rRegL dst, rRegL src1, rRegL src2, rFlagsReg cr)
11206 %{
11207 predicate(UseAPX);
11208 match(Set dst (XorL src1 src2));
11209 effect(KILL cr);
11210 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);
11211
11212 format %{ "exorq $dst, $src1, $src2\t# long ndd" %}
11213 ins_encode %{
11214 __ exorq($dst$$Register, $src1$$Register, $src2$$Register, false);
11215 %}
11216 ins_pipe(ialu_reg_reg);
11217 %}
11218
11219 // Xor Register with Immediate -1
11220 instruct xorL_rReg_im1(rRegL dst, immL_M1 imm)
11221 %{
11222 predicate(!UseAPX);
11223 match(Set dst (XorL dst imm));
11224
11225 format %{ "notq $dst" %}
11226 ins_encode %{
11227 __ notq($dst$$Register);
11228 %}
11229 ins_pipe(ialu_reg);
11230 %}
11231
11232 instruct xorL_rReg_im1_ndd(rRegL dst,rRegL src, immL_M1 imm)
11233 %{
11234 predicate(UseAPX);
11235 match(Set dst (XorL src imm));
11236
11237 format %{ "enotq $dst, $src" %}
11238 ins_encode %{
11239 __ enotq($dst$$Register, $src$$Register);
11240 %}
11241 ins_pipe(ialu_reg);
11242 %}
11243
11244 // Xor Register with Immediate
11245 instruct xorL_rReg_imm(rRegL dst, immL32 src, rFlagsReg cr)
11246 %{
11247 // Strict predicate check to make selection of xorL_rReg_im1 cost agnostic if immL32 src is -1.
11248 predicate(!UseAPX && n->in(2)->bottom_type()->is_long()->get_con() != -1L);
11249 match(Set dst (XorL dst src));
11250 effect(KILL cr);
11251 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);
11252
11253 format %{ "xorq $dst, $src\t# long" %}
11254 ins_encode %{
11255 __ xorq($dst$$Register, $src$$constant);
11256 %}
11257 ins_pipe(ialu_reg);
11258 %}
11259
11260 instruct xorL_rReg_rReg_imm(rRegL dst, rRegL src1, immL32 src2, rFlagsReg cr)
11261 %{
11262 // Strict predicate check to make selection of xorL_rReg_im1_ndd cost agnostic if immL32 src2 is -1.
11263 predicate(UseAPX && n->in(2)->bottom_type()->is_long()->get_con() != -1L);
11264 match(Set dst (XorL src1 src2));
11265 effect(KILL cr);
11266 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);
11267
11268 format %{ "exorq $dst, $src1, $src2\t# long ndd" %}
11269 ins_encode %{
11270 __ exorq($dst$$Register, $src1$$Register, $src2$$constant, false);
11271 %}
11272 ins_pipe(ialu_reg);
11273 %}
11274
11275 // Xor Memory with Immediate
11276 instruct xorL_rReg_mem_imm(rRegL dst, memory src1, immL32 src2, rFlagsReg cr)
11277 %{
11278 predicate(UseAPX);
11279 match(Set dst (XorL (LoadL src1) src2));
11280 effect(KILL cr);
11281 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);
11282 ins_cost(150);
11283
11284 format %{ "exorq $dst, $src1, $src2\t# long ndd" %}
11285 ins_encode %{
11286 __ exorq($dst$$Register, $src1$$Address, $src2$$constant, false);
11287 %}
11288 ins_pipe(ialu_reg);
11289 %}
11290
11291 // Xor Register with Memory
11292 instruct xorL_rReg_mem(rRegL dst, memory src, rFlagsReg cr)
11293 %{
11294 predicate(!UseAPX);
11295 match(Set dst (XorL dst (LoadL src)));
11296 effect(KILL cr);
11297 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);
11298
11299 ins_cost(150);
11300 format %{ "xorq $dst, $src\t# long" %}
11301 ins_encode %{
11302 __ xorq($dst$$Register, $src$$Address);
11303 %}
11304 ins_pipe(ialu_reg_mem);
11305 %}
11306
11307 instruct xorL_rReg_rReg_mem_ndd(rRegL dst, rRegL src1, memory src2, rFlagsReg cr)
11308 %{
11309 predicate(UseAPX);
11310 match(Set dst (XorL src1 (LoadL src2)));
11311 effect(KILL cr);
11312 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);
11313
11314 ins_cost(150);
11315 format %{ "exorq $dst, $src1, $src2\t# long ndd" %}
11316 ins_encode %{
11317 __ exorq($dst$$Register, $src1$$Register, $src2$$Address, false);
11318 %}
11319 ins_pipe(ialu_reg_mem);
11320 %}
11321
11322 // Xor Memory with Register
11323 instruct xorL_mem_rReg(memory dst, rRegL src, rFlagsReg cr)
11324 %{
11325 match(Set dst (StoreL dst (XorL (LoadL dst) src)));
11326 effect(KILL cr);
11327 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);
11328
11329 ins_cost(150);
11330 format %{ "xorq $dst, $src\t# long" %}
11331 ins_encode %{
11332 __ xorq($dst$$Address, $src$$Register);
11333 %}
11334 ins_pipe(ialu_mem_reg);
11335 %}
11336
11337 // Xor Memory with Immediate
11338 instruct xorL_mem_imm(memory dst, immL32 src, rFlagsReg cr)
11339 %{
11340 match(Set dst (StoreL dst (XorL (LoadL dst) src)));
11341 effect(KILL cr);
11342 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);
11343
11344 ins_cost(125);
11345 format %{ "xorq $dst, $src\t# long" %}
11346 ins_encode %{
11347 __ xorq($dst$$Address, $src$$constant);
11348 %}
11349 ins_pipe(ialu_mem_imm);
11350 %}
11351
11352 instruct cmpLTMask(rRegI dst, rRegI p, rRegI q, rFlagsReg cr)
11353 %{
11354 match(Set dst (CmpLTMask p q));
11355 effect(KILL cr);
11356
11357 ins_cost(400);
11358 format %{ "cmpl $p, $q\t# cmpLTMask\n\t"
11359 "setcc $dst \t# emits setlt + movzbl or setzul for APX"
11360 "negl $dst" %}
11361 ins_encode %{
11362 __ cmpl($p$$Register, $q$$Register);
11363 __ setcc(Assembler::less, $dst$$Register);
11364 __ negl($dst$$Register);
11365 %}
11366 ins_pipe(pipe_slow);
11367 %}
11368
11369 instruct cmpLTMask0(rRegI dst, immI_0 zero, rFlagsReg cr)
11370 %{
11371 match(Set dst (CmpLTMask dst zero));
11372 effect(KILL cr);
11373
11374 ins_cost(100);
11375 format %{ "sarl $dst, #31\t# cmpLTMask0" %}
11376 ins_encode %{
11377 __ sarl($dst$$Register, 31);
11378 %}
11379 ins_pipe(ialu_reg);
11380 %}
11381
11382 /* Better to save a register than avoid a branch */
11383 instruct cadd_cmpLTMask(rRegI p, rRegI q, rRegI y, rFlagsReg cr)
11384 %{
11385 match(Set p (AddI (AndI (CmpLTMask p q) y) (SubI p q)));
11386 effect(KILL cr);
11387 ins_cost(300);
11388 format %{ "subl $p,$q\t# cadd_cmpLTMask\n\t"
11389 "jge done\n\t"
11390 "addl $p,$y\n"
11391 "done: " %}
11392 ins_encode %{
11393 Register Rp = $p$$Register;
11394 Register Rq = $q$$Register;
11395 Register Ry = $y$$Register;
11396 Label done;
11397 __ subl(Rp, Rq);
11398 __ jccb(Assembler::greaterEqual, done);
11399 __ addl(Rp, Ry);
11400 __ bind(done);
11401 %}
11402 ins_pipe(pipe_cmplt);
11403 %}
11404
11405 /* Better to save a register than avoid a branch */
11406 instruct and_cmpLTMask(rRegI p, rRegI q, rRegI y, rFlagsReg cr)
11407 %{
11408 match(Set y (AndI (CmpLTMask p q) y));
11409 effect(KILL cr);
11410
11411 ins_cost(300);
11412
11413 format %{ "cmpl $p, $q\t# and_cmpLTMask\n\t"
11414 "jlt done\n\t"
11415 "xorl $y, $y\n"
11416 "done: " %}
11417 ins_encode %{
11418 Register Rp = $p$$Register;
11419 Register Rq = $q$$Register;
11420 Register Ry = $y$$Register;
11421 Label done;
11422 __ cmpl(Rp, Rq);
11423 __ jccb(Assembler::less, done);
11424 __ xorl(Ry, Ry);
11425 __ bind(done);
11426 %}
11427 ins_pipe(pipe_cmplt);
11428 %}
11429
11430
11431 //---------- FP Instructions------------------------------------------------
11432
11433 // Really expensive, avoid
11434 instruct cmpF_cc_reg(rFlagsRegU cr, regF src1, regF src2)
11435 %{
11436 match(Set cr (CmpF src1 src2));
11437
11438 ins_cost(500);
11439 format %{ "ucomiss $src1, $src2\n\t"
11440 "jnp,s exit\n\t"
11441 "pushfq\t# saw NaN, set CF\n\t"
11442 "andq [rsp], #0xffffff2b\n\t"
11443 "popfq\n"
11444 "exit:" %}
11445 ins_encode %{
11446 __ ucomiss($src1$$XMMRegister, $src2$$XMMRegister);
11447 emit_cmpfp_fixup(masm);
11448 %}
11449 ins_pipe(pipe_slow);
11450 %}
11451
11452 instruct cmpF_cc_reg_CF(rFlagsRegUCF cr, regF src1, regF src2) %{
11453 match(Set cr (CmpF src1 src2));
11454
11455 ins_cost(100);
11456 format %{ "ucomiss $src1, $src2" %}
11457 ins_encode %{
11458 __ ucomiss($src1$$XMMRegister, $src2$$XMMRegister);
11459 %}
11460 ins_pipe(pipe_slow);
11461 %}
11462
11463 instruct cmpF_cc_memCF(rFlagsRegUCF cr, regF src1, memory src2) %{
11464 match(Set cr (CmpF src1 (LoadF src2)));
11465
11466 ins_cost(100);
11467 format %{ "ucomiss $src1, $src2" %}
11468 ins_encode %{
11469 __ ucomiss($src1$$XMMRegister, $src2$$Address);
11470 %}
11471 ins_pipe(pipe_slow);
11472 %}
11473
11474 instruct cmpF_cc_immCF(rFlagsRegUCF cr, regF src, immF con) %{
11475 match(Set cr (CmpF src con));
11476 ins_cost(100);
11477 format %{ "ucomiss $src, [$constantaddress]\t# load from constant table: float=$con" %}
11478 ins_encode %{
11479 __ ucomiss($src$$XMMRegister, $constantaddress($con));
11480 %}
11481 ins_pipe(pipe_slow);
11482 %}
11483
11484 // Really expensive, avoid
11485 instruct cmpD_cc_reg(rFlagsRegU cr, regD src1, regD src2)
11486 %{
11487 match(Set cr (CmpD src1 src2));
11488
11489 ins_cost(500);
11490 format %{ "ucomisd $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 __ ucomisd($src1$$XMMRegister, $src2$$XMMRegister);
11498 emit_cmpfp_fixup(masm);
11499 %}
11500 ins_pipe(pipe_slow);
11501 %}
11502
11503 instruct cmpD_cc_reg_CF(rFlagsRegUCF cr, regD src1, regD src2) %{
11504 match(Set cr (CmpD src1 src2));
11505
11506 ins_cost(100);
11507 format %{ "ucomisd $src1, $src2 test" %}
11508 ins_encode %{
11509 __ ucomisd($src1$$XMMRegister, $src2$$XMMRegister);
11510 %}
11511 ins_pipe(pipe_slow);
11512 %}
11513
11514 instruct cmpD_cc_memCF(rFlagsRegUCF cr, regD src1, memory src2) %{
11515 match(Set cr (CmpD src1 (LoadD src2)));
11516
11517 ins_cost(100);
11518 format %{ "ucomisd $src1, $src2" %}
11519 ins_encode %{
11520 __ ucomisd($src1$$XMMRegister, $src2$$Address);
11521 %}
11522 ins_pipe(pipe_slow);
11523 %}
11524
11525 instruct cmpD_cc_immCF(rFlagsRegUCF cr, regD src, immD con) %{
11526 match(Set cr (CmpD src con));
11527 ins_cost(100);
11528 format %{ "ucomisd $src, [$constantaddress]\t# load from constant table: double=$con" %}
11529 ins_encode %{
11530 __ ucomisd($src$$XMMRegister, $constantaddress($con));
11531 %}
11532 ins_pipe(pipe_slow);
11533 %}
11534
11535 // Compare into -1,0,1
11536 instruct cmpF_reg(rRegI dst, regF src1, regF src2, rFlagsReg cr)
11537 %{
11538 match(Set dst (CmpF3 src1 src2));
11539 effect(KILL cr);
11540
11541 ins_cost(275);
11542 format %{ "ucomiss $src1, $src2\n\t"
11543 "movl $dst, #-1\n\t"
11544 "jp,s done\n\t"
11545 "jb,s done\n\t"
11546 "setne $dst\n\t"
11547 "movzbl $dst, $dst\n"
11548 "done:" %}
11549 ins_encode %{
11550 __ ucomiss($src1$$XMMRegister, $src2$$XMMRegister);
11551 emit_cmpfp3(masm, $dst$$Register);
11552 %}
11553 ins_pipe(pipe_slow);
11554 %}
11555
11556 // Compare into -1,0,1
11557 instruct cmpF_mem(rRegI dst, regF src1, memory src2, rFlagsReg cr)
11558 %{
11559 match(Set dst (CmpF3 src1 (LoadF src2)));
11560 effect(KILL cr);
11561
11562 ins_cost(275);
11563 format %{ "ucomiss $src1, $src2\n\t"
11564 "movl $dst, #-1\n\t"
11565 "jp,s done\n\t"
11566 "jb,s done\n\t"
11567 "setne $dst\n\t"
11568 "movzbl $dst, $dst\n"
11569 "done:" %}
11570 ins_encode %{
11571 __ ucomiss($src1$$XMMRegister, $src2$$Address);
11572 emit_cmpfp3(masm, $dst$$Register);
11573 %}
11574 ins_pipe(pipe_slow);
11575 %}
11576
11577 // Compare into -1,0,1
11578 instruct cmpF_imm(rRegI dst, regF src, immF con, rFlagsReg cr) %{
11579 match(Set dst (CmpF3 src con));
11580 effect(KILL cr);
11581
11582 ins_cost(275);
11583 format %{ "ucomiss $src, [$constantaddress]\t# load from constant table: float=$con\n\t"
11584 "movl $dst, #-1\n\t"
11585 "jp,s done\n\t"
11586 "jb,s done\n\t"
11587 "setne $dst\n\t"
11588 "movzbl $dst, $dst\n"
11589 "done:" %}
11590 ins_encode %{
11591 __ ucomiss($src$$XMMRegister, $constantaddress($con));
11592 emit_cmpfp3(masm, $dst$$Register);
11593 %}
11594 ins_pipe(pipe_slow);
11595 %}
11596
11597 // Compare into -1,0,1
11598 instruct cmpD_reg(rRegI dst, regD src1, regD src2, rFlagsReg cr)
11599 %{
11600 match(Set dst (CmpD3 src1 src2));
11601 effect(KILL cr);
11602
11603 ins_cost(275);
11604 format %{ "ucomisd $src1, $src2\n\t"
11605 "movl $dst, #-1\n\t"
11606 "jp,s done\n\t"
11607 "jb,s done\n\t"
11608 "setne $dst\n\t"
11609 "movzbl $dst, $dst\n"
11610 "done:" %}
11611 ins_encode %{
11612 __ ucomisd($src1$$XMMRegister, $src2$$XMMRegister);
11613 emit_cmpfp3(masm, $dst$$Register);
11614 %}
11615 ins_pipe(pipe_slow);
11616 %}
11617
11618 // Compare into -1,0,1
11619 instruct cmpD_mem(rRegI dst, regD src1, memory src2, rFlagsReg cr)
11620 %{
11621 match(Set dst (CmpD3 src1 (LoadD src2)));
11622 effect(KILL cr);
11623
11624 ins_cost(275);
11625 format %{ "ucomisd $src1, $src2\n\t"
11626 "movl $dst, #-1\n\t"
11627 "jp,s done\n\t"
11628 "jb,s done\n\t"
11629 "setne $dst\n\t"
11630 "movzbl $dst, $dst\n"
11631 "done:" %}
11632 ins_encode %{
11633 __ ucomisd($src1$$XMMRegister, $src2$$Address);
11634 emit_cmpfp3(masm, $dst$$Register);
11635 %}
11636 ins_pipe(pipe_slow);
11637 %}
11638
11639 // Compare into -1,0,1
11640 instruct cmpD_imm(rRegI dst, regD src, immD con, rFlagsReg cr) %{
11641 match(Set dst (CmpD3 src con));
11642 effect(KILL cr);
11643
11644 ins_cost(275);
11645 format %{ "ucomisd $src, [$constantaddress]\t# load from constant table: double=$con\n\t"
11646 "movl $dst, #-1\n\t"
11647 "jp,s done\n\t"
11648 "jb,s done\n\t"
11649 "setne $dst\n\t"
11650 "movzbl $dst, $dst\n"
11651 "done:" %}
11652 ins_encode %{
11653 __ ucomisd($src$$XMMRegister, $constantaddress($con));
11654 emit_cmpfp3(masm, $dst$$Register);
11655 %}
11656 ins_pipe(pipe_slow);
11657 %}
11658
11659 //----------Arithmetic Conversion Instructions---------------------------------
11660
11661 instruct convF2D_reg_reg(regD dst, regF src)
11662 %{
11663 match(Set dst (ConvF2D src));
11664
11665 format %{ "cvtss2sd $dst, $src" %}
11666 ins_encode %{
11667 __ cvtss2sd ($dst$$XMMRegister, $src$$XMMRegister);
11668 %}
11669 ins_pipe(pipe_slow); // XXX
11670 %}
11671
11672 instruct convF2D_reg_mem(regD dst, memory src)
11673 %{
11674 predicate(UseAVX == 0);
11675 match(Set dst (ConvF2D (LoadF src)));
11676
11677 format %{ "cvtss2sd $dst, $src" %}
11678 ins_encode %{
11679 __ cvtss2sd ($dst$$XMMRegister, $src$$Address);
11680 %}
11681 ins_pipe(pipe_slow); // XXX
11682 %}
11683
11684 instruct convD2F_reg_reg(regF dst, regD src)
11685 %{
11686 match(Set dst (ConvD2F src));
11687
11688 format %{ "cvtsd2ss $dst, $src" %}
11689 ins_encode %{
11690 __ cvtsd2ss ($dst$$XMMRegister, $src$$XMMRegister);
11691 %}
11692 ins_pipe(pipe_slow); // XXX
11693 %}
11694
11695 instruct convD2F_reg_mem(regF dst, memory src)
11696 %{
11697 predicate(UseAVX == 0);
11698 match(Set dst (ConvD2F (LoadD src)));
11699
11700 format %{ "cvtsd2ss $dst, $src" %}
11701 ins_encode %{
11702 __ cvtsd2ss ($dst$$XMMRegister, $src$$Address);
11703 %}
11704 ins_pipe(pipe_slow); // XXX
11705 %}
11706
11707 // XXX do mem variants
11708 instruct convF2I_reg_reg(rRegI dst, regF src, rFlagsReg cr)
11709 %{
11710 predicate(!VM_Version::supports_avx10_2());
11711 match(Set dst (ConvF2I src));
11712 effect(KILL cr);
11713 format %{ "convert_f2i $dst, $src" %}
11714 ins_encode %{
11715 __ convertF2I(T_INT, T_FLOAT, $dst$$Register, $src$$XMMRegister);
11716 %}
11717 ins_pipe(pipe_slow);
11718 %}
11719
11720 instruct convF2I_reg_reg_avx10(rRegI dst, regF src)
11721 %{
11722 predicate(VM_Version::supports_avx10_2());
11723 match(Set dst (ConvF2I src));
11724 format %{ "evcvttss2sisl $dst, $src" %}
11725 ins_encode %{
11726 __ evcvttss2sisl($dst$$Register, $src$$XMMRegister);
11727 %}
11728 ins_pipe(pipe_slow);
11729 %}
11730
11731 instruct convF2I_reg_mem_avx10(rRegI dst, memory src)
11732 %{
11733 predicate(VM_Version::supports_avx10_2());
11734 match(Set dst (ConvF2I (LoadF src)));
11735 format %{ "evcvttss2sisl $dst, $src" %}
11736 ins_encode %{
11737 __ evcvttss2sisl($dst$$Register, $src$$Address);
11738 %}
11739 ins_pipe(pipe_slow);
11740 %}
11741
11742 instruct convF2L_reg_reg(rRegL dst, regF src, rFlagsReg cr)
11743 %{
11744 predicate(!VM_Version::supports_avx10_2());
11745 match(Set dst (ConvF2L src));
11746 effect(KILL cr);
11747 format %{ "convert_f2l $dst, $src"%}
11748 ins_encode %{
11749 __ convertF2I(T_LONG, T_FLOAT, $dst$$Register, $src$$XMMRegister);
11750 %}
11751 ins_pipe(pipe_slow);
11752 %}
11753
11754 instruct convF2L_reg_reg_avx10(rRegL dst, regF src)
11755 %{
11756 predicate(VM_Version::supports_avx10_2());
11757 match(Set dst (ConvF2L src));
11758 format %{ "evcvttss2sisq $dst, $src" %}
11759 ins_encode %{
11760 __ evcvttss2sisq($dst$$Register, $src$$XMMRegister);
11761 %}
11762 ins_pipe(pipe_slow);
11763 %}
11764
11765 instruct convF2L_reg_mem_avx10(rRegL dst, memory src)
11766 %{
11767 predicate(VM_Version::supports_avx10_2());
11768 match(Set dst (ConvF2L (LoadF src)));
11769 format %{ "evcvttss2sisq $dst, $src" %}
11770 ins_encode %{
11771 __ evcvttss2sisq($dst$$Register, $src$$Address);
11772 %}
11773 ins_pipe(pipe_slow);
11774 %}
11775
11776 instruct convD2I_reg_reg(rRegI dst, regD src, rFlagsReg cr)
11777 %{
11778 predicate(!VM_Version::supports_avx10_2());
11779 match(Set dst (ConvD2I src));
11780 effect(KILL cr);
11781 format %{ "convert_d2i $dst, $src"%}
11782 ins_encode %{
11783 __ convertF2I(T_INT, T_DOUBLE, $dst$$Register, $src$$XMMRegister);
11784 %}
11785 ins_pipe(pipe_slow);
11786 %}
11787
11788 instruct convD2I_reg_reg_avx10(rRegI dst, regD src)
11789 %{
11790 predicate(VM_Version::supports_avx10_2());
11791 match(Set dst (ConvD2I src));
11792 format %{ "evcvttsd2sisl $dst, $src" %}
11793 ins_encode %{
11794 __ evcvttsd2sisl($dst$$Register, $src$$XMMRegister);
11795 %}
11796 ins_pipe(pipe_slow);
11797 %}
11798
11799 instruct convD2I_reg_mem_avx10(rRegI dst, memory src)
11800 %{
11801 predicate(VM_Version::supports_avx10_2());
11802 match(Set dst (ConvD2I (LoadD src)));
11803 format %{ "evcvttsd2sisl $dst, $src" %}
11804 ins_encode %{
11805 __ evcvttsd2sisl($dst$$Register, $src$$Address);
11806 %}
11807 ins_pipe(pipe_slow);
11808 %}
11809
11810 instruct convD2L_reg_reg(rRegL dst, regD src, rFlagsReg cr)
11811 %{
11812 predicate(!VM_Version::supports_avx10_2());
11813 match(Set dst (ConvD2L src));
11814 effect(KILL cr);
11815 format %{ "convert_d2l $dst, $src"%}
11816 ins_encode %{
11817 __ convertF2I(T_LONG, T_DOUBLE, $dst$$Register, $src$$XMMRegister);
11818 %}
11819 ins_pipe(pipe_slow);
11820 %}
11821
11822 instruct convD2L_reg_reg_avx10(rRegL dst, regD src)
11823 %{
11824 predicate(VM_Version::supports_avx10_2());
11825 match(Set dst (ConvD2L src));
11826 format %{ "evcvttsd2sisq $dst, $src" %}
11827 ins_encode %{
11828 __ evcvttsd2sisq($dst$$Register, $src$$XMMRegister);
11829 %}
11830 ins_pipe(pipe_slow);
11831 %}
11832
11833 instruct convD2L_reg_mem_avx10(rRegL dst, memory src)
11834 %{
11835 predicate(VM_Version::supports_avx10_2());
11836 match(Set dst (ConvD2L (LoadD src)));
11837 format %{ "evcvttsd2sisq $dst, $src" %}
11838 ins_encode %{
11839 __ evcvttsd2sisq($dst$$Register, $src$$Address);
11840 %}
11841 ins_pipe(pipe_slow);
11842 %}
11843
11844 instruct round_double_reg(rRegL dst, regD src, rRegL rtmp, rcx_RegL rcx, rFlagsReg cr)
11845 %{
11846 match(Set dst (RoundD src));
11847 effect(TEMP dst, TEMP rtmp, TEMP rcx, KILL cr);
11848 format %{ "round_double $dst,$src \t! using $rtmp and $rcx as TEMP"%}
11849 ins_encode %{
11850 __ round_double($dst$$Register, $src$$XMMRegister, $rtmp$$Register, $rcx$$Register);
11851 %}
11852 ins_pipe(pipe_slow);
11853 %}
11854
11855 instruct round_float_reg(rRegI dst, regF src, rRegL rtmp, rcx_RegL rcx, rFlagsReg cr)
11856 %{
11857 match(Set dst (RoundF src));
11858 effect(TEMP dst, TEMP rtmp, TEMP rcx, KILL cr);
11859 format %{ "round_float $dst,$src" %}
11860 ins_encode %{
11861 __ round_float($dst$$Register, $src$$XMMRegister, $rtmp$$Register, $rcx$$Register);
11862 %}
11863 ins_pipe(pipe_slow);
11864 %}
11865
11866 instruct convI2F_reg_reg(vlRegF dst, rRegI src)
11867 %{
11868 predicate(!UseXmmI2F);
11869 match(Set dst (ConvI2F src));
11870
11871 format %{ "cvtsi2ssl $dst, $src\t# i2f" %}
11872 ins_encode %{
11873 if (UseAVX > 0) {
11874 __ pxor($dst$$XMMRegister, $dst$$XMMRegister);
11875 }
11876 __ cvtsi2ssl ($dst$$XMMRegister, $src$$Register);
11877 %}
11878 ins_pipe(pipe_slow); // XXX
11879 %}
11880
11881 instruct convI2F_reg_mem(regF dst, memory src)
11882 %{
11883 predicate(UseAVX == 0);
11884 match(Set dst (ConvI2F (LoadI src)));
11885
11886 format %{ "cvtsi2ssl $dst, $src\t# i2f" %}
11887 ins_encode %{
11888 __ cvtsi2ssl ($dst$$XMMRegister, $src$$Address);
11889 %}
11890 ins_pipe(pipe_slow); // XXX
11891 %}
11892
11893 instruct convI2D_reg_reg(vlRegD dst, rRegI src)
11894 %{
11895 predicate(!UseXmmI2D);
11896 match(Set dst (ConvI2D src));
11897
11898 format %{ "cvtsi2sdl $dst, $src\t# i2d" %}
11899 ins_encode %{
11900 if (UseAVX > 0) {
11901 __ pxor($dst$$XMMRegister, $dst$$XMMRegister);
11902 }
11903 __ cvtsi2sdl ($dst$$XMMRegister, $src$$Register);
11904 %}
11905 ins_pipe(pipe_slow); // XXX
11906 %}
11907
11908 instruct convI2D_reg_mem(regD dst, memory src)
11909 %{
11910 predicate(UseAVX == 0);
11911 match(Set dst (ConvI2D (LoadI src)));
11912
11913 format %{ "cvtsi2sdl $dst, $src\t# i2d" %}
11914 ins_encode %{
11915 __ cvtsi2sdl ($dst$$XMMRegister, $src$$Address);
11916 %}
11917 ins_pipe(pipe_slow); // XXX
11918 %}
11919
11920 instruct convXI2F_reg(regF dst, rRegI src)
11921 %{
11922 predicate(UseXmmI2F);
11923 match(Set dst (ConvI2F src));
11924
11925 format %{ "movdl $dst, $src\n\t"
11926 "cvtdq2psl $dst, $dst\t# i2f" %}
11927 ins_encode %{
11928 __ movdl($dst$$XMMRegister, $src$$Register);
11929 __ cvtdq2ps($dst$$XMMRegister, $dst$$XMMRegister);
11930 %}
11931 ins_pipe(pipe_slow); // XXX
11932 %}
11933
11934 instruct convXI2D_reg(regD dst, rRegI src)
11935 %{
11936 predicate(UseXmmI2D);
11937 match(Set dst (ConvI2D src));
11938
11939 format %{ "movdl $dst, $src\n\t"
11940 "cvtdq2pdl $dst, $dst\t# i2d" %}
11941 ins_encode %{
11942 __ movdl($dst$$XMMRegister, $src$$Register);
11943 __ cvtdq2pd($dst$$XMMRegister, $dst$$XMMRegister);
11944 %}
11945 ins_pipe(pipe_slow); // XXX
11946 %}
11947
11948 instruct convL2F_reg_reg(vlRegF dst, rRegL src)
11949 %{
11950 match(Set dst (ConvL2F src));
11951
11952 format %{ "cvtsi2ssq $dst, $src\t# l2f" %}
11953 ins_encode %{
11954 if (UseAVX > 0) {
11955 __ pxor($dst$$XMMRegister, $dst$$XMMRegister);
11956 }
11957 __ cvtsi2ssq ($dst$$XMMRegister, $src$$Register);
11958 %}
11959 ins_pipe(pipe_slow); // XXX
11960 %}
11961
11962 instruct convL2F_reg_mem(regF dst, memory src)
11963 %{
11964 predicate(UseAVX == 0);
11965 match(Set dst (ConvL2F (LoadL src)));
11966
11967 format %{ "cvtsi2ssq $dst, $src\t# l2f" %}
11968 ins_encode %{
11969 __ cvtsi2ssq ($dst$$XMMRegister, $src$$Address);
11970 %}
11971 ins_pipe(pipe_slow); // XXX
11972 %}
11973
11974 instruct convL2D_reg_reg(vlRegD dst, rRegL src)
11975 %{
11976 match(Set dst (ConvL2D src));
11977
11978 format %{ "cvtsi2sdq $dst, $src\t# l2d" %}
11979 ins_encode %{
11980 if (UseAVX > 0) {
11981 __ pxor($dst$$XMMRegister, $dst$$XMMRegister);
11982 }
11983 __ cvtsi2sdq ($dst$$XMMRegister, $src$$Register);
11984 %}
11985 ins_pipe(pipe_slow); // XXX
11986 %}
11987
11988 instruct convL2D_reg_mem(regD dst, memory src)
11989 %{
11990 predicate(UseAVX == 0);
11991 match(Set dst (ConvL2D (LoadL src)));
11992
11993 format %{ "cvtsi2sdq $dst, $src\t# l2d" %}
11994 ins_encode %{
11995 __ cvtsi2sdq ($dst$$XMMRegister, $src$$Address);
11996 %}
11997 ins_pipe(pipe_slow); // XXX
11998 %}
11999
12000 instruct convI2L_reg_reg(rRegL dst, rRegI src)
12001 %{
12002 match(Set dst (ConvI2L src));
12003
12004 ins_cost(125);
12005 format %{ "movslq $dst, $src\t# i2l" %}
12006 ins_encode %{
12007 __ movslq($dst$$Register, $src$$Register);
12008 %}
12009 ins_pipe(ialu_reg_reg);
12010 %}
12011
12012 // Zero-extend convert int to long
12013 instruct convI2L_reg_reg_zex(rRegL dst, rRegI src, immL_32bits mask)
12014 %{
12015 match(Set dst (AndL (ConvI2L src) mask));
12016
12017 format %{ "movl $dst, $src\t# i2l zero-extend\n\t" %}
12018 ins_encode %{
12019 if ($dst$$reg != $src$$reg) {
12020 __ movl($dst$$Register, $src$$Register);
12021 }
12022 %}
12023 ins_pipe(ialu_reg_reg);
12024 %}
12025
12026 // Zero-extend convert int to long
12027 instruct convI2L_reg_mem_zex(rRegL dst, memory src, immL_32bits mask)
12028 %{
12029 match(Set dst (AndL (ConvI2L (LoadI src)) mask));
12030
12031 format %{ "movl $dst, $src\t# i2l zero-extend\n\t" %}
12032 ins_encode %{
12033 __ movl($dst$$Register, $src$$Address);
12034 %}
12035 ins_pipe(ialu_reg_mem);
12036 %}
12037
12038 instruct zerox_long_reg_reg(rRegL dst, rRegL src, immL_32bits mask)
12039 %{
12040 match(Set dst (AndL src mask));
12041
12042 format %{ "movl $dst, $src\t# zero-extend long" %}
12043 ins_encode %{
12044 __ movl($dst$$Register, $src$$Register);
12045 %}
12046 ins_pipe(ialu_reg_reg);
12047 %}
12048
12049 instruct convL2I_reg_reg(rRegI dst, rRegL src)
12050 %{
12051 match(Set dst (ConvL2I src));
12052
12053 format %{ "movl $dst, $src\t# l2i" %}
12054 ins_encode %{
12055 __ movl($dst$$Register, $src$$Register);
12056 %}
12057 ins_pipe(ialu_reg_reg);
12058 %}
12059
12060
12061 instruct MoveF2I_stack_reg(rRegI dst, stackSlotF src) %{
12062 match(Set dst (MoveF2I src));
12063 effect(DEF dst, USE src);
12064
12065 ins_cost(125);
12066 format %{ "movl $dst, $src\t# MoveF2I_stack_reg" %}
12067 ins_encode %{
12068 __ movl($dst$$Register, Address(rsp, $src$$disp));
12069 %}
12070 ins_pipe(ialu_reg_mem);
12071 %}
12072
12073 instruct MoveI2F_stack_reg(regF dst, stackSlotI src) %{
12074 match(Set dst (MoveI2F src));
12075 effect(DEF dst, USE src);
12076
12077 ins_cost(125);
12078 format %{ "movss $dst, $src\t# MoveI2F_stack_reg" %}
12079 ins_encode %{
12080 __ movflt($dst$$XMMRegister, Address(rsp, $src$$disp));
12081 %}
12082 ins_pipe(pipe_slow);
12083 %}
12084
12085 instruct MoveD2L_stack_reg(rRegL dst, stackSlotD src) %{
12086 match(Set dst (MoveD2L src));
12087 effect(DEF dst, USE src);
12088
12089 ins_cost(125);
12090 format %{ "movq $dst, $src\t# MoveD2L_stack_reg" %}
12091 ins_encode %{
12092 __ movq($dst$$Register, Address(rsp, $src$$disp));
12093 %}
12094 ins_pipe(ialu_reg_mem);
12095 %}
12096
12097 instruct MoveL2D_stack_reg_partial(regD dst, stackSlotL src) %{
12098 predicate(!UseXmmLoadAndClearUpper);
12099 match(Set dst (MoveL2D src));
12100 effect(DEF dst, USE src);
12101
12102 ins_cost(125);
12103 format %{ "movlpd $dst, $src\t# MoveL2D_stack_reg" %}
12104 ins_encode %{
12105 __ movdbl($dst$$XMMRegister, Address(rsp, $src$$disp));
12106 %}
12107 ins_pipe(pipe_slow);
12108 %}
12109
12110 instruct MoveL2D_stack_reg(regD dst, stackSlotL src) %{
12111 predicate(UseXmmLoadAndClearUpper);
12112 match(Set dst (MoveL2D src));
12113 effect(DEF dst, USE src);
12114
12115 ins_cost(125);
12116 format %{ "movsd $dst, $src\t# MoveL2D_stack_reg" %}
12117 ins_encode %{
12118 __ movdbl($dst$$XMMRegister, Address(rsp, $src$$disp));
12119 %}
12120 ins_pipe(pipe_slow);
12121 %}
12122
12123
12124 instruct MoveF2I_reg_stack(stackSlotI dst, regF src) %{
12125 match(Set dst (MoveF2I src));
12126 effect(DEF dst, USE src);
12127
12128 ins_cost(95); // XXX
12129 format %{ "movss $dst, $src\t# MoveF2I_reg_stack" %}
12130 ins_encode %{
12131 __ movflt(Address(rsp, $dst$$disp), $src$$XMMRegister);
12132 %}
12133 ins_pipe(pipe_slow);
12134 %}
12135
12136 instruct MoveI2F_reg_stack(stackSlotF dst, rRegI src) %{
12137 match(Set dst (MoveI2F src));
12138 effect(DEF dst, USE src);
12139
12140 ins_cost(100);
12141 format %{ "movl $dst, $src\t# MoveI2F_reg_stack" %}
12142 ins_encode %{
12143 __ movl(Address(rsp, $dst$$disp), $src$$Register);
12144 %}
12145 ins_pipe( ialu_mem_reg );
12146 %}
12147
12148 instruct MoveD2L_reg_stack(stackSlotL dst, regD src) %{
12149 match(Set dst (MoveD2L src));
12150 effect(DEF dst, USE src);
12151
12152 ins_cost(95); // XXX
12153 format %{ "movsd $dst, $src\t# MoveL2D_reg_stack" %}
12154 ins_encode %{
12155 __ movdbl(Address(rsp, $dst$$disp), $src$$XMMRegister);
12156 %}
12157 ins_pipe(pipe_slow);
12158 %}
12159
12160 instruct MoveL2D_reg_stack(stackSlotD dst, rRegL src) %{
12161 match(Set dst (MoveL2D src));
12162 effect(DEF dst, USE src);
12163
12164 ins_cost(100);
12165 format %{ "movq $dst, $src\t# MoveL2D_reg_stack" %}
12166 ins_encode %{
12167 __ movq(Address(rsp, $dst$$disp), $src$$Register);
12168 %}
12169 ins_pipe(ialu_mem_reg);
12170 %}
12171
12172 instruct MoveF2I_reg_reg(rRegI dst, regF src) %{
12173 match(Set dst (MoveF2I src));
12174 effect(DEF dst, USE src);
12175 ins_cost(85);
12176 format %{ "movd $dst,$src\t# MoveF2I" %}
12177 ins_encode %{
12178 __ movdl($dst$$Register, $src$$XMMRegister);
12179 %}
12180 ins_pipe( pipe_slow );
12181 %}
12182
12183 instruct MoveD2L_reg_reg(rRegL dst, regD src) %{
12184 match(Set dst (MoveD2L src));
12185 effect(DEF dst, USE src);
12186 ins_cost(85);
12187 format %{ "movd $dst,$src\t# MoveD2L" %}
12188 ins_encode %{
12189 __ movdq($dst$$Register, $src$$XMMRegister);
12190 %}
12191 ins_pipe( pipe_slow );
12192 %}
12193
12194 instruct MoveI2F_reg_reg(regF dst, rRegI src) %{
12195 match(Set dst (MoveI2F src));
12196 effect(DEF dst, USE src);
12197 ins_cost(100);
12198 format %{ "movd $dst,$src\t# MoveI2F" %}
12199 ins_encode %{
12200 __ movdl($dst$$XMMRegister, $src$$Register);
12201 %}
12202 ins_pipe( pipe_slow );
12203 %}
12204
12205 instruct MoveL2D_reg_reg(regD dst, rRegL src) %{
12206 match(Set dst (MoveL2D src));
12207 effect(DEF dst, USE src);
12208 ins_cost(100);
12209 format %{ "movd $dst,$src\t# MoveL2D" %}
12210 ins_encode %{
12211 __ movdq($dst$$XMMRegister, $src$$Register);
12212 %}
12213 ins_pipe( pipe_slow );
12214 %}
12215
12216 // Fast clearing of an array
12217 // Small non-constant lenght ClearArray for non-AVX512 targets.
12218 instruct rep_stos(rcx_RegL cnt, rdi_RegP base, regD tmp, rax_RegI zero,
12219 Universe dummy, rFlagsReg cr)
12220 %{
12221 predicate(!((ClearArrayNode*)n)->is_large() && (UseAVX <= 2));
12222 match(Set dummy (ClearArray cnt base));
12223 effect(USE_KILL cnt, USE_KILL base, TEMP tmp, KILL zero, KILL cr);
12224
12225 format %{ $$template
12226 $$emit$$"xorq rax, rax\t# ClearArray:\n\t"
12227 $$emit$$"cmp InitArrayShortSize,rcx\n\t"
12228 $$emit$$"jg LARGE\n\t"
12229 $$emit$$"dec rcx\n\t"
12230 $$emit$$"js DONE\t# Zero length\n\t"
12231 $$emit$$"mov rax,(rdi,rcx,8)\t# LOOP\n\t"
12232 $$emit$$"dec rcx\n\t"
12233 $$emit$$"jge LOOP\n\t"
12234 $$emit$$"jmp DONE\n\t"
12235 $$emit$$"# LARGE:\n\t"
12236 if (UseFastStosb) {
12237 $$emit$$"shlq rcx,3\t# Convert doublewords to bytes\n\t"
12238 $$emit$$"rep stosb\t# Store rax to *rdi++ while rcx--\n\t"
12239 } else if (UseXMMForObjInit) {
12240 $$emit$$"mov rdi,rax\n\t"
12241 $$emit$$"vpxor ymm0,ymm0,ymm0\n\t"
12242 $$emit$$"jmpq L_zero_64_bytes\n\t"
12243 $$emit$$"# L_loop:\t# 64-byte LOOP\n\t"
12244 $$emit$$"vmovdqu ymm0,(rax)\n\t"
12245 $$emit$$"vmovdqu ymm0,0x20(rax)\n\t"
12246 $$emit$$"add 0x40,rax\n\t"
12247 $$emit$$"# L_zero_64_bytes:\n\t"
12248 $$emit$$"sub 0x8,rcx\n\t"
12249 $$emit$$"jge L_loop\n\t"
12250 $$emit$$"add 0x4,rcx\n\t"
12251 $$emit$$"jl L_tail\n\t"
12252 $$emit$$"vmovdqu ymm0,(rax)\n\t"
12253 $$emit$$"add 0x20,rax\n\t"
12254 $$emit$$"sub 0x4,rcx\n\t"
12255 $$emit$$"# L_tail:\t# Clearing tail bytes\n\t"
12256 $$emit$$"add 0x4,rcx\n\t"
12257 $$emit$$"jle L_end\n\t"
12258 $$emit$$"dec rcx\n\t"
12259 $$emit$$"# L_sloop:\t# 8-byte short loop\n\t"
12260 $$emit$$"vmovq xmm0,(rax)\n\t"
12261 $$emit$$"add 0x8,rax\n\t"
12262 $$emit$$"dec rcx\n\t"
12263 $$emit$$"jge L_sloop\n\t"
12264 $$emit$$"# L_end:\n\t"
12265 } else {
12266 $$emit$$"rep stosq\t# Store rax to *rdi++ while rcx--\n\t"
12267 }
12268 $$emit$$"# DONE"
12269 %}
12270 ins_encode %{
12271 __ clear_mem($base$$Register, $cnt$$Register, $zero$$Register,
12272 $tmp$$XMMRegister, false, knoreg);
12273 %}
12274 ins_pipe(pipe_slow);
12275 %}
12276
12277 // Small non-constant length ClearArray for AVX512 targets.
12278 instruct rep_stos_evex(rcx_RegL cnt, rdi_RegP base, legRegD tmp, kReg ktmp, rax_RegI zero,
12279 Universe dummy, rFlagsReg cr)
12280 %{
12281 predicate(!((ClearArrayNode*)n)->is_large() && (UseAVX > 2));
12282 match(Set dummy (ClearArray cnt base));
12283 ins_cost(125);
12284 effect(USE_KILL cnt, USE_KILL base, TEMP tmp, TEMP ktmp, KILL zero, KILL cr);
12285
12286 format %{ $$template
12287 $$emit$$"xorq rax, rax\t# ClearArray:\n\t"
12288 $$emit$$"cmp InitArrayShortSize,rcx\n\t"
12289 $$emit$$"jg LARGE\n\t"
12290 $$emit$$"dec rcx\n\t"
12291 $$emit$$"js DONE\t# Zero length\n\t"
12292 $$emit$$"mov rax,(rdi,rcx,8)\t# LOOP\n\t"
12293 $$emit$$"dec rcx\n\t"
12294 $$emit$$"jge LOOP\n\t"
12295 $$emit$$"jmp DONE\n\t"
12296 $$emit$$"# LARGE:\n\t"
12297 if (UseFastStosb) {
12298 $$emit$$"shlq rcx,3\t# Convert doublewords to bytes\n\t"
12299 $$emit$$"rep stosb\t# Store rax to *rdi++ while rcx--\n\t"
12300 } else if (UseXMMForObjInit) {
12301 $$emit$$"mov rdi,rax\n\t"
12302 $$emit$$"vpxor ymm0,ymm0,ymm0\n\t"
12303 $$emit$$"jmpq L_zero_64_bytes\n\t"
12304 $$emit$$"# L_loop:\t# 64-byte LOOP\n\t"
12305 $$emit$$"vmovdqu ymm0,(rax)\n\t"
12306 $$emit$$"vmovdqu ymm0,0x20(rax)\n\t"
12307 $$emit$$"add 0x40,rax\n\t"
12308 $$emit$$"# L_zero_64_bytes:\n\t"
12309 $$emit$$"sub 0x8,rcx\n\t"
12310 $$emit$$"jge L_loop\n\t"
12311 $$emit$$"add 0x4,rcx\n\t"
12312 $$emit$$"jl L_tail\n\t"
12313 $$emit$$"vmovdqu ymm0,(rax)\n\t"
12314 $$emit$$"add 0x20,rax\n\t"
12315 $$emit$$"sub 0x4,rcx\n\t"
12316 $$emit$$"# L_tail:\t# Clearing tail bytes\n\t"
12317 $$emit$$"add 0x4,rcx\n\t"
12318 $$emit$$"jle L_end\n\t"
12319 $$emit$$"dec rcx\n\t"
12320 $$emit$$"# L_sloop:\t# 8-byte short loop\n\t"
12321 $$emit$$"vmovq xmm0,(rax)\n\t"
12322 $$emit$$"add 0x8,rax\n\t"
12323 $$emit$$"dec rcx\n\t"
12324 $$emit$$"jge L_sloop\n\t"
12325 $$emit$$"# L_end:\n\t"
12326 } else {
12327 $$emit$$"rep stosq\t# Store rax to *rdi++ while rcx--\n\t"
12328 }
12329 $$emit$$"# DONE"
12330 %}
12331 ins_encode %{
12332 __ clear_mem($base$$Register, $cnt$$Register, $zero$$Register,
12333 $tmp$$XMMRegister, false, $ktmp$$KRegister);
12334 %}
12335 ins_pipe(pipe_slow);
12336 %}
12337
12338 // Large non-constant length ClearArray for non-AVX512 targets.
12339 instruct rep_stos_large(rcx_RegL cnt, rdi_RegP base, regD tmp, rax_RegI zero,
12340 Universe dummy, rFlagsReg cr)
12341 %{
12342 predicate((UseAVX <=2) && ((ClearArrayNode*)n)->is_large());
12343 match(Set dummy (ClearArray cnt base));
12344 effect(USE_KILL cnt, USE_KILL base, TEMP tmp, KILL zero, KILL cr);
12345
12346 format %{ $$template
12347 if (UseFastStosb) {
12348 $$emit$$"xorq rax, rax\t# ClearArray:\n\t"
12349 $$emit$$"shlq rcx,3\t# Convert doublewords to bytes\n\t"
12350 $$emit$$"rep stosb\t# Store rax to *rdi++ while rcx--"
12351 } else if (UseXMMForObjInit) {
12352 $$emit$$"mov rdi,rax\t# ClearArray:\n\t"
12353 $$emit$$"vpxor ymm0,ymm0,ymm0\n\t"
12354 $$emit$$"jmpq L_zero_64_bytes\n\t"
12355 $$emit$$"# L_loop:\t# 64-byte LOOP\n\t"
12356 $$emit$$"vmovdqu ymm0,(rax)\n\t"
12357 $$emit$$"vmovdqu ymm0,0x20(rax)\n\t"
12358 $$emit$$"add 0x40,rax\n\t"
12359 $$emit$$"# L_zero_64_bytes:\n\t"
12360 $$emit$$"sub 0x8,rcx\n\t"
12361 $$emit$$"jge L_loop\n\t"
12362 $$emit$$"add 0x4,rcx\n\t"
12363 $$emit$$"jl L_tail\n\t"
12364 $$emit$$"vmovdqu ymm0,(rax)\n\t"
12365 $$emit$$"add 0x20,rax\n\t"
12366 $$emit$$"sub 0x4,rcx\n\t"
12367 $$emit$$"# L_tail:\t# Clearing tail bytes\n\t"
12368 $$emit$$"add 0x4,rcx\n\t"
12369 $$emit$$"jle L_end\n\t"
12370 $$emit$$"dec rcx\n\t"
12371 $$emit$$"# L_sloop:\t# 8-byte short loop\n\t"
12372 $$emit$$"vmovq xmm0,(rax)\n\t"
12373 $$emit$$"add 0x8,rax\n\t"
12374 $$emit$$"dec rcx\n\t"
12375 $$emit$$"jge L_sloop\n\t"
12376 $$emit$$"# L_end:\n\t"
12377 } else {
12378 $$emit$$"xorq rax, rax\t# ClearArray:\n\t"
12379 $$emit$$"rep stosq\t# Store rax to *rdi++ while rcx--"
12380 }
12381 %}
12382 ins_encode %{
12383 __ clear_mem($base$$Register, $cnt$$Register, $zero$$Register,
12384 $tmp$$XMMRegister, true, knoreg);
12385 %}
12386 ins_pipe(pipe_slow);
12387 %}
12388
12389 // Large non-constant length ClearArray for AVX512 targets.
12390 instruct rep_stos_large_evex(rcx_RegL cnt, rdi_RegP base, legRegD tmp, kReg ktmp, rax_RegI zero,
12391 Universe dummy, rFlagsReg cr)
12392 %{
12393 predicate((UseAVX > 2) && ((ClearArrayNode*)n)->is_large());
12394 match(Set dummy (ClearArray cnt base));
12395 effect(USE_KILL cnt, USE_KILL base, TEMP tmp, TEMP ktmp, KILL zero, KILL cr);
12396
12397 format %{ $$template
12398 if (UseFastStosb) {
12399 $$emit$$"xorq rax, rax\t# ClearArray:\n\t"
12400 $$emit$$"shlq rcx,3\t# Convert doublewords to bytes\n\t"
12401 $$emit$$"rep stosb\t# Store rax to *rdi++ while rcx--"
12402 } else if (UseXMMForObjInit) {
12403 $$emit$$"mov rdi,rax\t# ClearArray:\n\t"
12404 $$emit$$"vpxor ymm0,ymm0,ymm0\n\t"
12405 $$emit$$"jmpq L_zero_64_bytes\n\t"
12406 $$emit$$"# L_loop:\t# 64-byte LOOP\n\t"
12407 $$emit$$"vmovdqu ymm0,(rax)\n\t"
12408 $$emit$$"vmovdqu ymm0,0x20(rax)\n\t"
12409 $$emit$$"add 0x40,rax\n\t"
12410 $$emit$$"# L_zero_64_bytes:\n\t"
12411 $$emit$$"sub 0x8,rcx\n\t"
12412 $$emit$$"jge L_loop\n\t"
12413 $$emit$$"add 0x4,rcx\n\t"
12414 $$emit$$"jl L_tail\n\t"
12415 $$emit$$"vmovdqu ymm0,(rax)\n\t"
12416 $$emit$$"add 0x20,rax\n\t"
12417 $$emit$$"sub 0x4,rcx\n\t"
12418 $$emit$$"# L_tail:\t# Clearing tail bytes\n\t"
12419 $$emit$$"add 0x4,rcx\n\t"
12420 $$emit$$"jle L_end\n\t"
12421 $$emit$$"dec rcx\n\t"
12422 $$emit$$"# L_sloop:\t# 8-byte short loop\n\t"
12423 $$emit$$"vmovq xmm0,(rax)\n\t"
12424 $$emit$$"add 0x8,rax\n\t"
12425 $$emit$$"dec rcx\n\t"
12426 $$emit$$"jge L_sloop\n\t"
12427 $$emit$$"# L_end:\n\t"
12428 } else {
12429 $$emit$$"xorq rax, rax\t# ClearArray:\n\t"
12430 $$emit$$"rep stosq\t# Store rax to *rdi++ while rcx--"
12431 }
12432 %}
12433 ins_encode %{
12434 __ clear_mem($base$$Register, $cnt$$Register, $zero$$Register,
12435 $tmp$$XMMRegister, true, $ktmp$$KRegister);
12436 %}
12437 ins_pipe(pipe_slow);
12438 %}
12439
12440 // Small constant length ClearArray for AVX512 targets.
12441 instruct rep_stos_im(immL cnt, rRegP base, regD tmp, rRegI zero, kReg ktmp, Universe dummy, rFlagsReg cr)
12442 %{
12443 predicate(!((ClearArrayNode*)n)->is_large() && (MaxVectorSize >= 32) && VM_Version::supports_avx512vl());
12444 match(Set dummy (ClearArray cnt base));
12445 ins_cost(100);
12446 effect(TEMP tmp, TEMP zero, TEMP ktmp, KILL cr);
12447 format %{ "clear_mem_imm $base , $cnt \n\t" %}
12448 ins_encode %{
12449 __ clear_mem($base$$Register, $cnt$$constant, $zero$$Register, $tmp$$XMMRegister, $ktmp$$KRegister);
12450 %}
12451 ins_pipe(pipe_slow);
12452 %}
12453
12454 instruct string_compareL(rdi_RegP str1, rcx_RegI cnt1, rsi_RegP str2, rdx_RegI cnt2,
12455 rax_RegI result, legRegD tmp1, rFlagsReg cr)
12456 %{
12457 predicate(!VM_Version::supports_avx512vlbw() && ((StrCompNode*)n)->encoding() == StrIntrinsicNode::LL);
12458 match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
12459 effect(TEMP tmp1, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr);
12460
12461 format %{ "String Compare byte[] $str1,$cnt1,$str2,$cnt2 -> $result // KILL $tmp1" %}
12462 ins_encode %{
12463 __ string_compare($str1$$Register, $str2$$Register,
12464 $cnt1$$Register, $cnt2$$Register, $result$$Register,
12465 $tmp1$$XMMRegister, StrIntrinsicNode::LL, knoreg);
12466 %}
12467 ins_pipe( pipe_slow );
12468 %}
12469
12470 instruct string_compareL_evex(rdi_RegP str1, rcx_RegI cnt1, rsi_RegP str2, rdx_RegI cnt2,
12471 rax_RegI result, legRegD tmp1, kReg ktmp, rFlagsReg cr)
12472 %{
12473 predicate(VM_Version::supports_avx512vlbw() && ((StrCompNode*)n)->encoding() == StrIntrinsicNode::LL);
12474 match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
12475 effect(TEMP tmp1, TEMP ktmp, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr);
12476
12477 format %{ "String Compare byte[] $str1,$cnt1,$str2,$cnt2 -> $result // KILL $tmp1" %}
12478 ins_encode %{
12479 __ string_compare($str1$$Register, $str2$$Register,
12480 $cnt1$$Register, $cnt2$$Register, $result$$Register,
12481 $tmp1$$XMMRegister, StrIntrinsicNode::LL, $ktmp$$KRegister);
12482 %}
12483 ins_pipe( pipe_slow );
12484 %}
12485
12486 instruct string_compareU(rdi_RegP str1, rcx_RegI cnt1, rsi_RegP str2, rdx_RegI cnt2,
12487 rax_RegI result, legRegD tmp1, rFlagsReg cr)
12488 %{
12489 predicate(!VM_Version::supports_avx512vlbw() && ((StrCompNode*)n)->encoding() == StrIntrinsicNode::UU);
12490 match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
12491 effect(TEMP tmp1, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr);
12492
12493 format %{ "String Compare char[] $str1,$cnt1,$str2,$cnt2 -> $result // KILL $tmp1" %}
12494 ins_encode %{
12495 __ string_compare($str1$$Register, $str2$$Register,
12496 $cnt1$$Register, $cnt2$$Register, $result$$Register,
12497 $tmp1$$XMMRegister, StrIntrinsicNode::UU, knoreg);
12498 %}
12499 ins_pipe( pipe_slow );
12500 %}
12501
12502 instruct string_compareU_evex(rdi_RegP str1, rcx_RegI cnt1, rsi_RegP str2, rdx_RegI cnt2,
12503 rax_RegI result, legRegD tmp1, kReg ktmp, rFlagsReg cr)
12504 %{
12505 predicate(VM_Version::supports_avx512vlbw() && ((StrCompNode*)n)->encoding() == StrIntrinsicNode::UU);
12506 match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
12507 effect(TEMP tmp1, TEMP ktmp, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr);
12508
12509 format %{ "String Compare char[] $str1,$cnt1,$str2,$cnt2 -> $result // KILL $tmp1" %}
12510 ins_encode %{
12511 __ string_compare($str1$$Register, $str2$$Register,
12512 $cnt1$$Register, $cnt2$$Register, $result$$Register,
12513 $tmp1$$XMMRegister, StrIntrinsicNode::UU, $ktmp$$KRegister);
12514 %}
12515 ins_pipe( pipe_slow );
12516 %}
12517
12518 instruct string_compareLU(rdi_RegP str1, rcx_RegI cnt1, rsi_RegP str2, rdx_RegI cnt2,
12519 rax_RegI result, legRegD tmp1, rFlagsReg cr)
12520 %{
12521 predicate(!VM_Version::supports_avx512vlbw() && ((StrCompNode*)n)->encoding() == StrIntrinsicNode::LU);
12522 match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
12523 effect(TEMP tmp1, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr);
12524
12525 format %{ "String Compare byte[] $str1,$cnt1,$str2,$cnt2 -> $result // KILL $tmp1" %}
12526 ins_encode %{
12527 __ string_compare($str1$$Register, $str2$$Register,
12528 $cnt1$$Register, $cnt2$$Register, $result$$Register,
12529 $tmp1$$XMMRegister, StrIntrinsicNode::LU, knoreg);
12530 %}
12531 ins_pipe( pipe_slow );
12532 %}
12533
12534 instruct string_compareLU_evex(rdi_RegP str1, rcx_RegI cnt1, rsi_RegP str2, rdx_RegI cnt2,
12535 rax_RegI result, legRegD tmp1, kReg ktmp, rFlagsReg cr)
12536 %{
12537 predicate(VM_Version::supports_avx512vlbw() && ((StrCompNode*)n)->encoding() == StrIntrinsicNode::LU);
12538 match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
12539 effect(TEMP tmp1, TEMP ktmp, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr);
12540
12541 format %{ "String Compare byte[] $str1,$cnt1,$str2,$cnt2 -> $result // KILL $tmp1" %}
12542 ins_encode %{
12543 __ string_compare($str1$$Register, $str2$$Register,
12544 $cnt1$$Register, $cnt2$$Register, $result$$Register,
12545 $tmp1$$XMMRegister, StrIntrinsicNode::LU, $ktmp$$KRegister);
12546 %}
12547 ins_pipe( pipe_slow );
12548 %}
12549
12550 instruct string_compareUL(rsi_RegP str1, rdx_RegI cnt1, rdi_RegP str2, rcx_RegI cnt2,
12551 rax_RegI result, legRegD tmp1, rFlagsReg cr)
12552 %{
12553 predicate(!VM_Version::supports_avx512vlbw() && ((StrCompNode*)n)->encoding() == StrIntrinsicNode::UL);
12554 match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
12555 effect(TEMP tmp1, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr);
12556
12557 format %{ "String Compare byte[] $str1,$cnt1,$str2,$cnt2 -> $result // KILL $tmp1" %}
12558 ins_encode %{
12559 __ string_compare($str2$$Register, $str1$$Register,
12560 $cnt2$$Register, $cnt1$$Register, $result$$Register,
12561 $tmp1$$XMMRegister, StrIntrinsicNode::UL, knoreg);
12562 %}
12563 ins_pipe( pipe_slow );
12564 %}
12565
12566 instruct string_compareUL_evex(rsi_RegP str1, rdx_RegI cnt1, rdi_RegP str2, rcx_RegI cnt2,
12567 rax_RegI result, legRegD tmp1, kReg ktmp, rFlagsReg cr)
12568 %{
12569 predicate(VM_Version::supports_avx512vlbw() && ((StrCompNode*)n)->encoding() == StrIntrinsicNode::UL);
12570 match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
12571 effect(TEMP tmp1, TEMP ktmp, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr);
12572
12573 format %{ "String Compare byte[] $str1,$cnt1,$str2,$cnt2 -> $result // KILL $tmp1" %}
12574 ins_encode %{
12575 __ string_compare($str2$$Register, $str1$$Register,
12576 $cnt2$$Register, $cnt1$$Register, $result$$Register,
12577 $tmp1$$XMMRegister, StrIntrinsicNode::UL, $ktmp$$KRegister);
12578 %}
12579 ins_pipe( pipe_slow );
12580 %}
12581
12582 // fast search of substring with known size.
12583 instruct string_indexof_conL(rdi_RegP str1, rdx_RegI cnt1, rsi_RegP str2, immI int_cnt2,
12584 rbx_RegI result, legRegD tmp_vec, rax_RegI cnt2, rcx_RegI tmp, rFlagsReg cr)
12585 %{
12586 predicate(UseSSE42Intrinsics && (((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::LL));
12587 match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 int_cnt2)));
12588 effect(TEMP tmp_vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, KILL cnt2, KILL tmp, KILL cr);
12589
12590 format %{ "String IndexOf byte[] $str1,$cnt1,$str2,$int_cnt2 -> $result // KILL $tmp_vec, $cnt1, $cnt2, $tmp" %}
12591 ins_encode %{
12592 int icnt2 = (int)$int_cnt2$$constant;
12593 if (icnt2 >= 16) {
12594 // IndexOf for constant substrings with size >= 16 elements
12595 // which don't need to be loaded through stack.
12596 __ string_indexofC8($str1$$Register, $str2$$Register,
12597 $cnt1$$Register, $cnt2$$Register,
12598 icnt2, $result$$Register,
12599 $tmp_vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::LL);
12600 } else {
12601 // Small strings are loaded through stack if they cross page boundary.
12602 __ string_indexof($str1$$Register, $str2$$Register,
12603 $cnt1$$Register, $cnt2$$Register,
12604 icnt2, $result$$Register,
12605 $tmp_vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::LL);
12606 }
12607 %}
12608 ins_pipe( pipe_slow );
12609 %}
12610
12611 // fast search of substring with known size.
12612 instruct string_indexof_conU(rdi_RegP str1, rdx_RegI cnt1, rsi_RegP str2, immI int_cnt2,
12613 rbx_RegI result, legRegD tmp_vec, rax_RegI cnt2, rcx_RegI tmp, rFlagsReg cr)
12614 %{
12615 predicate(UseSSE42Intrinsics && (((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UU));
12616 match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 int_cnt2)));
12617 effect(TEMP tmp_vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, KILL cnt2, KILL tmp, KILL cr);
12618
12619 format %{ "String IndexOf char[] $str1,$cnt1,$str2,$int_cnt2 -> $result // KILL $tmp_vec, $cnt1, $cnt2, $tmp" %}
12620 ins_encode %{
12621 int icnt2 = (int)$int_cnt2$$constant;
12622 if (icnt2 >= 8) {
12623 // IndexOf for constant substrings with size >= 8 elements
12624 // which don't need to be loaded through stack.
12625 __ string_indexofC8($str1$$Register, $str2$$Register,
12626 $cnt1$$Register, $cnt2$$Register,
12627 icnt2, $result$$Register,
12628 $tmp_vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UU);
12629 } else {
12630 // Small strings are loaded through stack if they cross page boundary.
12631 __ string_indexof($str1$$Register, $str2$$Register,
12632 $cnt1$$Register, $cnt2$$Register,
12633 icnt2, $result$$Register,
12634 $tmp_vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UU);
12635 }
12636 %}
12637 ins_pipe( pipe_slow );
12638 %}
12639
12640 // fast search of substring with known size.
12641 instruct string_indexof_conUL(rdi_RegP str1, rdx_RegI cnt1, rsi_RegP str2, immI int_cnt2,
12642 rbx_RegI result, legRegD tmp_vec, rax_RegI cnt2, rcx_RegI tmp, rFlagsReg cr)
12643 %{
12644 predicate(UseSSE42Intrinsics && (((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UL));
12645 match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 int_cnt2)));
12646 effect(TEMP tmp_vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, KILL cnt2, KILL tmp, KILL cr);
12647
12648 format %{ "String IndexOf char[] $str1,$cnt1,$str2,$int_cnt2 -> $result // KILL $tmp_vec, $cnt1, $cnt2, $tmp" %}
12649 ins_encode %{
12650 int icnt2 = (int)$int_cnt2$$constant;
12651 if (icnt2 >= 8) {
12652 // IndexOf for constant substrings with size >= 8 elements
12653 // which don't need to be loaded through stack.
12654 __ string_indexofC8($str1$$Register, $str2$$Register,
12655 $cnt1$$Register, $cnt2$$Register,
12656 icnt2, $result$$Register,
12657 $tmp_vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UL);
12658 } else {
12659 // Small strings are loaded through stack if they cross page boundary.
12660 __ string_indexof($str1$$Register, $str2$$Register,
12661 $cnt1$$Register, $cnt2$$Register,
12662 icnt2, $result$$Register,
12663 $tmp_vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UL);
12664 }
12665 %}
12666 ins_pipe( pipe_slow );
12667 %}
12668
12669 instruct string_indexofL(rdi_RegP str1, rdx_RegI cnt1, rsi_RegP str2, rax_RegI cnt2,
12670 rbx_RegI result, legRegD tmp_vec, rcx_RegI tmp, rFlagsReg cr)
12671 %{
12672 predicate(UseSSE42Intrinsics && (((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::LL));
12673 match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 cnt2)));
12674 effect(TEMP tmp_vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL tmp, KILL cr);
12675
12676 format %{ "String IndexOf byte[] $str1,$cnt1,$str2,$cnt2 -> $result // KILL all" %}
12677 ins_encode %{
12678 __ string_indexof($str1$$Register, $str2$$Register,
12679 $cnt1$$Register, $cnt2$$Register,
12680 (-1), $result$$Register,
12681 $tmp_vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::LL);
12682 %}
12683 ins_pipe( pipe_slow );
12684 %}
12685
12686 instruct string_indexofU(rdi_RegP str1, rdx_RegI cnt1, rsi_RegP str2, rax_RegI cnt2,
12687 rbx_RegI result, legRegD tmp_vec, rcx_RegI tmp, rFlagsReg cr)
12688 %{
12689 predicate(UseSSE42Intrinsics && (((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UU));
12690 match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 cnt2)));
12691 effect(TEMP tmp_vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL tmp, KILL cr);
12692
12693 format %{ "String IndexOf char[] $str1,$cnt1,$str2,$cnt2 -> $result // KILL all" %}
12694 ins_encode %{
12695 __ string_indexof($str1$$Register, $str2$$Register,
12696 $cnt1$$Register, $cnt2$$Register,
12697 (-1), $result$$Register,
12698 $tmp_vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UU);
12699 %}
12700 ins_pipe( pipe_slow );
12701 %}
12702
12703 instruct string_indexofUL(rdi_RegP str1, rdx_RegI cnt1, rsi_RegP str2, rax_RegI cnt2,
12704 rbx_RegI result, legRegD tmp_vec, rcx_RegI tmp, rFlagsReg cr)
12705 %{
12706 predicate(UseSSE42Intrinsics && (((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UL));
12707 match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 cnt2)));
12708 effect(TEMP tmp_vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL tmp, KILL cr);
12709
12710 format %{ "String IndexOf char[] $str1,$cnt1,$str2,$cnt2 -> $result // KILL all" %}
12711 ins_encode %{
12712 __ string_indexof($str1$$Register, $str2$$Register,
12713 $cnt1$$Register, $cnt2$$Register,
12714 (-1), $result$$Register,
12715 $tmp_vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UL);
12716 %}
12717 ins_pipe( pipe_slow );
12718 %}
12719
12720 instruct string_indexof_char(rdi_RegP str1, rdx_RegI cnt1, rax_RegI ch,
12721 rbx_RegI result, legRegD tmp_vec1, legRegD tmp_vec2, legRegD tmp_vec3, rcx_RegI tmp, rFlagsReg cr)
12722 %{
12723 predicate(UseSSE42Intrinsics && (((StrIndexOfCharNode*)n)->encoding() == StrIntrinsicNode::U));
12724 match(Set result (StrIndexOfChar (Binary str1 cnt1) ch));
12725 effect(TEMP tmp_vec1, TEMP tmp_vec2, TEMP tmp_vec3, USE_KILL str1, USE_KILL cnt1, USE_KILL ch, TEMP tmp, KILL cr);
12726 format %{ "StringUTF16 IndexOf char[] $str1,$cnt1,$ch -> $result // KILL all" %}
12727 ins_encode %{
12728 __ string_indexof_char($str1$$Register, $cnt1$$Register, $ch$$Register, $result$$Register,
12729 $tmp_vec1$$XMMRegister, $tmp_vec2$$XMMRegister, $tmp_vec3$$XMMRegister, $tmp$$Register);
12730 %}
12731 ins_pipe( pipe_slow );
12732 %}
12733
12734 instruct stringL_indexof_char(rdi_RegP str1, rdx_RegI cnt1, rax_RegI ch,
12735 rbx_RegI result, legRegD tmp_vec1, legRegD tmp_vec2, legRegD tmp_vec3, rcx_RegI tmp, rFlagsReg cr)
12736 %{
12737 predicate(UseSSE42Intrinsics && (((StrIndexOfCharNode*)n)->encoding() == StrIntrinsicNode::L));
12738 match(Set result (StrIndexOfChar (Binary str1 cnt1) ch));
12739 effect(TEMP tmp_vec1, TEMP tmp_vec2, TEMP tmp_vec3, USE_KILL str1, USE_KILL cnt1, USE_KILL ch, TEMP tmp, KILL cr);
12740 format %{ "StringLatin1 IndexOf char[] $str1,$cnt1,$ch -> $result // KILL all" %}
12741 ins_encode %{
12742 __ stringL_indexof_char($str1$$Register, $cnt1$$Register, $ch$$Register, $result$$Register,
12743 $tmp_vec1$$XMMRegister, $tmp_vec2$$XMMRegister, $tmp_vec3$$XMMRegister, $tmp$$Register);
12744 %}
12745 ins_pipe( pipe_slow );
12746 %}
12747
12748 // fast string equals
12749 instruct string_equals(rdi_RegP str1, rsi_RegP str2, rcx_RegI cnt, rax_RegI result,
12750 legRegD tmp1, legRegD tmp2, rbx_RegI tmp3, rFlagsReg cr)
12751 %{
12752 predicate(!VM_Version::supports_avx512vlbw());
12753 match(Set result (StrEquals (Binary str1 str2) cnt));
12754 effect(TEMP tmp1, TEMP tmp2, USE_KILL str1, USE_KILL str2, USE_KILL cnt, KILL tmp3, KILL cr);
12755
12756 format %{ "String Equals $str1,$str2,$cnt -> $result // KILL $tmp1, $tmp2, $tmp3" %}
12757 ins_encode %{
12758 __ arrays_equals(false, $str1$$Register, $str2$$Register,
12759 $cnt$$Register, $result$$Register, $tmp3$$Register,
12760 $tmp1$$XMMRegister, $tmp2$$XMMRegister, false /* char */, knoreg);
12761 %}
12762 ins_pipe( pipe_slow );
12763 %}
12764
12765 instruct string_equals_evex(rdi_RegP str1, rsi_RegP str2, rcx_RegI cnt, rax_RegI result,
12766 legRegD tmp1, legRegD tmp2, kReg ktmp, rbx_RegI tmp3, rFlagsReg cr)
12767 %{
12768 predicate(VM_Version::supports_avx512vlbw());
12769 match(Set result (StrEquals (Binary str1 str2) cnt));
12770 effect(TEMP tmp1, TEMP tmp2, TEMP ktmp, USE_KILL str1, USE_KILL str2, USE_KILL cnt, KILL tmp3, KILL cr);
12771
12772 format %{ "String Equals $str1,$str2,$cnt -> $result // KILL $tmp1, $tmp2, $tmp3" %}
12773 ins_encode %{
12774 __ arrays_equals(false, $str1$$Register, $str2$$Register,
12775 $cnt$$Register, $result$$Register, $tmp3$$Register,
12776 $tmp1$$XMMRegister, $tmp2$$XMMRegister, false /* char */, $ktmp$$KRegister);
12777 %}
12778 ins_pipe( pipe_slow );
12779 %}
12780
12781 // fast array equals
12782 instruct array_equalsB(rdi_RegP ary1, rsi_RegP ary2, rax_RegI result,
12783 legRegD tmp1, legRegD tmp2, rcx_RegI tmp3, rbx_RegI tmp4, rFlagsReg cr)
12784 %{
12785 predicate(!VM_Version::supports_avx512vlbw() && ((AryEqNode*)n)->encoding() == StrIntrinsicNode::LL);
12786 match(Set result (AryEq ary1 ary2));
12787 effect(TEMP tmp1, TEMP tmp2, USE_KILL ary1, USE_KILL ary2, KILL tmp3, KILL tmp4, KILL cr);
12788
12789 format %{ "Array Equals byte[] $ary1,$ary2 -> $result // KILL $tmp1, $tmp2, $tmp3, $tmp4" %}
12790 ins_encode %{
12791 __ arrays_equals(true, $ary1$$Register, $ary2$$Register,
12792 $tmp3$$Register, $result$$Register, $tmp4$$Register,
12793 $tmp1$$XMMRegister, $tmp2$$XMMRegister, false /* char */, knoreg);
12794 %}
12795 ins_pipe( pipe_slow );
12796 %}
12797
12798 instruct array_equalsB_evex(rdi_RegP ary1, rsi_RegP ary2, rax_RegI result,
12799 legRegD tmp1, legRegD tmp2, kReg ktmp, rcx_RegI tmp3, rbx_RegI tmp4, rFlagsReg cr)
12800 %{
12801 predicate(VM_Version::supports_avx512vlbw() && ((AryEqNode*)n)->encoding() == StrIntrinsicNode::LL);
12802 match(Set result (AryEq ary1 ary2));
12803 effect(TEMP tmp1, TEMP tmp2, TEMP ktmp, USE_KILL ary1, USE_KILL ary2, KILL tmp3, KILL tmp4, KILL cr);
12804
12805 format %{ "Array Equals byte[] $ary1,$ary2 -> $result // KILL $tmp1, $tmp2, $tmp3, $tmp4" %}
12806 ins_encode %{
12807 __ arrays_equals(true, $ary1$$Register, $ary2$$Register,
12808 $tmp3$$Register, $result$$Register, $tmp4$$Register,
12809 $tmp1$$XMMRegister, $tmp2$$XMMRegister, false /* char */, $ktmp$$KRegister);
12810 %}
12811 ins_pipe( pipe_slow );
12812 %}
12813
12814 instruct array_equalsC(rdi_RegP ary1, rsi_RegP ary2, rax_RegI result,
12815 legRegD tmp1, legRegD tmp2, rcx_RegI tmp3, rbx_RegI tmp4, rFlagsReg cr)
12816 %{
12817 predicate(!VM_Version::supports_avx512vlbw() && ((AryEqNode*)n)->encoding() == StrIntrinsicNode::UU);
12818 match(Set result (AryEq ary1 ary2));
12819 effect(TEMP tmp1, TEMP tmp2, USE_KILL ary1, USE_KILL ary2, KILL tmp3, KILL tmp4, KILL cr);
12820
12821 format %{ "Array Equals char[] $ary1,$ary2 -> $result // KILL $tmp1, $tmp2, $tmp3, $tmp4" %}
12822 ins_encode %{
12823 __ arrays_equals(true, $ary1$$Register, $ary2$$Register,
12824 $tmp3$$Register, $result$$Register, $tmp4$$Register,
12825 $tmp1$$XMMRegister, $tmp2$$XMMRegister, true /* char */, knoreg);
12826 %}
12827 ins_pipe( pipe_slow );
12828 %}
12829
12830 instruct array_equalsC_evex(rdi_RegP ary1, rsi_RegP ary2, rax_RegI result,
12831 legRegD tmp1, legRegD tmp2, kReg ktmp, rcx_RegI tmp3, rbx_RegI tmp4, rFlagsReg cr)
12832 %{
12833 predicate(VM_Version::supports_avx512vlbw() && ((AryEqNode*)n)->encoding() == StrIntrinsicNode::UU);
12834 match(Set result (AryEq ary1 ary2));
12835 effect(TEMP tmp1, TEMP tmp2, TEMP ktmp, USE_KILL ary1, USE_KILL ary2, KILL tmp3, KILL tmp4, KILL cr);
12836
12837 format %{ "Array Equals char[] $ary1,$ary2 -> $result // KILL $tmp1, $tmp2, $tmp3, $tmp4" %}
12838 ins_encode %{
12839 __ arrays_equals(true, $ary1$$Register, $ary2$$Register,
12840 $tmp3$$Register, $result$$Register, $tmp4$$Register,
12841 $tmp1$$XMMRegister, $tmp2$$XMMRegister, true /* char */, $ktmp$$KRegister);
12842 %}
12843 ins_pipe( pipe_slow );
12844 %}
12845
12846 instruct arrays_hashcode(rdi_RegP ary1, rdx_RegI cnt1, rbx_RegI result, immU8 basic_type,
12847 legRegD tmp_vec1, legRegD tmp_vec2, legRegD tmp_vec3, legRegD tmp_vec4,
12848 legRegD tmp_vec5, legRegD tmp_vec6, legRegD tmp_vec7, legRegD tmp_vec8,
12849 legRegD tmp_vec9, legRegD tmp_vec10, legRegD tmp_vec11, legRegD tmp_vec12,
12850 legRegD tmp_vec13, rRegI tmp1, rRegI tmp2, rRegI tmp3, rFlagsReg cr)
12851 %{
12852 predicate(UseAVX >= 2);
12853 match(Set result (VectorizedHashCode (Binary ary1 cnt1) (Binary result basic_type)));
12854 effect(TEMP tmp_vec1, TEMP tmp_vec2, TEMP tmp_vec3, TEMP tmp_vec4, TEMP tmp_vec5, TEMP tmp_vec6,
12855 TEMP tmp_vec7, TEMP tmp_vec8, TEMP tmp_vec9, TEMP tmp_vec10, TEMP tmp_vec11, TEMP tmp_vec12,
12856 TEMP tmp_vec13, TEMP tmp1, TEMP tmp2, TEMP tmp3, USE_KILL ary1, USE_KILL cnt1,
12857 USE basic_type, KILL cr);
12858
12859 format %{ "Array HashCode array[] $ary1,$cnt1,$result,$basic_type -> $result // KILL all" %}
12860 ins_encode %{
12861 __ arrays_hashcode($ary1$$Register, $cnt1$$Register, $result$$Register,
12862 $tmp1$$Register, $tmp2$$Register, $tmp3$$Register,
12863 $tmp_vec1$$XMMRegister, $tmp_vec2$$XMMRegister, $tmp_vec3$$XMMRegister,
12864 $tmp_vec4$$XMMRegister, $tmp_vec5$$XMMRegister, $tmp_vec6$$XMMRegister,
12865 $tmp_vec7$$XMMRegister, $tmp_vec8$$XMMRegister, $tmp_vec9$$XMMRegister,
12866 $tmp_vec10$$XMMRegister, $tmp_vec11$$XMMRegister, $tmp_vec12$$XMMRegister,
12867 $tmp_vec13$$XMMRegister, (BasicType)$basic_type$$constant);
12868 %}
12869 ins_pipe( pipe_slow );
12870 %}
12871
12872 instruct count_positives(rsi_RegP ary1, rcx_RegI len, rax_RegI result,
12873 legRegD tmp1, legRegD tmp2, rbx_RegI tmp3, rFlagsReg cr,)
12874 %{
12875 predicate(!VM_Version::supports_avx512vlbw() || !VM_Version::supports_bmi2());
12876 match(Set result (CountPositives ary1 len));
12877 effect(TEMP tmp1, TEMP tmp2, USE_KILL ary1, USE_KILL len, KILL tmp3, KILL cr);
12878
12879 format %{ "countPositives byte[] $ary1,$len -> $result // KILL $tmp1, $tmp2, $tmp3" %}
12880 ins_encode %{
12881 __ count_positives($ary1$$Register, $len$$Register,
12882 $result$$Register, $tmp3$$Register,
12883 $tmp1$$XMMRegister, $tmp2$$XMMRegister, knoreg, knoreg);
12884 %}
12885 ins_pipe( pipe_slow );
12886 %}
12887
12888 instruct count_positives_evex(rsi_RegP ary1, rcx_RegI len, rax_RegI result,
12889 legRegD tmp1, legRegD tmp2, kReg ktmp1, kReg ktmp2, rbx_RegI tmp3, rFlagsReg cr,)
12890 %{
12891 predicate(VM_Version::supports_avx512vlbw() && VM_Version::supports_bmi2());
12892 match(Set result (CountPositives ary1 len));
12893 effect(TEMP tmp1, TEMP tmp2, TEMP ktmp1, TEMP ktmp2, USE_KILL ary1, USE_KILL len, KILL tmp3, KILL cr);
12894
12895 format %{ "countPositives byte[] $ary1,$len -> $result // KILL $tmp1, $tmp2, $tmp3" %}
12896 ins_encode %{
12897 __ count_positives($ary1$$Register, $len$$Register,
12898 $result$$Register, $tmp3$$Register,
12899 $tmp1$$XMMRegister, $tmp2$$XMMRegister, $ktmp1$$KRegister, $ktmp2$$KRegister);
12900 %}
12901 ins_pipe( pipe_slow );
12902 %}
12903
12904 // fast char[] to byte[] compression
12905 instruct string_compress(rsi_RegP src, rdi_RegP dst, rdx_RegI len, legRegD tmp1, legRegD tmp2, legRegD tmp3,
12906 legRegD tmp4, rcx_RegI tmp5, rax_RegI result, rFlagsReg cr) %{
12907 predicate(!VM_Version::supports_avx512vlbw() || !VM_Version::supports_bmi2());
12908 match(Set result (StrCompressedCopy src (Binary dst len)));
12909 effect(TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, USE_KILL src, USE_KILL dst,
12910 USE_KILL len, KILL tmp5, KILL cr);
12911
12912 format %{ "String Compress $src,$dst -> $result // KILL RAX, RCX, RDX" %}
12913 ins_encode %{
12914 __ char_array_compress($src$$Register, $dst$$Register, $len$$Register,
12915 $tmp1$$XMMRegister, $tmp2$$XMMRegister, $tmp3$$XMMRegister,
12916 $tmp4$$XMMRegister, $tmp5$$Register, $result$$Register,
12917 knoreg, knoreg);
12918 %}
12919 ins_pipe( pipe_slow );
12920 %}
12921
12922 instruct string_compress_evex(rsi_RegP src, rdi_RegP dst, rdx_RegI len, legRegD tmp1, legRegD tmp2, legRegD tmp3,
12923 legRegD tmp4, kReg ktmp1, kReg ktmp2, rcx_RegI tmp5, rax_RegI result, rFlagsReg cr) %{
12924 predicate(VM_Version::supports_avx512vlbw() && VM_Version::supports_bmi2());
12925 match(Set result (StrCompressedCopy src (Binary dst len)));
12926 effect(TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, TEMP ktmp1, TEMP ktmp2, USE_KILL src, USE_KILL dst,
12927 USE_KILL len, KILL tmp5, KILL cr);
12928
12929 format %{ "String Compress $src,$dst -> $result // KILL RAX, RCX, RDX" %}
12930 ins_encode %{
12931 __ char_array_compress($src$$Register, $dst$$Register, $len$$Register,
12932 $tmp1$$XMMRegister, $tmp2$$XMMRegister, $tmp3$$XMMRegister,
12933 $tmp4$$XMMRegister, $tmp5$$Register, $result$$Register,
12934 $ktmp1$$KRegister, $ktmp2$$KRegister);
12935 %}
12936 ins_pipe( pipe_slow );
12937 %}
12938 // fast byte[] to char[] inflation
12939 instruct string_inflate(Universe dummy, rsi_RegP src, rdi_RegP dst, rdx_RegI len,
12940 legRegD tmp1, rcx_RegI tmp2, rFlagsReg cr) %{
12941 predicate(!VM_Version::supports_avx512vlbw() || !VM_Version::supports_bmi2());
12942 match(Set dummy (StrInflatedCopy src (Binary dst len)));
12943 effect(TEMP tmp1, TEMP tmp2, USE_KILL src, USE_KILL dst, USE_KILL len, KILL cr);
12944
12945 format %{ "String Inflate $src,$dst // KILL $tmp1, $tmp2" %}
12946 ins_encode %{
12947 __ byte_array_inflate($src$$Register, $dst$$Register, $len$$Register,
12948 $tmp1$$XMMRegister, $tmp2$$Register, knoreg);
12949 %}
12950 ins_pipe( pipe_slow );
12951 %}
12952
12953 instruct string_inflate_evex(Universe dummy, rsi_RegP src, rdi_RegP dst, rdx_RegI len,
12954 legRegD tmp1, kReg ktmp, rcx_RegI tmp2, rFlagsReg cr) %{
12955 predicate(VM_Version::supports_avx512vlbw() && VM_Version::supports_bmi2());
12956 match(Set dummy (StrInflatedCopy src (Binary dst len)));
12957 effect(TEMP tmp1, TEMP tmp2, TEMP ktmp, USE_KILL src, USE_KILL dst, USE_KILL len, KILL cr);
12958
12959 format %{ "String Inflate $src,$dst // KILL $tmp1, $tmp2" %}
12960 ins_encode %{
12961 __ byte_array_inflate($src$$Register, $dst$$Register, $len$$Register,
12962 $tmp1$$XMMRegister, $tmp2$$Register, $ktmp$$KRegister);
12963 %}
12964 ins_pipe( pipe_slow );
12965 %}
12966
12967 // encode char[] to byte[] in ISO_8859_1
12968 instruct encode_iso_array(rsi_RegP src, rdi_RegP dst, rdx_RegI len,
12969 legRegD tmp1, legRegD tmp2, legRegD tmp3, legRegD tmp4,
12970 rcx_RegI tmp5, rax_RegI result, rFlagsReg cr) %{
12971 predicate(!((EncodeISOArrayNode*)n)->is_ascii());
12972 match(Set result (EncodeISOArray src (Binary dst len)));
12973 effect(TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, USE_KILL src, USE_KILL dst, USE_KILL len, KILL tmp5, KILL cr);
12974
12975 format %{ "Encode iso array $src,$dst,$len -> $result // KILL RCX, RDX, $tmp1, $tmp2, $tmp3, $tmp4, RSI, RDI " %}
12976 ins_encode %{
12977 __ encode_iso_array($src$$Register, $dst$$Register, $len$$Register,
12978 $tmp1$$XMMRegister, $tmp2$$XMMRegister, $tmp3$$XMMRegister,
12979 $tmp4$$XMMRegister, $tmp5$$Register, $result$$Register, false);
12980 %}
12981 ins_pipe( pipe_slow );
12982 %}
12983
12984 // encode char[] to byte[] in ASCII
12985 instruct encode_ascii_array(rsi_RegP src, rdi_RegP dst, rdx_RegI len,
12986 legRegD tmp1, legRegD tmp2, legRegD tmp3, legRegD tmp4,
12987 rcx_RegI tmp5, rax_RegI result, rFlagsReg cr) %{
12988 predicate(((EncodeISOArrayNode*)n)->is_ascii());
12989 match(Set result (EncodeISOArray src (Binary dst len)));
12990 effect(TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, USE_KILL src, USE_KILL dst, USE_KILL len, KILL tmp5, KILL cr);
12991
12992 format %{ "Encode ascii array $src,$dst,$len -> $result // KILL RCX, RDX, $tmp1, $tmp2, $tmp3, $tmp4, RSI, RDI " %}
12993 ins_encode %{
12994 __ encode_iso_array($src$$Register, $dst$$Register, $len$$Register,
12995 $tmp1$$XMMRegister, $tmp2$$XMMRegister, $tmp3$$XMMRegister,
12996 $tmp4$$XMMRegister, $tmp5$$Register, $result$$Register, true);
12997 %}
12998 ins_pipe( pipe_slow );
12999 %}
13000
13001 //----------Overflow Math Instructions-----------------------------------------
13002
13003 instruct overflowAddI_rReg(rFlagsReg cr, rax_RegI op1, rRegI op2)
13004 %{
13005 match(Set cr (OverflowAddI op1 op2));
13006 effect(DEF cr, USE_KILL op1, USE op2);
13007
13008 format %{ "addl $op1, $op2\t# overflow check int" %}
13009
13010 ins_encode %{
13011 __ addl($op1$$Register, $op2$$Register);
13012 %}
13013 ins_pipe(ialu_reg_reg);
13014 %}
13015
13016 instruct overflowAddI_rReg_imm(rFlagsReg cr, rax_RegI op1, immI op2)
13017 %{
13018 match(Set cr (OverflowAddI op1 op2));
13019 effect(DEF cr, USE_KILL op1, USE op2);
13020
13021 format %{ "addl $op1, $op2\t# overflow check int" %}
13022
13023 ins_encode %{
13024 __ addl($op1$$Register, $op2$$constant);
13025 %}
13026 ins_pipe(ialu_reg_reg);
13027 %}
13028
13029 instruct overflowAddL_rReg(rFlagsReg cr, rax_RegL op1, rRegL op2)
13030 %{
13031 match(Set cr (OverflowAddL op1 op2));
13032 effect(DEF cr, USE_KILL op1, USE op2);
13033
13034 format %{ "addq $op1, $op2\t# overflow check long" %}
13035 ins_encode %{
13036 __ addq($op1$$Register, $op2$$Register);
13037 %}
13038 ins_pipe(ialu_reg_reg);
13039 %}
13040
13041 instruct overflowAddL_rReg_imm(rFlagsReg cr, rax_RegL op1, immL32 op2)
13042 %{
13043 match(Set cr (OverflowAddL op1 op2));
13044 effect(DEF cr, USE_KILL op1, USE op2);
13045
13046 format %{ "addq $op1, $op2\t# overflow check long" %}
13047 ins_encode %{
13048 __ addq($op1$$Register, $op2$$constant);
13049 %}
13050 ins_pipe(ialu_reg_reg);
13051 %}
13052
13053 instruct overflowSubI_rReg(rFlagsReg cr, rRegI op1, rRegI op2)
13054 %{
13055 match(Set cr (OverflowSubI op1 op2));
13056
13057 format %{ "cmpl $op1, $op2\t# overflow check int" %}
13058 ins_encode %{
13059 __ cmpl($op1$$Register, $op2$$Register);
13060 %}
13061 ins_pipe(ialu_reg_reg);
13062 %}
13063
13064 instruct overflowSubI_rReg_imm(rFlagsReg cr, rRegI op1, immI op2)
13065 %{
13066 match(Set cr (OverflowSubI op1 op2));
13067
13068 format %{ "cmpl $op1, $op2\t# overflow check int" %}
13069 ins_encode %{
13070 __ cmpl($op1$$Register, $op2$$constant);
13071 %}
13072 ins_pipe(ialu_reg_reg);
13073 %}
13074
13075 instruct overflowSubL_rReg(rFlagsReg cr, rRegL op1, rRegL op2)
13076 %{
13077 match(Set cr (OverflowSubL op1 op2));
13078
13079 format %{ "cmpq $op1, $op2\t# overflow check long" %}
13080 ins_encode %{
13081 __ cmpq($op1$$Register, $op2$$Register);
13082 %}
13083 ins_pipe(ialu_reg_reg);
13084 %}
13085
13086 instruct overflowSubL_rReg_imm(rFlagsReg cr, rRegL op1, immL32 op2)
13087 %{
13088 match(Set cr (OverflowSubL op1 op2));
13089
13090 format %{ "cmpq $op1, $op2\t# overflow check long" %}
13091 ins_encode %{
13092 __ cmpq($op1$$Register, $op2$$constant);
13093 %}
13094 ins_pipe(ialu_reg_reg);
13095 %}
13096
13097 instruct overflowNegI_rReg(rFlagsReg cr, immI_0 zero, rax_RegI op2)
13098 %{
13099 match(Set cr (OverflowSubI zero op2));
13100 effect(DEF cr, USE_KILL op2);
13101
13102 format %{ "negl $op2\t# overflow check int" %}
13103 ins_encode %{
13104 __ negl($op2$$Register);
13105 %}
13106 ins_pipe(ialu_reg_reg);
13107 %}
13108
13109 instruct overflowNegL_rReg(rFlagsReg cr, immL0 zero, rax_RegL op2)
13110 %{
13111 match(Set cr (OverflowSubL zero op2));
13112 effect(DEF cr, USE_KILL op2);
13113
13114 format %{ "negq $op2\t# overflow check long" %}
13115 ins_encode %{
13116 __ negq($op2$$Register);
13117 %}
13118 ins_pipe(ialu_reg_reg);
13119 %}
13120
13121 instruct overflowMulI_rReg(rFlagsReg cr, rax_RegI op1, rRegI op2)
13122 %{
13123 match(Set cr (OverflowMulI op1 op2));
13124 effect(DEF cr, USE_KILL op1, USE op2);
13125
13126 format %{ "imull $op1, $op2\t# overflow check int" %}
13127 ins_encode %{
13128 __ imull($op1$$Register, $op2$$Register);
13129 %}
13130 ins_pipe(ialu_reg_reg_alu0);
13131 %}
13132
13133 instruct overflowMulI_rReg_imm(rFlagsReg cr, rRegI op1, immI op2, rRegI tmp)
13134 %{
13135 match(Set cr (OverflowMulI op1 op2));
13136 effect(DEF cr, TEMP tmp, USE op1, USE op2);
13137
13138 format %{ "imull $tmp, $op1, $op2\t# overflow check int" %}
13139 ins_encode %{
13140 __ imull($tmp$$Register, $op1$$Register, $op2$$constant);
13141 %}
13142 ins_pipe(ialu_reg_reg_alu0);
13143 %}
13144
13145 instruct overflowMulL_rReg(rFlagsReg cr, rax_RegL op1, rRegL op2)
13146 %{
13147 match(Set cr (OverflowMulL op1 op2));
13148 effect(DEF cr, USE_KILL op1, USE op2);
13149
13150 format %{ "imulq $op1, $op2\t# overflow check long" %}
13151 ins_encode %{
13152 __ imulq($op1$$Register, $op2$$Register);
13153 %}
13154 ins_pipe(ialu_reg_reg_alu0);
13155 %}
13156
13157 instruct overflowMulL_rReg_imm(rFlagsReg cr, rRegL op1, immL32 op2, rRegL tmp)
13158 %{
13159 match(Set cr (OverflowMulL op1 op2));
13160 effect(DEF cr, TEMP tmp, USE op1, USE op2);
13161
13162 format %{ "imulq $tmp, $op1, $op2\t# overflow check long" %}
13163 ins_encode %{
13164 __ imulq($tmp$$Register, $op1$$Register, $op2$$constant);
13165 %}
13166 ins_pipe(ialu_reg_reg_alu0);
13167 %}
13168
13169
13170 //----------Control Flow Instructions------------------------------------------
13171 // Signed compare Instructions
13172
13173 // XXX more variants!!
13174 instruct compI_rReg(rFlagsReg cr, rRegI op1, rRegI op2)
13175 %{
13176 match(Set cr (CmpI op1 op2));
13177 effect(DEF cr, USE op1, USE op2);
13178
13179 format %{ "cmpl $op1, $op2" %}
13180 ins_encode %{
13181 __ cmpl($op1$$Register, $op2$$Register);
13182 %}
13183 ins_pipe(ialu_cr_reg_reg);
13184 %}
13185
13186 instruct compI_rReg_imm(rFlagsReg cr, rRegI op1, immI op2)
13187 %{
13188 match(Set cr (CmpI op1 op2));
13189
13190 format %{ "cmpl $op1, $op2" %}
13191 ins_encode %{
13192 __ cmpl($op1$$Register, $op2$$constant);
13193 %}
13194 ins_pipe(ialu_cr_reg_imm);
13195 %}
13196
13197 instruct compI_rReg_mem(rFlagsReg cr, rRegI op1, memory op2)
13198 %{
13199 match(Set cr (CmpI op1 (LoadI op2)));
13200
13201 ins_cost(500); // XXX
13202 format %{ "cmpl $op1, $op2" %}
13203 ins_encode %{
13204 __ cmpl($op1$$Register, $op2$$Address);
13205 %}
13206 ins_pipe(ialu_cr_reg_mem);
13207 %}
13208
13209 instruct testI_reg(rFlagsReg cr, rRegI src, immI_0 zero)
13210 %{
13211 match(Set cr (CmpI src zero));
13212
13213 format %{ "testl $src, $src" %}
13214 ins_encode %{
13215 __ testl($src$$Register, $src$$Register);
13216 %}
13217 ins_pipe(ialu_cr_reg_imm);
13218 %}
13219
13220 instruct testI_reg_imm(rFlagsReg cr, rRegI src, immI con, immI_0 zero)
13221 %{
13222 match(Set cr (CmpI (AndI src con) zero));
13223
13224 format %{ "testl $src, $con" %}
13225 ins_encode %{
13226 __ testl($src$$Register, $con$$constant);
13227 %}
13228 ins_pipe(ialu_cr_reg_imm);
13229 %}
13230
13231 instruct testI_reg_reg(rFlagsReg cr, rRegI src1, rRegI src2, immI_0 zero)
13232 %{
13233 match(Set cr (CmpI (AndI src1 src2) zero));
13234
13235 format %{ "testl $src1, $src2" %}
13236 ins_encode %{
13237 __ testl($src1$$Register, $src2$$Register);
13238 %}
13239 ins_pipe(ialu_cr_reg_imm);
13240 %}
13241
13242 instruct testI_reg_mem(rFlagsReg cr, rRegI src, memory mem, immI_0 zero)
13243 %{
13244 match(Set cr (CmpI (AndI src (LoadI mem)) zero));
13245
13246 format %{ "testl $src, $mem" %}
13247 ins_encode %{
13248 __ testl($src$$Register, $mem$$Address);
13249 %}
13250 ins_pipe(ialu_cr_reg_mem);
13251 %}
13252
13253 // Unsigned compare Instructions; really, same as signed except they
13254 // produce an rFlagsRegU instead of rFlagsReg.
13255 instruct compU_rReg(rFlagsRegU cr, rRegI op1, rRegI op2)
13256 %{
13257 match(Set cr (CmpU op1 op2));
13258
13259 format %{ "cmpl $op1, $op2\t# unsigned" %}
13260 ins_encode %{
13261 __ cmpl($op1$$Register, $op2$$Register);
13262 %}
13263 ins_pipe(ialu_cr_reg_reg);
13264 %}
13265
13266 instruct compU_rReg_imm(rFlagsRegU cr, rRegI op1, immI op2)
13267 %{
13268 match(Set cr (CmpU op1 op2));
13269
13270 format %{ "cmpl $op1, $op2\t# unsigned" %}
13271 ins_encode %{
13272 __ cmpl($op1$$Register, $op2$$constant);
13273 %}
13274 ins_pipe(ialu_cr_reg_imm);
13275 %}
13276
13277 instruct compU_rReg_mem(rFlagsRegU cr, rRegI op1, memory op2)
13278 %{
13279 match(Set cr (CmpU op1 (LoadI op2)));
13280
13281 ins_cost(500); // XXX
13282 format %{ "cmpl $op1, $op2\t# unsigned" %}
13283 ins_encode %{
13284 __ cmpl($op1$$Register, $op2$$Address);
13285 %}
13286 ins_pipe(ialu_cr_reg_mem);
13287 %}
13288
13289 instruct testU_reg(rFlagsRegU cr, rRegI src, immI_0 zero)
13290 %{
13291 match(Set cr (CmpU src zero));
13292
13293 format %{ "testl $src, $src\t# unsigned" %}
13294 ins_encode %{
13295 __ testl($src$$Register, $src$$Register);
13296 %}
13297 ins_pipe(ialu_cr_reg_imm);
13298 %}
13299
13300 instruct compP_rReg(rFlagsRegU cr, rRegP op1, rRegP op2)
13301 %{
13302 match(Set cr (CmpP op1 op2));
13303
13304 format %{ "cmpq $op1, $op2\t# ptr" %}
13305 ins_encode %{
13306 __ cmpq($op1$$Register, $op2$$Register);
13307 %}
13308 ins_pipe(ialu_cr_reg_reg);
13309 %}
13310
13311 instruct compP_rReg_mem(rFlagsRegU cr, rRegP op1, memory op2)
13312 %{
13313 match(Set cr (CmpP op1 (LoadP op2)));
13314 predicate(n->in(2)->as_Load()->barrier_data() == 0);
13315
13316 ins_cost(500); // XXX
13317 format %{ "cmpq $op1, $op2\t# ptr" %}
13318 ins_encode %{
13319 __ cmpq($op1$$Register, $op2$$Address);
13320 %}
13321 ins_pipe(ialu_cr_reg_mem);
13322 %}
13323
13324 // XXX this is generalized by compP_rReg_mem???
13325 // Compare raw pointer (used in out-of-heap check).
13326 // Only works because non-oop pointers must be raw pointers
13327 // and raw pointers have no anti-dependencies.
13328 instruct compP_mem_rReg(rFlagsRegU cr, rRegP op1, memory op2)
13329 %{
13330 predicate(n->in(2)->in(2)->bottom_type()->reloc() == relocInfo::none &&
13331 n->in(2)->as_Load()->barrier_data() == 0);
13332 match(Set cr (CmpP op1 (LoadP op2)));
13333
13334 format %{ "cmpq $op1, $op2\t# raw ptr" %}
13335 ins_encode %{
13336 __ cmpq($op1$$Register, $op2$$Address);
13337 %}
13338 ins_pipe(ialu_cr_reg_mem);
13339 %}
13340
13341 // This will generate a signed flags result. This should be OK since
13342 // any compare to a zero should be eq/neq.
13343 instruct testP_reg(rFlagsReg cr, rRegP src, immP0 zero)
13344 %{
13345 match(Set cr (CmpP src zero));
13346
13347 format %{ "testq $src, $src\t# ptr" %}
13348 ins_encode %{
13349 __ testq($src$$Register, $src$$Register);
13350 %}
13351 ins_pipe(ialu_cr_reg_imm);
13352 %}
13353
13354 // This will generate a signed flags result. This should be OK since
13355 // any compare to a zero should be eq/neq.
13356 instruct testP_mem(rFlagsReg cr, memory op, immP0 zero)
13357 %{
13358 predicate((!UseCompressedOops || (CompressedOops::base() != nullptr)) &&
13359 n->in(1)->as_Load()->barrier_data() == 0);
13360 match(Set cr (CmpP (LoadP op) zero));
13361
13362 ins_cost(500); // XXX
13363 format %{ "testq $op, 0xffffffffffffffff\t# ptr" %}
13364 ins_encode %{
13365 __ testq($op$$Address, 0xFFFFFFFF);
13366 %}
13367 ins_pipe(ialu_cr_reg_imm);
13368 %}
13369
13370 instruct testP_mem_reg0(rFlagsReg cr, memory mem, immP0 zero)
13371 %{
13372 predicate(UseCompressedOops && (CompressedOops::base() == nullptr) &&
13373 n->in(1)->as_Load()->barrier_data() == 0);
13374 match(Set cr (CmpP (LoadP mem) zero));
13375
13376 format %{ "cmpq R12, $mem\t# ptr (R12_heapbase==0)" %}
13377 ins_encode %{
13378 __ cmpq(r12, $mem$$Address);
13379 %}
13380 ins_pipe(ialu_cr_reg_mem);
13381 %}
13382
13383 instruct compN_rReg(rFlagsRegU cr, rRegN op1, rRegN op2)
13384 %{
13385 match(Set cr (CmpN op1 op2));
13386
13387 format %{ "cmpl $op1, $op2\t# compressed ptr" %}
13388 ins_encode %{ __ cmpl($op1$$Register, $op2$$Register); %}
13389 ins_pipe(ialu_cr_reg_reg);
13390 %}
13391
13392 instruct compN_rReg_mem(rFlagsRegU cr, rRegN src, memory mem)
13393 %{
13394 predicate(n->in(2)->as_Load()->barrier_data() == 0);
13395 match(Set cr (CmpN src (LoadN mem)));
13396
13397 format %{ "cmpl $src, $mem\t# compressed ptr" %}
13398 ins_encode %{
13399 __ cmpl($src$$Register, $mem$$Address);
13400 %}
13401 ins_pipe(ialu_cr_reg_mem);
13402 %}
13403
13404 instruct compN_rReg_imm(rFlagsRegU cr, rRegN op1, immN op2) %{
13405 match(Set cr (CmpN op1 op2));
13406
13407 format %{ "cmpl $op1, $op2\t# compressed ptr" %}
13408 ins_encode %{
13409 __ cmp_narrow_oop($op1$$Register, (jobject)$op2$$constant);
13410 %}
13411 ins_pipe(ialu_cr_reg_imm);
13412 %}
13413
13414 instruct compN_mem_imm(rFlagsRegU cr, memory mem, immN src)
13415 %{
13416 predicate(n->in(2)->as_Load()->barrier_data() == 0);
13417 match(Set cr (CmpN src (LoadN mem)));
13418
13419 format %{ "cmpl $mem, $src\t# compressed ptr" %}
13420 ins_encode %{
13421 __ cmp_narrow_oop($mem$$Address, (jobject)$src$$constant);
13422 %}
13423 ins_pipe(ialu_cr_reg_mem);
13424 %}
13425
13426 instruct compN_rReg_imm_klass(rFlagsRegU cr, rRegN op1, immNKlass op2) %{
13427 match(Set cr (CmpN op1 op2));
13428
13429 format %{ "cmpl $op1, $op2\t# compressed klass ptr" %}
13430 ins_encode %{
13431 __ cmp_narrow_klass($op1$$Register, (Klass*)$op2$$constant);
13432 %}
13433 ins_pipe(ialu_cr_reg_imm);
13434 %}
13435
13436 instruct compN_mem_imm_klass(rFlagsRegU cr, memory mem, immNKlass src)
13437 %{
13438 predicate(!UseCompactObjectHeaders);
13439 match(Set cr (CmpN src (LoadNKlass mem)));
13440
13441 format %{ "cmpl $mem, $src\t# compressed klass ptr" %}
13442 ins_encode %{
13443 __ cmp_narrow_klass($mem$$Address, (Klass*)$src$$constant);
13444 %}
13445 ins_pipe(ialu_cr_reg_mem);
13446 %}
13447
13448 instruct testN_reg(rFlagsReg cr, rRegN src, immN0 zero) %{
13449 match(Set cr (CmpN src zero));
13450
13451 format %{ "testl $src, $src\t# compressed ptr" %}
13452 ins_encode %{ __ testl($src$$Register, $src$$Register); %}
13453 ins_pipe(ialu_cr_reg_imm);
13454 %}
13455
13456 instruct testN_mem(rFlagsReg cr, memory mem, immN0 zero)
13457 %{
13458 predicate(CompressedOops::base() != nullptr &&
13459 n->in(1)->as_Load()->barrier_data() == 0);
13460 match(Set cr (CmpN (LoadN mem) zero));
13461
13462 ins_cost(500); // XXX
13463 format %{ "testl $mem, 0xffffffff\t# compressed ptr" %}
13464 ins_encode %{
13465 __ cmpl($mem$$Address, (int)0xFFFFFFFF);
13466 %}
13467 ins_pipe(ialu_cr_reg_mem);
13468 %}
13469
13470 instruct testN_mem_reg0(rFlagsReg cr, memory mem, immN0 zero)
13471 %{
13472 predicate(CompressedOops::base() == nullptr &&
13473 n->in(1)->as_Load()->barrier_data() == 0);
13474 match(Set cr (CmpN (LoadN mem) zero));
13475
13476 format %{ "cmpl R12, $mem\t# compressed ptr (R12_heapbase==0)" %}
13477 ins_encode %{
13478 __ cmpl(r12, $mem$$Address);
13479 %}
13480 ins_pipe(ialu_cr_reg_mem);
13481 %}
13482
13483 // Yanked all unsigned pointer compare operations.
13484 // Pointer compares are done with CmpP which is already unsigned.
13485
13486 instruct compL_rReg(rFlagsReg cr, rRegL op1, rRegL op2)
13487 %{
13488 match(Set cr (CmpL op1 op2));
13489
13490 format %{ "cmpq $op1, $op2" %}
13491 ins_encode %{
13492 __ cmpq($op1$$Register, $op2$$Register);
13493 %}
13494 ins_pipe(ialu_cr_reg_reg);
13495 %}
13496
13497 instruct compL_rReg_imm(rFlagsReg cr, rRegL op1, immL32 op2)
13498 %{
13499 match(Set cr (CmpL op1 op2));
13500
13501 format %{ "cmpq $op1, $op2" %}
13502 ins_encode %{
13503 __ cmpq($op1$$Register, $op2$$constant);
13504 %}
13505 ins_pipe(ialu_cr_reg_imm);
13506 %}
13507
13508 instruct compL_rReg_mem(rFlagsReg cr, rRegL op1, memory op2)
13509 %{
13510 match(Set cr (CmpL op1 (LoadL op2)));
13511
13512 format %{ "cmpq $op1, $op2" %}
13513 ins_encode %{
13514 __ cmpq($op1$$Register, $op2$$Address);
13515 %}
13516 ins_pipe(ialu_cr_reg_mem);
13517 %}
13518
13519 instruct testL_reg(rFlagsReg cr, rRegL src, immL0 zero)
13520 %{
13521 match(Set cr (CmpL src zero));
13522
13523 format %{ "testq $src, $src" %}
13524 ins_encode %{
13525 __ testq($src$$Register, $src$$Register);
13526 %}
13527 ins_pipe(ialu_cr_reg_imm);
13528 %}
13529
13530 instruct testL_reg_imm(rFlagsReg cr, rRegL src, immL32 con, immL0 zero)
13531 %{
13532 match(Set cr (CmpL (AndL src con) zero));
13533
13534 format %{ "testq $src, $con\t# long" %}
13535 ins_encode %{
13536 __ testq($src$$Register, $con$$constant);
13537 %}
13538 ins_pipe(ialu_cr_reg_imm);
13539 %}
13540
13541 instruct testL_reg_reg(rFlagsReg cr, rRegL src1, rRegL src2, immL0 zero)
13542 %{
13543 match(Set cr (CmpL (AndL src1 src2) zero));
13544
13545 format %{ "testq $src1, $src2\t# long" %}
13546 ins_encode %{
13547 __ testq($src1$$Register, $src2$$Register);
13548 %}
13549 ins_pipe(ialu_cr_reg_imm);
13550 %}
13551
13552 instruct testL_reg_mem(rFlagsReg cr, rRegL src, memory mem, immL0 zero)
13553 %{
13554 match(Set cr (CmpL (AndL src (LoadL mem)) zero));
13555
13556 format %{ "testq $src, $mem" %}
13557 ins_encode %{
13558 __ testq($src$$Register, $mem$$Address);
13559 %}
13560 ins_pipe(ialu_cr_reg_mem);
13561 %}
13562
13563 instruct testL_reg_mem2(rFlagsReg cr, rRegP src, memory mem, immL0 zero)
13564 %{
13565 match(Set cr (CmpL (AndL (CastP2X src) (LoadL mem)) zero));
13566
13567 format %{ "testq $src, $mem" %}
13568 ins_encode %{
13569 __ testq($src$$Register, $mem$$Address);
13570 %}
13571 ins_pipe(ialu_cr_reg_mem);
13572 %}
13573
13574 // Manifest a CmpU result in an integer register. Very painful.
13575 // This is the test to avoid.
13576 instruct cmpU3_reg_reg(rRegI dst, rRegI src1, rRegI src2, rFlagsReg flags)
13577 %{
13578 match(Set dst (CmpU3 src1 src2));
13579 effect(KILL flags);
13580
13581 ins_cost(275); // XXX
13582 format %{ "cmpl $src1, $src2\t# CmpL3\n\t"
13583 "movl $dst, -1\n\t"
13584 "jb,u done\n\t"
13585 "setcc $dst \t# emits setne + movzbl or setzune for APX"
13586 "done:" %}
13587 ins_encode %{
13588 Label done;
13589 __ cmpl($src1$$Register, $src2$$Register);
13590 __ movl($dst$$Register, -1);
13591 __ jccb(Assembler::below, done);
13592 __ setcc(Assembler::notZero, $dst$$Register);
13593 __ bind(done);
13594 %}
13595 ins_pipe(pipe_slow);
13596 %}
13597
13598 // Manifest a CmpL result in an integer register. Very painful.
13599 // This is the test to avoid.
13600 instruct cmpL3_reg_reg(rRegI dst, rRegL src1, rRegL src2, rFlagsReg flags)
13601 %{
13602 match(Set dst (CmpL3 src1 src2));
13603 effect(KILL flags);
13604
13605 ins_cost(275); // XXX
13606 format %{ "cmpq $src1, $src2\t# CmpL3\n\t"
13607 "movl $dst, -1\n\t"
13608 "jl,s done\n\t"
13609 "setcc $dst \t# emits setne + movzbl or setzune for APX"
13610 "done:" %}
13611 ins_encode %{
13612 Label done;
13613 __ cmpq($src1$$Register, $src2$$Register);
13614 __ movl($dst$$Register, -1);
13615 __ jccb(Assembler::less, done);
13616 __ setcc(Assembler::notZero, $dst$$Register);
13617 __ bind(done);
13618 %}
13619 ins_pipe(pipe_slow);
13620 %}
13621
13622 // Manifest a CmpUL result in an integer register. Very painful.
13623 // This is the test to avoid.
13624 instruct cmpUL3_reg_reg(rRegI dst, rRegL src1, rRegL src2, rFlagsReg flags)
13625 %{
13626 match(Set dst (CmpUL3 src1 src2));
13627 effect(KILL flags);
13628
13629 ins_cost(275); // XXX
13630 format %{ "cmpq $src1, $src2\t# CmpL3\n\t"
13631 "movl $dst, -1\n\t"
13632 "jb,u done\n\t"
13633 "setcc $dst \t# emits setne + movzbl or setzune for APX"
13634 "done:" %}
13635 ins_encode %{
13636 Label done;
13637 __ cmpq($src1$$Register, $src2$$Register);
13638 __ movl($dst$$Register, -1);
13639 __ jccb(Assembler::below, done);
13640 __ setcc(Assembler::notZero, $dst$$Register);
13641 __ bind(done);
13642 %}
13643 ins_pipe(pipe_slow);
13644 %}
13645
13646 // Unsigned long compare Instructions; really, same as signed long except they
13647 // produce an rFlagsRegU instead of rFlagsReg.
13648 instruct compUL_rReg(rFlagsRegU cr, rRegL op1, rRegL op2)
13649 %{
13650 match(Set cr (CmpUL op1 op2));
13651
13652 format %{ "cmpq $op1, $op2\t# unsigned" %}
13653 ins_encode %{
13654 __ cmpq($op1$$Register, $op2$$Register);
13655 %}
13656 ins_pipe(ialu_cr_reg_reg);
13657 %}
13658
13659 instruct compUL_rReg_imm(rFlagsRegU cr, rRegL op1, immL32 op2)
13660 %{
13661 match(Set cr (CmpUL op1 op2));
13662
13663 format %{ "cmpq $op1, $op2\t# unsigned" %}
13664 ins_encode %{
13665 __ cmpq($op1$$Register, $op2$$constant);
13666 %}
13667 ins_pipe(ialu_cr_reg_imm);
13668 %}
13669
13670 instruct compUL_rReg_mem(rFlagsRegU cr, rRegL op1, memory op2)
13671 %{
13672 match(Set cr (CmpUL op1 (LoadL op2)));
13673
13674 format %{ "cmpq $op1, $op2\t# unsigned" %}
13675 ins_encode %{
13676 __ cmpq($op1$$Register, $op2$$Address);
13677 %}
13678 ins_pipe(ialu_cr_reg_mem);
13679 %}
13680
13681 instruct testUL_reg(rFlagsRegU cr, rRegL src, immL0 zero)
13682 %{
13683 match(Set cr (CmpUL src zero));
13684
13685 format %{ "testq $src, $src\t# unsigned" %}
13686 ins_encode %{
13687 __ testq($src$$Register, $src$$Register);
13688 %}
13689 ins_pipe(ialu_cr_reg_imm);
13690 %}
13691
13692 instruct compB_mem_imm(rFlagsReg cr, memory mem, immI8 imm)
13693 %{
13694 match(Set cr (CmpI (LoadB mem) imm));
13695
13696 ins_cost(125);
13697 format %{ "cmpb $mem, $imm" %}
13698 ins_encode %{ __ cmpb($mem$$Address, $imm$$constant); %}
13699 ins_pipe(ialu_cr_reg_mem);
13700 %}
13701
13702 instruct testUB_mem_imm(rFlagsReg cr, memory mem, immU7 imm, immI_0 zero)
13703 %{
13704 match(Set cr (CmpI (AndI (LoadUB mem) imm) zero));
13705
13706 ins_cost(125);
13707 format %{ "testb $mem, $imm\t# ubyte" %}
13708 ins_encode %{ __ testb($mem$$Address, $imm$$constant); %}
13709 ins_pipe(ialu_cr_reg_mem);
13710 %}
13711
13712 instruct testB_mem_imm(rFlagsReg cr, memory mem, immI8 imm, immI_0 zero)
13713 %{
13714 match(Set cr (CmpI (AndI (LoadB mem) imm) zero));
13715
13716 ins_cost(125);
13717 format %{ "testb $mem, $imm\t# byte" %}
13718 ins_encode %{ __ testb($mem$$Address, $imm$$constant); %}
13719 ins_pipe(ialu_cr_reg_mem);
13720 %}
13721
13722 //----------Max and Min--------------------------------------------------------
13723 // Min Instructions
13724
13725 instruct cmovI_reg_g(rRegI dst, rRegI src, rFlagsReg cr)
13726 %{
13727 predicate(!UseAPX);
13728 effect(USE_DEF dst, USE src, USE cr);
13729
13730 format %{ "cmovlgt $dst, $src\t# min" %}
13731 ins_encode %{
13732 __ cmovl(Assembler::greater, $dst$$Register, $src$$Register);
13733 %}
13734 ins_pipe(pipe_cmov_reg);
13735 %}
13736
13737 instruct cmovI_reg_g_ndd(rRegI dst, rRegI src1, rRegI src2, rFlagsReg cr)
13738 %{
13739 predicate(UseAPX);
13740 effect(DEF dst, USE src1, USE src2, USE cr);
13741
13742 format %{ "ecmovlgt $dst, $src1, $src2\t# min ndd" %}
13743 ins_encode %{
13744 __ ecmovl(Assembler::greater, $dst$$Register, $src1$$Register, $src2$$Register);
13745 %}
13746 ins_pipe(pipe_cmov_reg);
13747 %}
13748
13749 instruct minI_rReg(rRegI dst, rRegI src)
13750 %{
13751 predicate(!UseAPX);
13752 match(Set dst (MinI dst src));
13753
13754 ins_cost(200);
13755 expand %{
13756 rFlagsReg cr;
13757 compI_rReg(cr, dst, src);
13758 cmovI_reg_g(dst, src, cr);
13759 %}
13760 %}
13761
13762 instruct minI_rReg_ndd(rRegI dst, rRegI src1, rRegI src2)
13763 %{
13764 predicate(UseAPX);
13765 match(Set dst (MinI src1 src2));
13766 effect(DEF dst, USE src1, USE src2);
13767
13768 ins_cost(200);
13769 expand %{
13770 rFlagsReg cr;
13771 compI_rReg(cr, src1, src2);
13772 cmovI_reg_g_ndd(dst, src1, src2, cr);
13773 %}
13774 %}
13775
13776 instruct cmovI_reg_l(rRegI dst, rRegI src, rFlagsReg cr)
13777 %{
13778 predicate(!UseAPX);
13779 effect(USE_DEF dst, USE src, USE cr);
13780
13781 format %{ "cmovllt $dst, $src\t# max" %}
13782 ins_encode %{
13783 __ cmovl(Assembler::less, $dst$$Register, $src$$Register);
13784 %}
13785 ins_pipe(pipe_cmov_reg);
13786 %}
13787
13788 instruct cmovI_reg_l_ndd(rRegI dst, rRegI src1, rRegI src2, rFlagsReg cr)
13789 %{
13790 predicate(UseAPX);
13791 effect(DEF dst, USE src1, USE src2, USE cr);
13792
13793 format %{ "ecmovllt $dst, $src1, $src2\t# max ndd" %}
13794 ins_encode %{
13795 __ ecmovl(Assembler::less, $dst$$Register, $src1$$Register, $src2$$Register);
13796 %}
13797 ins_pipe(pipe_cmov_reg);
13798 %}
13799
13800 instruct maxI_rReg(rRegI dst, rRegI src)
13801 %{
13802 predicate(!UseAPX);
13803 match(Set dst (MaxI dst src));
13804
13805 ins_cost(200);
13806 expand %{
13807 rFlagsReg cr;
13808 compI_rReg(cr, dst, src);
13809 cmovI_reg_l(dst, src, cr);
13810 %}
13811 %}
13812
13813 instruct maxI_rReg_ndd(rRegI dst, rRegI src1, rRegI src2)
13814 %{
13815 predicate(UseAPX);
13816 match(Set dst (MaxI src1 src2));
13817 effect(DEF dst, USE src1, USE src2);
13818
13819 ins_cost(200);
13820 expand %{
13821 rFlagsReg cr;
13822 compI_rReg(cr, src1, src2);
13823 cmovI_reg_l_ndd(dst, src1, src2, cr);
13824 %}
13825 %}
13826
13827 // ============================================================================
13828 // Branch Instructions
13829
13830 // Jump Direct - Label defines a relative address from JMP+1
13831 instruct jmpDir(label labl)
13832 %{
13833 match(Goto);
13834 effect(USE labl);
13835
13836 ins_cost(300);
13837 format %{ "jmp $labl" %}
13838 size(5);
13839 ins_encode %{
13840 Label* L = $labl$$label;
13841 __ jmp(*L, false); // Always long jump
13842 %}
13843 ins_pipe(pipe_jmp);
13844 %}
13845
13846 // Jump Direct Conditional - Label defines a relative address from Jcc+1
13847 instruct jmpCon(cmpOp cop, rFlagsReg cr, label labl)
13848 %{
13849 match(If cop cr);
13850 effect(USE labl);
13851
13852 ins_cost(300);
13853 format %{ "j$cop $labl" %}
13854 size(6);
13855 ins_encode %{
13856 Label* L = $labl$$label;
13857 __ jcc((Assembler::Condition)($cop$$cmpcode), *L, false); // Always long jump
13858 %}
13859 ins_pipe(pipe_jcc);
13860 %}
13861
13862 // Jump Direct Conditional - Label defines a relative address from Jcc+1
13863 instruct jmpLoopEnd(cmpOp cop, rFlagsReg cr, label labl)
13864 %{
13865 match(CountedLoopEnd cop cr);
13866 effect(USE labl);
13867
13868 ins_cost(300);
13869 format %{ "j$cop $labl\t# loop end" %}
13870 size(6);
13871 ins_encode %{
13872 Label* L = $labl$$label;
13873 __ jcc((Assembler::Condition)($cop$$cmpcode), *L, false); // Always long jump
13874 %}
13875 ins_pipe(pipe_jcc);
13876 %}
13877
13878 // Jump Direct Conditional - using unsigned comparison
13879 instruct jmpConU(cmpOpU cop, rFlagsRegU cmp, label labl) %{
13880 match(If cop cmp);
13881 effect(USE labl);
13882
13883 ins_cost(300);
13884 format %{ "j$cop,u $labl" %}
13885 size(6);
13886 ins_encode %{
13887 Label* L = $labl$$label;
13888 __ jcc((Assembler::Condition)($cop$$cmpcode), *L, false); // Always long jump
13889 %}
13890 ins_pipe(pipe_jcc);
13891 %}
13892
13893 instruct jmpConUCF(cmpOpUCF cop, rFlagsRegUCF cmp, label labl) %{
13894 match(If cop cmp);
13895 effect(USE labl);
13896
13897 ins_cost(200);
13898 format %{ "j$cop,u $labl" %}
13899 size(6);
13900 ins_encode %{
13901 Label* L = $labl$$label;
13902 __ jcc((Assembler::Condition)($cop$$cmpcode), *L, false); // Always long jump
13903 %}
13904 ins_pipe(pipe_jcc);
13905 %}
13906
13907 instruct jmpConUCF2(cmpOpUCF2 cop, rFlagsRegUCF cmp, label labl) %{
13908 match(If cop cmp);
13909 effect(USE labl);
13910
13911 ins_cost(200);
13912 format %{ $$template
13913 if ($cop$$cmpcode == Assembler::notEqual) {
13914 $$emit$$"jp,u $labl\n\t"
13915 $$emit$$"j$cop,u $labl"
13916 } else {
13917 $$emit$$"jp,u done\n\t"
13918 $$emit$$"j$cop,u $labl\n\t"
13919 $$emit$$"done:"
13920 }
13921 %}
13922 ins_encode %{
13923 Label* l = $labl$$label;
13924 if ($cop$$cmpcode == Assembler::notEqual) {
13925 __ jcc(Assembler::parity, *l, false);
13926 __ jcc(Assembler::notEqual, *l, false);
13927 } else if ($cop$$cmpcode == Assembler::equal) {
13928 Label done;
13929 __ jccb(Assembler::parity, done);
13930 __ jcc(Assembler::equal, *l, false);
13931 __ bind(done);
13932 } else {
13933 ShouldNotReachHere();
13934 }
13935 %}
13936 ins_pipe(pipe_jcc);
13937 %}
13938
13939 // ============================================================================
13940 // The 2nd slow-half of a subtype check. Scan the subklass's 2ndary
13941 // superklass array for an instance of the superklass. Set a hidden
13942 // internal cache on a hit (cache is checked with exposed code in
13943 // gen_subtype_check()). Return NZ for a miss or zero for a hit. The
13944 // encoding ALSO sets flags.
13945
13946 instruct partialSubtypeCheck(rdi_RegP result,
13947 rsi_RegP sub, rax_RegP super, rcx_RegI rcx,
13948 rFlagsReg cr)
13949 %{
13950 match(Set result (PartialSubtypeCheck sub super));
13951 predicate(!UseSecondarySupersTable);
13952 effect(KILL rcx, KILL cr);
13953
13954 ins_cost(1100); // slightly larger than the next version
13955 format %{ "movq rdi, [$sub + in_bytes(Klass::secondary_supers_offset())]\n\t"
13956 "movl rcx, [rdi + Array<Klass*>::length_offset_in_bytes()]\t# length to scan\n\t"
13957 "addq rdi, Array<Klass*>::base_offset_in_bytes()\t# Skip to start of data; set NZ in case count is zero\n\t"
13958 "repne scasq\t# Scan *rdi++ for a match with rax while rcx--\n\t"
13959 "jne,s miss\t\t# Missed: rdi not-zero\n\t"
13960 "movq [$sub + in_bytes(Klass::secondary_super_cache_offset())], $super\t# Hit: update cache\n\t"
13961 "xorq $result, $result\t\t Hit: rdi zero\n\t"
13962 "miss:\t" %}
13963
13964 ins_encode %{
13965 Label miss;
13966 // NB: Callers may assume that, when $result is a valid register,
13967 // check_klass_subtype_slow_path_linear sets it to a nonzero
13968 // value.
13969 __ check_klass_subtype_slow_path_linear($sub$$Register, $super$$Register,
13970 $rcx$$Register, $result$$Register,
13971 nullptr, &miss,
13972 /*set_cond_codes:*/ true);
13973 __ xorptr($result$$Register, $result$$Register);
13974 __ bind(miss);
13975 %}
13976
13977 ins_pipe(pipe_slow);
13978 %}
13979
13980 // ============================================================================
13981 // Two versions of hashtable-based partialSubtypeCheck, both used when
13982 // we need to search for a super class in the secondary supers array.
13983 // The first is used when we don't know _a priori_ the class being
13984 // searched for. The second, far more common, is used when we do know:
13985 // this is used for instanceof, checkcast, and any case where C2 can
13986 // determine it by constant propagation.
13987
13988 instruct partialSubtypeCheckVarSuper(rsi_RegP sub, rax_RegP super, rdi_RegP result,
13989 rdx_RegL temp1, rcx_RegL temp2, rbx_RegP temp3, r11_RegL temp4,
13990 rFlagsReg cr)
13991 %{
13992 match(Set result (PartialSubtypeCheck sub super));
13993 predicate(UseSecondarySupersTable);
13994 effect(KILL cr, TEMP temp1, TEMP temp2, TEMP temp3, TEMP temp4);
13995
13996 ins_cost(1000);
13997 format %{ "partialSubtypeCheck $result, $sub, $super" %}
13998
13999 ins_encode %{
14000 __ lookup_secondary_supers_table_var($sub$$Register, $super$$Register, $temp1$$Register, $temp2$$Register,
14001 $temp3$$Register, $temp4$$Register, $result$$Register);
14002 %}
14003
14004 ins_pipe(pipe_slow);
14005 %}
14006
14007 instruct partialSubtypeCheckConstSuper(rsi_RegP sub, rax_RegP super_reg, immP super_con, rdi_RegP result,
14008 rdx_RegL temp1, rcx_RegL temp2, rbx_RegP temp3, r11_RegL temp4,
14009 rFlagsReg cr)
14010 %{
14011 match(Set result (PartialSubtypeCheck sub (Binary super_reg super_con)));
14012 predicate(UseSecondarySupersTable);
14013 effect(KILL cr, TEMP temp1, TEMP temp2, TEMP temp3, TEMP temp4);
14014
14015 ins_cost(700); // smaller than the next version
14016 format %{ "partialSubtypeCheck $result, $sub, $super_reg, $super_con" %}
14017
14018 ins_encode %{
14019 u1 super_klass_slot = ((Klass*)$super_con$$constant)->hash_slot();
14020 if (InlineSecondarySupersTest) {
14021 __ lookup_secondary_supers_table_const($sub$$Register, $super_reg$$Register, $temp1$$Register, $temp2$$Register,
14022 $temp3$$Register, $temp4$$Register, $result$$Register,
14023 super_klass_slot);
14024 } else {
14025 __ call(RuntimeAddress(StubRoutines::lookup_secondary_supers_table_stub(super_klass_slot)));
14026 }
14027 %}
14028
14029 ins_pipe(pipe_slow);
14030 %}
14031
14032 // ============================================================================
14033 // Branch Instructions -- short offset versions
14034 //
14035 // These instructions are used to replace jumps of a long offset (the default
14036 // match) with jumps of a shorter offset. These instructions are all tagged
14037 // with the ins_short_branch attribute, which causes the ADLC to suppress the
14038 // match rules in general matching. Instead, the ADLC generates a conversion
14039 // method in the MachNode which can be used to do in-place replacement of the
14040 // long variant with the shorter variant. The compiler will determine if a
14041 // branch can be taken by the is_short_branch_offset() predicate in the machine
14042 // specific code section of the file.
14043
14044 // Jump Direct - Label defines a relative address from JMP+1
14045 instruct jmpDir_short(label labl) %{
14046 match(Goto);
14047 effect(USE labl);
14048
14049 ins_cost(300);
14050 format %{ "jmp,s $labl" %}
14051 size(2);
14052 ins_encode %{
14053 Label* L = $labl$$label;
14054 __ jmpb(*L);
14055 %}
14056 ins_pipe(pipe_jmp);
14057 ins_short_branch(1);
14058 %}
14059
14060 // Jump Direct Conditional - Label defines a relative address from Jcc+1
14061 instruct jmpCon_short(cmpOp cop, rFlagsReg cr, label labl) %{
14062 match(If cop cr);
14063 effect(USE labl);
14064
14065 ins_cost(300);
14066 format %{ "j$cop,s $labl" %}
14067 size(2);
14068 ins_encode %{
14069 Label* L = $labl$$label;
14070 __ jccb((Assembler::Condition)($cop$$cmpcode), *L);
14071 %}
14072 ins_pipe(pipe_jcc);
14073 ins_short_branch(1);
14074 %}
14075
14076 // Jump Direct Conditional - Label defines a relative address from Jcc+1
14077 instruct jmpLoopEnd_short(cmpOp cop, rFlagsReg cr, label labl) %{
14078 match(CountedLoopEnd cop cr);
14079 effect(USE labl);
14080
14081 ins_cost(300);
14082 format %{ "j$cop,s $labl\t# loop end" %}
14083 size(2);
14084 ins_encode %{
14085 Label* L = $labl$$label;
14086 __ jccb((Assembler::Condition)($cop$$cmpcode), *L);
14087 %}
14088 ins_pipe(pipe_jcc);
14089 ins_short_branch(1);
14090 %}
14091
14092 // Jump Direct Conditional - using unsigned comparison
14093 instruct jmpConU_short(cmpOpU cop, rFlagsRegU cmp, label labl) %{
14094 match(If cop cmp);
14095 effect(USE labl);
14096
14097 ins_cost(300);
14098 format %{ "j$cop,us $labl" %}
14099 size(2);
14100 ins_encode %{
14101 Label* L = $labl$$label;
14102 __ jccb((Assembler::Condition)($cop$$cmpcode), *L);
14103 %}
14104 ins_pipe(pipe_jcc);
14105 ins_short_branch(1);
14106 %}
14107
14108 instruct jmpConUCF_short(cmpOpUCF cop, rFlagsRegUCF cmp, label labl) %{
14109 match(If cop cmp);
14110 effect(USE labl);
14111
14112 ins_cost(300);
14113 format %{ "j$cop,us $labl" %}
14114 size(2);
14115 ins_encode %{
14116 Label* L = $labl$$label;
14117 __ jccb((Assembler::Condition)($cop$$cmpcode), *L);
14118 %}
14119 ins_pipe(pipe_jcc);
14120 ins_short_branch(1);
14121 %}
14122
14123 instruct jmpConUCF2_short(cmpOpUCF2 cop, rFlagsRegUCF cmp, label labl) %{
14124 match(If cop cmp);
14125 effect(USE labl);
14126
14127 ins_cost(300);
14128 format %{ $$template
14129 if ($cop$$cmpcode == Assembler::notEqual) {
14130 $$emit$$"jp,u,s $labl\n\t"
14131 $$emit$$"j$cop,u,s $labl"
14132 } else {
14133 $$emit$$"jp,u,s done\n\t"
14134 $$emit$$"j$cop,u,s $labl\n\t"
14135 $$emit$$"done:"
14136 }
14137 %}
14138 size(4);
14139 ins_encode %{
14140 Label* l = $labl$$label;
14141 if ($cop$$cmpcode == Assembler::notEqual) {
14142 __ jccb(Assembler::parity, *l);
14143 __ jccb(Assembler::notEqual, *l);
14144 } else if ($cop$$cmpcode == Assembler::equal) {
14145 Label done;
14146 __ jccb(Assembler::parity, done);
14147 __ jccb(Assembler::equal, *l);
14148 __ bind(done);
14149 } else {
14150 ShouldNotReachHere();
14151 }
14152 %}
14153 ins_pipe(pipe_jcc);
14154 ins_short_branch(1);
14155 %}
14156
14157 // ============================================================================
14158 // inlined locking and unlocking
14159
14160 instruct cmpFastLockLightweight(rFlagsReg cr, rRegP object, rbx_RegP box, rax_RegI rax_reg, rRegP tmp) %{
14161 match(Set cr (FastLock object box));
14162 effect(TEMP rax_reg, TEMP tmp, USE_KILL box);
14163 ins_cost(300);
14164 format %{ "fastlock $object,$box\t! kills $box,$rax_reg,$tmp" %}
14165 ins_encode %{
14166 __ fast_lock_lightweight($object$$Register, $box$$Register, $rax_reg$$Register, $tmp$$Register, r15_thread);
14167 %}
14168 ins_pipe(pipe_slow);
14169 %}
14170
14171 instruct cmpFastUnlockLightweight(rFlagsReg cr, rRegP object, rax_RegP rax_reg, rRegP tmp) %{
14172 match(Set cr (FastUnlock object rax_reg));
14173 effect(TEMP tmp, USE_KILL rax_reg);
14174 ins_cost(300);
14175 format %{ "fastunlock $object,$rax_reg\t! kills $rax_reg,$tmp" %}
14176 ins_encode %{
14177 __ fast_unlock_lightweight($object$$Register, $rax_reg$$Register, $tmp$$Register, r15_thread);
14178 %}
14179 ins_pipe(pipe_slow);
14180 %}
14181
14182
14183 // ============================================================================
14184 // Safepoint Instructions
14185 instruct safePoint_poll_tls(rFlagsReg cr, rRegP poll)
14186 %{
14187 match(SafePoint poll);
14188 effect(KILL cr, USE poll);
14189
14190 format %{ "testl rax, [$poll]\t"
14191 "# Safepoint: poll for GC" %}
14192 ins_cost(125);
14193 ins_encode %{
14194 __ relocate(relocInfo::poll_type);
14195 address pre_pc = __ pc();
14196 __ testl(rax, Address($poll$$Register, 0));
14197 assert(nativeInstruction_at(pre_pc)->is_safepoint_poll(), "must emit test %%eax [reg]");
14198 %}
14199 ins_pipe(ialu_reg_mem);
14200 %}
14201
14202 instruct mask_all_evexL(kReg dst, rRegL src) %{
14203 match(Set dst (MaskAll src));
14204 format %{ "mask_all_evexL $dst, $src \t! mask all operation" %}
14205 ins_encode %{
14206 int mask_len = Matcher::vector_length(this);
14207 __ vector_maskall_operation($dst$$KRegister, $src$$Register, mask_len);
14208 %}
14209 ins_pipe( pipe_slow );
14210 %}
14211
14212 instruct mask_all_evexI_GT32(kReg dst, rRegI src, rRegL tmp) %{
14213 predicate(Matcher::vector_length(n) > 32);
14214 match(Set dst (MaskAll src));
14215 effect(TEMP tmp);
14216 format %{ "mask_all_evexI_GT32 $dst, $src \t! using $tmp as TEMP" %}
14217 ins_encode %{
14218 int mask_len = Matcher::vector_length(this);
14219 __ movslq($tmp$$Register, $src$$Register);
14220 __ vector_maskall_operation($dst$$KRegister, $tmp$$Register, mask_len);
14221 %}
14222 ins_pipe( pipe_slow );
14223 %}
14224
14225 // ============================================================================
14226 // Procedure Call/Return Instructions
14227 // Call Java Static Instruction
14228 // Note: If this code changes, the corresponding ret_addr_offset() and
14229 // compute_padding() functions will have to be adjusted.
14230 instruct CallStaticJavaDirect(method meth) %{
14231 match(CallStaticJava);
14232 effect(USE meth);
14233
14234 ins_cost(300);
14235 format %{ "call,static " %}
14236 opcode(0xE8); /* E8 cd */
14237 ins_encode(clear_avx, Java_Static_Call(meth), call_epilog);
14238 ins_pipe(pipe_slow);
14239 ins_alignment(4);
14240 %}
14241
14242 // Call Java Dynamic Instruction
14243 // Note: If this code changes, the corresponding ret_addr_offset() and
14244 // compute_padding() functions will have to be adjusted.
14245 instruct CallDynamicJavaDirect(method meth)
14246 %{
14247 match(CallDynamicJava);
14248 effect(USE meth);
14249
14250 ins_cost(300);
14251 format %{ "movq rax, #Universe::non_oop_word()\n\t"
14252 "call,dynamic " %}
14253 ins_encode(clear_avx, Java_Dynamic_Call(meth), call_epilog);
14254 ins_pipe(pipe_slow);
14255 ins_alignment(4);
14256 %}
14257
14258 // Call Runtime Instruction
14259 instruct CallRuntimeDirect(method meth)
14260 %{
14261 match(CallRuntime);
14262 effect(USE meth);
14263
14264 ins_cost(300);
14265 format %{ "call,runtime " %}
14266 ins_encode(clear_avx, Java_To_Runtime(meth));
14267 ins_pipe(pipe_slow);
14268 %}
14269
14270 // Call runtime without safepoint
14271 instruct CallLeafDirect(method meth)
14272 %{
14273 match(CallLeaf);
14274 effect(USE meth);
14275
14276 ins_cost(300);
14277 format %{ "call_leaf,runtime " %}
14278 ins_encode(clear_avx, Java_To_Runtime(meth));
14279 ins_pipe(pipe_slow);
14280 %}
14281
14282 // Call runtime without safepoint and with vector arguments
14283 instruct CallLeafDirectVector(method meth)
14284 %{
14285 match(CallLeafVector);
14286 effect(USE meth);
14287
14288 ins_cost(300);
14289 format %{ "call_leaf,vector " %}
14290 ins_encode(Java_To_Runtime(meth));
14291 ins_pipe(pipe_slow);
14292 %}
14293
14294 // Call runtime without safepoint
14295 instruct CallLeafNoFPDirect(method meth)
14296 %{
14297 match(CallLeafNoFP);
14298 effect(USE meth);
14299
14300 ins_cost(300);
14301 format %{ "call_leaf_nofp,runtime " %}
14302 ins_encode(clear_avx, Java_To_Runtime(meth));
14303 ins_pipe(pipe_slow);
14304 %}
14305
14306 // Return Instruction
14307 // Remove the return address & jump to it.
14308 // Notice: We always emit a nop after a ret to make sure there is room
14309 // for safepoint patching
14310 instruct Ret()
14311 %{
14312 match(Return);
14313
14314 format %{ "ret" %}
14315 ins_encode %{
14316 __ ret(0);
14317 %}
14318 ins_pipe(pipe_jmp);
14319 %}
14320
14321 // Tail Call; Jump from runtime stub to Java code.
14322 // Also known as an 'interprocedural jump'.
14323 // Target of jump will eventually return to caller.
14324 // TailJump below removes the return address.
14325 // Don't use rbp for 'jump_target' because a MachEpilogNode has already been
14326 // emitted just above the TailCall which has reset rbp to the caller state.
14327 instruct TailCalljmpInd(no_rbp_RegP jump_target, rbx_RegP method_ptr)
14328 %{
14329 match(TailCall jump_target method_ptr);
14330
14331 ins_cost(300);
14332 format %{ "jmp $jump_target\t# rbx holds method" %}
14333 ins_encode %{
14334 __ jmp($jump_target$$Register);
14335 %}
14336 ins_pipe(pipe_jmp);
14337 %}
14338
14339 // Tail Jump; remove the return address; jump to target.
14340 // TailCall above leaves the return address around.
14341 instruct tailjmpInd(no_rbp_RegP jump_target, rax_RegP ex_oop)
14342 %{
14343 match(TailJump jump_target ex_oop);
14344
14345 ins_cost(300);
14346 format %{ "popq rdx\t# pop return address\n\t"
14347 "jmp $jump_target" %}
14348 ins_encode %{
14349 __ popq(as_Register(RDX_enc));
14350 __ jmp($jump_target$$Register);
14351 %}
14352 ins_pipe(pipe_jmp);
14353 %}
14354
14355 // Forward exception.
14356 instruct ForwardExceptionjmp()
14357 %{
14358 match(ForwardException);
14359
14360 format %{ "jmp forward_exception_stub" %}
14361 ins_encode %{
14362 __ jump(RuntimeAddress(StubRoutines::forward_exception_entry()), noreg);
14363 %}
14364 ins_pipe(pipe_jmp);
14365 %}
14366
14367 // Create exception oop: created by stack-crawling runtime code.
14368 // Created exception is now available to this handler, and is setup
14369 // just prior to jumping to this handler. No code emitted.
14370 instruct CreateException(rax_RegP ex_oop)
14371 %{
14372 match(Set ex_oop (CreateEx));
14373
14374 size(0);
14375 // use the following format syntax
14376 format %{ "# exception oop is in rax; no code emitted" %}
14377 ins_encode();
14378 ins_pipe(empty);
14379 %}
14380
14381 // Rethrow exception:
14382 // The exception oop will come in the first argument position.
14383 // Then JUMP (not call) to the rethrow stub code.
14384 instruct RethrowException()
14385 %{
14386 match(Rethrow);
14387
14388 // use the following format syntax
14389 format %{ "jmp rethrow_stub" %}
14390 ins_encode %{
14391 __ jump(RuntimeAddress(OptoRuntime::rethrow_stub()), noreg);
14392 %}
14393 ins_pipe(pipe_jmp);
14394 %}
14395
14396 // ============================================================================
14397 // This name is KNOWN by the ADLC and cannot be changed.
14398 // The ADLC forces a 'TypeRawPtr::BOTTOM' output type
14399 // for this guy.
14400 instruct tlsLoadP(r15_RegP dst) %{
14401 match(Set dst (ThreadLocal));
14402 effect(DEF dst);
14403
14404 size(0);
14405 format %{ "# TLS is in R15" %}
14406 ins_encode( /*empty encoding*/ );
14407 ins_pipe(ialu_reg_reg);
14408 %}
14409
14410
14411 //----------PEEPHOLE RULES-----------------------------------------------------
14412 // These must follow all instruction definitions as they use the names
14413 // defined in the instructions definitions.
14414 //
14415 // peeppredicate ( rule_predicate );
14416 // // the predicate unless which the peephole rule will be ignored
14417 //
14418 // peepmatch ( root_instr_name [preceding_instruction]* );
14419 //
14420 // peepprocedure ( procedure_name );
14421 // // provide a procedure name to perform the optimization, the procedure should
14422 // // reside in the architecture dependent peephole file, the method has the
14423 // // signature of MachNode* (Block*, int, PhaseRegAlloc*, (MachNode*)(*)(), int...)
14424 // // with the arguments being the basic block, the current node index inside the
14425 // // block, the register allocator, the functions upon invoked return a new node
14426 // // defined in peepreplace, and the rules of the nodes appearing in the
14427 // // corresponding peepmatch, the function return true if successful, else
14428 // // return false
14429 //
14430 // peepconstraint %{
14431 // (instruction_number.operand_name relational_op instruction_number.operand_name
14432 // [, ...] );
14433 // // instruction numbers are zero-based using left to right order in peepmatch
14434 //
14435 // peepreplace ( instr_name ( [instruction_number.operand_name]* ) );
14436 // // provide an instruction_number.operand_name for each operand that appears
14437 // // in the replacement instruction's match rule
14438 //
14439 // ---------VM FLAGS---------------------------------------------------------
14440 //
14441 // All peephole optimizations can be turned off using -XX:-OptoPeephole
14442 //
14443 // Each peephole rule is given an identifying number starting with zero and
14444 // increasing by one in the order seen by the parser. An individual peephole
14445 // can be enabled, and all others disabled, by using -XX:OptoPeepholeAt=#
14446 // on the command-line.
14447 //
14448 // ---------CURRENT LIMITATIONS----------------------------------------------
14449 //
14450 // Only transformations inside a basic block (do we need more for peephole)
14451 //
14452 // ---------EXAMPLE----------------------------------------------------------
14453 //
14454 // // pertinent parts of existing instructions in architecture description
14455 // instruct movI(rRegI dst, rRegI src)
14456 // %{
14457 // match(Set dst (CopyI src));
14458 // %}
14459 //
14460 // instruct incI_rReg(rRegI dst, immI_1 src, rFlagsReg cr)
14461 // %{
14462 // match(Set dst (AddI dst src));
14463 // effect(KILL cr);
14464 // %}
14465 //
14466 // instruct leaI_rReg_immI(rRegI dst, immI_1 src)
14467 // %{
14468 // match(Set dst (AddI dst src));
14469 // %}
14470 //
14471 // 1. Simple replacement
14472 // - Only match adjacent instructions in same basic block
14473 // - Only equality constraints
14474 // - Only constraints between operands, not (0.dest_reg == RAX_enc)
14475 // - Only one replacement instruction
14476 //
14477 // // Change (inc mov) to lea
14478 // peephole %{
14479 // // lea should only be emitted when beneficial
14480 // peeppredicate( VM_Version::supports_fast_2op_lea() );
14481 // // increment preceded by register-register move
14482 // peepmatch ( incI_rReg movI );
14483 // // require that the destination register of the increment
14484 // // match the destination register of the move
14485 // peepconstraint ( 0.dst == 1.dst );
14486 // // construct a replacement instruction that sets
14487 // // the destination to ( move's source register + one )
14488 // peepreplace ( leaI_rReg_immI( 0.dst 1.src 0.src ) );
14489 // %}
14490 //
14491 // 2. Procedural replacement
14492 // - More flexible finding relevent nodes
14493 // - More flexible constraints
14494 // - More flexible transformations
14495 // - May utilise architecture-dependent API more effectively
14496 // - Currently only one replacement instruction due to adlc parsing capabilities
14497 //
14498 // // Change (inc mov) to lea
14499 // peephole %{
14500 // // lea should only be emitted when beneficial
14501 // peeppredicate( VM_Version::supports_fast_2op_lea() );
14502 // // the rule numbers of these nodes inside are passed into the function below
14503 // peepmatch ( incI_rReg movI );
14504 // // the method that takes the responsibility of transformation
14505 // peepprocedure ( inc_mov_to_lea );
14506 // // the replacement is a leaI_rReg_immI, a lambda upon invoked creating this
14507 // // node is passed into the function above
14508 // peepreplace ( leaI_rReg_immI() );
14509 // %}
14510
14511 // These instructions is not matched by the matcher but used by the peephole
14512 instruct leaI_rReg_rReg_peep(rRegI dst, rRegI src1, rRegI src2)
14513 %{
14514 predicate(false);
14515 match(Set dst (AddI src1 src2));
14516 format %{ "leal $dst, [$src1 + $src2]" %}
14517 ins_encode %{
14518 Register dst = $dst$$Register;
14519 Register src1 = $src1$$Register;
14520 Register src2 = $src2$$Register;
14521 if (src1 != rbp && src1 != r13) {
14522 __ leal(dst, Address(src1, src2, Address::times_1));
14523 } else {
14524 assert(src2 != rbp && src2 != r13, "");
14525 __ leal(dst, Address(src2, src1, Address::times_1));
14526 }
14527 %}
14528 ins_pipe(ialu_reg_reg);
14529 %}
14530
14531 instruct leaI_rReg_immI_peep(rRegI dst, rRegI src1, immI src2)
14532 %{
14533 predicate(false);
14534 match(Set dst (AddI src1 src2));
14535 format %{ "leal $dst, [$src1 + $src2]" %}
14536 ins_encode %{
14537 __ leal($dst$$Register, Address($src1$$Register, $src2$$constant));
14538 %}
14539 ins_pipe(ialu_reg_reg);
14540 %}
14541
14542 instruct leaI_rReg_immI2_peep(rRegI dst, rRegI src, immI2 shift)
14543 %{
14544 predicate(false);
14545 match(Set dst (LShiftI src shift));
14546 format %{ "leal $dst, [$src << $shift]" %}
14547 ins_encode %{
14548 Address::ScaleFactor scale = static_cast<Address::ScaleFactor>($shift$$constant);
14549 Register src = $src$$Register;
14550 if (scale == Address::times_2 && src != rbp && src != r13) {
14551 __ leal($dst$$Register, Address(src, src, Address::times_1));
14552 } else {
14553 __ leal($dst$$Register, Address(noreg, src, scale));
14554 }
14555 %}
14556 ins_pipe(ialu_reg_reg);
14557 %}
14558
14559 instruct leaL_rReg_rReg_peep(rRegL dst, rRegL src1, rRegL src2)
14560 %{
14561 predicate(false);
14562 match(Set dst (AddL src1 src2));
14563 format %{ "leaq $dst, [$src1 + $src2]" %}
14564 ins_encode %{
14565 Register dst = $dst$$Register;
14566 Register src1 = $src1$$Register;
14567 Register src2 = $src2$$Register;
14568 if (src1 != rbp && src1 != r13) {
14569 __ leaq(dst, Address(src1, src2, Address::times_1));
14570 } else {
14571 assert(src2 != rbp && src2 != r13, "");
14572 __ leaq(dst, Address(src2, src1, Address::times_1));
14573 }
14574 %}
14575 ins_pipe(ialu_reg_reg);
14576 %}
14577
14578 instruct leaL_rReg_immL32_peep(rRegL dst, rRegL src1, immL32 src2)
14579 %{
14580 predicate(false);
14581 match(Set dst (AddL src1 src2));
14582 format %{ "leaq $dst, [$src1 + $src2]" %}
14583 ins_encode %{
14584 __ leaq($dst$$Register, Address($src1$$Register, $src2$$constant));
14585 %}
14586 ins_pipe(ialu_reg_reg);
14587 %}
14588
14589 instruct leaL_rReg_immI2_peep(rRegL dst, rRegL src, immI2 shift)
14590 %{
14591 predicate(false);
14592 match(Set dst (LShiftL src shift));
14593 format %{ "leaq $dst, [$src << $shift]" %}
14594 ins_encode %{
14595 Address::ScaleFactor scale = static_cast<Address::ScaleFactor>($shift$$constant);
14596 Register src = $src$$Register;
14597 if (scale == Address::times_2 && src != rbp && src != r13) {
14598 __ leaq($dst$$Register, Address(src, src, Address::times_1));
14599 } else {
14600 __ leaq($dst$$Register, Address(noreg, src, scale));
14601 }
14602 %}
14603 ins_pipe(ialu_reg_reg);
14604 %}
14605
14606 // These peephole rules replace mov + I pairs (where I is one of {add, inc, dec,
14607 // sal}) with lea instructions. The {add, sal} rules are beneficial in
14608 // processors with at least partial ALU support for lea
14609 // (supports_fast_2op_lea()), whereas the {inc, dec} rules are only generally
14610 // beneficial for processors with full ALU support
14611 // (VM_Version::supports_fast_3op_lea()) and Intel Cascade Lake.
14612
14613 peephole
14614 %{
14615 peeppredicate(VM_Version::supports_fast_2op_lea());
14616 peepmatch (addI_rReg);
14617 peepprocedure (lea_coalesce_reg);
14618 peepreplace (leaI_rReg_rReg_peep());
14619 %}
14620
14621 peephole
14622 %{
14623 peeppredicate(VM_Version::supports_fast_2op_lea());
14624 peepmatch (addI_rReg_imm);
14625 peepprocedure (lea_coalesce_imm);
14626 peepreplace (leaI_rReg_immI_peep());
14627 %}
14628
14629 peephole
14630 %{
14631 peeppredicate(VM_Version::supports_fast_3op_lea() ||
14632 VM_Version::is_intel_cascade_lake());
14633 peepmatch (incI_rReg);
14634 peepprocedure (lea_coalesce_imm);
14635 peepreplace (leaI_rReg_immI_peep());
14636 %}
14637
14638 peephole
14639 %{
14640 peeppredicate(VM_Version::supports_fast_3op_lea() ||
14641 VM_Version::is_intel_cascade_lake());
14642 peepmatch (decI_rReg);
14643 peepprocedure (lea_coalesce_imm);
14644 peepreplace (leaI_rReg_immI_peep());
14645 %}
14646
14647 peephole
14648 %{
14649 peeppredicate(VM_Version::supports_fast_2op_lea());
14650 peepmatch (salI_rReg_immI2);
14651 peepprocedure (lea_coalesce_imm);
14652 peepreplace (leaI_rReg_immI2_peep());
14653 %}
14654
14655 peephole
14656 %{
14657 peeppredicate(VM_Version::supports_fast_2op_lea());
14658 peepmatch (addL_rReg);
14659 peepprocedure (lea_coalesce_reg);
14660 peepreplace (leaL_rReg_rReg_peep());
14661 %}
14662
14663 peephole
14664 %{
14665 peeppredicate(VM_Version::supports_fast_2op_lea());
14666 peepmatch (addL_rReg_imm);
14667 peepprocedure (lea_coalesce_imm);
14668 peepreplace (leaL_rReg_immL32_peep());
14669 %}
14670
14671 peephole
14672 %{
14673 peeppredicate(VM_Version::supports_fast_3op_lea() ||
14674 VM_Version::is_intel_cascade_lake());
14675 peepmatch (incL_rReg);
14676 peepprocedure (lea_coalesce_imm);
14677 peepreplace (leaL_rReg_immL32_peep());
14678 %}
14679
14680 peephole
14681 %{
14682 peeppredicate(VM_Version::supports_fast_3op_lea() ||
14683 VM_Version::is_intel_cascade_lake());
14684 peepmatch (decL_rReg);
14685 peepprocedure (lea_coalesce_imm);
14686 peepreplace (leaL_rReg_immL32_peep());
14687 %}
14688
14689 peephole
14690 %{
14691 peeppredicate(VM_Version::supports_fast_2op_lea());
14692 peepmatch (salL_rReg_immI2);
14693 peepprocedure (lea_coalesce_imm);
14694 peepreplace (leaL_rReg_immI2_peep());
14695 %}
14696
14697 peephole
14698 %{
14699 peepmatch (leaPCompressedOopOffset);
14700 peepprocedure (lea_remove_redundant);
14701 %}
14702
14703 peephole
14704 %{
14705 peepmatch (leaP8Narrow);
14706 peepprocedure (lea_remove_redundant);
14707 %}
14708
14709 peephole
14710 %{
14711 peepmatch (leaP32Narrow);
14712 peepprocedure (lea_remove_redundant);
14713 %}
14714
14715 // These peephole rules matches instructions which set flags and are followed by a testI/L_reg
14716 // 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
14717
14718 //int variant
14719 peephole
14720 %{
14721 peepmatch (testI_reg);
14722 peepprocedure (test_may_remove);
14723 %}
14724
14725 //long variant
14726 peephole
14727 %{
14728 peepmatch (testL_reg);
14729 peepprocedure (test_may_remove);
14730 %}
14731
14732
14733 //----------SMARTSPILL RULES---------------------------------------------------
14734 // These must follow all instruction definitions as they use the names
14735 // defined in the instructions definitions.