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 int MachPrologNode::reloc() const {
343 return 10; // a large enough number
344 }
345
346 //=============================================================================
347 #ifndef PRODUCT
348 void MachEpilogNode::format( PhaseRegAlloc *ra_, outputStream *st ) const {
349 Compile* C = ra_->C;
350
351 size_t framesize = C->output()->frame_size_in_bytes();
352 framesize -= 2*wordSize;
353
354 if (framesize != 0) {
355 st->print("ADD R_SP, R_SP, %zu\n\t",framesize);
356 }
357 st->print("POP R_FP|R_LR_LR");
358
359 if (do_polling() && ra_->C->is_method_compilation()) {
360 st->print("\n\t");
361 st->print("MOV Rtemp, #PollAddr\t! Load Polling address\n\t");
362 st->print("LDR Rtemp,[Rtemp]\t!Poll for Safepointing");
363 }
364 }
365 #endif
366
367 void MachEpilogNode::emit(C2_MacroAssembler *masm, PhaseRegAlloc *ra_) const {
368 Compile* C = ra_->C;
369
370 size_t framesize = C->output()->frame_size_in_bytes();
371 framesize -= 2*wordSize;
372 if (framesize != 0) {
373 __ add_slow(SP, SP, framesize);
374 }
375 __ raw_pop(FP, LR);
376
377 // If this does safepoint polling, then do it here
378 if (do_polling() && ra_->C->is_method_compilation()) {
379 __ read_polling_page(Rtemp, relocInfo::poll_return_type);
380 }
381 }
382
383 int MachEpilogNode::reloc() const {
384 return 16; // a large enough number
385 }
386
387 const Pipeline * MachEpilogNode::pipeline() const {
388 return MachNode::pipeline_class();
389 }
390
391 //=============================================================================
392
393 // Figure out which register class each belongs in: rc_int, rc_float, rc_stack
394 enum RC { rc_bad, rc_int, rc_float, rc_stack };
395 static enum RC rc_class( OptoReg::Name reg ) {
396 if (!OptoReg::is_valid(reg)) return rc_bad;
397 if (OptoReg::is_stack(reg)) return rc_stack;
398 VMReg r = OptoReg::as_VMReg(reg);
399 if (r->is_Register()) return rc_int;
400 assert(r->is_FloatRegister(), "must be");
401 return rc_float;
402 }
403
404 static inline bool is_iRegLd_memhd(OptoReg::Name src_first, OptoReg::Name src_second, int offset) {
405 int rlo = Matcher::_regEncode[src_first];
406 int rhi = Matcher::_regEncode[src_second];
407 if (!((rlo&1)==0 && (rlo+1 == rhi))) {
408 tty->print_cr("CAUGHT BAD LDRD/STRD");
409 }
410 return (rlo&1)==0 && (rlo+1 == rhi) && is_memoryHD(offset);
411 }
412
413 uint MachSpillCopyNode::implementation( C2_MacroAssembler *masm,
414 PhaseRegAlloc *ra_,
415 bool do_size,
416 outputStream* st ) const {
417 // Get registers to move
418 OptoReg::Name src_second = ra_->get_reg_second(in(1));
419 OptoReg::Name src_first = ra_->get_reg_first(in(1));
420 OptoReg::Name dst_second = ra_->get_reg_second(this );
421 OptoReg::Name dst_first = ra_->get_reg_first(this );
422
423 enum RC src_second_rc = rc_class(src_second);
424 enum RC src_first_rc = rc_class(src_first);
425 enum RC dst_second_rc = rc_class(dst_second);
426 enum RC dst_first_rc = rc_class(dst_first);
427
428 assert( OptoReg::is_valid(src_first) && OptoReg::is_valid(dst_first), "must move at least 1 register" );
429
430 // Generate spill code!
431 int size = 0;
432
433 if (src_first == dst_first && src_second == dst_second)
434 return size; // Self copy, no move
435
436 #ifdef TODO
437 if (bottom_type()->isa_vect() != nullptr) {
438 }
439 #endif
440
441 // Shared code does not expect instruction set capability based bailouts here.
442 // Handle offset unreachable bailout with minimal change in shared code.
443 // Bailout only for real instruction emit.
444 // This requires a single comment change in shared code. ( see output.cpp "Normal" instruction case )
445
446 // --------------------------------------
447 // Check for mem-mem move. Load into unused float registers and fall into
448 // the float-store case.
449 if (src_first_rc == rc_stack && dst_first_rc == rc_stack) {
450 int offset = ra_->reg2offset(src_first);
451 if (masm && !is_memoryfp(offset)) {
452 ra_->C->record_method_not_compilable("unable to handle large constant offsets");
453 return 0;
454 } else {
455 if (src_second_rc != rc_bad) {
456 assert((src_first&1)==0 && src_first+1 == src_second, "pair of registers must be aligned/contiguous");
457 src_first = OptoReg::Name(R_mem_copy_lo_num);
458 src_second = OptoReg::Name(R_mem_copy_hi_num);
459 src_first_rc = rc_float;
460 src_second_rc = rc_float;
461 if (masm) {
462 __ ldr_double(Rmemcopy, Address(SP, offset));
463 } else if (!do_size) {
464 st->print(LDR_DOUBLE " R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(src_first),offset);
465 }
466 } else {
467 src_first = OptoReg::Name(R_mem_copy_lo_num);
468 src_first_rc = rc_float;
469 if (masm) {
470 __ ldr_float(Rmemcopy, Address(SP, offset));
471 } else if (!do_size) {
472 st->print(LDR_FLOAT " R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(src_first),offset);
473 }
474 }
475 size += 4;
476 }
477 }
478
479 if (src_second_rc == rc_stack && dst_second_rc == rc_stack) {
480 Unimplemented();
481 }
482
483 // --------------------------------------
484 // Check for integer reg-reg copy
485 if (src_first_rc == rc_int && dst_first_rc == rc_int) {
486 // Else normal reg-reg copy
487 assert( src_second != dst_first, "smashed second before evacuating it" );
488 if (masm) {
489 __ mov(reg_to_register_object(Matcher::_regEncode[dst_first]), reg_to_register_object(Matcher::_regEncode[src_first]));
490 #ifndef PRODUCT
491 } else if (!do_size) {
492 st->print("MOV R_%s, R_%s\t# spill",
493 Matcher::regName[dst_first],
494 Matcher::regName[src_first]);
495 #endif
496 }
497 size += 4;
498 }
499
500 // Check for integer store
501 if (src_first_rc == rc_int && dst_first_rc == rc_stack) {
502 int offset = ra_->reg2offset(dst_first);
503 if (masm && !is_memoryI(offset)) {
504 ra_->C->record_method_not_compilable("unable to handle large constant offsets");
505 return 0;
506 } else {
507 if (src_second_rc != rc_bad && is_iRegLd_memhd(src_first, src_second, offset)) {
508 assert((src_first&1)==0 && src_first+1 == src_second, "pair of registers must be aligned/contiguous");
509 if (masm) {
510 __ str_64(reg_to_register_object(Matcher::_regEncode[src_first]), Address(SP, offset));
511 #ifndef PRODUCT
512 } else if (!do_size) {
513 if (size != 0) st->print("\n\t");
514 st->print(STR_64 " R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(src_first), offset);
515 #endif
516 }
517 return size + 4;
518 } else {
519 if (masm) {
520 __ str_32(reg_to_register_object(Matcher::_regEncode[src_first]), Address(SP, offset));
521 #ifndef PRODUCT
522 } else if (!do_size) {
523 if (size != 0) st->print("\n\t");
524 st->print(STR_32 " R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(src_first), offset);
525 #endif
526 }
527 }
528 }
529 size += 4;
530 }
531
532 // Check for integer load
533 if (dst_first_rc == rc_int && src_first_rc == rc_stack) {
534 int offset = ra_->reg2offset(src_first);
535 if (masm && !is_memoryI(offset)) {
536 ra_->C->record_method_not_compilable("unable to handle large constant offsets");
537 return 0;
538 } else {
539 if (src_second_rc != rc_bad && is_iRegLd_memhd(dst_first, dst_second, offset)) {
540 assert((src_first&1)==0 && src_first+1 == src_second, "pair of registers must be aligned/contiguous");
541 if (masm) {
542 __ ldr_64(reg_to_register_object(Matcher::_regEncode[dst_first]), Address(SP, offset));
543 #ifndef PRODUCT
544 } else if (!do_size) {
545 if (size != 0) st->print("\n\t");
546 st->print(LDR_64 " R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(dst_first), offset);
547 #endif
548 }
549 return size + 4;
550 } else {
551 if (masm) {
552 __ ldr_32(reg_to_register_object(Matcher::_regEncode[dst_first]), Address(SP, offset));
553 #ifndef PRODUCT
554 } else if (!do_size) {
555 if (size != 0) st->print("\n\t");
556 st->print(LDR_32 " R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(dst_first), offset);
557 #endif
558 }
559 }
560 }
561 size += 4;
562 }
563
564 // Check for float reg-reg copy
565 if (src_first_rc == rc_float && dst_first_rc == rc_float) {
566 if (src_second_rc != rc_bad) {
567 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");
568 if (masm) {
569 __ mov_double(reg_to_FloatRegister_object(Matcher::_regEncode[dst_first]), reg_to_FloatRegister_object(Matcher::_regEncode[src_first]));
570 #ifndef PRODUCT
571 } else if (!do_size) {
572 st->print(MOV_DOUBLE " R_%s, R_%s\t# spill",
573 Matcher::regName[dst_first],
574 Matcher::regName[src_first]);
575 #endif
576 }
577 return 4;
578 }
579 if (masm) {
580 __ mov_float(reg_to_FloatRegister_object(Matcher::_regEncode[dst_first]), reg_to_FloatRegister_object(Matcher::_regEncode[src_first]));
581 #ifndef PRODUCT
582 } else if (!do_size) {
583 st->print(MOV_FLOAT " R_%s, R_%s\t# spill",
584 Matcher::regName[dst_first],
585 Matcher::regName[src_first]);
586 #endif
587 }
588 size = 4;
589 }
590
591 // Check for float store
592 if (src_first_rc == rc_float && dst_first_rc == rc_stack) {
593 int offset = ra_->reg2offset(dst_first);
594 if (masm && !is_memoryfp(offset)) {
595 ra_->C->record_method_not_compilable("unable to handle large constant offsets");
596 return 0;
597 } else {
598 // Further check for aligned-adjacent pair, so we can use a double store
599 if (src_second_rc != rc_bad) {
600 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");
601 if (masm) {
602 __ str_double(reg_to_FloatRegister_object(Matcher::_regEncode[src_first]), Address(SP, offset));
603 #ifndef PRODUCT
604 } else if (!do_size) {
605 if (size != 0) st->print("\n\t");
606 st->print(STR_DOUBLE " R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(src_first),offset);
607 #endif
608 }
609 return size + 4;
610 } else {
611 if (masm) {
612 __ str_float(reg_to_FloatRegister_object(Matcher::_regEncode[src_first]), Address(SP, offset));
613 #ifndef PRODUCT
614 } else if (!do_size) {
615 if (size != 0) st->print("\n\t");
616 st->print(STR_FLOAT " R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(src_first),offset);
617 #endif
618 }
619 }
620 }
621 size += 4;
622 }
623
624 // Check for float load
625 if (dst_first_rc == rc_float && src_first_rc == rc_stack) {
626 int offset = ra_->reg2offset(src_first);
627 if (masm && !is_memoryfp(offset)) {
628 ra_->C->record_method_not_compilable("unable to handle large constant offsets");
629 return 0;
630 } else {
631 // Further check for aligned-adjacent pair, so we can use a double store
632 if (src_second_rc != rc_bad) {
633 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");
634 if (masm) {
635 __ ldr_double(reg_to_FloatRegister_object(Matcher::_regEncode[dst_first]), Address(SP, offset));
636 #ifndef PRODUCT
637 } else if (!do_size) {
638 if (size != 0) st->print("\n\t");
639 st->print(LDR_DOUBLE " R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(dst_first),offset);
640 #endif
641 }
642 return size + 4;
643 } else {
644 if (masm) {
645 __ ldr_float(reg_to_FloatRegister_object(Matcher::_regEncode[dst_first]), Address(SP, offset));
646 #ifndef PRODUCT
647 } else if (!do_size) {
648 if (size != 0) st->print("\n\t");
649 st->print(LDR_FLOAT " R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(dst_first),offset);
650 #endif
651 }
652 }
653 }
654 size += 4;
655 }
656
657 // check for int reg -> float reg move
658 if (src_first_rc == rc_int && dst_first_rc == rc_float) {
659 // Further check for aligned-adjacent pair, so we can use a single instruction
660 if (src_second_rc != rc_bad) {
661 assert((dst_first&1)==0 && dst_first+1 == dst_second, "pairs of registers must be aligned/contiguous");
662 assert((src_first&1)==0 && src_first+1 == src_second, "pairs of registers must be aligned/contiguous");
663 assert(src_second_rc == rc_int && dst_second_rc == rc_float, "unsupported");
664 if (masm) {
665 __ 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]));
666 #ifndef PRODUCT
667 } else if (!do_size) {
668 if (size != 0) st->print("\n\t");
669 st->print("FMDRR R_%s, R_%s, R_%s\t! spill",OptoReg::regname(dst_first), OptoReg::regname(src_first), OptoReg::regname(src_second));
670 #endif
671 }
672 return size + 4;
673 } else {
674 if (masm) {
675 __ fmsr(reg_to_FloatRegister_object(Matcher::_regEncode[dst_first]), reg_to_register_object(Matcher::_regEncode[src_first]));
676 #ifndef PRODUCT
677 } else if (!do_size) {
678 if (size != 0) st->print("\n\t");
679 st->print(FMSR " R_%s, R_%s\t! spill",OptoReg::regname(dst_first), OptoReg::regname(src_first));
680 #endif
681 }
682 size += 4;
683 }
684 }
685
686 // check for float reg -> int reg move
687 if (src_first_rc == rc_float && dst_first_rc == rc_int) {
688 // Further check for aligned-adjacent pair, so we can use a single instruction
689 if (src_second_rc != rc_bad) {
690 assert((src_first&1)==0 && src_first+1 == src_second, "pairs of registers must be aligned/contiguous");
691 assert((dst_first&1)==0 && dst_first+1 == dst_second, "pairs of registers must be aligned/contiguous");
692 assert(src_second_rc == rc_float && dst_second_rc == rc_int, "unsupported");
693 if (masm) {
694 __ 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]));
695 #ifndef PRODUCT
696 } else if (!do_size) {
697 if (size != 0) st->print("\n\t");
698 st->print("FMRRD R_%s, R_%s, R_%s\t! spill",OptoReg::regname(dst_first), OptoReg::regname(dst_second), OptoReg::regname(src_first));
699 #endif
700 }
701 return size + 4;
702 } else {
703 if (masm) {
704 __ fmrs(reg_to_register_object(Matcher::_regEncode[dst_first]), reg_to_FloatRegister_object(Matcher::_regEncode[src_first]));
705 #ifndef PRODUCT
706 } else if (!do_size) {
707 if (size != 0) st->print("\n\t");
708 st->print(FMRS " R_%s, R_%s\t! spill",OptoReg::regname(dst_first), OptoReg::regname(src_first));
709 #endif
710 }
711 size += 4;
712 }
713 }
714
715 // --------------------------------------------------------------------
716 // Check for hi bits still needing moving. Only happens for misaligned
717 // arguments to native calls.
718 if (src_second == dst_second)
719 return size; // Self copy; no move
720 assert( src_second_rc != rc_bad && dst_second_rc != rc_bad, "src_second & dst_second cannot be Bad" );
721
722 // Check for integer reg-reg copy. Hi bits are stuck up in the top
723 // 32-bits of a 64-bit register, but are needed in low bits of another
724 // register (else it's a hi-bits-to-hi-bits copy which should have
725 // happened already as part of a 64-bit move)
726 if (src_second_rc == rc_int && dst_second_rc == rc_int) {
727 if (masm) {
728 __ mov(reg_to_register_object(Matcher::_regEncode[dst_second]), reg_to_register_object(Matcher::_regEncode[src_second]));
729 #ifndef PRODUCT
730 } else if (!do_size) {
731 if (size != 0) st->print("\n\t");
732 st->print("MOV R_%s, R_%s\t# spill high",
733 Matcher::regName[dst_second],
734 Matcher::regName[src_second]);
735 #endif
736 }
737 return size+4;
738 }
739
740 // Check for high word integer store
741 if (src_second_rc == rc_int && dst_second_rc == rc_stack) {
742 int offset = ra_->reg2offset(dst_second);
743
744 if (masm && !is_memoryP(offset)) {
745 ra_->C->record_method_not_compilable("unable to handle large constant offsets");
746 return 0;
747 } else {
748 if (masm) {
749 __ str(reg_to_register_object(Matcher::_regEncode[src_second]), Address(SP, offset));
750 #ifndef PRODUCT
751 } else if (!do_size) {
752 if (size != 0) st->print("\n\t");
753 st->print("STR R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(src_second), offset);
754 #endif
755 }
756 }
757 return size + 4;
758 }
759
760 // Check for high word integer load
761 if (dst_second_rc == rc_int && src_second_rc == rc_stack) {
762 int offset = ra_->reg2offset(src_second);
763 if (masm && !is_memoryP(offset)) {
764 ra_->C->record_method_not_compilable("unable to handle large constant offsets");
765 return 0;
766 } else {
767 if (masm) {
768 __ ldr(reg_to_register_object(Matcher::_regEncode[dst_second]), Address(SP, offset));
769 #ifndef PRODUCT
770 } else if (!do_size) {
771 if (size != 0) st->print("\n\t");
772 st->print("LDR R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(dst_second), offset);
773 #endif
774 }
775 }
776 return size + 4;
777 }
778
779 Unimplemented();
780 return 0; // Mute compiler
781 }
782
783 #ifndef PRODUCT
784 void MachSpillCopyNode::format( PhaseRegAlloc *ra_, outputStream *st ) const {
785 implementation( nullptr, ra_, false, st );
786 }
787 #endif
788
789 void MachSpillCopyNode::emit(C2_MacroAssembler *masm, PhaseRegAlloc *ra_) const {
790 implementation( masm, ra_, false, nullptr );
791 }
792
793 uint MachSpillCopyNode::size(PhaseRegAlloc *ra_) const {
794 return implementation( nullptr, ra_, true, nullptr );
795 }
796
797 //=============================================================================
798 #ifndef PRODUCT
799 void MachNopNode::format( PhaseRegAlloc *, outputStream *st ) const {
800 st->print("NOP \t# %d bytes pad for loops and calls", 4 * _count);
801 }
802 #endif
803
804 void MachNopNode::emit(C2_MacroAssembler *masm, PhaseRegAlloc * ) const {
805 for(int i = 0; i < _count; i += 1) {
806 __ nop();
807 }
808 }
809
810 uint MachNopNode::size(PhaseRegAlloc *ra_) const {
811 return 4 * _count;
812 }
813
814
815 //=============================================================================
816 #ifndef PRODUCT
817 void BoxLockNode::format( PhaseRegAlloc *ra_, outputStream *st ) const {
818 int offset = ra_->reg2offset(in_RegMask(0).find_first_elem());
819 int reg = ra_->get_reg_first(this);
820 st->print("ADD %s,R_SP+#%d",Matcher::regName[reg], offset);
821 }
822 #endif
823
824 void BoxLockNode::emit(C2_MacroAssembler *masm, PhaseRegAlloc *ra_) const {
825 int offset = ra_->reg2offset(in_RegMask(0).find_first_elem());
826 int reg = ra_->get_encode(this);
827 Register dst = reg_to_register_object(reg);
828
829 if (is_aimm(offset)) {
830 __ add(dst, SP, offset);
831 } else {
832 __ mov_slow(dst, offset);
833 __ add(dst, SP, dst);
834 }
835 }
836
837 uint BoxLockNode::size(PhaseRegAlloc *ra_) const {
838 // BoxLockNode is not a MachNode, so we can't just call MachNode::size(ra_)
839 assert(ra_ == ra_->C->regalloc(), "sanity");
840 return ra_->C->output()->scratch_emit_size(this);
841 }
842
843 //=============================================================================
844 #ifndef PRODUCT
845 void MachVEPNode::format(PhaseRegAlloc* ra_, outputStream* st) const
846 {
847 Unimplemented();
848 }
849 #endif
850
851 void MachVEPNode::emit(C2_MacroAssembler *masm, PhaseRegAlloc* ra_) const
852 {
853 Unimplemented();
854 }
855
856 #ifndef PRODUCT
857 #define R_RTEMP "R_R12"
858 void MachUEPNode::format( PhaseRegAlloc *ra_, outputStream *st ) const {
859 st->print_cr("\nUEP:");
860 st->print_cr("\tLDR " R_RTEMP ",[R_R0 + oopDesc::klass_offset_in_bytes]\t! Inline cache check");
861 st->print_cr("\tCMP " R_RTEMP ",R_R8" );
862 st->print ("\tB.NE SharedRuntime::handle_ic_miss_stub");
863 }
864 #endif
865
866 void MachUEPNode::emit(C2_MacroAssembler *masm, PhaseRegAlloc *ra_) const {
867 __ ic_check(InteriorEntryAlignment);
868 }
869
870 //=============================================================================
871
872 int HandlerImpl::emit_deopt_handler(C2_MacroAssembler* masm) {
873 // Can't use any of the current frame's registers as we may have deopted
874 // at a poll and everything can be live.
875 address base = __ start_a_stub(size_deopt_handler());
876 if (base == nullptr) {
877 ciEnv::current()->record_failure("CodeCache is full");
878 return 0; // CodeBuffer::expand failed
879 }
880
881 int offset = __ offset();
882
883 Label start;
884 __ bind(start);
885
886 __ jump(SharedRuntime::deopt_blob()->unpack(), relocInfo::runtime_call_type, noreg);
887
888 int entry_offset = __ offset();
889 address deopt_pc = __ pc();
890 // Preserve R0 and reserve space for the address of the entry point
891 __ push(RegisterSet(R0) | RegisterSet(R1));
892 // Store the entry point address
893 __ mov_relative_address(R0, deopt_pc);
894 __ str(R0, Address(SP, wordSize));
895 __ pop(R0); // restore R0
896 __ b(start);
897
898 assert(__ offset() - offset <= (int) size_deopt_handler(), "overflow");
899 assert(__ offset() - entry_offset >= NativePostCallNop::first_check_size,
900 "out of bounds read in post-call NOP check");
901
902 __ end_a_stub();
903 return entry_offset;
904 }
905
906 bool Matcher::match_rule_supported(int opcode) {
907 if (!has_match_rule(opcode))
908 return false;
909
910 switch (opcode) {
911 case Op_PopCountI:
912 case Op_PopCountL:
913 if (!UsePopCountInstruction)
914 return false;
915 break;
916 case Op_LShiftCntV:
917 case Op_RShiftCntV:
918 case Op_AddVB:
919 case Op_AddVS:
920 case Op_AddVI:
921 case Op_AddVL:
922 case Op_SubVB:
923 case Op_SubVS:
924 case Op_SubVI:
925 case Op_SubVL:
926 case Op_MulVS:
927 case Op_MulVI:
928 case Op_LShiftVB:
929 case Op_LShiftVS:
930 case Op_LShiftVI:
931 case Op_LShiftVL:
932 case Op_RShiftVB:
933 case Op_RShiftVS:
934 case Op_RShiftVI:
935 case Op_RShiftVL:
936 case Op_URShiftVB:
937 case Op_URShiftVS:
938 case Op_URShiftVI:
939 case Op_URShiftVL:
940 case Op_AndV:
941 case Op_OrV:
942 case Op_XorV:
943 return VM_Version::has_simd();
944 case Op_LoadVector:
945 case Op_StoreVector:
946 case Op_AddVF:
947 case Op_SubVF:
948 case Op_MulVF:
949 return VM_Version::has_vfp() || VM_Version::has_simd();
950 case Op_AddVD:
951 case Op_SubVD:
952 case Op_MulVD:
953 case Op_DivVF:
954 case Op_DivVD:
955 return VM_Version::has_vfp();
956 }
957
958 return true; // Per default match rules are supported.
959 }
960
961 bool Matcher::match_rule_supported_auto_vectorization(int opcode, int vlen, BasicType bt) {
962 return match_rule_supported_vector(opcode, vlen, bt);
963 }
964
965 bool Matcher::match_rule_supported_vector(int opcode, int vlen, BasicType bt) {
966
967 // TODO
968 // identify extra cases that we might want to provide match rules for
969 // e.g. Op_ vector nodes and other intrinsics while guarding with vlen
970 bool ret_value = match_rule_supported(opcode) && vector_size_supported(bt, vlen);
971 // Add rules here.
972
973 return ret_value; // Per default match rules are supported.
974 }
975
976 bool Matcher::match_rule_supported_vector_masked(int opcode, int vlen, BasicType bt) {
977 return false;
978 }
979
980 bool Matcher::vector_needs_partial_operations(Node* node, const TypeVect* vt) {
981 return false;
982 }
983
984 bool Matcher::vector_rearrange_requires_load_shuffle(BasicType elem_bt, int vlen) {
985 return false;
986 }
987
988 bool Matcher::mask_op_prefers_predicate(int opcode, const TypeVect* vt) {
989 return false;
990 }
991
992 const RegMask* Matcher::predicate_reg_mask(void) {
993 return nullptr;
994 }
995
996 // Vector calling convention not yet implemented.
997 bool Matcher::supports_vector_calling_convention(void) {
998 return false;
999 }
1000
1001 OptoRegPair Matcher::vector_return_value(uint ideal_reg) {
1002 Unimplemented();
1003 return OptoRegPair(0, 0);
1004 }
1005
1006 // Vector width in bytes
1007 int Matcher::vector_width_in_bytes(BasicType bt) {
1008 return MaxVectorSize;
1009 }
1010
1011 int Matcher::scalable_vector_reg_size(const BasicType bt) {
1012 return -1;
1013 }
1014
1015 // Vector ideal reg corresponding to specified size in bytes
1016 uint Matcher::vector_ideal_reg(int size) {
1017 assert(MaxVectorSize >= size, "");
1018 switch(size) {
1019 case 8: return Op_VecD;
1020 case 16: return Op_VecX;
1021 }
1022 ShouldNotReachHere();
1023 return 0;
1024 }
1025
1026 // Limits on vector size (number of elements) loaded into vector.
1027 int Matcher::max_vector_size(const BasicType bt) {
1028 assert(is_java_primitive(bt), "only primitive type vectors");
1029 return vector_width_in_bytes(bt)/type2aelembytes(bt);
1030 }
1031
1032 int Matcher::min_vector_size(const BasicType bt) {
1033 assert(is_java_primitive(bt), "only primitive type vectors");
1034 return 8/type2aelembytes(bt);
1035 }
1036
1037 int Matcher::max_vector_size_auto_vectorization(const BasicType bt) {
1038 return Matcher::max_vector_size(bt);
1039 }
1040
1041 // Is this branch offset short enough that a short branch can be used?
1042 //
1043 // NOTE: If the platform does not provide any short branch variants, then
1044 // this method should return false for offset 0.
1045 bool Matcher::is_short_branch_offset(int rule, int br_size, int offset) {
1046 // The passed offset is relative to address of the branch.
1047 // On ARM a branch displacement is calculated relative to address
1048 // of the branch + 8.
1049 //
1050 // offset -= 8;
1051 // return (Assembler::is_simm24(offset));
1052 return false;
1053 }
1054
1055 MachOper* Matcher::pd_specialize_generic_vector_operand(MachOper* original_opnd, uint ideal_reg, bool is_temp) {
1056 ShouldNotReachHere(); // generic vector operands not supported
1057 return nullptr;
1058 }
1059
1060 bool Matcher::is_reg2reg_move(MachNode* m) {
1061 ShouldNotReachHere(); // generic vector operands not supported
1062 return false;
1063 }
1064
1065 bool Matcher::is_register_biasing_candidate(const MachNode* mdef, int oper_index) {
1066 return false;
1067 }
1068
1069 bool Matcher::is_generic_vector(MachOper* opnd) {
1070 ShouldNotReachHere(); // generic vector operands not supported
1071 return false;
1072 }
1073
1074 // Should the matcher clone input 'm' of node 'n'?
1075 bool Matcher::pd_clone_node(Node* n, Node* m, Matcher::MStack& mstack) {
1076 if (is_vshift_con_pattern(n, m)) { // ShiftV src (ShiftCntV con)
1077 mstack.push(m, Visit); // m = ShiftCntV
1078 return true;
1079 }
1080 return false;
1081 }
1082
1083 // Should the Matcher clone shifts on addressing modes, expecting them
1084 // to be subsumed into complex addressing expressions or compute them
1085 // into registers?
1086 bool Matcher::pd_clone_address_expressions(AddPNode* m, Matcher::MStack& mstack, VectorSet& address_visited) {
1087 return clone_base_plus_offset_address(m, mstack, address_visited);
1088 }
1089
1090 #ifdef ASSERT
1091 // Return whether or not this register is ever used as an argument.
1092 bool Matcher::can_be_java_arg( int reg ) {
1093 if (reg == R_R0_num ||
1094 reg == R_R1_num ||
1095 reg == R_R2_num ||
1096 reg == R_R3_num) return true;
1097
1098 if (reg >= R_S0_num &&
1099 reg <= R_S13_num) return true;
1100 return false;
1101 }
1102 #endif
1103
1104 uint Matcher::int_pressure_limit()
1105 {
1106 return (INTPRESSURE == -1) ? 12 : INTPRESSURE;
1107 }
1108
1109 uint Matcher::float_pressure_limit()
1110 {
1111 return (FLOATPRESSURE == -1) ? 30 : FLOATPRESSURE;
1112 }
1113
1114 // Register for DIVI projection of divmodI
1115 const RegMask& Matcher::divI_proj_mask() {
1116 ShouldNotReachHere();
1117 return RegMask::EMPTY;
1118 }
1119
1120 // Register for MODI projection of divmodI
1121 const RegMask& Matcher::modI_proj_mask() {
1122 ShouldNotReachHere();
1123 return RegMask::EMPTY;
1124 }
1125
1126 // Register for DIVL projection of divmodL
1127 const RegMask& Matcher::divL_proj_mask() {
1128 ShouldNotReachHere();
1129 return RegMask::EMPTY;
1130 }
1131
1132 // Register for MODL projection of divmodL
1133 const RegMask& Matcher::modL_proj_mask() {
1134 ShouldNotReachHere();
1135 return RegMask::EMPTY;
1136 }
1137
1138 bool maybe_far_call(const CallNode *n) {
1139 return !MacroAssembler::_reachable_from_cache(n->as_Call()->entry_point());
1140 }
1141
1142 bool maybe_far_call(const MachCallNode *n) {
1143 return !MacroAssembler::_reachable_from_cache(n->as_MachCall()->entry_point());
1144 }
1145
1146 %}
1147
1148 //----------ENCODING BLOCK-----------------------------------------------------
1149 // This block specifies the encoding classes used by the compiler to output
1150 // byte streams. Encoding classes are parameterized macros used by
1151 // Machine Instruction Nodes in order to generate the bit encoding of the
1152 // instruction. Operands specify their base encoding interface with the
1153 // interface keyword. There are currently supported four interfaces,
1154 // REG_INTER, CONST_INTER, MEMORY_INTER, & COND_INTER. REG_INTER causes an
1155 // operand to generate a function which returns its register number when
1156 // queried. CONST_INTER causes an operand to generate a function which
1157 // returns the value of the constant when queried. MEMORY_INTER causes an
1158 // operand to generate four functions which return the Base Register, the
1159 // Index Register, the Scale Value, and the Offset Value of the operand when
1160 // queried. COND_INTER causes an operand to generate six functions which
1161 // return the encoding code (ie - encoding bits for the instruction)
1162 // associated with each basic boolean condition for a conditional instruction.
1163 //
1164 // Instructions specify two basic values for encoding. Again, a function
1165 // is available to check if the constant displacement is an oop. They use the
1166 // ins_encode keyword to specify their encoding classes (which must be
1167 // a sequence of enc_class names, and their parameters, specified in
1168 // the encoding block), and they use the
1169 // opcode keyword to specify, in order, their primary, secondary, and
1170 // tertiary opcode. Only the opcode sections which a particular instruction
1171 // needs for encoding need to be specified.
1172 encode %{
1173 // Set instruction mark in MacroAssembler. This is used only in
1174 // instructions that emit bytes directly to the CodeBuffer wraped
1175 // in the MacroAssembler. Should go away once all "instruct" are
1176 // patched to emit bytes only using methods in MacroAssembler.
1177 enc_class SetInstMark %{
1178 __ set_inst_mark();
1179 %}
1180
1181 enc_class ClearInstMark %{
1182 __ clear_inst_mark();
1183 %}
1184
1185 enc_class call_epilog %{
1186 // nothing
1187 %}
1188
1189 enc_class Java_To_Runtime (method meth) %{
1190 // CALL directly to the runtime
1191 emit_call_reloc(masm, as_MachCall(), $meth, runtime_call_Relocation::spec());
1192 %}
1193
1194 enc_class Java_Static_Call (method meth) %{
1195 // CALL to fixup routine. Fixup routine uses ScopeDesc info to determine
1196 // who we intended to call.
1197
1198 if ( !_method) {
1199 emit_call_reloc(masm, as_MachCall(), $meth, runtime_call_Relocation::spec());
1200 } else {
1201 int method_index = resolved_method_index(masm);
1202 RelocationHolder rspec = _optimized_virtual ? opt_virtual_call_Relocation::spec(method_index)
1203 : static_call_Relocation::spec(method_index);
1204 emit_call_reloc(masm, as_MachCall(), $meth, rspec);
1205
1206 // Emit stubs for static call.
1207 address stub = CompiledDirectCall::emit_to_interp_stub(masm);
1208 if (stub == nullptr) {
1209 ciEnv::current()->record_failure("CodeCache is full");
1210 return;
1211 }
1212 }
1213 %}
1214
1215 enc_class save_last_PC %{
1216 // preserve mark
1217 address mark = __ inst_mark();
1218 DEBUG_ONLY(int off0 = __ offset());
1219 int ret_addr_offset = as_MachCall()->ret_addr_offset();
1220 __ adr(LR, mark + ret_addr_offset);
1221 __ str(LR, Address(Rthread, JavaThread::last_Java_pc_offset()));
1222 DEBUG_ONLY(int off1 = __ offset());
1223 assert(off1 - off0 == 2 * Assembler::InstructionSize, "correct size prediction");
1224 // restore mark
1225 __ set_inst_mark(mark);
1226 %}
1227
1228 enc_class Java_Dynamic_Call (method meth) %{
1229 Register R8_ic_reg = reg_to_register_object(Matcher::inline_cache_reg_encode());
1230 assert(R8_ic_reg == Ricklass, "should be");
1231 __ set_inst_mark();
1232 __ movw(R8_ic_reg, ((unsigned int)Universe::non_oop_word()) & 0xffff);
1233 __ movt(R8_ic_reg, ((unsigned int)Universe::non_oop_word()) >> 16);
1234 address virtual_call_oop_addr = __ inst_mark();
1235 // CALL to fixup routine. Fixup routine uses ScopeDesc info to determine
1236 // who we intended to call.
1237 int method_index = resolved_method_index(masm);
1238 __ relocate(virtual_call_Relocation::spec(virtual_call_oop_addr, method_index));
1239 emit_call_reloc(masm, as_MachCall(), $meth, RelocationHolder::none);
1240 %}
1241
1242 enc_class LdReplImmI(immI src, regD dst, iRegI tmp, int cnt, int wth) %{
1243 // FIXME: load from constant table?
1244 // Load a constant replicated "count" times with width "width"
1245 int count = $cnt$$constant;
1246 int width = $wth$$constant;
1247 assert(count*width == 4, "sanity");
1248 int val = $src$$constant;
1249 if (width < 4) {
1250 int bit_width = width * 8;
1251 val &= (((int)1) << bit_width) - 1; // mask off sign bits
1252 for (int i = 0; i < count - 1; i++) {
1253 val |= (val << bit_width);
1254 }
1255 }
1256
1257 if (val == -1) {
1258 __ mvn($tmp$$Register, 0);
1259 } else if (val == 0) {
1260 __ mov($tmp$$Register, 0);
1261 } else {
1262 __ movw($tmp$$Register, val & 0xffff);
1263 __ movt($tmp$$Register, (unsigned int)val >> 16);
1264 }
1265 __ fmdrr($dst$$FloatRegister, $tmp$$Register, $tmp$$Register);
1266 %}
1267
1268 enc_class LdReplImmF(immF src, regD dst, iRegI tmp) %{
1269 // Replicate float con 2 times and pack into vector (8 bytes) in regD.
1270 float fval = $src$$constant;
1271 int val = *((int*)&fval);
1272
1273 if (val == -1) {
1274 __ mvn($tmp$$Register, 0);
1275 } else if (val == 0) {
1276 __ mov($tmp$$Register, 0);
1277 } else {
1278 __ movw($tmp$$Register, val & 0xffff);
1279 __ movt($tmp$$Register, (unsigned int)val >> 16);
1280 }
1281 __ fmdrr($dst$$FloatRegister, $tmp$$Register, $tmp$$Register);
1282 %}
1283
1284 enc_class enc_String_Compare(R0RegP str1, R1RegP str2, R2RegI cnt1, R3RegI cnt2, iRegI result, iRegI tmp1, iRegI tmp2) %{
1285 Label Ldone, Lloop;
1286
1287 Register str1_reg = $str1$$Register;
1288 Register str2_reg = $str2$$Register;
1289 Register cnt1_reg = $cnt1$$Register; // int
1290 Register cnt2_reg = $cnt2$$Register; // int
1291 Register tmp1_reg = $tmp1$$Register;
1292 Register tmp2_reg = $tmp2$$Register;
1293 Register result_reg = $result$$Register;
1294
1295 assert_different_registers(str1_reg, str2_reg, cnt1_reg, cnt2_reg, tmp1_reg, tmp2_reg);
1296
1297 // Compute the minimum of the string lengths(str1_reg) and the
1298 // difference of the string lengths (stack)
1299
1300 // See if the lengths are different, and calculate min in str1_reg.
1301 // Stash diff in tmp2 in case we need it for a tie-breaker.
1302 __ subs_32(tmp2_reg, cnt1_reg, cnt2_reg);
1303 __ mov(cnt1_reg, AsmOperand(cnt1_reg, lsl, exact_log2(sizeof(jchar)))); // scale the limit
1304 __ mov(cnt1_reg, AsmOperand(cnt2_reg, lsl, exact_log2(sizeof(jchar))), pl); // scale the limit
1305
1306 // reallocate cnt1_reg, cnt2_reg, result_reg
1307 // Note: limit_reg holds the string length pre-scaled by 2
1308 Register limit_reg = cnt1_reg;
1309 Register chr2_reg = cnt2_reg;
1310 Register chr1_reg = tmp1_reg;
1311 // str{12} are the base pointers
1312
1313 // Is the minimum length zero?
1314 __ cmp_32(limit_reg, 0);
1315 if (result_reg != tmp2_reg) {
1316 __ mov(result_reg, tmp2_reg, eq);
1317 }
1318 __ b(Ldone, eq);
1319
1320 // Load first characters
1321 __ ldrh(chr1_reg, Address(str1_reg, 0));
1322 __ ldrh(chr2_reg, Address(str2_reg, 0));
1323
1324 // Compare first characters
1325 __ subs(chr1_reg, chr1_reg, chr2_reg);
1326 if (result_reg != chr1_reg) {
1327 __ mov(result_reg, chr1_reg, ne);
1328 }
1329 __ b(Ldone, ne);
1330
1331 {
1332 // Check after comparing first character to see if strings are equivalent
1333 // Check if the strings start at same location
1334 __ cmp(str1_reg, str2_reg);
1335 // Check if the length difference is zero
1336 __ cond_cmp(tmp2_reg, 0, eq);
1337 __ mov(result_reg, 0, eq); // result is zero
1338 __ b(Ldone, eq);
1339 // Strings might not be equal
1340 }
1341
1342 __ subs(chr1_reg, limit_reg, 1 * sizeof(jchar));
1343 if (result_reg != tmp2_reg) {
1344 __ mov(result_reg, tmp2_reg, eq);
1345 }
1346 __ b(Ldone, eq);
1347
1348 // Shift str1_reg and str2_reg to the end of the arrays, negate limit
1349 __ add(str1_reg, str1_reg, limit_reg);
1350 __ add(str2_reg, str2_reg, limit_reg);
1351 __ neg(limit_reg, chr1_reg); // limit = -(limit-2)
1352
1353 // Compare the rest of the characters
1354 __ bind(Lloop);
1355 __ ldrh(chr1_reg, Address(str1_reg, limit_reg));
1356 __ ldrh(chr2_reg, Address(str2_reg, limit_reg));
1357 __ subs(chr1_reg, chr1_reg, chr2_reg);
1358 if (result_reg != chr1_reg) {
1359 __ mov(result_reg, chr1_reg, ne);
1360 }
1361 __ b(Ldone, ne);
1362
1363 __ adds(limit_reg, limit_reg, sizeof(jchar));
1364 __ b(Lloop, ne);
1365
1366 // If strings are equal up to min length, return the length difference.
1367 if (result_reg != tmp2_reg) {
1368 __ mov(result_reg, tmp2_reg);
1369 }
1370
1371 // Otherwise, return the difference between the first mismatched chars.
1372 __ bind(Ldone);
1373 %}
1374
1375 enc_class enc_String_Equals(R0RegP str1, R1RegP str2, R2RegI cnt, iRegI result, iRegI tmp1, iRegI tmp2) %{
1376 Label Lchar, Lchar_loop, Ldone, Lequal;
1377
1378 Register str1_reg = $str1$$Register;
1379 Register str2_reg = $str2$$Register;
1380 Register cnt_reg = $cnt$$Register; // int
1381 Register tmp1_reg = $tmp1$$Register;
1382 Register tmp2_reg = $tmp2$$Register;
1383 Register result_reg = $result$$Register;
1384
1385 assert_different_registers(str1_reg, str2_reg, cnt_reg, tmp1_reg, tmp2_reg, result_reg);
1386
1387 __ cmp(str1_reg, str2_reg); //same char[] ?
1388 __ b(Lequal, eq);
1389
1390 __ cbz_32(cnt_reg, Lequal); // count == 0
1391
1392 //rename registers
1393 Register limit_reg = cnt_reg;
1394 Register chr1_reg = tmp1_reg;
1395 Register chr2_reg = tmp2_reg;
1396
1397 __ logical_shift_left(limit_reg, limit_reg, exact_log2(sizeof(jchar)));
1398
1399 //check for alignment and position the pointers to the ends
1400 __ orr(chr1_reg, str1_reg, str2_reg);
1401 __ tst(chr1_reg, 0x3);
1402
1403 // notZero means at least one not 4-byte aligned.
1404 // We could optimize the case when both arrays are not aligned
1405 // but it is not frequent case and it requires additional checks.
1406 __ b(Lchar, ne);
1407
1408 // Compare char[] arrays aligned to 4 bytes.
1409 __ char_arrays_equals(str1_reg, str2_reg, limit_reg, result_reg,
1410 chr1_reg, chr2_reg, Ldone);
1411
1412 __ b(Lequal); // equal
1413
1414 // char by char compare
1415 __ bind(Lchar);
1416 __ mov(result_reg, 0);
1417 __ add(str1_reg, limit_reg, str1_reg);
1418 __ add(str2_reg, limit_reg, str2_reg);
1419 __ neg(limit_reg, limit_reg); //negate count
1420
1421 // Lchar_loop
1422 __ bind(Lchar_loop);
1423 __ ldrh(chr1_reg, Address(str1_reg, limit_reg));
1424 __ ldrh(chr2_reg, Address(str2_reg, limit_reg));
1425 __ cmp(chr1_reg, chr2_reg);
1426 __ b(Ldone, ne);
1427 __ adds(limit_reg, limit_reg, sizeof(jchar));
1428 __ b(Lchar_loop, ne);
1429
1430 __ bind(Lequal);
1431 __ mov(result_reg, 1); //equal
1432
1433 __ bind(Ldone);
1434 %}
1435
1436 enc_class enc_Array_Equals(R0RegP ary1, R1RegP ary2, iRegI tmp1, iRegI tmp2, iRegI tmp3, iRegI result) %{
1437 Label Ldone, Lloop, Lequal;
1438
1439 Register ary1_reg = $ary1$$Register;
1440 Register ary2_reg = $ary2$$Register;
1441 Register tmp1_reg = $tmp1$$Register;
1442 Register tmp2_reg = $tmp2$$Register;
1443 Register tmp3_reg = $tmp3$$Register;
1444 Register result_reg = $result$$Register;
1445
1446 assert_different_registers(ary1_reg, ary2_reg, tmp1_reg, tmp2_reg, tmp3_reg, result_reg);
1447
1448 int length_offset = arrayOopDesc::length_offset_in_bytes();
1449 int base_offset = arrayOopDesc::base_offset_in_bytes(T_CHAR);
1450
1451 // return true if the same array
1452 __ teq(ary1_reg, ary2_reg);
1453 __ mov(result_reg, 1, eq);
1454 __ b(Ldone, eq); // equal
1455
1456 __ tst(ary1_reg, ary1_reg);
1457 __ mov(result_reg, 0, eq);
1458 __ b(Ldone, eq); // not equal
1459
1460 __ tst(ary2_reg, ary2_reg);
1461 __ mov(result_reg, 0, eq);
1462 __ b(Ldone, eq); // not equal
1463
1464 //load the lengths of arrays
1465 __ ldr_s32(tmp1_reg, Address(ary1_reg, length_offset)); // int
1466 __ ldr_s32(tmp2_reg, Address(ary2_reg, length_offset)); // int
1467
1468 // return false if the two arrays are not equal length
1469 __ teq_32(tmp1_reg, tmp2_reg);
1470 __ mov(result_reg, 0, ne);
1471 __ b(Ldone, ne); // not equal
1472
1473 __ tst(tmp1_reg, tmp1_reg);
1474 __ mov(result_reg, 1, eq);
1475 __ b(Ldone, eq); // zero-length arrays are equal
1476
1477 // load array addresses
1478 __ add(ary1_reg, ary1_reg, base_offset);
1479 __ add(ary2_reg, ary2_reg, base_offset);
1480
1481 // renaming registers
1482 Register chr1_reg = tmp3_reg; // for characters in ary1
1483 Register chr2_reg = tmp2_reg; // for characters in ary2
1484 Register limit_reg = tmp1_reg; // length
1485
1486 // set byte count
1487 __ logical_shift_left_32(limit_reg, limit_reg, exact_log2(sizeof(jchar)));
1488
1489 // Compare char[] arrays aligned to 4 bytes.
1490 __ char_arrays_equals(ary1_reg, ary2_reg, limit_reg, result_reg,
1491 chr1_reg, chr2_reg, Ldone);
1492 __ bind(Lequal);
1493 __ mov(result_reg, 1); //equal
1494
1495 __ bind(Ldone);
1496 %}
1497 %}
1498
1499 //----------FRAME--------------------------------------------------------------
1500 // Definition of frame structure and management information.
1501 //
1502 // S T A C K L A Y O U T Allocators stack-slot number
1503 // | (to get allocators register number
1504 // G Owned by | | v add VMRegImpl::stack0)
1505 // r CALLER | |
1506 // o | +--------+ pad to even-align allocators stack-slot
1507 // w V | pad0 | numbers; owned by CALLER
1508 // t -----------+--------+----> Matcher::_in_arg_limit, unaligned
1509 // h ^ | in | 5
1510 // | | args | 4 Holes in incoming args owned by SELF
1511 // | | | | 3
1512 // | | +--------+
1513 // V | | old out| Empty on Intel, window on Sparc
1514 // | old |preserve| Must be even aligned.
1515 // | SP-+--------+----> Matcher::_old_SP, 8 (or 16 in LP64)-byte aligned
1516 // | | in | 3 area for Intel ret address
1517 // Owned by |preserve| Empty on Sparc.
1518 // SELF +--------+
1519 // | | pad2 | 2 pad to align old SP
1520 // | +--------+ 1
1521 // | | locks | 0
1522 // | +--------+----> VMRegImpl::stack0, 8 (or 16 in LP64)-byte aligned
1523 // | | pad1 | 11 pad to align new SP
1524 // | +--------+
1525 // | | | 10
1526 // | | spills | 9 spills
1527 // V | | 8 (pad0 slot for callee)
1528 // -----------+--------+----> Matcher::_out_arg_limit, unaligned
1529 // ^ | out | 7
1530 // | | args | 6 Holes in outgoing args owned by CALLEE
1531 // Owned by +--------+
1532 // CALLEE | new out| 6 Empty on Intel, window on Sparc
1533 // | new |preserve| Must be even-aligned.
1534 // | SP-+--------+----> Matcher::_new_SP, even aligned
1535 // | | |
1536 //
1537 // Note 1: Only region 8-11 is determined by the allocator. Region 0-5 is
1538 // known from SELF's arguments and the Java calling convention.
1539 // Region 6-7 is determined per call site.
1540 // Note 2: If the calling convention leaves holes in the incoming argument
1541 // area, those holes are owned by SELF. Holes in the outgoing area
1542 // are owned by the CALLEE. Holes should not be necessary in the
1543 // incoming area, as the Java calling convention is completely under
1544 // the control of the AD file. Doubles can be sorted and packed to
1545 // avoid holes. Holes in the outgoing arguments may be necessary for
1546 // varargs C calling conventions.
1547 // Note 3: Region 0-3 is even aligned, with pad2 as needed. Region 3-5 is
1548 // even aligned with pad0 as needed.
1549 // Region 6 is even aligned. Region 6-7 is NOT even aligned;
1550 // region 6-11 is even aligned; it may be padded out more so that
1551 // the region from SP to FP meets the minimum stack alignment.
1552
1553 frame %{
1554 // These two registers define part of the calling convention
1555 // between compiled code and the interpreter.
1556 inline_cache_reg(R_Ricklass); // Inline Cache Register or Method* for I2C
1557
1558 // Optional: name the operand used by cisc-spilling to access [stack_pointer + offset]
1559 cisc_spilling_operand_name(indOffset);
1560
1561 // Number of stack slots consumed by a Monitor enter
1562 sync_stack_slots(1 * VMRegImpl::slots_per_word);
1563
1564 // Compiled code's Frame Pointer
1565 frame_pointer(R_R13);
1566
1567 // Stack alignment requirement
1568 stack_alignment(StackAlignmentInBytes);
1569 // LP64: Alignment size in bytes (128-bit -> 16 bytes)
1570 // !LP64: Alignment size in bytes (64-bit -> 8 bytes)
1571
1572 // Number of outgoing stack slots killed above the out_preserve_stack_slots
1573 // for calls to C. Supports the var-args backing area for register parms.
1574 // ADLC doesn't support parsing expressions, so I folded the math by hand.
1575 varargs_C_out_slots_killed( 0);
1576
1577 // The after-PROLOG location of the return address. Location of
1578 // return address specifies a type (REG or STACK) and a number
1579 // representing the register number (i.e. - use a register name) or
1580 // stack slot.
1581 // Ret Addr is on stack in slot 0 if no locks or verification or alignment.
1582 // Otherwise, it is above the locks and verification slot and alignment word
1583 return_addr(STACK - 1*VMRegImpl::slots_per_word +
1584 align_up((Compile::current()->in_preserve_stack_slots() +
1585 Compile::current()->fixed_slots()),
1586 stack_alignment_in_slots()));
1587
1588 // Location of compiled Java return values. Same as C
1589 return_value %{
1590 return c2::return_value(ideal_reg);
1591 %}
1592
1593 %}
1594
1595 //----------ATTRIBUTES---------------------------------------------------------
1596 //----------Instruction Attributes---------------------------------------------
1597 ins_attrib ins_cost(DEFAULT_COST); // Required cost attribute
1598 ins_attrib ins_size(32); // Required size attribute (in bits)
1599 ins_attrib ins_short_branch(0); // Required flag: is this instruction a
1600 // non-matching short branch variant of some
1601 // long branch?
1602
1603 //----------OPERANDS-----------------------------------------------------------
1604 // Operand definitions must precede instruction definitions for correct parsing
1605 // in the ADLC because operands constitute user defined types which are used in
1606 // instruction definitions.
1607
1608 //----------Simple Operands----------------------------------------------------
1609 // Immediate Operands
1610 // Integer Immediate: 32-bit
1611 operand immI() %{
1612 match(ConI);
1613
1614 op_cost(0);
1615 // formats are generated automatically for constants and base registers
1616 format %{ %}
1617 interface(CONST_INTER);
1618 %}
1619
1620 // Integer Immediate: 8-bit unsigned - for VMOV
1621 operand immU8() %{
1622 predicate(0 <= n->get_int() && (n->get_int() <= 255));
1623 match(ConI);
1624 op_cost(0);
1625
1626 format %{ %}
1627 interface(CONST_INTER);
1628 %}
1629
1630 // Integer Immediate: 16-bit
1631 operand immI16() %{
1632 predicate((n->get_int() >> 16) == 0 && VM_Version::supports_movw());
1633 match(ConI);
1634 op_cost(0);
1635
1636 format %{ %}
1637 interface(CONST_INTER);
1638 %}
1639
1640 // Integer Immediate: offset for half and double word loads and stores
1641 operand immIHD() %{
1642 predicate(is_memoryHD(n->get_int()));
1643 match(ConI);
1644 op_cost(0);
1645 format %{ %}
1646 interface(CONST_INTER);
1647 %}
1648
1649 // Integer Immediate: offset for fp loads and stores
1650 operand immIFP() %{
1651 predicate(is_memoryfp(n->get_int()) && ((n->get_int() & 3) == 0));
1652 match(ConI);
1653 op_cost(0);
1654
1655 format %{ %}
1656 interface(CONST_INTER);
1657 %}
1658
1659 // Valid scale values for addressing modes and shifts
1660 operand immU5() %{
1661 predicate(0 <= n->get_int() && (n->get_int() <= 31));
1662 match(ConI);
1663 op_cost(0);
1664
1665 format %{ %}
1666 interface(CONST_INTER);
1667 %}
1668
1669 // Integer Immediate: 6-bit
1670 operand immU6Big() %{
1671 predicate(n->get_int() >= 32 && n->get_int() <= 63);
1672 match(ConI);
1673 op_cost(0);
1674 format %{ %}
1675 interface(CONST_INTER);
1676 %}
1677
1678 // Integer Immediate: 0-bit
1679 operand immI0() %{
1680 predicate(n->get_int() == 0);
1681 match(ConI);
1682 op_cost(0);
1683
1684 format %{ %}
1685 interface(CONST_INTER);
1686 %}
1687
1688 // Int Immediate non-negative
1689 operand immU31()
1690 %{
1691 predicate(n->get_int() >= 0);
1692 match(ConI);
1693
1694 op_cost(0);
1695 format %{ %}
1696 interface(CONST_INTER);
1697 %}
1698
1699 // Integer Immediate: the values 32-63
1700 operand immI_32_63() %{
1701 predicate(n->get_int() >= 32 && n->get_int() <= 63);
1702 match(ConI);
1703 op_cost(0);
1704
1705 format %{ %}
1706 interface(CONST_INTER);
1707 %}
1708
1709 // Immediates for special shifts (sign extend)
1710
1711 // Integer Immediate: the value 16
1712 operand immI_16() %{
1713 predicate(n->get_int() == 16);
1714 match(ConI);
1715 op_cost(0);
1716
1717 format %{ %}
1718 interface(CONST_INTER);
1719 %}
1720
1721 // Integer Immediate: the value 24
1722 operand immI_24() %{
1723 predicate(n->get_int() == 24);
1724 match(ConI);
1725 op_cost(0);
1726
1727 format %{ %}
1728 interface(CONST_INTER);
1729 %}
1730
1731 // Integer Immediate: the value 255
1732 operand immI_255() %{
1733 predicate( n->get_int() == 255 );
1734 match(ConI);
1735 op_cost(0);
1736
1737 format %{ %}
1738 interface(CONST_INTER);
1739 %}
1740
1741 // Integer Immediate: the value 65535
1742 operand immI_65535() %{
1743 predicate(n->get_int() == 65535);
1744 match(ConI);
1745 op_cost(0);
1746
1747 format %{ %}
1748 interface(CONST_INTER);
1749 %}
1750
1751 // Integer Immediates for arithmetic instructions
1752
1753 operand aimmI() %{
1754 predicate(is_aimm(n->get_int()));
1755 match(ConI);
1756 op_cost(0);
1757
1758 format %{ %}
1759 interface(CONST_INTER);
1760 %}
1761
1762 operand aimmIneg() %{
1763 predicate(is_aimm(-n->get_int()));
1764 match(ConI);
1765 op_cost(0);
1766
1767 format %{ %}
1768 interface(CONST_INTER);
1769 %}
1770
1771 operand aimmU31() %{
1772 predicate((0 <= n->get_int()) && is_aimm(n->get_int()));
1773 match(ConI);
1774 op_cost(0);
1775
1776 format %{ %}
1777 interface(CONST_INTER);
1778 %}
1779
1780 // Integer Immediates for logical instructions
1781
1782 operand limmI() %{
1783 predicate(is_limmI(n->get_int()));
1784 match(ConI);
1785 op_cost(0);
1786
1787 format %{ %}
1788 interface(CONST_INTER);
1789 %}
1790
1791 operand limmIlow8() %{
1792 predicate(is_limmI_low(n->get_int(), 8));
1793 match(ConI);
1794 op_cost(0);
1795
1796 format %{ %}
1797 interface(CONST_INTER);
1798 %}
1799
1800 operand limmU31() %{
1801 predicate(0 <= n->get_int() && is_limmI(n->get_int()));
1802 match(ConI);
1803 op_cost(0);
1804
1805 format %{ %}
1806 interface(CONST_INTER);
1807 %}
1808
1809 operand limmIn() %{
1810 predicate(is_limmI(~n->get_int()));
1811 match(ConI);
1812 op_cost(0);
1813
1814 format %{ %}
1815 interface(CONST_INTER);
1816 %}
1817
1818 // Pointer Immediate: 32 or 64-bit
1819 operand immP() %{
1820 match(ConP);
1821
1822 op_cost(5);
1823 // formats are generated automatically for constants and base registers
1824 format %{ %}
1825 interface(CONST_INTER);
1826 %}
1827
1828 operand immP0() %{
1829 predicate(n->get_ptr() == 0);
1830 match(ConP);
1831 op_cost(0);
1832
1833 format %{ %}
1834 interface(CONST_INTER);
1835 %}
1836
1837 operand immL() %{
1838 match(ConL);
1839 op_cost(40);
1840 // formats are generated automatically for constants and base registers
1841 format %{ %}
1842 interface(CONST_INTER);
1843 %}
1844
1845 operand immL0() %{
1846 predicate(n->get_long() == 0L);
1847 match(ConL);
1848 op_cost(0);
1849 // formats are generated automatically for constants and base registers
1850 format %{ %}
1851 interface(CONST_INTER);
1852 %}
1853
1854 // Long Immediate: 16-bit
1855 operand immL16() %{
1856 predicate(n->get_long() >= 0 && n->get_long() < (1<<16) && VM_Version::supports_movw());
1857 match(ConL);
1858 op_cost(0);
1859
1860 format %{ %}
1861 interface(CONST_INTER);
1862 %}
1863
1864 // Long Immediate: low 32-bit mask
1865 operand immL_32bits() %{
1866 predicate(n->get_long() == 0xFFFFFFFFL);
1867 match(ConL);
1868 op_cost(0);
1869
1870 format %{ %}
1871 interface(CONST_INTER);
1872 %}
1873
1874 // Double Immediate
1875 operand immD() %{
1876 match(ConD);
1877
1878 op_cost(40);
1879 format %{ %}
1880 interface(CONST_INTER);
1881 %}
1882
1883 // Double Immediate: +0.0d.
1884 operand immD0() %{
1885 predicate(jlong_cast(n->getd()) == 0);
1886
1887 match(ConD);
1888 op_cost(0);
1889 format %{ %}
1890 interface(CONST_INTER);
1891 %}
1892
1893 operand imm8D() %{
1894 predicate(Assembler::double_num(n->getd()).can_be_imm8());
1895 match(ConD);
1896
1897 op_cost(0);
1898 format %{ %}
1899 interface(CONST_INTER);
1900 %}
1901
1902 // Float Immediate
1903 operand immF() %{
1904 match(ConF);
1905
1906 op_cost(20);
1907 format %{ %}
1908 interface(CONST_INTER);
1909 %}
1910
1911 // Float Immediate: +0.0f
1912 operand immF0() %{
1913 predicate(jint_cast(n->getf()) == 0);
1914 match(ConF);
1915
1916 op_cost(0);
1917 format %{ %}
1918 interface(CONST_INTER);
1919 %}
1920
1921 // Float Immediate: encoded as 8 bits
1922 operand imm8F() %{
1923 predicate(Assembler::float_num(n->getf()).can_be_imm8());
1924 match(ConF);
1925
1926 op_cost(0);
1927 format %{ %}
1928 interface(CONST_INTER);
1929 %}
1930
1931 // Integer Register Operands
1932 // Integer Register
1933 operand iRegI() %{
1934 constraint(ALLOC_IN_RC(int_reg));
1935 match(RegI);
1936 match(R0RegI);
1937 match(R1RegI);
1938 match(R2RegI);
1939 match(R3RegI);
1940 match(R12RegI);
1941
1942 format %{ %}
1943 interface(REG_INTER);
1944 %}
1945
1946 // Pointer Register
1947 operand iRegP() %{
1948 constraint(ALLOC_IN_RC(ptr_reg));
1949 match(RegP);
1950 match(R0RegP);
1951 match(R1RegP);
1952 match(R2RegP);
1953 match(RExceptionRegP);
1954 match(R8RegP);
1955 match(R9RegP);
1956 match(RthreadRegP); // FIXME: move to sp_ptr_RegP?
1957 match(R12RegP);
1958 match(LRRegP);
1959
1960 match(sp_ptr_RegP);
1961 match(store_ptr_RegP);
1962
1963 format %{ %}
1964 interface(REG_INTER);
1965 %}
1966
1967 // GPRs + Rthread + SP
1968 operand sp_ptr_RegP() %{
1969 constraint(ALLOC_IN_RC(sp_ptr_reg));
1970 match(RegP);
1971 match(iRegP);
1972 match(SPRegP); // FIXME: check cost
1973
1974 format %{ %}
1975 interface(REG_INTER);
1976 %}
1977
1978
1979 operand R0RegP() %{
1980 constraint(ALLOC_IN_RC(R0_regP));
1981 match(iRegP);
1982
1983 format %{ %}
1984 interface(REG_INTER);
1985 %}
1986
1987 operand R1RegP() %{
1988 constraint(ALLOC_IN_RC(R1_regP));
1989 match(iRegP);
1990
1991 format %{ %}
1992 interface(REG_INTER);
1993 %}
1994
1995 operand R8RegP() %{
1996 constraint(ALLOC_IN_RC(R8_regP));
1997 match(iRegP);
1998
1999 format %{ %}
2000 interface(REG_INTER);
2001 %}
2002
2003 operand R9RegP() %{
2004 constraint(ALLOC_IN_RC(R9_regP));
2005 match(iRegP);
2006
2007 format %{ %}
2008 interface(REG_INTER);
2009 %}
2010
2011 operand R12RegP() %{
2012 constraint(ALLOC_IN_RC(R12_regP));
2013 match(iRegP);
2014
2015 format %{ %}
2016 interface(REG_INTER);
2017 %}
2018
2019 operand R2RegP() %{
2020 constraint(ALLOC_IN_RC(R2_regP));
2021 match(iRegP);
2022
2023 format %{ %}
2024 interface(REG_INTER);
2025 %}
2026
2027 operand RExceptionRegP() %{
2028 constraint(ALLOC_IN_RC(Rexception_regP));
2029 match(iRegP);
2030
2031 format %{ %}
2032 interface(REG_INTER);
2033 %}
2034
2035 operand RthreadRegP() %{
2036 constraint(ALLOC_IN_RC(Rthread_regP));
2037 match(iRegP);
2038
2039 format %{ %}
2040 interface(REG_INTER);
2041 %}
2042
2043 operand IPRegP() %{
2044 constraint(ALLOC_IN_RC(IP_regP));
2045 match(iRegP);
2046
2047 format %{ %}
2048 interface(REG_INTER);
2049 %}
2050
2051 operand SPRegP() %{
2052 constraint(ALLOC_IN_RC(SP_regP));
2053 match(iRegP);
2054
2055 format %{ %}
2056 interface(REG_INTER);
2057 %}
2058
2059 operand LRRegP() %{
2060 constraint(ALLOC_IN_RC(LR_regP));
2061 match(iRegP);
2062
2063 format %{ %}
2064 interface(REG_INTER);
2065 %}
2066
2067 operand R0RegI() %{
2068 constraint(ALLOC_IN_RC(R0_regI));
2069 match(iRegI);
2070
2071 format %{ %}
2072 interface(REG_INTER);
2073 %}
2074
2075 operand R1RegI() %{
2076 constraint(ALLOC_IN_RC(R1_regI));
2077 match(iRegI);
2078
2079 format %{ %}
2080 interface(REG_INTER);
2081 %}
2082
2083 operand R2RegI() %{
2084 constraint(ALLOC_IN_RC(R2_regI));
2085 match(iRegI);
2086
2087 format %{ %}
2088 interface(REG_INTER);
2089 %}
2090
2091 operand R3RegI() %{
2092 constraint(ALLOC_IN_RC(R3_regI));
2093 match(iRegI);
2094
2095 format %{ %}
2096 interface(REG_INTER);
2097 %}
2098
2099 operand R12RegI() %{
2100 constraint(ALLOC_IN_RC(R12_regI));
2101 match(iRegI);
2102
2103 format %{ %}
2104 interface(REG_INTER);
2105 %}
2106
2107 // Long Register
2108 operand iRegL() %{
2109 constraint(ALLOC_IN_RC(long_reg));
2110 match(RegL);
2111 match(R0R1RegL);
2112 match(R2R3RegL);
2113 //match(iRegLex);
2114
2115 format %{ %}
2116 interface(REG_INTER);
2117 %}
2118
2119 operand iRegLd() %{
2120 constraint(ALLOC_IN_RC(long_reg_align));
2121 match(iRegL); // FIXME: allows unaligned R11/R12?
2122
2123 format %{ %}
2124 interface(REG_INTER);
2125 %}
2126
2127 // first long arg, or return value
2128 operand R0R1RegL() %{
2129 constraint(ALLOC_IN_RC(R0R1_regL));
2130 match(iRegL);
2131
2132 format %{ %}
2133 interface(REG_INTER);
2134 %}
2135
2136 operand R2R3RegL() %{
2137 constraint(ALLOC_IN_RC(R2R3_regL));
2138 match(iRegL);
2139
2140 format %{ %}
2141 interface(REG_INTER);
2142 %}
2143
2144 // Condition Code Flag Register
2145 operand flagsReg() %{
2146 constraint(ALLOC_IN_RC(int_flags));
2147 match(RegFlags);
2148
2149 format %{ "apsr" %}
2150 interface(REG_INTER);
2151 %}
2152
2153 // Result of compare to 0 (TST)
2154 operand flagsReg_EQNELTGE() %{
2155 constraint(ALLOC_IN_RC(int_flags));
2156 match(RegFlags);
2157
2158 format %{ "apsr_EQNELTGE" %}
2159 interface(REG_INTER);
2160 %}
2161
2162 // Condition Code Register, unsigned comparisons.
2163 operand flagsRegU() %{
2164 constraint(ALLOC_IN_RC(int_flags));
2165 match(RegFlags);
2166 #ifdef TODO
2167 match(RegFlagsP);
2168 #endif
2169
2170 format %{ "apsr_U" %}
2171 interface(REG_INTER);
2172 %}
2173
2174 // Condition Code Register, pointer comparisons.
2175 operand flagsRegP() %{
2176 constraint(ALLOC_IN_RC(int_flags));
2177 match(RegFlags);
2178
2179 format %{ "apsr_P" %}
2180 interface(REG_INTER);
2181 %}
2182
2183 // Condition Code Register, long comparisons.
2184 operand flagsRegL_LTGE() %{
2185 constraint(ALLOC_IN_RC(int_flags));
2186 match(RegFlags);
2187
2188 format %{ "apsr_L_LTGE" %}
2189 interface(REG_INTER);
2190 %}
2191
2192 operand flagsRegL_EQNE() %{
2193 constraint(ALLOC_IN_RC(int_flags));
2194 match(RegFlags);
2195
2196 format %{ "apsr_L_EQNE" %}
2197 interface(REG_INTER);
2198 %}
2199
2200 operand flagsRegL_LEGT() %{
2201 constraint(ALLOC_IN_RC(int_flags));
2202 match(RegFlags);
2203
2204 format %{ "apsr_L_LEGT" %}
2205 interface(REG_INTER);
2206 %}
2207
2208 operand flagsRegUL_LTGE() %{
2209 constraint(ALLOC_IN_RC(int_flags));
2210 match(RegFlags);
2211
2212 format %{ "apsr_UL_LTGE" %}
2213 interface(REG_INTER);
2214 %}
2215
2216 operand flagsRegUL_EQNE() %{
2217 constraint(ALLOC_IN_RC(int_flags));
2218 match(RegFlags);
2219
2220 format %{ "apsr_UL_EQNE" %}
2221 interface(REG_INTER);
2222 %}
2223
2224 operand flagsRegUL_LEGT() %{
2225 constraint(ALLOC_IN_RC(int_flags));
2226 match(RegFlags);
2227
2228 format %{ "apsr_UL_LEGT" %}
2229 interface(REG_INTER);
2230 %}
2231
2232 // Condition Code Register, floating comparisons, unordered same as "less".
2233 operand flagsRegF() %{
2234 constraint(ALLOC_IN_RC(float_flags));
2235 match(RegFlags);
2236
2237 format %{ "fpscr_F" %}
2238 interface(REG_INTER);
2239 %}
2240
2241 // Vectors
2242 operand vecD() %{
2243 constraint(ALLOC_IN_RC(actual_dflt_reg));
2244 match(VecD);
2245
2246 format %{ %}
2247 interface(REG_INTER);
2248 %}
2249
2250 operand vecX() %{
2251 constraint(ALLOC_IN_RC(vectorx_reg));
2252 match(VecX);
2253
2254 format %{ %}
2255 interface(REG_INTER);
2256 %}
2257
2258 operand regD() %{
2259 constraint(ALLOC_IN_RC(actual_dflt_reg));
2260 match(RegD);
2261 match(regD_low);
2262
2263 format %{ %}
2264 interface(REG_INTER);
2265 %}
2266
2267 operand regF() %{
2268 constraint(ALLOC_IN_RC(sflt_reg));
2269 match(RegF);
2270
2271 format %{ %}
2272 interface(REG_INTER);
2273 %}
2274
2275 operand regD_low() %{
2276 constraint(ALLOC_IN_RC(dflt_low_reg));
2277 match(RegD);
2278
2279 format %{ %}
2280 interface(REG_INTER);
2281 %}
2282
2283 // Special Registers
2284
2285 // Method Register
2286 operand inline_cache_regP(iRegP reg) %{
2287 constraint(ALLOC_IN_RC(Ricklass_regP));
2288 match(reg);
2289 format %{ %}
2290 interface(REG_INTER);
2291 %}
2292
2293 //----------Complex Operands---------------------------------------------------
2294 // Indirect Memory Reference
2295 operand indirect(sp_ptr_RegP reg) %{
2296 constraint(ALLOC_IN_RC(sp_ptr_reg));
2297 match(reg);
2298
2299 op_cost(100);
2300 format %{ "[$reg]" %}
2301 interface(MEMORY_INTER) %{
2302 base($reg);
2303 index(0xf); // PC => no index
2304 scale(0x0);
2305 disp(0x0);
2306 %}
2307 %}
2308
2309
2310 // Indirect with Offset in ]-4096, 4096[
2311 operand indOffset12(sp_ptr_RegP reg, immI12 offset) %{
2312 constraint(ALLOC_IN_RC(sp_ptr_reg));
2313 match(AddP reg offset);
2314
2315 op_cost(100);
2316 format %{ "[$reg + $offset]" %}
2317 interface(MEMORY_INTER) %{
2318 base($reg);
2319 index(0xf); // PC => no index
2320 scale(0x0);
2321 disp($offset);
2322 %}
2323 %}
2324
2325 // Indirect with offset for float load/store
2326 operand indOffsetFP(sp_ptr_RegP reg, immIFP offset) %{
2327 constraint(ALLOC_IN_RC(sp_ptr_reg));
2328 match(AddP reg offset);
2329
2330 op_cost(100);
2331 format %{ "[$reg + $offset]" %}
2332 interface(MEMORY_INTER) %{
2333 base($reg);
2334 index(0xf); // PC => no index
2335 scale(0x0);
2336 disp($offset);
2337 %}
2338 %}
2339
2340 // Indirect with Offset for half and double words
2341 operand indOffsetHD(sp_ptr_RegP reg, immIHD offset) %{
2342 constraint(ALLOC_IN_RC(sp_ptr_reg));
2343 match(AddP reg offset);
2344
2345 op_cost(100);
2346 format %{ "[$reg + $offset]" %}
2347 interface(MEMORY_INTER) %{
2348 base($reg);
2349 index(0xf); // PC => no index
2350 scale(0x0);
2351 disp($offset);
2352 %}
2353 %}
2354
2355 // Indirect with Offset and Offset+4 in ]-1024, 1024[
2356 operand indOffsetFPx2(sp_ptr_RegP reg, immX10x2 offset) %{
2357 constraint(ALLOC_IN_RC(sp_ptr_reg));
2358 match(AddP reg offset);
2359
2360 op_cost(100);
2361 format %{ "[$reg + $offset]" %}
2362 interface(MEMORY_INTER) %{
2363 base($reg);
2364 index(0xf); // PC => no index
2365 scale(0x0);
2366 disp($offset);
2367 %}
2368 %}
2369
2370 // Indirect with Offset and Offset+4 in ]-4096, 4096[
2371 operand indOffset12x2(sp_ptr_RegP reg, immI12x2 offset) %{
2372 constraint(ALLOC_IN_RC(sp_ptr_reg));
2373 match(AddP reg offset);
2374
2375 op_cost(100);
2376 format %{ "[$reg + $offset]" %}
2377 interface(MEMORY_INTER) %{
2378 base($reg);
2379 index(0xf); // PC => no index
2380 scale(0x0);
2381 disp($offset);
2382 %}
2383 %}
2384
2385 // Indirect with Register Index
2386 operand indIndex(iRegP addr, iRegX index) %{
2387 constraint(ALLOC_IN_RC(ptr_reg));
2388 match(AddP addr index);
2389
2390 op_cost(100);
2391 format %{ "[$addr + $index]" %}
2392 interface(MEMORY_INTER) %{
2393 base($addr);
2394 index($index);
2395 scale(0x0);
2396 disp(0x0);
2397 %}
2398 %}
2399
2400 // Indirect Memory Times Scale Plus Index Register
2401 operand indIndexScale(iRegP addr, iRegX index, immU5 scale) %{
2402 constraint(ALLOC_IN_RC(ptr_reg));
2403 match(AddP addr (LShiftX index scale));
2404
2405 op_cost(100);
2406 format %{"[$addr + $index << $scale]" %}
2407 interface(MEMORY_INTER) %{
2408 base($addr);
2409 index($index);
2410 scale($scale);
2411 disp(0x0);
2412 %}
2413 %}
2414
2415 // Operands for expressing Control Flow
2416 // NOTE: Label is a predefined operand which should not be redefined in
2417 // the AD file. It is generically handled within the ADLC.
2418
2419 //----------Conditional Branch Operands----------------------------------------
2420 // Comparison Op - This is the operation of the comparison, and is limited to
2421 // the following set of codes:
2422 // L (<), LE (<=), G (>), GE (>=), E (==), NE (!=)
2423 //
2424 // Other attributes of the comparison, such as unsignedness, are specified
2425 // by the comparison instruction that sets a condition code flags register.
2426 // That result is represented by a flags operand whose subtype is appropriate
2427 // to the unsignedness (etc.) of the comparison.
2428 //
2429 // Later, the instruction which matches both the Comparison Op (a Bool) and
2430 // the flags (produced by the Cmp) specifies the coding of the comparison op
2431 // by matching a specific subtype of Bool operand below, such as cmpOpU.
2432
2433 operand cmpOp() %{
2434 match(Bool);
2435
2436 format %{ "" %}
2437 interface(COND_INTER) %{
2438 equal(0x0);
2439 not_equal(0x1);
2440 less(0xb);
2441 greater_equal(0xa);
2442 less_equal(0xd);
2443 greater(0xc);
2444 overflow(0x0); // unsupported/unimplemented
2445 no_overflow(0x0); // unsupported/unimplemented
2446 %}
2447 %}
2448
2449 // integer comparison with 0, signed
2450 operand cmpOp0() %{
2451 match(Bool);
2452
2453 format %{ "" %}
2454 interface(COND_INTER) %{
2455 equal(0x0);
2456 not_equal(0x1);
2457 less(0x4);
2458 greater_equal(0x5);
2459 less_equal(0xd); // unsupported
2460 greater(0xc); // unsupported
2461 overflow(0x0); // unsupported/unimplemented
2462 no_overflow(0x0); // unsupported/unimplemented
2463 %}
2464 %}
2465
2466 // Comparison Op, unsigned
2467 operand cmpOpU() %{
2468 match(Bool);
2469
2470 format %{ "u" %}
2471 interface(COND_INTER) %{
2472 equal(0x0);
2473 not_equal(0x1);
2474 less(0x3);
2475 greater_equal(0x2);
2476 less_equal(0x9);
2477 greater(0x8);
2478 overflow(0x0); // unsupported/unimplemented
2479 no_overflow(0x0); // unsupported/unimplemented
2480 %}
2481 %}
2482
2483 // Comparison Op, pointer (same as unsigned)
2484 operand cmpOpP() %{
2485 match(Bool);
2486
2487 format %{ "p" %}
2488 interface(COND_INTER) %{
2489 equal(0x0);
2490 not_equal(0x1);
2491 less(0x3);
2492 greater_equal(0x2);
2493 less_equal(0x9);
2494 greater(0x8);
2495 overflow(0x0); // unsupported/unimplemented
2496 no_overflow(0x0); // unsupported/unimplemented
2497 %}
2498 %}
2499
2500 operand cmpOpL() %{
2501 match(Bool);
2502
2503 format %{ "L" %}
2504 interface(COND_INTER) %{
2505 equal(0x0);
2506 not_equal(0x1);
2507 less(0xb);
2508 greater_equal(0xa);
2509 less_equal(0xd);
2510 greater(0xc);
2511 overflow(0x0); // unsupported/unimplemented
2512 no_overflow(0x0); // unsupported/unimplemented
2513 %}
2514 %}
2515
2516 operand cmpOpL_commute() %{
2517 match(Bool);
2518
2519 format %{ "L" %}
2520 interface(COND_INTER) %{
2521 equal(0x0);
2522 not_equal(0x1);
2523 less(0xc);
2524 greater_equal(0xd);
2525 less_equal(0xa);
2526 greater(0xb);
2527 overflow(0x0); // unsupported/unimplemented
2528 no_overflow(0x0); // unsupported/unimplemented
2529 %}
2530 %}
2531
2532 operand cmpOpUL() %{
2533 match(Bool);
2534
2535 format %{ "UL" %}
2536 interface(COND_INTER) %{
2537 equal(0x0);
2538 not_equal(0x1);
2539 less(0x3);
2540 greater_equal(0x2);
2541 less_equal(0x9);
2542 greater(0x8);
2543 overflow(0x0); // unsupported/unimplemented
2544 no_overflow(0x0); // unsupported/unimplemented
2545 %}
2546 %}
2547
2548 operand cmpOpUL_commute() %{
2549 match(Bool);
2550
2551 format %{ "UL" %}
2552 interface(COND_INTER) %{
2553 equal(0x0);
2554 not_equal(0x1);
2555 less(0x8);
2556 greater_equal(0x9);
2557 less_equal(0x2);
2558 greater(0x3);
2559 overflow(0x0); // unsupported/unimplemented
2560 no_overflow(0x0); // unsupported/unimplemented
2561 %}
2562 %}
2563
2564
2565 //----------OPERAND CLASSES----------------------------------------------------
2566 // Operand Classes are groups of operands that are used to simplify
2567 // instruction definitions by not requiring the AD writer to specify separate
2568 // instructions for every form of operand when the instruction accepts
2569 // multiple operand types with the same basic encoding and format. The classic
2570 // case of this is memory operands.
2571
2572 opclass memoryI ( indirect, indOffset12, indIndex, indIndexScale );
2573 opclass memoryP ( indirect, indOffset12, indIndex, indIndexScale );
2574 opclass memoryF ( indirect, indOffsetFP );
2575 opclass memoryF2 ( indirect, indOffsetFPx2 );
2576 opclass memoryD ( indirect, indOffsetFP );
2577 opclass memoryfp( indirect, indOffsetFP );
2578 opclass memoryB ( indirect, indIndex, indOffsetHD );
2579 opclass memoryS ( indirect, indIndex, indOffsetHD );
2580 opclass memoryL ( indirect, indIndex, indOffsetHD );
2581
2582 opclass memoryScaledI(indIndexScale);
2583 opclass memoryScaledP(indIndexScale);
2584
2585 // when ldrex/strex is used:
2586 opclass memoryex ( indirect );
2587 opclass indIndexMemory( indIndex );
2588 opclass memorylong ( indirect, indOffset12x2 );
2589 opclass memoryvld ( indirect /* , write back mode not implemented */ );
2590
2591 //----------PIPELINE-----------------------------------------------------------
2592 pipeline %{
2593
2594 //----------ATTRIBUTES---------------------------------------------------------
2595 attributes %{
2596 fixed_size_instructions; // Fixed size instructions
2597 max_instructions_per_bundle = 4; // Up to 4 instructions per bundle
2598 instruction_unit_size = 4; // An instruction is 4 bytes long
2599 instruction_fetch_unit_size = 16; // The processor fetches one line
2600 instruction_fetch_units = 1; // of 16 bytes
2601 %}
2602
2603 //----------RESOURCES----------------------------------------------------------
2604 // Resources are the functional units available to the machine
2605 resources(A0, A1, MS, BR, FA, FM, IDIV, FDIV, IALU = A0 | A1);
2606
2607 //----------PIPELINE DESCRIPTION-----------------------------------------------
2608 // Pipeline Description specifies the stages in the machine's pipeline
2609
2610 pipe_desc(A, P, F, B, I, J, S, R, E, C, M, W, X, T, D);
2611
2612 //----------PIPELINE CLASSES---------------------------------------------------
2613 // Pipeline Classes describe the stages in which input and output are
2614 // referenced by the hardware pipeline.
2615
2616 // Integer ALU reg-reg operation
2617 pipe_class ialu_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{
2618 single_instruction;
2619 dst : E(write);
2620 src1 : R(read);
2621 src2 : R(read);
2622 IALU : R;
2623 %}
2624
2625 // Integer ALU reg-reg long operation
2626 pipe_class ialu_reg_reg_2(iRegL dst, iRegL src1, iRegL src2) %{
2627 instruction_count(2);
2628 dst : E(write);
2629 src1 : R(read);
2630 src2 : R(read);
2631 IALU : R;
2632 IALU : R;
2633 %}
2634
2635 // Integer ALU reg-reg long dependent operation
2636 pipe_class ialu_reg_reg_2_dep(iRegL dst, iRegL src1, iRegL src2, flagsReg cr) %{
2637 instruction_count(1); multiple_bundles;
2638 dst : E(write);
2639 src1 : R(read);
2640 src2 : R(read);
2641 cr : E(write);
2642 IALU : R(2);
2643 %}
2644
2645 // Integer ALU reg-imm operation
2646 pipe_class ialu_reg_imm(iRegI dst, iRegI src1) %{
2647 single_instruction;
2648 dst : E(write);
2649 src1 : R(read);
2650 IALU : R;
2651 %}
2652
2653 // Integer ALU reg-reg operation with condition code
2654 pipe_class ialu_cc_reg_reg(iRegI dst, iRegI src1, iRegI src2, flagsReg cr) %{
2655 single_instruction;
2656 dst : E(write);
2657 cr : E(write);
2658 src1 : R(read);
2659 src2 : R(read);
2660 IALU : R;
2661 %}
2662
2663 // Integer ALU zero-reg operation
2664 pipe_class ialu_zero_reg(iRegI dst, immI0 zero, iRegI src2) %{
2665 single_instruction;
2666 dst : E(write);
2667 src2 : R(read);
2668 IALU : R;
2669 %}
2670
2671 // Integer ALU zero-reg operation with condition code only
2672 pipe_class ialu_cconly_zero_reg(flagsReg cr, iRegI src) %{
2673 single_instruction;
2674 cr : E(write);
2675 src : R(read);
2676 IALU : R;
2677 %}
2678
2679 // Integer ALU reg-reg operation with condition code only
2680 pipe_class ialu_cconly_reg_reg(flagsReg cr, iRegI src1, iRegI src2) %{
2681 single_instruction;
2682 cr : E(write);
2683 src1 : R(read);
2684 src2 : R(read);
2685 IALU : R;
2686 %}
2687
2688 // Integer ALU reg-imm operation with condition code only
2689 pipe_class ialu_cconly_reg_imm(flagsReg cr, iRegI src1) %{
2690 single_instruction;
2691 cr : E(write);
2692 src1 : R(read);
2693 IALU : R;
2694 %}
2695
2696 // Integer ALU reg-reg-zero operation with condition code only
2697 pipe_class ialu_cconly_reg_reg_zero(flagsReg cr, iRegI src1, iRegI src2, immI0 zero) %{
2698 single_instruction;
2699 cr : E(write);
2700 src1 : R(read);
2701 src2 : R(read);
2702 IALU : R;
2703 %}
2704
2705 // Integer ALU reg-imm-zero operation with condition code only
2706 pipe_class ialu_cconly_reg_imm_zero(flagsReg cr, iRegI src1, immI0 zero) %{
2707 single_instruction;
2708 cr : E(write);
2709 src1 : R(read);
2710 IALU : R;
2711 %}
2712
2713 // Integer ALU reg-reg operation with condition code, src1 modified
2714 pipe_class ialu_cc_rwreg_reg(flagsReg cr, iRegI src1, iRegI src2) %{
2715 single_instruction;
2716 cr : E(write);
2717 src1 : E(write);
2718 src1 : R(read);
2719 src2 : R(read);
2720 IALU : R;
2721 %}
2722
2723 pipe_class cmpL_reg(iRegI dst, iRegL src1, iRegL src2, flagsReg cr ) %{
2724 multiple_bundles;
2725 dst : E(write)+4;
2726 cr : E(write);
2727 src1 : R(read);
2728 src2 : R(read);
2729 IALU : R(3);
2730 BR : R(2);
2731 %}
2732
2733 // Integer ALU operation
2734 pipe_class ialu_none(iRegI dst) %{
2735 single_instruction;
2736 dst : E(write);
2737 IALU : R;
2738 %}
2739
2740 // Integer ALU reg operation
2741 pipe_class ialu_reg(iRegI dst, iRegI src) %{
2742 single_instruction; may_have_no_code;
2743 dst : E(write);
2744 src : R(read);
2745 IALU : R;
2746 %}
2747
2748 // Integer ALU reg conditional operation
2749 // This instruction has a 1 cycle stall, and cannot execute
2750 // in the same cycle as the instruction setting the condition
2751 // code. We kludge this by pretending to read the condition code
2752 // 1 cycle earlier, and by marking the functional units as busy
2753 // for 2 cycles with the result available 1 cycle later than
2754 // is really the case.
2755 pipe_class ialu_reg_flags( iRegI op2_out, iRegI op2_in, iRegI op1, flagsReg cr ) %{
2756 single_instruction;
2757 op2_out : C(write);
2758 op1 : R(read);
2759 cr : R(read); // This is really E, with a 1 cycle stall
2760 BR : R(2);
2761 MS : R(2);
2762 %}
2763
2764 // Integer ALU reg operation
2765 pipe_class ialu_move_reg_L_to_I(iRegI dst, iRegL src) %{
2766 single_instruction; may_have_no_code;
2767 dst : E(write);
2768 src : R(read);
2769 IALU : R;
2770 %}
2771 pipe_class ialu_move_reg_I_to_L(iRegL dst, iRegI src) %{
2772 single_instruction; may_have_no_code;
2773 dst : E(write);
2774 src : R(read);
2775 IALU : R;
2776 %}
2777
2778 // Two integer ALU reg operations
2779 pipe_class ialu_reg_2(iRegL dst, iRegL src) %{
2780 instruction_count(2);
2781 dst : E(write);
2782 src : R(read);
2783 A0 : R;
2784 A1 : R;
2785 %}
2786
2787 // Two integer ALU reg operations
2788 pipe_class ialu_move_reg_L_to_L(iRegL dst, iRegL src) %{
2789 instruction_count(2); may_have_no_code;
2790 dst : E(write);
2791 src : R(read);
2792 A0 : R;
2793 A1 : R;
2794 %}
2795
2796 // Integer ALU imm operation
2797 pipe_class ialu_imm(iRegI dst) %{
2798 single_instruction;
2799 dst : E(write);
2800 IALU : R;
2801 %}
2802
2803 pipe_class ialu_imm_n(iRegI dst) %{
2804 single_instruction;
2805 dst : E(write);
2806 IALU : R;
2807 %}
2808
2809 // Integer ALU reg-reg with carry operation
2810 pipe_class ialu_reg_reg_cy(iRegI dst, iRegI src1, iRegI src2, iRegI cy) %{
2811 single_instruction;
2812 dst : E(write);
2813 src1 : R(read);
2814 src2 : R(read);
2815 IALU : R;
2816 %}
2817
2818 // Integer ALU cc operation
2819 pipe_class ialu_cc(iRegI dst, flagsReg cc) %{
2820 single_instruction;
2821 dst : E(write);
2822 cc : R(read);
2823 IALU : R;
2824 %}
2825
2826 // Integer ALU cc / second IALU operation
2827 pipe_class ialu_reg_ialu( iRegI dst, iRegI src ) %{
2828 instruction_count(1); multiple_bundles;
2829 dst : E(write)+1;
2830 src : R(read);
2831 IALU : R;
2832 %}
2833
2834 // Integer ALU cc / second IALU operation
2835 pipe_class ialu_reg_reg_ialu( iRegI dst, iRegI p, iRegI q ) %{
2836 instruction_count(1); multiple_bundles;
2837 dst : E(write)+1;
2838 p : R(read);
2839 q : R(read);
2840 IALU : R;
2841 %}
2842
2843 // Integer ALU hi-lo-reg operation
2844 pipe_class ialu_hi_lo_reg(iRegI dst, immI src) %{
2845 instruction_count(1); multiple_bundles;
2846 dst : E(write)+1;
2847 IALU : R(2);
2848 %}
2849
2850 // Long Constant
2851 pipe_class loadConL( iRegL dst, immL src ) %{
2852 instruction_count(2); multiple_bundles;
2853 dst : E(write)+1;
2854 IALU : R(2);
2855 IALU : R(2);
2856 %}
2857
2858 // Pointer Constant
2859 pipe_class loadConP( iRegP dst, immP src ) %{
2860 instruction_count(0); multiple_bundles;
2861 fixed_latency(6);
2862 %}
2863
2864 // Long Constant small
2865 pipe_class loadConLlo( iRegL dst, immL src ) %{
2866 instruction_count(2);
2867 dst : E(write);
2868 IALU : R;
2869 IALU : R;
2870 %}
2871
2872 // [PHH] This is wrong for 64-bit. See LdImmF/D.
2873 pipe_class loadConFD(regF dst, immF src, iRegP tmp) %{
2874 instruction_count(1); multiple_bundles;
2875 src : R(read);
2876 dst : M(write)+1;
2877 IALU : R;
2878 MS : E;
2879 %}
2880
2881 // Integer ALU nop operation
2882 pipe_class ialu_nop() %{
2883 single_instruction;
2884 IALU : R;
2885 %}
2886
2887 // Integer ALU nop operation
2888 pipe_class ialu_nop_A0() %{
2889 single_instruction;
2890 A0 : R;
2891 %}
2892
2893 // Integer ALU nop operation
2894 pipe_class ialu_nop_A1() %{
2895 single_instruction;
2896 A1 : R;
2897 %}
2898
2899 // Integer Multiply reg-reg operation
2900 pipe_class imul_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{
2901 single_instruction;
2902 dst : E(write);
2903 src1 : R(read);
2904 src2 : R(read);
2905 MS : R(5);
2906 %}
2907
2908 pipe_class mulL_reg_reg(iRegL dst, iRegL src1, iRegL src2) %{
2909 single_instruction;
2910 dst : E(write)+4;
2911 src1 : R(read);
2912 src2 : R(read);
2913 MS : R(6);
2914 %}
2915
2916 // Integer Divide reg-reg
2917 pipe_class sdiv_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI temp, flagsReg cr) %{
2918 instruction_count(1); multiple_bundles;
2919 dst : E(write);
2920 temp : E(write);
2921 src1 : R(read);
2922 src2 : R(read);
2923 temp : R(read);
2924 MS : R(38);
2925 %}
2926
2927 // Long Divide
2928 pipe_class divL_reg_reg(iRegL dst, iRegL src1, iRegL src2) %{
2929 dst : E(write)+71;
2930 src1 : R(read);
2931 src2 : R(read)+1;
2932 MS : R(70);
2933 %}
2934
2935 // Floating Point Add Float
2936 pipe_class faddF_reg_reg(regF dst, regF src1, regF src2) %{
2937 single_instruction;
2938 dst : X(write);
2939 src1 : E(read);
2940 src2 : E(read);
2941 FA : R;
2942 %}
2943
2944 // Floating Point Add Double
2945 pipe_class faddD_reg_reg(regD dst, regD src1, regD src2) %{
2946 single_instruction;
2947 dst : X(write);
2948 src1 : E(read);
2949 src2 : E(read);
2950 FA : R;
2951 %}
2952
2953 // Floating Point Conditional Move based on integer flags
2954 pipe_class int_conditional_float_move (cmpOp cmp, flagsReg cr, regF dst, regF src) %{
2955 single_instruction;
2956 dst : X(write);
2957 src : E(read);
2958 cr : R(read);
2959 FA : R(2);
2960 BR : R(2);
2961 %}
2962
2963 // Floating Point Conditional Move based on integer flags
2964 pipe_class int_conditional_double_move (cmpOp cmp, flagsReg cr, regD dst, regD src) %{
2965 single_instruction;
2966 dst : X(write);
2967 src : E(read);
2968 cr : R(read);
2969 FA : R(2);
2970 BR : R(2);
2971 %}
2972
2973 // Floating Point Multiply Float
2974 pipe_class fmulF_reg_reg(regF dst, regF src1, regF src2) %{
2975 single_instruction;
2976 dst : X(write);
2977 src1 : E(read);
2978 src2 : E(read);
2979 FM : R;
2980 %}
2981
2982 // Floating Point Multiply Double
2983 pipe_class fmulD_reg_reg(regD dst, regD src1, regD src2) %{
2984 single_instruction;
2985 dst : X(write);
2986 src1 : E(read);
2987 src2 : E(read);
2988 FM : R;
2989 %}
2990
2991 // Floating Point Divide Float
2992 pipe_class fdivF_reg_reg(regF dst, regF src1, regF src2) %{
2993 single_instruction;
2994 dst : X(write);
2995 src1 : E(read);
2996 src2 : E(read);
2997 FM : R;
2998 FDIV : C(14);
2999 %}
3000
3001 // Floating Point Divide Double
3002 pipe_class fdivD_reg_reg(regD dst, regD src1, regD src2) %{
3003 single_instruction;
3004 dst : X(write);
3005 src1 : E(read);
3006 src2 : E(read);
3007 FM : R;
3008 FDIV : C(17);
3009 %}
3010
3011 // Floating Point Move/Negate/Abs Float
3012 pipe_class faddF_reg(regF dst, regF src) %{
3013 single_instruction;
3014 dst : W(write);
3015 src : E(read);
3016 FA : R(1);
3017 %}
3018
3019 // Floating Point Move/Negate/Abs Double
3020 pipe_class faddD_reg(regD dst, regD src) %{
3021 single_instruction;
3022 dst : W(write);
3023 src : E(read);
3024 FA : R;
3025 %}
3026
3027 // Floating Point Convert F->D
3028 pipe_class fcvtF2D(regD dst, regF src) %{
3029 single_instruction;
3030 dst : X(write);
3031 src : E(read);
3032 FA : R;
3033 %}
3034
3035 // Floating Point Convert I->D
3036 pipe_class fcvtI2D(regD dst, regF src) %{
3037 single_instruction;
3038 dst : X(write);
3039 src : E(read);
3040 FA : R;
3041 %}
3042
3043 // Floating Point Convert LHi->D
3044 pipe_class fcvtLHi2D(regD dst, regD src) %{
3045 single_instruction;
3046 dst : X(write);
3047 src : E(read);
3048 FA : R;
3049 %}
3050
3051 // Floating Point Convert L->D
3052 pipe_class fcvtL2D(regD dst, iRegL src) %{
3053 single_instruction;
3054 dst : X(write);
3055 src : E(read);
3056 FA : R;
3057 %}
3058
3059 // Floating Point Convert L->F
3060 pipe_class fcvtL2F(regF dst, iRegL src) %{
3061 single_instruction;
3062 dst : X(write);
3063 src : E(read);
3064 FA : R;
3065 %}
3066
3067 // Floating Point Convert D->F
3068 pipe_class fcvtD2F(regD dst, regF src) %{
3069 single_instruction;
3070 dst : X(write);
3071 src : E(read);
3072 FA : R;
3073 %}
3074
3075 // Floating Point Convert I->L
3076 pipe_class fcvtI2L(regD dst, regF src) %{
3077 single_instruction;
3078 dst : X(write);
3079 src : E(read);
3080 FA : R;
3081 %}
3082
3083 // Floating Point Convert D->F
3084 pipe_class fcvtD2I(iRegI dst, regD src, flagsReg cr) %{
3085 instruction_count(1); multiple_bundles;
3086 dst : X(write)+6;
3087 src : E(read);
3088 FA : R;
3089 %}
3090
3091 // Floating Point Convert D->L
3092 pipe_class fcvtD2L(regD dst, regD src, flagsReg cr) %{
3093 instruction_count(1); multiple_bundles;
3094 dst : X(write)+6;
3095 src : E(read);
3096 FA : R;
3097 %}
3098
3099 // Floating Point Convert F->I
3100 pipe_class fcvtF2I(regF dst, regF src, flagsReg cr) %{
3101 instruction_count(1); multiple_bundles;
3102 dst : X(write)+6;
3103 src : E(read);
3104 FA : R;
3105 %}
3106
3107 // Floating Point Convert F->L
3108 pipe_class fcvtF2L(regD dst, regF src, flagsReg cr) %{
3109 instruction_count(1); multiple_bundles;
3110 dst : X(write)+6;
3111 src : E(read);
3112 FA : R;
3113 %}
3114
3115 // Floating Point Convert I->F
3116 pipe_class fcvtI2F(regF dst, regF src) %{
3117 single_instruction;
3118 dst : X(write);
3119 src : E(read);
3120 FA : R;
3121 %}
3122
3123 // Floating Point Compare
3124 pipe_class faddF_fcc_reg_reg_zero(flagsRegF cr, regF src1, regF src2, immI0 zero) %{
3125 single_instruction;
3126 cr : X(write);
3127 src1 : E(read);
3128 src2 : E(read);
3129 FA : R;
3130 %}
3131
3132 // Floating Point Compare
3133 pipe_class faddD_fcc_reg_reg_zero(flagsRegF cr, regD src1, regD src2, immI0 zero) %{
3134 single_instruction;
3135 cr : X(write);
3136 src1 : E(read);
3137 src2 : E(read);
3138 FA : R;
3139 %}
3140
3141 // Floating Add Nop
3142 pipe_class fadd_nop() %{
3143 single_instruction;
3144 FA : R;
3145 %}
3146
3147 // Integer Store to Memory
3148 pipe_class istore_mem_reg(memoryI mem, iRegI src) %{
3149 single_instruction;
3150 mem : R(read);
3151 src : C(read);
3152 MS : R;
3153 %}
3154
3155 // Integer Store to Memory
3156 pipe_class istore_mem_spORreg(memoryI mem, sp_ptr_RegP src) %{
3157 single_instruction;
3158 mem : R(read);
3159 src : C(read);
3160 MS : R;
3161 %}
3162
3163 // Float Store
3164 pipe_class fstoreF_mem_reg(memoryF mem, RegF src) %{
3165 single_instruction;
3166 mem : R(read);
3167 src : C(read);
3168 MS : R;
3169 %}
3170
3171 // Float Store
3172 pipe_class fstoreF_mem_zero(memoryF mem, immF0 src) %{
3173 single_instruction;
3174 mem : R(read);
3175 MS : R;
3176 %}
3177
3178 // Double Store
3179 pipe_class fstoreD_mem_reg(memoryD mem, RegD src) %{
3180 instruction_count(1);
3181 mem : R(read);
3182 src : C(read);
3183 MS : R;
3184 %}
3185
3186 // Double Store
3187 pipe_class fstoreD_mem_zero(memoryD mem, immD0 src) %{
3188 single_instruction;
3189 mem : R(read);
3190 MS : R;
3191 %}
3192
3193 // Integer Load (when sign bit propagation not needed)
3194 pipe_class iload_mem(iRegI dst, memoryI mem) %{
3195 single_instruction;
3196 mem : R(read);
3197 dst : C(write);
3198 MS : R;
3199 %}
3200
3201 // Integer Load (when sign bit propagation or masking is needed)
3202 pipe_class iload_mask_mem(iRegI dst, memoryI mem) %{
3203 single_instruction;
3204 mem : R(read);
3205 dst : M(write);
3206 MS : R;
3207 %}
3208
3209 // Float Load
3210 pipe_class floadF_mem(regF dst, memoryF mem) %{
3211 single_instruction;
3212 mem : R(read);
3213 dst : M(write);
3214 MS : R;
3215 %}
3216
3217 // Float Load
3218 pipe_class floadD_mem(regD dst, memoryD mem) %{
3219 instruction_count(1); multiple_bundles; // Again, unaligned argument is only multiple case
3220 mem : R(read);
3221 dst : M(write);
3222 MS : R;
3223 %}
3224
3225 // Memory Nop
3226 pipe_class mem_nop() %{
3227 single_instruction;
3228 MS : R;
3229 %}
3230
3231 pipe_class sethi(iRegP dst, immI src) %{
3232 single_instruction;
3233 dst : E(write);
3234 IALU : R;
3235 %}
3236
3237 pipe_class loadPollP(iRegP poll) %{
3238 single_instruction;
3239 poll : R(read);
3240 MS : R;
3241 %}
3242
3243 pipe_class br(Universe br, label labl) %{
3244 single_instruction;
3245 BR : R;
3246 %}
3247
3248 pipe_class br_cc(Universe br, cmpOp cmp, flagsReg cr, label labl) %{
3249 single_instruction;
3250 cr : E(read);
3251 BR : R;
3252 %}
3253
3254 pipe_class br_reg(Universe br, cmpOp cmp, iRegI op1, label labl) %{
3255 single_instruction;
3256 op1 : E(read);
3257 BR : R;
3258 MS : R;
3259 %}
3260
3261 pipe_class br_nop() %{
3262 single_instruction;
3263 BR : R;
3264 %}
3265
3266 pipe_class simple_call(method meth) %{
3267 instruction_count(2); multiple_bundles; force_serialization;
3268 fixed_latency(100);
3269 BR : R(1);
3270 MS : R(1);
3271 A0 : R(1);
3272 %}
3273
3274 pipe_class compiled_call(method meth) %{
3275 instruction_count(1); multiple_bundles; force_serialization;
3276 fixed_latency(100);
3277 MS : R(1);
3278 %}
3279
3280 pipe_class call(method meth) %{
3281 instruction_count(0); multiple_bundles; force_serialization;
3282 fixed_latency(100);
3283 %}
3284
3285 pipe_class tail_call(Universe ignore, label labl) %{
3286 single_instruction;
3287 fixed_latency(100);
3288 BR : R(1);
3289 MS : R(1);
3290 %}
3291
3292 pipe_class ret(Universe ignore) %{
3293 single_instruction;
3294 BR : R(1);
3295 MS : R(1);
3296 %}
3297
3298 // The real do-nothing guy
3299 pipe_class empty( ) %{
3300 instruction_count(0);
3301 %}
3302
3303 pipe_class long_memory_op() %{
3304 instruction_count(0); multiple_bundles; force_serialization;
3305 fixed_latency(25);
3306 MS : R(1);
3307 %}
3308
3309 // Check-cast
3310 pipe_class partial_subtype_check_pipe(Universe ignore, iRegP array, iRegP match ) %{
3311 array : R(read);
3312 match : R(read);
3313 IALU : R(2);
3314 BR : R(2);
3315 MS : R;
3316 %}
3317
3318 // Convert FPU flags into +1,0,-1
3319 pipe_class floating_cmp( iRegI dst, regF src1, regF src2 ) %{
3320 src1 : E(read);
3321 src2 : E(read);
3322 dst : E(write);
3323 FA : R;
3324 MS : R(2);
3325 BR : R(2);
3326 %}
3327
3328 // Compare for p < q, and conditionally add y
3329 pipe_class cadd_cmpltmask( iRegI p, iRegI q, iRegI y ) %{
3330 p : E(read);
3331 q : E(read);
3332 y : E(read);
3333 IALU : R(3)
3334 %}
3335
3336 // Define the class for the Nop node
3337 define %{
3338 MachNop = ialu_nop;
3339 %}
3340
3341 %}
3342
3343 //----------INSTRUCTIONS-------------------------------------------------------
3344
3345 //------------Special Nop instructions for bundling - no match rules-----------
3346 // Nop using the A0 functional unit
3347 instruct Nop_A0() %{
3348 ins_pipe(ialu_nop_A0);
3349 %}
3350
3351 // Nop using the A1 functional unit
3352 instruct Nop_A1( ) %{
3353 ins_pipe(ialu_nop_A1);
3354 %}
3355
3356 // Nop using the memory functional unit
3357 instruct Nop_MS( ) %{
3358 ins_pipe(mem_nop);
3359 %}
3360
3361 // Nop using the floating add functional unit
3362 instruct Nop_FA( ) %{
3363 ins_pipe(fadd_nop);
3364 %}
3365
3366 // Nop using the branch functional unit
3367 instruct Nop_BR( ) %{
3368 ins_pipe(br_nop);
3369 %}
3370
3371 //----------Load/Store/Move Instructions---------------------------------------
3372 //----------Load Instructions--------------------------------------------------
3373 // Load Byte (8bit signed)
3374 instruct loadB(iRegI dst, memoryB mem) %{
3375 match(Set dst (LoadB mem));
3376 ins_cost(MEMORY_REF_COST);
3377
3378 size(4);
3379 format %{ "LDRSB $dst,$mem\t! byte -> int" %}
3380 ins_encode %{
3381 __ ldrsb($dst$$Register, $mem$$Address);
3382 %}
3383 ins_pipe(iload_mask_mem);
3384 %}
3385
3386 // Load Byte (8bit signed) into a Long Register
3387 instruct loadB2L(iRegL dst, memoryB mem) %{
3388 match(Set dst (ConvI2L (LoadB mem)));
3389 ins_cost(MEMORY_REF_COST);
3390
3391 size(8);
3392 format %{ "LDRSB $dst.lo,$mem\t! byte -> long\n\t"
3393 "ASR $dst.hi,$dst.lo,31" %}
3394 ins_encode %{
3395 __ ldrsb($dst$$Register, $mem$$Address);
3396 __ mov($dst$$Register->successor(), AsmOperand($dst$$Register, asr, 31));
3397 %}
3398 ins_pipe(iload_mask_mem);
3399 %}
3400
3401 // Load Unsigned Byte (8bit UNsigned) into an int reg
3402 instruct loadUB(iRegI dst, memoryB mem) %{
3403 match(Set dst (LoadUB mem));
3404 ins_cost(MEMORY_REF_COST);
3405
3406 size(4);
3407 format %{ "LDRB $dst,$mem\t! ubyte -> int" %}
3408 ins_encode %{
3409 __ ldrb($dst$$Register, $mem$$Address);
3410 %}
3411 ins_pipe(iload_mem);
3412 %}
3413
3414 // Load Unsigned Byte (8bit UNsigned) into a Long Register
3415 instruct loadUB2L(iRegL dst, memoryB mem) %{
3416 match(Set dst (ConvI2L (LoadUB mem)));
3417 ins_cost(MEMORY_REF_COST);
3418
3419 size(8);
3420 format %{ "LDRB $dst.lo,$mem\t! ubyte -> long\n\t"
3421 "MOV $dst.hi,0" %}
3422 ins_encode %{
3423 __ ldrb($dst$$Register, $mem$$Address);
3424 __ mov($dst$$Register->successor(), 0);
3425 %}
3426 ins_pipe(iload_mem);
3427 %}
3428
3429 // Load Unsigned Byte (8 bit UNsigned) with immediate mask into Long Register
3430 instruct loadUB2L_limmI(iRegL dst, memoryB mem, limmIlow8 mask) %{
3431 match(Set dst (ConvI2L (AndI (LoadUB mem) mask)));
3432
3433 ins_cost(MEMORY_REF_COST + 2*DEFAULT_COST);
3434 size(12);
3435 format %{ "LDRB $dst.lo,$mem\t! ubyte -> long\n\t"
3436 "MOV $dst.hi,0\n\t"
3437 "AND $dst.lo,$dst.lo,$mask" %}
3438 ins_encode %{
3439 __ ldrb($dst$$Register, $mem$$Address);
3440 __ mov($dst$$Register->successor(), 0);
3441 __ andr($dst$$Register, $dst$$Register, limmI_low($mask$$constant, 8));
3442 %}
3443 ins_pipe(iload_mem);
3444 %}
3445
3446 // Load Short (16bit signed)
3447
3448 instruct loadS(iRegI dst, memoryS mem) %{
3449 match(Set dst (LoadS mem));
3450 ins_cost(MEMORY_REF_COST);
3451
3452 size(4);
3453 format %{ "LDRSH $dst,$mem\t! short" %}
3454 ins_encode %{
3455 __ ldrsh($dst$$Register, $mem$$Address);
3456 %}
3457 ins_pipe(iload_mask_mem);
3458 %}
3459
3460 // Load Short (16 bit signed) to Byte (8 bit signed)
3461 instruct loadS2B(iRegI dst, memoryS mem, immI_24 twentyfour) %{
3462 match(Set dst (RShiftI (LShiftI (LoadS mem) twentyfour) twentyfour));
3463 ins_cost(MEMORY_REF_COST);
3464
3465 size(4);
3466
3467 format %{ "LDRSB $dst,$mem\t! short -> byte" %}
3468 ins_encode %{
3469 __ ldrsb($dst$$Register, $mem$$Address);
3470 %}
3471 ins_pipe(iload_mask_mem);
3472 %}
3473
3474 // Load Short (16bit signed) into a Long Register
3475 instruct loadS2L(iRegL dst, memoryS mem) %{
3476 match(Set dst (ConvI2L (LoadS mem)));
3477 ins_cost(MEMORY_REF_COST);
3478
3479 size(8);
3480 format %{ "LDRSH $dst.lo,$mem\t! short -> long\n\t"
3481 "ASR $dst.hi,$dst.lo,31" %}
3482 ins_encode %{
3483 __ ldrsh($dst$$Register, $mem$$Address);
3484 __ mov($dst$$Register->successor(), AsmOperand($dst$$Register, asr, 31));
3485 %}
3486 ins_pipe(iload_mask_mem);
3487 %}
3488
3489 // Load Unsigned Short/Char (16bit UNsigned)
3490
3491
3492 instruct loadUS(iRegI dst, memoryS mem) %{
3493 match(Set dst (LoadUS mem));
3494 ins_cost(MEMORY_REF_COST);
3495
3496 size(4);
3497 format %{ "LDRH $dst,$mem\t! ushort/char" %}
3498 ins_encode %{
3499 __ ldrh($dst$$Register, $mem$$Address);
3500 %}
3501 ins_pipe(iload_mem);
3502 %}
3503
3504 // Load Unsigned Short/Char (16 bit UNsigned) to Byte (8 bit signed)
3505 instruct loadUS2B(iRegI dst, memoryB mem, immI_24 twentyfour) %{
3506 match(Set dst (RShiftI (LShiftI (LoadUS mem) twentyfour) twentyfour));
3507 ins_cost(MEMORY_REF_COST);
3508
3509 size(4);
3510 format %{ "LDRSB $dst,$mem\t! ushort -> byte" %}
3511 ins_encode %{
3512 __ ldrsb($dst$$Register, $mem$$Address);
3513 %}
3514 ins_pipe(iload_mask_mem);
3515 %}
3516
3517 // Load Unsigned Short/Char (16bit UNsigned) into a Long Register
3518 instruct loadUS2L(iRegL dst, memoryS mem) %{
3519 match(Set dst (ConvI2L (LoadUS mem)));
3520 ins_cost(MEMORY_REF_COST);
3521
3522 size(8);
3523 format %{ "LDRH $dst.lo,$mem\t! short -> long\n\t"
3524 "MOV $dst.hi, 0" %}
3525 ins_encode %{
3526 __ ldrh($dst$$Register, $mem$$Address);
3527 __ mov($dst$$Register->successor(), 0);
3528 %}
3529 ins_pipe(iload_mem);
3530 %}
3531
3532 // Load Unsigned Short/Char (16bit UNsigned) with mask 0xFF into a Long Register
3533 instruct loadUS2L_immI_255(iRegL dst, memoryB mem, immI_255 mask) %{
3534 match(Set dst (ConvI2L (AndI (LoadUS mem) mask)));
3535 ins_cost(MEMORY_REF_COST);
3536
3537 size(8);
3538 format %{ "LDRB $dst.lo,$mem\t! \n\t"
3539 "MOV $dst.hi, 0" %}
3540 ins_encode %{
3541 __ ldrb($dst$$Register, $mem$$Address);
3542 __ mov($dst$$Register->successor(), 0);
3543 %}
3544 ins_pipe(iload_mem);
3545 %}
3546
3547 // Load Unsigned Short/Char (16bit UNsigned) with a immediate mask into a Long Register
3548 instruct loadUS2L_limmI(iRegL dst, memoryS mem, limmI mask) %{
3549 match(Set dst (ConvI2L (AndI (LoadUS mem) mask)));
3550 ins_cost(MEMORY_REF_COST + 2*DEFAULT_COST);
3551
3552 size(12);
3553 format %{ "LDRH $dst,$mem\t! ushort/char & mask -> long\n\t"
3554 "MOV $dst.hi, 0\n\t"
3555 "AND $dst,$dst,$mask" %}
3556 ins_encode %{
3557 __ ldrh($dst$$Register, $mem$$Address);
3558 __ mov($dst$$Register->successor(), 0);
3559 __ andr($dst$$Register, $dst$$Register, $mask$$constant);
3560 %}
3561 ins_pipe(iload_mem);
3562 %}
3563
3564 // Load Integer
3565
3566
3567 instruct loadI(iRegI dst, memoryI mem) %{
3568 match(Set dst (LoadI mem));
3569 ins_cost(MEMORY_REF_COST);
3570
3571 size(4);
3572 format %{ "ldr_s32 $dst,$mem\t! int" %}
3573 ins_encode %{
3574 __ ldr_s32($dst$$Register, $mem$$Address);
3575 %}
3576 ins_pipe(iload_mem);
3577 %}
3578
3579 // Load Integer to Byte (8 bit signed)
3580 instruct loadI2B(iRegI dst, memoryS mem, immI_24 twentyfour) %{
3581 match(Set dst (RShiftI (LShiftI (LoadI mem) twentyfour) twentyfour));
3582 ins_cost(MEMORY_REF_COST);
3583
3584 size(4);
3585
3586 format %{ "LDRSB $dst,$mem\t! int -> byte" %}
3587 ins_encode %{
3588 __ ldrsb($dst$$Register, $mem$$Address);
3589 %}
3590 ins_pipe(iload_mask_mem);
3591 %}
3592
3593 // Load Integer to Unsigned Byte (8 bit UNsigned)
3594 instruct loadI2UB(iRegI dst, memoryB mem, immI_255 mask) %{
3595 match(Set dst (AndI (LoadI mem) mask));
3596 ins_cost(MEMORY_REF_COST);
3597
3598 size(4);
3599
3600 format %{ "LDRB $dst,$mem\t! int -> ubyte" %}
3601 ins_encode %{
3602 __ ldrb($dst$$Register, $mem$$Address);
3603 %}
3604 ins_pipe(iload_mask_mem);
3605 %}
3606
3607 // Load Integer to Short (16 bit signed)
3608 instruct loadI2S(iRegI dst, memoryS mem, immI_16 sixteen) %{
3609 match(Set dst (RShiftI (LShiftI (LoadI mem) sixteen) sixteen));
3610 ins_cost(MEMORY_REF_COST);
3611
3612 size(4);
3613 format %{ "LDRSH $dst,$mem\t! int -> short" %}
3614 ins_encode %{
3615 __ ldrsh($dst$$Register, $mem$$Address);
3616 %}
3617 ins_pipe(iload_mask_mem);
3618 %}
3619
3620 // Load Integer to Unsigned Short (16 bit UNsigned)
3621 instruct loadI2US(iRegI dst, memoryS mem, immI_65535 mask) %{
3622 match(Set dst (AndI (LoadI mem) mask));
3623 ins_cost(MEMORY_REF_COST);
3624
3625 size(4);
3626 format %{ "LDRH $dst,$mem\t! int -> ushort/char" %}
3627 ins_encode %{
3628 __ ldrh($dst$$Register, $mem$$Address);
3629 %}
3630 ins_pipe(iload_mask_mem);
3631 %}
3632
3633 // Load Integer into a Long Register
3634 instruct loadI2L(iRegL dst, memoryI mem) %{
3635 match(Set dst (ConvI2L (LoadI mem)));
3636 ins_cost(MEMORY_REF_COST);
3637
3638 size(8);
3639 format %{ "LDR $dst.lo,$mem\t! int -> long\n\t"
3640 "ASR $dst.hi,$dst.lo,31\t! int->long" %}
3641 ins_encode %{
3642 __ ldr($dst$$Register, $mem$$Address);
3643 __ mov($dst$$Register->successor(), AsmOperand($dst$$Register, asr, 31));
3644 %}
3645 ins_pipe(iload_mask_mem);
3646 %}
3647
3648 // Load Integer with mask 0xFF into a Long Register
3649 instruct loadI2L_immI_255(iRegL dst, memoryB mem, immI_255 mask) %{
3650 match(Set dst (ConvI2L (AndI (LoadI mem) mask)));
3651 ins_cost(MEMORY_REF_COST);
3652
3653 size(8);
3654 format %{ "LDRB $dst.lo,$mem\t! int & 0xFF -> long\n\t"
3655 "MOV $dst.hi, 0" %}
3656 ins_encode %{
3657 __ ldrb($dst$$Register, $mem$$Address);
3658 __ mov($dst$$Register->successor(), 0);
3659 %}
3660 ins_pipe(iload_mem);
3661 %}
3662
3663 // Load Integer with mask 0xFFFF into a Long Register
3664 instruct loadI2L_immI_65535(iRegL dst, memoryS mem, immI_65535 mask) %{
3665 match(Set dst (ConvI2L (AndI (LoadI mem) mask)));
3666 ins_cost(MEMORY_REF_COST);
3667
3668 size(8);
3669 format %{ "LDRH $dst,$mem\t! int & 0xFFFF -> long\n\t"
3670 "MOV $dst.hi, 0" %}
3671 ins_encode %{
3672 __ ldrh($dst$$Register, $mem$$Address);
3673 __ mov($dst$$Register->successor(), 0);
3674 %}
3675 ins_pipe(iload_mask_mem);
3676 %}
3677
3678 // Load Integer with a 31-bit immediate mask into a Long Register
3679 instruct loadI2L_limmU31(iRegL dst, memoryI mem, limmU31 mask) %{
3680 match(Set dst (ConvI2L (AndI (LoadI mem) mask)));
3681 ins_cost(MEMORY_REF_COST + 2*DEFAULT_COST);
3682
3683 size(12);
3684 format %{ "LDR $dst.lo,$mem\t! int -> long\n\t"
3685 "MOV $dst.hi, 0\n\t"
3686 "AND $dst,$dst,$mask" %}
3687
3688 ins_encode %{
3689 __ ldr($dst$$Register, $mem$$Address);
3690 __ mov($dst$$Register->successor(), 0);
3691 __ andr($dst$$Register, $dst$$Register, $mask$$constant);
3692 %}
3693 ins_pipe(iload_mem);
3694 %}
3695
3696 // Load Integer with a 31-bit mask into a Long Register
3697 // FIXME: use iRegI mask, remove tmp?
3698 instruct loadI2L_immU31(iRegL dst, memoryI mem, immU31 mask, iRegI tmp) %{
3699 match(Set dst (ConvI2L (AndI (LoadI mem) mask)));
3700 effect(TEMP dst, TEMP tmp);
3701
3702 ins_cost(MEMORY_REF_COST + 4*DEFAULT_COST);
3703 size(20);
3704 format %{ "LDR $mem,$dst\t! int & 31-bit mask -> long\n\t"
3705 "MOV $dst.hi, 0\n\t"
3706 "MOV_SLOW $tmp,$mask\n\t"
3707 "AND $dst,$tmp,$dst" %}
3708 ins_encode %{
3709 __ ldr($dst$$Register, $mem$$Address);
3710 __ mov($dst$$Register->successor(), 0);
3711 __ mov_slow($tmp$$Register, $mask$$constant);
3712 __ andr($dst$$Register, $dst$$Register, $tmp$$Register);
3713 %}
3714 ins_pipe(iload_mem);
3715 %}
3716
3717 // Load Unsigned Integer into a Long Register
3718 instruct loadUI2L(iRegL dst, memoryI mem, immL_32bits mask) %{
3719 match(Set dst (AndL (ConvI2L (LoadI mem)) mask));
3720 ins_cost(MEMORY_REF_COST);
3721
3722 size(8);
3723 format %{ "LDR $dst.lo,$mem\t! uint -> long\n\t"
3724 "MOV $dst.hi,0" %}
3725 ins_encode %{
3726 __ ldr($dst$$Register, $mem$$Address);
3727 __ mov($dst$$Register->successor(), 0);
3728 %}
3729 ins_pipe(iload_mem);
3730 %}
3731
3732 // Load Long
3733
3734
3735 instruct loadL(iRegLd dst, memoryL mem ) %{
3736 predicate(!((LoadLNode*)n)->require_atomic_access());
3737 match(Set dst (LoadL mem));
3738 effect(TEMP dst);
3739 ins_cost(MEMORY_REF_COST);
3740
3741 size(4);
3742 format %{ "ldr_64 $dst,$mem\t! long" %}
3743 ins_encode %{
3744 __ ldr_64($dst$$Register, $mem$$Address);
3745 %}
3746 ins_pipe(iload_mem);
3747 %}
3748
3749 instruct loadL_2instr(iRegL dst, memorylong mem ) %{
3750 predicate(!((LoadLNode*)n)->require_atomic_access());
3751 match(Set dst (LoadL mem));
3752 ins_cost(MEMORY_REF_COST + DEFAULT_COST);
3753
3754 size(8);
3755 format %{ "LDR $dst.lo,$mem \t! long order of instrs reversed if $dst.lo == base($mem)\n\t"
3756 "LDR $dst.hi,$mem+4 or $mem" %}
3757 ins_encode %{
3758 Address Amemlo = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none);
3759 Address Amemhi = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp + 4, relocInfo::none);
3760
3761 if ($dst$$Register == reg_to_register_object($mem$$base)) {
3762 __ ldr($dst$$Register->successor(), Amemhi);
3763 __ ldr($dst$$Register, Amemlo);
3764 } else {
3765 __ ldr($dst$$Register, Amemlo);
3766 __ ldr($dst$$Register->successor(), Amemhi);
3767 }
3768 %}
3769 ins_pipe(iload_mem);
3770 %}
3771
3772 instruct loadL_volatile(iRegL dst, indirect mem ) %{
3773 predicate(((LoadLNode*)n)->require_atomic_access());
3774 match(Set dst (LoadL mem));
3775 ins_cost(MEMORY_REF_COST);
3776
3777 size(4);
3778 format %{ "LDMIA $dst,$mem\t! long" %}
3779 ins_encode %{
3780 // FIXME: why is ldmia considered atomic? Should be ldrexd
3781 RegisterSet set($dst$$Register);
3782 set = set | reg_to_register_object($dst$$reg + 1);
3783 __ ldmia(reg_to_register_object($mem$$base), set);
3784 %}
3785 ins_pipe(iload_mem);
3786 %}
3787
3788 instruct loadL_volatile_fp(iRegL dst, memoryD mem ) %{
3789 predicate(((LoadLNode*)n)->require_atomic_access());
3790 match(Set dst (LoadL mem));
3791 ins_cost(MEMORY_REF_COST);
3792
3793 size(8);
3794 format %{ "FLDD S14, $mem"
3795 "FMRRD $dst, S14\t! long \n't" %}
3796 ins_encode %{
3797 __ fldd(S14, $mem$$Address);
3798 __ fmrrd($dst$$Register, $dst$$Register->successor(), S14);
3799 %}
3800 ins_pipe(iload_mem);
3801 %}
3802
3803 instruct loadL_unaligned(iRegL dst, memorylong mem ) %{
3804 match(Set dst (LoadL_unaligned mem));
3805 ins_cost(MEMORY_REF_COST);
3806
3807 size(8);
3808 format %{ "LDR $dst.lo,$mem\t! long order of instrs reversed if $dst.lo == base($mem)\n\t"
3809 "LDR $dst.hi,$mem+4" %}
3810 ins_encode %{
3811 Address Amemlo = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none);
3812 Address Amemhi = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp + 4, relocInfo::none);
3813
3814 if ($dst$$Register == reg_to_register_object($mem$$base)) {
3815 __ ldr($dst$$Register->successor(), Amemhi);
3816 __ ldr($dst$$Register, Amemlo);
3817 } else {
3818 __ ldr($dst$$Register, Amemlo);
3819 __ ldr($dst$$Register->successor(), Amemhi);
3820 }
3821 %}
3822 ins_pipe(iload_mem);
3823 %}
3824
3825 // Load Range
3826 instruct loadRange(iRegI dst, memoryI mem) %{
3827 match(Set dst (LoadRange mem));
3828 ins_cost(MEMORY_REF_COST);
3829
3830 size(4);
3831 format %{ "LDR_u32 $dst,$mem\t! range" %}
3832 ins_encode %{
3833 __ ldr_u32($dst$$Register, $mem$$Address);
3834 %}
3835 ins_pipe(iload_mem);
3836 %}
3837
3838 // Load Pointer
3839
3840
3841 instruct loadP(iRegP dst, memoryP mem) %{
3842 predicate(!(UseG1GC && n->as_Load()->barrier_data() != 0));
3843 match(Set dst (LoadP mem));
3844 ins_cost(MEMORY_REF_COST);
3845 size(4);
3846
3847 format %{ "LDR $dst,$mem\t! ptr" %}
3848 ins_encode %{
3849 __ ldr($dst$$Register, $mem$$Address);
3850 %}
3851 ins_pipe(iload_mem);
3852 %}
3853
3854 #ifdef XXX
3855 // FIXME XXXX
3856 //instruct loadSP(iRegP dst, memoryP mem) %{
3857 instruct loadSP(SPRegP dst, memoryP mem, iRegP tmp) %{
3858 match(Set dst (LoadP mem));
3859 effect(TEMP tmp);
3860 ins_cost(MEMORY_REF_COST+1);
3861 size(8);
3862
3863 format %{ "LDR $tmp,$mem\t! ptr\n\t"
3864 "MOV $dst,$tmp\t! ptr" %}
3865 ins_encode %{
3866 __ ldr($tmp$$Register, $mem$$Address);
3867 __ mov($dst$$Register, $tmp$$Register);
3868 %}
3869 ins_pipe(iload_mem);
3870 %}
3871 #endif
3872
3873 #ifdef _LP64
3874 // Load Compressed Pointer
3875
3876 // XXX This variant shouldn't be necessary if 6217251 is implemented
3877 instruct loadNoff(iRegN dst, memoryScaledI mem, aimmX off, iRegP tmp) %{
3878 match(Set dst (LoadN (AddP mem off)));
3879 ins_cost(MEMORY_REF_COST + DEFAULT_COST); // assume shift/sign-extend is free
3880 effect(TEMP tmp);
3881 size(4 * 2);
3882
3883 format %{ "ldr_u32 $dst,$mem+$off\t! compressed ptr temp=$tmp" %}
3884 ins_encode %{
3885 Register base = reg_to_register_object($mem$$base);
3886 __ add($tmp$$Register, base, $off$$constant);
3887 Address nmem = Address::make_raw($tmp$$reg, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none);
3888 __ ldr_u32($dst$$Register, nmem);
3889 %}
3890 ins_pipe(iload_mem);
3891 %}
3892
3893 instruct loadN(iRegN dst, memoryI mem) %{
3894 match(Set dst (LoadN mem));
3895 ins_cost(MEMORY_REF_COST);
3896 size(4);
3897
3898 format %{ "ldr_u32 $dst,$mem\t! compressed ptr" %}
3899 ins_encode %{
3900 __ ldr_u32($dst$$Register, $mem$$Address);
3901 %}
3902 ins_pipe(iload_mem);
3903 %}
3904 #endif
3905
3906 // Load Klass Pointer
3907 instruct loadKlass(iRegP dst, memoryI mem) %{
3908 match(Set dst (LoadKlass mem));
3909 ins_cost(MEMORY_REF_COST);
3910 size(4);
3911
3912 format %{ "LDR $dst,$mem\t! klass ptr" %}
3913 ins_encode %{
3914 __ ldr($dst$$Register, $mem$$Address);
3915 %}
3916 ins_pipe(iload_mem);
3917 %}
3918
3919 #ifdef _LP64
3920 // Load narrow Klass Pointer
3921 instruct loadNKlass(iRegN dst, memoryI mem) %{
3922 match(Set dst (LoadNKlass mem));
3923 ins_cost(MEMORY_REF_COST);
3924 size(4);
3925
3926 format %{ "ldr_u32 $dst,$mem\t! compressed klass ptr" %}
3927 ins_encode %{
3928 __ ldr_u32($dst$$Register, $mem$$Address);
3929 %}
3930 ins_pipe(iload_mem);
3931 %}
3932 #endif
3933
3934
3935 instruct loadD(regD dst, memoryD mem) %{
3936 match(Set dst (LoadD mem));
3937 ins_cost(MEMORY_REF_COST);
3938
3939 size(4);
3940 // FIXME: needs to be atomic, but ARMv7 A.R.M. guarantees
3941 // only LDREXD and STREXD are 64-bit single-copy atomic
3942 format %{ "FLDD $dst,$mem" %}
3943 ins_encode %{
3944 __ ldr_double($dst$$FloatRegister, $mem$$Address);
3945 %}
3946 ins_pipe(floadD_mem);
3947 %}
3948
3949 // Load Double - UNaligned
3950 instruct loadD_unaligned(regD_low dst, memoryF2 mem ) %{
3951 match(Set dst (LoadD_unaligned mem));
3952 ins_cost(MEMORY_REF_COST*2+DEFAULT_COST);
3953 size(8);
3954 format %{ "FLDS $dst.lo,$mem\t! misaligned double\n"
3955 "\tFLDS $dst.hi,$mem+4\t!" %}
3956 ins_encode %{
3957 Address Amemlo = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none);
3958 Address Amemhi = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp + 4, relocInfo::none);
3959 __ flds($dst$$FloatRegister, Amemlo);
3960 __ flds($dst$$FloatRegister->successor(), Amemhi);
3961 %}
3962 ins_pipe(iload_mem);
3963 %}
3964
3965
3966 instruct loadF(regF dst, memoryF mem) %{
3967 match(Set dst (LoadF mem));
3968
3969 ins_cost(MEMORY_REF_COST);
3970 size(4);
3971 format %{ "FLDS $dst,$mem" %}
3972 ins_encode %{
3973 __ ldr_float($dst$$FloatRegister, $mem$$Address);
3974 %}
3975 ins_pipe(floadF_mem);
3976 %}
3977
3978
3979 // // Load Constant
3980 instruct loadConI( iRegI dst, immI src ) %{
3981 match(Set dst src);
3982 ins_cost(DEFAULT_COST * 3/2);
3983 format %{ "MOV_SLOW $dst, $src" %}
3984 ins_encode %{
3985 __ mov_slow($dst$$Register, $src$$constant);
3986 %}
3987 ins_pipe(ialu_hi_lo_reg);
3988 %}
3989
3990 instruct loadConIMov( iRegI dst, immIMov src ) %{
3991 match(Set dst src);
3992 size(4);
3993 format %{ "MOV $dst, $src" %}
3994 ins_encode %{
3995 __ mov($dst$$Register, $src$$constant);
3996 %}
3997 ins_pipe(ialu_imm);
3998 %}
3999
4000 instruct loadConIMovn( iRegI dst, immIRotn src ) %{
4001 match(Set dst src);
4002 size(4);
4003 format %{ "MVN $dst, ~$src" %}
4004 ins_encode %{
4005 __ mvn($dst$$Register, ~$src$$constant);
4006 %}
4007 ins_pipe(ialu_imm_n);
4008 %}
4009
4010 instruct loadConI16( iRegI dst, immI16 src ) %{
4011 match(Set dst src);
4012 size(4);
4013 format %{ "MOVW $dst, $src" %}
4014 ins_encode %{
4015 __ movw($dst$$Register, $src$$constant);
4016 %}
4017 ins_pipe(ialu_imm_n);
4018 %}
4019
4020 instruct loadConP(iRegP dst, immP src) %{
4021 match(Set dst src);
4022 ins_cost(DEFAULT_COST * 3/2);
4023 format %{ "MOV_SLOW $dst,$src\t!ptr" %}
4024 ins_encode %{
4025 relocInfo::relocType constant_reloc = _opnds[1]->constant_reloc();
4026 intptr_t val = $src$$constant;
4027 if (constant_reloc == relocInfo::oop_type) {
4028 __ mov_oop($dst$$Register, (jobject)val);
4029 } else if (constant_reloc == relocInfo::metadata_type) {
4030 __ mov_metadata($dst$$Register, (Metadata*)val);
4031 } else {
4032 __ mov_slow($dst$$Register, val);
4033 }
4034 %}
4035 ins_pipe(loadConP);
4036 %}
4037
4038
4039 instruct loadConL(iRegL dst, immL src) %{
4040 match(Set dst src);
4041 ins_cost(DEFAULT_COST * 4);
4042 format %{ "MOV_SLOW $dst.lo, $src & 0x0FFFFFFFFL \t! long\n\t"
4043 "MOV_SLOW $dst.hi, $src >> 32" %}
4044 ins_encode %{
4045 __ mov_slow(reg_to_register_object($dst$$reg), $src$$constant & 0x0FFFFFFFFL);
4046 __ mov_slow(reg_to_register_object($dst$$reg + 1), ((julong)($src$$constant)) >> 32);
4047 %}
4048 ins_pipe(loadConL);
4049 %}
4050
4051 instruct loadConL16( iRegL dst, immL16 src ) %{
4052 match(Set dst src);
4053 ins_cost(DEFAULT_COST * 2);
4054
4055 size(8);
4056 format %{ "MOVW $dst.lo, $src \n\t"
4057 "MOVW $dst.hi, 0 \n\t" %}
4058 ins_encode %{
4059 __ movw($dst$$Register, $src$$constant);
4060 __ movw($dst$$Register->successor(), 0);
4061 %}
4062 ins_pipe(ialu_imm);
4063 %}
4064
4065 instruct loadConF_imm8(regF dst, imm8F src) %{
4066 match(Set dst src);
4067 ins_cost(DEFAULT_COST);
4068 size(4);
4069
4070 format %{ "FCONSTS $dst, $src"%}
4071
4072 ins_encode %{
4073 __ fconsts($dst$$FloatRegister, Assembler::float_num($src$$constant).imm8());
4074 %}
4075 ins_pipe(loadConFD); // FIXME
4076 %}
4077
4078
4079 instruct loadConF(regF dst, immF src, iRegI tmp) %{
4080 match(Set dst src);
4081 ins_cost(DEFAULT_COST * 2);
4082 effect(TEMP tmp);
4083 size(3*4);
4084
4085 format %{ "MOV_SLOW $tmp, $src\n\t"
4086 "FMSR $dst, $tmp"%}
4087
4088 ins_encode %{
4089 // FIXME revisit once 6961697 is in
4090 union {
4091 jfloat f;
4092 int i;
4093 } v;
4094 v.f = $src$$constant;
4095 __ mov_slow($tmp$$Register, v.i);
4096 __ fmsr($dst$$FloatRegister, $tmp$$Register);
4097 %}
4098 ins_pipe(loadConFD); // FIXME
4099 %}
4100
4101 instruct loadConD_imm8(regD dst, imm8D src) %{
4102 match(Set dst src);
4103 ins_cost(DEFAULT_COST);
4104 size(4);
4105
4106 format %{ "FCONSTD $dst, $src"%}
4107
4108 ins_encode %{
4109 __ fconstd($dst$$FloatRegister, Assembler::double_num($src$$constant).imm8());
4110 %}
4111 ins_pipe(loadConFD); // FIXME
4112 %}
4113
4114 instruct loadConD(regD dst, immD src, iRegP tmp) %{
4115 match(Set dst src);
4116 effect(TEMP tmp);
4117 ins_cost(MEMORY_REF_COST);
4118 format %{ "FLDD $dst, [$constanttablebase + $constantoffset]\t! load from constant table: double=$src" %}
4119
4120 ins_encode %{
4121 Register r = $constanttablebase;
4122 int offset = $constantoffset($src);
4123 if (!is_memoryD(offset)) { // can't use a predicate
4124 // in load constant instructs
4125 __ add_slow($tmp$$Register, r, offset);
4126 r = $tmp$$Register;
4127 offset = 0;
4128 }
4129 __ ldr_double($dst$$FloatRegister, Address(r, offset));
4130 %}
4131 ins_pipe(loadConFD);
4132 %}
4133
4134 // Prefetch instructions.
4135 // Must be safe to execute with invalid address (cannot fault).
4136
4137 instruct prefetchAlloc_mp( memoryP mem ) %{
4138 predicate(VM_Version::has_multiprocessing_extensions());
4139 match( PrefetchAllocation mem );
4140 ins_cost(MEMORY_REF_COST);
4141 size(4);
4142
4143 format %{ "PLDW $mem\t! Prefetch allocation" %}
4144 ins_encode %{
4145 __ pldw($mem$$Address);
4146 %}
4147 ins_pipe(iload_mem);
4148 %}
4149
4150 instruct prefetchAlloc_sp( memoryP mem ) %{
4151 predicate(!VM_Version::has_multiprocessing_extensions());
4152 match( PrefetchAllocation mem );
4153 ins_cost(MEMORY_REF_COST);
4154 size(4);
4155
4156 format %{ "PLD $mem\t! Prefetch allocation" %}
4157 ins_encode %{
4158 __ pld($mem$$Address);
4159 %}
4160 ins_pipe(iload_mem);
4161 %}
4162
4163
4164 //----------Store Instructions-------------------------------------------------
4165 // Store Byte
4166 instruct storeB(memoryB mem, store_RegI src) %{
4167 match(Set mem (StoreB mem src));
4168 ins_cost(MEMORY_REF_COST);
4169
4170 size(4);
4171 format %{ "STRB $src,$mem\t! byte" %}
4172 ins_encode %{
4173 __ strb($src$$Register, $mem$$Address);
4174 %}
4175 ins_pipe(istore_mem_reg);
4176 %}
4177
4178 // Store Char/Short
4179
4180
4181 instruct storeC(memoryS mem, store_RegI src) %{
4182 match(Set mem (StoreC mem src));
4183 ins_cost(MEMORY_REF_COST);
4184
4185 size(4);
4186 format %{ "STRH $src,$mem\t! short" %}
4187 ins_encode %{
4188 __ strh($src$$Register, $mem$$Address);
4189 %}
4190 ins_pipe(istore_mem_reg);
4191 %}
4192
4193 // Store Integer
4194
4195
4196 instruct storeI(memoryI mem, store_RegI src) %{
4197 match(Set mem (StoreI mem src));
4198 ins_cost(MEMORY_REF_COST);
4199
4200 size(4);
4201 format %{ "str_32 $src,$mem" %}
4202 ins_encode %{
4203 __ str_32($src$$Register, $mem$$Address);
4204 %}
4205 ins_pipe(istore_mem_reg);
4206 %}
4207
4208 // Store Long
4209
4210
4211 instruct storeL(memoryL mem, store_RegLd src) %{
4212 predicate(!((StoreLNode*)n)->require_atomic_access());
4213 match(Set mem (StoreL mem src));
4214 ins_cost(MEMORY_REF_COST);
4215
4216 size(4);
4217 format %{ "str_64 $src,$mem\t! long\n\t" %}
4218
4219 ins_encode %{
4220 __ str_64($src$$Register, $mem$$Address);
4221 %}
4222 ins_pipe(istore_mem_reg);
4223 %}
4224
4225 instruct storeL_2instr(memorylong mem, iRegL src) %{
4226 predicate(!((StoreLNode*)n)->require_atomic_access());
4227 match(Set mem (StoreL mem src));
4228 ins_cost(MEMORY_REF_COST + DEFAULT_COST);
4229
4230 size(8);
4231 format %{ "STR $src.lo,$mem\t! long\n\t"
4232 "STR $src.hi,$mem+4" %}
4233
4234 ins_encode %{
4235 Address Amemlo = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none);
4236 Address Amemhi = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp + 4, relocInfo::none);
4237 __ str($src$$Register, Amemlo);
4238 __ str($src$$Register->successor(), Amemhi);
4239 %}
4240 ins_pipe(istore_mem_reg);
4241 %}
4242
4243 instruct storeL_volatile(indirect mem, iRegL src) %{
4244 predicate(((StoreLNode*)n)->require_atomic_access());
4245 match(Set mem (StoreL mem src));
4246 ins_cost(MEMORY_REF_COST);
4247 size(4);
4248 format %{ "STMIA $src,$mem\t! long" %}
4249 ins_encode %{
4250 // FIXME: why is stmia considered atomic? Should be strexd
4251 RegisterSet set($src$$Register);
4252 set = set | reg_to_register_object($src$$reg + 1);
4253 __ stmia(reg_to_register_object($mem$$base), set);
4254 %}
4255 ins_pipe(istore_mem_reg);
4256 %}
4257
4258 instruct storeL_volatile_fp(memoryD mem, iRegL src) %{
4259 predicate(((StoreLNode*)n)->require_atomic_access());
4260 match(Set mem (StoreL mem src));
4261 ins_cost(MEMORY_REF_COST);
4262 size(8);
4263 format %{ "FMDRR S14, $src\t! long \n\t"
4264 "FSTD S14, $mem" %}
4265 ins_encode %{
4266 __ fmdrr(S14, $src$$Register, $src$$Register->successor());
4267 __ fstd(S14, $mem$$Address);
4268 %}
4269 ins_pipe(istore_mem_reg);
4270 %}
4271
4272 #ifdef XXX
4273 // Move SP Pointer
4274 //instruct movSP(sp_ptr_RegP dst, SPRegP src) %{
4275 //instruct movSP(iRegP dst, SPRegP src) %{
4276 instruct movSP(store_ptr_RegP dst, SPRegP src) %{
4277 match(Set dst src);
4278 //predicate(!_kids[1]->_leaf->is_Proj() || _kids[1]->_leaf->as_Proj()->_con == TypeFunc::FramePtr);
4279 ins_cost(MEMORY_REF_COST);
4280 size(4);
4281
4282 format %{ "MOV $dst,$src\t! SP ptr\n\t" %}
4283 ins_encode %{
4284 assert(false, "XXX1 got here");
4285 __ mov($dst$$Register, SP);
4286 __ mov($dst$$Register, $src$$Register);
4287 %}
4288 ins_pipe(ialu_reg);
4289 %}
4290 #endif
4291
4292
4293 // Store Pointer
4294
4295
4296 instruct storeP(memoryP mem, store_ptr_RegP src) %{
4297 predicate(!(UseG1GC && n->as_Store()->barrier_data() != 0));
4298 match(Set mem (StoreP mem src));
4299 ins_cost(MEMORY_REF_COST);
4300 size(4);
4301
4302 format %{ "STR $src,$mem\t! ptr" %}
4303 ins_encode %{
4304 __ str($src$$Register, $mem$$Address);
4305 %}
4306 ins_pipe(istore_mem_spORreg);
4307 %}
4308
4309
4310 #ifdef _LP64
4311 // Store Compressed Pointer
4312
4313
4314 instruct storeN(memoryI mem, store_RegN src) %{
4315 match(Set mem (StoreN mem src));
4316 ins_cost(MEMORY_REF_COST);
4317 size(4);
4318
4319 format %{ "str_32 $src,$mem\t! compressed ptr" %}
4320 ins_encode %{
4321 __ str_32($src$$Register, $mem$$Address);
4322 %}
4323 ins_pipe(istore_mem_reg);
4324 %}
4325
4326
4327 // Store Compressed Klass Pointer
4328 instruct storeNKlass(memoryI mem, store_RegN src) %{
4329 match(Set mem (StoreNKlass mem src));
4330 ins_cost(MEMORY_REF_COST);
4331 size(4);
4332
4333 format %{ "str_32 $src,$mem\t! compressed klass ptr" %}
4334 ins_encode %{
4335 __ str_32($src$$Register, $mem$$Address);
4336 %}
4337 ins_pipe(istore_mem_reg);
4338 %}
4339 #endif
4340
4341 // Store Double
4342
4343
4344 instruct storeD(memoryD mem, regD src) %{
4345 match(Set mem (StoreD mem src));
4346 ins_cost(MEMORY_REF_COST);
4347
4348 size(4);
4349 // FIXME: needs to be atomic, but ARMv7 A.R.M. guarantees
4350 // only LDREXD and STREXD are 64-bit single-copy atomic
4351 format %{ "FSTD $src,$mem" %}
4352 ins_encode %{
4353 __ str_double($src$$FloatRegister, $mem$$Address);
4354 %}
4355 ins_pipe(fstoreD_mem_reg);
4356 %}
4357
4358
4359 // Store Float
4360
4361
4362 instruct storeF( memoryF mem, regF src) %{
4363 match(Set mem (StoreF mem src));
4364 ins_cost(MEMORY_REF_COST);
4365
4366 size(4);
4367 format %{ "FSTS $src,$mem" %}
4368 ins_encode %{
4369 __ str_float($src$$FloatRegister, $mem$$Address);
4370 %}
4371 ins_pipe(fstoreF_mem_reg);
4372 %}
4373
4374
4375 //----------MemBar Instructions-----------------------------------------------
4376 // Memory barrier flavors
4377
4378 // pattern-match out unnecessary membars
4379 instruct membar_storestore() %{
4380 match(MemBarStoreStore);
4381 match(StoreStoreFence);
4382 ins_cost(4*MEMORY_REF_COST);
4383
4384 size(4);
4385 format %{ "MEMBAR-storestore" %}
4386 ins_encode %{
4387 __ membar(MacroAssembler::Membar_mask_bits(MacroAssembler::StoreStore), noreg);
4388 %}
4389 ins_pipe(long_memory_op);
4390 %}
4391
4392 instruct membar_acquire() %{
4393 match(MemBarAcquire);
4394 match(LoadFence);
4395 ins_cost(4*MEMORY_REF_COST);
4396
4397 size(4);
4398 format %{ "MEMBAR-acquire" %}
4399 ins_encode %{
4400 __ membar(MacroAssembler::Membar_mask_bits(MacroAssembler::LoadLoad | MacroAssembler::LoadStore), noreg);
4401 %}
4402 ins_pipe(long_memory_op);
4403 %}
4404
4405 instruct membar_acquire_lock() %{
4406 match(MemBarAcquireLock);
4407 ins_cost(0);
4408
4409 size(0);
4410 format %{ "!MEMBAR-acquire (CAS in prior FastLock so empty encoding)" %}
4411 ins_encode( );
4412 ins_pipe(empty);
4413 %}
4414
4415 instruct membar_release() %{
4416 match(MemBarRelease);
4417 match(StoreFence);
4418 ins_cost(4*MEMORY_REF_COST);
4419
4420 size(4);
4421 format %{ "MEMBAR-release" %}
4422 ins_encode %{
4423 __ membar(MacroAssembler::Membar_mask_bits(MacroAssembler::StoreStore | MacroAssembler::LoadStore), noreg);
4424 %}
4425 ins_pipe(long_memory_op);
4426 %}
4427
4428 instruct membar_release_lock() %{
4429 match(MemBarReleaseLock);
4430 ins_cost(0);
4431
4432 size(0);
4433 format %{ "!MEMBAR-release (CAS in succeeding FastUnlock so empty encoding)" %}
4434 ins_encode( );
4435 ins_pipe(empty);
4436 %}
4437
4438 instruct membar_storeload() %{
4439 match(MemBarStoreLoad);
4440 ins_cost(4*MEMORY_REF_COST);
4441
4442 size(4);
4443 format %{ "MEMBAR-storeload" %}
4444 ins_encode %{
4445 __ membar(MacroAssembler::StoreLoad, noreg);
4446 %}
4447 ins_pipe(long_memory_op);
4448 %}
4449
4450 instruct membar_volatile() %{
4451 match(MemBarVolatile);
4452 ins_cost(4*MEMORY_REF_COST);
4453
4454 size(4);
4455 format %{ "MEMBAR-volatile" %}
4456 ins_encode %{
4457 __ membar(MacroAssembler::StoreLoad, noreg);
4458 %}
4459 ins_pipe(long_memory_op);
4460 %}
4461
4462 instruct unnecessary_membar_volatile() %{
4463 match(MemBarVolatile);
4464 predicate(Matcher::post_store_load_barrier(n));
4465 ins_cost(0);
4466
4467 size(0);
4468 format %{ "!MEMBAR-volatile (unnecessary so empty encoding)" %}
4469 ins_encode( );
4470 ins_pipe(empty);
4471 %}
4472
4473 instruct membar_full() %{
4474 match(MemBarFull);
4475 ins_cost(4*MEMORY_REF_COST);
4476
4477 size(4);
4478 format %{ "MEMBAR-full" %}
4479 ins_encode %{
4480 __ membar(MacroAssembler::StoreLoad, noreg);
4481 %}
4482 ins_pipe(long_memory_op);
4483 %}
4484
4485 //----------Register Move Instructions-----------------------------------------
4486
4487 // Cast Index to Pointer for unsafe natives
4488 instruct castX2P(iRegX src, iRegP dst) %{
4489 match(Set dst (CastX2P src));
4490
4491 format %{ "MOV $dst,$src\t! IntX->Ptr if $dst != $src" %}
4492 ins_encode %{
4493 if ($dst$$Register != $src$$Register) {
4494 __ mov($dst$$Register, $src$$Register);
4495 }
4496 %}
4497 ins_pipe(ialu_reg);
4498 %}
4499
4500 // Cast Pointer to Index for unsafe natives
4501 instruct castP2X(iRegP src, iRegX dst) %{
4502 match(Set dst (CastP2X src));
4503
4504 format %{ "MOV $dst,$src\t! Ptr->IntX if $dst != $src" %}
4505 ins_encode %{
4506 if ($dst$$Register != $src$$Register) {
4507 __ mov($dst$$Register, $src$$Register);
4508 }
4509 %}
4510 ins_pipe(ialu_reg);
4511 %}
4512
4513 //----------Conditional Move---------------------------------------------------
4514 // Conditional move
4515 instruct cmovIP_reg(cmpOpP cmp, flagsRegP pcc, iRegI dst, iRegI src) %{
4516 match(Set dst (CMoveI (Binary cmp pcc) (Binary dst src)));
4517 ins_cost(150);
4518 size(4);
4519 format %{ "MOV$cmp $dst,$src\t! int" %}
4520 ins_encode %{
4521 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
4522 %}
4523 ins_pipe(ialu_reg);
4524 %}
4525
4526
4527 instruct cmovIP_immMov(cmpOpP cmp, flagsRegP pcc, iRegI dst, immIMov src) %{
4528 match(Set dst (CMoveI (Binary cmp pcc) (Binary dst src)));
4529 ins_cost(140);
4530 size(4);
4531 format %{ "MOV$cmp $dst,$src" %}
4532 ins_encode %{
4533 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
4534 %}
4535 ins_pipe(ialu_imm);
4536 %}
4537
4538 instruct cmovIP_imm16(cmpOpP cmp, flagsRegP pcc, iRegI dst, immI16 src) %{
4539 match(Set dst (CMoveI (Binary cmp pcc) (Binary dst src)));
4540 ins_cost(140);
4541 size(4);
4542 format %{ "MOVw$cmp $dst,$src" %}
4543 ins_encode %{
4544 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
4545 %}
4546 ins_pipe(ialu_imm);
4547 %}
4548
4549 instruct cmovI_reg(cmpOp cmp, flagsReg icc, iRegI dst, iRegI src) %{
4550 match(Set dst (CMoveI (Binary cmp icc) (Binary dst src)));
4551 ins_cost(150);
4552 size(4);
4553 format %{ "MOV$cmp $dst,$src" %}
4554 ins_encode %{
4555 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
4556 %}
4557 ins_pipe(ialu_reg);
4558 %}
4559
4560
4561 instruct cmovI_immMov(cmpOp cmp, flagsReg icc, iRegI dst, immIMov src) %{
4562 match(Set dst (CMoveI (Binary cmp icc) (Binary dst src)));
4563 ins_cost(140);
4564 size(4);
4565 format %{ "MOV$cmp $dst,$src" %}
4566 ins_encode %{
4567 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
4568 %}
4569 ins_pipe(ialu_imm);
4570 %}
4571
4572 instruct cmovII_imm16(cmpOp cmp, flagsReg icc, iRegI dst, immI16 src) %{
4573 match(Set dst (CMoveI (Binary cmp icc) (Binary dst src)));
4574 ins_cost(140);
4575 size(4);
4576 format %{ "MOVw$cmp $dst,$src" %}
4577 ins_encode %{
4578 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
4579 %}
4580 ins_pipe(ialu_imm);
4581 %}
4582
4583 instruct cmovII_reg_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegI dst, iRegI src) %{
4584 match(Set dst (CMoveI (Binary cmp icc) (Binary dst src)));
4585 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq ||
4586 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ||
4587 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt ||
4588 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
4589 ins_cost(150);
4590 size(4);
4591 format %{ "MOV$cmp $dst,$src" %}
4592 ins_encode %{
4593 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
4594 %}
4595 ins_pipe(ialu_reg);
4596 %}
4597
4598 instruct cmovII_immMov_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegI dst, immIMov src) %{
4599 match(Set dst (CMoveI (Binary cmp icc) (Binary dst src)));
4600 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq ||
4601 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ||
4602 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt ||
4603 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
4604 ins_cost(140);
4605 size(4);
4606 format %{ "MOV$cmp $dst,$src" %}
4607 ins_encode %{
4608 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
4609 %}
4610 ins_pipe(ialu_imm);
4611 %}
4612
4613 instruct cmovII_imm16_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegI dst, immI16 src) %{
4614 match(Set dst (CMoveI (Binary cmp icc) (Binary dst src)));
4615 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq ||
4616 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ||
4617 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt ||
4618 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
4619 ins_cost(140);
4620 size(4);
4621 format %{ "MOVW$cmp $dst,$src" %}
4622 ins_encode %{
4623 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
4624 %}
4625 ins_pipe(ialu_imm);
4626 %}
4627
4628 instruct cmovIIu_reg(cmpOpU cmp, flagsRegU icc, iRegI dst, iRegI src) %{
4629 match(Set dst (CMoveI (Binary cmp icc) (Binary dst src)));
4630 ins_cost(150);
4631 size(4);
4632 format %{ "MOV$cmp $dst,$src" %}
4633 ins_encode %{
4634 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
4635 %}
4636 ins_pipe(ialu_reg);
4637 %}
4638
4639 instruct cmovIIu_immMov(cmpOpU cmp, flagsRegU icc, iRegI dst, immIMov src) %{
4640 match(Set dst (CMoveI (Binary cmp icc) (Binary dst src)));
4641 ins_cost(140);
4642 size(4);
4643 format %{ "MOV$cmp $dst,$src" %}
4644 ins_encode %{
4645 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
4646 %}
4647 ins_pipe(ialu_imm);
4648 %}
4649
4650 instruct cmovIIu_imm16(cmpOpU cmp, flagsRegU icc, iRegI dst, immI16 src) %{
4651 match(Set dst (CMoveI (Binary cmp icc) (Binary dst src)));
4652 ins_cost(140);
4653 size(4);
4654 format %{ "MOVW$cmp $dst,$src" %}
4655 ins_encode %{
4656 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
4657 %}
4658 ins_pipe(ialu_imm);
4659 %}
4660
4661 // Conditional move
4662 instruct cmovPP_reg(cmpOpP cmp, flagsRegP pcc, iRegP dst, iRegP src) %{
4663 match(Set dst (CMoveP (Binary cmp pcc) (Binary dst src)));
4664 ins_cost(150);
4665 size(4);
4666 format %{ "MOV$cmp $dst,$src" %}
4667 ins_encode %{
4668 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
4669 %}
4670 ins_pipe(ialu_reg);
4671 %}
4672
4673 instruct cmovPP_imm(cmpOpP cmp, flagsRegP pcc, iRegP dst, immP0 src) %{
4674 match(Set dst (CMoveP (Binary cmp pcc) (Binary dst src)));
4675 ins_cost(140);
4676 size(4);
4677 format %{ "MOV$cmp $dst,$src" %}
4678 ins_encode %{
4679 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
4680 %}
4681 ins_pipe(ialu_imm);
4682 %}
4683
4684 // This instruction also works with CmpN so we don't need cmovPN_reg.
4685 instruct cmovPI_reg(cmpOp cmp, flagsReg icc, iRegP dst, iRegP src) %{
4686 match(Set dst (CMoveP (Binary cmp icc) (Binary dst src)));
4687 ins_cost(150);
4688
4689 size(4);
4690 format %{ "MOV$cmp $dst,$src\t! ptr" %}
4691 ins_encode %{
4692 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
4693 %}
4694 ins_pipe(ialu_reg);
4695 %}
4696
4697 instruct cmovPI_reg_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegP dst, iRegP src) %{
4698 match(Set dst (CMoveP (Binary cmp icc) (Binary dst src)));
4699 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq ||
4700 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ||
4701 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt ||
4702 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
4703 ins_cost(150);
4704
4705 size(4);
4706 format %{ "MOV$cmp $dst,$src\t! ptr" %}
4707 ins_encode %{
4708 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
4709 %}
4710 ins_pipe(ialu_reg);
4711 %}
4712
4713 instruct cmovPIu_reg(cmpOpU cmp, flagsRegU icc, iRegP dst, iRegP src) %{
4714 match(Set dst (CMoveP (Binary cmp icc) (Binary dst src)));
4715 ins_cost(150);
4716
4717 size(4);
4718 format %{ "MOV$cmp $dst,$src\t! ptr" %}
4719 ins_encode %{
4720 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
4721 %}
4722 ins_pipe(ialu_reg);
4723 %}
4724
4725 instruct cmovPI_imm(cmpOp cmp, flagsReg icc, iRegP dst, immP0 src) %{
4726 match(Set dst (CMoveP (Binary cmp icc) (Binary dst src)));
4727 ins_cost(140);
4728
4729 size(4);
4730 format %{ "MOV$cmp $dst,$src\t! ptr" %}
4731 ins_encode %{
4732 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
4733 %}
4734 ins_pipe(ialu_imm);
4735 %}
4736
4737 instruct cmovPI_imm_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegP dst, immP0 src) %{
4738 match(Set dst (CMoveP (Binary cmp icc) (Binary dst src)));
4739 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq ||
4740 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ||
4741 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt ||
4742 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
4743 ins_cost(140);
4744
4745 size(4);
4746 format %{ "MOV$cmp $dst,$src\t! ptr" %}
4747 ins_encode %{
4748 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
4749 %}
4750 ins_pipe(ialu_imm);
4751 %}
4752
4753 instruct cmovPIu_imm(cmpOpU cmp, flagsRegU icc, iRegP dst, immP0 src) %{
4754 match(Set dst (CMoveP (Binary cmp icc) (Binary dst src)));
4755 ins_cost(140);
4756
4757 size(4);
4758 format %{ "MOV$cmp $dst,$src\t! ptr" %}
4759 ins_encode %{
4760 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
4761 %}
4762 ins_pipe(ialu_imm);
4763 %}
4764
4765
4766 // Conditional move
4767 instruct cmovFP_reg(cmpOpP cmp, flagsRegP pcc, regF dst, regF src) %{
4768 match(Set dst (CMoveF (Binary cmp pcc) (Binary dst src)));
4769 ins_cost(150);
4770 size(4);
4771 format %{ "FCPYS$cmp $dst,$src" %}
4772 ins_encode %{
4773 __ fcpys($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
4774 %}
4775 ins_pipe(int_conditional_float_move);
4776 %}
4777
4778 instruct cmovFI_reg(cmpOp cmp, flagsReg icc, regF dst, regF src) %{
4779 match(Set dst (CMoveF (Binary cmp icc) (Binary dst src)));
4780 ins_cost(150);
4781
4782 size(4);
4783 format %{ "FCPYS$cmp $dst,$src" %}
4784 ins_encode %{
4785 __ fcpys($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
4786 %}
4787 ins_pipe(int_conditional_float_move);
4788 %}
4789
4790 instruct cmovFI_reg_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, regF dst, regF src) %{
4791 match(Set dst (CMoveF (Binary cmp icc) (Binary dst src)));
4792 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq ||
4793 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ||
4794 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt ||
4795 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
4796 ins_cost(150);
4797
4798 size(4);
4799 format %{ "FCPYS$cmp $dst,$src" %}
4800 ins_encode %{
4801 __ fcpys($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
4802 %}
4803 ins_pipe(int_conditional_float_move);
4804 %}
4805
4806 instruct cmovFIu_reg(cmpOpU cmp, flagsRegU icc, regF dst, regF src) %{
4807 match(Set dst (CMoveF (Binary cmp icc) (Binary dst src)));
4808 ins_cost(150);
4809
4810 size(4);
4811 format %{ "FCPYS$cmp $dst,$src" %}
4812 ins_encode %{
4813 __ fcpys($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
4814 %}
4815 ins_pipe(int_conditional_float_move);
4816 %}
4817
4818 // Conditional move
4819 instruct cmovDP_reg(cmpOpP cmp, flagsRegP pcc, regD dst, regD src) %{
4820 match(Set dst (CMoveD (Binary cmp pcc) (Binary dst src)));
4821 ins_cost(150);
4822 size(4);
4823 format %{ "FCPYD$cmp $dst,$src" %}
4824 ins_encode %{
4825 __ fcpyd($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
4826 %}
4827 ins_pipe(int_conditional_double_move);
4828 %}
4829
4830 instruct cmovDI_reg(cmpOp cmp, flagsReg icc, regD dst, regD src) %{
4831 match(Set dst (CMoveD (Binary cmp icc) (Binary dst src)));
4832 ins_cost(150);
4833
4834 size(4);
4835 format %{ "FCPYD$cmp $dst,$src" %}
4836 ins_encode %{
4837 __ fcpyd($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
4838 %}
4839 ins_pipe(int_conditional_double_move);
4840 %}
4841
4842 instruct cmovDI_reg_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, regD dst, regD src) %{
4843 match(Set dst (CMoveD (Binary cmp icc) (Binary dst src)));
4844 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);
4845 ins_cost(150);
4846
4847 size(4);
4848 format %{ "FCPYD$cmp $dst,$src" %}
4849 ins_encode %{
4850 __ fcpyd($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
4851 %}
4852 ins_pipe(int_conditional_double_move);
4853 %}
4854
4855 instruct cmovDIu_reg(cmpOpU cmp, flagsRegU icc, regD dst, regD src) %{
4856 match(Set dst (CMoveD (Binary cmp icc) (Binary dst src)));
4857 ins_cost(150);
4858
4859 size(4);
4860 format %{ "FCPYD$cmp $dst,$src" %}
4861 ins_encode %{
4862 __ fcpyd($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
4863 %}
4864 ins_pipe(int_conditional_double_move);
4865 %}
4866
4867 // Conditional move
4868 instruct cmovLP_reg(cmpOpP cmp, flagsRegP pcc, iRegL dst, iRegL src) %{
4869 match(Set dst (CMoveL (Binary cmp pcc) (Binary dst src)));
4870 ins_cost(150);
4871
4872 size(8);
4873 format %{ "MOV$cmp $dst.lo,$src.lo\t! long\n\t"
4874 "MOV$cmp $dst.hi,$src.hi" %}
4875 ins_encode %{
4876 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
4877 __ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode));
4878 %}
4879 ins_pipe(ialu_reg);
4880 %}
4881
4882 // TODO: try immLRot2 instead, (0, $con$$constant) becomes
4883 // (hi($con$$constant), lo($con$$constant)) becomes
4884 instruct cmovLP_immRot(cmpOpP cmp, flagsRegP pcc, iRegL dst, immLlowRot src) %{
4885 match(Set dst (CMoveL (Binary cmp pcc) (Binary dst src)));
4886 ins_cost(140);
4887
4888 size(8);
4889 format %{ "MOV$cmp $dst.lo,$src\t! long\n\t"
4890 "MOV$cmp $dst.hi,0" %}
4891 ins_encode %{
4892 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
4893 __ mov($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode));
4894 %}
4895 ins_pipe(ialu_imm);
4896 %}
4897
4898 instruct cmovLP_imm16(cmpOpP cmp, flagsRegP pcc, iRegL dst, immL16 src) %{
4899 match(Set dst (CMoveL (Binary cmp pcc) (Binary dst src)));
4900 ins_cost(140);
4901
4902 size(8);
4903 format %{ "MOV$cmp $dst.lo,$src\t! long\n\t"
4904 "MOV$cmp $dst.hi,0" %}
4905 ins_encode %{
4906 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
4907 __ mov($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode));
4908 %}
4909 ins_pipe(ialu_imm);
4910 %}
4911
4912 instruct cmovLI_reg(cmpOp cmp, flagsReg icc, iRegL dst, iRegL src) %{
4913 match(Set dst (CMoveL (Binary cmp icc) (Binary dst src)));
4914 ins_cost(150);
4915
4916 size(8);
4917 format %{ "MOV$cmp $dst.lo,$src.lo\t! long\n\t"
4918 "MOV$cmp $dst.hi,$src.hi" %}
4919 ins_encode %{
4920 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
4921 __ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode));
4922 %}
4923 ins_pipe(ialu_reg);
4924 %}
4925
4926 instruct cmovLI_reg_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegL dst, iRegL src) %{
4927 match(Set dst (CMoveL (Binary cmp icc) (Binary dst src)));
4928 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq ||
4929 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ||
4930 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt ||
4931 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
4932 ins_cost(150);
4933
4934 size(8);
4935 format %{ "MOV$cmp $dst.lo,$src.lo\t! long\n\t"
4936 "MOV$cmp $dst.hi,$src.hi" %}
4937 ins_encode %{
4938 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
4939 __ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode));
4940 %}
4941 ins_pipe(ialu_reg);
4942 %}
4943
4944 // TODO: try immLRot2 instead, (0, $con$$constant) becomes
4945 // (hi($con$$constant), lo($con$$constant)) becomes
4946 instruct cmovLI_immRot(cmpOp cmp, flagsReg icc, iRegL dst, immLlowRot src) %{
4947 match(Set dst (CMoveL (Binary cmp icc) (Binary dst src)));
4948 ins_cost(140);
4949
4950 size(8);
4951 format %{ "MOV$cmp $dst.lo,$src\t! long\n\t"
4952 "MOV$cmp $dst.hi,0" %}
4953 ins_encode %{
4954 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
4955 __ mov($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode));
4956 %}
4957 ins_pipe(ialu_imm);
4958 %}
4959
4960 // TODO: try immLRot2 instead, (0, $con$$constant) becomes
4961 // (hi($con$$constant), lo($con$$constant)) becomes
4962 instruct cmovLI_immRot_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegL dst, immLlowRot src) %{
4963 match(Set dst (CMoveL (Binary cmp icc) (Binary dst src)));
4964 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq ||
4965 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ||
4966 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt ||
4967 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
4968 ins_cost(140);
4969
4970 size(8);
4971 format %{ "MOV$cmp $dst.lo,$src\t! long\n\t"
4972 "MOV$cmp $dst.hi,0" %}
4973 ins_encode %{
4974 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
4975 __ mov($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode));
4976 %}
4977 ins_pipe(ialu_imm);
4978 %}
4979
4980 instruct cmovLI_imm16(cmpOp cmp, flagsReg icc, iRegL dst, immL16 src) %{
4981 match(Set dst (CMoveL (Binary cmp icc) (Binary dst src)));
4982 ins_cost(140);
4983
4984 size(8);
4985 format %{ "MOV$cmp $dst.lo,$src\t! long\n\t"
4986 "MOV$cmp $dst.hi,0" %}
4987 ins_encode %{
4988 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
4989 __ movw($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode));
4990 %}
4991 ins_pipe(ialu_imm);
4992 %}
4993
4994 instruct cmovLI_imm16_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegL dst, immL16 src) %{
4995 match(Set dst (CMoveL (Binary cmp icc) (Binary dst src)));
4996 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq ||
4997 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ||
4998 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt ||
4999 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
5000 ins_cost(140);
5001
5002 size(8);
5003 format %{ "MOV$cmp $dst.lo,$src\t! long\n\t"
5004 "MOV$cmp $dst.hi,0" %}
5005 ins_encode %{
5006 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
5007 __ movw($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode));
5008 %}
5009 ins_pipe(ialu_imm);
5010 %}
5011
5012 instruct cmovLIu_reg(cmpOpU cmp, flagsRegU icc, iRegL dst, iRegL src) %{
5013 match(Set dst (CMoveL (Binary cmp icc) (Binary dst src)));
5014 ins_cost(150);
5015
5016 size(8);
5017 format %{ "MOV$cmp $dst.lo,$src.lo\t! long\n\t"
5018 "MOV$cmp $dst.hi,$src.hi" %}
5019 ins_encode %{
5020 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
5021 __ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode));
5022 %}
5023 ins_pipe(ialu_reg);
5024 %}
5025
5026
5027 //----------OS and Locking Instructions----------------------------------------
5028
5029 // This name is KNOWN by the ADLC and cannot be changed.
5030 // The ADLC forces a 'TypeRawPtr::BOTTOM' output type
5031 // for this guy.
5032 instruct tlsLoadP(RthreadRegP dst) %{
5033 match(Set dst (ThreadLocal));
5034
5035 size(0);
5036 ins_cost(0);
5037 format %{ "! TLS is in $dst" %}
5038 ins_encode( /*empty encoding*/ );
5039 ins_pipe(ialu_none);
5040 %}
5041
5042 instruct checkCastPP( iRegP dst ) %{
5043 match(Set dst (CheckCastPP dst));
5044
5045 size(0);
5046 format %{ "! checkcastPP of $dst" %}
5047 ins_encode( /*empty encoding*/ );
5048 ins_pipe(empty);
5049 %}
5050
5051
5052 instruct castPP( iRegP dst ) %{
5053 match(Set dst (CastPP dst));
5054 format %{ "! castPP of $dst" %}
5055 ins_encode( /*empty encoding*/ );
5056 ins_pipe(empty);
5057 %}
5058
5059 instruct castII( iRegI dst ) %{
5060 match(Set dst (CastII dst));
5061 format %{ "! castII of $dst" %}
5062 ins_encode( /*empty encoding*/ );
5063 ins_cost(0);
5064 ins_pipe(empty);
5065 %}
5066
5067 instruct castLL( iRegL dst ) %{
5068 match(Set dst (CastLL dst));
5069 format %{ "! castLL of $dst" %}
5070 ins_encode( /*empty encoding*/ );
5071 ins_cost(0);
5072 ins_pipe(empty);
5073 %}
5074
5075 instruct castFF( regF dst ) %{
5076 match(Set dst (CastFF dst));
5077 format %{ "! castFF of $dst" %}
5078 ins_encode( /*empty encoding*/ );
5079 ins_cost(0);
5080 ins_pipe(empty);
5081 %}
5082
5083 instruct castDD( regD dst ) %{
5084 match(Set dst (CastDD dst));
5085 format %{ "! castDD of $dst" %}
5086 ins_encode( /*empty encoding*/ );
5087 ins_cost(0);
5088 ins_pipe(empty);
5089 %}
5090
5091 instruct castVVD( vecD dst ) %{
5092 match(Set dst (CastVV dst));
5093 format %{ "! castVV of $dst" %}
5094 ins_encode( /*empty encoding*/ );
5095 ins_cost(0);
5096 ins_pipe(empty);
5097 %}
5098
5099 instruct castVVX( vecX dst ) %{
5100 match(Set dst (CastVV dst));
5101 format %{ "! castVV of $dst" %}
5102 ins_encode( /*empty encoding*/ );
5103 ins_cost(0);
5104 ins_pipe(empty);
5105 %}
5106
5107
5108 //----------Arithmetic Instructions--------------------------------------------
5109 // Addition Instructions
5110 // Register Addition
5111 instruct addI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{
5112 match(Set dst (AddI src1 src2));
5113
5114 size(4);
5115 format %{ "add_32 $dst,$src1,$src2\t! int" %}
5116 ins_encode %{
5117 __ add_32($dst$$Register, $src1$$Register, $src2$$Register);
5118 %}
5119 ins_pipe(ialu_reg_reg);
5120 %}
5121
5122 instruct addshlI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
5123 match(Set dst (AddI (LShiftI src1 src2) src3));
5124
5125 size(4);
5126 format %{ "add_32 $dst,$src3,$src1<<$src2\t! int" %}
5127 ins_encode %{
5128 __ add_32($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsl, $src2$$Register));
5129 %}
5130 ins_pipe(ialu_reg_reg);
5131 %}
5132
5133
5134 instruct addshlI_reg_imm_reg(iRegI dst, iRegI src1, immU5 src2, iRegI src3) %{
5135 match(Set dst (AddI (LShiftI src1 src2) src3));
5136
5137 size(4);
5138 format %{ "add_32 $dst,$src3,$src1<<$src2\t! int" %}
5139 ins_encode %{
5140 __ add_32($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsl, $src2$$constant));
5141 %}
5142 ins_pipe(ialu_reg_reg);
5143 %}
5144
5145 instruct addsarI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
5146 match(Set dst (AddI (RShiftI src1 src2) src3));
5147
5148 size(4);
5149 format %{ "add_32 $dst,$src3,$src1>>$src2\t! int" %}
5150 ins_encode %{
5151 __ add_32($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, asr, $src2$$Register));
5152 %}
5153 ins_pipe(ialu_reg_reg);
5154 %}
5155
5156 instruct addsarI_reg_imm_reg(iRegI dst, iRegI src1, immU5 src2, iRegI src3) %{
5157 match(Set dst (AddI (RShiftI src1 src2) src3));
5158
5159 size(4);
5160 format %{ "add_32 $dst,$src3,$src1>>$src2\t! int" %}
5161 ins_encode %{
5162 __ add_32($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, asr, $src2$$constant));
5163 %}
5164 ins_pipe(ialu_reg_reg);
5165 %}
5166
5167 instruct addshrI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
5168 match(Set dst (AddI (URShiftI src1 src2) src3));
5169
5170 size(4);
5171 format %{ "add_32 $dst,$src3,$src1>>>$src2\t! int" %}
5172 ins_encode %{
5173 __ add_32($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsr, $src2$$Register));
5174 %}
5175 ins_pipe(ialu_reg_reg);
5176 %}
5177
5178 instruct addshrI_reg_imm_reg(iRegI dst, iRegI src1, immU5 src2, iRegI src3) %{
5179 match(Set dst (AddI (URShiftI src1 src2) src3));
5180
5181 size(4);
5182 format %{ "add_32 $dst,$src3,$src1>>>$src2\t! int" %}
5183 ins_encode %{
5184 __ add_32($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsr, $src2$$constant));
5185 %}
5186 ins_pipe(ialu_reg_reg);
5187 %}
5188
5189 // Immediate Addition
5190 instruct addI_reg_aimmI(iRegI dst, iRegI src1, aimmI src2) %{
5191 match(Set dst (AddI src1 src2));
5192
5193 size(4);
5194 format %{ "add_32 $dst,$src1,$src2\t! int" %}
5195 ins_encode %{
5196 __ add_32($dst$$Register, $src1$$Register, $src2$$constant);
5197 %}
5198 ins_pipe(ialu_reg_imm);
5199 %}
5200
5201 // Pointer Register Addition
5202 instruct addP_reg_reg(iRegP dst, iRegP src1, iRegX src2) %{
5203 match(Set dst (AddP src1 src2));
5204
5205 size(4);
5206 format %{ "ADD $dst,$src1,$src2\t! ptr" %}
5207 ins_encode %{
5208 __ add($dst$$Register, $src1$$Register, $src2$$Register);
5209 %}
5210 ins_pipe(ialu_reg_reg);
5211 %}
5212
5213
5214 // shifted iRegX operand
5215 operand shiftedX(iRegX src2, shimmX src3) %{
5216 //constraint(ALLOC_IN_RC(sp_ptr_reg));
5217 match(LShiftX src2 src3);
5218
5219 op_cost(1);
5220 format %{ "$src2 << $src3" %}
5221 interface(MEMORY_INTER) %{
5222 base($src2);
5223 index(0xff);
5224 scale($src3);
5225 disp(0x0);
5226 %}
5227 %}
5228
5229 instruct addshlP_reg_reg_imm(iRegP dst, iRegP src1, shiftedX src2) %{
5230 match(Set dst (AddP src1 src2));
5231
5232 ins_cost(DEFAULT_COST * 3/2);
5233 size(4);
5234 format %{ "ADD $dst,$src1,$src2\t! ptr" %}
5235 ins_encode %{
5236 Register base = reg_to_register_object($src2$$base);
5237 __ add($dst$$Register, $src1$$Register, AsmOperand(base, lsl, $src2$$scale));
5238 %}
5239 ins_pipe(ialu_reg_reg);
5240 %}
5241
5242 // Pointer Immediate Addition
5243 instruct addP_reg_aimmX(iRegP dst, iRegP src1, aimmX src2) %{
5244 match(Set dst (AddP src1 src2));
5245
5246 size(4);
5247 format %{ "ADD $dst,$src1,$src2\t! ptr" %}
5248 ins_encode %{
5249 __ add($dst$$Register, $src1$$Register, $src2$$constant);
5250 %}
5251 ins_pipe(ialu_reg_imm);
5252 %}
5253
5254 // Long Addition
5255 instruct addL_reg_reg(iRegL dst, iRegL src1, iRegL src2, flagsReg ccr) %{
5256 match(Set dst (AddL src1 src2));
5257 effect(KILL ccr);
5258 size(8);
5259 format %{ "ADDS $dst.lo,$src1.lo,$src2.lo\t! long\n\t"
5260 "ADC $dst.hi,$src1.hi,$src2.hi" %}
5261 ins_encode %{
5262 __ adds($dst$$Register, $src1$$Register, $src2$$Register);
5263 __ adc($dst$$Register->successor(), $src1$$Register->successor(), $src2$$Register->successor());
5264 %}
5265 ins_pipe(ialu_reg_reg);
5266 %}
5267
5268 // TODO
5269
5270 // TODO: try immLRot2 instead, (0, $con$$constant) becomes
5271 // (hi($con$$constant), lo($con$$constant)) becomes
5272 instruct addL_reg_immRot(iRegL dst, iRegL src1, immLlowRot con, flagsReg ccr) %{
5273 match(Set dst (AddL src1 con));
5274 effect(KILL ccr);
5275 size(8);
5276 format %{ "ADDS $dst.lo,$src1.lo,$con\t! long\n\t"
5277 "ADC $dst.hi,$src1.hi,0" %}
5278 ins_encode %{
5279 __ adds($dst$$Register, $src1$$Register, $con$$constant);
5280 __ adc($dst$$Register->successor(), $src1$$Register->successor(), 0);
5281 %}
5282 ins_pipe(ialu_reg_imm);
5283 %}
5284
5285 // No flag versions for CompareAndSwap{P,I,L} because matcher can't match them
5286
5287 instruct compareAndSwapL_bool(memoryex mem, iRegL oldval, iRegLd newval, iRegI res, iRegLd tmp, flagsReg ccr ) %{
5288 match(Set res (CompareAndSwapL mem (Binary oldval newval)));
5289 effect( KILL ccr, TEMP tmp);
5290 size(32);
5291 format %{ "loop: \n\t"
5292 "LDREXD $tmp, $mem\t! If $oldval==[$mem] Then store $newval into [$mem]\n\t"
5293 "CMP $tmp.lo, $oldval.lo\n\t"
5294 "CMP.eq $tmp.hi, $oldval.hi\n\t"
5295 "STREXD.eq $tmp, $newval, $mem\n\t"
5296 "MOV.ne $tmp, 0 \n\t"
5297 "XORS.eq $tmp,$tmp, 1 \n\t"
5298 "B.eq loop \n\t"
5299 "MOV $res, $tmp" %}
5300 ins_encode %{
5301 Label loop;
5302 __ bind(loop);
5303 __ ldrexd($tmp$$Register, $mem$$Address);
5304 __ cmp($tmp$$Register, $oldval$$Register);
5305 __ cmp($tmp$$Register->successor(), $oldval$$Register->successor(), eq);
5306 __ strexd($tmp$$Register, $newval$$Register, $mem$$Address, eq);
5307 __ mov($tmp$$Register, 0, ne);
5308 __ eors($tmp$$Register, $tmp$$Register, 1, eq);
5309 __ b(loop, eq);
5310 __ mov($res$$Register, $tmp$$Register);
5311 %}
5312 ins_pipe( long_memory_op );
5313 %}
5314
5315
5316 instruct compareAndSwapI_bool(memoryex mem, iRegI oldval, iRegI newval, iRegI res, iRegI tmp, flagsReg ccr ) %{
5317 match(Set res (CompareAndSwapI mem (Binary oldval newval)));
5318 effect( KILL ccr, TEMP tmp);
5319 size(28);
5320 format %{ "loop: \n\t"
5321 "LDREX $tmp, $mem\t! If $oldval==[$mem] Then store $newval into [$mem]\n\t"
5322 "CMP $tmp, $oldval\n\t"
5323 "STREX.eq $tmp, $newval, $mem\n\t"
5324 "MOV.ne $tmp, 0 \n\t"
5325 "XORS.eq $tmp,$tmp, 1 \n\t"
5326 "B.eq loop \n\t"
5327 "MOV $res, $tmp" %}
5328
5329 ins_encode %{
5330 Label loop;
5331 __ bind(loop);
5332 __ ldrex($tmp$$Register,$mem$$Address);
5333 __ cmp($tmp$$Register, $oldval$$Register);
5334 __ strex($tmp$$Register, $newval$$Register, $mem$$Address, eq);
5335 __ mov($tmp$$Register, 0, ne);
5336 __ eors($tmp$$Register, $tmp$$Register, 1, eq);
5337 __ b(loop, eq);
5338 __ mov($res$$Register, $tmp$$Register);
5339 %}
5340 ins_pipe( long_memory_op );
5341 %}
5342
5343 instruct compareAndSwapP_bool(memoryex mem, iRegP oldval, iRegP newval, iRegI res, iRegI tmp, flagsReg ccr ) %{
5344 predicate(!(UseG1GC && n->as_LoadStore()->barrier_data() != 0));
5345 match(Set res (CompareAndSwapP mem (Binary oldval newval)));
5346 effect( KILL ccr, TEMP tmp);
5347 size(28);
5348 format %{ "loop: \n\t"
5349 "LDREX $tmp, $mem\t! If $oldval==[$mem] Then store $newval into [$mem]\n\t"
5350 "CMP $tmp, $oldval\n\t"
5351 "STREX.eq $tmp, $newval, $mem\n\t"
5352 "MOV.ne $tmp, 0 \n\t"
5353 "EORS.eq $tmp,$tmp, 1 \n\t"
5354 "B.eq loop \n\t"
5355 "MOV $res, $tmp" %}
5356
5357 ins_encode %{
5358 Label loop;
5359 __ bind(loop);
5360 __ ldrex($tmp$$Register,$mem$$Address);
5361 __ cmp($tmp$$Register, $oldval$$Register);
5362 __ strex($tmp$$Register, $newval$$Register, $mem$$Address, eq);
5363 __ mov($tmp$$Register, 0, ne);
5364 __ eors($tmp$$Register, $tmp$$Register, 1, eq);
5365 __ b(loop, eq);
5366 __ mov($res$$Register, $tmp$$Register);
5367 %}
5368 ins_pipe( long_memory_op );
5369 %}
5370
5371 instruct xaddI_aimmI_no_res(memoryex mem, aimmI add, Universe dummy, iRegI tmp1, iRegI tmp2, flagsReg ccr) %{
5372 predicate(n->as_LoadStore()->result_not_used());
5373 match(Set dummy (GetAndAddI mem add));
5374 effect(KILL ccr, TEMP tmp1, TEMP tmp2);
5375 size(20);
5376 format %{ "loop: \n\t"
5377 "LDREX $tmp1, $mem\n\t"
5378 "ADD $tmp1, $tmp1, $add\n\t"
5379 "STREX $tmp2, $tmp1, $mem\n\t"
5380 "CMP $tmp2, 0 \n\t"
5381 "B.ne loop \n\t" %}
5382
5383 ins_encode %{
5384 Label loop;
5385 __ bind(loop);
5386 __ ldrex($tmp1$$Register,$mem$$Address);
5387 __ add($tmp1$$Register, $tmp1$$Register, $add$$constant);
5388 __ strex($tmp2$$Register, $tmp1$$Register, $mem$$Address);
5389 __ cmp($tmp2$$Register, 0);
5390 __ b(loop, ne);
5391 %}
5392 ins_pipe( long_memory_op );
5393 %}
5394
5395 instruct xaddI_reg_no_res(memoryex mem, iRegI add, Universe dummy, iRegI tmp1, iRegI tmp2, flagsReg ccr) %{
5396 predicate(n->as_LoadStore()->result_not_used());
5397 match(Set dummy (GetAndAddI mem add));
5398 effect(KILL ccr, TEMP tmp1, TEMP tmp2);
5399 size(20);
5400 format %{ "loop: \n\t"
5401 "LDREX $tmp1, $mem\n\t"
5402 "ADD $tmp1, $tmp1, $add\n\t"
5403 "STREX $tmp2, $tmp1, $mem\n\t"
5404 "CMP $tmp2, 0 \n\t"
5405 "B.ne loop \n\t" %}
5406
5407 ins_encode %{
5408 Label loop;
5409 __ bind(loop);
5410 __ ldrex($tmp1$$Register,$mem$$Address);
5411 __ add($tmp1$$Register, $tmp1$$Register, $add$$Register);
5412 __ strex($tmp2$$Register, $tmp1$$Register, $mem$$Address);
5413 __ cmp($tmp2$$Register, 0);
5414 __ b(loop, ne);
5415 %}
5416 ins_pipe( long_memory_op );
5417 %}
5418
5419 instruct xaddI_aimmI(memoryex mem, aimmI add, iRegI res, iRegI tmp1, iRegI tmp2, flagsReg ccr) %{
5420 match(Set res (GetAndAddI mem add));
5421 effect(KILL ccr, TEMP tmp1, TEMP tmp2, TEMP res);
5422 size(20);
5423 format %{ "loop: \n\t"
5424 "LDREX $res, $mem\n\t"
5425 "ADD $tmp1, $res, $add\n\t"
5426 "STREX $tmp2, $tmp1, $mem\n\t"
5427 "CMP $tmp2, 0 \n\t"
5428 "B.ne loop \n\t" %}
5429
5430 ins_encode %{
5431 Label loop;
5432 __ bind(loop);
5433 __ ldrex($res$$Register,$mem$$Address);
5434 __ add($tmp1$$Register, $res$$Register, $add$$constant);
5435 __ strex($tmp2$$Register, $tmp1$$Register, $mem$$Address);
5436 __ cmp($tmp2$$Register, 0);
5437 __ b(loop, ne);
5438 %}
5439 ins_pipe( long_memory_op );
5440 %}
5441
5442 instruct xaddI_reg(memoryex mem, iRegI add, iRegI res, iRegI tmp1, iRegI tmp2, flagsReg ccr) %{
5443 match(Set res (GetAndAddI mem add));
5444 effect(KILL ccr, TEMP tmp1, TEMP tmp2, TEMP res);
5445 size(20);
5446 format %{ "loop: \n\t"
5447 "LDREX $res, $mem\n\t"
5448 "ADD $tmp1, $res, $add\n\t"
5449 "STREX $tmp2, $tmp1, $mem\n\t"
5450 "CMP $tmp2, 0 \n\t"
5451 "B.ne loop \n\t" %}
5452
5453 ins_encode %{
5454 Label loop;
5455 __ bind(loop);
5456 __ ldrex($res$$Register,$mem$$Address);
5457 __ add($tmp1$$Register, $res$$Register, $add$$Register);
5458 __ strex($tmp2$$Register, $tmp1$$Register, $mem$$Address);
5459 __ cmp($tmp2$$Register, 0);
5460 __ b(loop, ne);
5461 %}
5462 ins_pipe( long_memory_op );
5463 %}
5464
5465 instruct xaddL_reg_no_res(memoryex mem, iRegL add, Universe dummy, iRegLd tmp1, iRegI tmp2, flagsReg ccr) %{
5466 predicate(n->as_LoadStore()->result_not_used());
5467 match(Set dummy (GetAndAddL mem add));
5468 effect( KILL ccr, TEMP tmp1, TEMP tmp2);
5469 size(24);
5470 format %{ "loop: \n\t"
5471 "LDREXD $tmp1, $mem\n\t"
5472 "ADDS $tmp1.lo, $tmp1.lo, $add.lo\n\t"
5473 "ADC $tmp1.hi, $tmp1.hi, $add.hi\n\t"
5474 "STREXD $tmp2, $tmp1, $mem\n\t"
5475 "CMP $tmp2, 0 \n\t"
5476 "B.ne loop \n\t" %}
5477
5478 ins_encode %{
5479 Label loop;
5480 __ bind(loop);
5481 __ ldrexd($tmp1$$Register, $mem$$Address);
5482 __ adds($tmp1$$Register, $tmp1$$Register, $add$$Register);
5483 __ adc($tmp1$$Register->successor(), $tmp1$$Register->successor(), $add$$Register->successor());
5484 __ strexd($tmp2$$Register, $tmp1$$Register, $mem$$Address);
5485 __ cmp($tmp2$$Register, 0);
5486 __ b(loop, ne);
5487 %}
5488 ins_pipe( long_memory_op );
5489 %}
5490
5491 // TODO: try immLRot2 instead, (0, $con$$constant) becomes
5492 // (hi($con$$constant), lo($con$$constant)) becomes
5493 instruct xaddL_immRot_no_res(memoryex mem, immLlowRot add, Universe dummy, iRegLd tmp1, iRegI tmp2, flagsReg ccr) %{
5494 predicate(n->as_LoadStore()->result_not_used());
5495 match(Set dummy (GetAndAddL mem add));
5496 effect( KILL ccr, TEMP tmp1, TEMP tmp2);
5497 size(24);
5498 format %{ "loop: \n\t"
5499 "LDREXD $tmp1, $mem\n\t"
5500 "ADDS $tmp1.lo, $tmp1.lo, $add\n\t"
5501 "ADC $tmp1.hi, $tmp1.hi, 0\n\t"
5502 "STREXD $tmp2, $tmp1, $mem\n\t"
5503 "CMP $tmp2, 0 \n\t"
5504 "B.ne loop \n\t" %}
5505
5506 ins_encode %{
5507 Label loop;
5508 __ bind(loop);
5509 __ ldrexd($tmp1$$Register, $mem$$Address);
5510 __ adds($tmp1$$Register, $tmp1$$Register, $add$$constant);
5511 __ adc($tmp1$$Register->successor(), $tmp1$$Register->successor(), 0);
5512 __ strexd($tmp2$$Register, $tmp1$$Register, $mem$$Address);
5513 __ cmp($tmp2$$Register, 0);
5514 __ b(loop, ne);
5515 %}
5516 ins_pipe( long_memory_op );
5517 %}
5518
5519 instruct xaddL_reg(memoryex mem, iRegL add, iRegLd res, iRegLd tmp1, iRegI tmp2, flagsReg ccr) %{
5520 match(Set res (GetAndAddL mem add));
5521 effect( KILL ccr, TEMP tmp1, TEMP tmp2, TEMP res);
5522 size(24);
5523 format %{ "loop: \n\t"
5524 "LDREXD $res, $mem\n\t"
5525 "ADDS $tmp1.lo, $res.lo, $add.lo\n\t"
5526 "ADC $tmp1.hi, $res.hi, $add.hi\n\t"
5527 "STREXD $tmp2, $tmp1, $mem\n\t"
5528 "CMP $tmp2, 0 \n\t"
5529 "B.ne loop \n\t" %}
5530
5531 ins_encode %{
5532 Label loop;
5533 __ bind(loop);
5534 __ ldrexd($res$$Register, $mem$$Address);
5535 __ adds($tmp1$$Register, $res$$Register, $add$$Register);
5536 __ adc($tmp1$$Register->successor(), $res$$Register->successor(), $add$$Register->successor());
5537 __ strexd($tmp2$$Register, $tmp1$$Register, $mem$$Address);
5538 __ cmp($tmp2$$Register, 0);
5539 __ b(loop, ne);
5540 %}
5541 ins_pipe( long_memory_op );
5542 %}
5543
5544 // TODO: try immLRot2 instead, (0, $con$$constant) becomes
5545 // (hi($con$$constant), lo($con$$constant)) becomes
5546 instruct xaddL_immRot(memoryex mem, immLlowRot add, iRegLd res, iRegLd tmp1, iRegI tmp2, flagsReg ccr) %{
5547 match(Set res (GetAndAddL mem add));
5548 effect( KILL ccr, TEMP tmp1, TEMP tmp2, TEMP res);
5549 size(24);
5550 format %{ "loop: \n\t"
5551 "LDREXD $res, $mem\n\t"
5552 "ADDS $tmp1.lo, $res.lo, $add\n\t"
5553 "ADC $tmp1.hi, $res.hi, 0\n\t"
5554 "STREXD $tmp2, $tmp1, $mem\n\t"
5555 "CMP $tmp2, 0 \n\t"
5556 "B.ne loop \n\t" %}
5557
5558 ins_encode %{
5559 Label loop;
5560 __ bind(loop);
5561 __ ldrexd($res$$Register, $mem$$Address);
5562 __ adds($tmp1$$Register, $res$$Register, $add$$constant);
5563 __ adc($tmp1$$Register->successor(), $res$$Register->successor(), 0);
5564 __ strexd($tmp2$$Register, $tmp1$$Register, $mem$$Address);
5565 __ cmp($tmp2$$Register, 0);
5566 __ b(loop, ne);
5567 %}
5568 ins_pipe( long_memory_op );
5569 %}
5570
5571 instruct xchgI(memoryex mem, iRegI newval, iRegI res, iRegI tmp, flagsReg ccr) %{
5572 match(Set res (GetAndSetI mem newval));
5573 effect(KILL ccr, TEMP tmp, TEMP res);
5574 size(16);
5575 format %{ "loop: \n\t"
5576 "LDREX $res, $mem\n\t"
5577 "STREX $tmp, $newval, $mem\n\t"
5578 "CMP $tmp, 0 \n\t"
5579 "B.ne loop \n\t" %}
5580
5581 ins_encode %{
5582 Label loop;
5583 __ bind(loop);
5584 __ ldrex($res$$Register,$mem$$Address);
5585 __ strex($tmp$$Register, $newval$$Register, $mem$$Address);
5586 __ cmp($tmp$$Register, 0);
5587 __ b(loop, ne);
5588 %}
5589 ins_pipe( long_memory_op );
5590 %}
5591
5592 instruct xchgL(memoryex mem, iRegLd newval, iRegLd res, iRegI tmp, flagsReg ccr) %{
5593 match(Set res (GetAndSetL mem newval));
5594 effect( KILL ccr, TEMP tmp, TEMP res);
5595 size(16);
5596 format %{ "loop: \n\t"
5597 "LDREXD $res, $mem\n\t"
5598 "STREXD $tmp, $newval, $mem\n\t"
5599 "CMP $tmp, 0 \n\t"
5600 "B.ne loop \n\t" %}
5601
5602 ins_encode %{
5603 Label loop;
5604 __ bind(loop);
5605 __ ldrexd($res$$Register, $mem$$Address);
5606 __ strexd($tmp$$Register, $newval$$Register, $mem$$Address);
5607 __ cmp($tmp$$Register, 0);
5608 __ b(loop, ne);
5609 %}
5610 ins_pipe( long_memory_op );
5611 %}
5612
5613 instruct xchgP(memoryex mem, iRegP newval, iRegP res, iRegI tmp, flagsReg ccr) %{
5614 predicate(!(UseG1GC && n->as_LoadStore()->barrier_data() != 0));
5615 match(Set res (GetAndSetP mem newval));
5616 effect(KILL ccr, TEMP tmp, TEMP res);
5617 size(16);
5618 format %{ "loop: \n\t"
5619 "LDREX $res, $mem\n\t"
5620 "STREX $tmp, $newval, $mem\n\t"
5621 "CMP $tmp, 0 \n\t"
5622 "B.ne loop \n\t" %}
5623
5624 ins_encode %{
5625 Label loop;
5626 __ bind(loop);
5627 __ ldrex($res$$Register,$mem$$Address);
5628 __ strex($tmp$$Register, $newval$$Register, $mem$$Address);
5629 __ cmp($tmp$$Register, 0);
5630 __ b(loop, ne);
5631 %}
5632 ins_pipe( long_memory_op );
5633 %}
5634
5635 //---------------------
5636 // Subtraction Instructions
5637 // Register Subtraction
5638 instruct subI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{
5639 match(Set dst (SubI src1 src2));
5640
5641 size(4);
5642 format %{ "sub_32 $dst,$src1,$src2\t! int" %}
5643 ins_encode %{
5644 __ sub_32($dst$$Register, $src1$$Register, $src2$$Register);
5645 %}
5646 ins_pipe(ialu_reg_reg);
5647 %}
5648
5649 instruct subshlI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
5650 match(Set dst (SubI src1 (LShiftI src2 src3)));
5651
5652 size(4);
5653 format %{ "SUB $dst,$src1,$src2<<$src3" %}
5654 ins_encode %{
5655 __ sub($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$Register));
5656 %}
5657 ins_pipe(ialu_reg_reg);
5658 %}
5659
5660 instruct subshlI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{
5661 match(Set dst (SubI src1 (LShiftI src2 src3)));
5662
5663 size(4);
5664 format %{ "sub_32 $dst,$src1,$src2<<$src3\t! int" %}
5665 ins_encode %{
5666 __ sub_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$constant));
5667 %}
5668 ins_pipe(ialu_reg_reg);
5669 %}
5670
5671 instruct subsarI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
5672 match(Set dst (SubI src1 (RShiftI src2 src3)));
5673
5674 size(4);
5675 format %{ "SUB $dst,$src1,$src2>>$src3" %}
5676 ins_encode %{
5677 __ sub($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$Register));
5678 %}
5679 ins_pipe(ialu_reg_reg);
5680 %}
5681
5682 instruct subsarI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{
5683 match(Set dst (SubI src1 (RShiftI src2 src3)));
5684
5685 size(4);
5686 format %{ "sub_32 $dst,$src1,$src2>>$src3\t! int" %}
5687 ins_encode %{
5688 __ sub_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$constant));
5689 %}
5690 ins_pipe(ialu_reg_reg);
5691 %}
5692
5693 instruct subshrI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
5694 match(Set dst (SubI src1 (URShiftI src2 src3)));
5695
5696 size(4);
5697 format %{ "SUB $dst,$src1,$src2>>>$src3" %}
5698 ins_encode %{
5699 __ sub($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$Register));
5700 %}
5701 ins_pipe(ialu_reg_reg);
5702 %}
5703
5704 instruct subshrI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{
5705 match(Set dst (SubI src1 (URShiftI src2 src3)));
5706
5707 size(4);
5708 format %{ "sub_32 $dst,$src1,$src2>>>$src3\t! int" %}
5709 ins_encode %{
5710 __ sub_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$constant));
5711 %}
5712 ins_pipe(ialu_reg_reg);
5713 %}
5714
5715 instruct rsbshlI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
5716 match(Set dst (SubI (LShiftI src1 src2) src3));
5717
5718 size(4);
5719 format %{ "RSB $dst,$src3,$src1<<$src2" %}
5720 ins_encode %{
5721 __ rsb($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsl, $src2$$Register));
5722 %}
5723 ins_pipe(ialu_reg_reg);
5724 %}
5725
5726 instruct rsbshlI_reg_imm_reg(iRegI dst, iRegI src1, immU5 src2, iRegI src3) %{
5727 match(Set dst (SubI (LShiftI src1 src2) src3));
5728
5729 size(4);
5730 format %{ "RSB $dst,$src3,$src1<<$src2" %}
5731 ins_encode %{
5732 __ rsb($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsl, $src2$$constant));
5733 %}
5734 ins_pipe(ialu_reg_reg);
5735 %}
5736
5737 instruct rsbsarI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
5738 match(Set dst (SubI (RShiftI src1 src2) src3));
5739
5740 size(4);
5741 format %{ "RSB $dst,$src3,$src1>>$src2" %}
5742 ins_encode %{
5743 __ rsb($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, asr, $src2$$Register));
5744 %}
5745 ins_pipe(ialu_reg_reg);
5746 %}
5747
5748 instruct rsbsarI_reg_imm_reg(iRegI dst, iRegI src1, immU5 src2, iRegI src3) %{
5749 match(Set dst (SubI (RShiftI src1 src2) src3));
5750
5751 size(4);
5752 format %{ "RSB $dst,$src3,$src1>>$src2" %}
5753 ins_encode %{
5754 __ rsb($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, asr, $src2$$constant));
5755 %}
5756 ins_pipe(ialu_reg_reg);
5757 %}
5758
5759 instruct rsbshrI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
5760 match(Set dst (SubI (URShiftI src1 src2) src3));
5761
5762 size(4);
5763 format %{ "RSB $dst,$src3,$src1>>>$src2" %}
5764 ins_encode %{
5765 __ rsb($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsr, $src2$$Register));
5766 %}
5767 ins_pipe(ialu_reg_reg);
5768 %}
5769
5770 instruct rsbshrI_reg_imm_reg(iRegI dst, iRegI src1, immU5 src2, iRegI src3) %{
5771 match(Set dst (SubI (URShiftI src1 src2) src3));
5772
5773 size(4);
5774 format %{ "RSB $dst,$src3,$src1>>>$src2" %}
5775 ins_encode %{
5776 __ rsb($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsr, $src2$$constant));
5777 %}
5778 ins_pipe(ialu_reg_reg);
5779 %}
5780
5781 // Immediate Subtraction
5782 instruct subI_reg_aimmI(iRegI dst, iRegI src1, aimmI src2) %{
5783 match(Set dst (SubI src1 src2));
5784
5785 size(4);
5786 format %{ "sub_32 $dst,$src1,$src2\t! int" %}
5787 ins_encode %{
5788 __ sub_32($dst$$Register, $src1$$Register, $src2$$constant);
5789 %}
5790 ins_pipe(ialu_reg_imm);
5791 %}
5792
5793 instruct subI_reg_immRotneg(iRegI dst, iRegI src1, aimmIneg src2) %{
5794 match(Set dst (AddI src1 src2));
5795
5796 size(4);
5797 format %{ "sub_32 $dst,$src1,-($src2)\t! int" %}
5798 ins_encode %{
5799 __ sub_32($dst$$Register, $src1$$Register, -$src2$$constant);
5800 %}
5801 ins_pipe(ialu_reg_imm);
5802 %}
5803
5804 instruct subI_immRot_reg(iRegI dst, immIRot src1, iRegI src2) %{
5805 match(Set dst (SubI src1 src2));
5806
5807 size(4);
5808 format %{ "RSB $dst,$src2,src1" %}
5809 ins_encode %{
5810 __ rsb($dst$$Register, $src2$$Register, $src1$$constant);
5811 %}
5812 ins_pipe(ialu_zero_reg);
5813 %}
5814
5815 // Register Subtraction
5816 instruct subL_reg_reg(iRegL dst, iRegL src1, iRegL src2, flagsReg icc ) %{
5817 match(Set dst (SubL src1 src2));
5818 effect (KILL icc);
5819
5820 size(8);
5821 format %{ "SUBS $dst.lo,$src1.lo,$src2.lo\t! long\n\t"
5822 "SBC $dst.hi,$src1.hi,$src2.hi" %}
5823 ins_encode %{
5824 __ subs($dst$$Register, $src1$$Register, $src2$$Register);
5825 __ sbc($dst$$Register->successor(), $src1$$Register->successor(), $src2$$Register->successor());
5826 %}
5827 ins_pipe(ialu_reg_reg);
5828 %}
5829
5830 // TODO
5831
5832 // Immediate Subtraction
5833 // TODO: try immLRot2 instead, (0, $con$$constant) becomes
5834 // (hi($con$$constant), lo($con$$constant)) becomes
5835 instruct subL_reg_immRot(iRegL dst, iRegL src1, immLlowRot con, flagsReg icc) %{
5836 match(Set dst (SubL src1 con));
5837 effect (KILL icc);
5838
5839 size(8);
5840 format %{ "SUB $dst.lo,$src1.lo,$con\t! long\n\t"
5841 "SBC $dst.hi,$src1.hi,0" %}
5842 ins_encode %{
5843 __ subs($dst$$Register, $src1$$Register, $con$$constant);
5844 __ sbc($dst$$Register->successor(), $src1$$Register->successor(), 0);
5845 %}
5846 ins_pipe(ialu_reg_imm);
5847 %}
5848
5849 // Long negation
5850 instruct negL_reg_reg(iRegL dst, immL0 zero, iRegL src2, flagsReg icc) %{
5851 match(Set dst (SubL zero src2));
5852 effect (KILL icc);
5853
5854 size(8);
5855 format %{ "RSBS $dst.lo,$src2.lo,0\t! long\n\t"
5856 "RSC $dst.hi,$src2.hi,0" %}
5857 ins_encode %{
5858 __ rsbs($dst$$Register, $src2$$Register, 0);
5859 __ rsc($dst$$Register->successor(), $src2$$Register->successor(), 0);
5860 %}
5861 ins_pipe(ialu_zero_reg);
5862 %}
5863
5864 // Multiplication Instructions
5865 // Integer Multiplication
5866 // Register Multiplication
5867 instruct mulI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{
5868 match(Set dst (MulI src1 src2));
5869
5870 size(4);
5871 format %{ "mul_32 $dst,$src1,$src2" %}
5872 ins_encode %{
5873 __ mul_32($dst$$Register, $src1$$Register, $src2$$Register);
5874 %}
5875 ins_pipe(imul_reg_reg);
5876 %}
5877
5878 instruct mulL_lo1_hi2(iRegL dst, iRegL src1, iRegL src2) %{
5879 effect(DEF dst, USE src1, USE src2);
5880 size(4);
5881 format %{ "MUL $dst.hi,$src1.lo,$src2.hi\t! long" %}
5882 ins_encode %{
5883 __ mul($dst$$Register->successor(), $src1$$Register, $src2$$Register->successor());
5884 %}
5885 ins_pipe(imul_reg_reg);
5886 %}
5887
5888 instruct mulL_hi1_lo2(iRegL dst, iRegL src1, iRegL src2) %{
5889 effect(USE_DEF dst, USE src1, USE src2);
5890 size(8);
5891 format %{ "MLA $dst.hi,$src1.hi,$src2.lo,$dst.hi\t! long\n\t"
5892 "MOV $dst.lo, 0"%}
5893 ins_encode %{
5894 __ mla($dst$$Register->successor(), $src1$$Register->successor(), $src2$$Register, $dst$$Register->successor());
5895 __ mov($dst$$Register, 0);
5896 %}
5897 ins_pipe(imul_reg_reg);
5898 %}
5899
5900 instruct mulL_lo1_lo2(iRegL dst, iRegL src1, iRegL src2) %{
5901 effect(USE_DEF dst, USE src1, USE src2);
5902 size(4);
5903 format %{ "UMLAL $dst.lo,$dst.hi,$src1,$src2\t! long" %}
5904 ins_encode %{
5905 __ umlal($dst$$Register, $dst$$Register->successor(), $src1$$Register, $src2$$Register);
5906 %}
5907 ins_pipe(imul_reg_reg);
5908 %}
5909
5910 instruct mulL_reg_reg(iRegL dst, iRegL src1, iRegL src2) %{
5911 match(Set dst (MulL src1 src2));
5912
5913 expand %{
5914 mulL_lo1_hi2(dst, src1, src2);
5915 mulL_hi1_lo2(dst, src1, src2);
5916 mulL_lo1_lo2(dst, src1, src2);
5917 %}
5918 %}
5919
5920 // Integer Division
5921 // Register Division
5922 instruct divI_reg_reg(R1RegI dst, R0RegI src1, R2RegI src2, LRRegP lr, flagsReg ccr) %{
5923 match(Set dst (DivI src1 src2));
5924 effect( KILL ccr, KILL src1, KILL src2, KILL lr);
5925 ins_cost((2+71)*DEFAULT_COST);
5926
5927 format %{ "DIV $dst,$src1,$src2 ! call to StubRoutines::Arm::idiv_irem_entry()" %}
5928 ins_encode %{
5929 __ call(StubRoutines::Arm::idiv_irem_entry(), relocInfo::runtime_call_type);
5930 %}
5931 ins_pipe(sdiv_reg_reg);
5932 %}
5933
5934 // Register Long Division
5935 instruct divL_reg_reg(R0R1RegL dst, R2R3RegL src1, R0R1RegL src2) %{
5936 match(Set dst (DivL src1 src2));
5937 effect(CALL);
5938 ins_cost(DEFAULT_COST*71);
5939 format %{ "DIVL $src1,$src2,$dst\t! long ! call to SharedRuntime::ldiv" %}
5940 ins_encode %{
5941 address target = CAST_FROM_FN_PTR(address, SharedRuntime::ldiv);
5942 __ call(target, relocInfo::runtime_call_type);
5943 %}
5944 ins_pipe(divL_reg_reg);
5945 %}
5946
5947 // Integer Remainder
5948 // Register Remainder
5949 instruct modI_reg_reg(R0RegI dst, R0RegI src1, R2RegI src2, R1RegI temp, LRRegP lr, flagsReg ccr ) %{
5950 match(Set dst (ModI src1 src2));
5951 effect( KILL ccr, KILL temp, KILL src2, KILL lr);
5952
5953 format %{ "MODI $dst,$src1,$src2\t ! call to StubRoutines::Arm::idiv_irem_entry" %}
5954 ins_encode %{
5955 __ call(StubRoutines::Arm::idiv_irem_entry(), relocInfo::runtime_call_type);
5956 %}
5957 ins_pipe(sdiv_reg_reg);
5958 %}
5959
5960 // Register Long Remainder
5961 instruct modL_reg_reg(R0R1RegL dst, R2R3RegL src1, R0R1RegL src2) %{
5962 match(Set dst (ModL src1 src2));
5963 effect(CALL);
5964 ins_cost(MEMORY_REF_COST); // FIXME
5965 format %{ "modL $dst,$src1,$src2\t ! call to SharedRuntime::lrem" %}
5966 ins_encode %{
5967 address target = CAST_FROM_FN_PTR(address, SharedRuntime::lrem);
5968 __ call(target, relocInfo::runtime_call_type);
5969 %}
5970 ins_pipe(divL_reg_reg);
5971 %}
5972
5973 // Integer Shift Instructions
5974
5975 // Register Shift Left
5976 instruct shlI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{
5977 match(Set dst (LShiftI src1 src2));
5978
5979 size(4);
5980 format %{ "LSL $dst,$src1,$src2 \n\t" %}
5981 ins_encode %{
5982 __ mov($dst$$Register, AsmOperand($src1$$Register, lsl, $src2$$Register));
5983 %}
5984 ins_pipe(ialu_reg_reg);
5985 %}
5986
5987 // Register Shift Left Immediate
5988 instruct shlI_reg_imm5(iRegI dst, iRegI src1, immU5 src2) %{
5989 match(Set dst (LShiftI src1 src2));
5990
5991 size(4);
5992 format %{ "LSL $dst,$src1,$src2\t! int" %}
5993 ins_encode %{
5994 __ logical_shift_left($dst$$Register, $src1$$Register, $src2$$constant);
5995 %}
5996 ins_pipe(ialu_reg_imm);
5997 %}
5998
5999 instruct shlL_reg_reg_merge_hi(iRegL dst, iRegL src1, iRegI src2) %{
6000 effect(USE_DEF dst, USE src1, USE src2);
6001 size(4);
6002 format %{"OR $dst.hi,$dst.hi,($src1.hi << $src2)" %}
6003 ins_encode %{
6004 __ orr($dst$$Register->successor(), $dst$$Register->successor(), AsmOperand($src1$$Register->successor(), lsl, $src2$$Register));
6005 %}
6006 ins_pipe(ialu_reg_reg);
6007 %}
6008
6009 instruct shlL_reg_reg_merge_lo(iRegL dst, iRegL src1, iRegI src2) %{
6010 effect(USE_DEF dst, USE src1, USE src2);
6011 size(4);
6012 format %{ "LSL $dst.lo,$src1.lo,$src2 \n\t" %}
6013 ins_encode %{
6014 __ mov($dst$$Register, AsmOperand($src1$$Register, lsl, $src2$$Register));
6015 %}
6016 ins_pipe(ialu_reg_reg);
6017 %}
6018
6019 instruct shlL_reg_reg_overlap(iRegL dst, iRegL src1, iRegI src2, flagsReg ccr) %{
6020 effect(DEF dst, USE src1, USE src2, KILL ccr);
6021 size(16);
6022 format %{ "SUBS $dst.hi,$src2,32 \n\t"
6023 "LSLpl $dst.hi,$src1.lo,$dst.hi \n\t"
6024 "RSBmi $dst.hi,$dst.hi,0 \n\t"
6025 "LSRmi $dst.hi,$src1.lo,$dst.hi" %}
6026
6027 ins_encode %{
6028 // $src1$$Register and $dst$$Register->successor() can't be the same
6029 __ subs($dst$$Register->successor(), $src2$$Register, 32);
6030 __ mov($dst$$Register->successor(), AsmOperand($src1$$Register, lsl, $dst$$Register->successor()), pl);
6031 __ rsb($dst$$Register->successor(), $dst$$Register->successor(), 0, mi);
6032 __ mov($dst$$Register->successor(), AsmOperand($src1$$Register, lsr, $dst$$Register->successor()), mi);
6033 %}
6034 ins_pipe(ialu_reg_reg);
6035 %}
6036
6037 instruct shlL_reg_reg(iRegL dst, iRegL src1, iRegI src2) %{
6038 match(Set dst (LShiftL src1 src2));
6039
6040 expand %{
6041 flagsReg ccr;
6042 shlL_reg_reg_overlap(dst, src1, src2, ccr);
6043 shlL_reg_reg_merge_hi(dst, src1, src2);
6044 shlL_reg_reg_merge_lo(dst, src1, src2);
6045 %}
6046 %}
6047
6048 // Register Shift Left Immediate
6049 instruct shlL_reg_imm6(iRegL dst, iRegL src1, immU6Big src2) %{
6050 match(Set dst (LShiftL src1 src2));
6051
6052 size(8);
6053 format %{ "LSL $dst.hi,$src1.lo,$src2-32\t! or mov if $src2==32\n\t"
6054 "MOV $dst.lo, 0" %}
6055 ins_encode %{
6056 if ($src2$$constant == 32) {
6057 __ mov($dst$$Register->successor(), $src1$$Register);
6058 } else {
6059 __ mov($dst$$Register->successor(), AsmOperand($src1$$Register, lsl, $src2$$constant-32));
6060 }
6061 __ mov($dst$$Register, 0);
6062 %}
6063 ins_pipe(ialu_reg_imm);
6064 %}
6065
6066 instruct shlL_reg_imm5(iRegL dst, iRegL src1, immU5 src2) %{
6067 match(Set dst (LShiftL src1 src2));
6068
6069 size(12);
6070 format %{ "LSL $dst.hi,$src1.lo,$src2\n\t"
6071 "OR $dst.hi, $dst.hi, $src1.lo >> 32-$src2\n\t"
6072 "LSL $dst.lo,$src1.lo,$src2" %}
6073 ins_encode %{
6074 // The order of the following 3 instructions matters: src1.lo and
6075 // dst.hi can't overlap but src.hi and dst.hi can.
6076 __ mov($dst$$Register->successor(), AsmOperand($src1$$Register->successor(), lsl, $src2$$constant));
6077 __ orr($dst$$Register->successor(), $dst$$Register->successor(), AsmOperand($src1$$Register, lsr, 32-$src2$$constant));
6078 __ mov($dst$$Register, AsmOperand($src1$$Register, lsl, $src2$$constant));
6079 %}
6080 ins_pipe(ialu_reg_imm);
6081 %}
6082
6083 // Register Arithmetic Shift Right
6084 instruct sarI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{
6085 match(Set dst (RShiftI src1 src2));
6086 size(4);
6087 format %{ "ASR $dst,$src1,$src2\t! int" %}
6088 ins_encode %{
6089 __ mov($dst$$Register, AsmOperand($src1$$Register, asr, $src2$$Register));
6090 %}
6091 ins_pipe(ialu_reg_reg);
6092 %}
6093
6094 // Register Arithmetic Shift Right Immediate
6095 instruct sarI_reg_imm5(iRegI dst, iRegI src1, immU5 src2) %{
6096 match(Set dst (RShiftI src1 src2));
6097
6098 size(4);
6099 format %{ "ASR $dst,$src1,$src2" %}
6100 ins_encode %{
6101 __ mov($dst$$Register, AsmOperand($src1$$Register, asr, $src2$$constant));
6102 %}
6103 ins_pipe(ialu_reg_imm);
6104 %}
6105
6106 // Register Shift Right Arithmetic Long
6107 instruct sarL_reg_reg_merge_lo(iRegL dst, iRegL src1, iRegI src2) %{
6108 effect(USE_DEF dst, USE src1, USE src2);
6109 size(4);
6110 format %{ "OR $dst.lo,$dst.lo,($src1.lo >> $src2)" %}
6111 ins_encode %{
6112 __ orr($dst$$Register, $dst$$Register, AsmOperand($src1$$Register, lsr, $src2$$Register));
6113 %}
6114 ins_pipe(ialu_reg_reg);
6115 %}
6116
6117 instruct sarL_reg_reg_merge_hi(iRegL dst, iRegL src1, iRegI src2) %{
6118 effect(USE_DEF dst, USE src1, USE src2);
6119 size(4);
6120 format %{ "ASR $dst.hi,$src1.hi,$src2 \n\t" %}
6121 ins_encode %{
6122 __ mov($dst$$Register->successor(), AsmOperand($src1$$Register->successor(), asr, $src2$$Register));
6123 %}
6124 ins_pipe(ialu_reg_reg);
6125 %}
6126
6127 instruct sarL_reg_reg_overlap(iRegL dst, iRegL src1, iRegI src2, flagsReg ccr) %{
6128 effect(DEF dst, USE src1, USE src2, KILL ccr);
6129 size(16);
6130 format %{ "SUBS $dst.lo,$src2,32 \n\t"
6131 "ASRpl $dst.lo,$src1.hi,$dst.lo \n\t"
6132 "RSBmi $dst.lo,$dst.lo,0 \n\t"
6133 "LSLmi $dst.lo,$src1.hi,$dst.lo" %}
6134
6135 ins_encode %{
6136 // $src1$$Register->successor() and $dst$$Register can't be the same
6137 __ subs($dst$$Register, $src2$$Register, 32);
6138 __ mov($dst$$Register, AsmOperand($src1$$Register->successor(), asr, $dst$$Register), pl);
6139 __ rsb($dst$$Register, $dst$$Register, 0, mi);
6140 __ mov($dst$$Register, AsmOperand($src1$$Register->successor(), lsl, $dst$$Register), mi);
6141 %}
6142 ins_pipe(ialu_reg_reg);
6143 %}
6144
6145 instruct sarL_reg_reg(iRegL dst, iRegL src1, iRegI src2) %{
6146 match(Set dst (RShiftL src1 src2));
6147
6148 expand %{
6149 flagsReg ccr;
6150 sarL_reg_reg_overlap(dst, src1, src2, ccr);
6151 sarL_reg_reg_merge_lo(dst, src1, src2);
6152 sarL_reg_reg_merge_hi(dst, src1, src2);
6153 %}
6154 %}
6155
6156 // Register Shift Left Immediate
6157 instruct sarL_reg_imm6(iRegL dst, iRegL src1, immU6Big src2) %{
6158 match(Set dst (RShiftL src1 src2));
6159
6160 size(8);
6161 format %{ "ASR $dst.lo,$src1.hi,$src2-32\t! or mov if $src2==32\n\t"
6162 "ASR $dst.hi,$src1.hi, $src2" %}
6163 ins_encode %{
6164 if ($src2$$constant == 32) {
6165 __ mov($dst$$Register, $src1$$Register->successor());
6166 } else{
6167 __ mov($dst$$Register, AsmOperand($src1$$Register->successor(), asr, $src2$$constant-32));
6168 }
6169 __ mov($dst$$Register->successor(), AsmOperand($src1$$Register->successor(), asr, 0));
6170 %}
6171
6172 ins_pipe(ialu_reg_imm);
6173 %}
6174
6175 instruct sarL_reg_imm5(iRegL dst, iRegL src1, immU5 src2) %{
6176 match(Set dst (RShiftL src1 src2));
6177 size(12);
6178 format %{ "LSR $dst.lo,$src1.lo,$src2\n\t"
6179 "OR $dst.lo, $dst.lo, $src1.hi << 32-$src2\n\t"
6180 "ASR $dst.hi,$src1.hi,$src2" %}
6181 ins_encode %{
6182 // The order of the following 3 instructions matters: src1.lo and
6183 // dst.hi can't overlap but src.hi and dst.hi can.
6184 __ mov($dst$$Register, AsmOperand($src1$$Register, lsr, $src2$$constant));
6185 __ orr($dst$$Register, $dst$$Register, AsmOperand($src1$$Register->successor(), lsl, 32-$src2$$constant));
6186 __ mov($dst$$Register->successor(), AsmOperand($src1$$Register->successor(), asr, $src2$$constant));
6187 %}
6188 ins_pipe(ialu_reg_imm);
6189 %}
6190
6191 // Register Shift Right
6192 instruct shrI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{
6193 match(Set dst (URShiftI src1 src2));
6194 size(4);
6195 format %{ "LSR $dst,$src1,$src2\t! int" %}
6196 ins_encode %{
6197 __ mov($dst$$Register, AsmOperand($src1$$Register, lsr, $src2$$Register));
6198 %}
6199 ins_pipe(ialu_reg_reg);
6200 %}
6201
6202 // Register Shift Right Immediate
6203 instruct shrI_reg_imm5(iRegI dst, iRegI src1, immU5 src2) %{
6204 match(Set dst (URShiftI src1 src2));
6205
6206 size(4);
6207 format %{ "LSR $dst,$src1,$src2" %}
6208 ins_encode %{
6209 __ mov($dst$$Register, AsmOperand($src1$$Register, lsr, $src2$$constant));
6210 %}
6211 ins_pipe(ialu_reg_imm);
6212 %}
6213
6214 // Register Shift Right
6215 instruct shrL_reg_reg_merge_lo(iRegL dst, iRegL src1, iRegI src2) %{
6216 effect(USE_DEF dst, USE src1, USE src2);
6217 size(4);
6218 format %{ "OR $dst.lo,$dst,($src1.lo >>> $src2)" %}
6219 ins_encode %{
6220 __ orr($dst$$Register, $dst$$Register, AsmOperand($src1$$Register, lsr, $src2$$Register));
6221 %}
6222 ins_pipe(ialu_reg_reg);
6223 %}
6224
6225 instruct shrL_reg_reg_merge_hi(iRegL dst, iRegL src1, iRegI src2) %{
6226 effect(USE_DEF dst, USE src1, USE src2);
6227 size(4);
6228 format %{ "LSR $dst.hi,$src1.hi,$src2 \n\t" %}
6229 ins_encode %{
6230 __ mov($dst$$Register->successor(), AsmOperand($src1$$Register->successor(), lsr, $src2$$Register));
6231 %}
6232 ins_pipe(ialu_reg_reg);
6233 %}
6234
6235 instruct shrL_reg_reg_overlap(iRegL dst, iRegL src1, iRegI src2, flagsReg ccr) %{
6236 effect(DEF dst, USE src1, USE src2, KILL ccr);
6237 size(16);
6238 format %{ "SUBS $dst,$src2,32 \n\t"
6239 "LSRpl $dst,$src1.hi,$dst \n\t"
6240 "RSBmi $dst,$dst,0 \n\t"
6241 "LSLmi $dst,$src1.hi,$dst" %}
6242
6243 ins_encode %{
6244 // $src1$$Register->successor() and $dst$$Register can't be the same
6245 __ subs($dst$$Register, $src2$$Register, 32);
6246 __ mov($dst$$Register, AsmOperand($src1$$Register->successor(), lsr, $dst$$Register), pl);
6247 __ rsb($dst$$Register, $dst$$Register, 0, mi);
6248 __ mov($dst$$Register, AsmOperand($src1$$Register->successor(), lsl, $dst$$Register), mi);
6249 %}
6250 ins_pipe(ialu_reg_reg);
6251 %}
6252
6253 instruct shrL_reg_reg(iRegL dst, iRegL src1, iRegI src2) %{
6254 match(Set dst (URShiftL src1 src2));
6255
6256 expand %{
6257 flagsReg ccr;
6258 shrL_reg_reg_overlap(dst, src1, src2, ccr);
6259 shrL_reg_reg_merge_lo(dst, src1, src2);
6260 shrL_reg_reg_merge_hi(dst, src1, src2);
6261 %}
6262 %}
6263
6264 // Register Shift Right Immediate
6265 instruct shrL_reg_imm6(iRegL dst, iRegL src1, immU6Big src2) %{
6266 match(Set dst (URShiftL src1 src2));
6267
6268 size(8);
6269 format %{ "LSR $dst.lo,$src1.hi,$src2-32\t! or mov if $src2==32\n\t"
6270 "MOV $dst.hi, 0" %}
6271 ins_encode %{
6272 if ($src2$$constant == 32) {
6273 __ mov($dst$$Register, $src1$$Register->successor());
6274 } else {
6275 __ mov($dst$$Register, AsmOperand($src1$$Register->successor(), lsr, $src2$$constant-32));
6276 }
6277 __ mov($dst$$Register->successor(), 0);
6278 %}
6279
6280 ins_pipe(ialu_reg_imm);
6281 %}
6282
6283 instruct shrL_reg_imm5(iRegL dst, iRegL src1, immU5 src2) %{
6284 match(Set dst (URShiftL src1 src2));
6285
6286 size(12);
6287 format %{ "LSR $dst.lo,$src1.lo,$src2\n\t"
6288 "OR $dst.lo, $dst.lo, $src1.hi << 32-$src2\n\t"
6289 "LSR $dst.hi,$src1.hi,$src2" %}
6290 ins_encode %{
6291 // The order of the following 3 instructions matters: src1.lo and
6292 // dst.hi can't overlap but src.hi and dst.hi can.
6293 __ mov($dst$$Register, AsmOperand($src1$$Register, lsr, $src2$$constant));
6294 __ orr($dst$$Register, $dst$$Register, AsmOperand($src1$$Register->successor(), lsl, 32-$src2$$constant));
6295 __ mov($dst$$Register->successor(), AsmOperand($src1$$Register->successor(), lsr, $src2$$constant));
6296 %}
6297 ins_pipe(ialu_reg_imm);
6298 %}
6299
6300
6301 instruct shrP_reg_imm5(iRegX dst, iRegP src1, immU5 src2) %{
6302 match(Set dst (URShiftI (CastP2X src1) src2));
6303 size(4);
6304 format %{ "LSR $dst,$src1,$src2\t! Cast ptr $src1 to int and shift" %}
6305 ins_encode %{
6306 __ logical_shift_right($dst$$Register, $src1$$Register, $src2$$constant);
6307 %}
6308 ins_pipe(ialu_reg_imm);
6309 %}
6310
6311 //----------Floating Point Arithmetic Instructions-----------------------------
6312
6313 // Add float single precision
6314 instruct addF_reg_reg(regF dst, regF src1, regF src2) %{
6315 match(Set dst (AddF src1 src2));
6316
6317 size(4);
6318 format %{ "FADDS $dst,$src1,$src2" %}
6319 ins_encode %{
6320 __ add_float($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
6321 %}
6322
6323 ins_pipe(faddF_reg_reg);
6324 %}
6325
6326 // Add float double precision
6327 instruct addD_reg_reg(regD dst, regD src1, regD src2) %{
6328 match(Set dst (AddD src1 src2));
6329
6330 size(4);
6331 format %{ "FADDD $dst,$src1,$src2" %}
6332 ins_encode %{
6333 __ add_double($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
6334 %}
6335
6336 ins_pipe(faddD_reg_reg);
6337 %}
6338
6339 // Sub float single precision
6340 instruct subF_reg_reg(regF dst, regF src1, regF src2) %{
6341 match(Set dst (SubF src1 src2));
6342
6343 size(4);
6344 format %{ "FSUBS $dst,$src1,$src2" %}
6345 ins_encode %{
6346 __ sub_float($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
6347 %}
6348 ins_pipe(faddF_reg_reg);
6349 %}
6350
6351 // Sub float double precision
6352 instruct subD_reg_reg(regD dst, regD src1, regD src2) %{
6353 match(Set dst (SubD src1 src2));
6354
6355 size(4);
6356 format %{ "FSUBD $dst,$src1,$src2" %}
6357 ins_encode %{
6358 __ sub_double($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
6359 %}
6360 ins_pipe(faddD_reg_reg);
6361 %}
6362
6363 // Mul float single precision
6364 instruct mulF_reg_reg(regF dst, regF src1, regF src2) %{
6365 match(Set dst (MulF src1 src2));
6366
6367 size(4);
6368 format %{ "FMULS $dst,$src1,$src2" %}
6369 ins_encode %{
6370 __ mul_float($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
6371 %}
6372
6373 ins_pipe(fmulF_reg_reg);
6374 %}
6375
6376 // Mul float double precision
6377 instruct mulD_reg_reg(regD dst, regD src1, regD src2) %{
6378 match(Set dst (MulD src1 src2));
6379
6380 size(4);
6381 format %{ "FMULD $dst,$src1,$src2" %}
6382 ins_encode %{
6383 __ mul_double($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
6384 %}
6385
6386 ins_pipe(fmulD_reg_reg);
6387 %}
6388
6389 // Div float single precision
6390 instruct divF_reg_reg(regF dst, regF src1, regF src2) %{
6391 match(Set dst (DivF src1 src2));
6392
6393 size(4);
6394 format %{ "FDIVS $dst,$src1,$src2" %}
6395 ins_encode %{
6396 __ div_float($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
6397 %}
6398
6399 ins_pipe(fdivF_reg_reg);
6400 %}
6401
6402 // Div float double precision
6403 instruct divD_reg_reg(regD dst, regD src1, regD src2) %{
6404 match(Set dst (DivD src1 src2));
6405
6406 size(4);
6407 format %{ "FDIVD $dst,$src1,$src2" %}
6408 ins_encode %{
6409 __ div_double($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
6410 %}
6411
6412 ins_pipe(fdivD_reg_reg);
6413 %}
6414
6415 // Absolute float double precision
6416 instruct absD_reg(regD dst, regD src) %{
6417 match(Set dst (AbsD src));
6418
6419 size(4);
6420 format %{ "FABSd $dst,$src" %}
6421 ins_encode %{
6422 __ abs_double($dst$$FloatRegister, $src$$FloatRegister);
6423 %}
6424 ins_pipe(faddD_reg);
6425 %}
6426
6427 // Absolute float single precision
6428 instruct absF_reg(regF dst, regF src) %{
6429 match(Set dst (AbsF src));
6430 format %{ "FABSs $dst,$src" %}
6431 ins_encode %{
6432 __ abs_float($dst$$FloatRegister, $src$$FloatRegister);
6433 %}
6434 ins_pipe(faddF_reg);
6435 %}
6436
6437 instruct negF_reg(regF dst, regF src) %{
6438 match(Set dst (NegF src));
6439
6440 size(4);
6441 format %{ "FNEGs $dst,$src" %}
6442 ins_encode %{
6443 __ neg_float($dst$$FloatRegister, $src$$FloatRegister);
6444 %}
6445 ins_pipe(faddF_reg);
6446 %}
6447
6448 instruct negD_reg(regD dst, regD src) %{
6449 match(Set dst (NegD src));
6450
6451 format %{ "FNEGd $dst,$src" %}
6452 ins_encode %{
6453 __ neg_double($dst$$FloatRegister, $src$$FloatRegister);
6454 %}
6455 ins_pipe(faddD_reg);
6456 %}
6457
6458 // Sqrt float double precision
6459 instruct sqrtF_reg_reg(regF dst, regF src) %{
6460 match(Set dst (ConvD2F (SqrtD (ConvF2D src))));
6461
6462 size(4);
6463 format %{ "FSQRTS $dst,$src" %}
6464 ins_encode %{
6465 __ sqrt_float($dst$$FloatRegister, $src$$FloatRegister);
6466 %}
6467 ins_pipe(fdivF_reg_reg);
6468 %}
6469
6470 // Sqrt float double precision
6471 instruct sqrtD_reg_reg(regD dst, regD src) %{
6472 match(Set dst (SqrtD src));
6473
6474 size(4);
6475 format %{ "FSQRTD $dst,$src" %}
6476 ins_encode %{
6477 __ sqrt_double($dst$$FloatRegister, $src$$FloatRegister);
6478 %}
6479 ins_pipe(fdivD_reg_reg);
6480 %}
6481
6482 //----------Logical Instructions-----------------------------------------------
6483 // And Instructions
6484 // Register And
6485 instruct andI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{
6486 match(Set dst (AndI src1 src2));
6487
6488 size(4);
6489 format %{ "and_32 $dst,$src1,$src2" %}
6490 ins_encode %{
6491 __ and_32($dst$$Register, $src1$$Register, $src2$$Register);
6492 %}
6493 ins_pipe(ialu_reg_reg);
6494 %}
6495
6496 instruct andshlI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
6497 match(Set dst (AndI src1 (LShiftI src2 src3)));
6498
6499 size(4);
6500 format %{ "AND $dst,$src1,$src2<<$src3" %}
6501 ins_encode %{
6502 __ andr($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$Register));
6503 %}
6504 ins_pipe(ialu_reg_reg);
6505 %}
6506
6507 instruct andshlI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{
6508 match(Set dst (AndI src1 (LShiftI src2 src3)));
6509
6510 size(4);
6511 format %{ "and_32 $dst,$src1,$src2<<$src3" %}
6512 ins_encode %{
6513 __ and_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$constant));
6514 %}
6515 ins_pipe(ialu_reg_reg);
6516 %}
6517
6518 instruct andsarI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
6519 match(Set dst (AndI src1 (RShiftI src2 src3)));
6520
6521 size(4);
6522 format %{ "AND $dst,$src1,$src2>>$src3" %}
6523 ins_encode %{
6524 __ andr($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$Register));
6525 %}
6526 ins_pipe(ialu_reg_reg);
6527 %}
6528
6529 instruct andsarI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{
6530 match(Set dst (AndI src1 (RShiftI src2 src3)));
6531
6532 size(4);
6533 format %{ "and_32 $dst,$src1,$src2>>$src3" %}
6534 ins_encode %{
6535 __ and_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$constant));
6536 %}
6537 ins_pipe(ialu_reg_reg);
6538 %}
6539
6540 instruct andshrI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
6541 match(Set dst (AndI src1 (URShiftI src2 src3)));
6542
6543 size(4);
6544 format %{ "AND $dst,$src1,$src2>>>$src3" %}
6545 ins_encode %{
6546 __ andr($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$Register));
6547 %}
6548 ins_pipe(ialu_reg_reg);
6549 %}
6550
6551 instruct andshrI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{
6552 match(Set dst (AndI src1 (URShiftI src2 src3)));
6553
6554 size(4);
6555 format %{ "and_32 $dst,$src1,$src2>>>$src3" %}
6556 ins_encode %{
6557 __ and_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$constant));
6558 %}
6559 ins_pipe(ialu_reg_reg);
6560 %}
6561
6562 // Immediate And
6563 instruct andI_reg_limm(iRegI dst, iRegI src1, limmI src2) %{
6564 match(Set dst (AndI src1 src2));
6565
6566 size(4);
6567 format %{ "and_32 $dst,$src1,$src2\t! int" %}
6568 ins_encode %{
6569 __ and_32($dst$$Register, $src1$$Register, $src2$$constant);
6570 %}
6571 ins_pipe(ialu_reg_imm);
6572 %}
6573
6574 instruct andI_reg_limmn(iRegI dst, iRegI src1, limmIn src2) %{
6575 match(Set dst (AndI src1 src2));
6576
6577 size(4);
6578 format %{ "bic $dst,$src1,~$src2\t! int" %}
6579 ins_encode %{
6580 __ bic($dst$$Register, $src1$$Register, ~$src2$$constant);
6581 %}
6582 ins_pipe(ialu_reg_imm);
6583 %}
6584
6585 // Register And Long
6586 instruct andL_reg_reg(iRegL dst, iRegL src1, iRegL src2) %{
6587 match(Set dst (AndL src1 src2));
6588
6589 ins_cost(DEFAULT_COST);
6590 size(8);
6591 format %{ "AND $dst,$src1,$src2\t! long" %}
6592 ins_encode %{
6593 __ andr($dst$$Register, $src1$$Register, $src2$$Register);
6594 __ andr($dst$$Register->successor(), $src1$$Register->successor(), $src2$$Register->successor());
6595 %}
6596 ins_pipe(ialu_reg_reg);
6597 %}
6598
6599 // TODO: try immLRot2 instead, (0, $con$$constant) becomes
6600 // (hi($con$$constant), lo($con$$constant)) becomes
6601 instruct andL_reg_immRot(iRegL dst, iRegL src1, immLlowRot con) %{
6602 match(Set dst (AndL src1 con));
6603 ins_cost(DEFAULT_COST);
6604 size(8);
6605 format %{ "AND $dst,$src1,$con\t! long" %}
6606 ins_encode %{
6607 __ andr($dst$$Register, $src1$$Register, $con$$constant);
6608 __ andr($dst$$Register->successor(), $src1$$Register->successor(), 0);
6609 %}
6610 ins_pipe(ialu_reg_imm);
6611 %}
6612
6613 // Or Instructions
6614 // Register Or
6615 instruct orI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{
6616 match(Set dst (OrI src1 src2));
6617
6618 size(4);
6619 format %{ "orr_32 $dst,$src1,$src2\t! int" %}
6620 ins_encode %{
6621 __ orr_32($dst$$Register, $src1$$Register, $src2$$Register);
6622 %}
6623 ins_pipe(ialu_reg_reg);
6624 %}
6625
6626 instruct orshlI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
6627 match(Set dst (OrI src1 (LShiftI src2 src3)));
6628
6629 size(4);
6630 format %{ "OR $dst,$src1,$src2<<$src3" %}
6631 ins_encode %{
6632 __ orr($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$Register));
6633 %}
6634 ins_pipe(ialu_reg_reg);
6635 %}
6636
6637 instruct orshlI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{
6638 match(Set dst (OrI src1 (LShiftI src2 src3)));
6639
6640 size(4);
6641 format %{ "orr_32 $dst,$src1,$src2<<$src3" %}
6642 ins_encode %{
6643 __ orr_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$constant));
6644 %}
6645 ins_pipe(ialu_reg_reg);
6646 %}
6647
6648 instruct orsarI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
6649 match(Set dst (OrI src1 (RShiftI src2 src3)));
6650
6651 size(4);
6652 format %{ "OR $dst,$src1,$src2>>$src3" %}
6653 ins_encode %{
6654 __ orr($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$Register));
6655 %}
6656 ins_pipe(ialu_reg_reg);
6657 %}
6658
6659 instruct orsarI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{
6660 match(Set dst (OrI src1 (RShiftI src2 src3)));
6661
6662 size(4);
6663 format %{ "orr_32 $dst,$src1,$src2>>$src3" %}
6664 ins_encode %{
6665 __ orr_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$constant));
6666 %}
6667 ins_pipe(ialu_reg_reg);
6668 %}
6669
6670 instruct orshrI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
6671 match(Set dst (OrI src1 (URShiftI src2 src3)));
6672
6673 size(4);
6674 format %{ "OR $dst,$src1,$src2>>>$src3" %}
6675 ins_encode %{
6676 __ orr($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$Register));
6677 %}
6678 ins_pipe(ialu_reg_reg);
6679 %}
6680
6681 instruct orshrI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{
6682 match(Set dst (OrI src1 (URShiftI src2 src3)));
6683
6684 size(4);
6685 format %{ "orr_32 $dst,$src1,$src2>>>$src3" %}
6686 ins_encode %{
6687 __ orr_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$constant));
6688 %}
6689 ins_pipe(ialu_reg_reg);
6690 %}
6691
6692 // Immediate Or
6693 instruct orI_reg_limm(iRegI dst, iRegI src1, limmI src2) %{
6694 match(Set dst (OrI src1 src2));
6695
6696 size(4);
6697 format %{ "orr_32 $dst,$src1,$src2" %}
6698 ins_encode %{
6699 __ orr_32($dst$$Register, $src1$$Register, $src2$$constant);
6700 %}
6701 ins_pipe(ialu_reg_imm);
6702 %}
6703 // TODO: orn_32 with limmIn
6704
6705 // Register Or Long
6706 instruct orL_reg_reg(iRegL dst, iRegL src1, iRegL src2) %{
6707 match(Set dst (OrL src1 src2));
6708
6709 ins_cost(DEFAULT_COST);
6710 size(8);
6711 format %{ "OR $dst.lo,$src1.lo,$src2.lo\t! long\n\t"
6712 "OR $dst.hi,$src1.hi,$src2.hi" %}
6713 ins_encode %{
6714 __ orr($dst$$Register, $src1$$Register, $src2$$Register);
6715 __ orr($dst$$Register->successor(), $src1$$Register->successor(), $src2$$Register->successor());
6716 %}
6717 ins_pipe(ialu_reg_reg);
6718 %}
6719
6720 // TODO: try immLRot2 instead, (0, $con$$constant) becomes
6721 // (hi($con$$constant), lo($con$$constant)) becomes
6722 instruct orL_reg_immRot(iRegL dst, iRegL src1, immLlowRot con) %{
6723 match(Set dst (OrL src1 con));
6724 ins_cost(DEFAULT_COST);
6725 size(8);
6726 format %{ "OR $dst.lo,$src1.lo,$con\t! long\n\t"
6727 "OR $dst.hi,$src1.hi,$con" %}
6728 ins_encode %{
6729 __ orr($dst$$Register, $src1$$Register, $con$$constant);
6730 __ orr($dst$$Register->successor(), $src1$$Register->successor(), 0);
6731 %}
6732 ins_pipe(ialu_reg_imm);
6733 %}
6734
6735 #ifdef TODO
6736 // Use SPRegP to match Rthread (TLS register) without spilling.
6737 // Use store_ptr_RegP to match Rthread (TLS register) without spilling.
6738 // Use sp_ptr_RegP to match Rthread (TLS register) without spilling.
6739 instruct orI_reg_castP2X(iRegI dst, iRegI src1, sp_ptr_RegP src2) %{
6740 match(Set dst (OrI src1 (CastP2X src2)));
6741 size(4);
6742 format %{ "OR $dst,$src1,$src2" %}
6743 ins_encode %{
6744 __ orr($dst$$Register, $src1$$Register, $src2$$Register);
6745 %}
6746 ins_pipe(ialu_reg_reg);
6747 %}
6748 #endif
6749
6750 // Xor Instructions
6751 // Register Xor
6752 instruct xorI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{
6753 match(Set dst (XorI src1 src2));
6754
6755 size(4);
6756 format %{ "eor_32 $dst,$src1,$src2" %}
6757 ins_encode %{
6758 __ eor_32($dst$$Register, $src1$$Register, $src2$$Register);
6759 %}
6760 ins_pipe(ialu_reg_reg);
6761 %}
6762
6763 instruct xorshlI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
6764 match(Set dst (XorI src1 (LShiftI src2 src3)));
6765
6766 size(4);
6767 format %{ "XOR $dst,$src1,$src2<<$src3" %}
6768 ins_encode %{
6769 __ eor($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$Register));
6770 %}
6771 ins_pipe(ialu_reg_reg);
6772 %}
6773
6774 instruct xorshlI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{
6775 match(Set dst (XorI src1 (LShiftI src2 src3)));
6776
6777 size(4);
6778 format %{ "eor_32 $dst,$src1,$src2<<$src3" %}
6779 ins_encode %{
6780 __ eor_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$constant));
6781 %}
6782 ins_pipe(ialu_reg_reg);
6783 %}
6784
6785 instruct xorsarI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
6786 match(Set dst (XorI src1 (RShiftI src2 src3)));
6787
6788 size(4);
6789 format %{ "XOR $dst,$src1,$src2>>$src3" %}
6790 ins_encode %{
6791 __ eor($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$Register));
6792 %}
6793 ins_pipe(ialu_reg_reg);
6794 %}
6795
6796 instruct xorsarI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{
6797 match(Set dst (XorI src1 (RShiftI src2 src3)));
6798
6799 size(4);
6800 format %{ "eor_32 $dst,$src1,$src2>>$src3" %}
6801 ins_encode %{
6802 __ eor_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$constant));
6803 %}
6804 ins_pipe(ialu_reg_reg);
6805 %}
6806
6807 instruct xorshrI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{
6808 match(Set dst (XorI src1 (URShiftI src2 src3)));
6809
6810 size(4);
6811 format %{ "XOR $dst,$src1,$src2>>>$src3" %}
6812 ins_encode %{
6813 __ eor($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$Register));
6814 %}
6815 ins_pipe(ialu_reg_reg);
6816 %}
6817
6818 instruct xorshrI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{
6819 match(Set dst (XorI src1 (URShiftI src2 src3)));
6820
6821 size(4);
6822 format %{ "eor_32 $dst,$src1,$src2>>>$src3" %}
6823 ins_encode %{
6824 __ eor_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$constant));
6825 %}
6826 ins_pipe(ialu_reg_reg);
6827 %}
6828
6829 // Immediate Xor
6830 instruct xorI_reg_imm(iRegI dst, iRegI src1, limmI src2) %{
6831 match(Set dst (XorI src1 src2));
6832
6833 size(4);
6834 format %{ "eor_32 $dst,$src1,$src2" %}
6835 ins_encode %{
6836 __ eor_32($dst$$Register, $src1$$Register, $src2$$constant);
6837 %}
6838 ins_pipe(ialu_reg_imm);
6839 %}
6840
6841 // Register Xor Long
6842 instruct xorL_reg_reg(iRegL dst, iRegL src1, iRegL src2) %{
6843 match(Set dst (XorL src1 src2));
6844 ins_cost(DEFAULT_COST);
6845 size(8);
6846 format %{ "XOR $dst.hi,$src1.hi,$src2.hi\t! long\n\t"
6847 "XOR $dst.lo,$src1.lo,$src2.lo\t! long" %}
6848 ins_encode %{
6849 __ eor($dst$$Register, $src1$$Register, $src2$$Register);
6850 __ eor($dst$$Register->successor(), $src1$$Register->successor(), $src2$$Register->successor());
6851 %}
6852 ins_pipe(ialu_reg_reg);
6853 %}
6854
6855 // TODO: try immLRot2 instead, (0, $con$$constant) becomes
6856 // (hi($con$$constant), lo($con$$constant)) becomes
6857 instruct xorL_reg_immRot(iRegL dst, iRegL src1, immLlowRot con) %{
6858 match(Set dst (XorL src1 con));
6859 ins_cost(DEFAULT_COST);
6860 size(8);
6861 format %{ "XOR $dst.hi,$src1.hi,$con\t! long\n\t"
6862 "XOR $dst.lo,$src1.lo,0\t! long" %}
6863 ins_encode %{
6864 __ eor($dst$$Register, $src1$$Register, $con$$constant);
6865 __ eor($dst$$Register->successor(), $src1$$Register->successor(), 0);
6866 %}
6867 ins_pipe(ialu_reg_imm);
6868 %}
6869
6870 instruct cmpLTMask_reg_reg( iRegI dst, iRegI p, iRegI q, flagsReg ccr ) %{
6871 match(Set dst (CmpLTMask p q));
6872 effect( KILL ccr );
6873 ins_cost(DEFAULT_COST*3);
6874 format %{ "CMP $p,$q\n\t"
6875 "MOV $dst, #0\n\t"
6876 "MOV.lt $dst, #-1" %}
6877 ins_encode %{
6878 __ cmp($p$$Register, $q$$Register);
6879 __ mov($dst$$Register, 0);
6880 __ mvn($dst$$Register, 0, lt);
6881 %}
6882 ins_pipe(ialu_reg_reg_ialu);
6883 %}
6884
6885 instruct cmpLTMask_reg_imm( iRegI dst, iRegI p, aimmI q, flagsReg ccr ) %{
6886 match(Set dst (CmpLTMask p q));
6887 effect( KILL ccr );
6888 ins_cost(DEFAULT_COST*3);
6889 format %{ "CMP $p,$q\n\t"
6890 "MOV $dst, #0\n\t"
6891 "MOV.lt $dst, #-1" %}
6892 ins_encode %{
6893 __ cmp($p$$Register, $q$$constant);
6894 __ mov($dst$$Register, 0);
6895 __ mvn($dst$$Register, 0, lt);
6896 %}
6897 ins_pipe(ialu_reg_reg_ialu);
6898 %}
6899
6900 instruct cadd_cmpLTMask3( iRegI p, iRegI q, iRegI y, iRegI z, flagsReg ccr ) %{
6901 match(Set z (AddI (AndI (CmpLTMask p q) y) z));
6902 effect( KILL ccr );
6903 ins_cost(DEFAULT_COST*2);
6904 format %{ "CMP $p,$q\n\t"
6905 "ADD.lt $z,$y,$z" %}
6906 ins_encode %{
6907 __ cmp($p$$Register, $q$$Register);
6908 __ add($z$$Register, $y$$Register, $z$$Register, lt);
6909 %}
6910 ins_pipe( cadd_cmpltmask );
6911 %}
6912
6913 // FIXME: remove unused "dst"
6914 instruct cadd_cmpLTMask4( iRegI dst, iRegI p, aimmI q, iRegI y, iRegI z, flagsReg ccr ) %{
6915 match(Set z (AddI (AndI (CmpLTMask p q) y) z));
6916 effect( KILL ccr );
6917 ins_cost(DEFAULT_COST*2);
6918 format %{ "CMP $p,$q\n\t"
6919 "ADD.lt $z,$y,$z" %}
6920 ins_encode %{
6921 __ cmp($p$$Register, $q$$constant);
6922 __ add($z$$Register, $y$$Register, $z$$Register, lt);
6923 %}
6924 ins_pipe( cadd_cmpltmask );
6925 %}
6926
6927 instruct cadd_cmpLTMask( iRegI p, iRegI q, iRegI y, flagsReg ccr ) %{
6928 match(Set p (AddI (AndI (CmpLTMask p q) y) (SubI p q)));
6929 effect( KILL ccr );
6930 ins_cost(DEFAULT_COST*2);
6931 format %{ "SUBS $p,$p,$q\n\t"
6932 "ADD.lt $p,$y,$p" %}
6933 ins_encode %{
6934 __ subs($p$$Register, $p$$Register, $q$$Register);
6935 __ add($p$$Register, $y$$Register, $p$$Register, lt);
6936 %}
6937 ins_pipe( cadd_cmpltmask );
6938 %}
6939
6940 //----------Arithmetic Conversion Instructions---------------------------------
6941 // The conversions operations are all Alpha sorted. Please keep it that way!
6942
6943 instruct convD2F_reg(regF dst, regD src) %{
6944 match(Set dst (ConvD2F src));
6945 size(4);
6946 format %{ "FCVTSD $dst,$src" %}
6947 ins_encode %{
6948 __ convert_d2f($dst$$FloatRegister, $src$$FloatRegister);
6949 %}
6950 ins_pipe(fcvtD2F);
6951 %}
6952
6953 // Convert a double to an int in a float register.
6954 // If the double is a NAN, stuff a zero in instead.
6955
6956 instruct convD2I_reg_reg(iRegI dst, regD src, regF tmp) %{
6957 match(Set dst (ConvD2I src));
6958 effect( TEMP tmp );
6959 ins_cost(DEFAULT_COST*2 + MEMORY_REF_COST*2 + BRANCH_COST); // FIXME
6960 format %{ "FTOSIZD $tmp,$src\n\t"
6961 "FMRS $dst, $tmp" %}
6962 ins_encode %{
6963 __ ftosizd($tmp$$FloatRegister, $src$$FloatRegister);
6964 __ fmrs($dst$$Register, $tmp$$FloatRegister);
6965 %}
6966 ins_pipe(fcvtD2I);
6967 %}
6968
6969 // Convert a double to a long in a double register.
6970 // If the double is a NAN, stuff a zero in instead.
6971
6972 // Double to Long conversion
6973 instruct convD2L_reg(R0R1RegL dst, regD src) %{
6974 match(Set dst (ConvD2L src));
6975 effect(CALL);
6976 ins_cost(MEMORY_REF_COST); // FIXME
6977 format %{ "convD2L $dst,$src\t ! call to SharedRuntime::d2l" %}
6978 ins_encode %{
6979 #ifndef __ABI_HARD__
6980 __ fmrrd($dst$$Register, $dst$$Register->successor(), $src$$FloatRegister);
6981 #else
6982 if ($src$$FloatRegister != D0) {
6983 __ mov_double(D0, $src$$FloatRegister);
6984 }
6985 #endif
6986 address target = CAST_FROM_FN_PTR(address, SharedRuntime::d2l);
6987 __ call(target, relocInfo::runtime_call_type);
6988 %}
6989 ins_pipe(fcvtD2L);
6990 %}
6991
6992 instruct convF2D_reg(regD dst, regF src) %{
6993 match(Set dst (ConvF2D src));
6994 size(4);
6995 format %{ "FCVTDS $dst,$src" %}
6996 ins_encode %{
6997 __ convert_f2d($dst$$FloatRegister, $src$$FloatRegister);
6998 %}
6999 ins_pipe(fcvtF2D);
7000 %}
7001
7002 instruct convF2I_reg_reg(iRegI dst, regF src, regF tmp) %{
7003 match(Set dst (ConvF2I src));
7004 effect( TEMP tmp );
7005 ins_cost(DEFAULT_COST*2 + MEMORY_REF_COST*2 + BRANCH_COST); // FIXME
7006 size(8);
7007 format %{ "FTOSIZS $tmp,$src\n\t"
7008 "FMRS $dst, $tmp" %}
7009 ins_encode %{
7010 __ ftosizs($tmp$$FloatRegister, $src$$FloatRegister);
7011 __ fmrs($dst$$Register, $tmp$$FloatRegister);
7012 %}
7013 ins_pipe(fcvtF2I);
7014 %}
7015
7016 // Float to Long conversion
7017 instruct convF2L_reg(R0R1RegL dst, regF src, R0RegI arg1) %{
7018 match(Set dst (ConvF2L src));
7019 ins_cost(DEFAULT_COST*2 + MEMORY_REF_COST*2 + BRANCH_COST); // FIXME
7020 effect(CALL);
7021 format %{ "convF2L $dst,$src\t! call to SharedRuntime::f2l" %}
7022 ins_encode %{
7023 #ifndef __ABI_HARD__
7024 __ fmrs($arg1$$Register, $src$$FloatRegister);
7025 #else
7026 if($src$$FloatRegister != S0) {
7027 __ mov_float(S0, $src$$FloatRegister);
7028 }
7029 #endif
7030 address target = CAST_FROM_FN_PTR(address, SharedRuntime::f2l);
7031 __ call(target, relocInfo::runtime_call_type);
7032 %}
7033 ins_pipe(fcvtF2L);
7034 %}
7035
7036 instruct convI2D_reg_reg(iRegI src, regD_low dst) %{
7037 match(Set dst (ConvI2D src));
7038 ins_cost(DEFAULT_COST + MEMORY_REF_COST); // FIXME
7039 size(8);
7040 format %{ "FMSR $dst,$src \n\t"
7041 "FSITOD $dst $dst"%}
7042 ins_encode %{
7043 __ fmsr($dst$$FloatRegister, $src$$Register);
7044 __ fsitod($dst$$FloatRegister, $dst$$FloatRegister);
7045 %}
7046 ins_pipe(fcvtI2D);
7047 %}
7048
7049 instruct convI2F_reg_reg( regF dst, iRegI src ) %{
7050 match(Set dst (ConvI2F src));
7051 ins_cost(DEFAULT_COST + MEMORY_REF_COST); // FIXME
7052 size(8);
7053 format %{ "FMSR $dst,$src \n\t"
7054 "FSITOS $dst, $dst"%}
7055 ins_encode %{
7056 __ fmsr($dst$$FloatRegister, $src$$Register);
7057 __ fsitos($dst$$FloatRegister, $dst$$FloatRegister);
7058 %}
7059 ins_pipe(fcvtI2F);
7060 %}
7061
7062 instruct convI2L_reg(iRegL dst, iRegI src) %{
7063 match(Set dst (ConvI2L src));
7064 size(8);
7065 format %{ "MOV $dst.lo, $src \n\t"
7066 "ASR $dst.hi,$src,31\t! int->long" %}
7067 ins_encode %{
7068 __ mov($dst$$Register, $src$$Register);
7069 __ mov($dst$$Register->successor(), AsmOperand($src$$Register, asr, 31));
7070 %}
7071 ins_pipe(ialu_reg_reg);
7072 %}
7073
7074 // Zero-extend convert int to long
7075 instruct convI2L_reg_zex(iRegL dst, iRegI src, immL_32bits mask ) %{
7076 match(Set dst (AndL (ConvI2L src) mask) );
7077 size(8);
7078 format %{ "MOV $dst.lo,$src.lo\t! zero-extend int to long\n\t"
7079 "MOV $dst.hi, 0"%}
7080 ins_encode %{
7081 __ mov($dst$$Register, $src$$Register);
7082 __ mov($dst$$Register->successor(), 0);
7083 %}
7084 ins_pipe(ialu_reg_reg);
7085 %}
7086
7087 // Zero-extend long
7088 instruct zerox_long(iRegL dst, iRegL src, immL_32bits mask ) %{
7089 match(Set dst (AndL src mask) );
7090 size(8);
7091 format %{ "MOV $dst.lo,$src.lo\t! zero-extend long\n\t"
7092 "MOV $dst.hi, 0"%}
7093 ins_encode %{
7094 __ mov($dst$$Register, $src$$Register);
7095 __ mov($dst$$Register->successor(), 0);
7096 %}
7097 ins_pipe(ialu_reg_reg);
7098 %}
7099
7100 instruct MoveF2I_reg_reg(iRegI dst, regF src) %{
7101 match(Set dst (MoveF2I src));
7102 effect(DEF dst, USE src);
7103 ins_cost(MEMORY_REF_COST); // FIXME
7104
7105 size(4);
7106 format %{ "FMRS $dst,$src\t! MoveF2I" %}
7107 ins_encode %{
7108 __ fmrs($dst$$Register, $src$$FloatRegister);
7109 %}
7110 ins_pipe(iload_mem); // FIXME
7111 %}
7112
7113 instruct MoveI2F_reg_reg(regF dst, iRegI src) %{
7114 match(Set dst (MoveI2F src));
7115 ins_cost(MEMORY_REF_COST); // FIXME
7116
7117 size(4);
7118 format %{ "FMSR $dst,$src\t! MoveI2F" %}
7119 ins_encode %{
7120 __ fmsr($dst$$FloatRegister, $src$$Register);
7121 %}
7122 ins_pipe(iload_mem); // FIXME
7123 %}
7124
7125 instruct MoveD2L_reg_reg(iRegL dst, regD src) %{
7126 match(Set dst (MoveD2L src));
7127 effect(DEF dst, USE src);
7128 ins_cost(MEMORY_REF_COST); // FIXME
7129
7130 size(4);
7131 format %{ "FMRRD $dst,$src\t! MoveD2L" %}
7132 ins_encode %{
7133 __ fmrrd($dst$$Register, $dst$$Register->successor(), $src$$FloatRegister);
7134 %}
7135 ins_pipe(iload_mem); // FIXME
7136 %}
7137
7138 instruct MoveL2D_reg_reg(regD dst, iRegL src) %{
7139 match(Set dst (MoveL2D src));
7140 effect(DEF dst, USE src);
7141 ins_cost(MEMORY_REF_COST); // FIXME
7142
7143 size(4);
7144 format %{ "FMDRR $dst,$src\t! MoveL2D" %}
7145 ins_encode %{
7146 __ fmdrr($dst$$FloatRegister, $src$$Register, $src$$Register->successor());
7147 %}
7148 ins_pipe(ialu_reg_reg); // FIXME
7149 %}
7150
7151 //-----------
7152 // Long to Double conversion
7153
7154 // Magic constant, 0x43300000
7155 instruct loadConI_x43300000(iRegI dst) %{
7156 effect(DEF dst);
7157 size(8);
7158 format %{ "MOV_SLOW $dst,0x43300000\t! 2^52" %}
7159 ins_encode %{
7160 __ mov_slow($dst$$Register, 0x43300000);
7161 %}
7162 ins_pipe(ialu_none);
7163 %}
7164
7165 // Magic constant, 0x41f00000
7166 instruct loadConI_x41f00000(iRegI dst) %{
7167 effect(DEF dst);
7168 size(8);
7169 format %{ "MOV_SLOW $dst, 0x41f00000\t! 2^32" %}
7170 ins_encode %{
7171 __ mov_slow($dst$$Register, 0x41f00000);
7172 %}
7173 ins_pipe(ialu_none);
7174 %}
7175
7176 instruct loadConI_x0(iRegI dst) %{
7177 effect(DEF dst);
7178 size(4);
7179 format %{ "MOV $dst, 0x0\t! 0" %}
7180 ins_encode %{
7181 __ mov($dst$$Register, 0);
7182 %}
7183 ins_pipe(ialu_none);
7184 %}
7185
7186 // Construct a double from two float halves
7187 instruct regDHi_regDLo_to_regD(regD_low dst, regD_low src1, regD_low src2) %{
7188 effect(DEF dst, USE src1, USE src2);
7189 size(8);
7190 format %{ "FCPYS $dst.hi,$src1.hi\n\t"
7191 "FCPYS $dst.lo,$src2.lo" %}
7192 ins_encode %{
7193 __ fcpys($dst$$FloatRegister->successor(), $src1$$FloatRegister->successor());
7194 __ fcpys($dst$$FloatRegister, $src2$$FloatRegister);
7195 %}
7196 ins_pipe(faddD_reg_reg);
7197 %}
7198
7199 // Convert integer in high half of a double register (in the lower half of
7200 // the double register file) to double
7201 instruct convI2D_regDHi_regD(regD dst, regD_low src) %{
7202 effect(DEF dst, USE src);
7203 size(4);
7204 format %{ "FSITOD $dst,$src" %}
7205 ins_encode %{
7206 __ fsitod($dst$$FloatRegister, $src$$FloatRegister->successor());
7207 %}
7208 ins_pipe(fcvtLHi2D);
7209 %}
7210
7211 // Add float double precision
7212 instruct addD_regD_regD(regD dst, regD src1, regD src2) %{
7213 effect(DEF dst, USE src1, USE src2);
7214 size(4);
7215 format %{ "FADDD $dst,$src1,$src2" %}
7216 ins_encode %{
7217 __ add_double($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
7218 %}
7219 ins_pipe(faddD_reg_reg);
7220 %}
7221
7222 // Sub float double precision
7223 instruct subD_regD_regD(regD dst, regD src1, regD src2) %{
7224 effect(DEF dst, USE src1, USE src2);
7225 size(4);
7226 format %{ "FSUBD $dst,$src1,$src2" %}
7227 ins_encode %{
7228 __ sub_double($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
7229 %}
7230 ins_pipe(faddD_reg_reg);
7231 %}
7232
7233 // Mul float double precision
7234 instruct mulD_regD_regD(regD dst, regD src1, regD src2) %{
7235 effect(DEF dst, USE src1, USE src2);
7236 size(4);
7237 format %{ "FMULD $dst,$src1,$src2" %}
7238 ins_encode %{
7239 __ mul_double($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
7240 %}
7241 ins_pipe(fmulD_reg_reg);
7242 %}
7243
7244 instruct regL_to_regD(regD dst, iRegL src) %{
7245 // No match rule to avoid chain rule match.
7246 effect(DEF dst, USE src);
7247 ins_cost(MEMORY_REF_COST);
7248 size(4);
7249 format %{ "FMDRR $dst,$src\t! regL to regD" %}
7250 ins_encode %{
7251 __ fmdrr($dst$$FloatRegister, $src$$Register, $src$$Register->successor());
7252 %}
7253 ins_pipe(ialu_reg_reg); // FIXME
7254 %}
7255
7256 instruct regI_regI_to_regD(regD dst, iRegI src1, iRegI src2) %{
7257 // No match rule to avoid chain rule match.
7258 effect(DEF dst, USE src1, USE src2);
7259 ins_cost(MEMORY_REF_COST);
7260 size(4);
7261 format %{ "FMDRR $dst,$src1,$src2\t! regI,regI to regD" %}
7262 ins_encode %{
7263 __ fmdrr($dst$$FloatRegister, $src1$$Register, $src2$$Register);
7264 %}
7265 ins_pipe(ialu_reg_reg); // FIXME
7266 %}
7267
7268 instruct convL2D_reg_slow_fxtof(regD dst, iRegL src) %{
7269 match(Set dst (ConvL2D src));
7270 ins_cost(DEFAULT_COST*8 + MEMORY_REF_COST*6); // FIXME
7271
7272 expand %{
7273 regD_low tmpsrc;
7274 iRegI ix43300000;
7275 iRegI ix41f00000;
7276 iRegI ix0;
7277 regD_low dx43300000;
7278 regD dx41f00000;
7279 regD tmp1;
7280 regD_low tmp2;
7281 regD tmp3;
7282 regD tmp4;
7283
7284 regL_to_regD(tmpsrc, src);
7285
7286 loadConI_x43300000(ix43300000);
7287 loadConI_x41f00000(ix41f00000);
7288 loadConI_x0(ix0);
7289
7290 regI_regI_to_regD(dx43300000, ix0, ix43300000);
7291 regI_regI_to_regD(dx41f00000, ix0, ix41f00000);
7292
7293 convI2D_regDHi_regD(tmp1, tmpsrc);
7294 regDHi_regDLo_to_regD(tmp2, dx43300000, tmpsrc);
7295 subD_regD_regD(tmp3, tmp2, dx43300000);
7296 mulD_regD_regD(tmp4, tmp1, dx41f00000);
7297 addD_regD_regD(dst, tmp3, tmp4);
7298 %}
7299 %}
7300
7301 instruct convL2I_reg(iRegI dst, iRegL src) %{
7302 match(Set dst (ConvL2I src));
7303 size(4);
7304 format %{ "MOV $dst,$src.lo\t! long->int" %}
7305 ins_encode %{
7306 __ mov($dst$$Register, $src$$Register);
7307 %}
7308 ins_pipe(ialu_move_reg_I_to_L);
7309 %}
7310
7311 // Register Shift Right Immediate
7312 instruct shrL_reg_imm6_L2I(iRegI dst, iRegL src, immI_32_63 cnt) %{
7313 match(Set dst (ConvL2I (RShiftL src cnt)));
7314 size(4);
7315 format %{ "ASR $dst,$src.hi,($cnt - 32)\t! long->int or mov if $cnt==32" %}
7316 ins_encode %{
7317 if ($cnt$$constant == 32) {
7318 __ mov($dst$$Register, $src$$Register->successor());
7319 } else {
7320 __ mov($dst$$Register, AsmOperand($src$$Register->successor(), asr, $cnt$$constant - 32));
7321 }
7322 %}
7323 ins_pipe(ialu_reg_imm);
7324 %}
7325
7326
7327 //----------Control Flow Instructions------------------------------------------
7328 // Compare Instructions
7329 // Compare Integers
7330 instruct compI_iReg(flagsReg icc, iRegI op1, iRegI op2) %{
7331 match(Set icc (CmpI op1 op2));
7332 effect( DEF icc, USE op1, USE op2 );
7333
7334 size(4);
7335 format %{ "cmp_32 $op1,$op2\t! int" %}
7336 ins_encode %{
7337 __ cmp_32($op1$$Register, $op2$$Register);
7338 %}
7339 ins_pipe(ialu_cconly_reg_reg);
7340 %}
7341
7342 #ifdef _LP64
7343 // Compare compressed pointers
7344 instruct compN_reg2(flagsRegU icc, iRegN op1, iRegN op2) %{
7345 match(Set icc (CmpN op1 op2));
7346 effect( DEF icc, USE op1, USE op2 );
7347
7348 size(4);
7349 format %{ "cmp_32 $op1,$op2\t! int" %}
7350 ins_encode %{
7351 __ cmp_32($op1$$Register, $op2$$Register);
7352 %}
7353 ins_pipe(ialu_cconly_reg_reg);
7354 %}
7355 #endif
7356
7357 instruct compU_iReg(flagsRegU icc, iRegI op1, iRegI op2) %{
7358 match(Set icc (CmpU op1 op2));
7359
7360 size(4);
7361 format %{ "cmp_32 $op1,$op2\t! unsigned int" %}
7362 ins_encode %{
7363 __ cmp_32($op1$$Register, $op2$$Register);
7364 %}
7365 ins_pipe(ialu_cconly_reg_reg);
7366 %}
7367
7368 instruct compI_iReg_immneg(flagsReg icc, iRegI op1, aimmIneg op2) %{
7369 match(Set icc (CmpI op1 op2));
7370 effect( DEF icc, USE op1 );
7371
7372 size(4);
7373 format %{ "cmn_32 $op1,-$op2\t! int" %}
7374 ins_encode %{
7375 __ cmn_32($op1$$Register, -$op2$$constant);
7376 %}
7377 ins_pipe(ialu_cconly_reg_imm);
7378 %}
7379
7380 instruct compI_iReg_imm(flagsReg icc, iRegI op1, aimmI op2) %{
7381 match(Set icc (CmpI op1 op2));
7382 effect( DEF icc, USE op1 );
7383
7384 size(4);
7385 format %{ "cmp_32 $op1,$op2\t! int" %}
7386 ins_encode %{
7387 __ cmp_32($op1$$Register, $op2$$constant);
7388 %}
7389 ins_pipe(ialu_cconly_reg_imm);
7390 %}
7391
7392 instruct testI_reg_reg( flagsReg_EQNELTGE icc, iRegI op1, iRegI op2, immI0 zero ) %{
7393 match(Set icc (CmpI (AndI op1 op2) zero));
7394 size(4);
7395 format %{ "tst_32 $op2,$op1" %}
7396
7397 ins_encode %{
7398 __ tst_32($op1$$Register, $op2$$Register);
7399 %}
7400 ins_pipe(ialu_cconly_reg_reg_zero);
7401 %}
7402
7403 instruct testshlI_reg_reg_reg( flagsReg_EQNELTGE icc, iRegI op1, iRegI op2, iRegI op3, immI0 zero ) %{
7404 match(Set icc (CmpI (AndI op1 (LShiftI op2 op3)) zero));
7405 size(4);
7406 format %{ "TST $op2,$op1<<$op3" %}
7407
7408 ins_encode %{
7409 __ tst($op1$$Register, AsmOperand($op2$$Register, lsl, $op3$$Register));
7410 %}
7411 ins_pipe(ialu_cconly_reg_reg_zero);
7412 %}
7413
7414 instruct testshlI_reg_reg_imm( flagsReg_EQNELTGE icc, iRegI op1, iRegI op2, immU5 op3, immI0 zero ) %{
7415 match(Set icc (CmpI (AndI op1 (LShiftI op2 op3)) zero));
7416 size(4);
7417 format %{ "tst_32 $op2,$op1<<$op3" %}
7418
7419 ins_encode %{
7420 __ tst_32($op1$$Register, AsmOperand($op2$$Register, lsl, $op3$$constant));
7421 %}
7422 ins_pipe(ialu_cconly_reg_reg_zero);
7423 %}
7424
7425 instruct testsarI_reg_reg_reg( flagsReg_EQNELTGE icc, iRegI op1, iRegI op2, iRegI op3, immI0 zero ) %{
7426 match(Set icc (CmpI (AndI op1 (RShiftI op2 op3)) zero));
7427 size(4);
7428 format %{ "TST $op2,$op1<<$op3" %}
7429
7430 ins_encode %{
7431 __ tst($op1$$Register, AsmOperand($op2$$Register, asr, $op3$$Register));
7432 %}
7433 ins_pipe(ialu_cconly_reg_reg_zero);
7434 %}
7435
7436 instruct testsarI_reg_reg_imm( flagsReg_EQNELTGE icc, iRegI op1, iRegI op2, immU5 op3, immI0 zero ) %{
7437 match(Set icc (CmpI (AndI op1 (RShiftI op2 op3)) zero));
7438 size(4);
7439 format %{ "tst_32 $op2,$op1<<$op3" %}
7440
7441 ins_encode %{
7442 __ tst_32($op1$$Register, AsmOperand($op2$$Register, asr, $op3$$constant));
7443 %}
7444 ins_pipe(ialu_cconly_reg_reg_zero);
7445 %}
7446
7447 instruct testshrI_reg_reg_reg( flagsReg_EQNELTGE icc, iRegI op1, iRegI op2, iRegI op3, immI0 zero ) %{
7448 match(Set icc (CmpI (AndI op1 (URShiftI op2 op3)) zero));
7449 size(4);
7450 format %{ "TST $op2,$op1<<$op3" %}
7451
7452 ins_encode %{
7453 __ tst($op1$$Register, AsmOperand($op2$$Register, lsr, $op3$$Register));
7454 %}
7455 ins_pipe(ialu_cconly_reg_reg_zero);
7456 %}
7457
7458 instruct testshrI_reg_reg_imm( flagsReg_EQNELTGE icc, iRegI op1, iRegI op2, immU5 op3, immI0 zero ) %{
7459 match(Set icc (CmpI (AndI op1 (URShiftI op2 op3)) zero));
7460 size(4);
7461 format %{ "tst_32 $op2,$op1<<$op3" %}
7462
7463 ins_encode %{
7464 __ tst_32($op1$$Register, AsmOperand($op2$$Register, lsr, $op3$$constant));
7465 %}
7466 ins_pipe(ialu_cconly_reg_reg_zero);
7467 %}
7468
7469 instruct testI_reg_imm( flagsReg_EQNELTGE icc, iRegI op1, limmI op2, immI0 zero ) %{
7470 match(Set icc (CmpI (AndI op1 op2) zero));
7471 size(4);
7472 format %{ "tst_32 $op2,$op1" %}
7473
7474 ins_encode %{
7475 __ tst_32($op1$$Register, $op2$$constant);
7476 %}
7477 ins_pipe(ialu_cconly_reg_imm_zero);
7478 %}
7479
7480 instruct compL_reg_reg_LTGE(flagsRegL_LTGE xcc, iRegL op1, iRegL op2, iRegL tmp) %{
7481 match(Set xcc (CmpL op1 op2));
7482 effect( DEF xcc, USE op1, USE op2, TEMP tmp );
7483
7484 size(8);
7485 format %{ "SUBS $tmp,$op1.low,$op2.low\t\t! long\n\t"
7486 "SBCS $tmp,$op1.hi,$op2.hi" %}
7487 ins_encode %{
7488 __ subs($tmp$$Register, $op1$$Register, $op2$$Register);
7489 __ sbcs($tmp$$Register->successor(), $op1$$Register->successor(), $op2$$Register->successor());
7490 %}
7491 ins_pipe(ialu_cconly_reg_reg);
7492 %}
7493
7494 instruct compUL_reg_reg_LTGE(flagsRegUL_LTGE xcc, iRegL op1, iRegL op2, iRegL tmp) %{
7495 match(Set xcc (CmpUL op1 op2));
7496 effect(DEF xcc, USE op1, USE op2, TEMP tmp);
7497
7498 size(8);
7499 format %{ "SUBS $tmp,$op1.low,$op2.low\t\t! unsigned long\n\t"
7500 "SBCS $tmp,$op1.hi,$op2.hi" %}
7501 ins_encode %{
7502 __ subs($tmp$$Register, $op1$$Register, $op2$$Register);
7503 __ sbcs($tmp$$Register->successor(), $op1$$Register->successor(), $op2$$Register->successor());
7504 %}
7505 ins_pipe(ialu_cconly_reg_reg);
7506 %}
7507
7508 instruct compL_reg_reg_EQNE(flagsRegL_EQNE xcc, iRegL op1, iRegL op2) %{
7509 match(Set xcc (CmpL op1 op2));
7510 effect( DEF xcc, USE op1, USE op2 );
7511
7512 size(8);
7513 format %{ "TEQ $op1.hi,$op2.hi\t\t! long\n\t"
7514 "TEQ.eq $op1.lo,$op2.lo" %}
7515 ins_encode %{
7516 __ teq($op1$$Register->successor(), $op2$$Register->successor());
7517 __ teq($op1$$Register, $op2$$Register, eq);
7518 %}
7519 ins_pipe(ialu_cconly_reg_reg);
7520 %}
7521
7522 instruct compL_reg_reg_LEGT(flagsRegL_LEGT xcc, iRegL op1, iRegL op2, iRegL tmp) %{
7523 match(Set xcc (CmpL op1 op2));
7524 effect( DEF xcc, USE op1, USE op2, TEMP tmp );
7525
7526 size(8);
7527 format %{ "SUBS $tmp,$op2.low,$op1.low\t\t! long\n\t"
7528 "SBCS $tmp,$op2.hi,$op1.hi" %}
7529 ins_encode %{
7530 __ subs($tmp$$Register, $op2$$Register, $op1$$Register);
7531 __ sbcs($tmp$$Register->successor(), $op2$$Register->successor(), $op1$$Register->successor());
7532 %}
7533 ins_pipe(ialu_cconly_reg_reg);
7534 %}
7535
7536 // TODO: try immLRot2 instead, (0, $con$$constant) becomes
7537 // (hi($con$$constant), lo($con$$constant)) becomes
7538 instruct compL_reg_con_LTGE(flagsRegL_LTGE xcc, iRegL op1, immLlowRot con, iRegL tmp) %{
7539 match(Set xcc (CmpL op1 con));
7540 effect( DEF xcc, USE op1, USE con, TEMP tmp );
7541
7542 size(8);
7543 format %{ "SUBS $tmp,$op1.low,$con\t\t! long\n\t"
7544 "SBCS $tmp,$op1.hi,0" %}
7545 ins_encode %{
7546 __ subs($tmp$$Register, $op1$$Register, $con$$constant);
7547 __ sbcs($tmp$$Register->successor(), $op1$$Register->successor(), 0);
7548 %}
7549
7550 ins_pipe(ialu_cconly_reg_reg);
7551 %}
7552
7553 // TODO: try immLRot2 instead, (0, $con$$constant) becomes
7554 // (hi($con$$constant), lo($con$$constant)) becomes
7555 instruct compL_reg_con_EQNE(flagsRegL_EQNE xcc, iRegL op1, immLlowRot con) %{
7556 match(Set xcc (CmpL op1 con));
7557 effect( DEF xcc, USE op1, USE con );
7558
7559 size(8);
7560 format %{ "TEQ $op1.hi,0\t\t! long\n\t"
7561 "TEQ.eq $op1.lo,$con" %}
7562 ins_encode %{
7563 __ teq($op1$$Register->successor(), 0);
7564 __ teq($op1$$Register, $con$$constant, eq);
7565 %}
7566
7567 ins_pipe(ialu_cconly_reg_reg);
7568 %}
7569
7570 // TODO: try immLRot2 instead, (0, $con$$constant) becomes
7571 // (hi($con$$constant), lo($con$$constant)) becomes
7572 instruct compL_reg_con_LEGT(flagsRegL_LEGT xcc, iRegL op1, immLlowRot con, iRegL tmp) %{
7573 match(Set xcc (CmpL op1 con));
7574 effect( DEF xcc, USE op1, USE con, TEMP tmp );
7575
7576 size(8);
7577 format %{ "RSBS $tmp,$op1.low,$con\t\t! long\n\t"
7578 "RSCS $tmp,$op1.hi,0" %}
7579 ins_encode %{
7580 __ rsbs($tmp$$Register, $op1$$Register, $con$$constant);
7581 __ rscs($tmp$$Register->successor(), $op1$$Register->successor(), 0);
7582 %}
7583
7584 ins_pipe(ialu_cconly_reg_reg);
7585 %}
7586
7587 instruct compUL_reg_reg_EQNE(flagsRegUL_EQNE xcc, iRegL op1, iRegL op2) %{
7588 match(Set xcc (CmpUL op1 op2));
7589 effect(DEF xcc, USE op1, USE op2);
7590
7591 size(8);
7592 format %{ "TEQ $op1.hi,$op2.hi\t\t! unsigned long\n\t"
7593 "TEQ.eq $op1.lo,$op2.lo" %}
7594 ins_encode %{
7595 __ teq($op1$$Register->successor(), $op2$$Register->successor());
7596 __ teq($op1$$Register, $op2$$Register, eq);
7597 %}
7598 ins_pipe(ialu_cconly_reg_reg);
7599 %}
7600
7601 instruct compUL_reg_reg_LEGT(flagsRegUL_LEGT xcc, iRegL op1, iRegL op2, iRegL tmp) %{
7602 match(Set xcc (CmpUL op1 op2));
7603 effect(DEF xcc, USE op1, USE op2, TEMP tmp);
7604
7605 size(8);
7606 format %{ "SUBS $tmp,$op2.low,$op1.low\t\t! unsigned long\n\t"
7607 "SBCS $tmp,$op2.hi,$op1.hi" %}
7608 ins_encode %{
7609 __ subs($tmp$$Register, $op2$$Register, $op1$$Register);
7610 __ sbcs($tmp$$Register->successor(), $op2$$Register->successor(), $op1$$Register->successor());
7611 %}
7612 ins_pipe(ialu_cconly_reg_reg);
7613 %}
7614
7615 // TODO: try immLRot2 instead, (0, $con$$constant) becomes
7616 // (hi($con$$constant), lo($con$$constant)) becomes
7617 instruct compUL_reg_con_LTGE(flagsRegUL_LTGE xcc, iRegL op1, immLlowRot con, iRegL tmp) %{
7618 match(Set xcc (CmpUL op1 con));
7619 effect(DEF xcc, USE op1, USE con, TEMP tmp);
7620
7621 size(8);
7622 format %{ "SUBS $tmp,$op1.low,$con\t\t! unsigned long\n\t"
7623 "SBCS $tmp,$op1.hi,0" %}
7624 ins_encode %{
7625 __ subs($tmp$$Register, $op1$$Register, $con$$constant);
7626 __ sbcs($tmp$$Register->successor(), $op1$$Register->successor(), 0);
7627 %}
7628
7629 ins_pipe(ialu_cconly_reg_reg);
7630 %}
7631
7632 // TODO: try immLRot2 instead, (0, $con$$constant) becomes
7633 // (hi($con$$constant), lo($con$$constant)) becomes
7634 instruct compUL_reg_con_EQNE(flagsRegUL_EQNE xcc, iRegL op1, immLlowRot con) %{
7635 match(Set xcc (CmpUL op1 con));
7636 effect(DEF xcc, USE op1, USE con);
7637
7638 size(8);
7639 format %{ "TEQ $op1.hi,0\t\t! unsigned long\n\t"
7640 "TEQ.eq $op1.lo,$con" %}
7641 ins_encode %{
7642 __ teq($op1$$Register->successor(), 0);
7643 __ teq($op1$$Register, $con$$constant, eq);
7644 %}
7645
7646 ins_pipe(ialu_cconly_reg_reg);
7647 %}
7648
7649 // TODO: try immLRot2 instead, (0, $con$$constant) becomes
7650 // (hi($con$$constant), lo($con$$constant)) becomes
7651 instruct compUL_reg_con_LEGT(flagsRegUL_LEGT xcc, iRegL op1, immLlowRot con, iRegL tmp) %{
7652 match(Set xcc (CmpUL op1 con));
7653 effect(DEF xcc, USE op1, USE con, TEMP tmp);
7654
7655 size(8);
7656 format %{ "RSBS $tmp,$op1.low,$con\t\t! unsigned long\n\t"
7657 "RSCS $tmp,$op1.hi,0" %}
7658 ins_encode %{
7659 __ rsbs($tmp$$Register, $op1$$Register, $con$$constant);
7660 __ rscs($tmp$$Register->successor(), $op1$$Register->successor(), 0);
7661 %}
7662
7663 ins_pipe(ialu_cconly_reg_reg);
7664 %}
7665
7666 /* instruct testL_reg_reg(flagsRegL xcc, iRegL op1, iRegL op2, immL0 zero) %{ */
7667 /* match(Set xcc (CmpL (AndL op1 op2) zero)); */
7668 /* ins_encode %{ */
7669 /* __ stop("testL_reg_reg unimplemented"); */
7670 /* %} */
7671 /* ins_pipe(ialu_cconly_reg_reg); */
7672 /* %} */
7673
7674 /* // useful for checking the alignment of a pointer: */
7675 /* instruct testL_reg_con(flagsRegL xcc, iRegL op1, immLlowRot con, immL0 zero) %{ */
7676 /* match(Set xcc (CmpL (AndL op1 con) zero)); */
7677 /* ins_encode %{ */
7678 /* __ stop("testL_reg_con unimplemented"); */
7679 /* %} */
7680 /* ins_pipe(ialu_cconly_reg_reg); */
7681 /* %} */
7682
7683 instruct compU_iReg_imm(flagsRegU icc, iRegI op1, aimmU31 op2 ) %{
7684 match(Set icc (CmpU op1 op2));
7685
7686 size(4);
7687 format %{ "cmp_32 $op1,$op2\t! unsigned" %}
7688 ins_encode %{
7689 __ cmp_32($op1$$Register, $op2$$constant);
7690 %}
7691 ins_pipe(ialu_cconly_reg_imm);
7692 %}
7693
7694 // Compare Pointers
7695 instruct compP_iRegP(flagsRegP pcc, iRegP op1, iRegP op2 ) %{
7696 match(Set pcc (CmpP op1 op2));
7697
7698 size(4);
7699 format %{ "CMP $op1,$op2\t! ptr" %}
7700 ins_encode %{
7701 __ cmp($op1$$Register, $op2$$Register);
7702 %}
7703 ins_pipe(ialu_cconly_reg_reg);
7704 %}
7705
7706 instruct compP_iRegP_imm(flagsRegP pcc, iRegP op1, aimmP op2 ) %{
7707 match(Set pcc (CmpP op1 op2));
7708
7709 size(4);
7710 format %{ "CMP $op1,$op2\t! ptr" %}
7711 ins_encode %{
7712 assert($op2$$constant == 0 || _opnds[2]->constant_reloc() == relocInfo::none, "reloc in cmp?");
7713 __ cmp($op1$$Register, $op2$$constant);
7714 %}
7715 ins_pipe(ialu_cconly_reg_imm);
7716 %}
7717
7718 //----------Max and Min--------------------------------------------------------
7719 // Min Instructions
7720 // Conditional move for min
7721 instruct cmovI_reg_lt( iRegI op2, iRegI op1, flagsReg icc ) %{
7722 effect( USE_DEF op2, USE op1, USE icc );
7723
7724 size(4);
7725 format %{ "MOV.lt $op2,$op1\t! min" %}
7726 ins_encode %{
7727 __ mov($op2$$Register, $op1$$Register, lt);
7728 %}
7729 ins_pipe(ialu_reg_flags);
7730 %}
7731
7732 // Min Register with Register.
7733 instruct minI_eReg(iRegI op1, iRegI op2) %{
7734 match(Set op2 (MinI op1 op2));
7735 ins_cost(DEFAULT_COST*2);
7736 expand %{
7737 flagsReg icc;
7738 compI_iReg(icc,op1,op2);
7739 cmovI_reg_lt(op2,op1,icc);
7740 %}
7741 %}
7742
7743 // Max Instructions
7744 // Conditional move for max
7745 instruct cmovI_reg_gt( iRegI op2, iRegI op1, flagsReg icc ) %{
7746 effect( USE_DEF op2, USE op1, USE icc );
7747 format %{ "MOV.gt $op2,$op1\t! max" %}
7748 ins_encode %{
7749 __ mov($op2$$Register, $op1$$Register, gt);
7750 %}
7751 ins_pipe(ialu_reg_flags);
7752 %}
7753
7754 // Max Register with Register
7755 instruct maxI_eReg(iRegI op1, iRegI op2) %{
7756 match(Set op2 (MaxI op1 op2));
7757 ins_cost(DEFAULT_COST*2);
7758 expand %{
7759 flagsReg icc;
7760 compI_iReg(icc,op1,op2);
7761 cmovI_reg_gt(op2,op1,icc);
7762 %}
7763 %}
7764
7765
7766 //----------Float Compares----------------------------------------------------
7767 // Compare floating, generate condition code
7768 instruct cmpF_cc(flagsRegF fcc, flagsReg icc, regF src1, regF src2) %{
7769 match(Set icc (CmpF src1 src2));
7770 effect(KILL fcc);
7771
7772 size(8);
7773 format %{ "FCMPs $src1,$src2\n\t"
7774 "FMSTAT" %}
7775 ins_encode %{
7776 __ fcmps($src1$$FloatRegister, $src2$$FloatRegister);
7777 __ fmstat();
7778 %}
7779 ins_pipe(faddF_fcc_reg_reg_zero);
7780 %}
7781
7782 instruct cmpF0_cc(flagsRegF fcc, flagsReg icc, regF src1, immF0 src2) %{
7783 match(Set icc (CmpF src1 src2));
7784 effect(KILL fcc);
7785
7786 size(8);
7787 format %{ "FCMPs $src1,$src2\n\t"
7788 "FMSTAT" %}
7789 ins_encode %{
7790 __ fcmpzs($src1$$FloatRegister);
7791 __ fmstat();
7792 %}
7793 ins_pipe(faddF_fcc_reg_reg_zero);
7794 %}
7795
7796 instruct cmpD_cc(flagsRegF fcc, flagsReg icc, regD src1, regD src2) %{
7797 match(Set icc (CmpD src1 src2));
7798 effect(KILL fcc);
7799
7800 size(8);
7801 format %{ "FCMPd $src1,$src2 \n\t"
7802 "FMSTAT" %}
7803 ins_encode %{
7804 __ fcmpd($src1$$FloatRegister, $src2$$FloatRegister);
7805 __ fmstat();
7806 %}
7807 ins_pipe(faddD_fcc_reg_reg_zero);
7808 %}
7809
7810 instruct cmpD0_cc(flagsRegF fcc, flagsReg icc, regD src1, immD0 src2) %{
7811 match(Set icc (CmpD src1 src2));
7812 effect(KILL fcc);
7813
7814 size(8);
7815 format %{ "FCMPZd $src1,$src2 \n\t"
7816 "FMSTAT" %}
7817 ins_encode %{
7818 __ fcmpzd($src1$$FloatRegister);
7819 __ fmstat();
7820 %}
7821 ins_pipe(faddD_fcc_reg_reg_zero);
7822 %}
7823
7824 // Compare floating, generate -1,0,1
7825 instruct cmpF_reg(iRegI dst, regF src1, regF src2, flagsRegF fcc) %{
7826 match(Set dst (CmpF3 src1 src2));
7827 effect(KILL fcc);
7828 ins_cost(DEFAULT_COST*3+BRANCH_COST*3); // FIXME
7829 size(20);
7830 // same number of instructions as code using conditional moves but
7831 // doesn't kill integer condition register
7832 format %{ "FCMPs $dst,$src1,$src2 \n\t"
7833 "VMRS $dst, FPSCR \n\t"
7834 "OR $dst, $dst, 0x08000000 \n\t"
7835 "EOR $dst, $dst, $dst << 3 \n\t"
7836 "MOV $dst, $dst >> 30" %}
7837 ins_encode %{
7838 __ fcmps($src1$$FloatRegister, $src2$$FloatRegister);
7839 __ floating_cmp($dst$$Register);
7840 %}
7841 ins_pipe( floating_cmp );
7842 %}
7843
7844 instruct cmpF0_reg(iRegI dst, regF src1, immF0 src2, flagsRegF fcc) %{
7845 match(Set dst (CmpF3 src1 src2));
7846 effect(KILL fcc);
7847 ins_cost(DEFAULT_COST*3+BRANCH_COST*3); // FIXME
7848 size(20);
7849 // same number of instructions as code using conditional moves but
7850 // doesn't kill integer condition register
7851 format %{ "FCMPZs $dst,$src1,$src2 \n\t"
7852 "VMRS $dst, FPSCR \n\t"
7853 "OR $dst, $dst, 0x08000000 \n\t"
7854 "EOR $dst, $dst, $dst << 3 \n\t"
7855 "MOV $dst, $dst >> 30" %}
7856 ins_encode %{
7857 __ fcmpzs($src1$$FloatRegister);
7858 __ floating_cmp($dst$$Register);
7859 %}
7860 ins_pipe( floating_cmp );
7861 %}
7862
7863 instruct cmpD_reg(iRegI dst, regD src1, regD src2, flagsRegF fcc) %{
7864 match(Set dst (CmpD3 src1 src2));
7865 effect(KILL fcc);
7866 ins_cost(DEFAULT_COST*3+BRANCH_COST*3); // FIXME
7867 size(20);
7868 // same number of instructions as code using conditional moves but
7869 // doesn't kill integer condition register
7870 format %{ "FCMPd $dst,$src1,$src2 \n\t"
7871 "VMRS $dst, FPSCR \n\t"
7872 "OR $dst, $dst, 0x08000000 \n\t"
7873 "EOR $dst, $dst, $dst << 3 \n\t"
7874 "MOV $dst, $dst >> 30" %}
7875 ins_encode %{
7876 __ fcmpd($src1$$FloatRegister, $src2$$FloatRegister);
7877 __ floating_cmp($dst$$Register);
7878 %}
7879 ins_pipe( floating_cmp );
7880 %}
7881
7882 instruct cmpD0_reg(iRegI dst, regD src1, immD0 src2, flagsRegF fcc) %{
7883 match(Set dst (CmpD3 src1 src2));
7884 effect(KILL fcc);
7885 ins_cost(DEFAULT_COST*3+BRANCH_COST*3); // FIXME
7886 size(20);
7887 // same number of instructions as code using conditional moves but
7888 // doesn't kill integer condition register
7889 format %{ "FCMPZd $dst,$src1,$src2 \n\t"
7890 "VMRS $dst, FPSCR \n\t"
7891 "OR $dst, $dst, 0x08000000 \n\t"
7892 "EOR $dst, $dst, $dst << 3 \n\t"
7893 "MOV $dst, $dst >> 30" %}
7894 ins_encode %{
7895 __ fcmpzd($src1$$FloatRegister);
7896 __ floating_cmp($dst$$Register);
7897 %}
7898 ins_pipe( floating_cmp );
7899 %}
7900
7901 //----------Branches---------------------------------------------------------
7902 // Jump
7903 // (compare 'operand indIndex' and 'instruct addP_reg_reg' above)
7904 // FIXME
7905 instruct jumpXtnd(iRegX switch_val, iRegP tmp) %{
7906 match(Jump switch_val);
7907 effect(TEMP tmp);
7908 ins_cost(350);
7909 format %{ "ADD $tmp, $constanttablebase, $switch_val\n\t"
7910 "LDR $tmp,[$tmp + $constantoffset]\n\t"
7911 "BX $tmp" %}
7912 size(20);
7913 ins_encode %{
7914 Register table_reg;
7915 Register label_reg = $tmp$$Register;
7916 if (constant_offset() == 0) {
7917 table_reg = $constanttablebase;
7918 __ ldr(label_reg, Address(table_reg, $switch_val$$Register));
7919 } else {
7920 table_reg = $tmp$$Register;
7921 int offset = $constantoffset;
7922 if (is_memoryP(offset)) {
7923 __ add(table_reg, $constanttablebase, $switch_val$$Register);
7924 __ ldr(label_reg, Address(table_reg, offset));
7925 } else {
7926 __ mov_slow(table_reg, $constantoffset);
7927 __ add(table_reg, $constanttablebase, table_reg);
7928 __ ldr(label_reg, Address(table_reg, $switch_val$$Register));
7929 }
7930 }
7931 __ jump(label_reg); // ldr + b better than ldr to PC for branch predictor?
7932 // __ ldr(PC, Address($table$$Register, $switch_val$$Register));
7933 %}
7934 ins_pipe(ialu_reg_reg);
7935 %}
7936
7937 // // Direct Branch.
7938 instruct branch(label labl) %{
7939 match(Goto);
7940 effect(USE labl);
7941
7942 size(4);
7943 ins_cost(BRANCH_COST);
7944 format %{ "B $labl" %}
7945 ins_encode %{
7946 __ b(*($labl$$label));
7947 %}
7948 ins_pipe(br);
7949 %}
7950
7951 // Conditional Direct Branch
7952 instruct branchCon(cmpOp cmp, flagsReg icc, label labl) %{
7953 match(If cmp icc);
7954 effect(USE labl);
7955
7956 size(4);
7957 ins_cost(BRANCH_COST);
7958 format %{ "B$cmp $icc,$labl" %}
7959 ins_encode %{
7960 __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode));
7961 %}
7962 ins_pipe(br_cc);
7963 %}
7964
7965 #ifdef ARM
7966 instruct branchCon_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, label labl) %{
7967 match(If cmp icc);
7968 effect(USE labl);
7969 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);
7970
7971 size(4);
7972 ins_cost(BRANCH_COST);
7973 format %{ "B$cmp $icc,$labl" %}
7974 ins_encode %{
7975 __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode));
7976 %}
7977 ins_pipe(br_cc);
7978 %}
7979 #endif
7980
7981
7982 instruct branchConU(cmpOpU cmp, flagsRegU icc, label labl) %{
7983 match(If cmp icc);
7984 effect(USE labl);
7985
7986 size(4);
7987 ins_cost(BRANCH_COST);
7988 format %{ "B$cmp $icc,$labl" %}
7989 ins_encode %{
7990 __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode));
7991 %}
7992 ins_pipe(br_cc);
7993 %}
7994
7995 instruct branchConP(cmpOpP cmp, flagsRegP pcc, label labl) %{
7996 match(If cmp pcc);
7997 effect(USE labl);
7998
7999 size(4);
8000 ins_cost(BRANCH_COST);
8001 format %{ "B$cmp $pcc,$labl" %}
8002 ins_encode %{
8003 __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode));
8004 %}
8005 ins_pipe(br_cc);
8006 %}
8007
8008 instruct branchConL_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, label labl) %{
8009 match(If cmp xcc);
8010 effect(USE labl);
8011 predicate( _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge );
8012
8013 size(4);
8014 ins_cost(BRANCH_COST);
8015 format %{ "B$cmp $xcc,$labl" %}
8016 ins_encode %{
8017 __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode));
8018 %}
8019 ins_pipe(br_cc);
8020 %}
8021
8022 instruct branchConL_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, label labl) %{
8023 match(If cmp xcc);
8024 effect(USE labl);
8025 predicate( _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne );
8026
8027 size(4);
8028 ins_cost(BRANCH_COST);
8029 format %{ "B$cmp $xcc,$labl" %}
8030 ins_encode %{
8031 __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode));
8032 %}
8033 ins_pipe(br_cc);
8034 %}
8035
8036 instruct branchConL_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, label labl) %{
8037 match(If cmp xcc);
8038 effect(USE labl);
8039 predicate( _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le );
8040
8041 size(4);
8042 ins_cost(BRANCH_COST);
8043 format %{ "B$cmp $xcc,$labl" %}
8044 ins_encode %{
8045 __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode));
8046 %}
8047 ins_pipe(br_cc);
8048 %}
8049
8050 instruct branchConUL_LTGE(cmpOpUL cmp, flagsRegUL_LTGE xcc, label labl) %{
8051 match(If cmp xcc);
8052 effect(USE labl);
8053 predicate(_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
8054
8055 size(4);
8056 ins_cost(BRANCH_COST);
8057 format %{ "B$cmp $xcc,$labl" %}
8058 ins_encode %{
8059 __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode));
8060 %}
8061 ins_pipe(br_cc);
8062 %}
8063
8064 instruct branchConUL_EQNE(cmpOpUL cmp, flagsRegUL_EQNE xcc, label labl) %{
8065 match(If cmp xcc);
8066 effect(USE labl);
8067 predicate(_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne);
8068
8069 size(4);
8070 ins_cost(BRANCH_COST);
8071 format %{ "B$cmp $xcc,$labl" %}
8072 ins_encode %{
8073 __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode));
8074 %}
8075 ins_pipe(br_cc);
8076 %}
8077
8078 instruct branchConUL_LEGT(cmpOpUL_commute cmp, flagsRegUL_LEGT xcc, label labl) %{
8079 match(If cmp xcc);
8080 effect(USE labl);
8081 predicate(_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le);
8082
8083 size(4);
8084 ins_cost(BRANCH_COST);
8085 format %{ "B$cmp $xcc,$labl" %}
8086 ins_encode %{
8087 __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode));
8088 %}
8089 ins_pipe(br_cc);
8090 %}
8091
8092 instruct branchLoopEnd(cmpOp cmp, flagsReg icc, label labl) %{
8093 match(CountedLoopEnd cmp icc);
8094 effect(USE labl);
8095
8096 size(4);
8097 ins_cost(BRANCH_COST);
8098 format %{ "B$cmp $icc,$labl\t! Loop end" %}
8099 ins_encode %{
8100 __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode));
8101 %}
8102 ins_pipe(br_cc);
8103 %}
8104
8105 // instruct branchLoopEndU(cmpOpU cmp, flagsRegU icc, label labl) %{
8106 // match(CountedLoopEnd cmp icc);
8107 // ins_pipe(br_cc);
8108 // %}
8109
8110 // ============================================================================
8111 // Long Compare
8112 //
8113 // Currently we hold longs in 2 registers. Comparing such values efficiently
8114 // is tricky. The flavor of compare used depends on whether we are testing
8115 // for LT, LE, or EQ. For a simple LT test we can check just the sign bit.
8116 // The GE test is the negated LT test. The LE test can be had by commuting
8117 // the operands (yielding a GE test) and then negating; negate again for the
8118 // GT test. The EQ test is done by ORcc'ing the high and low halves, and the
8119 // NE test is negated from that.
8120
8121 // Due to a shortcoming in the ADLC, it mixes up expressions like:
8122 // (foo (CmpI (CmpL X Y) 0)) and (bar (CmpI (CmpL X 0L) 0)). Note the
8123 // difference between 'Y' and '0L'. The tree-matches for the CmpI sections
8124 // are collapsed internally in the ADLC's dfa-gen code. The match for
8125 // (CmpI (CmpL X Y) 0) is silently replaced with (CmpI (CmpL X 0L) 0) and the
8126 // foo match ends up with the wrong leaf. One fix is to not match both
8127 // reg-reg and reg-zero forms of long-compare. This is unfortunate because
8128 // both forms beat the trinary form of long-compare and both are very useful
8129 // on Intel which has so few registers.
8130
8131 // instruct branchCon_long(cmpOp cmp, flagsRegL xcc, label labl) %{
8132 // match(If cmp xcc);
8133 // ins_pipe(br_cc);
8134 // %}
8135
8136 // Manifest a CmpL3 result in an integer register. Very painful.
8137 // This is the test to avoid.
8138 instruct cmpL3_reg_reg(iRegI dst, iRegL src1, iRegL src2, flagsReg ccr ) %{
8139 match(Set dst (CmpL3 src1 src2) );
8140 effect( KILL ccr );
8141 ins_cost(6*DEFAULT_COST); // FIXME
8142 size(32);
8143 format %{
8144 "CMP $src1.hi, $src2.hi\t\t! long\n"
8145 "\tMOV.gt $dst, 1\n"
8146 "\tmvn.lt $dst, 0\n"
8147 "\tB.ne done\n"
8148 "\tSUBS $dst, $src1.lo, $src2.lo\n"
8149 "\tMOV.hi $dst, 1\n"
8150 "\tmvn.lo $dst, 0\n"
8151 "done:" %}
8152 ins_encode %{
8153 Label done;
8154 __ cmp($src1$$Register->successor(), $src2$$Register->successor());
8155 __ mov($dst$$Register, 1, gt);
8156 __ mvn($dst$$Register, 0, lt);
8157 __ b(done, ne);
8158 __ subs($dst$$Register, $src1$$Register, $src2$$Register);
8159 __ mov($dst$$Register, 1, hi);
8160 __ mvn($dst$$Register, 0, lo);
8161 __ bind(done);
8162 %}
8163 ins_pipe(cmpL_reg);
8164 %}
8165
8166 // Conditional move
8167 instruct cmovLL_reg_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, iRegL dst, iRegL src) %{
8168 match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src)));
8169 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
8170
8171 ins_cost(150);
8172 size(8);
8173 format %{ "MOV$cmp $dst.lo,$src.lo\t! long\n\t"
8174 "MOV$cmp $dst,$src.hi" %}
8175 ins_encode %{
8176 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
8177 __ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode));
8178 %}
8179 ins_pipe(ialu_reg);
8180 %}
8181
8182 instruct cmovLL_reg_LTGE_U(cmpOpUL cmp, flagsRegUL_LTGE xcc, iRegL dst, iRegL src) %{
8183 match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src)));
8184 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
8185
8186 ins_cost(150);
8187 size(8);
8188 format %{ "MOV$cmp $dst.lo,$src.lo\t! long\n\t"
8189 "MOV$cmp $dst,$src.hi" %}
8190 ins_encode %{
8191 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
8192 __ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode));
8193 %}
8194 ins_pipe(ialu_reg);
8195 %}
8196
8197 instruct cmovLL_reg_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, iRegL dst, iRegL src) %{
8198 match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src)));
8199 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne);
8200
8201 ins_cost(150);
8202 size(8);
8203 format %{ "MOV$cmp $dst.lo,$src.lo\t! long\n\t"
8204 "MOV$cmp $dst,$src.hi" %}
8205 ins_encode %{
8206 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
8207 __ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode));
8208 %}
8209 ins_pipe(ialu_reg);
8210 %}
8211
8212 instruct cmovLL_reg_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, iRegL dst, iRegL src) %{
8213 match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src)));
8214 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt);
8215
8216 ins_cost(150);
8217 size(8);
8218 format %{ "MOV$cmp $dst.lo,$src.lo\t! long\n\t"
8219 "MOV$cmp $dst,$src.hi" %}
8220 ins_encode %{
8221 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
8222 __ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode));
8223 %}
8224 ins_pipe(ialu_reg);
8225 %}
8226
8227 instruct cmovLL_reg_LEGT_U(cmpOpUL_commute cmp, flagsRegUL_LEGT xcc, iRegL dst, iRegL src) %{
8228 match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src)));
8229 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt);
8230
8231 ins_cost(150);
8232 size(8);
8233 format %{ "MOV$cmp $dst.lo,$src.lo\t! long\n\t"
8234 "MOV$cmp $dst,$src.hi" %}
8235 ins_encode %{
8236 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
8237 __ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode));
8238 %}
8239 ins_pipe(ialu_reg);
8240 %}
8241
8242 instruct cmovLL_imm_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, iRegL dst, immL0 src) %{
8243 match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src)));
8244 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
8245 ins_cost(140);
8246 size(8);
8247 format %{ "MOV$cmp $dst.lo,0\t! long\n\t"
8248 "MOV$cmp $dst,0" %}
8249 ins_encode %{
8250 __ mov($dst$$Register, 0, (AsmCondition)($cmp$$cmpcode));
8251 __ mov($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode));
8252 %}
8253 ins_pipe(ialu_imm);
8254 %}
8255
8256 instruct cmovLL_imm_LTGE_U(cmpOpUL cmp, flagsRegUL_LTGE xcc, iRegL dst, immL0 src) %{
8257 match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src)));
8258 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
8259 ins_cost(140);
8260 size(8);
8261 format %{ "MOV$cmp $dst.lo,0\t! long\n\t"
8262 "MOV$cmp $dst,0" %}
8263 ins_encode %{
8264 __ mov($dst$$Register, 0, (AsmCondition)($cmp$$cmpcode));
8265 __ mov($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode));
8266 %}
8267 ins_pipe(ialu_imm);
8268 %}
8269
8270 instruct cmovLL_imm_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, iRegL dst, immL0 src) %{
8271 match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src)));
8272 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne);
8273 ins_cost(140);
8274 size(8);
8275 format %{ "MOV$cmp $dst.lo,0\t! long\n\t"
8276 "MOV$cmp $dst,0" %}
8277 ins_encode %{
8278 __ mov($dst$$Register, 0, (AsmCondition)($cmp$$cmpcode));
8279 __ mov($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode));
8280 %}
8281 ins_pipe(ialu_imm);
8282 %}
8283
8284 instruct cmovLL_imm_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, iRegL dst, immL0 src) %{
8285 match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src)));
8286 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt);
8287 ins_cost(140);
8288 size(8);
8289 format %{ "MOV$cmp $dst.lo,0\t! long\n\t"
8290 "MOV$cmp $dst,0" %}
8291 ins_encode %{
8292 __ mov($dst$$Register, 0, (AsmCondition)($cmp$$cmpcode));
8293 __ mov($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode));
8294 %}
8295 ins_pipe(ialu_imm);
8296 %}
8297
8298 instruct cmovIL_reg_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, iRegI dst, iRegI src) %{
8299 match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src)));
8300 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
8301
8302 ins_cost(150);
8303 size(4);
8304 format %{ "MOV$cmp $dst,$src" %}
8305 ins_encode %{
8306 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
8307 %}
8308 ins_pipe(ialu_reg);
8309 %}
8310
8311 instruct cmovIL_reg_LTGE_U(cmpOpUL cmp, flagsRegUL_LTGE xcc, iRegI dst, iRegI src) %{
8312 match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src)));
8313 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
8314
8315 ins_cost(150);
8316 size(4);
8317 format %{ "MOV$cmp $dst,$src" %}
8318 ins_encode %{
8319 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
8320 %}
8321 ins_pipe(ialu_reg);
8322 %}
8323
8324 instruct cmovIL_reg_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, iRegI dst, iRegI src) %{
8325 match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src)));
8326 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne);
8327
8328 ins_cost(150);
8329 size(4);
8330 format %{ "MOV$cmp $dst,$src" %}
8331 ins_encode %{
8332 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
8333 %}
8334 ins_pipe(ialu_reg);
8335 %}
8336
8337 instruct cmovIL_reg_EQNE_U(cmpOpUL cmp, flagsRegUL_EQNE xcc, iRegI dst, iRegI src) %{
8338 match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src)));
8339 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne);
8340
8341 ins_cost(150);
8342 size(4);
8343 format %{ "MOV$cmp $dst,$src" %}
8344 ins_encode %{
8345 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
8346 %}
8347 ins_pipe(ialu_reg);
8348 %}
8349
8350 instruct cmovIL_reg_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, iRegI dst, iRegI src) %{
8351 match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src)));
8352 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt);
8353
8354 ins_cost(150);
8355 size(4);
8356 format %{ "MOV$cmp $dst,$src" %}
8357 ins_encode %{
8358 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
8359 %}
8360 ins_pipe(ialu_reg);
8361 %}
8362
8363 instruct cmovIL_reg_LEGT_U(cmpOpUL_commute cmp, flagsRegUL_LEGT xcc, iRegI dst, iRegI src) %{
8364 match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src)));
8365 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt);
8366
8367 ins_cost(150);
8368 size(4);
8369 format %{ "MOV$cmp $dst,$src" %}
8370 ins_encode %{
8371 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
8372 %}
8373 ins_pipe(ialu_reg);
8374 %}
8375
8376 instruct cmovIL_imm16_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, iRegI dst, immI16 src) %{
8377 match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src)));
8378 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
8379
8380 ins_cost(140);
8381 size(4);
8382 format %{ "MOVW$cmp $dst,$src" %}
8383 ins_encode %{
8384 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
8385 %}
8386 ins_pipe(ialu_imm);
8387 %}
8388
8389 instruct cmovIL_imm16_LTGE_U(cmpOpUL cmp, flagsRegUL_LTGE xcc, iRegI dst, immI16 src) %{
8390 match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src)));
8391 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
8392
8393 ins_cost(140);
8394 size(4);
8395 format %{ "MOVW$cmp $dst,$src" %}
8396 ins_encode %{
8397 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
8398 %}
8399 ins_pipe(ialu_imm);
8400 %}
8401
8402 instruct cmovIL_imm16_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, iRegI dst, immI16 src) %{
8403 match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src)));
8404 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne);
8405
8406 ins_cost(140);
8407 size(4);
8408 format %{ "MOVW$cmp $dst,$src" %}
8409 ins_encode %{
8410 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
8411 %}
8412 ins_pipe(ialu_imm);
8413 %}
8414
8415 instruct cmovIL_imm16_EQNE_U(cmpOpUL cmp, flagsRegUL_EQNE xcc, iRegI dst, immI16 src) %{
8416 match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src)));
8417 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne);
8418
8419 ins_cost(140);
8420 size(4);
8421 format %{ "MOVW$cmp $dst,$src" %}
8422 ins_encode %{
8423 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
8424 %}
8425 ins_pipe(ialu_imm);
8426 %}
8427
8428 instruct cmovIL_imm16_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, iRegI dst, immI16 src) %{
8429 match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src)));
8430 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt);
8431
8432 ins_cost(140);
8433 size(4);
8434 format %{ "MOVW$cmp $dst,$src" %}
8435 ins_encode %{
8436 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
8437 %}
8438 ins_pipe(ialu_imm);
8439 %}
8440
8441 instruct cmovIL_imm16_LEGT_U(cmpOpUL_commute cmp, flagsRegUL_LEGT xcc, iRegI dst, immI16 src) %{
8442 match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src)));
8443 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt);
8444
8445 ins_cost(140);
8446 size(4);
8447 format %{ "MOVW$cmp $dst,$src" %}
8448 ins_encode %{
8449 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
8450 %}
8451 ins_pipe(ialu_imm);
8452 %}
8453
8454 instruct cmovIL_immMov_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, iRegI dst, immIMov src) %{
8455 match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src)));
8456 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
8457
8458 ins_cost(140);
8459 size(4);
8460 format %{ "MOV$cmp $dst,$src" %}
8461 ins_encode %{
8462 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
8463 %}
8464 ins_pipe(ialu_imm);
8465 %}
8466
8467 instruct cmovIL_immMov_LTGE_U(cmpOpUL cmp, flagsRegUL_LTGE xcc, iRegI dst, immIMov src) %{
8468 match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src)));
8469 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
8470
8471 ins_cost(140);
8472 size(4);
8473 format %{ "MOV$cmp $dst,$src" %}
8474 ins_encode %{
8475 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
8476 %}
8477 ins_pipe(ialu_imm);
8478 %}
8479
8480 instruct cmovIL_immMov_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, iRegI dst, immIMov src) %{
8481 match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src)));
8482 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne);
8483
8484 ins_cost(140);
8485 size(4);
8486 format %{ "MOV$cmp $dst,$src" %}
8487 ins_encode %{
8488 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
8489 %}
8490 ins_pipe(ialu_imm);
8491 %}
8492
8493 instruct cmovIL_immMov_EQNE_U(cmpOpUL cmp, flagsRegUL_EQNE xcc, iRegI dst, immIMov src) %{
8494 match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src)));
8495 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne);
8496
8497 ins_cost(140);
8498 size(4);
8499 format %{ "MOV$cmp $dst,$src" %}
8500 ins_encode %{
8501 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
8502 %}
8503 ins_pipe(ialu_imm);
8504 %}
8505
8506 instruct cmovIL_immMov_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, iRegI dst, immIMov src) %{
8507 match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src)));
8508 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt);
8509
8510 ins_cost(140);
8511 size(4);
8512 format %{ "MOV$cmp $dst,$src" %}
8513 ins_encode %{
8514 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
8515 %}
8516 ins_pipe(ialu_imm);
8517 %}
8518
8519 instruct cmovIL_immMov_LEGT_U(cmpOpUL_commute cmp, flagsRegUL_LEGT xcc, iRegI dst, immIMov src) %{
8520 match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src)));
8521 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt);
8522
8523 ins_cost(140);
8524 size(4);
8525 format %{ "MOV$cmp $dst,$src" %}
8526 ins_encode %{
8527 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
8528 %}
8529 ins_pipe(ialu_imm);
8530 %}
8531
8532 instruct cmovPL_reg_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, iRegP dst, iRegP src) %{
8533 match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src)));
8534 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
8535
8536 ins_cost(150);
8537 size(4);
8538 format %{ "MOV$cmp $dst,$src" %}
8539 ins_encode %{
8540 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
8541 %}
8542 ins_pipe(ialu_reg);
8543 %}
8544
8545 instruct cmovPL_reg_LTGE_U(cmpOpUL cmp, flagsRegUL_LTGE xcc, iRegP dst, iRegP src) %{
8546 match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src)));
8547 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
8548
8549 ins_cost(150);
8550 size(4);
8551 format %{ "MOV$cmp $dst,$src" %}
8552 ins_encode %{
8553 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
8554 %}
8555 ins_pipe(ialu_reg);
8556 %}
8557
8558 instruct cmovPL_reg_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, iRegP dst, iRegP src) %{
8559 match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src)));
8560 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne);
8561
8562 ins_cost(150);
8563 size(4);
8564 format %{ "MOV$cmp $dst,$src" %}
8565 ins_encode %{
8566 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
8567 %}
8568 ins_pipe(ialu_reg);
8569 %}
8570
8571 instruct cmovPL_reg_EQNE_U(cmpOpUL cmp, flagsRegUL_EQNE xcc, iRegP dst, iRegP src) %{
8572 match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src)));
8573 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne);
8574
8575 ins_cost(150);
8576 size(4);
8577 format %{ "MOV$cmp $dst,$src" %}
8578 ins_encode %{
8579 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
8580 %}
8581 ins_pipe(ialu_reg);
8582 %}
8583
8584 instruct cmovPL_reg_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, iRegP dst, iRegP src) %{
8585 match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src)));
8586 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt);
8587
8588 ins_cost(150);
8589 size(4);
8590 format %{ "MOV$cmp $dst,$src" %}
8591 ins_encode %{
8592 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
8593 %}
8594 ins_pipe(ialu_reg);
8595 %}
8596
8597 instruct cmovPL_reg_LEGT_U(cmpOpUL_commute cmp, flagsRegUL_LEGT xcc, iRegP dst, iRegP src) %{
8598 match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src)));
8599 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt);
8600
8601 ins_cost(150);
8602 size(4);
8603 format %{ "MOV$cmp $dst,$src" %}
8604 ins_encode %{
8605 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode));
8606 %}
8607 ins_pipe(ialu_reg);
8608 %}
8609
8610 instruct cmovPL_imm_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, iRegP dst, immP0 src) %{
8611 match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src)));
8612 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
8613
8614 ins_cost(140);
8615 size(4);
8616 format %{ "MOVW$cmp $dst,$src" %}
8617 ins_encode %{
8618 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
8619 %}
8620 ins_pipe(ialu_imm);
8621 %}
8622
8623 instruct cmovPL_imm_LTGE_U(cmpOpUL cmp, flagsRegUL_LTGE xcc, iRegP dst, immP0 src) %{
8624 match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src)));
8625 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
8626
8627 ins_cost(140);
8628 size(4);
8629 format %{ "MOVW$cmp $dst,$src" %}
8630 ins_encode %{
8631 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
8632 %}
8633 ins_pipe(ialu_imm);
8634 %}
8635
8636 instruct cmovPL_imm_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, iRegP dst, immP0 src) %{
8637 match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src)));
8638 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne);
8639
8640 ins_cost(140);
8641 size(4);
8642 format %{ "MOVW$cmp $dst,$src" %}
8643 ins_encode %{
8644 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
8645 %}
8646 ins_pipe(ialu_imm);
8647 %}
8648
8649 instruct cmovPL_imm_EQNE_U(cmpOpUL cmp, flagsRegUL_EQNE xcc, iRegP dst, immP0 src) %{
8650 match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src)));
8651 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne);
8652
8653 ins_cost(140);
8654 size(4);
8655 format %{ "MOVW$cmp $dst,$src" %}
8656 ins_encode %{
8657 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
8658 %}
8659 ins_pipe(ialu_imm);
8660 %}
8661
8662 instruct cmovPL_imm_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, iRegP dst, immP0 src) %{
8663 match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src)));
8664 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt);
8665
8666 ins_cost(140);
8667 size(4);
8668 format %{ "MOVW$cmp $dst,$src" %}
8669 ins_encode %{
8670 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
8671 %}
8672 ins_pipe(ialu_imm);
8673 %}
8674
8675 instruct cmovPL_imm_LEGT_U(cmpOpUL_commute cmp, flagsRegUL_LEGT xcc, iRegP dst, immP0 src) %{
8676 match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src)));
8677 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt);
8678
8679 ins_cost(140);
8680 size(4);
8681 format %{ "MOVW$cmp $dst,$src" %}
8682 ins_encode %{
8683 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode));
8684 %}
8685 ins_pipe(ialu_imm);
8686 %}
8687
8688 instruct cmovFL_reg_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, regF dst, regF src) %{
8689 match(Set dst (CMoveF (Binary cmp xcc) (Binary dst src)));
8690 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
8691 ins_cost(150);
8692 size(4);
8693 format %{ "FCPYS$cmp $dst,$src" %}
8694 ins_encode %{
8695 __ fcpys($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
8696 %}
8697 ins_pipe(int_conditional_float_move);
8698 %}
8699
8700 instruct cmovFL_reg_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, regF dst, regF src) %{
8701 match(Set dst (CMoveF (Binary cmp xcc) (Binary dst src)));
8702 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne);
8703 ins_cost(150);
8704 size(4);
8705 format %{ "FCPYS$cmp $dst,$src" %}
8706 ins_encode %{
8707 __ fcpys($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
8708 %}
8709 ins_pipe(int_conditional_float_move);
8710 %}
8711
8712 instruct cmovFL_reg_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, regF dst, regF src) %{
8713 match(Set dst (CMoveF (Binary cmp xcc) (Binary dst src)));
8714 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt);
8715 ins_cost(150);
8716 size(4);
8717 format %{ "FCPYS$cmp $dst,$src" %}
8718 ins_encode %{
8719 __ fcpys($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
8720 %}
8721 ins_pipe(int_conditional_float_move);
8722 %}
8723
8724 instruct cmovDL_reg_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, regD dst, regD src) %{
8725 match(Set dst (CMoveD (Binary cmp xcc) (Binary dst src)));
8726 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
8727
8728 ins_cost(150);
8729 size(4);
8730 format %{ "FCPYD$cmp $dst,$src" %}
8731 ins_encode %{
8732 __ fcpyd($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
8733 %}
8734 ins_pipe(int_conditional_float_move);
8735 %}
8736
8737 instruct cmovDL_reg_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, regD dst, regD src) %{
8738 match(Set dst (CMoveD (Binary cmp xcc) (Binary dst src)));
8739 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne);
8740
8741 ins_cost(150);
8742 size(4);
8743 format %{ "FCPYD$cmp $dst,$src" %}
8744 ins_encode %{
8745 __ fcpyd($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
8746 %}
8747 ins_pipe(int_conditional_float_move);
8748 %}
8749
8750 instruct cmovDL_reg_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, regD dst, regD src) %{
8751 match(Set dst (CMoveD (Binary cmp xcc) (Binary dst src)));
8752 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt);
8753
8754 ins_cost(150);
8755 size(4);
8756 format %{ "FCPYD$cmp $dst,$src" %}
8757 ins_encode %{
8758 __ fcpyd($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode));
8759 %}
8760 ins_pipe(int_conditional_float_move);
8761 %}
8762
8763 // ============================================================================
8764 // Safepoint Instruction
8765 // rather than KILL R12, it would be better to use any reg as
8766 // TEMP. Can't do that at this point because it crashes the compiler
8767 instruct safePoint_poll(iRegP poll, R12RegI tmp, flagsReg icc) %{
8768 match(SafePoint poll);
8769 effect(USE poll, KILL tmp, KILL icc);
8770
8771 size(4);
8772 format %{ "LDR $tmp,[$poll]\t! Safepoint: poll for GC" %}
8773 ins_encode %{
8774 __ relocate(relocInfo::poll_type);
8775 __ ldr($tmp$$Register, Address($poll$$Register));
8776 %}
8777 ins_pipe(loadPollP);
8778 %}
8779
8780
8781 // ============================================================================
8782 // Call Instructions
8783 // Call Java Static Instruction
8784 instruct CallStaticJavaDirect( method meth ) %{
8785 match(CallStaticJava);
8786 effect(USE meth);
8787
8788 ins_cost(CALL_COST);
8789 format %{ "CALL,static ==> " %}
8790 ins_encode( SetInstMark, Java_Static_Call( meth ), call_epilog, ClearInstMark );
8791 ins_pipe(simple_call);
8792 %}
8793
8794 // Call Java Dynamic Instruction
8795 instruct CallDynamicJavaDirect( method meth ) %{
8796 match(CallDynamicJava);
8797 effect(USE meth);
8798
8799 ins_cost(CALL_COST);
8800 format %{ "MOV_OOP (empty),R_R8\n\t"
8801 "CALL,dynamic ; NOP ==> " %}
8802 ins_encode( SetInstMark, Java_Dynamic_Call( meth ), call_epilog, ClearInstMark );
8803 ins_pipe(call);
8804 %}
8805
8806 // Call Runtime Instruction
8807 instruct CallRuntimeDirect(method meth) %{
8808 match(CallRuntime);
8809 effect(USE meth);
8810 ins_cost(CALL_COST);
8811 format %{ "CALL,runtime" %}
8812 ins_encode( SetInstMark, Java_To_Runtime( meth ),
8813 call_epilog, ClearInstMark );
8814 ins_pipe(simple_call);
8815 %}
8816
8817 // Call runtime without safepoint - same as CallRuntime
8818 instruct CallLeafDirect(method meth) %{
8819 match(CallLeaf);
8820 effect(USE meth);
8821 ins_cost(CALL_COST);
8822 format %{ "CALL,runtime leaf" %}
8823 // TODO: need save_last_PC here?
8824 ins_encode( SetInstMark, Java_To_Runtime( meth ),
8825 call_epilog, ClearInstMark );
8826 ins_pipe(simple_call);
8827 %}
8828
8829 // Call runtime without safepoint - same as CallLeaf
8830 instruct CallLeafNoFPDirect(method meth) %{
8831 match(CallLeafNoFP);
8832 effect(USE meth);
8833 ins_cost(CALL_COST);
8834 format %{ "CALL,runtime leaf nofp" %}
8835 // TODO: need save_last_PC here?
8836 ins_encode( SetInstMark, Java_To_Runtime( meth ),
8837 call_epilog, ClearInstMark );
8838 ins_pipe(simple_call);
8839 %}
8840
8841 // Tail Call; Jump from runtime stub to Java code.
8842 // Also known as an 'interprocedural jump'.
8843 // Target of jump will eventually return to caller.
8844 // TailJump below removes the return address.
8845 instruct TailCalljmpInd(IPRegP jump_target, inline_cache_regP method_ptr) %{
8846 match(TailCall jump_target method_ptr);
8847
8848 ins_cost(CALL_COST);
8849 format %{ "jump $jump_target \t! $method_ptr holds method" %}
8850 ins_encode %{
8851 __ jump($jump_target$$Register);
8852 %}
8853 ins_pipe(tail_call);
8854 %}
8855
8856
8857 // Return Instruction
8858 instruct Ret() %{
8859 match(Return);
8860
8861 format %{ "ret LR" %}
8862
8863 ins_encode %{
8864 __ ret(LR);
8865 %}
8866
8867 ins_pipe(br);
8868 %}
8869
8870
8871 // Tail Jump; remove the return address; jump to target.
8872 // TailCall above leaves the return address around.
8873 // TailJump is used in only one place, the rethrow_Java stub (fancy_jump=2).
8874 // ex_oop (Exception Oop) is needed in %o0 at the jump. As there would be a
8875 // "restore" before this instruction (in Epilogue), we need to materialize it
8876 // in %i0.
8877 instruct tailjmpInd(IPRegP jump_target, RExceptionRegP ex_oop) %{
8878 match( TailJump jump_target ex_oop );
8879 ins_cost(CALL_COST);
8880 format %{ "MOV Rexception_pc, LR\n\t"
8881 "jump $jump_target \t! $ex_oop holds exc. oop" %}
8882 ins_encode %{
8883 __ mov(Rexception_pc, LR);
8884 __ jump($jump_target$$Register);
8885 %}
8886 ins_pipe(tail_call);
8887 %}
8888
8889 // Forward exception.
8890 instruct ForwardExceptionjmp()
8891 %{
8892 match(ForwardException);
8893 ins_cost(CALL_COST);
8894
8895 format %{ "MOV Rexception_pc, LR\n\t"
8896 "b forward_exception_entry" %}
8897 ins_encode %{
8898 __ mov(Rexception_pc, LR);
8899 // OK to trash Rtemp, because Rtemp is used by stub
8900 __ jump(StubRoutines::forward_exception_entry(), relocInfo::runtime_call_type, Rtemp);
8901 %}
8902 ins_pipe(tail_call);
8903 %}
8904
8905 // Create exception oop: created by stack-crawling runtime code.
8906 // Created exception is now available to this handler, and is setup
8907 // just prior to jumping to this handler. No code emitted.
8908 instruct CreateException( RExceptionRegP ex_oop )
8909 %{
8910 match(Set ex_oop (CreateEx));
8911 ins_cost(0);
8912
8913 size(0);
8914 // use the following format syntax
8915 format %{ "! exception oop is in Rexception_obj; no code emitted" %}
8916 ins_encode();
8917 ins_pipe(empty);
8918 %}
8919
8920
8921 // Rethrow exception:
8922 // The exception oop will come in the first argument position.
8923 // Then JUMP (not call) to the rethrow stub code.
8924 instruct RethrowException()
8925 %{
8926 match(Rethrow);
8927 ins_cost(CALL_COST);
8928
8929 // use the following format syntax
8930 format %{ "b rethrow_stub" %}
8931 ins_encode %{
8932 Register scratch = R1_tmp;
8933 assert_different_registers(scratch, c_rarg0, LR);
8934 __ jump(OptoRuntime::rethrow_stub(), relocInfo::runtime_call_type, scratch);
8935 %}
8936 ins_pipe(tail_call);
8937 %}
8938
8939
8940 // Die now
8941 instruct ShouldNotReachHere( )
8942 %{
8943 match(Halt);
8944 ins_cost(CALL_COST);
8945
8946 // Use the following format syntax
8947 format %{ "ShouldNotReachHere" %}
8948 ins_encode %{
8949 if (is_reachable()) {
8950 const char* str = __ code_string(_halt_reason);
8951 __ stop(str);
8952 }
8953 %}
8954 ins_pipe(tail_call);
8955 %}
8956
8957 // ============================================================================
8958 // The 2nd slow-half of a subtype check. Scan the subklass's 2ndary superklass
8959 // array for an instance of the superklass. Set a hidden internal cache on a
8960 // hit (cache is checked with exposed code in gen_subtype_check()). Return
8961 // not zero for a miss or zero for a hit. The encoding ALSO sets flags.
8962 instruct partialSubtypeCheck( R0RegP index, R1RegP sub, R2RegP super, flagsRegP pcc, LRRegP lr ) %{
8963 match(Set index (PartialSubtypeCheck sub super));
8964 effect( KILL pcc, KILL lr );
8965 ins_cost(DEFAULT_COST*10);
8966 format %{ "CALL PartialSubtypeCheck" %}
8967 ins_encode %{
8968 __ call(StubRoutines::Arm::partial_subtype_check(), relocInfo::runtime_call_type);
8969 %}
8970 ins_pipe(partial_subtype_check_pipe);
8971 %}
8972
8973 /* instruct partialSubtypeCheck_vs_zero( flagsRegP pcc, o1RegP sub, o2RegP super, immP0 zero, o0RegP idx, o7RegP o7 ) %{ */
8974 /* match(Set pcc (CmpP (PartialSubtypeCheck sub super) zero)); */
8975 /* ins_pipe(partial_subtype_check_pipe); */
8976 /* %} */
8977
8978
8979 // ============================================================================
8980 // inlined locking and unlocking
8981
8982 instruct cmpFastLock(flagsRegP pcc, iRegP object, iRegP box, iRegP scratch2, iRegP scratch )
8983 %{
8984 match(Set pcc (FastLock object box));
8985
8986 effect(TEMP scratch, TEMP scratch2);
8987 ins_cost(DEFAULT_COST*3);
8988
8989 format %{ "FASTLOCK $object, $box; KILL $scratch, $scratch2" %}
8990 ins_encode %{
8991 __ fast_lock($object$$Register, $box$$Register, $scratch$$Register, $scratch2$$Register);
8992 %}
8993 ins_pipe(long_memory_op);
8994 %}
8995
8996 instruct cmpFastUnlock(flagsRegP pcc, iRegP object, iRegP box, iRegP scratch2, iRegP scratch ) %{
8997 match(Set pcc (FastUnlock object box));
8998 effect(TEMP scratch, TEMP scratch2);
8999 ins_cost(100);
9000
9001 format %{ "FASTUNLOCK $object, $box; KILL $scratch, $scratch2" %}
9002 ins_encode %{
9003 __ fast_unlock($object$$Register, $box$$Register, $scratch$$Register, $scratch2$$Register);
9004 %}
9005 ins_pipe(long_memory_op);
9006 %}
9007
9008 // Count and Base registers are fixed because the allocator cannot
9009 // kill unknown registers. The encodings are generic.
9010 instruct clear_array(iRegX cnt, iRegP base, iRegI temp, iRegX zero, Universe dummy, flagsReg cpsr) %{
9011 match(Set dummy (ClearArray cnt base));
9012 effect(TEMP temp, TEMP zero, KILL cpsr);
9013 ins_cost(300);
9014 format %{ "MOV $zero,0\n"
9015 " MOV $temp,$cnt\n"
9016 "loop: SUBS $temp,$temp,4\t! Count down a dword of bytes\n"
9017 " STR.ge $zero,[$base+$temp]\n"
9018 " B.gt loop\t\t! Clearing loop\n" %}
9019 ins_encode %{
9020 __ mov($zero$$Register, 0);
9021 __ mov($temp$$Register, $cnt$$Register);
9022 Label loop;
9023 __ bind(loop);
9024 __ subs($temp$$Register, $temp$$Register, 4);
9025 __ str($zero$$Register, Address($base$$Register, $temp$$Register), ge);
9026 __ b(loop, gt);
9027 %}
9028 ins_pipe(long_memory_op);
9029 %}
9030
9031 #ifdef XXX
9032 // FIXME: Why R0/R1/R2/R3?
9033 instruct string_compare(R0RegP str1, R1RegP str2, R2RegI cnt1, R3RegI cnt2, iRegI result,
9034 iRegI tmp1, iRegI tmp2, flagsReg ccr) %{
9035 predicate(!CompactStrings);
9036 match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
9037 effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL ccr, TEMP tmp1, TEMP tmp2);
9038 ins_cost(300);
9039 format %{ "String Compare $str1,$cnt1,$str2,$cnt2 -> $result // TEMP $tmp1, $tmp2" %}
9040 ins_encode( enc_String_Compare(str1, str2, cnt1, cnt2, result, tmp1, tmp2) );
9041
9042 ins_pipe(long_memory_op);
9043 %}
9044
9045 // FIXME: Why R0/R1/R2?
9046 instruct string_equals(R0RegP str1, R1RegP str2, R2RegI cnt, iRegI result, iRegI tmp1, iRegI tmp2,
9047 flagsReg ccr) %{
9048 predicate(!CompactStrings);
9049 match(Set result (StrEquals (Binary str1 str2) cnt));
9050 effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt, TEMP tmp1, TEMP tmp2, TEMP result, KILL ccr);
9051
9052 ins_cost(300);
9053 format %{ "String Equals $str1,$str2,$cnt -> $result // TEMP $tmp1, $tmp2" %}
9054 ins_encode( enc_String_Equals(str1, str2, cnt, result, tmp1, tmp2) );
9055 ins_pipe(long_memory_op);
9056 %}
9057
9058 // FIXME: Why R0/R1?
9059 instruct array_equals(R0RegP ary1, R1RegP ary2, iRegI tmp1, iRegI tmp2, iRegI tmp3, iRegI result,
9060 flagsReg ccr) %{
9061 predicate(((AryEqNode*)n)->encoding() == StrIntrinsicNode::UU);
9062 match(Set result (AryEq ary1 ary2));
9063 effect(USE_KILL ary1, USE_KILL ary2, TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP result, KILL ccr);
9064
9065 ins_cost(300);
9066 format %{ "Array Equals $ary1,$ary2 -> $result // TEMP $tmp1,$tmp2,$tmp3" %}
9067 ins_encode( enc_Array_Equals(ary1, ary2, tmp1, tmp2, tmp3, result));
9068 ins_pipe(long_memory_op);
9069 %}
9070 #endif
9071
9072 //---------- Zeros Count Instructions ------------------------------------------
9073
9074 instruct countLeadingZerosI(iRegI dst, iRegI src) %{
9075 match(Set dst (CountLeadingZerosI src));
9076 size(4);
9077 format %{ "CLZ_32 $dst,$src" %}
9078 ins_encode %{
9079 __ clz_32($dst$$Register, $src$$Register);
9080 %}
9081 ins_pipe(ialu_reg);
9082 %}
9083
9084 instruct countLeadingZerosL(iRegI dst, iRegL src, iRegI tmp, flagsReg ccr) %{
9085 match(Set dst (CountLeadingZerosL src));
9086 effect(TEMP tmp, TEMP dst, KILL ccr);
9087 size(16);
9088 format %{ "CLZ $dst,$src.hi\n\t"
9089 "TEQ $dst,32\n\t"
9090 "CLZ.eq $tmp,$src.lo\n\t"
9091 "ADD.eq $dst, $dst, $tmp\n\t" %}
9092 ins_encode %{
9093 __ clz($dst$$Register, $src$$Register->successor());
9094 __ teq($dst$$Register, 32);
9095 __ clz($tmp$$Register, $src$$Register, eq);
9096 __ add($dst$$Register, $dst$$Register, $tmp$$Register, eq);
9097 %}
9098 ins_pipe(ialu_reg);
9099 %}
9100
9101 instruct countTrailingZerosI(iRegI dst, iRegI src, iRegI tmp) %{
9102 match(Set dst (CountTrailingZerosI src));
9103 effect(TEMP tmp);
9104 size(8);
9105 format %{ "RBIT_32 $tmp, $src\n\t"
9106 "CLZ_32 $dst,$tmp" %}
9107 ins_encode %{
9108 __ rbit_32($tmp$$Register, $src$$Register);
9109 __ clz_32($dst$$Register, $tmp$$Register);
9110 %}
9111 ins_pipe(ialu_reg);
9112 %}
9113
9114 instruct countTrailingZerosL(iRegI dst, iRegL src, iRegI tmp, flagsReg ccr) %{
9115 match(Set dst (CountTrailingZerosL src));
9116 effect(TEMP tmp, TEMP dst, KILL ccr);
9117 size(24);
9118 format %{ "RBIT $tmp,$src.lo\n\t"
9119 "CLZ $dst,$tmp\n\t"
9120 "TEQ $dst,32\n\t"
9121 "RBIT $tmp,$src.hi\n\t"
9122 "CLZ.eq $tmp,$tmp\n\t"
9123 "ADD.eq $dst,$dst,$tmp\n\t" %}
9124 ins_encode %{
9125 __ rbit($tmp$$Register, $src$$Register);
9126 __ clz($dst$$Register, $tmp$$Register);
9127 __ teq($dst$$Register, 32);
9128 __ rbit($tmp$$Register, $src$$Register->successor());
9129 __ clz($tmp$$Register, $tmp$$Register, eq);
9130 __ add($dst$$Register, $dst$$Register, $tmp$$Register, eq);
9131 %}
9132 ins_pipe(ialu_reg);
9133 %}
9134
9135
9136 //---------- Population Count Instructions -------------------------------------
9137
9138 instruct popCountI(iRegI dst, iRegI src, regD_low tmp) %{
9139 predicate(UsePopCountInstruction);
9140 match(Set dst (PopCountI src));
9141 effect(TEMP tmp);
9142
9143 format %{ "FMSR $tmp,$src\n\t"
9144 "VCNT.8 $tmp,$tmp\n\t"
9145 "VPADDL.U8 $tmp,$tmp\n\t"
9146 "VPADDL.U16 $tmp,$tmp\n\t"
9147 "FMRS $dst,$tmp" %}
9148 size(20);
9149
9150 ins_encode %{
9151 __ fmsr($tmp$$FloatRegister, $src$$Register);
9152 __ vcnt($tmp$$FloatRegister, $tmp$$FloatRegister);
9153 __ vpaddl($tmp$$FloatRegister, $tmp$$FloatRegister, 8, 0);
9154 __ vpaddl($tmp$$FloatRegister, $tmp$$FloatRegister, 16, 0);
9155 __ fmrs($dst$$Register, $tmp$$FloatRegister);
9156 %}
9157 ins_pipe(ialu_reg); // FIXME
9158 %}
9159
9160 // Note: Long.bitCount(long) returns an int.
9161 instruct popCountL(iRegI dst, iRegL src, regD_low tmp) %{
9162 predicate(UsePopCountInstruction);
9163 match(Set dst (PopCountL src));
9164 effect(TEMP tmp);
9165
9166 format %{ "FMDRR $tmp,$src.lo,$src.hi\n\t"
9167 "VCNT.8 $tmp,$tmp\n\t"
9168 "VPADDL.U8 $tmp,$tmp\n\t"
9169 "VPADDL.U16 $tmp,$tmp\n\t"
9170 "VPADDL.U32 $tmp,$tmp\n\t"
9171 "FMRS $dst,$tmp" %}
9172
9173 size(32);
9174
9175 ins_encode %{
9176 __ fmdrr($tmp$$FloatRegister, $src$$Register, $src$$Register->successor());
9177 __ vcnt($tmp$$FloatRegister, $tmp$$FloatRegister);
9178 __ vpaddl($tmp$$FloatRegister, $tmp$$FloatRegister, 8, 0);
9179 __ vpaddl($tmp$$FloatRegister, $tmp$$FloatRegister, 16, 0);
9180 __ vpaddl($tmp$$FloatRegister, $tmp$$FloatRegister, 32, 0);
9181 __ fmrs($dst$$Register, $tmp$$FloatRegister);
9182 %}
9183 ins_pipe(ialu_reg);
9184 %}
9185
9186
9187 // ============================================================================
9188 //------------Bytes reverse--------------------------------------------------
9189
9190 instruct bytes_reverse_int(iRegI dst, iRegI src) %{
9191 match(Set dst (ReverseBytesI src));
9192
9193 size(4);
9194 format %{ "REV32 $dst,$src" %}
9195 ins_encode %{
9196 __ rev($dst$$Register, $src$$Register);
9197 %}
9198 ins_pipe( iload_mem ); // FIXME
9199 %}
9200
9201 instruct bytes_reverse_long(iRegL dst, iRegL src) %{
9202 match(Set dst (ReverseBytesL src));
9203 effect(TEMP dst);
9204 size(8);
9205 format %{ "REV $dst.lo,$src.lo\n\t"
9206 "REV $dst.hi,$src.hi" %}
9207 ins_encode %{
9208 __ rev($dst$$Register, $src$$Register->successor());
9209 __ rev($dst$$Register->successor(), $src$$Register);
9210 %}
9211 ins_pipe( iload_mem ); // FIXME
9212 %}
9213
9214 instruct bytes_reverse_unsigned_short(iRegI dst, iRegI src) %{
9215 match(Set dst (ReverseBytesUS src));
9216 size(8);
9217 format %{ "REV32 $dst,$src\n\t"
9218 "LSR $dst,$dst,#16" %}
9219 ins_encode %{
9220 __ rev($dst$$Register, $src$$Register);
9221 __ mov($dst$$Register, AsmOperand($dst$$Register, lsr, 16));
9222 %}
9223 ins_pipe( iload_mem ); // FIXME
9224 %}
9225
9226 instruct bytes_reverse_short(iRegI dst, iRegI src) %{
9227 match(Set dst (ReverseBytesS src));
9228 size(4);
9229 format %{ "REVSH $dst,$src" %}
9230 ins_encode %{
9231 __ revsh($dst$$Register, $src$$Register);
9232 %}
9233 ins_pipe( iload_mem ); // FIXME
9234 %}
9235
9236
9237 // ====================VECTOR INSTRUCTIONS=====================================
9238
9239 // Load Aligned Packed values into a Double Register
9240 instruct loadV8(vecD dst, memoryD mem) %{
9241 predicate(n->as_LoadVector()->memory_size() == 8);
9242 match(Set dst (LoadVector mem));
9243 ins_cost(MEMORY_REF_COST);
9244 size(4);
9245 format %{ "FLDD $mem,$dst\t! load vector (8 bytes)" %}
9246 ins_encode %{
9247 __ ldr_double($dst$$FloatRegister, $mem$$Address);
9248 %}
9249 ins_pipe(floadD_mem);
9250 %}
9251
9252 // Load Aligned Packed values into a Double Register Pair
9253 instruct loadV16(vecX dst, memoryvld mem) %{
9254 predicate(n->as_LoadVector()->memory_size() == 16);
9255 match(Set dst (LoadVector mem));
9256 ins_cost(MEMORY_REF_COST);
9257 size(4);
9258 format %{ "VLD1 $mem,$dst.Q\t! load vector (16 bytes)" %}
9259 ins_encode %{
9260 __ vld1($dst$$FloatRegister, $mem$$Address, MacroAssembler::VELEM_SIZE_16, 128);
9261 %}
9262 ins_pipe(floadD_mem); // FIXME
9263 %}
9264
9265 // Store Vector in Double register to memory
9266 instruct storeV8(memoryD mem, vecD src) %{
9267 predicate(n->as_StoreVector()->memory_size() == 8);
9268 match(Set mem (StoreVector mem src));
9269 ins_cost(MEMORY_REF_COST);
9270 size(4);
9271 format %{ "FSTD $src,$mem\t! store vector (8 bytes)" %}
9272 ins_encode %{
9273 __ str_double($src$$FloatRegister, $mem$$Address);
9274 %}
9275 ins_pipe(fstoreD_mem_reg);
9276 %}
9277
9278 // Store Vector in Double Register Pair to memory
9279 instruct storeV16(memoryvld mem, vecX src) %{
9280 predicate(n->as_StoreVector()->memory_size() == 16);
9281 match(Set mem (StoreVector mem src));
9282 ins_cost(MEMORY_REF_COST);
9283 size(4);
9284 format %{ "VST1 $src,$mem\t! store vector (16 bytes)" %}
9285 ins_encode %{
9286 __ vst1($src$$FloatRegister, $mem$$Address, MacroAssembler::VELEM_SIZE_16, 128);
9287 %}
9288 ins_pipe(fstoreD_mem_reg); // FIXME
9289 %}
9290
9291 // Replicate scalar to packed byte values in Double register
9292 instruct Repl8B_reg(vecD dst, iRegI src, iRegI tmp) %{
9293 predicate(n->as_Vector()->length() == 8 &&
9294 Matcher::vector_element_basic_type(n) == T_BYTE);
9295 match(Set dst (Replicate src));
9296 ins_cost(DEFAULT_COST*4);
9297 effect(TEMP tmp);
9298 size(16);
9299
9300 // FIXME: could use PKH instruction instead?
9301 format %{ "LSL $tmp, $src, 24 \n\t"
9302 "OR $tmp, $tmp, ($tmp >> 8) \n\t"
9303 "OR $tmp, $tmp, ($tmp >> 16) \n\t"
9304 "FMDRR $dst,$tmp,$tmp\t" %}
9305 ins_encode %{
9306 __ mov($tmp$$Register, AsmOperand($src$$Register, lsl, 24));
9307 __ orr($tmp$$Register, $tmp$$Register, AsmOperand($tmp$$Register, lsr, 8));
9308 __ orr($tmp$$Register, $tmp$$Register, AsmOperand($tmp$$Register, lsr, 16));
9309 __ fmdrr($dst$$FloatRegister, $tmp$$Register, $tmp$$Register);
9310 %}
9311 ins_pipe(ialu_reg); // FIXME
9312 %}
9313
9314 // Replicate scalar to packed byte values in Double register
9315 instruct Repl8B_reg_simd(vecD dst, iRegI src) %{
9316 predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd() &&
9317 Matcher::vector_element_basic_type(n) == T_BYTE);
9318 match(Set dst (Replicate src));
9319 size(4);
9320
9321 format %{ "VDUP.8 $dst,$src\t" %}
9322 ins_encode %{
9323 bool quad = false;
9324 __ vdupI($dst$$FloatRegister, $src$$Register,
9325 MacroAssembler::VELEM_SIZE_8, quad);
9326 %}
9327 ins_pipe(ialu_reg); // FIXME
9328 %}
9329
9330 // Replicate scalar to packed byte values in Double register pair
9331 instruct Repl16B_reg(vecX dst, iRegI src) %{
9332 predicate(n->as_Vector()->length_in_bytes() == 16 &&
9333 Matcher::vector_element_basic_type(n) == T_BYTE);
9334 match(Set dst (Replicate src));
9335 size(4);
9336
9337 format %{ "VDUP.8 $dst.Q,$src\t" %}
9338 ins_encode %{
9339 bool quad = true;
9340 __ vdupI($dst$$FloatRegister, $src$$Register,
9341 MacroAssembler::VELEM_SIZE_8, quad);
9342 %}
9343 ins_pipe(ialu_reg); // FIXME
9344 %}
9345
9346 // Replicate scalar constant to packed byte values in Double register
9347 instruct Repl8B_immI(vecD dst, immI src, iRegI tmp) %{
9348 predicate(n->as_Vector()->length() == 8 &&
9349 Matcher::vector_element_basic_type(n) == T_BYTE);
9350 match(Set dst (Replicate src));
9351 ins_cost(DEFAULT_COST*2);
9352 effect(TEMP tmp);
9353 size(12);
9354
9355 format %{ "MOV $tmp, Repl4($src))\n\t"
9356 "FMDRR $dst,$tmp,$tmp\t" %}
9357 ins_encode( LdReplImmI(src, dst, tmp, (4), (1)) );
9358 ins_pipe(loadConFD); // FIXME
9359 %}
9360
9361 // Replicate scalar constant to packed byte values in Double register
9362 // TODO: support negative constants with MVNI?
9363 instruct Repl8B_immU8(vecD dst, immU8 src) %{
9364 predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd() &&
9365 Matcher::vector_element_basic_type(n) == T_BYTE);
9366 match(Set dst (Replicate src));
9367 size(4);
9368
9369 format %{ "VMOV.U8 $dst,$src" %}
9370 ins_encode %{
9371 bool quad = false;
9372 __ vmovI($dst$$FloatRegister, $src$$constant,
9373 MacroAssembler::VELEM_SIZE_8, quad);
9374 %}
9375 ins_pipe(loadConFD); // FIXME
9376 %}
9377
9378 // Replicate scalar constant to packed byte values in Double register pair
9379 instruct Repl16B_immU8(vecX dst, immU8 src) %{
9380 predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd() &&
9381 Matcher::vector_element_basic_type(n) == T_BYTE);
9382 match(Set dst (Replicate src));
9383 size(4);
9384
9385 format %{ "VMOV.U8 $dst.Q,$src" %}
9386 ins_encode %{
9387 bool quad = true;
9388 __ vmovI($dst$$FloatRegister, $src$$constant,
9389 MacroAssembler::VELEM_SIZE_8, quad);
9390 %}
9391 ins_pipe(loadConFD); // FIXME
9392 %}
9393
9394 // Replicate scalar to packed short/char values into Double register
9395 instruct Repl4S_reg(vecD dst, iRegI src, iRegI tmp) %{
9396 predicate(n->as_Vector()->length() == 4 &&
9397 Matcher::vector_element_basic_type(n) == T_SHORT);
9398 match(Set dst (Replicate src));
9399 ins_cost(DEFAULT_COST*3);
9400 effect(TEMP tmp);
9401 size(12);
9402
9403 // FIXME: could use PKH instruction instead?
9404 format %{ "LSL $tmp, $src, 16 \n\t"
9405 "OR $tmp, $tmp, ($tmp >> 16) \n\t"
9406 "FMDRR $dst,$tmp,$tmp\t" %}
9407 ins_encode %{
9408 __ mov($tmp$$Register, AsmOperand($src$$Register, lsl, 16));
9409 __ orr($tmp$$Register, $tmp$$Register, AsmOperand($tmp$$Register, lsr, 16));
9410 __ fmdrr($dst$$FloatRegister, $tmp$$Register, $tmp$$Register);
9411 %}
9412 ins_pipe(ialu_reg); // FIXME
9413 %}
9414
9415 // Replicate scalar to packed byte values in Double register
9416 instruct Repl4S_reg_simd(vecD dst, iRegI src) %{
9417 predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd() &&
9418 Matcher::vector_element_basic_type(n) == T_SHORT);
9419 match(Set dst (Replicate src));
9420 size(4);
9421
9422 format %{ "VDUP.16 $dst,$src\t" %}
9423 ins_encode %{
9424 bool quad = false;
9425 __ vdupI($dst$$FloatRegister, $src$$Register,
9426 MacroAssembler::VELEM_SIZE_16, quad);
9427 %}
9428 ins_pipe(ialu_reg); // FIXME
9429 %}
9430
9431 // Replicate scalar to packed byte values in Double register pair
9432 instruct Repl8S_reg(vecX dst, iRegI src) %{
9433 predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd() &&
9434 Matcher::vector_element_basic_type(n) == T_SHORT);
9435 match(Set dst (Replicate src));
9436 size(4);
9437
9438 format %{ "VDUP.16 $dst.Q,$src\t" %}
9439 ins_encode %{
9440 bool quad = true;
9441 __ vdupI($dst$$FloatRegister, $src$$Register,
9442 MacroAssembler::VELEM_SIZE_16, quad);
9443 %}
9444 ins_pipe(ialu_reg); // FIXME
9445 %}
9446
9447
9448 // Replicate scalar constant to packed short/char values in Double register
9449 instruct Repl4S_immI(vecD dst, immI src, iRegP tmp) %{
9450 predicate(n->as_Vector()->length() == 4 &&
9451 Matcher::vector_element_basic_type(n) == T_SHORT);
9452 match(Set dst (Replicate src));
9453 effect(TEMP tmp);
9454 size(12);
9455 ins_cost(DEFAULT_COST*4); // FIXME
9456
9457 format %{ "MOV $tmp, Repl2($src))\n\t"
9458 "FMDRR $dst,$tmp,$tmp\t" %}
9459 ins_encode( LdReplImmI(src, dst, tmp, (2), (2)) );
9460 ins_pipe(loadConFD); // FIXME
9461 %}
9462
9463 // Replicate scalar constant to packed byte values in Double register
9464 instruct Repl4S_immU8(vecD dst, immU8 src) %{
9465 predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd() &&
9466 Matcher::vector_element_basic_type(n) == T_SHORT);
9467 match(Set dst (Replicate src));
9468 size(4);
9469
9470 format %{ "VMOV.U16 $dst,$src" %}
9471 ins_encode %{
9472 bool quad = false;
9473 __ vmovI($dst$$FloatRegister, $src$$constant,
9474 MacroAssembler::VELEM_SIZE_16, quad);
9475 %}
9476 ins_pipe(loadConFD); // FIXME
9477 %}
9478
9479 // Replicate scalar constant to packed byte values in Double register pair
9480 instruct Repl8S_immU8(vecX dst, immU8 src) %{
9481 predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd() &&
9482 Matcher::vector_element_basic_type(n) == T_SHORT);
9483 match(Set dst (Replicate src));
9484 size(4);
9485
9486 format %{ "VMOV.U16 $dst.Q,$src" %}
9487 ins_encode %{
9488 bool quad = true;
9489 __ vmovI($dst$$FloatRegister, $src$$constant,
9490 MacroAssembler::VELEM_SIZE_16, quad);
9491 %}
9492 ins_pipe(loadConFD); // FIXME
9493 %}
9494
9495 // Replicate scalar to packed int values in Double register
9496 instruct Repl2I_reg(vecD dst, iRegI src) %{
9497 predicate(n->as_Vector()->length() == 2 &&
9498 Matcher::vector_element_basic_type(n) == T_INT);
9499 match(Set dst (Replicate src));
9500 size(4);
9501
9502 format %{ "FMDRR $dst,$src,$src\t" %}
9503 ins_encode %{
9504 __ fmdrr($dst$$FloatRegister, $src$$Register, $src$$Register);
9505 %}
9506 ins_pipe(ialu_reg); // FIXME
9507 %}
9508
9509 // Replicate scalar to packed int values in Double register pair
9510 instruct Repl4I_reg(vecX dst, iRegI src) %{
9511 predicate(n->as_Vector()->length() == 4 &&
9512 Matcher::vector_element_basic_type(n) == T_INT);
9513 match(Set dst (Replicate src));
9514 ins_cost(DEFAULT_COST*2);
9515 size(8);
9516
9517 format %{ "FMDRR $dst.lo,$src,$src\n\t"
9518 "FMDRR $dst.hi,$src,$src" %}
9519
9520 ins_encode %{
9521 __ fmdrr($dst$$FloatRegister, $src$$Register, $src$$Register);
9522 __ fmdrr($dst$$FloatRegister->successor()->successor(),
9523 $src$$Register, $src$$Register);
9524 %}
9525 ins_pipe(ialu_reg); // FIXME
9526 %}
9527
9528 // Replicate scalar to packed int values in Double register
9529 instruct Repl2I_reg_simd(vecD dst, iRegI src) %{
9530 predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd() &&
9531 Matcher::vector_element_basic_type(n) == T_INT);
9532 match(Set dst (Replicate src));
9533 size(4);
9534
9535 format %{ "VDUP.32 $dst.D,$src\t" %}
9536 ins_encode %{
9537 bool quad = false;
9538 __ vdupI($dst$$FloatRegister, $src$$Register,
9539 MacroAssembler::VELEM_SIZE_32, quad);
9540 %}
9541 ins_pipe(ialu_reg); // FIXME
9542 %}
9543
9544 // Replicate scalar to packed int values in Double register pair
9545 instruct Repl4I_reg_simd(vecX dst, iRegI src) %{
9546 predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd() &&
9547 Matcher::vector_element_basic_type(n) == T_INT);
9548 match(Set dst (Replicate src));
9549 size(4);
9550
9551 format %{ "VDUP.32 $dst.Q,$src\t" %}
9552 ins_encode %{
9553 bool quad = true;
9554 __ vdupI($dst$$FloatRegister, $src$$Register,
9555 MacroAssembler::VELEM_SIZE_32, quad);
9556 %}
9557 ins_pipe(ialu_reg); // FIXME
9558 %}
9559
9560
9561 // Replicate scalar zero constant to packed int values in Double register
9562 instruct Repl2I_immI(vecD dst, immI src, iRegI tmp) %{
9563 predicate(n->as_Vector()->length() == 2 &&
9564 Matcher::vector_element_basic_type(n) == T_INT);
9565 match(Set dst (Replicate src));
9566 effect(TEMP tmp);
9567 size(12);
9568 ins_cost(DEFAULT_COST*4); // FIXME
9569
9570 format %{ "MOV $tmp, Repl1($src))\n\t"
9571 "FMDRR $dst,$tmp,$tmp\t" %}
9572 ins_encode( LdReplImmI(src, dst, tmp, (1), (4)) );
9573 ins_pipe(loadConFD); // FIXME
9574 %}
9575
9576 // Replicate scalar constant to packed byte values in Double register
9577 instruct Repl2I_immU8(vecD dst, immU8 src) %{
9578 predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd() &&
9579 Matcher::vector_element_basic_type(n) == T_INT);
9580 match(Set dst (Replicate src));
9581 size(4);
9582
9583 format %{ "VMOV.I32 $dst.D,$src" %}
9584 ins_encode %{
9585 bool quad = false;
9586 __ vmovI($dst$$FloatRegister, $src$$constant,
9587 MacroAssembler::VELEM_SIZE_32, quad);
9588 %}
9589 ins_pipe(loadConFD); // FIXME
9590 %}
9591
9592 // Replicate scalar constant to packed byte values in Double register pair
9593 instruct Repl4I_immU8(vecX dst, immU8 src) %{
9594 predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd() &&
9595 Matcher::vector_element_basic_type(n) == T_INT);
9596 match(Set dst (Replicate src));
9597 size(4);
9598
9599 format %{ "VMOV.I32 $dst.Q,$src" %}
9600 ins_encode %{
9601 bool quad = true;
9602 __ vmovI($dst$$FloatRegister, $src$$constant,
9603 MacroAssembler::VELEM_SIZE_32, quad);
9604 %}
9605 ins_pipe(loadConFD); // FIXME
9606 %}
9607
9608 // Replicate scalar to packed byte values in Double register pair
9609 instruct Repl2L_reg(vecX dst, iRegL src) %{
9610 predicate(n->as_Vector()->length() == 2 &&
9611 Matcher::vector_element_basic_type(n) == T_LONG);
9612 match(Set dst (Replicate src));
9613 size(8);
9614 ins_cost(DEFAULT_COST*2); // FIXME
9615
9616 format %{ "FMDRR $dst.D,$src.lo,$src.hi\t\n"
9617 "FMDRR $dst.D.next,$src.lo,$src.hi" %}
9618 ins_encode %{
9619 __ fmdrr($dst$$FloatRegister, $src$$Register, $src$$Register->successor());
9620 __ fmdrr($dst$$FloatRegister->successor()->successor(),
9621 $src$$Register, $src$$Register->successor());
9622 %}
9623 ins_pipe(ialu_reg); // FIXME
9624 %}
9625
9626
9627 // Replicate scalar to packed float values in Double register
9628 instruct Repl2F_regI(vecD dst, iRegI src) %{
9629 predicate(n->as_Vector()->length() == 2 &&
9630 Matcher::vector_element_basic_type(n) == T_FLOAT);
9631 match(Set dst (Replicate src));
9632 size(4);
9633
9634 format %{ "FMDRR $dst.D,$src,$src\t" %}
9635 ins_encode %{
9636 __ fmdrr($dst$$FloatRegister, $src$$Register, $src$$Register);
9637 %}
9638 ins_pipe(ialu_reg); // FIXME
9639 %}
9640
9641 // Replicate scalar to packed float values in Double register
9642 instruct Repl2F_reg_vfp(vecD dst, regF src) %{
9643 predicate(n->as_Vector()->length() == 2 &&
9644 Matcher::vector_element_basic_type(n) == T_FLOAT);
9645 match(Set dst (Replicate src));
9646 size(4*2);
9647 ins_cost(DEFAULT_COST*2); // FIXME
9648
9649 expand %{
9650 iRegI tmp;
9651 MoveF2I_reg_reg(tmp, src);
9652 Repl2F_regI(dst,tmp);
9653 %}
9654 %}
9655
9656 // Replicate scalar to packed float values in Double register
9657 instruct Repl2F_reg_simd(vecD dst, regF src) %{
9658 predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd() &&
9659 Matcher::vector_element_basic_type(n) == T_FLOAT);
9660 match(Set dst (Replicate src));
9661 size(4);
9662 ins_cost(DEFAULT_COST); // FIXME
9663
9664 format %{ "VDUP.32 $dst.D,$src.D\t" %}
9665 ins_encode %{
9666 bool quad = false;
9667 __ vdupF($dst$$FloatRegister, $src$$FloatRegister, quad);
9668 %}
9669 ins_pipe(ialu_reg); // FIXME
9670 %}
9671
9672 // Replicate scalar to packed float values in Double register pair
9673 instruct Repl4F_reg(vecX dst, regF src, iRegI tmp) %{
9674 predicate(n->as_Vector()->length() == 4 &&
9675 Matcher::vector_element_basic_type(n) == T_FLOAT);
9676 match(Set dst (Replicate src));
9677 effect(TEMP tmp);
9678 size(4*3);
9679 ins_cost(DEFAULT_COST*3); // FIXME
9680
9681 format %{ "FMRS $tmp,$src\n\t"
9682 "FMDRR $dst.D,$tmp,$tmp\n\t"
9683 "FMDRR $dst.D.next,$tmp,$tmp\t" %}
9684 ins_encode %{
9685 __ fmrs($tmp$$Register, $src$$FloatRegister);
9686 __ fmdrr($dst$$FloatRegister, $tmp$$Register, $tmp$$Register);
9687 __ fmdrr($dst$$FloatRegister->successor()->successor(),
9688 $tmp$$Register, $tmp$$Register);
9689 %}
9690 ins_pipe(ialu_reg); // FIXME
9691 %}
9692
9693 // Replicate scalar to packed float values in Double register pair
9694 instruct Repl4F_reg_simd(vecX dst, regF src) %{
9695 predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd() &&
9696 Matcher::vector_element_basic_type(n) == T_FLOAT);
9697 match(Set dst (Replicate src));
9698 size(4);
9699 ins_cost(DEFAULT_COST); // FIXME
9700
9701 format %{ "VDUP.32 $dst.Q,$src.D\t" %}
9702 ins_encode %{
9703 bool quad = true;
9704 __ vdupF($dst$$FloatRegister, $src$$FloatRegister, quad);
9705 %}
9706 ins_pipe(ialu_reg); // FIXME
9707 %}
9708
9709 // Replicate scalar zero constant to packed float values in Double register
9710 instruct Repl2F_immI(vecD dst, immF src, iRegI tmp) %{
9711 predicate(n->as_Vector()->length() == 2 &&
9712 Matcher::vector_element_basic_type(n) == T_FLOAT);
9713 match(Set dst (Replicate src));
9714 effect(TEMP tmp);
9715 size(12);
9716 ins_cost(DEFAULT_COST*4); // FIXME
9717
9718 format %{ "MOV $tmp, Repl1($src))\n\t"
9719 "FMDRR $dst,$tmp,$tmp\t" %}
9720 ins_encode( LdReplImmF(src, dst, tmp) );
9721 ins_pipe(loadConFD); // FIXME
9722 %}
9723
9724 // Replicate scalar to packed double float values in Double register pair
9725 instruct Repl2D_reg(vecX dst, regD src) %{
9726 predicate(n->as_Vector()->length() == 2 &&
9727 Matcher::vector_element_basic_type(n) == T_DOUBLE);
9728 match(Set dst (Replicate src));
9729 size(4*2);
9730 ins_cost(DEFAULT_COST*2); // FIXME
9731
9732 format %{ "FCPYD $dst.D.a,$src\n\t"
9733 "FCPYD $dst.D.b,$src\t" %}
9734 ins_encode %{
9735 FloatRegister dsta = $dst$$FloatRegister;
9736 FloatRegister src = $src$$FloatRegister;
9737 __ fcpyd(dsta, src);
9738 FloatRegister dstb = dsta->successor()->successor();
9739 __ fcpyd(dstb, src);
9740 %}
9741 ins_pipe(ialu_reg); // FIXME
9742 %}
9743
9744 // ====================VECTOR ARITHMETIC=======================================
9745
9746 // --------------------------------- ADD --------------------------------------
9747
9748 // Bytes vector add
9749 instruct vadd8B_reg(vecD dst, vecD src1, vecD src2) %{
9750 predicate(n->as_Vector()->length() == 8);
9751 match(Set dst (AddVB src1 src2));
9752 format %{ "VADD.I8 $dst,$src1,$src2\t! add packed8B" %}
9753 size(4);
9754 ins_encode %{
9755 bool quad = false;
9756 __ vaddI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
9757 MacroAssembler::VELEM_SIZE_8, quad);
9758 %}
9759 ins_pipe( ialu_reg_reg ); // FIXME
9760 %}
9761
9762 instruct vadd16B_reg(vecX dst, vecX src1, vecX src2) %{
9763 predicate(n->as_Vector()->length() == 16);
9764 match(Set dst (AddVB src1 src2));
9765 size(4);
9766 format %{ "VADD.I8 $dst.Q,$src1.Q,$src2.Q\t! add packed16B" %}
9767 ins_encode %{
9768 bool quad = true;
9769 __ vaddI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
9770 MacroAssembler::VELEM_SIZE_8, quad);
9771 %}
9772 ins_pipe( ialu_reg_reg ); // FIXME
9773 %}
9774
9775 // Shorts/Chars vector add
9776 instruct vadd4S_reg(vecD dst, vecD src1, vecD src2) %{
9777 predicate(n->as_Vector()->length() == 4);
9778 match(Set dst (AddVS src1 src2));
9779 size(4);
9780 format %{ "VADD.I16 $dst,$src1,$src2\t! add packed4S" %}
9781 ins_encode %{
9782 bool quad = false;
9783 __ vaddI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
9784 MacroAssembler::VELEM_SIZE_16, quad);
9785 %}
9786 ins_pipe( ialu_reg_reg ); // FIXME
9787 %}
9788
9789 instruct vadd8S_reg(vecX dst, vecX src1, vecX src2) %{
9790 predicate(n->as_Vector()->length() == 8);
9791 match(Set dst (AddVS src1 src2));
9792 size(4);
9793 format %{ "VADD.I16 $dst.Q,$src1.Q,$src2.Q\t! add packed8S" %}
9794 ins_encode %{
9795 bool quad = true;
9796 __ vaddI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
9797 MacroAssembler::VELEM_SIZE_16, quad);
9798 %}
9799 ins_pipe( ialu_reg_reg ); // FIXME
9800 %}
9801
9802 // Integers vector add
9803 instruct vadd2I_reg(vecD dst, vecD src1, vecD src2) %{
9804 predicate(n->as_Vector()->length() == 2);
9805 match(Set dst (AddVI src1 src2));
9806 size(4);
9807 format %{ "VADD.I32 $dst.D,$src1.D,$src2.D\t! add packed2I" %}
9808 ins_encode %{
9809 bool quad = false;
9810 __ vaddI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
9811 MacroAssembler::VELEM_SIZE_32, quad);
9812 %}
9813 ins_pipe( ialu_reg_reg ); // FIXME
9814 %}
9815
9816 instruct vadd4I_reg(vecX dst, vecX src1, vecX src2) %{
9817 predicate(n->as_Vector()->length() == 4);
9818 match(Set dst (AddVI src1 src2));
9819 size(4);
9820 format %{ "VADD.I32 $dst.Q,$src1.Q,$src2.Q\t! add packed4I" %}
9821 ins_encode %{
9822 bool quad = true;
9823 __ vaddI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
9824 MacroAssembler::VELEM_SIZE_32, quad);
9825 %}
9826 ins_pipe( ialu_reg_reg ); // FIXME
9827 %}
9828
9829 // Longs vector add
9830 instruct vadd2L_reg(vecX dst, vecX src1, vecX src2) %{
9831 predicate(n->as_Vector()->length() == 2);
9832 match(Set dst (AddVL src1 src2));
9833 size(4);
9834 format %{ "VADD.I64 $dst.Q,$src1.Q,$src2.Q\t! add packed2L" %}
9835 ins_encode %{
9836 bool quad = true;
9837 __ vaddI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
9838 MacroAssembler::VELEM_SIZE_64, quad);
9839 %}
9840 ins_pipe( ialu_reg_reg ); // FIXME
9841 %}
9842
9843 // Floats vector add
9844 instruct vadd2F_reg(vecD dst, vecD src1, vecD src2) %{
9845 predicate(n->as_Vector()->length() == 2 && VM_Version::simd_math_is_compliant());
9846 match(Set dst (AddVF src1 src2));
9847 size(4);
9848 format %{ "VADD.F32 $dst,$src1,$src2\t! add packed2F" %}
9849 ins_encode %{
9850 bool quad = false;
9851 __ vaddF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
9852 MacroAssembler::VFA_SIZE_F32, quad);
9853 %}
9854 ins_pipe( faddD_reg_reg ); // FIXME
9855 %}
9856
9857 instruct vadd2F_reg_vfp(vecD dst, vecD src1, vecD src2) %{
9858 predicate(n->as_Vector()->length() == 2 && !VM_Version::simd_math_is_compliant());
9859 match(Set dst (AddVF src1 src2));
9860 ins_cost(DEFAULT_COST*2); // FIXME
9861
9862 size(4*2);
9863 format %{ "FADDS $dst.a,$src1.a,$src2.a\n\t"
9864 "FADDS $dst.b,$src1.b,$src2.b" %}
9865 ins_encode %{
9866 __ add_float($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
9867 __ add_float($dst$$FloatRegister->successor(),
9868 $src1$$FloatRegister->successor(),
9869 $src2$$FloatRegister->successor());
9870 %}
9871
9872 ins_pipe(faddF_reg_reg); // FIXME
9873 %}
9874
9875 instruct vadd4F_reg_simd(vecX dst, vecX src1, vecX src2) %{
9876 predicate(n->as_Vector()->length() == 4 && VM_Version::simd_math_is_compliant());
9877 match(Set dst (AddVF src1 src2));
9878 size(4);
9879 format %{ "VADD.F32 $dst.Q,$src1.Q,$src2.Q\t! add packed4F" %}
9880 ins_encode %{
9881 bool quad = true;
9882 __ vaddF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
9883 MacroAssembler::VFA_SIZE_F32, quad);
9884 %}
9885 ins_pipe( faddD_reg_reg ); // FIXME
9886 %}
9887
9888 instruct vadd4F_reg_vfp(vecX dst, vecX src1, vecX src2) %{
9889 predicate(n->as_Vector()->length() == 4 && !VM_Version::simd_math_is_compliant());
9890 match(Set dst (AddVF src1 src2));
9891 size(4*4);
9892 ins_cost(DEFAULT_COST*4); // FIXME
9893
9894 format %{ "FADDS $dst.a,$src1.a,$src2.a\n\t"
9895 "FADDS $dst.b,$src1.b,$src2.b\n\t"
9896 "FADDS $dst.c,$src1.c,$src2.c\n\t"
9897 "FADDS $dst.d,$src1.d,$src2.d" %}
9898
9899 ins_encode %{
9900 FloatRegister dsta = $dst$$FloatRegister;
9901 FloatRegister src1a = $src1$$FloatRegister;
9902 FloatRegister src2a = $src2$$FloatRegister;
9903 __ add_float(dsta, src1a, src2a);
9904 FloatRegister dstb = dsta->successor();
9905 FloatRegister src1b = src1a->successor();
9906 FloatRegister src2b = src2a->successor();
9907 __ add_float(dstb, src1b, src2b);
9908 FloatRegister dstc = dstb->successor();
9909 FloatRegister src1c = src1b->successor();
9910 FloatRegister src2c = src2b->successor();
9911 __ add_float(dstc, src1c, src2c);
9912 FloatRegister dstd = dstc->successor();
9913 FloatRegister src1d = src1c->successor();
9914 FloatRegister src2d = src2c->successor();
9915 __ add_float(dstd, src1d, src2d);
9916 %}
9917
9918 ins_pipe(faddF_reg_reg); // FIXME
9919 %}
9920
9921 instruct vadd2D_reg_vfp(vecX dst, vecX src1, vecX src2) %{
9922 predicate(n->as_Vector()->length() == 2);
9923 match(Set dst (AddVD src1 src2));
9924 size(4*2);
9925 ins_cost(DEFAULT_COST*2); // FIXME
9926
9927 format %{ "FADDD $dst.a,$src1.a,$src2.a\n\t"
9928 "FADDD $dst.b,$src1.b,$src2.b" %}
9929
9930 ins_encode %{
9931 FloatRegister dsta = $dst$$FloatRegister;
9932 FloatRegister src1a = $src1$$FloatRegister;
9933 FloatRegister src2a = $src2$$FloatRegister;
9934 __ add_double(dsta, src1a, src2a);
9935 FloatRegister dstb = dsta->successor()->successor();
9936 FloatRegister src1b = src1a->successor()->successor();
9937 FloatRegister src2b = src2a->successor()->successor();
9938 __ add_double(dstb, src1b, src2b);
9939 %}
9940
9941 ins_pipe(faddF_reg_reg); // FIXME
9942 %}
9943
9944
9945 // Bytes vector sub
9946 instruct vsub8B_reg(vecD dst, vecD src1, vecD src2) %{
9947 predicate(n->as_Vector()->length() == 8);
9948 match(Set dst (SubVB src1 src2));
9949 size(4);
9950 format %{ "VSUB.I8 $dst,$src1,$src2\t! sub packed8B" %}
9951 ins_encode %{
9952 bool quad = false;
9953 __ vsubI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
9954 MacroAssembler::VELEM_SIZE_8, quad);
9955 %}
9956 ins_pipe( ialu_reg_reg ); // FIXME
9957 %}
9958
9959 instruct vsub16B_reg(vecX dst, vecX src1, vecX src2) %{
9960 predicate(n->as_Vector()->length() == 16);
9961 match(Set dst (SubVB src1 src2));
9962 size(4);
9963 format %{ "VSUB.I8 $dst.Q,$src1.Q,$src2.Q\t! sub packed16B" %}
9964 ins_encode %{
9965 bool quad = true;
9966 __ vsubI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
9967 MacroAssembler::VELEM_SIZE_8, quad);
9968 %}
9969 ins_pipe( ialu_reg_reg ); // FIXME
9970 %}
9971
9972 // Shorts/Chars vector sub
9973 instruct vsub4S_reg(vecD dst, vecD src1, vecD src2) %{
9974 predicate(n->as_Vector()->length() == 4);
9975 match(Set dst (SubVS src1 src2));
9976 size(4);
9977 format %{ "VSUB.I16 $dst,$src1,$src2\t! sub packed4S" %}
9978 ins_encode %{
9979 bool quad = false;
9980 __ vsubI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
9981 MacroAssembler::VELEM_SIZE_16, quad);
9982 %}
9983 ins_pipe( ialu_reg_reg ); // FIXME
9984 %}
9985
9986 instruct vsub16S_reg(vecX dst, vecX src1, vecX src2) %{
9987 predicate(n->as_Vector()->length() == 8);
9988 match(Set dst (SubVS src1 src2));
9989 size(4);
9990 format %{ "VSUB.I16 $dst.Q,$src1.Q,$src2.Q\t! sub packed8S" %}
9991 ins_encode %{
9992 bool quad = true;
9993 __ vsubI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
9994 MacroAssembler::VELEM_SIZE_16, quad);
9995 %}
9996 ins_pipe( ialu_reg_reg ); // FIXME
9997 %}
9998
9999 // Integers vector sub
10000 instruct vsub2I_reg(vecD dst, vecD src1, vecD src2) %{
10001 predicate(n->as_Vector()->length() == 2);
10002 match(Set dst (SubVI src1 src2));
10003 size(4);
10004 format %{ "VSUB.I32 $dst,$src1,$src2\t! sub packed2I" %}
10005 ins_encode %{
10006 bool quad = false;
10007 __ vsubI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
10008 MacroAssembler::VELEM_SIZE_32, quad);
10009 %}
10010 ins_pipe( ialu_reg_reg ); // FIXME
10011 %}
10012
10013 instruct vsub4I_reg(vecX dst, vecX src1, vecX src2) %{
10014 predicate(n->as_Vector()->length() == 4);
10015 match(Set dst (SubVI src1 src2));
10016 size(4);
10017 format %{ "VSUB.I32 $dst.Q,$src1.Q,$src2.Q\t! sub packed4I" %}
10018 ins_encode %{
10019 bool quad = true;
10020 __ vsubI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
10021 MacroAssembler::VELEM_SIZE_32, quad);
10022 %}
10023 ins_pipe( ialu_reg_reg ); // FIXME
10024 %}
10025
10026 // Longs vector sub
10027 instruct vsub2L_reg(vecX dst, vecX src1, vecX src2) %{
10028 predicate(n->as_Vector()->length() == 2);
10029 match(Set dst (SubVL src1 src2));
10030 size(4);
10031 format %{ "VSUB.I64 $dst.Q,$src1.Q,$src2.Q\t! sub packed2L" %}
10032 ins_encode %{
10033 bool quad = true;
10034 __ vsubI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
10035 MacroAssembler::VELEM_SIZE_64, quad);
10036 %}
10037 ins_pipe( ialu_reg_reg ); // FIXME
10038 %}
10039
10040 // Floats vector sub
10041 instruct vsub2F_reg(vecD dst, vecD src1, vecD src2) %{
10042 predicate(n->as_Vector()->length() == 2 && VM_Version::simd_math_is_compliant());
10043 match(Set dst (SubVF src1 src2));
10044 size(4);
10045 format %{ "VSUB.F32 $dst,$src1,$src2\t! sub packed2F" %}
10046 ins_encode %{
10047 bool quad = false;
10048 __ vsubF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
10049 MacroAssembler::VFA_SIZE_F32, quad);
10050 %}
10051 ins_pipe( faddF_reg_reg ); // FIXME
10052 %}
10053
10054 instruct vsub2F_reg_vfp(vecD dst, vecD src1, vecD src2) %{
10055 predicate(n->as_Vector()->length() == 2 && !VM_Version::simd_math_is_compliant());
10056 match(Set dst (SubVF src1 src2));
10057 size(4*2);
10058 ins_cost(DEFAULT_COST*2); // FIXME
10059
10060 format %{ "FSUBS $dst.a,$src1.a,$src2.a\n\t"
10061 "FSUBS $dst.b,$src1.b,$src2.b" %}
10062
10063 ins_encode %{
10064 FloatRegister dsta = $dst$$FloatRegister;
10065 FloatRegister src1a = $src1$$FloatRegister;
10066 FloatRegister src2a = $src2$$FloatRegister;
10067 __ sub_float(dsta, src1a, src2a);
10068 FloatRegister dstb = dsta->successor();
10069 FloatRegister src1b = src1a->successor();
10070 FloatRegister src2b = src2a->successor();
10071 __ sub_float(dstb, src1b, src2b);
10072 %}
10073
10074 ins_pipe(faddF_reg_reg); // FIXME
10075 %}
10076
10077
10078 instruct vsub4F_reg(vecX dst, vecX src1, vecX src2) %{
10079 predicate(n->as_Vector()->length() == 4 && VM_Version::simd_math_is_compliant());
10080 match(Set dst (SubVF src1 src2));
10081 size(4);
10082 format %{ "VSUB.F32 $dst.Q,$src1.Q,$src2.Q\t! sub packed4F" %}
10083 ins_encode %{
10084 bool quad = true;
10085 __ vsubF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
10086 MacroAssembler::VFA_SIZE_F32, quad);
10087 %}
10088 ins_pipe( faddF_reg_reg ); // FIXME
10089 %}
10090
10091 instruct vsub4F_reg_vfp(vecX dst, vecX src1, vecX src2) %{
10092 predicate(n->as_Vector()->length() == 4 && !VM_Version::simd_math_is_compliant());
10093 match(Set dst (SubVF src1 src2));
10094 size(4*4);
10095 ins_cost(DEFAULT_COST*4); // FIXME
10096
10097 format %{ "FSUBS $dst.a,$src1.a,$src2.a\n\t"
10098 "FSUBS $dst.b,$src1.b,$src2.b\n\t"
10099 "FSUBS $dst.c,$src1.c,$src2.c\n\t"
10100 "FSUBS $dst.d,$src1.d,$src2.d" %}
10101
10102 ins_encode %{
10103 FloatRegister dsta = $dst$$FloatRegister;
10104 FloatRegister src1a = $src1$$FloatRegister;
10105 FloatRegister src2a = $src2$$FloatRegister;
10106 __ sub_float(dsta, src1a, src2a);
10107 FloatRegister dstb = dsta->successor();
10108 FloatRegister src1b = src1a->successor();
10109 FloatRegister src2b = src2a->successor();
10110 __ sub_float(dstb, src1b, src2b);
10111 FloatRegister dstc = dstb->successor();
10112 FloatRegister src1c = src1b->successor();
10113 FloatRegister src2c = src2b->successor();
10114 __ sub_float(dstc, src1c, src2c);
10115 FloatRegister dstd = dstc->successor();
10116 FloatRegister src1d = src1c->successor();
10117 FloatRegister src2d = src2c->successor();
10118 __ sub_float(dstd, src1d, src2d);
10119 %}
10120
10121 ins_pipe(faddF_reg_reg); // FIXME
10122 %}
10123
10124 instruct vsub2D_reg_vfp(vecX dst, vecX src1, vecX src2) %{
10125 predicate(n->as_Vector()->length() == 2);
10126 match(Set dst (SubVD src1 src2));
10127 size(4*2);
10128 ins_cost(DEFAULT_COST*2); // FIXME
10129
10130 format %{ "FSUBD $dst.a,$src1.a,$src2.a\n\t"
10131 "FSUBD $dst.b,$src1.b,$src2.b" %}
10132
10133 ins_encode %{
10134 FloatRegister dsta = $dst$$FloatRegister;
10135 FloatRegister src1a = $src1$$FloatRegister;
10136 FloatRegister src2a = $src2$$FloatRegister;
10137 __ sub_double(dsta, src1a, src2a);
10138 FloatRegister dstb = dsta->successor()->successor();
10139 FloatRegister src1b = src1a->successor()->successor();
10140 FloatRegister src2b = src2a->successor()->successor();
10141 __ sub_double(dstb, src1b, src2b);
10142 %}
10143
10144 ins_pipe(faddF_reg_reg); // FIXME
10145 %}
10146
10147 // Shorts/Chars vector mul
10148 instruct vmul4S_reg(vecD dst, vecD src1, vecD src2) %{
10149 predicate(n->as_Vector()->length() == 4);
10150 match(Set dst (MulVS src1 src2));
10151 size(4);
10152 format %{ "VMUL.I16 $dst,$src1,$src2\t! mul packed4S" %}
10153 ins_encode %{
10154 __ vmulI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
10155 MacroAssembler::VELEM_SIZE_16, 0);
10156 %}
10157 ins_pipe( ialu_reg_reg ); // FIXME
10158 %}
10159
10160 instruct vmul8S_reg(vecX dst, vecX src1, vecX src2) %{
10161 predicate(n->as_Vector()->length() == 8);
10162 match(Set dst (MulVS src1 src2));
10163 size(4);
10164 format %{ "VMUL.I16 $dst.Q,$src1.Q,$src2.Q\t! mul packed8S" %}
10165 ins_encode %{
10166 __ vmulI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
10167 MacroAssembler::VELEM_SIZE_16, 1);
10168 %}
10169 ins_pipe( ialu_reg_reg ); // FIXME
10170 %}
10171
10172 // Integers vector mul
10173 instruct vmul2I_reg(vecD dst, vecD src1, vecD src2) %{
10174 predicate(n->as_Vector()->length() == 2);
10175 match(Set dst (MulVI src1 src2));
10176 size(4);
10177 format %{ "VMUL.I32 $dst,$src1,$src2\t! mul packed2I" %}
10178 ins_encode %{
10179 __ vmulI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
10180 MacroAssembler::VELEM_SIZE_32, 0);
10181 %}
10182 ins_pipe( ialu_reg_reg ); // FIXME
10183 %}
10184
10185 instruct vmul4I_reg(vecX dst, vecX src1, vecX src2) %{
10186 predicate(n->as_Vector()->length() == 4);
10187 match(Set dst (MulVI src1 src2));
10188 size(4);
10189 format %{ "VMUL.I32 $dst.Q,$src1.Q,$src2.Q\t! mul packed4I" %}
10190 ins_encode %{
10191 __ vmulI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
10192 MacroAssembler::VELEM_SIZE_32, 1);
10193 %}
10194 ins_pipe( ialu_reg_reg ); // FIXME
10195 %}
10196
10197 // Floats vector mul
10198 instruct vmul2F_reg(vecD dst, vecD src1, vecD src2) %{
10199 predicate(n->as_Vector()->length() == 2 && VM_Version::simd_math_is_compliant());
10200 match(Set dst (MulVF src1 src2));
10201 size(4);
10202 format %{ "VMUL.F32 $dst,$src1,$src2\t! mul packed2F" %}
10203 ins_encode %{
10204 __ vmulF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
10205 MacroAssembler::VFA_SIZE_F32, 0);
10206 %}
10207 ins_pipe( fmulF_reg_reg ); // FIXME
10208 %}
10209
10210 instruct vmul2F_reg_vfp(vecD dst, vecD src1, vecD src2) %{
10211 predicate(n->as_Vector()->length() == 2 && !VM_Version::simd_math_is_compliant());
10212 match(Set dst (MulVF src1 src2));
10213 size(4*2);
10214 ins_cost(DEFAULT_COST*2); // FIXME
10215
10216 format %{ "FMULS $dst.a,$src1.a,$src2.a\n\t"
10217 "FMULS $dst.b,$src1.b,$src2.b" %}
10218 ins_encode %{
10219 __ mul_float($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
10220 __ mul_float($dst$$FloatRegister->successor(),
10221 $src1$$FloatRegister->successor(),
10222 $src2$$FloatRegister->successor());
10223 %}
10224
10225 ins_pipe(fmulF_reg_reg); // FIXME
10226 %}
10227
10228 instruct vmul4F_reg(vecX dst, vecX src1, vecX src2) %{
10229 predicate(n->as_Vector()->length() == 4 && VM_Version::simd_math_is_compliant());
10230 match(Set dst (MulVF src1 src2));
10231 size(4);
10232 format %{ "VMUL.F32 $dst.Q,$src1.Q,$src2.Q\t! mul packed4F" %}
10233 ins_encode %{
10234 __ vmulF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
10235 MacroAssembler::VFA_SIZE_F32, 1);
10236 %}
10237 ins_pipe( fmulF_reg_reg ); // FIXME
10238 %}
10239
10240 instruct vmul4F_reg_vfp(vecX dst, vecX src1, vecX src2) %{
10241 predicate(n->as_Vector()->length() == 4 && !VM_Version::simd_math_is_compliant());
10242 match(Set dst (MulVF src1 src2));
10243 size(4*4);
10244 ins_cost(DEFAULT_COST*4); // FIXME
10245
10246 format %{ "FMULS $dst.a,$src1.a,$src2.a\n\t"
10247 "FMULS $dst.b,$src1.b,$src2.b\n\t"
10248 "FMULS $dst.c,$src1.c,$src2.c\n\t"
10249 "FMULS $dst.d,$src1.d,$src2.d" %}
10250
10251 ins_encode %{
10252 FloatRegister dsta = $dst$$FloatRegister;
10253 FloatRegister src1a = $src1$$FloatRegister;
10254 FloatRegister src2a = $src2$$FloatRegister;
10255 __ mul_float(dsta, src1a, src2a);
10256 FloatRegister dstb = dsta->successor();
10257 FloatRegister src1b = src1a->successor();
10258 FloatRegister src2b = src2a->successor();
10259 __ mul_float(dstb, src1b, src2b);
10260 FloatRegister dstc = dstb->successor();
10261 FloatRegister src1c = src1b->successor();
10262 FloatRegister src2c = src2b->successor();
10263 __ mul_float(dstc, src1c, src2c);
10264 FloatRegister dstd = dstc->successor();
10265 FloatRegister src1d = src1c->successor();
10266 FloatRegister src2d = src2c->successor();
10267 __ mul_float(dstd, src1d, src2d);
10268 %}
10269
10270 ins_pipe(fmulF_reg_reg); // FIXME
10271 %}
10272
10273 instruct vmul2D_reg_vfp(vecX dst, vecX src1, vecX src2) %{
10274 predicate(n->as_Vector()->length() == 2);
10275 match(Set dst (MulVD src1 src2));
10276 size(4*2);
10277 ins_cost(DEFAULT_COST*2); // FIXME
10278
10279 format %{ "FMULD $dst.D.a,$src1.D.a,$src2.D.a\n\t"
10280 "FMULD $dst.D.b,$src1.D.b,$src2.D.b" %}
10281 ins_encode %{
10282 FloatRegister dsta = $dst$$FloatRegister;
10283 FloatRegister src1a = $src1$$FloatRegister;
10284 FloatRegister src2a = $src2$$FloatRegister;
10285 __ mul_double(dsta, src1a, src2a);
10286 FloatRegister dstb = dsta->successor()->successor();
10287 FloatRegister src1b = src1a->successor()->successor();
10288 FloatRegister src2b = src2a->successor()->successor();
10289 __ mul_double(dstb, src1b, src2b);
10290 %}
10291
10292 ins_pipe(fmulD_reg_reg); // FIXME
10293 %}
10294
10295
10296 // Floats vector div
10297 instruct vdiv2F_reg_vfp(vecD dst, vecD src1, vecD src2) %{
10298 predicate(n->as_Vector()->length() == 2);
10299 match(Set dst (DivVF src1 src2));
10300 size(4*2);
10301 ins_cost(DEFAULT_COST*2); // FIXME
10302
10303 format %{ "FDIVS $dst.a,$src1.a,$src2.a\n\t"
10304 "FDIVS $dst.b,$src1.b,$src2.b" %}
10305 ins_encode %{
10306 __ div_float($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
10307 __ div_float($dst$$FloatRegister->successor(),
10308 $src1$$FloatRegister->successor(),
10309 $src2$$FloatRegister->successor());
10310 %}
10311
10312 ins_pipe(fdivF_reg_reg); // FIXME
10313 %}
10314
10315 instruct vdiv4F_reg_vfp(vecX dst, vecX src1, vecX src2) %{
10316 predicate(n->as_Vector()->length() == 4);
10317 match(Set dst (DivVF src1 src2));
10318 size(4*4);
10319 ins_cost(DEFAULT_COST*4); // FIXME
10320
10321 format %{ "FDIVS $dst.a,$src1.a,$src2.a\n\t"
10322 "FDIVS $dst.b,$src1.b,$src2.b\n\t"
10323 "FDIVS $dst.c,$src1.c,$src2.c\n\t"
10324 "FDIVS $dst.d,$src1.d,$src2.d" %}
10325
10326 ins_encode %{
10327 FloatRegister dsta = $dst$$FloatRegister;
10328 FloatRegister src1a = $src1$$FloatRegister;
10329 FloatRegister src2a = $src2$$FloatRegister;
10330 __ div_float(dsta, src1a, src2a);
10331 FloatRegister dstb = dsta->successor();
10332 FloatRegister src1b = src1a->successor();
10333 FloatRegister src2b = src2a->successor();
10334 __ div_float(dstb, src1b, src2b);
10335 FloatRegister dstc = dstb->successor();
10336 FloatRegister src1c = src1b->successor();
10337 FloatRegister src2c = src2b->successor();
10338 __ div_float(dstc, src1c, src2c);
10339 FloatRegister dstd = dstc->successor();
10340 FloatRegister src1d = src1c->successor();
10341 FloatRegister src2d = src2c->successor();
10342 __ div_float(dstd, src1d, src2d);
10343 %}
10344
10345 ins_pipe(fdivF_reg_reg); // FIXME
10346 %}
10347
10348 instruct vdiv2D_reg_vfp(vecX dst, vecX src1, vecX src2) %{
10349 predicate(n->as_Vector()->length() == 2);
10350 match(Set dst (DivVD src1 src2));
10351 size(4*2);
10352 ins_cost(DEFAULT_COST*2); // FIXME
10353
10354 format %{ "FDIVD $dst.D.a,$src1.D.a,$src2.D.a\n\t"
10355 "FDIVD $dst.D.b,$src1.D.b,$src2.D.b" %}
10356 ins_encode %{
10357 FloatRegister dsta = $dst$$FloatRegister;
10358 FloatRegister src1a = $src1$$FloatRegister;
10359 FloatRegister src2a = $src2$$FloatRegister;
10360 __ div_double(dsta, src1a, src2a);
10361 FloatRegister dstb = dsta->successor()->successor();
10362 FloatRegister src1b = src1a->successor()->successor();
10363 FloatRegister src2b = src2a->successor()->successor();
10364 __ div_double(dstb, src1b, src2b);
10365 %}
10366
10367 ins_pipe(fdivD_reg_reg); // FIXME
10368 %}
10369
10370 // --------------------------------- NEG --------------------------------------
10371
10372 instruct vneg8B_reg(vecD dst, vecD src) %{
10373 predicate(n->as_Vector()->length_in_bytes() == 8);
10374 effect(DEF dst, USE src);
10375 size(4);
10376 ins_cost(DEFAULT_COST); // FIXME
10377 format %{ "VNEG.S8 $dst.D,$src.D\t! neg packed8B" %}
10378 ins_encode %{
10379 bool quad = false;
10380 __ vnegI($dst$$FloatRegister, $src$$FloatRegister,
10381 MacroAssembler::VELEM_SIZE_8, quad);
10382 %}
10383 ins_pipe( ialu_reg_reg ); // FIXME
10384 %}
10385
10386 instruct vneg16B_reg(vecX dst, vecX src) %{
10387 predicate(n->as_Vector()->length_in_bytes() == 16);
10388 effect(DEF dst, USE src);
10389 size(4);
10390 ins_cost(DEFAULT_COST); // FIXME
10391 format %{ "VNEG.S8 $dst.Q,$src.Q\t! neg0 packed16B" %}
10392 ins_encode %{
10393 bool _float = false;
10394 bool quad = true;
10395 __ vnegI($dst$$FloatRegister, $src$$FloatRegister,
10396 MacroAssembler::VELEM_SIZE_8, quad);
10397 %}
10398 ins_pipe( ialu_reg_reg ); // FIXME
10399 %}
10400
10401 // ------------------------------ ShiftCount ----------------------------------
10402
10403 instruct vslcntD(vecD dst, iRegI cnt) %{
10404 predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd());
10405 match(Set dst (LShiftCntV cnt));
10406 size(4);
10407 ins_cost(DEFAULT_COST); // FIXME
10408 expand %{
10409 Repl8B_reg_simd(dst, cnt);
10410 %}
10411 %}
10412
10413 instruct vslcntX(vecX dst, iRegI cnt) %{
10414 predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd());
10415 match(Set dst (LShiftCntV cnt));
10416 size(4);
10417 ins_cost(DEFAULT_COST); // FIXME
10418 expand %{
10419 Repl16B_reg(dst, cnt);
10420 %}
10421 %}
10422
10423 // Low bits of vector "shift" elements are used, so it
10424 // doesn't matter if we treat it as ints or bytes here.
10425 instruct vsrcntD(vecD dst, iRegI cnt) %{
10426 predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd());
10427 match(Set dst (RShiftCntV cnt));
10428 size(4*2);
10429 ins_cost(DEFAULT_COST*2); // FIXME
10430
10431 format %{ "VDUP.8 $dst.D,$cnt\n\t"
10432 "VNEG.S8 $dst.D,$dst.D\t! neg packed8B" %}
10433 ins_encode %{
10434 bool quad = false;
10435 __ vdupI($dst$$FloatRegister, $cnt$$Register,
10436 MacroAssembler::VELEM_SIZE_8, quad);
10437 __ vnegI($dst$$FloatRegister, $dst$$FloatRegister,
10438 MacroAssembler::VELEM_SIZE_8, quad);
10439 %}
10440 ins_pipe( ialu_reg_reg ); // FIXME
10441 %}
10442
10443 instruct vsrcntX(vecX dst, iRegI cnt) %{
10444 predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd());
10445 match(Set dst (RShiftCntV cnt));
10446 size(4*2);
10447 ins_cost(DEFAULT_COST*2); // FIXME
10448 format %{ "VDUP.8 $dst.Q,$cnt\n\t"
10449 "VNEG.S8 $dst.Q,$dst.Q\t! neg packed16B" %}
10450 ins_encode %{
10451 bool quad = true;
10452 __ vdupI($dst$$FloatRegister, $cnt$$Register,
10453 MacroAssembler::VELEM_SIZE_8, quad);
10454 __ vnegI($dst$$FloatRegister, $dst$$FloatRegister,
10455 MacroAssembler::VELEM_SIZE_8, quad);
10456 %}
10457 ins_pipe( ialu_reg_reg ); // FIXME
10458 %}
10459
10460 // ------------------------------ LogicalShift --------------------------------
10461
10462 // Byte vector logical left/right shift based on sign
10463 instruct vsh8B_reg(vecD dst, vecD src, vecD shift) %{
10464 predicate(n->as_Vector()->length() == 8);
10465 effect(DEF dst, USE src, USE shift);
10466 size(4);
10467 ins_cost(DEFAULT_COST); // FIXME
10468 format %{
10469 "VSHL.U8 $dst.D,$src.D,$shift.D\t! logical left/right shift packed8B"
10470 %}
10471 ins_encode %{
10472 bool quad = false;
10473 __ vshlUI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister,
10474 MacroAssembler::VELEM_SIZE_8, quad);
10475 %}
10476 ins_pipe( ialu_reg_reg ); // FIXME
10477 %}
10478
10479 instruct vsh16B_reg(vecX dst, vecX src, vecX shift) %{
10480 predicate(n->as_Vector()->length() == 16);
10481 effect(DEF dst, USE src, USE shift);
10482 size(4);
10483 ins_cost(DEFAULT_COST); // FIXME
10484 format %{
10485 "VSHL.U8 $dst.Q,$src.Q,$shift.Q\t! logical left/right shift packed16B"
10486 %}
10487 ins_encode %{
10488 bool quad = true;
10489 __ vshlUI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister,
10490 MacroAssembler::VELEM_SIZE_8, quad);
10491 %}
10492 ins_pipe( ialu_reg_reg ); // FIXME
10493 %}
10494
10495 // Shorts/Char vector logical left/right shift based on sign
10496 instruct vsh4S_reg(vecD dst, vecD src, vecD shift) %{
10497 predicate(n->as_Vector()->length() == 4);
10498 effect(DEF dst, USE src, USE shift);
10499 size(4);
10500 ins_cost(DEFAULT_COST); // FIXME
10501 format %{
10502 "VSHL.U16 $dst.D,$src.D,$shift.D\t! logical left/right shift packed4S"
10503 %}
10504 ins_encode %{
10505 bool quad = false;
10506 __ vshlUI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister,
10507 MacroAssembler::VELEM_SIZE_16, quad);
10508 %}
10509 ins_pipe( ialu_reg_reg ); // FIXME
10510 %}
10511
10512 instruct vsh8S_reg(vecX dst, vecX src, vecX shift) %{
10513 predicate(n->as_Vector()->length() == 8);
10514 effect(DEF dst, USE src, USE shift);
10515 size(4);
10516 ins_cost(DEFAULT_COST); // FIXME
10517 format %{
10518 "VSHL.U16 $dst.Q,$src.Q,$shift.Q\t! logical left/right shift packed8S"
10519 %}
10520 ins_encode %{
10521 bool quad = true;
10522 __ vshlUI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister,
10523 MacroAssembler::VELEM_SIZE_16, quad);
10524 %}
10525 ins_pipe( ialu_reg_reg ); // FIXME
10526 %}
10527
10528 // Integers vector logical left/right shift based on sign
10529 instruct vsh2I_reg(vecD dst, vecD src, vecD shift) %{
10530 predicate(n->as_Vector()->length() == 2);
10531 effect(DEF dst, USE src, USE shift);
10532 size(4);
10533 ins_cost(DEFAULT_COST); // FIXME
10534 format %{
10535 "VSHL.U32 $dst.D,$src.D,$shift.D\t! logical left/right shift packed2I"
10536 %}
10537 ins_encode %{
10538 bool quad = false;
10539 __ vshlUI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister,
10540 MacroAssembler::VELEM_SIZE_32, quad);
10541 %}
10542 ins_pipe( ialu_reg_reg ); // FIXME
10543 %}
10544
10545 instruct vsh4I_reg(vecX dst, vecX src, vecX shift) %{
10546 predicate(n->as_Vector()->length() == 4);
10547 effect(DEF dst, USE src, USE shift);
10548 size(4);
10549 ins_cost(DEFAULT_COST); // FIXME
10550 format %{
10551 "VSHL.U32 $dst.Q,$src.Q,$shift.Q\t! logical left/right shift packed4I"
10552 %}
10553 ins_encode %{
10554 bool quad = true;
10555 __ vshlUI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister,
10556 MacroAssembler::VELEM_SIZE_32, quad);
10557 %}
10558 ins_pipe( ialu_reg_reg ); // FIXME
10559 %}
10560
10561 // Longs vector logical left/right shift based on sign
10562 instruct vsh2L_reg(vecX dst, vecX src, vecX shift) %{
10563 predicate(n->as_Vector()->length() == 2);
10564 effect(DEF dst, USE src, USE shift);
10565 size(4);
10566 ins_cost(DEFAULT_COST); // FIXME
10567 format %{
10568 "VSHL.U64 $dst.Q,$src.Q,$shift.Q\t! logical left/right shift packed2L"
10569 %}
10570 ins_encode %{
10571 bool quad = true;
10572 __ vshlUI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister,
10573 MacroAssembler::VELEM_SIZE_64, quad);
10574 %}
10575 ins_pipe( ialu_reg_reg ); // FIXME
10576 %}
10577
10578 // ------------------------------ LogicalLeftShift ----------------------------
10579
10580 // Byte vector logical left shift
10581 instruct vsl8B_reg(vecD dst, vecD src, vecD shift) %{
10582 predicate(n->as_Vector()->length() == 8);
10583 match(Set dst (LShiftVB src shift));
10584 size(4*1);
10585 ins_cost(DEFAULT_COST*1); // FIXME
10586 expand %{
10587 vsh8B_reg(dst, src, shift);
10588 %}
10589 %}
10590
10591 instruct vsl16B_reg(vecX dst, vecX src, vecX shift) %{
10592 predicate(n->as_Vector()->length() == 16);
10593 match(Set dst (LShiftVB src shift));
10594 size(4*1);
10595 ins_cost(DEFAULT_COST*1); // FIXME
10596 expand %{
10597 vsh16B_reg(dst, src, shift);
10598 %}
10599 %}
10600
10601 instruct vsl8B_immI(vecD dst, vecD src, immI shift) %{
10602 predicate(n->as_Vector()->length() == 8 && assert_not_var_shift(n));
10603 match(Set dst (LShiftVB src (LShiftCntV shift)));
10604 size(4);
10605 ins_cost(DEFAULT_COST); // FIXME
10606 format %{
10607 "VSHL.I8 $dst.D,$src.D,$shift\t! logical left shift packed8B"
10608 %}
10609 ins_encode %{
10610 bool quad = false;
10611 __ vshli($dst$$FloatRegister, $src$$FloatRegister, 8, $shift$$constant,
10612 quad);
10613 %}
10614 ins_pipe( ialu_reg_reg ); // FIXME
10615 %}
10616
10617 instruct vsl16B_immI(vecX dst, vecX src, immI shift) %{
10618 predicate(n->as_Vector()->length() == 16 && assert_not_var_shift(n));
10619 match(Set dst (LShiftVB src (LShiftCntV shift)));
10620 size(4);
10621 ins_cost(DEFAULT_COST); // FIXME
10622 format %{
10623 "VSHL.I8 $dst.Q,$src.Q,$shift\t! logical left shift packed16B"
10624 %}
10625 ins_encode %{
10626 bool quad = true;
10627 __ vshli($dst$$FloatRegister, $src$$FloatRegister, 8, $shift$$constant,
10628 quad);
10629 %}
10630 ins_pipe( ialu_reg_reg ); // FIXME
10631 %}
10632
10633 // Shorts/Chars vector logical left shift
10634 instruct vsl4S_reg(vecD dst, vecD src, vecD shift) %{
10635 predicate(n->as_Vector()->length() == 4);
10636 match(Set dst (LShiftVS src shift));
10637 size(4*1);
10638 ins_cost(DEFAULT_COST*1); // FIXME
10639 expand %{
10640 vsh4S_reg(dst, src, shift);
10641 %}
10642 %}
10643
10644 instruct vsl8S_reg(vecX dst, vecX src, vecX shift) %{
10645 predicate(n->as_Vector()->length() == 8);
10646 match(Set dst (LShiftVS src shift));
10647 size(4*1);
10648 ins_cost(DEFAULT_COST*1); // FIXME
10649 expand %{
10650 vsh8S_reg(dst, src, shift);
10651 %}
10652 %}
10653
10654 instruct vsl4S_immI(vecD dst, vecD src, immI shift) %{
10655 predicate(n->as_Vector()->length() == 4 && assert_not_var_shift(n));
10656 match(Set dst (LShiftVS src (LShiftCntV shift)));
10657 size(4);
10658 ins_cost(DEFAULT_COST); // FIXME
10659 format %{
10660 "VSHL.I16 $dst.D,$src.D,$shift\t! logical left shift packed4S"
10661 %}
10662 ins_encode %{
10663 bool quad = false;
10664 __ vshli($dst$$FloatRegister, $src$$FloatRegister, 16, $shift$$constant,
10665 quad);
10666 %}
10667 ins_pipe( ialu_reg_reg ); // FIXME
10668 %}
10669
10670 instruct vsl8S_immI(vecX dst, vecX src, immI shift) %{
10671 predicate(n->as_Vector()->length() == 8 && assert_not_var_shift(n));
10672 match(Set dst (LShiftVS src shift));
10673 size(4);
10674 ins_cost(DEFAULT_COST); // FIXME
10675 format %{
10676 "VSHL.I16 $dst.Q,$src.Q,$shift\t! logical left shift packed8S"
10677 %}
10678 ins_encode %{
10679 bool quad = true;
10680 __ vshli($dst$$FloatRegister, $src$$FloatRegister, 16, $shift$$constant,
10681 quad);
10682 %}
10683 ins_pipe( ialu_reg_reg ); // FIXME
10684 %}
10685
10686 // Integers vector logical left shift
10687 instruct vsl2I_reg(vecD dst, vecD src, vecD shift) %{
10688 predicate(n->as_Vector()->length() == 2 && VM_Version::has_simd());
10689 match(Set dst (LShiftVI src shift));
10690 size(4*1);
10691 ins_cost(DEFAULT_COST*1); // FIXME
10692 expand %{
10693 vsh2I_reg(dst, src, shift);
10694 %}
10695 %}
10696
10697 instruct vsl4I_reg(vecX dst, vecX src, vecX shift) %{
10698 predicate(n->as_Vector()->length() == 4 && VM_Version::has_simd());
10699 match(Set dst (LShiftVI src shift));
10700 size(4*1);
10701 ins_cost(DEFAULT_COST*1); // FIXME
10702 expand %{
10703 vsh4I_reg(dst, src, shift);
10704 %}
10705 %}
10706
10707 instruct vsl2I_immI(vecD dst, vecD src, immI shift) %{
10708 predicate(n->as_Vector()->length() == 2 &&
10709 VM_Version::has_simd() &&
10710 assert_not_var_shift(n));
10711 match(Set dst (LShiftVI src (LShiftCntV shift)));
10712 size(4);
10713 ins_cost(DEFAULT_COST); // FIXME
10714 format %{
10715 "VSHL.I32 $dst.D,$src.D,$shift\t! logical left shift packed2I"
10716 %}
10717 ins_encode %{
10718 bool quad = false;
10719 __ vshli($dst$$FloatRegister, $src$$FloatRegister, 32, $shift$$constant,
10720 quad);
10721 %}
10722 ins_pipe( ialu_reg_reg ); // FIXME
10723 %}
10724
10725 instruct vsl4I_immI(vecX dst, vecX src, immI shift) %{
10726 predicate(n->as_Vector()->length() == 4 &&
10727 VM_Version::has_simd() &&
10728 assert_not_var_shift(n));
10729 match(Set dst (LShiftVI src (LShiftCntV shift)));
10730 size(4);
10731 ins_cost(DEFAULT_COST); // FIXME
10732 format %{
10733 "VSHL.I32 $dst.Q,$src.Q,$shift\t! logical left shift packed4I"
10734 %}
10735 ins_encode %{
10736 bool quad = true;
10737 __ vshli($dst$$FloatRegister, $src$$FloatRegister, 32, $shift$$constant,
10738 quad);
10739 %}
10740 ins_pipe( ialu_reg_reg ); // FIXME
10741 %}
10742
10743 // Longs vector logical left shift
10744 instruct vsl2L_reg(vecX dst, vecX src, vecX shift) %{
10745 predicate(n->as_Vector()->length() == 2);
10746 match(Set dst (LShiftVL src shift));
10747 size(4*1);
10748 ins_cost(DEFAULT_COST*1); // FIXME
10749 expand %{
10750 vsh2L_reg(dst, src, shift);
10751 %}
10752 %}
10753
10754 instruct vsl2L_immI(vecX dst, vecX src, immI shift) %{
10755 predicate(n->as_Vector()->length() == 2 && assert_not_var_shift(n));
10756 match(Set dst (LShiftVL src (LShiftCntV shift)));
10757 size(4);
10758 ins_cost(DEFAULT_COST); // FIXME
10759 format %{
10760 "VSHL.I64 $dst.Q,$src.Q,$shift\t! logical left shift packed2L"
10761 %}
10762 ins_encode %{
10763 bool quad = true;
10764 __ vshli($dst$$FloatRegister, $src$$FloatRegister, 64, $shift$$constant,
10765 quad);
10766 %}
10767 ins_pipe( ialu_reg_reg ); // FIXME
10768 %}
10769
10770 // ----------------------- LogicalRightShift -----------------------------------
10771
10772 // Bytes/Shorts vector logical right shift produces incorrect Java result
10773 // for negative data because java code convert short value into int with
10774 // sign extension before a shift.
10775
10776 // Right shift with vector shift count on aarch32 SIMD is implemented as left
10777 // shift by negative shift count value.
10778 //
10779 // Method is_var_shift() denotes that vector shift count is a variable shift:
10780 // 1) for this case, vector shift count should be negated before conducting
10781 // right shifts. E.g., vsrl4S_reg_var rule.
10782 // 2) for the opposite case, vector shift count is generated via RShiftCntV
10783 // rules and is already negated there. Hence, no negation is needed.
10784 // E.g., vsrl4S_reg rule.
10785
10786 // Chars vector logical right shift
10787 instruct vsrl4S_reg(vecD dst, vecD src, vecD shift) %{
10788 predicate(n->as_Vector()->length() == 4 && !n->as_ShiftV()->is_var_shift());
10789 match(Set dst (URShiftVS src shift));
10790 size(4);
10791 ins_cost(DEFAULT_COST);
10792 expand %{
10793 vsh4S_reg(dst, src, shift);
10794 %}
10795 %}
10796
10797 instruct vsrl4S_reg_var(vecD dst, vecD src, vecD shift, vecD tmp) %{
10798 predicate(n->as_Vector()->length() == 4 && n->as_ShiftV()->is_var_shift());
10799 match(Set dst (URShiftVS src shift));
10800 effect(TEMP tmp);
10801 size(4*2);
10802 ins_cost(DEFAULT_COST*2);
10803 format %{
10804 "VNEG.S8 $tmp.D,$shift.D\n\t! neg packed8B"
10805 "VSHL.U16 $dst.D,$src.D,$tmp.D\t! logical right shift packed4S"
10806 %}
10807 ins_encode %{
10808 bool quad = false;
10809 __ vnegI($tmp$$FloatRegister, $shift$$FloatRegister,
10810 MacroAssembler::VELEM_SIZE_8, quad);
10811 __ vshlUI($dst$$FloatRegister, $tmp$$FloatRegister, $src$$FloatRegister,
10812 MacroAssembler::VELEM_SIZE_16, quad);
10813 %}
10814 ins_pipe(ialu_reg_reg);
10815 %}
10816
10817 instruct vsrl8S_reg(vecX dst, vecX src, vecX shift) %{
10818 predicate(n->as_Vector()->length() == 8 && !n->as_ShiftV()->is_var_shift());
10819 match(Set dst (URShiftVS src shift));
10820 size(4);
10821 ins_cost(DEFAULT_COST);
10822 expand %{
10823 vsh8S_reg(dst, src, shift);
10824 %}
10825 %}
10826
10827 instruct vsrl8S_reg_var(vecX dst, vecX src, vecX shift, vecX tmp) %{
10828 predicate(n->as_Vector()->length() == 8 && n->as_ShiftV()->is_var_shift());
10829 match(Set dst (URShiftVS src shift));
10830 effect(TEMP tmp);
10831 size(4*2);
10832 ins_cost(DEFAULT_COST*2);
10833 format %{
10834 "VNEG.S8 $tmp.Q,$shift.Q\n\t! neg packed16B"
10835 "VSHL.U16 $dst.Q,$src.Q,$tmp.Q\t! logical right shift packed8S"
10836 %}
10837 ins_encode %{
10838 bool quad = true;
10839 __ vnegI($tmp$$FloatRegister, $shift$$FloatRegister,
10840 MacroAssembler::VELEM_SIZE_8, quad);
10841 __ vshlUI($dst$$FloatRegister, $tmp$$FloatRegister, $src$$FloatRegister,
10842 MacroAssembler::VELEM_SIZE_16, quad);
10843 %}
10844 ins_pipe(ialu_reg_reg);
10845 %}
10846
10847 instruct vsrl4S_immI(vecD dst, vecD src, immI shift) %{
10848 predicate(n->as_Vector()->length() == 4 && assert_not_var_shift(n));
10849 match(Set dst (URShiftVS src (RShiftCntV shift)));
10850 size(4);
10851 ins_cost(DEFAULT_COST); // FIXME
10852 format %{
10853 "VSHR.U16 $dst.D,$src.D,$shift\t! logical right shift packed4S"
10854 %}
10855 ins_encode %{
10856 bool quad = false;
10857 __ vshrUI($dst$$FloatRegister, $src$$FloatRegister, 16, $shift$$constant,
10858 quad);
10859 %}
10860 ins_pipe( ialu_reg_reg ); // FIXME
10861 %}
10862
10863 instruct vsrl8S_immI(vecX dst, vecX src, immI shift) %{
10864 predicate(n->as_Vector()->length() == 8 && assert_not_var_shift(n));
10865 match(Set dst (URShiftVS src (RShiftCntV shift)));
10866 size(4);
10867 ins_cost(DEFAULT_COST); // FIXME
10868 format %{
10869 "VSHR.U16 $dst.Q,$src.Q,$shift\t! logical right shift packed8S"
10870 %}
10871 ins_encode %{
10872 bool quad = true;
10873 __ vshrUI($dst$$FloatRegister, $src$$FloatRegister, 16, $shift$$constant,
10874 quad);
10875 %}
10876 ins_pipe( ialu_reg_reg ); // FIXME
10877 %}
10878
10879 // Integers vector logical right shift
10880 instruct vsrl2I_reg(vecD dst, vecD src, vecD shift) %{
10881 predicate(n->as_Vector()->length() == 2 &&
10882 VM_Version::has_simd() &&
10883 !n->as_ShiftV()->is_var_shift());
10884 match(Set dst (URShiftVI src shift));
10885 size(4);
10886 ins_cost(DEFAULT_COST);
10887 expand %{
10888 vsh2I_reg(dst, src, shift);
10889 %}
10890 %}
10891
10892 instruct vsrl2I_reg_var(vecD dst, vecD src, vecD shift, vecD tmp) %{
10893 predicate(n->as_Vector()->length() == 2 &&
10894 VM_Version::has_simd() &&
10895 n->as_ShiftV()->is_var_shift());
10896 match(Set dst (URShiftVI src shift));
10897 effect(TEMP tmp);
10898 size(4*2);
10899 ins_cost(DEFAULT_COST*2);
10900 format %{
10901 "VNEG.S8 $tmp.D,$shift.D\n\t! neg packed8B"
10902 "VSHL.U32 $dst.D,$src.D,$tmp.D\t! logical right shift packed2I"
10903 %}
10904 ins_encode %{
10905 bool quad = false;
10906 __ vnegI($tmp$$FloatRegister, $shift$$FloatRegister,
10907 MacroAssembler::VELEM_SIZE_8, quad);
10908 __ vshlUI($dst$$FloatRegister, $tmp$$FloatRegister, $src$$FloatRegister,
10909 MacroAssembler::VELEM_SIZE_32, quad);
10910 %}
10911 ins_pipe(ialu_reg_reg);
10912 %}
10913
10914 instruct vsrl4I_reg(vecX dst, vecX src, vecX shift) %{
10915 predicate(n->as_Vector()->length() == 4 &&
10916 VM_Version::has_simd() &&
10917 !n->as_ShiftV()->is_var_shift());
10918 match(Set dst (URShiftVI src shift));
10919 size(4);
10920 ins_cost(DEFAULT_COST);
10921 expand %{
10922 vsh4I_reg(dst, src, shift);
10923 %}
10924 %}
10925
10926 instruct vsrl4I_reg_var(vecX dst, vecX src, vecX shift, vecX tmp) %{
10927 predicate(n->as_Vector()->length() == 4 &&
10928 VM_Version::has_simd() &&
10929 n->as_ShiftV()->is_var_shift());
10930 match(Set dst (URShiftVI src shift));
10931 effect(TEMP tmp);
10932 size(4*2);
10933 ins_cost(DEFAULT_COST*2);
10934 format %{
10935 "VNEG.S8 $tmp.Q,$shift.Q\n\t! neg packed16B"
10936 "VSHL.U32 $dst.Q,$src.Q,$tmp.Q\t! logical right shift packed4I"
10937 %}
10938 ins_encode %{
10939 bool quad = true;
10940 __ vnegI($tmp$$FloatRegister, $shift$$FloatRegister,
10941 MacroAssembler::VELEM_SIZE_8, quad);
10942 __ vshlUI($dst$$FloatRegister, $tmp$$FloatRegister, $src$$FloatRegister,
10943 MacroAssembler::VELEM_SIZE_32, quad);
10944 %}
10945 ins_pipe(ialu_reg_reg);
10946 %}
10947
10948 instruct vsrl2I_immI(vecD dst, vecD src, immI shift) %{
10949 predicate(n->as_Vector()->length() == 2 &&
10950 VM_Version::has_simd() &&
10951 assert_not_var_shift(n));
10952 match(Set dst (URShiftVI src (RShiftCntV shift)));
10953 size(4);
10954 ins_cost(DEFAULT_COST); // FIXME
10955 format %{
10956 "VSHR.U32 $dst.D,$src.D,$shift\t! logical right shift packed2I"
10957 %}
10958 ins_encode %{
10959 bool quad = false;
10960 __ vshrUI($dst$$FloatRegister, $src$$FloatRegister, 32, $shift$$constant,
10961 quad);
10962 %}
10963 ins_pipe( ialu_reg_reg ); // FIXME
10964 %}
10965
10966 instruct vsrl4I_immI(vecX dst, vecX src, immI shift) %{
10967 predicate(n->as_Vector()->length() == 4 &&
10968 VM_Version::has_simd() &&
10969 assert_not_var_shift(n));
10970 match(Set dst (URShiftVI src (RShiftCntV shift)));
10971 size(4);
10972 ins_cost(DEFAULT_COST); // FIXME
10973 format %{
10974 "VSHR.U32 $dst.Q,$src.Q,$shift\t! logical right shift packed4I"
10975 %}
10976 ins_encode %{
10977 bool quad = true;
10978 __ vshrUI($dst$$FloatRegister, $src$$FloatRegister, 32, $shift$$constant,
10979 quad);
10980 %}
10981 ins_pipe( ialu_reg_reg ); // FIXME
10982 %}
10983
10984 // Longs vector logical right shift
10985 instruct vsrl2L_reg(vecX dst, vecX src, vecX shift) %{
10986 predicate(n->as_Vector()->length() == 2 && !n->as_ShiftV()->is_var_shift());
10987 match(Set dst (URShiftVL src shift));
10988 size(4);
10989 ins_cost(DEFAULT_COST);
10990 expand %{
10991 vsh2L_reg(dst, src, shift);
10992 %}
10993 %}
10994
10995 instruct vsrl2L_reg_var(vecX dst, vecX src, vecX shift, vecX tmp) %{
10996 predicate(n->as_Vector()->length() == 2 && n->as_ShiftV()->is_var_shift());
10997 match(Set dst (URShiftVL src shift));
10998 effect(TEMP tmp, DEF dst, USE src, USE shift);
10999 size(4*2);
11000 ins_cost(DEFAULT_COST*2);
11001 format %{
11002 "VNEG.S8 $tmp.Q,$shift.Q\n\t! neg packed16B"
11003 "VSHL.U64 $dst.Q,$src.Q,$tmp.Q\t! logical right shift packed2L"
11004 %}
11005 ins_encode %{
11006 bool quad = true;
11007 __ vnegI($tmp$$FloatRegister, $shift$$FloatRegister,
11008 MacroAssembler::VELEM_SIZE_8, quad);
11009 __ vshlUI($dst$$FloatRegister, $tmp$$FloatRegister, $src$$FloatRegister,
11010 MacroAssembler::VELEM_SIZE_64, quad);
11011 %}
11012 ins_pipe(ialu_reg_reg);
11013 %}
11014
11015 instruct vsrl2L_immI(vecX dst, vecX src, immI shift) %{
11016 predicate(n->as_Vector()->length() == 2 && assert_not_var_shift(n));
11017 match(Set dst (URShiftVL src (RShiftCntV shift)));
11018 size(4);
11019 ins_cost(DEFAULT_COST); // FIXME
11020 format %{
11021 "VSHR.U64 $dst.Q,$src.Q,$shift\t! logical right shift packed2L"
11022 %}
11023 ins_encode %{
11024 bool quad = true;
11025 __ vshrUI($dst$$FloatRegister, $src$$FloatRegister, 64, $shift$$constant,
11026 quad);
11027 %}
11028 ins_pipe( ialu_reg_reg ); // FIXME
11029 %}
11030
11031 // ------------------- ArithmeticRightShift -----------------------------------
11032
11033 // Bytes vector arithmetic left/right shift based on sign
11034 instruct vsha8B_reg(vecD dst, vecD src, vecD shift) %{
11035 predicate(n->as_Vector()->length() == 8);
11036 effect(DEF dst, USE src, USE shift);
11037 size(4);
11038 ins_cost(DEFAULT_COST); // FIXME
11039 format %{
11040 "VSHL.S8 $dst.D,$src.D,$shift.D\t! arithmetic right shift packed8B"
11041 %}
11042 ins_encode %{
11043 bool quad = false;
11044 __ vshlSI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister,
11045 MacroAssembler::VELEM_SIZE_8, quad);
11046 %}
11047 ins_pipe( ialu_reg_reg ); // FIXME
11048 %}
11049
11050 instruct vsha16B_reg(vecX dst, vecX src, vecX shift) %{
11051 predicate(n->as_Vector()->length() == 16);
11052 effect(DEF dst, USE src, USE shift);
11053 size(4);
11054 ins_cost(DEFAULT_COST); // FIXME
11055 format %{
11056 "VSHL.S8 $dst.Q,$src.Q,$shift.Q\t! arithmetic right shift packed16B"
11057 %}
11058 ins_encode %{
11059 bool quad = true;
11060 __ vshlSI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister,
11061 MacroAssembler::VELEM_SIZE_8, quad);
11062 %}
11063 ins_pipe( ialu_reg_reg ); // FIXME
11064 %}
11065
11066 // Shorts vector arithmetic left/right shift based on sign
11067 instruct vsha4S_reg(vecD dst, vecD src, vecD shift) %{
11068 predicate(n->as_Vector()->length() == 4);
11069 effect(DEF dst, USE src, USE shift);
11070 size(4);
11071 ins_cost(DEFAULT_COST); // FIXME
11072 format %{
11073 "VSHL.S16 $dst.D,$src.D,$shift.D\t! arithmetic right shift packed4S"
11074 %}
11075 ins_encode %{
11076 bool quad = false;
11077 __ vshlSI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister,
11078 MacroAssembler::VELEM_SIZE_16, quad);
11079 %}
11080 ins_pipe( ialu_reg_reg ); // FIXME
11081 %}
11082
11083 instruct vsha8S_reg(vecX dst, vecX src, vecX shift) %{
11084 predicate(n->as_Vector()->length() == 8);
11085 effect(DEF dst, USE src, USE shift);
11086 size(4);
11087 ins_cost(DEFAULT_COST); // FIXME
11088 format %{
11089 "VSHL.S16 $dst.Q,$src.Q,$shift.Q\t! arithmetic right shift packed8S"
11090 %}
11091 ins_encode %{
11092 bool quad = true;
11093 __ vshlSI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister,
11094 MacroAssembler::VELEM_SIZE_16, quad);
11095 %}
11096 ins_pipe( ialu_reg_reg ); // FIXME
11097 %}
11098
11099 // Integers vector arithmetic left/right shift based on sign
11100 instruct vsha2I_reg(vecD dst, vecD src, vecD shift) %{
11101 predicate(n->as_Vector()->length() == 2);
11102 effect(DEF dst, USE src, USE shift);
11103 size(4);
11104 ins_cost(DEFAULT_COST); // FIXME
11105 format %{
11106 "VSHL.S32 $dst.D,$src.D,$shift.D\t! arithmetic right shift packed2I"
11107 %}
11108 ins_encode %{
11109 bool quad = false;
11110 __ vshlSI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister,
11111 MacroAssembler::VELEM_SIZE_32, quad);
11112 %}
11113 ins_pipe( ialu_reg_reg ); // FIXME
11114 %}
11115
11116 instruct vsha4I_reg(vecX dst, vecX src, vecX shift) %{
11117 predicate(n->as_Vector()->length() == 4);
11118 effect(DEF dst, USE src, USE shift);
11119 size(4);
11120 ins_cost(DEFAULT_COST); // FIXME
11121 format %{
11122 "VSHL.S32 $dst.Q,$src.Q,$shift.Q\t! arithmetic right shift packed4I"
11123 %}
11124 ins_encode %{
11125 bool quad = true;
11126 __ vshlSI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister,
11127 MacroAssembler::VELEM_SIZE_32, quad);
11128 %}
11129 ins_pipe( ialu_reg_reg ); // FIXME
11130 %}
11131
11132 // Longs vector arithmetic left/right shift based on sign
11133 instruct vsha2L_reg(vecX dst, vecX src, vecX shift) %{
11134 predicate(n->as_Vector()->length() == 2);
11135 effect(DEF dst, USE src, USE shift);
11136 size(4);
11137 ins_cost(DEFAULT_COST); // FIXME
11138 format %{
11139 "VSHL.S64 $dst.Q,$src.Q,$shift.Q\t! arithmetic right shift packed2L"
11140 %}
11141 ins_encode %{
11142 bool quad = true;
11143 __ vshlSI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister,
11144 MacroAssembler::VELEM_SIZE_64, quad);
11145 %}
11146 ins_pipe( ialu_reg_reg ); // FIXME
11147 %}
11148
11149 // Byte vector arithmetic right shift
11150 instruct vsra8B_reg(vecD dst, vecD src, vecD shift) %{
11151 predicate(n->as_Vector()->length() == 8 && !n->as_ShiftV()->is_var_shift());
11152 match(Set dst (RShiftVB src shift));
11153 size(4);
11154 ins_cost(DEFAULT_COST); // FIXME
11155 expand %{
11156 vsha8B_reg(dst, src, shift);
11157 %}
11158 %}
11159
11160 instruct vsra8B_reg_var(vecD dst, vecD src, vecD shift, vecD tmp) %{
11161 predicate(n->as_Vector()->length() == 8 && n->as_ShiftV()->is_var_shift());
11162 match(Set dst (RShiftVB src shift));
11163 effect(TEMP tmp);
11164 size(4*2);
11165 ins_cost(DEFAULT_COST*2);
11166 format %{
11167 "VNEG.S8 $tmp.D,$shift.D\n\t! neg packed8B"
11168 "VSHL.S8 $dst.D,$src.D,$tmp.D\t! arithmetic right shift packed8B"
11169 %}
11170 ins_encode %{
11171 bool quad = false;
11172 __ vnegI($tmp$$FloatRegister, $shift$$FloatRegister,
11173 MacroAssembler::VELEM_SIZE_8, quad);
11174 __ vshlSI($dst$$FloatRegister, $tmp$$FloatRegister, $src$$FloatRegister,
11175 MacroAssembler::VELEM_SIZE_8, quad);
11176 %}
11177 ins_pipe(ialu_reg_reg);
11178 %}
11179
11180 instruct vsra16B_reg(vecX dst, vecX src, vecX shift) %{
11181 predicate(n->as_Vector()->length() == 16 && !n->as_ShiftV()->is_var_shift());
11182 match(Set dst (RShiftVB src shift));
11183 size(4);
11184 ins_cost(DEFAULT_COST); // FIXME
11185 expand %{
11186 vsha16B_reg(dst, src, shift);
11187 %}
11188 %}
11189
11190 instruct vsra16B_reg_var(vecX dst, vecX src, vecX shift, vecX tmp) %{
11191 predicate(n->as_Vector()->length() == 16 && n->as_ShiftV()->is_var_shift());
11192 match(Set dst (RShiftVB src shift));
11193 effect(TEMP tmp);
11194 size(4*2);
11195 ins_cost(DEFAULT_COST*2);
11196 format %{
11197 "VNEG.S8 $tmp.Q,$shift.Q\n\t! neg packed16B"
11198 "VSHL.S8 $dst.Q,$src.Q,$tmp.Q\t! arithmetic right shift packed16B"
11199 %}
11200 ins_encode %{
11201 bool quad = true;
11202 __ vnegI($tmp$$FloatRegister, $shift$$FloatRegister,
11203 MacroAssembler::VELEM_SIZE_8, quad);
11204 __ vshlSI($dst$$FloatRegister, $tmp$$FloatRegister, $src$$FloatRegister,
11205 MacroAssembler::VELEM_SIZE_8, quad);
11206 %}
11207 ins_pipe(ialu_reg_reg);
11208 %}
11209
11210 instruct vsra8B_immI(vecD dst, vecD src, immI shift) %{
11211 predicate(n->as_Vector()->length() == 8 && assert_not_var_shift(n));
11212 match(Set dst (RShiftVB src (RShiftCntV shift)));
11213 size(4);
11214 ins_cost(DEFAULT_COST); // FIXME
11215 format %{
11216 "VSHR.S8 $dst.D,$src.D,$shift\t! arithmetic right shift packed8B"
11217 %}
11218 ins_encode %{
11219 bool quad = false;
11220 __ vshrSI($dst$$FloatRegister, $src$$FloatRegister, 8, $shift$$constant,
11221 quad);
11222 %}
11223 ins_pipe( ialu_reg_reg ); // FIXME
11224 %}
11225
11226 instruct vsra16B_immI(vecX dst, vecX src, immI shift) %{
11227 predicate(n->as_Vector()->length() == 16 && assert_not_var_shift(n));
11228 match(Set dst (RShiftVB src (RShiftCntV shift)));
11229 size(4);
11230 ins_cost(DEFAULT_COST); // FIXME
11231 format %{
11232 "VSHR.S8 $dst.Q,$src.Q,$shift\t! arithmetic right shift packed16B"
11233 %}
11234 ins_encode %{
11235 bool quad = true;
11236 __ vshrSI($dst$$FloatRegister, $src$$FloatRegister, 8, $shift$$constant,
11237 quad);
11238 %}
11239 ins_pipe( ialu_reg_reg ); // FIXME
11240 %}
11241
11242 // Shorts vector arithmetic right shift
11243 instruct vsra4S_reg(vecD dst, vecD src, vecD shift) %{
11244 predicate(n->as_Vector()->length() == 4 && !n->as_ShiftV()->is_var_shift());
11245 match(Set dst (RShiftVS src shift));
11246 size(4);
11247 ins_cost(DEFAULT_COST); // FIXME
11248 expand %{
11249 vsha4S_reg(dst, src, shift);
11250 %}
11251 %}
11252
11253 instruct vsra4S_reg_var(vecD dst, vecD src, vecD shift, vecD tmp) %{
11254 predicate(n->as_Vector()->length() == 4 && n->as_ShiftV()->is_var_shift());
11255 match(Set dst (RShiftVS src shift));
11256 effect(TEMP tmp);
11257 size(4*2);
11258 ins_cost(DEFAULT_COST*2);
11259 format %{
11260 "VNEG.S8 $tmp.D,$shift.D\n\t! neg packed8B"
11261 "VSHL.S16 $dst.D,$src.D,$tmp.D\t! arithmetic right shift packed4S"
11262 %}
11263 ins_encode %{
11264 bool quad = false;
11265 __ vnegI($tmp$$FloatRegister, $shift$$FloatRegister,
11266 MacroAssembler::VELEM_SIZE_8, quad);
11267 __ vshlSI($dst$$FloatRegister, $tmp$$FloatRegister, $src$$FloatRegister,
11268 MacroAssembler::VELEM_SIZE_16, quad);
11269 %}
11270 ins_pipe(ialu_reg_reg);
11271 %}
11272
11273 instruct vsra8S_reg(vecX dst, vecX src, vecX shift) %{
11274 predicate(n->as_Vector()->length() == 8 && !n->as_ShiftV()->is_var_shift());
11275 match(Set dst (RShiftVS src shift));
11276 size(4);
11277 ins_cost(DEFAULT_COST); // FIXME
11278 expand %{
11279 vsha8S_reg(dst, src, shift);
11280 %}
11281 %}
11282
11283 instruct vsra8S_reg_var(vecX dst, vecX src, vecX shift, vecX tmp) %{
11284 predicate(n->as_Vector()->length() == 8 && n->as_ShiftV()->is_var_shift());
11285 match(Set dst (RShiftVS src shift));
11286 effect(TEMP tmp);
11287 size(4*2);
11288 ins_cost(DEFAULT_COST*2);
11289 format %{
11290 "VNEG.S8 $tmp.Q,$shift.Q\n\t! neg packed16B"
11291 "VSHL.S16 $dst.Q,$src.Q,$tmp.Q\t! arithmetic right shift packed8S"
11292 %}
11293 ins_encode %{
11294 bool quad = true;
11295 __ vnegI($tmp$$FloatRegister, $shift$$FloatRegister,
11296 MacroAssembler::VELEM_SIZE_8, quad);
11297 __ vshlSI($dst$$FloatRegister, $tmp$$FloatRegister, $src$$FloatRegister,
11298 MacroAssembler::VELEM_SIZE_16, quad);
11299 %}
11300 ins_pipe(ialu_reg_reg);
11301 %}
11302
11303 instruct vsra4S_immI(vecD dst, vecD src, immI shift) %{
11304 predicate(n->as_Vector()->length() == 4 && assert_not_var_shift(n));
11305 match(Set dst (RShiftVS src (RShiftCntV shift)));
11306 size(4);
11307 ins_cost(DEFAULT_COST); // FIXME
11308 format %{
11309 "VSHR.S16 $dst.D,$src.D,$shift\t! arithmetic right shift packed4S"
11310 %}
11311 ins_encode %{
11312 bool quad = false;
11313 __ vshrSI($dst$$FloatRegister, $src$$FloatRegister, 16, $shift$$constant,
11314 quad);
11315 %}
11316 ins_pipe( ialu_reg_reg ); // FIXME
11317 %}
11318
11319 instruct vsra8S_immI(vecX dst, vecX src, immI shift) %{
11320 predicate(n->as_Vector()->length() == 8 && assert_not_var_shift(n));
11321 match(Set dst (RShiftVS src (RShiftCntV shift)));
11322 size(4);
11323 ins_cost(DEFAULT_COST); // FIXME
11324 format %{
11325 "VSHR.S16 $dst.Q,$src.Q,$shift\t! arithmetic right shift packed8S"
11326 %}
11327 ins_encode %{
11328 bool quad = true;
11329 __ vshrSI($dst$$FloatRegister, $src$$FloatRegister, 16, $shift$$constant,
11330 quad);
11331 %}
11332 ins_pipe( ialu_reg_reg ); // FIXME
11333 %}
11334
11335 // Integers vector arithmetic right shift
11336 instruct vsra2I_reg(vecD dst, vecD src, vecD shift) %{
11337 predicate(n->as_Vector()->length() == 2 && !n->as_ShiftV()->is_var_shift());
11338 match(Set dst (RShiftVI src shift));
11339 size(4);
11340 ins_cost(DEFAULT_COST); // FIXME
11341 expand %{
11342 vsha2I_reg(dst, src, shift);
11343 %}
11344 %}
11345
11346 instruct vsra2I_reg_var(vecD dst, vecD src, vecD shift, vecD tmp) %{
11347 predicate(n->as_Vector()->length() == 2 && n->as_ShiftV()->is_var_shift());
11348 match(Set dst (RShiftVI src shift));
11349 effect(TEMP tmp);
11350 size(4*2);
11351 ins_cost(DEFAULT_COST*2);
11352 format %{
11353 "VNEG.S8 $tmp.D,$shift.D\n\t! neg packed8B"
11354 "VSHL.S32 $dst.D,$src.D,$tmp.D\t! arithmetic right shift packed2I"
11355 %}
11356 ins_encode %{
11357 bool quad = false;
11358 __ vnegI($tmp$$FloatRegister, $shift$$FloatRegister,
11359 MacroAssembler::VELEM_SIZE_8, quad);
11360 __ vshlSI($dst$$FloatRegister, $tmp$$FloatRegister, $src$$FloatRegister,
11361 MacroAssembler::VELEM_SIZE_32, quad);
11362 %}
11363 ins_pipe(ialu_reg_reg);
11364 %}
11365
11366 instruct vsra4I_reg(vecX dst, vecX src, vecX shift) %{
11367 predicate(n->as_Vector()->length() == 4 && !n->as_ShiftV()->is_var_shift());
11368 match(Set dst (RShiftVI src shift));
11369 size(4);
11370 ins_cost(DEFAULT_COST); // FIXME
11371 expand %{
11372 vsha4I_reg(dst, src, shift);
11373 %}
11374 %}
11375
11376 instruct vsra4I_reg_var(vecX dst, vecX src, vecX shift, vecX tmp) %{
11377 predicate(n->as_Vector()->length() == 4 && n->as_ShiftV()->is_var_shift());
11378 match(Set dst (RShiftVI src shift));
11379 effect(TEMP tmp);
11380 size(4*2);
11381 ins_cost(DEFAULT_COST*2);
11382 format %{
11383 "VNEG.S8 $tmp.Q,$shift.Q\n\t! neg packed16B"
11384 "VSHL.S32 $dst.Q,$src.Q,$tmp.Q\t! arithmetic right shift packed4I"
11385 %}
11386 ins_encode %{
11387 bool quad = true;
11388 __ vnegI($tmp$$FloatRegister, $shift$$FloatRegister,
11389 MacroAssembler::VELEM_SIZE_8, quad);
11390 __ vshlSI($dst$$FloatRegister, $tmp$$FloatRegister, $src$$FloatRegister,
11391 MacroAssembler::VELEM_SIZE_32, quad);
11392 %}
11393 ins_pipe(ialu_reg_reg);
11394 %}
11395
11396 instruct vsra2I_immI(vecD dst, vecD src, immI shift) %{
11397 predicate(n->as_Vector()->length() == 2 && assert_not_var_shift(n));
11398 match(Set dst (RShiftVI src (RShiftCntV shift)));
11399 size(4);
11400 ins_cost(DEFAULT_COST); // FIXME
11401 format %{
11402 "VSHR.S32 $dst.D,$src.D,$shift\t! arithmetic right shift packed2I"
11403 %}
11404 ins_encode %{
11405 bool quad = false;
11406 __ vshrSI($dst$$FloatRegister, $src$$FloatRegister, 32, $shift$$constant,
11407 quad);
11408 %}
11409 ins_pipe( ialu_reg_reg ); // FIXME
11410 %}
11411
11412 instruct vsra4I_immI(vecX dst, vecX src, immI shift) %{
11413 predicate(n->as_Vector()->length() == 4 && assert_not_var_shift(n));
11414 match(Set dst (RShiftVI src (RShiftCntV shift)));
11415 size(4);
11416 ins_cost(DEFAULT_COST); // FIXME
11417 format %{
11418 "VSHR.S32 $dst.Q,$src.Q,$shift\t! arithmetic right shift packed4I"
11419 %}
11420 ins_encode %{
11421 bool quad = true;
11422 __ vshrSI($dst$$FloatRegister, $src$$FloatRegister, 32, $shift$$constant,
11423 quad);
11424 %}
11425 ins_pipe( ialu_reg_reg ); // FIXME
11426 %}
11427
11428 // Longs vector arithmetic right shift
11429 instruct vsra2L_reg(vecX dst, vecX src, vecX shift) %{
11430 predicate(n->as_Vector()->length() == 2 && !n->as_ShiftV()->is_var_shift());
11431 match(Set dst (RShiftVL src shift));
11432 size(4);
11433 ins_cost(DEFAULT_COST); // FIXME
11434 expand %{
11435 vsha2L_reg(dst, src, shift);
11436 %}
11437 %}
11438
11439 instruct vsra2L_reg_var(vecX dst, vecX src, vecX shift, vecX tmp) %{
11440 predicate(n->as_Vector()->length() == 2 && n->as_ShiftV()->is_var_shift());
11441 match(Set dst (RShiftVL src shift));
11442 effect(TEMP tmp);
11443 size(4*2);
11444 ins_cost(DEFAULT_COST*2);
11445 format %{
11446 "VNEG.S8 $tmp.Q,$shift.Q\n\t! neg packed16B"
11447 "VSHL.S64 $dst.Q,$src.Q,$tmp.Q\t! arithmetic right shift packed2L"
11448 %}
11449 ins_encode %{
11450 bool quad = true;
11451 __ vnegI($tmp$$FloatRegister, $shift$$FloatRegister,
11452 MacroAssembler::VELEM_SIZE_8, quad);
11453 __ vshlSI($dst$$FloatRegister, $tmp$$FloatRegister, $src$$FloatRegister,
11454 MacroAssembler::VELEM_SIZE_64, quad);
11455 %}
11456 ins_pipe(ialu_reg_reg);
11457 %}
11458
11459 instruct vsra2L_immI(vecX dst, vecX src, immI shift) %{
11460 predicate(n->as_Vector()->length() == 2 && assert_not_var_shift(n));
11461 match(Set dst (RShiftVL src (RShiftCntV shift)));
11462 size(4);
11463 ins_cost(DEFAULT_COST); // FIXME
11464 format %{
11465 "VSHR.S64 $dst.Q,$src.Q,$shift\t! arithmetic right shift packed2L"
11466 %}
11467 ins_encode %{
11468 bool quad = true;
11469 __ vshrSI($dst$$FloatRegister, $src$$FloatRegister, 64, $shift$$constant,
11470 quad);
11471 %}
11472 ins_pipe( ialu_reg_reg ); // FIXME
11473 %}
11474
11475 // --------------------------------- AND --------------------------------------
11476
11477 instruct vandD(vecD dst, vecD src1, vecD src2) %{
11478 predicate(n->as_Vector()->length_in_bytes() == 8);
11479 match(Set dst (AndV src1 src2));
11480 format %{ "VAND $dst.D,$src1.D,$src2.D\t! and vectors (8 bytes)" %}
11481 ins_encode %{
11482 bool quad = false;
11483 __ vandI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
11484 quad);
11485 %}
11486 ins_pipe( ialu_reg_reg ); // FIXME
11487 %}
11488
11489 instruct vandX(vecX dst, vecX src1, vecX src2) %{
11490 predicate(n->as_Vector()->length_in_bytes() == 16);
11491 match(Set dst (AndV src1 src2));
11492 format %{ "VAND $dst.Q,$src1.Q,$src2.Q\t! and vectors (16 bytes)" %}
11493 ins_encode %{
11494 bool quad = true;
11495 __ vandI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
11496 quad);
11497 %}
11498 ins_pipe( ialu_reg_reg ); // FIXME
11499 %}
11500
11501 // --------------------------------- OR ---------------------------------------
11502
11503 instruct vorD(vecD dst, vecD src1, vecD src2) %{
11504 predicate(n->as_Vector()->length_in_bytes() == 8);
11505 match(Set dst (OrV src1 src2));
11506 format %{ "VOR $dst.D,$src1.D,$src2.D\t! and vectors (8 bytes)" %}
11507 ins_encode %{
11508 bool quad = false;
11509 __ vorI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
11510 quad);
11511 %}
11512 ins_pipe( ialu_reg_reg ); // FIXME
11513 %}
11514
11515 instruct vorX(vecX dst, vecX src1, vecX src2) %{
11516 predicate(n->as_Vector()->length_in_bytes() == 16);
11517 match(Set dst (OrV src1 src2));
11518 format %{ "VOR $dst.Q,$src1.Q,$src2.Q\t! and vectors (16 bytes)" %}
11519 ins_encode %{
11520 bool quad = true;
11521 __ vorI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
11522 quad);
11523 %}
11524 ins_pipe( ialu_reg_reg ); // FIXME
11525 %}
11526
11527 // --------------------------------- XOR --------------------------------------
11528
11529 instruct vxorD(vecD dst, vecD src1, vecD src2) %{
11530 predicate(n->as_Vector()->length_in_bytes() == 8);
11531 match(Set dst (XorV src1 src2));
11532 format %{ "VXOR $dst.D,$src1.D,$src2.D\t! and vectors (8 bytes)" %}
11533 ins_encode %{
11534 bool quad = false;
11535 __ vxorI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
11536 quad);
11537 %}
11538 ins_pipe( ialu_reg_reg ); // FIXME
11539 %}
11540
11541 instruct vxorX(vecX dst, vecX src1, vecX src2) %{
11542 predicate(n->as_Vector()->length_in_bytes() == 16);
11543 match(Set dst (XorV src1 src2));
11544 format %{ "VXOR $dst.Q,$src1.Q,$src2.Q\t! and vectors (16 bytes)" %}
11545 ins_encode %{
11546 bool quad = true;
11547 __ vxorI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister,
11548 quad);
11549 %}
11550 ins_pipe( ialu_reg_reg ); // FIXME
11551 %}
11552
11553
11554 //----------PEEPHOLE RULES-----------------------------------------------------
11555 // These must follow all instruction definitions as they use the names
11556 // defined in the instructions definitions.
11557 //
11558 // peepmatch ( root_instr_name [preceding_instruction]* );
11559 //
11560 // peepconstraint %{
11561 // (instruction_number.operand_name relational_op instruction_number.operand_name
11562 // [, ...] );
11563 // // instruction numbers are zero-based using left to right order in peepmatch
11564 //
11565 // peepreplace ( instr_name ( [instruction_number.operand_name]* ) );
11566 // // provide an instruction_number.operand_name for each operand that appears
11567 // // in the replacement instruction's match rule
11568 //
11569 // ---------VM FLAGS---------------------------------------------------------
11570 //
11571 // All peephole optimizations can be turned off using -XX:-OptoPeephole
11572 //
11573 // Each peephole rule is given an identifying number starting with zero and
11574 // increasing by one in the order seen by the parser. An individual peephole
11575 // can be enabled, and all others disabled, by using -XX:OptoPeepholeAt=#
11576 // on the command-line.
11577 //
11578 // ---------CURRENT LIMITATIONS----------------------------------------------
11579 //
11580 // Only match adjacent instructions in same basic block
11581 // Only equality constraints
11582 // Only constraints between operands, not (0.dest_reg == EAX_enc)
11583 // Only one replacement instruction
11584 //
11585 // ---------EXAMPLE----------------------------------------------------------
11586 //
11587 // // pertinent parts of existing instructions in architecture description
11588 // instruct movI(eRegI dst, eRegI src) %{
11589 // match(Set dst (CopyI src));
11590 // %}
11591 //
11592 // instruct incI_eReg(eRegI dst, immI1 src, eFlagsReg cr) %{
11593 // match(Set dst (AddI dst src));
11594 // effect(KILL cr);
11595 // %}
11596 //
11597 // // Change (inc mov) to lea
11598 // peephole %{
11599 // // increment preceded by register-register move
11600 // peepmatch ( incI_eReg movI );
11601 // // require that the destination register of the increment
11602 // // match the destination register of the move
11603 // peepconstraint ( 0.dst == 1.dst );
11604 // // construct a replacement instruction that sets
11605 // // the destination to ( move's source register + one )
11606 // peepreplace ( incI_eReg_immI1( 0.dst 1.src 0.src ) );
11607 // %}
11608 //
11609
11610 // // Change load of spilled value to only a spill
11611 // instruct storeI(memory mem, eRegI src) %{
11612 // match(Set mem (StoreI mem src));
11613 // %}
11614 //
11615 // instruct loadI(eRegI dst, memory mem) %{
11616 // match(Set dst (LoadI mem));
11617 // %}
11618 //
11619 // peephole %{
11620 // peepmatch ( loadI storeI );
11621 // peepconstraint ( 1.src == 0.dst, 1.mem == 0.mem );
11622 // peepreplace ( storeI( 1.mem 1.mem 1.src ) );
11623 // %}
11624
11625 //----------SMARTSPILL RULES---------------------------------------------------
11626 // These must follow all instruction definitions as they use the names
11627 // defined in the instructions definitions.
11628 //
11629 // ARM will probably not have any of these rules due to RISC instruction set.
11630
11631 //----------PIPELINE-----------------------------------------------------------
11632 // Rules which define the behavior of the target architectures pipeline.