1 //
2 // Copyright (c) 2008, 2026, 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 // ARM Architecture Description File
25
26 //----------DEFINITION BLOCK---------------------------------------------------
27 // Define name --> value mappings to inform the ADLC of an integer valued name
28 // Current support includes integer values in the range [0, 0x7FFFFFFF]
29 // Format:
30 // int_def <name> ( <int_value>, <expression>);
31 // Generated Code in ad_<arch>.hpp
32 // #define <name> (<expression>)
33 // // value == <int_value>
34 // Generated code in ad_<arch>.cpp adlc_verification()
35 // assert( <name> == <int_value>, "Expect (<expression>) to equal <int_value>");
36 //
37 definitions %{
38 // The default cost (of an ALU instruction).
39 int_def DEFAULT_COST ( 100, 100);
40 int_def HUGE_COST (1000000, 1000000);
41
42 // Memory refs are twice as expensive as run-of-the-mill.
43 int_def MEMORY_REF_COST ( 200, DEFAULT_COST * 2);
44
45 // Branches are even more expensive.
46 int_def BRANCH_COST ( 300, DEFAULT_COST * 3);
47 int_def CALL_COST ( 300, DEFAULT_COST * 3);
48 %}
49
50
51 //----------SOURCE BLOCK-------------------------------------------------------
52 // This is a block of C++ code which provides values, functions, and
53 // definitions necessary in the rest of the architecture description
54 source_hpp %{
55 // Header information of the source block.
56 // Method declarations/definitions which are used outside
57 // the ad-scope can conveniently be defined here.
58 //
59 // To keep related declarations/definitions/uses close together,
60 // we switch between source %{ }% and source_hpp %{ }% freely as needed.
61
62 #include "asm/macroAssembler.hpp"
63 #include "gc/shared/barrierSetAssembler.hpp"
64
65 // Does destination need to be loaded in a register then passed to a
66 // branch instruction?
67 extern bool maybe_far_call(const CallNode *n);
68 extern bool maybe_far_call(const MachCallNode *n);
69 static inline bool cache_reachable() {
70 return MacroAssembler::_cache_fully_reachable();
71 }
72
73 #define ldr_32 ldr
74 #define str_32 str
75 #define tst_32 tst
76 #define teq_32 teq
77 #if 1
78 extern bool PrintOptoAssembly;
79 #endif
80
81 class c2 {
82 public:
83 static OptoRegPair return_value(int ideal_reg);
84 };
85
86 class CallStubImpl {
87
88 //--------------------------------------------------------------
89 //---< Used for optimization in Compile::Shorten_branches >---
90 //--------------------------------------------------------------
91
92 public:
93 // Size of call trampoline stub.
94 static uint size_call_trampoline() {
95 return 0; // no call trampolines on this platform
96 }
97
98 // number of relocations needed by a call trampoline stub
99 static uint reloc_call_trampoline() {
100 return 0; // no call trampolines on this platform
101 }
102 };
103
104 class HandlerImpl {
105
106 public:
107
108 static int emit_deopt_handler(C2_MacroAssembler* masm);
109
110 static uint size_deopt_handler() {
111 return ( 9 * 4 );
112 }
113
114 };
115
116 class Node::PD {
117 public:
118 enum NodeFlags {
119 _last_flag = Node::_last_flag
120 };
121 };
122
123 // Assert that the given node is not a var shift.
124 bool assert_not_var_shift(const Node *n);
125 %}
126
127 source %{
128
129 // Assert that the given node is not a var shift.
130 bool assert_not_var_shift(const Node *n) {
131 assert(!n->as_ShiftV()->is_var_shift(), "illegal var shift");
132 return true;
133 }
134
135 #define __ masm->
136
137 static FloatRegister reg_to_FloatRegister_object(int register_encoding);
138 static Register reg_to_register_object(int register_encoding);
139
140 void PhaseOutput::pd_perform_mach_node_analysis() {
141 }
142
143 int MachNode::pd_alignment_required() const {
144 return 1;
145 }
146
147 int MachNode::compute_padding(int current_offset) const {
148 return 0;
149 }
150
151 // ****************************************************************************
152
153 // REQUIRED FUNCTIONALITY
154
155 // emit an interrupt that is caught by the debugger (for debugging compiler)
156 void emit_break(C2_MacroAssembler *masm) {
157 __ breakpoint();
158 }
159
160 #ifndef PRODUCT
161 void MachBreakpointNode::format( PhaseRegAlloc *, outputStream *st ) const {
162 st->print("TA");
163 }
164 #endif
165
166 void MachBreakpointNode::emit(C2_MacroAssembler *masm, PhaseRegAlloc *ra_) const {
167 emit_break(masm);
168 }
169
170 uint MachBreakpointNode::size(PhaseRegAlloc *ra_) const {
171 return MachNode::size(ra_);
172 }
173
174
175 void emit_nop(C2_MacroAssembler *masm) {
176 __ nop();
177 }
178
179
180 void emit_call_reloc(C2_MacroAssembler *masm, const MachCallNode *n, MachOper *m, RelocationHolder const& rspec) {
181 int ret_addr_offset0 = n->as_MachCall()->ret_addr_offset();
182 int call_site_offset = __ code()->insts()->mark_off();
183 __ set_inst_mark(); // needed in emit_to_interp_stub() to locate the call
184 address target = (address)m->method();
185 assert(n->as_MachCall()->entry_point() == target, "sanity");
186 assert(maybe_far_call(n) == !__ reachable_from_cache(target), "sanity");
187 assert(cache_reachable() == __ cache_fully_reachable(), "sanity");
188
189 assert(target != nullptr, "need real address");
190
191 int ret_addr_offset = -1;
192 if (rspec.type() == relocInfo::runtime_call_type) {
193 __ call(target, rspec);
194 ret_addr_offset = __ offset();
195 } else {
196 // scratches Rtemp
197 ret_addr_offset = __ patchable_call(target, rspec, true);
198 }
199 assert(ret_addr_offset - call_site_offset == ret_addr_offset0, "fix ret_addr_offset()");
200 }
201
202 //=============================================================================
203 // REQUIRED FUNCTIONALITY for encoding
204 void emit_lo(C2_MacroAssembler *masm, int val) { }
205 void emit_hi(C2_MacroAssembler *masm, int val) { }
206
207
208 //=============================================================================
209 const RegMask& MachConstantBaseNode::_out_RegMask = PTR_REG_mask();
210
211 int ConstantTable::calculate_table_base_offset() const {
212 int offset = -(size() / 2);
213 // flds, fldd: 8-bit offset multiplied by 4: +/- 1024
214 // ldr, ldrb : 12-bit offset: +/- 4096
215 if (!Assembler::is_simm10(offset)) {
216 offset = Assembler::min_simm10;
217 }
218 return offset;
219 }
220
221 bool MachConstantBaseNode::requires_postalloc_expand() const { return false; }
222 void MachConstantBaseNode::postalloc_expand(GrowableArray <Node *> *nodes, PhaseRegAlloc *ra_) {
223 ShouldNotReachHere();
224 }
225
226 void MachConstantBaseNode::emit(C2_MacroAssembler* masm, PhaseRegAlloc* ra_) const {
227 Compile* C = ra_->C;
228 ConstantTable& constant_table = C->output()->constant_table();
229
230 Register r = as_Register(ra_->get_encode(this));
231 CodeSection* consts_section = __ code()->consts();
232 CodeSection* insts_section = __ code()->insts();
233 // constants section size is aligned according to the align_at_start settings of the next section
234 int consts_size = insts_section->align_at_start(consts_section->size());
235 assert(constant_table.size() == consts_size, "must be: %d == %d", constant_table.size(), consts_size);
236
237 // Materialize the constant table base.
238 address baseaddr = consts_section->start() + -(constant_table.table_base_offset());
239 RelocationHolder rspec = internal_word_Relocation::spec(baseaddr);
240 __ mov_address(r, baseaddr, rspec);
241 }
242
243 uint MachConstantBaseNode::size(PhaseRegAlloc*) const {
244 return 8;
245 }
246
247 #ifndef PRODUCT
248 void MachConstantBaseNode::format(PhaseRegAlloc* ra_, outputStream* st) const {
249 char reg[128];
250 ra_->dump_register(this, reg, sizeof(reg));
251 st->print("MOV_SLOW &constanttable,%s\t! constant table base", reg);
252 }
253 #endif
254
255 #ifndef PRODUCT
256 void MachPrologNode::format( PhaseRegAlloc *ra_, outputStream *st ) const {
257 Compile* C = ra_->C;
258
259 for (int i = 0; i < OptoPrologueNops; i++) {
260 st->print_cr("NOP"); st->print("\t");
261 }
262
263 size_t framesize = C->output()->frame_size_in_bytes();
264 assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned");
265 int bangsize = C->output()->bang_size_in_bytes();
266 // Remove two words for return addr and rbp,
267 framesize -= 2*wordSize;
268 bangsize -= 2*wordSize;
269
270 // Calls to C2R adapters often do not accept exceptional returns.
271 // We require that their callers must bang for them. But be careful, because
272 // some VM calls (such as call site linkage) can use several kilobytes of
273 // stack. But the stack safety zone should account for that.
274 // See bugs 4446381, 4468289, 4497237.
275 if (C->output()->need_stack_bang(bangsize)) {
276 st->print_cr("! stack bang (%d bytes)", bangsize); st->print("\t");
277 }
278 st->print_cr("PUSH R_FP|R_LR_LR"); st->print("\t");
279 if (framesize != 0) {
280 st->print ("SUB R_SP, R_SP, %zu", framesize);
281 }
282
283 if (C->stub_function() == nullptr) {
284 st->print("ldr t0, [guard]\n\t");
285 st->print("ldr t1, [Rthread, #thread_disarmed_guard_value_offset]\n\t");
286 st->print("cmp t0, t1\n\t");
287 st->print("beq skip\n\t");
288 st->print("blr #nmethod_entry_barrier_stub\n\t");
289 st->print("b skip\n\t");
290 st->print("guard: int\n\t");
291 st->print("skip:\n\t");
292 }
293 }
294 #endif
295
296 void MachPrologNode::emit(C2_MacroAssembler *masm, PhaseRegAlloc *ra_) const {
297 Compile* C = ra_->C;
298
299 for (int i = 0; i < OptoPrologueNops; i++) {
300 __ nop();
301 }
302
303 size_t framesize = C->output()->frame_size_in_bytes();
304 assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned");
305 int bangsize = C->output()->bang_size_in_bytes();
306 // Remove two words for return addr and fp,
307 framesize -= 2*wordSize;
308 bangsize -= 2*wordSize;
309
310 // Calls to C2R adapters often do not accept exceptional returns.
311 // We require that their callers must bang for them. But be careful, because
312 // some VM calls (such as call site linkage) can use several kilobytes of
313 // stack. But the stack safety zone should account for that.
314 // See bugs 4446381, 4468289, 4497237.
315 if (C->output()->need_stack_bang(bangsize)) {
316 __ arm_stack_overflow_check(bangsize, Rtemp);
317 }
318
319 __ raw_push(FP, LR);
320 if (framesize != 0) {
321 __ sub_slow(SP, SP, framesize);
322 }
323
324 if (C->stub_function() == nullptr) {
325 BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler();
326 bs->nmethod_entry_barrier(masm);
327 }
328
329 // offset from scratch buffer is not valid
330 if (strcmp(__ code()->name(), "Compile::Fill_buffer") == 0) {
331 C->output()->set_frame_complete( __ offset() );
332 }
333
334 if (C->has_mach_constant_base_node()) {
335 // NOTE: We set the table base offset here because users might be
336 // emitted before MachConstantBaseNode.
337 ConstantTable& constant_table = C->output()->constant_table();
338 constant_table.set_table_base_offset(constant_table.calculate_table_base_offset());
339 }
340 }
341
342 uint MachPrologNode::size(PhaseRegAlloc *ra_) const {
343 return MachNode::size(ra_);
344 }
345
346 int MachPrologNode::reloc() const {
347 return 10; // a large enough number
348 }
349
350 //=============================================================================
351 #ifndef PRODUCT
352 void MachEpilogNode::format( PhaseRegAlloc *ra_, outputStream *st ) const {
353 Compile* C = ra_->C;
354
355 size_t framesize = C->output()->frame_size_in_bytes();
356 framesize -= 2*wordSize;
357
358 if (framesize != 0) {
359 st->print("ADD R_SP, R_SP, %zu\n\t",framesize);
360 }
361 st->print("POP R_FP|R_LR_LR");
362
363 if (do_polling() && ra_->C->is_method_compilation()) {
364 st->print("\n\t");
365 st->print("MOV Rtemp, #PollAddr\t! Load Polling address\n\t");
366 st->print("LDR Rtemp,[Rtemp]\t!Poll for Safepointing");
367 }
368 }
369 #endif
370
371 void MachEpilogNode::emit(C2_MacroAssembler *masm, PhaseRegAlloc *ra_) const {
372 Compile* C = ra_->C;
373
374 size_t framesize = C->output()->frame_size_in_bytes();
375 framesize -= 2*wordSize;
376 if (framesize != 0) {
377 __ add_slow(SP, SP, framesize);
378 }
379 __ raw_pop(FP, LR);
380
381 // If this does safepoint polling, then do it here
382 if (do_polling() && ra_->C->is_method_compilation()) {
383 __ read_polling_page(Rtemp, relocInfo::poll_return_type);
384 }
385 }
386
387 uint MachEpilogNode::size(PhaseRegAlloc *ra_) const {
388 return MachNode::size(ra_);
389 }
390
391 int MachEpilogNode::reloc() const {
392 return 16; // a large enough number
393 }
394
395 const Pipeline * MachEpilogNode::pipeline() const {
396 return MachNode::pipeline_class();
397 }
398
399 //=============================================================================
400
401 // Figure out which register class each belongs in: rc_int, rc_float, rc_stack
402 enum RC { rc_bad, rc_int, rc_float, rc_stack };
403 static enum RC rc_class( OptoReg::Name reg ) {
404 if (!OptoReg::is_valid(reg)) return rc_bad;
405 if (OptoReg::is_stack(reg)) return rc_stack;
406 VMReg r = OptoReg::as_VMReg(reg);
407 if (r->is_Register()) return rc_int;
408 assert(r->is_FloatRegister(), "must be");
409 return rc_float;
410 }
411
412 static inline bool is_iRegLd_memhd(OptoReg::Name src_first, OptoReg::Name src_second, int offset) {
413 int rlo = Matcher::_regEncode[src_first];
414 int rhi = Matcher::_regEncode[src_second];
415 if (!((rlo&1)==0 && (rlo+1 == rhi))) {
416 tty->print_cr("CAUGHT BAD LDRD/STRD");
417 }
418 return (rlo&1)==0 && (rlo+1 == rhi) && is_memoryHD(offset);
419 }
420
421 uint MachSpillCopyNode::implementation( C2_MacroAssembler *masm,
422 PhaseRegAlloc *ra_,
423 bool do_size,
424 outputStream* st ) const {
425 // Get registers to move
426 OptoReg::Name src_second = ra_->get_reg_second(in(1));
427 OptoReg::Name src_first = ra_->get_reg_first(in(1));
428 OptoReg::Name dst_second = ra_->get_reg_second(this );
429 OptoReg::Name dst_first = ra_->get_reg_first(this );
430
431 enum RC src_second_rc = rc_class(src_second);
432 enum RC src_first_rc = rc_class(src_first);
433 enum RC dst_second_rc = rc_class(dst_second);
434 enum RC dst_first_rc = rc_class(dst_first);
435
436 assert( OptoReg::is_valid(src_first) && OptoReg::is_valid(dst_first), "must move at least 1 register" );
437
438 // Generate spill code!
439 int size = 0;
440
441 if (src_first == dst_first && src_second == dst_second)
442 return size; // Self copy, no move
443
444 #ifdef TODO
445 if (bottom_type()->isa_vect() != nullptr) {
446 }
447 #endif
448
449 // Shared code does not expect instruction set capability based bailouts here.
450 // Handle offset unreachable bailout with minimal change in shared code.
451 // Bailout only for real instruction emit.
452 // This requires a single comment change in shared code. ( see output.cpp "Normal" instruction case )
453
454 // --------------------------------------
455 // Check for mem-mem move. Load into unused float registers and fall into
456 // the float-store case.
457 if (src_first_rc == rc_stack && dst_first_rc == rc_stack) {
458 int offset = ra_->reg2offset(src_first);
459 if (masm && !is_memoryfp(offset)) {
460 ra_->C->record_method_not_compilable("unable to handle large constant offsets");
461 return 0;
462 } else {
463 if (src_second_rc != rc_bad) {
464 assert((src_first&1)==0 && src_first+1 == src_second, "pair of registers must be aligned/contiguous");
465 src_first = OptoReg::Name(R_mem_copy_lo_num);
466 src_second = OptoReg::Name(R_mem_copy_hi_num);
467 src_first_rc = rc_float;
468 src_second_rc = rc_float;
469 if (masm) {
470 __ ldr_double(Rmemcopy, Address(SP, offset));
471 } else if (!do_size) {
472 st->print(LDR_DOUBLE " R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(src_first),offset);
473 }
474 } else {
475 src_first = OptoReg::Name(R_mem_copy_lo_num);
476 src_first_rc = rc_float;
477 if (masm) {
478 __ ldr_float(Rmemcopy, Address(SP, offset));
479 } else if (!do_size) {
480 st->print(LDR_FLOAT " R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(src_first),offset);
481 }
482 }
483 size += 4;
484 }
485 }
486
487 if (src_second_rc == rc_stack && dst_second_rc == rc_stack) {
488 Unimplemented();
489 }
490
491 // --------------------------------------
492 // Check for integer reg-reg copy
493 if (src_first_rc == rc_int && dst_first_rc == rc_int) {
494 // Else normal reg-reg copy
495 assert( src_second != dst_first, "smashed second before evacuating it" );
496 if (masm) {
497 __ mov(reg_to_register_object(Matcher::_regEncode[dst_first]), reg_to_register_object(Matcher::_regEncode[src_first]));
498 #ifndef PRODUCT
499 } else if (!do_size) {
500 st->print("MOV R_%s, R_%s\t# spill",
501 Matcher::regName[dst_first],
502 Matcher::regName[src_first]);
503 #endif
504 }
505 size += 4;
506 }
507
508 // Check for integer store
509 if (src_first_rc == rc_int && dst_first_rc == rc_stack) {
510 int offset = ra_->reg2offset(dst_first);
511 if (masm && !is_memoryI(offset)) {
512 ra_->C->record_method_not_compilable("unable to handle large constant offsets");
513 return 0;
514 } else {
515 if (src_second_rc != rc_bad && is_iRegLd_memhd(src_first, src_second, offset)) {
516 assert((src_first&1)==0 && src_first+1 == src_second, "pair of registers must be aligned/contiguous");
517 if (masm) {
518 __ str_64(reg_to_register_object(Matcher::_regEncode[src_first]), Address(SP, offset));
519 #ifndef PRODUCT
520 } else if (!do_size) {
521 if (size != 0) st->print("\n\t");
522 st->print(STR_64 " R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(src_first), offset);
523 #endif
524 }
525 return size + 4;
526 } else {
527 if (masm) {
528 __ str_32(reg_to_register_object(Matcher::_regEncode[src_first]), Address(SP, offset));
529 #ifndef PRODUCT
530 } else if (!do_size) {
531 if (size != 0) st->print("\n\t");
532 st->print(STR_32 " R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(src_first), offset);
533 #endif
534 }
535 }
536 }
537 size += 4;
538 }
539
540 // Check for integer load
541 if (dst_first_rc == rc_int && src_first_rc == rc_stack) {
542 int offset = ra_->reg2offset(src_first);
543 if (masm && !is_memoryI(offset)) {
544 ra_->C->record_method_not_compilable("unable to handle large constant offsets");
545 return 0;
546 } else {
547 if (src_second_rc != rc_bad && is_iRegLd_memhd(dst_first, dst_second, offset)) {
548 assert((src_first&1)==0 && src_first+1 == src_second, "pair of registers must be aligned/contiguous");
549 if (masm) {
550 __ ldr_64(reg_to_register_object(Matcher::_regEncode[dst_first]), Address(SP, offset));
551 #ifndef PRODUCT
552 } else if (!do_size) {
553 if (size != 0) st->print("\n\t");
554 st->print(LDR_64 " R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(dst_first), offset);
555 #endif
556 }
557 return size + 4;
558 } else {
559 if (masm) {
560 __ ldr_32(reg_to_register_object(Matcher::_regEncode[dst_first]), Address(SP, offset));
561 #ifndef PRODUCT
562 } else if (!do_size) {
563 if (size != 0) st->print("\n\t");
564 st->print(LDR_32 " R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(dst_first), offset);
565 #endif
566 }
567 }
568 }
569 size += 4;
570 }
571
572 // Check for float reg-reg copy
573 if (src_first_rc == rc_float && dst_first_rc == rc_float) {
574 if (src_second_rc != rc_bad) {
575 assert((src_first&1)==0 && src_first+1 == src_second && (dst_first&1)==0 && dst_first+1 == dst_second, "pairs of registers must be aligned/contiguous");
576 if (masm) {
577 __ mov_double(reg_to_FloatRegister_object(Matcher::_regEncode[dst_first]), reg_to_FloatRegister_object(Matcher::_regEncode[src_first]));
578 #ifndef PRODUCT
579 } else if (!do_size) {
580 st->print(MOV_DOUBLE " R_%s, R_%s\t# spill",
581 Matcher::regName[dst_first],
582 Matcher::regName[src_first]);
583 #endif
584 }
585 return 4;
586 }
587 if (masm) {
588 __ mov_float(reg_to_FloatRegister_object(Matcher::_regEncode[dst_first]), reg_to_FloatRegister_object(Matcher::_regEncode[src_first]));
589 #ifndef PRODUCT
590 } else if (!do_size) {
591 st->print(MOV_FLOAT " R_%s, R_%s\t# spill",
592 Matcher::regName[dst_first],
593 Matcher::regName[src_first]);
594 #endif
595 }
596 size = 4;
597 }
598
599 // Check for float store
600 if (src_first_rc == rc_float && dst_first_rc == rc_stack) {
601 int offset = ra_->reg2offset(dst_first);
602 if (masm && !is_memoryfp(offset)) {
603 ra_->C->record_method_not_compilable("unable to handle large constant offsets");
604 return 0;
605 } else {
606 // Further check for aligned-adjacent pair, so we can use a double store
607 if (src_second_rc != rc_bad) {
608 assert((src_first&1)==0 && src_first+1 == src_second && (dst_first&1)==0 && dst_first+1 == dst_second, "pairs of registers and stack slots must be aligned/contiguous");
609 if (masm) {
610 __ str_double(reg_to_FloatRegister_object(Matcher::_regEncode[src_first]), Address(SP, offset));
611 #ifndef PRODUCT
612 } else if (!do_size) {
613 if (size != 0) st->print("\n\t");
614 st->print(STR_DOUBLE " R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(src_first),offset);
615 #endif
616 }
617 return size + 4;
618 } else {
619 if (masm) {
620 __ str_float(reg_to_FloatRegister_object(Matcher::_regEncode[src_first]), Address(SP, offset));
621 #ifndef PRODUCT
622 } else if (!do_size) {
623 if (size != 0) st->print("\n\t");
624 st->print(STR_FLOAT " R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(src_first),offset);
625 #endif
626 }
627 }
628 }
629 size += 4;
630 }
631
632 // Check for float load
633 if (dst_first_rc == rc_float && src_first_rc == rc_stack) {
634 int offset = ra_->reg2offset(src_first);
635 if (masm && !is_memoryfp(offset)) {
636 ra_->C->record_method_not_compilable("unable to handle large constant offsets");
637 return 0;
638 } else {
639 // Further check for aligned-adjacent pair, so we can use a double store
640 if (src_second_rc != rc_bad) {
641 assert((src_first&1)==0 && src_first+1 == src_second && (dst_first&1)==0 && dst_first+1 == dst_second, "pairs of registers and stack slots must be aligned/contiguous");
642 if (masm) {
643 __ ldr_double(reg_to_FloatRegister_object(Matcher::_regEncode[dst_first]), Address(SP, offset));
644 #ifndef PRODUCT
645 } else if (!do_size) {
646 if (size != 0) st->print("\n\t");
647 st->print(LDR_DOUBLE " R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(dst_first),offset);
648 #endif
649 }
650 return size + 4;
651 } else {
652 if (masm) {
653 __ ldr_float(reg_to_FloatRegister_object(Matcher::_regEncode[dst_first]), Address(SP, offset));
654 #ifndef PRODUCT
655 } else if (!do_size) {
656 if (size != 0) st->print("\n\t");
657 st->print(LDR_FLOAT " R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(dst_first),offset);
658 #endif
659 }
660 }
661 }
662 size += 4;
663 }
664
665 // check for int reg -> float reg move
666 if (src_first_rc == rc_int && dst_first_rc == rc_float) {
667 // Further check for aligned-adjacent pair, so we can use a single instruction
668 if (src_second_rc != rc_bad) {
669 assert((dst_first&1)==0 && dst_first+1 == dst_second, "pairs of registers must be aligned/contiguous");
670 assert((src_first&1)==0 && src_first+1 == src_second, "pairs of registers must be aligned/contiguous");
671 assert(src_second_rc == rc_int && dst_second_rc == rc_float, "unsupported");
672 if (masm) {
673 __ fmdrr(reg_to_FloatRegister_object(Matcher::_regEncode[dst_first]), reg_to_register_object(Matcher::_regEncode[src_first]), reg_to_register_object(Matcher::_regEncode[src_second]));
674 #ifndef PRODUCT
675 } else if (!do_size) {
676 if (size != 0) st->print("\n\t");
677 st->print("FMDRR R_%s, R_%s, R_%s\t! spill",OptoReg::regname(dst_first), OptoReg::regname(src_first), OptoReg::regname(src_second));
678 #endif
679 }
680 return size + 4;
681 } else {
682 if (masm) {
683 __ fmsr(reg_to_FloatRegister_object(Matcher::_regEncode[dst_first]), reg_to_register_object(Matcher::_regEncode[src_first]));
684 #ifndef PRODUCT
685 } else if (!do_size) {
686 if (size != 0) st->print("\n\t");
687 st->print(FMSR " R_%s, R_%s\t! spill",OptoReg::regname(dst_first), OptoReg::regname(src_first));
688 #endif
689 }
690 size += 4;
691 }
692 }
693
694 // check for float reg -> int reg move
695 if (src_first_rc == rc_float && dst_first_rc == rc_int) {
696 // Further check for aligned-adjacent pair, so we can use a single instruction
697 if (src_second_rc != rc_bad) {
698 assert((src_first&1)==0 && src_first+1 == src_second, "pairs of registers must be aligned/contiguous");
699 assert((dst_first&1)==0 && dst_first+1 == dst_second, "pairs of registers must be aligned/contiguous");
700 assert(src_second_rc == rc_float && dst_second_rc == rc_int, "unsupported");
701 if (masm) {
702 __ fmrrd(reg_to_register_object(Matcher::_regEncode[dst_first]), reg_to_register_object(Matcher::_regEncode[dst_second]), reg_to_FloatRegister_object(Matcher::_regEncode[src_first]));
703 #ifndef PRODUCT
704 } else if (!do_size) {
705 if (size != 0) st->print("\n\t");
706 st->print("FMRRD R_%s, R_%s, R_%s\t! spill",OptoReg::regname(dst_first), OptoReg::regname(dst_second), OptoReg::regname(src_first));
707 #endif
708 }
709 return size + 4;
710 } else {
711 if (masm) {
712 __ fmrs(reg_to_register_object(Matcher::_regEncode[dst_first]), reg_to_FloatRegister_object(Matcher::_regEncode[src_first]));
713 #ifndef PRODUCT
714 } else if (!do_size) {
715 if (size != 0) st->print("\n\t");
716 st->print(FMRS " R_%s, R_%s\t! spill",OptoReg::regname(dst_first), OptoReg::regname(src_first));
717 #endif
718 }
719 size += 4;
720 }
721 }
722
723 // --------------------------------------------------------------------
724 // Check for hi bits still needing moving. Only happens for misaligned
725 // arguments to native calls.
726 if (src_second == dst_second)
727 return size; // Self copy; no move
728 assert( src_second_rc != rc_bad && dst_second_rc != rc_bad, "src_second & dst_second cannot be Bad" );
729
730 // Check for integer reg-reg copy. Hi bits are stuck up in the top
731 // 32-bits of a 64-bit register, but are needed in low bits of another
732 // register (else it's a hi-bits-to-hi-bits copy which should have
733 // happened already as part of a 64-bit move)
734 if (src_second_rc == rc_int && dst_second_rc == rc_int) {
735 if (masm) {
736 __ mov(reg_to_register_object(Matcher::_regEncode[dst_second]), reg_to_register_object(Matcher::_regEncode[src_second]));
737 #ifndef PRODUCT
738 } else if (!do_size) {
739 if (size != 0) st->print("\n\t");
740 st->print("MOV R_%s, R_%s\t# spill high",
741 Matcher::regName[dst_second],
742 Matcher::regName[src_second]);
743 #endif
744 }
745 return size+4;
746 }
747
748 // Check for high word integer store
749 if (src_second_rc == rc_int && dst_second_rc == rc_stack) {
750 int offset = ra_->reg2offset(dst_second);
751
752 if (masm && !is_memoryP(offset)) {
753 ra_->C->record_method_not_compilable("unable to handle large constant offsets");
754 return 0;
755 } else {
756 if (masm) {
757 __ str(reg_to_register_object(Matcher::_regEncode[src_second]), Address(SP, offset));
758 #ifndef PRODUCT
759 } else if (!do_size) {
760 if (size != 0) st->print("\n\t");
761 st->print("STR R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(src_second), offset);
762 #endif
763 }
764 }
765 return size + 4;
766 }
767
768 // Check for high word integer load
769 if (dst_second_rc == rc_int && src_second_rc == rc_stack) {
770 int offset = ra_->reg2offset(src_second);
771 if (masm && !is_memoryP(offset)) {
772 ra_->C->record_method_not_compilable("unable to handle large constant offsets");
773 return 0;
774 } else {
775 if (masm) {
776 __ ldr(reg_to_register_object(Matcher::_regEncode[dst_second]), Address(SP, offset));
777 #ifndef PRODUCT
778 } else if (!do_size) {
779 if (size != 0) st->print("\n\t");
780 st->print("LDR R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(dst_second), offset);
781 #endif
782 }
783 }
784 return size + 4;
785 }
786
787 Unimplemented();
788 return 0; // Mute compiler
789 }
790
791 #ifndef PRODUCT
792 void MachSpillCopyNode::format( PhaseRegAlloc *ra_, outputStream *st ) const {
793 implementation( nullptr, ra_, false, st );
794 }
795 #endif
796
797 void MachSpillCopyNode::emit(C2_MacroAssembler *masm, PhaseRegAlloc *ra_) const {
798 implementation( masm, ra_, false, nullptr );
799 }
800
801 uint MachSpillCopyNode::size(PhaseRegAlloc *ra_) const {
802 return implementation( nullptr, ra_, true, nullptr );
803 }
804
805 //=============================================================================
806 #ifndef PRODUCT
807 void MachNopNode::format( PhaseRegAlloc *, outputStream *st ) const {
808 st->print("NOP \t# %d bytes pad for loops and calls", 4 * _count);
809 }
810 #endif
811
812 void MachNopNode::emit(C2_MacroAssembler *masm, PhaseRegAlloc * ) const {
813 for(int i = 0; i < _count; i += 1) {
814 __ nop();
815 }
816 }
817
818 uint MachNopNode::size(PhaseRegAlloc *ra_) const {
819 return 4 * _count;
820 }
821
822
823 //=============================================================================
824 #ifndef PRODUCT
825 void BoxLockNode::format( PhaseRegAlloc *ra_, outputStream *st ) const {
826 int offset = ra_->reg2offset(in_RegMask(0).find_first_elem());
827 int reg = ra_->get_reg_first(this);
828 st->print("ADD %s,R_SP+#%d",Matcher::regName[reg], offset);
829 }
830 #endif
831
832 void BoxLockNode::emit(C2_MacroAssembler *masm, PhaseRegAlloc *ra_) const {
833 int offset = ra_->reg2offset(in_RegMask(0).find_first_elem());
834 int reg = ra_->get_encode(this);
835 Register dst = reg_to_register_object(reg);
836
837 if (is_aimm(offset)) {
838 __ add(dst, SP, offset);
839 } else {
840 __ mov_slow(dst, offset);
841 __ add(dst, SP, dst);
842 }
843 }
844
845 uint BoxLockNode::size(PhaseRegAlloc *ra_) const {
846 // BoxLockNode is not a MachNode, so we can't just call MachNode::size(ra_)
847 assert(ra_ == ra_->C->regalloc(), "sanity");
848 return ra_->C->output()->scratch_emit_size(this);
849 }
850
851 //=============================================================================
852 #ifndef PRODUCT
853 #define R_RTEMP "R_R12"
854 void MachUEPNode::format( PhaseRegAlloc *ra_, outputStream *st ) const {
855 st->print_cr("\nUEP:");
856 st->print_cr("\tLDR " R_RTEMP ",[R_R0 + oopDesc::klass_offset_in_bytes]\t! Inline cache check");
857 st->print_cr("\tCMP " R_RTEMP ",R_R8" );
858 st->print ("\tB.NE SharedRuntime::handle_ic_miss_stub");
859 }
860 #endif
861
862 void MachUEPNode::emit(C2_MacroAssembler *masm, PhaseRegAlloc *ra_) const {
863 __ ic_check(InteriorEntryAlignment);
864 }
865
866 uint MachUEPNode::size(PhaseRegAlloc *ra_) const {
867 return MachNode::size(ra_);
868 }
869
870
871 //=============================================================================
872
873 int HandlerImpl::emit_deopt_handler(C2_MacroAssembler* masm) {
874 // Can't use any of the current frame's registers as we may have deopted
875 // at a poll and everything can be live.
876 address base = __ start_a_stub(size_deopt_handler());
877 if (base == nullptr) {
878 ciEnv::current()->record_failure("CodeCache is full");
879 return 0; // CodeBuffer::expand failed
880 }
881
882 int offset = __ offset();
883
884 Label start;
885 __ bind(start);
886
887 __ jump(SharedRuntime::deopt_blob()->unpack(), relocInfo::runtime_call_type, noreg);
888
889 int entry_offset = __ offset();
890 address deopt_pc = __ pc();
891 // Preserve R0 and reserve space for the address of the entry point
892 __ push(RegisterSet(R0) | RegisterSet(R1));
893 // Store the entry point address
894 __ mov_relative_address(R0, deopt_pc);
895 __ str(R0, Address(SP, wordSize));
896 __ pop(R0); // restore R0
897 __ b(start);
898
899 assert(__ offset() - offset <= (int) size_deopt_handler(), "overflow");
900 assert(__ offset() - entry_offset >= NativePostCallNop::first_check_size,
901 "out of bounds read in post-call NOP check");
902
903 __ end_a_stub();
904 return entry_offset;
905 }
906
907 bool Matcher::match_rule_supported(int opcode) {
908 if (!has_match_rule(opcode))
909 return false;
910
911 switch (opcode) {
912 case Op_PopCountI:
913 case Op_PopCountL:
914 if (!UsePopCountInstruction)
915 return false;
916 break;
917 case Op_LShiftCntV:
918 case Op_RShiftCntV:
919 case Op_AddVB:
920 case Op_AddVS:
921 case Op_AddVI:
922 case Op_AddVL:
923 case Op_SubVB:
924 case Op_SubVS:
925 case Op_SubVI:
926 case Op_SubVL:
927 case Op_MulVS:
928 case Op_MulVI:
929 case Op_LShiftVB:
930 case Op_LShiftVS:
931 case Op_LShiftVI:
932 case Op_LShiftVL:
933 case Op_RShiftVB:
934 case Op_RShiftVS:
935 case Op_RShiftVI:
936 case Op_RShiftVL:
937 case Op_URShiftVB:
938 case Op_URShiftVS:
939 case Op_URShiftVI:
940 case Op_URShiftVL:
941 case Op_AndV:
942 case Op_OrV:
943 case Op_XorV:
944 return VM_Version::has_simd();
945 case Op_LoadVector:
946 case Op_StoreVector:
947 case Op_AddVF:
948 case Op_SubVF:
949 case Op_MulVF:
950 return VM_Version::has_vfp() || VM_Version::has_simd();
951 case Op_AddVD:
952 case Op_SubVD:
953 case Op_MulVD:
954 case Op_DivVF:
955 case Op_DivVD:
956 return VM_Version::has_vfp();
957 }
958
959 return true; // Per default match rules are supported.
960 }
961
962 bool Matcher::match_rule_supported_auto_vectorization(int opcode, int vlen, BasicType bt) {
963 return match_rule_supported_vector(opcode, vlen, bt);
964 }
965
966 bool Matcher::match_rule_supported_vector(int opcode, int vlen, BasicType bt) {
967
968 // TODO
969 // identify extra cases that we might want to provide match rules for
970 // e.g. Op_ vector nodes and other intrinsics while guarding with vlen
971 bool ret_value = match_rule_supported(opcode) && vector_size_supported(bt, vlen);
972 // Add rules here.
973
974 return ret_value; // Per default match rules are supported.
975 }
976
977 bool Matcher::match_rule_supported_vector_masked(int opcode, int vlen, BasicType bt) {
978 return false;
979 }
980
981 bool Matcher::vector_needs_partial_operations(Node* node, const TypeVect* vt) {
982 return false;
983 }
984
985 bool Matcher::vector_rearrange_requires_load_shuffle(BasicType elem_bt, int vlen) {
986 return false;
987 }
988
989 bool Matcher::mask_op_prefers_predicate(int opcode, const TypeVect* vt) {
990 return false;
991 }
992
993 const RegMask* Matcher::predicate_reg_mask(void) {
994 return nullptr;
995 }
996
997 // Vector calling convention not yet implemented.
998 bool Matcher::supports_vector_calling_convention(void) {
999 return false;
1000 }
1001
1002 OptoRegPair Matcher::vector_return_value(uint ideal_reg) {
1003 Unimplemented();
1004 return OptoRegPair(0, 0);
1005 }
1006
1007 // Vector width in bytes
1008 int Matcher::vector_width_in_bytes(BasicType bt) {
1009 return MaxVectorSize;
1010 }
1011
1012 int Matcher::scalable_vector_reg_size(const BasicType bt) {
1013 return -1;
1014 }
1015
1016 // Vector ideal reg corresponding to specified size in bytes
1017 uint Matcher::vector_ideal_reg(int size) {
1018 assert(MaxVectorSize >= size, "");
1019 switch(size) {
1020 case 8: return Op_VecD;
1021 case 16: return Op_VecX;
1022 }
1023 ShouldNotReachHere();
1024 return 0;
1025 }
1026
1027 // Limits on vector size (number of elements) loaded into vector.
1028 int Matcher::max_vector_size(const BasicType bt) {
1029 assert(is_java_primitive(bt), "only primitive type vectors");
1030 return vector_width_in_bytes(bt)/type2aelembytes(bt);
1031 }
1032
1033 int Matcher::min_vector_size(const BasicType bt) {
1034 assert(is_java_primitive(bt), "only primitive type vectors");
1035 return 8/type2aelembytes(bt);
1036 }
1037
1038 int Matcher::max_vector_size_auto_vectorization(const BasicType bt) {
1039 return Matcher::max_vector_size(bt);
1040 }
1041
1042 // Is this branch offset short enough that a short branch can be used?
1043 //
1044 // NOTE: If the platform does not provide any short branch variants, then
1045 // this method should return false for offset 0.
1046 bool Matcher::is_short_branch_offset(int rule, int br_size, int offset) {
1047 // The passed offset is relative to address of the branch.
1048 // On ARM a branch displacement is calculated relative to address
1049 // of the branch + 8.
1050 //
1051 // offset -= 8;
1052 // return (Assembler::is_simm24(offset));
1053 return false;
1054 }
1055
1056 MachOper* Matcher::pd_specialize_generic_vector_operand(MachOper* original_opnd, uint ideal_reg, bool is_temp) {
1057 ShouldNotReachHere(); // generic vector operands not supported
1058 return nullptr;
1059 }
1060
1061 bool Matcher::is_reg2reg_move(MachNode* m) {
1062 ShouldNotReachHere(); // generic vector operands not supported
1063 return false;
1064 }
1065
1066 bool Matcher::is_register_biasing_candidate(const MachNode* mdef, int oper_index) {
1067 return false;
1068 }
1069
1070 bool Matcher::is_generic_vector(MachOper* opnd) {
1071 ShouldNotReachHere(); // generic vector operands not supported
1072 return false;
1073 }
1074
1075 // Should the matcher clone input 'm' of node 'n'?
1076 bool Matcher::pd_clone_node(Node* n, Node* m, Matcher::MStack& mstack) {
1077 if (is_vshift_con_pattern(n, m)) { // ShiftV src (ShiftCntV con)
1078 mstack.push(m, Visit); // m = ShiftCntV
1079 return true;
1080 }
1081 return false;
1082 }
1083
1084 // Should the Matcher clone shifts on addressing modes, expecting them
1085 // to be subsumed into complex addressing expressions or compute them
1086 // into registers?
1087 bool Matcher::pd_clone_address_expressions(AddPNode* m, Matcher::MStack& mstack, VectorSet& address_visited) {
1088 return clone_base_plus_offset_address(m, mstack, address_visited);
1089 }
1090
1091 #ifdef ASSERT
1092 // Return whether or not this register is ever used as an argument.
1093 bool Matcher::can_be_java_arg( int reg ) {
1094 if (reg == R_R0_num ||
1095 reg == R_R1_num ||
1096 reg == R_R2_num ||
1097 reg == R_R3_num) return true;
1098
1099 if (reg >= R_S0_num &&
1100 reg <= R_S13_num) return true;
1101 return false;
1102 }
1103 #endif
1104
1105 uint Matcher::int_pressure_limit()
1106 {
1107 return (INTPRESSURE == -1) ? 12 : INTPRESSURE;
1108 }
1109
1110 uint Matcher::float_pressure_limit()
1111 {
1112 return (FLOATPRESSURE == -1) ? 30 : FLOATPRESSURE;
1113 }
1114
1115 // Register for DIVI projection of divmodI
1116 const RegMask& Matcher::divI_proj_mask() {
1117 ShouldNotReachHere();
1118 return RegMask::EMPTY;
1119 }
1120
1121 // Register for MODI projection of divmodI
1122 const RegMask& Matcher::modI_proj_mask() {
1123 ShouldNotReachHere();
1124 return RegMask::EMPTY;
1125 }
1126
1127 // Register for DIVL projection of divmodL
1128 const RegMask& Matcher::divL_proj_mask() {
1129 ShouldNotReachHere();
1130 return RegMask::EMPTY;
1131 }
1132
1133 // Register for MODL projection of divmodL
1134 const RegMask& Matcher::modL_proj_mask() {
1135 ShouldNotReachHere();
1136 return RegMask::EMPTY;
1137 }
1138
1139 bool maybe_far_call(const CallNode *n) {
1140 return !MacroAssembler::_reachable_from_cache(n->as_Call()->entry_point());
1141 }
1142
1143 bool maybe_far_call(const MachCallNode *n) {
1144 return !MacroAssembler::_reachable_from_cache(n->as_MachCall()->entry_point());
1145 }
1146
1147 %}
1148
1149 //----------ENCODING BLOCK-----------------------------------------------------
1150 // This block specifies the encoding classes used by the compiler to output
1151 // byte streams. Encoding classes are parameterized macros used by
1152 // Machine Instruction Nodes in order to generate the bit encoding of the
1153 // instruction. Operands specify their base encoding interface with the
1154 // interface keyword. There are currently supported four interfaces,
1155 // REG_INTER, CONST_INTER, MEMORY_INTER, & COND_INTER. REG_INTER causes an
1156 // operand to generate a function which returns its register number when
1157 // queried. CONST_INTER causes an operand to generate a function which
1158 // returns the value of the constant when queried. MEMORY_INTER causes an
1159 // operand to generate four functions which return the Base Register, the
1160 // Index Register, the Scale Value, and the Offset Value of the operand when
1161 // queried. COND_INTER causes an operand to generate six functions which
1162 // return the encoding code (ie - encoding bits for the instruction)
1163 // associated with each basic boolean condition for a conditional instruction.
1164 //
1165 // Instructions specify two basic values for encoding. Again, a function
1166 // is available to check if the constant displacement is an oop. They use the
1167 // ins_encode keyword to specify their encoding classes (which must be
1168 // a sequence of enc_class names, and their parameters, specified in
1169 // the encoding block), and they use the
1170 // opcode keyword to specify, in order, their primary, secondary, and
1171 // tertiary opcode. Only the opcode sections which a particular instruction
1172 // needs for encoding need to be specified.
1173 encode %{
1174 // Set instruction mark in MacroAssembler. This is used only in
1175 // instructions that emit bytes directly to the CodeBuffer wraped
1176 // in the MacroAssembler. Should go away once all "instruct" are
1177 // patched to emit bytes only using methods in MacroAssembler.
1178 enc_class SetInstMark %{
1179 __ set_inst_mark();
1180 %}
1181
1182 enc_class ClearInstMark %{
1183 __ clear_inst_mark();
1184 %}
1185
1186 enc_class call_epilog %{
1187 // nothing
1188 %}
1189
1190 enc_class Java_To_Runtime (method meth) %{
1191 // CALL directly to the runtime
1192 emit_call_reloc(masm, as_MachCall(), $meth, runtime_call_Relocation::spec());
1193 %}
1194
1195 enc_class Java_Static_Call (method meth) %{
1196 // CALL to fixup routine. Fixup routine uses ScopeDesc info to determine
1197 // who we intended to call.
1198
1199 if ( !_method) {
1200 emit_call_reloc(masm, as_MachCall(), $meth, runtime_call_Relocation::spec());
1201 } else {
1202 int method_index = resolved_method_index(masm);
1203 RelocationHolder rspec = _optimized_virtual ? opt_virtual_call_Relocation::spec(method_index)
1204 : static_call_Relocation::spec(method_index);
1205 emit_call_reloc(masm, as_MachCall(), $meth, rspec);
1206
1207 // Emit stubs for static call.
1208 address stub = CompiledDirectCall::emit_to_interp_stub(masm);
1209 if (stub == nullptr) {
1210 ciEnv::current()->record_failure("CodeCache is full");
1211 return;
1212 }
1213 }
1214 %}
1215
1216 enc_class save_last_PC %{
1217 // preserve mark
1218 address mark = __ inst_mark();
1219 DEBUG_ONLY(int off0 = __ offset());
1220 int ret_addr_offset = as_MachCall()->ret_addr_offset();
1221 __ adr(LR, mark + ret_addr_offset);
1222 __ str(LR, Address(Rthread, JavaThread::last_Java_pc_offset()));
1223 DEBUG_ONLY(int off1 = __ offset());
1224 assert(off1 - off0 == 2 * Assembler::InstructionSize, "correct size prediction");
1225 // restore mark
1226 __ set_inst_mark(mark);
1227 %}
1228
1229 enc_class Java_Dynamic_Call (method meth) %{
1230 Register R8_ic_reg = reg_to_register_object(Matcher::inline_cache_reg_encode());
1231 assert(R8_ic_reg == Ricklass, "should be");
1232 __ set_inst_mark();
1233 __ movw(R8_ic_reg, ((unsigned int)Universe::non_oop_word()) & 0xffff);
1234 __ movt(R8_ic_reg, ((unsigned int)Universe::non_oop_word()) >> 16);
1235 address virtual_call_oop_addr = __ inst_mark();
1236 // CALL to fixup routine. Fixup routine uses ScopeDesc info to determine
1237 // who we intended to call.
1238 int method_index = resolved_method_index(masm);
1239 __ relocate(virtual_call_Relocation::spec(virtual_call_oop_addr, method_index));
1240 emit_call_reloc(masm, as_MachCall(), $meth, RelocationHolder::none);
1241 %}
1242
1243 enc_class LdReplImmI(immI src, regD dst, iRegI tmp, int cnt, int wth) %{
1244 // FIXME: load from constant table?
1245 // Load a constant replicated "count" times with width "width"
1246 int count = $cnt$$constant;
1247 int width = $wth$$constant;
1248 assert(count*width == 4, "sanity");
1249 int val = $src$$constant;
1250 if (width < 4) {
1251 int bit_width = width * 8;
1252 val &= (((int)1) << bit_width) - 1; // mask off sign bits
1253 for (int i = 0; i < count - 1; i++) {
1254 val |= (val << bit_width);
1255 }
1256 }
1257
1258 if (val == -1) {
1259 __ mvn($tmp$$Register, 0);
1260 } else if (val == 0) {
1261 __ mov($tmp$$Register, 0);
1262 } else {
1263 __ movw($tmp$$Register, val & 0xffff);
1264 __ movt($tmp$$Register, (unsigned int)val >> 16);
1265 }
1266 __ fmdrr($dst$$FloatRegister, $tmp$$Register, $tmp$$Register);
1267 %}
1268
1269 enc_class LdReplImmF(immF src, regD dst, iRegI tmp) %{
1270 // Replicate float con 2 times and pack into vector (8 bytes) in regD.
1271 float fval = $src$$constant;
1272 int val = *((int*)&fval);
1273
1274 if (val == -1) {
1275 __ mvn($tmp$$Register, 0);
1276 } else if (val == 0) {
1277 __ mov($tmp$$Register, 0);
1278 } else {
1279 __ movw($tmp$$Register, val & 0xffff);
1280 __ movt($tmp$$Register, (unsigned int)val >> 16);
1281 }
1282 __ fmdrr($dst$$FloatRegister, $tmp$$Register, $tmp$$Register);
1283 %}
1284
1285 enc_class enc_String_Compare(R0RegP str1, R1RegP str2, R2RegI cnt1, R3RegI cnt2, iRegI result, iRegI tmp1, iRegI tmp2) %{
1286 Label Ldone, Lloop;
1287
1288 Register str1_reg = $str1$$Register;
1289 Register str2_reg = $str2$$Register;
1290 Register cnt1_reg = $cnt1$$Register; // int
1291 Register cnt2_reg = $cnt2$$Register; // int
1292 Register tmp1_reg = $tmp1$$Register;
1293 Register tmp2_reg = $tmp2$$Register;
1294 Register result_reg = $result$$Register;
1295
1296 assert_different_registers(str1_reg, str2_reg, cnt1_reg, cnt2_reg, tmp1_reg, tmp2_reg);
1297
1298 // Compute the minimum of the string lengths(str1_reg) and the
1299 // difference of the string lengths (stack)
1300
1301 // See if the lengths are different, and calculate min in str1_reg.
1302 // Stash diff in tmp2 in case we need it for a tie-breaker.
1303 __ subs_32(tmp2_reg, cnt1_reg, cnt2_reg);
1304 __ mov(cnt1_reg, AsmOperand(cnt1_reg, lsl, exact_log2(sizeof(jchar)))); // scale the limit
1305 __ mov(cnt1_reg, AsmOperand(cnt2_reg, lsl, exact_log2(sizeof(jchar))), pl); // scale the limit
1306
1307 // reallocate cnt1_reg, cnt2_reg, result_reg
1308 // Note: limit_reg holds the string length pre-scaled by 2
1309 Register limit_reg = cnt1_reg;
1310 Register chr2_reg = cnt2_reg;
1311 Register chr1_reg = tmp1_reg;
1312 // str{12} are the base pointers
1313
1314 // Is the minimum length zero?
1315 __ cmp_32(limit_reg, 0);
1316 if (result_reg != tmp2_reg) {
1317 __ mov(result_reg, tmp2_reg, eq);
1318 }
1319 __ b(Ldone, eq);
1320
1321 // Load first characters
1322 __ ldrh(chr1_reg, Address(str1_reg, 0));
1323 __ ldrh(chr2_reg, Address(str2_reg, 0));
1324
1325 // Compare first characters
1326 __ subs(chr1_reg, chr1_reg, chr2_reg);
1327 if (result_reg != chr1_reg) {
1328 __ mov(result_reg, chr1_reg, ne);
1329 }
1330 __ b(Ldone, ne);
1331
1332 {
1333 // Check after comparing first character to see if strings are equivalent
1334 // Check if the strings start at same location
1335 __ cmp(str1_reg, str2_reg);
1336 // Check if the length difference is zero
1337 __ cond_cmp(tmp2_reg, 0, eq);
1338 __ mov(result_reg, 0, eq); // result is zero
1339 __ b(Ldone, eq);
1340 // Strings might not be equal
1341 }
1342
1343 __ subs(chr1_reg, limit_reg, 1 * sizeof(jchar));
1344 if (result_reg != tmp2_reg) {
1345 __ mov(result_reg, tmp2_reg, eq);
1346 }
1347 __ b(Ldone, eq);
1348
1349 // Shift str1_reg and str2_reg to the end of the arrays, negate limit
1350 __ add(str1_reg, str1_reg, limit_reg);
1351 __ add(str2_reg, str2_reg, limit_reg);
1352 __ neg(limit_reg, chr1_reg); // limit = -(limit-2)
1353
1354 // Compare the rest of the characters
1355 __ bind(Lloop);
1356 __ ldrh(chr1_reg, Address(str1_reg, limit_reg));
1357 __ ldrh(chr2_reg, Address(str2_reg, limit_reg));
1358 __ subs(chr1_reg, chr1_reg, chr2_reg);
1359 if (result_reg != chr1_reg) {
1360 __ mov(result_reg, chr1_reg, ne);
1361 }
1362 __ b(Ldone, ne);
1363
1364 __ adds(limit_reg, limit_reg, sizeof(jchar));
1365 __ b(Lloop, ne);
1366
1367 // If strings are equal up to min length, return the length difference.
1368 if (result_reg != tmp2_reg) {
1369 __ mov(result_reg, tmp2_reg);
1370 }
1371
1372 // Otherwise, return the difference between the first mismatched chars.
1373 __ bind(Ldone);
1374 %}
1375
1376 enc_class enc_String_Equals(R0RegP str1, R1RegP str2, R2RegI cnt, iRegI result, iRegI tmp1, iRegI tmp2) %{
1377 Label Lchar, Lchar_loop, Ldone, Lequal;
1378
1379 Register str1_reg = $str1$$Register;
1380 Register str2_reg = $str2$$Register;
1381 Register cnt_reg = $cnt$$Register; // int
1382 Register tmp1_reg = $tmp1$$Register;
1383 Register tmp2_reg = $tmp2$$Register;
1384 Register result_reg = $result$$Register;
1385
1386 assert_different_registers(str1_reg, str2_reg, cnt_reg, tmp1_reg, tmp2_reg, result_reg);
1387
1388 __ cmp(str1_reg, str2_reg); //same char[] ?
1389 __ b(Lequal, eq);
1390
1391 __ cbz_32(cnt_reg, Lequal); // count == 0
1392
1393 //rename registers
1394 Register limit_reg = cnt_reg;
1395 Register chr1_reg = tmp1_reg;
1396 Register chr2_reg = tmp2_reg;
1397
1398 __ logical_shift_left(limit_reg, limit_reg, exact_log2(sizeof(jchar)));
1399
1400 //check for alignment and position the pointers to the ends
1401 __ orr(chr1_reg, str1_reg, str2_reg);
1402 __ tst(chr1_reg, 0x3);
1403
1404 // notZero means at least one not 4-byte aligned.
1405 // We could optimize the case when both arrays are not aligned
1406 // but it is not frequent case and it requires additional checks.
1407 __ b(Lchar, ne);
1408
1409 // Compare char[] arrays aligned to 4 bytes.
1410 __ char_arrays_equals(str1_reg, str2_reg, limit_reg, result_reg,
1411 chr1_reg, chr2_reg, Ldone);
1412
1413 __ b(Lequal); // equal
1414
1415 // char by char compare
1416 __ bind(Lchar);
1417 __ mov(result_reg, 0);
1418 __ add(str1_reg, limit_reg, str1_reg);
1419 __ add(str2_reg, limit_reg, str2_reg);
1420 __ neg(limit_reg, limit_reg); //negate count
1421
1422 // Lchar_loop
1423 __ bind(Lchar_loop);
1424 __ ldrh(chr1_reg, Address(str1_reg, limit_reg));
1425 __ ldrh(chr2_reg, Address(str2_reg, limit_reg));
1426 __ cmp(chr1_reg, chr2_reg);
1427 __ b(Ldone, ne);
1428 __ adds(limit_reg, limit_reg, sizeof(jchar));
1429 __ b(Lchar_loop, ne);
1430
1431 __ bind(Lequal);
1432 __ mov(result_reg, 1); //equal
1433
1434 __ bind(Ldone);
1435 %}
1436
1437 enc_class enc_Array_Equals(R0RegP ary1, R1RegP ary2, iRegI tmp1, iRegI tmp2, iRegI tmp3, iRegI result) %{
1438 Label Ldone, Lloop, Lequal;
1439
1440 Register ary1_reg = $ary1$$Register;
1441 Register ary2_reg = $ary2$$Register;
1442 Register tmp1_reg = $tmp1$$Register;
1443 Register tmp2_reg = $tmp2$$Register;
1444 Register tmp3_reg = $tmp3$$Register;
1445 Register result_reg = $result$$Register;
1446
1447 assert_different_registers(ary1_reg, ary2_reg, tmp1_reg, tmp2_reg, tmp3_reg, result_reg);
1448
1449 int length_offset = arrayOopDesc::length_offset_in_bytes();
1450 int base_offset = arrayOopDesc::base_offset_in_bytes(T_CHAR);
1451
1452 // return true if the same array
1453 __ teq(ary1_reg, ary2_reg);
1454 __ mov(result_reg, 1, eq);
1455 __ b(Ldone, eq); // equal
1456
1457 __ tst(ary1_reg, ary1_reg);
1458 __ mov(result_reg, 0, eq);
1459 __ b(Ldone, eq); // not equal
1460
1461 __ tst(ary2_reg, ary2_reg);
1462 __ mov(result_reg, 0, eq);
1463 __ b(Ldone, eq); // not equal
1464
1465 //load the lengths of arrays
1466 __ ldr_s32(tmp1_reg, Address(ary1_reg, length_offset)); // int
1467 __ ldr_s32(tmp2_reg, Address(ary2_reg, length_offset)); // int
1468
1469 // return false if the two arrays are not equal length
1470 __ teq_32(tmp1_reg, tmp2_reg);
1471 __ mov(result_reg, 0, ne);
1472 __ b(Ldone, ne); // not equal
1473
1474 __ tst(tmp1_reg, tmp1_reg);
1475 __ mov(result_reg, 1, eq);
1476 __ b(Ldone, eq); // zero-length arrays are equal
1477
1478 // load array addresses
1479 __ add(ary1_reg, ary1_reg, base_offset);
1480 __ add(ary2_reg, ary2_reg, base_offset);
1481
1482 // renaming registers
1483 Register chr1_reg = tmp3_reg; // for characters in ary1
1484 Register chr2_reg = tmp2_reg; // for characters in ary2
1485 Register limit_reg = tmp1_reg; // length
1486
1487 // set byte count
1488 __ logical_shift_left_32(limit_reg, limit_reg, exact_log2(sizeof(jchar)));
1489
1490 // Compare char[] arrays aligned to 4 bytes.
1491 __ char_arrays_equals(ary1_reg, ary2_reg, limit_reg, result_reg,
1492 chr1_reg, chr2_reg, Ldone);
1493 __ bind(Lequal);
1494 __ mov(result_reg, 1); //equal
1495
1496 __ bind(Ldone);
1497 %}
1498 %}
1499
1500 //----------FRAME--------------------------------------------------------------
1501 // Definition of frame structure and management information.
1502 //
1503 // S T A C K L A Y O U T Allocators stack-slot number
1504 // | (to get allocators register number
1505 // G Owned by | | v add VMRegImpl::stack0)
1506 // r CALLER | |
1507 // o | +--------+ pad to even-align allocators stack-slot
1508 // w V | pad0 | numbers; owned by CALLER
1509 // t -----------+--------+----> Matcher::_in_arg_limit, unaligned
1510 // h ^ | in | 5
1511 // | | args | 4 Holes in incoming args owned by SELF
1512 // | | | | 3
1513 // | | +--------+
1514 // V | | old out| Empty on Intel, window on Sparc
1515 // | old |preserve| Must be even aligned.
1516 // | SP-+--------+----> Matcher::_old_SP, 8 (or 16 in LP64)-byte aligned
1517 // | | in | 3 area for Intel ret address
1518 // Owned by |preserve| Empty on Sparc.
1519 // SELF +--------+
1520 // | | pad2 | 2 pad to align old SP
1521 // | +--------+ 1
1522 // | | locks | 0
1523 // | +--------+----> VMRegImpl::stack0, 8 (or 16 in LP64)-byte aligned
1524 // | | pad1 | 11 pad to align new SP
1525 // | +--------+
1526 // | | | 10
1527 // | | spills | 9 spills
1528 // V | | 8 (pad0 slot for callee)
1529 // -----------+--------+----> Matcher::_out_arg_limit, unaligned
1530 // ^ | out | 7
1531 // | | args | 6 Holes in outgoing args owned by CALLEE
1532 // Owned by +--------+
1533 // CALLEE | new out| 6 Empty on Intel, window on Sparc
1534 // | new |preserve| Must be even-aligned.
1535 // | SP-+--------+----> Matcher::_new_SP, even aligned
1536 // | | |
1537 //
1538 // Note 1: Only region 8-11 is determined by the allocator. Region 0-5 is
1539 // known from SELF's arguments and the Java calling convention.
1540 // Region 6-7 is determined per call site.
1541 // Note 2: If the calling convention leaves holes in the incoming argument
1542 // area, those holes are owned by SELF. Holes in the outgoing area
1543 // are owned by the CALLEE. Holes should not be necessary in the
1544 // incoming area, as the Java calling convention is completely under
1545 // the control of the AD file. Doubles can be sorted and packed to
1546 // avoid holes. Holes in the outgoing arguments may be necessary for
1547 // varargs C calling conventions.
1548 // Note 3: Region 0-3 is even aligned, with pad2 as needed. Region 3-5 is
1549 // even aligned with pad0 as needed.
1550 // Region 6 is even aligned. Region 6-7 is NOT even aligned;
1551 // region 6-11 is even aligned; it may be padded out more so that
1552 // the region from SP to FP meets the minimum stack alignment.
1553
1554 frame %{
1555 // These two registers define part of the calling convention
1556 // between compiled code and the interpreter.
1557 inline_cache_reg(R_Ricklass); // Inline Cache Register or Method* for I2C
1558
1559 // Optional: name the operand used by cisc-spilling to access [stack_pointer + offset]
1560 cisc_spilling_operand_name(indOffset);
1561
1562 // Number of stack slots consumed by a Monitor enter
1563 sync_stack_slots(1 * VMRegImpl::slots_per_word);
1564
1565 // Compiled code's Frame Pointer
1566 frame_pointer(R_R13);
1567
1568 // Stack alignment requirement
1569 stack_alignment(StackAlignmentInBytes);
1570 // LP64: Alignment size in bytes (128-bit -> 16 bytes)
1571 // !LP64: Alignment size in bytes (64-bit -> 8 bytes)
1572
1573 // Number of outgoing stack slots killed above the out_preserve_stack_slots
1574 // for calls to C. Supports the var-args backing area for register parms.
1575 // ADLC doesn't support parsing expressions, so I folded the math by hand.
1576 varargs_C_out_slots_killed( 0);
1577
1578 // The after-PROLOG location of the return address. Location of
1579 // return address specifies a type (REG or STACK) and a number
1580 // representing the register number (i.e. - use a register name) or
1581 // stack slot.
1582 // Ret Addr is on stack in slot 0 if no locks or verification or alignment.
1583 // Otherwise, it is above the locks and verification slot and alignment word
1584 return_addr(STACK - 1*VMRegImpl::slots_per_word +
1585 align_up((Compile::current()->in_preserve_stack_slots() +
1586 Compile::current()->fixed_slots()),
1587 stack_alignment_in_slots()));
1588
1589 // Location of compiled Java return values. Same as C
1590 return_value %{
1591 return c2::return_value(ideal_reg);
1592 %}
1593
1594 %}
1595
1596 //----------ATTRIBUTES---------------------------------------------------------
1597 //----------Instruction Attributes---------------------------------------------
1598 ins_attrib ins_cost(DEFAULT_COST); // Required cost attribute
1599 ins_attrib ins_size(32); // Required size attribute (in bits)
1600 ins_attrib ins_short_branch(0); // Required flag: is this instruction a
1601 // non-matching short branch variant of some
1602 // long branch?
1603
1604 //----------OPERANDS-----------------------------------------------------------
1605 // Operand definitions must precede instruction definitions for correct parsing
1606 // in the ADLC because operands constitute user defined types which are used in
1607 // instruction definitions.
1608
1609 //----------Simple Operands----------------------------------------------------
1610 // Immediate Operands
1611 // Integer Immediate: 32-bit
1612 operand immI() %{
1613 match(ConI);
1614
1615 op_cost(0);
1616 // formats are generated automatically for constants and base registers
1617 format %{ %}
1618 interface(CONST_INTER);
1619 %}
1620
1621 // Integer Immediate: 8-bit unsigned - for VMOV
1622 operand immU8() %{
1623 predicate(0 <= n->get_int() && (n->get_int() <= 255));
1624 match(ConI);
1625 op_cost(0);
1626
1627 format %{ %}
1628 interface(CONST_INTER);
1629 %}
1630
1631 // Integer Immediate: 16-bit
1632 operand immI16() %{
1633 predicate((n->get_int() >> 16) == 0 && VM_Version::supports_movw());
1634 match(ConI);
1635 op_cost(0);
1636
1637 format %{ %}
1638 interface(CONST_INTER);
1639 %}
1640
1641 // Integer Immediate: offset for half and double word loads and stores
1642 operand immIHD() %{
1643 predicate(is_memoryHD(n->get_int()));
1644 match(ConI);
1645 op_cost(0);
1646 format %{ %}
1647 interface(CONST_INTER);
1648 %}
1649
1650 // Integer Immediate: offset for fp loads and stores
1651 operand immIFP() %{
1652 predicate(is_memoryfp(n->get_int()) && ((n->get_int() & 3) == 0));
1653 match(ConI);
1654 op_cost(0);
1655
1656 format %{ %}
1657 interface(CONST_INTER);
1658 %}
1659
1660 // Valid scale values for addressing modes and shifts
1661 operand immU5() %{
1662 predicate(0 <= n->get_int() && (n->get_int() <= 31));
1663 match(ConI);
1664 op_cost(0);
1665
1666 format %{ %}
1667 interface(CONST_INTER);
1668 %}
1669
1670 // Integer Immediate: 6-bit
1671 operand immU6Big() %{
1672 predicate(n->get_int() >= 32 && n->get_int() <= 63);
1673 match(ConI);
1674 op_cost(0);
1675 format %{ %}
1676 interface(CONST_INTER);
1677 %}
1678
1679 // Integer Immediate: 0-bit
1680 operand immI0() %{
1681 predicate(n->get_int() == 0);
1682 match(ConI);
1683 op_cost(0);
1684
1685 format %{ %}
1686 interface(CONST_INTER);
1687 %}
1688
1689 // Int Immediate non-negative
1690 operand immU31()
1691 %{
1692 predicate(n->get_int() >= 0);
1693 match(ConI);
1694
1695 op_cost(0);
1696 format %{ %}
1697 interface(CONST_INTER);
1698 %}
1699
1700 // Integer Immediate: the values 32-63
1701 operand immI_32_63() %{
1702 predicate(n->get_int() >= 32 && n->get_int() <= 63);
1703 match(ConI);
1704 op_cost(0);
1705
1706 format %{ %}
1707 interface(CONST_INTER);
1708 %}
1709
1710 // Immediates for special shifts (sign extend)
1711
1712 // Integer Immediate: the value 16
1713 operand immI_16() %{
1714 predicate(n->get_int() == 16);
1715 match(ConI);
1716 op_cost(0);
1717
1718 format %{ %}
1719 interface(CONST_INTER);
1720 %}
1721
1722 // Integer Immediate: the value 24
1723 operand immI_24() %{
1724 predicate(n->get_int() == 24);
1725 match(ConI);
1726 op_cost(0);
1727
1728 format %{ %}
1729 interface(CONST_INTER);
1730 %}
1731
1732 // Integer Immediate: the value 255
1733 operand immI_255() %{
1734 predicate( n->get_int() == 255 );
1735 match(ConI);
1736 op_cost(0);
1737
1738 format %{ %}
1739 interface(CONST_INTER);
1740 %}
1741
1742 // Integer Immediate: the value 65535
1743 operand immI_65535() %{
1744 predicate(n->get_int() == 65535);
1745 match(ConI);
1746 op_cost(0);
1747
1748 format %{ %}
1749 interface(CONST_INTER);
1750 %}
1751
1752 // Integer Immediates for arithmetic instructions
1753
1754 operand aimmI() %{
1755 predicate(is_aimm(n->get_int()));
1756 match(ConI);
1757 op_cost(0);
1758
1759 format %{ %}
1760 interface(CONST_INTER);
1761 %}
1762
1763 operand aimmIneg() %{
1764 predicate(is_aimm(-n->get_int()));
1765 match(ConI);
1766 op_cost(0);
1767
1768 format %{ %}
1769 interface(CONST_INTER);
1770 %}
1771
1772 operand aimmU31() %{
1773 predicate((0 <= n->get_int()) && is_aimm(n->get_int()));
1774 match(ConI);
1775 op_cost(0);
1776
1777 format %{ %}
1778 interface(CONST_INTER);
1779 %}
1780
1781 // Integer Immediates for logical instructions
1782
1783 operand limmI() %{
1784 predicate(is_limmI(n->get_int()));
1785 match(ConI);
1786 op_cost(0);
1787
1788 format %{ %}
1789 interface(CONST_INTER);
1790 %}
1791
1792 operand limmIlow8() %{
1793 predicate(is_limmI_low(n->get_int(), 8));
1794 match(ConI);
1795 op_cost(0);
1796
1797 format %{ %}
1798 interface(CONST_INTER);
1799 %}
1800
1801 operand limmU31() %{
1802 predicate(0 <= n->get_int() && is_limmI(n->get_int()));
1803 match(ConI);
1804 op_cost(0);
1805
1806 format %{ %}
1807 interface(CONST_INTER);
1808 %}
1809
1810 operand limmIn() %{
1811 predicate(is_limmI(~n->get_int()));
1812 match(ConI);
1813 op_cost(0);
1814
1815 format %{ %}
1816 interface(CONST_INTER);
1817 %}
1818
1819 // Pointer Immediate: 32 or 64-bit
1820 operand immP() %{
1821 match(ConP);
1822
1823 op_cost(5);
1824 // formats are generated automatically for constants and base registers
1825 format %{ %}
1826 interface(CONST_INTER);
1827 %}
1828
1829 operand immP0() %{
1830 predicate(n->get_ptr() == 0);
1831 match(ConP);
1832 op_cost(0);
1833
1834 format %{ %}
1835 interface(CONST_INTER);
1836 %}
1837
1838 operand immL() %{
1839 match(ConL);
1840 op_cost(40);
1841 // formats are generated automatically for constants and base registers
1842 format %{ %}
1843 interface(CONST_INTER);
1844 %}
1845
1846 operand immL0() %{
1847 predicate(n->get_long() == 0L);
1848 match(ConL);
1849 op_cost(0);
1850 // formats are generated automatically for constants and base registers
1851 format %{ %}
1852 interface(CONST_INTER);
1853 %}
1854
1855 // Long Immediate: 16-bit
1856 operand immL16() %{
1857 predicate(n->get_long() >= 0 && n->get_long() < (1<<16) && VM_Version::supports_movw());
1858 match(ConL);
1859 op_cost(0);
1860
1861 format %{ %}
1862 interface(CONST_INTER);
1863 %}
1864
1865 // Long Immediate: low 32-bit mask
1866 operand immL_32bits() %{
1867 predicate(n->get_long() == 0xFFFFFFFFL);
1868 match(ConL);
1869 op_cost(0);
1870
1871 format %{ %}
1872 interface(CONST_INTER);
1873 %}
1874
1875 // Double Immediate
1876 operand immD() %{
1877 match(ConD);
1878
1879 op_cost(40);
1880 format %{ %}
1881 interface(CONST_INTER);
1882 %}
1883
1884 // Double Immediate: +0.0d.
1885 operand immD0() %{
1886 predicate(jlong_cast(n->getd()) == 0);
1887
1888 match(ConD);
1889 op_cost(0);
1890 format %{ %}
1891 interface(CONST_INTER);
1892 %}
1893
1894 operand imm8D() %{
1895 predicate(Assembler::double_num(n->getd()).can_be_imm8());
1896 match(ConD);
1897
1898 op_cost(0);
1899 format %{ %}
1900 interface(CONST_INTER);
1901 %}
1902
1903 // Float Immediate
1904 operand immF() %{
1905 match(ConF);
1906
1907 op_cost(20);
1908 format %{ %}
1909 interface(CONST_INTER);
1910 %}
1911
1912 // Float Immediate: +0.0f
1913 operand immF0() %{
1914 predicate(jint_cast(n->getf()) == 0);
1915 match(ConF);
1916
1917 op_cost(0);
1918 format %{ %}
1919 interface(CONST_INTER);
1920 %}
1921
1922 // Float Immediate: encoded as 8 bits
1923 operand imm8F() %{
1924 predicate(Assembler::float_num(n->getf()).can_be_imm8());
1925 match(ConF);
1926
1927 op_cost(0);
1928 format %{ %}
1929 interface(CONST_INTER);
1930 %}
1931
1932 // Integer Register Operands
1933 // Integer Register
1934 operand iRegI() %{
1935 constraint(ALLOC_IN_RC(int_reg));
1936 match(RegI);
1937 match(R0RegI);
1938 match(R1RegI);
1939 match(R2RegI);
1940 match(R3RegI);
1941 match(R12RegI);
1942
1943 format %{ %}
1944 interface(REG_INTER);
1945 %}
1946
1947 // Pointer Register
1948 operand iRegP() %{
1949 constraint(ALLOC_IN_RC(ptr_reg));
1950 match(RegP);
1951 match(R0RegP);
1952 match(R1RegP);
1953 match(R2RegP);
1954 match(RExceptionRegP);
1955 match(R8RegP);
1956 match(R9RegP);
1957 match(RthreadRegP); // FIXME: move to sp_ptr_RegP?
1958 match(R12RegP);
1959 match(LRRegP);
1960
1961 match(sp_ptr_RegP);
1962 match(store_ptr_RegP);
1963
1964 format %{ %}
1965 interface(REG_INTER);
1966 %}
1967
1968 // GPRs + Rthread + SP
1969 operand sp_ptr_RegP() %{
1970 constraint(ALLOC_IN_RC(sp_ptr_reg));
1971 match(RegP);
1972 match(iRegP);
1973 match(SPRegP); // FIXME: check cost
1974
1975 format %{ %}
1976 interface(REG_INTER);
1977 %}
1978
1979
1980 operand R0RegP() %{
1981 constraint(ALLOC_IN_RC(R0_regP));
1982 match(iRegP);
1983
1984 format %{ %}
1985 interface(REG_INTER);
1986 %}
1987
1988 operand R1RegP() %{
1989 constraint(ALLOC_IN_RC(R1_regP));
1990 match(iRegP);
1991
1992 format %{ %}
1993 interface(REG_INTER);
1994 %}
1995
1996 operand R8RegP() %{
1997 constraint(ALLOC_IN_RC(R8_regP));
1998 match(iRegP);
1999
2000 format %{ %}
2001 interface(REG_INTER);
2002 %}
2003
2004 operand R9RegP() %{
2005 constraint(ALLOC_IN_RC(R9_regP));
2006 match(iRegP);
2007
2008 format %{ %}
2009 interface(REG_INTER);
2010 %}
2011
2012 operand R12RegP() %{
2013 constraint(ALLOC_IN_RC(R12_regP));
2014 match(iRegP);
2015
2016 format %{ %}
2017 interface(REG_INTER);
2018 %}
2019
2020 operand R2RegP() %{
2021 constraint(ALLOC_IN_RC(R2_regP));
2022 match(iRegP);
2023
2024 format %{ %}
2025 interface(REG_INTER);
2026 %}
2027
2028 operand RExceptionRegP() %{
2029 constraint(ALLOC_IN_RC(Rexception_regP));
2030 match(iRegP);
2031
2032 format %{ %}
2033 interface(REG_INTER);
2034 %}
2035
2036 operand RthreadRegP() %{
2037 constraint(ALLOC_IN_RC(Rthread_regP));
2038 match(iRegP);
2039
2040 format %{ %}
2041 interface(REG_INTER);
2042 %}
2043
2044 operand IPRegP() %{
2045 constraint(ALLOC_IN_RC(IP_regP));
2046 match(iRegP);
2047
2048 format %{ %}
2049 interface(REG_INTER);
2050 %}
2051
2052 operand SPRegP() %{
2053 constraint(ALLOC_IN_RC(SP_regP));
2054 match(iRegP);
2055
2056 format %{ %}
2057 interface(REG_INTER);
2058 %}
2059
2060 operand LRRegP() %{
2061 constraint(ALLOC_IN_RC(LR_regP));
2062 match(iRegP);
2063
2064 format %{ %}
2065 interface(REG_INTER);
2066 %}
2067
2068 operand R0RegI() %{
2069 constraint(ALLOC_IN_RC(R0_regI));
2070 match(iRegI);
2071
2072 format %{ %}
2073 interface(REG_INTER);
2074 %}
2075
2076 operand R1RegI() %{
2077 constraint(ALLOC_IN_RC(R1_regI));
2078 match(iRegI);
2079
2080 format %{ %}
2081 interface(REG_INTER);
2082 %}
2083
2084 operand R2RegI() %{
2085 constraint(ALLOC_IN_RC(R2_regI));
2086 match(iRegI);
2087
2088 format %{ %}
2089 interface(REG_INTER);
2090 %}
2091
2092 operand R3RegI() %{
2093 constraint(ALLOC_IN_RC(R3_regI));
2094 match(iRegI);
2095
2096 format %{ %}
2097 interface(REG_INTER);
2098 %}
2099
2100 operand R12RegI() %{
2101 constraint(ALLOC_IN_RC(R12_regI));
2102 match(iRegI);
2103
2104 format %{ %}
2105 interface(REG_INTER);
2106 %}
2107
2108 // Long Register
2109 operand iRegL() %{
2110 constraint(ALLOC_IN_RC(long_reg));
2111 match(RegL);
2112 match(R0R1RegL);
2113 match(R2R3RegL);
2114 //match(iRegLex);
2115
2116 format %{ %}
2117 interface(REG_INTER);
2118 %}
2119
2120 operand iRegLd() %{
2121 constraint(ALLOC_IN_RC(long_reg_align));
2122 match(iRegL); // FIXME: allows unaligned R11/R12?
2123
2124 format %{ %}
2125 interface(REG_INTER);
2126 %}
2127
2128 // first long arg, or return value
2129 operand R0R1RegL() %{
2130 constraint(ALLOC_IN_RC(R0R1_regL));
2131 match(iRegL);
2132
2133 format %{ %}
2134 interface(REG_INTER);
2135 %}
2136
2137 operand R2R3RegL() %{
2138 constraint(ALLOC_IN_RC(R2R3_regL));
2139 match(iRegL);
2140
2141 format %{ %}
2142 interface(REG_INTER);
2143 %}
2144
2145 // Condition Code Flag Register
2146 operand flagsReg() %{
2147 constraint(ALLOC_IN_RC(int_flags));
2148 match(RegFlags);
2149
2150 format %{ "apsr" %}
2151 interface(REG_INTER);
2152 %}
2153
2154 // Result of compare to 0 (TST)
2155 operand flagsReg_EQNELTGE() %{
2156 constraint(ALLOC_IN_RC(int_flags));
2157 match(RegFlags);
2158
2159 format %{ "apsr_EQNELTGE" %}
2160 interface(REG_INTER);
2161 %}
2162
2163 // Condition Code Register, unsigned comparisons.
2164 operand flagsRegU() %{
2165 constraint(ALLOC_IN_RC(int_flags));
2166 match(RegFlags);
2167 #ifdef TODO
2168 match(RegFlagsP);
2169 #endif
2170
2171 format %{ "apsr_U" %}
2172 interface(REG_INTER);
2173 %}
2174
2175 // Condition Code Register, pointer comparisons.
2176 operand flagsRegP() %{
2177 constraint(ALLOC_IN_RC(int_flags));
2178 match(RegFlags);
2179
2180 format %{ "apsr_P" %}
2181 interface(REG_INTER);
2182 %}
2183
2184 // Condition Code Register, long comparisons.
2185 operand flagsRegL_LTGE() %{
2186 constraint(ALLOC_IN_RC(int_flags));
2187 match(RegFlags);
2188
2189 format %{ "apsr_L_LTGE" %}
2190 interface(REG_INTER);
2191 %}
2192
2193 operand flagsRegL_EQNE() %{
2194 constraint(ALLOC_IN_RC(int_flags));
2195 match(RegFlags);
2196
2197 format %{ "apsr_L_EQNE" %}
2198 interface(REG_INTER);
2199 %}
2200
2201 operand flagsRegL_LEGT() %{
2202 constraint(ALLOC_IN_RC(int_flags));
2203 match(RegFlags);
2204
2205 format %{ "apsr_L_LEGT" %}
2206 interface(REG_INTER);
2207 %}
2208
2209 operand flagsRegUL_LTGE() %{
2210 constraint(ALLOC_IN_RC(int_flags));
2211 match(RegFlags);
2212
2213 format %{ "apsr_UL_LTGE" %}
2214 interface(REG_INTER);
2215 %}
2216
2217 operand flagsRegUL_EQNE() %{
2218 constraint(ALLOC_IN_RC(int_flags));
2219 match(RegFlags);
2220
2221 format %{ "apsr_UL_EQNE" %}
2222 interface(REG_INTER);
2223 %}
2224
2225 operand flagsRegUL_LEGT() %{
2226 constraint(ALLOC_IN_RC(int_flags));
2227 match(RegFlags);
2228
2229 format %{ "apsr_UL_LEGT" %}
2230 interface(REG_INTER);
2231 %}
2232
2233 // Condition Code Register, floating comparisons, unordered same as "less".
2234 operand flagsRegF() %{
2235 constraint(ALLOC_IN_RC(float_flags));
2236 match(RegFlags);
2237
2238 format %{ "fpscr_F" %}
2239 interface(REG_INTER);
2240 %}
2241
2242 // Vectors
2243 operand vecD() %{
2244 constraint(ALLOC_IN_RC(actual_dflt_reg));
2245 match(VecD);
2246
2247 format %{ %}
2248 interface(REG_INTER);
2249 %}
2250
2251 operand vecX() %{
2252 constraint(ALLOC_IN_RC(vectorx_reg));
2253 match(VecX);
2254
2255 format %{ %}
2256 interface(REG_INTER);
2257 %}
2258
2259 operand regD() %{
2260 constraint(ALLOC_IN_RC(actual_dflt_reg));
2261 match(RegD);
2262 match(regD_low);
2263
2264 format %{ %}
2265 interface(REG_INTER);
2266 %}
2267
2268 operand regF() %{
2269 constraint(ALLOC_IN_RC(sflt_reg));
2270 match(RegF);
2271
2272 format %{ %}
2273 interface(REG_INTER);
2274 %}
2275
2276 operand regD_low() %{
2277 constraint(ALLOC_IN_RC(dflt_low_reg));
2278 match(RegD);
2279
2280 format %{ %}
2281 interface(REG_INTER);
2282 %}
2283
2284 // Special Registers
2285
2286 // Method Register
2287 operand inline_cache_regP(iRegP reg) %{
2288 constraint(ALLOC_IN_RC(Ricklass_regP));
2289 match(reg);
2290 format %{ %}
2291 interface(REG_INTER);
2292 %}
2293
2294 //----------Complex Operands---------------------------------------------------
2295 // Indirect Memory Reference
2296 operand indirect(sp_ptr_RegP reg) %{
2297 constraint(ALLOC_IN_RC(sp_ptr_reg));
2298 match(reg);
2299
2300 op_cost(100);
2301 format %{ "[$reg]" %}
2302 interface(MEMORY_INTER) %{
2303 base($reg);
2304 index(0xf); // PC => no index
2305 scale(0x0);
2306 disp(0x0);
2307 %}
2308 %}
2309
2310
2311 // Indirect with Offset in ]-4096, 4096[
2312 operand indOffset12(sp_ptr_RegP reg, immI12 offset) %{
2313 constraint(ALLOC_IN_RC(sp_ptr_reg));
2314 match(AddP reg offset);
2315
2316 op_cost(100);
2317 format %{ "[$reg + $offset]" %}
2318 interface(MEMORY_INTER) %{
2319 base($reg);
2320 index(0xf); // PC => no index
2321 scale(0x0);
2322 disp($offset);
2323 %}
2324 %}
2325
2326 // Indirect with offset for float load/store
2327 operand indOffsetFP(sp_ptr_RegP reg, immIFP offset) %{
2328 constraint(ALLOC_IN_RC(sp_ptr_reg));
2329 match(AddP reg offset);
2330
2331 op_cost(100);
2332 format %{ "[$reg + $offset]" %}
2333 interface(MEMORY_INTER) %{
2334 base($reg);
2335 index(0xf); // PC => no index
2336 scale(0x0);
2337 disp($offset);
2338 %}
2339 %}
2340
2341 // Indirect with Offset for half and double words
2342 operand indOffsetHD(sp_ptr_RegP reg, immIHD offset) %{
2343 constraint(ALLOC_IN_RC(sp_ptr_reg));
2344 match(AddP reg offset);
2345
2346 op_cost(100);
2347 format %{ "[$reg + $offset]" %}
2348 interface(MEMORY_INTER) %{
2349 base($reg);
2350 index(0xf); // PC => no index
2351 scale(0x0);
2352 disp($offset);
2353 %}
2354 %}
2355
2356 // Indirect with Offset and Offset+4 in ]-1024, 1024[
2357 operand indOffsetFPx2(sp_ptr_RegP reg, immX10x2 offset) %{
2358 constraint(ALLOC_IN_RC(sp_ptr_reg));
2359 match(AddP reg offset);
2360
2361 op_cost(100);
2362 format %{ "[$reg + $offset]" %}
2363 interface(MEMORY_INTER) %{
2364 base($reg);
2365 index(0xf); // PC => no index
2366 scale(0x0);
2367 disp($offset);
2368 %}
2369 %}
2370
2371 // Indirect with Offset and Offset+4 in ]-4096, 4096[
2372 operand indOffset12x2(sp_ptr_RegP reg, immI12x2 offset) %{
2373 constraint(ALLOC_IN_RC(sp_ptr_reg));
2374 match(AddP reg offset);
2375
2376 op_cost(100);
2377 format %{ "[$reg + $offset]" %}
2378 interface(MEMORY_INTER) %{
2379 base($reg);
2380 index(0xf); // PC => no index
2381 scale(0x0);
2382 disp($offset);
2383 %}
2384 %}
2385
2386 // Indirect with Register Index
2387 operand indIndex(iRegP addr, iRegX index) %{
2388 constraint(ALLOC_IN_RC(ptr_reg));
2389 match(AddP addr index);
2390
2391 op_cost(100);
2392 format %{ "[$addr + $index]" %}
2393 interface(MEMORY_INTER) %{
2394 base($addr);
2395 index($index);
2396 scale(0x0);
2397 disp(0x0);
2398 %}
2399 %}
2400
2401 // Indirect Memory Times Scale Plus Index Register
2402 operand indIndexScale(iRegP addr, iRegX index, immU5 scale) %{
2403 constraint(ALLOC_IN_RC(ptr_reg));
2404 match(AddP addr (LShiftX index scale));
2405
2406 op_cost(100);
2407 format %{"[$addr + $index << $scale]" %}
2408 interface(MEMORY_INTER) %{
2409 base($addr);
2410 index($index);
2411 scale($scale);
2412 disp(0x0);
2413 %}
2414 %}
2415
2416 // Operands for expressing Control Flow
2417 // NOTE: Label is a predefined operand which should not be redefined in
2418 // the AD file. It is generically handled within the ADLC.
2419
2420 //----------Conditional Branch Operands----------------------------------------
2421 // Comparison Op - This is the operation of the comparison, and is limited to
2422 // the following set of codes:
2423 // L (<), LE (<=), G (>), GE (>=), E (==), NE (!=)
2424 //
2425 // Other attributes of the comparison, such as unsignedness, are specified
2426 // by the comparison instruction that sets a condition code flags register.
2427 // That result is represented by a flags operand whose subtype is appropriate
2428 // to the unsignedness (etc.) of the comparison.
2429 //
2430 // Later, the instruction which matches both the Comparison Op (a Bool) and
2431 // the flags (produced by the Cmp) specifies the coding of the comparison op
2432 // by matching a specific subtype of Bool operand below, such as cmpOpU.
2433
2434 operand cmpOp() %{
2435 match(Bool);
2436
2437 format %{ "" %}
2438 interface(COND_INTER) %{
2439 equal(0x0);
2440 not_equal(0x1);
2441 less(0xb);
2442 greater_equal(0xa);
2443 less_equal(0xd);
2444 greater(0xc);
2445 overflow(0x0); // unsupported/unimplemented
2446 no_overflow(0x0); // unsupported/unimplemented
2447 %}
2448 %}
2449
2450 // integer comparison with 0, signed
2451 operand cmpOp0() %{
2452 match(Bool);
2453
2454 format %{ "" %}
2455 interface(COND_INTER) %{
2456 equal(0x0);
2457 not_equal(0x1);
2458 less(0x4);
2459 greater_equal(0x5);
2460 less_equal(0xd); // unsupported
2461 greater(0xc); // unsupported
2462 overflow(0x0); // unsupported/unimplemented
2463 no_overflow(0x0); // unsupported/unimplemented
2464 %}
2465 %}
2466
2467 // Comparison Op, unsigned
2468 operand cmpOpU() %{
2469 match(Bool);
2470
2471 format %{ "u" %}
2472 interface(COND_INTER) %{
2473 equal(0x0);
2474 not_equal(0x1);
2475 less(0x3);
2476 greater_equal(0x2);
2477 less_equal(0x9);
2478 greater(0x8);
2479 overflow(0x0); // unsupported/unimplemented
2480 no_overflow(0x0); // unsupported/unimplemented
2481 %}
2482 %}
2483
2484 // Comparison Op, pointer (same as unsigned)
2485 operand cmpOpP() %{
2486 match(Bool);
2487
2488 format %{ "p" %}
2489 interface(COND_INTER) %{
2490 equal(0x0);
2491 not_equal(0x1);
2492 less(0x3);
2493 greater_equal(0x2);
2494 less_equal(0x9);
2495 greater(0x8);
2496 overflow(0x0); // unsupported/unimplemented
2497 no_overflow(0x0); // unsupported/unimplemented
2498 %}
2499 %}
2500
2501 operand cmpOpL() %{
2502 match(Bool);
2503
2504 format %{ "L" %}
2505 interface(COND_INTER) %{
2506 equal(0x0);
2507 not_equal(0x1);
2508 less(0xb);
2509 greater_equal(0xa);
2510 less_equal(0xd);
2511 greater(0xc);
2512 overflow(0x0); // unsupported/unimplemented
2513 no_overflow(0x0); // unsupported/unimplemented
2514 %}
2515 %}
2516
2517 operand cmpOpL_commute() %{
2518 match(Bool);
2519
2520 format %{ "L" %}
2521 interface(COND_INTER) %{
2522 equal(0x0);
2523 not_equal(0x1);
2524 less(0xc);
2525 greater_equal(0xd);
2526 less_equal(0xa);
2527 greater(0xb);
2528 overflow(0x0); // unsupported/unimplemented
2529 no_overflow(0x0); // unsupported/unimplemented
2530 %}
2531 %}
2532
2533 operand cmpOpUL() %{
2534 match(Bool);
2535
2536 format %{ "UL" %}
2537 interface(COND_INTER) %{
2538 equal(0x0);
2539 not_equal(0x1);
2540 less(0x3);
2541 greater_equal(0x2);
2542 less_equal(0x9);
2543 greater(0x8);
2544 overflow(0x0); // unsupported/unimplemented
2545 no_overflow(0x0); // unsupported/unimplemented
2546 %}
2547 %}
2548
2549 operand cmpOpUL_commute() %{
2550 match(Bool);
2551
2552 format %{ "UL" %}
2553 interface(COND_INTER) %{
2554 equal(0x0);
2555 not_equal(0x1);
2556 less(0x8);
2557 greater_equal(0x9);
2558 less_equal(0x2);
2559 greater(0x3);
2560 overflow(0x0); // unsupported/unimplemented
2561 no_overflow(0x0); // unsupported/unimplemented
2562 %}
2563 %}
2564
2565
2566 //----------OPERAND CLASSES----------------------------------------------------
2567 // Operand Classes are groups of operands that are used to simplify
2568 // instruction definitions by not requiring the AD writer to specify separate
2569 // instructions for every form of operand when the instruction accepts
2570 // multiple operand types with the same basic encoding and format. The classic
2571 // case of this is memory operands.
2572
2573 opclass memoryI ( indirect, indOffset12, indIndex, indIndexScale );
2574 opclass memoryP ( indirect, indOffset12, indIndex, indIndexScale );
2575 opclass memoryF ( indirect, indOffsetFP );
2576 opclass memoryF2 ( indirect, indOffsetFPx2 );
2577 opclass memoryD ( indirect, indOffsetFP );
2578 opclass memoryfp( indirect, indOffsetFP );
2579 opclass memoryB ( indirect, indIndex, indOffsetHD );
2580 opclass memoryS ( indirect, indIndex, indOffsetHD );
2581 opclass memoryL ( indirect, indIndex, indOffsetHD );
2582
2583 opclass memoryScaledI(indIndexScale);
2584 opclass memoryScaledP(indIndexScale);
2585
2586 // when ldrex/strex is used:
2587 opclass memoryex ( indirect );
2588 opclass indIndexMemory( indIndex );
2589 opclass memorylong ( indirect, indOffset12x2 );
2590 opclass memoryvld ( indirect /* , write back mode not implemented */ );
2591
2592 //----------PIPELINE-----------------------------------------------------------
2593 pipeline %{
2594
2595 //----------ATTRIBUTES---------------------------------------------------------
2596 attributes %{
2597 fixed_size_instructions; // Fixed size instructions
2598 max_instructions_per_bundle = 4; // Up to 4 instructions per bundle
2599 instruction_unit_size = 4; // An instruction is 4 bytes long
2600 instruction_fetch_unit_size = 16; // The processor fetches one line
2601 instruction_fetch_units = 1; // of 16 bytes
2602 %}
2603
2604 //----------RESOURCES----------------------------------------------------------
2605 // Resources are the functional units available to the machine
2606 resources(A0, A1, MS, BR, FA, FM, IDIV, FDIV, IALU = A0 | A1);
2607
2608 //----------PIPELINE DESCRIPTION-----------------------------------------------
2609 // Pipeline Description specifies the stages in the machine's pipeline
2610
2611 pipe_desc(A, P, F, B, I, J, S, R, E, C, M, W, X, T, D);
2612
2613 //----------PIPELINE CLASSES---------------------------------------------------
2614 // Pipeline Classes describe the stages in which input and output are
2615 // referenced by the hardware pipeline.
2616
2617 // Integer ALU reg-reg operation
2618 pipe_class ialu_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{
2619 single_instruction;
2620 dst : E(write);
2621 src1 : R(read);
2622 src2 : R(read);
2623 IALU : R;
2624 %}
2625
2626 // Integer ALU reg-reg long operation
2627 pipe_class ialu_reg_reg_2(iRegL dst, iRegL src1, iRegL src2) %{
2628 instruction_count(2);
2629 dst : E(write);
2630 src1 : R(read);
2631 src2 : R(read);
2632 IALU : R;
2633 IALU : R;
2634 %}
2635
2636 // Integer ALU reg-reg long dependent operation
2637 pipe_class ialu_reg_reg_2_dep(iRegL dst, iRegL src1, iRegL src2, flagsReg cr) %{
2638 instruction_count(1); multiple_bundles;
2639 dst : E(write);
2640 src1 : R(read);
2641 src2 : R(read);
2642 cr : E(write);
2643 IALU : R(2);
2644 %}
2645
2646 // Integer ALU reg-imm operation
2647 pipe_class ialu_reg_imm(iRegI dst, iRegI src1) %{
2648 single_instruction;
2649 dst : E(write);
2650 src1 : R(read);
2651 IALU : R;
2652 %}
2653
2654 // Integer ALU reg-reg operation with condition code
2655 pipe_class ialu_cc_reg_reg(iRegI dst, iRegI src1, iRegI src2, flagsReg cr) %{
2656 single_instruction;
2657 dst : E(write);
2658 cr : E(write);
2659 src1 : R(read);
2660 src2 : R(read);
2661 IALU : R;
2662 %}
2663
2664 // Integer ALU zero-reg operation
2665 pipe_class ialu_zero_reg(iRegI dst, immI0 zero, iRegI src2) %{
2666 single_instruction;
2667 dst : E(write);
2668 src2 : R(read);
2669 IALU : R;
2670 %}
2671
2672 // Integer ALU zero-reg operation with condition code only
2673 pipe_class ialu_cconly_zero_reg(flagsReg cr, iRegI src) %{
2674 single_instruction;
2675 cr : E(write);
2676 src : R(read);
2677 IALU : R;
2678 %}
2679
2680 // Integer ALU reg-reg operation with condition code only
2681 pipe_class ialu_cconly_reg_reg(flagsReg cr, iRegI src1, iRegI src2) %{
2682 single_instruction;
2683 cr : E(write);
2684 src1 : R(read);
2685 src2 : R(read);
2686 IALU : R;
2687 %}
2688
2689 // Integer ALU reg-imm operation with condition code only
2690 pipe_class ialu_cconly_reg_imm(flagsReg cr, iRegI src1) %{
2691 single_instruction;
2692 cr : E(write);
2693 src1 : R(read);
2694 IALU : R;
2695 %}
2696
2697 // Integer ALU reg-reg-zero operation with condition code only
2698 pipe_class ialu_cconly_reg_reg_zero(flagsReg cr, iRegI src1, iRegI src2, immI0 zero) %{
2699 single_instruction;
2700 cr : E(write);
2701 src1 : R(read);
2702 src2 : R(read);
2703 IALU : R;
2704 %}
2705
2706 // Integer ALU reg-imm-zero operation with condition code only
2707 pipe_class ialu_cconly_reg_imm_zero(flagsReg cr, iRegI src1, immI0 zero) %{
2708 single_instruction;
2709 cr : E(write);
2710 src1 : R(read);
2711 IALU : R;
2712 %}
2713
2714 // Integer ALU reg-reg operation with condition code, src1 modified
2715 pipe_class ialu_cc_rwreg_reg(flagsReg cr, iRegI src1, iRegI src2) %{
2716 single_instruction;
2717 cr : E(write);
2718 src1 : E(write);
2719 src1 : R(read);
2720 src2 : R(read);
2721 IALU : R;
2722 %}
2723
2724 pipe_class cmpL_reg(iRegI dst, iRegL src1, iRegL src2, flagsReg cr ) %{
2725 multiple_bundles;
2726 dst : E(write)+4;
2727 cr : E(write);
2728 src1 : R(read);
2729 src2 : R(read);
2730 IALU : R(3);
2731 BR : R(2);
2732 %}
2733
2734 // Integer ALU operation
2735 pipe_class ialu_none(iRegI dst) %{
2736 single_instruction;
2737 dst : E(write);
2738 IALU : R;
2739 %}
2740
2741 // Integer ALU reg operation
2742 pipe_class ialu_reg(iRegI dst, iRegI src) %{
2743 single_instruction; may_have_no_code;
2744 dst : E(write);
2745 src : R(read);
2746 IALU : R;
2747 %}
2748
2749 // Integer ALU reg conditional operation
2750 // This instruction has a 1 cycle stall, and cannot execute
2751 // in the same cycle as the instruction setting the condition
2752 // code. We kludge this by pretending to read the condition code
2753 // 1 cycle earlier, and by marking the functional units as busy
2754 // for 2 cycles with the result available 1 cycle later than
2755 // is really the case.
2756 pipe_class ialu_reg_flags( iRegI op2_out, iRegI op2_in, iRegI op1, flagsReg cr ) %{
2757 single_instruction;
2758 op2_out : C(write);
2759 op1 : R(read);
2760 cr : R(read); // This is really E, with a 1 cycle stall
2761 BR : R(2);
2762 MS : R(2);
2763 %}
2764
2765 // Integer ALU reg operation
2766 pipe_class ialu_move_reg_L_to_I(iRegI dst, iRegL src) %{
2767 single_instruction; may_have_no_code;
2768 dst : E(write);
2769 src : R(read);
2770 IALU : R;
2771 %}
2772 pipe_class ialu_move_reg_I_to_L(iRegL dst, iRegI src) %{
2773 single_instruction; may_have_no_code;
2774 dst : E(write);
2775 src : R(read);
2776 IALU : R;
2777 %}
2778
2779 // Two integer ALU reg operations
2780 pipe_class ialu_reg_2(iRegL dst, iRegL src) %{
2781 instruction_count(2);
2782 dst : E(write);
2783 src : R(read);
2784 A0 : R;
2785 A1 : R;
2786 %}
2787
2788 // Two integer ALU reg operations
2789 pipe_class ialu_move_reg_L_to_L(iRegL dst, iRegL src) %{
2790 instruction_count(2); may_have_no_code;
2791 dst : E(write);
2792 src : R(read);
2793 A0 : R;
2794 A1 : R;
2795 %}
2796
2797 // Integer ALU imm operation
2798 pipe_class ialu_imm(iRegI dst) %{
2799 single_instruction;
2800 dst : E(write);
2801 IALU : R;
2802 %}
2803
2804 pipe_class ialu_imm_n(iRegI dst) %{
2805 single_instruction;
2806 dst : E(write);
2807 IALU : R;
2808 %}
2809
2810 // Integer ALU reg-reg with carry operation
2811 pipe_class ialu_reg_reg_cy(iRegI dst, iRegI src1, iRegI src2, iRegI cy) %{
2812 single_instruction;
2813 dst : E(write);
2814 src1 : R(read);
2815 src2 : R(read);
2816 IALU : R;
2817 %}
2818
2819 // Integer ALU cc operation
2820 pipe_class ialu_cc(iRegI dst, flagsReg cc) %{
2821 single_instruction;
2822 dst : E(write);
2823 cc : R(read);
2824 IALU : R;
2825 %}
2826
2827 // Integer ALU cc / second IALU operation
2828 pipe_class ialu_reg_ialu( iRegI dst, iRegI src ) %{
2829 instruction_count(1); multiple_bundles;
2830 dst : E(write)+1;
2831 src : R(read);
2832 IALU : R;
2833 %}
2834
2835 // Integer ALU cc / second IALU operation
2836 pipe_class ialu_reg_reg_ialu( iRegI dst, iRegI p, iRegI q ) %{
2837 instruction_count(1); multiple_bundles;
2838 dst : E(write)+1;
2839 p : R(read);
2840 q : R(read);
2841 IALU : R;
2842 %}
2843
2844 // Integer ALU hi-lo-reg operation
2845 pipe_class ialu_hi_lo_reg(iRegI dst, immI src) %{
2846 instruction_count(1); multiple_bundles;
2847 dst : E(write)+1;
2848 IALU : R(2);
2849 %}
2850
2851 // Long Constant
2852 pipe_class loadConL( iRegL dst, immL src ) %{
2853 instruction_count(2); multiple_bundles;
2854 dst : E(write)+1;
2855 IALU : R(2);
2856 IALU : R(2);
2857 %}
2858
2859 // Pointer Constant
2860 pipe_class loadConP( iRegP dst, immP src ) %{
2861 instruction_count(0); multiple_bundles;
2862 fixed_latency(6);
2863 %}
2864
2865 // Long Constant small
2866 pipe_class loadConLlo( iRegL dst, immL src ) %{
2867 instruction_count(2);
2868 dst : E(write);
2869 IALU : R;
2870 IALU : R;
2871 %}
2872
2873 // [PHH] This is wrong for 64-bit. See LdImmF/D.
2874 pipe_class loadConFD(regF dst, immF src, iRegP tmp) %{
2875 instruction_count(1); multiple_bundles;
2876 src : R(read);
2877 dst : M(write)+1;
2878 IALU : R;
2879 MS : E;
2880 %}
2881
2882 // Integer ALU nop operation
2883 pipe_class ialu_nop() %{
2884 single_instruction;
2885 IALU : R;
2886 %}
2887
2888 // Integer ALU nop operation
2889 pipe_class ialu_nop_A0() %{
2890 single_instruction;
2891 A0 : R;
2892 %}
2893
2894 // Integer ALU nop operation
2895 pipe_class ialu_nop_A1() %{
2896 single_instruction;
2897 A1 : R;
2898 %}
2899
2900 // Integer Multiply reg-reg operation
2901 pipe_class imul_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{
2902 single_instruction;
2903 dst : E(write);
2904 src1 : R(read);
2905 src2 : R(read);
2906 MS : R(5);
2907 %}
2908
2909 pipe_class mulL_reg_reg(iRegL dst, iRegL src1, iRegL src2) %{
2910 single_instruction;
2911 dst : E(write)+4;
2912 src1 : R(read);
2913 src2 : R(read);
2914 MS : R(6);
2915 %}
2916
2917 // Integer Divide reg-reg
2918 pipe_class sdiv_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI temp, flagsReg cr) %{
2919 instruction_count(1); multiple_bundles;
2920 dst : E(write);
2921 temp : E(write);
2922 src1 : R(read);
2923 src2 : R(read);
2924 temp : R(read);
2925 MS : R(38);
2926 %}
2927
2928 // Long Divide
2929 pipe_class divL_reg_reg(iRegL dst, iRegL src1, iRegL src2) %{
2930 dst : E(write)+71;
2931 src1 : R(read);
2932 src2 : R(read)+1;
2933 MS : R(70);
2934 %}
2935
2936 // Floating Point Add Float
2937 pipe_class faddF_reg_reg(regF dst, regF src1, regF src2) %{
2938 single_instruction;
2939 dst : X(write);
2940 src1 : E(read);
2941 src2 : E(read);
2942 FA : R;
2943 %}
2944
2945 // Floating Point Add Double
2946 pipe_class faddD_reg_reg(regD dst, regD src1, regD src2) %{
2947 single_instruction;
2948 dst : X(write);
2949 src1 : E(read);
2950 src2 : E(read);
2951 FA : R;
2952 %}
2953
2954 // Floating Point Conditional Move based on integer flags
2955 pipe_class int_conditional_float_move (cmpOp cmp, flagsReg cr, regF dst, regF src) %{
2956 single_instruction;
2957 dst : X(write);
2958 src : E(read);
2959 cr : R(read);
2960 FA : R(2);
2961 BR : R(2);
2962 %}
2963
2964 // Floating Point Conditional Move based on integer flags
2965 pipe_class int_conditional_double_move (cmpOp cmp, flagsReg cr, regD dst, regD src) %{
2966 single_instruction;
2967 dst : X(write);
2968 src : E(read);
2969 cr : R(read);
2970 FA : R(2);
2971 BR : R(2);
2972 %}
2973
2974 // Floating Point Multiply Float
2975 pipe_class fmulF_reg_reg(regF dst, regF src1, regF src2) %{
2976 single_instruction;
2977 dst : X(write);
2978 src1 : E(read);
2979 src2 : E(read);
2980 FM : R;
2981 %}
2982
2983 // Floating Point Multiply Double
2984 pipe_class fmulD_reg_reg(regD dst, regD src1, regD src2) %{
2985 single_instruction;
2986 dst : X(write);
2987 src1 : E(read);
2988 src2 : E(read);
2989 FM : R;
2990 %}
2991
2992 // Floating Point Divide Float
2993 pipe_class fdivF_reg_reg(regF dst, regF src1, regF src2) %{
2994 single_instruction;
2995 dst : X(write);
2996 src1 : E(read);
2997 src2 : E(read);
2998 FM : R;
2999 FDIV : C(14);
3000 %}
3001
3002 // Floating Point Divide Double
3003 pipe_class fdivD_reg_reg(regD dst, regD src1, regD src2) %{
3004 single_instruction;
3005 dst : X(write);
3006 src1 : E(read);
3007 src2 : E(read);
3008 FM : R;
3009 FDIV : C(17);
3010 %}
3011
3012 // Floating Point Move/Negate/Abs Float
3013 pipe_class faddF_reg(regF dst, regF src) %{
3014 single_instruction;
3015 dst : W(write);
3016 src : E(read);
3017 FA : R(1);
3018 %}
3019
3020 // Floating Point Move/Negate/Abs Double
3021 pipe_class faddD_reg(regD dst, regD src) %{
3022 single_instruction;
3023 dst : W(write);
3024 src : E(read);
3025 FA : R;
3026 %}
3027
3028 // Floating Point Convert F->D
3029 pipe_class fcvtF2D(regD dst, regF src) %{
3030 single_instruction;
3031 dst : X(write);
3032 src : E(read);
3033 FA : R;
3034 %}
3035
3036 // Floating Point Convert I->D
3037 pipe_class fcvtI2D(regD dst, regF src) %{
3038 single_instruction;
3039 dst : X(write);
3040 src : E(read);
3041 FA : R;
3042 %}
3043
3044 // Floating Point Convert LHi->D
3045 pipe_class fcvtLHi2D(regD dst, regD src) %{
3046 single_instruction;
3047 dst : X(write);
3048 src : E(read);
3049 FA : R;
3050 %}
3051
3052 // Floating Point Convert L->D
3053 pipe_class fcvtL2D(regD dst, iRegL src) %{
3054 single_instruction;
3055 dst : X(write);
3056 src : E(read);
3057 FA : R;
3058 %}
3059
3060 // Floating Point Convert L->F
3061 pipe_class fcvtL2F(regF dst, iRegL src) %{
3062 single_instruction;
3063 dst : X(write);
3064 src : E(read);
3065 FA : R;
3066 %}
3067
3068 // Floating Point Convert D->F
3069 pipe_class fcvtD2F(regD dst, regF src) %{
3070 single_instruction;
3071 dst : X(write);
3072 src : E(read);
3073 FA : R;
3074 %}
3075
3076 // Floating Point Convert I->L
3077 pipe_class fcvtI2L(regD dst, regF src) %{
3078 single_instruction;
3079 dst : X(write);
3080 src : E(read);
3081 FA : R;
3082 %}
3083
3084 // Floating Point Convert D->F
3085 pipe_class fcvtD2I(iRegI dst, regD src, flagsReg cr) %{
3086 instruction_count(1); multiple_bundles;
3087 dst : X(write)+6;
3088 src : E(read);
3089 FA : R;
3090 %}
3091
3092 // Floating Point Convert D->L
3093 pipe_class fcvtD2L(regD dst, regD src, flagsReg cr) %{
3094 instruction_count(1); multiple_bundles;
3095 dst : X(write)+6;
3096 src : E(read);
3097 FA : R;
3098 %}
3099
3100 // Floating Point Convert F->I
3101 pipe_class fcvtF2I(regF dst, regF src, flagsReg cr) %{
3102 instruction_count(1); multiple_bundles;
3103 dst : X(write)+6;
3104 src : E(read);
3105 FA : R;
3106 %}
3107
3108 // Floating Point Convert F->L
3109 pipe_class fcvtF2L(regD dst, regF src, flagsReg cr) %{
3110 instruction_count(1); multiple_bundles;
3111 dst : X(write)+6;
3112 src : E(read);
3113 FA : R;
3114 %}
3115
3116 // Floating Point Convert I->F
3117 pipe_class fcvtI2F(regF dst, regF src) %{
3118 single_instruction;
3119 dst : X(write);
3120 src : E(read);
3121 FA : R;
3122 %}
3123
3124 // Floating Point Compare
3125 pipe_class faddF_fcc_reg_reg_zero(flagsRegF cr, regF src1, regF src2, immI0 zero) %{
3126 single_instruction;
3127 cr : X(write);
3128 src1 : E(read);
3129 src2 : E(read);
3130 FA : R;
3131 %}
3132
3133 // Floating Point Compare
3134 pipe_class faddD_fcc_reg_reg_zero(flagsRegF cr, regD src1, regD src2, immI0 zero) %{
3135 single_instruction;
3136 cr : X(write);
3137 src1 : E(read);
3138 src2 : E(read);
3139 FA : R;
3140 %}
3141
3142 // Floating Add Nop
3143 pipe_class fadd_nop() %{
3144 single_instruction;
3145 FA : R;
3146 %}
3147
3148 // Integer Store to Memory
3149 pipe_class istore_mem_reg(memoryI mem, iRegI src) %{
3150 single_instruction;
3151 mem : R(read);
3152 src : C(read);
3153 MS : R;
3154 %}
3155
3156 // Integer Store to Memory
3157 pipe_class istore_mem_spORreg(memoryI mem, sp_ptr_RegP src) %{
3158 single_instruction;
3159 mem : R(read);
3160 src : C(read);
3161 MS : R;
3162 %}
3163
3164 // Float Store
3165 pipe_class fstoreF_mem_reg(memoryF mem, RegF src) %{
3166 single_instruction;
3167 mem : R(read);
3168 src : C(read);
3169 MS : R;
3170 %}
3171
3172 // Float Store
3173 pipe_class fstoreF_mem_zero(memoryF mem, immF0 src) %{
3174 single_instruction;
3175 mem : R(read);
3176 MS : R;
3177 %}
3178
3179 // Double Store
3180 pipe_class fstoreD_mem_reg(memoryD mem, RegD src) %{
3181 instruction_count(1);
3182 mem : R(read);
3183 src : C(read);
3184 MS : R;
3185 %}
3186
3187 // Double Store
3188 pipe_class fstoreD_mem_zero(memoryD mem, immD0 src) %{
3189 single_instruction;
3190 mem : R(read);
3191 MS : R;
3192 %}
3193
3194 // Integer Load (when sign bit propagation not needed)
3195 pipe_class iload_mem(iRegI dst, memoryI mem) %{
3196 single_instruction;
3197 mem : R(read);
3198 dst : C(write);
3199 MS : R;
3200 %}
3201
3202 // Integer Load (when sign bit propagation or masking is needed)
3203 pipe_class iload_mask_mem(iRegI dst, memoryI mem) %{
3204 single_instruction;
3205 mem : R(read);
3206 dst : M(write);
3207 MS : R;
3208 %}
3209
3210 // Float Load
3211 pipe_class floadF_mem(regF dst, memoryF mem) %{
3212 single_instruction;
3213 mem : R(read);
3214 dst : M(write);
3215 MS : R;
3216 %}
3217
3218 // Float Load
3219 pipe_class floadD_mem(regD dst, memoryD mem) %{
3220 instruction_count(1); multiple_bundles; // Again, unaligned argument is only multiple case
3221 mem : R(read);
3222 dst : M(write);
3223 MS : R;
3224 %}
3225
3226 // Memory Nop
3227 pipe_class mem_nop() %{
3228 single_instruction;
3229 MS : R;
3230 %}
3231
3232 pipe_class sethi(iRegP dst, immI src) %{
3233 single_instruction;
3234 dst : E(write);
3235 IALU : R;
3236 %}
3237
3238 pipe_class loadPollP(iRegP poll) %{
3239 single_instruction;
3240 poll : R(read);
3241 MS : R;
3242 %}
3243
3244 pipe_class br(Universe br, label labl) %{
3245 single_instruction;
3246 BR : R;
3247 %}
3248
3249 pipe_class br_cc(Universe br, cmpOp cmp, flagsReg cr, label labl) %{
3250 single_instruction;
3251 cr : E(read);
3252 BR : R;
3253 %}
3254
3255 pipe_class br_reg(Universe br, cmpOp cmp, iRegI op1, label labl) %{
3256 single_instruction;
3257 op1 : E(read);
3258 BR : R;
3259 MS : R;
3260 %}
3261
3262 pipe_class br_nop() %{
3263 single_instruction;
3264 BR : R;
3265 %}
3266
3267 pipe_class simple_call(method meth) %{
3268 instruction_count(2); multiple_bundles; force_serialization;
3269 fixed_latency(100);
3270 BR : R(1);
3271 MS : R(1);
3272 A0 : R(1);
3273 %}
3274
3275 pipe_class compiled_call(method meth) %{
3276 instruction_count(1); multiple_bundles; force_serialization;
3277 fixed_latency(100);
3278 MS : R(1);
3279 %}
3280
3281 pipe_class call(method meth) %{
3282 instruction_count(0); multiple_bundles; force_serialization;
3283 fixed_latency(100);
3284 %}
3285
3286 pipe_class tail_call(Universe ignore, label labl) %{
3287 single_instruction;
3288 fixed_latency(100);
3289 BR : R(1);
3290 MS : R(1);
3291 %}
3292
3293 pipe_class ret(Universe ignore) %{
3294 single_instruction;
3295 BR : R(1);
3296 MS : R(1);
3297 %}
3298
3299 // The real do-nothing guy
3300 pipe_class empty( ) %{
3301 instruction_count(0);
3302 %}
3303
3304 pipe_class long_memory_op() %{
3305 instruction_count(0); multiple_bundles; force_serialization;
3306 fixed_latency(25);
3307 MS : R(1);
3308 %}
3309
3310 // Check-cast
3311 pipe_class partial_subtype_check_pipe(Universe ignore, iRegP array, iRegP match ) %{
3312 array : R(read);
3313 match : R(read);
3314 IALU : R(2);
3315 BR : R(2);
3316 MS : R;
3317 %}
3318
3319 // Convert FPU flags into +1,0,-1
3320 pipe_class floating_cmp( iRegI dst, regF src1, regF src2 ) %{
3321 src1 : E(read);
3322 src2 : E(read);
3323 dst : E(write);
3324 FA : R;
3325 MS : R(2);
3326 BR : R(2);
3327 %}
3328
3329 // Compare for p < q, and conditionally add y
3330 pipe_class cadd_cmpltmask( iRegI p, iRegI q, iRegI y ) %{
3331 p : E(read);
3332 q : E(read);
3333 y : E(read);
3334 IALU : R(3)
3335 %}
3336
3337 // Define the class for the Nop node
3338 define %{
3339 MachNop = ialu_nop;
3340 %}
3341
3342 %}
3343
3344 //----------INSTRUCTIONS-------------------------------------------------------
3345
3346 //------------Special Nop instructions for bundling - no match rules-----------
3347 // Nop using the A0 functional unit
3348 instruct Nop_A0() %{
3349 ins_pipe(ialu_nop_A0);
3350 %}
3351
3352 // Nop using the A1 functional unit
3353 instruct Nop_A1( ) %{
3354 ins_pipe(ialu_nop_A1);
3355 %}
3356
3357 // Nop using the memory functional unit
3358 instruct Nop_MS( ) %{
3359 ins_pipe(mem_nop);
3360 %}
3361
3362 // Nop using the floating add functional unit
3363 instruct Nop_FA( ) %{
3364 ins_pipe(fadd_nop);
3365 %}
3366
3367 // Nop using the branch functional unit
3368 instruct Nop_BR( ) %{
3369 ins_pipe(br_nop);
3370 %}
3371
3372 //----------Load/Store/Move Instructions---------------------------------------
3373 //----------Load Instructions--------------------------------------------------
3374 // Load Byte (8bit signed)
3375 instruct loadB(iRegI dst, memoryB mem) %{
3376 match(Set dst (LoadB mem));
3377 ins_cost(MEMORY_REF_COST);
3378
3379 size(4);
3380 format %{ "LDRSB $dst,$mem\t! byte -> int" %}
3381 ins_encode %{
3382 __ ldrsb($dst$$Register, $mem$$Address);
3383 %}
3384 ins_pipe(iload_mask_mem);
3385 %}
3386
3387 // Load Byte (8bit signed) into a Long Register
3388 instruct loadB2L(iRegL dst, memoryB mem) %{
3389 match(Set dst (ConvI2L (LoadB mem)));
3390 ins_cost(MEMORY_REF_COST);
3391
3392 size(8);
3393 format %{ "LDRSB $dst.lo,$mem\t! byte -> long\n\t"
3394 "ASR $dst.hi,$dst.lo,31" %}
3395 ins_encode %{
3396 __ ldrsb($dst$$Register, $mem$$Address);
3397 __ mov($dst$$Register->successor(), AsmOperand($dst$$Register, asr, 31));
3398 %}
3399 ins_pipe(iload_mask_mem);
3400 %}
3401
3402 // Load Unsigned Byte (8bit UNsigned) into an int reg
3403 instruct loadUB(iRegI dst, memoryB mem) %{
3404 match(Set dst (LoadUB mem));
3405 ins_cost(MEMORY_REF_COST);
3406
3407 size(4);
3408 format %{ "LDRB $dst,$mem\t! ubyte -> int" %}
3409 ins_encode %{
3410 __ ldrb($dst$$Register, $mem$$Address);
3411 %}
3412 ins_pipe(iload_mem);
3413 %}
3414
3415 // Load Unsigned Byte (8bit UNsigned) into a Long Register
3416 instruct loadUB2L(iRegL dst, memoryB mem) %{
3417 match(Set dst (ConvI2L (LoadUB mem)));
3418 ins_cost(MEMORY_REF_COST);
3419
3420 size(8);
3421 format %{ "LDRB $dst.lo,$mem\t! ubyte -> long\n\t"
3422 "MOV $dst.hi,0" %}
3423 ins_encode %{
3424 __ ldrb($dst$$Register, $mem$$Address);
3425 __ mov($dst$$Register->successor(), 0);
3426 %}
3427 ins_pipe(iload_mem);
3428 %}
3429
3430 // Load Unsigned Byte (8 bit UNsigned) with immediate mask into Long Register
3431 instruct loadUB2L_limmI(iRegL dst, memoryB mem, limmIlow8 mask) %{
3432 match(Set dst (ConvI2L (AndI (LoadUB mem) mask)));
3433
3434 ins_cost(MEMORY_REF_COST + 2*DEFAULT_COST);
3435 size(12);
3436 format %{ "LDRB $dst.lo,$mem\t! ubyte -> long\n\t"
3437 "MOV $dst.hi,0\n\t"
3438 "AND $dst.lo,$dst.lo,$mask" %}
3439 ins_encode %{
3440 __ ldrb($dst$$Register, $mem$$Address);
3441 __ mov($dst$$Register->successor(), 0);
3442 __ andr($dst$$Register, $dst$$Register, limmI_low($mask$$constant, 8));
3443 %}
3444 ins_pipe(iload_mem);
3445 %}
3446
3447 // Load Short (16bit signed)
3448
3449 instruct loadS(iRegI dst, memoryS mem) %{
3450 match(Set dst (LoadS mem));
3451 ins_cost(MEMORY_REF_COST);
3452
3453 size(4);
3454 format %{ "LDRSH $dst,$mem\t! short" %}
3455 ins_encode %{
3456 __ ldrsh($dst$$Register, $mem$$Address);
3457 %}
3458 ins_pipe(iload_mask_mem);
3459 %}
3460
3461 // Load Short (16 bit signed) to Byte (8 bit signed)
3462 instruct loadS2B(iRegI dst, memoryS mem, immI_24 twentyfour) %{
3463 match(Set dst (RShiftI (LShiftI (LoadS mem) twentyfour) twentyfour));
3464 ins_cost(MEMORY_REF_COST);
3465
3466 size(4);
3467
3468 format %{ "LDRSB $dst,$mem\t! short -> byte" %}
3469 ins_encode %{
3470 __ ldrsb($dst$$Register, $mem$$Address);
3471 %}
3472 ins_pipe(iload_mask_mem);
3473 %}
3474
3475 // Load Short (16bit signed) into a Long Register
3476 instruct loadS2L(iRegL dst, memoryS mem) %{
3477 match(Set dst (ConvI2L (LoadS mem)));
3478 ins_cost(MEMORY_REF_COST);
3479
3480 size(8);
3481 format %{ "LDRSH $dst.lo,$mem\t! short -> long\n\t"
3482 "ASR $dst.hi,$dst.lo,31" %}
3483 ins_encode %{
3484 __ ldrsh($dst$$Register, $mem$$Address);
3485 __ mov($dst$$Register->successor(), AsmOperand($dst$$Register, asr, 31));
3486 %}
3487 ins_pipe(iload_mask_mem);
3488 %}
3489
3490 // Load Unsigned Short/Char (16bit UNsigned)
3491
3492
3493 instruct loadUS(iRegI dst, memoryS mem) %{
3494 match(Set dst (LoadUS mem));
3495 ins_cost(MEMORY_REF_COST);
3496
3497 size(4);
3498 format %{ "LDRH $dst,$mem\t! ushort/char" %}
3499 ins_encode %{
3500 __ ldrh($dst$$Register, $mem$$Address);
3501 %}
3502 ins_pipe(iload_mem);
3503 %}
3504
3505 // Load Unsigned Short/Char (16 bit UNsigned) to Byte (8 bit signed)
3506 instruct loadUS2B(iRegI dst, memoryB mem, immI_24 twentyfour) %{
3507 match(Set dst (RShiftI (LShiftI (LoadUS mem) twentyfour) twentyfour));
3508 ins_cost(MEMORY_REF_COST);
3509
3510 size(4);
3511 format %{ "LDRSB $dst,$mem\t! ushort -> byte" %}
3512 ins_encode %{
3513 __ ldrsb($dst$$Register, $mem$$Address);
3514 %}
3515 ins_pipe(iload_mask_mem);
3516 %}
3517
3518 // Load Unsigned Short/Char (16bit UNsigned) into a Long Register
3519 instruct loadUS2L(iRegL dst, memoryS mem) %{
3520 match(Set dst (ConvI2L (LoadUS mem)));
3521 ins_cost(MEMORY_REF_COST);
3522
3523 size(8);
3524 format %{ "LDRH $dst.lo,$mem\t! short -> long\n\t"
3525 "MOV $dst.hi, 0" %}
3526 ins_encode %{
3527 __ ldrh($dst$$Register, $mem$$Address);
3528 __ mov($dst$$Register->successor(), 0);
3529 %}
3530 ins_pipe(iload_mem);
3531 %}
3532
3533 // Load Unsigned Short/Char (16bit UNsigned) with mask 0xFF into a Long Register
3534 instruct loadUS2L_immI_255(iRegL dst, memoryB mem, immI_255 mask) %{
3535 match(Set dst (ConvI2L (AndI (LoadUS mem) mask)));
3536 ins_cost(MEMORY_REF_COST);
3537
3538 size(8);
3539 format %{ "LDRB $dst.lo,$mem\t! \n\t"
3540 "MOV $dst.hi, 0" %}
3541 ins_encode %{
3542 __ ldrb($dst$$Register, $mem$$Address);
3543 __ mov($dst$$Register->successor(), 0);
3544 %}
3545 ins_pipe(iload_mem);
3546 %}
3547
3548 // Load Unsigned Short/Char (16bit UNsigned) with a immediate mask into a Long Register
3549 instruct loadUS2L_limmI(iRegL dst, memoryS mem, limmI mask) %{
3550 match(Set dst (ConvI2L (AndI (LoadUS mem) mask)));
3551 ins_cost(MEMORY_REF_COST + 2*DEFAULT_COST);
3552
3553 size(12);
3554 format %{ "LDRH $dst,$mem\t! ushort/char & mask -> long\n\t"
3555 "MOV $dst.hi, 0\n\t"
3556 "AND $dst,$dst,$mask" %}
3557 ins_encode %{
3558 __ ldrh($dst$$Register, $mem$$Address);
3559 __ mov($dst$$Register->successor(), 0);
3560 __ andr($dst$$Register, $dst$$Register, $mask$$constant);
3561 %}
3562 ins_pipe(iload_mem);
3563 %}
3564
3565 // Load Integer
3566
3567
3568 instruct loadI(iRegI dst, memoryI mem) %{
3569 match(Set dst (LoadI mem));
3570 ins_cost(MEMORY_REF_COST);
3571
3572 size(4);
3573 format %{ "ldr_s32 $dst,$mem\t! int" %}
3574 ins_encode %{
3575 __ ldr_s32($dst$$Register, $mem$$Address);
3576 %}
3577 ins_pipe(iload_mem);
3578 %}
3579
3580 // Load Integer to Byte (8 bit signed)
3581 instruct loadI2B(iRegI dst, memoryS mem, immI_24 twentyfour) %{
3582 match(Set dst (RShiftI (LShiftI (LoadI mem) twentyfour) twentyfour));
3583 ins_cost(MEMORY_REF_COST);
3584
3585 size(4);
3586
3587 format %{ "LDRSB $dst,$mem\t! int -> byte" %}
3588 ins_encode %{
3589 __ ldrsb($dst$$Register, $mem$$Address);
3590 %}
3591 ins_pipe(iload_mask_mem);
3592 %}
3593
3594 // Load Integer to Unsigned Byte (8 bit UNsigned)
3595 instruct loadI2UB(iRegI dst, memoryB mem, immI_255 mask) %{
3596 match(Set dst (AndI (LoadI mem) mask));
3597 ins_cost(MEMORY_REF_COST);
3598
3599 size(4);
3600
3601 format %{ "LDRB $dst,$mem\t! int -> ubyte" %}
3602 ins_encode %{
3603 __ ldrb($dst$$Register, $mem$$Address);
3604 %}
3605 ins_pipe(iload_mask_mem);
3606 %}
3607
3608 // Load Integer to Short (16 bit signed)
3609 instruct loadI2S(iRegI dst, memoryS mem, immI_16 sixteen) %{
3610 match(Set dst (RShiftI (LShiftI (LoadI mem) sixteen) sixteen));
3611 ins_cost(MEMORY_REF_COST);
3612
3613 size(4);
3614 format %{ "LDRSH $dst,$mem\t! int -> short" %}
3615 ins_encode %{
3616 __ ldrsh($dst$$Register, $mem$$Address);
3617 %}
3618 ins_pipe(iload_mask_mem);
3619 %}
3620
3621 // Load Integer to Unsigned Short (16 bit UNsigned)
3622 instruct loadI2US(iRegI dst, memoryS mem, immI_65535 mask) %{
3623 match(Set dst (AndI (LoadI mem) mask));
3624 ins_cost(MEMORY_REF_COST);
3625
3626 size(4);
3627 format %{ "LDRH $dst,$mem\t! int -> ushort/char" %}
3628 ins_encode %{
3629 __ ldrh($dst$$Register, $mem$$Address);
3630 %}
3631 ins_pipe(iload_mask_mem);
3632 %}
3633
3634 // Load Integer into a Long Register
3635 instruct loadI2L(iRegL dst, memoryI mem) %{
3636 match(Set dst (ConvI2L (LoadI mem)));
3637 ins_cost(MEMORY_REF_COST);
3638
3639 size(8);
3640 format %{ "LDR $dst.lo,$mem\t! int -> long\n\t"
3641 "ASR $dst.hi,$dst.lo,31\t! int->long" %}
3642 ins_encode %{
3643 __ ldr($dst$$Register, $mem$$Address);
3644 __ mov($dst$$Register->successor(), AsmOperand($dst$$Register, asr, 31));
3645 %}
3646 ins_pipe(iload_mask_mem);
3647 %}
3648
3649 // Load Integer with mask 0xFF into a Long Register
3650 instruct loadI2L_immI_255(iRegL dst, memoryB mem, immI_255 mask) %{
3651 match(Set dst (ConvI2L (AndI (LoadI mem) mask)));
3652 ins_cost(MEMORY_REF_COST);
3653
3654 size(8);
3655 format %{ "LDRB $dst.lo,$mem\t! int & 0xFF -> long\n\t"
3656 "MOV $dst.hi, 0" %}
3657 ins_encode %{
3658 __ ldrb($dst$$Register, $mem$$Address);
3659 __ mov($dst$$Register->successor(), 0);
3660 %}
3661 ins_pipe(iload_mem);
3662 %}
3663
3664 // Load Integer with mask 0xFFFF into a Long Register
3665 instruct loadI2L_immI_65535(iRegL dst, memoryS mem, immI_65535 mask) %{
3666 match(Set dst (ConvI2L (AndI (LoadI mem) mask)));
3667 ins_cost(MEMORY_REF_COST);
3668
3669 size(8);
3670 format %{ "LDRH $dst,$mem\t! int & 0xFFFF -> long\n\t"
3671 "MOV $dst.hi, 0" %}
3672 ins_encode %{
3673 __ ldrh($dst$$Register, $mem$$Address);
3674 __ mov($dst$$Register->successor(), 0);
3675 %}
3676 ins_pipe(iload_mask_mem);
3677 %}
3678
3679 // Load Integer with a 31-bit immediate mask into a Long Register
3680 instruct loadI2L_limmU31(iRegL dst, memoryI mem, limmU31 mask) %{
3681 match(Set dst (ConvI2L (AndI (LoadI mem) mask)));
3682 ins_cost(MEMORY_REF_COST + 2*DEFAULT_COST);
3683
3684 size(12);
3685 format %{ "LDR $dst.lo,$mem\t! int -> long\n\t"
3686 "MOV $dst.hi, 0\n\t"
3687 "AND $dst,$dst,$mask" %}
3688
3689 ins_encode %{
3690 __ ldr($dst$$Register, $mem$$Address);
3691 __ mov($dst$$Register->successor(), 0);
3692 __ andr($dst$$Register, $dst$$Register, $mask$$constant);
3693 %}
3694 ins_pipe(iload_mem);
3695 %}
3696
3697 // Load Integer with a 31-bit mask into a Long Register
3698 // FIXME: use iRegI mask, remove tmp?
3699 instruct loadI2L_immU31(iRegL dst, memoryI mem, immU31 mask, iRegI tmp) %{
3700 match(Set dst (ConvI2L (AndI (LoadI mem) mask)));
3701 effect(TEMP dst, TEMP tmp);
3702
3703 ins_cost(MEMORY_REF_COST + 4*DEFAULT_COST);
3704 size(20);
3705 format %{ "LDR $mem,$dst\t! int & 31-bit mask -> long\n\t"
3706 "MOV $dst.hi, 0\n\t"
3707 "MOV_SLOW $tmp,$mask\n\t"
3708 "AND $dst,$tmp,$dst" %}
3709 ins_encode %{
3710 __ ldr($dst$$Register, $mem$$Address);
3711 __ mov($dst$$Register->successor(), 0);
3712 __ mov_slow($tmp$$Register, $mask$$constant);
3713 __ andr($dst$$Register, $dst$$Register, $tmp$$Register);
3714 %}
3715 ins_pipe(iload_mem);
3716 %}
3717
3718 // Load Unsigned Integer into a Long Register
3719 instruct loadUI2L(iRegL dst, memoryI mem, immL_32bits mask) %{
3720 match(Set dst (AndL (ConvI2L (LoadI mem)) mask));
3721 ins_cost(MEMORY_REF_COST);
3722
3723 size(8);
3724 format %{ "LDR $dst.lo,$mem\t! uint -> long\n\t"
3725 "MOV $dst.hi,0" %}
3726 ins_encode %{
3727 __ ldr($dst$$Register, $mem$$Address);
3728 __ mov($dst$$Register->successor(), 0);
3729 %}
3730 ins_pipe(iload_mem);
3731 %}
3732
3733 // Load Long
3734
3735
3736 instruct loadL(iRegLd dst, memoryL mem ) %{
3737 predicate(!((LoadLNode*)n)->require_atomic_access());
3738 match(Set dst (LoadL mem));
3739 effect(TEMP dst);
3740 ins_cost(MEMORY_REF_COST);
3741
3742 size(4);
3743 format %{ "ldr_64 $dst,$mem\t! long" %}
3744 ins_encode %{
3745 __ ldr_64($dst$$Register, $mem$$Address);
3746 %}
3747 ins_pipe(iload_mem);
3748 %}
3749
3750 instruct loadL_2instr(iRegL dst, memorylong mem ) %{
3751 predicate(!((LoadLNode*)n)->require_atomic_access());
3752 match(Set dst (LoadL mem));
3753 ins_cost(MEMORY_REF_COST + DEFAULT_COST);
3754
3755 size(8);
3756 format %{ "LDR $dst.lo,$mem \t! long order of instrs reversed if $dst.lo == base($mem)\n\t"
3757 "LDR $dst.hi,$mem+4 or $mem" %}
3758 ins_encode %{
3759 Address Amemlo = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none);
3760 Address Amemhi = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp + 4, relocInfo::none);
3761
3762 if ($dst$$Register == reg_to_register_object($mem$$base)) {
3763 __ ldr($dst$$Register->successor(), Amemhi);
3764 __ ldr($dst$$Register, Amemlo);
3765 } else {
3766 __ ldr($dst$$Register, Amemlo);
3767 __ ldr($dst$$Register->successor(), Amemhi);
3768 }
3769 %}
3770 ins_pipe(iload_mem);
3771 %}
3772
3773 instruct loadL_volatile(iRegL dst, indirect mem ) %{
3774 predicate(((LoadLNode*)n)->require_atomic_access());
3775 match(Set dst (LoadL mem));
3776 ins_cost(MEMORY_REF_COST);
3777
3778 size(4);
3779 format %{ "LDMIA $dst,$mem\t! long" %}
3780 ins_encode %{
3781 // FIXME: why is ldmia considered atomic? Should be ldrexd
3782 RegisterSet set($dst$$Register);
3783 set = set | reg_to_register_object($dst$$reg + 1);
3784 __ ldmia(reg_to_register_object($mem$$base), set);
3785 %}
3786 ins_pipe(iload_mem);
3787 %}
3788
3789 instruct loadL_volatile_fp(iRegL dst, memoryD mem ) %{
3790 predicate(((LoadLNode*)n)->require_atomic_access());
3791 match(Set dst (LoadL mem));
3792 ins_cost(MEMORY_REF_COST);
3793
3794 size(8);
3795 format %{ "FLDD S14, $mem"
3796 "FMRRD $dst, S14\t! long \n't" %}
3797 ins_encode %{
3798 __ fldd(S14, $mem$$Address);
3799 __ fmrrd($dst$$Register, $dst$$Register->successor(), S14);
3800 %}
3801 ins_pipe(iload_mem);
3802 %}
3803
3804 instruct loadL_unaligned(iRegL dst, memorylong mem ) %{
3805 match(Set dst (LoadL_unaligned mem));
3806 ins_cost(MEMORY_REF_COST);
3807
3808 size(8);
3809 format %{ "LDR $dst.lo,$mem\t! long order of instrs reversed if $dst.lo == base($mem)\n\t"
3810 "LDR $dst.hi,$mem+4" %}
3811 ins_encode %{
3812 Address Amemlo = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none);
3813 Address Amemhi = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp + 4, relocInfo::none);
3814
3815 if ($dst$$Register == reg_to_register_object($mem$$base)) {
3816 __ ldr($dst$$Register->successor(), Amemhi);
3817 __ ldr($dst$$Register, Amemlo);
3818 } else {
3819 __ ldr($dst$$Register, Amemlo);
3820 __ ldr($dst$$Register->successor(), Amemhi);
3821 }
3822 %}
3823 ins_pipe(iload_mem);
3824 %}
3825
3826 // Load Range
3827 instruct loadRange(iRegI dst, memoryI mem) %{
3828 match(Set dst (LoadRange mem));
3829 ins_cost(MEMORY_REF_COST);
3830
3831 size(4);
3832 format %{ "LDR_u32 $dst,$mem\t! range" %}
3833 ins_encode %{
3834 __ ldr_u32($dst$$Register, $mem$$Address);
3835 %}
3836 ins_pipe(iload_mem);
3837 %}
3838
3839 // Load Pointer
3840
3841
3842 instruct loadP(iRegP dst, memoryP mem) %{
3843 predicate(!(UseG1GC && n->as_Load()->barrier_data() != 0));
3844 match(Set dst (LoadP mem));
3845 ins_cost(MEMORY_REF_COST);
3846 size(4);
3847
3848 format %{ "LDR $dst,$mem\t! ptr" %}
3849 ins_encode %{
3850 __ ldr($dst$$Register, $mem$$Address);
3851 %}
3852 ins_pipe(iload_mem);
3853 %}
3854
3855 #ifdef XXX
3856 // FIXME XXXX
3857 //instruct loadSP(iRegP dst, memoryP mem) %{
3858 instruct loadSP(SPRegP dst, memoryP mem, iRegP tmp) %{
3859 match(Set dst (LoadP mem));
3860 effect(TEMP tmp);
3861 ins_cost(MEMORY_REF_COST+1);
3862 size(8);
3863
3864 format %{ "LDR $tmp,$mem\t! ptr\n\t"
3865 "MOV $dst,$tmp\t! ptr" %}
3866 ins_encode %{
3867 __ ldr($tmp$$Register, $mem$$Address);
3868 __ mov($dst$$Register, $tmp$$Register);
3869 %}
3870 ins_pipe(iload_mem);
3871 %}
3872 #endif
3873
3874 #ifdef _LP64
3875 // Load Compressed Pointer
3876
3877 // XXX This variant shouldn't be necessary if 6217251 is implemented
3878 instruct loadNoff(iRegN dst, memoryScaledI mem, aimmX off, iRegP tmp) %{
3879 match(Set dst (LoadN (AddP mem off)));
3880 ins_cost(MEMORY_REF_COST + DEFAULT_COST); // assume shift/sign-extend is free
3881 effect(TEMP tmp);
3882 size(4 * 2);
3883
3884 format %{ "ldr_u32 $dst,$mem+$off\t! compressed ptr temp=$tmp" %}
3885 ins_encode %{
3886 Register base = reg_to_register_object($mem$$base);
3887 __ add($tmp$$Register, base, $off$$constant);
3888 Address nmem = Address::make_raw($tmp$$reg, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none);
3889 __ ldr_u32($dst$$Register, nmem);
3890 %}
3891 ins_pipe(iload_mem);
3892 %}
3893
3894 instruct loadN(iRegN dst, memoryI mem) %{
3895 match(Set dst (LoadN mem));
3896 ins_cost(MEMORY_REF_COST);
3897 size(4);
3898
3899 format %{ "ldr_u32 $dst,$mem\t! compressed ptr" %}
3900 ins_encode %{
3901 __ ldr_u32($dst$$Register, $mem$$Address);
3902 %}
3903 ins_pipe(iload_mem);
3904 %}
3905 #endif
3906
3907 // Load Klass Pointer
3908 instruct loadKlass(iRegP dst, memoryI mem) %{
3909 match(Set dst (LoadKlass mem));
3910 ins_cost(MEMORY_REF_COST);
3911 size(4);
3912
3913 format %{ "LDR $dst,$mem\t! klass ptr" %}
3914 ins_encode %{
3915 __ ldr($dst$$Register, $mem$$Address);
3916 %}
3917 ins_pipe(iload_mem);
3918 %}
3919
3920 #ifdef _LP64
3921 // Load narrow Klass Pointer
3922 instruct loadNKlass(iRegN dst, memoryI mem) %{
3923 match(Set dst (LoadNKlass mem));
3924 ins_cost(MEMORY_REF_COST);
3925 size(4);
3926
3927 format %{ "ldr_u32 $dst,$mem\t! compressed klass ptr" %}
3928 ins_encode %{
3929 __ ldr_u32($dst$$Register, $mem$$Address);
3930 %}
3931 ins_pipe(iload_mem);
3932 %}
3933 #endif
3934
3935
3936 instruct loadD(regD dst, memoryD mem) %{
3937 match(Set dst (LoadD mem));
3938 ins_cost(MEMORY_REF_COST);
3939
3940 size(4);
3941 // FIXME: needs to be atomic, but ARMv7 A.R.M. guarantees
3942 // only LDREXD and STREXD are 64-bit single-copy atomic
3943 format %{ "FLDD $dst,$mem" %}
3944 ins_encode %{
3945 __ ldr_double($dst$$FloatRegister, $mem$$Address);
3946 %}
3947 ins_pipe(floadD_mem);
3948 %}
3949
3950 // Load Double - UNaligned
3951 instruct loadD_unaligned(regD_low dst, memoryF2 mem ) %{
3952 match(Set dst (LoadD_unaligned mem));
3953 ins_cost(MEMORY_REF_COST*2+DEFAULT_COST);
3954 size(8);
3955 format %{ "FLDS $dst.lo,$mem\t! misaligned double\n"
3956 "\tFLDS $dst.hi,$mem+4\t!" %}
3957 ins_encode %{
3958 Address Amemlo = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none);
3959 Address Amemhi = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp + 4, relocInfo::none);
3960 __ flds($dst$$FloatRegister, Amemlo);
3961 __ flds($dst$$FloatRegister->successor(), Amemhi);
3962 %}
3963 ins_pipe(iload_mem);
3964 %}
3965
3966
3967 instruct loadF(regF dst, memoryF mem) %{
3968 match(Set dst (LoadF mem));
3969
3970 ins_cost(MEMORY_REF_COST);
3971 size(4);
3972 format %{ "FLDS $dst,$mem" %}
3973 ins_encode %{
3974 __ ldr_float($dst$$FloatRegister, $mem$$Address);
3975 %}
3976 ins_pipe(floadF_mem);
3977 %}
3978
3979
3980 // // Load Constant
3981 instruct loadConI( iRegI dst, immI src ) %{
3982 match(Set dst src);
3983 ins_cost(DEFAULT_COST * 3/2);
3984 format %{ "MOV_SLOW $dst, $src" %}
3985 ins_encode %{
3986 __ mov_slow($dst$$Register, $src$$constant);
3987 %}
3988 ins_pipe(ialu_hi_lo_reg);
3989 %}
3990
3991 instruct loadConIMov( iRegI dst, immIMov src ) %{
3992 match(Set dst src);
3993 size(4);
3994 format %{ "MOV $dst, $src" %}
3995 ins_encode %{
3996 __ mov($dst$$Register, $src$$constant);
3997 %}
3998 ins_pipe(ialu_imm);
3999 %}
4000
4001 instruct loadConIMovn( iRegI dst, immIRotn src ) %{
4002 match(Set dst src);
4003 size(4);
4004 format %{ "MVN $dst, ~$src" %}
4005 ins_encode %{
4006 __ mvn($dst$$Register, ~$src$$constant);
4007 %}
4008 ins_pipe(ialu_imm_n);
4009 %}
4010
4011 instruct loadConI16( iRegI dst, immI16 src ) %{
4012 match(Set dst src);
4013 size(4);
4014 format %{ "MOVW $dst, $src" %}
4015 ins_encode %{
4016 __ movw($dst$$Register, $src$$constant);
4017 %}
4018 ins_pipe(ialu_imm_n);
4019 %}
4020
4021 instruct loadConP(iRegP dst, immP src) %{
4022 match(Set dst src);
4023 ins_cost(DEFAULT_COST * 3/2);
4024 format %{ "MOV_SLOW $dst,$src\t!ptr" %}
4025 ins_encode %{
4026 relocInfo::relocType constant_reloc = _opnds[1]->constant_reloc();
4027 intptr_t val = $src$$constant;
4028 if (constant_reloc == relocInfo::oop_type) {
4029 __ mov_oop($dst$$Register, (jobject)val);
4030 } else if (constant_reloc == relocInfo::metadata_type) {
4031 __ mov_metadata($dst$$Register, (Metadata*)val);
4032 } else {
4033 __ mov_slow($dst$$Register, val);
4034 }
4035 %}
4036 ins_pipe(loadConP);
4037 %}
4038
4039
4040 instruct loadConL(iRegL dst, immL src) %{
4041 match(Set dst src);
4042 ins_cost(DEFAULT_COST * 4);
4043 format %{ "MOV_SLOW $dst.lo, $src & 0x0FFFFFFFFL \t! long\n\t"
4044 "MOV_SLOW $dst.hi, $src >> 32" %}
4045 ins_encode %{
4046 __ mov_slow(reg_to_register_object($dst$$reg), $src$$constant & 0x0FFFFFFFFL);
4047 __ mov_slow(reg_to_register_object($dst$$reg + 1), ((julong)($src$$constant)) >> 32);
4048 %}
4049 ins_pipe(loadConL);
4050 %}
4051
4052 instruct loadConL16( iRegL dst, immL16 src ) %{
4053 match(Set dst src);
4054 ins_cost(DEFAULT_COST * 2);
4055
4056 size(8);
4057 format %{ "MOVW $dst.lo, $src \n\t"
4058 "MOVW $dst.hi, 0 \n\t" %}
4059 ins_encode %{
4060 __ movw($dst$$Register, $src$$constant);
4061 __ movw($dst$$Register->successor(), 0);
4062 %}
4063 ins_pipe(ialu_imm);
4064 %}
4065
4066 instruct loadConF_imm8(regF dst, imm8F src) %{
4067 match(Set dst src);
4068 ins_cost(DEFAULT_COST);
4069 size(4);
4070
4071 format %{ "FCONSTS $dst, $src"%}
4072
4073 ins_encode %{
4074 __ fconsts($dst$$FloatRegister, Assembler::float_num($src$$constant).imm8());
4075 %}
4076 ins_pipe(loadConFD); // FIXME
4077 %}
4078
4079
4080 instruct loadConF(regF dst, immF src, iRegI tmp) %{
4081 match(Set dst src);
4082 ins_cost(DEFAULT_COST * 2);
4083 effect(TEMP tmp);
4084 size(3*4);
4085
4086 format %{ "MOV_SLOW $tmp, $src\n\t"
4087 "FMSR $dst, $tmp"%}
4088
4089 ins_encode %{
4090 // FIXME revisit once 6961697 is in
4091 union {
4092 jfloat f;
4093 int i;
4094 } v;
4095 v.f = $src$$constant;
4096 __ mov_slow($tmp$$Register, v.i);
4097 __ fmsr($dst$$FloatRegister, $tmp$$Register);
4098 %}
4099 ins_pipe(loadConFD); // FIXME
4100 %}
4101
4102 instruct loadConD_imm8(regD dst, imm8D src) %{
4103 match(Set dst src);
4104 ins_cost(DEFAULT_COST);
4105 size(4);
4106
4107 format %{ "FCONSTD $dst, $src"%}
4108
4109 ins_encode %{
4110 __ fconstd($dst$$FloatRegister, Assembler::double_num($src$$constant).imm8());
4111 %}
4112 ins_pipe(loadConFD); // FIXME
4113 %}
4114
4115 instruct loadConD(regD dst, immD src, iRegP tmp) %{
4116 match(Set dst src);
4117 effect(TEMP tmp);
4118 ins_cost(MEMORY_REF_COST);
4119 format %{ "FLDD $dst, [$constanttablebase + $constantoffset]\t! load from constant table: double=$src" %}
4120
4121 ins_encode %{
4122 Register r = $constanttablebase;
4123 int offset = $constantoffset($src);
4124 if (!is_memoryD(offset)) { // can't use a predicate
4125 // in load constant instructs
4126 __ add_slow($tmp$$Register, r, offset);
4127 r = $tmp$$Register;
4128 offset = 0;
4129 }
4130 __ ldr_double($dst$$FloatRegister, Address(r, offset));
4131 %}
4132 ins_pipe(loadConFD);
4133 %}
4134
4135 // Prefetch instructions.
4136 // Must be safe to execute with invalid address (cannot fault).
4137
4138 instruct prefetchAlloc_mp( memoryP mem ) %{
4139 predicate(VM_Version::has_multiprocessing_extensions());
4140 match( PrefetchAllocation mem );
4141 ins_cost(MEMORY_REF_COST);
4142 size(4);
4143
4144 format %{ "PLDW $mem\t! Prefetch allocation" %}
4145 ins_encode %{
4146 __ pldw($mem$$Address);
4147 %}
4148 ins_pipe(iload_mem);
4149 %}
4150
4151 instruct prefetchAlloc_sp( memoryP mem ) %{
4152 predicate(!VM_Version::has_multiprocessing_extensions());
4153 match( PrefetchAllocation mem );
4154 ins_cost(MEMORY_REF_COST);
4155 size(4);
4156
4157 format %{ "PLD $mem\t! Prefetch allocation" %}
4158 ins_encode %{
4159 __ pld($mem$$Address);
4160 %}
4161 ins_pipe(iload_mem);
4162 %}
4163
4164
4165 //----------Store Instructions-------------------------------------------------
4166 // Store Byte
4167 instruct storeB(memoryB mem, store_RegI src) %{
4168 match(Set mem (StoreB mem src));
4169 ins_cost(MEMORY_REF_COST);
4170
4171 size(4);
4172 format %{ "STRB $src,$mem\t! byte" %}
4173 ins_encode %{
4174 __ strb($src$$Register, $mem$$Address);
4175 %}
4176 ins_pipe(istore_mem_reg);
4177 %}
4178
4179 // Store Char/Short
4180
4181
4182 instruct storeC(memoryS mem, store_RegI src) %{
4183 match(Set mem (StoreC mem src));
4184 ins_cost(MEMORY_REF_COST);
4185
4186 size(4);
4187 format %{ "STRH $src,$mem\t! short" %}
4188 ins_encode %{
4189 __ strh($src$$Register, $mem$$Address);
4190 %}
4191 ins_pipe(istore_mem_reg);
4192 %}
4193
4194 // Store Integer
4195
4196
4197 instruct storeI(memoryI mem, store_RegI src) %{
4198 match(Set mem (StoreI mem src));
4199 ins_cost(MEMORY_REF_COST);
4200
4201 size(4);
4202 format %{ "str_32 $src,$mem" %}
4203 ins_encode %{
4204 __ str_32($src$$Register, $mem$$Address);
4205 %}
4206 ins_pipe(istore_mem_reg);
4207 %}
4208
4209 // Store Long
4210
4211
4212 instruct storeL(memoryL mem, store_RegLd src) %{
4213 predicate(!((StoreLNode*)n)->require_atomic_access());
4214 match(Set mem (StoreL mem src));
4215 ins_cost(MEMORY_REF_COST);
4216
4217 size(4);
4218 format %{ "str_64 $src,$mem\t! long\n\t" %}
4219
4220 ins_encode %{
4221 __ str_64($src$$Register, $mem$$Address);
4222 %}
4223 ins_pipe(istore_mem_reg);
4224 %}
4225
4226 instruct storeL_2instr(memorylong mem, iRegL src) %{
4227 predicate(!((StoreLNode*)n)->require_atomic_access());
4228 match(Set mem (StoreL mem src));
4229 ins_cost(MEMORY_REF_COST + DEFAULT_COST);
4230
4231 size(8);
4232 format %{ "STR $src.lo,$mem\t! long\n\t"
4233 "STR $src.hi,$mem+4" %}
4234
4235 ins_encode %{
4236 Address Amemlo = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none);
4237 Address Amemhi = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp + 4, relocInfo::none);
4238 __ str($src$$Register, Amemlo);
4239 __ str($src$$Register->successor(), Amemhi);
4240 %}
4241 ins_pipe(istore_mem_reg);
4242 %}
4243
4244 instruct storeL_volatile(indirect mem, iRegL src) %{
4245 predicate(((StoreLNode*)n)->require_atomic_access());
4246 match(Set mem (StoreL mem src));
4247 ins_cost(MEMORY_REF_COST);
4248 size(4);
4249 format %{ "STMIA $src,$mem\t! long" %}
4250 ins_encode %{
4251 // FIXME: why is stmia considered atomic? Should be strexd
4252 RegisterSet set($src$$Register);
4253 set = set | reg_to_register_object($src$$reg + 1);
4254 __ stmia(reg_to_register_object($mem$$base), set);
4255 %}
4256 ins_pipe(istore_mem_reg);
4257 %}
4258
4259 instruct storeL_volatile_fp(memoryD mem, iRegL src) %{
4260 predicate(((StoreLNode*)n)->require_atomic_access());
4261 match(Set mem (StoreL mem src));
4262 ins_cost(MEMORY_REF_COST);
4263 size(8);
4264 format %{ "FMDRR S14, $src\t! long \n\t"
4265 "FSTD S14, $mem" %}
4266 ins_encode %{
4267 __ fmdrr(S14, $src$$Register, $src$$Register->successor());
4268 __ fstd(S14, $mem$$Address);
4269 %}
4270 ins_pipe(istore_mem_reg);
4271 %}
4272
4273 #ifdef XXX
4274 // Move SP Pointer
4275 //instruct movSP(sp_ptr_RegP dst, SPRegP src) %{
4276 //instruct movSP(iRegP dst, SPRegP src) %{
4277 instruct movSP(store_ptr_RegP dst, SPRegP src) %{
4278 match(Set dst src);
4279 //predicate(!_kids[1]->_leaf->is_Proj() || _kids[1]->_leaf->as_Proj()->_con == TypeFunc::FramePtr);
4280 ins_cost(MEMORY_REF_COST);
4281 size(4);
4282
4283 format %{ "MOV $dst,$src\t! SP ptr\n\t" %}
4284 ins_encode %{
4285 assert(false, "XXX1 got here");
4286 __ mov($dst$$Register, SP);
4287 __ mov($dst$$Register, $src$$Register);
4288 %}
4289 ins_pipe(ialu_reg);
4290 %}
4291 #endif
4292
4293
4294 // Store Pointer
4295
4296
4297 instruct storeP(memoryP mem, store_ptr_RegP src) %{
4298 predicate(!(UseG1GC && n->as_Store()->barrier_data() != 0));
4299 match(Set mem (StoreP mem src));
4300 ins_cost(MEMORY_REF_COST);
4301 size(4);
4302
4303 format %{ "STR $src,$mem\t! ptr" %}
4304 ins_encode %{
4305 __ str($src$$Register, $mem$$Address);
4306 %}
4307 ins_pipe(istore_mem_spORreg);
4308 %}
4309
4310
4311 #ifdef _LP64
4312 // Store Compressed Pointer
4313
4314
4315 instruct storeN(memoryI mem, store_RegN src) %{
4316 match(Set mem (StoreN mem src));
4317 ins_cost(MEMORY_REF_COST);
4318 size(4);
4319
4320 format %{ "str_32 $src,$mem\t! compressed ptr" %}
4321 ins_encode %{
4322 __ str_32($src$$Register, $mem$$Address);
4323 %}
4324 ins_pipe(istore_mem_reg);
4325 %}
4326
4327
4328 // Store Compressed Klass Pointer
4329 instruct storeNKlass(memoryI mem, store_RegN src) %{
4330 match(Set mem (StoreNKlass mem src));
4331 ins_cost(MEMORY_REF_COST);
4332 size(4);
4333
4334 format %{ "str_32 $src,$mem\t! compressed klass ptr" %}
4335 ins_encode %{
4336 __ str_32($src$$Register, $mem$$Address);
4337 %}
4338 ins_pipe(istore_mem_reg);
4339 %}
4340 #endif
4341
4342 // Store Double
4343
4344
4345 instruct storeD(memoryD mem, regD src) %{
4346 match(Set mem (StoreD mem src));
4347 ins_cost(MEMORY_REF_COST);
4348
4349 size(4);
4350 // FIXME: needs to be atomic, but ARMv7 A.R.M. guarantees
4351 // only LDREXD and STREXD are 64-bit single-copy atomic
4352 format %{ "FSTD $src,$mem" %}
4353 ins_encode %{
4354 __ str_double($src$$FloatRegister, $mem$$Address);
4355 %}
4356 ins_pipe(fstoreD_mem_reg);
4357 %}
4358
4359
4360 // Store Float
4361
4362
4363 instruct storeF( memoryF mem, regF src) %{
4364 match(Set mem (StoreF mem src));
4365 ins_cost(MEMORY_REF_COST);
4366
4367 size(4);
4368 format %{ "FSTS $src,$mem" %}
4369 ins_encode %{
4370 __ str_float($src$$FloatRegister, $mem$$Address);
4371 %}
4372 ins_pipe(fstoreF_mem_reg);
4373 %}
4374
4375
4376 //----------MemBar Instructions-----------------------------------------------
4377 // Memory barrier flavors
4378
4379 // pattern-match out unnecessary membars
4380 instruct membar_storestore() %{
4381 match(MemBarStoreStore);
4382 match(StoreStoreFence);
4383 ins_cost(4*MEMORY_REF_COST);
4384
4385 size(4);
4386 format %{ "MEMBAR-storestore" %}
4387 ins_encode %{
4388 __ membar(MacroAssembler::Membar_mask_bits(MacroAssembler::StoreStore), noreg);
4389 %}
4390 ins_pipe(long_memory_op);
4391 %}
4392
4393 instruct membar_acquire() %{
4394 match(MemBarAcquire);
4395 match(LoadFence);
4396 ins_cost(4*MEMORY_REF_COST);
4397
4398 size(4);
4399 format %{ "MEMBAR-acquire" %}
4400 ins_encode %{
4401 __ membar(MacroAssembler::Membar_mask_bits(MacroAssembler::LoadLoad | MacroAssembler::LoadStore), noreg);
4402 %}
4403 ins_pipe(long_memory_op);
4404 %}
4405
4406 instruct membar_acquire_lock() %{
4407 match(MemBarAcquireLock);
4408 ins_cost(0);
4409
4410 size(0);
4411 format %{ "!MEMBAR-acquire (CAS in prior FastLock so empty encoding)" %}
4412 ins_encode( );
4413 ins_pipe(empty);
4414 %}
4415
4416 instruct membar_release() %{
4417 match(MemBarRelease);
4418 match(StoreFence);
4419 ins_cost(4*MEMORY_REF_COST);
4420
4421 size(4);
4422 format %{ "MEMBAR-release" %}
4423 ins_encode %{
4424 __ membar(MacroAssembler::Membar_mask_bits(MacroAssembler::StoreStore | MacroAssembler::LoadStore), noreg);
4425 %}
4426 ins_pipe(long_memory_op);
4427 %}
4428
4429 instruct membar_release_lock() %{
4430 match(MemBarReleaseLock);
4431 ins_cost(0);
4432
4433 size(0);
4434 format %{ "!MEMBAR-release (CAS in succeeding FastUnlock so empty encoding)" %}
4435 ins_encode( );
4436 ins_pipe(empty);
4437 %}
4438
4439 instruct membar_storeload() %{
4440 match(MemBarStoreLoad);
4441 ins_cost(4*MEMORY_REF_COST);
4442
4443 size(4);
4444 format %{ "MEMBAR-storeload" %}
4445 ins_encode %{
4446 __ membar(MacroAssembler::StoreLoad, noreg);
4447 %}
4448 ins_pipe(long_memory_op);
4449 %}
4450
4451 instruct membar_volatile() %{
4452 match(MemBarVolatile);
4453 ins_cost(4*MEMORY_REF_COST);
4454
4455 size(4);
4456 format %{ "MEMBAR-volatile" %}
4457 ins_encode %{
4458 __ membar(MacroAssembler::StoreLoad, noreg);
4459 %}
4460 ins_pipe(long_memory_op);
4461 %}
4462
4463 instruct unnecessary_membar_volatile() %{
4464 match(MemBarVolatile);
4465 predicate(Matcher::post_store_load_barrier(n));
4466 ins_cost(0);
4467
4468 size(0);
4469 format %{ "!MEMBAR-volatile (unnecessary so empty encoding)" %}
4470 ins_encode( );
4471 ins_pipe(empty);
4472 %}
4473
4474 instruct membar_full() %{
4475 match(MemBarFull);
4476 ins_cost(4*MEMORY_REF_COST);
4477
4478 size(4);
4479 format %{ "MEMBAR-full" %}
4480 ins_encode %{
4481 __ membar(MacroAssembler::StoreLoad, noreg);
4482 %}
4483 ins_pipe(long_memory_op);
4484 %}
4485
4486 //----------Register Move Instructions-----------------------------------------
4487
4488 // Cast Index to Pointer for unsafe natives
4489 instruct castX2P(iRegX src, iRegP dst) %{
4490 match(Set dst (CastX2P src));
4491
4492 format %{ "MOV $dst,$src\t! IntX->Ptr if $dst != $src" %}
4493 ins_encode %{
4494 if ($dst$$Register != $src$$Register) {
4495 __ mov($dst$$Register, $src$$Register);
4496 }
4497 %}
4498 ins_pipe(ialu_reg);
4499 %}
4500
4501 // Cast Pointer to Index for unsafe natives
4502 instruct castP2X(iRegP src, iRegX dst) %{
4503 match(Set dst (CastP2X src));
4504
4505 format %{ "MOV $dst,$src\t! Ptr->IntX if $dst != $src" %}
4506 ins_encode %{
4507 if ($dst$$Register != $src$$Register) {
4508 __ mov($dst$$Register, $src$$Register);
4509 }
4510 %}
4511 ins_pipe(ialu_reg);
4512 %}
4513
4514 //----------Conditional Move---------------------------------------------------
4515 // Conditional move
4516 instruct cmovIP_reg(cmpOpP cmp, flagsRegP pcc, iRegI dst, iRegI src) %{
4517 match(Set dst (CMoveI (Binary cmp pcc) (Binary dst src)));
4518 ins_cost(150);
4519 size(4);
4520 format %{ "MOV$cmp $dst,$src\t! int" %}
4521 ins_encode %{
4522 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
4523 %}
4524 ins_pipe(ialu_reg);
4525 %}
4526
4527
4528 instruct cmovIP_immMov(cmpOpP cmp, flagsRegP pcc, iRegI dst, immIMov src) %{
4529 match(Set dst (CMoveI (Binary cmp pcc) (Binary dst src)));
4530 ins_cost(140);
4531 size(4);
4532 format %{ "MOV$cmp $dst,$src" %}
4533 ins_encode %{
4534 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
4535 %}
4536 ins_pipe(ialu_imm);
4537 %}
4538
4539 instruct cmovIP_imm16(cmpOpP cmp, flagsRegP pcc, iRegI dst, immI16 src) %{
4540 match(Set dst (CMoveI (Binary cmp pcc) (Binary dst src)));
4541 ins_cost(140);
4542 size(4);
4543 format %{ "MOVw$cmp $dst,$src" %}
4544 ins_encode %{
4545 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
4546 %}
4547 ins_pipe(ialu_imm);
4548 %}
4549
4550 instruct cmovI_reg(cmpOp cmp, flagsReg icc, iRegI dst, iRegI src) %{
4551 match(Set dst (CMoveI (Binary cmp icc) (Binary dst src)));
4552 ins_cost(150);
4553 size(4);
4554 format %{ "MOV$cmp $dst,$src" %}
4555 ins_encode %{
4556 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
4557 %}
4558 ins_pipe(ialu_reg);
4559 %}
4560
4561
4562 instruct cmovI_immMov(cmpOp cmp, flagsReg icc, iRegI dst, immIMov src) %{
4563 match(Set dst (CMoveI (Binary cmp icc) (Binary dst src)));
4564 ins_cost(140);
4565 size(4);
4566 format %{ "MOV$cmp $dst,$src" %}
4567 ins_encode %{
4568 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
4569 %}
4570 ins_pipe(ialu_imm);
4571 %}
4572
4573 instruct cmovII_imm16(cmpOp cmp, flagsReg icc, iRegI dst, immI16 src) %{
4574 match(Set dst (CMoveI (Binary cmp icc) (Binary dst src)));
4575 ins_cost(140);
4576 size(4);
4577 format %{ "MOVw$cmp $dst,$src" %}
4578 ins_encode %{
4579 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
4580 %}
4581 ins_pipe(ialu_imm);
4582 %}
4583
4584 instruct cmovII_reg_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegI dst, iRegI src) %{
4585 match(Set dst (CMoveI (Binary cmp icc) (Binary dst src)));
4586 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq ||
4587 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ||
4588 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt ||
4589 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
4590 ins_cost(150);
4591 size(4);
4592 format %{ "MOV$cmp $dst,$src" %}
4593 ins_encode %{
4594 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
4595 %}
4596 ins_pipe(ialu_reg);
4597 %}
4598
4599 instruct cmovII_immMov_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegI dst, immIMov src) %{
4600 match(Set dst (CMoveI (Binary cmp icc) (Binary dst src)));
4601 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq ||
4602 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ||
4603 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt ||
4604 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
4605 ins_cost(140);
4606 size(4);
4607 format %{ "MOV$cmp $dst,$src" %}
4608 ins_encode %{
4609 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
4610 %}
4611 ins_pipe(ialu_imm);
4612 %}
4613
4614 instruct cmovII_imm16_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegI dst, immI16 src) %{
4615 match(Set dst (CMoveI (Binary cmp icc) (Binary dst src)));
4616 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq ||
4617 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ||
4618 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt ||
4619 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
4620 ins_cost(140);
4621 size(4);
4622 format %{ "MOVW$cmp $dst,$src" %}
4623 ins_encode %{
4624 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
4625 %}
4626 ins_pipe(ialu_imm);
4627 %}
4628
4629 instruct cmovIIu_reg(cmpOpU cmp, flagsRegU icc, iRegI dst, iRegI src) %{
4630 match(Set dst (CMoveI (Binary cmp icc) (Binary dst src)));
4631 ins_cost(150);
4632 size(4);
4633 format %{ "MOV$cmp $dst,$src" %}
4634 ins_encode %{
4635 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
4636 %}
4637 ins_pipe(ialu_reg);
4638 %}
4639
4640 instruct cmovIIu_immMov(cmpOpU cmp, flagsRegU icc, iRegI dst, immIMov src) %{
4641 match(Set dst (CMoveI (Binary cmp icc) (Binary dst src)));
4642 ins_cost(140);
4643 size(4);
4644 format %{ "MOV$cmp $dst,$src" %}
4645 ins_encode %{
4646 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
4647 %}
4648 ins_pipe(ialu_imm);
4649 %}
4650
4651 instruct cmovIIu_imm16(cmpOpU cmp, flagsRegU icc, iRegI dst, immI16 src) %{
4652 match(Set dst (CMoveI (Binary cmp icc) (Binary dst src)));
4653 ins_cost(140);
4654 size(4);
4655 format %{ "MOVW$cmp $dst,$src" %}
4656 ins_encode %{
4657 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
4658 %}
4659 ins_pipe(ialu_imm);
4660 %}
4661
4662 // Conditional move
4663 instruct cmovPP_reg(cmpOpP cmp, flagsRegP pcc, iRegP dst, iRegP src) %{
4664 match(Set dst (CMoveP (Binary cmp pcc) (Binary dst src)));
4665 ins_cost(150);
4666 size(4);
4667 format %{ "MOV$cmp $dst,$src" %}
4668 ins_encode %{
4669 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
4670 %}
4671 ins_pipe(ialu_reg);
4672 %}
4673
4674 instruct cmovPP_imm(cmpOpP cmp, flagsRegP pcc, iRegP dst, immP0 src) %{
4675 match(Set dst (CMoveP (Binary cmp pcc) (Binary dst src)));
4676 ins_cost(140);
4677 size(4);
4678 format %{ "MOV$cmp $dst,$src" %}
4679 ins_encode %{
4680 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
4681 %}
4682 ins_pipe(ialu_imm);
4683 %}
4684
4685 // This instruction also works with CmpN so we don't need cmovPN_reg.
4686 instruct cmovPI_reg(cmpOp cmp, flagsReg icc, iRegP dst, iRegP src) %{
4687 match(Set dst (CMoveP (Binary cmp icc) (Binary dst src)));
4688 ins_cost(150);
4689
4690 size(4);
4691 format %{ "MOV$cmp $dst,$src\t! ptr" %}
4692 ins_encode %{
4693 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
4694 %}
4695 ins_pipe(ialu_reg);
4696 %}
4697
4698 instruct cmovPI_reg_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegP dst, iRegP src) %{
4699 match(Set dst (CMoveP (Binary cmp icc) (Binary dst src)));
4700 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq ||
4701 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ||
4702 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt ||
4703 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
4704 ins_cost(150);
4705
4706 size(4);
4707 format %{ "MOV$cmp $dst,$src\t! ptr" %}
4708 ins_encode %{
4709 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
4710 %}
4711 ins_pipe(ialu_reg);
4712 %}
4713
4714 instruct cmovPIu_reg(cmpOpU cmp, flagsRegU icc, iRegP dst, iRegP src) %{
4715 match(Set dst (CMoveP (Binary cmp icc) (Binary dst src)));
4716 ins_cost(150);
4717
4718 size(4);
4719 format %{ "MOV$cmp $dst,$src\t! ptr" %}
4720 ins_encode %{
4721 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
4722 %}
4723 ins_pipe(ialu_reg);
4724 %}
4725
4726 instruct cmovPI_imm(cmpOp cmp, flagsReg icc, iRegP dst, immP0 src) %{
4727 match(Set dst (CMoveP (Binary cmp icc) (Binary dst src)));
4728 ins_cost(140);
4729
4730 size(4);
4731 format %{ "MOV$cmp $dst,$src\t! ptr" %}
4732 ins_encode %{
4733 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
4734 %}
4735 ins_pipe(ialu_imm);
4736 %}
4737
4738 instruct cmovPI_imm_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegP dst, immP0 src) %{
4739 match(Set dst (CMoveP (Binary cmp icc) (Binary dst src)));
4740 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq ||
4741 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ||
4742 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt ||
4743 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
4744 ins_cost(140);
4745
4746 size(4);
4747 format %{ "MOV$cmp $dst,$src\t! ptr" %}
4748 ins_encode %{
4749 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
4750 %}
4751 ins_pipe(ialu_imm);
4752 %}
4753
4754 instruct cmovPIu_imm(cmpOpU cmp, flagsRegU icc, iRegP dst, immP0 src) %{
4755 match(Set dst (CMoveP (Binary cmp icc) (Binary dst src)));
4756 ins_cost(140);
4757
4758 size(4);
4759 format %{ "MOV$cmp $dst,$src\t! ptr" %}
4760 ins_encode %{
4761 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
4762 %}
4763 ins_pipe(ialu_imm);
4764 %}
4765
4766
4767 // Conditional move
4768 instruct cmovFP_reg(cmpOpP cmp, flagsRegP pcc, regF dst, regF src) %{
4769 match(Set dst (CMoveF (Binary cmp pcc) (Binary dst src)));
4770 ins_cost(150);
4771 size(4);
4772 format %{ "FCPYS$cmp $dst,$src" %}
4773 ins_encode %{
4774 __ fcpys($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
4775 %}
4776 ins_pipe(int_conditional_float_move);
4777 %}
4778
4779 instruct cmovFI_reg(cmpOp cmp, flagsReg icc, regF dst, regF src) %{
4780 match(Set dst (CMoveF (Binary cmp icc) (Binary dst src)));
4781 ins_cost(150);
4782
4783 size(4);
4784 format %{ "FCPYS$cmp $dst,$src" %}
4785 ins_encode %{
4786 __ fcpys($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
4787 %}
4788 ins_pipe(int_conditional_float_move);
4789 %}
4790
4791 instruct cmovFI_reg_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, regF dst, regF src) %{
4792 match(Set dst (CMoveF (Binary cmp icc) (Binary dst src)));
4793 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq ||
4794 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ||
4795 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt ||
4796 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
4797 ins_cost(150);
4798
4799 size(4);
4800 format %{ "FCPYS$cmp $dst,$src" %}
4801 ins_encode %{
4802 __ fcpys($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
4803 %}
4804 ins_pipe(int_conditional_float_move);
4805 %}
4806
4807 instruct cmovFIu_reg(cmpOpU cmp, flagsRegU icc, regF dst, regF src) %{
4808 match(Set dst (CMoveF (Binary cmp icc) (Binary dst src)));
4809 ins_cost(150);
4810
4811 size(4);
4812 format %{ "FCPYS$cmp $dst,$src" %}
4813 ins_encode %{
4814 __ fcpys($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
4815 %}
4816 ins_pipe(int_conditional_float_move);
4817 %}
4818
4819 // Conditional move
4820 instruct cmovDP_reg(cmpOpP cmp, flagsRegP pcc, regD dst, regD src) %{
4821 match(Set dst (CMoveD (Binary cmp pcc) (Binary dst src)));
4822 ins_cost(150);
4823 size(4);
4824 format %{ "FCPYD$cmp $dst,$src" %}
4825 ins_encode %{
4826 __ fcpyd($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
4827 %}
4828 ins_pipe(int_conditional_double_move);
4829 %}
4830
4831 instruct cmovDI_reg(cmpOp cmp, flagsReg icc, regD dst, regD src) %{
4832 match(Set dst (CMoveD (Binary cmp icc) (Binary dst src)));
4833 ins_cost(150);
4834
4835 size(4);
4836 format %{ "FCPYD$cmp $dst,$src" %}
4837 ins_encode %{
4838 __ fcpyd($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
4839 %}
4840 ins_pipe(int_conditional_double_move);
4841 %}
4842
4843 instruct cmovDI_reg_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, regD dst, regD src) %{
4844 match(Set dst (CMoveD (Binary cmp icc) (Binary dst src)));
4845 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
4846 ins_cost(150);
4847
4848 size(4);
4849 format %{ "FCPYD$cmp $dst,$src" %}
4850 ins_encode %{
4851 __ fcpyd($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
4852 %}
4853 ins_pipe(int_conditional_double_move);
4854 %}
4855
4856 instruct cmovDIu_reg(cmpOpU cmp, flagsRegU icc, regD dst, regD src) %{
4857 match(Set dst (CMoveD (Binary cmp icc) (Binary dst src)));
4858 ins_cost(150);
4859
4860 size(4);
4861 format %{ "FCPYD$cmp $dst,$src" %}
4862 ins_encode %{
4863 __ fcpyd($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
4864 %}
4865 ins_pipe(int_conditional_double_move);
4866 %}
4867
4868 // Conditional move
4869 instruct cmovLP_reg(cmpOpP cmp, flagsRegP pcc, iRegL dst, iRegL src) %{
4870 match(Set dst (CMoveL (Binary cmp pcc) (Binary dst src)));
4871 ins_cost(150);
4872
4873 size(8);
4874 format %{ "MOV$cmp $dst.lo,$src.lo\t! long\n\t"
4875 "MOV$cmp $dst.hi,$src.hi" %}
4876 ins_encode %{
4877 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
4878 __ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode));
4879 %}
4880 ins_pipe(ialu_reg);
4881 %}
4882
4883 // TODO: try immLRot2 instead, (0, $con$$constant) becomes
4884 // (hi($con$$constant), lo($con$$constant)) becomes
4885 instruct cmovLP_immRot(cmpOpP cmp, flagsRegP pcc, iRegL dst, immLlowRot src) %{
4886 match(Set dst (CMoveL (Binary cmp pcc) (Binary dst src)));
4887 ins_cost(140);
4888
4889 size(8);
4890 format %{ "MOV$cmp $dst.lo,$src\t! long\n\t"
4891 "MOV$cmp $dst.hi,0" %}
4892 ins_encode %{
4893 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
4894 __ mov($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode));
4895 %}
4896 ins_pipe(ialu_imm);
4897 %}
4898
4899 instruct cmovLP_imm16(cmpOpP cmp, flagsRegP pcc, iRegL dst, immL16 src) %{
4900 match(Set dst (CMoveL (Binary cmp pcc) (Binary dst src)));
4901 ins_cost(140);
4902
4903 size(8);
4904 format %{ "MOV$cmp $dst.lo,$src\t! long\n\t"
4905 "MOV$cmp $dst.hi,0" %}
4906 ins_encode %{
4907 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
4908 __ mov($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode));
4909 %}
4910 ins_pipe(ialu_imm);
4911 %}
4912
4913 instruct cmovLI_reg(cmpOp cmp, flagsReg icc, iRegL dst, iRegL src) %{
4914 match(Set dst (CMoveL (Binary cmp icc) (Binary dst src)));
4915 ins_cost(150);
4916
4917 size(8);
4918 format %{ "MOV$cmp $dst.lo,$src.lo\t! long\n\t"
4919 "MOV$cmp $dst.hi,$src.hi" %}
4920 ins_encode %{
4921 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
4922 __ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode));
4923 %}
4924 ins_pipe(ialu_reg);
4925 %}
4926
4927 instruct cmovLI_reg_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegL dst, iRegL src) %{
4928 match(Set dst (CMoveL (Binary cmp icc) (Binary dst src)));
4929 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq ||
4930 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ||
4931 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt ||
4932 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
4933 ins_cost(150);
4934
4935 size(8);
4936 format %{ "MOV$cmp $dst.lo,$src.lo\t! long\n\t"
4937 "MOV$cmp $dst.hi,$src.hi" %}
4938 ins_encode %{
4939 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
4940 __ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode));
4941 %}
4942 ins_pipe(ialu_reg);
4943 %}
4944
4945 // TODO: try immLRot2 instead, (0, $con$$constant) becomes
4946 // (hi($con$$constant), lo($con$$constant)) becomes
4947 instruct cmovLI_immRot(cmpOp cmp, flagsReg icc, iRegL dst, immLlowRot src) %{
4948 match(Set dst (CMoveL (Binary cmp icc) (Binary dst src)));
4949 ins_cost(140);
4950
4951 size(8);
4952 format %{ "MOV$cmp $dst.lo,$src\t! long\n\t"
4953 "MOV$cmp $dst.hi,0" %}
4954 ins_encode %{
4955 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
4956 __ mov($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode));
4957 %}
4958 ins_pipe(ialu_imm);
4959 %}
4960
4961 // TODO: try immLRot2 instead, (0, $con$$constant) becomes
4962 // (hi($con$$constant), lo($con$$constant)) becomes
4963 instruct cmovLI_immRot_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegL dst, immLlowRot src) %{
4964 match(Set dst (CMoveL (Binary cmp icc) (Binary dst src)));
4965 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq ||
4966 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ||
4967 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt ||
4968 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
4969 ins_cost(140);
4970
4971 size(8);
4972 format %{ "MOV$cmp $dst.lo,$src\t! long\n\t"
4973 "MOV$cmp $dst.hi,0" %}
4974 ins_encode %{
4975 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
4976 __ mov($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode));
4977 %}
4978 ins_pipe(ialu_imm);
4979 %}
4980
4981 instruct cmovLI_imm16(cmpOp cmp, flagsReg icc, iRegL dst, immL16 src) %{
4982 match(Set dst (CMoveL (Binary cmp icc) (Binary dst src)));
4983 ins_cost(140);
4984
4985 size(8);
4986 format %{ "MOV$cmp $dst.lo,$src\t! long\n\t"
4987 "MOV$cmp $dst.hi,0" %}
4988 ins_encode %{
4989 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
4990 __ movw($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode));
4991 %}
4992 ins_pipe(ialu_imm);
4993 %}
4994
4995 instruct cmovLI_imm16_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegL dst, immL16 src) %{
4996 match(Set dst (CMoveL (Binary cmp icc) (Binary dst src)));
4997 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq ||
4998 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ||
4999 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt ||
5000 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
5001 ins_cost(140);
5002
5003 size(8);
5004 format %{ "MOV$cmp $dst.lo,$src\t! long\n\t"
5005 "MOV$cmp $dst.hi,0" %}
5006 ins_encode %{
5007 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
5008 __ movw($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode));
5009 %}
5010 ins_pipe(ialu_imm);
5011 %}
5012
5013 instruct cmovLIu_reg(cmpOpU cmp, flagsRegU icc, iRegL dst, iRegL src) %{
5014 match(Set dst (CMoveL (Binary cmp icc) (Binary dst src)));
5015 ins_cost(150);
5016
5017 size(8);
5018 format %{ "MOV$cmp $dst.lo,$src.lo\t! long\n\t"
5019 "MOV$cmp $dst.hi,$src.hi" %}
5020 ins_encode %{
5021 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
5022 __ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode));
5023 %}
5024 ins_pipe(ialu_reg);
5025 %}
5026
5027
5028 //----------OS and Locking Instructions----------------------------------------
5029
5030 // This name is KNOWN by the ADLC and cannot be changed.
5031 // The ADLC forces a 'TypeRawPtr::BOTTOM' output type
5032 // for this guy.
5033 instruct tlsLoadP(RthreadRegP dst) %{
5034 match(Set dst (ThreadLocal));
5035
5036 size(0);
5037 ins_cost(0);
5038 format %{ "! TLS is in $dst" %}
5039 ins_encode( /*empty encoding*/ );
5040 ins_pipe(ialu_none);
5041 %}
5042
5043 instruct checkCastPP( iRegP dst ) %{
5044 match(Set dst (CheckCastPP dst));
5045
5046 size(0);
5047 format %{ "! checkcastPP of $dst" %}
5048 ins_encode( /*empty encoding*/ );
5049 ins_pipe(empty);
5050 %}
5051
5052
5053 instruct castPP( iRegP dst ) %{
5054 match(Set dst (CastPP dst));
5055 format %{ "! castPP of $dst" %}
5056 ins_encode( /*empty encoding*/ );
5057 ins_pipe(empty);
5058 %}
5059
5060 instruct castII( iRegI dst ) %{
5061 match(Set dst (CastII dst));
5062 format %{ "! castII of $dst" %}
5063 ins_encode( /*empty encoding*/ );
5064 ins_cost(0);
5065 ins_pipe(empty);
5066 %}
5067
5068 instruct castLL( iRegL dst ) %{
5069 match(Set dst (CastLL dst));
5070 format %{ "! castLL of $dst" %}
5071 ins_encode( /*empty encoding*/ );
5072 ins_cost(0);
5073 ins_pipe(empty);
5074 %}
5075
5076 instruct castFF( regF dst ) %{
5077 match(Set dst (CastFF dst));
5078 format %{ "! castFF of $dst" %}
5079 ins_encode( /*empty encoding*/ );
5080 ins_cost(0);
5081 ins_pipe(empty);
5082 %}
5083
5084 instruct castDD( regD dst ) %{
5085 match(Set dst (CastDD dst));
5086 format %{ "! castDD of $dst" %}
5087 ins_encode( /*empty encoding*/ );
5088 ins_cost(0);
5089 ins_pipe(empty);
5090 %}
5091
5092 instruct castVVD( vecD dst ) %{
5093 match(Set dst (CastVV dst));
5094 format %{ "! castVV of $dst" %}
5095 ins_encode( /*empty encoding*/ );
5096 ins_cost(0);
5097 ins_pipe(empty);
5098 %}
5099
5100 instruct castVVX( vecX dst ) %{
5101 match(Set dst (CastVV dst));
5102 format %{ "! castVV of $dst" %}
5103 ins_encode( /*empty encoding*/ );
5104 ins_cost(0);
5105 ins_pipe(empty);
5106 %}
5107
5108
5109 //----------Arithmetic Instructions--------------------------------------------
5110 // Addition Instructions
5111 // Register Addition
5112 instruct addI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{
5113 match(Set dst (AddI src1 src2));
5114
5115 size(4);
5116 format %{ "add_32 $dst,$src1,$src2\t! int" %}
5117 ins_encode %{
5118 __ add_32($dst$$Register, $src1$$Register, $src2$$Register);
5119 %}
5120 ins_pipe(ialu_reg_reg);
5121 %}
5122
5123 instruct addshlI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
5124 match(Set dst (AddI (LShiftI src1 src2) src3));
5125
5126 size(4);
5127 format %{ "add_32 $dst,$src3,$src1<<$src2\t! int" %}
5128 ins_encode %{
5129 __ add_32($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsl, $src2$$Register));
5130 %}
5131 ins_pipe(ialu_reg_reg);
5132 %}
5133
5134
5135 instruct addshlI_reg_imm_reg(iRegI dst, iRegI src1, immU5 src2, iRegI src3) %{
5136 match(Set dst (AddI (LShiftI src1 src2) src3));
5137
5138 size(4);
5139 format %{ "add_32 $dst,$src3,$src1<<$src2\t! int" %}
5140 ins_encode %{
5141 __ add_32($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsl, $src2$$constant));
5142 %}
5143 ins_pipe(ialu_reg_reg);
5144 %}
5145
5146 instruct addsarI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
5147 match(Set dst (AddI (RShiftI src1 src2) src3));
5148
5149 size(4);
5150 format %{ "add_32 $dst,$src3,$src1>>$src2\t! int" %}
5151 ins_encode %{
5152 __ add_32($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, asr, $src2$$Register));
5153 %}
5154 ins_pipe(ialu_reg_reg);
5155 %}
5156
5157 instruct addsarI_reg_imm_reg(iRegI dst, iRegI src1, immU5 src2, iRegI src3) %{
5158 match(Set dst (AddI (RShiftI src1 src2) src3));
5159
5160 size(4);
5161 format %{ "add_32 $dst,$src3,$src1>>$src2\t! int" %}
5162 ins_encode %{
5163 __ add_32($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, asr, $src2$$constant));
5164 %}
5165 ins_pipe(ialu_reg_reg);
5166 %}
5167
5168 instruct addshrI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
5169 match(Set dst (AddI (URShiftI src1 src2) src3));
5170
5171 size(4);
5172 format %{ "add_32 $dst,$src3,$src1>>>$src2\t! int" %}
5173 ins_encode %{
5174 __ add_32($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsr, $src2$$Register));
5175 %}
5176 ins_pipe(ialu_reg_reg);
5177 %}
5178
5179 instruct addshrI_reg_imm_reg(iRegI dst, iRegI src1, immU5 src2, iRegI src3) %{
5180 match(Set dst (AddI (URShiftI src1 src2) src3));
5181
5182 size(4);
5183 format %{ "add_32 $dst,$src3,$src1>>>$src2\t! int" %}
5184 ins_encode %{
5185 __ add_32($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsr, $src2$$constant));
5186 %}
5187 ins_pipe(ialu_reg_reg);
5188 %}
5189
5190 // Immediate Addition
5191 instruct addI_reg_aimmI(iRegI dst, iRegI src1, aimmI src2) %{
5192 match(Set dst (AddI src1 src2));
5193
5194 size(4);
5195 format %{ "add_32 $dst,$src1,$src2\t! int" %}
5196 ins_encode %{
5197 __ add_32($dst$$Register, $src1$$Register, $src2$$constant);
5198 %}
5199 ins_pipe(ialu_reg_imm);
5200 %}
5201
5202 // Pointer Register Addition
5203 instruct addP_reg_reg(iRegP dst, iRegP src1, iRegX src2) %{
5204 match(Set dst (AddP src1 src2));
5205
5206 size(4);
5207 format %{ "ADD $dst,$src1,$src2\t! ptr" %}
5208 ins_encode %{
5209 __ add($dst$$Register, $src1$$Register, $src2$$Register);
5210 %}
5211 ins_pipe(ialu_reg_reg);
5212 %}
5213
5214
5215 // shifted iRegX operand
5216 operand shiftedX(iRegX src2, shimmX src3) %{
5217 //constraint(ALLOC_IN_RC(sp_ptr_reg));
5218 match(LShiftX src2 src3);
5219
5220 op_cost(1);
5221 format %{ "$src2 << $src3" %}
5222 interface(MEMORY_INTER) %{
5223 base($src2);
5224 index(0xff);
5225 scale($src3);
5226 disp(0x0);
5227 %}
5228 %}
5229
5230 instruct addshlP_reg_reg_imm(iRegP dst, iRegP src1, shiftedX src2) %{
5231 match(Set dst (AddP src1 src2));
5232
5233 ins_cost(DEFAULT_COST * 3/2);
5234 size(4);
5235 format %{ "ADD $dst,$src1,$src2\t! ptr" %}
5236 ins_encode %{
5237 Register base = reg_to_register_object($src2$$base);
5238 __ add($dst$$Register, $src1$$Register, AsmOperand(base, lsl, $src2$$scale));
5239 %}
5240 ins_pipe(ialu_reg_reg);
5241 %}
5242
5243 // Pointer Immediate Addition
5244 instruct addP_reg_aimmX(iRegP dst, iRegP src1, aimmX src2) %{
5245 match(Set dst (AddP src1 src2));
5246
5247 size(4);
5248 format %{ "ADD $dst,$src1,$src2\t! ptr" %}
5249 ins_encode %{
5250 __ add($dst$$Register, $src1$$Register, $src2$$constant);
5251 %}
5252 ins_pipe(ialu_reg_imm);
5253 %}
5254
5255 // Long Addition
5256 instruct addL_reg_reg(iRegL dst, iRegL src1, iRegL src2, flagsReg ccr) %{
5257 match(Set dst (AddL src1 src2));
5258 effect(KILL ccr);
5259 size(8);
5260 format %{ "ADDS $dst.lo,$src1.lo,$src2.lo\t! long\n\t"
5261 "ADC $dst.hi,$src1.hi,$src2.hi" %}
5262 ins_encode %{
5263 __ adds($dst$$Register, $src1$$Register, $src2$$Register);
5264 __ adc($dst$$Register->successor(), $src1$$Register->successor(), $src2$$Register->successor());
5265 %}
5266 ins_pipe(ialu_reg_reg);
5267 %}
5268
5269 // TODO
5270
5271 // TODO: try immLRot2 instead, (0, $con$$constant) becomes
5272 // (hi($con$$constant), lo($con$$constant)) becomes
5273 instruct addL_reg_immRot(iRegL dst, iRegL src1, immLlowRot con, flagsReg ccr) %{
5274 match(Set dst (AddL src1 con));
5275 effect(KILL ccr);
5276 size(8);
5277 format %{ "ADDS $dst.lo,$src1.lo,$con\t! long\n\t"
5278 "ADC $dst.hi,$src1.hi,0" %}
5279 ins_encode %{
5280 __ adds($dst$$Register, $src1$$Register, $con$$constant);
5281 __ adc($dst$$Register->successor(), $src1$$Register->successor(), 0);
5282 %}
5283 ins_pipe(ialu_reg_imm);
5284 %}
5285
5286 // No flag versions for CompareAndSwap{P,I,L} because matcher can't match them
5287
5288 instruct compareAndSwapL_bool(memoryex mem, iRegL oldval, iRegLd newval, iRegI res, iRegLd tmp, flagsReg ccr ) %{
5289 match(Set res (CompareAndSwapL mem (Binary oldval newval)));
5290 effect( KILL ccr, TEMP tmp);
5291 size(32);
5292 format %{ "loop: \n\t"
5293 "LDREXD $tmp, $mem\t! If $oldval==[$mem] Then store $newval into [$mem]\n\t"
5294 "CMP $tmp.lo, $oldval.lo\n\t"
5295 "CMP.eq $tmp.hi, $oldval.hi\n\t"
5296 "STREXD.eq $tmp, $newval, $mem\n\t"
5297 "MOV.ne $tmp, 0 \n\t"
5298 "XORS.eq $tmp,$tmp, 1 \n\t"
5299 "B.eq loop \n\t"
5300 "MOV $res, $tmp" %}
5301 ins_encode %{
5302 Label loop;
5303 __ bind(loop);
5304 __ ldrexd($tmp$$Register, $mem$$Address);
5305 __ cmp($tmp$$Register, $oldval$$Register);
5306 __ cmp($tmp$$Register->successor(), $oldval$$Register->successor(), eq);
5307 __ strexd($tmp$$Register, $newval$$Register, $mem$$Address, eq);
5308 __ mov($tmp$$Register, 0, ne);
5309 __ eors($tmp$$Register, $tmp$$Register, 1, eq);
5310 __ b(loop, eq);
5311 __ mov($res$$Register, $tmp$$Register);
5312 %}
5313 ins_pipe( long_memory_op );
5314 %}
5315
5316
5317 instruct compareAndSwapI_bool(memoryex mem, iRegI oldval, iRegI newval, iRegI res, iRegI tmp, flagsReg ccr ) %{
5318 match(Set res (CompareAndSwapI mem (Binary oldval newval)));
5319 effect( KILL ccr, TEMP tmp);
5320 size(28);
5321 format %{ "loop: \n\t"
5322 "LDREX $tmp, $mem\t! If $oldval==[$mem] Then store $newval into [$mem]\n\t"
5323 "CMP $tmp, $oldval\n\t"
5324 "STREX.eq $tmp, $newval, $mem\n\t"
5325 "MOV.ne $tmp, 0 \n\t"
5326 "XORS.eq $tmp,$tmp, 1 \n\t"
5327 "B.eq loop \n\t"
5328 "MOV $res, $tmp" %}
5329
5330 ins_encode %{
5331 Label loop;
5332 __ bind(loop);
5333 __ ldrex($tmp$$Register,$mem$$Address);
5334 __ cmp($tmp$$Register, $oldval$$Register);
5335 __ strex($tmp$$Register, $newval$$Register, $mem$$Address, eq);
5336 __ mov($tmp$$Register, 0, ne);
5337 __ eors($tmp$$Register, $tmp$$Register, 1, eq);
5338 __ b(loop, eq);
5339 __ mov($res$$Register, $tmp$$Register);
5340 %}
5341 ins_pipe( long_memory_op );
5342 %}
5343
5344 instruct compareAndSwapP_bool(memoryex mem, iRegP oldval, iRegP newval, iRegI res, iRegI tmp, flagsReg ccr ) %{
5345 predicate(!(UseG1GC && n->as_LoadStore()->barrier_data() != 0));
5346 match(Set res (CompareAndSwapP mem (Binary oldval newval)));
5347 effect( KILL ccr, TEMP tmp);
5348 size(28);
5349 format %{ "loop: \n\t"
5350 "LDREX $tmp, $mem\t! If $oldval==[$mem] Then store $newval into [$mem]\n\t"
5351 "CMP $tmp, $oldval\n\t"
5352 "STREX.eq $tmp, $newval, $mem\n\t"
5353 "MOV.ne $tmp, 0 \n\t"
5354 "EORS.eq $tmp,$tmp, 1 \n\t"
5355 "B.eq loop \n\t"
5356 "MOV $res, $tmp" %}
5357
5358 ins_encode %{
5359 Label loop;
5360 __ bind(loop);
5361 __ ldrex($tmp$$Register,$mem$$Address);
5362 __ cmp($tmp$$Register, $oldval$$Register);
5363 __ strex($tmp$$Register, $newval$$Register, $mem$$Address, eq);
5364 __ mov($tmp$$Register, 0, ne);
5365 __ eors($tmp$$Register, $tmp$$Register, 1, eq);
5366 __ b(loop, eq);
5367 __ mov($res$$Register, $tmp$$Register);
5368 %}
5369 ins_pipe( long_memory_op );
5370 %}
5371
5372 instruct xaddI_aimmI_no_res(memoryex mem, aimmI add, Universe dummy, iRegI tmp1, iRegI tmp2, flagsReg ccr) %{
5373 predicate(n->as_LoadStore()->result_not_used());
5374 match(Set dummy (GetAndAddI mem add));
5375 effect(KILL ccr, TEMP tmp1, TEMP tmp2);
5376 size(20);
5377 format %{ "loop: \n\t"
5378 "LDREX $tmp1, $mem\n\t"
5379 "ADD $tmp1, $tmp1, $add\n\t"
5380 "STREX $tmp2, $tmp1, $mem\n\t"
5381 "CMP $tmp2, 0 \n\t"
5382 "B.ne loop \n\t" %}
5383
5384 ins_encode %{
5385 Label loop;
5386 __ bind(loop);
5387 __ ldrex($tmp1$$Register,$mem$$Address);
5388 __ add($tmp1$$Register, $tmp1$$Register, $add$$constant);
5389 __ strex($tmp2$$Register, $tmp1$$Register, $mem$$Address);
5390 __ cmp($tmp2$$Register, 0);
5391 __ b(loop, ne);
5392 %}
5393 ins_pipe( long_memory_op );
5394 %}
5395
5396 instruct xaddI_reg_no_res(memoryex mem, iRegI add, Universe dummy, iRegI tmp1, iRegI tmp2, flagsReg ccr) %{
5397 predicate(n->as_LoadStore()->result_not_used());
5398 match(Set dummy (GetAndAddI mem add));
5399 effect(KILL ccr, TEMP tmp1, TEMP tmp2);
5400 size(20);
5401 format %{ "loop: \n\t"
5402 "LDREX $tmp1, $mem\n\t"
5403 "ADD $tmp1, $tmp1, $add\n\t"
5404 "STREX $tmp2, $tmp1, $mem\n\t"
5405 "CMP $tmp2, 0 \n\t"
5406 "B.ne loop \n\t" %}
5407
5408 ins_encode %{
5409 Label loop;
5410 __ bind(loop);
5411 __ ldrex($tmp1$$Register,$mem$$Address);
5412 __ add($tmp1$$Register, $tmp1$$Register, $add$$Register);
5413 __ strex($tmp2$$Register, $tmp1$$Register, $mem$$Address);
5414 __ cmp($tmp2$$Register, 0);
5415 __ b(loop, ne);
5416 %}
5417 ins_pipe( long_memory_op );
5418 %}
5419
5420 instruct xaddI_aimmI(memoryex mem, aimmI add, iRegI res, iRegI tmp1, iRegI tmp2, flagsReg ccr) %{
5421 match(Set res (GetAndAddI mem add));
5422 effect(KILL ccr, TEMP tmp1, TEMP tmp2, TEMP res);
5423 size(20);
5424 format %{ "loop: \n\t"
5425 "LDREX $res, $mem\n\t"
5426 "ADD $tmp1, $res, $add\n\t"
5427 "STREX $tmp2, $tmp1, $mem\n\t"
5428 "CMP $tmp2, 0 \n\t"
5429 "B.ne loop \n\t" %}
5430
5431 ins_encode %{
5432 Label loop;
5433 __ bind(loop);
5434 __ ldrex($res$$Register,$mem$$Address);
5435 __ add($tmp1$$Register, $res$$Register, $add$$constant);
5436 __ strex($tmp2$$Register, $tmp1$$Register, $mem$$Address);
5437 __ cmp($tmp2$$Register, 0);
5438 __ b(loop, ne);
5439 %}
5440 ins_pipe( long_memory_op );
5441 %}
5442
5443 instruct xaddI_reg(memoryex mem, iRegI add, iRegI res, iRegI tmp1, iRegI tmp2, flagsReg ccr) %{
5444 match(Set res (GetAndAddI mem add));
5445 effect(KILL ccr, TEMP tmp1, TEMP tmp2, TEMP res);
5446 size(20);
5447 format %{ "loop: \n\t"
5448 "LDREX $res, $mem\n\t"
5449 "ADD $tmp1, $res, $add\n\t"
5450 "STREX $tmp2, $tmp1, $mem\n\t"
5451 "CMP $tmp2, 0 \n\t"
5452 "B.ne loop \n\t" %}
5453
5454 ins_encode %{
5455 Label loop;
5456 __ bind(loop);
5457 __ ldrex($res$$Register,$mem$$Address);
5458 __ add($tmp1$$Register, $res$$Register, $add$$Register);
5459 __ strex($tmp2$$Register, $tmp1$$Register, $mem$$Address);
5460 __ cmp($tmp2$$Register, 0);
5461 __ b(loop, ne);
5462 %}
5463 ins_pipe( long_memory_op );
5464 %}
5465
5466 instruct xaddL_reg_no_res(memoryex mem, iRegL add, Universe dummy, iRegLd tmp1, iRegI tmp2, flagsReg ccr) %{
5467 predicate(n->as_LoadStore()->result_not_used());
5468 match(Set dummy (GetAndAddL mem add));
5469 effect( KILL ccr, TEMP tmp1, TEMP tmp2);
5470 size(24);
5471 format %{ "loop: \n\t"
5472 "LDREXD $tmp1, $mem\n\t"
5473 "ADDS $tmp1.lo, $tmp1.lo, $add.lo\n\t"
5474 "ADC $tmp1.hi, $tmp1.hi, $add.hi\n\t"
5475 "STREXD $tmp2, $tmp1, $mem\n\t"
5476 "CMP $tmp2, 0 \n\t"
5477 "B.ne loop \n\t" %}
5478
5479 ins_encode %{
5480 Label loop;
5481 __ bind(loop);
5482 __ ldrexd($tmp1$$Register, $mem$$Address);
5483 __ adds($tmp1$$Register, $tmp1$$Register, $add$$Register);
5484 __ adc($tmp1$$Register->successor(), $tmp1$$Register->successor(), $add$$Register->successor());
5485 __ strexd($tmp2$$Register, $tmp1$$Register, $mem$$Address);
5486 __ cmp($tmp2$$Register, 0);
5487 __ b(loop, ne);
5488 %}
5489 ins_pipe( long_memory_op );
5490 %}
5491
5492 // TODO: try immLRot2 instead, (0, $con$$constant) becomes
5493 // (hi($con$$constant), lo($con$$constant)) becomes
5494 instruct xaddL_immRot_no_res(memoryex mem, immLlowRot add, Universe dummy, iRegLd tmp1, iRegI tmp2, flagsReg ccr) %{
5495 predicate(n->as_LoadStore()->result_not_used());
5496 match(Set dummy (GetAndAddL mem add));
5497 effect( KILL ccr, TEMP tmp1, TEMP tmp2);
5498 size(24);
5499 format %{ "loop: \n\t"
5500 "LDREXD $tmp1, $mem\n\t"
5501 "ADDS $tmp1.lo, $tmp1.lo, $add\n\t"
5502 "ADC $tmp1.hi, $tmp1.hi, 0\n\t"
5503 "STREXD $tmp2, $tmp1, $mem\n\t"
5504 "CMP $tmp2, 0 \n\t"
5505 "B.ne loop \n\t" %}
5506
5507 ins_encode %{
5508 Label loop;
5509 __ bind(loop);
5510 __ ldrexd($tmp1$$Register, $mem$$Address);
5511 __ adds($tmp1$$Register, $tmp1$$Register, $add$$constant);
5512 __ adc($tmp1$$Register->successor(), $tmp1$$Register->successor(), 0);
5513 __ strexd($tmp2$$Register, $tmp1$$Register, $mem$$Address);
5514 __ cmp($tmp2$$Register, 0);
5515 __ b(loop, ne);
5516 %}
5517 ins_pipe( long_memory_op );
5518 %}
5519
5520 instruct xaddL_reg(memoryex mem, iRegL add, iRegLd res, iRegLd tmp1, iRegI tmp2, flagsReg ccr) %{
5521 match(Set res (GetAndAddL mem add));
5522 effect( KILL ccr, TEMP tmp1, TEMP tmp2, TEMP res);
5523 size(24);
5524 format %{ "loop: \n\t"
5525 "LDREXD $res, $mem\n\t"
5526 "ADDS $tmp1.lo, $res.lo, $add.lo\n\t"
5527 "ADC $tmp1.hi, $res.hi, $add.hi\n\t"
5528 "STREXD $tmp2, $tmp1, $mem\n\t"
5529 "CMP $tmp2, 0 \n\t"
5530 "B.ne loop \n\t" %}
5531
5532 ins_encode %{
5533 Label loop;
5534 __ bind(loop);
5535 __ ldrexd($res$$Register, $mem$$Address);
5536 __ adds($tmp1$$Register, $res$$Register, $add$$Register);
5537 __ adc($tmp1$$Register->successor(), $res$$Register->successor(), $add$$Register->successor());
5538 __ strexd($tmp2$$Register, $tmp1$$Register, $mem$$Address);
5539 __ cmp($tmp2$$Register, 0);
5540 __ b(loop, ne);
5541 %}
5542 ins_pipe( long_memory_op );
5543 %}
5544
5545 // TODO: try immLRot2 instead, (0, $con$$constant) becomes
5546 // (hi($con$$constant), lo($con$$constant)) becomes
5547 instruct xaddL_immRot(memoryex mem, immLlowRot add, iRegLd res, iRegLd tmp1, iRegI tmp2, flagsReg ccr) %{
5548 match(Set res (GetAndAddL mem add));
5549 effect( KILL ccr, TEMP tmp1, TEMP tmp2, TEMP res);
5550 size(24);
5551 format %{ "loop: \n\t"
5552 "LDREXD $res, $mem\n\t"
5553 "ADDS $tmp1.lo, $res.lo, $add\n\t"
5554 "ADC $tmp1.hi, $res.hi, 0\n\t"
5555 "STREXD $tmp2, $tmp1, $mem\n\t"
5556 "CMP $tmp2, 0 \n\t"
5557 "B.ne loop \n\t" %}
5558
5559 ins_encode %{
5560 Label loop;
5561 __ bind(loop);
5562 __ ldrexd($res$$Register, $mem$$Address);
5563 __ adds($tmp1$$Register, $res$$Register, $add$$constant);
5564 __ adc($tmp1$$Register->successor(), $res$$Register->successor(), 0);
5565 __ strexd($tmp2$$Register, $tmp1$$Register, $mem$$Address);
5566 __ cmp($tmp2$$Register, 0);
5567 __ b(loop, ne);
5568 %}
5569 ins_pipe( long_memory_op );
5570 %}
5571
5572 instruct xchgI(memoryex mem, iRegI newval, iRegI res, iRegI tmp, flagsReg ccr) %{
5573 match(Set res (GetAndSetI mem newval));
5574 effect(KILL ccr, TEMP tmp, TEMP res);
5575 size(16);
5576 format %{ "loop: \n\t"
5577 "LDREX $res, $mem\n\t"
5578 "STREX $tmp, $newval, $mem\n\t"
5579 "CMP $tmp, 0 \n\t"
5580 "B.ne loop \n\t" %}
5581
5582 ins_encode %{
5583 Label loop;
5584 __ bind(loop);
5585 __ ldrex($res$$Register,$mem$$Address);
5586 __ strex($tmp$$Register, $newval$$Register, $mem$$Address);
5587 __ cmp($tmp$$Register, 0);
5588 __ b(loop, ne);
5589 %}
5590 ins_pipe( long_memory_op );
5591 %}
5592
5593 instruct xchgL(memoryex mem, iRegLd newval, iRegLd res, iRegI tmp, flagsReg ccr) %{
5594 match(Set res (GetAndSetL mem newval));
5595 effect( KILL ccr, TEMP tmp, TEMP res);
5596 size(16);
5597 format %{ "loop: \n\t"
5598 "LDREXD $res, $mem\n\t"
5599 "STREXD $tmp, $newval, $mem\n\t"
5600 "CMP $tmp, 0 \n\t"
5601 "B.ne loop \n\t" %}
5602
5603 ins_encode %{
5604 Label loop;
5605 __ bind(loop);
5606 __ ldrexd($res$$Register, $mem$$Address);
5607 __ strexd($tmp$$Register, $newval$$Register, $mem$$Address);
5608 __ cmp($tmp$$Register, 0);
5609 __ b(loop, ne);
5610 %}
5611 ins_pipe( long_memory_op );
5612 %}
5613
5614 instruct xchgP(memoryex mem, iRegP newval, iRegP res, iRegI tmp, flagsReg ccr) %{
5615 predicate(!(UseG1GC && n->as_LoadStore()->barrier_data() != 0));
5616 match(Set res (GetAndSetP mem newval));
5617 effect(KILL ccr, TEMP tmp, TEMP res);
5618 size(16);
5619 format %{ "loop: \n\t"
5620 "LDREX $res, $mem\n\t"
5621 "STREX $tmp, $newval, $mem\n\t"
5622 "CMP $tmp, 0 \n\t"
5623 "B.ne loop \n\t" %}
5624
5625 ins_encode %{
5626 Label loop;
5627 __ bind(loop);
5628 __ ldrex($res$$Register,$mem$$Address);
5629 __ strex($tmp$$Register, $newval$$Register, $mem$$Address);
5630 __ cmp($tmp$$Register, 0);
5631 __ b(loop, ne);
5632 %}
5633 ins_pipe( long_memory_op );
5634 %}
5635
5636 //---------------------
5637 // Subtraction Instructions
5638 // Register Subtraction
5639 instruct subI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{
5640 match(Set dst (SubI src1 src2));
5641
5642 size(4);
5643 format %{ "sub_32 $dst,$src1,$src2\t! int" %}
5644 ins_encode %{
5645 __ sub_32($dst$$Register, $src1$$Register, $src2$$Register);
5646 %}
5647 ins_pipe(ialu_reg_reg);
5648 %}
5649
5650 instruct subshlI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
5651 match(Set dst (SubI src1 (LShiftI src2 src3)));
5652
5653 size(4);
5654 format %{ "SUB $dst,$src1,$src2<<$src3" %}
5655 ins_encode %{
5656 __ sub($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$Register));
5657 %}
5658 ins_pipe(ialu_reg_reg);
5659 %}
5660
5661 instruct subshlI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{
5662 match(Set dst (SubI src1 (LShiftI src2 src3)));
5663
5664 size(4);
5665 format %{ "sub_32 $dst,$src1,$src2<<$src3\t! int" %}
5666 ins_encode %{
5667 __ sub_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$constant));
5668 %}
5669 ins_pipe(ialu_reg_reg);
5670 %}
5671
5672 instruct subsarI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
5673 match(Set dst (SubI src1 (RShiftI src2 src3)));
5674
5675 size(4);
5676 format %{ "SUB $dst,$src1,$src2>>$src3" %}
5677 ins_encode %{
5678 __ sub($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$Register));
5679 %}
5680 ins_pipe(ialu_reg_reg);
5681 %}
5682
5683 instruct subsarI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{
5684 match(Set dst (SubI src1 (RShiftI src2 src3)));
5685
5686 size(4);
5687 format %{ "sub_32 $dst,$src1,$src2>>$src3\t! int" %}
5688 ins_encode %{
5689 __ sub_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$constant));
5690 %}
5691 ins_pipe(ialu_reg_reg);
5692 %}
5693
5694 instruct subshrI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
5695 match(Set dst (SubI src1 (URShiftI src2 src3)));
5696
5697 size(4);
5698 format %{ "SUB $dst,$src1,$src2>>>$src3" %}
5699 ins_encode %{
5700 __ sub($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$Register));
5701 %}
5702 ins_pipe(ialu_reg_reg);
5703 %}
5704
5705 instruct subshrI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{
5706 match(Set dst (SubI src1 (URShiftI src2 src3)));
5707
5708 size(4);
5709 format %{ "sub_32 $dst,$src1,$src2>>>$src3\t! int" %}
5710 ins_encode %{
5711 __ sub_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$constant));
5712 %}
5713 ins_pipe(ialu_reg_reg);
5714 %}
5715
5716 instruct rsbshlI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
5717 match(Set dst (SubI (LShiftI src1 src2) src3));
5718
5719 size(4);
5720 format %{ "RSB $dst,$src3,$src1<<$src2" %}
5721 ins_encode %{
5722 __ rsb($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsl, $src2$$Register));
5723 %}
5724 ins_pipe(ialu_reg_reg);
5725 %}
5726
5727 instruct rsbshlI_reg_imm_reg(iRegI dst, iRegI src1, immU5 src2, iRegI src3) %{
5728 match(Set dst (SubI (LShiftI src1 src2) src3));
5729
5730 size(4);
5731 format %{ "RSB $dst,$src3,$src1<<$src2" %}
5732 ins_encode %{
5733 __ rsb($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsl, $src2$$constant));
5734 %}
5735 ins_pipe(ialu_reg_reg);
5736 %}
5737
5738 instruct rsbsarI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
5739 match(Set dst (SubI (RShiftI src1 src2) src3));
5740
5741 size(4);
5742 format %{ "RSB $dst,$src3,$src1>>$src2" %}
5743 ins_encode %{
5744 __ rsb($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, asr, $src2$$Register));
5745 %}
5746 ins_pipe(ialu_reg_reg);
5747 %}
5748
5749 instruct rsbsarI_reg_imm_reg(iRegI dst, iRegI src1, immU5 src2, iRegI src3) %{
5750 match(Set dst (SubI (RShiftI src1 src2) src3));
5751
5752 size(4);
5753 format %{ "RSB $dst,$src3,$src1>>$src2" %}
5754 ins_encode %{
5755 __ rsb($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, asr, $src2$$constant));
5756 %}
5757 ins_pipe(ialu_reg_reg);
5758 %}
5759
5760 instruct rsbshrI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
5761 match(Set dst (SubI (URShiftI src1 src2) src3));
5762
5763 size(4);
5764 format %{ "RSB $dst,$src3,$src1>>>$src2" %}
5765 ins_encode %{
5766 __ rsb($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsr, $src2$$Register));
5767 %}
5768 ins_pipe(ialu_reg_reg);
5769 %}
5770
5771 instruct rsbshrI_reg_imm_reg(iRegI dst, iRegI src1, immU5 src2, iRegI src3) %{
5772 match(Set dst (SubI (URShiftI src1 src2) src3));
5773
5774 size(4);
5775 format %{ "RSB $dst,$src3,$src1>>>$src2" %}
5776 ins_encode %{
5777 __ rsb($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsr, $src2$$constant));
5778 %}
5779 ins_pipe(ialu_reg_reg);
5780 %}
5781
5782 // Immediate Subtraction
5783 instruct subI_reg_aimmI(iRegI dst, iRegI src1, aimmI src2) %{
5784 match(Set dst (SubI src1 src2));
5785
5786 size(4);
5787 format %{ "sub_32 $dst,$src1,$src2\t! int" %}
5788 ins_encode %{
5789 __ sub_32($dst$$Register, $src1$$Register, $src2$$constant);
5790 %}
5791 ins_pipe(ialu_reg_imm);
5792 %}
5793
5794 instruct subI_reg_immRotneg(iRegI dst, iRegI src1, aimmIneg src2) %{
5795 match(Set dst (AddI src1 src2));
5796
5797 size(4);
5798 format %{ "sub_32 $dst,$src1,-($src2)\t! int" %}
5799 ins_encode %{
5800 __ sub_32($dst$$Register, $src1$$Register, -$src2$$constant);
5801 %}
5802 ins_pipe(ialu_reg_imm);
5803 %}
5804
5805 instruct subI_immRot_reg(iRegI dst, immIRot src1, iRegI src2) %{
5806 match(Set dst (SubI src1 src2));
5807
5808 size(4);
5809 format %{ "RSB $dst,$src2,src1" %}
5810 ins_encode %{
5811 __ rsb($dst$$Register, $src2$$Register, $src1$$constant);
5812 %}
5813 ins_pipe(ialu_zero_reg);
5814 %}
5815
5816 // Register Subtraction
5817 instruct subL_reg_reg(iRegL dst, iRegL src1, iRegL src2, flagsReg icc ) %{
5818 match(Set dst (SubL src1 src2));
5819 effect (KILL icc);
5820
5821 size(8);
5822 format %{ "SUBS $dst.lo,$src1.lo,$src2.lo\t! long\n\t"
5823 "SBC $dst.hi,$src1.hi,$src2.hi" %}
5824 ins_encode %{
5825 __ subs($dst$$Register, $src1$$Register, $src2$$Register);
5826 __ sbc($dst$$Register->successor(), $src1$$Register->successor(), $src2$$Register->successor());
5827 %}
5828 ins_pipe(ialu_reg_reg);
5829 %}
5830
5831 // TODO
5832
5833 // Immediate Subtraction
5834 // TODO: try immLRot2 instead, (0, $con$$constant) becomes
5835 // (hi($con$$constant), lo($con$$constant)) becomes
5836 instruct subL_reg_immRot(iRegL dst, iRegL src1, immLlowRot con, flagsReg icc) %{
5837 match(Set dst (SubL src1 con));
5838 effect (KILL icc);
5839
5840 size(8);
5841 format %{ "SUB $dst.lo,$src1.lo,$con\t! long\n\t"
5842 "SBC $dst.hi,$src1.hi,0" %}
5843 ins_encode %{
5844 __ subs($dst$$Register, $src1$$Register, $con$$constant);
5845 __ sbc($dst$$Register->successor(), $src1$$Register->successor(), 0);
5846 %}
5847 ins_pipe(ialu_reg_imm);
5848 %}
5849
5850 // Long negation
5851 instruct negL_reg_reg(iRegL dst, immL0 zero, iRegL src2, flagsReg icc) %{
5852 match(Set dst (SubL zero src2));
5853 effect (KILL icc);
5854
5855 size(8);
5856 format %{ "RSBS $dst.lo,$src2.lo,0\t! long\n\t"
5857 "RSC $dst.hi,$src2.hi,0" %}
5858 ins_encode %{
5859 __ rsbs($dst$$Register, $src2$$Register, 0);
5860 __ rsc($dst$$Register->successor(), $src2$$Register->successor(), 0);
5861 %}
5862 ins_pipe(ialu_zero_reg);
5863 %}
5864
5865 // Multiplication Instructions
5866 // Integer Multiplication
5867 // Register Multiplication
5868 instruct mulI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{
5869 match(Set dst (MulI src1 src2));
5870
5871 size(4);
5872 format %{ "mul_32 $dst,$src1,$src2" %}
5873 ins_encode %{
5874 __ mul_32($dst$$Register, $src1$$Register, $src2$$Register);
5875 %}
5876 ins_pipe(imul_reg_reg);
5877 %}
5878
5879 instruct mulL_lo1_hi2(iRegL dst, iRegL src1, iRegL src2) %{
5880 effect(DEF dst, USE src1, USE src2);
5881 size(4);
5882 format %{ "MUL $dst.hi,$src1.lo,$src2.hi\t! long" %}
5883 ins_encode %{
5884 __ mul($dst$$Register->successor(), $src1$$Register, $src2$$Register->successor());
5885 %}
5886 ins_pipe(imul_reg_reg);
5887 %}
5888
5889 instruct mulL_hi1_lo2(iRegL dst, iRegL src1, iRegL src2) %{
5890 effect(USE_DEF dst, USE src1, USE src2);
5891 size(8);
5892 format %{ "MLA $dst.hi,$src1.hi,$src2.lo,$dst.hi\t! long\n\t"
5893 "MOV $dst.lo, 0"%}
5894 ins_encode %{
5895 __ mla($dst$$Register->successor(), $src1$$Register->successor(), $src2$$Register, $dst$$Register->successor());
5896 __ mov($dst$$Register, 0);
5897 %}
5898 ins_pipe(imul_reg_reg);
5899 %}
5900
5901 instruct mulL_lo1_lo2(iRegL dst, iRegL src1, iRegL src2) %{
5902 effect(USE_DEF dst, USE src1, USE src2);
5903 size(4);
5904 format %{ "UMLAL $dst.lo,$dst.hi,$src1,$src2\t! long" %}
5905 ins_encode %{
5906 __ umlal($dst$$Register, $dst$$Register->successor(), $src1$$Register, $src2$$Register);
5907 %}
5908 ins_pipe(imul_reg_reg);
5909 %}
5910
5911 instruct mulL_reg_reg(iRegL dst, iRegL src1, iRegL src2) %{
5912 match(Set dst (MulL src1 src2));
5913
5914 expand %{
5915 mulL_lo1_hi2(dst, src1, src2);
5916 mulL_hi1_lo2(dst, src1, src2);
5917 mulL_lo1_lo2(dst, src1, src2);
5918 %}
5919 %}
5920
5921 // Integer Division
5922 // Register Division
5923 instruct divI_reg_reg(R1RegI dst, R0RegI src1, R2RegI src2, LRRegP lr, flagsReg ccr) %{
5924 match(Set dst (DivI src1 src2));
5925 effect( KILL ccr, KILL src1, KILL src2, KILL lr);
5926 ins_cost((2+71)*DEFAULT_COST);
5927
5928 format %{ "DIV $dst,$src1,$src2 ! call to StubRoutines::Arm::idiv_irem_entry()" %}
5929 ins_encode %{
5930 __ call(StubRoutines::Arm::idiv_irem_entry(), relocInfo::runtime_call_type);
5931 %}
5932 ins_pipe(sdiv_reg_reg);
5933 %}
5934
5935 // Register Long Division
5936 instruct divL_reg_reg(R0R1RegL dst, R2R3RegL src1, R0R1RegL src2) %{
5937 match(Set dst (DivL src1 src2));
5938 effect(CALL);
5939 ins_cost(DEFAULT_COST*71);
5940 format %{ "DIVL $src1,$src2,$dst\t! long ! call to SharedRuntime::ldiv" %}
5941 ins_encode %{
5942 address target = CAST_FROM_FN_PTR(address, SharedRuntime::ldiv);
5943 __ call(target, relocInfo::runtime_call_type);
5944 %}
5945 ins_pipe(divL_reg_reg);
5946 %}
5947
5948 // Integer Remainder
5949 // Register Remainder
5950 instruct modI_reg_reg(R0RegI dst, R0RegI src1, R2RegI src2, R1RegI temp, LRRegP lr, flagsReg ccr ) %{
5951 match(Set dst (ModI src1 src2));
5952 effect( KILL ccr, KILL temp, KILL src2, KILL lr);
5953
5954 format %{ "MODI $dst,$src1,$src2\t ! call to StubRoutines::Arm::idiv_irem_entry" %}
5955 ins_encode %{
5956 __ call(StubRoutines::Arm::idiv_irem_entry(), relocInfo::runtime_call_type);
5957 %}
5958 ins_pipe(sdiv_reg_reg);
5959 %}
5960
5961 // Register Long Remainder
5962 instruct modL_reg_reg(R0R1RegL dst, R2R3RegL src1, R0R1RegL src2) %{
5963 match(Set dst (ModL src1 src2));
5964 effect(CALL);
5965 ins_cost(MEMORY_REF_COST); // FIXME
5966 format %{ "modL $dst,$src1,$src2\t ! call to SharedRuntime::lrem" %}
5967 ins_encode %{
5968 address target = CAST_FROM_FN_PTR(address, SharedRuntime::lrem);
5969 __ call(target, relocInfo::runtime_call_type);
5970 %}
5971 ins_pipe(divL_reg_reg);
5972 %}
5973
5974 // Integer Shift Instructions
5975
5976 // Register Shift Left
5977 instruct shlI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{
5978 match(Set dst (LShiftI src1 src2));
5979
5980 size(4);
5981 format %{ "LSL $dst,$src1,$src2 \n\t" %}
5982 ins_encode %{
5983 __ mov($dst$$Register, AsmOperand($src1$$Register, lsl, $src2$$Register));
5984 %}
5985 ins_pipe(ialu_reg_reg);
5986 %}
5987
5988 // Register Shift Left Immediate
5989 instruct shlI_reg_imm5(iRegI dst, iRegI src1, immU5 src2) %{
5990 match(Set dst (LShiftI src1 src2));
5991
5992 size(4);
5993 format %{ "LSL $dst,$src1,$src2\t! int" %}
5994 ins_encode %{
5995 __ logical_shift_left($dst$$Register, $src1$$Register, $src2$$constant);
5996 %}
5997 ins_pipe(ialu_reg_imm);
5998 %}
5999
6000 instruct shlL_reg_reg_merge_hi(iRegL dst, iRegL src1, iRegI src2) %{
6001 effect(USE_DEF dst, USE src1, USE src2);
6002 size(4);
6003 format %{"OR $dst.hi,$dst.hi,($src1.hi << $src2)" %}
6004 ins_encode %{
6005 __ orr($dst$$Register->successor(), $dst$$Register->successor(), AsmOperand($src1$$Register->successor(), lsl, $src2$$Register));
6006 %}
6007 ins_pipe(ialu_reg_reg);
6008 %}
6009
6010 instruct shlL_reg_reg_merge_lo(iRegL dst, iRegL src1, iRegI src2) %{
6011 effect(USE_DEF dst, USE src1, USE src2);
6012 size(4);
6013 format %{ "LSL $dst.lo,$src1.lo,$src2 \n\t" %}
6014 ins_encode %{
6015 __ mov($dst$$Register, AsmOperand($src1$$Register, lsl, $src2$$Register));
6016 %}
6017 ins_pipe(ialu_reg_reg);
6018 %}
6019
6020 instruct shlL_reg_reg_overlap(iRegL dst, iRegL src1, iRegI src2, flagsReg ccr) %{
6021 effect(DEF dst, USE src1, USE src2, KILL ccr);
6022 size(16);
6023 format %{ "SUBS $dst.hi,$src2,32 \n\t"
6024 "LSLpl $dst.hi,$src1.lo,$dst.hi \n\t"
6025 "RSBmi $dst.hi,$dst.hi,0 \n\t"
6026 "LSRmi $dst.hi,$src1.lo,$dst.hi" %}
6027
6028 ins_encode %{
6029 // $src1$$Register and $dst$$Register->successor() can't be the same
6030 __ subs($dst$$Register->successor(), $src2$$Register, 32);
6031 __ mov($dst$$Register->successor(), AsmOperand($src1$$Register, lsl, $dst$$Register->successor()), pl);
6032 __ rsb($dst$$Register->successor(), $dst$$Register->successor(), 0, mi);
6033 __ mov($dst$$Register->successor(), AsmOperand($src1$$Register, lsr, $dst$$Register->successor()), mi);
6034 %}
6035 ins_pipe(ialu_reg_reg);
6036 %}
6037
6038 instruct shlL_reg_reg(iRegL dst, iRegL src1, iRegI src2) %{
6039 match(Set dst (LShiftL src1 src2));
6040
6041 expand %{
6042 flagsReg ccr;
6043 shlL_reg_reg_overlap(dst, src1, src2, ccr);
6044 shlL_reg_reg_merge_hi(dst, src1, src2);
6045 shlL_reg_reg_merge_lo(dst, src1, src2);
6046 %}
6047 %}
6048
6049 // Register Shift Left Immediate
6050 instruct shlL_reg_imm6(iRegL dst, iRegL src1, immU6Big src2) %{
6051 match(Set dst (LShiftL src1 src2));
6052
6053 size(8);
6054 format %{ "LSL $dst.hi,$src1.lo,$src2-32\t! or mov if $src2==32\n\t"
6055 "MOV $dst.lo, 0" %}
6056 ins_encode %{
6057 if ($src2$$constant == 32) {
6058 __ mov($dst$$Register->successor(), $src1$$Register);
6059 } else {
6060 __ mov($dst$$Register->successor(), AsmOperand($src1$$Register, lsl, $src2$$constant-32));
6061 }
6062 __ mov($dst$$Register, 0);
6063 %}
6064 ins_pipe(ialu_reg_imm);
6065 %}
6066
6067 instruct shlL_reg_imm5(iRegL dst, iRegL src1, immU5 src2) %{
6068 match(Set dst (LShiftL src1 src2));
6069
6070 size(12);
6071 format %{ "LSL $dst.hi,$src1.lo,$src2\n\t"
6072 "OR $dst.hi, $dst.hi, $src1.lo >> 32-$src2\n\t"
6073 "LSL $dst.lo,$src1.lo,$src2" %}
6074 ins_encode %{
6075 // The order of the following 3 instructions matters: src1.lo and
6076 // dst.hi can't overlap but src.hi and dst.hi can.
6077 __ mov($dst$$Register->successor(), AsmOperand($src1$$Register->successor(), lsl, $src2$$constant));
6078 __ orr($dst$$Register->successor(), $dst$$Register->successor(), AsmOperand($src1$$Register, lsr, 32-$src2$$constant));
6079 __ mov($dst$$Register, AsmOperand($src1$$Register, lsl, $src2$$constant));
6080 %}
6081 ins_pipe(ialu_reg_imm);
6082 %}
6083
6084 // Register Arithmetic Shift Right
6085 instruct sarI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{
6086 match(Set dst (RShiftI src1 src2));
6087 size(4);
6088 format %{ "ASR $dst,$src1,$src2\t! int" %}
6089 ins_encode %{
6090 __ mov($dst$$Register, AsmOperand($src1$$Register, asr, $src2$$Register));
6091 %}
6092 ins_pipe(ialu_reg_reg);
6093 %}
6094
6095 // Register Arithmetic Shift Right Immediate
6096 instruct sarI_reg_imm5(iRegI dst, iRegI src1, immU5 src2) %{
6097 match(Set dst (RShiftI src1 src2));
6098
6099 size(4);
6100 format %{ "ASR $dst,$src1,$src2" %}
6101 ins_encode %{
6102 __ mov($dst$$Register, AsmOperand($src1$$Register, asr, $src2$$constant));
6103 %}
6104 ins_pipe(ialu_reg_imm);
6105 %}
6106
6107 // Register Shift Right Arithmetic Long
6108 instruct sarL_reg_reg_merge_lo(iRegL dst, iRegL src1, iRegI src2) %{
6109 effect(USE_DEF dst, USE src1, USE src2);
6110 size(4);
6111 format %{ "OR $dst.lo,$dst.lo,($src1.lo >> $src2)" %}
6112 ins_encode %{
6113 __ orr($dst$$Register, $dst$$Register, AsmOperand($src1$$Register, lsr, $src2$$Register));
6114 %}
6115 ins_pipe(ialu_reg_reg);
6116 %}
6117
6118 instruct sarL_reg_reg_merge_hi(iRegL dst, iRegL src1, iRegI src2) %{
6119 effect(USE_DEF dst, USE src1, USE src2);
6120 size(4);
6121 format %{ "ASR $dst.hi,$src1.hi,$src2 \n\t" %}
6122 ins_encode %{
6123 __ mov($dst$$Register->successor(), AsmOperand($src1$$Register->successor(), asr, $src2$$Register));
6124 %}
6125 ins_pipe(ialu_reg_reg);
6126 %}
6127
6128 instruct sarL_reg_reg_overlap(iRegL dst, iRegL src1, iRegI src2, flagsReg ccr) %{
6129 effect(DEF dst, USE src1, USE src2, KILL ccr);
6130 size(16);
6131 format %{ "SUBS $dst.lo,$src2,32 \n\t"
6132 "ASRpl $dst.lo,$src1.hi,$dst.lo \n\t"
6133 "RSBmi $dst.lo,$dst.lo,0 \n\t"
6134 "LSLmi $dst.lo,$src1.hi,$dst.lo" %}
6135
6136 ins_encode %{
6137 // $src1$$Register->successor() and $dst$$Register can't be the same
6138 __ subs($dst$$Register, $src2$$Register, 32);
6139 __ mov($dst$$Register, AsmOperand($src1$$Register->successor(), asr, $dst$$Register), pl);
6140 __ rsb($dst$$Register, $dst$$Register, 0, mi);
6141 __ mov($dst$$Register, AsmOperand($src1$$Register->successor(), lsl, $dst$$Register), mi);
6142 %}
6143 ins_pipe(ialu_reg_reg);
6144 %}
6145
6146 instruct sarL_reg_reg(iRegL dst, iRegL src1, iRegI src2) %{
6147 match(Set dst (RShiftL src1 src2));
6148
6149 expand %{
6150 flagsReg ccr;
6151 sarL_reg_reg_overlap(dst, src1, src2, ccr);
6152 sarL_reg_reg_merge_lo(dst, src1, src2);
6153 sarL_reg_reg_merge_hi(dst, src1, src2);
6154 %}
6155 %}
6156
6157 // Register Shift Left Immediate
6158 instruct sarL_reg_imm6(iRegL dst, iRegL src1, immU6Big src2) %{
6159 match(Set dst (RShiftL src1 src2));
6160
6161 size(8);
6162 format %{ "ASR $dst.lo,$src1.hi,$src2-32\t! or mov if $src2==32\n\t"
6163 "ASR $dst.hi,$src1.hi, $src2" %}
6164 ins_encode %{
6165 if ($src2$$constant == 32) {
6166 __ mov($dst$$Register, $src1$$Register->successor());
6167 } else{
6168 __ mov($dst$$Register, AsmOperand($src1$$Register->successor(), asr, $src2$$constant-32));
6169 }
6170 __ mov($dst$$Register->successor(), AsmOperand($src1$$Register->successor(), asr, 0));
6171 %}
6172
6173 ins_pipe(ialu_reg_imm);
6174 %}
6175
6176 instruct sarL_reg_imm5(iRegL dst, iRegL src1, immU5 src2) %{
6177 match(Set dst (RShiftL src1 src2));
6178 size(12);
6179 format %{ "LSR $dst.lo,$src1.lo,$src2\n\t"
6180 "OR $dst.lo, $dst.lo, $src1.hi << 32-$src2\n\t"
6181 "ASR $dst.hi,$src1.hi,$src2" %}
6182 ins_encode %{
6183 // The order of the following 3 instructions matters: src1.lo and
6184 // dst.hi can't overlap but src.hi and dst.hi can.
6185 __ mov($dst$$Register, AsmOperand($src1$$Register, lsr, $src2$$constant));
6186 __ orr($dst$$Register, $dst$$Register, AsmOperand($src1$$Register->successor(), lsl, 32-$src2$$constant));
6187 __ mov($dst$$Register->successor(), AsmOperand($src1$$Register->successor(), asr, $src2$$constant));
6188 %}
6189 ins_pipe(ialu_reg_imm);
6190 %}
6191
6192 // Register Shift Right
6193 instruct shrI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{
6194 match(Set dst (URShiftI src1 src2));
6195 size(4);
6196 format %{ "LSR $dst,$src1,$src2\t! int" %}
6197 ins_encode %{
6198 __ mov($dst$$Register, AsmOperand($src1$$Register, lsr, $src2$$Register));
6199 %}
6200 ins_pipe(ialu_reg_reg);
6201 %}
6202
6203 // Register Shift Right Immediate
6204 instruct shrI_reg_imm5(iRegI dst, iRegI src1, immU5 src2) %{
6205 match(Set dst (URShiftI src1 src2));
6206
6207 size(4);
6208 format %{ "LSR $dst,$src1,$src2" %}
6209 ins_encode %{
6210 __ mov($dst$$Register, AsmOperand($src1$$Register, lsr, $src2$$constant));
6211 %}
6212 ins_pipe(ialu_reg_imm);
6213 %}
6214
6215 // Register Shift Right
6216 instruct shrL_reg_reg_merge_lo(iRegL dst, iRegL src1, iRegI src2) %{
6217 effect(USE_DEF dst, USE src1, USE src2);
6218 size(4);
6219 format %{ "OR $dst.lo,$dst,($src1.lo >>> $src2)" %}
6220 ins_encode %{
6221 __ orr($dst$$Register, $dst$$Register, AsmOperand($src1$$Register, lsr, $src2$$Register));
6222 %}
6223 ins_pipe(ialu_reg_reg);
6224 %}
6225
6226 instruct shrL_reg_reg_merge_hi(iRegL dst, iRegL src1, iRegI src2) %{
6227 effect(USE_DEF dst, USE src1, USE src2);
6228 size(4);
6229 format %{ "LSR $dst.hi,$src1.hi,$src2 \n\t" %}
6230 ins_encode %{
6231 __ mov($dst$$Register->successor(), AsmOperand($src1$$Register->successor(), lsr, $src2$$Register));
6232 %}
6233 ins_pipe(ialu_reg_reg);
6234 %}
6235
6236 instruct shrL_reg_reg_overlap(iRegL dst, iRegL src1, iRegI src2, flagsReg ccr) %{
6237 effect(DEF dst, USE src1, USE src2, KILL ccr);
6238 size(16);
6239 format %{ "SUBS $dst,$src2,32 \n\t"
6240 "LSRpl $dst,$src1.hi,$dst \n\t"
6241 "RSBmi $dst,$dst,0 \n\t"
6242 "LSLmi $dst,$src1.hi,$dst" %}
6243
6244 ins_encode %{
6245 // $src1$$Register->successor() and $dst$$Register can't be the same
6246 __ subs($dst$$Register, $src2$$Register, 32);
6247 __ mov($dst$$Register, AsmOperand($src1$$Register->successor(), lsr, $dst$$Register), pl);
6248 __ rsb($dst$$Register, $dst$$Register, 0, mi);
6249 __ mov($dst$$Register, AsmOperand($src1$$Register->successor(), lsl, $dst$$Register), mi);
6250 %}
6251 ins_pipe(ialu_reg_reg);
6252 %}
6253
6254 instruct shrL_reg_reg(iRegL dst, iRegL src1, iRegI src2) %{
6255 match(Set dst (URShiftL src1 src2));
6256
6257 expand %{
6258 flagsReg ccr;
6259 shrL_reg_reg_overlap(dst, src1, src2, ccr);
6260 shrL_reg_reg_merge_lo(dst, src1, src2);
6261 shrL_reg_reg_merge_hi(dst, src1, src2);
6262 %}
6263 %}
6264
6265 // Register Shift Right Immediate
6266 instruct shrL_reg_imm6(iRegL dst, iRegL src1, immU6Big src2) %{
6267 match(Set dst (URShiftL src1 src2));
6268
6269 size(8);
6270 format %{ "LSR $dst.lo,$src1.hi,$src2-32\t! or mov if $src2==32\n\t"
6271 "MOV $dst.hi, 0" %}
6272 ins_encode %{
6273 if ($src2$$constant == 32) {
6274 __ mov($dst$$Register, $src1$$Register->successor());
6275 } else {
6276 __ mov($dst$$Register, AsmOperand($src1$$Register->successor(), lsr, $src2$$constant-32));
6277 }
6278 __ mov($dst$$Register->successor(), 0);
6279 %}
6280
6281 ins_pipe(ialu_reg_imm);
6282 %}
6283
6284 instruct shrL_reg_imm5(iRegL dst, iRegL src1, immU5 src2) %{
6285 match(Set dst (URShiftL src1 src2));
6286
6287 size(12);
6288 format %{ "LSR $dst.lo,$src1.lo,$src2\n\t"
6289 "OR $dst.lo, $dst.lo, $src1.hi << 32-$src2\n\t"
6290 "LSR $dst.hi,$src1.hi,$src2" %}
6291 ins_encode %{
6292 // The order of the following 3 instructions matters: src1.lo and
6293 // dst.hi can't overlap but src.hi and dst.hi can.
6294 __ mov($dst$$Register, AsmOperand($src1$$Register, lsr, $src2$$constant));
6295 __ orr($dst$$Register, $dst$$Register, AsmOperand($src1$$Register->successor(), lsl, 32-$src2$$constant));
6296 __ mov($dst$$Register->successor(), AsmOperand($src1$$Register->successor(), lsr, $src2$$constant));
6297 %}
6298 ins_pipe(ialu_reg_imm);
6299 %}
6300
6301
6302 instruct shrP_reg_imm5(iRegX dst, iRegP src1, immU5 src2) %{
6303 match(Set dst (URShiftI (CastP2X src1) src2));
6304 size(4);
6305 format %{ "LSR $dst,$src1,$src2\t! Cast ptr $src1 to int and shift" %}
6306 ins_encode %{
6307 __ logical_shift_right($dst$$Register, $src1$$Register, $src2$$constant);
6308 %}
6309 ins_pipe(ialu_reg_imm);
6310 %}
6311
6312 //----------Floating Point Arithmetic Instructions-----------------------------
6313
6314 // Add float single precision
6315 instruct addF_reg_reg(regF dst, regF src1, regF src2) %{
6316 match(Set dst (AddF src1 src2));
6317
6318 size(4);
6319 format %{ "FADDS $dst,$src1,$src2" %}
6320 ins_encode %{
6321 __ add_float($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
6322 %}
6323
6324 ins_pipe(faddF_reg_reg);
6325 %}
6326
6327 // Add float double precision
6328 instruct addD_reg_reg(regD dst, regD src1, regD src2) %{
6329 match(Set dst (AddD src1 src2));
6330
6331 size(4);
6332 format %{ "FADDD $dst,$src1,$src2" %}
6333 ins_encode %{
6334 __ add_double($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
6335 %}
6336
6337 ins_pipe(faddD_reg_reg);
6338 %}
6339
6340 // Sub float single precision
6341 instruct subF_reg_reg(regF dst, regF src1, regF src2) %{
6342 match(Set dst (SubF src1 src2));
6343
6344 size(4);
6345 format %{ "FSUBS $dst,$src1,$src2" %}
6346 ins_encode %{
6347 __ sub_float($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
6348 %}
6349 ins_pipe(faddF_reg_reg);
6350 %}
6351
6352 // Sub float double precision
6353 instruct subD_reg_reg(regD dst, regD src1, regD src2) %{
6354 match(Set dst (SubD src1 src2));
6355
6356 size(4);
6357 format %{ "FSUBD $dst,$src1,$src2" %}
6358 ins_encode %{
6359 __ sub_double($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
6360 %}
6361 ins_pipe(faddD_reg_reg);
6362 %}
6363
6364 // Mul float single precision
6365 instruct mulF_reg_reg(regF dst, regF src1, regF src2) %{
6366 match(Set dst (MulF src1 src2));
6367
6368 size(4);
6369 format %{ "FMULS $dst,$src1,$src2" %}
6370 ins_encode %{
6371 __ mul_float($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
6372 %}
6373
6374 ins_pipe(fmulF_reg_reg);
6375 %}
6376
6377 // Mul float double precision
6378 instruct mulD_reg_reg(regD dst, regD src1, regD src2) %{
6379 match(Set dst (MulD src1 src2));
6380
6381 size(4);
6382 format %{ "FMULD $dst,$src1,$src2" %}
6383 ins_encode %{
6384 __ mul_double($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
6385 %}
6386
6387 ins_pipe(fmulD_reg_reg);
6388 %}
6389
6390 // Div float single precision
6391 instruct divF_reg_reg(regF dst, regF src1, regF src2) %{
6392 match(Set dst (DivF src1 src2));
6393
6394 size(4);
6395 format %{ "FDIVS $dst,$src1,$src2" %}
6396 ins_encode %{
6397 __ div_float($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
6398 %}
6399
6400 ins_pipe(fdivF_reg_reg);
6401 %}
6402
6403 // Div float double precision
6404 instruct divD_reg_reg(regD dst, regD src1, regD src2) %{
6405 match(Set dst (DivD src1 src2));
6406
6407 size(4);
6408 format %{ "FDIVD $dst,$src1,$src2" %}
6409 ins_encode %{
6410 __ div_double($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
6411 %}
6412
6413 ins_pipe(fdivD_reg_reg);
6414 %}
6415
6416 // Absolute float double precision
6417 instruct absD_reg(regD dst, regD src) %{
6418 match(Set dst (AbsD src));
6419
6420 size(4);
6421 format %{ "FABSd $dst,$src" %}
6422 ins_encode %{
6423 __ abs_double($dst$$FloatRegister, $src$$FloatRegister);
6424 %}
6425 ins_pipe(faddD_reg);
6426 %}
6427
6428 // Absolute float single precision
6429 instruct absF_reg(regF dst, regF src) %{
6430 match(Set dst (AbsF src));
6431 format %{ "FABSs $dst,$src" %}
6432 ins_encode %{
6433 __ abs_float($dst$$FloatRegister, $src$$FloatRegister);
6434 %}
6435 ins_pipe(faddF_reg);
6436 %}
6437
6438 instruct negF_reg(regF dst, regF src) %{
6439 match(Set dst (NegF src));
6440
6441 size(4);
6442 format %{ "FNEGs $dst,$src" %}
6443 ins_encode %{
6444 __ neg_float($dst$$FloatRegister, $src$$FloatRegister);
6445 %}
6446 ins_pipe(faddF_reg);
6447 %}
6448
6449 instruct negD_reg(regD dst, regD src) %{
6450 match(Set dst (NegD src));
6451
6452 format %{ "FNEGd $dst,$src" %}
6453 ins_encode %{
6454 __ neg_double($dst$$FloatRegister, $src$$FloatRegister);
6455 %}
6456 ins_pipe(faddD_reg);
6457 %}
6458
6459 // Sqrt float double precision
6460 instruct sqrtF_reg_reg(regF dst, regF src) %{
6461 match(Set dst (ConvD2F (SqrtD (ConvF2D src))));
6462
6463 size(4);
6464 format %{ "FSQRTS $dst,$src" %}
6465 ins_encode %{
6466 __ sqrt_float($dst$$FloatRegister, $src$$FloatRegister);
6467 %}
6468 ins_pipe(fdivF_reg_reg);
6469 %}
6470
6471 // Sqrt float double precision
6472 instruct sqrtD_reg_reg(regD dst, regD src) %{
6473 match(Set dst (SqrtD src));
6474
6475 size(4);
6476 format %{ "FSQRTD $dst,$src" %}
6477 ins_encode %{
6478 __ sqrt_double($dst$$FloatRegister, $src$$FloatRegister);
6479 %}
6480 ins_pipe(fdivD_reg_reg);
6481 %}
6482
6483 //----------Logical Instructions-----------------------------------------------
6484 // And Instructions
6485 // Register And
6486 instruct andI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{
6487 match(Set dst (AndI src1 src2));
6488
6489 size(4);
6490 format %{ "and_32 $dst,$src1,$src2" %}
6491 ins_encode %{
6492 __ and_32($dst$$Register, $src1$$Register, $src2$$Register);
6493 %}
6494 ins_pipe(ialu_reg_reg);
6495 %}
6496
6497 instruct andshlI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
6498 match(Set dst (AndI src1 (LShiftI src2 src3)));
6499
6500 size(4);
6501 format %{ "AND $dst,$src1,$src2<<$src3" %}
6502 ins_encode %{
6503 __ andr($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$Register));
6504 %}
6505 ins_pipe(ialu_reg_reg);
6506 %}
6507
6508 instruct andshlI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{
6509 match(Set dst (AndI src1 (LShiftI src2 src3)));
6510
6511 size(4);
6512 format %{ "and_32 $dst,$src1,$src2<<$src3" %}
6513 ins_encode %{
6514 __ and_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$constant));
6515 %}
6516 ins_pipe(ialu_reg_reg);
6517 %}
6518
6519 instruct andsarI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
6520 match(Set dst (AndI src1 (RShiftI src2 src3)));
6521
6522 size(4);
6523 format %{ "AND $dst,$src1,$src2>>$src3" %}
6524 ins_encode %{
6525 __ andr($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$Register));
6526 %}
6527 ins_pipe(ialu_reg_reg);
6528 %}
6529
6530 instruct andsarI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{
6531 match(Set dst (AndI src1 (RShiftI src2 src3)));
6532
6533 size(4);
6534 format %{ "and_32 $dst,$src1,$src2>>$src3" %}
6535 ins_encode %{
6536 __ and_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$constant));
6537 %}
6538 ins_pipe(ialu_reg_reg);
6539 %}
6540
6541 instruct andshrI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
6542 match(Set dst (AndI src1 (URShiftI src2 src3)));
6543
6544 size(4);
6545 format %{ "AND $dst,$src1,$src2>>>$src3" %}
6546 ins_encode %{
6547 __ andr($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$Register));
6548 %}
6549 ins_pipe(ialu_reg_reg);
6550 %}
6551
6552 instruct andshrI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{
6553 match(Set dst (AndI src1 (URShiftI src2 src3)));
6554
6555 size(4);
6556 format %{ "and_32 $dst,$src1,$src2>>>$src3" %}
6557 ins_encode %{
6558 __ and_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$constant));
6559 %}
6560 ins_pipe(ialu_reg_reg);
6561 %}
6562
6563 // Immediate And
6564 instruct andI_reg_limm(iRegI dst, iRegI src1, limmI src2) %{
6565 match(Set dst (AndI src1 src2));
6566
6567 size(4);
6568 format %{ "and_32 $dst,$src1,$src2\t! int" %}
6569 ins_encode %{
6570 __ and_32($dst$$Register, $src1$$Register, $src2$$constant);
6571 %}
6572 ins_pipe(ialu_reg_imm);
6573 %}
6574
6575 instruct andI_reg_limmn(iRegI dst, iRegI src1, limmIn src2) %{
6576 match(Set dst (AndI src1 src2));
6577
6578 size(4);
6579 format %{ "bic $dst,$src1,~$src2\t! int" %}
6580 ins_encode %{
6581 __ bic($dst$$Register, $src1$$Register, ~$src2$$constant);
6582 %}
6583 ins_pipe(ialu_reg_imm);
6584 %}
6585
6586 // Register And Long
6587 instruct andL_reg_reg(iRegL dst, iRegL src1, iRegL src2) %{
6588 match(Set dst (AndL src1 src2));
6589
6590 ins_cost(DEFAULT_COST);
6591 size(8);
6592 format %{ "AND $dst,$src1,$src2\t! long" %}
6593 ins_encode %{
6594 __ andr($dst$$Register, $src1$$Register, $src2$$Register);
6595 __ andr($dst$$Register->successor(), $src1$$Register->successor(), $src2$$Register->successor());
6596 %}
6597 ins_pipe(ialu_reg_reg);
6598 %}
6599
6600 // TODO: try immLRot2 instead, (0, $con$$constant) becomes
6601 // (hi($con$$constant), lo($con$$constant)) becomes
6602 instruct andL_reg_immRot(iRegL dst, iRegL src1, immLlowRot con) %{
6603 match(Set dst (AndL src1 con));
6604 ins_cost(DEFAULT_COST);
6605 size(8);
6606 format %{ "AND $dst,$src1,$con\t! long" %}
6607 ins_encode %{
6608 __ andr($dst$$Register, $src1$$Register, $con$$constant);
6609 __ andr($dst$$Register->successor(), $src1$$Register->successor(), 0);
6610 %}
6611 ins_pipe(ialu_reg_imm);
6612 %}
6613
6614 // Or Instructions
6615 // Register Or
6616 instruct orI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{
6617 match(Set dst (OrI src1 src2));
6618
6619 size(4);
6620 format %{ "orr_32 $dst,$src1,$src2\t! int" %}
6621 ins_encode %{
6622 __ orr_32($dst$$Register, $src1$$Register, $src2$$Register);
6623 %}
6624 ins_pipe(ialu_reg_reg);
6625 %}
6626
6627 instruct orshlI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
6628 match(Set dst (OrI src1 (LShiftI src2 src3)));
6629
6630 size(4);
6631 format %{ "OR $dst,$src1,$src2<<$src3" %}
6632 ins_encode %{
6633 __ orr($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$Register));
6634 %}
6635 ins_pipe(ialu_reg_reg);
6636 %}
6637
6638 instruct orshlI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{
6639 match(Set dst (OrI src1 (LShiftI src2 src3)));
6640
6641 size(4);
6642 format %{ "orr_32 $dst,$src1,$src2<<$src3" %}
6643 ins_encode %{
6644 __ orr_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$constant));
6645 %}
6646 ins_pipe(ialu_reg_reg);
6647 %}
6648
6649 instruct orsarI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
6650 match(Set dst (OrI src1 (RShiftI src2 src3)));
6651
6652 size(4);
6653 format %{ "OR $dst,$src1,$src2>>$src3" %}
6654 ins_encode %{
6655 __ orr($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$Register));
6656 %}
6657 ins_pipe(ialu_reg_reg);
6658 %}
6659
6660 instruct orsarI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{
6661 match(Set dst (OrI src1 (RShiftI src2 src3)));
6662
6663 size(4);
6664 format %{ "orr_32 $dst,$src1,$src2>>$src3" %}
6665 ins_encode %{
6666 __ orr_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$constant));
6667 %}
6668 ins_pipe(ialu_reg_reg);
6669 %}
6670
6671 instruct orshrI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
6672 match(Set dst (OrI src1 (URShiftI src2 src3)));
6673
6674 size(4);
6675 format %{ "OR $dst,$src1,$src2>>>$src3" %}
6676 ins_encode %{
6677 __ orr($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$Register));
6678 %}
6679 ins_pipe(ialu_reg_reg);
6680 %}
6681
6682 instruct orshrI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{
6683 match(Set dst (OrI src1 (URShiftI src2 src3)));
6684
6685 size(4);
6686 format %{ "orr_32 $dst,$src1,$src2>>>$src3" %}
6687 ins_encode %{
6688 __ orr_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$constant));
6689 %}
6690 ins_pipe(ialu_reg_reg);
6691 %}
6692
6693 // Immediate Or
6694 instruct orI_reg_limm(iRegI dst, iRegI src1, limmI src2) %{
6695 match(Set dst (OrI src1 src2));
6696
6697 size(4);
6698 format %{ "orr_32 $dst,$src1,$src2" %}
6699 ins_encode %{
6700 __ orr_32($dst$$Register, $src1$$Register, $src2$$constant);
6701 %}
6702 ins_pipe(ialu_reg_imm);
6703 %}
6704 // TODO: orn_32 with limmIn
6705
6706 // Register Or Long
6707 instruct orL_reg_reg(iRegL dst, iRegL src1, iRegL src2) %{
6708 match(Set dst (OrL src1 src2));
6709
6710 ins_cost(DEFAULT_COST);
6711 size(8);
6712 format %{ "OR $dst.lo,$src1.lo,$src2.lo\t! long\n\t"
6713 "OR $dst.hi,$src1.hi,$src2.hi" %}
6714 ins_encode %{
6715 __ orr($dst$$Register, $src1$$Register, $src2$$Register);
6716 __ orr($dst$$Register->successor(), $src1$$Register->successor(), $src2$$Register->successor());
6717 %}
6718 ins_pipe(ialu_reg_reg);
6719 %}
6720
6721 // TODO: try immLRot2 instead, (0, $con$$constant) becomes
6722 // (hi($con$$constant), lo($con$$constant)) becomes
6723 instruct orL_reg_immRot(iRegL dst, iRegL src1, immLlowRot con) %{
6724 match(Set dst (OrL src1 con));
6725 ins_cost(DEFAULT_COST);
6726 size(8);
6727 format %{ "OR $dst.lo,$src1.lo,$con\t! long\n\t"
6728 "OR $dst.hi,$src1.hi,$con" %}
6729 ins_encode %{
6730 __ orr($dst$$Register, $src1$$Register, $con$$constant);
6731 __ orr($dst$$Register->successor(), $src1$$Register->successor(), 0);
6732 %}
6733 ins_pipe(ialu_reg_imm);
6734 %}
6735
6736 #ifdef TODO
6737 // Use SPRegP to match Rthread (TLS register) without spilling.
6738 // Use store_ptr_RegP to match Rthread (TLS register) without spilling.
6739 // Use sp_ptr_RegP to match Rthread (TLS register) without spilling.
6740 instruct orI_reg_castP2X(iRegI dst, iRegI src1, sp_ptr_RegP src2) %{
6741 match(Set dst (OrI src1 (CastP2X src2)));
6742 size(4);
6743 format %{ "OR $dst,$src1,$src2" %}
6744 ins_encode %{
6745 __ orr($dst$$Register, $src1$$Register, $src2$$Register);
6746 %}
6747 ins_pipe(ialu_reg_reg);
6748 %}
6749 #endif
6750
6751 // Xor Instructions
6752 // Register Xor
6753 instruct xorI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{
6754 match(Set dst (XorI src1 src2));
6755
6756 size(4);
6757 format %{ "eor_32 $dst,$src1,$src2" %}
6758 ins_encode %{
6759 __ eor_32($dst$$Register, $src1$$Register, $src2$$Register);
6760 %}
6761 ins_pipe(ialu_reg_reg);
6762 %}
6763
6764 instruct xorshlI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
6765 match(Set dst (XorI src1 (LShiftI src2 src3)));
6766
6767 size(4);
6768 format %{ "XOR $dst,$src1,$src2<<$src3" %}
6769 ins_encode %{
6770 __ eor($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$Register));
6771 %}
6772 ins_pipe(ialu_reg_reg);
6773 %}
6774
6775 instruct xorshlI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{
6776 match(Set dst (XorI src1 (LShiftI src2 src3)));
6777
6778 size(4);
6779 format %{ "eor_32 $dst,$src1,$src2<<$src3" %}
6780 ins_encode %{
6781 __ eor_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$constant));
6782 %}
6783 ins_pipe(ialu_reg_reg);
6784 %}
6785
6786 instruct xorsarI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
6787 match(Set dst (XorI src1 (RShiftI src2 src3)));
6788
6789 size(4);
6790 format %{ "XOR $dst,$src1,$src2>>$src3" %}
6791 ins_encode %{
6792 __ eor($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$Register));
6793 %}
6794 ins_pipe(ialu_reg_reg);
6795 %}
6796
6797 instruct xorsarI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{
6798 match(Set dst (XorI src1 (RShiftI src2 src3)));
6799
6800 size(4);
6801 format %{ "eor_32 $dst,$src1,$src2>>$src3" %}
6802 ins_encode %{
6803 __ eor_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$constant));
6804 %}
6805 ins_pipe(ialu_reg_reg);
6806 %}
6807
6808 instruct xorshrI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
6809 match(Set dst (XorI src1 (URShiftI src2 src3)));
6810
6811 size(4);
6812 format %{ "XOR $dst,$src1,$src2>>>$src3" %}
6813 ins_encode %{
6814 __ eor($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$Register));
6815 %}
6816 ins_pipe(ialu_reg_reg);
6817 %}
6818
6819 instruct xorshrI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{
6820 match(Set dst (XorI src1 (URShiftI src2 src3)));
6821
6822 size(4);
6823 format %{ "eor_32 $dst,$src1,$src2>>>$src3" %}
6824 ins_encode %{
6825 __ eor_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$constant));
6826 %}
6827 ins_pipe(ialu_reg_reg);
6828 %}
6829
6830 // Immediate Xor
6831 instruct xorI_reg_imm(iRegI dst, iRegI src1, limmI src2) %{
6832 match(Set dst (XorI src1 src2));
6833
6834 size(4);
6835 format %{ "eor_32 $dst,$src1,$src2" %}
6836 ins_encode %{
6837 __ eor_32($dst$$Register, $src1$$Register, $src2$$constant);
6838 %}
6839 ins_pipe(ialu_reg_imm);
6840 %}
6841
6842 // Register Xor Long
6843 instruct xorL_reg_reg(iRegL dst, iRegL src1, iRegL src2) %{
6844 match(Set dst (XorL src1 src2));
6845 ins_cost(DEFAULT_COST);
6846 size(8);
6847 format %{ "XOR $dst.hi,$src1.hi,$src2.hi\t! long\n\t"
6848 "XOR $dst.lo,$src1.lo,$src2.lo\t! long" %}
6849 ins_encode %{
6850 __ eor($dst$$Register, $src1$$Register, $src2$$Register);
6851 __ eor($dst$$Register->successor(), $src1$$Register->successor(), $src2$$Register->successor());
6852 %}
6853 ins_pipe(ialu_reg_reg);
6854 %}
6855
6856 // TODO: try immLRot2 instead, (0, $con$$constant) becomes
6857 // (hi($con$$constant), lo($con$$constant)) becomes
6858 instruct xorL_reg_immRot(iRegL dst, iRegL src1, immLlowRot con) %{
6859 match(Set dst (XorL src1 con));
6860 ins_cost(DEFAULT_COST);
6861 size(8);
6862 format %{ "XOR $dst.hi,$src1.hi,$con\t! long\n\t"
6863 "XOR $dst.lo,$src1.lo,0\t! long" %}
6864 ins_encode %{
6865 __ eor($dst$$Register, $src1$$Register, $con$$constant);
6866 __ eor($dst$$Register->successor(), $src1$$Register->successor(), 0);
6867 %}
6868 ins_pipe(ialu_reg_imm);
6869 %}
6870
6871 instruct cmpLTMask_reg_reg( iRegI dst, iRegI p, iRegI q, flagsReg ccr ) %{
6872 match(Set dst (CmpLTMask p q));
6873 effect( KILL ccr );
6874 ins_cost(DEFAULT_COST*3);
6875 format %{ "CMP $p,$q\n\t"
6876 "MOV $dst, #0\n\t"
6877 "MOV.lt $dst, #-1" %}
6878 ins_encode %{
6879 __ cmp($p$$Register, $q$$Register);
6880 __ mov($dst$$Register, 0);
6881 __ mvn($dst$$Register, 0, lt);
6882 %}
6883 ins_pipe(ialu_reg_reg_ialu);
6884 %}
6885
6886 instruct cmpLTMask_reg_imm( iRegI dst, iRegI p, aimmI q, flagsReg ccr ) %{
6887 match(Set dst (CmpLTMask p q));
6888 effect( KILL ccr );
6889 ins_cost(DEFAULT_COST*3);
6890 format %{ "CMP $p,$q\n\t"
6891 "MOV $dst, #0\n\t"
6892 "MOV.lt $dst, #-1" %}
6893 ins_encode %{
6894 __ cmp($p$$Register, $q$$constant);
6895 __ mov($dst$$Register, 0);
6896 __ mvn($dst$$Register, 0, lt);
6897 %}
6898 ins_pipe(ialu_reg_reg_ialu);
6899 %}
6900
6901 instruct cadd_cmpLTMask3( iRegI p, iRegI q, iRegI y, iRegI z, flagsReg ccr ) %{
6902 match(Set z (AddI (AndI (CmpLTMask p q) y) z));
6903 effect( KILL ccr );
6904 ins_cost(DEFAULT_COST*2);
6905 format %{ "CMP $p,$q\n\t"
6906 "ADD.lt $z,$y,$z" %}
6907 ins_encode %{
6908 __ cmp($p$$Register, $q$$Register);
6909 __ add($z$$Register, $y$$Register, $z$$Register, lt);
6910 %}
6911 ins_pipe( cadd_cmpltmask );
6912 %}
6913
6914 // FIXME: remove unused "dst"
6915 instruct cadd_cmpLTMask4( iRegI dst, iRegI p, aimmI q, iRegI y, iRegI z, flagsReg ccr ) %{
6916 match(Set z (AddI (AndI (CmpLTMask p q) y) z));
6917 effect( KILL ccr );
6918 ins_cost(DEFAULT_COST*2);
6919 format %{ "CMP $p,$q\n\t"
6920 "ADD.lt $z,$y,$z" %}
6921 ins_encode %{
6922 __ cmp($p$$Register, $q$$constant);
6923 __ add($z$$Register, $y$$Register, $z$$Register, lt);
6924 %}
6925 ins_pipe( cadd_cmpltmask );
6926 %}
6927
6928 instruct cadd_cmpLTMask( iRegI p, iRegI q, iRegI y, flagsReg ccr ) %{
6929 match(Set p (AddI (AndI (CmpLTMask p q) y) (SubI p q)));
6930 effect( KILL ccr );
6931 ins_cost(DEFAULT_COST*2);
6932 format %{ "SUBS $p,$p,$q\n\t"
6933 "ADD.lt $p,$y,$p" %}
6934 ins_encode %{
6935 __ subs($p$$Register, $p$$Register, $q$$Register);
6936 __ add($p$$Register, $y$$Register, $p$$Register, lt);
6937 %}
6938 ins_pipe( cadd_cmpltmask );
6939 %}
6940
6941 //----------Arithmetic Conversion Instructions---------------------------------
6942 // The conversions operations are all Alpha sorted. Please keep it that way!
6943
6944 instruct convD2F_reg(regF dst, regD src) %{
6945 match(Set dst (ConvD2F src));
6946 size(4);
6947 format %{ "FCVTSD $dst,$src" %}
6948 ins_encode %{
6949 __ convert_d2f($dst$$FloatRegister, $src$$FloatRegister);
6950 %}
6951 ins_pipe(fcvtD2F);
6952 %}
6953
6954 // Convert a double to an int in a float register.
6955 // If the double is a NAN, stuff a zero in instead.
6956
6957 instruct convD2I_reg_reg(iRegI dst, regD src, regF tmp) %{
6958 match(Set dst (ConvD2I src));
6959 effect( TEMP tmp );
6960 ins_cost(DEFAULT_COST*2 + MEMORY_REF_COST*2 + BRANCH_COST); // FIXME
6961 format %{ "FTOSIZD $tmp,$src\n\t"
6962 "FMRS $dst, $tmp" %}
6963 ins_encode %{
6964 __ ftosizd($tmp$$FloatRegister, $src$$FloatRegister);
6965 __ fmrs($dst$$Register, $tmp$$FloatRegister);
6966 %}
6967 ins_pipe(fcvtD2I);
6968 %}
6969
6970 // Convert a double to a long in a double register.
6971 // If the double is a NAN, stuff a zero in instead.
6972
6973 // Double to Long conversion
6974 instruct convD2L_reg(R0R1RegL dst, regD src) %{
6975 match(Set dst (ConvD2L src));
6976 effect(CALL);
6977 ins_cost(MEMORY_REF_COST); // FIXME
6978 format %{ "convD2L $dst,$src\t ! call to SharedRuntime::d2l" %}
6979 ins_encode %{
6980 #ifndef __ABI_HARD__
6981 __ fmrrd($dst$$Register, $dst$$Register->successor(), $src$$FloatRegister);
6982 #else
6983 if ($src$$FloatRegister != D0) {
6984 __ mov_double(D0, $src$$FloatRegister);
6985 }
6986 #endif
6987 address target = CAST_FROM_FN_PTR(address, SharedRuntime::d2l);
6988 __ call(target, relocInfo::runtime_call_type);
6989 %}
6990 ins_pipe(fcvtD2L);
6991 %}
6992
6993 instruct convF2D_reg(regD dst, regF src) %{
6994 match(Set dst (ConvF2D src));
6995 size(4);
6996 format %{ "FCVTDS $dst,$src" %}
6997 ins_encode %{
6998 __ convert_f2d($dst$$FloatRegister, $src$$FloatRegister);
6999 %}
7000 ins_pipe(fcvtF2D);
7001 %}
7002
7003 instruct convF2I_reg_reg(iRegI dst, regF src, regF tmp) %{
7004 match(Set dst (ConvF2I src));
7005 effect( TEMP tmp );
7006 ins_cost(DEFAULT_COST*2 + MEMORY_REF_COST*2 + BRANCH_COST); // FIXME
7007 size(8);
7008 format %{ "FTOSIZS $tmp,$src\n\t"
7009 "FMRS $dst, $tmp" %}
7010 ins_encode %{
7011 __ ftosizs($tmp$$FloatRegister, $src$$FloatRegister);
7012 __ fmrs($dst$$Register, $tmp$$FloatRegister);
7013 %}
7014 ins_pipe(fcvtF2I);
7015 %}
7016
7017 // Float to Long conversion
7018 instruct convF2L_reg(R0R1RegL dst, regF src, R0RegI arg1) %{
7019 match(Set dst (ConvF2L src));
7020 ins_cost(DEFAULT_COST*2 + MEMORY_REF_COST*2 + BRANCH_COST); // FIXME
7021 effect(CALL);
7022 format %{ "convF2L $dst,$src\t! call to SharedRuntime::f2l" %}
7023 ins_encode %{
7024 #ifndef __ABI_HARD__
7025 __ fmrs($arg1$$Register, $src$$FloatRegister);
7026 #else
7027 if($src$$FloatRegister != S0) {
7028 __ mov_float(S0, $src$$FloatRegister);
7029 }
7030 #endif
7031 address target = CAST_FROM_FN_PTR(address, SharedRuntime::f2l);
7032 __ call(target, relocInfo::runtime_call_type);
7033 %}
7034 ins_pipe(fcvtF2L);
7035 %}
7036
7037 instruct convI2D_reg_reg(iRegI src, regD_low dst) %{
7038 match(Set dst (ConvI2D src));
7039 ins_cost(DEFAULT_COST + MEMORY_REF_COST); // FIXME
7040 size(8);
7041 format %{ "FMSR $dst,$src \n\t"
7042 "FSITOD $dst $dst"%}
7043 ins_encode %{
7044 __ fmsr($dst$$FloatRegister, $src$$Register);
7045 __ fsitod($dst$$FloatRegister, $dst$$FloatRegister);
7046 %}
7047 ins_pipe(fcvtI2D);
7048 %}
7049
7050 instruct convI2F_reg_reg( regF dst, iRegI src ) %{
7051 match(Set dst (ConvI2F src));
7052 ins_cost(DEFAULT_COST + MEMORY_REF_COST); // FIXME
7053 size(8);
7054 format %{ "FMSR $dst,$src \n\t"
7055 "FSITOS $dst, $dst"%}
7056 ins_encode %{
7057 __ fmsr($dst$$FloatRegister, $src$$Register);
7058 __ fsitos($dst$$FloatRegister, $dst$$FloatRegister);
7059 %}
7060 ins_pipe(fcvtI2F);
7061 %}
7062
7063 instruct convI2L_reg(iRegL dst, iRegI src) %{
7064 match(Set dst (ConvI2L src));
7065 size(8);
7066 format %{ "MOV $dst.lo, $src \n\t"
7067 "ASR $dst.hi,$src,31\t! int->long" %}
7068 ins_encode %{
7069 __ mov($dst$$Register, $src$$Register);
7070 __ mov($dst$$Register->successor(), AsmOperand($src$$Register, asr, 31));
7071 %}
7072 ins_pipe(ialu_reg_reg);
7073 %}
7074
7075 // Zero-extend convert int to long
7076 instruct convI2L_reg_zex(iRegL dst, iRegI src, immL_32bits mask ) %{
7077 match(Set dst (AndL (ConvI2L src) mask) );
7078 size(8);
7079 format %{ "MOV $dst.lo,$src.lo\t! zero-extend int to long\n\t"
7080 "MOV $dst.hi, 0"%}
7081 ins_encode %{
7082 __ mov($dst$$Register, $src$$Register);
7083 __ mov($dst$$Register->successor(), 0);
7084 %}
7085 ins_pipe(ialu_reg_reg);
7086 %}
7087
7088 // Zero-extend long
7089 instruct zerox_long(iRegL dst, iRegL src, immL_32bits mask ) %{
7090 match(Set dst (AndL src mask) );
7091 size(8);
7092 format %{ "MOV $dst.lo,$src.lo\t! zero-extend long\n\t"
7093 "MOV $dst.hi, 0"%}
7094 ins_encode %{
7095 __ mov($dst$$Register, $src$$Register);
7096 __ mov($dst$$Register->successor(), 0);
7097 %}
7098 ins_pipe(ialu_reg_reg);
7099 %}
7100
7101 instruct MoveF2I_reg_reg(iRegI dst, regF src) %{
7102 match(Set dst (MoveF2I src));
7103 effect(DEF dst, USE src);
7104 ins_cost(MEMORY_REF_COST); // FIXME
7105
7106 size(4);
7107 format %{ "FMRS $dst,$src\t! MoveF2I" %}
7108 ins_encode %{
7109 __ fmrs($dst$$Register, $src$$FloatRegister);
7110 %}
7111 ins_pipe(iload_mem); // FIXME
7112 %}
7113
7114 instruct MoveI2F_reg_reg(regF dst, iRegI src) %{
7115 match(Set dst (MoveI2F src));
7116 ins_cost(MEMORY_REF_COST); // FIXME
7117
7118 size(4);
7119 format %{ "FMSR $dst,$src\t! MoveI2F" %}
7120 ins_encode %{
7121 __ fmsr($dst$$FloatRegister, $src$$Register);
7122 %}
7123 ins_pipe(iload_mem); // FIXME
7124 %}
7125
7126 instruct MoveD2L_reg_reg(iRegL dst, regD src) %{
7127 match(Set dst (MoveD2L src));
7128 effect(DEF dst, USE src);
7129 ins_cost(MEMORY_REF_COST); // FIXME
7130
7131 size(4);
7132 format %{ "FMRRD $dst,$src\t! MoveD2L" %}
7133 ins_encode %{
7134 __ fmrrd($dst$$Register, $dst$$Register->successor(), $src$$FloatRegister);
7135 %}
7136 ins_pipe(iload_mem); // FIXME
7137 %}
7138
7139 instruct MoveL2D_reg_reg(regD dst, iRegL src) %{
7140 match(Set dst (MoveL2D src));
7141 effect(DEF dst, USE src);
7142 ins_cost(MEMORY_REF_COST); // FIXME
7143
7144 size(4);
7145 format %{ "FMDRR $dst,$src\t! MoveL2D" %}
7146 ins_encode %{
7147 __ fmdrr($dst$$FloatRegister, $src$$Register, $src$$Register->successor());
7148 %}
7149 ins_pipe(ialu_reg_reg); // FIXME
7150 %}
7151
7152 //-----------
7153 // Long to Double conversion
7154
7155 // Magic constant, 0x43300000
7156 instruct loadConI_x43300000(iRegI dst) %{
7157 effect(DEF dst);
7158 size(8);
7159 format %{ "MOV_SLOW $dst,0x43300000\t! 2^52" %}
7160 ins_encode %{
7161 __ mov_slow($dst$$Register, 0x43300000);
7162 %}
7163 ins_pipe(ialu_none);
7164 %}
7165
7166 // Magic constant, 0x41f00000
7167 instruct loadConI_x41f00000(iRegI dst) %{
7168 effect(DEF dst);
7169 size(8);
7170 format %{ "MOV_SLOW $dst, 0x41f00000\t! 2^32" %}
7171 ins_encode %{
7172 __ mov_slow($dst$$Register, 0x41f00000);
7173 %}
7174 ins_pipe(ialu_none);
7175 %}
7176
7177 instruct loadConI_x0(iRegI dst) %{
7178 effect(DEF dst);
7179 size(4);
7180 format %{ "MOV $dst, 0x0\t! 0" %}
7181 ins_encode %{
7182 __ mov($dst$$Register, 0);
7183 %}
7184 ins_pipe(ialu_none);
7185 %}
7186
7187 // Construct a double from two float halves
7188 instruct regDHi_regDLo_to_regD(regD_low dst, regD_low src1, regD_low src2) %{
7189 effect(DEF dst, USE src1, USE src2);
7190 size(8);
7191 format %{ "FCPYS $dst.hi,$src1.hi\n\t"
7192 "FCPYS $dst.lo,$src2.lo" %}
7193 ins_encode %{
7194 __ fcpys($dst$$FloatRegister->successor(), $src1$$FloatRegister->successor());
7195 __ fcpys($dst$$FloatRegister, $src2$$FloatRegister);
7196 %}
7197 ins_pipe(faddD_reg_reg);
7198 %}
7199
7200 // Convert integer in high half of a double register (in the lower half of
7201 // the double register file) to double
7202 instruct convI2D_regDHi_regD(regD dst, regD_low src) %{
7203 effect(DEF dst, USE src);
7204 size(4);
7205 format %{ "FSITOD $dst,$src" %}
7206 ins_encode %{
7207 __ fsitod($dst$$FloatRegister, $src$$FloatRegister->successor());
7208 %}
7209 ins_pipe(fcvtLHi2D);
7210 %}
7211
7212 // Add float double precision
7213 instruct addD_regD_regD(regD dst, regD src1, regD src2) %{
7214 effect(DEF dst, USE src1, USE src2);
7215 size(4);
7216 format %{ "FADDD $dst,$src1,$src2" %}
7217 ins_encode %{
7218 __ add_double($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
7219 %}
7220 ins_pipe(faddD_reg_reg);
7221 %}
7222
7223 // Sub float double precision
7224 instruct subD_regD_regD(regD dst, regD src1, regD src2) %{
7225 effect(DEF dst, USE src1, USE src2);
7226 size(4);
7227 format %{ "FSUBD $dst,$src1,$src2" %}
7228 ins_encode %{
7229 __ sub_double($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
7230 %}
7231 ins_pipe(faddD_reg_reg);
7232 %}
7233
7234 // Mul float double precision
7235 instruct mulD_regD_regD(regD dst, regD src1, regD src2) %{
7236 effect(DEF dst, USE src1, USE src2);
7237 size(4);
7238 format %{ "FMULD $dst,$src1,$src2" %}
7239 ins_encode %{
7240 __ mul_double($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
7241 %}
7242 ins_pipe(fmulD_reg_reg);
7243 %}
7244
7245 instruct regL_to_regD(regD dst, iRegL src) %{
7246 // No match rule to avoid chain rule match.
7247 effect(DEF dst, USE src);
7248 ins_cost(MEMORY_REF_COST);
7249 size(4);
7250 format %{ "FMDRR $dst,$src\t! regL to regD" %}
7251 ins_encode %{
7252 __ fmdrr($dst$$FloatRegister, $src$$Register, $src$$Register->successor());
7253 %}
7254 ins_pipe(ialu_reg_reg); // FIXME
7255 %}
7256
7257 instruct regI_regI_to_regD(regD dst, iRegI src1, iRegI src2) %{
7258 // No match rule to avoid chain rule match.
7259 effect(DEF dst, USE src1, USE src2);
7260 ins_cost(MEMORY_REF_COST);
7261 size(4);
7262 format %{ "FMDRR $dst,$src1,$src2\t! regI,regI to regD" %}
7263 ins_encode %{
7264 __ fmdrr($dst$$FloatRegister, $src1$$Register, $src2$$Register);
7265 %}
7266 ins_pipe(ialu_reg_reg); // FIXME
7267 %}
7268
7269 instruct convL2D_reg_slow_fxtof(regD dst, iRegL src) %{
7270 match(Set dst (ConvL2D src));
7271 ins_cost(DEFAULT_COST*8 + MEMORY_REF_COST*6); // FIXME
7272
7273 expand %{
7274 regD_low tmpsrc;
7275 iRegI ix43300000;
7276 iRegI ix41f00000;
7277 iRegI ix0;
7278 regD_low dx43300000;
7279 regD dx41f00000;
7280 regD tmp1;
7281 regD_low tmp2;
7282 regD tmp3;
7283 regD tmp4;
7284
7285 regL_to_regD(tmpsrc, src);
7286
7287 loadConI_x43300000(ix43300000);
7288 loadConI_x41f00000(ix41f00000);
7289 loadConI_x0(ix0);
7290
7291 regI_regI_to_regD(dx43300000, ix0, ix43300000);
7292 regI_regI_to_regD(dx41f00000, ix0, ix41f00000);
7293
7294 convI2D_regDHi_regD(tmp1, tmpsrc);
7295 regDHi_regDLo_to_regD(tmp2, dx43300000, tmpsrc);
7296 subD_regD_regD(tmp3, tmp2, dx43300000);
7297 mulD_regD_regD(tmp4, tmp1, dx41f00000);
7298 addD_regD_regD(dst, tmp3, tmp4);
7299 %}
7300 %}
7301
7302 instruct convL2I_reg(iRegI dst, iRegL src) %{
7303 match(Set dst (ConvL2I src));
7304 size(4);
7305 format %{ "MOV $dst,$src.lo\t! long->int" %}
7306 ins_encode %{
7307 __ mov($dst$$Register, $src$$Register);
7308 %}
7309 ins_pipe(ialu_move_reg_I_to_L);
7310 %}
7311
7312 // Register Shift Right Immediate
7313 instruct shrL_reg_imm6_L2I(iRegI dst, iRegL src, immI_32_63 cnt) %{
7314 match(Set dst (ConvL2I (RShiftL src cnt)));
7315 size(4);
7316 format %{ "ASR $dst,$src.hi,($cnt - 32)\t! long->int or mov if $cnt==32" %}
7317 ins_encode %{
7318 if ($cnt$$constant == 32) {
7319 __ mov($dst$$Register, $src$$Register->successor());
7320 } else {
7321 __ mov($dst$$Register, AsmOperand($src$$Register->successor(), asr, $cnt$$constant - 32));
7322 }
7323 %}
7324 ins_pipe(ialu_reg_imm);
7325 %}
7326
7327
7328 //----------Control Flow Instructions------------------------------------------
7329 // Compare Instructions
7330 // Compare Integers
7331 instruct compI_iReg(flagsReg icc, iRegI op1, iRegI op2) %{
7332 match(Set icc (CmpI op1 op2));
7333 effect( DEF icc, USE op1, USE op2 );
7334
7335 size(4);
7336 format %{ "cmp_32 $op1,$op2\t! int" %}
7337 ins_encode %{
7338 __ cmp_32($op1$$Register, $op2$$Register);
7339 %}
7340 ins_pipe(ialu_cconly_reg_reg);
7341 %}
7342
7343 #ifdef _LP64
7344 // Compare compressed pointers
7345 instruct compN_reg2(flagsRegU icc, iRegN op1, iRegN op2) %{
7346 match(Set icc (CmpN op1 op2));
7347 effect( DEF icc, USE op1, USE op2 );
7348
7349 size(4);
7350 format %{ "cmp_32 $op1,$op2\t! int" %}
7351 ins_encode %{
7352 __ cmp_32($op1$$Register, $op2$$Register);
7353 %}
7354 ins_pipe(ialu_cconly_reg_reg);
7355 %}
7356 #endif
7357
7358 instruct compU_iReg(flagsRegU icc, iRegI op1, iRegI op2) %{
7359 match(Set icc (CmpU op1 op2));
7360
7361 size(4);
7362 format %{ "cmp_32 $op1,$op2\t! unsigned int" %}
7363 ins_encode %{
7364 __ cmp_32($op1$$Register, $op2$$Register);
7365 %}
7366 ins_pipe(ialu_cconly_reg_reg);
7367 %}
7368
7369 instruct compI_iReg_immneg(flagsReg icc, iRegI op1, aimmIneg op2) %{
7370 match(Set icc (CmpI op1 op2));
7371 effect( DEF icc, USE op1 );
7372
7373 size(4);
7374 format %{ "cmn_32 $op1,-$op2\t! int" %}
7375 ins_encode %{
7376 __ cmn_32($op1$$Register, -$op2$$constant);
7377 %}
7378 ins_pipe(ialu_cconly_reg_imm);
7379 %}
7380
7381 instruct compI_iReg_imm(flagsReg icc, iRegI op1, aimmI op2) %{
7382 match(Set icc (CmpI op1 op2));
7383 effect( DEF icc, USE op1 );
7384
7385 size(4);
7386 format %{ "cmp_32 $op1,$op2\t! int" %}
7387 ins_encode %{
7388 __ cmp_32($op1$$Register, $op2$$constant);
7389 %}
7390 ins_pipe(ialu_cconly_reg_imm);
7391 %}
7392
7393 instruct testI_reg_reg( flagsReg_EQNELTGE icc, iRegI op1, iRegI op2, immI0 zero ) %{
7394 match(Set icc (CmpI (AndI op1 op2) zero));
7395 size(4);
7396 format %{ "tst_32 $op2,$op1" %}
7397
7398 ins_encode %{
7399 __ tst_32($op1$$Register, $op2$$Register);
7400 %}
7401 ins_pipe(ialu_cconly_reg_reg_zero);
7402 %}
7403
7404 instruct testshlI_reg_reg_reg( flagsReg_EQNELTGE icc, iRegI op1, iRegI op2, iRegI op3, immI0 zero ) %{
7405 match(Set icc (CmpI (AndI op1 (LShiftI op2 op3)) zero));
7406 size(4);
7407 format %{ "TST $op2,$op1<<$op3" %}
7408
7409 ins_encode %{
7410 __ tst($op1$$Register, AsmOperand($op2$$Register, lsl, $op3$$Register));
7411 %}
7412 ins_pipe(ialu_cconly_reg_reg_zero);
7413 %}
7414
7415 instruct testshlI_reg_reg_imm( flagsReg_EQNELTGE icc, iRegI op1, iRegI op2, immU5 op3, immI0 zero ) %{
7416 match(Set icc (CmpI (AndI op1 (LShiftI op2 op3)) zero));
7417 size(4);
7418 format %{ "tst_32 $op2,$op1<<$op3" %}
7419
7420 ins_encode %{
7421 __ tst_32($op1$$Register, AsmOperand($op2$$Register, lsl, $op3$$constant));
7422 %}
7423 ins_pipe(ialu_cconly_reg_reg_zero);
7424 %}
7425
7426 instruct testsarI_reg_reg_reg( flagsReg_EQNELTGE icc, iRegI op1, iRegI op2, iRegI op3, immI0 zero ) %{
7427 match(Set icc (CmpI (AndI op1 (RShiftI op2 op3)) zero));
7428 size(4);
7429 format %{ "TST $op2,$op1<<$op3" %}
7430
7431 ins_encode %{
7432 __ tst($op1$$Register, AsmOperand($op2$$Register, asr, $op3$$Register));
7433 %}
7434 ins_pipe(ialu_cconly_reg_reg_zero);
7435 %}
7436
7437 instruct testsarI_reg_reg_imm( flagsReg_EQNELTGE icc, iRegI op1, iRegI op2, immU5 op3, immI0 zero ) %{
7438 match(Set icc (CmpI (AndI op1 (RShiftI op2 op3)) zero));
7439 size(4);
7440 format %{ "tst_32 $op2,$op1<<$op3" %}
7441
7442 ins_encode %{
7443 __ tst_32($op1$$Register, AsmOperand($op2$$Register, asr, $op3$$constant));
7444 %}
7445 ins_pipe(ialu_cconly_reg_reg_zero);
7446 %}
7447
7448 instruct testshrI_reg_reg_reg( flagsReg_EQNELTGE icc, iRegI op1, iRegI op2, iRegI op3, immI0 zero ) %{
7449 match(Set icc (CmpI (AndI op1 (URShiftI op2 op3)) zero));
7450 size(4);
7451 format %{ "TST $op2,$op1<<$op3" %}
7452
7453 ins_encode %{
7454 __ tst($op1$$Register, AsmOperand($op2$$Register, lsr, $op3$$Register));
7455 %}
7456 ins_pipe(ialu_cconly_reg_reg_zero);
7457 %}
7458
7459 instruct testshrI_reg_reg_imm( flagsReg_EQNELTGE icc, iRegI op1, iRegI op2, immU5 op3, immI0 zero ) %{
7460 match(Set icc (CmpI (AndI op1 (URShiftI op2 op3)) zero));
7461 size(4);
7462 format %{ "tst_32 $op2,$op1<<$op3" %}
7463
7464 ins_encode %{
7465 __ tst_32($op1$$Register, AsmOperand($op2$$Register, lsr, $op3$$constant));
7466 %}
7467 ins_pipe(ialu_cconly_reg_reg_zero);
7468 %}
7469
7470 instruct testI_reg_imm( flagsReg_EQNELTGE icc, iRegI op1, limmI op2, immI0 zero ) %{
7471 match(Set icc (CmpI (AndI op1 op2) zero));
7472 size(4);
7473 format %{ "tst_32 $op2,$op1" %}
7474
7475 ins_encode %{
7476 __ tst_32($op1$$Register, $op2$$constant);
7477 %}
7478 ins_pipe(ialu_cconly_reg_imm_zero);
7479 %}
7480
7481 instruct compL_reg_reg_LTGE(flagsRegL_LTGE xcc, iRegL op1, iRegL op2, iRegL tmp) %{
7482 match(Set xcc (CmpL op1 op2));
7483 effect( DEF xcc, USE op1, USE op2, TEMP tmp );
7484
7485 size(8);
7486 format %{ "SUBS $tmp,$op1.low,$op2.low\t\t! long\n\t"
7487 "SBCS $tmp,$op1.hi,$op2.hi" %}
7488 ins_encode %{
7489 __ subs($tmp$$Register, $op1$$Register, $op2$$Register);
7490 __ sbcs($tmp$$Register->successor(), $op1$$Register->successor(), $op2$$Register->successor());
7491 %}
7492 ins_pipe(ialu_cconly_reg_reg);
7493 %}
7494
7495 instruct compUL_reg_reg_LTGE(flagsRegUL_LTGE xcc, iRegL op1, iRegL op2, iRegL tmp) %{
7496 match(Set xcc (CmpUL op1 op2));
7497 effect(DEF xcc, USE op1, USE op2, TEMP tmp);
7498
7499 size(8);
7500 format %{ "SUBS $tmp,$op1.low,$op2.low\t\t! unsigned long\n\t"
7501 "SBCS $tmp,$op1.hi,$op2.hi" %}
7502 ins_encode %{
7503 __ subs($tmp$$Register, $op1$$Register, $op2$$Register);
7504 __ sbcs($tmp$$Register->successor(), $op1$$Register->successor(), $op2$$Register->successor());
7505 %}
7506 ins_pipe(ialu_cconly_reg_reg);
7507 %}
7508
7509 instruct compL_reg_reg_EQNE(flagsRegL_EQNE xcc, iRegL op1, iRegL op2) %{
7510 match(Set xcc (CmpL op1 op2));
7511 effect( DEF xcc, USE op1, USE op2 );
7512
7513 size(8);
7514 format %{ "TEQ $op1.hi,$op2.hi\t\t! long\n\t"
7515 "TEQ.eq $op1.lo,$op2.lo" %}
7516 ins_encode %{
7517 __ teq($op1$$Register->successor(), $op2$$Register->successor());
7518 __ teq($op1$$Register, $op2$$Register, eq);
7519 %}
7520 ins_pipe(ialu_cconly_reg_reg);
7521 %}
7522
7523 instruct compL_reg_reg_LEGT(flagsRegL_LEGT xcc, iRegL op1, iRegL op2, iRegL tmp) %{
7524 match(Set xcc (CmpL op1 op2));
7525 effect( DEF xcc, USE op1, USE op2, TEMP tmp );
7526
7527 size(8);
7528 format %{ "SUBS $tmp,$op2.low,$op1.low\t\t! long\n\t"
7529 "SBCS $tmp,$op2.hi,$op1.hi" %}
7530 ins_encode %{
7531 __ subs($tmp$$Register, $op2$$Register, $op1$$Register);
7532 __ sbcs($tmp$$Register->successor(), $op2$$Register->successor(), $op1$$Register->successor());
7533 %}
7534 ins_pipe(ialu_cconly_reg_reg);
7535 %}
7536
7537 // TODO: try immLRot2 instead, (0, $con$$constant) becomes
7538 // (hi($con$$constant), lo($con$$constant)) becomes
7539 instruct compL_reg_con_LTGE(flagsRegL_LTGE xcc, iRegL op1, immLlowRot con, iRegL tmp) %{
7540 match(Set xcc (CmpL op1 con));
7541 effect( DEF xcc, USE op1, USE con, TEMP tmp );
7542
7543 size(8);
7544 format %{ "SUBS $tmp,$op1.low,$con\t\t! long\n\t"
7545 "SBCS $tmp,$op1.hi,0" %}
7546 ins_encode %{
7547 __ subs($tmp$$Register, $op1$$Register, $con$$constant);
7548 __ sbcs($tmp$$Register->successor(), $op1$$Register->successor(), 0);
7549 %}
7550
7551 ins_pipe(ialu_cconly_reg_reg);
7552 %}
7553
7554 // TODO: try immLRot2 instead, (0, $con$$constant) becomes
7555 // (hi($con$$constant), lo($con$$constant)) becomes
7556 instruct compL_reg_con_EQNE(flagsRegL_EQNE xcc, iRegL op1, immLlowRot con) %{
7557 match(Set xcc (CmpL op1 con));
7558 effect( DEF xcc, USE op1, USE con );
7559
7560 size(8);
7561 format %{ "TEQ $op1.hi,0\t\t! long\n\t"
7562 "TEQ.eq $op1.lo,$con" %}
7563 ins_encode %{
7564 __ teq($op1$$Register->successor(), 0);
7565 __ teq($op1$$Register, $con$$constant, eq);
7566 %}
7567
7568 ins_pipe(ialu_cconly_reg_reg);
7569 %}
7570
7571 // TODO: try immLRot2 instead, (0, $con$$constant) becomes
7572 // (hi($con$$constant), lo($con$$constant)) becomes
7573 instruct compL_reg_con_LEGT(flagsRegL_LEGT xcc, iRegL op1, immLlowRot con, iRegL tmp) %{
7574 match(Set xcc (CmpL op1 con));
7575 effect( DEF xcc, USE op1, USE con, TEMP tmp );
7576
7577 size(8);
7578 format %{ "RSBS $tmp,$op1.low,$con\t\t! long\n\t"
7579 "RSCS $tmp,$op1.hi,0" %}
7580 ins_encode %{
7581 __ rsbs($tmp$$Register, $op1$$Register, $con$$constant);
7582 __ rscs($tmp$$Register->successor(), $op1$$Register->successor(), 0);
7583 %}
7584
7585 ins_pipe(ialu_cconly_reg_reg);
7586 %}
7587
7588 instruct compUL_reg_reg_EQNE(flagsRegUL_EQNE xcc, iRegL op1, iRegL op2) %{
7589 match(Set xcc (CmpUL op1 op2));
7590 effect(DEF xcc, USE op1, USE op2);
7591
7592 size(8);
7593 format %{ "TEQ $op1.hi,$op2.hi\t\t! unsigned long\n\t"
7594 "TEQ.eq $op1.lo,$op2.lo" %}
7595 ins_encode %{
7596 __ teq($op1$$Register->successor(), $op2$$Register->successor());
7597 __ teq($op1$$Register, $op2$$Register, eq);
7598 %}
7599 ins_pipe(ialu_cconly_reg_reg);
7600 %}
7601
7602 instruct compUL_reg_reg_LEGT(flagsRegUL_LEGT xcc, iRegL op1, iRegL op2, iRegL tmp) %{
7603 match(Set xcc (CmpUL op1 op2));
7604 effect(DEF xcc, USE op1, USE op2, TEMP tmp);
7605
7606 size(8);
7607 format %{ "SUBS $tmp,$op2.low,$op1.low\t\t! unsigned long\n\t"
7608 "SBCS $tmp,$op2.hi,$op1.hi" %}
7609 ins_encode %{
7610 __ subs($tmp$$Register, $op2$$Register, $op1$$Register);
7611 __ sbcs($tmp$$Register->successor(), $op2$$Register->successor(), $op1$$Register->successor());
7612 %}
7613 ins_pipe(ialu_cconly_reg_reg);
7614 %}
7615
7616 // TODO: try immLRot2 instead, (0, $con$$constant) becomes
7617 // (hi($con$$constant), lo($con$$constant)) becomes
7618 instruct compUL_reg_con_LTGE(flagsRegUL_LTGE xcc, iRegL op1, immLlowRot con, iRegL tmp) %{
7619 match(Set xcc (CmpUL op1 con));
7620 effect(DEF xcc, USE op1, USE con, TEMP tmp);
7621
7622 size(8);
7623 format %{ "SUBS $tmp,$op1.low,$con\t\t! unsigned long\n\t"
7624 "SBCS $tmp,$op1.hi,0" %}
7625 ins_encode %{
7626 __ subs($tmp$$Register, $op1$$Register, $con$$constant);
7627 __ sbcs($tmp$$Register->successor(), $op1$$Register->successor(), 0);
7628 %}
7629
7630 ins_pipe(ialu_cconly_reg_reg);
7631 %}
7632
7633 // TODO: try immLRot2 instead, (0, $con$$constant) becomes
7634 // (hi($con$$constant), lo($con$$constant)) becomes
7635 instruct compUL_reg_con_EQNE(flagsRegUL_EQNE xcc, iRegL op1, immLlowRot con) %{
7636 match(Set xcc (CmpUL op1 con));
7637 effect(DEF xcc, USE op1, USE con);
7638
7639 size(8);
7640 format %{ "TEQ $op1.hi,0\t\t! unsigned long\n\t"
7641 "TEQ.eq $op1.lo,$con" %}
7642 ins_encode %{
7643 __ teq($op1$$Register->successor(), 0);
7644 __ teq($op1$$Register, $con$$constant, eq);
7645 %}
7646
7647 ins_pipe(ialu_cconly_reg_reg);
7648 %}
7649
7650 // TODO: try immLRot2 instead, (0, $con$$constant) becomes
7651 // (hi($con$$constant), lo($con$$constant)) becomes
7652 instruct compUL_reg_con_LEGT(flagsRegUL_LEGT xcc, iRegL op1, immLlowRot con, iRegL tmp) %{
7653 match(Set xcc (CmpUL op1 con));
7654 effect(DEF xcc, USE op1, USE con, TEMP tmp);
7655
7656 size(8);
7657 format %{ "RSBS $tmp,$op1.low,$con\t\t! unsigned long\n\t"
7658 "RSCS $tmp,$op1.hi,0" %}
7659 ins_encode %{
7660 __ rsbs($tmp$$Register, $op1$$Register, $con$$constant);
7661 __ rscs($tmp$$Register->successor(), $op1$$Register->successor(), 0);
7662 %}
7663
7664 ins_pipe(ialu_cconly_reg_reg);
7665 %}
7666
7667 /* instruct testL_reg_reg(flagsRegL xcc, iRegL op1, iRegL op2, immL0 zero) %{ */
7668 /* match(Set xcc (CmpL (AndL op1 op2) zero)); */
7669 /* ins_encode %{ */
7670 /* __ stop("testL_reg_reg unimplemented"); */
7671 /* %} */
7672 /* ins_pipe(ialu_cconly_reg_reg); */
7673 /* %} */
7674
7675 /* // useful for checking the alignment of a pointer: */
7676 /* instruct testL_reg_con(flagsRegL xcc, iRegL op1, immLlowRot con, immL0 zero) %{ */
7677 /* match(Set xcc (CmpL (AndL op1 con) zero)); */
7678 /* ins_encode %{ */
7679 /* __ stop("testL_reg_con unimplemented"); */
7680 /* %} */
7681 /* ins_pipe(ialu_cconly_reg_reg); */
7682 /* %} */
7683
7684 instruct compU_iReg_imm(flagsRegU icc, iRegI op1, aimmU31 op2 ) %{
7685 match(Set icc (CmpU op1 op2));
7686
7687 size(4);
7688 format %{ "cmp_32 $op1,$op2\t! unsigned" %}
7689 ins_encode %{
7690 __ cmp_32($op1$$Register, $op2$$constant);
7691 %}
7692 ins_pipe(ialu_cconly_reg_imm);
7693 %}
7694
7695 // Compare Pointers
7696 instruct compP_iRegP(flagsRegP pcc, iRegP op1, iRegP op2 ) %{
7697 match(Set pcc (CmpP op1 op2));
7698
7699 size(4);
7700 format %{ "CMP $op1,$op2\t! ptr" %}
7701 ins_encode %{
7702 __ cmp($op1$$Register, $op2$$Register);
7703 %}
7704 ins_pipe(ialu_cconly_reg_reg);
7705 %}
7706
7707 instruct compP_iRegP_imm(flagsRegP pcc, iRegP op1, aimmP op2 ) %{
7708 match(Set pcc (CmpP op1 op2));
7709
7710 size(4);
7711 format %{ "CMP $op1,$op2\t! ptr" %}
7712 ins_encode %{
7713 assert($op2$$constant == 0 || _opnds[2]->constant_reloc() == relocInfo::none, "reloc in cmp?");
7714 __ cmp($op1$$Register, $op2$$constant);
7715 %}
7716 ins_pipe(ialu_cconly_reg_imm);
7717 %}
7718
7719 //----------Max and Min--------------------------------------------------------
7720 // Min Instructions
7721 // Conditional move for min
7722 instruct cmovI_reg_lt( iRegI op2, iRegI op1, flagsReg icc ) %{
7723 effect( USE_DEF op2, USE op1, USE icc );
7724
7725 size(4);
7726 format %{ "MOV.lt $op2,$op1\t! min" %}
7727 ins_encode %{
7728 __ mov($op2$$Register, $op1$$Register, lt);
7729 %}
7730 ins_pipe(ialu_reg_flags);
7731 %}
7732
7733 // Min Register with Register.
7734 instruct minI_eReg(iRegI op1, iRegI op2) %{
7735 match(Set op2 (MinI op1 op2));
7736 ins_cost(DEFAULT_COST*2);
7737 expand %{
7738 flagsReg icc;
7739 compI_iReg(icc,op1,op2);
7740 cmovI_reg_lt(op2,op1,icc);
7741 %}
7742 %}
7743
7744 // Max Instructions
7745 // Conditional move for max
7746 instruct cmovI_reg_gt( iRegI op2, iRegI op1, flagsReg icc ) %{
7747 effect( USE_DEF op2, USE op1, USE icc );
7748 format %{ "MOV.gt $op2,$op1\t! max" %}
7749 ins_encode %{
7750 __ mov($op2$$Register, $op1$$Register, gt);
7751 %}
7752 ins_pipe(ialu_reg_flags);
7753 %}
7754
7755 // Max Register with Register
7756 instruct maxI_eReg(iRegI op1, iRegI op2) %{
7757 match(Set op2 (MaxI op1 op2));
7758 ins_cost(DEFAULT_COST*2);
7759 expand %{
7760 flagsReg icc;
7761 compI_iReg(icc,op1,op2);
7762 cmovI_reg_gt(op2,op1,icc);
7763 %}
7764 %}
7765
7766
7767 //----------Float Compares----------------------------------------------------
7768 // Compare floating, generate condition code
7769 instruct cmpF_cc(flagsRegF fcc, flagsReg icc, regF src1, regF src2) %{
7770 match(Set icc (CmpF src1 src2));
7771 effect(KILL fcc);
7772
7773 size(8);
7774 format %{ "FCMPs $src1,$src2\n\t"
7775 "FMSTAT" %}
7776 ins_encode %{
7777 __ fcmps($src1$$FloatRegister, $src2$$FloatRegister);
7778 __ fmstat();
7779 %}
7780 ins_pipe(faddF_fcc_reg_reg_zero);
7781 %}
7782
7783 instruct cmpF0_cc(flagsRegF fcc, flagsReg icc, regF src1, immF0 src2) %{
7784 match(Set icc (CmpF src1 src2));
7785 effect(KILL fcc);
7786
7787 size(8);
7788 format %{ "FCMPs $src1,$src2\n\t"
7789 "FMSTAT" %}
7790 ins_encode %{
7791 __ fcmpzs($src1$$FloatRegister);
7792 __ fmstat();
7793 %}
7794 ins_pipe(faddF_fcc_reg_reg_zero);
7795 %}
7796
7797 instruct cmpD_cc(flagsRegF fcc, flagsReg icc, regD src1, regD src2) %{
7798 match(Set icc (CmpD src1 src2));
7799 effect(KILL fcc);
7800
7801 size(8);
7802 format %{ "FCMPd $src1,$src2 \n\t"
7803 "FMSTAT" %}
7804 ins_encode %{
7805 __ fcmpd($src1$$FloatRegister, $src2$$FloatRegister);
7806 __ fmstat();
7807 %}
7808 ins_pipe(faddD_fcc_reg_reg_zero);
7809 %}
7810
7811 instruct cmpD0_cc(flagsRegF fcc, flagsReg icc, regD src1, immD0 src2) %{
7812 match(Set icc (CmpD src1 src2));
7813 effect(KILL fcc);
7814
7815 size(8);
7816 format %{ "FCMPZd $src1,$src2 \n\t"
7817 "FMSTAT" %}
7818 ins_encode %{
7819 __ fcmpzd($src1$$FloatRegister);
7820 __ fmstat();
7821 %}
7822 ins_pipe(faddD_fcc_reg_reg_zero);
7823 %}
7824
7825 // Compare floating, generate -1,0,1
7826 instruct cmpF_reg(iRegI dst, regF src1, regF src2, flagsRegF fcc) %{
7827 match(Set dst (CmpF3 src1 src2));
7828 effect(KILL fcc);
7829 ins_cost(DEFAULT_COST*3+BRANCH_COST*3); // FIXME
7830 size(20);
7831 // same number of instructions as code using conditional moves but
7832 // doesn't kill integer condition register
7833 format %{ "FCMPs $dst,$src1,$src2 \n\t"
7834 "VMRS $dst, FPSCR \n\t"
7835 "OR $dst, $dst, 0x08000000 \n\t"
7836 "EOR $dst, $dst, $dst << 3 \n\t"
7837 "MOV $dst, $dst >> 30" %}
7838 ins_encode %{
7839 __ fcmps($src1$$FloatRegister, $src2$$FloatRegister);
7840 __ floating_cmp($dst$$Register);
7841 %}
7842 ins_pipe( floating_cmp );
7843 %}
7844
7845 instruct cmpF0_reg(iRegI dst, regF src1, immF0 src2, flagsRegF fcc) %{
7846 match(Set dst (CmpF3 src1 src2));
7847 effect(KILL fcc);
7848 ins_cost(DEFAULT_COST*3+BRANCH_COST*3); // FIXME
7849 size(20);
7850 // same number of instructions as code using conditional moves but
7851 // doesn't kill integer condition register
7852 format %{ "FCMPZs $dst,$src1,$src2 \n\t"
7853 "VMRS $dst, FPSCR \n\t"
7854 "OR $dst, $dst, 0x08000000 \n\t"
7855 "EOR $dst, $dst, $dst << 3 \n\t"
7856 "MOV $dst, $dst >> 30" %}
7857 ins_encode %{
7858 __ fcmpzs($src1$$FloatRegister);
7859 __ floating_cmp($dst$$Register);
7860 %}
7861 ins_pipe( floating_cmp );
7862 %}
7863
7864 instruct cmpD_reg(iRegI dst, regD src1, regD src2, flagsRegF fcc) %{
7865 match(Set dst (CmpD3 src1 src2));
7866 effect(KILL fcc);
7867 ins_cost(DEFAULT_COST*3+BRANCH_COST*3); // FIXME
7868 size(20);
7869 // same number of instructions as code using conditional moves but
7870 // doesn't kill integer condition register
7871 format %{ "FCMPd $dst,$src1,$src2 \n\t"
7872 "VMRS $dst, FPSCR \n\t"
7873 "OR $dst, $dst, 0x08000000 \n\t"
7874 "EOR $dst, $dst, $dst << 3 \n\t"
7875 "MOV $dst, $dst >> 30" %}
7876 ins_encode %{
7877 __ fcmpd($src1$$FloatRegister, $src2$$FloatRegister);
7878 __ floating_cmp($dst$$Register);
7879 %}
7880 ins_pipe( floating_cmp );
7881 %}
7882
7883 instruct cmpD0_reg(iRegI dst, regD src1, immD0 src2, flagsRegF fcc) %{
7884 match(Set dst (CmpD3 src1 src2));
7885 effect(KILL fcc);
7886 ins_cost(DEFAULT_COST*3+BRANCH_COST*3); // FIXME
7887 size(20);
7888 // same number of instructions as code using conditional moves but
7889 // doesn't kill integer condition register
7890 format %{ "FCMPZd $dst,$src1,$src2 \n\t"
7891 "VMRS $dst, FPSCR \n\t"
7892 "OR $dst, $dst, 0x08000000 \n\t"
7893 "EOR $dst, $dst, $dst << 3 \n\t"
7894 "MOV $dst, $dst >> 30" %}
7895 ins_encode %{
7896 __ fcmpzd($src1$$FloatRegister);
7897 __ floating_cmp($dst$$Register);
7898 %}
7899 ins_pipe( floating_cmp );
7900 %}
7901
7902 //----------Branches---------------------------------------------------------
7903 // Jump
7904 // (compare 'operand indIndex' and 'instruct addP_reg_reg' above)
7905 // FIXME
7906 instruct jumpXtnd(iRegX switch_val, iRegP tmp) %{
7907 match(Jump switch_val);
7908 effect(TEMP tmp);
7909 ins_cost(350);
7910 format %{ "ADD $tmp, $constanttablebase, $switch_val\n\t"
7911 "LDR $tmp,[$tmp + $constantoffset]\n\t"
7912 "BX $tmp" %}
7913 size(20);
7914 ins_encode %{
7915 Register table_reg;
7916 Register label_reg = $tmp$$Register;
7917 if (constant_offset() == 0) {
7918 table_reg = $constanttablebase;
7919 __ ldr(label_reg, Address(table_reg, $switch_val$$Register));
7920 } else {
7921 table_reg = $tmp$$Register;
7922 int offset = $constantoffset;
7923 if (is_memoryP(offset)) {
7924 __ add(table_reg, $constanttablebase, $switch_val$$Register);
7925 __ ldr(label_reg, Address(table_reg, offset));
7926 } else {
7927 __ mov_slow(table_reg, $constantoffset);
7928 __ add(table_reg, $constanttablebase, table_reg);
7929 __ ldr(label_reg, Address(table_reg, $switch_val$$Register));
7930 }
7931 }
7932 __ jump(label_reg); // ldr + b better than ldr to PC for branch predictor?
7933 // __ ldr(PC, Address($table$$Register, $switch_val$$Register));
7934 %}
7935 ins_pipe(ialu_reg_reg);
7936 %}
7937
7938 // // Direct Branch.
7939 instruct branch(label labl) %{
7940 match(Goto);
7941 effect(USE labl);
7942
7943 size(4);
7944 ins_cost(BRANCH_COST);
7945 format %{ "B $labl" %}
7946 ins_encode %{
7947 __ b(*($labl$$label));
7948 %}
7949 ins_pipe(br);
7950 %}
7951
7952 // Conditional Direct Branch
7953 instruct branchCon(cmpOp cmp, flagsReg icc, label labl) %{
7954 match(If cmp icc);
7955 effect(USE labl);
7956
7957 size(4);
7958 ins_cost(BRANCH_COST);
7959 format %{ "B$cmp $icc,$labl" %}
7960 ins_encode %{
7961 __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode));
7962 %}
7963 ins_pipe(br_cc);
7964 %}
7965
7966 #ifdef ARM
7967 instruct branchCon_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, label labl) %{
7968 match(If cmp icc);
7969 effect(USE labl);
7970 predicate( _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
7971
7972 size(4);
7973 ins_cost(BRANCH_COST);
7974 format %{ "B$cmp $icc,$labl" %}
7975 ins_encode %{
7976 __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode));
7977 %}
7978 ins_pipe(br_cc);
7979 %}
7980 #endif
7981
7982
7983 instruct branchConU(cmpOpU cmp, flagsRegU icc, label labl) %{
7984 match(If cmp icc);
7985 effect(USE labl);
7986
7987 size(4);
7988 ins_cost(BRANCH_COST);
7989 format %{ "B$cmp $icc,$labl" %}
7990 ins_encode %{
7991 __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode));
7992 %}
7993 ins_pipe(br_cc);
7994 %}
7995
7996 instruct branchConP(cmpOpP cmp, flagsRegP pcc, label labl) %{
7997 match(If cmp pcc);
7998 effect(USE labl);
7999
8000 size(4);
8001 ins_cost(BRANCH_COST);
8002 format %{ "B$cmp $pcc,$labl" %}
8003 ins_encode %{
8004 __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode));
8005 %}
8006 ins_pipe(br_cc);
8007 %}
8008
8009 instruct branchConL_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, label labl) %{
8010 match(If cmp xcc);
8011 effect(USE labl);
8012 predicate( _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge );
8013
8014 size(4);
8015 ins_cost(BRANCH_COST);
8016 format %{ "B$cmp $xcc,$labl" %}
8017 ins_encode %{
8018 __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode));
8019 %}
8020 ins_pipe(br_cc);
8021 %}
8022
8023 instruct branchConL_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, label labl) %{
8024 match(If cmp xcc);
8025 effect(USE labl);
8026 predicate( _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne );
8027
8028 size(4);
8029 ins_cost(BRANCH_COST);
8030 format %{ "B$cmp $xcc,$labl" %}
8031 ins_encode %{
8032 __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode));
8033 %}
8034 ins_pipe(br_cc);
8035 %}
8036
8037 instruct branchConL_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, label labl) %{
8038 match(If cmp xcc);
8039 effect(USE labl);
8040 predicate( _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le );
8041
8042 size(4);
8043 ins_cost(BRANCH_COST);
8044 format %{ "B$cmp $xcc,$labl" %}
8045 ins_encode %{
8046 __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode));
8047 %}
8048 ins_pipe(br_cc);
8049 %}
8050
8051 instruct branchConUL_LTGE(cmpOpUL cmp, flagsRegUL_LTGE xcc, label labl) %{
8052 match(If cmp xcc);
8053 effect(USE labl);
8054 predicate(_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
8055
8056 size(4);
8057 ins_cost(BRANCH_COST);
8058 format %{ "B$cmp $xcc,$labl" %}
8059 ins_encode %{
8060 __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode));
8061 %}
8062 ins_pipe(br_cc);
8063 %}
8064
8065 instruct branchConUL_EQNE(cmpOpUL cmp, flagsRegUL_EQNE xcc, label labl) %{
8066 match(If cmp xcc);
8067 effect(USE labl);
8068 predicate(_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne);
8069
8070 size(4);
8071 ins_cost(BRANCH_COST);
8072 format %{ "B$cmp $xcc,$labl" %}
8073 ins_encode %{
8074 __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode));
8075 %}
8076 ins_pipe(br_cc);
8077 %}
8078
8079 instruct branchConUL_LEGT(cmpOpUL_commute cmp, flagsRegUL_LEGT xcc, label labl) %{
8080 match(If cmp xcc);
8081 effect(USE labl);
8082 predicate(_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le);
8083
8084 size(4);
8085 ins_cost(BRANCH_COST);
8086 format %{ "B$cmp $xcc,$labl" %}
8087 ins_encode %{
8088 __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode));
8089 %}
8090 ins_pipe(br_cc);
8091 %}
8092
8093 instruct branchLoopEnd(cmpOp cmp, flagsReg icc, label labl) %{
8094 match(CountedLoopEnd cmp icc);
8095 effect(USE labl);
8096
8097 size(4);
8098 ins_cost(BRANCH_COST);
8099 format %{ "B$cmp $icc,$labl\t! Loop end" %}
8100 ins_encode %{
8101 __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode));
8102 %}
8103 ins_pipe(br_cc);
8104 %}
8105
8106 // instruct branchLoopEndU(cmpOpU cmp, flagsRegU icc, label labl) %{
8107 // match(CountedLoopEnd cmp icc);
8108 // ins_pipe(br_cc);
8109 // %}
8110
8111 // ============================================================================
8112 // Long Compare
8113 //
8114 // Currently we hold longs in 2 registers. Comparing such values efficiently
8115 // is tricky. The flavor of compare used depends on whether we are testing
8116 // for LT, LE, or EQ. For a simple LT test we can check just the sign bit.
8117 // The GE test is the negated LT test. The LE test can be had by commuting
8118 // the operands (yielding a GE test) and then negating; negate again for the
8119 // GT test. The EQ test is done by ORcc'ing the high and low halves, and the
8120 // NE test is negated from that.
8121
8122 // Due to a shortcoming in the ADLC, it mixes up expressions like:
8123 // (foo (CmpI (CmpL X Y) 0)) and (bar (CmpI (CmpL X 0L) 0)). Note the
8124 // difference between 'Y' and '0L'. The tree-matches for the CmpI sections
8125 // are collapsed internally in the ADLC's dfa-gen code. The match for
8126 // (CmpI (CmpL X Y) 0) is silently replaced with (CmpI (CmpL X 0L) 0) and the
8127 // foo match ends up with the wrong leaf. One fix is to not match both
8128 // reg-reg and reg-zero forms of long-compare. This is unfortunate because
8129 // both forms beat the trinary form of long-compare and both are very useful
8130 // on Intel which has so few registers.
8131
8132 // instruct branchCon_long(cmpOp cmp, flagsRegL xcc, label labl) %{
8133 // match(If cmp xcc);
8134 // ins_pipe(br_cc);
8135 // %}
8136
8137 // Manifest a CmpL3 result in an integer register. Very painful.
8138 // This is the test to avoid.
8139 instruct cmpL3_reg_reg(iRegI dst, iRegL src1, iRegL src2, flagsReg ccr ) %{
8140 match(Set dst (CmpL3 src1 src2) );
8141 effect( KILL ccr );
8142 ins_cost(6*DEFAULT_COST); // FIXME
8143 size(32);
8144 format %{
8145 "CMP $src1.hi, $src2.hi\t\t! long\n"
8146 "\tMOV.gt $dst, 1\n"
8147 "\tmvn.lt $dst, 0\n"
8148 "\tB.ne done\n"
8149 "\tSUBS $dst, $src1.lo, $src2.lo\n"
8150 "\tMOV.hi $dst, 1\n"
8151 "\tmvn.lo $dst, 0\n"
8152 "done:" %}
8153 ins_encode %{
8154 Label done;
8155 __ cmp($src1$$Register->successor(), $src2$$Register->successor());
8156 __ mov($dst$$Register, 1, gt);
8157 __ mvn($dst$$Register, 0, lt);
8158 __ b(done, ne);
8159 __ subs($dst$$Register, $src1$$Register, $src2$$Register);
8160 __ mov($dst$$Register, 1, hi);
8161 __ mvn($dst$$Register, 0, lo);
8162 __ bind(done);
8163 %}
8164 ins_pipe(cmpL_reg);
8165 %}
8166
8167 // Conditional move
8168 instruct cmovLL_reg_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, iRegL dst, iRegL src) %{
8169 match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src)));
8170 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
8171
8172 ins_cost(150);
8173 size(8);
8174 format %{ "MOV$cmp $dst.lo,$src.lo\t! long\n\t"
8175 "MOV$cmp $dst,$src.hi" %}
8176 ins_encode %{
8177 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
8178 __ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode));
8179 %}
8180 ins_pipe(ialu_reg);
8181 %}
8182
8183 instruct cmovLL_reg_LTGE_U(cmpOpUL cmp, flagsRegUL_LTGE xcc, iRegL dst, iRegL src) %{
8184 match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src)));
8185 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
8186
8187 ins_cost(150);
8188 size(8);
8189 format %{ "MOV$cmp $dst.lo,$src.lo\t! long\n\t"
8190 "MOV$cmp $dst,$src.hi" %}
8191 ins_encode %{
8192 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
8193 __ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode));
8194 %}
8195 ins_pipe(ialu_reg);
8196 %}
8197
8198 instruct cmovLL_reg_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, iRegL dst, iRegL src) %{
8199 match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src)));
8200 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne);
8201
8202 ins_cost(150);
8203 size(8);
8204 format %{ "MOV$cmp $dst.lo,$src.lo\t! long\n\t"
8205 "MOV$cmp $dst,$src.hi" %}
8206 ins_encode %{
8207 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
8208 __ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode));
8209 %}
8210 ins_pipe(ialu_reg);
8211 %}
8212
8213 instruct cmovLL_reg_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, iRegL dst, iRegL src) %{
8214 match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src)));
8215 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt);
8216
8217 ins_cost(150);
8218 size(8);
8219 format %{ "MOV$cmp $dst.lo,$src.lo\t! long\n\t"
8220 "MOV$cmp $dst,$src.hi" %}
8221 ins_encode %{
8222 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
8223 __ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode));
8224 %}
8225 ins_pipe(ialu_reg);
8226 %}
8227
8228 instruct cmovLL_reg_LEGT_U(cmpOpUL_commute cmp, flagsRegUL_LEGT xcc, iRegL dst, iRegL src) %{
8229 match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src)));
8230 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt);
8231
8232 ins_cost(150);
8233 size(8);
8234 format %{ "MOV$cmp $dst.lo,$src.lo\t! long\n\t"
8235 "MOV$cmp $dst,$src.hi" %}
8236 ins_encode %{
8237 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
8238 __ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode));
8239 %}
8240 ins_pipe(ialu_reg);
8241 %}
8242
8243 instruct cmovLL_imm_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, iRegL dst, immL0 src) %{
8244 match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src)));
8245 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
8246 ins_cost(140);
8247 size(8);
8248 format %{ "MOV$cmp $dst.lo,0\t! long\n\t"
8249 "MOV$cmp $dst,0" %}
8250 ins_encode %{
8251 __ mov($dst$$Register, 0, (AsmCondition)($cmp$$cmpcode));
8252 __ mov($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode));
8253 %}
8254 ins_pipe(ialu_imm);
8255 %}
8256
8257 instruct cmovLL_imm_LTGE_U(cmpOpUL cmp, flagsRegUL_LTGE xcc, iRegL dst, immL0 src) %{
8258 match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src)));
8259 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
8260 ins_cost(140);
8261 size(8);
8262 format %{ "MOV$cmp $dst.lo,0\t! long\n\t"
8263 "MOV$cmp $dst,0" %}
8264 ins_encode %{
8265 __ mov($dst$$Register, 0, (AsmCondition)($cmp$$cmpcode));
8266 __ mov($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode));
8267 %}
8268 ins_pipe(ialu_imm);
8269 %}
8270
8271 instruct cmovLL_imm_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, iRegL dst, immL0 src) %{
8272 match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src)));
8273 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne);
8274 ins_cost(140);
8275 size(8);
8276 format %{ "MOV$cmp $dst.lo,0\t! long\n\t"
8277 "MOV$cmp $dst,0" %}
8278 ins_encode %{
8279 __ mov($dst$$Register, 0, (AsmCondition)($cmp$$cmpcode));
8280 __ mov($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode));
8281 %}
8282 ins_pipe(ialu_imm);
8283 %}
8284
8285 instruct cmovLL_imm_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, iRegL dst, immL0 src) %{
8286 match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src)));
8287 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt);
8288 ins_cost(140);
8289 size(8);
8290 format %{ "MOV$cmp $dst.lo,0\t! long\n\t"
8291 "MOV$cmp $dst,0" %}
8292 ins_encode %{
8293 __ mov($dst$$Register, 0, (AsmCondition)($cmp$$cmpcode));
8294 __ mov($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode));
8295 %}
8296 ins_pipe(ialu_imm);
8297 %}
8298
8299 instruct cmovIL_reg_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, iRegI dst, iRegI src) %{
8300 match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src)));
8301 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
8302
8303 ins_cost(150);
8304 size(4);
8305 format %{ "MOV$cmp $dst,$src" %}
8306 ins_encode %{
8307 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
8308 %}
8309 ins_pipe(ialu_reg);
8310 %}
8311
8312 instruct cmovIL_reg_LTGE_U(cmpOpUL cmp, flagsRegUL_LTGE xcc, iRegI dst, iRegI src) %{
8313 match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src)));
8314 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
8315
8316 ins_cost(150);
8317 size(4);
8318 format %{ "MOV$cmp $dst,$src" %}
8319 ins_encode %{
8320 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
8321 %}
8322 ins_pipe(ialu_reg);
8323 %}
8324
8325 instruct cmovIL_reg_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, iRegI dst, iRegI src) %{
8326 match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src)));
8327 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne);
8328
8329 ins_cost(150);
8330 size(4);
8331 format %{ "MOV$cmp $dst,$src" %}
8332 ins_encode %{
8333 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
8334 %}
8335 ins_pipe(ialu_reg);
8336 %}
8337
8338 instruct cmovIL_reg_EQNE_U(cmpOpUL cmp, flagsRegUL_EQNE xcc, iRegI dst, iRegI src) %{
8339 match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src)));
8340 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne);
8341
8342 ins_cost(150);
8343 size(4);
8344 format %{ "MOV$cmp $dst,$src" %}
8345 ins_encode %{
8346 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
8347 %}
8348 ins_pipe(ialu_reg);
8349 %}
8350
8351 instruct cmovIL_reg_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, iRegI dst, iRegI src) %{
8352 match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src)));
8353 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt);
8354
8355 ins_cost(150);
8356 size(4);
8357 format %{ "MOV$cmp $dst,$src" %}
8358 ins_encode %{
8359 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
8360 %}
8361 ins_pipe(ialu_reg);
8362 %}
8363
8364 instruct cmovIL_reg_LEGT_U(cmpOpUL_commute cmp, flagsRegUL_LEGT xcc, iRegI dst, iRegI src) %{
8365 match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src)));
8366 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt);
8367
8368 ins_cost(150);
8369 size(4);
8370 format %{ "MOV$cmp $dst,$src" %}
8371 ins_encode %{
8372 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
8373 %}
8374 ins_pipe(ialu_reg);
8375 %}
8376
8377 instruct cmovIL_imm16_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, iRegI dst, immI16 src) %{
8378 match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src)));
8379 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
8380
8381 ins_cost(140);
8382 size(4);
8383 format %{ "MOVW$cmp $dst,$src" %}
8384 ins_encode %{
8385 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
8386 %}
8387 ins_pipe(ialu_imm);
8388 %}
8389
8390 instruct cmovIL_imm16_LTGE_U(cmpOpUL cmp, flagsRegUL_LTGE xcc, iRegI dst, immI16 src) %{
8391 match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src)));
8392 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
8393
8394 ins_cost(140);
8395 size(4);
8396 format %{ "MOVW$cmp $dst,$src" %}
8397 ins_encode %{
8398 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
8399 %}
8400 ins_pipe(ialu_imm);
8401 %}
8402
8403 instruct cmovIL_imm16_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, iRegI dst, immI16 src) %{
8404 match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src)));
8405 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne);
8406
8407 ins_cost(140);
8408 size(4);
8409 format %{ "MOVW$cmp $dst,$src" %}
8410 ins_encode %{
8411 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
8412 %}
8413 ins_pipe(ialu_imm);
8414 %}
8415
8416 instruct cmovIL_imm16_EQNE_U(cmpOpUL cmp, flagsRegUL_EQNE xcc, iRegI dst, immI16 src) %{
8417 match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src)));
8418 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne);
8419
8420 ins_cost(140);
8421 size(4);
8422 format %{ "MOVW$cmp $dst,$src" %}
8423 ins_encode %{
8424 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
8425 %}
8426 ins_pipe(ialu_imm);
8427 %}
8428
8429 instruct cmovIL_imm16_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, iRegI dst, immI16 src) %{
8430 match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src)));
8431 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt);
8432
8433 ins_cost(140);
8434 size(4);
8435 format %{ "MOVW$cmp $dst,$src" %}
8436 ins_encode %{
8437 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
8438 %}
8439 ins_pipe(ialu_imm);
8440 %}
8441
8442 instruct cmovIL_imm16_LEGT_U(cmpOpUL_commute cmp, flagsRegUL_LEGT xcc, iRegI dst, immI16 src) %{
8443 match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src)));
8444 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt);
8445
8446 ins_cost(140);
8447 size(4);
8448 format %{ "MOVW$cmp $dst,$src" %}
8449 ins_encode %{
8450 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
8451 %}
8452 ins_pipe(ialu_imm);
8453 %}
8454
8455 instruct cmovIL_immMov_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, iRegI dst, immIMov src) %{
8456 match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src)));
8457 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
8458
8459 ins_cost(140);
8460 size(4);
8461 format %{ "MOV$cmp $dst,$src" %}
8462 ins_encode %{
8463 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
8464 %}
8465 ins_pipe(ialu_imm);
8466 %}
8467
8468 instruct cmovIL_immMov_LTGE_U(cmpOpUL cmp, flagsRegUL_LTGE xcc, iRegI dst, immIMov src) %{
8469 match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src)));
8470 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
8471
8472 ins_cost(140);
8473 size(4);
8474 format %{ "MOV$cmp $dst,$src" %}
8475 ins_encode %{
8476 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
8477 %}
8478 ins_pipe(ialu_imm);
8479 %}
8480
8481 instruct cmovIL_immMov_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, iRegI dst, immIMov src) %{
8482 match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src)));
8483 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne);
8484
8485 ins_cost(140);
8486 size(4);
8487 format %{ "MOV$cmp $dst,$src" %}
8488 ins_encode %{
8489 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
8490 %}
8491 ins_pipe(ialu_imm);
8492 %}
8493
8494 instruct cmovIL_immMov_EQNE_U(cmpOpUL cmp, flagsRegUL_EQNE xcc, iRegI dst, immIMov src) %{
8495 match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src)));
8496 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne);
8497
8498 ins_cost(140);
8499 size(4);
8500 format %{ "MOV$cmp $dst,$src" %}
8501 ins_encode %{
8502 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
8503 %}
8504 ins_pipe(ialu_imm);
8505 %}
8506
8507 instruct cmovIL_immMov_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, iRegI dst, immIMov src) %{
8508 match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src)));
8509 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt);
8510
8511 ins_cost(140);
8512 size(4);
8513 format %{ "MOV$cmp $dst,$src" %}
8514 ins_encode %{
8515 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
8516 %}
8517 ins_pipe(ialu_imm);
8518 %}
8519
8520 instruct cmovIL_immMov_LEGT_U(cmpOpUL_commute cmp, flagsRegUL_LEGT xcc, iRegI dst, immIMov src) %{
8521 match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src)));
8522 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt);
8523
8524 ins_cost(140);
8525 size(4);
8526 format %{ "MOV$cmp $dst,$src" %}
8527 ins_encode %{
8528 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
8529 %}
8530 ins_pipe(ialu_imm);
8531 %}
8532
8533 instruct cmovPL_reg_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, iRegP dst, iRegP src) %{
8534 match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src)));
8535 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
8536
8537 ins_cost(150);
8538 size(4);
8539 format %{ "MOV$cmp $dst,$src" %}
8540 ins_encode %{
8541 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
8542 %}
8543 ins_pipe(ialu_reg);
8544 %}
8545
8546 instruct cmovPL_reg_LTGE_U(cmpOpUL cmp, flagsRegUL_LTGE xcc, iRegP dst, iRegP src) %{
8547 match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src)));
8548 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
8549
8550 ins_cost(150);
8551 size(4);
8552 format %{ "MOV$cmp $dst,$src" %}
8553 ins_encode %{
8554 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
8555 %}
8556 ins_pipe(ialu_reg);
8557 %}
8558
8559 instruct cmovPL_reg_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, iRegP dst, iRegP src) %{
8560 match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src)));
8561 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne);
8562
8563 ins_cost(150);
8564 size(4);
8565 format %{ "MOV$cmp $dst,$src" %}
8566 ins_encode %{
8567 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
8568 %}
8569 ins_pipe(ialu_reg);
8570 %}
8571
8572 instruct cmovPL_reg_EQNE_U(cmpOpUL cmp, flagsRegUL_EQNE xcc, iRegP dst, iRegP src) %{
8573 match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src)));
8574 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne);
8575
8576 ins_cost(150);
8577 size(4);
8578 format %{ "MOV$cmp $dst,$src" %}
8579 ins_encode %{
8580 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
8581 %}
8582 ins_pipe(ialu_reg);
8583 %}
8584
8585 instruct cmovPL_reg_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, iRegP dst, iRegP src) %{
8586 match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src)));
8587 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt);
8588
8589 ins_cost(150);
8590 size(4);
8591 format %{ "MOV$cmp $dst,$src" %}
8592 ins_encode %{
8593 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
8594 %}
8595 ins_pipe(ialu_reg);
8596 %}
8597
8598 instruct cmovPL_reg_LEGT_U(cmpOpUL_commute cmp, flagsRegUL_LEGT xcc, iRegP dst, iRegP src) %{
8599 match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src)));
8600 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt);
8601
8602 ins_cost(150);
8603 size(4);
8604 format %{ "MOV$cmp $dst,$src" %}
8605 ins_encode %{
8606 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
8607 %}
8608 ins_pipe(ialu_reg);
8609 %}
8610
8611 instruct cmovPL_imm_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, iRegP dst, immP0 src) %{
8612 match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src)));
8613 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
8614
8615 ins_cost(140);
8616 size(4);
8617 format %{ "MOVW$cmp $dst,$src" %}
8618 ins_encode %{
8619 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
8620 %}
8621 ins_pipe(ialu_imm);
8622 %}
8623
8624 instruct cmovPL_imm_LTGE_U(cmpOpUL cmp, flagsRegUL_LTGE xcc, iRegP dst, immP0 src) %{
8625 match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src)));
8626 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
8627
8628 ins_cost(140);
8629 size(4);
8630 format %{ "MOVW$cmp $dst,$src" %}
8631 ins_encode %{
8632 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
8633 %}
8634 ins_pipe(ialu_imm);
8635 %}
8636
8637 instruct cmovPL_imm_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, iRegP dst, immP0 src) %{
8638 match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src)));
8639 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne);
8640
8641 ins_cost(140);
8642 size(4);
8643 format %{ "MOVW$cmp $dst,$src" %}
8644 ins_encode %{
8645 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
8646 %}
8647 ins_pipe(ialu_imm);
8648 %}
8649
8650 instruct cmovPL_imm_EQNE_U(cmpOpUL cmp, flagsRegUL_EQNE xcc, iRegP dst, immP0 src) %{
8651 match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src)));
8652 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne);
8653
8654 ins_cost(140);
8655 size(4);
8656 format %{ "MOVW$cmp $dst,$src" %}
8657 ins_encode %{
8658 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
8659 %}
8660 ins_pipe(ialu_imm);
8661 %}
8662
8663 instruct cmovPL_imm_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, iRegP dst, immP0 src) %{
8664 match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src)));
8665 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt);
8666
8667 ins_cost(140);
8668 size(4);
8669 format %{ "MOVW$cmp $dst,$src" %}
8670 ins_encode %{
8671 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
8672 %}
8673 ins_pipe(ialu_imm);
8674 %}
8675
8676 instruct cmovPL_imm_LEGT_U(cmpOpUL_commute cmp, flagsRegUL_LEGT xcc, iRegP dst, immP0 src) %{
8677 match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src)));
8678 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt);
8679
8680 ins_cost(140);
8681 size(4);
8682 format %{ "MOVW$cmp $dst,$src" %}
8683 ins_encode %{
8684 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
8685 %}
8686 ins_pipe(ialu_imm);
8687 %}
8688
8689 instruct cmovFL_reg_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, regF dst, regF src) %{
8690 match(Set dst (CMoveF (Binary cmp xcc) (Binary dst src)));
8691 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
8692 ins_cost(150);
8693 size(4);
8694 format %{ "FCPYS$cmp $dst,$src" %}
8695 ins_encode %{
8696 __ fcpys($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
8697 %}
8698 ins_pipe(int_conditional_float_move);
8699 %}
8700
8701 instruct cmovFL_reg_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, regF dst, regF src) %{
8702 match(Set dst (CMoveF (Binary cmp xcc) (Binary dst src)));
8703 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne);
8704 ins_cost(150);
8705 size(4);
8706 format %{ "FCPYS$cmp $dst,$src" %}
8707 ins_encode %{
8708 __ fcpys($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
8709 %}
8710 ins_pipe(int_conditional_float_move);
8711 %}
8712
8713 instruct cmovFL_reg_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, regF dst, regF src) %{
8714 match(Set dst (CMoveF (Binary cmp xcc) (Binary dst src)));
8715 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt);
8716 ins_cost(150);
8717 size(4);
8718 format %{ "FCPYS$cmp $dst,$src" %}
8719 ins_encode %{
8720 __ fcpys($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
8721 %}
8722 ins_pipe(int_conditional_float_move);
8723 %}
8724
8725 instruct cmovDL_reg_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, regD dst, regD src) %{
8726 match(Set dst (CMoveD (Binary cmp xcc) (Binary dst src)));
8727 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
8728
8729 ins_cost(150);
8730 size(4);
8731 format %{ "FCPYD$cmp $dst,$src" %}
8732 ins_encode %{
8733 __ fcpyd($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
8734 %}
8735 ins_pipe(int_conditional_float_move);
8736 %}
8737
8738 instruct cmovDL_reg_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, regD dst, regD src) %{
8739 match(Set dst (CMoveD (Binary cmp xcc) (Binary dst src)));
8740 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne);
8741
8742 ins_cost(150);
8743 size(4);
8744 format %{ "FCPYD$cmp $dst,$src" %}
8745 ins_encode %{
8746 __ fcpyd($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
8747 %}
8748 ins_pipe(int_conditional_float_move);
8749 %}
8750
8751 instruct cmovDL_reg_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, regD dst, regD src) %{
8752 match(Set dst (CMoveD (Binary cmp xcc) (Binary dst src)));
8753 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt);
8754
8755 ins_cost(150);
8756 size(4);
8757 format %{ "FCPYD$cmp $dst,$src" %}
8758 ins_encode %{
8759 __ fcpyd($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
8760 %}
8761 ins_pipe(int_conditional_float_move);
8762 %}
8763
8764 // ============================================================================
8765 // Safepoint Instruction
8766 // rather than KILL R12, it would be better to use any reg as
8767 // TEMP. Can't do that at this point because it crashes the compiler
8768 instruct safePoint_poll(iRegP poll, R12RegI tmp, flagsReg icc) %{
8769 match(SafePoint poll);
8770 effect(USE poll, KILL tmp, KILL icc);
8771
8772 size(4);
8773 format %{ "LDR $tmp,[$poll]\t! Safepoint: poll for GC" %}
8774 ins_encode %{
8775 __ relocate(relocInfo::poll_type);
8776 __ ldr($tmp$$Register, Address($poll$$Register));
8777 %}
8778 ins_pipe(loadPollP);
8779 %}
8780
8781
8782 // ============================================================================
8783 // Call Instructions
8784 // Call Java Static Instruction
8785 instruct CallStaticJavaDirect( method meth ) %{
8786 match(CallStaticJava);
8787 effect(USE meth);
8788
8789 ins_cost(CALL_COST);
8790 format %{ "CALL,static ==> " %}
8791 ins_encode( SetInstMark, Java_Static_Call( meth ), call_epilog, ClearInstMark );
8792 ins_pipe(simple_call);
8793 %}
8794
8795 // Call Java Dynamic Instruction
8796 instruct CallDynamicJavaDirect( method meth ) %{
8797 match(CallDynamicJava);
8798 effect(USE meth);
8799
8800 ins_cost(CALL_COST);
8801 format %{ "MOV_OOP (empty),R_R8\n\t"
8802 "CALL,dynamic ; NOP ==> " %}
8803 ins_encode( SetInstMark, Java_Dynamic_Call( meth ), call_epilog, ClearInstMark );
8804 ins_pipe(call);
8805 %}
8806
8807 // Call Runtime Instruction
8808 instruct CallRuntimeDirect(method meth) %{
8809 match(CallRuntime);
8810 effect(USE meth);
8811 ins_cost(CALL_COST);
8812 format %{ "CALL,runtime" %}
8813 ins_encode( SetInstMark, Java_To_Runtime( meth ),
8814 call_epilog, ClearInstMark );
8815 ins_pipe(simple_call);
8816 %}
8817
8818 // Call runtime without safepoint - same as CallRuntime
8819 instruct CallLeafDirect(method meth) %{
8820 match(CallLeaf);
8821 effect(USE meth);
8822 ins_cost(CALL_COST);
8823 format %{ "CALL,runtime leaf" %}
8824 // TODO: need save_last_PC here?
8825 ins_encode( SetInstMark, Java_To_Runtime( meth ),
8826 call_epilog, ClearInstMark );
8827 ins_pipe(simple_call);
8828 %}
8829
8830 // Call runtime without safepoint - same as CallLeaf
8831 instruct CallLeafNoFPDirect(method meth) %{
8832 match(CallLeafNoFP);
8833 effect(USE meth);
8834 ins_cost(CALL_COST);
8835 format %{ "CALL,runtime leaf nofp" %}
8836 // TODO: need save_last_PC here?
8837 ins_encode( SetInstMark, Java_To_Runtime( meth ),
8838 call_epilog, ClearInstMark );
8839 ins_pipe(simple_call);
8840 %}
8841
8842 // Tail Call; Jump from runtime stub to Java code.
8843 // Also known as an 'interprocedural jump'.
8844 // Target of jump will eventually return to caller.
8845 // TailJump below removes the return address.
8846 instruct TailCalljmpInd(IPRegP jump_target, inline_cache_regP method_ptr) %{
8847 match(TailCall jump_target method_ptr);
8848
8849 ins_cost(CALL_COST);
8850 format %{ "jump $jump_target \t! $method_ptr holds method" %}
8851 ins_encode %{
8852 __ jump($jump_target$$Register);
8853 %}
8854 ins_pipe(tail_call);
8855 %}
8856
8857
8858 // Return Instruction
8859 instruct Ret() %{
8860 match(Return);
8861
8862 format %{ "ret LR" %}
8863
8864 ins_encode %{
8865 __ ret(LR);
8866 %}
8867
8868 ins_pipe(br);
8869 %}
8870
8871
8872 // Tail Jump; remove the return address; jump to target.
8873 // TailCall above leaves the return address around.
8874 // TailJump is used in only one place, the rethrow_Java stub (fancy_jump=2).
8875 // ex_oop (Exception Oop) is needed in %o0 at the jump. As there would be a
8876 // "restore" before this instruction (in Epilogue), we need to materialize it
8877 // in %i0.
8878 instruct tailjmpInd(IPRegP jump_target, RExceptionRegP ex_oop) %{
8879 match( TailJump jump_target ex_oop );
8880 ins_cost(CALL_COST);
8881 format %{ "MOV Rexception_pc, LR\n\t"
8882 "jump $jump_target \t! $ex_oop holds exc. oop" %}
8883 ins_encode %{
8884 __ mov(Rexception_pc, LR);
8885 __ jump($jump_target$$Register);
8886 %}
8887 ins_pipe(tail_call);
8888 %}
8889
8890 // Forward exception.
8891 instruct ForwardExceptionjmp()
8892 %{
8893 match(ForwardException);
8894 ins_cost(CALL_COST);
8895
8896 format %{ "MOV Rexception_pc, LR\n\t"
8897 "b forward_exception_entry" %}
8898 ins_encode %{
8899 __ mov(Rexception_pc, LR);
8900 // OK to trash Rtemp, because Rtemp is used by stub
8901 __ jump(StubRoutines::forward_exception_entry(), relocInfo::runtime_call_type, Rtemp);
8902 %}
8903 ins_pipe(tail_call);
8904 %}
8905
8906 // Create exception oop: created by stack-crawling runtime code.
8907 // Created exception is now available to this handler, and is setup
8908 // just prior to jumping to this handler. No code emitted.
8909 instruct CreateException( RExceptionRegP ex_oop )
8910 %{
8911 match(Set ex_oop (CreateEx));
8912 ins_cost(0);
8913
8914 size(0);
8915 // use the following format syntax
8916 format %{ "! exception oop is in Rexception_obj; no code emitted" %}
8917 ins_encode();
8918 ins_pipe(empty);
8919 %}
8920
8921
8922 // Rethrow exception:
8923 // The exception oop will come in the first argument position.
8924 // Then JUMP (not call) to the rethrow stub code.
8925 instruct RethrowException()
8926 %{
8927 match(Rethrow);
8928 ins_cost(CALL_COST);
8929
8930 // use the following format syntax
8931 format %{ "b rethrow_stub" %}
8932 ins_encode %{
8933 Register scratch = R1_tmp;
8934 assert_different_registers(scratch, c_rarg0, LR);
8935 __ jump(OptoRuntime::rethrow_stub(), relocInfo::runtime_call_type, scratch);
8936 %}
8937 ins_pipe(tail_call);
8938 %}
8939
8940
8941 // Die now
8942 instruct ShouldNotReachHere( )
8943 %{
8944 match(Halt);
8945 ins_cost(CALL_COST);
8946
8947 // Use the following format syntax
8948 format %{ "ShouldNotReachHere" %}
8949 ins_encode %{
8950 if (is_reachable()) {
8951 const char* str = __ code_string(_halt_reason);
8952 __ stop(str);
8953 }
8954 %}
8955 ins_pipe(tail_call);
8956 %}
8957
8958 // ============================================================================
8959 // The 2nd slow-half of a subtype check. Scan the subklass's 2ndary superklass
8960 // array for an instance of the superklass. Set a hidden internal cache on a
8961 // hit (cache is checked with exposed code in gen_subtype_check()). Return
8962 // not zero for a miss or zero for a hit. The encoding ALSO sets flags.
8963 instruct partialSubtypeCheck( R0RegP index, R1RegP sub, R2RegP super, flagsRegP pcc, LRRegP lr ) %{
8964 match(Set index (PartialSubtypeCheck sub super));
8965 effect( KILL pcc, KILL lr );
8966 ins_cost(DEFAULT_COST*10);
8967 format %{ "CALL PartialSubtypeCheck" %}
8968 ins_encode %{
8969 __ call(StubRoutines::Arm::partial_subtype_check(), relocInfo::runtime_call_type);
8970 %}
8971 ins_pipe(partial_subtype_check_pipe);
8972 %}
8973
8974 /* instruct partialSubtypeCheck_vs_zero( flagsRegP pcc, o1RegP sub, o2RegP super, immP0 zero, o0RegP idx, o7RegP o7 ) %{ */
8975 /* match(Set pcc (CmpP (PartialSubtypeCheck sub super) zero)); */
8976 /* ins_pipe(partial_subtype_check_pipe); */
8977 /* %} */
8978
8979
8980 // ============================================================================
8981 // inlined locking and unlocking
8982
8983 instruct cmpFastLock(flagsRegP pcc, iRegP object, iRegP box, iRegP scratch2, iRegP scratch )
8984 %{
8985 match(Set pcc (FastLock object box));
8986
8987 effect(TEMP scratch, TEMP scratch2);
8988 ins_cost(DEFAULT_COST*3);
8989
8990 format %{ "FASTLOCK $object, $box; KILL $scratch, $scratch2" %}
8991 ins_encode %{
8992 __ fast_lock($object$$Register, $box$$Register, $scratch$$Register, $scratch2$$Register);
8993 %}
8994 ins_pipe(long_memory_op);
8995 %}
8996
8997 instruct cmpFastUnlock(flagsRegP pcc, iRegP object, iRegP box, iRegP scratch2, iRegP scratch ) %{
8998 match(Set pcc (FastUnlock object box));
8999 effect(TEMP scratch, TEMP scratch2);
9000 ins_cost(100);
9001
9002 format %{ "FASTUNLOCK $object, $box; KILL $scratch, $scratch2" %}
9003 ins_encode %{
9004 __ fast_unlock($object$$Register, $box$$Register, $scratch$$Register, $scratch2$$Register);
9005 %}
9006 ins_pipe(long_memory_op);
9007 %}
9008
9009 // Count and Base registers are fixed because the allocator cannot
9010 // kill unknown registers. The encodings are generic.
9011 instruct clear_array(iRegX cnt, iRegP base, iRegI temp, iRegX zero, Universe dummy, flagsReg cpsr) %{
9012 match(Set dummy (ClearArray cnt base));
9013 effect(TEMP temp, TEMP zero, KILL cpsr);
9014 ins_cost(300);
9015 format %{ "MOV $zero,0\n"
9016 " MOV $temp,$cnt\n"
9017 "loop: SUBS $temp,$temp,4\t! Count down a dword of bytes\n"
9018 " STR.ge $zero,[$base+$temp]\n"
9019 " B.gt loop\t\t! Clearing loop\n" %}
9020 ins_encode %{
9021 __ mov($zero$$Register, 0);
9022 __ mov($temp$$Register, $cnt$$Register);
9023 Label loop;
9024 __ bind(loop);
9025 __ subs($temp$$Register, $temp$$Register, 4);
9026 __ str($zero$$Register, Address($base$$Register, $temp$$Register), ge);
9027 __ b(loop, gt);
9028 %}
9029 ins_pipe(long_memory_op);
9030 %}
9031
9032 #ifdef XXX
9033 // FIXME: Why R0/R1/R2/R3?
9034 instruct string_compare(R0RegP str1, R1RegP str2, R2RegI cnt1, R3RegI cnt2, iRegI result,
9035 iRegI tmp1, iRegI tmp2, flagsReg ccr) %{
9036 predicate(!CompactStrings);
9037 match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
9038 effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL ccr, TEMP tmp1, TEMP tmp2);
9039 ins_cost(300);
9040 format %{ "String Compare $str1,$cnt1,$str2,$cnt2 -> $result // TEMP $tmp1, $tmp2" %}
9041 ins_encode( enc_String_Compare(str1, str2, cnt1, cnt2, result, tmp1, tmp2) );
9042
9043 ins_pipe(long_memory_op);
9044 %}
9045
9046 // FIXME: Why R0/R1/R2?
9047 instruct string_equals(R0RegP str1, R1RegP str2, R2RegI cnt, iRegI result, iRegI tmp1, iRegI tmp2,
9048 flagsReg ccr) %{
9049 predicate(!CompactStrings);
9050 match(Set result (StrEquals (Binary str1 str2) cnt));
9051 effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt, TEMP tmp1, TEMP tmp2, TEMP result, KILL ccr);
9052
9053 ins_cost(300);
9054 format %{ "String Equals $str1,$str2,$cnt -> $result // TEMP $tmp1, $tmp2" %}
9055 ins_encode( enc_String_Equals(str1, str2, cnt, result, tmp1, tmp2) );
9056 ins_pipe(long_memory_op);
9057 %}
9058
9059 // FIXME: Why R0/R1?
9060 instruct array_equals(R0RegP ary1, R1RegP ary2, iRegI tmp1, iRegI tmp2, iRegI tmp3, iRegI result,
9061 flagsReg ccr) %{
9062 predicate(((AryEqNode*)n)->encoding() == StrIntrinsicNode::UU);
9063 match(Set result (AryEq ary1 ary2));
9064 effect(USE_KILL ary1, USE_KILL ary2, TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP result, KILL ccr);
9065
9066 ins_cost(300);
9067 format %{ "Array Equals $ary1,$ary2 -> $result // TEMP $tmp1,$tmp2,$tmp3" %}
9068 ins_encode( enc_Array_Equals(ary1, ary2, tmp1, tmp2, tmp3, result));
9069 ins_pipe(long_memory_op);
9070 %}
9071 #endif
9072
9073 //---------- Zeros Count Instructions ------------------------------------------
9074
9075 instruct countLeadingZerosI(iRegI dst, iRegI src) %{
9076 match(Set dst (CountLeadingZerosI src));
9077 size(4);
9078 format %{ "CLZ_32 $dst,$src" %}
9079 ins_encode %{
9080 __ clz_32($dst$$Register, $src$$Register);
9081 %}
9082 ins_pipe(ialu_reg);
9083 %}
9084
9085 instruct countLeadingZerosL(iRegI dst, iRegL src, iRegI tmp, flagsReg ccr) %{
9086 match(Set dst (CountLeadingZerosL src));
9087 effect(TEMP tmp, TEMP dst, KILL ccr);
9088 size(16);
9089 format %{ "CLZ $dst,$src.hi\n\t"
9090 "TEQ $dst,32\n\t"
9091 "CLZ.eq $tmp,$src.lo\n\t"
9092 "ADD.eq $dst, $dst, $tmp\n\t" %}
9093 ins_encode %{
9094 __ clz($dst$$Register, $src$$Register->successor());
9095 __ teq($dst$$Register, 32);
9096 __ clz($tmp$$Register, $src$$Register, eq);
9097 __ add($dst$$Register, $dst$$Register, $tmp$$Register, eq);
9098 %}
9099 ins_pipe(ialu_reg);
9100 %}
9101
9102 instruct countTrailingZerosI(iRegI dst, iRegI src, iRegI tmp) %{
9103 match(Set dst (CountTrailingZerosI src));
9104 effect(TEMP tmp);
9105 size(8);
9106 format %{ "RBIT_32 $tmp, $src\n\t"
9107 "CLZ_32 $dst,$tmp" %}
9108 ins_encode %{
9109 __ rbit_32($tmp$$Register, $src$$Register);
9110 __ clz_32($dst$$Register, $tmp$$Register);
9111 %}
9112 ins_pipe(ialu_reg);
9113 %}
9114
9115 instruct countTrailingZerosL(iRegI dst, iRegL src, iRegI tmp, flagsReg ccr) %{
9116 match(Set dst (CountTrailingZerosL src));
9117 effect(TEMP tmp, TEMP dst, KILL ccr);
9118 size(24);
9119 format %{ "RBIT $tmp,$src.lo\n\t"
9120 "CLZ $dst,$tmp\n\t"
9121 "TEQ $dst,32\n\t"
9122 "RBIT $tmp,$src.hi\n\t"
9123 "CLZ.eq $tmp,$tmp\n\t"
9124 "ADD.eq $dst,$dst,$tmp\n\t" %}
9125 ins_encode %{
9126 __ rbit($tmp$$Register, $src$$Register);
9127 __ clz($dst$$Register, $tmp$$Register);
9128 __ teq($dst$$Register, 32);
9129 __ rbit($tmp$$Register, $src$$Register->successor());
9130 __ clz($tmp$$Register, $tmp$$Register, eq);
9131 __ add($dst$$Register, $dst$$Register, $tmp$$Register, eq);
9132 %}
9133 ins_pipe(ialu_reg);
9134 %}
9135
9136
9137 //---------- Population Count Instructions -------------------------------------
9138
9139 instruct popCountI(iRegI dst, iRegI src, regD_low tmp) %{
9140 predicate(UsePopCountInstruction);
9141 match(Set dst (PopCountI src));
9142 effect(TEMP tmp);
9143
9144 format %{ "FMSR $tmp,$src\n\t"
9145 "VCNT.8 $tmp,$tmp\n\t"
9146 "VPADDL.U8 $tmp,$tmp\n\t"
9147 "VPADDL.U16 $tmp,$tmp\n\t"
9148 "FMRS $dst,$tmp" %}
9149 size(20);
9150
9151 ins_encode %{
9152 __ fmsr($tmp$$FloatRegister, $src$$Register);
9153 __ vcnt($tmp$$FloatRegister, $tmp$$FloatRegister);
9154 __ vpaddl($tmp$$FloatRegister, $tmp$$FloatRegister, 8, 0);
9155 __ vpaddl($tmp$$FloatRegister, $tmp$$FloatRegister, 16, 0);
9156 __ fmrs($dst$$Register, $tmp$$FloatRegister);
9157 %}
9158 ins_pipe(ialu_reg); // FIXME
9159 %}
9160
9161 // Note: Long.bitCount(long) returns an int.
9162 instruct popCountL(iRegI dst, iRegL src, regD_low tmp) %{
9163 predicate(UsePopCountInstruction);
9164 match(Set dst (PopCountL src));
9165 effect(TEMP tmp);
9166
9167 format %{ "FMDRR $tmp,$src.lo,$src.hi\n\t"
9168 "VCNT.8 $tmp,$tmp\n\t"
9169 "VPADDL.U8 $tmp,$tmp\n\t"
9170 "VPADDL.U16 $tmp,$tmp\n\t"
9171 "VPADDL.U32 $tmp,$tmp\n\t"
9172 "FMRS $dst,$tmp" %}
9173
9174 size(32);
9175
9176 ins_encode %{
9177 __ fmdrr($tmp$$FloatRegister, $src$$Register, $src$$Register->successor());
9178 __ vcnt($tmp$$FloatRegister, $tmp$$FloatRegister);
9179 __ vpaddl($tmp$$FloatRegister, $tmp$$FloatRegister, 8, 0);
9180 __ vpaddl($tmp$$FloatRegister, $tmp$$FloatRegister, 16, 0);
9181 __ vpaddl($tmp$$FloatRegister, $tmp$$FloatRegister, 32, 0);
9182 __ fmrs($dst$$Register, $tmp$$FloatRegister);
9183 %}
9184 ins_pipe(ialu_reg);
9185 %}
9186
9187
9188 // ============================================================================
9189 //------------Bytes reverse--------------------------------------------------
9190
9191 instruct bytes_reverse_int(iRegI dst, iRegI src) %{
9192 match(Set dst (ReverseBytesI src));
9193
9194 size(4);
9195 format %{ "REV32 $dst,$src" %}
9196 ins_encode %{
9197 __ rev($dst$$Register, $src$$Register);
9198 %}
9199 ins_pipe( iload_mem ); // FIXME
9200 %}
9201
9202 instruct bytes_reverse_long(iRegL dst, iRegL src) %{
9203 match(Set dst (ReverseBytesL src));
9204 effect(TEMP dst);
9205 size(8);
9206 format %{ "REV $dst.lo,$src.lo\n\t"
9207 "REV $dst.hi,$src.hi" %}
9208 ins_encode %{
9209 __ rev($dst$$Register, $src$$Register->successor());
9210 __ rev($dst$$Register->successor(), $src$$Register);
9211 %}
9212 ins_pipe( iload_mem ); // FIXME
9213 %}
9214
9215 instruct bytes_reverse_unsigned_short(iRegI dst, iRegI src) %{
9216 match(Set dst (ReverseBytesUS src));
9217 size(8);
9218 format %{ "REV32 $dst,$src\n\t"
9219 "LSR $dst,$dst,#16" %}
9220 ins_encode %{
9221 __ rev($dst$$Register, $src$$Register);
9222 __ mov($dst$$Register, AsmOperand($dst$$Register, lsr, 16));
9223 %}
9224 ins_pipe( iload_mem ); // FIXME
9225 %}
9226
9227 instruct bytes_reverse_short(iRegI dst, iRegI src) %{
9228 match(Set dst (ReverseBytesS src));
9229 size(4);
9230 format %{ "REVSH $dst,$src" %}
9231 ins_encode %{
9232 __ revsh($dst$$Register, $src$$Register);
9233 %}
9234 ins_pipe( iload_mem ); // FIXME
9235 %}
9236
9237
9238 // ====================VECTOR INSTRUCTIONS=====================================
9239
9240 // Load Aligned Packed values into a Double Register
9241 instruct loadV8(vecD dst, memoryD mem) %{
9242 predicate(n->as_LoadVector()->memory_size() == 8);
9243 match(Set dst (LoadVector mem));
9244 ins_cost(MEMORY_REF_COST);
9245 size(4);
9246 format %{ "FLDD $mem,$dst\t! load vector (8 bytes)" %}
9247 ins_encode %{
9248 __ ldr_double($dst$$FloatRegister, $mem$$Address);
9249 %}
9250 ins_pipe(floadD_mem);
9251 %}
9252
9253 // Load Aligned Packed values into a Double Register Pair
9254 instruct loadV16(vecX dst, memoryvld mem) %{
9255 predicate(n->as_LoadVector()->memory_size() == 16);
9256 match(Set dst (LoadVector mem));
9257 ins_cost(MEMORY_REF_COST);
9258 size(4);
9259 format %{ "VLD1 $mem,$dst.Q\t! load vector (16 bytes)" %}
9260 ins_encode %{
9261 __ vld1($dst$$FloatRegister, $mem$$Address, MacroAssembler::VELEM_SIZE_16, 128);
9262 %}
9263 ins_pipe(floadD_mem); // FIXME
9264 %}
9265
9266 // Store Vector in Double register to memory
9267 instruct storeV8(memoryD mem, vecD src) %{
9268 predicate(n->as_StoreVector()->memory_size() == 8);
9269 match(Set mem (StoreVector mem src));
9270 ins_cost(MEMORY_REF_COST);
9271 size(4);
9272 format %{ "FSTD $src,$mem\t! store vector (8 bytes)" %}
9273 ins_encode %{
9274 __ str_double($src$$FloatRegister, $mem$$Address);
9275 %}
9276 ins_pipe(fstoreD_mem_reg);
9277 %}
9278
9279 // Store Vector in Double Register Pair to memory
9280 instruct storeV16(memoryvld mem, vecX src) %{
9281 predicate(n->as_StoreVector()->memory_size() == 16);
9282 match(Set mem (StoreVector mem src));
9283 ins_cost(MEMORY_REF_COST);
9284 size(4);
9285 format %{ "VST1 $src,$mem\t! store vector (16 bytes)" %}
9286 ins_encode %{
9287 __ vst1($src$$FloatRegister, $mem$$Address, MacroAssembler::VELEM_SIZE_16, 128);
9288 %}
9289 ins_pipe(fstoreD_mem_reg); // FIXME
9290 %}
9291
9292 // Replicate scalar to packed byte values in Double register
9293 instruct Repl8B_reg(vecD dst, iRegI src, iRegI tmp) %{
9294 predicate(n->as_Vector()->length() == 8 &&
9295 Matcher::vector_element_basic_type(n) == T_BYTE);
9296 match(Set dst (Replicate src));
9297 ins_cost(DEFAULT_COST*4);
9298 effect(TEMP tmp);
9299 size(16);
9300
9301 // FIXME: could use PKH instruction instead?
9302 format %{ "LSL $tmp, $src, 24 \n\t"
9303 "OR $tmp, $tmp, ($tmp >> 8) \n\t"
9304 "OR $tmp, $tmp, ($tmp >> 16) \n\t"
9305 "FMDRR $dst,$tmp,$tmp\t" %}
9306 ins_encode %{
9307 __ mov($tmp$$Register, AsmOperand($src$$Register, lsl, 24));
9308 __ orr($tmp$$Register, $tmp$$Register, AsmOperand($tmp$$Register, lsr, 8));
9309 __ orr($tmp$$Register, $tmp$$Register, AsmOperand($tmp$$Register, lsr, 16));
9310 __ fmdrr($dst$$FloatRegister, $tmp$$Register, $tmp$$Register);
9311 %}
9312 ins_pipe(ialu_reg); // FIXME
9313 %}
9314
9315 // Replicate scalar to packed byte values in Double register
9316 instruct Repl8B_reg_simd(vecD dst, iRegI src) %{
9317 predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd() &&
9318 Matcher::vector_element_basic_type(n) == T_BYTE);
9319 match(Set dst (Replicate src));
9320 size(4);
9321
9322 format %{ "VDUP.8 $dst,$src\t" %}
9323 ins_encode %{
9324 bool quad = false;
9325 __ vdupI($dst$$FloatRegister, $src$$Register,
9326 MacroAssembler::VELEM_SIZE_8, quad);
9327 %}
9328 ins_pipe(ialu_reg); // FIXME
9329 %}
9330
9331 // Replicate scalar to packed byte values in Double register pair
9332 instruct Repl16B_reg(vecX dst, iRegI src) %{
9333 predicate(n->as_Vector()->length_in_bytes() == 16 &&
9334 Matcher::vector_element_basic_type(n) == T_BYTE);
9335 match(Set dst (Replicate src));
9336 size(4);
9337
9338 format %{ "VDUP.8 $dst.Q,$src\t" %}
9339 ins_encode %{
9340 bool quad = true;
9341 __ vdupI($dst$$FloatRegister, $src$$Register,
9342 MacroAssembler::VELEM_SIZE_8, quad);
9343 %}
9344 ins_pipe(ialu_reg); // FIXME
9345 %}
9346
9347 // Replicate scalar constant to packed byte values in Double register
9348 instruct Repl8B_immI(vecD dst, immI src, iRegI tmp) %{
9349 predicate(n->as_Vector()->length() == 8 &&
9350 Matcher::vector_element_basic_type(n) == T_BYTE);
9351 match(Set dst (Replicate src));
9352 ins_cost(DEFAULT_COST*2);
9353 effect(TEMP tmp);
9354 size(12);
9355
9356 format %{ "MOV $tmp, Repl4($src))\n\t"
9357 "FMDRR $dst,$tmp,$tmp\t" %}
9358 ins_encode( LdReplImmI(src, dst, tmp, (4), (1)) );
9359 ins_pipe(loadConFD); // FIXME
9360 %}
9361
9362 // Replicate scalar constant to packed byte values in Double register
9363 // TODO: support negative constants with MVNI?
9364 instruct Repl8B_immU8(vecD dst, immU8 src) %{
9365 predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd() &&
9366 Matcher::vector_element_basic_type(n) == T_BYTE);
9367 match(Set dst (Replicate src));
9368 size(4);
9369
9370 format %{ "VMOV.U8 $dst,$src" %}
9371 ins_encode %{
9372 bool quad = false;
9373 __ vmovI($dst$$FloatRegister, $src$$constant,
9374 MacroAssembler::VELEM_SIZE_8, quad);
9375 %}
9376 ins_pipe(loadConFD); // FIXME
9377 %}
9378
9379 // Replicate scalar constant to packed byte values in Double register pair
9380 instruct Repl16B_immU8(vecX dst, immU8 src) %{
9381 predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd() &&
9382 Matcher::vector_element_basic_type(n) == T_BYTE);
9383 match(Set dst (Replicate src));
9384 size(4);
9385
9386 format %{ "VMOV.U8 $dst.Q,$src" %}
9387 ins_encode %{
9388 bool quad = true;
9389 __ vmovI($dst$$FloatRegister, $src$$constant,
9390 MacroAssembler::VELEM_SIZE_8, quad);
9391 %}
9392 ins_pipe(loadConFD); // FIXME
9393 %}
9394
9395 // Replicate scalar to packed short/char values into Double register
9396 instruct Repl4S_reg(vecD dst, iRegI src, iRegI tmp) %{
9397 predicate(n->as_Vector()->length() == 4 &&
9398 Matcher::vector_element_basic_type(n) == T_SHORT);
9399 match(Set dst (Replicate src));
9400 ins_cost(DEFAULT_COST*3);
9401 effect(TEMP tmp);
9402 size(12);
9403
9404 // FIXME: could use PKH instruction instead?
9405 format %{ "LSL $tmp, $src, 16 \n\t"
9406 "OR $tmp, $tmp, ($tmp >> 16) \n\t"
9407 "FMDRR $dst,$tmp,$tmp\t" %}
9408 ins_encode %{
9409 __ mov($tmp$$Register, AsmOperand($src$$Register, lsl, 16));
9410 __ orr($tmp$$Register, $tmp$$Register, AsmOperand($tmp$$Register, lsr, 16));
9411 __ fmdrr($dst$$FloatRegister, $tmp$$Register, $tmp$$Register);
9412 %}
9413 ins_pipe(ialu_reg); // FIXME
9414 %}
9415
9416 // Replicate scalar to packed byte values in Double register
9417 instruct Repl4S_reg_simd(vecD dst, iRegI src) %{
9418 predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd() &&
9419 Matcher::vector_element_basic_type(n) == T_SHORT);
9420 match(Set dst (Replicate src));
9421 size(4);
9422
9423 format %{ "VDUP.16 $dst,$src\t" %}
9424 ins_encode %{
9425 bool quad = false;
9426 __ vdupI($dst$$FloatRegister, $src$$Register,
9427 MacroAssembler::VELEM_SIZE_16, quad);
9428 %}
9429 ins_pipe(ialu_reg); // FIXME
9430 %}
9431
9432 // Replicate scalar to packed byte values in Double register pair
9433 instruct Repl8S_reg(vecX dst, iRegI src) %{
9434 predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd() &&
9435 Matcher::vector_element_basic_type(n) == T_SHORT);
9436 match(Set dst (Replicate src));
9437 size(4);
9438
9439 format %{ "VDUP.16 $dst.Q,$src\t" %}
9440 ins_encode %{
9441 bool quad = true;
9442 __ vdupI($dst$$FloatRegister, $src$$Register,
9443 MacroAssembler::VELEM_SIZE_16, quad);
9444 %}
9445 ins_pipe(ialu_reg); // FIXME
9446 %}
9447
9448
9449 // Replicate scalar constant to packed short/char values in Double register
9450 instruct Repl4S_immI(vecD dst, immI src, iRegP tmp) %{
9451 predicate(n->as_Vector()->length() == 4 &&
9452 Matcher::vector_element_basic_type(n) == T_SHORT);
9453 match(Set dst (Replicate src));
9454 effect(TEMP tmp);
9455 size(12);
9456 ins_cost(DEFAULT_COST*4); // FIXME
9457
9458 format %{ "MOV $tmp, Repl2($src))\n\t"
9459 "FMDRR $dst,$tmp,$tmp\t" %}
9460 ins_encode( LdReplImmI(src, dst, tmp, (2), (2)) );
9461 ins_pipe(loadConFD); // FIXME
9462 %}
9463
9464 // Replicate scalar constant to packed byte values in Double register
9465 instruct Repl4S_immU8(vecD dst, immU8 src) %{
9466 predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd() &&
9467 Matcher::vector_element_basic_type(n) == T_SHORT);
9468 match(Set dst (Replicate src));
9469 size(4);
9470
9471 format %{ "VMOV.U16 $dst,$src" %}
9472 ins_encode %{
9473 bool quad = false;
9474 __ vmovI($dst$$FloatRegister, $src$$constant,
9475 MacroAssembler::VELEM_SIZE_16, quad);
9476 %}
9477 ins_pipe(loadConFD); // FIXME
9478 %}
9479
9480 // Replicate scalar constant to packed byte values in Double register pair
9481 instruct Repl8S_immU8(vecX dst, immU8 src) %{
9482 predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd() &&
9483 Matcher::vector_element_basic_type(n) == T_SHORT);
9484 match(Set dst (Replicate src));
9485 size(4);
9486
9487 format %{ "VMOV.U16 $dst.Q,$src" %}
9488 ins_encode %{
9489 bool quad = true;
9490 __ vmovI($dst$$FloatRegister, $src$$constant,
9491 MacroAssembler::VELEM_SIZE_16, quad);
9492 %}
9493 ins_pipe(loadConFD); // FIXME
9494 %}
9495
9496 // Replicate scalar to packed int values in Double register
9497 instruct Repl2I_reg(vecD dst, iRegI src) %{
9498 predicate(n->as_Vector()->length() == 2 &&
9499 Matcher::vector_element_basic_type(n) == T_INT);
9500 match(Set dst (Replicate src));
9501 size(4);
9502
9503 format %{ "FMDRR $dst,$src,$src\t" %}
9504 ins_encode %{
9505 __ fmdrr($dst$$FloatRegister, $src$$Register, $src$$Register);
9506 %}
9507 ins_pipe(ialu_reg); // FIXME
9508 %}
9509
9510 // Replicate scalar to packed int values in Double register pair
9511 instruct Repl4I_reg(vecX dst, iRegI src) %{
9512 predicate(n->as_Vector()->length() == 4 &&
9513 Matcher::vector_element_basic_type(n) == T_INT);
9514 match(Set dst (Replicate src));
9515 ins_cost(DEFAULT_COST*2);
9516 size(8);
9517
9518 format %{ "FMDRR $dst.lo,$src,$src\n\t"
9519 "FMDRR $dst.hi,$src,$src" %}
9520
9521 ins_encode %{
9522 __ fmdrr($dst$$FloatRegister, $src$$Register, $src$$Register);
9523 __ fmdrr($dst$$FloatRegister->successor()->successor(),
9524 $src$$Register, $src$$Register);
9525 %}
9526 ins_pipe(ialu_reg); // FIXME
9527 %}
9528
9529 // Replicate scalar to packed int values in Double register
9530 instruct Repl2I_reg_simd(vecD dst, iRegI src) %{
9531 predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd() &&
9532 Matcher::vector_element_basic_type(n) == T_INT);
9533 match(Set dst (Replicate src));
9534 size(4);
9535
9536 format %{ "VDUP.32 $dst.D,$src\t" %}
9537 ins_encode %{
9538 bool quad = false;
9539 __ vdupI($dst$$FloatRegister, $src$$Register,
9540 MacroAssembler::VELEM_SIZE_32, quad);
9541 %}
9542 ins_pipe(ialu_reg); // FIXME
9543 %}
9544
9545 // Replicate scalar to packed int values in Double register pair
9546 instruct Repl4I_reg_simd(vecX dst, iRegI src) %{
9547 predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd() &&
9548 Matcher::vector_element_basic_type(n) == T_INT);
9549 match(Set dst (Replicate src));
9550 size(4);
9551
9552 format %{ "VDUP.32 $dst.Q,$src\t" %}
9553 ins_encode %{
9554 bool quad = true;
9555 __ vdupI($dst$$FloatRegister, $src$$Register,
9556 MacroAssembler::VELEM_SIZE_32, quad);
9557 %}
9558 ins_pipe(ialu_reg); // FIXME
9559 %}
9560
9561
9562 // Replicate scalar zero constant to packed int values in Double register
9563 instruct Repl2I_immI(vecD dst, immI src, iRegI tmp) %{
9564 predicate(n->as_Vector()->length() == 2 &&
9565 Matcher::vector_element_basic_type(n) == T_INT);
9566 match(Set dst (Replicate src));
9567 effect(TEMP tmp);
9568 size(12);
9569 ins_cost(DEFAULT_COST*4); // FIXME
9570
9571 format %{ "MOV $tmp, Repl1($src))\n\t"
9572 "FMDRR $dst,$tmp,$tmp\t" %}
9573 ins_encode( LdReplImmI(src, dst, tmp, (1), (4)) );
9574 ins_pipe(loadConFD); // FIXME
9575 %}
9576
9577 // Replicate scalar constant to packed byte values in Double register
9578 instruct Repl2I_immU8(vecD dst, immU8 src) %{
9579 predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd() &&
9580 Matcher::vector_element_basic_type(n) == T_INT);
9581 match(Set dst (Replicate src));
9582 size(4);
9583
9584 format %{ "VMOV.I32 $dst.D,$src" %}
9585 ins_encode %{
9586 bool quad = false;
9587 __ vmovI($dst$$FloatRegister, $src$$constant,
9588 MacroAssembler::VELEM_SIZE_32, quad);
9589 %}
9590 ins_pipe(loadConFD); // FIXME
9591 %}
9592
9593 // Replicate scalar constant to packed byte values in Double register pair
9594 instruct Repl4I_immU8(vecX dst, immU8 src) %{
9595 predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd() &&
9596 Matcher::vector_element_basic_type(n) == T_INT);
9597 match(Set dst (Replicate src));
9598 size(4);
9599
9600 format %{ "VMOV.I32 $dst.Q,$src" %}
9601 ins_encode %{
9602 bool quad = true;
9603 __ vmovI($dst$$FloatRegister, $src$$constant,
9604 MacroAssembler::VELEM_SIZE_32, quad);
9605 %}
9606 ins_pipe(loadConFD); // FIXME
9607 %}
9608
9609 // Replicate scalar to packed byte values in Double register pair
9610 instruct Repl2L_reg(vecX dst, iRegL src) %{
9611 predicate(n->as_Vector()->length() == 2 &&
9612 Matcher::vector_element_basic_type(n) == T_LONG);
9613 match(Set dst (Replicate src));
9614 size(8);
9615 ins_cost(DEFAULT_COST*2); // FIXME
9616
9617 format %{ "FMDRR $dst.D,$src.lo,$src.hi\t\n"
9618 "FMDRR $dst.D.next,$src.lo,$src.hi" %}
9619 ins_encode %{
9620 __ fmdrr($dst$$FloatRegister, $src$$Register, $src$$Register->successor());
9621 __ fmdrr($dst$$FloatRegister->successor()->successor(),
9622 $src$$Register, $src$$Register->successor());
9623 %}
9624 ins_pipe(ialu_reg); // FIXME
9625 %}
9626
9627
9628 // Replicate scalar to packed float values in Double register
9629 instruct Repl2F_regI(vecD dst, iRegI src) %{
9630 predicate(n->as_Vector()->length() == 2 &&
9631 Matcher::vector_element_basic_type(n) == T_FLOAT);
9632 match(Set dst (Replicate src));
9633 size(4);
9634
9635 format %{ "FMDRR $dst.D,$src,$src\t" %}
9636 ins_encode %{
9637 __ fmdrr($dst$$FloatRegister, $src$$Register, $src$$Register);
9638 %}
9639 ins_pipe(ialu_reg); // FIXME
9640 %}
9641
9642 // Replicate scalar to packed float values in Double register
9643 instruct Repl2F_reg_vfp(vecD dst, regF src) %{
9644 predicate(n->as_Vector()->length() == 2 &&
9645 Matcher::vector_element_basic_type(n) == T_FLOAT);
9646 match(Set dst (Replicate src));
9647 size(4*2);
9648 ins_cost(DEFAULT_COST*2); // FIXME
9649
9650 expand %{
9651 iRegI tmp;
9652 MoveF2I_reg_reg(tmp, src);
9653 Repl2F_regI(dst,tmp);
9654 %}
9655 %}
9656
9657 // Replicate scalar to packed float values in Double register
9658 instruct Repl2F_reg_simd(vecD dst, regF src) %{
9659 predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd() &&
9660 Matcher::vector_element_basic_type(n) == T_FLOAT);
9661 match(Set dst (Replicate src));
9662 size(4);
9663 ins_cost(DEFAULT_COST); // FIXME
9664
9665 format %{ "VDUP.32 $dst.D,$src.D\t" %}
9666 ins_encode %{
9667 bool quad = false;
9668 __ vdupF($dst$$FloatRegister, $src$$FloatRegister, quad);
9669 %}
9670 ins_pipe(ialu_reg); // FIXME
9671 %}
9672
9673 // Replicate scalar to packed float values in Double register pair
9674 instruct Repl4F_reg(vecX dst, regF src, iRegI tmp) %{
9675 predicate(n->as_Vector()->length() == 4 &&
9676 Matcher::vector_element_basic_type(n) == T_FLOAT);
9677 match(Set dst (Replicate src));
9678 effect(TEMP tmp);
9679 size(4*3);
9680 ins_cost(DEFAULT_COST*3); // FIXME
9681
9682 format %{ "FMRS $tmp,$src\n\t"
9683 "FMDRR $dst.D,$tmp,$tmp\n\t"
9684 "FMDRR $dst.D.next,$tmp,$tmp\t" %}
9685 ins_encode %{
9686 __ fmrs($tmp$$Register, $src$$FloatRegister);
9687 __ fmdrr($dst$$FloatRegister, $tmp$$Register, $tmp$$Register);
9688 __ fmdrr($dst$$FloatRegister->successor()->successor(),
9689 $tmp$$Register, $tmp$$Register);
9690 %}
9691 ins_pipe(ialu_reg); // FIXME
9692 %}
9693
9694 // Replicate scalar to packed float values in Double register pair
9695 instruct Repl4F_reg_simd(vecX dst, regF src) %{
9696 predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd() &&
9697 Matcher::vector_element_basic_type(n) == T_FLOAT);
9698 match(Set dst (Replicate src));
9699 size(4);
9700 ins_cost(DEFAULT_COST); // FIXME
9701
9702 format %{ "VDUP.32 $dst.Q,$src.D\t" %}
9703 ins_encode %{
9704 bool quad = true;
9705 __ vdupF($dst$$FloatRegister, $src$$FloatRegister, quad);
9706 %}
9707 ins_pipe(ialu_reg); // FIXME
9708 %}
9709
9710 // Replicate scalar zero constant to packed float values in Double register
9711 instruct Repl2F_immI(vecD dst, immF src, iRegI tmp) %{
9712 predicate(n->as_Vector()->length() == 2 &&
9713 Matcher::vector_element_basic_type(n) == T_FLOAT);
9714 match(Set dst (Replicate src));
9715 effect(TEMP tmp);
9716 size(12);
9717 ins_cost(DEFAULT_COST*4); // FIXME
9718
9719 format %{ "MOV $tmp, Repl1($src))\n\t"
9720 "FMDRR $dst,$tmp,$tmp\t" %}
9721 ins_encode( LdReplImmF(src, dst, tmp) );
9722 ins_pipe(loadConFD); // FIXME
9723 %}
9724
9725 // Replicate scalar to packed double float values in Double register pair
9726 instruct Repl2D_reg(vecX dst, regD src) %{
9727 predicate(n->as_Vector()->length() == 2 &&
9728 Matcher::vector_element_basic_type(n) == T_DOUBLE);
9729 match(Set dst (Replicate src));
9730 size(4*2);
9731 ins_cost(DEFAULT_COST*2); // FIXME
9732
9733 format %{ "FCPYD $dst.D.a,$src\n\t"
9734 "FCPYD $dst.D.b,$src\t" %}
9735 ins_encode %{
9736 FloatRegister dsta = $dst$$FloatRegister;
9737 FloatRegister src = $src$$FloatRegister;
9738 __ fcpyd(dsta, src);
9739 FloatRegister dstb = dsta->successor()->successor();
9740 __ fcpyd(dstb, src);
9741 %}
9742 ins_pipe(ialu_reg); // FIXME
9743 %}
9744
9745 // ====================VECTOR ARITHMETIC=======================================
9746
9747 // --------------------------------- ADD --------------------------------------
9748
9749 // Bytes vector add
9750 instruct vadd8B_reg(vecD dst, vecD src1, vecD src2) %{
9751 predicate(n->as_Vector()->length() == 8);
9752 match(Set dst (AddVB src1 src2));
9753 format %{ "VADD.I8 $dst,$src1,$src2\t! add packed8B" %}
9754 size(4);
9755 ins_encode %{
9756 bool quad = false;
9757 __ vaddI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
9758 MacroAssembler::VELEM_SIZE_8, quad);
9759 %}
9760 ins_pipe( ialu_reg_reg ); // FIXME
9761 %}
9762
9763 instruct vadd16B_reg(vecX dst, vecX src1, vecX src2) %{
9764 predicate(n->as_Vector()->length() == 16);
9765 match(Set dst (AddVB src1 src2));
9766 size(4);
9767 format %{ "VADD.I8 $dst.Q,$src1.Q,$src2.Q\t! add packed16B" %}
9768 ins_encode %{
9769 bool quad = true;
9770 __ vaddI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
9771 MacroAssembler::VELEM_SIZE_8, quad);
9772 %}
9773 ins_pipe( ialu_reg_reg ); // FIXME
9774 %}
9775
9776 // Shorts/Chars vector add
9777 instruct vadd4S_reg(vecD dst, vecD src1, vecD src2) %{
9778 predicate(n->as_Vector()->length() == 4);
9779 match(Set dst (AddVS src1 src2));
9780 size(4);
9781 format %{ "VADD.I16 $dst,$src1,$src2\t! add packed4S" %}
9782 ins_encode %{
9783 bool quad = false;
9784 __ vaddI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
9785 MacroAssembler::VELEM_SIZE_16, quad);
9786 %}
9787 ins_pipe( ialu_reg_reg ); // FIXME
9788 %}
9789
9790 instruct vadd8S_reg(vecX dst, vecX src1, vecX src2) %{
9791 predicate(n->as_Vector()->length() == 8);
9792 match(Set dst (AddVS src1 src2));
9793 size(4);
9794 format %{ "VADD.I16 $dst.Q,$src1.Q,$src2.Q\t! add packed8S" %}
9795 ins_encode %{
9796 bool quad = true;
9797 __ vaddI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
9798 MacroAssembler::VELEM_SIZE_16, quad);
9799 %}
9800 ins_pipe( ialu_reg_reg ); // FIXME
9801 %}
9802
9803 // Integers vector add
9804 instruct vadd2I_reg(vecD dst, vecD src1, vecD src2) %{
9805 predicate(n->as_Vector()->length() == 2);
9806 match(Set dst (AddVI src1 src2));
9807 size(4);
9808 format %{ "VADD.I32 $dst.D,$src1.D,$src2.D\t! add packed2I" %}
9809 ins_encode %{
9810 bool quad = false;
9811 __ vaddI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
9812 MacroAssembler::VELEM_SIZE_32, quad);
9813 %}
9814 ins_pipe( ialu_reg_reg ); // FIXME
9815 %}
9816
9817 instruct vadd4I_reg(vecX dst, vecX src1, vecX src2) %{
9818 predicate(n->as_Vector()->length() == 4);
9819 match(Set dst (AddVI src1 src2));
9820 size(4);
9821 format %{ "VADD.I32 $dst.Q,$src1.Q,$src2.Q\t! add packed4I" %}
9822 ins_encode %{
9823 bool quad = true;
9824 __ vaddI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
9825 MacroAssembler::VELEM_SIZE_32, quad);
9826 %}
9827 ins_pipe( ialu_reg_reg ); // FIXME
9828 %}
9829
9830 // Longs vector add
9831 instruct vadd2L_reg(vecX dst, vecX src1, vecX src2) %{
9832 predicate(n->as_Vector()->length() == 2);
9833 match(Set dst (AddVL src1 src2));
9834 size(4);
9835 format %{ "VADD.I64 $dst.Q,$src1.Q,$src2.Q\t! add packed2L" %}
9836 ins_encode %{
9837 bool quad = true;
9838 __ vaddI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
9839 MacroAssembler::VELEM_SIZE_64, quad);
9840 %}
9841 ins_pipe( ialu_reg_reg ); // FIXME
9842 %}
9843
9844 // Floats vector add
9845 instruct vadd2F_reg(vecD dst, vecD src1, vecD src2) %{
9846 predicate(n->as_Vector()->length() == 2 && VM_Version::simd_math_is_compliant());
9847 match(Set dst (AddVF src1 src2));
9848 size(4);
9849 format %{ "VADD.F32 $dst,$src1,$src2\t! add packed2F" %}
9850 ins_encode %{
9851 bool quad = false;
9852 __ vaddF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
9853 MacroAssembler::VFA_SIZE_F32, quad);
9854 %}
9855 ins_pipe( faddD_reg_reg ); // FIXME
9856 %}
9857
9858 instruct vadd2F_reg_vfp(vecD dst, vecD src1, vecD src2) %{
9859 predicate(n->as_Vector()->length() == 2 && !VM_Version::simd_math_is_compliant());
9860 match(Set dst (AddVF src1 src2));
9861 ins_cost(DEFAULT_COST*2); // FIXME
9862
9863 size(4*2);
9864 format %{ "FADDS $dst.a,$src1.a,$src2.a\n\t"
9865 "FADDS $dst.b,$src1.b,$src2.b" %}
9866 ins_encode %{
9867 __ add_float($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
9868 __ add_float($dst$$FloatRegister->successor(),
9869 $src1$$FloatRegister->successor(),
9870 $src2$$FloatRegister->successor());
9871 %}
9872
9873 ins_pipe(faddF_reg_reg); // FIXME
9874 %}
9875
9876 instruct vadd4F_reg_simd(vecX dst, vecX src1, vecX src2) %{
9877 predicate(n->as_Vector()->length() == 4 && VM_Version::simd_math_is_compliant());
9878 match(Set dst (AddVF src1 src2));
9879 size(4);
9880 format %{ "VADD.F32 $dst.Q,$src1.Q,$src2.Q\t! add packed4F" %}
9881 ins_encode %{
9882 bool quad = true;
9883 __ vaddF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
9884 MacroAssembler::VFA_SIZE_F32, quad);
9885 %}
9886 ins_pipe( faddD_reg_reg ); // FIXME
9887 %}
9888
9889 instruct vadd4F_reg_vfp(vecX dst, vecX src1, vecX src2) %{
9890 predicate(n->as_Vector()->length() == 4 && !VM_Version::simd_math_is_compliant());
9891 match(Set dst (AddVF src1 src2));
9892 size(4*4);
9893 ins_cost(DEFAULT_COST*4); // FIXME
9894
9895 format %{ "FADDS $dst.a,$src1.a,$src2.a\n\t"
9896 "FADDS $dst.b,$src1.b,$src2.b\n\t"
9897 "FADDS $dst.c,$src1.c,$src2.c\n\t"
9898 "FADDS $dst.d,$src1.d,$src2.d" %}
9899
9900 ins_encode %{
9901 FloatRegister dsta = $dst$$FloatRegister;
9902 FloatRegister src1a = $src1$$FloatRegister;
9903 FloatRegister src2a = $src2$$FloatRegister;
9904 __ add_float(dsta, src1a, src2a);
9905 FloatRegister dstb = dsta->successor();
9906 FloatRegister src1b = src1a->successor();
9907 FloatRegister src2b = src2a->successor();
9908 __ add_float(dstb, src1b, src2b);
9909 FloatRegister dstc = dstb->successor();
9910 FloatRegister src1c = src1b->successor();
9911 FloatRegister src2c = src2b->successor();
9912 __ add_float(dstc, src1c, src2c);
9913 FloatRegister dstd = dstc->successor();
9914 FloatRegister src1d = src1c->successor();
9915 FloatRegister src2d = src2c->successor();
9916 __ add_float(dstd, src1d, src2d);
9917 %}
9918
9919 ins_pipe(faddF_reg_reg); // FIXME
9920 %}
9921
9922 instruct vadd2D_reg_vfp(vecX dst, vecX src1, vecX src2) %{
9923 predicate(n->as_Vector()->length() == 2);
9924 match(Set dst (AddVD src1 src2));
9925 size(4*2);
9926 ins_cost(DEFAULT_COST*2); // FIXME
9927
9928 format %{ "FADDD $dst.a,$src1.a,$src2.a\n\t"
9929 "FADDD $dst.b,$src1.b,$src2.b" %}
9930
9931 ins_encode %{
9932 FloatRegister dsta = $dst$$FloatRegister;
9933 FloatRegister src1a = $src1$$FloatRegister;
9934 FloatRegister src2a = $src2$$FloatRegister;
9935 __ add_double(dsta, src1a, src2a);
9936 FloatRegister dstb = dsta->successor()->successor();
9937 FloatRegister src1b = src1a->successor()->successor();
9938 FloatRegister src2b = src2a->successor()->successor();
9939 __ add_double(dstb, src1b, src2b);
9940 %}
9941
9942 ins_pipe(faddF_reg_reg); // FIXME
9943 %}
9944
9945
9946 // Bytes vector sub
9947 instruct vsub8B_reg(vecD dst, vecD src1, vecD src2) %{
9948 predicate(n->as_Vector()->length() == 8);
9949 match(Set dst (SubVB src1 src2));
9950 size(4);
9951 format %{ "VSUB.I8 $dst,$src1,$src2\t! sub packed8B" %}
9952 ins_encode %{
9953 bool quad = false;
9954 __ vsubI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
9955 MacroAssembler::VELEM_SIZE_8, quad);
9956 %}
9957 ins_pipe( ialu_reg_reg ); // FIXME
9958 %}
9959
9960 instruct vsub16B_reg(vecX dst, vecX src1, vecX src2) %{
9961 predicate(n->as_Vector()->length() == 16);
9962 match(Set dst (SubVB src1 src2));
9963 size(4);
9964 format %{ "VSUB.I8 $dst.Q,$src1.Q,$src2.Q\t! sub packed16B" %}
9965 ins_encode %{
9966 bool quad = true;
9967 __ vsubI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
9968 MacroAssembler::VELEM_SIZE_8, quad);
9969 %}
9970 ins_pipe( ialu_reg_reg ); // FIXME
9971 %}
9972
9973 // Shorts/Chars vector sub
9974 instruct vsub4S_reg(vecD dst, vecD src1, vecD src2) %{
9975 predicate(n->as_Vector()->length() == 4);
9976 match(Set dst (SubVS src1 src2));
9977 size(4);
9978 format %{ "VSUB.I16 $dst,$src1,$src2\t! sub packed4S" %}
9979 ins_encode %{
9980 bool quad = false;
9981 __ vsubI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
9982 MacroAssembler::VELEM_SIZE_16, quad);
9983 %}
9984 ins_pipe( ialu_reg_reg ); // FIXME
9985 %}
9986
9987 instruct vsub16S_reg(vecX dst, vecX src1, vecX src2) %{
9988 predicate(n->as_Vector()->length() == 8);
9989 match(Set dst (SubVS src1 src2));
9990 size(4);
9991 format %{ "VSUB.I16 $dst.Q,$src1.Q,$src2.Q\t! sub packed8S" %}
9992 ins_encode %{
9993 bool quad = true;
9994 __ vsubI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
9995 MacroAssembler::VELEM_SIZE_16, quad);
9996 %}
9997 ins_pipe( ialu_reg_reg ); // FIXME
9998 %}
9999
10000 // Integers vector sub
10001 instruct vsub2I_reg(vecD dst, vecD src1, vecD src2) %{
10002 predicate(n->as_Vector()->length() == 2);
10003 match(Set dst (SubVI src1 src2));
10004 size(4);
10005 format %{ "VSUB.I32 $dst,$src1,$src2\t! sub packed2I" %}
10006 ins_encode %{
10007 bool quad = false;
10008 __ vsubI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
10009 MacroAssembler::VELEM_SIZE_32, quad);
10010 %}
10011 ins_pipe( ialu_reg_reg ); // FIXME
10012 %}
10013
10014 instruct vsub4I_reg(vecX dst, vecX src1, vecX src2) %{
10015 predicate(n->as_Vector()->length() == 4);
10016 match(Set dst (SubVI src1 src2));
10017 size(4);
10018 format %{ "VSUB.I32 $dst.Q,$src1.Q,$src2.Q\t! sub packed4I" %}
10019 ins_encode %{
10020 bool quad = true;
10021 __ vsubI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
10022 MacroAssembler::VELEM_SIZE_32, quad);
10023 %}
10024 ins_pipe( ialu_reg_reg ); // FIXME
10025 %}
10026
10027 // Longs vector sub
10028 instruct vsub2L_reg(vecX dst, vecX src1, vecX src2) %{
10029 predicate(n->as_Vector()->length() == 2);
10030 match(Set dst (SubVL src1 src2));
10031 size(4);
10032 format %{ "VSUB.I64 $dst.Q,$src1.Q,$src2.Q\t! sub packed2L" %}
10033 ins_encode %{
10034 bool quad = true;
10035 __ vsubI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
10036 MacroAssembler::VELEM_SIZE_64, quad);
10037 %}
10038 ins_pipe( ialu_reg_reg ); // FIXME
10039 %}
10040
10041 // Floats vector sub
10042 instruct vsub2F_reg(vecD dst, vecD src1, vecD src2) %{
10043 predicate(n->as_Vector()->length() == 2 && VM_Version::simd_math_is_compliant());
10044 match(Set dst (SubVF src1 src2));
10045 size(4);
10046 format %{ "VSUB.F32 $dst,$src1,$src2\t! sub packed2F" %}
10047 ins_encode %{
10048 bool quad = false;
10049 __ vsubF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
10050 MacroAssembler::VFA_SIZE_F32, quad);
10051 %}
10052 ins_pipe( faddF_reg_reg ); // FIXME
10053 %}
10054
10055 instruct vsub2F_reg_vfp(vecD dst, vecD src1, vecD src2) %{
10056 predicate(n->as_Vector()->length() == 2 && !VM_Version::simd_math_is_compliant());
10057 match(Set dst (SubVF src1 src2));
10058 size(4*2);
10059 ins_cost(DEFAULT_COST*2); // FIXME
10060
10061 format %{ "FSUBS $dst.a,$src1.a,$src2.a\n\t"
10062 "FSUBS $dst.b,$src1.b,$src2.b" %}
10063
10064 ins_encode %{
10065 FloatRegister dsta = $dst$$FloatRegister;
10066 FloatRegister src1a = $src1$$FloatRegister;
10067 FloatRegister src2a = $src2$$FloatRegister;
10068 __ sub_float(dsta, src1a, src2a);
10069 FloatRegister dstb = dsta->successor();
10070 FloatRegister src1b = src1a->successor();
10071 FloatRegister src2b = src2a->successor();
10072 __ sub_float(dstb, src1b, src2b);
10073 %}
10074
10075 ins_pipe(faddF_reg_reg); // FIXME
10076 %}
10077
10078
10079 instruct vsub4F_reg(vecX dst, vecX src1, vecX src2) %{
10080 predicate(n->as_Vector()->length() == 4 && VM_Version::simd_math_is_compliant());
10081 match(Set dst (SubVF src1 src2));
10082 size(4);
10083 format %{ "VSUB.F32 $dst.Q,$src1.Q,$src2.Q\t! sub packed4F" %}
10084 ins_encode %{
10085 bool quad = true;
10086 __ vsubF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
10087 MacroAssembler::VFA_SIZE_F32, quad);
10088 %}
10089 ins_pipe( faddF_reg_reg ); // FIXME
10090 %}
10091
10092 instruct vsub4F_reg_vfp(vecX dst, vecX src1, vecX src2) %{
10093 predicate(n->as_Vector()->length() == 4 && !VM_Version::simd_math_is_compliant());
10094 match(Set dst (SubVF src1 src2));
10095 size(4*4);
10096 ins_cost(DEFAULT_COST*4); // FIXME
10097
10098 format %{ "FSUBS $dst.a,$src1.a,$src2.a\n\t"
10099 "FSUBS $dst.b,$src1.b,$src2.b\n\t"
10100 "FSUBS $dst.c,$src1.c,$src2.c\n\t"
10101 "FSUBS $dst.d,$src1.d,$src2.d" %}
10102
10103 ins_encode %{
10104 FloatRegister dsta = $dst$$FloatRegister;
10105 FloatRegister src1a = $src1$$FloatRegister;
10106 FloatRegister src2a = $src2$$FloatRegister;
10107 __ sub_float(dsta, src1a, src2a);
10108 FloatRegister dstb = dsta->successor();
10109 FloatRegister src1b = src1a->successor();
10110 FloatRegister src2b = src2a->successor();
10111 __ sub_float(dstb, src1b, src2b);
10112 FloatRegister dstc = dstb->successor();
10113 FloatRegister src1c = src1b->successor();
10114 FloatRegister src2c = src2b->successor();
10115 __ sub_float(dstc, src1c, src2c);
10116 FloatRegister dstd = dstc->successor();
10117 FloatRegister src1d = src1c->successor();
10118 FloatRegister src2d = src2c->successor();
10119 __ sub_float(dstd, src1d, src2d);
10120 %}
10121
10122 ins_pipe(faddF_reg_reg); // FIXME
10123 %}
10124
10125 instruct vsub2D_reg_vfp(vecX dst, vecX src1, vecX src2) %{
10126 predicate(n->as_Vector()->length() == 2);
10127 match(Set dst (SubVD src1 src2));
10128 size(4*2);
10129 ins_cost(DEFAULT_COST*2); // FIXME
10130
10131 format %{ "FSUBD $dst.a,$src1.a,$src2.a\n\t"
10132 "FSUBD $dst.b,$src1.b,$src2.b" %}
10133
10134 ins_encode %{
10135 FloatRegister dsta = $dst$$FloatRegister;
10136 FloatRegister src1a = $src1$$FloatRegister;
10137 FloatRegister src2a = $src2$$FloatRegister;
10138 __ sub_double(dsta, src1a, src2a);
10139 FloatRegister dstb = dsta->successor()->successor();
10140 FloatRegister src1b = src1a->successor()->successor();
10141 FloatRegister src2b = src2a->successor()->successor();
10142 __ sub_double(dstb, src1b, src2b);
10143 %}
10144
10145 ins_pipe(faddF_reg_reg); // FIXME
10146 %}
10147
10148 // Shorts/Chars vector mul
10149 instruct vmul4S_reg(vecD dst, vecD src1, vecD src2) %{
10150 predicate(n->as_Vector()->length() == 4);
10151 match(Set dst (MulVS src1 src2));
10152 size(4);
10153 format %{ "VMUL.I16 $dst,$src1,$src2\t! mul packed4S" %}
10154 ins_encode %{
10155 __ vmulI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
10156 MacroAssembler::VELEM_SIZE_16, 0);
10157 %}
10158 ins_pipe( ialu_reg_reg ); // FIXME
10159 %}
10160
10161 instruct vmul8S_reg(vecX dst, vecX src1, vecX src2) %{
10162 predicate(n->as_Vector()->length() == 8);
10163 match(Set dst (MulVS src1 src2));
10164 size(4);
10165 format %{ "VMUL.I16 $dst.Q,$src1.Q,$src2.Q\t! mul packed8S" %}
10166 ins_encode %{
10167 __ vmulI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
10168 MacroAssembler::VELEM_SIZE_16, 1);
10169 %}
10170 ins_pipe( ialu_reg_reg ); // FIXME
10171 %}
10172
10173 // Integers vector mul
10174 instruct vmul2I_reg(vecD dst, vecD src1, vecD src2) %{
10175 predicate(n->as_Vector()->length() == 2);
10176 match(Set dst (MulVI src1 src2));
10177 size(4);
10178 format %{ "VMUL.I32 $dst,$src1,$src2\t! mul packed2I" %}
10179 ins_encode %{
10180 __ vmulI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
10181 MacroAssembler::VELEM_SIZE_32, 0);
10182 %}
10183 ins_pipe( ialu_reg_reg ); // FIXME
10184 %}
10185
10186 instruct vmul4I_reg(vecX dst, vecX src1, vecX src2) %{
10187 predicate(n->as_Vector()->length() == 4);
10188 match(Set dst (MulVI src1 src2));
10189 size(4);
10190 format %{ "VMUL.I32 $dst.Q,$src1.Q,$src2.Q\t! mul packed4I" %}
10191 ins_encode %{
10192 __ vmulI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
10193 MacroAssembler::VELEM_SIZE_32, 1);
10194 %}
10195 ins_pipe( ialu_reg_reg ); // FIXME
10196 %}
10197
10198 // Floats vector mul
10199 instruct vmul2F_reg(vecD dst, vecD src1, vecD src2) %{
10200 predicate(n->as_Vector()->length() == 2 && VM_Version::simd_math_is_compliant());
10201 match(Set dst (MulVF src1 src2));
10202 size(4);
10203 format %{ "VMUL.F32 $dst,$src1,$src2\t! mul packed2F" %}
10204 ins_encode %{
10205 __ vmulF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
10206 MacroAssembler::VFA_SIZE_F32, 0);
10207 %}
10208 ins_pipe( fmulF_reg_reg ); // FIXME
10209 %}
10210
10211 instruct vmul2F_reg_vfp(vecD dst, vecD src1, vecD src2) %{
10212 predicate(n->as_Vector()->length() == 2 && !VM_Version::simd_math_is_compliant());
10213 match(Set dst (MulVF src1 src2));
10214 size(4*2);
10215 ins_cost(DEFAULT_COST*2); // FIXME
10216
10217 format %{ "FMULS $dst.a,$src1.a,$src2.a\n\t"
10218 "FMULS $dst.b,$src1.b,$src2.b" %}
10219 ins_encode %{
10220 __ mul_float($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
10221 __ mul_float($dst$$FloatRegister->successor(),
10222 $src1$$FloatRegister->successor(),
10223 $src2$$FloatRegister->successor());
10224 %}
10225
10226 ins_pipe(fmulF_reg_reg); // FIXME
10227 %}
10228
10229 instruct vmul4F_reg(vecX dst, vecX src1, vecX src2) %{
10230 predicate(n->as_Vector()->length() == 4 && VM_Version::simd_math_is_compliant());
10231 match(Set dst (MulVF src1 src2));
10232 size(4);
10233 format %{ "VMUL.F32 $dst.Q,$src1.Q,$src2.Q\t! mul packed4F" %}
10234 ins_encode %{
10235 __ vmulF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
10236 MacroAssembler::VFA_SIZE_F32, 1);
10237 %}
10238 ins_pipe( fmulF_reg_reg ); // FIXME
10239 %}
10240
10241 instruct vmul4F_reg_vfp(vecX dst, vecX src1, vecX src2) %{
10242 predicate(n->as_Vector()->length() == 4 && !VM_Version::simd_math_is_compliant());
10243 match(Set dst (MulVF src1 src2));
10244 size(4*4);
10245 ins_cost(DEFAULT_COST*4); // FIXME
10246
10247 format %{ "FMULS $dst.a,$src1.a,$src2.a\n\t"
10248 "FMULS $dst.b,$src1.b,$src2.b\n\t"
10249 "FMULS $dst.c,$src1.c,$src2.c\n\t"
10250 "FMULS $dst.d,$src1.d,$src2.d" %}
10251
10252 ins_encode %{
10253 FloatRegister dsta = $dst$$FloatRegister;
10254 FloatRegister src1a = $src1$$FloatRegister;
10255 FloatRegister src2a = $src2$$FloatRegister;
10256 __ mul_float(dsta, src1a, src2a);
10257 FloatRegister dstb = dsta->successor();
10258 FloatRegister src1b = src1a->successor();
10259 FloatRegister src2b = src2a->successor();
10260 __ mul_float(dstb, src1b, src2b);
10261 FloatRegister dstc = dstb->successor();
10262 FloatRegister src1c = src1b->successor();
10263 FloatRegister src2c = src2b->successor();
10264 __ mul_float(dstc, src1c, src2c);
10265 FloatRegister dstd = dstc->successor();
10266 FloatRegister src1d = src1c->successor();
10267 FloatRegister src2d = src2c->successor();
10268 __ mul_float(dstd, src1d, src2d);
10269 %}
10270
10271 ins_pipe(fmulF_reg_reg); // FIXME
10272 %}
10273
10274 instruct vmul2D_reg_vfp(vecX dst, vecX src1, vecX src2) %{
10275 predicate(n->as_Vector()->length() == 2);
10276 match(Set dst (MulVD src1 src2));
10277 size(4*2);
10278 ins_cost(DEFAULT_COST*2); // FIXME
10279
10280 format %{ "FMULD $dst.D.a,$src1.D.a,$src2.D.a\n\t"
10281 "FMULD $dst.D.b,$src1.D.b,$src2.D.b" %}
10282 ins_encode %{
10283 FloatRegister dsta = $dst$$FloatRegister;
10284 FloatRegister src1a = $src1$$FloatRegister;
10285 FloatRegister src2a = $src2$$FloatRegister;
10286 __ mul_double(dsta, src1a, src2a);
10287 FloatRegister dstb = dsta->successor()->successor();
10288 FloatRegister src1b = src1a->successor()->successor();
10289 FloatRegister src2b = src2a->successor()->successor();
10290 __ mul_double(dstb, src1b, src2b);
10291 %}
10292
10293 ins_pipe(fmulD_reg_reg); // FIXME
10294 %}
10295
10296
10297 // Floats vector div
10298 instruct vdiv2F_reg_vfp(vecD dst, vecD src1, vecD src2) %{
10299 predicate(n->as_Vector()->length() == 2);
10300 match(Set dst (DivVF src1 src2));
10301 size(4*2);
10302 ins_cost(DEFAULT_COST*2); // FIXME
10303
10304 format %{ "FDIVS $dst.a,$src1.a,$src2.a\n\t"
10305 "FDIVS $dst.b,$src1.b,$src2.b" %}
10306 ins_encode %{
10307 __ div_float($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
10308 __ div_float($dst$$FloatRegister->successor(),
10309 $src1$$FloatRegister->successor(),
10310 $src2$$FloatRegister->successor());
10311 %}
10312
10313 ins_pipe(fdivF_reg_reg); // FIXME
10314 %}
10315
10316 instruct vdiv4F_reg_vfp(vecX dst, vecX src1, vecX src2) %{
10317 predicate(n->as_Vector()->length() == 4);
10318 match(Set dst (DivVF src1 src2));
10319 size(4*4);
10320 ins_cost(DEFAULT_COST*4); // FIXME
10321
10322 format %{ "FDIVS $dst.a,$src1.a,$src2.a\n\t"
10323 "FDIVS $dst.b,$src1.b,$src2.b\n\t"
10324 "FDIVS $dst.c,$src1.c,$src2.c\n\t"
10325 "FDIVS $dst.d,$src1.d,$src2.d" %}
10326
10327 ins_encode %{
10328 FloatRegister dsta = $dst$$FloatRegister;
10329 FloatRegister src1a = $src1$$FloatRegister;
10330 FloatRegister src2a = $src2$$FloatRegister;
10331 __ div_float(dsta, src1a, src2a);
10332 FloatRegister dstb = dsta->successor();
10333 FloatRegister src1b = src1a->successor();
10334 FloatRegister src2b = src2a->successor();
10335 __ div_float(dstb, src1b, src2b);
10336 FloatRegister dstc = dstb->successor();
10337 FloatRegister src1c = src1b->successor();
10338 FloatRegister src2c = src2b->successor();
10339 __ div_float(dstc, src1c, src2c);
10340 FloatRegister dstd = dstc->successor();
10341 FloatRegister src1d = src1c->successor();
10342 FloatRegister src2d = src2c->successor();
10343 __ div_float(dstd, src1d, src2d);
10344 %}
10345
10346 ins_pipe(fdivF_reg_reg); // FIXME
10347 %}
10348
10349 instruct vdiv2D_reg_vfp(vecX dst, vecX src1, vecX src2) %{
10350 predicate(n->as_Vector()->length() == 2);
10351 match(Set dst (DivVD src1 src2));
10352 size(4*2);
10353 ins_cost(DEFAULT_COST*2); // FIXME
10354
10355 format %{ "FDIVD $dst.D.a,$src1.D.a,$src2.D.a\n\t"
10356 "FDIVD $dst.D.b,$src1.D.b,$src2.D.b" %}
10357 ins_encode %{
10358 FloatRegister dsta = $dst$$FloatRegister;
10359 FloatRegister src1a = $src1$$FloatRegister;
10360 FloatRegister src2a = $src2$$FloatRegister;
10361 __ div_double(dsta, src1a, src2a);
10362 FloatRegister dstb = dsta->successor()->successor();
10363 FloatRegister src1b = src1a->successor()->successor();
10364 FloatRegister src2b = src2a->successor()->successor();
10365 __ div_double(dstb, src1b, src2b);
10366 %}
10367
10368 ins_pipe(fdivD_reg_reg); // FIXME
10369 %}
10370
10371 // --------------------------------- NEG --------------------------------------
10372
10373 instruct vneg8B_reg(vecD dst, vecD src) %{
10374 predicate(n->as_Vector()->length_in_bytes() == 8);
10375 effect(DEF dst, USE src);
10376 size(4);
10377 ins_cost(DEFAULT_COST); // FIXME
10378 format %{ "VNEG.S8 $dst.D,$src.D\t! neg packed8B" %}
10379 ins_encode %{
10380 bool quad = false;
10381 __ vnegI($dst$$FloatRegister, $src$$FloatRegister,
10382 MacroAssembler::VELEM_SIZE_8, quad);
10383 %}
10384 ins_pipe( ialu_reg_reg ); // FIXME
10385 %}
10386
10387 instruct vneg16B_reg(vecX dst, vecX src) %{
10388 predicate(n->as_Vector()->length_in_bytes() == 16);
10389 effect(DEF dst, USE src);
10390 size(4);
10391 ins_cost(DEFAULT_COST); // FIXME
10392 format %{ "VNEG.S8 $dst.Q,$src.Q\t! neg0 packed16B" %}
10393 ins_encode %{
10394 bool _float = false;
10395 bool quad = true;
10396 __ vnegI($dst$$FloatRegister, $src$$FloatRegister,
10397 MacroAssembler::VELEM_SIZE_8, quad);
10398 %}
10399 ins_pipe( ialu_reg_reg ); // FIXME
10400 %}
10401
10402 // ------------------------------ ShiftCount ----------------------------------
10403
10404 instruct vslcntD(vecD dst, iRegI cnt) %{
10405 predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd());
10406 match(Set dst (LShiftCntV cnt));
10407 size(4);
10408 ins_cost(DEFAULT_COST); // FIXME
10409 expand %{
10410 Repl8B_reg_simd(dst, cnt);
10411 %}
10412 %}
10413
10414 instruct vslcntX(vecX dst, iRegI cnt) %{
10415 predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd());
10416 match(Set dst (LShiftCntV cnt));
10417 size(4);
10418 ins_cost(DEFAULT_COST); // FIXME
10419 expand %{
10420 Repl16B_reg(dst, cnt);
10421 %}
10422 %}
10423
10424 // Low bits of vector "shift" elements are used, so it
10425 // doesn't matter if we treat it as ints or bytes here.
10426 instruct vsrcntD(vecD dst, iRegI cnt) %{
10427 predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd());
10428 match(Set dst (RShiftCntV cnt));
10429 size(4*2);
10430 ins_cost(DEFAULT_COST*2); // FIXME
10431
10432 format %{ "VDUP.8 $dst.D,$cnt\n\t"
10433 "VNEG.S8 $dst.D,$dst.D\t! neg packed8B" %}
10434 ins_encode %{
10435 bool quad = false;
10436 __ vdupI($dst$$FloatRegister, $cnt$$Register,
10437 MacroAssembler::VELEM_SIZE_8, quad);
10438 __ vnegI($dst$$FloatRegister, $dst$$FloatRegister,
10439 MacroAssembler::VELEM_SIZE_8, quad);
10440 %}
10441 ins_pipe( ialu_reg_reg ); // FIXME
10442 %}
10443
10444 instruct vsrcntX(vecX dst, iRegI cnt) %{
10445 predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd());
10446 match(Set dst (RShiftCntV cnt));
10447 size(4*2);
10448 ins_cost(DEFAULT_COST*2); // FIXME
10449 format %{ "VDUP.8 $dst.Q,$cnt\n\t"
10450 "VNEG.S8 $dst.Q,$dst.Q\t! neg packed16B" %}
10451 ins_encode %{
10452 bool quad = true;
10453 __ vdupI($dst$$FloatRegister, $cnt$$Register,
10454 MacroAssembler::VELEM_SIZE_8, quad);
10455 __ vnegI($dst$$FloatRegister, $dst$$FloatRegister,
10456 MacroAssembler::VELEM_SIZE_8, quad);
10457 %}
10458 ins_pipe( ialu_reg_reg ); // FIXME
10459 %}
10460
10461 // ------------------------------ LogicalShift --------------------------------
10462
10463 // Byte vector logical left/right shift based on sign
10464 instruct vsh8B_reg(vecD dst, vecD src, vecD shift) %{
10465 predicate(n->as_Vector()->length() == 8);
10466 effect(DEF dst, USE src, USE shift);
10467 size(4);
10468 ins_cost(DEFAULT_COST); // FIXME
10469 format %{
10470 "VSHL.U8 $dst.D,$src.D,$shift.D\t! logical left/right shift packed8B"
10471 %}
10472 ins_encode %{
10473 bool quad = false;
10474 __ vshlUI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister,
10475 MacroAssembler::VELEM_SIZE_8, quad);
10476 %}
10477 ins_pipe( ialu_reg_reg ); // FIXME
10478 %}
10479
10480 instruct vsh16B_reg(vecX dst, vecX src, vecX shift) %{
10481 predicate(n->as_Vector()->length() == 16);
10482 effect(DEF dst, USE src, USE shift);
10483 size(4);
10484 ins_cost(DEFAULT_COST); // FIXME
10485 format %{
10486 "VSHL.U8 $dst.Q,$src.Q,$shift.Q\t! logical left/right shift packed16B"
10487 %}
10488 ins_encode %{
10489 bool quad = true;
10490 __ vshlUI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister,
10491 MacroAssembler::VELEM_SIZE_8, quad);
10492 %}
10493 ins_pipe( ialu_reg_reg ); // FIXME
10494 %}
10495
10496 // Shorts/Char vector logical left/right shift based on sign
10497 instruct vsh4S_reg(vecD dst, vecD src, vecD shift) %{
10498 predicate(n->as_Vector()->length() == 4);
10499 effect(DEF dst, USE src, USE shift);
10500 size(4);
10501 ins_cost(DEFAULT_COST); // FIXME
10502 format %{
10503 "VSHL.U16 $dst.D,$src.D,$shift.D\t! logical left/right shift packed4S"
10504 %}
10505 ins_encode %{
10506 bool quad = false;
10507 __ vshlUI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister,
10508 MacroAssembler::VELEM_SIZE_16, quad);
10509 %}
10510 ins_pipe( ialu_reg_reg ); // FIXME
10511 %}
10512
10513 instruct vsh8S_reg(vecX dst, vecX src, vecX shift) %{
10514 predicate(n->as_Vector()->length() == 8);
10515 effect(DEF dst, USE src, USE shift);
10516 size(4);
10517 ins_cost(DEFAULT_COST); // FIXME
10518 format %{
10519 "VSHL.U16 $dst.Q,$src.Q,$shift.Q\t! logical left/right shift packed8S"
10520 %}
10521 ins_encode %{
10522 bool quad = true;
10523 __ vshlUI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister,
10524 MacroAssembler::VELEM_SIZE_16, quad);
10525 %}
10526 ins_pipe( ialu_reg_reg ); // FIXME
10527 %}
10528
10529 // Integers vector logical left/right shift based on sign
10530 instruct vsh2I_reg(vecD dst, vecD src, vecD shift) %{
10531 predicate(n->as_Vector()->length() == 2);
10532 effect(DEF dst, USE src, USE shift);
10533 size(4);
10534 ins_cost(DEFAULT_COST); // FIXME
10535 format %{
10536 "VSHL.U32 $dst.D,$src.D,$shift.D\t! logical left/right shift packed2I"
10537 %}
10538 ins_encode %{
10539 bool quad = false;
10540 __ vshlUI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister,
10541 MacroAssembler::VELEM_SIZE_32, quad);
10542 %}
10543 ins_pipe( ialu_reg_reg ); // FIXME
10544 %}
10545
10546 instruct vsh4I_reg(vecX dst, vecX src, vecX shift) %{
10547 predicate(n->as_Vector()->length() == 4);
10548 effect(DEF dst, USE src, USE shift);
10549 size(4);
10550 ins_cost(DEFAULT_COST); // FIXME
10551 format %{
10552 "VSHL.U32 $dst.Q,$src.Q,$shift.Q\t! logical left/right shift packed4I"
10553 %}
10554 ins_encode %{
10555 bool quad = true;
10556 __ vshlUI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister,
10557 MacroAssembler::VELEM_SIZE_32, quad);
10558 %}
10559 ins_pipe( ialu_reg_reg ); // FIXME
10560 %}
10561
10562 // Longs vector logical left/right shift based on sign
10563 instruct vsh2L_reg(vecX dst, vecX src, vecX shift) %{
10564 predicate(n->as_Vector()->length() == 2);
10565 effect(DEF dst, USE src, USE shift);
10566 size(4);
10567 ins_cost(DEFAULT_COST); // FIXME
10568 format %{
10569 "VSHL.U64 $dst.Q,$src.Q,$shift.Q\t! logical left/right shift packed2L"
10570 %}
10571 ins_encode %{
10572 bool quad = true;
10573 __ vshlUI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister,
10574 MacroAssembler::VELEM_SIZE_64, quad);
10575 %}
10576 ins_pipe( ialu_reg_reg ); // FIXME
10577 %}
10578
10579 // ------------------------------ LogicalLeftShift ----------------------------
10580
10581 // Byte vector logical left shift
10582 instruct vsl8B_reg(vecD dst, vecD src, vecD shift) %{
10583 predicate(n->as_Vector()->length() == 8);
10584 match(Set dst (LShiftVB src shift));
10585 size(4*1);
10586 ins_cost(DEFAULT_COST*1); // FIXME
10587 expand %{
10588 vsh8B_reg(dst, src, shift);
10589 %}
10590 %}
10591
10592 instruct vsl16B_reg(vecX dst, vecX src, vecX shift) %{
10593 predicate(n->as_Vector()->length() == 16);
10594 match(Set dst (LShiftVB src shift));
10595 size(4*1);
10596 ins_cost(DEFAULT_COST*1); // FIXME
10597 expand %{
10598 vsh16B_reg(dst, src, shift);
10599 %}
10600 %}
10601
10602 instruct vsl8B_immI(vecD dst, vecD src, immI shift) %{
10603 predicate(n->as_Vector()->length() == 8 && assert_not_var_shift(n));
10604 match(Set dst (LShiftVB src (LShiftCntV shift)));
10605 size(4);
10606 ins_cost(DEFAULT_COST); // FIXME
10607 format %{
10608 "VSHL.I8 $dst.D,$src.D,$shift\t! logical left shift packed8B"
10609 %}
10610 ins_encode %{
10611 bool quad = false;
10612 __ vshli($dst$$FloatRegister, $src$$FloatRegister, 8, $shift$$constant,
10613 quad);
10614 %}
10615 ins_pipe( ialu_reg_reg ); // FIXME
10616 %}
10617
10618 instruct vsl16B_immI(vecX dst, vecX src, immI shift) %{
10619 predicate(n->as_Vector()->length() == 16 && assert_not_var_shift(n));
10620 match(Set dst (LShiftVB src (LShiftCntV shift)));
10621 size(4);
10622 ins_cost(DEFAULT_COST); // FIXME
10623 format %{
10624 "VSHL.I8 $dst.Q,$src.Q,$shift\t! logical left shift packed16B"
10625 %}
10626 ins_encode %{
10627 bool quad = true;
10628 __ vshli($dst$$FloatRegister, $src$$FloatRegister, 8, $shift$$constant,
10629 quad);
10630 %}
10631 ins_pipe( ialu_reg_reg ); // FIXME
10632 %}
10633
10634 // Shorts/Chars vector logical left shift
10635 instruct vsl4S_reg(vecD dst, vecD src, vecD shift) %{
10636 predicate(n->as_Vector()->length() == 4);
10637 match(Set dst (LShiftVS src shift));
10638 size(4*1);
10639 ins_cost(DEFAULT_COST*1); // FIXME
10640 expand %{
10641 vsh4S_reg(dst, src, shift);
10642 %}
10643 %}
10644
10645 instruct vsl8S_reg(vecX dst, vecX src, vecX shift) %{
10646 predicate(n->as_Vector()->length() == 8);
10647 match(Set dst (LShiftVS src shift));
10648 size(4*1);
10649 ins_cost(DEFAULT_COST*1); // FIXME
10650 expand %{
10651 vsh8S_reg(dst, src, shift);
10652 %}
10653 %}
10654
10655 instruct vsl4S_immI(vecD dst, vecD src, immI shift) %{
10656 predicate(n->as_Vector()->length() == 4 && assert_not_var_shift(n));
10657 match(Set dst (LShiftVS src (LShiftCntV shift)));
10658 size(4);
10659 ins_cost(DEFAULT_COST); // FIXME
10660 format %{
10661 "VSHL.I16 $dst.D,$src.D,$shift\t! logical left shift packed4S"
10662 %}
10663 ins_encode %{
10664 bool quad = false;
10665 __ vshli($dst$$FloatRegister, $src$$FloatRegister, 16, $shift$$constant,
10666 quad);
10667 %}
10668 ins_pipe( ialu_reg_reg ); // FIXME
10669 %}
10670
10671 instruct vsl8S_immI(vecX dst, vecX src, immI shift) %{
10672 predicate(n->as_Vector()->length() == 8 && assert_not_var_shift(n));
10673 match(Set dst (LShiftVS src shift));
10674 size(4);
10675 ins_cost(DEFAULT_COST); // FIXME
10676 format %{
10677 "VSHL.I16 $dst.Q,$src.Q,$shift\t! logical left shift packed8S"
10678 %}
10679 ins_encode %{
10680 bool quad = true;
10681 __ vshli($dst$$FloatRegister, $src$$FloatRegister, 16, $shift$$constant,
10682 quad);
10683 %}
10684 ins_pipe( ialu_reg_reg ); // FIXME
10685 %}
10686
10687 // Integers vector logical left shift
10688 instruct vsl2I_reg(vecD dst, vecD src, vecD shift) %{
10689 predicate(n->as_Vector()->length() == 2 && VM_Version::has_simd());
10690 match(Set dst (LShiftVI src shift));
10691 size(4*1);
10692 ins_cost(DEFAULT_COST*1); // FIXME
10693 expand %{
10694 vsh2I_reg(dst, src, shift);
10695 %}
10696 %}
10697
10698 instruct vsl4I_reg(vecX dst, vecX src, vecX shift) %{
10699 predicate(n->as_Vector()->length() == 4 && VM_Version::has_simd());
10700 match(Set dst (LShiftVI src shift));
10701 size(4*1);
10702 ins_cost(DEFAULT_COST*1); // FIXME
10703 expand %{
10704 vsh4I_reg(dst, src, shift);
10705 %}
10706 %}
10707
10708 instruct vsl2I_immI(vecD dst, vecD src, immI shift) %{
10709 predicate(n->as_Vector()->length() == 2 &&
10710 VM_Version::has_simd() &&
10711 assert_not_var_shift(n));
10712 match(Set dst (LShiftVI src (LShiftCntV shift)));
10713 size(4);
10714 ins_cost(DEFAULT_COST); // FIXME
10715 format %{
10716 "VSHL.I32 $dst.D,$src.D,$shift\t! logical left shift packed2I"
10717 %}
10718 ins_encode %{
10719 bool quad = false;
10720 __ vshli($dst$$FloatRegister, $src$$FloatRegister, 32, $shift$$constant,
10721 quad);
10722 %}
10723 ins_pipe( ialu_reg_reg ); // FIXME
10724 %}
10725
10726 instruct vsl4I_immI(vecX dst, vecX src, immI shift) %{
10727 predicate(n->as_Vector()->length() == 4 &&
10728 VM_Version::has_simd() &&
10729 assert_not_var_shift(n));
10730 match(Set dst (LShiftVI src (LShiftCntV shift)));
10731 size(4);
10732 ins_cost(DEFAULT_COST); // FIXME
10733 format %{
10734 "VSHL.I32 $dst.Q,$src.Q,$shift\t! logical left shift packed4I"
10735 %}
10736 ins_encode %{
10737 bool quad = true;
10738 __ vshli($dst$$FloatRegister, $src$$FloatRegister, 32, $shift$$constant,
10739 quad);
10740 %}
10741 ins_pipe( ialu_reg_reg ); // FIXME
10742 %}
10743
10744 // Longs vector logical left shift
10745 instruct vsl2L_reg(vecX dst, vecX src, vecX shift) %{
10746 predicate(n->as_Vector()->length() == 2);
10747 match(Set dst (LShiftVL src shift));
10748 size(4*1);
10749 ins_cost(DEFAULT_COST*1); // FIXME
10750 expand %{
10751 vsh2L_reg(dst, src, shift);
10752 %}
10753 %}
10754
10755 instruct vsl2L_immI(vecX dst, vecX src, immI shift) %{
10756 predicate(n->as_Vector()->length() == 2 && assert_not_var_shift(n));
10757 match(Set dst (LShiftVL src (LShiftCntV shift)));
10758 size(4);
10759 ins_cost(DEFAULT_COST); // FIXME
10760 format %{
10761 "VSHL.I64 $dst.Q,$src.Q,$shift\t! logical left shift packed2L"
10762 %}
10763 ins_encode %{
10764 bool quad = true;
10765 __ vshli($dst$$FloatRegister, $src$$FloatRegister, 64, $shift$$constant,
10766 quad);
10767 %}
10768 ins_pipe( ialu_reg_reg ); // FIXME
10769 %}
10770
10771 // ----------------------- LogicalRightShift -----------------------------------
10772
10773 // Bytes/Shorts vector logical right shift produces incorrect Java result
10774 // for negative data because java code convert short value into int with
10775 // sign extension before a shift.
10776
10777 // Right shift with vector shift count on aarch32 SIMD is implemented as left
10778 // shift by negative shift count value.
10779 //
10780 // Method is_var_shift() denotes that vector shift count is a variable shift:
10781 // 1) for this case, vector shift count should be negated before conducting
10782 // right shifts. E.g., vsrl4S_reg_var rule.
10783 // 2) for the opposite case, vector shift count is generated via RShiftCntV
10784 // rules and is already negated there. Hence, no negation is needed.
10785 // E.g., vsrl4S_reg rule.
10786
10787 // Chars vector logical right shift
10788 instruct vsrl4S_reg(vecD dst, vecD src, vecD shift) %{
10789 predicate(n->as_Vector()->length() == 4 && !n->as_ShiftV()->is_var_shift());
10790 match(Set dst (URShiftVS src shift));
10791 size(4);
10792 ins_cost(DEFAULT_COST);
10793 expand %{
10794 vsh4S_reg(dst, src, shift);
10795 %}
10796 %}
10797
10798 instruct vsrl4S_reg_var(vecD dst, vecD src, vecD shift, vecD tmp) %{
10799 predicate(n->as_Vector()->length() == 4 && n->as_ShiftV()->is_var_shift());
10800 match(Set dst (URShiftVS src shift));
10801 effect(TEMP tmp);
10802 size(4*2);
10803 ins_cost(DEFAULT_COST*2);
10804 format %{
10805 "VNEG.S8 $tmp.D,$shift.D\n\t! neg packed8B"
10806 "VSHL.U16 $dst.D,$src.D,$tmp.D\t! logical right shift packed4S"
10807 %}
10808 ins_encode %{
10809 bool quad = false;
10810 __ vnegI($tmp$$FloatRegister, $shift$$FloatRegister,
10811 MacroAssembler::VELEM_SIZE_8, quad);
10812 __ vshlUI($dst$$FloatRegister, $tmp$$FloatRegister, $src$$FloatRegister,
10813 MacroAssembler::VELEM_SIZE_16, quad);
10814 %}
10815 ins_pipe(ialu_reg_reg);
10816 %}
10817
10818 instruct vsrl8S_reg(vecX dst, vecX src, vecX shift) %{
10819 predicate(n->as_Vector()->length() == 8 && !n->as_ShiftV()->is_var_shift());
10820 match(Set dst (URShiftVS src shift));
10821 size(4);
10822 ins_cost(DEFAULT_COST);
10823 expand %{
10824 vsh8S_reg(dst, src, shift);
10825 %}
10826 %}
10827
10828 instruct vsrl8S_reg_var(vecX dst, vecX src, vecX shift, vecX tmp) %{
10829 predicate(n->as_Vector()->length() == 8 && n->as_ShiftV()->is_var_shift());
10830 match(Set dst (URShiftVS src shift));
10831 effect(TEMP tmp);
10832 size(4*2);
10833 ins_cost(DEFAULT_COST*2);
10834 format %{
10835 "VNEG.S8 $tmp.Q,$shift.Q\n\t! neg packed16B"
10836 "VSHL.U16 $dst.Q,$src.Q,$tmp.Q\t! logical right shift packed8S"
10837 %}
10838 ins_encode %{
10839 bool quad = true;
10840 __ vnegI($tmp$$FloatRegister, $shift$$FloatRegister,
10841 MacroAssembler::VELEM_SIZE_8, quad);
10842 __ vshlUI($dst$$FloatRegister, $tmp$$FloatRegister, $src$$FloatRegister,
10843 MacroAssembler::VELEM_SIZE_16, quad);
10844 %}
10845 ins_pipe(ialu_reg_reg);
10846 %}
10847
10848 instruct vsrl4S_immI(vecD dst, vecD src, immI shift) %{
10849 predicate(n->as_Vector()->length() == 4 && assert_not_var_shift(n));
10850 match(Set dst (URShiftVS src (RShiftCntV shift)));
10851 size(4);
10852 ins_cost(DEFAULT_COST); // FIXME
10853 format %{
10854 "VSHR.U16 $dst.D,$src.D,$shift\t! logical right shift packed4S"
10855 %}
10856 ins_encode %{
10857 bool quad = false;
10858 __ vshrUI($dst$$FloatRegister, $src$$FloatRegister, 16, $shift$$constant,
10859 quad);
10860 %}
10861 ins_pipe( ialu_reg_reg ); // FIXME
10862 %}
10863
10864 instruct vsrl8S_immI(vecX dst, vecX src, immI shift) %{
10865 predicate(n->as_Vector()->length() == 8 && assert_not_var_shift(n));
10866 match(Set dst (URShiftVS src (RShiftCntV shift)));
10867 size(4);
10868 ins_cost(DEFAULT_COST); // FIXME
10869 format %{
10870 "VSHR.U16 $dst.Q,$src.Q,$shift\t! logical right shift packed8S"
10871 %}
10872 ins_encode %{
10873 bool quad = true;
10874 __ vshrUI($dst$$FloatRegister, $src$$FloatRegister, 16, $shift$$constant,
10875 quad);
10876 %}
10877 ins_pipe( ialu_reg_reg ); // FIXME
10878 %}
10879
10880 // Integers vector logical right shift
10881 instruct vsrl2I_reg(vecD dst, vecD src, vecD shift) %{
10882 predicate(n->as_Vector()->length() == 2 &&
10883 VM_Version::has_simd() &&
10884 !n->as_ShiftV()->is_var_shift());
10885 match(Set dst (URShiftVI src shift));
10886 size(4);
10887 ins_cost(DEFAULT_COST);
10888 expand %{
10889 vsh2I_reg(dst, src, shift);
10890 %}
10891 %}
10892
10893 instruct vsrl2I_reg_var(vecD dst, vecD src, vecD shift, vecD tmp) %{
10894 predicate(n->as_Vector()->length() == 2 &&
10895 VM_Version::has_simd() &&
10896 n->as_ShiftV()->is_var_shift());
10897 match(Set dst (URShiftVI src shift));
10898 effect(TEMP tmp);
10899 size(4*2);
10900 ins_cost(DEFAULT_COST*2);
10901 format %{
10902 "VNEG.S8 $tmp.D,$shift.D\n\t! neg packed8B"
10903 "VSHL.U32 $dst.D,$src.D,$tmp.D\t! logical right shift packed2I"
10904 %}
10905 ins_encode %{
10906 bool quad = false;
10907 __ vnegI($tmp$$FloatRegister, $shift$$FloatRegister,
10908 MacroAssembler::VELEM_SIZE_8, quad);
10909 __ vshlUI($dst$$FloatRegister, $tmp$$FloatRegister, $src$$FloatRegister,
10910 MacroAssembler::VELEM_SIZE_32, quad);
10911 %}
10912 ins_pipe(ialu_reg_reg);
10913 %}
10914
10915 instruct vsrl4I_reg(vecX dst, vecX src, vecX shift) %{
10916 predicate(n->as_Vector()->length() == 4 &&
10917 VM_Version::has_simd() &&
10918 !n->as_ShiftV()->is_var_shift());
10919 match(Set dst (URShiftVI src shift));
10920 size(4);
10921 ins_cost(DEFAULT_COST);
10922 expand %{
10923 vsh4I_reg(dst, src, shift);
10924 %}
10925 %}
10926
10927 instruct vsrl4I_reg_var(vecX dst, vecX src, vecX shift, vecX tmp) %{
10928 predicate(n->as_Vector()->length() == 4 &&
10929 VM_Version::has_simd() &&
10930 n->as_ShiftV()->is_var_shift());
10931 match(Set dst (URShiftVI src shift));
10932 effect(TEMP tmp);
10933 size(4*2);
10934 ins_cost(DEFAULT_COST*2);
10935 format %{
10936 "VNEG.S8 $tmp.Q,$shift.Q\n\t! neg packed16B"
10937 "VSHL.U32 $dst.Q,$src.Q,$tmp.Q\t! logical right shift packed4I"
10938 %}
10939 ins_encode %{
10940 bool quad = true;
10941 __ vnegI($tmp$$FloatRegister, $shift$$FloatRegister,
10942 MacroAssembler::VELEM_SIZE_8, quad);
10943 __ vshlUI($dst$$FloatRegister, $tmp$$FloatRegister, $src$$FloatRegister,
10944 MacroAssembler::VELEM_SIZE_32, quad);
10945 %}
10946 ins_pipe(ialu_reg_reg);
10947 %}
10948
10949 instruct vsrl2I_immI(vecD dst, vecD src, immI shift) %{
10950 predicate(n->as_Vector()->length() == 2 &&
10951 VM_Version::has_simd() &&
10952 assert_not_var_shift(n));
10953 match(Set dst (URShiftVI src (RShiftCntV shift)));
10954 size(4);
10955 ins_cost(DEFAULT_COST); // FIXME
10956 format %{
10957 "VSHR.U32 $dst.D,$src.D,$shift\t! logical right shift packed2I"
10958 %}
10959 ins_encode %{
10960 bool quad = false;
10961 __ vshrUI($dst$$FloatRegister, $src$$FloatRegister, 32, $shift$$constant,
10962 quad);
10963 %}
10964 ins_pipe( ialu_reg_reg ); // FIXME
10965 %}
10966
10967 instruct vsrl4I_immI(vecX dst, vecX src, immI shift) %{
10968 predicate(n->as_Vector()->length() == 4 &&
10969 VM_Version::has_simd() &&
10970 assert_not_var_shift(n));
10971 match(Set dst (URShiftVI src (RShiftCntV shift)));
10972 size(4);
10973 ins_cost(DEFAULT_COST); // FIXME
10974 format %{
10975 "VSHR.U32 $dst.Q,$src.Q,$shift\t! logical right shift packed4I"
10976 %}
10977 ins_encode %{
10978 bool quad = true;
10979 __ vshrUI($dst$$FloatRegister, $src$$FloatRegister, 32, $shift$$constant,
10980 quad);
10981 %}
10982 ins_pipe( ialu_reg_reg ); // FIXME
10983 %}
10984
10985 // Longs vector logical right shift
10986 instruct vsrl2L_reg(vecX dst, vecX src, vecX shift) %{
10987 predicate(n->as_Vector()->length() == 2 && !n->as_ShiftV()->is_var_shift());
10988 match(Set dst (URShiftVL src shift));
10989 size(4);
10990 ins_cost(DEFAULT_COST);
10991 expand %{
10992 vsh2L_reg(dst, src, shift);
10993 %}
10994 %}
10995
10996 instruct vsrl2L_reg_var(vecX dst, vecX src, vecX shift, vecX tmp) %{
10997 predicate(n->as_Vector()->length() == 2 && n->as_ShiftV()->is_var_shift());
10998 match(Set dst (URShiftVL src shift));
10999 effect(TEMP tmp, DEF dst, USE src, USE shift);
11000 size(4*2);
11001 ins_cost(DEFAULT_COST*2);
11002 format %{
11003 "VNEG.S8 $tmp.Q,$shift.Q\n\t! neg packed16B"
11004 "VSHL.U64 $dst.Q,$src.Q,$tmp.Q\t! logical right shift packed2L"
11005 %}
11006 ins_encode %{
11007 bool quad = true;
11008 __ vnegI($tmp$$FloatRegister, $shift$$FloatRegister,
11009 MacroAssembler::VELEM_SIZE_8, quad);
11010 __ vshlUI($dst$$FloatRegister, $tmp$$FloatRegister, $src$$FloatRegister,
11011 MacroAssembler::VELEM_SIZE_64, quad);
11012 %}
11013 ins_pipe(ialu_reg_reg);
11014 %}
11015
11016 instruct vsrl2L_immI(vecX dst, vecX src, immI shift) %{
11017 predicate(n->as_Vector()->length() == 2 && assert_not_var_shift(n));
11018 match(Set dst (URShiftVL src (RShiftCntV shift)));
11019 size(4);
11020 ins_cost(DEFAULT_COST); // FIXME
11021 format %{
11022 "VSHR.U64 $dst.Q,$src.Q,$shift\t! logical right shift packed2L"
11023 %}
11024 ins_encode %{
11025 bool quad = true;
11026 __ vshrUI($dst$$FloatRegister, $src$$FloatRegister, 64, $shift$$constant,
11027 quad);
11028 %}
11029 ins_pipe( ialu_reg_reg ); // FIXME
11030 %}
11031
11032 // ------------------- ArithmeticRightShift -----------------------------------
11033
11034 // Bytes vector arithmetic left/right shift based on sign
11035 instruct vsha8B_reg(vecD dst, vecD src, vecD shift) %{
11036 predicate(n->as_Vector()->length() == 8);
11037 effect(DEF dst, USE src, USE shift);
11038 size(4);
11039 ins_cost(DEFAULT_COST); // FIXME
11040 format %{
11041 "VSHL.S8 $dst.D,$src.D,$shift.D\t! arithmetic right shift packed8B"
11042 %}
11043 ins_encode %{
11044 bool quad = false;
11045 __ vshlSI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister,
11046 MacroAssembler::VELEM_SIZE_8, quad);
11047 %}
11048 ins_pipe( ialu_reg_reg ); // FIXME
11049 %}
11050
11051 instruct vsha16B_reg(vecX dst, vecX src, vecX shift) %{
11052 predicate(n->as_Vector()->length() == 16);
11053 effect(DEF dst, USE src, USE shift);
11054 size(4);
11055 ins_cost(DEFAULT_COST); // FIXME
11056 format %{
11057 "VSHL.S8 $dst.Q,$src.Q,$shift.Q\t! arithmetic right shift packed16B"
11058 %}
11059 ins_encode %{
11060 bool quad = true;
11061 __ vshlSI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister,
11062 MacroAssembler::VELEM_SIZE_8, quad);
11063 %}
11064 ins_pipe( ialu_reg_reg ); // FIXME
11065 %}
11066
11067 // Shorts vector arithmetic left/right shift based on sign
11068 instruct vsha4S_reg(vecD dst, vecD src, vecD shift) %{
11069 predicate(n->as_Vector()->length() == 4);
11070 effect(DEF dst, USE src, USE shift);
11071 size(4);
11072 ins_cost(DEFAULT_COST); // FIXME
11073 format %{
11074 "VSHL.S16 $dst.D,$src.D,$shift.D\t! arithmetic right shift packed4S"
11075 %}
11076 ins_encode %{
11077 bool quad = false;
11078 __ vshlSI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister,
11079 MacroAssembler::VELEM_SIZE_16, quad);
11080 %}
11081 ins_pipe( ialu_reg_reg ); // FIXME
11082 %}
11083
11084 instruct vsha8S_reg(vecX dst, vecX src, vecX shift) %{
11085 predicate(n->as_Vector()->length() == 8);
11086 effect(DEF dst, USE src, USE shift);
11087 size(4);
11088 ins_cost(DEFAULT_COST); // FIXME
11089 format %{
11090 "VSHL.S16 $dst.Q,$src.Q,$shift.Q\t! arithmetic right shift packed8S"
11091 %}
11092 ins_encode %{
11093 bool quad = true;
11094 __ vshlSI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister,
11095 MacroAssembler::VELEM_SIZE_16, quad);
11096 %}
11097 ins_pipe( ialu_reg_reg ); // FIXME
11098 %}
11099
11100 // Integers vector arithmetic left/right shift based on sign
11101 instruct vsha2I_reg(vecD dst, vecD src, vecD shift) %{
11102 predicate(n->as_Vector()->length() == 2);
11103 effect(DEF dst, USE src, USE shift);
11104 size(4);
11105 ins_cost(DEFAULT_COST); // FIXME
11106 format %{
11107 "VSHL.S32 $dst.D,$src.D,$shift.D\t! arithmetic right shift packed2I"
11108 %}
11109 ins_encode %{
11110 bool quad = false;
11111 __ vshlSI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister,
11112 MacroAssembler::VELEM_SIZE_32, quad);
11113 %}
11114 ins_pipe( ialu_reg_reg ); // FIXME
11115 %}
11116
11117 instruct vsha4I_reg(vecX dst, vecX src, vecX shift) %{
11118 predicate(n->as_Vector()->length() == 4);
11119 effect(DEF dst, USE src, USE shift);
11120 size(4);
11121 ins_cost(DEFAULT_COST); // FIXME
11122 format %{
11123 "VSHL.S32 $dst.Q,$src.Q,$shift.Q\t! arithmetic right shift packed4I"
11124 %}
11125 ins_encode %{
11126 bool quad = true;
11127 __ vshlSI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister,
11128 MacroAssembler::VELEM_SIZE_32, quad);
11129 %}
11130 ins_pipe( ialu_reg_reg ); // FIXME
11131 %}
11132
11133 // Longs vector arithmetic left/right shift based on sign
11134 instruct vsha2L_reg(vecX dst, vecX src, vecX shift) %{
11135 predicate(n->as_Vector()->length() == 2);
11136 effect(DEF dst, USE src, USE shift);
11137 size(4);
11138 ins_cost(DEFAULT_COST); // FIXME
11139 format %{
11140 "VSHL.S64 $dst.Q,$src.Q,$shift.Q\t! arithmetic right shift packed2L"
11141 %}
11142 ins_encode %{
11143 bool quad = true;
11144 __ vshlSI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister,
11145 MacroAssembler::VELEM_SIZE_64, quad);
11146 %}
11147 ins_pipe( ialu_reg_reg ); // FIXME
11148 %}
11149
11150 // Byte vector arithmetic right shift
11151 instruct vsra8B_reg(vecD dst, vecD src, vecD shift) %{
11152 predicate(n->as_Vector()->length() == 8 && !n->as_ShiftV()->is_var_shift());
11153 match(Set dst (RShiftVB src shift));
11154 size(4);
11155 ins_cost(DEFAULT_COST); // FIXME
11156 expand %{
11157 vsha8B_reg(dst, src, shift);
11158 %}
11159 %}
11160
11161 instruct vsra8B_reg_var(vecD dst, vecD src, vecD shift, vecD tmp) %{
11162 predicate(n->as_Vector()->length() == 8 && n->as_ShiftV()->is_var_shift());
11163 match(Set dst (RShiftVB src shift));
11164 effect(TEMP tmp);
11165 size(4*2);
11166 ins_cost(DEFAULT_COST*2);
11167 format %{
11168 "VNEG.S8 $tmp.D,$shift.D\n\t! neg packed8B"
11169 "VSHL.S8 $dst.D,$src.D,$tmp.D\t! arithmetic right shift packed8B"
11170 %}
11171 ins_encode %{
11172 bool quad = false;
11173 __ vnegI($tmp$$FloatRegister, $shift$$FloatRegister,
11174 MacroAssembler::VELEM_SIZE_8, quad);
11175 __ vshlSI($dst$$FloatRegister, $tmp$$FloatRegister, $src$$FloatRegister,
11176 MacroAssembler::VELEM_SIZE_8, quad);
11177 %}
11178 ins_pipe(ialu_reg_reg);
11179 %}
11180
11181 instruct vsra16B_reg(vecX dst, vecX src, vecX shift) %{
11182 predicate(n->as_Vector()->length() == 16 && !n->as_ShiftV()->is_var_shift());
11183 match(Set dst (RShiftVB src shift));
11184 size(4);
11185 ins_cost(DEFAULT_COST); // FIXME
11186 expand %{
11187 vsha16B_reg(dst, src, shift);
11188 %}
11189 %}
11190
11191 instruct vsra16B_reg_var(vecX dst, vecX src, vecX shift, vecX tmp) %{
11192 predicate(n->as_Vector()->length() == 16 && n->as_ShiftV()->is_var_shift());
11193 match(Set dst (RShiftVB src shift));
11194 effect(TEMP tmp);
11195 size(4*2);
11196 ins_cost(DEFAULT_COST*2);
11197 format %{
11198 "VNEG.S8 $tmp.Q,$shift.Q\n\t! neg packed16B"
11199 "VSHL.S8 $dst.Q,$src.Q,$tmp.Q\t! arithmetic right shift packed16B"
11200 %}
11201 ins_encode %{
11202 bool quad = true;
11203 __ vnegI($tmp$$FloatRegister, $shift$$FloatRegister,
11204 MacroAssembler::VELEM_SIZE_8, quad);
11205 __ vshlSI($dst$$FloatRegister, $tmp$$FloatRegister, $src$$FloatRegister,
11206 MacroAssembler::VELEM_SIZE_8, quad);
11207 %}
11208 ins_pipe(ialu_reg_reg);
11209 %}
11210
11211 instruct vsra8B_immI(vecD dst, vecD src, immI shift) %{
11212 predicate(n->as_Vector()->length() == 8 && assert_not_var_shift(n));
11213 match(Set dst (RShiftVB src (RShiftCntV shift)));
11214 size(4);
11215 ins_cost(DEFAULT_COST); // FIXME
11216 format %{
11217 "VSHR.S8 $dst.D,$src.D,$shift\t! arithmetic right shift packed8B"
11218 %}
11219 ins_encode %{
11220 bool quad = false;
11221 __ vshrSI($dst$$FloatRegister, $src$$FloatRegister, 8, $shift$$constant,
11222 quad);
11223 %}
11224 ins_pipe( ialu_reg_reg ); // FIXME
11225 %}
11226
11227 instruct vsra16B_immI(vecX dst, vecX src, immI shift) %{
11228 predicate(n->as_Vector()->length() == 16 && assert_not_var_shift(n));
11229 match(Set dst (RShiftVB src (RShiftCntV shift)));
11230 size(4);
11231 ins_cost(DEFAULT_COST); // FIXME
11232 format %{
11233 "VSHR.S8 $dst.Q,$src.Q,$shift\t! arithmetic right shift packed16B"
11234 %}
11235 ins_encode %{
11236 bool quad = true;
11237 __ vshrSI($dst$$FloatRegister, $src$$FloatRegister, 8, $shift$$constant,
11238 quad);
11239 %}
11240 ins_pipe( ialu_reg_reg ); // FIXME
11241 %}
11242
11243 // Shorts vector arithmetic right shift
11244 instruct vsra4S_reg(vecD dst, vecD src, vecD shift) %{
11245 predicate(n->as_Vector()->length() == 4 && !n->as_ShiftV()->is_var_shift());
11246 match(Set dst (RShiftVS src shift));
11247 size(4);
11248 ins_cost(DEFAULT_COST); // FIXME
11249 expand %{
11250 vsha4S_reg(dst, src, shift);
11251 %}
11252 %}
11253
11254 instruct vsra4S_reg_var(vecD dst, vecD src, vecD shift, vecD tmp) %{
11255 predicate(n->as_Vector()->length() == 4 && n->as_ShiftV()->is_var_shift());
11256 match(Set dst (RShiftVS src shift));
11257 effect(TEMP tmp);
11258 size(4*2);
11259 ins_cost(DEFAULT_COST*2);
11260 format %{
11261 "VNEG.S8 $tmp.D,$shift.D\n\t! neg packed8B"
11262 "VSHL.S16 $dst.D,$src.D,$tmp.D\t! arithmetic right shift packed4S"
11263 %}
11264 ins_encode %{
11265 bool quad = false;
11266 __ vnegI($tmp$$FloatRegister, $shift$$FloatRegister,
11267 MacroAssembler::VELEM_SIZE_8, quad);
11268 __ vshlSI($dst$$FloatRegister, $tmp$$FloatRegister, $src$$FloatRegister,
11269 MacroAssembler::VELEM_SIZE_16, quad);
11270 %}
11271 ins_pipe(ialu_reg_reg);
11272 %}
11273
11274 instruct vsra8S_reg(vecX dst, vecX src, vecX shift) %{
11275 predicate(n->as_Vector()->length() == 8 && !n->as_ShiftV()->is_var_shift());
11276 match(Set dst (RShiftVS src shift));
11277 size(4);
11278 ins_cost(DEFAULT_COST); // FIXME
11279 expand %{
11280 vsha8S_reg(dst, src, shift);
11281 %}
11282 %}
11283
11284 instruct vsra8S_reg_var(vecX dst, vecX src, vecX shift, vecX tmp) %{
11285 predicate(n->as_Vector()->length() == 8 && n->as_ShiftV()->is_var_shift());
11286 match(Set dst (RShiftVS src shift));
11287 effect(TEMP tmp);
11288 size(4*2);
11289 ins_cost(DEFAULT_COST*2);
11290 format %{
11291 "VNEG.S8 $tmp.Q,$shift.Q\n\t! neg packed16B"
11292 "VSHL.S16 $dst.Q,$src.Q,$tmp.Q\t! arithmetic right shift packed8S"
11293 %}
11294 ins_encode %{
11295 bool quad = true;
11296 __ vnegI($tmp$$FloatRegister, $shift$$FloatRegister,
11297 MacroAssembler::VELEM_SIZE_8, quad);
11298 __ vshlSI($dst$$FloatRegister, $tmp$$FloatRegister, $src$$FloatRegister,
11299 MacroAssembler::VELEM_SIZE_16, quad);
11300 %}
11301 ins_pipe(ialu_reg_reg);
11302 %}
11303
11304 instruct vsra4S_immI(vecD dst, vecD src, immI shift) %{
11305 predicate(n->as_Vector()->length() == 4 && assert_not_var_shift(n));
11306 match(Set dst (RShiftVS src (RShiftCntV shift)));
11307 size(4);
11308 ins_cost(DEFAULT_COST); // FIXME
11309 format %{
11310 "VSHR.S16 $dst.D,$src.D,$shift\t! arithmetic right shift packed4S"
11311 %}
11312 ins_encode %{
11313 bool quad = false;
11314 __ vshrSI($dst$$FloatRegister, $src$$FloatRegister, 16, $shift$$constant,
11315 quad);
11316 %}
11317 ins_pipe( ialu_reg_reg ); // FIXME
11318 %}
11319
11320 instruct vsra8S_immI(vecX dst, vecX src, immI shift) %{
11321 predicate(n->as_Vector()->length() == 8 && assert_not_var_shift(n));
11322 match(Set dst (RShiftVS src (RShiftCntV shift)));
11323 size(4);
11324 ins_cost(DEFAULT_COST); // FIXME
11325 format %{
11326 "VSHR.S16 $dst.Q,$src.Q,$shift\t! arithmetic right shift packed8S"
11327 %}
11328 ins_encode %{
11329 bool quad = true;
11330 __ vshrSI($dst$$FloatRegister, $src$$FloatRegister, 16, $shift$$constant,
11331 quad);
11332 %}
11333 ins_pipe( ialu_reg_reg ); // FIXME
11334 %}
11335
11336 // Integers vector arithmetic right shift
11337 instruct vsra2I_reg(vecD dst, vecD src, vecD shift) %{
11338 predicate(n->as_Vector()->length() == 2 && !n->as_ShiftV()->is_var_shift());
11339 match(Set dst (RShiftVI src shift));
11340 size(4);
11341 ins_cost(DEFAULT_COST); // FIXME
11342 expand %{
11343 vsha2I_reg(dst, src, shift);
11344 %}
11345 %}
11346
11347 instruct vsra2I_reg_var(vecD dst, vecD src, vecD shift, vecD tmp) %{
11348 predicate(n->as_Vector()->length() == 2 && n->as_ShiftV()->is_var_shift());
11349 match(Set dst (RShiftVI src shift));
11350 effect(TEMP tmp);
11351 size(4*2);
11352 ins_cost(DEFAULT_COST*2);
11353 format %{
11354 "VNEG.S8 $tmp.D,$shift.D\n\t! neg packed8B"
11355 "VSHL.S32 $dst.D,$src.D,$tmp.D\t! arithmetic right shift packed2I"
11356 %}
11357 ins_encode %{
11358 bool quad = false;
11359 __ vnegI($tmp$$FloatRegister, $shift$$FloatRegister,
11360 MacroAssembler::VELEM_SIZE_8, quad);
11361 __ vshlSI($dst$$FloatRegister, $tmp$$FloatRegister, $src$$FloatRegister,
11362 MacroAssembler::VELEM_SIZE_32, quad);
11363 %}
11364 ins_pipe(ialu_reg_reg);
11365 %}
11366
11367 instruct vsra4I_reg(vecX dst, vecX src, vecX shift) %{
11368 predicate(n->as_Vector()->length() == 4 && !n->as_ShiftV()->is_var_shift());
11369 match(Set dst (RShiftVI src shift));
11370 size(4);
11371 ins_cost(DEFAULT_COST); // FIXME
11372 expand %{
11373 vsha4I_reg(dst, src, shift);
11374 %}
11375 %}
11376
11377 instruct vsra4I_reg_var(vecX dst, vecX src, vecX shift, vecX tmp) %{
11378 predicate(n->as_Vector()->length() == 4 && n->as_ShiftV()->is_var_shift());
11379 match(Set dst (RShiftVI src shift));
11380 effect(TEMP tmp);
11381 size(4*2);
11382 ins_cost(DEFAULT_COST*2);
11383 format %{
11384 "VNEG.S8 $tmp.Q,$shift.Q\n\t! neg packed16B"
11385 "VSHL.S32 $dst.Q,$src.Q,$tmp.Q\t! arithmetic right shift packed4I"
11386 %}
11387 ins_encode %{
11388 bool quad = true;
11389 __ vnegI($tmp$$FloatRegister, $shift$$FloatRegister,
11390 MacroAssembler::VELEM_SIZE_8, quad);
11391 __ vshlSI($dst$$FloatRegister, $tmp$$FloatRegister, $src$$FloatRegister,
11392 MacroAssembler::VELEM_SIZE_32, quad);
11393 %}
11394 ins_pipe(ialu_reg_reg);
11395 %}
11396
11397 instruct vsra2I_immI(vecD dst, vecD src, immI shift) %{
11398 predicate(n->as_Vector()->length() == 2 && assert_not_var_shift(n));
11399 match(Set dst (RShiftVI src (RShiftCntV shift)));
11400 size(4);
11401 ins_cost(DEFAULT_COST); // FIXME
11402 format %{
11403 "VSHR.S32 $dst.D,$src.D,$shift\t! arithmetic right shift packed2I"
11404 %}
11405 ins_encode %{
11406 bool quad = false;
11407 __ vshrSI($dst$$FloatRegister, $src$$FloatRegister, 32, $shift$$constant,
11408 quad);
11409 %}
11410 ins_pipe( ialu_reg_reg ); // FIXME
11411 %}
11412
11413 instruct vsra4I_immI(vecX dst, vecX src, immI shift) %{
11414 predicate(n->as_Vector()->length() == 4 && assert_not_var_shift(n));
11415 match(Set dst (RShiftVI src (RShiftCntV shift)));
11416 size(4);
11417 ins_cost(DEFAULT_COST); // FIXME
11418 format %{
11419 "VSHR.S32 $dst.Q,$src.Q,$shift\t! arithmetic right shift packed4I"
11420 %}
11421 ins_encode %{
11422 bool quad = true;
11423 __ vshrSI($dst$$FloatRegister, $src$$FloatRegister, 32, $shift$$constant,
11424 quad);
11425 %}
11426 ins_pipe( ialu_reg_reg ); // FIXME
11427 %}
11428
11429 // Longs vector arithmetic right shift
11430 instruct vsra2L_reg(vecX dst, vecX src, vecX shift) %{
11431 predicate(n->as_Vector()->length() == 2 && !n->as_ShiftV()->is_var_shift());
11432 match(Set dst (RShiftVL src shift));
11433 size(4);
11434 ins_cost(DEFAULT_COST); // FIXME
11435 expand %{
11436 vsha2L_reg(dst, src, shift);
11437 %}
11438 %}
11439
11440 instruct vsra2L_reg_var(vecX dst, vecX src, vecX shift, vecX tmp) %{
11441 predicate(n->as_Vector()->length() == 2 && n->as_ShiftV()->is_var_shift());
11442 match(Set dst (RShiftVL src shift));
11443 effect(TEMP tmp);
11444 size(4*2);
11445 ins_cost(DEFAULT_COST*2);
11446 format %{
11447 "VNEG.S8 $tmp.Q,$shift.Q\n\t! neg packed16B"
11448 "VSHL.S64 $dst.Q,$src.Q,$tmp.Q\t! arithmetic right shift packed2L"
11449 %}
11450 ins_encode %{
11451 bool quad = true;
11452 __ vnegI($tmp$$FloatRegister, $shift$$FloatRegister,
11453 MacroAssembler::VELEM_SIZE_8, quad);
11454 __ vshlSI($dst$$FloatRegister, $tmp$$FloatRegister, $src$$FloatRegister,
11455 MacroAssembler::VELEM_SIZE_64, quad);
11456 %}
11457 ins_pipe(ialu_reg_reg);
11458 %}
11459
11460 instruct vsra2L_immI(vecX dst, vecX src, immI shift) %{
11461 predicate(n->as_Vector()->length() == 2 && assert_not_var_shift(n));
11462 match(Set dst (RShiftVL src (RShiftCntV shift)));
11463 size(4);
11464 ins_cost(DEFAULT_COST); // FIXME
11465 format %{
11466 "VSHR.S64 $dst.Q,$src.Q,$shift\t! arithmetic right shift packed2L"
11467 %}
11468 ins_encode %{
11469 bool quad = true;
11470 __ vshrSI($dst$$FloatRegister, $src$$FloatRegister, 64, $shift$$constant,
11471 quad);
11472 %}
11473 ins_pipe( ialu_reg_reg ); // FIXME
11474 %}
11475
11476 // --------------------------------- AND --------------------------------------
11477
11478 instruct vandD(vecD dst, vecD src1, vecD src2) %{
11479 predicate(n->as_Vector()->length_in_bytes() == 8);
11480 match(Set dst (AndV src1 src2));
11481 format %{ "VAND $dst.D,$src1.D,$src2.D\t! and vectors (8 bytes)" %}
11482 ins_encode %{
11483 bool quad = false;
11484 __ vandI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
11485 quad);
11486 %}
11487 ins_pipe( ialu_reg_reg ); // FIXME
11488 %}
11489
11490 instruct vandX(vecX dst, vecX src1, vecX src2) %{
11491 predicate(n->as_Vector()->length_in_bytes() == 16);
11492 match(Set dst (AndV src1 src2));
11493 format %{ "VAND $dst.Q,$src1.Q,$src2.Q\t! and vectors (16 bytes)" %}
11494 ins_encode %{
11495 bool quad = true;
11496 __ vandI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
11497 quad);
11498 %}
11499 ins_pipe( ialu_reg_reg ); // FIXME
11500 %}
11501
11502 // --------------------------------- OR ---------------------------------------
11503
11504 instruct vorD(vecD dst, vecD src1, vecD src2) %{
11505 predicate(n->as_Vector()->length_in_bytes() == 8);
11506 match(Set dst (OrV src1 src2));
11507 format %{ "VOR $dst.D,$src1.D,$src2.D\t! and vectors (8 bytes)" %}
11508 ins_encode %{
11509 bool quad = false;
11510 __ vorI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
11511 quad);
11512 %}
11513 ins_pipe( ialu_reg_reg ); // FIXME
11514 %}
11515
11516 instruct vorX(vecX dst, vecX src1, vecX src2) %{
11517 predicate(n->as_Vector()->length_in_bytes() == 16);
11518 match(Set dst (OrV src1 src2));
11519 format %{ "VOR $dst.Q,$src1.Q,$src2.Q\t! and vectors (16 bytes)" %}
11520 ins_encode %{
11521 bool quad = true;
11522 __ vorI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
11523 quad);
11524 %}
11525 ins_pipe( ialu_reg_reg ); // FIXME
11526 %}
11527
11528 // --------------------------------- XOR --------------------------------------
11529
11530 instruct vxorD(vecD dst, vecD src1, vecD src2) %{
11531 predicate(n->as_Vector()->length_in_bytes() == 8);
11532 match(Set dst (XorV src1 src2));
11533 format %{ "VXOR $dst.D,$src1.D,$src2.D\t! and vectors (8 bytes)" %}
11534 ins_encode %{
11535 bool quad = false;
11536 __ vxorI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
11537 quad);
11538 %}
11539 ins_pipe( ialu_reg_reg ); // FIXME
11540 %}
11541
11542 instruct vxorX(vecX dst, vecX src1, vecX src2) %{
11543 predicate(n->as_Vector()->length_in_bytes() == 16);
11544 match(Set dst (XorV src1 src2));
11545 format %{ "VXOR $dst.Q,$src1.Q,$src2.Q\t! and vectors (16 bytes)" %}
11546 ins_encode %{
11547 bool quad = true;
11548 __ vxorI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
11549 quad);
11550 %}
11551 ins_pipe( ialu_reg_reg ); // FIXME
11552 %}
11553
11554
11555 //----------PEEPHOLE RULES-----------------------------------------------------
11556 // These must follow all instruction definitions as they use the names
11557 // defined in the instructions definitions.
11558 //
11559 // peepmatch ( root_instr_name [preceding_instruction]* );
11560 //
11561 // peepconstraint %{
11562 // (instruction_number.operand_name relational_op instruction_number.operand_name
11563 // [, ...] );
11564 // // instruction numbers are zero-based using left to right order in peepmatch
11565 //
11566 // peepreplace ( instr_name ( [instruction_number.operand_name]* ) );
11567 // // provide an instruction_number.operand_name for each operand that appears
11568 // // in the replacement instruction's match rule
11569 //
11570 // ---------VM FLAGS---------------------------------------------------------
11571 //
11572 // All peephole optimizations can be turned off using -XX:-OptoPeephole
11573 //
11574 // Each peephole rule is given an identifying number starting with zero and
11575 // increasing by one in the order seen by the parser. An individual peephole
11576 // can be enabled, and all others disabled, by using -XX:OptoPeepholeAt=#
11577 // on the command-line.
11578 //
11579 // ---------CURRENT LIMITATIONS----------------------------------------------
11580 //
11581 // Only match adjacent instructions in same basic block
11582 // Only equality constraints
11583 // Only constraints between operands, not (0.dest_reg == EAX_enc)
11584 // Only one replacement instruction
11585 //
11586 // ---------EXAMPLE----------------------------------------------------------
11587 //
11588 // // pertinent parts of existing instructions in architecture description
11589 // instruct movI(eRegI dst, eRegI src) %{
11590 // match(Set dst (CopyI src));
11591 // %}
11592 //
11593 // instruct incI_eReg(eRegI dst, immI1 src, eFlagsReg cr) %{
11594 // match(Set dst (AddI dst src));
11595 // effect(KILL cr);
11596 // %}
11597 //
11598 // // Change (inc mov) to lea
11599 // peephole %{
11600 // // increment preceded by register-register move
11601 // peepmatch ( incI_eReg movI );
11602 // // require that the destination register of the increment
11603 // // match the destination register of the move
11604 // peepconstraint ( 0.dst == 1.dst );
11605 // // construct a replacement instruction that sets
11606 // // the destination to ( move's source register + one )
11607 // peepreplace ( incI_eReg_immI1( 0.dst 1.src 0.src ) );
11608 // %}
11609 //
11610
11611 // // Change load of spilled value to only a spill
11612 // instruct storeI(memory mem, eRegI src) %{
11613 // match(Set mem (StoreI mem src));
11614 // %}
11615 //
11616 // instruct loadI(eRegI dst, memory mem) %{
11617 // match(Set dst (LoadI mem));
11618 // %}
11619 //
11620 // peephole %{
11621 // peepmatch ( loadI storeI );
11622 // peepconstraint ( 1.src == 0.dst, 1.mem == 0.mem );
11623 // peepreplace ( storeI( 1.mem 1.mem 1.src ) );
11624 // %}
11625
11626 //----------SMARTSPILL RULES---------------------------------------------------
11627 // These must follow all instruction definitions as they use the names
11628 // defined in the instructions definitions.
11629 //
11630 // ARM will probably not have any of these rules due to RISC instruction set.
11631
11632 //----------PIPELINE-----------------------------------------------------------
11633 // Rules which define the behavior of the target architectures pipeline.