1 // 2 // Copyright (c) 2008, 2025, Oracle and/or its affiliates. All rights reserved. 3 // DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 // 5 // This code is free software; you can redistribute it and/or modify it 6 // under the terms of the GNU General Public License version 2 only, as 7 // published by the Free Software Foundation. 8 // 9 // This code is distributed in the hope that it will be useful, but WITHOUT 10 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 // version 2 for more details (a copy is included in the LICENSE file that 13 // accompanied this code). 14 // 15 // You should have received a copy of the GNU General Public License version 16 // 2 along with this work; if not, write to the Free Software Foundation, 17 // Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 // 19 // Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 // or visit www.oracle.com if you need additional information or have any 21 // questions. 22 // 23 24 // 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_exception_handler(C2_MacroAssembler *masm); 109 static int emit_deopt_handler(C2_MacroAssembler* masm); 110 111 static uint size_exception_handler() { 112 return ( 3 * 4 ); 113 } 114 115 116 static uint size_deopt_handler() { 117 return ( 9 * 4 ); 118 } 119 120 }; 121 122 class Node::PD { 123 public: 124 enum NodeFlags { 125 _last_flag = Node::_last_flag 126 }; 127 }; 128 129 // Assert that the given node is not a var shift. 130 bool assert_not_var_shift(const Node *n); 131 %} 132 133 source %{ 134 135 // Assert that the given node is not a var shift. 136 bool assert_not_var_shift(const Node *n) { 137 assert(!n->as_ShiftV()->is_var_shift(), "illegal var shift"); 138 return true; 139 } 140 141 #define __ masm-> 142 143 static FloatRegister reg_to_FloatRegister_object(int register_encoding); 144 static Register reg_to_register_object(int register_encoding); 145 146 void PhaseOutput::pd_perform_mach_node_analysis() { 147 } 148 149 int MachNode::pd_alignment_required() const { 150 return 1; 151 } 152 153 int MachNode::compute_padding(int current_offset) const { 154 return 0; 155 } 156 157 // **************************************************************************** 158 159 // REQUIRED FUNCTIONALITY 160 161 // emit an interrupt that is caught by the debugger (for debugging compiler) 162 void emit_break(C2_MacroAssembler *masm) { 163 __ breakpoint(); 164 } 165 166 #ifndef PRODUCT 167 void MachBreakpointNode::format( PhaseRegAlloc *, outputStream *st ) const { 168 st->print("TA"); 169 } 170 #endif 171 172 void MachBreakpointNode::emit(C2_MacroAssembler *masm, PhaseRegAlloc *ra_) const { 173 emit_break(masm); 174 } 175 176 uint MachBreakpointNode::size(PhaseRegAlloc *ra_) const { 177 return MachNode::size(ra_); 178 } 179 180 181 void emit_nop(C2_MacroAssembler *masm) { 182 __ nop(); 183 } 184 185 186 void emit_call_reloc(C2_MacroAssembler *masm, const MachCallNode *n, MachOper *m, RelocationHolder const& rspec) { 187 int ret_addr_offset0 = n->as_MachCall()->ret_addr_offset(); 188 int call_site_offset = __ code()->insts()->mark_off(); 189 __ set_inst_mark(); // needed in emit_to_interp_stub() to locate the call 190 address target = (address)m->method(); 191 assert(n->as_MachCall()->entry_point() == target, "sanity"); 192 assert(maybe_far_call(n) == !__ reachable_from_cache(target), "sanity"); 193 assert(cache_reachable() == __ cache_fully_reachable(), "sanity"); 194 195 assert(target != nullptr, "need real address"); 196 197 int ret_addr_offset = -1; 198 if (rspec.type() == relocInfo::runtime_call_type) { 199 __ call(target, rspec); 200 ret_addr_offset = __ offset(); 201 } else { 202 // scratches Rtemp 203 ret_addr_offset = __ patchable_call(target, rspec, true); 204 } 205 assert(ret_addr_offset - call_site_offset == ret_addr_offset0, "fix ret_addr_offset()"); 206 } 207 208 //============================================================================= 209 // REQUIRED FUNCTIONALITY for encoding 210 void emit_lo(C2_MacroAssembler *masm, int val) { } 211 void emit_hi(C2_MacroAssembler *masm, int val) { } 212 213 214 //============================================================================= 215 const RegMask& MachConstantBaseNode::_out_RegMask = PTR_REG_mask(); 216 217 int ConstantTable::calculate_table_base_offset() const { 218 int offset = -(size() / 2); 219 // flds, fldd: 8-bit offset multiplied by 4: +/- 1024 220 // ldr, ldrb : 12-bit offset: +/- 4096 221 if (!Assembler::is_simm10(offset)) { 222 offset = Assembler::min_simm10; 223 } 224 return offset; 225 } 226 227 bool MachConstantBaseNode::requires_postalloc_expand() const { return false; } 228 void MachConstantBaseNode::postalloc_expand(GrowableArray <Node *> *nodes, PhaseRegAlloc *ra_) { 229 ShouldNotReachHere(); 230 } 231 232 void MachConstantBaseNode::emit(C2_MacroAssembler* masm, PhaseRegAlloc* ra_) const { 233 Compile* C = ra_->C; 234 ConstantTable& constant_table = C->output()->constant_table(); 235 236 Register r = as_Register(ra_->get_encode(this)); 237 CodeSection* consts_section = __ code()->consts(); 238 CodeSection* insts_section = __ code()->insts(); 239 // constants section size is aligned according to the align_at_start settings of the next section 240 int consts_size = insts_section->align_at_start(consts_section->size()); 241 assert(constant_table.size() == consts_size, "must be: %d == %d", constant_table.size(), consts_size); 242 243 // Materialize the constant table base. 244 address baseaddr = consts_section->start() + -(constant_table.table_base_offset()); 245 RelocationHolder rspec = internal_word_Relocation::spec(baseaddr); 246 __ mov_address(r, baseaddr, rspec); 247 } 248 249 uint MachConstantBaseNode::size(PhaseRegAlloc*) const { 250 return 8; 251 } 252 253 #ifndef PRODUCT 254 void MachConstantBaseNode::format(PhaseRegAlloc* ra_, outputStream* st) const { 255 char reg[128]; 256 ra_->dump_register(this, reg, sizeof(reg)); 257 st->print("MOV_SLOW &constanttable,%s\t! constant table base", reg); 258 } 259 #endif 260 261 #ifndef PRODUCT 262 void MachPrologNode::format( PhaseRegAlloc *ra_, outputStream *st ) const { 263 Compile* C = ra_->C; 264 265 for (int i = 0; i < OptoPrologueNops; i++) { 266 st->print_cr("NOP"); st->print("\t"); 267 } 268 269 size_t framesize = C->output()->frame_size_in_bytes(); 270 assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned"); 271 int bangsize = C->output()->bang_size_in_bytes(); 272 // Remove two words for return addr and rbp, 273 framesize -= 2*wordSize; 274 bangsize -= 2*wordSize; 275 276 // Calls to C2R adapters often do not accept exceptional returns. 277 // We require that their callers must bang for them. But be careful, because 278 // some VM calls (such as call site linkage) can use several kilobytes of 279 // stack. But the stack safety zone should account for that. 280 // See bugs 4446381, 4468289, 4497237. 281 if (C->output()->need_stack_bang(bangsize)) { 282 st->print_cr("! stack bang (%d bytes)", bangsize); st->print("\t"); 283 } 284 st->print_cr("PUSH R_FP|R_LR_LR"); st->print("\t"); 285 if (framesize != 0) { 286 st->print ("SUB R_SP, R_SP, %zu", framesize); 287 } 288 289 if (C->stub_function() == nullptr) { 290 st->print("ldr t0, [guard]\n\t"); 291 st->print("ldr t1, [Rthread, #thread_disarmed_guard_value_offset]\n\t"); 292 st->print("cmp t0, t1\n\t"); 293 st->print("beq skip\n\t"); 294 st->print("blr #nmethod_entry_barrier_stub\n\t"); 295 st->print("b skip\n\t"); 296 st->print("guard: int\n\t"); 297 st->print("skip:\n\t"); 298 } 299 } 300 #endif 301 302 void MachPrologNode::emit(C2_MacroAssembler *masm, PhaseRegAlloc *ra_) const { 303 Compile* C = ra_->C; 304 305 for (int i = 0; i < OptoPrologueNops; i++) { 306 __ nop(); 307 } 308 309 size_t framesize = C->output()->frame_size_in_bytes(); 310 assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned"); 311 int bangsize = C->output()->bang_size_in_bytes(); 312 // Remove two words for return addr and fp, 313 framesize -= 2*wordSize; 314 bangsize -= 2*wordSize; 315 316 // Calls to C2R adapters often do not accept exceptional returns. 317 // We require that their callers must bang for them. But be careful, because 318 // some VM calls (such as call site linkage) can use several kilobytes of 319 // stack. But the stack safety zone should account for that. 320 // See bugs 4446381, 4468289, 4497237. 321 if (C->output()->need_stack_bang(bangsize)) { 322 __ arm_stack_overflow_check(bangsize, Rtemp); 323 } 324 325 __ raw_push(FP, LR); 326 if (framesize != 0) { 327 __ sub_slow(SP, SP, framesize); 328 } 329 330 if (C->stub_function() == nullptr) { 331 BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler(); 332 bs->nmethod_entry_barrier(masm); 333 } 334 335 // offset from scratch buffer is not valid 336 if (strcmp(__ code()->name(), "Compile::Fill_buffer") == 0) { 337 C->output()->set_frame_complete( __ offset() ); 338 } 339 340 if (C->has_mach_constant_base_node()) { 341 // NOTE: We set the table base offset here because users might be 342 // emitted before MachConstantBaseNode. 343 ConstantTable& constant_table = C->output()->constant_table(); 344 constant_table.set_table_base_offset(constant_table.calculate_table_base_offset()); 345 } 346 } 347 348 uint MachPrologNode::size(PhaseRegAlloc *ra_) const { 349 return MachNode::size(ra_); 350 } 351 352 int MachPrologNode::reloc() const { 353 return 10; // a large enough number 354 } 355 356 //============================================================================= 357 #ifndef PRODUCT 358 void MachEpilogNode::format( PhaseRegAlloc *ra_, outputStream *st ) const { 359 Compile* C = ra_->C; 360 361 size_t framesize = C->output()->frame_size_in_bytes(); 362 framesize -= 2*wordSize; 363 364 if (framesize != 0) { 365 st->print("ADD R_SP, R_SP, %zu\n\t",framesize); 366 } 367 st->print("POP R_FP|R_LR_LR"); 368 369 if (do_polling() && ra_->C->is_method_compilation()) { 370 st->print("\n\t"); 371 st->print("MOV Rtemp, #PollAddr\t! Load Polling address\n\t"); 372 st->print("LDR Rtemp,[Rtemp]\t!Poll for Safepointing"); 373 } 374 } 375 #endif 376 377 void MachEpilogNode::emit(C2_MacroAssembler *masm, PhaseRegAlloc *ra_) const { 378 Compile* C = ra_->C; 379 380 size_t framesize = C->output()->frame_size_in_bytes(); 381 framesize -= 2*wordSize; 382 if (framesize != 0) { 383 __ add_slow(SP, SP, framesize); 384 } 385 __ raw_pop(FP, LR); 386 387 // If this does safepoint polling, then do it here 388 if (do_polling() && ra_->C->is_method_compilation()) { 389 __ read_polling_page(Rtemp, relocInfo::poll_return_type); 390 } 391 } 392 393 uint MachEpilogNode::size(PhaseRegAlloc *ra_) const { 394 return MachNode::size(ra_); 395 } 396 397 int MachEpilogNode::reloc() const { 398 return 16; // a large enough number 399 } 400 401 const Pipeline * MachEpilogNode::pipeline() const { 402 return MachNode::pipeline_class(); 403 } 404 405 //============================================================================= 406 407 // Figure out which register class each belongs in: rc_int, rc_float, rc_stack 408 enum RC { rc_bad, rc_int, rc_float, rc_stack }; 409 static enum RC rc_class( OptoReg::Name reg ) { 410 if (!OptoReg::is_valid(reg)) return rc_bad; 411 if (OptoReg::is_stack(reg)) return rc_stack; 412 VMReg r = OptoReg::as_VMReg(reg); 413 if (r->is_Register()) return rc_int; 414 assert(r->is_FloatRegister(), "must be"); 415 return rc_float; 416 } 417 418 static inline bool is_iRegLd_memhd(OptoReg::Name src_first, OptoReg::Name src_second, int offset) { 419 int rlo = Matcher::_regEncode[src_first]; 420 int rhi = Matcher::_regEncode[src_second]; 421 if (!((rlo&1)==0 && (rlo+1 == rhi))) { 422 tty->print_cr("CAUGHT BAD LDRD/STRD"); 423 } 424 return (rlo&1)==0 && (rlo+1 == rhi) && is_memoryHD(offset); 425 } 426 427 uint MachSpillCopyNode::implementation( C2_MacroAssembler *masm, 428 PhaseRegAlloc *ra_, 429 bool do_size, 430 outputStream* st ) const { 431 // Get registers to move 432 OptoReg::Name src_second = ra_->get_reg_second(in(1)); 433 OptoReg::Name src_first = ra_->get_reg_first(in(1)); 434 OptoReg::Name dst_second = ra_->get_reg_second(this ); 435 OptoReg::Name dst_first = ra_->get_reg_first(this ); 436 437 enum RC src_second_rc = rc_class(src_second); 438 enum RC src_first_rc = rc_class(src_first); 439 enum RC dst_second_rc = rc_class(dst_second); 440 enum RC dst_first_rc = rc_class(dst_first); 441 442 assert( OptoReg::is_valid(src_first) && OptoReg::is_valid(dst_first), "must move at least 1 register" ); 443 444 // Generate spill code! 445 int size = 0; 446 447 if (src_first == dst_first && src_second == dst_second) 448 return size; // Self copy, no move 449 450 #ifdef TODO 451 if (bottom_type()->isa_vect() != nullptr) { 452 } 453 #endif 454 455 // Shared code does not expect instruction set capability based bailouts here. 456 // Handle offset unreachable bailout with minimal change in shared code. 457 // Bailout only for real instruction emit. 458 // This requires a single comment change in shared code. ( see output.cpp "Normal" instruction case ) 459 460 // -------------------------------------- 461 // Check for mem-mem move. Load into unused float registers and fall into 462 // the float-store case. 463 if (src_first_rc == rc_stack && dst_first_rc == rc_stack) { 464 int offset = ra_->reg2offset(src_first); 465 if (masm && !is_memoryfp(offset)) { 466 ra_->C->record_method_not_compilable("unable to handle large constant offsets"); 467 return 0; 468 } else { 469 if (src_second_rc != rc_bad) { 470 assert((src_first&1)==0 && src_first+1 == src_second, "pair of registers must be aligned/contiguous"); 471 src_first = OptoReg::Name(R_mem_copy_lo_num); 472 src_second = OptoReg::Name(R_mem_copy_hi_num); 473 src_first_rc = rc_float; 474 src_second_rc = rc_float; 475 if (masm) { 476 __ ldr_double(Rmemcopy, Address(SP, offset)); 477 } else if (!do_size) { 478 st->print(LDR_DOUBLE " R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(src_first),offset); 479 } 480 } else { 481 src_first = OptoReg::Name(R_mem_copy_lo_num); 482 src_first_rc = rc_float; 483 if (masm) { 484 __ ldr_float(Rmemcopy, Address(SP, offset)); 485 } else if (!do_size) { 486 st->print(LDR_FLOAT " R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(src_first),offset); 487 } 488 } 489 size += 4; 490 } 491 } 492 493 if (src_second_rc == rc_stack && dst_second_rc == rc_stack) { 494 Unimplemented(); 495 } 496 497 // -------------------------------------- 498 // Check for integer reg-reg copy 499 if (src_first_rc == rc_int && dst_first_rc == rc_int) { 500 // Else normal reg-reg copy 501 assert( src_second != dst_first, "smashed second before evacuating it" ); 502 if (masm) { 503 __ mov(reg_to_register_object(Matcher::_regEncode[dst_first]), reg_to_register_object(Matcher::_regEncode[src_first])); 504 #ifndef PRODUCT 505 } else if (!do_size) { 506 st->print("MOV R_%s, R_%s\t# spill", 507 Matcher::regName[dst_first], 508 Matcher::regName[src_first]); 509 #endif 510 } 511 size += 4; 512 } 513 514 // Check for integer store 515 if (src_first_rc == rc_int && dst_first_rc == rc_stack) { 516 int offset = ra_->reg2offset(dst_first); 517 if (masm && !is_memoryI(offset)) { 518 ra_->C->record_method_not_compilable("unable to handle large constant offsets"); 519 return 0; 520 } else { 521 if (src_second_rc != rc_bad && is_iRegLd_memhd(src_first, src_second, offset)) { 522 assert((src_first&1)==0 && src_first+1 == src_second, "pair of registers must be aligned/contiguous"); 523 if (masm) { 524 __ str_64(reg_to_register_object(Matcher::_regEncode[src_first]), Address(SP, offset)); 525 #ifndef PRODUCT 526 } else if (!do_size) { 527 if (size != 0) st->print("\n\t"); 528 st->print(STR_64 " R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(src_first), offset); 529 #endif 530 } 531 return size + 4; 532 } else { 533 if (masm) { 534 __ str_32(reg_to_register_object(Matcher::_regEncode[src_first]), Address(SP, offset)); 535 #ifndef PRODUCT 536 } else if (!do_size) { 537 if (size != 0) st->print("\n\t"); 538 st->print(STR_32 " R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(src_first), offset); 539 #endif 540 } 541 } 542 } 543 size += 4; 544 } 545 546 // Check for integer load 547 if (dst_first_rc == rc_int && src_first_rc == rc_stack) { 548 int offset = ra_->reg2offset(src_first); 549 if (masm && !is_memoryI(offset)) { 550 ra_->C->record_method_not_compilable("unable to handle large constant offsets"); 551 return 0; 552 } else { 553 if (src_second_rc != rc_bad && is_iRegLd_memhd(dst_first, dst_second, offset)) { 554 assert((src_first&1)==0 && src_first+1 == src_second, "pair of registers must be aligned/contiguous"); 555 if (masm) { 556 __ ldr_64(reg_to_register_object(Matcher::_regEncode[dst_first]), Address(SP, offset)); 557 #ifndef PRODUCT 558 } else if (!do_size) { 559 if (size != 0) st->print("\n\t"); 560 st->print(LDR_64 " R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(dst_first), offset); 561 #endif 562 } 563 return size + 4; 564 } else { 565 if (masm) { 566 __ ldr_32(reg_to_register_object(Matcher::_regEncode[dst_first]), Address(SP, offset)); 567 #ifndef PRODUCT 568 } else if (!do_size) { 569 if (size != 0) st->print("\n\t"); 570 st->print(LDR_32 " R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(dst_first), offset); 571 #endif 572 } 573 } 574 } 575 size += 4; 576 } 577 578 // Check for float reg-reg copy 579 if (src_first_rc == rc_float && dst_first_rc == rc_float) { 580 if (src_second_rc != rc_bad) { 581 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"); 582 if (masm) { 583 __ mov_double(reg_to_FloatRegister_object(Matcher::_regEncode[dst_first]), reg_to_FloatRegister_object(Matcher::_regEncode[src_first])); 584 #ifndef PRODUCT 585 } else if (!do_size) { 586 st->print(MOV_DOUBLE " R_%s, R_%s\t# spill", 587 Matcher::regName[dst_first], 588 Matcher::regName[src_first]); 589 #endif 590 } 591 return 4; 592 } 593 if (masm) { 594 __ mov_float(reg_to_FloatRegister_object(Matcher::_regEncode[dst_first]), reg_to_FloatRegister_object(Matcher::_regEncode[src_first])); 595 #ifndef PRODUCT 596 } else if (!do_size) { 597 st->print(MOV_FLOAT " R_%s, R_%s\t# spill", 598 Matcher::regName[dst_first], 599 Matcher::regName[src_first]); 600 #endif 601 } 602 size = 4; 603 } 604 605 // Check for float store 606 if (src_first_rc == rc_float && dst_first_rc == rc_stack) { 607 int offset = ra_->reg2offset(dst_first); 608 if (masm && !is_memoryfp(offset)) { 609 ra_->C->record_method_not_compilable("unable to handle large constant offsets"); 610 return 0; 611 } else { 612 // Further check for aligned-adjacent pair, so we can use a double store 613 if (src_second_rc != rc_bad) { 614 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"); 615 if (masm) { 616 __ str_double(reg_to_FloatRegister_object(Matcher::_regEncode[src_first]), Address(SP, offset)); 617 #ifndef PRODUCT 618 } else if (!do_size) { 619 if (size != 0) st->print("\n\t"); 620 st->print(STR_DOUBLE " R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(src_first),offset); 621 #endif 622 } 623 return size + 4; 624 } else { 625 if (masm) { 626 __ str_float(reg_to_FloatRegister_object(Matcher::_regEncode[src_first]), Address(SP, offset)); 627 #ifndef PRODUCT 628 } else if (!do_size) { 629 if (size != 0) st->print("\n\t"); 630 st->print(STR_FLOAT " R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(src_first),offset); 631 #endif 632 } 633 } 634 } 635 size += 4; 636 } 637 638 // Check for float load 639 if (dst_first_rc == rc_float && src_first_rc == rc_stack) { 640 int offset = ra_->reg2offset(src_first); 641 if (masm && !is_memoryfp(offset)) { 642 ra_->C->record_method_not_compilable("unable to handle large constant offsets"); 643 return 0; 644 } else { 645 // Further check for aligned-adjacent pair, so we can use a double store 646 if (src_second_rc != rc_bad) { 647 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"); 648 if (masm) { 649 __ ldr_double(reg_to_FloatRegister_object(Matcher::_regEncode[dst_first]), Address(SP, offset)); 650 #ifndef PRODUCT 651 } else if (!do_size) { 652 if (size != 0) st->print("\n\t"); 653 st->print(LDR_DOUBLE " R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(dst_first),offset); 654 #endif 655 } 656 return size + 4; 657 } else { 658 if (masm) { 659 __ ldr_float(reg_to_FloatRegister_object(Matcher::_regEncode[dst_first]), Address(SP, offset)); 660 #ifndef PRODUCT 661 } else if (!do_size) { 662 if (size != 0) st->print("\n\t"); 663 st->print(LDR_FLOAT " R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(dst_first),offset); 664 #endif 665 } 666 } 667 } 668 size += 4; 669 } 670 671 // check for int reg -> float reg move 672 if (src_first_rc == rc_int && dst_first_rc == rc_float) { 673 // Further check for aligned-adjacent pair, so we can use a single instruction 674 if (src_second_rc != rc_bad) { 675 assert((dst_first&1)==0 && dst_first+1 == dst_second, "pairs of registers must be aligned/contiguous"); 676 assert((src_first&1)==0 && src_first+1 == src_second, "pairs of registers must be aligned/contiguous"); 677 assert(src_second_rc == rc_int && dst_second_rc == rc_float, "unsupported"); 678 if (masm) { 679 __ 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])); 680 #ifndef PRODUCT 681 } else if (!do_size) { 682 if (size != 0) st->print("\n\t"); 683 st->print("FMDRR R_%s, R_%s, R_%s\t! spill",OptoReg::regname(dst_first), OptoReg::regname(src_first), OptoReg::regname(src_second)); 684 #endif 685 } 686 return size + 4; 687 } else { 688 if (masm) { 689 __ fmsr(reg_to_FloatRegister_object(Matcher::_regEncode[dst_first]), reg_to_register_object(Matcher::_regEncode[src_first])); 690 #ifndef PRODUCT 691 } else if (!do_size) { 692 if (size != 0) st->print("\n\t"); 693 st->print(FMSR " R_%s, R_%s\t! spill",OptoReg::regname(dst_first), OptoReg::regname(src_first)); 694 #endif 695 } 696 size += 4; 697 } 698 } 699 700 // check for float reg -> int reg move 701 if (src_first_rc == rc_float && dst_first_rc == rc_int) { 702 // Further check for aligned-adjacent pair, so we can use a single instruction 703 if (src_second_rc != rc_bad) { 704 assert((src_first&1)==0 && src_first+1 == src_second, "pairs of registers must be aligned/contiguous"); 705 assert((dst_first&1)==0 && dst_first+1 == dst_second, "pairs of registers must be aligned/contiguous"); 706 assert(src_second_rc == rc_float && dst_second_rc == rc_int, "unsupported"); 707 if (masm) { 708 __ 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])); 709 #ifndef PRODUCT 710 } else if (!do_size) { 711 if (size != 0) st->print("\n\t"); 712 st->print("FMRRD R_%s, R_%s, R_%s\t! spill",OptoReg::regname(dst_first), OptoReg::regname(dst_second), OptoReg::regname(src_first)); 713 #endif 714 } 715 return size + 4; 716 } else { 717 if (masm) { 718 __ fmrs(reg_to_register_object(Matcher::_regEncode[dst_first]), reg_to_FloatRegister_object(Matcher::_regEncode[src_first])); 719 #ifndef PRODUCT 720 } else if (!do_size) { 721 if (size != 0) st->print("\n\t"); 722 st->print(FMRS " R_%s, R_%s\t! spill",OptoReg::regname(dst_first), OptoReg::regname(src_first)); 723 #endif 724 } 725 size += 4; 726 } 727 } 728 729 // -------------------------------------------------------------------- 730 // Check for hi bits still needing moving. Only happens for misaligned 731 // arguments to native calls. 732 if (src_second == dst_second) 733 return size; // Self copy; no move 734 assert( src_second_rc != rc_bad && dst_second_rc != rc_bad, "src_second & dst_second cannot be Bad" ); 735 736 // Check for integer reg-reg copy. Hi bits are stuck up in the top 737 // 32-bits of a 64-bit register, but are needed in low bits of another 738 // register (else it's a hi-bits-to-hi-bits copy which should have 739 // happened already as part of a 64-bit move) 740 if (src_second_rc == rc_int && dst_second_rc == rc_int) { 741 if (masm) { 742 __ mov(reg_to_register_object(Matcher::_regEncode[dst_second]), reg_to_register_object(Matcher::_regEncode[src_second])); 743 #ifndef PRODUCT 744 } else if (!do_size) { 745 if (size != 0) st->print("\n\t"); 746 st->print("MOV R_%s, R_%s\t# spill high", 747 Matcher::regName[dst_second], 748 Matcher::regName[src_second]); 749 #endif 750 } 751 return size+4; 752 } 753 754 // Check for high word integer store 755 if (src_second_rc == rc_int && dst_second_rc == rc_stack) { 756 int offset = ra_->reg2offset(dst_second); 757 758 if (masm && !is_memoryP(offset)) { 759 ra_->C->record_method_not_compilable("unable to handle large constant offsets"); 760 return 0; 761 } else { 762 if (masm) { 763 __ str(reg_to_register_object(Matcher::_regEncode[src_second]), Address(SP, offset)); 764 #ifndef PRODUCT 765 } else if (!do_size) { 766 if (size != 0) st->print("\n\t"); 767 st->print("STR R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(src_second), offset); 768 #endif 769 } 770 } 771 return size + 4; 772 } 773 774 // Check for high word integer load 775 if (dst_second_rc == rc_int && src_second_rc == rc_stack) { 776 int offset = ra_->reg2offset(src_second); 777 if (masm && !is_memoryP(offset)) { 778 ra_->C->record_method_not_compilable("unable to handle large constant offsets"); 779 return 0; 780 } else { 781 if (masm) { 782 __ ldr(reg_to_register_object(Matcher::_regEncode[dst_second]), Address(SP, offset)); 783 #ifndef PRODUCT 784 } else if (!do_size) { 785 if (size != 0) st->print("\n\t"); 786 st->print("LDR R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(dst_second), offset); 787 #endif 788 } 789 } 790 return size + 4; 791 } 792 793 Unimplemented(); 794 return 0; // Mute compiler 795 } 796 797 #ifndef PRODUCT 798 void MachSpillCopyNode::format( PhaseRegAlloc *ra_, outputStream *st ) const { 799 implementation( nullptr, ra_, false, st ); 800 } 801 #endif 802 803 void MachSpillCopyNode::emit(C2_MacroAssembler *masm, PhaseRegAlloc *ra_) const { 804 implementation( masm, ra_, false, nullptr ); 805 } 806 807 uint MachSpillCopyNode::size(PhaseRegAlloc *ra_) const { 808 return implementation( nullptr, ra_, true, nullptr ); 809 } 810 811 //============================================================================= 812 #ifndef PRODUCT 813 void MachNopNode::format( PhaseRegAlloc *, outputStream *st ) const { 814 st->print("NOP \t# %d bytes pad for loops and calls", 4 * _count); 815 } 816 #endif 817 818 void MachNopNode::emit(C2_MacroAssembler *masm, PhaseRegAlloc * ) const { 819 for(int i = 0; i < _count; i += 1) { 820 __ nop(); 821 } 822 } 823 824 uint MachNopNode::size(PhaseRegAlloc *ra_) const { 825 return 4 * _count; 826 } 827 828 829 //============================================================================= 830 #ifndef PRODUCT 831 void BoxLockNode::format( PhaseRegAlloc *ra_, outputStream *st ) const { 832 int offset = ra_->reg2offset(in_RegMask(0).find_first_elem()); 833 int reg = ra_->get_reg_first(this); 834 st->print("ADD %s,R_SP+#%d",Matcher::regName[reg], offset); 835 } 836 #endif 837 838 void BoxLockNode::emit(C2_MacroAssembler *masm, PhaseRegAlloc *ra_) const { 839 int offset = ra_->reg2offset(in_RegMask(0).find_first_elem()); 840 int reg = ra_->get_encode(this); 841 Register dst = reg_to_register_object(reg); 842 843 if (is_aimm(offset)) { 844 __ add(dst, SP, offset); 845 } else { 846 __ mov_slow(dst, offset); 847 __ add(dst, SP, dst); 848 } 849 } 850 851 uint BoxLockNode::size(PhaseRegAlloc *ra_) const { 852 // BoxLockNode is not a MachNode, so we can't just call MachNode::size(ra_) 853 assert(ra_ == ra_->C->regalloc(), "sanity"); 854 return ra_->C->output()->scratch_emit_size(this); 855 } 856 857 //============================================================================= 858 #ifndef PRODUCT 859 #define R_RTEMP "R_R12" 860 void MachUEPNode::format( PhaseRegAlloc *ra_, outputStream *st ) const { 861 st->print_cr("\nUEP:"); 862 st->print_cr("\tLDR " R_RTEMP ",[R_R0 + oopDesc::klass_offset_in_bytes]\t! Inline cache check"); 863 st->print_cr("\tCMP " R_RTEMP ",R_R8" ); 864 st->print ("\tB.NE SharedRuntime::handle_ic_miss_stub"); 865 } 866 #endif 867 868 void MachUEPNode::emit(C2_MacroAssembler *masm, PhaseRegAlloc *ra_) const { 869 __ ic_check(InteriorEntryAlignment); 870 } 871 872 uint MachUEPNode::size(PhaseRegAlloc *ra_) const { 873 return MachNode::size(ra_); 874 } 875 876 877 //============================================================================= 878 879 // Emit exception handler code. 880 int HandlerImpl::emit_exception_handler(C2_MacroAssembler* masm) { 881 address base = __ start_a_stub(size_exception_handler()); 882 if (base == nullptr) { 883 ciEnv::current()->record_failure("CodeCache is full"); 884 return 0; // CodeBuffer::expand failed 885 } 886 887 int offset = __ offset(); 888 889 // OK to trash LR, because exception blob will kill it 890 __ jump(OptoRuntime::exception_blob()->entry_point(), relocInfo::runtime_call_type, LR_tmp); 891 892 assert(__ offset() - offset <= (int) size_exception_handler(), "overflow"); 893 894 __ end_a_stub(); 895 896 return offset; 897 } 898 899 int HandlerImpl::emit_deopt_handler(C2_MacroAssembler* masm) { 900 // Can't use any of the current frame's registers as we may have deopted 901 // at a poll and everything can be live. 902 address base = __ start_a_stub(size_deopt_handler()); 903 if (base == nullptr) { 904 ciEnv::current()->record_failure("CodeCache is full"); 905 return 0; // CodeBuffer::expand failed 906 } 907 908 int offset = __ offset(); 909 address deopt_pc = __ pc(); 910 911 __ sub(SP, SP, wordSize); // make room for saved PC 912 __ push(LR); // save LR that may be live when we get here 913 __ mov_relative_address(LR, deopt_pc); 914 __ str(LR, Address(SP, wordSize)); // save deopt PC 915 __ pop(LR); // restore LR 916 __ jump(SharedRuntime::deopt_blob()->unpack(), relocInfo::runtime_call_type, noreg); 917 918 assert(__ offset() - offset <= (int) size_deopt_handler(), "overflow"); 919 920 __ end_a_stub(); 921 return offset; 922 } 923 924 bool Matcher::match_rule_supported(int opcode) { 925 if (!has_match_rule(opcode)) 926 return false; 927 928 switch (opcode) { 929 case Op_PopCountI: 930 case Op_PopCountL: 931 if (!UsePopCountInstruction) 932 return false; 933 break; 934 case Op_LShiftCntV: 935 case Op_RShiftCntV: 936 case Op_AddVB: 937 case Op_AddVS: 938 case Op_AddVI: 939 case Op_AddVL: 940 case Op_SubVB: 941 case Op_SubVS: 942 case Op_SubVI: 943 case Op_SubVL: 944 case Op_MulVS: 945 case Op_MulVI: 946 case Op_LShiftVB: 947 case Op_LShiftVS: 948 case Op_LShiftVI: 949 case Op_LShiftVL: 950 case Op_RShiftVB: 951 case Op_RShiftVS: 952 case Op_RShiftVI: 953 case Op_RShiftVL: 954 case Op_URShiftVB: 955 case Op_URShiftVS: 956 case Op_URShiftVI: 957 case Op_URShiftVL: 958 case Op_AndV: 959 case Op_OrV: 960 case Op_XorV: 961 return VM_Version::has_simd(); 962 case Op_LoadVector: 963 case Op_StoreVector: 964 case Op_AddVF: 965 case Op_SubVF: 966 case Op_MulVF: 967 return VM_Version::has_vfp() || VM_Version::has_simd(); 968 case Op_AddVD: 969 case Op_SubVD: 970 case Op_MulVD: 971 case Op_DivVF: 972 case Op_DivVD: 973 return VM_Version::has_vfp(); 974 } 975 976 return true; // Per default match rules are supported. 977 } 978 979 bool Matcher::match_rule_supported_auto_vectorization(int opcode, int vlen, BasicType bt) { 980 return match_rule_supported_vector(opcode, vlen, bt); 981 } 982 983 bool Matcher::match_rule_supported_vector(int opcode, int vlen, BasicType bt) { 984 985 // TODO 986 // identify extra cases that we might want to provide match rules for 987 // e.g. Op_ vector nodes and other intrinsics while guarding with vlen 988 bool ret_value = match_rule_supported(opcode) && vector_size_supported(bt, vlen); 989 // Add rules here. 990 991 return ret_value; // Per default match rules are supported. 992 } 993 994 bool Matcher::match_rule_supported_vector_masked(int opcode, int vlen, BasicType bt) { 995 return false; 996 } 997 998 bool Matcher::vector_needs_partial_operations(Node* node, const TypeVect* vt) { 999 return false; 1000 } 1001 1002 bool Matcher::vector_rearrange_requires_load_shuffle(BasicType elem_bt, int vlen) { 1003 return false; 1004 } 1005 1006 const RegMask* Matcher::predicate_reg_mask(void) { 1007 return nullptr; 1008 } 1009 1010 // Vector calling convention not yet implemented. 1011 bool Matcher::supports_vector_calling_convention(void) { 1012 return false; 1013 } 1014 1015 OptoRegPair Matcher::vector_return_value(uint ideal_reg) { 1016 Unimplemented(); 1017 return OptoRegPair(0, 0); 1018 } 1019 1020 // Vector width in bytes 1021 int Matcher::vector_width_in_bytes(BasicType bt) { 1022 return MaxVectorSize; 1023 } 1024 1025 int Matcher::scalable_vector_reg_size(const BasicType bt) { 1026 return -1; 1027 } 1028 1029 // Vector ideal reg corresponding to specified size in bytes 1030 uint Matcher::vector_ideal_reg(int size) { 1031 assert(MaxVectorSize >= size, ""); 1032 switch(size) { 1033 case 8: return Op_VecD; 1034 case 16: return Op_VecX; 1035 } 1036 ShouldNotReachHere(); 1037 return 0; 1038 } 1039 1040 // Limits on vector size (number of elements) loaded into vector. 1041 int Matcher::max_vector_size(const BasicType bt) { 1042 assert(is_java_primitive(bt), "only primitive type vectors"); 1043 return vector_width_in_bytes(bt)/type2aelembytes(bt); 1044 } 1045 1046 int Matcher::min_vector_size(const BasicType bt) { 1047 assert(is_java_primitive(bt), "only primitive type vectors"); 1048 return 8/type2aelembytes(bt); 1049 } 1050 1051 int Matcher::max_vector_size_auto_vectorization(const BasicType bt) { 1052 return Matcher::max_vector_size(bt); 1053 } 1054 1055 // Is this branch offset short enough that a short branch can be used? 1056 // 1057 // NOTE: If the platform does not provide any short branch variants, then 1058 // this method should return false for offset 0. 1059 bool Matcher::is_short_branch_offset(int rule, int br_size, int offset) { 1060 // The passed offset is relative to address of the branch. 1061 // On ARM a branch displacement is calculated relative to address 1062 // of the branch + 8. 1063 // 1064 // offset -= 8; 1065 // return (Assembler::is_simm24(offset)); 1066 return false; 1067 } 1068 1069 MachOper* Matcher::pd_specialize_generic_vector_operand(MachOper* original_opnd, uint ideal_reg, bool is_temp) { 1070 ShouldNotReachHere(); // generic vector operands not supported 1071 return nullptr; 1072 } 1073 1074 bool Matcher::is_reg2reg_move(MachNode* m) { 1075 ShouldNotReachHere(); // generic vector operands not supported 1076 return false; 1077 } 1078 1079 bool Matcher::is_generic_vector(MachOper* opnd) { 1080 ShouldNotReachHere(); // generic vector operands not supported 1081 return false; 1082 } 1083 1084 // Should the matcher clone input 'm' of node 'n'? 1085 bool Matcher::pd_clone_node(Node* n, Node* m, Matcher::MStack& mstack) { 1086 if (is_vshift_con_pattern(n, m)) { // ShiftV src (ShiftCntV con) 1087 mstack.push(m, Visit); // m = ShiftCntV 1088 return true; 1089 } 1090 return false; 1091 } 1092 1093 // Should the Matcher clone shifts on addressing modes, expecting them 1094 // to be subsumed into complex addressing expressions or compute them 1095 // into registers? 1096 bool Matcher::pd_clone_address_expressions(AddPNode* m, Matcher::MStack& mstack, VectorSet& address_visited) { 1097 return clone_base_plus_offset_address(m, mstack, address_visited); 1098 } 1099 1100 // Return whether or not this register is ever used as an argument. This 1101 // function is used on startup to build the trampoline stubs in generateOptoStub. 1102 // Registers not mentioned will be killed by the VM call in the trampoline, and 1103 // arguments in those registers not be available to the callee. 1104 bool Matcher::can_be_java_arg( int reg ) { 1105 if (reg == R_R0_num || 1106 reg == R_R1_num || 1107 reg == R_R2_num || 1108 reg == R_R3_num) return true; 1109 1110 if (reg >= R_S0_num && 1111 reg <= R_S13_num) return true; 1112 return false; 1113 } 1114 1115 bool Matcher::is_spillable_arg( int reg ) { 1116 return can_be_java_arg(reg); 1117 } 1118 1119 uint Matcher::int_pressure_limit() 1120 { 1121 return (INTPRESSURE == -1) ? 12 : INTPRESSURE; 1122 } 1123 1124 uint Matcher::float_pressure_limit() 1125 { 1126 return (FLOATPRESSURE == -1) ? 30 : FLOATPRESSURE; 1127 } 1128 1129 bool Matcher::use_asm_for_ldiv_by_con( jlong divisor ) { 1130 return false; 1131 } 1132 1133 // Register for DIVI projection of divmodI 1134 RegMask Matcher::divI_proj_mask() { 1135 ShouldNotReachHere(); 1136 return RegMask(); 1137 } 1138 1139 // Register for MODI projection of divmodI 1140 RegMask Matcher::modI_proj_mask() { 1141 ShouldNotReachHere(); 1142 return RegMask(); 1143 } 1144 1145 // Register for DIVL projection of divmodL 1146 RegMask Matcher::divL_proj_mask() { 1147 ShouldNotReachHere(); 1148 return RegMask(); 1149 } 1150 1151 // Register for MODL projection of divmodL 1152 RegMask Matcher::modL_proj_mask() { 1153 ShouldNotReachHere(); 1154 return RegMask(); 1155 } 1156 1157 const RegMask Matcher::method_handle_invoke_SP_save_mask() { 1158 return FP_REGP_mask(); 1159 } 1160 1161 bool maybe_far_call(const CallNode *n) { 1162 return !MacroAssembler::_reachable_from_cache(n->as_Call()->entry_point()); 1163 } 1164 1165 bool maybe_far_call(const MachCallNode *n) { 1166 return !MacroAssembler::_reachable_from_cache(n->as_MachCall()->entry_point()); 1167 } 1168 1169 %} 1170 1171 //----------ENCODING BLOCK----------------------------------------------------- 1172 // This block specifies the encoding classes used by the compiler to output 1173 // byte streams. Encoding classes are parameterized macros used by 1174 // Machine Instruction Nodes in order to generate the bit encoding of the 1175 // instruction. Operands specify their base encoding interface with the 1176 // interface keyword. There are currently supported four interfaces, 1177 // REG_INTER, CONST_INTER, MEMORY_INTER, & COND_INTER. REG_INTER causes an 1178 // operand to generate a function which returns its register number when 1179 // queried. CONST_INTER causes an operand to generate a function which 1180 // returns the value of the constant when queried. MEMORY_INTER causes an 1181 // operand to generate four functions which return the Base Register, the 1182 // Index Register, the Scale Value, and the Offset Value of the operand when 1183 // queried. COND_INTER causes an operand to generate six functions which 1184 // return the encoding code (ie - encoding bits for the instruction) 1185 // associated with each basic boolean condition for a conditional instruction. 1186 // 1187 // Instructions specify two basic values for encoding. Again, a function 1188 // is available to check if the constant displacement is an oop. They use the 1189 // ins_encode keyword to specify their encoding classes (which must be 1190 // a sequence of enc_class names, and their parameters, specified in 1191 // the encoding block), and they use the 1192 // opcode keyword to specify, in order, their primary, secondary, and 1193 // tertiary opcode. Only the opcode sections which a particular instruction 1194 // needs for encoding need to be specified. 1195 encode %{ 1196 // Set instruction mark in MacroAssembler. This is used only in 1197 // instructions that emit bytes directly to the CodeBuffer wraped 1198 // in the MacroAssembler. Should go away once all "instruct" are 1199 // patched to emit bytes only using methods in MacroAssembler. 1200 enc_class SetInstMark %{ 1201 __ set_inst_mark(); 1202 %} 1203 1204 enc_class ClearInstMark %{ 1205 __ clear_inst_mark(); 1206 %} 1207 1208 enc_class call_epilog %{ 1209 // nothing 1210 %} 1211 1212 enc_class Java_To_Runtime (method meth) %{ 1213 // CALL directly to the runtime 1214 emit_call_reloc(masm, as_MachCall(), $meth, runtime_call_Relocation::spec()); 1215 %} 1216 1217 enc_class Java_Static_Call (method meth) %{ 1218 // CALL to fixup routine. Fixup routine uses ScopeDesc info to determine 1219 // who we intended to call. 1220 1221 if ( !_method) { 1222 emit_call_reloc(masm, as_MachCall(), $meth, runtime_call_Relocation::spec()); 1223 } else { 1224 int method_index = resolved_method_index(masm); 1225 RelocationHolder rspec = _optimized_virtual ? opt_virtual_call_Relocation::spec(method_index) 1226 : static_call_Relocation::spec(method_index); 1227 emit_call_reloc(masm, as_MachCall(), $meth, rspec); 1228 1229 // Emit stubs for static call. 1230 address stub = CompiledDirectCall::emit_to_interp_stub(masm); 1231 if (stub == nullptr) { 1232 ciEnv::current()->record_failure("CodeCache is full"); 1233 return; 1234 } 1235 } 1236 %} 1237 1238 enc_class save_last_PC %{ 1239 // preserve mark 1240 address mark = __ inst_mark(); 1241 DEBUG_ONLY(int off0 = __ offset()); 1242 int ret_addr_offset = as_MachCall()->ret_addr_offset(); 1243 __ adr(LR, mark + ret_addr_offset); 1244 __ str(LR, Address(Rthread, JavaThread::last_Java_pc_offset())); 1245 DEBUG_ONLY(int off1 = __ offset()); 1246 assert(off1 - off0 == 2 * Assembler::InstructionSize, "correct size prediction"); 1247 // restore mark 1248 __ set_inst_mark(mark); 1249 %} 1250 1251 enc_class preserve_SP %{ 1252 // preserve mark 1253 address mark = __ inst_mark(); 1254 DEBUG_ONLY(int off0 = __ offset()); 1255 // FP is preserved across all calls, even compiled calls. 1256 // Use it to preserve SP in places where the callee might change the SP. 1257 __ mov(Rmh_SP_save, SP); 1258 DEBUG_ONLY(int off1 = __ offset()); 1259 assert(off1 - off0 == 4, "correct size prediction"); 1260 // restore mark 1261 __ set_inst_mark(mark); 1262 %} 1263 1264 enc_class restore_SP %{ 1265 __ mov(SP, Rmh_SP_save); 1266 %} 1267 1268 enc_class Java_Dynamic_Call (method meth) %{ 1269 Register R8_ic_reg = reg_to_register_object(Matcher::inline_cache_reg_encode()); 1270 assert(R8_ic_reg == Ricklass, "should be"); 1271 __ set_inst_mark(); 1272 __ movw(R8_ic_reg, ((unsigned int)Universe::non_oop_word()) & 0xffff); 1273 __ movt(R8_ic_reg, ((unsigned int)Universe::non_oop_word()) >> 16); 1274 address virtual_call_oop_addr = __ inst_mark(); 1275 // CALL to fixup routine. Fixup routine uses ScopeDesc info to determine 1276 // who we intended to call. 1277 int method_index = resolved_method_index(masm); 1278 __ relocate(virtual_call_Relocation::spec(virtual_call_oop_addr, method_index)); 1279 emit_call_reloc(masm, as_MachCall(), $meth, RelocationHolder::none); 1280 %} 1281 1282 enc_class LdReplImmI(immI src, regD dst, iRegI tmp, int cnt, int wth) %{ 1283 // FIXME: load from constant table? 1284 // Load a constant replicated "count" times with width "width" 1285 int count = $cnt$$constant; 1286 int width = $wth$$constant; 1287 assert(count*width == 4, "sanity"); 1288 int val = $src$$constant; 1289 if (width < 4) { 1290 int bit_width = width * 8; 1291 val &= (((int)1) << bit_width) - 1; // mask off sign bits 1292 for (int i = 0; i < count - 1; i++) { 1293 val |= (val << bit_width); 1294 } 1295 } 1296 1297 if (val == -1) { 1298 __ mvn($tmp$$Register, 0); 1299 } else if (val == 0) { 1300 __ mov($tmp$$Register, 0); 1301 } else { 1302 __ movw($tmp$$Register, val & 0xffff); 1303 __ movt($tmp$$Register, (unsigned int)val >> 16); 1304 } 1305 __ fmdrr($dst$$FloatRegister, $tmp$$Register, $tmp$$Register); 1306 %} 1307 1308 enc_class LdReplImmF(immF src, regD dst, iRegI tmp) %{ 1309 // Replicate float con 2 times and pack into vector (8 bytes) in regD. 1310 float fval = $src$$constant; 1311 int val = *((int*)&fval); 1312 1313 if (val == -1) { 1314 __ mvn($tmp$$Register, 0); 1315 } else if (val == 0) { 1316 __ mov($tmp$$Register, 0); 1317 } else { 1318 __ movw($tmp$$Register, val & 0xffff); 1319 __ movt($tmp$$Register, (unsigned int)val >> 16); 1320 } 1321 __ fmdrr($dst$$FloatRegister, $tmp$$Register, $tmp$$Register); 1322 %} 1323 1324 enc_class enc_String_Compare(R0RegP str1, R1RegP str2, R2RegI cnt1, R3RegI cnt2, iRegI result, iRegI tmp1, iRegI tmp2) %{ 1325 Label Ldone, Lloop; 1326 1327 Register str1_reg = $str1$$Register; 1328 Register str2_reg = $str2$$Register; 1329 Register cnt1_reg = $cnt1$$Register; // int 1330 Register cnt2_reg = $cnt2$$Register; // int 1331 Register tmp1_reg = $tmp1$$Register; 1332 Register tmp2_reg = $tmp2$$Register; 1333 Register result_reg = $result$$Register; 1334 1335 assert_different_registers(str1_reg, str2_reg, cnt1_reg, cnt2_reg, tmp1_reg, tmp2_reg); 1336 1337 // Compute the minimum of the string lengths(str1_reg) and the 1338 // difference of the string lengths (stack) 1339 1340 // See if the lengths are different, and calculate min in str1_reg. 1341 // Stash diff in tmp2 in case we need it for a tie-breaker. 1342 __ subs_32(tmp2_reg, cnt1_reg, cnt2_reg); 1343 __ mov(cnt1_reg, AsmOperand(cnt1_reg, lsl, exact_log2(sizeof(jchar)))); // scale the limit 1344 __ mov(cnt1_reg, AsmOperand(cnt2_reg, lsl, exact_log2(sizeof(jchar))), pl); // scale the limit 1345 1346 // reallocate cnt1_reg, cnt2_reg, result_reg 1347 // Note: limit_reg holds the string length pre-scaled by 2 1348 Register limit_reg = cnt1_reg; 1349 Register chr2_reg = cnt2_reg; 1350 Register chr1_reg = tmp1_reg; 1351 // str{12} are the base pointers 1352 1353 // Is the minimum length zero? 1354 __ cmp_32(limit_reg, 0); 1355 if (result_reg != tmp2_reg) { 1356 __ mov(result_reg, tmp2_reg, eq); 1357 } 1358 __ b(Ldone, eq); 1359 1360 // Load first characters 1361 __ ldrh(chr1_reg, Address(str1_reg, 0)); 1362 __ ldrh(chr2_reg, Address(str2_reg, 0)); 1363 1364 // Compare first characters 1365 __ subs(chr1_reg, chr1_reg, chr2_reg); 1366 if (result_reg != chr1_reg) { 1367 __ mov(result_reg, chr1_reg, ne); 1368 } 1369 __ b(Ldone, ne); 1370 1371 { 1372 // Check after comparing first character to see if strings are equivalent 1373 // Check if the strings start at same location 1374 __ cmp(str1_reg, str2_reg); 1375 // Check if the length difference is zero 1376 __ cond_cmp(tmp2_reg, 0, eq); 1377 __ mov(result_reg, 0, eq); // result is zero 1378 __ b(Ldone, eq); 1379 // Strings might not be equal 1380 } 1381 1382 __ subs(chr1_reg, limit_reg, 1 * sizeof(jchar)); 1383 if (result_reg != tmp2_reg) { 1384 __ mov(result_reg, tmp2_reg, eq); 1385 } 1386 __ b(Ldone, eq); 1387 1388 // Shift str1_reg and str2_reg to the end of the arrays, negate limit 1389 __ add(str1_reg, str1_reg, limit_reg); 1390 __ add(str2_reg, str2_reg, limit_reg); 1391 __ neg(limit_reg, chr1_reg); // limit = -(limit-2) 1392 1393 // Compare the rest of the characters 1394 __ bind(Lloop); 1395 __ ldrh(chr1_reg, Address(str1_reg, limit_reg)); 1396 __ ldrh(chr2_reg, Address(str2_reg, limit_reg)); 1397 __ subs(chr1_reg, chr1_reg, chr2_reg); 1398 if (result_reg != chr1_reg) { 1399 __ mov(result_reg, chr1_reg, ne); 1400 } 1401 __ b(Ldone, ne); 1402 1403 __ adds(limit_reg, limit_reg, sizeof(jchar)); 1404 __ b(Lloop, ne); 1405 1406 // If strings are equal up to min length, return the length difference. 1407 if (result_reg != tmp2_reg) { 1408 __ mov(result_reg, tmp2_reg); 1409 } 1410 1411 // Otherwise, return the difference between the first mismatched chars. 1412 __ bind(Ldone); 1413 %} 1414 1415 enc_class enc_String_Equals(R0RegP str1, R1RegP str2, R2RegI cnt, iRegI result, iRegI tmp1, iRegI tmp2) %{ 1416 Label Lchar, Lchar_loop, Ldone, Lequal; 1417 1418 Register str1_reg = $str1$$Register; 1419 Register str2_reg = $str2$$Register; 1420 Register cnt_reg = $cnt$$Register; // int 1421 Register tmp1_reg = $tmp1$$Register; 1422 Register tmp2_reg = $tmp2$$Register; 1423 Register result_reg = $result$$Register; 1424 1425 assert_different_registers(str1_reg, str2_reg, cnt_reg, tmp1_reg, tmp2_reg, result_reg); 1426 1427 __ cmp(str1_reg, str2_reg); //same char[] ? 1428 __ b(Lequal, eq); 1429 1430 __ cbz_32(cnt_reg, Lequal); // count == 0 1431 1432 //rename registers 1433 Register limit_reg = cnt_reg; 1434 Register chr1_reg = tmp1_reg; 1435 Register chr2_reg = tmp2_reg; 1436 1437 __ logical_shift_left(limit_reg, limit_reg, exact_log2(sizeof(jchar))); 1438 1439 //check for alignment and position the pointers to the ends 1440 __ orr(chr1_reg, str1_reg, str2_reg); 1441 __ tst(chr1_reg, 0x3); 1442 1443 // notZero means at least one not 4-byte aligned. 1444 // We could optimize the case when both arrays are not aligned 1445 // but it is not frequent case and it requires additional checks. 1446 __ b(Lchar, ne); 1447 1448 // Compare char[] arrays aligned to 4 bytes. 1449 __ char_arrays_equals(str1_reg, str2_reg, limit_reg, result_reg, 1450 chr1_reg, chr2_reg, Ldone); 1451 1452 __ b(Lequal); // equal 1453 1454 // char by char compare 1455 __ bind(Lchar); 1456 __ mov(result_reg, 0); 1457 __ add(str1_reg, limit_reg, str1_reg); 1458 __ add(str2_reg, limit_reg, str2_reg); 1459 __ neg(limit_reg, limit_reg); //negate count 1460 1461 // Lchar_loop 1462 __ bind(Lchar_loop); 1463 __ ldrh(chr1_reg, Address(str1_reg, limit_reg)); 1464 __ ldrh(chr2_reg, Address(str2_reg, limit_reg)); 1465 __ cmp(chr1_reg, chr2_reg); 1466 __ b(Ldone, ne); 1467 __ adds(limit_reg, limit_reg, sizeof(jchar)); 1468 __ b(Lchar_loop, ne); 1469 1470 __ bind(Lequal); 1471 __ mov(result_reg, 1); //equal 1472 1473 __ bind(Ldone); 1474 %} 1475 1476 enc_class enc_Array_Equals(R0RegP ary1, R1RegP ary2, iRegI tmp1, iRegI tmp2, iRegI tmp3, iRegI result) %{ 1477 Label Ldone, Lloop, Lequal; 1478 1479 Register ary1_reg = $ary1$$Register; 1480 Register ary2_reg = $ary2$$Register; 1481 Register tmp1_reg = $tmp1$$Register; 1482 Register tmp2_reg = $tmp2$$Register; 1483 Register tmp3_reg = $tmp3$$Register; 1484 Register result_reg = $result$$Register; 1485 1486 assert_different_registers(ary1_reg, ary2_reg, tmp1_reg, tmp2_reg, tmp3_reg, result_reg); 1487 1488 int length_offset = arrayOopDesc::length_offset_in_bytes(); 1489 int base_offset = arrayOopDesc::base_offset_in_bytes(T_CHAR); 1490 1491 // return true if the same array 1492 __ teq(ary1_reg, ary2_reg); 1493 __ mov(result_reg, 1, eq); 1494 __ b(Ldone, eq); // equal 1495 1496 __ tst(ary1_reg, ary1_reg); 1497 __ mov(result_reg, 0, eq); 1498 __ b(Ldone, eq); // not equal 1499 1500 __ tst(ary2_reg, ary2_reg); 1501 __ mov(result_reg, 0, eq); 1502 __ b(Ldone, eq); // not equal 1503 1504 //load the lengths of arrays 1505 __ ldr_s32(tmp1_reg, Address(ary1_reg, length_offset)); // int 1506 __ ldr_s32(tmp2_reg, Address(ary2_reg, length_offset)); // int 1507 1508 // return false if the two arrays are not equal length 1509 __ teq_32(tmp1_reg, tmp2_reg); 1510 __ mov(result_reg, 0, ne); 1511 __ b(Ldone, ne); // not equal 1512 1513 __ tst(tmp1_reg, tmp1_reg); 1514 __ mov(result_reg, 1, eq); 1515 __ b(Ldone, eq); // zero-length arrays are equal 1516 1517 // load array addresses 1518 __ add(ary1_reg, ary1_reg, base_offset); 1519 __ add(ary2_reg, ary2_reg, base_offset); 1520 1521 // renaming registers 1522 Register chr1_reg = tmp3_reg; // for characters in ary1 1523 Register chr2_reg = tmp2_reg; // for characters in ary2 1524 Register limit_reg = tmp1_reg; // length 1525 1526 // set byte count 1527 __ logical_shift_left_32(limit_reg, limit_reg, exact_log2(sizeof(jchar))); 1528 1529 // Compare char[] arrays aligned to 4 bytes. 1530 __ char_arrays_equals(ary1_reg, ary2_reg, limit_reg, result_reg, 1531 chr1_reg, chr2_reg, Ldone); 1532 __ bind(Lequal); 1533 __ mov(result_reg, 1); //equal 1534 1535 __ bind(Ldone); 1536 %} 1537 %} 1538 1539 //----------FRAME-------------------------------------------------------------- 1540 // Definition of frame structure and management information. 1541 // 1542 // S T A C K L A Y O U T Allocators stack-slot number 1543 // | (to get allocators register number 1544 // G Owned by | | v add VMRegImpl::stack0) 1545 // r CALLER | | 1546 // o | +--------+ pad to even-align allocators stack-slot 1547 // w V | pad0 | numbers; owned by CALLER 1548 // t -----------+--------+----> Matcher::_in_arg_limit, unaligned 1549 // h ^ | in | 5 1550 // | | args | 4 Holes in incoming args owned by SELF 1551 // | | | | 3 1552 // | | +--------+ 1553 // V | | old out| Empty on Intel, window on Sparc 1554 // | old |preserve| Must be even aligned. 1555 // | SP-+--------+----> Matcher::_old_SP, 8 (or 16 in LP64)-byte aligned 1556 // | | in | 3 area for Intel ret address 1557 // Owned by |preserve| Empty on Sparc. 1558 // SELF +--------+ 1559 // | | pad2 | 2 pad to align old SP 1560 // | +--------+ 1 1561 // | | locks | 0 1562 // | +--------+----> VMRegImpl::stack0, 8 (or 16 in LP64)-byte aligned 1563 // | | pad1 | 11 pad to align new SP 1564 // | +--------+ 1565 // | | | 10 1566 // | | spills | 9 spills 1567 // V | | 8 (pad0 slot for callee) 1568 // -----------+--------+----> Matcher::_out_arg_limit, unaligned 1569 // ^ | out | 7 1570 // | | args | 6 Holes in outgoing args owned by CALLEE 1571 // Owned by +--------+ 1572 // CALLEE | new out| 6 Empty on Intel, window on Sparc 1573 // | new |preserve| Must be even-aligned. 1574 // | SP-+--------+----> Matcher::_new_SP, even aligned 1575 // | | | 1576 // 1577 // Note 1: Only region 8-11 is determined by the allocator. Region 0-5 is 1578 // known from SELF's arguments and the Java calling convention. 1579 // Region 6-7 is determined per call site. 1580 // Note 2: If the calling convention leaves holes in the incoming argument 1581 // area, those holes are owned by SELF. Holes in the outgoing area 1582 // are owned by the CALLEE. Holes should not be necessary in the 1583 // incoming area, as the Java calling convention is completely under 1584 // the control of the AD file. Doubles can be sorted and packed to 1585 // avoid holes. Holes in the outgoing arguments may be necessary for 1586 // varargs C calling conventions. 1587 // Note 3: Region 0-3 is even aligned, with pad2 as needed. Region 3-5 is 1588 // even aligned with pad0 as needed. 1589 // Region 6 is even aligned. Region 6-7 is NOT even aligned; 1590 // region 6-11 is even aligned; it may be padded out more so that 1591 // the region from SP to FP meets the minimum stack alignment. 1592 1593 frame %{ 1594 // These two registers define part of the calling convention 1595 // between compiled code and the interpreter. 1596 inline_cache_reg(R_Ricklass); // Inline Cache Register or Method* for I2C 1597 1598 // Optional: name the operand used by cisc-spilling to access [stack_pointer + offset] 1599 cisc_spilling_operand_name(indOffset); 1600 1601 // Number of stack slots consumed by a Monitor enter 1602 sync_stack_slots(1 * VMRegImpl::slots_per_word); 1603 1604 // Compiled code's Frame Pointer 1605 frame_pointer(R_R13); 1606 1607 // Stack alignment requirement 1608 stack_alignment(StackAlignmentInBytes); 1609 // LP64: Alignment size in bytes (128-bit -> 16 bytes) 1610 // !LP64: Alignment size in bytes (64-bit -> 8 bytes) 1611 1612 // Number of outgoing stack slots killed above the out_preserve_stack_slots 1613 // for calls to C. Supports the var-args backing area for register parms. 1614 // ADLC doesn't support parsing expressions, so I folded the math by hand. 1615 varargs_C_out_slots_killed( 0); 1616 1617 // The after-PROLOG location of the return address. Location of 1618 // return address specifies a type (REG or STACK) and a number 1619 // representing the register number (i.e. - use a register name) or 1620 // stack slot. 1621 // Ret Addr is on stack in slot 0 if no locks or verification or alignment. 1622 // Otherwise, it is above the locks and verification slot and alignment word 1623 return_addr(STACK - 1*VMRegImpl::slots_per_word + 1624 align_up((Compile::current()->in_preserve_stack_slots() + 1625 Compile::current()->fixed_slots()), 1626 stack_alignment_in_slots())); 1627 1628 // Location of compiled Java return values. Same as C 1629 return_value %{ 1630 return c2::return_value(ideal_reg); 1631 %} 1632 1633 %} 1634 1635 //----------ATTRIBUTES--------------------------------------------------------- 1636 //----------Instruction Attributes--------------------------------------------- 1637 ins_attrib ins_cost(DEFAULT_COST); // Required cost attribute 1638 ins_attrib ins_size(32); // Required size attribute (in bits) 1639 ins_attrib ins_short_branch(0); // Required flag: is this instruction a 1640 // non-matching short branch variant of some 1641 // long branch? 1642 1643 //----------OPERANDS----------------------------------------------------------- 1644 // Operand definitions must precede instruction definitions for correct parsing 1645 // in the ADLC because operands constitute user defined types which are used in 1646 // instruction definitions. 1647 1648 //----------Simple Operands---------------------------------------------------- 1649 // Immediate Operands 1650 // Integer Immediate: 32-bit 1651 operand immI() %{ 1652 match(ConI); 1653 1654 op_cost(0); 1655 // formats are generated automatically for constants and base registers 1656 format %{ %} 1657 interface(CONST_INTER); 1658 %} 1659 1660 // Integer Immediate: 8-bit unsigned - for VMOV 1661 operand immU8() %{ 1662 predicate(0 <= n->get_int() && (n->get_int() <= 255)); 1663 match(ConI); 1664 op_cost(0); 1665 1666 format %{ %} 1667 interface(CONST_INTER); 1668 %} 1669 1670 // Integer Immediate: 16-bit 1671 operand immI16() %{ 1672 predicate((n->get_int() >> 16) == 0 && VM_Version::supports_movw()); 1673 match(ConI); 1674 op_cost(0); 1675 1676 format %{ %} 1677 interface(CONST_INTER); 1678 %} 1679 1680 // Integer Immediate: offset for half and double word loads and stores 1681 operand immIHD() %{ 1682 predicate(is_memoryHD(n->get_int())); 1683 match(ConI); 1684 op_cost(0); 1685 format %{ %} 1686 interface(CONST_INTER); 1687 %} 1688 1689 // Integer Immediate: offset for fp loads and stores 1690 operand immIFP() %{ 1691 predicate(is_memoryfp(n->get_int()) && ((n->get_int() & 3) == 0)); 1692 match(ConI); 1693 op_cost(0); 1694 1695 format %{ %} 1696 interface(CONST_INTER); 1697 %} 1698 1699 // Valid scale values for addressing modes and shifts 1700 operand immU5() %{ 1701 predicate(0 <= n->get_int() && (n->get_int() <= 31)); 1702 match(ConI); 1703 op_cost(0); 1704 1705 format %{ %} 1706 interface(CONST_INTER); 1707 %} 1708 1709 // Integer Immediate: 6-bit 1710 operand immU6Big() %{ 1711 predicate(n->get_int() >= 32 && n->get_int() <= 63); 1712 match(ConI); 1713 op_cost(0); 1714 format %{ %} 1715 interface(CONST_INTER); 1716 %} 1717 1718 // Integer Immediate: 0-bit 1719 operand immI0() %{ 1720 predicate(n->get_int() == 0); 1721 match(ConI); 1722 op_cost(0); 1723 1724 format %{ %} 1725 interface(CONST_INTER); 1726 %} 1727 1728 // Int Immediate non-negative 1729 operand immU31() 1730 %{ 1731 predicate(n->get_int() >= 0); 1732 match(ConI); 1733 1734 op_cost(0); 1735 format %{ %} 1736 interface(CONST_INTER); 1737 %} 1738 1739 // Integer Immediate: the values 32-63 1740 operand immI_32_63() %{ 1741 predicate(n->get_int() >= 32 && n->get_int() <= 63); 1742 match(ConI); 1743 op_cost(0); 1744 1745 format %{ %} 1746 interface(CONST_INTER); 1747 %} 1748 1749 // Immediates for special shifts (sign extend) 1750 1751 // Integer Immediate: the value 16 1752 operand immI_16() %{ 1753 predicate(n->get_int() == 16); 1754 match(ConI); 1755 op_cost(0); 1756 1757 format %{ %} 1758 interface(CONST_INTER); 1759 %} 1760 1761 // Integer Immediate: the value 24 1762 operand immI_24() %{ 1763 predicate(n->get_int() == 24); 1764 match(ConI); 1765 op_cost(0); 1766 1767 format %{ %} 1768 interface(CONST_INTER); 1769 %} 1770 1771 // Integer Immediate: the value 255 1772 operand immI_255() %{ 1773 predicate( n->get_int() == 255 ); 1774 match(ConI); 1775 op_cost(0); 1776 1777 format %{ %} 1778 interface(CONST_INTER); 1779 %} 1780 1781 // Integer Immediate: the value 65535 1782 operand immI_65535() %{ 1783 predicate(n->get_int() == 65535); 1784 match(ConI); 1785 op_cost(0); 1786 1787 format %{ %} 1788 interface(CONST_INTER); 1789 %} 1790 1791 // Integer Immediates for arithmetic instructions 1792 1793 operand aimmI() %{ 1794 predicate(is_aimm(n->get_int())); 1795 match(ConI); 1796 op_cost(0); 1797 1798 format %{ %} 1799 interface(CONST_INTER); 1800 %} 1801 1802 operand aimmIneg() %{ 1803 predicate(is_aimm(-n->get_int())); 1804 match(ConI); 1805 op_cost(0); 1806 1807 format %{ %} 1808 interface(CONST_INTER); 1809 %} 1810 1811 operand aimmU31() %{ 1812 predicate((0 <= n->get_int()) && is_aimm(n->get_int())); 1813 match(ConI); 1814 op_cost(0); 1815 1816 format %{ %} 1817 interface(CONST_INTER); 1818 %} 1819 1820 // Integer Immediates for logical instructions 1821 1822 operand limmI() %{ 1823 predicate(is_limmI(n->get_int())); 1824 match(ConI); 1825 op_cost(0); 1826 1827 format %{ %} 1828 interface(CONST_INTER); 1829 %} 1830 1831 operand limmIlow8() %{ 1832 predicate(is_limmI_low(n->get_int(), 8)); 1833 match(ConI); 1834 op_cost(0); 1835 1836 format %{ %} 1837 interface(CONST_INTER); 1838 %} 1839 1840 operand limmU31() %{ 1841 predicate(0 <= n->get_int() && is_limmI(n->get_int())); 1842 match(ConI); 1843 op_cost(0); 1844 1845 format %{ %} 1846 interface(CONST_INTER); 1847 %} 1848 1849 operand limmIn() %{ 1850 predicate(is_limmI(~n->get_int())); 1851 match(ConI); 1852 op_cost(0); 1853 1854 format %{ %} 1855 interface(CONST_INTER); 1856 %} 1857 1858 // Pointer Immediate: 32 or 64-bit 1859 operand immP() %{ 1860 match(ConP); 1861 1862 op_cost(5); 1863 // formats are generated automatically for constants and base registers 1864 format %{ %} 1865 interface(CONST_INTER); 1866 %} 1867 1868 operand immP0() %{ 1869 predicate(n->get_ptr() == 0); 1870 match(ConP); 1871 op_cost(0); 1872 1873 format %{ %} 1874 interface(CONST_INTER); 1875 %} 1876 1877 operand immL() %{ 1878 match(ConL); 1879 op_cost(40); 1880 // formats are generated automatically for constants and base registers 1881 format %{ %} 1882 interface(CONST_INTER); 1883 %} 1884 1885 operand immL0() %{ 1886 predicate(n->get_long() == 0L); 1887 match(ConL); 1888 op_cost(0); 1889 // formats are generated automatically for constants and base registers 1890 format %{ %} 1891 interface(CONST_INTER); 1892 %} 1893 1894 // Long Immediate: 16-bit 1895 operand immL16() %{ 1896 predicate(n->get_long() >= 0 && n->get_long() < (1<<16) && VM_Version::supports_movw()); 1897 match(ConL); 1898 op_cost(0); 1899 1900 format %{ %} 1901 interface(CONST_INTER); 1902 %} 1903 1904 // Long Immediate: low 32-bit mask 1905 operand immL_32bits() %{ 1906 predicate(n->get_long() == 0xFFFFFFFFL); 1907 match(ConL); 1908 op_cost(0); 1909 1910 format %{ %} 1911 interface(CONST_INTER); 1912 %} 1913 1914 // Double Immediate 1915 operand immD() %{ 1916 match(ConD); 1917 1918 op_cost(40); 1919 format %{ %} 1920 interface(CONST_INTER); 1921 %} 1922 1923 // Double Immediate: +0.0d. 1924 operand immD0() %{ 1925 predicate(jlong_cast(n->getd()) == 0); 1926 1927 match(ConD); 1928 op_cost(0); 1929 format %{ %} 1930 interface(CONST_INTER); 1931 %} 1932 1933 operand imm8D() %{ 1934 predicate(Assembler::double_num(n->getd()).can_be_imm8()); 1935 match(ConD); 1936 1937 op_cost(0); 1938 format %{ %} 1939 interface(CONST_INTER); 1940 %} 1941 1942 // Float Immediate 1943 operand immF() %{ 1944 match(ConF); 1945 1946 op_cost(20); 1947 format %{ %} 1948 interface(CONST_INTER); 1949 %} 1950 1951 // Float Immediate: +0.0f 1952 operand immF0() %{ 1953 predicate(jint_cast(n->getf()) == 0); 1954 match(ConF); 1955 1956 op_cost(0); 1957 format %{ %} 1958 interface(CONST_INTER); 1959 %} 1960 1961 // Float Immediate: encoded as 8 bits 1962 operand imm8F() %{ 1963 predicate(Assembler::float_num(n->getf()).can_be_imm8()); 1964 match(ConF); 1965 1966 op_cost(0); 1967 format %{ %} 1968 interface(CONST_INTER); 1969 %} 1970 1971 // Integer Register Operands 1972 // Integer Register 1973 operand iRegI() %{ 1974 constraint(ALLOC_IN_RC(int_reg)); 1975 match(RegI); 1976 match(R0RegI); 1977 match(R1RegI); 1978 match(R2RegI); 1979 match(R3RegI); 1980 match(R12RegI); 1981 1982 format %{ %} 1983 interface(REG_INTER); 1984 %} 1985 1986 // Pointer Register 1987 operand iRegP() %{ 1988 constraint(ALLOC_IN_RC(ptr_reg)); 1989 match(RegP); 1990 match(R0RegP); 1991 match(R1RegP); 1992 match(R2RegP); 1993 match(RExceptionRegP); 1994 match(R8RegP); 1995 match(R9RegP); 1996 match(RthreadRegP); // FIXME: move to sp_ptr_RegP? 1997 match(R12RegP); 1998 match(LRRegP); 1999 2000 match(sp_ptr_RegP); 2001 match(store_ptr_RegP); 2002 2003 format %{ %} 2004 interface(REG_INTER); 2005 %} 2006 2007 // GPRs + Rthread + SP 2008 operand sp_ptr_RegP() %{ 2009 constraint(ALLOC_IN_RC(sp_ptr_reg)); 2010 match(RegP); 2011 match(iRegP); 2012 match(SPRegP); // FIXME: check cost 2013 2014 format %{ %} 2015 interface(REG_INTER); 2016 %} 2017 2018 2019 operand R0RegP() %{ 2020 constraint(ALLOC_IN_RC(R0_regP)); 2021 match(iRegP); 2022 2023 format %{ %} 2024 interface(REG_INTER); 2025 %} 2026 2027 operand R1RegP() %{ 2028 constraint(ALLOC_IN_RC(R1_regP)); 2029 match(iRegP); 2030 2031 format %{ %} 2032 interface(REG_INTER); 2033 %} 2034 2035 operand R8RegP() %{ 2036 constraint(ALLOC_IN_RC(R8_regP)); 2037 match(iRegP); 2038 2039 format %{ %} 2040 interface(REG_INTER); 2041 %} 2042 2043 operand R9RegP() %{ 2044 constraint(ALLOC_IN_RC(R9_regP)); 2045 match(iRegP); 2046 2047 format %{ %} 2048 interface(REG_INTER); 2049 %} 2050 2051 operand R12RegP() %{ 2052 constraint(ALLOC_IN_RC(R12_regP)); 2053 match(iRegP); 2054 2055 format %{ %} 2056 interface(REG_INTER); 2057 %} 2058 2059 operand R2RegP() %{ 2060 constraint(ALLOC_IN_RC(R2_regP)); 2061 match(iRegP); 2062 2063 format %{ %} 2064 interface(REG_INTER); 2065 %} 2066 2067 operand RExceptionRegP() %{ 2068 constraint(ALLOC_IN_RC(Rexception_regP)); 2069 match(iRegP); 2070 2071 format %{ %} 2072 interface(REG_INTER); 2073 %} 2074 2075 operand RthreadRegP() %{ 2076 constraint(ALLOC_IN_RC(Rthread_regP)); 2077 match(iRegP); 2078 2079 format %{ %} 2080 interface(REG_INTER); 2081 %} 2082 2083 operand IPRegP() %{ 2084 constraint(ALLOC_IN_RC(IP_regP)); 2085 match(iRegP); 2086 2087 format %{ %} 2088 interface(REG_INTER); 2089 %} 2090 2091 operand SPRegP() %{ 2092 constraint(ALLOC_IN_RC(SP_regP)); 2093 match(iRegP); 2094 2095 format %{ %} 2096 interface(REG_INTER); 2097 %} 2098 2099 operand LRRegP() %{ 2100 constraint(ALLOC_IN_RC(LR_regP)); 2101 match(iRegP); 2102 2103 format %{ %} 2104 interface(REG_INTER); 2105 %} 2106 2107 operand R0RegI() %{ 2108 constraint(ALLOC_IN_RC(R0_regI)); 2109 match(iRegI); 2110 2111 format %{ %} 2112 interface(REG_INTER); 2113 %} 2114 2115 operand R1RegI() %{ 2116 constraint(ALLOC_IN_RC(R1_regI)); 2117 match(iRegI); 2118 2119 format %{ %} 2120 interface(REG_INTER); 2121 %} 2122 2123 operand R2RegI() %{ 2124 constraint(ALLOC_IN_RC(R2_regI)); 2125 match(iRegI); 2126 2127 format %{ %} 2128 interface(REG_INTER); 2129 %} 2130 2131 operand R3RegI() %{ 2132 constraint(ALLOC_IN_RC(R3_regI)); 2133 match(iRegI); 2134 2135 format %{ %} 2136 interface(REG_INTER); 2137 %} 2138 2139 operand R12RegI() %{ 2140 constraint(ALLOC_IN_RC(R12_regI)); 2141 match(iRegI); 2142 2143 format %{ %} 2144 interface(REG_INTER); 2145 %} 2146 2147 // Long Register 2148 operand iRegL() %{ 2149 constraint(ALLOC_IN_RC(long_reg)); 2150 match(RegL); 2151 match(R0R1RegL); 2152 match(R2R3RegL); 2153 //match(iRegLex); 2154 2155 format %{ %} 2156 interface(REG_INTER); 2157 %} 2158 2159 operand iRegLd() %{ 2160 constraint(ALLOC_IN_RC(long_reg_align)); 2161 match(iRegL); // FIXME: allows unaligned R11/R12? 2162 2163 format %{ %} 2164 interface(REG_INTER); 2165 %} 2166 2167 // first long arg, or return value 2168 operand R0R1RegL() %{ 2169 constraint(ALLOC_IN_RC(R0R1_regL)); 2170 match(iRegL); 2171 2172 format %{ %} 2173 interface(REG_INTER); 2174 %} 2175 2176 operand R2R3RegL() %{ 2177 constraint(ALLOC_IN_RC(R2R3_regL)); 2178 match(iRegL); 2179 2180 format %{ %} 2181 interface(REG_INTER); 2182 %} 2183 2184 // Condition Code Flag Register 2185 operand flagsReg() %{ 2186 constraint(ALLOC_IN_RC(int_flags)); 2187 match(RegFlags); 2188 2189 format %{ "apsr" %} 2190 interface(REG_INTER); 2191 %} 2192 2193 // Result of compare to 0 (TST) 2194 operand flagsReg_EQNELTGE() %{ 2195 constraint(ALLOC_IN_RC(int_flags)); 2196 match(RegFlags); 2197 2198 format %{ "apsr_EQNELTGE" %} 2199 interface(REG_INTER); 2200 %} 2201 2202 // Condition Code Register, unsigned comparisons. 2203 operand flagsRegU() %{ 2204 constraint(ALLOC_IN_RC(int_flags)); 2205 match(RegFlags); 2206 #ifdef TODO 2207 match(RegFlagsP); 2208 #endif 2209 2210 format %{ "apsr_U" %} 2211 interface(REG_INTER); 2212 %} 2213 2214 // Condition Code Register, pointer comparisons. 2215 operand flagsRegP() %{ 2216 constraint(ALLOC_IN_RC(int_flags)); 2217 match(RegFlags); 2218 2219 format %{ "apsr_P" %} 2220 interface(REG_INTER); 2221 %} 2222 2223 // Condition Code Register, long comparisons. 2224 operand flagsRegL_LTGE() %{ 2225 constraint(ALLOC_IN_RC(int_flags)); 2226 match(RegFlags); 2227 2228 format %{ "apsr_L_LTGE" %} 2229 interface(REG_INTER); 2230 %} 2231 2232 operand flagsRegL_EQNE() %{ 2233 constraint(ALLOC_IN_RC(int_flags)); 2234 match(RegFlags); 2235 2236 format %{ "apsr_L_EQNE" %} 2237 interface(REG_INTER); 2238 %} 2239 2240 operand flagsRegL_LEGT() %{ 2241 constraint(ALLOC_IN_RC(int_flags)); 2242 match(RegFlags); 2243 2244 format %{ "apsr_L_LEGT" %} 2245 interface(REG_INTER); 2246 %} 2247 2248 operand flagsRegUL_LTGE() %{ 2249 constraint(ALLOC_IN_RC(int_flags)); 2250 match(RegFlags); 2251 2252 format %{ "apsr_UL_LTGE" %} 2253 interface(REG_INTER); 2254 %} 2255 2256 operand flagsRegUL_EQNE() %{ 2257 constraint(ALLOC_IN_RC(int_flags)); 2258 match(RegFlags); 2259 2260 format %{ "apsr_UL_EQNE" %} 2261 interface(REG_INTER); 2262 %} 2263 2264 operand flagsRegUL_LEGT() %{ 2265 constraint(ALLOC_IN_RC(int_flags)); 2266 match(RegFlags); 2267 2268 format %{ "apsr_UL_LEGT" %} 2269 interface(REG_INTER); 2270 %} 2271 2272 // Condition Code Register, floating comparisons, unordered same as "less". 2273 operand flagsRegF() %{ 2274 constraint(ALLOC_IN_RC(float_flags)); 2275 match(RegFlags); 2276 2277 format %{ "fpscr_F" %} 2278 interface(REG_INTER); 2279 %} 2280 2281 // Vectors 2282 operand vecD() %{ 2283 constraint(ALLOC_IN_RC(actual_dflt_reg)); 2284 match(VecD); 2285 2286 format %{ %} 2287 interface(REG_INTER); 2288 %} 2289 2290 operand vecX() %{ 2291 constraint(ALLOC_IN_RC(vectorx_reg)); 2292 match(VecX); 2293 2294 format %{ %} 2295 interface(REG_INTER); 2296 %} 2297 2298 operand regD() %{ 2299 constraint(ALLOC_IN_RC(actual_dflt_reg)); 2300 match(RegD); 2301 match(regD_low); 2302 2303 format %{ %} 2304 interface(REG_INTER); 2305 %} 2306 2307 operand regF() %{ 2308 constraint(ALLOC_IN_RC(sflt_reg)); 2309 match(RegF); 2310 2311 format %{ %} 2312 interface(REG_INTER); 2313 %} 2314 2315 operand regD_low() %{ 2316 constraint(ALLOC_IN_RC(dflt_low_reg)); 2317 match(RegD); 2318 2319 format %{ %} 2320 interface(REG_INTER); 2321 %} 2322 2323 // Special Registers 2324 2325 // Method Register 2326 operand inline_cache_regP(iRegP reg) %{ 2327 constraint(ALLOC_IN_RC(Ricklass_regP)); 2328 match(reg); 2329 format %{ %} 2330 interface(REG_INTER); 2331 %} 2332 2333 //----------Complex Operands--------------------------------------------------- 2334 // Indirect Memory Reference 2335 operand indirect(sp_ptr_RegP reg) %{ 2336 constraint(ALLOC_IN_RC(sp_ptr_reg)); 2337 match(reg); 2338 2339 op_cost(100); 2340 format %{ "[$reg]" %} 2341 interface(MEMORY_INTER) %{ 2342 base($reg); 2343 index(0xf); // PC => no index 2344 scale(0x0); 2345 disp(0x0); 2346 %} 2347 %} 2348 2349 2350 // Indirect with Offset in ]-4096, 4096[ 2351 operand indOffset12(sp_ptr_RegP reg, immI12 offset) %{ 2352 constraint(ALLOC_IN_RC(sp_ptr_reg)); 2353 match(AddP reg offset); 2354 2355 op_cost(100); 2356 format %{ "[$reg + $offset]" %} 2357 interface(MEMORY_INTER) %{ 2358 base($reg); 2359 index(0xf); // PC => no index 2360 scale(0x0); 2361 disp($offset); 2362 %} 2363 %} 2364 2365 // Indirect with offset for float load/store 2366 operand indOffsetFP(sp_ptr_RegP reg, immIFP offset) %{ 2367 constraint(ALLOC_IN_RC(sp_ptr_reg)); 2368 match(AddP reg offset); 2369 2370 op_cost(100); 2371 format %{ "[$reg + $offset]" %} 2372 interface(MEMORY_INTER) %{ 2373 base($reg); 2374 index(0xf); // PC => no index 2375 scale(0x0); 2376 disp($offset); 2377 %} 2378 %} 2379 2380 // Indirect with Offset for half and double words 2381 operand indOffsetHD(sp_ptr_RegP reg, immIHD offset) %{ 2382 constraint(ALLOC_IN_RC(sp_ptr_reg)); 2383 match(AddP reg offset); 2384 2385 op_cost(100); 2386 format %{ "[$reg + $offset]" %} 2387 interface(MEMORY_INTER) %{ 2388 base($reg); 2389 index(0xf); // PC => no index 2390 scale(0x0); 2391 disp($offset); 2392 %} 2393 %} 2394 2395 // Indirect with Offset and Offset+4 in ]-1024, 1024[ 2396 operand indOffsetFPx2(sp_ptr_RegP reg, immX10x2 offset) %{ 2397 constraint(ALLOC_IN_RC(sp_ptr_reg)); 2398 match(AddP reg offset); 2399 2400 op_cost(100); 2401 format %{ "[$reg + $offset]" %} 2402 interface(MEMORY_INTER) %{ 2403 base($reg); 2404 index(0xf); // PC => no index 2405 scale(0x0); 2406 disp($offset); 2407 %} 2408 %} 2409 2410 // Indirect with Offset and Offset+4 in ]-4096, 4096[ 2411 operand indOffset12x2(sp_ptr_RegP reg, immI12x2 offset) %{ 2412 constraint(ALLOC_IN_RC(sp_ptr_reg)); 2413 match(AddP reg offset); 2414 2415 op_cost(100); 2416 format %{ "[$reg + $offset]" %} 2417 interface(MEMORY_INTER) %{ 2418 base($reg); 2419 index(0xf); // PC => no index 2420 scale(0x0); 2421 disp($offset); 2422 %} 2423 %} 2424 2425 // Indirect with Register Index 2426 operand indIndex(iRegP addr, iRegX index) %{ 2427 constraint(ALLOC_IN_RC(ptr_reg)); 2428 match(AddP addr index); 2429 2430 op_cost(100); 2431 format %{ "[$addr + $index]" %} 2432 interface(MEMORY_INTER) %{ 2433 base($addr); 2434 index($index); 2435 scale(0x0); 2436 disp(0x0); 2437 %} 2438 %} 2439 2440 // Indirect Memory Times Scale Plus Index Register 2441 operand indIndexScale(iRegP addr, iRegX index, immU5 scale) %{ 2442 constraint(ALLOC_IN_RC(ptr_reg)); 2443 match(AddP addr (LShiftX index scale)); 2444 2445 op_cost(100); 2446 format %{"[$addr + $index << $scale]" %} 2447 interface(MEMORY_INTER) %{ 2448 base($addr); 2449 index($index); 2450 scale($scale); 2451 disp(0x0); 2452 %} 2453 %} 2454 2455 // Operands for expressing Control Flow 2456 // NOTE: Label is a predefined operand which should not be redefined in 2457 // the AD file. It is generically handled within the ADLC. 2458 2459 //----------Conditional Branch Operands---------------------------------------- 2460 // Comparison Op - This is the operation of the comparison, and is limited to 2461 // the following set of codes: 2462 // L (<), LE (<=), G (>), GE (>=), E (==), NE (!=) 2463 // 2464 // Other attributes of the comparison, such as unsignedness, are specified 2465 // by the comparison instruction that sets a condition code flags register. 2466 // That result is represented by a flags operand whose subtype is appropriate 2467 // to the unsignedness (etc.) of the comparison. 2468 // 2469 // Later, the instruction which matches both the Comparison Op (a Bool) and 2470 // the flags (produced by the Cmp) specifies the coding of the comparison op 2471 // by matching a specific subtype of Bool operand below, such as cmpOpU. 2472 2473 operand cmpOp() %{ 2474 match(Bool); 2475 2476 format %{ "" %} 2477 interface(COND_INTER) %{ 2478 equal(0x0); 2479 not_equal(0x1); 2480 less(0xb); 2481 greater_equal(0xa); 2482 less_equal(0xd); 2483 greater(0xc); 2484 overflow(0x0); // unsupported/unimplemented 2485 no_overflow(0x0); // unsupported/unimplemented 2486 %} 2487 %} 2488 2489 // integer comparison with 0, signed 2490 operand cmpOp0() %{ 2491 match(Bool); 2492 2493 format %{ "" %} 2494 interface(COND_INTER) %{ 2495 equal(0x0); 2496 not_equal(0x1); 2497 less(0x4); 2498 greater_equal(0x5); 2499 less_equal(0xd); // unsupported 2500 greater(0xc); // unsupported 2501 overflow(0x0); // unsupported/unimplemented 2502 no_overflow(0x0); // unsupported/unimplemented 2503 %} 2504 %} 2505 2506 // Comparison Op, unsigned 2507 operand cmpOpU() %{ 2508 match(Bool); 2509 2510 format %{ "u" %} 2511 interface(COND_INTER) %{ 2512 equal(0x0); 2513 not_equal(0x1); 2514 less(0x3); 2515 greater_equal(0x2); 2516 less_equal(0x9); 2517 greater(0x8); 2518 overflow(0x0); // unsupported/unimplemented 2519 no_overflow(0x0); // unsupported/unimplemented 2520 %} 2521 %} 2522 2523 // Comparison Op, pointer (same as unsigned) 2524 operand cmpOpP() %{ 2525 match(Bool); 2526 2527 format %{ "p" %} 2528 interface(COND_INTER) %{ 2529 equal(0x0); 2530 not_equal(0x1); 2531 less(0x3); 2532 greater_equal(0x2); 2533 less_equal(0x9); 2534 greater(0x8); 2535 overflow(0x0); // unsupported/unimplemented 2536 no_overflow(0x0); // unsupported/unimplemented 2537 %} 2538 %} 2539 2540 operand cmpOpL() %{ 2541 match(Bool); 2542 2543 format %{ "L" %} 2544 interface(COND_INTER) %{ 2545 equal(0x0); 2546 not_equal(0x1); 2547 less(0xb); 2548 greater_equal(0xa); 2549 less_equal(0xd); 2550 greater(0xc); 2551 overflow(0x0); // unsupported/unimplemented 2552 no_overflow(0x0); // unsupported/unimplemented 2553 %} 2554 %} 2555 2556 operand cmpOpL_commute() %{ 2557 match(Bool); 2558 2559 format %{ "L" %} 2560 interface(COND_INTER) %{ 2561 equal(0x0); 2562 not_equal(0x1); 2563 less(0xc); 2564 greater_equal(0xd); 2565 less_equal(0xa); 2566 greater(0xb); 2567 overflow(0x0); // unsupported/unimplemented 2568 no_overflow(0x0); // unsupported/unimplemented 2569 %} 2570 %} 2571 2572 operand cmpOpUL() %{ 2573 match(Bool); 2574 2575 format %{ "UL" %} 2576 interface(COND_INTER) %{ 2577 equal(0x0); 2578 not_equal(0x1); 2579 less(0x3); 2580 greater_equal(0x2); 2581 less_equal(0x9); 2582 greater(0x8); 2583 overflow(0x0); // unsupported/unimplemented 2584 no_overflow(0x0); // unsupported/unimplemented 2585 %} 2586 %} 2587 2588 operand cmpOpUL_commute() %{ 2589 match(Bool); 2590 2591 format %{ "UL" %} 2592 interface(COND_INTER) %{ 2593 equal(0x0); 2594 not_equal(0x1); 2595 less(0x8); 2596 greater_equal(0x9); 2597 less_equal(0x2); 2598 greater(0x3); 2599 overflow(0x0); // unsupported/unimplemented 2600 no_overflow(0x0); // unsupported/unimplemented 2601 %} 2602 %} 2603 2604 2605 //----------OPERAND CLASSES---------------------------------------------------- 2606 // Operand Classes are groups of operands that are used to simplify 2607 // instruction definitions by not requiring the AD writer to specify separate 2608 // instructions for every form of operand when the instruction accepts 2609 // multiple operand types with the same basic encoding and format. The classic 2610 // case of this is memory operands. 2611 2612 opclass memoryI ( indirect, indOffset12, indIndex, indIndexScale ); 2613 opclass memoryP ( indirect, indOffset12, indIndex, indIndexScale ); 2614 opclass memoryF ( indirect, indOffsetFP ); 2615 opclass memoryF2 ( indirect, indOffsetFPx2 ); 2616 opclass memoryD ( indirect, indOffsetFP ); 2617 opclass memoryfp( indirect, indOffsetFP ); 2618 opclass memoryB ( indirect, indIndex, indOffsetHD ); 2619 opclass memoryS ( indirect, indIndex, indOffsetHD ); 2620 opclass memoryL ( indirect, indIndex, indOffsetHD ); 2621 2622 opclass memoryScaledI(indIndexScale); 2623 opclass memoryScaledP(indIndexScale); 2624 2625 // when ldrex/strex is used: 2626 opclass memoryex ( indirect ); 2627 opclass indIndexMemory( indIndex ); 2628 opclass memorylong ( indirect, indOffset12x2 ); 2629 opclass memoryvld ( indirect /* , write back mode not implemented */ ); 2630 2631 //----------PIPELINE----------------------------------------------------------- 2632 pipeline %{ 2633 2634 //----------ATTRIBUTES--------------------------------------------------------- 2635 attributes %{ 2636 fixed_size_instructions; // Fixed size instructions 2637 max_instructions_per_bundle = 4; // Up to 4 instructions per bundle 2638 instruction_unit_size = 4; // An instruction is 4 bytes long 2639 instruction_fetch_unit_size = 16; // The processor fetches one line 2640 instruction_fetch_units = 1; // of 16 bytes 2641 2642 // List of nop instructions 2643 nops( Nop_A0, Nop_A1, Nop_MS, Nop_FA, Nop_BR ); 2644 %} 2645 2646 //----------RESOURCES---------------------------------------------------------- 2647 // Resources are the functional units available to the machine 2648 resources(A0, A1, MS, BR, FA, FM, IDIV, FDIV, IALU = A0 | A1); 2649 2650 //----------PIPELINE DESCRIPTION----------------------------------------------- 2651 // Pipeline Description specifies the stages in the machine's pipeline 2652 2653 pipe_desc(A, P, F, B, I, J, S, R, E, C, M, W, X, T, D); 2654 2655 //----------PIPELINE CLASSES--------------------------------------------------- 2656 // Pipeline Classes describe the stages in which input and output are 2657 // referenced by the hardware pipeline. 2658 2659 // Integer ALU reg-reg operation 2660 pipe_class ialu_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{ 2661 single_instruction; 2662 dst : E(write); 2663 src1 : R(read); 2664 src2 : R(read); 2665 IALU : R; 2666 %} 2667 2668 // Integer ALU reg-reg long operation 2669 pipe_class ialu_reg_reg_2(iRegL dst, iRegL src1, iRegL src2) %{ 2670 instruction_count(2); 2671 dst : E(write); 2672 src1 : R(read); 2673 src2 : R(read); 2674 IALU : R; 2675 IALU : R; 2676 %} 2677 2678 // Integer ALU reg-reg long dependent operation 2679 pipe_class ialu_reg_reg_2_dep(iRegL dst, iRegL src1, iRegL src2, flagsReg cr) %{ 2680 instruction_count(1); multiple_bundles; 2681 dst : E(write); 2682 src1 : R(read); 2683 src2 : R(read); 2684 cr : E(write); 2685 IALU : R(2); 2686 %} 2687 2688 // Integer ALU reg-imm operation 2689 pipe_class ialu_reg_imm(iRegI dst, iRegI src1) %{ 2690 single_instruction; 2691 dst : E(write); 2692 src1 : R(read); 2693 IALU : R; 2694 %} 2695 2696 // Integer ALU reg-reg operation with condition code 2697 pipe_class ialu_cc_reg_reg(iRegI dst, iRegI src1, iRegI src2, flagsReg cr) %{ 2698 single_instruction; 2699 dst : E(write); 2700 cr : E(write); 2701 src1 : R(read); 2702 src2 : R(read); 2703 IALU : R; 2704 %} 2705 2706 // Integer ALU zero-reg operation 2707 pipe_class ialu_zero_reg(iRegI dst, immI0 zero, iRegI src2) %{ 2708 single_instruction; 2709 dst : E(write); 2710 src2 : R(read); 2711 IALU : R; 2712 %} 2713 2714 // Integer ALU zero-reg operation with condition code only 2715 pipe_class ialu_cconly_zero_reg(flagsReg cr, iRegI src) %{ 2716 single_instruction; 2717 cr : E(write); 2718 src : R(read); 2719 IALU : R; 2720 %} 2721 2722 // Integer ALU reg-reg operation with condition code only 2723 pipe_class ialu_cconly_reg_reg(flagsReg cr, iRegI src1, iRegI src2) %{ 2724 single_instruction; 2725 cr : E(write); 2726 src1 : R(read); 2727 src2 : R(read); 2728 IALU : R; 2729 %} 2730 2731 // Integer ALU reg-imm operation with condition code only 2732 pipe_class ialu_cconly_reg_imm(flagsReg cr, iRegI src1) %{ 2733 single_instruction; 2734 cr : E(write); 2735 src1 : R(read); 2736 IALU : R; 2737 %} 2738 2739 // Integer ALU reg-reg-zero operation with condition code only 2740 pipe_class ialu_cconly_reg_reg_zero(flagsReg cr, iRegI src1, iRegI src2, immI0 zero) %{ 2741 single_instruction; 2742 cr : E(write); 2743 src1 : R(read); 2744 src2 : R(read); 2745 IALU : R; 2746 %} 2747 2748 // Integer ALU reg-imm-zero operation with condition code only 2749 pipe_class ialu_cconly_reg_imm_zero(flagsReg cr, iRegI src1, immI0 zero) %{ 2750 single_instruction; 2751 cr : E(write); 2752 src1 : R(read); 2753 IALU : R; 2754 %} 2755 2756 // Integer ALU reg-reg operation with condition code, src1 modified 2757 pipe_class ialu_cc_rwreg_reg(flagsReg cr, iRegI src1, iRegI src2) %{ 2758 single_instruction; 2759 cr : E(write); 2760 src1 : E(write); 2761 src1 : R(read); 2762 src2 : R(read); 2763 IALU : R; 2764 %} 2765 2766 pipe_class cmpL_reg(iRegI dst, iRegL src1, iRegL src2, flagsReg cr ) %{ 2767 multiple_bundles; 2768 dst : E(write)+4; 2769 cr : E(write); 2770 src1 : R(read); 2771 src2 : R(read); 2772 IALU : R(3); 2773 BR : R(2); 2774 %} 2775 2776 // Integer ALU operation 2777 pipe_class ialu_none(iRegI dst) %{ 2778 single_instruction; 2779 dst : E(write); 2780 IALU : R; 2781 %} 2782 2783 // Integer ALU reg operation 2784 pipe_class ialu_reg(iRegI dst, iRegI src) %{ 2785 single_instruction; may_have_no_code; 2786 dst : E(write); 2787 src : R(read); 2788 IALU : R; 2789 %} 2790 2791 // Integer ALU reg conditional operation 2792 // This instruction has a 1 cycle stall, and cannot execute 2793 // in the same cycle as the instruction setting the condition 2794 // code. We kludge this by pretending to read the condition code 2795 // 1 cycle earlier, and by marking the functional units as busy 2796 // for 2 cycles with the result available 1 cycle later than 2797 // is really the case. 2798 pipe_class ialu_reg_flags( iRegI op2_out, iRegI op2_in, iRegI op1, flagsReg cr ) %{ 2799 single_instruction; 2800 op2_out : C(write); 2801 op1 : R(read); 2802 cr : R(read); // This is really E, with a 1 cycle stall 2803 BR : R(2); 2804 MS : R(2); 2805 %} 2806 2807 // Integer ALU reg operation 2808 pipe_class ialu_move_reg_L_to_I(iRegI dst, iRegL src) %{ 2809 single_instruction; may_have_no_code; 2810 dst : E(write); 2811 src : R(read); 2812 IALU : R; 2813 %} 2814 pipe_class ialu_move_reg_I_to_L(iRegL dst, iRegI src) %{ 2815 single_instruction; may_have_no_code; 2816 dst : E(write); 2817 src : R(read); 2818 IALU : R; 2819 %} 2820 2821 // Two integer ALU reg operations 2822 pipe_class ialu_reg_2(iRegL dst, iRegL src) %{ 2823 instruction_count(2); 2824 dst : E(write); 2825 src : R(read); 2826 A0 : R; 2827 A1 : R; 2828 %} 2829 2830 // Two integer ALU reg operations 2831 pipe_class ialu_move_reg_L_to_L(iRegL dst, iRegL src) %{ 2832 instruction_count(2); may_have_no_code; 2833 dst : E(write); 2834 src : R(read); 2835 A0 : R; 2836 A1 : R; 2837 %} 2838 2839 // Integer ALU imm operation 2840 pipe_class ialu_imm(iRegI dst) %{ 2841 single_instruction; 2842 dst : E(write); 2843 IALU : R; 2844 %} 2845 2846 pipe_class ialu_imm_n(iRegI dst) %{ 2847 single_instruction; 2848 dst : E(write); 2849 IALU : R; 2850 %} 2851 2852 // Integer ALU reg-reg with carry operation 2853 pipe_class ialu_reg_reg_cy(iRegI dst, iRegI src1, iRegI src2, iRegI cy) %{ 2854 single_instruction; 2855 dst : E(write); 2856 src1 : R(read); 2857 src2 : R(read); 2858 IALU : R; 2859 %} 2860 2861 // Integer ALU cc operation 2862 pipe_class ialu_cc(iRegI dst, flagsReg cc) %{ 2863 single_instruction; 2864 dst : E(write); 2865 cc : R(read); 2866 IALU : R; 2867 %} 2868 2869 // Integer ALU cc / second IALU operation 2870 pipe_class ialu_reg_ialu( iRegI dst, iRegI src ) %{ 2871 instruction_count(1); multiple_bundles; 2872 dst : E(write)+1; 2873 src : R(read); 2874 IALU : R; 2875 %} 2876 2877 // Integer ALU cc / second IALU operation 2878 pipe_class ialu_reg_reg_ialu( iRegI dst, iRegI p, iRegI q ) %{ 2879 instruction_count(1); multiple_bundles; 2880 dst : E(write)+1; 2881 p : R(read); 2882 q : R(read); 2883 IALU : R; 2884 %} 2885 2886 // Integer ALU hi-lo-reg operation 2887 pipe_class ialu_hi_lo_reg(iRegI dst, immI src) %{ 2888 instruction_count(1); multiple_bundles; 2889 dst : E(write)+1; 2890 IALU : R(2); 2891 %} 2892 2893 // Long Constant 2894 pipe_class loadConL( iRegL dst, immL src ) %{ 2895 instruction_count(2); multiple_bundles; 2896 dst : E(write)+1; 2897 IALU : R(2); 2898 IALU : R(2); 2899 %} 2900 2901 // Pointer Constant 2902 pipe_class loadConP( iRegP dst, immP src ) %{ 2903 instruction_count(0); multiple_bundles; 2904 fixed_latency(6); 2905 %} 2906 2907 // Long Constant small 2908 pipe_class loadConLlo( iRegL dst, immL src ) %{ 2909 instruction_count(2); 2910 dst : E(write); 2911 IALU : R; 2912 IALU : R; 2913 %} 2914 2915 // [PHH] This is wrong for 64-bit. See LdImmF/D. 2916 pipe_class loadConFD(regF dst, immF src, iRegP tmp) %{ 2917 instruction_count(1); multiple_bundles; 2918 src : R(read); 2919 dst : M(write)+1; 2920 IALU : R; 2921 MS : E; 2922 %} 2923 2924 // Integer ALU nop operation 2925 pipe_class ialu_nop() %{ 2926 single_instruction; 2927 IALU : R; 2928 %} 2929 2930 // Integer ALU nop operation 2931 pipe_class ialu_nop_A0() %{ 2932 single_instruction; 2933 A0 : R; 2934 %} 2935 2936 // Integer ALU nop operation 2937 pipe_class ialu_nop_A1() %{ 2938 single_instruction; 2939 A1 : R; 2940 %} 2941 2942 // Integer Multiply reg-reg operation 2943 pipe_class imul_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{ 2944 single_instruction; 2945 dst : E(write); 2946 src1 : R(read); 2947 src2 : R(read); 2948 MS : R(5); 2949 %} 2950 2951 pipe_class mulL_reg_reg(iRegL dst, iRegL src1, iRegL src2) %{ 2952 single_instruction; 2953 dst : E(write)+4; 2954 src1 : R(read); 2955 src2 : R(read); 2956 MS : R(6); 2957 %} 2958 2959 // Integer Divide reg-reg 2960 pipe_class sdiv_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI temp, flagsReg cr) %{ 2961 instruction_count(1); multiple_bundles; 2962 dst : E(write); 2963 temp : E(write); 2964 src1 : R(read); 2965 src2 : R(read); 2966 temp : R(read); 2967 MS : R(38); 2968 %} 2969 2970 // Long Divide 2971 pipe_class divL_reg_reg(iRegL dst, iRegL src1, iRegL src2) %{ 2972 dst : E(write)+71; 2973 src1 : R(read); 2974 src2 : R(read)+1; 2975 MS : R(70); 2976 %} 2977 2978 // Floating Point Add Float 2979 pipe_class faddF_reg_reg(regF dst, regF src1, regF src2) %{ 2980 single_instruction; 2981 dst : X(write); 2982 src1 : E(read); 2983 src2 : E(read); 2984 FA : R; 2985 %} 2986 2987 // Floating Point Add Double 2988 pipe_class faddD_reg_reg(regD dst, regD src1, regD src2) %{ 2989 single_instruction; 2990 dst : X(write); 2991 src1 : E(read); 2992 src2 : E(read); 2993 FA : R; 2994 %} 2995 2996 // Floating Point Conditional Move based on integer flags 2997 pipe_class int_conditional_float_move (cmpOp cmp, flagsReg cr, regF dst, regF src) %{ 2998 single_instruction; 2999 dst : X(write); 3000 src : E(read); 3001 cr : R(read); 3002 FA : R(2); 3003 BR : R(2); 3004 %} 3005 3006 // Floating Point Conditional Move based on integer flags 3007 pipe_class int_conditional_double_move (cmpOp cmp, flagsReg cr, regD dst, regD src) %{ 3008 single_instruction; 3009 dst : X(write); 3010 src : E(read); 3011 cr : R(read); 3012 FA : R(2); 3013 BR : R(2); 3014 %} 3015 3016 // Floating Point Multiply Float 3017 pipe_class fmulF_reg_reg(regF dst, regF src1, regF src2) %{ 3018 single_instruction; 3019 dst : X(write); 3020 src1 : E(read); 3021 src2 : E(read); 3022 FM : R; 3023 %} 3024 3025 // Floating Point Multiply Double 3026 pipe_class fmulD_reg_reg(regD dst, regD src1, regD src2) %{ 3027 single_instruction; 3028 dst : X(write); 3029 src1 : E(read); 3030 src2 : E(read); 3031 FM : R; 3032 %} 3033 3034 // Floating Point Divide Float 3035 pipe_class fdivF_reg_reg(regF dst, regF src1, regF src2) %{ 3036 single_instruction; 3037 dst : X(write); 3038 src1 : E(read); 3039 src2 : E(read); 3040 FM : R; 3041 FDIV : C(14); 3042 %} 3043 3044 // Floating Point Divide Double 3045 pipe_class fdivD_reg_reg(regD dst, regD src1, regD src2) %{ 3046 single_instruction; 3047 dst : X(write); 3048 src1 : E(read); 3049 src2 : E(read); 3050 FM : R; 3051 FDIV : C(17); 3052 %} 3053 3054 // Floating Point Move/Negate/Abs Float 3055 pipe_class faddF_reg(regF dst, regF src) %{ 3056 single_instruction; 3057 dst : W(write); 3058 src : E(read); 3059 FA : R(1); 3060 %} 3061 3062 // Floating Point Move/Negate/Abs Double 3063 pipe_class faddD_reg(regD dst, regD src) %{ 3064 single_instruction; 3065 dst : W(write); 3066 src : E(read); 3067 FA : R; 3068 %} 3069 3070 // Floating Point Convert F->D 3071 pipe_class fcvtF2D(regD dst, regF src) %{ 3072 single_instruction; 3073 dst : X(write); 3074 src : E(read); 3075 FA : R; 3076 %} 3077 3078 // Floating Point Convert I->D 3079 pipe_class fcvtI2D(regD dst, regF src) %{ 3080 single_instruction; 3081 dst : X(write); 3082 src : E(read); 3083 FA : R; 3084 %} 3085 3086 // Floating Point Convert LHi->D 3087 pipe_class fcvtLHi2D(regD dst, regD src) %{ 3088 single_instruction; 3089 dst : X(write); 3090 src : E(read); 3091 FA : R; 3092 %} 3093 3094 // Floating Point Convert L->D 3095 pipe_class fcvtL2D(regD dst, iRegL src) %{ 3096 single_instruction; 3097 dst : X(write); 3098 src : E(read); 3099 FA : R; 3100 %} 3101 3102 // Floating Point Convert L->F 3103 pipe_class fcvtL2F(regF dst, iRegL src) %{ 3104 single_instruction; 3105 dst : X(write); 3106 src : E(read); 3107 FA : R; 3108 %} 3109 3110 // Floating Point Convert D->F 3111 pipe_class fcvtD2F(regD dst, regF src) %{ 3112 single_instruction; 3113 dst : X(write); 3114 src : E(read); 3115 FA : R; 3116 %} 3117 3118 // Floating Point Convert I->L 3119 pipe_class fcvtI2L(regD dst, regF src) %{ 3120 single_instruction; 3121 dst : X(write); 3122 src : E(read); 3123 FA : R; 3124 %} 3125 3126 // Floating Point Convert D->F 3127 pipe_class fcvtD2I(iRegI dst, regD src, flagsReg cr) %{ 3128 instruction_count(1); multiple_bundles; 3129 dst : X(write)+6; 3130 src : E(read); 3131 FA : R; 3132 %} 3133 3134 // Floating Point Convert D->L 3135 pipe_class fcvtD2L(regD dst, regD src, flagsReg cr) %{ 3136 instruction_count(1); multiple_bundles; 3137 dst : X(write)+6; 3138 src : E(read); 3139 FA : R; 3140 %} 3141 3142 // Floating Point Convert F->I 3143 pipe_class fcvtF2I(regF dst, regF src, flagsReg cr) %{ 3144 instruction_count(1); multiple_bundles; 3145 dst : X(write)+6; 3146 src : E(read); 3147 FA : R; 3148 %} 3149 3150 // Floating Point Convert F->L 3151 pipe_class fcvtF2L(regD dst, regF src, flagsReg cr) %{ 3152 instruction_count(1); multiple_bundles; 3153 dst : X(write)+6; 3154 src : E(read); 3155 FA : R; 3156 %} 3157 3158 // Floating Point Convert I->F 3159 pipe_class fcvtI2F(regF dst, regF src) %{ 3160 single_instruction; 3161 dst : X(write); 3162 src : E(read); 3163 FA : R; 3164 %} 3165 3166 // Floating Point Compare 3167 pipe_class faddF_fcc_reg_reg_zero(flagsRegF cr, regF src1, regF src2, immI0 zero) %{ 3168 single_instruction; 3169 cr : X(write); 3170 src1 : E(read); 3171 src2 : E(read); 3172 FA : R; 3173 %} 3174 3175 // Floating Point Compare 3176 pipe_class faddD_fcc_reg_reg_zero(flagsRegF cr, regD src1, regD src2, immI0 zero) %{ 3177 single_instruction; 3178 cr : X(write); 3179 src1 : E(read); 3180 src2 : E(read); 3181 FA : R; 3182 %} 3183 3184 // Floating Add Nop 3185 pipe_class fadd_nop() %{ 3186 single_instruction; 3187 FA : R; 3188 %} 3189 3190 // Integer Store to Memory 3191 pipe_class istore_mem_reg(memoryI mem, iRegI src) %{ 3192 single_instruction; 3193 mem : R(read); 3194 src : C(read); 3195 MS : R; 3196 %} 3197 3198 // Integer Store to Memory 3199 pipe_class istore_mem_spORreg(memoryI mem, sp_ptr_RegP src) %{ 3200 single_instruction; 3201 mem : R(read); 3202 src : C(read); 3203 MS : R; 3204 %} 3205 3206 // Float Store 3207 pipe_class fstoreF_mem_reg(memoryF mem, RegF src) %{ 3208 single_instruction; 3209 mem : R(read); 3210 src : C(read); 3211 MS : R; 3212 %} 3213 3214 // Float Store 3215 pipe_class fstoreF_mem_zero(memoryF mem, immF0 src) %{ 3216 single_instruction; 3217 mem : R(read); 3218 MS : R; 3219 %} 3220 3221 // Double Store 3222 pipe_class fstoreD_mem_reg(memoryD mem, RegD src) %{ 3223 instruction_count(1); 3224 mem : R(read); 3225 src : C(read); 3226 MS : R; 3227 %} 3228 3229 // Double Store 3230 pipe_class fstoreD_mem_zero(memoryD mem, immD0 src) %{ 3231 single_instruction; 3232 mem : R(read); 3233 MS : R; 3234 %} 3235 3236 // Integer Load (when sign bit propagation not needed) 3237 pipe_class iload_mem(iRegI dst, memoryI mem) %{ 3238 single_instruction; 3239 mem : R(read); 3240 dst : C(write); 3241 MS : R; 3242 %} 3243 3244 // Integer Load (when sign bit propagation or masking is needed) 3245 pipe_class iload_mask_mem(iRegI dst, memoryI mem) %{ 3246 single_instruction; 3247 mem : R(read); 3248 dst : M(write); 3249 MS : R; 3250 %} 3251 3252 // Float Load 3253 pipe_class floadF_mem(regF dst, memoryF mem) %{ 3254 single_instruction; 3255 mem : R(read); 3256 dst : M(write); 3257 MS : R; 3258 %} 3259 3260 // Float Load 3261 pipe_class floadD_mem(regD dst, memoryD mem) %{ 3262 instruction_count(1); multiple_bundles; // Again, unaligned argument is only multiple case 3263 mem : R(read); 3264 dst : M(write); 3265 MS : R; 3266 %} 3267 3268 // Memory Nop 3269 pipe_class mem_nop() %{ 3270 single_instruction; 3271 MS : R; 3272 %} 3273 3274 pipe_class sethi(iRegP dst, immI src) %{ 3275 single_instruction; 3276 dst : E(write); 3277 IALU : R; 3278 %} 3279 3280 pipe_class loadPollP(iRegP poll) %{ 3281 single_instruction; 3282 poll : R(read); 3283 MS : R; 3284 %} 3285 3286 pipe_class br(Universe br, label labl) %{ 3287 single_instruction_with_delay_slot; 3288 BR : R; 3289 %} 3290 3291 pipe_class br_cc(Universe br, cmpOp cmp, flagsReg cr, label labl) %{ 3292 single_instruction_with_delay_slot; 3293 cr : E(read); 3294 BR : R; 3295 %} 3296 3297 pipe_class br_reg(Universe br, cmpOp cmp, iRegI op1, label labl) %{ 3298 single_instruction_with_delay_slot; 3299 op1 : E(read); 3300 BR : R; 3301 MS : R; 3302 %} 3303 3304 pipe_class br_nop() %{ 3305 single_instruction; 3306 BR : R; 3307 %} 3308 3309 pipe_class simple_call(method meth) %{ 3310 instruction_count(2); multiple_bundles; force_serialization; 3311 fixed_latency(100); 3312 BR : R(1); 3313 MS : R(1); 3314 A0 : R(1); 3315 %} 3316 3317 pipe_class compiled_call(method meth) %{ 3318 instruction_count(1); multiple_bundles; force_serialization; 3319 fixed_latency(100); 3320 MS : R(1); 3321 %} 3322 3323 pipe_class call(method meth) %{ 3324 instruction_count(0); multiple_bundles; force_serialization; 3325 fixed_latency(100); 3326 %} 3327 3328 pipe_class tail_call(Universe ignore, label labl) %{ 3329 single_instruction; has_delay_slot; 3330 fixed_latency(100); 3331 BR : R(1); 3332 MS : R(1); 3333 %} 3334 3335 pipe_class ret(Universe ignore) %{ 3336 single_instruction; has_delay_slot; 3337 BR : R(1); 3338 MS : R(1); 3339 %} 3340 3341 // The real do-nothing guy 3342 pipe_class empty( ) %{ 3343 instruction_count(0); 3344 %} 3345 3346 pipe_class long_memory_op() %{ 3347 instruction_count(0); multiple_bundles; force_serialization; 3348 fixed_latency(25); 3349 MS : R(1); 3350 %} 3351 3352 // Check-cast 3353 pipe_class partial_subtype_check_pipe(Universe ignore, iRegP array, iRegP match ) %{ 3354 array : R(read); 3355 match : R(read); 3356 IALU : R(2); 3357 BR : R(2); 3358 MS : R; 3359 %} 3360 3361 // Convert FPU flags into +1,0,-1 3362 pipe_class floating_cmp( iRegI dst, regF src1, regF src2 ) %{ 3363 src1 : E(read); 3364 src2 : E(read); 3365 dst : E(write); 3366 FA : R; 3367 MS : R(2); 3368 BR : R(2); 3369 %} 3370 3371 // Compare for p < q, and conditionally add y 3372 pipe_class cadd_cmpltmask( iRegI p, iRegI q, iRegI y ) %{ 3373 p : E(read); 3374 q : E(read); 3375 y : E(read); 3376 IALU : R(3) 3377 %} 3378 3379 // Perform a compare, then move conditionally in a branch delay slot. 3380 pipe_class min_max( iRegI src2, iRegI srcdst ) %{ 3381 src2 : E(read); 3382 srcdst : E(read); 3383 IALU : R; 3384 BR : R; 3385 %} 3386 3387 // Define the class for the Nop node 3388 define %{ 3389 MachNop = ialu_nop; 3390 %} 3391 3392 %} 3393 3394 //----------INSTRUCTIONS------------------------------------------------------- 3395 3396 //------------Special Nop instructions for bundling - no match rules----------- 3397 // Nop using the A0 functional unit 3398 instruct Nop_A0() %{ 3399 ins_pipe(ialu_nop_A0); 3400 %} 3401 3402 // Nop using the A1 functional unit 3403 instruct Nop_A1( ) %{ 3404 ins_pipe(ialu_nop_A1); 3405 %} 3406 3407 // Nop using the memory functional unit 3408 instruct Nop_MS( ) %{ 3409 ins_pipe(mem_nop); 3410 %} 3411 3412 // Nop using the floating add functional unit 3413 instruct Nop_FA( ) %{ 3414 ins_pipe(fadd_nop); 3415 %} 3416 3417 // Nop using the branch functional unit 3418 instruct Nop_BR( ) %{ 3419 ins_pipe(br_nop); 3420 %} 3421 3422 //----------Load/Store/Move Instructions--------------------------------------- 3423 //----------Load Instructions-------------------------------------------------- 3424 // Load Byte (8bit signed) 3425 instruct loadB(iRegI dst, memoryB mem) %{ 3426 match(Set dst (LoadB mem)); 3427 ins_cost(MEMORY_REF_COST); 3428 3429 size(4); 3430 format %{ "LDRSB $dst,$mem\t! byte -> int" %} 3431 ins_encode %{ 3432 __ ldrsb($dst$$Register, $mem$$Address); 3433 %} 3434 ins_pipe(iload_mask_mem); 3435 %} 3436 3437 // Load Byte (8bit signed) into a Long Register 3438 instruct loadB2L(iRegL dst, memoryB mem) %{ 3439 match(Set dst (ConvI2L (LoadB mem))); 3440 ins_cost(MEMORY_REF_COST); 3441 3442 size(8); 3443 format %{ "LDRSB $dst.lo,$mem\t! byte -> long\n\t" 3444 "ASR $dst.hi,$dst.lo,31" %} 3445 ins_encode %{ 3446 __ ldrsb($dst$$Register, $mem$$Address); 3447 __ mov($dst$$Register->successor(), AsmOperand($dst$$Register, asr, 31)); 3448 %} 3449 ins_pipe(iload_mask_mem); 3450 %} 3451 3452 // Load Unsigned Byte (8bit UNsigned) into an int reg 3453 instruct loadUB(iRegI dst, memoryB mem) %{ 3454 match(Set dst (LoadUB mem)); 3455 ins_cost(MEMORY_REF_COST); 3456 3457 size(4); 3458 format %{ "LDRB $dst,$mem\t! ubyte -> int" %} 3459 ins_encode %{ 3460 __ ldrb($dst$$Register, $mem$$Address); 3461 %} 3462 ins_pipe(iload_mem); 3463 %} 3464 3465 // Load Unsigned Byte (8bit UNsigned) into a Long Register 3466 instruct loadUB2L(iRegL dst, memoryB mem) %{ 3467 match(Set dst (ConvI2L (LoadUB mem))); 3468 ins_cost(MEMORY_REF_COST); 3469 3470 size(8); 3471 format %{ "LDRB $dst.lo,$mem\t! ubyte -> long\n\t" 3472 "MOV $dst.hi,0" %} 3473 ins_encode %{ 3474 __ ldrb($dst$$Register, $mem$$Address); 3475 __ mov($dst$$Register->successor(), 0); 3476 %} 3477 ins_pipe(iload_mem); 3478 %} 3479 3480 // Load Unsigned Byte (8 bit UNsigned) with immediate mask into Long Register 3481 instruct loadUB2L_limmI(iRegL dst, memoryB mem, limmIlow8 mask) %{ 3482 match(Set dst (ConvI2L (AndI (LoadUB mem) mask))); 3483 3484 ins_cost(MEMORY_REF_COST + 2*DEFAULT_COST); 3485 size(12); 3486 format %{ "LDRB $dst.lo,$mem\t! ubyte -> long\n\t" 3487 "MOV $dst.hi,0\n\t" 3488 "AND $dst.lo,$dst.lo,$mask" %} 3489 ins_encode %{ 3490 __ ldrb($dst$$Register, $mem$$Address); 3491 __ mov($dst$$Register->successor(), 0); 3492 __ andr($dst$$Register, $dst$$Register, limmI_low($mask$$constant, 8)); 3493 %} 3494 ins_pipe(iload_mem); 3495 %} 3496 3497 // Load Short (16bit signed) 3498 3499 instruct loadS(iRegI dst, memoryS mem) %{ 3500 match(Set dst (LoadS mem)); 3501 ins_cost(MEMORY_REF_COST); 3502 3503 size(4); 3504 format %{ "LDRSH $dst,$mem\t! short" %} 3505 ins_encode %{ 3506 __ ldrsh($dst$$Register, $mem$$Address); 3507 %} 3508 ins_pipe(iload_mask_mem); 3509 %} 3510 3511 // Load Short (16 bit signed) to Byte (8 bit signed) 3512 instruct loadS2B(iRegI dst, memoryS mem, immI_24 twentyfour) %{ 3513 match(Set dst (RShiftI (LShiftI (LoadS mem) twentyfour) twentyfour)); 3514 ins_cost(MEMORY_REF_COST); 3515 3516 size(4); 3517 3518 format %{ "LDRSB $dst,$mem\t! short -> byte" %} 3519 ins_encode %{ 3520 __ ldrsb($dst$$Register, $mem$$Address); 3521 %} 3522 ins_pipe(iload_mask_mem); 3523 %} 3524 3525 // Load Short (16bit signed) into a Long Register 3526 instruct loadS2L(iRegL dst, memoryS mem) %{ 3527 match(Set dst (ConvI2L (LoadS mem))); 3528 ins_cost(MEMORY_REF_COST); 3529 3530 size(8); 3531 format %{ "LDRSH $dst.lo,$mem\t! short -> long\n\t" 3532 "ASR $dst.hi,$dst.lo,31" %} 3533 ins_encode %{ 3534 __ ldrsh($dst$$Register, $mem$$Address); 3535 __ mov($dst$$Register->successor(), AsmOperand($dst$$Register, asr, 31)); 3536 %} 3537 ins_pipe(iload_mask_mem); 3538 %} 3539 3540 // Load Unsigned Short/Char (16bit UNsigned) 3541 3542 3543 instruct loadUS(iRegI dst, memoryS mem) %{ 3544 match(Set dst (LoadUS mem)); 3545 ins_cost(MEMORY_REF_COST); 3546 3547 size(4); 3548 format %{ "LDRH $dst,$mem\t! ushort/char" %} 3549 ins_encode %{ 3550 __ ldrh($dst$$Register, $mem$$Address); 3551 %} 3552 ins_pipe(iload_mem); 3553 %} 3554 3555 // Load Unsigned Short/Char (16 bit UNsigned) to Byte (8 bit signed) 3556 instruct loadUS2B(iRegI dst, memoryB mem, immI_24 twentyfour) %{ 3557 match(Set dst (RShiftI (LShiftI (LoadUS mem) twentyfour) twentyfour)); 3558 ins_cost(MEMORY_REF_COST); 3559 3560 size(4); 3561 format %{ "LDRSB $dst,$mem\t! ushort -> byte" %} 3562 ins_encode %{ 3563 __ ldrsb($dst$$Register, $mem$$Address); 3564 %} 3565 ins_pipe(iload_mask_mem); 3566 %} 3567 3568 // Load Unsigned Short/Char (16bit UNsigned) into a Long Register 3569 instruct loadUS2L(iRegL dst, memoryS mem) %{ 3570 match(Set dst (ConvI2L (LoadUS mem))); 3571 ins_cost(MEMORY_REF_COST); 3572 3573 size(8); 3574 format %{ "LDRH $dst.lo,$mem\t! short -> long\n\t" 3575 "MOV $dst.hi, 0" %} 3576 ins_encode %{ 3577 __ ldrh($dst$$Register, $mem$$Address); 3578 __ mov($dst$$Register->successor(), 0); 3579 %} 3580 ins_pipe(iload_mem); 3581 %} 3582 3583 // Load Unsigned Short/Char (16bit UNsigned) with mask 0xFF into a Long Register 3584 instruct loadUS2L_immI_255(iRegL dst, memoryB mem, immI_255 mask) %{ 3585 match(Set dst (ConvI2L (AndI (LoadUS mem) mask))); 3586 ins_cost(MEMORY_REF_COST); 3587 3588 size(8); 3589 format %{ "LDRB $dst.lo,$mem\t! \n\t" 3590 "MOV $dst.hi, 0" %} 3591 ins_encode %{ 3592 __ ldrb($dst$$Register, $mem$$Address); 3593 __ mov($dst$$Register->successor(), 0); 3594 %} 3595 ins_pipe(iload_mem); 3596 %} 3597 3598 // Load Unsigned Short/Char (16bit UNsigned) with a immediate mask into a Long Register 3599 instruct loadUS2L_limmI(iRegL dst, memoryS mem, limmI mask) %{ 3600 match(Set dst (ConvI2L (AndI (LoadUS mem) mask))); 3601 ins_cost(MEMORY_REF_COST + 2*DEFAULT_COST); 3602 3603 size(12); 3604 format %{ "LDRH $dst,$mem\t! ushort/char & mask -> long\n\t" 3605 "MOV $dst.hi, 0\n\t" 3606 "AND $dst,$dst,$mask" %} 3607 ins_encode %{ 3608 __ ldrh($dst$$Register, $mem$$Address); 3609 __ mov($dst$$Register->successor(), 0); 3610 __ andr($dst$$Register, $dst$$Register, $mask$$constant); 3611 %} 3612 ins_pipe(iload_mem); 3613 %} 3614 3615 // Load Integer 3616 3617 3618 instruct loadI(iRegI dst, memoryI mem) %{ 3619 match(Set dst (LoadI mem)); 3620 ins_cost(MEMORY_REF_COST); 3621 3622 size(4); 3623 format %{ "ldr_s32 $dst,$mem\t! int" %} 3624 ins_encode %{ 3625 __ ldr_s32($dst$$Register, $mem$$Address); 3626 %} 3627 ins_pipe(iload_mem); 3628 %} 3629 3630 // Load Integer to Byte (8 bit signed) 3631 instruct loadI2B(iRegI dst, memoryS mem, immI_24 twentyfour) %{ 3632 match(Set dst (RShiftI (LShiftI (LoadI mem) twentyfour) twentyfour)); 3633 ins_cost(MEMORY_REF_COST); 3634 3635 size(4); 3636 3637 format %{ "LDRSB $dst,$mem\t! int -> byte" %} 3638 ins_encode %{ 3639 __ ldrsb($dst$$Register, $mem$$Address); 3640 %} 3641 ins_pipe(iload_mask_mem); 3642 %} 3643 3644 // Load Integer to Unsigned Byte (8 bit UNsigned) 3645 instruct loadI2UB(iRegI dst, memoryB mem, immI_255 mask) %{ 3646 match(Set dst (AndI (LoadI mem) mask)); 3647 ins_cost(MEMORY_REF_COST); 3648 3649 size(4); 3650 3651 format %{ "LDRB $dst,$mem\t! int -> ubyte" %} 3652 ins_encode %{ 3653 __ ldrb($dst$$Register, $mem$$Address); 3654 %} 3655 ins_pipe(iload_mask_mem); 3656 %} 3657 3658 // Load Integer to Short (16 bit signed) 3659 instruct loadI2S(iRegI dst, memoryS mem, immI_16 sixteen) %{ 3660 match(Set dst (RShiftI (LShiftI (LoadI mem) sixteen) sixteen)); 3661 ins_cost(MEMORY_REF_COST); 3662 3663 size(4); 3664 format %{ "LDRSH $dst,$mem\t! int -> short" %} 3665 ins_encode %{ 3666 __ ldrsh($dst$$Register, $mem$$Address); 3667 %} 3668 ins_pipe(iload_mask_mem); 3669 %} 3670 3671 // Load Integer to Unsigned Short (16 bit UNsigned) 3672 instruct loadI2US(iRegI dst, memoryS mem, immI_65535 mask) %{ 3673 match(Set dst (AndI (LoadI mem) mask)); 3674 ins_cost(MEMORY_REF_COST); 3675 3676 size(4); 3677 format %{ "LDRH $dst,$mem\t! int -> ushort/char" %} 3678 ins_encode %{ 3679 __ ldrh($dst$$Register, $mem$$Address); 3680 %} 3681 ins_pipe(iload_mask_mem); 3682 %} 3683 3684 // Load Integer into a Long Register 3685 instruct loadI2L(iRegL dst, memoryI mem) %{ 3686 match(Set dst (ConvI2L (LoadI mem))); 3687 ins_cost(MEMORY_REF_COST); 3688 3689 size(8); 3690 format %{ "LDR $dst.lo,$mem\t! int -> long\n\t" 3691 "ASR $dst.hi,$dst.lo,31\t! int->long" %} 3692 ins_encode %{ 3693 __ ldr($dst$$Register, $mem$$Address); 3694 __ mov($dst$$Register->successor(), AsmOperand($dst$$Register, asr, 31)); 3695 %} 3696 ins_pipe(iload_mask_mem); 3697 %} 3698 3699 // Load Integer with mask 0xFF into a Long Register 3700 instruct loadI2L_immI_255(iRegL dst, memoryB mem, immI_255 mask) %{ 3701 match(Set dst (ConvI2L (AndI (LoadI mem) mask))); 3702 ins_cost(MEMORY_REF_COST); 3703 3704 size(8); 3705 format %{ "LDRB $dst.lo,$mem\t! int & 0xFF -> long\n\t" 3706 "MOV $dst.hi, 0" %} 3707 ins_encode %{ 3708 __ ldrb($dst$$Register, $mem$$Address); 3709 __ mov($dst$$Register->successor(), 0); 3710 %} 3711 ins_pipe(iload_mem); 3712 %} 3713 3714 // Load Integer with mask 0xFFFF into a Long Register 3715 instruct loadI2L_immI_65535(iRegL dst, memoryS mem, immI_65535 mask) %{ 3716 match(Set dst (ConvI2L (AndI (LoadI mem) mask))); 3717 ins_cost(MEMORY_REF_COST); 3718 3719 size(8); 3720 format %{ "LDRH $dst,$mem\t! int & 0xFFFF -> long\n\t" 3721 "MOV $dst.hi, 0" %} 3722 ins_encode %{ 3723 __ ldrh($dst$$Register, $mem$$Address); 3724 __ mov($dst$$Register->successor(), 0); 3725 %} 3726 ins_pipe(iload_mask_mem); 3727 %} 3728 3729 // Load Integer with a 31-bit immediate mask into a Long Register 3730 instruct loadI2L_limmU31(iRegL dst, memoryI mem, limmU31 mask) %{ 3731 match(Set dst (ConvI2L (AndI (LoadI mem) mask))); 3732 ins_cost(MEMORY_REF_COST + 2*DEFAULT_COST); 3733 3734 size(12); 3735 format %{ "LDR $dst.lo,$mem\t! int -> long\n\t" 3736 "MOV $dst.hi, 0\n\t" 3737 "AND $dst,$dst,$mask" %} 3738 3739 ins_encode %{ 3740 __ ldr($dst$$Register, $mem$$Address); 3741 __ mov($dst$$Register->successor(), 0); 3742 __ andr($dst$$Register, $dst$$Register, $mask$$constant); 3743 %} 3744 ins_pipe(iload_mem); 3745 %} 3746 3747 // Load Integer with a 31-bit mask into a Long Register 3748 // FIXME: use iRegI mask, remove tmp? 3749 instruct loadI2L_immU31(iRegL dst, memoryI mem, immU31 mask, iRegI tmp) %{ 3750 match(Set dst (ConvI2L (AndI (LoadI mem) mask))); 3751 effect(TEMP dst, TEMP tmp); 3752 3753 ins_cost(MEMORY_REF_COST + 4*DEFAULT_COST); 3754 size(20); 3755 format %{ "LDR $mem,$dst\t! int & 31-bit mask -> long\n\t" 3756 "MOV $dst.hi, 0\n\t" 3757 "MOV_SLOW $tmp,$mask\n\t" 3758 "AND $dst,$tmp,$dst" %} 3759 ins_encode %{ 3760 __ ldr($dst$$Register, $mem$$Address); 3761 __ mov($dst$$Register->successor(), 0); 3762 __ mov_slow($tmp$$Register, $mask$$constant); 3763 __ andr($dst$$Register, $dst$$Register, $tmp$$Register); 3764 %} 3765 ins_pipe(iload_mem); 3766 %} 3767 3768 // Load Unsigned Integer into a Long Register 3769 instruct loadUI2L(iRegL dst, memoryI mem, immL_32bits mask) %{ 3770 match(Set dst (AndL (ConvI2L (LoadI mem)) mask)); 3771 ins_cost(MEMORY_REF_COST); 3772 3773 size(8); 3774 format %{ "LDR $dst.lo,$mem\t! uint -> long\n\t" 3775 "MOV $dst.hi,0" %} 3776 ins_encode %{ 3777 __ ldr($dst$$Register, $mem$$Address); 3778 __ mov($dst$$Register->successor(), 0); 3779 %} 3780 ins_pipe(iload_mem); 3781 %} 3782 3783 // Load Long 3784 3785 3786 instruct loadL(iRegLd dst, memoryL mem ) %{ 3787 predicate(!((LoadLNode*)n)->require_atomic_access()); 3788 match(Set dst (LoadL mem)); 3789 effect(TEMP dst); 3790 ins_cost(MEMORY_REF_COST); 3791 3792 size(4); 3793 format %{ "ldr_64 $dst,$mem\t! long" %} 3794 ins_encode %{ 3795 __ ldr_64($dst$$Register, $mem$$Address); 3796 %} 3797 ins_pipe(iload_mem); 3798 %} 3799 3800 instruct loadL_2instr(iRegL dst, memorylong mem ) %{ 3801 predicate(!((LoadLNode*)n)->require_atomic_access()); 3802 match(Set dst (LoadL mem)); 3803 ins_cost(MEMORY_REF_COST + DEFAULT_COST); 3804 3805 size(8); 3806 format %{ "LDR $dst.lo,$mem \t! long order of instrs reversed if $dst.lo == base($mem)\n\t" 3807 "LDR $dst.hi,$mem+4 or $mem" %} 3808 ins_encode %{ 3809 Address Amemlo = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none); 3810 Address Amemhi = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp + 4, relocInfo::none); 3811 3812 if ($dst$$Register == reg_to_register_object($mem$$base)) { 3813 __ ldr($dst$$Register->successor(), Amemhi); 3814 __ ldr($dst$$Register, Amemlo); 3815 } else { 3816 __ ldr($dst$$Register, Amemlo); 3817 __ ldr($dst$$Register->successor(), Amemhi); 3818 } 3819 %} 3820 ins_pipe(iload_mem); 3821 %} 3822 3823 instruct loadL_volatile(iRegL dst, indirect mem ) %{ 3824 predicate(((LoadLNode*)n)->require_atomic_access()); 3825 match(Set dst (LoadL mem)); 3826 ins_cost(MEMORY_REF_COST); 3827 3828 size(4); 3829 format %{ "LDMIA $dst,$mem\t! long" %} 3830 ins_encode %{ 3831 // FIXME: why is ldmia considered atomic? Should be ldrexd 3832 RegisterSet set($dst$$Register); 3833 set = set | reg_to_register_object($dst$$reg + 1); 3834 __ ldmia(reg_to_register_object($mem$$base), set); 3835 %} 3836 ins_pipe(iload_mem); 3837 %} 3838 3839 instruct loadL_volatile_fp(iRegL dst, memoryD mem ) %{ 3840 predicate(((LoadLNode*)n)->require_atomic_access()); 3841 match(Set dst (LoadL mem)); 3842 ins_cost(MEMORY_REF_COST); 3843 3844 size(8); 3845 format %{ "FLDD S14, $mem" 3846 "FMRRD $dst, S14\t! long \n't" %} 3847 ins_encode %{ 3848 __ fldd(S14, $mem$$Address); 3849 __ fmrrd($dst$$Register, $dst$$Register->successor(), S14); 3850 %} 3851 ins_pipe(iload_mem); 3852 %} 3853 3854 instruct loadL_unaligned(iRegL dst, memorylong mem ) %{ 3855 match(Set dst (LoadL_unaligned mem)); 3856 ins_cost(MEMORY_REF_COST); 3857 3858 size(8); 3859 format %{ "LDR $dst.lo,$mem\t! long order of instrs reversed if $dst.lo == base($mem)\n\t" 3860 "LDR $dst.hi,$mem+4" %} 3861 ins_encode %{ 3862 Address Amemlo = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none); 3863 Address Amemhi = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp + 4, relocInfo::none); 3864 3865 if ($dst$$Register == reg_to_register_object($mem$$base)) { 3866 __ ldr($dst$$Register->successor(), Amemhi); 3867 __ ldr($dst$$Register, Amemlo); 3868 } else { 3869 __ ldr($dst$$Register, Amemlo); 3870 __ ldr($dst$$Register->successor(), Amemhi); 3871 } 3872 %} 3873 ins_pipe(iload_mem); 3874 %} 3875 3876 // Load Range 3877 instruct loadRange(iRegI dst, memoryI mem) %{ 3878 match(Set dst (LoadRange mem)); 3879 ins_cost(MEMORY_REF_COST); 3880 3881 size(4); 3882 format %{ "LDR_u32 $dst,$mem\t! range" %} 3883 ins_encode %{ 3884 __ ldr_u32($dst$$Register, $mem$$Address); 3885 %} 3886 ins_pipe(iload_mem); 3887 %} 3888 3889 // Load Pointer 3890 3891 3892 instruct loadP(iRegP dst, memoryP mem) %{ 3893 predicate(!(UseG1GC && n->as_Load()->barrier_data() != 0)); 3894 match(Set dst (LoadP mem)); 3895 ins_cost(MEMORY_REF_COST); 3896 size(4); 3897 3898 format %{ "LDR $dst,$mem\t! ptr" %} 3899 ins_encode %{ 3900 __ ldr($dst$$Register, $mem$$Address); 3901 %} 3902 ins_pipe(iload_mem); 3903 %} 3904 3905 #ifdef XXX 3906 // FIXME XXXX 3907 //instruct loadSP(iRegP dst, memoryP mem) %{ 3908 instruct loadSP(SPRegP dst, memoryP mem, iRegP tmp) %{ 3909 match(Set dst (LoadP mem)); 3910 effect(TEMP tmp); 3911 ins_cost(MEMORY_REF_COST+1); 3912 size(8); 3913 3914 format %{ "LDR $tmp,$mem\t! ptr\n\t" 3915 "MOV $dst,$tmp\t! ptr" %} 3916 ins_encode %{ 3917 __ ldr($tmp$$Register, $mem$$Address); 3918 __ mov($dst$$Register, $tmp$$Register); 3919 %} 3920 ins_pipe(iload_mem); 3921 %} 3922 #endif 3923 3924 #ifdef _LP64 3925 // Load Compressed Pointer 3926 3927 // XXX This variant shouldn't be necessary if 6217251 is implemented 3928 instruct loadNoff(iRegN dst, memoryScaledI mem, aimmX off, iRegP tmp) %{ 3929 match(Set dst (LoadN (AddP mem off))); 3930 ins_cost(MEMORY_REF_COST + DEFAULT_COST); // assume shift/sign-extend is free 3931 effect(TEMP tmp); 3932 size(4 * 2); 3933 3934 format %{ "ldr_u32 $dst,$mem+$off\t! compressed ptr temp=$tmp" %} 3935 ins_encode %{ 3936 Register base = reg_to_register_object($mem$$base); 3937 __ add($tmp$$Register, base, $off$$constant); 3938 Address nmem = Address::make_raw($tmp$$reg, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none); 3939 __ ldr_u32($dst$$Register, nmem); 3940 %} 3941 ins_pipe(iload_mem); 3942 %} 3943 3944 instruct loadN(iRegN dst, memoryI mem) %{ 3945 match(Set dst (LoadN mem)); 3946 ins_cost(MEMORY_REF_COST); 3947 size(4); 3948 3949 format %{ "ldr_u32 $dst,$mem\t! compressed ptr" %} 3950 ins_encode %{ 3951 __ ldr_u32($dst$$Register, $mem$$Address); 3952 %} 3953 ins_pipe(iload_mem); 3954 %} 3955 #endif 3956 3957 // Load Klass Pointer 3958 instruct loadKlass(iRegP dst, memoryI mem) %{ 3959 match(Set dst (LoadKlass mem)); 3960 ins_cost(MEMORY_REF_COST); 3961 size(4); 3962 3963 format %{ "LDR $dst,$mem\t! klass ptr" %} 3964 ins_encode %{ 3965 __ ldr($dst$$Register, $mem$$Address); 3966 %} 3967 ins_pipe(iload_mem); 3968 %} 3969 3970 #ifdef _LP64 3971 // Load narrow Klass Pointer 3972 instruct loadNKlass(iRegN dst, memoryI mem) %{ 3973 match(Set dst (LoadNKlass mem)); 3974 ins_cost(MEMORY_REF_COST); 3975 size(4); 3976 3977 format %{ "ldr_u32 $dst,$mem\t! compressed klass ptr" %} 3978 ins_encode %{ 3979 __ ldr_u32($dst$$Register, $mem$$Address); 3980 %} 3981 ins_pipe(iload_mem); 3982 %} 3983 #endif 3984 3985 3986 instruct loadD(regD dst, memoryD mem) %{ 3987 match(Set dst (LoadD mem)); 3988 ins_cost(MEMORY_REF_COST); 3989 3990 size(4); 3991 // FIXME: needs to be atomic, but ARMv7 A.R.M. guarantees 3992 // only LDREXD and STREXD are 64-bit single-copy atomic 3993 format %{ "FLDD $dst,$mem" %} 3994 ins_encode %{ 3995 __ ldr_double($dst$$FloatRegister, $mem$$Address); 3996 %} 3997 ins_pipe(floadD_mem); 3998 %} 3999 4000 // Load Double - UNaligned 4001 instruct loadD_unaligned(regD_low dst, memoryF2 mem ) %{ 4002 match(Set dst (LoadD_unaligned mem)); 4003 ins_cost(MEMORY_REF_COST*2+DEFAULT_COST); 4004 size(8); 4005 format %{ "FLDS $dst.lo,$mem\t! misaligned double\n" 4006 "\tFLDS $dst.hi,$mem+4\t!" %} 4007 ins_encode %{ 4008 Address Amemlo = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none); 4009 Address Amemhi = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp + 4, relocInfo::none); 4010 __ flds($dst$$FloatRegister, Amemlo); 4011 __ flds($dst$$FloatRegister->successor(), Amemhi); 4012 %} 4013 ins_pipe(iload_mem); 4014 %} 4015 4016 4017 instruct loadF(regF dst, memoryF mem) %{ 4018 match(Set dst (LoadF mem)); 4019 4020 ins_cost(MEMORY_REF_COST); 4021 size(4); 4022 format %{ "FLDS $dst,$mem" %} 4023 ins_encode %{ 4024 __ ldr_float($dst$$FloatRegister, $mem$$Address); 4025 %} 4026 ins_pipe(floadF_mem); 4027 %} 4028 4029 4030 // // Load Constant 4031 instruct loadConI( iRegI dst, immI src ) %{ 4032 match(Set dst src); 4033 ins_cost(DEFAULT_COST * 3/2); 4034 format %{ "MOV_SLOW $dst, $src" %} 4035 ins_encode %{ 4036 __ mov_slow($dst$$Register, $src$$constant); 4037 %} 4038 ins_pipe(ialu_hi_lo_reg); 4039 %} 4040 4041 instruct loadConIMov( iRegI dst, immIMov src ) %{ 4042 match(Set dst src); 4043 size(4); 4044 format %{ "MOV $dst, $src" %} 4045 ins_encode %{ 4046 __ mov($dst$$Register, $src$$constant); 4047 %} 4048 ins_pipe(ialu_imm); 4049 %} 4050 4051 instruct loadConIMovn( iRegI dst, immIRotn src ) %{ 4052 match(Set dst src); 4053 size(4); 4054 format %{ "MVN $dst, ~$src" %} 4055 ins_encode %{ 4056 __ mvn($dst$$Register, ~$src$$constant); 4057 %} 4058 ins_pipe(ialu_imm_n); 4059 %} 4060 4061 instruct loadConI16( iRegI dst, immI16 src ) %{ 4062 match(Set dst src); 4063 size(4); 4064 format %{ "MOVW $dst, $src" %} 4065 ins_encode %{ 4066 __ movw($dst$$Register, $src$$constant); 4067 %} 4068 ins_pipe(ialu_imm_n); 4069 %} 4070 4071 instruct loadConP(iRegP dst, immP src) %{ 4072 match(Set dst src); 4073 ins_cost(DEFAULT_COST * 3/2); 4074 format %{ "MOV_SLOW $dst,$src\t!ptr" %} 4075 ins_encode %{ 4076 relocInfo::relocType constant_reloc = _opnds[1]->constant_reloc(); 4077 intptr_t val = $src$$constant; 4078 if (constant_reloc == relocInfo::oop_type) { 4079 __ mov_oop($dst$$Register, (jobject)val); 4080 } else if (constant_reloc == relocInfo::metadata_type) { 4081 __ mov_metadata($dst$$Register, (Metadata*)val); 4082 } else { 4083 __ mov_slow($dst$$Register, val); 4084 } 4085 %} 4086 ins_pipe(loadConP); 4087 %} 4088 4089 4090 instruct loadConL(iRegL dst, immL src) %{ 4091 match(Set dst src); 4092 ins_cost(DEFAULT_COST * 4); 4093 format %{ "MOV_SLOW $dst.lo, $src & 0x0FFFFFFFFL \t! long\n\t" 4094 "MOV_SLOW $dst.hi, $src >> 32" %} 4095 ins_encode %{ 4096 __ mov_slow(reg_to_register_object($dst$$reg), $src$$constant & 0x0FFFFFFFFL); 4097 __ mov_slow(reg_to_register_object($dst$$reg + 1), ((julong)($src$$constant)) >> 32); 4098 %} 4099 ins_pipe(loadConL); 4100 %} 4101 4102 instruct loadConL16( iRegL dst, immL16 src ) %{ 4103 match(Set dst src); 4104 ins_cost(DEFAULT_COST * 2); 4105 4106 size(8); 4107 format %{ "MOVW $dst.lo, $src \n\t" 4108 "MOVW $dst.hi, 0 \n\t" %} 4109 ins_encode %{ 4110 __ movw($dst$$Register, $src$$constant); 4111 __ movw($dst$$Register->successor(), 0); 4112 %} 4113 ins_pipe(ialu_imm); 4114 %} 4115 4116 instruct loadConF_imm8(regF dst, imm8F src) %{ 4117 match(Set dst src); 4118 ins_cost(DEFAULT_COST); 4119 size(4); 4120 4121 format %{ "FCONSTS $dst, $src"%} 4122 4123 ins_encode %{ 4124 __ fconsts($dst$$FloatRegister, Assembler::float_num($src$$constant).imm8()); 4125 %} 4126 ins_pipe(loadConFD); // FIXME 4127 %} 4128 4129 4130 instruct loadConF(regF dst, immF src, iRegI tmp) %{ 4131 match(Set dst src); 4132 ins_cost(DEFAULT_COST * 2); 4133 effect(TEMP tmp); 4134 size(3*4); 4135 4136 format %{ "MOV_SLOW $tmp, $src\n\t" 4137 "FMSR $dst, $tmp"%} 4138 4139 ins_encode %{ 4140 // FIXME revisit once 6961697 is in 4141 union { 4142 jfloat f; 4143 int i; 4144 } v; 4145 v.f = $src$$constant; 4146 __ mov_slow($tmp$$Register, v.i); 4147 __ fmsr($dst$$FloatRegister, $tmp$$Register); 4148 %} 4149 ins_pipe(loadConFD); // FIXME 4150 %} 4151 4152 instruct loadConD_imm8(regD dst, imm8D src) %{ 4153 match(Set dst src); 4154 ins_cost(DEFAULT_COST); 4155 size(4); 4156 4157 format %{ "FCONSTD $dst, $src"%} 4158 4159 ins_encode %{ 4160 __ fconstd($dst$$FloatRegister, Assembler::double_num($src$$constant).imm8()); 4161 %} 4162 ins_pipe(loadConFD); // FIXME 4163 %} 4164 4165 instruct loadConD(regD dst, immD src, iRegP tmp) %{ 4166 match(Set dst src); 4167 effect(TEMP tmp); 4168 ins_cost(MEMORY_REF_COST); 4169 format %{ "FLDD $dst, [$constanttablebase + $constantoffset]\t! load from constant table: double=$src" %} 4170 4171 ins_encode %{ 4172 Register r = $constanttablebase; 4173 int offset = $constantoffset($src); 4174 if (!is_memoryD(offset)) { // can't use a predicate 4175 // in load constant instructs 4176 __ add_slow($tmp$$Register, r, offset); 4177 r = $tmp$$Register; 4178 offset = 0; 4179 } 4180 __ ldr_double($dst$$FloatRegister, Address(r, offset)); 4181 %} 4182 ins_pipe(loadConFD); 4183 %} 4184 4185 // Prefetch instructions. 4186 // Must be safe to execute with invalid address (cannot fault). 4187 4188 instruct prefetchAlloc_mp( memoryP mem ) %{ 4189 predicate(VM_Version::has_multiprocessing_extensions()); 4190 match( PrefetchAllocation mem ); 4191 ins_cost(MEMORY_REF_COST); 4192 size(4); 4193 4194 format %{ "PLDW $mem\t! Prefetch allocation" %} 4195 ins_encode %{ 4196 __ pldw($mem$$Address); 4197 %} 4198 ins_pipe(iload_mem); 4199 %} 4200 4201 instruct prefetchAlloc_sp( memoryP mem ) %{ 4202 predicate(!VM_Version::has_multiprocessing_extensions()); 4203 match( PrefetchAllocation mem ); 4204 ins_cost(MEMORY_REF_COST); 4205 size(4); 4206 4207 format %{ "PLD $mem\t! Prefetch allocation" %} 4208 ins_encode %{ 4209 __ pld($mem$$Address); 4210 %} 4211 ins_pipe(iload_mem); 4212 %} 4213 4214 4215 //----------Store Instructions------------------------------------------------- 4216 // Store Byte 4217 instruct storeB(memoryB mem, store_RegI src) %{ 4218 match(Set mem (StoreB mem src)); 4219 ins_cost(MEMORY_REF_COST); 4220 4221 size(4); 4222 format %{ "STRB $src,$mem\t! byte" %} 4223 ins_encode %{ 4224 __ strb($src$$Register, $mem$$Address); 4225 %} 4226 ins_pipe(istore_mem_reg); 4227 %} 4228 4229 // Store Char/Short 4230 4231 4232 instruct storeC(memoryS mem, store_RegI src) %{ 4233 match(Set mem (StoreC mem src)); 4234 ins_cost(MEMORY_REF_COST); 4235 4236 size(4); 4237 format %{ "STRH $src,$mem\t! short" %} 4238 ins_encode %{ 4239 __ strh($src$$Register, $mem$$Address); 4240 %} 4241 ins_pipe(istore_mem_reg); 4242 %} 4243 4244 // Store Integer 4245 4246 4247 instruct storeI(memoryI mem, store_RegI src) %{ 4248 match(Set mem (StoreI mem src)); 4249 ins_cost(MEMORY_REF_COST); 4250 4251 size(4); 4252 format %{ "str_32 $src,$mem" %} 4253 ins_encode %{ 4254 __ str_32($src$$Register, $mem$$Address); 4255 %} 4256 ins_pipe(istore_mem_reg); 4257 %} 4258 4259 // Store Long 4260 4261 4262 instruct storeL(memoryL mem, store_RegLd src) %{ 4263 predicate(!((StoreLNode*)n)->require_atomic_access()); 4264 match(Set mem (StoreL mem src)); 4265 ins_cost(MEMORY_REF_COST); 4266 4267 size(4); 4268 format %{ "str_64 $src,$mem\t! long\n\t" %} 4269 4270 ins_encode %{ 4271 __ str_64($src$$Register, $mem$$Address); 4272 %} 4273 ins_pipe(istore_mem_reg); 4274 %} 4275 4276 instruct storeL_2instr(memorylong mem, iRegL src) %{ 4277 predicate(!((StoreLNode*)n)->require_atomic_access()); 4278 match(Set mem (StoreL mem src)); 4279 ins_cost(MEMORY_REF_COST + DEFAULT_COST); 4280 4281 size(8); 4282 format %{ "STR $src.lo,$mem\t! long\n\t" 4283 "STR $src.hi,$mem+4" %} 4284 4285 ins_encode %{ 4286 Address Amemlo = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none); 4287 Address Amemhi = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp + 4, relocInfo::none); 4288 __ str($src$$Register, Amemlo); 4289 __ str($src$$Register->successor(), Amemhi); 4290 %} 4291 ins_pipe(istore_mem_reg); 4292 %} 4293 4294 instruct storeL_volatile(indirect mem, iRegL src) %{ 4295 predicate(((StoreLNode*)n)->require_atomic_access()); 4296 match(Set mem (StoreL mem src)); 4297 ins_cost(MEMORY_REF_COST); 4298 size(4); 4299 format %{ "STMIA $src,$mem\t! long" %} 4300 ins_encode %{ 4301 // FIXME: why is stmia considered atomic? Should be strexd 4302 RegisterSet set($src$$Register); 4303 set = set | reg_to_register_object($src$$reg + 1); 4304 __ stmia(reg_to_register_object($mem$$base), set); 4305 %} 4306 ins_pipe(istore_mem_reg); 4307 %} 4308 4309 instruct storeL_volatile_fp(memoryD mem, iRegL src) %{ 4310 predicate(((StoreLNode*)n)->require_atomic_access()); 4311 match(Set mem (StoreL mem src)); 4312 ins_cost(MEMORY_REF_COST); 4313 size(8); 4314 format %{ "FMDRR S14, $src\t! long \n\t" 4315 "FSTD S14, $mem" %} 4316 ins_encode %{ 4317 __ fmdrr(S14, $src$$Register, $src$$Register->successor()); 4318 __ fstd(S14, $mem$$Address); 4319 %} 4320 ins_pipe(istore_mem_reg); 4321 %} 4322 4323 #ifdef XXX 4324 // Move SP Pointer 4325 //instruct movSP(sp_ptr_RegP dst, SPRegP src) %{ 4326 //instruct movSP(iRegP dst, SPRegP src) %{ 4327 instruct movSP(store_ptr_RegP dst, SPRegP src) %{ 4328 match(Set dst src); 4329 //predicate(!_kids[1]->_leaf->is_Proj() || _kids[1]->_leaf->as_Proj()->_con == TypeFunc::FramePtr); 4330 ins_cost(MEMORY_REF_COST); 4331 size(4); 4332 4333 format %{ "MOV $dst,$src\t! SP ptr\n\t" %} 4334 ins_encode %{ 4335 assert(false, "XXX1 got here"); 4336 __ mov($dst$$Register, SP); 4337 __ mov($dst$$Register, $src$$Register); 4338 %} 4339 ins_pipe(ialu_reg); 4340 %} 4341 #endif 4342 4343 4344 // Store Pointer 4345 4346 4347 instruct storeP(memoryP mem, store_ptr_RegP src) %{ 4348 predicate(!(UseG1GC && n->as_Store()->barrier_data() != 0)); 4349 match(Set mem (StoreP mem src)); 4350 ins_cost(MEMORY_REF_COST); 4351 size(4); 4352 4353 format %{ "STR $src,$mem\t! ptr" %} 4354 ins_encode %{ 4355 __ str($src$$Register, $mem$$Address); 4356 %} 4357 ins_pipe(istore_mem_spORreg); 4358 %} 4359 4360 4361 #ifdef _LP64 4362 // Store Compressed Pointer 4363 4364 4365 instruct storeN(memoryI mem, store_RegN src) %{ 4366 match(Set mem (StoreN mem src)); 4367 ins_cost(MEMORY_REF_COST); 4368 size(4); 4369 4370 format %{ "str_32 $src,$mem\t! compressed ptr" %} 4371 ins_encode %{ 4372 __ str_32($src$$Register, $mem$$Address); 4373 %} 4374 ins_pipe(istore_mem_reg); 4375 %} 4376 4377 4378 // Store Compressed Klass Pointer 4379 instruct storeNKlass(memoryI mem, store_RegN src) %{ 4380 match(Set mem (StoreNKlass mem src)); 4381 ins_cost(MEMORY_REF_COST); 4382 size(4); 4383 4384 format %{ "str_32 $src,$mem\t! compressed klass ptr" %} 4385 ins_encode %{ 4386 __ str_32($src$$Register, $mem$$Address); 4387 %} 4388 ins_pipe(istore_mem_reg); 4389 %} 4390 #endif 4391 4392 // Store Double 4393 4394 4395 instruct storeD(memoryD mem, regD src) %{ 4396 match(Set mem (StoreD mem src)); 4397 ins_cost(MEMORY_REF_COST); 4398 4399 size(4); 4400 // FIXME: needs to be atomic, but ARMv7 A.R.M. guarantees 4401 // only LDREXD and STREXD are 64-bit single-copy atomic 4402 format %{ "FSTD $src,$mem" %} 4403 ins_encode %{ 4404 __ str_double($src$$FloatRegister, $mem$$Address); 4405 %} 4406 ins_pipe(fstoreD_mem_reg); 4407 %} 4408 4409 4410 // Store Float 4411 4412 4413 instruct storeF( memoryF mem, regF src) %{ 4414 match(Set mem (StoreF mem src)); 4415 ins_cost(MEMORY_REF_COST); 4416 4417 size(4); 4418 format %{ "FSTS $src,$mem" %} 4419 ins_encode %{ 4420 __ str_float($src$$FloatRegister, $mem$$Address); 4421 %} 4422 ins_pipe(fstoreF_mem_reg); 4423 %} 4424 4425 4426 //----------MemBar Instructions----------------------------------------------- 4427 // Memory barrier flavors 4428 4429 // pattern-match out unnecessary membars 4430 instruct membar_storestore() %{ 4431 match(MemBarStoreStore); 4432 match(StoreStoreFence); 4433 ins_cost(4*MEMORY_REF_COST); 4434 4435 size(4); 4436 format %{ "MEMBAR-storestore" %} 4437 ins_encode %{ 4438 __ membar(MacroAssembler::Membar_mask_bits(MacroAssembler::StoreStore), noreg); 4439 %} 4440 ins_pipe(long_memory_op); 4441 %} 4442 4443 instruct membar_acquire() %{ 4444 match(MemBarAcquire); 4445 match(LoadFence); 4446 ins_cost(4*MEMORY_REF_COST); 4447 4448 size(4); 4449 format %{ "MEMBAR-acquire" %} 4450 ins_encode %{ 4451 __ membar(MacroAssembler::Membar_mask_bits(MacroAssembler::LoadLoad | MacroAssembler::LoadStore), noreg); 4452 %} 4453 ins_pipe(long_memory_op); 4454 %} 4455 4456 instruct membar_acquire_lock() %{ 4457 match(MemBarAcquireLock); 4458 ins_cost(0); 4459 4460 size(0); 4461 format %{ "!MEMBAR-acquire (CAS in prior FastLock so empty encoding)" %} 4462 ins_encode( ); 4463 ins_pipe(empty); 4464 %} 4465 4466 instruct membar_release() %{ 4467 match(MemBarRelease); 4468 match(StoreFence); 4469 ins_cost(4*MEMORY_REF_COST); 4470 4471 size(4); 4472 format %{ "MEMBAR-release" %} 4473 ins_encode %{ 4474 __ membar(MacroAssembler::Membar_mask_bits(MacroAssembler::StoreStore | MacroAssembler::LoadStore), noreg); 4475 %} 4476 ins_pipe(long_memory_op); 4477 %} 4478 4479 instruct membar_release_lock() %{ 4480 match(MemBarReleaseLock); 4481 ins_cost(0); 4482 4483 size(0); 4484 format %{ "!MEMBAR-release (CAS in succeeding FastUnlock so empty encoding)" %} 4485 ins_encode( ); 4486 ins_pipe(empty); 4487 %} 4488 4489 instruct membar_volatile() %{ 4490 match(MemBarVolatile); 4491 ins_cost(4*MEMORY_REF_COST); 4492 4493 size(4); 4494 format %{ "MEMBAR-volatile" %} 4495 ins_encode %{ 4496 __ membar(MacroAssembler::StoreLoad, noreg); 4497 %} 4498 ins_pipe(long_memory_op); 4499 %} 4500 4501 instruct unnecessary_membar_volatile() %{ 4502 match(MemBarVolatile); 4503 predicate(Matcher::post_store_load_barrier(n)); 4504 ins_cost(0); 4505 4506 size(0); 4507 format %{ "!MEMBAR-volatile (unnecessary so empty encoding)" %} 4508 ins_encode( ); 4509 ins_pipe(empty); 4510 %} 4511 4512 //----------Register Move Instructions----------------------------------------- 4513 4514 // Cast Index to Pointer for unsafe natives 4515 instruct castX2P(iRegX src, iRegP dst) %{ 4516 match(Set dst (CastX2P src)); 4517 4518 format %{ "MOV $dst,$src\t! IntX->Ptr if $dst != $src" %} 4519 ins_encode %{ 4520 if ($dst$$Register != $src$$Register) { 4521 __ mov($dst$$Register, $src$$Register); 4522 } 4523 %} 4524 ins_pipe(ialu_reg); 4525 %} 4526 4527 // Cast Pointer to Index for unsafe natives 4528 instruct castP2X(iRegP src, iRegX dst) %{ 4529 match(Set dst (CastP2X src)); 4530 4531 format %{ "MOV $dst,$src\t! Ptr->IntX if $dst != $src" %} 4532 ins_encode %{ 4533 if ($dst$$Register != $src$$Register) { 4534 __ mov($dst$$Register, $src$$Register); 4535 } 4536 %} 4537 ins_pipe(ialu_reg); 4538 %} 4539 4540 //----------Conditional Move--------------------------------------------------- 4541 // Conditional move 4542 instruct cmovIP_reg(cmpOpP cmp, flagsRegP pcc, iRegI dst, iRegI src) %{ 4543 match(Set dst (CMoveI (Binary cmp pcc) (Binary dst src))); 4544 ins_cost(150); 4545 size(4); 4546 format %{ "MOV$cmp $dst,$src\t! int" %} 4547 ins_encode %{ 4548 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 4549 %} 4550 ins_pipe(ialu_reg); 4551 %} 4552 4553 4554 instruct cmovIP_immMov(cmpOpP cmp, flagsRegP pcc, iRegI dst, immIMov src) %{ 4555 match(Set dst (CMoveI (Binary cmp pcc) (Binary dst src))); 4556 ins_cost(140); 4557 size(4); 4558 format %{ "MOV$cmp $dst,$src" %} 4559 ins_encode %{ 4560 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 4561 %} 4562 ins_pipe(ialu_imm); 4563 %} 4564 4565 instruct cmovIP_imm16(cmpOpP cmp, flagsRegP pcc, iRegI dst, immI16 src) %{ 4566 match(Set dst (CMoveI (Binary cmp pcc) (Binary dst src))); 4567 ins_cost(140); 4568 size(4); 4569 format %{ "MOVw$cmp $dst,$src" %} 4570 ins_encode %{ 4571 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 4572 %} 4573 ins_pipe(ialu_imm); 4574 %} 4575 4576 instruct cmovI_reg(cmpOp cmp, flagsReg icc, iRegI dst, iRegI src) %{ 4577 match(Set dst (CMoveI (Binary cmp icc) (Binary dst src))); 4578 ins_cost(150); 4579 size(4); 4580 format %{ "MOV$cmp $dst,$src" %} 4581 ins_encode %{ 4582 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 4583 %} 4584 ins_pipe(ialu_reg); 4585 %} 4586 4587 4588 instruct cmovI_immMov(cmpOp cmp, flagsReg icc, iRegI dst, immIMov src) %{ 4589 match(Set dst (CMoveI (Binary cmp icc) (Binary dst src))); 4590 ins_cost(140); 4591 size(4); 4592 format %{ "MOV$cmp $dst,$src" %} 4593 ins_encode %{ 4594 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 4595 %} 4596 ins_pipe(ialu_imm); 4597 %} 4598 4599 instruct cmovII_imm16(cmpOp cmp, flagsReg icc, iRegI dst, immI16 src) %{ 4600 match(Set dst (CMoveI (Binary cmp icc) (Binary dst src))); 4601 ins_cost(140); 4602 size(4); 4603 format %{ "MOVw$cmp $dst,$src" %} 4604 ins_encode %{ 4605 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 4606 %} 4607 ins_pipe(ialu_imm); 4608 %} 4609 4610 instruct cmovII_reg_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegI dst, iRegI src) %{ 4611 match(Set dst (CMoveI (Binary cmp icc) (Binary dst src))); 4612 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || 4613 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne || 4614 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || 4615 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge); 4616 ins_cost(150); 4617 size(4); 4618 format %{ "MOV$cmp $dst,$src" %} 4619 ins_encode %{ 4620 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 4621 %} 4622 ins_pipe(ialu_reg); 4623 %} 4624 4625 instruct cmovII_immMov_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegI dst, immIMov src) %{ 4626 match(Set dst (CMoveI (Binary cmp icc) (Binary dst src))); 4627 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || 4628 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne || 4629 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || 4630 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge); 4631 ins_cost(140); 4632 size(4); 4633 format %{ "MOV$cmp $dst,$src" %} 4634 ins_encode %{ 4635 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 4636 %} 4637 ins_pipe(ialu_imm); 4638 %} 4639 4640 instruct cmovII_imm16_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegI dst, immI16 src) %{ 4641 match(Set dst (CMoveI (Binary cmp icc) (Binary dst src))); 4642 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || 4643 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne || 4644 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || 4645 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge); 4646 ins_cost(140); 4647 size(4); 4648 format %{ "MOVW$cmp $dst,$src" %} 4649 ins_encode %{ 4650 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 4651 %} 4652 ins_pipe(ialu_imm); 4653 %} 4654 4655 instruct cmovIIu_reg(cmpOpU cmp, flagsRegU icc, iRegI dst, iRegI src) %{ 4656 match(Set dst (CMoveI (Binary cmp icc) (Binary dst src))); 4657 ins_cost(150); 4658 size(4); 4659 format %{ "MOV$cmp $dst,$src" %} 4660 ins_encode %{ 4661 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 4662 %} 4663 ins_pipe(ialu_reg); 4664 %} 4665 4666 instruct cmovIIu_immMov(cmpOpU cmp, flagsRegU icc, iRegI dst, immIMov src) %{ 4667 match(Set dst (CMoveI (Binary cmp icc) (Binary dst src))); 4668 ins_cost(140); 4669 size(4); 4670 format %{ "MOV$cmp $dst,$src" %} 4671 ins_encode %{ 4672 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 4673 %} 4674 ins_pipe(ialu_imm); 4675 %} 4676 4677 instruct cmovIIu_imm16(cmpOpU cmp, flagsRegU icc, iRegI dst, immI16 src) %{ 4678 match(Set dst (CMoveI (Binary cmp icc) (Binary dst src))); 4679 ins_cost(140); 4680 size(4); 4681 format %{ "MOVW$cmp $dst,$src" %} 4682 ins_encode %{ 4683 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 4684 %} 4685 ins_pipe(ialu_imm); 4686 %} 4687 4688 // Conditional move 4689 instruct cmovPP_reg(cmpOpP cmp, flagsRegP pcc, iRegP dst, iRegP src) %{ 4690 match(Set dst (CMoveP (Binary cmp pcc) (Binary dst src))); 4691 ins_cost(150); 4692 size(4); 4693 format %{ "MOV$cmp $dst,$src" %} 4694 ins_encode %{ 4695 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 4696 %} 4697 ins_pipe(ialu_reg); 4698 %} 4699 4700 instruct cmovPP_imm(cmpOpP cmp, flagsRegP pcc, iRegP dst, immP0 src) %{ 4701 match(Set dst (CMoveP (Binary cmp pcc) (Binary dst src))); 4702 ins_cost(140); 4703 size(4); 4704 format %{ "MOV$cmp $dst,$src" %} 4705 ins_encode %{ 4706 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 4707 %} 4708 ins_pipe(ialu_imm); 4709 %} 4710 4711 // This instruction also works with CmpN so we don't need cmovPN_reg. 4712 instruct cmovPI_reg(cmpOp cmp, flagsReg icc, iRegP dst, iRegP src) %{ 4713 match(Set dst (CMoveP (Binary cmp icc) (Binary dst src))); 4714 ins_cost(150); 4715 4716 size(4); 4717 format %{ "MOV$cmp $dst,$src\t! ptr" %} 4718 ins_encode %{ 4719 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 4720 %} 4721 ins_pipe(ialu_reg); 4722 %} 4723 4724 instruct cmovPI_reg_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegP dst, iRegP src) %{ 4725 match(Set dst (CMoveP (Binary cmp icc) (Binary dst src))); 4726 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || 4727 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne || 4728 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || 4729 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge); 4730 ins_cost(150); 4731 4732 size(4); 4733 format %{ "MOV$cmp $dst,$src\t! ptr" %} 4734 ins_encode %{ 4735 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 4736 %} 4737 ins_pipe(ialu_reg); 4738 %} 4739 4740 instruct cmovPIu_reg(cmpOpU cmp, flagsRegU icc, iRegP dst, iRegP src) %{ 4741 match(Set dst (CMoveP (Binary cmp icc) (Binary dst src))); 4742 ins_cost(150); 4743 4744 size(4); 4745 format %{ "MOV$cmp $dst,$src\t! ptr" %} 4746 ins_encode %{ 4747 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 4748 %} 4749 ins_pipe(ialu_reg); 4750 %} 4751 4752 instruct cmovPI_imm(cmpOp cmp, flagsReg icc, iRegP dst, immP0 src) %{ 4753 match(Set dst (CMoveP (Binary cmp icc) (Binary dst src))); 4754 ins_cost(140); 4755 4756 size(4); 4757 format %{ "MOV$cmp $dst,$src\t! ptr" %} 4758 ins_encode %{ 4759 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 4760 %} 4761 ins_pipe(ialu_imm); 4762 %} 4763 4764 instruct cmovPI_imm_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegP dst, immP0 src) %{ 4765 match(Set dst (CMoveP (Binary cmp icc) (Binary dst src))); 4766 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || 4767 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne || 4768 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || 4769 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge); 4770 ins_cost(140); 4771 4772 size(4); 4773 format %{ "MOV$cmp $dst,$src\t! ptr" %} 4774 ins_encode %{ 4775 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 4776 %} 4777 ins_pipe(ialu_imm); 4778 %} 4779 4780 instruct cmovPIu_imm(cmpOpU cmp, flagsRegU icc, iRegP dst, immP0 src) %{ 4781 match(Set dst (CMoveP (Binary cmp icc) (Binary dst src))); 4782 ins_cost(140); 4783 4784 size(4); 4785 format %{ "MOV$cmp $dst,$src\t! ptr" %} 4786 ins_encode %{ 4787 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 4788 %} 4789 ins_pipe(ialu_imm); 4790 %} 4791 4792 4793 // Conditional move 4794 instruct cmovFP_reg(cmpOpP cmp, flagsRegP pcc, regF dst, regF src) %{ 4795 match(Set dst (CMoveF (Binary cmp pcc) (Binary dst src))); 4796 ins_cost(150); 4797 size(4); 4798 format %{ "FCPYS$cmp $dst,$src" %} 4799 ins_encode %{ 4800 __ fcpys($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode)); 4801 %} 4802 ins_pipe(int_conditional_float_move); 4803 %} 4804 4805 instruct cmovFI_reg(cmpOp cmp, flagsReg icc, regF dst, regF src) %{ 4806 match(Set dst (CMoveF (Binary cmp icc) (Binary dst src))); 4807 ins_cost(150); 4808 4809 size(4); 4810 format %{ "FCPYS$cmp $dst,$src" %} 4811 ins_encode %{ 4812 __ fcpys($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode)); 4813 %} 4814 ins_pipe(int_conditional_float_move); 4815 %} 4816 4817 instruct cmovFI_reg_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, regF dst, regF src) %{ 4818 match(Set dst (CMoveF (Binary cmp icc) (Binary dst src))); 4819 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || 4820 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne || 4821 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || 4822 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge); 4823 ins_cost(150); 4824 4825 size(4); 4826 format %{ "FCPYS$cmp $dst,$src" %} 4827 ins_encode %{ 4828 __ fcpys($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode)); 4829 %} 4830 ins_pipe(int_conditional_float_move); 4831 %} 4832 4833 instruct cmovFIu_reg(cmpOpU cmp, flagsRegU icc, regF dst, regF src) %{ 4834 match(Set dst (CMoveF (Binary cmp icc) (Binary dst src))); 4835 ins_cost(150); 4836 4837 size(4); 4838 format %{ "FCPYS$cmp $dst,$src" %} 4839 ins_encode %{ 4840 __ fcpys($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode)); 4841 %} 4842 ins_pipe(int_conditional_float_move); 4843 %} 4844 4845 // Conditional move 4846 instruct cmovDP_reg(cmpOpP cmp, flagsRegP pcc, regD dst, regD src) %{ 4847 match(Set dst (CMoveD (Binary cmp pcc) (Binary dst src))); 4848 ins_cost(150); 4849 size(4); 4850 format %{ "FCPYD$cmp $dst,$src" %} 4851 ins_encode %{ 4852 __ fcpyd($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode)); 4853 %} 4854 ins_pipe(int_conditional_double_move); 4855 %} 4856 4857 instruct cmovDI_reg(cmpOp cmp, flagsReg icc, regD dst, regD src) %{ 4858 match(Set dst (CMoveD (Binary cmp icc) (Binary dst src))); 4859 ins_cost(150); 4860 4861 size(4); 4862 format %{ "FCPYD$cmp $dst,$src" %} 4863 ins_encode %{ 4864 __ fcpyd($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode)); 4865 %} 4866 ins_pipe(int_conditional_double_move); 4867 %} 4868 4869 instruct cmovDI_reg_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, regD dst, regD src) %{ 4870 match(Set dst (CMoveD (Binary cmp icc) (Binary dst src))); 4871 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); 4872 ins_cost(150); 4873 4874 size(4); 4875 format %{ "FCPYD$cmp $dst,$src" %} 4876 ins_encode %{ 4877 __ fcpyd($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode)); 4878 %} 4879 ins_pipe(int_conditional_double_move); 4880 %} 4881 4882 instruct cmovDIu_reg(cmpOpU cmp, flagsRegU icc, regD dst, regD src) %{ 4883 match(Set dst (CMoveD (Binary cmp icc) (Binary dst src))); 4884 ins_cost(150); 4885 4886 size(4); 4887 format %{ "FCPYD$cmp $dst,$src" %} 4888 ins_encode %{ 4889 __ fcpyd($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode)); 4890 %} 4891 ins_pipe(int_conditional_double_move); 4892 %} 4893 4894 // Conditional move 4895 instruct cmovLP_reg(cmpOpP cmp, flagsRegP pcc, iRegL dst, iRegL src) %{ 4896 match(Set dst (CMoveL (Binary cmp pcc) (Binary dst src))); 4897 ins_cost(150); 4898 4899 size(8); 4900 format %{ "MOV$cmp $dst.lo,$src.lo\t! long\n\t" 4901 "MOV$cmp $dst.hi,$src.hi" %} 4902 ins_encode %{ 4903 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 4904 __ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode)); 4905 %} 4906 ins_pipe(ialu_reg); 4907 %} 4908 4909 // TODO: try immLRot2 instead, (0, $con$$constant) becomes 4910 // (hi($con$$constant), lo($con$$constant)) becomes 4911 instruct cmovLP_immRot(cmpOpP cmp, flagsRegP pcc, iRegL dst, immLlowRot src) %{ 4912 match(Set dst (CMoveL (Binary cmp pcc) (Binary dst src))); 4913 ins_cost(140); 4914 4915 size(8); 4916 format %{ "MOV$cmp $dst.lo,$src\t! long\n\t" 4917 "MOV$cmp $dst.hi,0" %} 4918 ins_encode %{ 4919 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 4920 __ mov($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode)); 4921 %} 4922 ins_pipe(ialu_imm); 4923 %} 4924 4925 instruct cmovLP_imm16(cmpOpP cmp, flagsRegP pcc, iRegL dst, immL16 src) %{ 4926 match(Set dst (CMoveL (Binary cmp pcc) (Binary dst src))); 4927 ins_cost(140); 4928 4929 size(8); 4930 format %{ "MOV$cmp $dst.lo,$src\t! long\n\t" 4931 "MOV$cmp $dst.hi,0" %} 4932 ins_encode %{ 4933 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 4934 __ mov($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode)); 4935 %} 4936 ins_pipe(ialu_imm); 4937 %} 4938 4939 instruct cmovLI_reg(cmpOp cmp, flagsReg icc, iRegL dst, iRegL src) %{ 4940 match(Set dst (CMoveL (Binary cmp icc) (Binary dst src))); 4941 ins_cost(150); 4942 4943 size(8); 4944 format %{ "MOV$cmp $dst.lo,$src.lo\t! long\n\t" 4945 "MOV$cmp $dst.hi,$src.hi" %} 4946 ins_encode %{ 4947 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 4948 __ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode)); 4949 %} 4950 ins_pipe(ialu_reg); 4951 %} 4952 4953 instruct cmovLI_reg_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegL dst, iRegL src) %{ 4954 match(Set dst (CMoveL (Binary cmp icc) (Binary dst src))); 4955 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || 4956 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne || 4957 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || 4958 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge); 4959 ins_cost(150); 4960 4961 size(8); 4962 format %{ "MOV$cmp $dst.lo,$src.lo\t! long\n\t" 4963 "MOV$cmp $dst.hi,$src.hi" %} 4964 ins_encode %{ 4965 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 4966 __ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode)); 4967 %} 4968 ins_pipe(ialu_reg); 4969 %} 4970 4971 // TODO: try immLRot2 instead, (0, $con$$constant) becomes 4972 // (hi($con$$constant), lo($con$$constant)) becomes 4973 instruct cmovLI_immRot(cmpOp cmp, flagsReg icc, iRegL dst, immLlowRot src) %{ 4974 match(Set dst (CMoveL (Binary cmp icc) (Binary dst src))); 4975 ins_cost(140); 4976 4977 size(8); 4978 format %{ "MOV$cmp $dst.lo,$src\t! long\n\t" 4979 "MOV$cmp $dst.hi,0" %} 4980 ins_encode %{ 4981 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 4982 __ mov($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode)); 4983 %} 4984 ins_pipe(ialu_imm); 4985 %} 4986 4987 // TODO: try immLRot2 instead, (0, $con$$constant) becomes 4988 // (hi($con$$constant), lo($con$$constant)) becomes 4989 instruct cmovLI_immRot_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegL dst, immLlowRot src) %{ 4990 match(Set dst (CMoveL (Binary cmp icc) (Binary dst src))); 4991 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || 4992 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne || 4993 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || 4994 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge); 4995 ins_cost(140); 4996 4997 size(8); 4998 format %{ "MOV$cmp $dst.lo,$src\t! long\n\t" 4999 "MOV$cmp $dst.hi,0" %} 5000 ins_encode %{ 5001 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 5002 __ mov($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode)); 5003 %} 5004 ins_pipe(ialu_imm); 5005 %} 5006 5007 instruct cmovLI_imm16(cmpOp cmp, flagsReg icc, iRegL dst, immL16 src) %{ 5008 match(Set dst (CMoveL (Binary cmp icc) (Binary dst src))); 5009 ins_cost(140); 5010 5011 size(8); 5012 format %{ "MOV$cmp $dst.lo,$src\t! long\n\t" 5013 "MOV$cmp $dst.hi,0" %} 5014 ins_encode %{ 5015 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 5016 __ movw($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode)); 5017 %} 5018 ins_pipe(ialu_imm); 5019 %} 5020 5021 instruct cmovLI_imm16_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegL dst, immL16 src) %{ 5022 match(Set dst (CMoveL (Binary cmp icc) (Binary dst src))); 5023 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || 5024 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne || 5025 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || 5026 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge); 5027 ins_cost(140); 5028 5029 size(8); 5030 format %{ "MOV$cmp $dst.lo,$src\t! long\n\t" 5031 "MOV$cmp $dst.hi,0" %} 5032 ins_encode %{ 5033 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 5034 __ movw($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode)); 5035 %} 5036 ins_pipe(ialu_imm); 5037 %} 5038 5039 instruct cmovLIu_reg(cmpOpU cmp, flagsRegU icc, iRegL dst, iRegL src) %{ 5040 match(Set dst (CMoveL (Binary cmp icc) (Binary dst src))); 5041 ins_cost(150); 5042 5043 size(8); 5044 format %{ "MOV$cmp $dst.lo,$src.lo\t! long\n\t" 5045 "MOV$cmp $dst.hi,$src.hi" %} 5046 ins_encode %{ 5047 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 5048 __ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode)); 5049 %} 5050 ins_pipe(ialu_reg); 5051 %} 5052 5053 5054 //----------OS and Locking Instructions---------------------------------------- 5055 5056 // This name is KNOWN by the ADLC and cannot be changed. 5057 // The ADLC forces a 'TypeRawPtr::BOTTOM' output type 5058 // for this guy. 5059 instruct tlsLoadP(RthreadRegP dst) %{ 5060 match(Set dst (ThreadLocal)); 5061 5062 size(0); 5063 ins_cost(0); 5064 format %{ "! TLS is in $dst" %} 5065 ins_encode( /*empty encoding*/ ); 5066 ins_pipe(ialu_none); 5067 %} 5068 5069 instruct checkCastPP( iRegP dst ) %{ 5070 match(Set dst (CheckCastPP dst)); 5071 5072 size(0); 5073 format %{ "! checkcastPP of $dst" %} 5074 ins_encode( /*empty encoding*/ ); 5075 ins_pipe(empty); 5076 %} 5077 5078 5079 instruct castPP( iRegP dst ) %{ 5080 match(Set dst (CastPP dst)); 5081 format %{ "! castPP of $dst" %} 5082 ins_encode( /*empty encoding*/ ); 5083 ins_pipe(empty); 5084 %} 5085 5086 instruct castII( iRegI dst ) %{ 5087 match(Set dst (CastII dst)); 5088 format %{ "! castII of $dst" %} 5089 ins_encode( /*empty encoding*/ ); 5090 ins_cost(0); 5091 ins_pipe(empty); 5092 %} 5093 5094 instruct castLL( iRegL dst ) %{ 5095 match(Set dst (CastLL dst)); 5096 format %{ "! castLL of $dst" %} 5097 ins_encode( /*empty encoding*/ ); 5098 ins_cost(0); 5099 ins_pipe(empty); 5100 %} 5101 5102 instruct castFF( regF dst ) %{ 5103 match(Set dst (CastFF dst)); 5104 format %{ "! castFF of $dst" %} 5105 ins_encode( /*empty encoding*/ ); 5106 ins_cost(0); 5107 ins_pipe(empty); 5108 %} 5109 5110 instruct castDD( regD dst ) %{ 5111 match(Set dst (CastDD dst)); 5112 format %{ "! castDD of $dst" %} 5113 ins_encode( /*empty encoding*/ ); 5114 ins_cost(0); 5115 ins_pipe(empty); 5116 %} 5117 5118 instruct castVVD( vecD dst ) %{ 5119 match(Set dst (CastVV dst)); 5120 format %{ "! castVV of $dst" %} 5121 ins_encode( /*empty encoding*/ ); 5122 ins_cost(0); 5123 ins_pipe(empty); 5124 %} 5125 5126 instruct castVVX( vecX dst ) %{ 5127 match(Set dst (CastVV dst)); 5128 format %{ "! castVV of $dst" %} 5129 ins_encode( /*empty encoding*/ ); 5130 ins_cost(0); 5131 ins_pipe(empty); 5132 %} 5133 5134 5135 //----------Arithmetic Instructions-------------------------------------------- 5136 // Addition Instructions 5137 // Register Addition 5138 instruct addI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{ 5139 match(Set dst (AddI src1 src2)); 5140 5141 size(4); 5142 format %{ "add_32 $dst,$src1,$src2\t! int" %} 5143 ins_encode %{ 5144 __ add_32($dst$$Register, $src1$$Register, $src2$$Register); 5145 %} 5146 ins_pipe(ialu_reg_reg); 5147 %} 5148 5149 instruct addshlI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 5150 match(Set dst (AddI (LShiftI src1 src2) src3)); 5151 5152 size(4); 5153 format %{ "add_32 $dst,$src3,$src1<<$src2\t! int" %} 5154 ins_encode %{ 5155 __ add_32($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsl, $src2$$Register)); 5156 %} 5157 ins_pipe(ialu_reg_reg); 5158 %} 5159 5160 5161 instruct addshlI_reg_imm_reg(iRegI dst, iRegI src1, immU5 src2, iRegI src3) %{ 5162 match(Set dst (AddI (LShiftI src1 src2) src3)); 5163 5164 size(4); 5165 format %{ "add_32 $dst,$src3,$src1<<$src2\t! int" %} 5166 ins_encode %{ 5167 __ add_32($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsl, $src2$$constant)); 5168 %} 5169 ins_pipe(ialu_reg_reg); 5170 %} 5171 5172 instruct addsarI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 5173 match(Set dst (AddI (RShiftI src1 src2) src3)); 5174 5175 size(4); 5176 format %{ "add_32 $dst,$src3,$src1>>$src2\t! int" %} 5177 ins_encode %{ 5178 __ add_32($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, asr, $src2$$Register)); 5179 %} 5180 ins_pipe(ialu_reg_reg); 5181 %} 5182 5183 instruct addsarI_reg_imm_reg(iRegI dst, iRegI src1, immU5 src2, iRegI src3) %{ 5184 match(Set dst (AddI (RShiftI src1 src2) src3)); 5185 5186 size(4); 5187 format %{ "add_32 $dst,$src3,$src1>>$src2\t! int" %} 5188 ins_encode %{ 5189 __ add_32($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, asr, $src2$$constant)); 5190 %} 5191 ins_pipe(ialu_reg_reg); 5192 %} 5193 5194 instruct addshrI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 5195 match(Set dst (AddI (URShiftI src1 src2) src3)); 5196 5197 size(4); 5198 format %{ "add_32 $dst,$src3,$src1>>>$src2\t! int" %} 5199 ins_encode %{ 5200 __ add_32($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsr, $src2$$Register)); 5201 %} 5202 ins_pipe(ialu_reg_reg); 5203 %} 5204 5205 instruct addshrI_reg_imm_reg(iRegI dst, iRegI src1, immU5 src2, iRegI src3) %{ 5206 match(Set dst (AddI (URShiftI src1 src2) src3)); 5207 5208 size(4); 5209 format %{ "add_32 $dst,$src3,$src1>>>$src2\t! int" %} 5210 ins_encode %{ 5211 __ add_32($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsr, $src2$$constant)); 5212 %} 5213 ins_pipe(ialu_reg_reg); 5214 %} 5215 5216 // Immediate Addition 5217 instruct addI_reg_aimmI(iRegI dst, iRegI src1, aimmI src2) %{ 5218 match(Set dst (AddI src1 src2)); 5219 5220 size(4); 5221 format %{ "add_32 $dst,$src1,$src2\t! int" %} 5222 ins_encode %{ 5223 __ add_32($dst$$Register, $src1$$Register, $src2$$constant); 5224 %} 5225 ins_pipe(ialu_reg_imm); 5226 %} 5227 5228 // Pointer Register Addition 5229 instruct addP_reg_reg(iRegP dst, iRegP src1, iRegX src2) %{ 5230 match(Set dst (AddP src1 src2)); 5231 5232 size(4); 5233 format %{ "ADD $dst,$src1,$src2\t! ptr" %} 5234 ins_encode %{ 5235 __ add($dst$$Register, $src1$$Register, $src2$$Register); 5236 %} 5237 ins_pipe(ialu_reg_reg); 5238 %} 5239 5240 5241 // shifted iRegX operand 5242 operand shiftedX(iRegX src2, shimmX src3) %{ 5243 //constraint(ALLOC_IN_RC(sp_ptr_reg)); 5244 match(LShiftX src2 src3); 5245 5246 op_cost(1); 5247 format %{ "$src2 << $src3" %} 5248 interface(MEMORY_INTER) %{ 5249 base($src2); 5250 index(0xff); 5251 scale($src3); 5252 disp(0x0); 5253 %} 5254 %} 5255 5256 instruct addshlP_reg_reg_imm(iRegP dst, iRegP src1, shiftedX src2) %{ 5257 match(Set dst (AddP src1 src2)); 5258 5259 ins_cost(DEFAULT_COST * 3/2); 5260 size(4); 5261 format %{ "ADD $dst,$src1,$src2\t! ptr" %} 5262 ins_encode %{ 5263 Register base = reg_to_register_object($src2$$base); 5264 __ add($dst$$Register, $src1$$Register, AsmOperand(base, lsl, $src2$$scale)); 5265 %} 5266 ins_pipe(ialu_reg_reg); 5267 %} 5268 5269 // Pointer Immediate Addition 5270 instruct addP_reg_aimmX(iRegP dst, iRegP src1, aimmX src2) %{ 5271 match(Set dst (AddP src1 src2)); 5272 5273 size(4); 5274 format %{ "ADD $dst,$src1,$src2\t! ptr" %} 5275 ins_encode %{ 5276 __ add($dst$$Register, $src1$$Register, $src2$$constant); 5277 %} 5278 ins_pipe(ialu_reg_imm); 5279 %} 5280 5281 // Long Addition 5282 instruct addL_reg_reg(iRegL dst, iRegL src1, iRegL src2, flagsReg ccr) %{ 5283 match(Set dst (AddL src1 src2)); 5284 effect(KILL ccr); 5285 size(8); 5286 format %{ "ADDS $dst.lo,$src1.lo,$src2.lo\t! long\n\t" 5287 "ADC $dst.hi,$src1.hi,$src2.hi" %} 5288 ins_encode %{ 5289 __ adds($dst$$Register, $src1$$Register, $src2$$Register); 5290 __ adc($dst$$Register->successor(), $src1$$Register->successor(), $src2$$Register->successor()); 5291 %} 5292 ins_pipe(ialu_reg_reg); 5293 %} 5294 5295 // TODO 5296 5297 // TODO: try immLRot2 instead, (0, $con$$constant) becomes 5298 // (hi($con$$constant), lo($con$$constant)) becomes 5299 instruct addL_reg_immRot(iRegL dst, iRegL src1, immLlowRot con, flagsReg ccr) %{ 5300 match(Set dst (AddL src1 con)); 5301 effect(KILL ccr); 5302 size(8); 5303 format %{ "ADDS $dst.lo,$src1.lo,$con\t! long\n\t" 5304 "ADC $dst.hi,$src1.hi,0" %} 5305 ins_encode %{ 5306 __ adds($dst$$Register, $src1$$Register, $con$$constant); 5307 __ adc($dst$$Register->successor(), $src1$$Register->successor(), 0); 5308 %} 5309 ins_pipe(ialu_reg_imm); 5310 %} 5311 5312 // No flag versions for CompareAndSwap{P,I,L} because matcher can't match them 5313 5314 instruct compareAndSwapL_bool(memoryex mem, iRegL oldval, iRegLd newval, iRegI res, iRegLd tmp, flagsReg ccr ) %{ 5315 match(Set res (CompareAndSwapL mem (Binary oldval newval))); 5316 effect( KILL ccr, TEMP tmp); 5317 size(32); 5318 format %{ "loop: \n\t" 5319 "LDREXD $tmp, $mem\t! If $oldval==[$mem] Then store $newval into [$mem]\n\t" 5320 "CMP $tmp.lo, $oldval.lo\n\t" 5321 "CMP.eq $tmp.hi, $oldval.hi\n\t" 5322 "STREXD.eq $tmp, $newval, $mem\n\t" 5323 "MOV.ne $tmp, 0 \n\t" 5324 "XORS.eq $tmp,$tmp, 1 \n\t" 5325 "B.eq loop \n\t" 5326 "MOV $res, $tmp" %} 5327 ins_encode %{ 5328 Label loop; 5329 __ bind(loop); 5330 __ ldrexd($tmp$$Register, $mem$$Address); 5331 __ cmp($tmp$$Register, $oldval$$Register); 5332 __ cmp($tmp$$Register->successor(), $oldval$$Register->successor(), eq); 5333 __ strexd($tmp$$Register, $newval$$Register, $mem$$Address, eq); 5334 __ mov($tmp$$Register, 0, ne); 5335 __ eors($tmp$$Register, $tmp$$Register, 1, eq); 5336 __ b(loop, eq); 5337 __ mov($res$$Register, $tmp$$Register); 5338 %} 5339 ins_pipe( long_memory_op ); 5340 %} 5341 5342 5343 instruct compareAndSwapI_bool(memoryex mem, iRegI oldval, iRegI newval, iRegI res, iRegI tmp, flagsReg ccr ) %{ 5344 match(Set res (CompareAndSwapI mem (Binary oldval newval))); 5345 effect( KILL ccr, TEMP tmp); 5346 size(28); 5347 format %{ "loop: \n\t" 5348 "LDREX $tmp, $mem\t! If $oldval==[$mem] Then store $newval into [$mem]\n\t" 5349 "CMP $tmp, $oldval\n\t" 5350 "STREX.eq $tmp, $newval, $mem\n\t" 5351 "MOV.ne $tmp, 0 \n\t" 5352 "XORS.eq $tmp,$tmp, 1 \n\t" 5353 "B.eq loop \n\t" 5354 "MOV $res, $tmp" %} 5355 5356 ins_encode %{ 5357 Label loop; 5358 __ bind(loop); 5359 __ ldrex($tmp$$Register,$mem$$Address); 5360 __ cmp($tmp$$Register, $oldval$$Register); 5361 __ strex($tmp$$Register, $newval$$Register, $mem$$Address, eq); 5362 __ mov($tmp$$Register, 0, ne); 5363 __ eors($tmp$$Register, $tmp$$Register, 1, eq); 5364 __ b(loop, eq); 5365 __ mov($res$$Register, $tmp$$Register); 5366 %} 5367 ins_pipe( long_memory_op ); 5368 %} 5369 5370 instruct compareAndSwapP_bool(memoryex mem, iRegP oldval, iRegP newval, iRegI res, iRegI tmp, flagsReg ccr ) %{ 5371 predicate(!(UseG1GC && n->as_LoadStore()->barrier_data() != 0)); 5372 match(Set res (CompareAndSwapP mem (Binary oldval newval))); 5373 effect( KILL ccr, TEMP tmp); 5374 size(28); 5375 format %{ "loop: \n\t" 5376 "LDREX $tmp, $mem\t! If $oldval==[$mem] Then store $newval into [$mem]\n\t" 5377 "CMP $tmp, $oldval\n\t" 5378 "STREX.eq $tmp, $newval, $mem\n\t" 5379 "MOV.ne $tmp, 0 \n\t" 5380 "EORS.eq $tmp,$tmp, 1 \n\t" 5381 "B.eq loop \n\t" 5382 "MOV $res, $tmp" %} 5383 5384 ins_encode %{ 5385 Label loop; 5386 __ bind(loop); 5387 __ ldrex($tmp$$Register,$mem$$Address); 5388 __ cmp($tmp$$Register, $oldval$$Register); 5389 __ strex($tmp$$Register, $newval$$Register, $mem$$Address, eq); 5390 __ mov($tmp$$Register, 0, ne); 5391 __ eors($tmp$$Register, $tmp$$Register, 1, eq); 5392 __ b(loop, eq); 5393 __ mov($res$$Register, $tmp$$Register); 5394 %} 5395 ins_pipe( long_memory_op ); 5396 %} 5397 5398 instruct xaddI_aimmI_no_res(memoryex mem, aimmI add, Universe dummy, iRegI tmp1, iRegI tmp2, flagsReg ccr) %{ 5399 predicate(n->as_LoadStore()->result_not_used()); 5400 match(Set dummy (GetAndAddI mem add)); 5401 effect(KILL ccr, TEMP tmp1, TEMP tmp2); 5402 size(20); 5403 format %{ "loop: \n\t" 5404 "LDREX $tmp1, $mem\n\t" 5405 "ADD $tmp1, $tmp1, $add\n\t" 5406 "STREX $tmp2, $tmp1, $mem\n\t" 5407 "CMP $tmp2, 0 \n\t" 5408 "B.ne loop \n\t" %} 5409 5410 ins_encode %{ 5411 Label loop; 5412 __ bind(loop); 5413 __ ldrex($tmp1$$Register,$mem$$Address); 5414 __ add($tmp1$$Register, $tmp1$$Register, $add$$constant); 5415 __ strex($tmp2$$Register, $tmp1$$Register, $mem$$Address); 5416 __ cmp($tmp2$$Register, 0); 5417 __ b(loop, ne); 5418 %} 5419 ins_pipe( long_memory_op ); 5420 %} 5421 5422 instruct xaddI_reg_no_res(memoryex mem, iRegI add, Universe dummy, iRegI tmp1, iRegI tmp2, flagsReg ccr) %{ 5423 predicate(n->as_LoadStore()->result_not_used()); 5424 match(Set dummy (GetAndAddI mem add)); 5425 effect(KILL ccr, TEMP tmp1, TEMP tmp2); 5426 size(20); 5427 format %{ "loop: \n\t" 5428 "LDREX $tmp1, $mem\n\t" 5429 "ADD $tmp1, $tmp1, $add\n\t" 5430 "STREX $tmp2, $tmp1, $mem\n\t" 5431 "CMP $tmp2, 0 \n\t" 5432 "B.ne loop \n\t" %} 5433 5434 ins_encode %{ 5435 Label loop; 5436 __ bind(loop); 5437 __ ldrex($tmp1$$Register,$mem$$Address); 5438 __ add($tmp1$$Register, $tmp1$$Register, $add$$Register); 5439 __ strex($tmp2$$Register, $tmp1$$Register, $mem$$Address); 5440 __ cmp($tmp2$$Register, 0); 5441 __ b(loop, ne); 5442 %} 5443 ins_pipe( long_memory_op ); 5444 %} 5445 5446 instruct xaddI_aimmI(memoryex mem, aimmI add, iRegI res, iRegI tmp1, iRegI tmp2, flagsReg ccr) %{ 5447 match(Set res (GetAndAddI mem add)); 5448 effect(KILL ccr, TEMP tmp1, TEMP tmp2, TEMP res); 5449 size(20); 5450 format %{ "loop: \n\t" 5451 "LDREX $res, $mem\n\t" 5452 "ADD $tmp1, $res, $add\n\t" 5453 "STREX $tmp2, $tmp1, $mem\n\t" 5454 "CMP $tmp2, 0 \n\t" 5455 "B.ne loop \n\t" %} 5456 5457 ins_encode %{ 5458 Label loop; 5459 __ bind(loop); 5460 __ ldrex($res$$Register,$mem$$Address); 5461 __ add($tmp1$$Register, $res$$Register, $add$$constant); 5462 __ strex($tmp2$$Register, $tmp1$$Register, $mem$$Address); 5463 __ cmp($tmp2$$Register, 0); 5464 __ b(loop, ne); 5465 %} 5466 ins_pipe( long_memory_op ); 5467 %} 5468 5469 instruct xaddI_reg(memoryex mem, iRegI add, iRegI res, iRegI tmp1, iRegI tmp2, flagsReg ccr) %{ 5470 match(Set res (GetAndAddI mem add)); 5471 effect(KILL ccr, TEMP tmp1, TEMP tmp2, TEMP res); 5472 size(20); 5473 format %{ "loop: \n\t" 5474 "LDREX $res, $mem\n\t" 5475 "ADD $tmp1, $res, $add\n\t" 5476 "STREX $tmp2, $tmp1, $mem\n\t" 5477 "CMP $tmp2, 0 \n\t" 5478 "B.ne loop \n\t" %} 5479 5480 ins_encode %{ 5481 Label loop; 5482 __ bind(loop); 5483 __ ldrex($res$$Register,$mem$$Address); 5484 __ add($tmp1$$Register, $res$$Register, $add$$Register); 5485 __ strex($tmp2$$Register, $tmp1$$Register, $mem$$Address); 5486 __ cmp($tmp2$$Register, 0); 5487 __ b(loop, ne); 5488 %} 5489 ins_pipe( long_memory_op ); 5490 %} 5491 5492 instruct xaddL_reg_no_res(memoryex mem, iRegL add, Universe dummy, iRegLd tmp1, iRegI tmp2, flagsReg ccr) %{ 5493 predicate(n->as_LoadStore()->result_not_used()); 5494 match(Set dummy (GetAndAddL mem add)); 5495 effect( KILL ccr, TEMP tmp1, TEMP tmp2); 5496 size(24); 5497 format %{ "loop: \n\t" 5498 "LDREXD $tmp1, $mem\n\t" 5499 "ADDS $tmp1.lo, $tmp1.lo, $add.lo\n\t" 5500 "ADC $tmp1.hi, $tmp1.hi, $add.hi\n\t" 5501 "STREXD $tmp2, $tmp1, $mem\n\t" 5502 "CMP $tmp2, 0 \n\t" 5503 "B.ne loop \n\t" %} 5504 5505 ins_encode %{ 5506 Label loop; 5507 __ bind(loop); 5508 __ ldrexd($tmp1$$Register, $mem$$Address); 5509 __ adds($tmp1$$Register, $tmp1$$Register, $add$$Register); 5510 __ adc($tmp1$$Register->successor(), $tmp1$$Register->successor(), $add$$Register->successor()); 5511 __ strexd($tmp2$$Register, $tmp1$$Register, $mem$$Address); 5512 __ cmp($tmp2$$Register, 0); 5513 __ b(loop, ne); 5514 %} 5515 ins_pipe( long_memory_op ); 5516 %} 5517 5518 // TODO: try immLRot2 instead, (0, $con$$constant) becomes 5519 // (hi($con$$constant), lo($con$$constant)) becomes 5520 instruct xaddL_immRot_no_res(memoryex mem, immLlowRot add, Universe dummy, iRegLd tmp1, iRegI tmp2, flagsReg ccr) %{ 5521 predicate(n->as_LoadStore()->result_not_used()); 5522 match(Set dummy (GetAndAddL mem add)); 5523 effect( KILL ccr, TEMP tmp1, TEMP tmp2); 5524 size(24); 5525 format %{ "loop: \n\t" 5526 "LDREXD $tmp1, $mem\n\t" 5527 "ADDS $tmp1.lo, $tmp1.lo, $add\n\t" 5528 "ADC $tmp1.hi, $tmp1.hi, 0\n\t" 5529 "STREXD $tmp2, $tmp1, $mem\n\t" 5530 "CMP $tmp2, 0 \n\t" 5531 "B.ne loop \n\t" %} 5532 5533 ins_encode %{ 5534 Label loop; 5535 __ bind(loop); 5536 __ ldrexd($tmp1$$Register, $mem$$Address); 5537 __ adds($tmp1$$Register, $tmp1$$Register, $add$$constant); 5538 __ adc($tmp1$$Register->successor(), $tmp1$$Register->successor(), 0); 5539 __ strexd($tmp2$$Register, $tmp1$$Register, $mem$$Address); 5540 __ cmp($tmp2$$Register, 0); 5541 __ b(loop, ne); 5542 %} 5543 ins_pipe( long_memory_op ); 5544 %} 5545 5546 instruct xaddL_reg(memoryex mem, iRegL 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.lo\n\t" 5553 "ADC $tmp1.hi, $res.hi, $add.hi\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$$Register); 5563 __ adc($tmp1$$Register->successor(), $res$$Register->successor(), $add$$Register->successor()); 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 // TODO: try immLRot2 instead, (0, $con$$constant) becomes 5572 // (hi($con$$constant), lo($con$$constant)) becomes 5573 instruct xaddL_immRot(memoryex mem, immLlowRot add, iRegLd res, iRegLd tmp1, iRegI tmp2, flagsReg ccr) %{ 5574 match(Set res (GetAndAddL mem add)); 5575 effect( KILL ccr, TEMP tmp1, TEMP tmp2, TEMP res); 5576 size(24); 5577 format %{ "loop: \n\t" 5578 "LDREXD $res, $mem\n\t" 5579 "ADDS $tmp1.lo, $res.lo, $add\n\t" 5580 "ADC $tmp1.hi, $res.hi, 0\n\t" 5581 "STREXD $tmp2, $tmp1, $mem\n\t" 5582 "CMP $tmp2, 0 \n\t" 5583 "B.ne loop \n\t" %} 5584 5585 ins_encode %{ 5586 Label loop; 5587 __ bind(loop); 5588 __ ldrexd($res$$Register, $mem$$Address); 5589 __ adds($tmp1$$Register, $res$$Register, $add$$constant); 5590 __ adc($tmp1$$Register->successor(), $res$$Register->successor(), 0); 5591 __ strexd($tmp2$$Register, $tmp1$$Register, $mem$$Address); 5592 __ cmp($tmp2$$Register, 0); 5593 __ b(loop, ne); 5594 %} 5595 ins_pipe( long_memory_op ); 5596 %} 5597 5598 instruct xchgI(memoryex mem, iRegI newval, iRegI res, iRegI tmp, flagsReg ccr) %{ 5599 match(Set res (GetAndSetI mem newval)); 5600 effect(KILL ccr, TEMP tmp, TEMP res); 5601 size(16); 5602 format %{ "loop: \n\t" 5603 "LDREX $res, $mem\n\t" 5604 "STREX $tmp, $newval, $mem\n\t" 5605 "CMP $tmp, 0 \n\t" 5606 "B.ne loop \n\t" %} 5607 5608 ins_encode %{ 5609 Label loop; 5610 __ bind(loop); 5611 __ ldrex($res$$Register,$mem$$Address); 5612 __ strex($tmp$$Register, $newval$$Register, $mem$$Address); 5613 __ cmp($tmp$$Register, 0); 5614 __ b(loop, ne); 5615 %} 5616 ins_pipe( long_memory_op ); 5617 %} 5618 5619 instruct xchgL(memoryex mem, iRegLd newval, iRegLd res, iRegI tmp, flagsReg ccr) %{ 5620 match(Set res (GetAndSetL mem newval)); 5621 effect( KILL ccr, TEMP tmp, TEMP res); 5622 size(16); 5623 format %{ "loop: \n\t" 5624 "LDREXD $res, $mem\n\t" 5625 "STREXD $tmp, $newval, $mem\n\t" 5626 "CMP $tmp, 0 \n\t" 5627 "B.ne loop \n\t" %} 5628 5629 ins_encode %{ 5630 Label loop; 5631 __ bind(loop); 5632 __ ldrexd($res$$Register, $mem$$Address); 5633 __ strexd($tmp$$Register, $newval$$Register, $mem$$Address); 5634 __ cmp($tmp$$Register, 0); 5635 __ b(loop, ne); 5636 %} 5637 ins_pipe( long_memory_op ); 5638 %} 5639 5640 instruct xchgP(memoryex mem, iRegP newval, iRegP res, iRegI tmp, flagsReg ccr) %{ 5641 predicate(!(UseG1GC && n->as_LoadStore()->barrier_data() != 0)); 5642 match(Set res (GetAndSetP mem newval)); 5643 effect(KILL ccr, TEMP tmp, TEMP res); 5644 size(16); 5645 format %{ "loop: \n\t" 5646 "LDREX $res, $mem\n\t" 5647 "STREX $tmp, $newval, $mem\n\t" 5648 "CMP $tmp, 0 \n\t" 5649 "B.ne loop \n\t" %} 5650 5651 ins_encode %{ 5652 Label loop; 5653 __ bind(loop); 5654 __ ldrex($res$$Register,$mem$$Address); 5655 __ strex($tmp$$Register, $newval$$Register, $mem$$Address); 5656 __ cmp($tmp$$Register, 0); 5657 __ b(loop, ne); 5658 %} 5659 ins_pipe( long_memory_op ); 5660 %} 5661 5662 //--------------------- 5663 // Subtraction Instructions 5664 // Register Subtraction 5665 instruct subI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{ 5666 match(Set dst (SubI src1 src2)); 5667 5668 size(4); 5669 format %{ "sub_32 $dst,$src1,$src2\t! int" %} 5670 ins_encode %{ 5671 __ sub_32($dst$$Register, $src1$$Register, $src2$$Register); 5672 %} 5673 ins_pipe(ialu_reg_reg); 5674 %} 5675 5676 instruct subshlI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 5677 match(Set dst (SubI src1 (LShiftI src2 src3))); 5678 5679 size(4); 5680 format %{ "SUB $dst,$src1,$src2<<$src3" %} 5681 ins_encode %{ 5682 __ sub($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$Register)); 5683 %} 5684 ins_pipe(ialu_reg_reg); 5685 %} 5686 5687 instruct subshlI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{ 5688 match(Set dst (SubI src1 (LShiftI src2 src3))); 5689 5690 size(4); 5691 format %{ "sub_32 $dst,$src1,$src2<<$src3\t! int" %} 5692 ins_encode %{ 5693 __ sub_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$constant)); 5694 %} 5695 ins_pipe(ialu_reg_reg); 5696 %} 5697 5698 instruct subsarI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 5699 match(Set dst (SubI src1 (RShiftI src2 src3))); 5700 5701 size(4); 5702 format %{ "SUB $dst,$src1,$src2>>$src3" %} 5703 ins_encode %{ 5704 __ sub($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$Register)); 5705 %} 5706 ins_pipe(ialu_reg_reg); 5707 %} 5708 5709 instruct subsarI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{ 5710 match(Set dst (SubI src1 (RShiftI src2 src3))); 5711 5712 size(4); 5713 format %{ "sub_32 $dst,$src1,$src2>>$src3\t! int" %} 5714 ins_encode %{ 5715 __ sub_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$constant)); 5716 %} 5717 ins_pipe(ialu_reg_reg); 5718 %} 5719 5720 instruct subshrI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 5721 match(Set dst (SubI src1 (URShiftI src2 src3))); 5722 5723 size(4); 5724 format %{ "SUB $dst,$src1,$src2>>>$src3" %} 5725 ins_encode %{ 5726 __ sub($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$Register)); 5727 %} 5728 ins_pipe(ialu_reg_reg); 5729 %} 5730 5731 instruct subshrI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{ 5732 match(Set dst (SubI src1 (URShiftI src2 src3))); 5733 5734 size(4); 5735 format %{ "sub_32 $dst,$src1,$src2>>>$src3\t! int" %} 5736 ins_encode %{ 5737 __ sub_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$constant)); 5738 %} 5739 ins_pipe(ialu_reg_reg); 5740 %} 5741 5742 instruct rsbshlI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 5743 match(Set dst (SubI (LShiftI src1 src2) src3)); 5744 5745 size(4); 5746 format %{ "RSB $dst,$src3,$src1<<$src2" %} 5747 ins_encode %{ 5748 __ rsb($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsl, $src2$$Register)); 5749 %} 5750 ins_pipe(ialu_reg_reg); 5751 %} 5752 5753 instruct rsbshlI_reg_imm_reg(iRegI dst, iRegI src1, immU5 src2, iRegI src3) %{ 5754 match(Set dst (SubI (LShiftI src1 src2) src3)); 5755 5756 size(4); 5757 format %{ "RSB $dst,$src3,$src1<<$src2" %} 5758 ins_encode %{ 5759 __ rsb($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsl, $src2$$constant)); 5760 %} 5761 ins_pipe(ialu_reg_reg); 5762 %} 5763 5764 instruct rsbsarI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 5765 match(Set dst (SubI (RShiftI src1 src2) src3)); 5766 5767 size(4); 5768 format %{ "RSB $dst,$src3,$src1>>$src2" %} 5769 ins_encode %{ 5770 __ rsb($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, asr, $src2$$Register)); 5771 %} 5772 ins_pipe(ialu_reg_reg); 5773 %} 5774 5775 instruct rsbsarI_reg_imm_reg(iRegI dst, iRegI src1, immU5 src2, iRegI src3) %{ 5776 match(Set dst (SubI (RShiftI src1 src2) src3)); 5777 5778 size(4); 5779 format %{ "RSB $dst,$src3,$src1>>$src2" %} 5780 ins_encode %{ 5781 __ rsb($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, asr, $src2$$constant)); 5782 %} 5783 ins_pipe(ialu_reg_reg); 5784 %} 5785 5786 instruct rsbshrI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 5787 match(Set dst (SubI (URShiftI src1 src2) src3)); 5788 5789 size(4); 5790 format %{ "RSB $dst,$src3,$src1>>>$src2" %} 5791 ins_encode %{ 5792 __ rsb($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsr, $src2$$Register)); 5793 %} 5794 ins_pipe(ialu_reg_reg); 5795 %} 5796 5797 instruct rsbshrI_reg_imm_reg(iRegI dst, iRegI src1, immU5 src2, iRegI src3) %{ 5798 match(Set dst (SubI (URShiftI src1 src2) src3)); 5799 5800 size(4); 5801 format %{ "RSB $dst,$src3,$src1>>>$src2" %} 5802 ins_encode %{ 5803 __ rsb($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsr, $src2$$constant)); 5804 %} 5805 ins_pipe(ialu_reg_reg); 5806 %} 5807 5808 // Immediate Subtraction 5809 instruct subI_reg_aimmI(iRegI dst, iRegI src1, aimmI src2) %{ 5810 match(Set dst (SubI src1 src2)); 5811 5812 size(4); 5813 format %{ "sub_32 $dst,$src1,$src2\t! int" %} 5814 ins_encode %{ 5815 __ sub_32($dst$$Register, $src1$$Register, $src2$$constant); 5816 %} 5817 ins_pipe(ialu_reg_imm); 5818 %} 5819 5820 instruct subI_reg_immRotneg(iRegI dst, iRegI src1, aimmIneg src2) %{ 5821 match(Set dst (AddI src1 src2)); 5822 5823 size(4); 5824 format %{ "sub_32 $dst,$src1,-($src2)\t! int" %} 5825 ins_encode %{ 5826 __ sub_32($dst$$Register, $src1$$Register, -$src2$$constant); 5827 %} 5828 ins_pipe(ialu_reg_imm); 5829 %} 5830 5831 instruct subI_immRot_reg(iRegI dst, immIRot src1, iRegI src2) %{ 5832 match(Set dst (SubI src1 src2)); 5833 5834 size(4); 5835 format %{ "RSB $dst,$src2,src1" %} 5836 ins_encode %{ 5837 __ rsb($dst$$Register, $src2$$Register, $src1$$constant); 5838 %} 5839 ins_pipe(ialu_zero_reg); 5840 %} 5841 5842 // Register Subtraction 5843 instruct subL_reg_reg(iRegL dst, iRegL src1, iRegL src2, flagsReg icc ) %{ 5844 match(Set dst (SubL src1 src2)); 5845 effect (KILL icc); 5846 5847 size(8); 5848 format %{ "SUBS $dst.lo,$src1.lo,$src2.lo\t! long\n\t" 5849 "SBC $dst.hi,$src1.hi,$src2.hi" %} 5850 ins_encode %{ 5851 __ subs($dst$$Register, $src1$$Register, $src2$$Register); 5852 __ sbc($dst$$Register->successor(), $src1$$Register->successor(), $src2$$Register->successor()); 5853 %} 5854 ins_pipe(ialu_reg_reg); 5855 %} 5856 5857 // TODO 5858 5859 // Immediate Subtraction 5860 // TODO: try immLRot2 instead, (0, $con$$constant) becomes 5861 // (hi($con$$constant), lo($con$$constant)) becomes 5862 instruct subL_reg_immRot(iRegL dst, iRegL src1, immLlowRot con, flagsReg icc) %{ 5863 match(Set dst (SubL src1 con)); 5864 effect (KILL icc); 5865 5866 size(8); 5867 format %{ "SUB $dst.lo,$src1.lo,$con\t! long\n\t" 5868 "SBC $dst.hi,$src1.hi,0" %} 5869 ins_encode %{ 5870 __ subs($dst$$Register, $src1$$Register, $con$$constant); 5871 __ sbc($dst$$Register->successor(), $src1$$Register->successor(), 0); 5872 %} 5873 ins_pipe(ialu_reg_imm); 5874 %} 5875 5876 // Long negation 5877 instruct negL_reg_reg(iRegL dst, immL0 zero, iRegL src2, flagsReg icc) %{ 5878 match(Set dst (SubL zero src2)); 5879 effect (KILL icc); 5880 5881 size(8); 5882 format %{ "RSBS $dst.lo,$src2.lo,0\t! long\n\t" 5883 "RSC $dst.hi,$src2.hi,0" %} 5884 ins_encode %{ 5885 __ rsbs($dst$$Register, $src2$$Register, 0); 5886 __ rsc($dst$$Register->successor(), $src2$$Register->successor(), 0); 5887 %} 5888 ins_pipe(ialu_zero_reg); 5889 %} 5890 5891 // Multiplication Instructions 5892 // Integer Multiplication 5893 // Register Multiplication 5894 instruct mulI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{ 5895 match(Set dst (MulI src1 src2)); 5896 5897 size(4); 5898 format %{ "mul_32 $dst,$src1,$src2" %} 5899 ins_encode %{ 5900 __ mul_32($dst$$Register, $src1$$Register, $src2$$Register); 5901 %} 5902 ins_pipe(imul_reg_reg); 5903 %} 5904 5905 instruct mulL_lo1_hi2(iRegL dst, iRegL src1, iRegL src2) %{ 5906 effect(DEF dst, USE src1, USE src2); 5907 size(4); 5908 format %{ "MUL $dst.hi,$src1.lo,$src2.hi\t! long" %} 5909 ins_encode %{ 5910 __ mul($dst$$Register->successor(), $src1$$Register, $src2$$Register->successor()); 5911 %} 5912 ins_pipe(imul_reg_reg); 5913 %} 5914 5915 instruct mulL_hi1_lo2(iRegL dst, iRegL src1, iRegL src2) %{ 5916 effect(USE_DEF dst, USE src1, USE src2); 5917 size(8); 5918 format %{ "MLA $dst.hi,$src1.hi,$src2.lo,$dst.hi\t! long\n\t" 5919 "MOV $dst.lo, 0"%} 5920 ins_encode %{ 5921 __ mla($dst$$Register->successor(), $src1$$Register->successor(), $src2$$Register, $dst$$Register->successor()); 5922 __ mov($dst$$Register, 0); 5923 %} 5924 ins_pipe(imul_reg_reg); 5925 %} 5926 5927 instruct mulL_lo1_lo2(iRegL dst, iRegL src1, iRegL src2) %{ 5928 effect(USE_DEF dst, USE src1, USE src2); 5929 size(4); 5930 format %{ "UMLAL $dst.lo,$dst.hi,$src1,$src2\t! long" %} 5931 ins_encode %{ 5932 __ umlal($dst$$Register, $dst$$Register->successor(), $src1$$Register, $src2$$Register); 5933 %} 5934 ins_pipe(imul_reg_reg); 5935 %} 5936 5937 instruct mulL_reg_reg(iRegL dst, iRegL src1, iRegL src2) %{ 5938 match(Set dst (MulL src1 src2)); 5939 5940 expand %{ 5941 mulL_lo1_hi2(dst, src1, src2); 5942 mulL_hi1_lo2(dst, src1, src2); 5943 mulL_lo1_lo2(dst, src1, src2); 5944 %} 5945 %} 5946 5947 // Integer Division 5948 // Register Division 5949 instruct divI_reg_reg(R1RegI dst, R0RegI src1, R2RegI src2, LRRegP lr, flagsReg ccr) %{ 5950 match(Set dst (DivI src1 src2)); 5951 effect( KILL ccr, KILL src1, KILL src2, KILL lr); 5952 ins_cost((2+71)*DEFAULT_COST); 5953 5954 format %{ "DIV $dst,$src1,$src2 ! call to StubRoutines::Arm::idiv_irem_entry()" %} 5955 ins_encode %{ 5956 __ call(StubRoutines::Arm::idiv_irem_entry(), relocInfo::runtime_call_type); 5957 %} 5958 ins_pipe(sdiv_reg_reg); 5959 %} 5960 5961 // Register Long Division 5962 instruct divL_reg_reg(R0R1RegL dst, R2R3RegL src1, R0R1RegL src2) %{ 5963 match(Set dst (DivL src1 src2)); 5964 effect(CALL); 5965 ins_cost(DEFAULT_COST*71); 5966 format %{ "DIVL $src1,$src2,$dst\t! long ! call to SharedRuntime::ldiv" %} 5967 ins_encode %{ 5968 address target = CAST_FROM_FN_PTR(address, SharedRuntime::ldiv); 5969 __ call(target, relocInfo::runtime_call_type); 5970 %} 5971 ins_pipe(divL_reg_reg); 5972 %} 5973 5974 // Integer Remainder 5975 // Register Remainder 5976 instruct modI_reg_reg(R0RegI dst, R0RegI src1, R2RegI src2, R1RegI temp, LRRegP lr, flagsReg ccr ) %{ 5977 match(Set dst (ModI src1 src2)); 5978 effect( KILL ccr, KILL temp, KILL src2, KILL lr); 5979 5980 format %{ "MODI $dst,$src1,$src2\t ! call to StubRoutines::Arm::idiv_irem_entry" %} 5981 ins_encode %{ 5982 __ call(StubRoutines::Arm::idiv_irem_entry(), relocInfo::runtime_call_type); 5983 %} 5984 ins_pipe(sdiv_reg_reg); 5985 %} 5986 5987 // Register Long Remainder 5988 instruct modL_reg_reg(R0R1RegL dst, R2R3RegL src1, R0R1RegL src2) %{ 5989 match(Set dst (ModL src1 src2)); 5990 effect(CALL); 5991 ins_cost(MEMORY_REF_COST); // FIXME 5992 format %{ "modL $dst,$src1,$src2\t ! call to SharedRuntime::lrem" %} 5993 ins_encode %{ 5994 address target = CAST_FROM_FN_PTR(address, SharedRuntime::lrem); 5995 __ call(target, relocInfo::runtime_call_type); 5996 %} 5997 ins_pipe(divL_reg_reg); 5998 %} 5999 6000 // Integer Shift Instructions 6001 6002 // Register Shift Left 6003 instruct shlI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{ 6004 match(Set dst (LShiftI src1 src2)); 6005 6006 size(4); 6007 format %{ "LSL $dst,$src1,$src2 \n\t" %} 6008 ins_encode %{ 6009 __ mov($dst$$Register, AsmOperand($src1$$Register, lsl, $src2$$Register)); 6010 %} 6011 ins_pipe(ialu_reg_reg); 6012 %} 6013 6014 // Register Shift Left Immediate 6015 instruct shlI_reg_imm5(iRegI dst, iRegI src1, immU5 src2) %{ 6016 match(Set dst (LShiftI src1 src2)); 6017 6018 size(4); 6019 format %{ "LSL $dst,$src1,$src2\t! int" %} 6020 ins_encode %{ 6021 __ logical_shift_left($dst$$Register, $src1$$Register, $src2$$constant); 6022 %} 6023 ins_pipe(ialu_reg_imm); 6024 %} 6025 6026 instruct shlL_reg_reg_merge_hi(iRegL dst, iRegL src1, iRegI src2) %{ 6027 effect(USE_DEF dst, USE src1, USE src2); 6028 size(4); 6029 format %{"OR $dst.hi,$dst.hi,($src1.hi << $src2)" %} 6030 ins_encode %{ 6031 __ orr($dst$$Register->successor(), $dst$$Register->successor(), AsmOperand($src1$$Register->successor(), lsl, $src2$$Register)); 6032 %} 6033 ins_pipe(ialu_reg_reg); 6034 %} 6035 6036 instruct shlL_reg_reg_merge_lo(iRegL dst, iRegL src1, iRegI src2) %{ 6037 effect(USE_DEF dst, USE src1, USE src2); 6038 size(4); 6039 format %{ "LSL $dst.lo,$src1.lo,$src2 \n\t" %} 6040 ins_encode %{ 6041 __ mov($dst$$Register, AsmOperand($src1$$Register, lsl, $src2$$Register)); 6042 %} 6043 ins_pipe(ialu_reg_reg); 6044 %} 6045 6046 instruct shlL_reg_reg_overlap(iRegL dst, iRegL src1, iRegI src2, flagsReg ccr) %{ 6047 effect(DEF dst, USE src1, USE src2, KILL ccr); 6048 size(16); 6049 format %{ "SUBS $dst.hi,$src2,32 \n\t" 6050 "LSLpl $dst.hi,$src1.lo,$dst.hi \n\t" 6051 "RSBmi $dst.hi,$dst.hi,0 \n\t" 6052 "LSRmi $dst.hi,$src1.lo,$dst.hi" %} 6053 6054 ins_encode %{ 6055 // $src1$$Register and $dst$$Register->successor() can't be the same 6056 __ subs($dst$$Register->successor(), $src2$$Register, 32); 6057 __ mov($dst$$Register->successor(), AsmOperand($src1$$Register, lsl, $dst$$Register->successor()), pl); 6058 __ rsb($dst$$Register->successor(), $dst$$Register->successor(), 0, mi); 6059 __ mov($dst$$Register->successor(), AsmOperand($src1$$Register, lsr, $dst$$Register->successor()), mi); 6060 %} 6061 ins_pipe(ialu_reg_reg); 6062 %} 6063 6064 instruct shlL_reg_reg(iRegL dst, iRegL src1, iRegI src2) %{ 6065 match(Set dst (LShiftL src1 src2)); 6066 6067 expand %{ 6068 flagsReg ccr; 6069 shlL_reg_reg_overlap(dst, src1, src2, ccr); 6070 shlL_reg_reg_merge_hi(dst, src1, src2); 6071 shlL_reg_reg_merge_lo(dst, src1, src2); 6072 %} 6073 %} 6074 6075 // Register Shift Left Immediate 6076 instruct shlL_reg_imm6(iRegL dst, iRegL src1, immU6Big src2) %{ 6077 match(Set dst (LShiftL src1 src2)); 6078 6079 size(8); 6080 format %{ "LSL $dst.hi,$src1.lo,$src2-32\t! or mov if $src2==32\n\t" 6081 "MOV $dst.lo, 0" %} 6082 ins_encode %{ 6083 if ($src2$$constant == 32) { 6084 __ mov($dst$$Register->successor(), $src1$$Register); 6085 } else { 6086 __ mov($dst$$Register->successor(), AsmOperand($src1$$Register, lsl, $src2$$constant-32)); 6087 } 6088 __ mov($dst$$Register, 0); 6089 %} 6090 ins_pipe(ialu_reg_imm); 6091 %} 6092 6093 instruct shlL_reg_imm5(iRegL dst, iRegL src1, immU5 src2) %{ 6094 match(Set dst (LShiftL src1 src2)); 6095 6096 size(12); 6097 format %{ "LSL $dst.hi,$src1.lo,$src2\n\t" 6098 "OR $dst.hi, $dst.hi, $src1.lo >> 32-$src2\n\t" 6099 "LSL $dst.lo,$src1.lo,$src2" %} 6100 ins_encode %{ 6101 // The order of the following 3 instructions matters: src1.lo and 6102 // dst.hi can't overlap but src.hi and dst.hi can. 6103 __ mov($dst$$Register->successor(), AsmOperand($src1$$Register->successor(), lsl, $src2$$constant)); 6104 __ orr($dst$$Register->successor(), $dst$$Register->successor(), AsmOperand($src1$$Register, lsr, 32-$src2$$constant)); 6105 __ mov($dst$$Register, AsmOperand($src1$$Register, lsl, $src2$$constant)); 6106 %} 6107 ins_pipe(ialu_reg_imm); 6108 %} 6109 6110 // Register Arithmetic Shift Right 6111 instruct sarI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{ 6112 match(Set dst (RShiftI src1 src2)); 6113 size(4); 6114 format %{ "ASR $dst,$src1,$src2\t! int" %} 6115 ins_encode %{ 6116 __ mov($dst$$Register, AsmOperand($src1$$Register, asr, $src2$$Register)); 6117 %} 6118 ins_pipe(ialu_reg_reg); 6119 %} 6120 6121 // Register Arithmetic Shift Right Immediate 6122 instruct sarI_reg_imm5(iRegI dst, iRegI src1, immU5 src2) %{ 6123 match(Set dst (RShiftI src1 src2)); 6124 6125 size(4); 6126 format %{ "ASR $dst,$src1,$src2" %} 6127 ins_encode %{ 6128 __ mov($dst$$Register, AsmOperand($src1$$Register, asr, $src2$$constant)); 6129 %} 6130 ins_pipe(ialu_reg_imm); 6131 %} 6132 6133 // Register Shift Right Arithmetic Long 6134 instruct sarL_reg_reg_merge_lo(iRegL dst, iRegL src1, iRegI src2) %{ 6135 effect(USE_DEF dst, USE src1, USE src2); 6136 size(4); 6137 format %{ "OR $dst.lo,$dst.lo,($src1.lo >> $src2)" %} 6138 ins_encode %{ 6139 __ orr($dst$$Register, $dst$$Register, AsmOperand($src1$$Register, lsr, $src2$$Register)); 6140 %} 6141 ins_pipe(ialu_reg_reg); 6142 %} 6143 6144 instruct sarL_reg_reg_merge_hi(iRegL dst, iRegL src1, iRegI src2) %{ 6145 effect(USE_DEF dst, USE src1, USE src2); 6146 size(4); 6147 format %{ "ASR $dst.hi,$src1.hi,$src2 \n\t" %} 6148 ins_encode %{ 6149 __ mov($dst$$Register->successor(), AsmOperand($src1$$Register->successor(), asr, $src2$$Register)); 6150 %} 6151 ins_pipe(ialu_reg_reg); 6152 %} 6153 6154 instruct sarL_reg_reg_overlap(iRegL dst, iRegL src1, iRegI src2, flagsReg ccr) %{ 6155 effect(DEF dst, USE src1, USE src2, KILL ccr); 6156 size(16); 6157 format %{ "SUBS $dst.lo,$src2,32 \n\t" 6158 "ASRpl $dst.lo,$src1.hi,$dst.lo \n\t" 6159 "RSBmi $dst.lo,$dst.lo,0 \n\t" 6160 "LSLmi $dst.lo,$src1.hi,$dst.lo" %} 6161 6162 ins_encode %{ 6163 // $src1$$Register->successor() and $dst$$Register can't be the same 6164 __ subs($dst$$Register, $src2$$Register, 32); 6165 __ mov($dst$$Register, AsmOperand($src1$$Register->successor(), asr, $dst$$Register), pl); 6166 __ rsb($dst$$Register, $dst$$Register, 0, mi); 6167 __ mov($dst$$Register, AsmOperand($src1$$Register->successor(), lsl, $dst$$Register), mi); 6168 %} 6169 ins_pipe(ialu_reg_reg); 6170 %} 6171 6172 instruct sarL_reg_reg(iRegL dst, iRegL src1, iRegI src2) %{ 6173 match(Set dst (RShiftL src1 src2)); 6174 6175 expand %{ 6176 flagsReg ccr; 6177 sarL_reg_reg_overlap(dst, src1, src2, ccr); 6178 sarL_reg_reg_merge_lo(dst, src1, src2); 6179 sarL_reg_reg_merge_hi(dst, src1, src2); 6180 %} 6181 %} 6182 6183 // Register Shift Left Immediate 6184 instruct sarL_reg_imm6(iRegL dst, iRegL src1, immU6Big src2) %{ 6185 match(Set dst (RShiftL src1 src2)); 6186 6187 size(8); 6188 format %{ "ASR $dst.lo,$src1.hi,$src2-32\t! or mov if $src2==32\n\t" 6189 "ASR $dst.hi,$src1.hi, $src2" %} 6190 ins_encode %{ 6191 if ($src2$$constant == 32) { 6192 __ mov($dst$$Register, $src1$$Register->successor()); 6193 } else{ 6194 __ mov($dst$$Register, AsmOperand($src1$$Register->successor(), asr, $src2$$constant-32)); 6195 } 6196 __ mov($dst$$Register->successor(), AsmOperand($src1$$Register->successor(), asr, 0)); 6197 %} 6198 6199 ins_pipe(ialu_reg_imm); 6200 %} 6201 6202 instruct sarL_reg_imm5(iRegL dst, iRegL src1, immU5 src2) %{ 6203 match(Set dst (RShiftL src1 src2)); 6204 size(12); 6205 format %{ "LSR $dst.lo,$src1.lo,$src2\n\t" 6206 "OR $dst.lo, $dst.lo, $src1.hi << 32-$src2\n\t" 6207 "ASR $dst.hi,$src1.hi,$src2" %} 6208 ins_encode %{ 6209 // The order of the following 3 instructions matters: src1.lo and 6210 // dst.hi can't overlap but src.hi and dst.hi can. 6211 __ mov($dst$$Register, AsmOperand($src1$$Register, lsr, $src2$$constant)); 6212 __ orr($dst$$Register, $dst$$Register, AsmOperand($src1$$Register->successor(), lsl, 32-$src2$$constant)); 6213 __ mov($dst$$Register->successor(), AsmOperand($src1$$Register->successor(), asr, $src2$$constant)); 6214 %} 6215 ins_pipe(ialu_reg_imm); 6216 %} 6217 6218 // Register Shift Right 6219 instruct shrI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{ 6220 match(Set dst (URShiftI src1 src2)); 6221 size(4); 6222 format %{ "LSR $dst,$src1,$src2\t! int" %} 6223 ins_encode %{ 6224 __ mov($dst$$Register, AsmOperand($src1$$Register, lsr, $src2$$Register)); 6225 %} 6226 ins_pipe(ialu_reg_reg); 6227 %} 6228 6229 // Register Shift Right Immediate 6230 instruct shrI_reg_imm5(iRegI dst, iRegI src1, immU5 src2) %{ 6231 match(Set dst (URShiftI src1 src2)); 6232 6233 size(4); 6234 format %{ "LSR $dst,$src1,$src2" %} 6235 ins_encode %{ 6236 __ mov($dst$$Register, AsmOperand($src1$$Register, lsr, $src2$$constant)); 6237 %} 6238 ins_pipe(ialu_reg_imm); 6239 %} 6240 6241 // Register Shift Right 6242 instruct shrL_reg_reg_merge_lo(iRegL dst, iRegL src1, iRegI src2) %{ 6243 effect(USE_DEF dst, USE src1, USE src2); 6244 size(4); 6245 format %{ "OR $dst.lo,$dst,($src1.lo >>> $src2)" %} 6246 ins_encode %{ 6247 __ orr($dst$$Register, $dst$$Register, AsmOperand($src1$$Register, lsr, $src2$$Register)); 6248 %} 6249 ins_pipe(ialu_reg_reg); 6250 %} 6251 6252 instruct shrL_reg_reg_merge_hi(iRegL dst, iRegL src1, iRegI src2) %{ 6253 effect(USE_DEF dst, USE src1, USE src2); 6254 size(4); 6255 format %{ "LSR $dst.hi,$src1.hi,$src2 \n\t" %} 6256 ins_encode %{ 6257 __ mov($dst$$Register->successor(), AsmOperand($src1$$Register->successor(), lsr, $src2$$Register)); 6258 %} 6259 ins_pipe(ialu_reg_reg); 6260 %} 6261 6262 instruct shrL_reg_reg_overlap(iRegL dst, iRegL src1, iRegI src2, flagsReg ccr) %{ 6263 effect(DEF dst, USE src1, USE src2, KILL ccr); 6264 size(16); 6265 format %{ "SUBS $dst,$src2,32 \n\t" 6266 "LSRpl $dst,$src1.hi,$dst \n\t" 6267 "RSBmi $dst,$dst,0 \n\t" 6268 "LSLmi $dst,$src1.hi,$dst" %} 6269 6270 ins_encode %{ 6271 // $src1$$Register->successor() and $dst$$Register can't be the same 6272 __ subs($dst$$Register, $src2$$Register, 32); 6273 __ mov($dst$$Register, AsmOperand($src1$$Register->successor(), lsr, $dst$$Register), pl); 6274 __ rsb($dst$$Register, $dst$$Register, 0, mi); 6275 __ mov($dst$$Register, AsmOperand($src1$$Register->successor(), lsl, $dst$$Register), mi); 6276 %} 6277 ins_pipe(ialu_reg_reg); 6278 %} 6279 6280 instruct shrL_reg_reg(iRegL dst, iRegL src1, iRegI src2) %{ 6281 match(Set dst (URShiftL src1 src2)); 6282 6283 expand %{ 6284 flagsReg ccr; 6285 shrL_reg_reg_overlap(dst, src1, src2, ccr); 6286 shrL_reg_reg_merge_lo(dst, src1, src2); 6287 shrL_reg_reg_merge_hi(dst, src1, src2); 6288 %} 6289 %} 6290 6291 // Register Shift Right Immediate 6292 instruct shrL_reg_imm6(iRegL dst, iRegL src1, immU6Big src2) %{ 6293 match(Set dst (URShiftL src1 src2)); 6294 6295 size(8); 6296 format %{ "LSR $dst.lo,$src1.hi,$src2-32\t! or mov if $src2==32\n\t" 6297 "MOV $dst.hi, 0" %} 6298 ins_encode %{ 6299 if ($src2$$constant == 32) { 6300 __ mov($dst$$Register, $src1$$Register->successor()); 6301 } else { 6302 __ mov($dst$$Register, AsmOperand($src1$$Register->successor(), lsr, $src2$$constant-32)); 6303 } 6304 __ mov($dst$$Register->successor(), 0); 6305 %} 6306 6307 ins_pipe(ialu_reg_imm); 6308 %} 6309 6310 instruct shrL_reg_imm5(iRegL dst, iRegL src1, immU5 src2) %{ 6311 match(Set dst (URShiftL src1 src2)); 6312 6313 size(12); 6314 format %{ "LSR $dst.lo,$src1.lo,$src2\n\t" 6315 "OR $dst.lo, $dst.lo, $src1.hi << 32-$src2\n\t" 6316 "LSR $dst.hi,$src1.hi,$src2" %} 6317 ins_encode %{ 6318 // The order of the following 3 instructions matters: src1.lo and 6319 // dst.hi can't overlap but src.hi and dst.hi can. 6320 __ mov($dst$$Register, AsmOperand($src1$$Register, lsr, $src2$$constant)); 6321 __ orr($dst$$Register, $dst$$Register, AsmOperand($src1$$Register->successor(), lsl, 32-$src2$$constant)); 6322 __ mov($dst$$Register->successor(), AsmOperand($src1$$Register->successor(), lsr, $src2$$constant)); 6323 %} 6324 ins_pipe(ialu_reg_imm); 6325 %} 6326 6327 6328 instruct shrP_reg_imm5(iRegX dst, iRegP src1, immU5 src2) %{ 6329 match(Set dst (URShiftI (CastP2X src1) src2)); 6330 size(4); 6331 format %{ "LSR $dst,$src1,$src2\t! Cast ptr $src1 to int and shift" %} 6332 ins_encode %{ 6333 __ logical_shift_right($dst$$Register, $src1$$Register, $src2$$constant); 6334 %} 6335 ins_pipe(ialu_reg_imm); 6336 %} 6337 6338 //----------Floating Point Arithmetic Instructions----------------------------- 6339 6340 // Add float single precision 6341 instruct addF_reg_reg(regF dst, regF src1, regF src2) %{ 6342 match(Set dst (AddF src1 src2)); 6343 6344 size(4); 6345 format %{ "FADDS $dst,$src1,$src2" %} 6346 ins_encode %{ 6347 __ add_float($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister); 6348 %} 6349 6350 ins_pipe(faddF_reg_reg); 6351 %} 6352 6353 // Add float double precision 6354 instruct addD_reg_reg(regD dst, regD src1, regD src2) %{ 6355 match(Set dst (AddD src1 src2)); 6356 6357 size(4); 6358 format %{ "FADDD $dst,$src1,$src2" %} 6359 ins_encode %{ 6360 __ add_double($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister); 6361 %} 6362 6363 ins_pipe(faddD_reg_reg); 6364 %} 6365 6366 // Sub float single precision 6367 instruct subF_reg_reg(regF dst, regF src1, regF src2) %{ 6368 match(Set dst (SubF src1 src2)); 6369 6370 size(4); 6371 format %{ "FSUBS $dst,$src1,$src2" %} 6372 ins_encode %{ 6373 __ sub_float($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister); 6374 %} 6375 ins_pipe(faddF_reg_reg); 6376 %} 6377 6378 // Sub float double precision 6379 instruct subD_reg_reg(regD dst, regD src1, regD src2) %{ 6380 match(Set dst (SubD src1 src2)); 6381 6382 size(4); 6383 format %{ "FSUBD $dst,$src1,$src2" %} 6384 ins_encode %{ 6385 __ sub_double($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister); 6386 %} 6387 ins_pipe(faddD_reg_reg); 6388 %} 6389 6390 // Mul float single precision 6391 instruct mulF_reg_reg(regF dst, regF src1, regF src2) %{ 6392 match(Set dst (MulF src1 src2)); 6393 6394 size(4); 6395 format %{ "FMULS $dst,$src1,$src2" %} 6396 ins_encode %{ 6397 __ mul_float($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister); 6398 %} 6399 6400 ins_pipe(fmulF_reg_reg); 6401 %} 6402 6403 // Mul float double precision 6404 instruct mulD_reg_reg(regD dst, regD src1, regD src2) %{ 6405 match(Set dst (MulD src1 src2)); 6406 6407 size(4); 6408 format %{ "FMULD $dst,$src1,$src2" %} 6409 ins_encode %{ 6410 __ mul_double($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister); 6411 %} 6412 6413 ins_pipe(fmulD_reg_reg); 6414 %} 6415 6416 // Div float single precision 6417 instruct divF_reg_reg(regF dst, regF src1, regF src2) %{ 6418 match(Set dst (DivF src1 src2)); 6419 6420 size(4); 6421 format %{ "FDIVS $dst,$src1,$src2" %} 6422 ins_encode %{ 6423 __ div_float($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister); 6424 %} 6425 6426 ins_pipe(fdivF_reg_reg); 6427 %} 6428 6429 // Div float double precision 6430 instruct divD_reg_reg(regD dst, regD src1, regD src2) %{ 6431 match(Set dst (DivD src1 src2)); 6432 6433 size(4); 6434 format %{ "FDIVD $dst,$src1,$src2" %} 6435 ins_encode %{ 6436 __ div_double($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister); 6437 %} 6438 6439 ins_pipe(fdivD_reg_reg); 6440 %} 6441 6442 // Absolute float double precision 6443 instruct absD_reg(regD dst, regD src) %{ 6444 match(Set dst (AbsD src)); 6445 6446 size(4); 6447 format %{ "FABSd $dst,$src" %} 6448 ins_encode %{ 6449 __ abs_double($dst$$FloatRegister, $src$$FloatRegister); 6450 %} 6451 ins_pipe(faddD_reg); 6452 %} 6453 6454 // Absolute float single precision 6455 instruct absF_reg(regF dst, regF src) %{ 6456 match(Set dst (AbsF src)); 6457 format %{ "FABSs $dst,$src" %} 6458 ins_encode %{ 6459 __ abs_float($dst$$FloatRegister, $src$$FloatRegister); 6460 %} 6461 ins_pipe(faddF_reg); 6462 %} 6463 6464 instruct negF_reg(regF dst, regF src) %{ 6465 match(Set dst (NegF src)); 6466 6467 size(4); 6468 format %{ "FNEGs $dst,$src" %} 6469 ins_encode %{ 6470 __ neg_float($dst$$FloatRegister, $src$$FloatRegister); 6471 %} 6472 ins_pipe(faddF_reg); 6473 %} 6474 6475 instruct negD_reg(regD dst, regD src) %{ 6476 match(Set dst (NegD src)); 6477 6478 format %{ "FNEGd $dst,$src" %} 6479 ins_encode %{ 6480 __ neg_double($dst$$FloatRegister, $src$$FloatRegister); 6481 %} 6482 ins_pipe(faddD_reg); 6483 %} 6484 6485 // Sqrt float double precision 6486 instruct sqrtF_reg_reg(regF dst, regF src) %{ 6487 match(Set dst (ConvD2F (SqrtD (ConvF2D src)))); 6488 6489 size(4); 6490 format %{ "FSQRTS $dst,$src" %} 6491 ins_encode %{ 6492 __ sqrt_float($dst$$FloatRegister, $src$$FloatRegister); 6493 %} 6494 ins_pipe(fdivF_reg_reg); 6495 %} 6496 6497 // Sqrt float double precision 6498 instruct sqrtD_reg_reg(regD dst, regD src) %{ 6499 match(Set dst (SqrtD src)); 6500 6501 size(4); 6502 format %{ "FSQRTD $dst,$src" %} 6503 ins_encode %{ 6504 __ sqrt_double($dst$$FloatRegister, $src$$FloatRegister); 6505 %} 6506 ins_pipe(fdivD_reg_reg); 6507 %} 6508 6509 //----------Logical Instructions----------------------------------------------- 6510 // And Instructions 6511 // Register And 6512 instruct andI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{ 6513 match(Set dst (AndI src1 src2)); 6514 6515 size(4); 6516 format %{ "and_32 $dst,$src1,$src2" %} 6517 ins_encode %{ 6518 __ and_32($dst$$Register, $src1$$Register, $src2$$Register); 6519 %} 6520 ins_pipe(ialu_reg_reg); 6521 %} 6522 6523 instruct andshlI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 6524 match(Set dst (AndI src1 (LShiftI src2 src3))); 6525 6526 size(4); 6527 format %{ "AND $dst,$src1,$src2<<$src3" %} 6528 ins_encode %{ 6529 __ andr($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$Register)); 6530 %} 6531 ins_pipe(ialu_reg_reg); 6532 %} 6533 6534 instruct andshlI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{ 6535 match(Set dst (AndI src1 (LShiftI src2 src3))); 6536 6537 size(4); 6538 format %{ "and_32 $dst,$src1,$src2<<$src3" %} 6539 ins_encode %{ 6540 __ and_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$constant)); 6541 %} 6542 ins_pipe(ialu_reg_reg); 6543 %} 6544 6545 instruct andsarI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 6546 match(Set dst (AndI src1 (RShiftI src2 src3))); 6547 6548 size(4); 6549 format %{ "AND $dst,$src1,$src2>>$src3" %} 6550 ins_encode %{ 6551 __ andr($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$Register)); 6552 %} 6553 ins_pipe(ialu_reg_reg); 6554 %} 6555 6556 instruct andsarI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{ 6557 match(Set dst (AndI src1 (RShiftI src2 src3))); 6558 6559 size(4); 6560 format %{ "and_32 $dst,$src1,$src2>>$src3" %} 6561 ins_encode %{ 6562 __ and_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$constant)); 6563 %} 6564 ins_pipe(ialu_reg_reg); 6565 %} 6566 6567 instruct andshrI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 6568 match(Set dst (AndI src1 (URShiftI src2 src3))); 6569 6570 size(4); 6571 format %{ "AND $dst,$src1,$src2>>>$src3" %} 6572 ins_encode %{ 6573 __ andr($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$Register)); 6574 %} 6575 ins_pipe(ialu_reg_reg); 6576 %} 6577 6578 instruct andshrI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{ 6579 match(Set dst (AndI src1 (URShiftI src2 src3))); 6580 6581 size(4); 6582 format %{ "and_32 $dst,$src1,$src2>>>$src3" %} 6583 ins_encode %{ 6584 __ and_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$constant)); 6585 %} 6586 ins_pipe(ialu_reg_reg); 6587 %} 6588 6589 // Immediate And 6590 instruct andI_reg_limm(iRegI dst, iRegI src1, limmI src2) %{ 6591 match(Set dst (AndI src1 src2)); 6592 6593 size(4); 6594 format %{ "and_32 $dst,$src1,$src2\t! int" %} 6595 ins_encode %{ 6596 __ and_32($dst$$Register, $src1$$Register, $src2$$constant); 6597 %} 6598 ins_pipe(ialu_reg_imm); 6599 %} 6600 6601 instruct andI_reg_limmn(iRegI dst, iRegI src1, limmIn src2) %{ 6602 match(Set dst (AndI src1 src2)); 6603 6604 size(4); 6605 format %{ "bic $dst,$src1,~$src2\t! int" %} 6606 ins_encode %{ 6607 __ bic($dst$$Register, $src1$$Register, ~$src2$$constant); 6608 %} 6609 ins_pipe(ialu_reg_imm); 6610 %} 6611 6612 // Register And Long 6613 instruct andL_reg_reg(iRegL dst, iRegL src1, iRegL src2) %{ 6614 match(Set dst (AndL src1 src2)); 6615 6616 ins_cost(DEFAULT_COST); 6617 size(8); 6618 format %{ "AND $dst,$src1,$src2\t! long" %} 6619 ins_encode %{ 6620 __ andr($dst$$Register, $src1$$Register, $src2$$Register); 6621 __ andr($dst$$Register->successor(), $src1$$Register->successor(), $src2$$Register->successor()); 6622 %} 6623 ins_pipe(ialu_reg_reg); 6624 %} 6625 6626 // TODO: try immLRot2 instead, (0, $con$$constant) becomes 6627 // (hi($con$$constant), lo($con$$constant)) becomes 6628 instruct andL_reg_immRot(iRegL dst, iRegL src1, immLlowRot con) %{ 6629 match(Set dst (AndL src1 con)); 6630 ins_cost(DEFAULT_COST); 6631 size(8); 6632 format %{ "AND $dst,$src1,$con\t! long" %} 6633 ins_encode %{ 6634 __ andr($dst$$Register, $src1$$Register, $con$$constant); 6635 __ andr($dst$$Register->successor(), $src1$$Register->successor(), 0); 6636 %} 6637 ins_pipe(ialu_reg_imm); 6638 %} 6639 6640 // Or Instructions 6641 // Register Or 6642 instruct orI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{ 6643 match(Set dst (OrI src1 src2)); 6644 6645 size(4); 6646 format %{ "orr_32 $dst,$src1,$src2\t! int" %} 6647 ins_encode %{ 6648 __ orr_32($dst$$Register, $src1$$Register, $src2$$Register); 6649 %} 6650 ins_pipe(ialu_reg_reg); 6651 %} 6652 6653 instruct orshlI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 6654 match(Set dst (OrI src1 (LShiftI src2 src3))); 6655 6656 size(4); 6657 format %{ "OR $dst,$src1,$src2<<$src3" %} 6658 ins_encode %{ 6659 __ orr($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$Register)); 6660 %} 6661 ins_pipe(ialu_reg_reg); 6662 %} 6663 6664 instruct orshlI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{ 6665 match(Set dst (OrI src1 (LShiftI src2 src3))); 6666 6667 size(4); 6668 format %{ "orr_32 $dst,$src1,$src2<<$src3" %} 6669 ins_encode %{ 6670 __ orr_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$constant)); 6671 %} 6672 ins_pipe(ialu_reg_reg); 6673 %} 6674 6675 instruct orsarI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 6676 match(Set dst (OrI src1 (RShiftI src2 src3))); 6677 6678 size(4); 6679 format %{ "OR $dst,$src1,$src2>>$src3" %} 6680 ins_encode %{ 6681 __ orr($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$Register)); 6682 %} 6683 ins_pipe(ialu_reg_reg); 6684 %} 6685 6686 instruct orsarI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{ 6687 match(Set dst (OrI src1 (RShiftI src2 src3))); 6688 6689 size(4); 6690 format %{ "orr_32 $dst,$src1,$src2>>$src3" %} 6691 ins_encode %{ 6692 __ orr_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$constant)); 6693 %} 6694 ins_pipe(ialu_reg_reg); 6695 %} 6696 6697 instruct orshrI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 6698 match(Set dst (OrI src1 (URShiftI src2 src3))); 6699 6700 size(4); 6701 format %{ "OR $dst,$src1,$src2>>>$src3" %} 6702 ins_encode %{ 6703 __ orr($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$Register)); 6704 %} 6705 ins_pipe(ialu_reg_reg); 6706 %} 6707 6708 instruct orshrI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{ 6709 match(Set dst (OrI src1 (URShiftI src2 src3))); 6710 6711 size(4); 6712 format %{ "orr_32 $dst,$src1,$src2>>>$src3" %} 6713 ins_encode %{ 6714 __ orr_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$constant)); 6715 %} 6716 ins_pipe(ialu_reg_reg); 6717 %} 6718 6719 // Immediate Or 6720 instruct orI_reg_limm(iRegI dst, iRegI src1, limmI src2) %{ 6721 match(Set dst (OrI src1 src2)); 6722 6723 size(4); 6724 format %{ "orr_32 $dst,$src1,$src2" %} 6725 ins_encode %{ 6726 __ orr_32($dst$$Register, $src1$$Register, $src2$$constant); 6727 %} 6728 ins_pipe(ialu_reg_imm); 6729 %} 6730 // TODO: orn_32 with limmIn 6731 6732 // Register Or Long 6733 instruct orL_reg_reg(iRegL dst, iRegL src1, iRegL src2) %{ 6734 match(Set dst (OrL src1 src2)); 6735 6736 ins_cost(DEFAULT_COST); 6737 size(8); 6738 format %{ "OR $dst.lo,$src1.lo,$src2.lo\t! long\n\t" 6739 "OR $dst.hi,$src1.hi,$src2.hi" %} 6740 ins_encode %{ 6741 __ orr($dst$$Register, $src1$$Register, $src2$$Register); 6742 __ orr($dst$$Register->successor(), $src1$$Register->successor(), $src2$$Register->successor()); 6743 %} 6744 ins_pipe(ialu_reg_reg); 6745 %} 6746 6747 // TODO: try immLRot2 instead, (0, $con$$constant) becomes 6748 // (hi($con$$constant), lo($con$$constant)) becomes 6749 instruct orL_reg_immRot(iRegL dst, iRegL src1, immLlowRot con) %{ 6750 match(Set dst (OrL src1 con)); 6751 ins_cost(DEFAULT_COST); 6752 size(8); 6753 format %{ "OR $dst.lo,$src1.lo,$con\t! long\n\t" 6754 "OR $dst.hi,$src1.hi,$con" %} 6755 ins_encode %{ 6756 __ orr($dst$$Register, $src1$$Register, $con$$constant); 6757 __ orr($dst$$Register->successor(), $src1$$Register->successor(), 0); 6758 %} 6759 ins_pipe(ialu_reg_imm); 6760 %} 6761 6762 #ifdef TODO 6763 // Use SPRegP to match Rthread (TLS register) without spilling. 6764 // Use store_ptr_RegP to match Rthread (TLS register) without spilling. 6765 // Use sp_ptr_RegP to match Rthread (TLS register) without spilling. 6766 instruct orI_reg_castP2X(iRegI dst, iRegI src1, sp_ptr_RegP src2) %{ 6767 match(Set dst (OrI src1 (CastP2X src2))); 6768 size(4); 6769 format %{ "OR $dst,$src1,$src2" %} 6770 ins_encode %{ 6771 __ orr($dst$$Register, $src1$$Register, $src2$$Register); 6772 %} 6773 ins_pipe(ialu_reg_reg); 6774 %} 6775 #endif 6776 6777 // Xor Instructions 6778 // Register Xor 6779 instruct xorI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{ 6780 match(Set dst (XorI src1 src2)); 6781 6782 size(4); 6783 format %{ "eor_32 $dst,$src1,$src2" %} 6784 ins_encode %{ 6785 __ eor_32($dst$$Register, $src1$$Register, $src2$$Register); 6786 %} 6787 ins_pipe(ialu_reg_reg); 6788 %} 6789 6790 instruct xorshlI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 6791 match(Set dst (XorI src1 (LShiftI src2 src3))); 6792 6793 size(4); 6794 format %{ "XOR $dst,$src1,$src2<<$src3" %} 6795 ins_encode %{ 6796 __ eor($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$Register)); 6797 %} 6798 ins_pipe(ialu_reg_reg); 6799 %} 6800 6801 instruct xorshlI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{ 6802 match(Set dst (XorI src1 (LShiftI src2 src3))); 6803 6804 size(4); 6805 format %{ "eor_32 $dst,$src1,$src2<<$src3" %} 6806 ins_encode %{ 6807 __ eor_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$constant)); 6808 %} 6809 ins_pipe(ialu_reg_reg); 6810 %} 6811 6812 instruct xorsarI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 6813 match(Set dst (XorI src1 (RShiftI src2 src3))); 6814 6815 size(4); 6816 format %{ "XOR $dst,$src1,$src2>>$src3" %} 6817 ins_encode %{ 6818 __ eor($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$Register)); 6819 %} 6820 ins_pipe(ialu_reg_reg); 6821 %} 6822 6823 instruct xorsarI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{ 6824 match(Set dst (XorI src1 (RShiftI src2 src3))); 6825 6826 size(4); 6827 format %{ "eor_32 $dst,$src1,$src2>>$src3" %} 6828 ins_encode %{ 6829 __ eor_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$constant)); 6830 %} 6831 ins_pipe(ialu_reg_reg); 6832 %} 6833 6834 instruct xorshrI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 6835 match(Set dst (XorI src1 (URShiftI src2 src3))); 6836 6837 size(4); 6838 format %{ "XOR $dst,$src1,$src2>>>$src3" %} 6839 ins_encode %{ 6840 __ eor($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$Register)); 6841 %} 6842 ins_pipe(ialu_reg_reg); 6843 %} 6844 6845 instruct xorshrI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{ 6846 match(Set dst (XorI src1 (URShiftI src2 src3))); 6847 6848 size(4); 6849 format %{ "eor_32 $dst,$src1,$src2>>>$src3" %} 6850 ins_encode %{ 6851 __ eor_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$constant)); 6852 %} 6853 ins_pipe(ialu_reg_reg); 6854 %} 6855 6856 // Immediate Xor 6857 instruct xorI_reg_imm(iRegI dst, iRegI src1, limmI src2) %{ 6858 match(Set dst (XorI src1 src2)); 6859 6860 size(4); 6861 format %{ "eor_32 $dst,$src1,$src2" %} 6862 ins_encode %{ 6863 __ eor_32($dst$$Register, $src1$$Register, $src2$$constant); 6864 %} 6865 ins_pipe(ialu_reg_imm); 6866 %} 6867 6868 // Register Xor Long 6869 instruct xorL_reg_reg(iRegL dst, iRegL src1, iRegL src2) %{ 6870 match(Set dst (XorL src1 src2)); 6871 ins_cost(DEFAULT_COST); 6872 size(8); 6873 format %{ "XOR $dst.hi,$src1.hi,$src2.hi\t! long\n\t" 6874 "XOR $dst.lo,$src1.lo,$src2.lo\t! long" %} 6875 ins_encode %{ 6876 __ eor($dst$$Register, $src1$$Register, $src2$$Register); 6877 __ eor($dst$$Register->successor(), $src1$$Register->successor(), $src2$$Register->successor()); 6878 %} 6879 ins_pipe(ialu_reg_reg); 6880 %} 6881 6882 // TODO: try immLRot2 instead, (0, $con$$constant) becomes 6883 // (hi($con$$constant), lo($con$$constant)) becomes 6884 instruct xorL_reg_immRot(iRegL dst, iRegL src1, immLlowRot con) %{ 6885 match(Set dst (XorL src1 con)); 6886 ins_cost(DEFAULT_COST); 6887 size(8); 6888 format %{ "XOR $dst.hi,$src1.hi,$con\t! long\n\t" 6889 "XOR $dst.lo,$src1.lo,0\t! long" %} 6890 ins_encode %{ 6891 __ eor($dst$$Register, $src1$$Register, $con$$constant); 6892 __ eor($dst$$Register->successor(), $src1$$Register->successor(), 0); 6893 %} 6894 ins_pipe(ialu_reg_imm); 6895 %} 6896 6897 instruct cmpLTMask_reg_reg( iRegI dst, iRegI p, iRegI q, flagsReg ccr ) %{ 6898 match(Set dst (CmpLTMask p q)); 6899 effect( KILL ccr ); 6900 ins_cost(DEFAULT_COST*3); 6901 format %{ "CMP $p,$q\n\t" 6902 "MOV $dst, #0\n\t" 6903 "MOV.lt $dst, #-1" %} 6904 ins_encode %{ 6905 __ cmp($p$$Register, $q$$Register); 6906 __ mov($dst$$Register, 0); 6907 __ mvn($dst$$Register, 0, lt); 6908 %} 6909 ins_pipe(ialu_reg_reg_ialu); 6910 %} 6911 6912 instruct cmpLTMask_reg_imm( iRegI dst, iRegI p, aimmI q, flagsReg ccr ) %{ 6913 match(Set dst (CmpLTMask p q)); 6914 effect( KILL ccr ); 6915 ins_cost(DEFAULT_COST*3); 6916 format %{ "CMP $p,$q\n\t" 6917 "MOV $dst, #0\n\t" 6918 "MOV.lt $dst, #-1" %} 6919 ins_encode %{ 6920 __ cmp($p$$Register, $q$$constant); 6921 __ mov($dst$$Register, 0); 6922 __ mvn($dst$$Register, 0, lt); 6923 %} 6924 ins_pipe(ialu_reg_reg_ialu); 6925 %} 6926 6927 instruct cadd_cmpLTMask3( iRegI p, iRegI q, iRegI y, iRegI z, flagsReg ccr ) %{ 6928 match(Set z (AddI (AndI (CmpLTMask p q) y) z)); 6929 effect( KILL ccr ); 6930 ins_cost(DEFAULT_COST*2); 6931 format %{ "CMP $p,$q\n\t" 6932 "ADD.lt $z,$y,$z" %} 6933 ins_encode %{ 6934 __ cmp($p$$Register, $q$$Register); 6935 __ add($z$$Register, $y$$Register, $z$$Register, lt); 6936 %} 6937 ins_pipe( cadd_cmpltmask ); 6938 %} 6939 6940 // FIXME: remove unused "dst" 6941 instruct cadd_cmpLTMask4( iRegI dst, iRegI p, aimmI q, iRegI y, iRegI z, flagsReg ccr ) %{ 6942 match(Set z (AddI (AndI (CmpLTMask p q) y) z)); 6943 effect( KILL ccr ); 6944 ins_cost(DEFAULT_COST*2); 6945 format %{ "CMP $p,$q\n\t" 6946 "ADD.lt $z,$y,$z" %} 6947 ins_encode %{ 6948 __ cmp($p$$Register, $q$$constant); 6949 __ add($z$$Register, $y$$Register, $z$$Register, lt); 6950 %} 6951 ins_pipe( cadd_cmpltmask ); 6952 %} 6953 6954 instruct cadd_cmpLTMask( iRegI p, iRegI q, iRegI y, flagsReg ccr ) %{ 6955 match(Set p (AddI (AndI (CmpLTMask p q) y) (SubI p q))); 6956 effect( KILL ccr ); 6957 ins_cost(DEFAULT_COST*2); 6958 format %{ "SUBS $p,$p,$q\n\t" 6959 "ADD.lt $p,$y,$p" %} 6960 ins_encode %{ 6961 __ subs($p$$Register, $p$$Register, $q$$Register); 6962 __ add($p$$Register, $y$$Register, $p$$Register, lt); 6963 %} 6964 ins_pipe( cadd_cmpltmask ); 6965 %} 6966 6967 //----------Arithmetic Conversion Instructions--------------------------------- 6968 // The conversions operations are all Alpha sorted. Please keep it that way! 6969 6970 instruct convD2F_reg(regF dst, regD src) %{ 6971 match(Set dst (ConvD2F src)); 6972 size(4); 6973 format %{ "FCVTSD $dst,$src" %} 6974 ins_encode %{ 6975 __ convert_d2f($dst$$FloatRegister, $src$$FloatRegister); 6976 %} 6977 ins_pipe(fcvtD2F); 6978 %} 6979 6980 // Convert a double to an int in a float register. 6981 // If the double is a NAN, stuff a zero in instead. 6982 6983 instruct convD2I_reg_reg(iRegI dst, regD src, regF tmp) %{ 6984 match(Set dst (ConvD2I src)); 6985 effect( TEMP tmp ); 6986 ins_cost(DEFAULT_COST*2 + MEMORY_REF_COST*2 + BRANCH_COST); // FIXME 6987 format %{ "FTOSIZD $tmp,$src\n\t" 6988 "FMRS $dst, $tmp" %} 6989 ins_encode %{ 6990 __ ftosizd($tmp$$FloatRegister, $src$$FloatRegister); 6991 __ fmrs($dst$$Register, $tmp$$FloatRegister); 6992 %} 6993 ins_pipe(fcvtD2I); 6994 %} 6995 6996 // Convert a double to a long in a double register. 6997 // If the double is a NAN, stuff a zero in instead. 6998 6999 // Double to Long conversion 7000 instruct convD2L_reg(R0R1RegL dst, regD src) %{ 7001 match(Set dst (ConvD2L src)); 7002 effect(CALL); 7003 ins_cost(MEMORY_REF_COST); // FIXME 7004 format %{ "convD2L $dst,$src\t ! call to SharedRuntime::d2l" %} 7005 ins_encode %{ 7006 #ifndef __ABI_HARD__ 7007 __ fmrrd($dst$$Register, $dst$$Register->successor(), $src$$FloatRegister); 7008 #else 7009 if ($src$$FloatRegister != D0) { 7010 __ mov_double(D0, $src$$FloatRegister); 7011 } 7012 #endif 7013 address target = CAST_FROM_FN_PTR(address, SharedRuntime::d2l); 7014 __ call(target, relocInfo::runtime_call_type); 7015 %} 7016 ins_pipe(fcvtD2L); 7017 %} 7018 7019 instruct convF2D_reg(regD dst, regF src) %{ 7020 match(Set dst (ConvF2D src)); 7021 size(4); 7022 format %{ "FCVTDS $dst,$src" %} 7023 ins_encode %{ 7024 __ convert_f2d($dst$$FloatRegister, $src$$FloatRegister); 7025 %} 7026 ins_pipe(fcvtF2D); 7027 %} 7028 7029 instruct convF2I_reg_reg(iRegI dst, regF src, regF tmp) %{ 7030 match(Set dst (ConvF2I src)); 7031 effect( TEMP tmp ); 7032 ins_cost(DEFAULT_COST*2 + MEMORY_REF_COST*2 + BRANCH_COST); // FIXME 7033 size(8); 7034 format %{ "FTOSIZS $tmp,$src\n\t" 7035 "FMRS $dst, $tmp" %} 7036 ins_encode %{ 7037 __ ftosizs($tmp$$FloatRegister, $src$$FloatRegister); 7038 __ fmrs($dst$$Register, $tmp$$FloatRegister); 7039 %} 7040 ins_pipe(fcvtF2I); 7041 %} 7042 7043 // Float to Long conversion 7044 instruct convF2L_reg(R0R1RegL dst, regF src, R0RegI arg1) %{ 7045 match(Set dst (ConvF2L src)); 7046 ins_cost(DEFAULT_COST*2 + MEMORY_REF_COST*2 + BRANCH_COST); // FIXME 7047 effect(CALL); 7048 format %{ "convF2L $dst,$src\t! call to SharedRuntime::f2l" %} 7049 ins_encode %{ 7050 #ifndef __ABI_HARD__ 7051 __ fmrs($arg1$$Register, $src$$FloatRegister); 7052 #else 7053 if($src$$FloatRegister != S0) { 7054 __ mov_float(S0, $src$$FloatRegister); 7055 } 7056 #endif 7057 address target = CAST_FROM_FN_PTR(address, SharedRuntime::f2l); 7058 __ call(target, relocInfo::runtime_call_type); 7059 %} 7060 ins_pipe(fcvtF2L); 7061 %} 7062 7063 instruct convI2D_reg_reg(iRegI src, regD_low dst) %{ 7064 match(Set dst (ConvI2D src)); 7065 ins_cost(DEFAULT_COST + MEMORY_REF_COST); // FIXME 7066 size(8); 7067 format %{ "FMSR $dst,$src \n\t" 7068 "FSITOD $dst $dst"%} 7069 ins_encode %{ 7070 __ fmsr($dst$$FloatRegister, $src$$Register); 7071 __ fsitod($dst$$FloatRegister, $dst$$FloatRegister); 7072 %} 7073 ins_pipe(fcvtI2D); 7074 %} 7075 7076 instruct convI2F_reg_reg( regF dst, iRegI src ) %{ 7077 match(Set dst (ConvI2F src)); 7078 ins_cost(DEFAULT_COST + MEMORY_REF_COST); // FIXME 7079 size(8); 7080 format %{ "FMSR $dst,$src \n\t" 7081 "FSITOS $dst, $dst"%} 7082 ins_encode %{ 7083 __ fmsr($dst$$FloatRegister, $src$$Register); 7084 __ fsitos($dst$$FloatRegister, $dst$$FloatRegister); 7085 %} 7086 ins_pipe(fcvtI2F); 7087 %} 7088 7089 instruct convI2L_reg(iRegL dst, iRegI src) %{ 7090 match(Set dst (ConvI2L src)); 7091 size(8); 7092 format %{ "MOV $dst.lo, $src \n\t" 7093 "ASR $dst.hi,$src,31\t! int->long" %} 7094 ins_encode %{ 7095 __ mov($dst$$Register, $src$$Register); 7096 __ mov($dst$$Register->successor(), AsmOperand($src$$Register, asr, 31)); 7097 %} 7098 ins_pipe(ialu_reg_reg); 7099 %} 7100 7101 // Zero-extend convert int to long 7102 instruct convI2L_reg_zex(iRegL dst, iRegI src, immL_32bits mask ) %{ 7103 match(Set dst (AndL (ConvI2L src) mask) ); 7104 size(8); 7105 format %{ "MOV $dst.lo,$src.lo\t! zero-extend int to long\n\t" 7106 "MOV $dst.hi, 0"%} 7107 ins_encode %{ 7108 __ mov($dst$$Register, $src$$Register); 7109 __ mov($dst$$Register->successor(), 0); 7110 %} 7111 ins_pipe(ialu_reg_reg); 7112 %} 7113 7114 // Zero-extend long 7115 instruct zerox_long(iRegL dst, iRegL src, immL_32bits mask ) %{ 7116 match(Set dst (AndL src mask) ); 7117 size(8); 7118 format %{ "MOV $dst.lo,$src.lo\t! zero-extend long\n\t" 7119 "MOV $dst.hi, 0"%} 7120 ins_encode %{ 7121 __ mov($dst$$Register, $src$$Register); 7122 __ mov($dst$$Register->successor(), 0); 7123 %} 7124 ins_pipe(ialu_reg_reg); 7125 %} 7126 7127 instruct MoveF2I_reg_reg(iRegI dst, regF src) %{ 7128 match(Set dst (MoveF2I src)); 7129 effect(DEF dst, USE src); 7130 ins_cost(MEMORY_REF_COST); // FIXME 7131 7132 size(4); 7133 format %{ "FMRS $dst,$src\t! MoveF2I" %} 7134 ins_encode %{ 7135 __ fmrs($dst$$Register, $src$$FloatRegister); 7136 %} 7137 ins_pipe(iload_mem); // FIXME 7138 %} 7139 7140 instruct MoveI2F_reg_reg(regF dst, iRegI src) %{ 7141 match(Set dst (MoveI2F src)); 7142 ins_cost(MEMORY_REF_COST); // FIXME 7143 7144 size(4); 7145 format %{ "FMSR $dst,$src\t! MoveI2F" %} 7146 ins_encode %{ 7147 __ fmsr($dst$$FloatRegister, $src$$Register); 7148 %} 7149 ins_pipe(iload_mem); // FIXME 7150 %} 7151 7152 instruct MoveD2L_reg_reg(iRegL dst, regD src) %{ 7153 match(Set dst (MoveD2L src)); 7154 effect(DEF dst, USE src); 7155 ins_cost(MEMORY_REF_COST); // FIXME 7156 7157 size(4); 7158 format %{ "FMRRD $dst,$src\t! MoveD2L" %} 7159 ins_encode %{ 7160 __ fmrrd($dst$$Register, $dst$$Register->successor(), $src$$FloatRegister); 7161 %} 7162 ins_pipe(iload_mem); // FIXME 7163 %} 7164 7165 instruct MoveL2D_reg_reg(regD dst, iRegL src) %{ 7166 match(Set dst (MoveL2D src)); 7167 effect(DEF dst, USE src); 7168 ins_cost(MEMORY_REF_COST); // FIXME 7169 7170 size(4); 7171 format %{ "FMDRR $dst,$src\t! MoveL2D" %} 7172 ins_encode %{ 7173 __ fmdrr($dst$$FloatRegister, $src$$Register, $src$$Register->successor()); 7174 %} 7175 ins_pipe(ialu_reg_reg); // FIXME 7176 %} 7177 7178 //----------- 7179 // Long to Double conversion 7180 7181 // Magic constant, 0x43300000 7182 instruct loadConI_x43300000(iRegI dst) %{ 7183 effect(DEF dst); 7184 size(8); 7185 format %{ "MOV_SLOW $dst,0x43300000\t! 2^52" %} 7186 ins_encode %{ 7187 __ mov_slow($dst$$Register, 0x43300000); 7188 %} 7189 ins_pipe(ialu_none); 7190 %} 7191 7192 // Magic constant, 0x41f00000 7193 instruct loadConI_x41f00000(iRegI dst) %{ 7194 effect(DEF dst); 7195 size(8); 7196 format %{ "MOV_SLOW $dst, 0x41f00000\t! 2^32" %} 7197 ins_encode %{ 7198 __ mov_slow($dst$$Register, 0x41f00000); 7199 %} 7200 ins_pipe(ialu_none); 7201 %} 7202 7203 instruct loadConI_x0(iRegI dst) %{ 7204 effect(DEF dst); 7205 size(4); 7206 format %{ "MOV $dst, 0x0\t! 0" %} 7207 ins_encode %{ 7208 __ mov($dst$$Register, 0); 7209 %} 7210 ins_pipe(ialu_none); 7211 %} 7212 7213 // Construct a double from two float halves 7214 instruct regDHi_regDLo_to_regD(regD_low dst, regD_low src1, regD_low src2) %{ 7215 effect(DEF dst, USE src1, USE src2); 7216 size(8); 7217 format %{ "FCPYS $dst.hi,$src1.hi\n\t" 7218 "FCPYS $dst.lo,$src2.lo" %} 7219 ins_encode %{ 7220 __ fcpys($dst$$FloatRegister->successor(), $src1$$FloatRegister->successor()); 7221 __ fcpys($dst$$FloatRegister, $src2$$FloatRegister); 7222 %} 7223 ins_pipe(faddD_reg_reg); 7224 %} 7225 7226 // Convert integer in high half of a double register (in the lower half of 7227 // the double register file) to double 7228 instruct convI2D_regDHi_regD(regD dst, regD_low src) %{ 7229 effect(DEF dst, USE src); 7230 size(4); 7231 format %{ "FSITOD $dst,$src" %} 7232 ins_encode %{ 7233 __ fsitod($dst$$FloatRegister, $src$$FloatRegister->successor()); 7234 %} 7235 ins_pipe(fcvtLHi2D); 7236 %} 7237 7238 // Add float double precision 7239 instruct addD_regD_regD(regD dst, regD src1, regD src2) %{ 7240 effect(DEF dst, USE src1, USE src2); 7241 size(4); 7242 format %{ "FADDD $dst,$src1,$src2" %} 7243 ins_encode %{ 7244 __ add_double($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister); 7245 %} 7246 ins_pipe(faddD_reg_reg); 7247 %} 7248 7249 // Sub float double precision 7250 instruct subD_regD_regD(regD dst, regD src1, regD src2) %{ 7251 effect(DEF dst, USE src1, USE src2); 7252 size(4); 7253 format %{ "FSUBD $dst,$src1,$src2" %} 7254 ins_encode %{ 7255 __ sub_double($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister); 7256 %} 7257 ins_pipe(faddD_reg_reg); 7258 %} 7259 7260 // Mul float double precision 7261 instruct mulD_regD_regD(regD dst, regD src1, regD src2) %{ 7262 effect(DEF dst, USE src1, USE src2); 7263 size(4); 7264 format %{ "FMULD $dst,$src1,$src2" %} 7265 ins_encode %{ 7266 __ mul_double($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister); 7267 %} 7268 ins_pipe(fmulD_reg_reg); 7269 %} 7270 7271 instruct regL_to_regD(regD dst, iRegL src) %{ 7272 // No match rule to avoid chain rule match. 7273 effect(DEF dst, USE src); 7274 ins_cost(MEMORY_REF_COST); 7275 size(4); 7276 format %{ "FMDRR $dst,$src\t! regL to regD" %} 7277 ins_encode %{ 7278 __ fmdrr($dst$$FloatRegister, $src$$Register, $src$$Register->successor()); 7279 %} 7280 ins_pipe(ialu_reg_reg); // FIXME 7281 %} 7282 7283 instruct regI_regI_to_regD(regD dst, iRegI src1, iRegI src2) %{ 7284 // No match rule to avoid chain rule match. 7285 effect(DEF dst, USE src1, USE src2); 7286 ins_cost(MEMORY_REF_COST); 7287 size(4); 7288 format %{ "FMDRR $dst,$src1,$src2\t! regI,regI to regD" %} 7289 ins_encode %{ 7290 __ fmdrr($dst$$FloatRegister, $src1$$Register, $src2$$Register); 7291 %} 7292 ins_pipe(ialu_reg_reg); // FIXME 7293 %} 7294 7295 instruct convL2D_reg_slow_fxtof(regD dst, iRegL src) %{ 7296 match(Set dst (ConvL2D src)); 7297 ins_cost(DEFAULT_COST*8 + MEMORY_REF_COST*6); // FIXME 7298 7299 expand %{ 7300 regD_low tmpsrc; 7301 iRegI ix43300000; 7302 iRegI ix41f00000; 7303 iRegI ix0; 7304 regD_low dx43300000; 7305 regD dx41f00000; 7306 regD tmp1; 7307 regD_low tmp2; 7308 regD tmp3; 7309 regD tmp4; 7310 7311 regL_to_regD(tmpsrc, src); 7312 7313 loadConI_x43300000(ix43300000); 7314 loadConI_x41f00000(ix41f00000); 7315 loadConI_x0(ix0); 7316 7317 regI_regI_to_regD(dx43300000, ix0, ix43300000); 7318 regI_regI_to_regD(dx41f00000, ix0, ix41f00000); 7319 7320 convI2D_regDHi_regD(tmp1, tmpsrc); 7321 regDHi_regDLo_to_regD(tmp2, dx43300000, tmpsrc); 7322 subD_regD_regD(tmp3, tmp2, dx43300000); 7323 mulD_regD_regD(tmp4, tmp1, dx41f00000); 7324 addD_regD_regD(dst, tmp3, tmp4); 7325 %} 7326 %} 7327 7328 instruct convL2I_reg(iRegI dst, iRegL src) %{ 7329 match(Set dst (ConvL2I src)); 7330 size(4); 7331 format %{ "MOV $dst,$src.lo\t! long->int" %} 7332 ins_encode %{ 7333 __ mov($dst$$Register, $src$$Register); 7334 %} 7335 ins_pipe(ialu_move_reg_I_to_L); 7336 %} 7337 7338 // Register Shift Right Immediate 7339 instruct shrL_reg_imm6_L2I(iRegI dst, iRegL src, immI_32_63 cnt) %{ 7340 match(Set dst (ConvL2I (RShiftL src cnt))); 7341 size(4); 7342 format %{ "ASR $dst,$src.hi,($cnt - 32)\t! long->int or mov if $cnt==32" %} 7343 ins_encode %{ 7344 if ($cnt$$constant == 32) { 7345 __ mov($dst$$Register, $src$$Register->successor()); 7346 } else { 7347 __ mov($dst$$Register, AsmOperand($src$$Register->successor(), asr, $cnt$$constant - 32)); 7348 } 7349 %} 7350 ins_pipe(ialu_reg_imm); 7351 %} 7352 7353 7354 //----------Control Flow Instructions------------------------------------------ 7355 // Compare Instructions 7356 // Compare Integers 7357 instruct compI_iReg(flagsReg icc, iRegI op1, iRegI op2) %{ 7358 match(Set icc (CmpI op1 op2)); 7359 effect( DEF icc, USE op1, USE op2 ); 7360 7361 size(4); 7362 format %{ "cmp_32 $op1,$op2\t! int" %} 7363 ins_encode %{ 7364 __ cmp_32($op1$$Register, $op2$$Register); 7365 %} 7366 ins_pipe(ialu_cconly_reg_reg); 7367 %} 7368 7369 #ifdef _LP64 7370 // Compare compressed pointers 7371 instruct compN_reg2(flagsRegU icc, iRegN op1, iRegN op2) %{ 7372 match(Set icc (CmpN op1 op2)); 7373 effect( DEF icc, USE op1, USE op2 ); 7374 7375 size(4); 7376 format %{ "cmp_32 $op1,$op2\t! int" %} 7377 ins_encode %{ 7378 __ cmp_32($op1$$Register, $op2$$Register); 7379 %} 7380 ins_pipe(ialu_cconly_reg_reg); 7381 %} 7382 #endif 7383 7384 instruct compU_iReg(flagsRegU icc, iRegI op1, iRegI op2) %{ 7385 match(Set icc (CmpU op1 op2)); 7386 7387 size(4); 7388 format %{ "cmp_32 $op1,$op2\t! unsigned int" %} 7389 ins_encode %{ 7390 __ cmp_32($op1$$Register, $op2$$Register); 7391 %} 7392 ins_pipe(ialu_cconly_reg_reg); 7393 %} 7394 7395 instruct compI_iReg_immneg(flagsReg icc, iRegI op1, aimmIneg op2) %{ 7396 match(Set icc (CmpI op1 op2)); 7397 effect( DEF icc, USE op1 ); 7398 7399 size(4); 7400 format %{ "cmn_32 $op1,-$op2\t! int" %} 7401 ins_encode %{ 7402 __ cmn_32($op1$$Register, -$op2$$constant); 7403 %} 7404 ins_pipe(ialu_cconly_reg_imm); 7405 %} 7406 7407 instruct compI_iReg_imm(flagsReg icc, iRegI op1, aimmI op2) %{ 7408 match(Set icc (CmpI op1 op2)); 7409 effect( DEF icc, USE op1 ); 7410 7411 size(4); 7412 format %{ "cmp_32 $op1,$op2\t! int" %} 7413 ins_encode %{ 7414 __ cmp_32($op1$$Register, $op2$$constant); 7415 %} 7416 ins_pipe(ialu_cconly_reg_imm); 7417 %} 7418 7419 instruct testI_reg_reg( flagsReg_EQNELTGE icc, iRegI op1, iRegI op2, immI0 zero ) %{ 7420 match(Set icc (CmpI (AndI op1 op2) zero)); 7421 size(4); 7422 format %{ "tst_32 $op2,$op1" %} 7423 7424 ins_encode %{ 7425 __ tst_32($op1$$Register, $op2$$Register); 7426 %} 7427 ins_pipe(ialu_cconly_reg_reg_zero); 7428 %} 7429 7430 instruct testshlI_reg_reg_reg( flagsReg_EQNELTGE icc, iRegI op1, iRegI op2, iRegI op3, immI0 zero ) %{ 7431 match(Set icc (CmpI (AndI op1 (LShiftI op2 op3)) zero)); 7432 size(4); 7433 format %{ "TST $op2,$op1<<$op3" %} 7434 7435 ins_encode %{ 7436 __ tst($op1$$Register, AsmOperand($op2$$Register, lsl, $op3$$Register)); 7437 %} 7438 ins_pipe(ialu_cconly_reg_reg_zero); 7439 %} 7440 7441 instruct testshlI_reg_reg_imm( flagsReg_EQNELTGE icc, iRegI op1, iRegI op2, immU5 op3, immI0 zero ) %{ 7442 match(Set icc (CmpI (AndI op1 (LShiftI op2 op3)) zero)); 7443 size(4); 7444 format %{ "tst_32 $op2,$op1<<$op3" %} 7445 7446 ins_encode %{ 7447 __ tst_32($op1$$Register, AsmOperand($op2$$Register, lsl, $op3$$constant)); 7448 %} 7449 ins_pipe(ialu_cconly_reg_reg_zero); 7450 %} 7451 7452 instruct testsarI_reg_reg_reg( flagsReg_EQNELTGE icc, iRegI op1, iRegI op2, iRegI op3, immI0 zero ) %{ 7453 match(Set icc (CmpI (AndI op1 (RShiftI op2 op3)) zero)); 7454 size(4); 7455 format %{ "TST $op2,$op1<<$op3" %} 7456 7457 ins_encode %{ 7458 __ tst($op1$$Register, AsmOperand($op2$$Register, asr, $op3$$Register)); 7459 %} 7460 ins_pipe(ialu_cconly_reg_reg_zero); 7461 %} 7462 7463 instruct testsarI_reg_reg_imm( flagsReg_EQNELTGE icc, iRegI op1, iRegI op2, immU5 op3, immI0 zero ) %{ 7464 match(Set icc (CmpI (AndI op1 (RShiftI op2 op3)) zero)); 7465 size(4); 7466 format %{ "tst_32 $op2,$op1<<$op3" %} 7467 7468 ins_encode %{ 7469 __ tst_32($op1$$Register, AsmOperand($op2$$Register, asr, $op3$$constant)); 7470 %} 7471 ins_pipe(ialu_cconly_reg_reg_zero); 7472 %} 7473 7474 instruct testshrI_reg_reg_reg( flagsReg_EQNELTGE icc, iRegI op1, iRegI op2, iRegI op3, immI0 zero ) %{ 7475 match(Set icc (CmpI (AndI op1 (URShiftI op2 op3)) zero)); 7476 size(4); 7477 format %{ "TST $op2,$op1<<$op3" %} 7478 7479 ins_encode %{ 7480 __ tst($op1$$Register, AsmOperand($op2$$Register, lsr, $op3$$Register)); 7481 %} 7482 ins_pipe(ialu_cconly_reg_reg_zero); 7483 %} 7484 7485 instruct testshrI_reg_reg_imm( flagsReg_EQNELTGE icc, iRegI op1, iRegI op2, immU5 op3, immI0 zero ) %{ 7486 match(Set icc (CmpI (AndI op1 (URShiftI op2 op3)) zero)); 7487 size(4); 7488 format %{ "tst_32 $op2,$op1<<$op3" %} 7489 7490 ins_encode %{ 7491 __ tst_32($op1$$Register, AsmOperand($op2$$Register, lsr, $op3$$constant)); 7492 %} 7493 ins_pipe(ialu_cconly_reg_reg_zero); 7494 %} 7495 7496 instruct testI_reg_imm( flagsReg_EQNELTGE icc, iRegI op1, limmI op2, immI0 zero ) %{ 7497 match(Set icc (CmpI (AndI op1 op2) zero)); 7498 size(4); 7499 format %{ "tst_32 $op2,$op1" %} 7500 7501 ins_encode %{ 7502 __ tst_32($op1$$Register, $op2$$constant); 7503 %} 7504 ins_pipe(ialu_cconly_reg_imm_zero); 7505 %} 7506 7507 instruct compL_reg_reg_LTGE(flagsRegL_LTGE xcc, iRegL op1, iRegL op2, iRegL tmp) %{ 7508 match(Set xcc (CmpL op1 op2)); 7509 effect( DEF xcc, USE op1, USE op2, TEMP tmp ); 7510 7511 size(8); 7512 format %{ "SUBS $tmp,$op1.low,$op2.low\t\t! long\n\t" 7513 "SBCS $tmp,$op1.hi,$op2.hi" %} 7514 ins_encode %{ 7515 __ subs($tmp$$Register, $op1$$Register, $op2$$Register); 7516 __ sbcs($tmp$$Register->successor(), $op1$$Register->successor(), $op2$$Register->successor()); 7517 %} 7518 ins_pipe(ialu_cconly_reg_reg); 7519 %} 7520 7521 instruct compUL_reg_reg_LTGE(flagsRegUL_LTGE xcc, iRegL op1, iRegL op2, iRegL tmp) %{ 7522 match(Set xcc (CmpUL op1 op2)); 7523 effect(DEF xcc, USE op1, USE op2, TEMP tmp); 7524 7525 size(8); 7526 format %{ "SUBS $tmp,$op1.low,$op2.low\t\t! unsigned long\n\t" 7527 "SBCS $tmp,$op1.hi,$op2.hi" %} 7528 ins_encode %{ 7529 __ subs($tmp$$Register, $op1$$Register, $op2$$Register); 7530 __ sbcs($tmp$$Register->successor(), $op1$$Register->successor(), $op2$$Register->successor()); 7531 %} 7532 ins_pipe(ialu_cconly_reg_reg); 7533 %} 7534 7535 instruct compL_reg_reg_EQNE(flagsRegL_EQNE xcc, iRegL op1, iRegL op2) %{ 7536 match(Set xcc (CmpL op1 op2)); 7537 effect( DEF xcc, USE op1, USE op2 ); 7538 7539 size(8); 7540 format %{ "TEQ $op1.hi,$op2.hi\t\t! long\n\t" 7541 "TEQ.eq $op1.lo,$op2.lo" %} 7542 ins_encode %{ 7543 __ teq($op1$$Register->successor(), $op2$$Register->successor()); 7544 __ teq($op1$$Register, $op2$$Register, eq); 7545 %} 7546 ins_pipe(ialu_cconly_reg_reg); 7547 %} 7548 7549 instruct compL_reg_reg_LEGT(flagsRegL_LEGT xcc, iRegL op1, iRegL op2, iRegL tmp) %{ 7550 match(Set xcc (CmpL op1 op2)); 7551 effect( DEF xcc, USE op1, USE op2, TEMP tmp ); 7552 7553 size(8); 7554 format %{ "SUBS $tmp,$op2.low,$op1.low\t\t! long\n\t" 7555 "SBCS $tmp,$op2.hi,$op1.hi" %} 7556 ins_encode %{ 7557 __ subs($tmp$$Register, $op2$$Register, $op1$$Register); 7558 __ sbcs($tmp$$Register->successor(), $op2$$Register->successor(), $op1$$Register->successor()); 7559 %} 7560 ins_pipe(ialu_cconly_reg_reg); 7561 %} 7562 7563 // TODO: try immLRot2 instead, (0, $con$$constant) becomes 7564 // (hi($con$$constant), lo($con$$constant)) becomes 7565 instruct compL_reg_con_LTGE(flagsRegL_LTGE xcc, iRegL op1, immLlowRot con, iRegL tmp) %{ 7566 match(Set xcc (CmpL op1 con)); 7567 effect( DEF xcc, USE op1, USE con, TEMP tmp ); 7568 7569 size(8); 7570 format %{ "SUBS $tmp,$op1.low,$con\t\t! long\n\t" 7571 "SBCS $tmp,$op1.hi,0" %} 7572 ins_encode %{ 7573 __ subs($tmp$$Register, $op1$$Register, $con$$constant); 7574 __ sbcs($tmp$$Register->successor(), $op1$$Register->successor(), 0); 7575 %} 7576 7577 ins_pipe(ialu_cconly_reg_reg); 7578 %} 7579 7580 // TODO: try immLRot2 instead, (0, $con$$constant) becomes 7581 // (hi($con$$constant), lo($con$$constant)) becomes 7582 instruct compL_reg_con_EQNE(flagsRegL_EQNE xcc, iRegL op1, immLlowRot con) %{ 7583 match(Set xcc (CmpL op1 con)); 7584 effect( DEF xcc, USE op1, USE con ); 7585 7586 size(8); 7587 format %{ "TEQ $op1.hi,0\t\t! long\n\t" 7588 "TEQ.eq $op1.lo,$con" %} 7589 ins_encode %{ 7590 __ teq($op1$$Register->successor(), 0); 7591 __ teq($op1$$Register, $con$$constant, eq); 7592 %} 7593 7594 ins_pipe(ialu_cconly_reg_reg); 7595 %} 7596 7597 // TODO: try immLRot2 instead, (0, $con$$constant) becomes 7598 // (hi($con$$constant), lo($con$$constant)) becomes 7599 instruct compL_reg_con_LEGT(flagsRegL_LEGT xcc, iRegL op1, immLlowRot con, iRegL tmp) %{ 7600 match(Set xcc (CmpL op1 con)); 7601 effect( DEF xcc, USE op1, USE con, TEMP tmp ); 7602 7603 size(8); 7604 format %{ "RSBS $tmp,$op1.low,$con\t\t! long\n\t" 7605 "RSCS $tmp,$op1.hi,0" %} 7606 ins_encode %{ 7607 __ rsbs($tmp$$Register, $op1$$Register, $con$$constant); 7608 __ rscs($tmp$$Register->successor(), $op1$$Register->successor(), 0); 7609 %} 7610 7611 ins_pipe(ialu_cconly_reg_reg); 7612 %} 7613 7614 instruct compUL_reg_reg_EQNE(flagsRegUL_EQNE xcc, iRegL op1, iRegL op2) %{ 7615 match(Set xcc (CmpUL op1 op2)); 7616 effect(DEF xcc, USE op1, USE op2); 7617 7618 size(8); 7619 format %{ "TEQ $op1.hi,$op2.hi\t\t! unsigned long\n\t" 7620 "TEQ.eq $op1.lo,$op2.lo" %} 7621 ins_encode %{ 7622 __ teq($op1$$Register->successor(), $op2$$Register->successor()); 7623 __ teq($op1$$Register, $op2$$Register, eq); 7624 %} 7625 ins_pipe(ialu_cconly_reg_reg); 7626 %} 7627 7628 instruct compUL_reg_reg_LEGT(flagsRegUL_LEGT xcc, iRegL op1, iRegL op2, iRegL tmp) %{ 7629 match(Set xcc (CmpUL op1 op2)); 7630 effect(DEF xcc, USE op1, USE op2, TEMP tmp); 7631 7632 size(8); 7633 format %{ "SUBS $tmp,$op2.low,$op1.low\t\t! unsigned long\n\t" 7634 "SBCS $tmp,$op2.hi,$op1.hi" %} 7635 ins_encode %{ 7636 __ subs($tmp$$Register, $op2$$Register, $op1$$Register); 7637 __ sbcs($tmp$$Register->successor(), $op2$$Register->successor(), $op1$$Register->successor()); 7638 %} 7639 ins_pipe(ialu_cconly_reg_reg); 7640 %} 7641 7642 // TODO: try immLRot2 instead, (0, $con$$constant) becomes 7643 // (hi($con$$constant), lo($con$$constant)) becomes 7644 instruct compUL_reg_con_LTGE(flagsRegUL_LTGE xcc, iRegL op1, immLlowRot con, iRegL tmp) %{ 7645 match(Set xcc (CmpUL op1 con)); 7646 effect(DEF xcc, USE op1, USE con, TEMP tmp); 7647 7648 size(8); 7649 format %{ "SUBS $tmp,$op1.low,$con\t\t! unsigned long\n\t" 7650 "SBCS $tmp,$op1.hi,0" %} 7651 ins_encode %{ 7652 __ subs($tmp$$Register, $op1$$Register, $con$$constant); 7653 __ sbcs($tmp$$Register->successor(), $op1$$Register->successor(), 0); 7654 %} 7655 7656 ins_pipe(ialu_cconly_reg_reg); 7657 %} 7658 7659 // TODO: try immLRot2 instead, (0, $con$$constant) becomes 7660 // (hi($con$$constant), lo($con$$constant)) becomes 7661 instruct compUL_reg_con_EQNE(flagsRegUL_EQNE xcc, iRegL op1, immLlowRot con) %{ 7662 match(Set xcc (CmpUL op1 con)); 7663 effect(DEF xcc, USE op1, USE con); 7664 7665 size(8); 7666 format %{ "TEQ $op1.hi,0\t\t! unsigned long\n\t" 7667 "TEQ.eq $op1.lo,$con" %} 7668 ins_encode %{ 7669 __ teq($op1$$Register->successor(), 0); 7670 __ teq($op1$$Register, $con$$constant, eq); 7671 %} 7672 7673 ins_pipe(ialu_cconly_reg_reg); 7674 %} 7675 7676 // TODO: try immLRot2 instead, (0, $con$$constant) becomes 7677 // (hi($con$$constant), lo($con$$constant)) becomes 7678 instruct compUL_reg_con_LEGT(flagsRegUL_LEGT xcc, iRegL op1, immLlowRot con, iRegL tmp) %{ 7679 match(Set xcc (CmpUL op1 con)); 7680 effect(DEF xcc, USE op1, USE con, TEMP tmp); 7681 7682 size(8); 7683 format %{ "RSBS $tmp,$op1.low,$con\t\t! unsigned long\n\t" 7684 "RSCS $tmp,$op1.hi,0" %} 7685 ins_encode %{ 7686 __ rsbs($tmp$$Register, $op1$$Register, $con$$constant); 7687 __ rscs($tmp$$Register->successor(), $op1$$Register->successor(), 0); 7688 %} 7689 7690 ins_pipe(ialu_cconly_reg_reg); 7691 %} 7692 7693 /* instruct testL_reg_reg(flagsRegL xcc, iRegL op1, iRegL op2, immL0 zero) %{ */ 7694 /* match(Set xcc (CmpL (AndL op1 op2) zero)); */ 7695 /* ins_encode %{ */ 7696 /* __ stop("testL_reg_reg unimplemented"); */ 7697 /* %} */ 7698 /* ins_pipe(ialu_cconly_reg_reg); */ 7699 /* %} */ 7700 7701 /* // useful for checking the alignment of a pointer: */ 7702 /* instruct testL_reg_con(flagsRegL xcc, iRegL op1, immLlowRot con, immL0 zero) %{ */ 7703 /* match(Set xcc (CmpL (AndL op1 con) zero)); */ 7704 /* ins_encode %{ */ 7705 /* __ stop("testL_reg_con unimplemented"); */ 7706 /* %} */ 7707 /* ins_pipe(ialu_cconly_reg_reg); */ 7708 /* %} */ 7709 7710 instruct compU_iReg_imm(flagsRegU icc, iRegI op1, aimmU31 op2 ) %{ 7711 match(Set icc (CmpU op1 op2)); 7712 7713 size(4); 7714 format %{ "cmp_32 $op1,$op2\t! unsigned" %} 7715 ins_encode %{ 7716 __ cmp_32($op1$$Register, $op2$$constant); 7717 %} 7718 ins_pipe(ialu_cconly_reg_imm); 7719 %} 7720 7721 // Compare Pointers 7722 instruct compP_iRegP(flagsRegP pcc, iRegP op1, iRegP op2 ) %{ 7723 match(Set pcc (CmpP op1 op2)); 7724 7725 size(4); 7726 format %{ "CMP $op1,$op2\t! ptr" %} 7727 ins_encode %{ 7728 __ cmp($op1$$Register, $op2$$Register); 7729 %} 7730 ins_pipe(ialu_cconly_reg_reg); 7731 %} 7732 7733 instruct compP_iRegP_imm(flagsRegP pcc, iRegP op1, aimmP op2 ) %{ 7734 match(Set pcc (CmpP op1 op2)); 7735 7736 size(4); 7737 format %{ "CMP $op1,$op2\t! ptr" %} 7738 ins_encode %{ 7739 assert($op2$$constant == 0 || _opnds[2]->constant_reloc() == relocInfo::none, "reloc in cmp?"); 7740 __ cmp($op1$$Register, $op2$$constant); 7741 %} 7742 ins_pipe(ialu_cconly_reg_imm); 7743 %} 7744 7745 //----------Max and Min-------------------------------------------------------- 7746 // Min Instructions 7747 // Conditional move for min 7748 instruct cmovI_reg_lt( iRegI op2, iRegI op1, flagsReg icc ) %{ 7749 effect( USE_DEF op2, USE op1, USE icc ); 7750 7751 size(4); 7752 format %{ "MOV.lt $op2,$op1\t! min" %} 7753 ins_encode %{ 7754 __ mov($op2$$Register, $op1$$Register, lt); 7755 %} 7756 ins_pipe(ialu_reg_flags); 7757 %} 7758 7759 // Min Register with Register. 7760 instruct minI_eReg(iRegI op1, iRegI op2) %{ 7761 match(Set op2 (MinI op1 op2)); 7762 ins_cost(DEFAULT_COST*2); 7763 expand %{ 7764 flagsReg icc; 7765 compI_iReg(icc,op1,op2); 7766 cmovI_reg_lt(op2,op1,icc); 7767 %} 7768 %} 7769 7770 // Max Instructions 7771 // Conditional move for max 7772 instruct cmovI_reg_gt( iRegI op2, iRegI op1, flagsReg icc ) %{ 7773 effect( USE_DEF op2, USE op1, USE icc ); 7774 format %{ "MOV.gt $op2,$op1\t! max" %} 7775 ins_encode %{ 7776 __ mov($op2$$Register, $op1$$Register, gt); 7777 %} 7778 ins_pipe(ialu_reg_flags); 7779 %} 7780 7781 // Max Register with Register 7782 instruct maxI_eReg(iRegI op1, iRegI op2) %{ 7783 match(Set op2 (MaxI op1 op2)); 7784 ins_cost(DEFAULT_COST*2); 7785 expand %{ 7786 flagsReg icc; 7787 compI_iReg(icc,op1,op2); 7788 cmovI_reg_gt(op2,op1,icc); 7789 %} 7790 %} 7791 7792 7793 //----------Float Compares---------------------------------------------------- 7794 // Compare floating, generate condition code 7795 instruct cmpF_cc(flagsRegF fcc, flagsReg icc, regF src1, regF src2) %{ 7796 match(Set icc (CmpF src1 src2)); 7797 effect(KILL fcc); 7798 7799 size(8); 7800 format %{ "FCMPs $src1,$src2\n\t" 7801 "FMSTAT" %} 7802 ins_encode %{ 7803 __ fcmps($src1$$FloatRegister, $src2$$FloatRegister); 7804 __ fmstat(); 7805 %} 7806 ins_pipe(faddF_fcc_reg_reg_zero); 7807 %} 7808 7809 instruct cmpF0_cc(flagsRegF fcc, flagsReg icc, regF src1, immF0 src2) %{ 7810 match(Set icc (CmpF src1 src2)); 7811 effect(KILL fcc); 7812 7813 size(8); 7814 format %{ "FCMPs $src1,$src2\n\t" 7815 "FMSTAT" %} 7816 ins_encode %{ 7817 __ fcmpzs($src1$$FloatRegister); 7818 __ fmstat(); 7819 %} 7820 ins_pipe(faddF_fcc_reg_reg_zero); 7821 %} 7822 7823 instruct cmpD_cc(flagsRegF fcc, flagsReg icc, regD src1, regD src2) %{ 7824 match(Set icc (CmpD src1 src2)); 7825 effect(KILL fcc); 7826 7827 size(8); 7828 format %{ "FCMPd $src1,$src2 \n\t" 7829 "FMSTAT" %} 7830 ins_encode %{ 7831 __ fcmpd($src1$$FloatRegister, $src2$$FloatRegister); 7832 __ fmstat(); 7833 %} 7834 ins_pipe(faddD_fcc_reg_reg_zero); 7835 %} 7836 7837 instruct cmpD0_cc(flagsRegF fcc, flagsReg icc, regD src1, immD0 src2) %{ 7838 match(Set icc (CmpD src1 src2)); 7839 effect(KILL fcc); 7840 7841 size(8); 7842 format %{ "FCMPZd $src1,$src2 \n\t" 7843 "FMSTAT" %} 7844 ins_encode %{ 7845 __ fcmpzd($src1$$FloatRegister); 7846 __ fmstat(); 7847 %} 7848 ins_pipe(faddD_fcc_reg_reg_zero); 7849 %} 7850 7851 // Compare floating, generate -1,0,1 7852 instruct cmpF_reg(iRegI dst, regF src1, regF src2, flagsRegF fcc) %{ 7853 match(Set dst (CmpF3 src1 src2)); 7854 effect(KILL fcc); 7855 ins_cost(DEFAULT_COST*3+BRANCH_COST*3); // FIXME 7856 size(20); 7857 // same number of instructions as code using conditional moves but 7858 // doesn't kill integer condition register 7859 format %{ "FCMPs $dst,$src1,$src2 \n\t" 7860 "VMRS $dst, FPSCR \n\t" 7861 "OR $dst, $dst, 0x08000000 \n\t" 7862 "EOR $dst, $dst, $dst << 3 \n\t" 7863 "MOV $dst, $dst >> 30" %} 7864 ins_encode %{ 7865 __ fcmps($src1$$FloatRegister, $src2$$FloatRegister); 7866 __ floating_cmp($dst$$Register); 7867 %} 7868 ins_pipe( floating_cmp ); 7869 %} 7870 7871 instruct cmpF0_reg(iRegI dst, regF src1, immF0 src2, flagsRegF fcc) %{ 7872 match(Set dst (CmpF3 src1 src2)); 7873 effect(KILL fcc); 7874 ins_cost(DEFAULT_COST*3+BRANCH_COST*3); // FIXME 7875 size(20); 7876 // same number of instructions as code using conditional moves but 7877 // doesn't kill integer condition register 7878 format %{ "FCMPZs $dst,$src1,$src2 \n\t" 7879 "VMRS $dst, FPSCR \n\t" 7880 "OR $dst, $dst, 0x08000000 \n\t" 7881 "EOR $dst, $dst, $dst << 3 \n\t" 7882 "MOV $dst, $dst >> 30" %} 7883 ins_encode %{ 7884 __ fcmpzs($src1$$FloatRegister); 7885 __ floating_cmp($dst$$Register); 7886 %} 7887 ins_pipe( floating_cmp ); 7888 %} 7889 7890 instruct cmpD_reg(iRegI dst, regD src1, regD src2, flagsRegF fcc) %{ 7891 match(Set dst (CmpD3 src1 src2)); 7892 effect(KILL fcc); 7893 ins_cost(DEFAULT_COST*3+BRANCH_COST*3); // FIXME 7894 size(20); 7895 // same number of instructions as code using conditional moves but 7896 // doesn't kill integer condition register 7897 format %{ "FCMPd $dst,$src1,$src2 \n\t" 7898 "VMRS $dst, FPSCR \n\t" 7899 "OR $dst, $dst, 0x08000000 \n\t" 7900 "EOR $dst, $dst, $dst << 3 \n\t" 7901 "MOV $dst, $dst >> 30" %} 7902 ins_encode %{ 7903 __ fcmpd($src1$$FloatRegister, $src2$$FloatRegister); 7904 __ floating_cmp($dst$$Register); 7905 %} 7906 ins_pipe( floating_cmp ); 7907 %} 7908 7909 instruct cmpD0_reg(iRegI dst, regD src1, immD0 src2, flagsRegF fcc) %{ 7910 match(Set dst (CmpD3 src1 src2)); 7911 effect(KILL fcc); 7912 ins_cost(DEFAULT_COST*3+BRANCH_COST*3); // FIXME 7913 size(20); 7914 // same number of instructions as code using conditional moves but 7915 // doesn't kill integer condition register 7916 format %{ "FCMPZd $dst,$src1,$src2 \n\t" 7917 "VMRS $dst, FPSCR \n\t" 7918 "OR $dst, $dst, 0x08000000 \n\t" 7919 "EOR $dst, $dst, $dst << 3 \n\t" 7920 "MOV $dst, $dst >> 30" %} 7921 ins_encode %{ 7922 __ fcmpzd($src1$$FloatRegister); 7923 __ floating_cmp($dst$$Register); 7924 %} 7925 ins_pipe( floating_cmp ); 7926 %} 7927 7928 //----------Branches--------------------------------------------------------- 7929 // Jump 7930 // (compare 'operand indIndex' and 'instruct addP_reg_reg' above) 7931 // FIXME 7932 instruct jumpXtnd(iRegX switch_val, iRegP tmp) %{ 7933 match(Jump switch_val); 7934 effect(TEMP tmp); 7935 ins_cost(350); 7936 format %{ "ADD $tmp, $constanttablebase, $switch_val\n\t" 7937 "LDR $tmp,[$tmp + $constantoffset]\n\t" 7938 "BX $tmp" %} 7939 size(20); 7940 ins_encode %{ 7941 Register table_reg; 7942 Register label_reg = $tmp$$Register; 7943 if (constant_offset() == 0) { 7944 table_reg = $constanttablebase; 7945 __ ldr(label_reg, Address(table_reg, $switch_val$$Register)); 7946 } else { 7947 table_reg = $tmp$$Register; 7948 int offset = $constantoffset; 7949 if (is_memoryP(offset)) { 7950 __ add(table_reg, $constanttablebase, $switch_val$$Register); 7951 __ ldr(label_reg, Address(table_reg, offset)); 7952 } else { 7953 __ mov_slow(table_reg, $constantoffset); 7954 __ add(table_reg, $constanttablebase, table_reg); 7955 __ ldr(label_reg, Address(table_reg, $switch_val$$Register)); 7956 } 7957 } 7958 __ jump(label_reg); // ldr + b better than ldr to PC for branch predictor? 7959 // __ ldr(PC, Address($table$$Register, $switch_val$$Register)); 7960 %} 7961 ins_pipe(ialu_reg_reg); 7962 %} 7963 7964 // // Direct Branch. 7965 instruct branch(label labl) %{ 7966 match(Goto); 7967 effect(USE labl); 7968 7969 size(4); 7970 ins_cost(BRANCH_COST); 7971 format %{ "B $labl" %} 7972 ins_encode %{ 7973 __ b(*($labl$$label)); 7974 %} 7975 ins_pipe(br); 7976 %} 7977 7978 // Conditional Direct Branch 7979 instruct branchCon(cmpOp cmp, flagsReg icc, label labl) %{ 7980 match(If cmp icc); 7981 effect(USE labl); 7982 7983 size(4); 7984 ins_cost(BRANCH_COST); 7985 format %{ "B$cmp $icc,$labl" %} 7986 ins_encode %{ 7987 __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode)); 7988 %} 7989 ins_pipe(br_cc); 7990 %} 7991 7992 #ifdef ARM 7993 instruct branchCon_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, label labl) %{ 7994 match(If cmp icc); 7995 effect(USE labl); 7996 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); 7997 7998 size(4); 7999 ins_cost(BRANCH_COST); 8000 format %{ "B$cmp $icc,$labl" %} 8001 ins_encode %{ 8002 __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode)); 8003 %} 8004 ins_pipe(br_cc); 8005 %} 8006 #endif 8007 8008 8009 instruct branchConU(cmpOpU cmp, flagsRegU icc, label labl) %{ 8010 match(If cmp icc); 8011 effect(USE labl); 8012 8013 size(4); 8014 ins_cost(BRANCH_COST); 8015 format %{ "B$cmp $icc,$labl" %} 8016 ins_encode %{ 8017 __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode)); 8018 %} 8019 ins_pipe(br_cc); 8020 %} 8021 8022 instruct branchConP(cmpOpP cmp, flagsRegP pcc, label labl) %{ 8023 match(If cmp pcc); 8024 effect(USE labl); 8025 8026 size(4); 8027 ins_cost(BRANCH_COST); 8028 format %{ "B$cmp $pcc,$labl" %} 8029 ins_encode %{ 8030 __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode)); 8031 %} 8032 ins_pipe(br_cc); 8033 %} 8034 8035 instruct branchConL_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, label labl) %{ 8036 match(If cmp xcc); 8037 effect(USE labl); 8038 predicate( _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge ); 8039 8040 size(4); 8041 ins_cost(BRANCH_COST); 8042 format %{ "B$cmp $xcc,$labl" %} 8043 ins_encode %{ 8044 __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode)); 8045 %} 8046 ins_pipe(br_cc); 8047 %} 8048 8049 instruct branchConL_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, label labl) %{ 8050 match(If cmp xcc); 8051 effect(USE labl); 8052 predicate( _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ); 8053 8054 size(4); 8055 ins_cost(BRANCH_COST); 8056 format %{ "B$cmp $xcc,$labl" %} 8057 ins_encode %{ 8058 __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode)); 8059 %} 8060 ins_pipe(br_cc); 8061 %} 8062 8063 instruct branchConL_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, label labl) %{ 8064 match(If cmp xcc); 8065 effect(USE labl); 8066 predicate( _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le ); 8067 8068 size(4); 8069 ins_cost(BRANCH_COST); 8070 format %{ "B$cmp $xcc,$labl" %} 8071 ins_encode %{ 8072 __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode)); 8073 %} 8074 ins_pipe(br_cc); 8075 %} 8076 8077 instruct branchConUL_LTGE(cmpOpUL cmp, flagsRegUL_LTGE xcc, label labl) %{ 8078 match(If cmp xcc); 8079 effect(USE labl); 8080 predicate(_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge); 8081 8082 size(4); 8083 ins_cost(BRANCH_COST); 8084 format %{ "B$cmp $xcc,$labl" %} 8085 ins_encode %{ 8086 __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode)); 8087 %} 8088 ins_pipe(br_cc); 8089 %} 8090 8091 instruct branchConUL_EQNE(cmpOpUL cmp, flagsRegUL_EQNE xcc, label labl) %{ 8092 match(If cmp xcc); 8093 effect(USE labl); 8094 predicate(_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne); 8095 8096 size(4); 8097 ins_cost(BRANCH_COST); 8098 format %{ "B$cmp $xcc,$labl" %} 8099 ins_encode %{ 8100 __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode)); 8101 %} 8102 ins_pipe(br_cc); 8103 %} 8104 8105 instruct branchConUL_LEGT(cmpOpUL_commute cmp, flagsRegUL_LEGT xcc, label labl) %{ 8106 match(If cmp xcc); 8107 effect(USE labl); 8108 predicate(_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le); 8109 8110 size(4); 8111 ins_cost(BRANCH_COST); 8112 format %{ "B$cmp $xcc,$labl" %} 8113 ins_encode %{ 8114 __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode)); 8115 %} 8116 ins_pipe(br_cc); 8117 %} 8118 8119 instruct branchLoopEnd(cmpOp cmp, flagsReg icc, label labl) %{ 8120 match(CountedLoopEnd cmp icc); 8121 effect(USE labl); 8122 8123 size(4); 8124 ins_cost(BRANCH_COST); 8125 format %{ "B$cmp $icc,$labl\t! Loop end" %} 8126 ins_encode %{ 8127 __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode)); 8128 %} 8129 ins_pipe(br_cc); 8130 %} 8131 8132 // instruct branchLoopEndU(cmpOpU cmp, flagsRegU icc, label labl) %{ 8133 // match(CountedLoopEnd cmp icc); 8134 // ins_pipe(br_cc); 8135 // %} 8136 8137 // ============================================================================ 8138 // Long Compare 8139 // 8140 // Currently we hold longs in 2 registers. Comparing such values efficiently 8141 // is tricky. The flavor of compare used depends on whether we are testing 8142 // for LT, LE, or EQ. For a simple LT test we can check just the sign bit. 8143 // The GE test is the negated LT test. The LE test can be had by commuting 8144 // the operands (yielding a GE test) and then negating; negate again for the 8145 // GT test. The EQ test is done by ORcc'ing the high and low halves, and the 8146 // NE test is negated from that. 8147 8148 // Due to a shortcoming in the ADLC, it mixes up expressions like: 8149 // (foo (CmpI (CmpL X Y) 0)) and (bar (CmpI (CmpL X 0L) 0)). Note the 8150 // difference between 'Y' and '0L'. The tree-matches for the CmpI sections 8151 // are collapsed internally in the ADLC's dfa-gen code. The match for 8152 // (CmpI (CmpL X Y) 0) is silently replaced with (CmpI (CmpL X 0L) 0) and the 8153 // foo match ends up with the wrong leaf. One fix is to not match both 8154 // reg-reg and reg-zero forms of long-compare. This is unfortunate because 8155 // both forms beat the trinary form of long-compare and both are very useful 8156 // on Intel which has so few registers. 8157 8158 // instruct branchCon_long(cmpOp cmp, flagsRegL xcc, label labl) %{ 8159 // match(If cmp xcc); 8160 // ins_pipe(br_cc); 8161 // %} 8162 8163 // Manifest a CmpL3 result in an integer register. Very painful. 8164 // This is the test to avoid. 8165 instruct cmpL3_reg_reg(iRegI dst, iRegL src1, iRegL src2, flagsReg ccr ) %{ 8166 match(Set dst (CmpL3 src1 src2) ); 8167 effect( KILL ccr ); 8168 ins_cost(6*DEFAULT_COST); // FIXME 8169 size(32); 8170 format %{ 8171 "CMP $src1.hi, $src2.hi\t\t! long\n" 8172 "\tMOV.gt $dst, 1\n" 8173 "\tmvn.lt $dst, 0\n" 8174 "\tB.ne done\n" 8175 "\tSUBS $dst, $src1.lo, $src2.lo\n" 8176 "\tMOV.hi $dst, 1\n" 8177 "\tmvn.lo $dst, 0\n" 8178 "done:" %} 8179 ins_encode %{ 8180 Label done; 8181 __ cmp($src1$$Register->successor(), $src2$$Register->successor()); 8182 __ mov($dst$$Register, 1, gt); 8183 __ mvn($dst$$Register, 0, lt); 8184 __ b(done, ne); 8185 __ subs($dst$$Register, $src1$$Register, $src2$$Register); 8186 __ mov($dst$$Register, 1, hi); 8187 __ mvn($dst$$Register, 0, lo); 8188 __ bind(done); 8189 %} 8190 ins_pipe(cmpL_reg); 8191 %} 8192 8193 // Conditional move 8194 instruct cmovLL_reg_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, iRegL dst, iRegL src) %{ 8195 match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src))); 8196 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge); 8197 8198 ins_cost(150); 8199 size(8); 8200 format %{ "MOV$cmp $dst.lo,$src.lo\t! long\n\t" 8201 "MOV$cmp $dst,$src.hi" %} 8202 ins_encode %{ 8203 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 8204 __ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode)); 8205 %} 8206 ins_pipe(ialu_reg); 8207 %} 8208 8209 instruct cmovLL_reg_LTGE_U(cmpOpUL cmp, flagsRegUL_LTGE xcc, iRegL dst, iRegL src) %{ 8210 match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src))); 8211 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge); 8212 8213 ins_cost(150); 8214 size(8); 8215 format %{ "MOV$cmp $dst.lo,$src.lo\t! long\n\t" 8216 "MOV$cmp $dst,$src.hi" %} 8217 ins_encode %{ 8218 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 8219 __ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode)); 8220 %} 8221 ins_pipe(ialu_reg); 8222 %} 8223 8224 instruct cmovLL_reg_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, iRegL dst, iRegL src) %{ 8225 match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src))); 8226 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne); 8227 8228 ins_cost(150); 8229 size(8); 8230 format %{ "MOV$cmp $dst.lo,$src.lo\t! long\n\t" 8231 "MOV$cmp $dst,$src.hi" %} 8232 ins_encode %{ 8233 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 8234 __ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode)); 8235 %} 8236 ins_pipe(ialu_reg); 8237 %} 8238 8239 instruct cmovLL_reg_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, iRegL dst, iRegL src) %{ 8240 match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src))); 8241 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt); 8242 8243 ins_cost(150); 8244 size(8); 8245 format %{ "MOV$cmp $dst.lo,$src.lo\t! long\n\t" 8246 "MOV$cmp $dst,$src.hi" %} 8247 ins_encode %{ 8248 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 8249 __ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode)); 8250 %} 8251 ins_pipe(ialu_reg); 8252 %} 8253 8254 instruct cmovLL_reg_LEGT_U(cmpOpUL_commute cmp, flagsRegUL_LEGT xcc, iRegL dst, iRegL src) %{ 8255 match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src))); 8256 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt); 8257 8258 ins_cost(150); 8259 size(8); 8260 format %{ "MOV$cmp $dst.lo,$src.lo\t! long\n\t" 8261 "MOV$cmp $dst,$src.hi" %} 8262 ins_encode %{ 8263 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 8264 __ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode)); 8265 %} 8266 ins_pipe(ialu_reg); 8267 %} 8268 8269 instruct cmovLL_imm_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, iRegL dst, immL0 src) %{ 8270 match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src))); 8271 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge); 8272 ins_cost(140); 8273 size(8); 8274 format %{ "MOV$cmp $dst.lo,0\t! long\n\t" 8275 "MOV$cmp $dst,0" %} 8276 ins_encode %{ 8277 __ mov($dst$$Register, 0, (AsmCondition)($cmp$$cmpcode)); 8278 __ mov($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode)); 8279 %} 8280 ins_pipe(ialu_imm); 8281 %} 8282 8283 instruct cmovLL_imm_LTGE_U(cmpOpUL cmp, flagsRegUL_LTGE xcc, iRegL dst, immL0 src) %{ 8284 match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src))); 8285 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge); 8286 ins_cost(140); 8287 size(8); 8288 format %{ "MOV$cmp $dst.lo,0\t! long\n\t" 8289 "MOV$cmp $dst,0" %} 8290 ins_encode %{ 8291 __ mov($dst$$Register, 0, (AsmCondition)($cmp$$cmpcode)); 8292 __ mov($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode)); 8293 %} 8294 ins_pipe(ialu_imm); 8295 %} 8296 8297 instruct cmovLL_imm_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, iRegL dst, immL0 src) %{ 8298 match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src))); 8299 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne); 8300 ins_cost(140); 8301 size(8); 8302 format %{ "MOV$cmp $dst.lo,0\t! long\n\t" 8303 "MOV$cmp $dst,0" %} 8304 ins_encode %{ 8305 __ mov($dst$$Register, 0, (AsmCondition)($cmp$$cmpcode)); 8306 __ mov($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode)); 8307 %} 8308 ins_pipe(ialu_imm); 8309 %} 8310 8311 instruct cmovLL_imm_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, iRegL dst, immL0 src) %{ 8312 match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src))); 8313 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt); 8314 ins_cost(140); 8315 size(8); 8316 format %{ "MOV$cmp $dst.lo,0\t! long\n\t" 8317 "MOV$cmp $dst,0" %} 8318 ins_encode %{ 8319 __ mov($dst$$Register, 0, (AsmCondition)($cmp$$cmpcode)); 8320 __ mov($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode)); 8321 %} 8322 ins_pipe(ialu_imm); 8323 %} 8324 8325 instruct cmovIL_reg_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, iRegI dst, iRegI src) %{ 8326 match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src))); 8327 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge); 8328 8329 ins_cost(150); 8330 size(4); 8331 format %{ "MOV$cmp $dst,$src" %} 8332 ins_encode %{ 8333 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 8334 %} 8335 ins_pipe(ialu_reg); 8336 %} 8337 8338 instruct cmovIL_reg_LTGE_U(cmpOpUL cmp, flagsRegUL_LTGE xcc, iRegI dst, iRegI src) %{ 8339 match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src))); 8340 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge); 8341 8342 ins_cost(150); 8343 size(4); 8344 format %{ "MOV$cmp $dst,$src" %} 8345 ins_encode %{ 8346 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 8347 %} 8348 ins_pipe(ialu_reg); 8349 %} 8350 8351 instruct cmovIL_reg_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, iRegI dst, iRegI src) %{ 8352 match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src))); 8353 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne); 8354 8355 ins_cost(150); 8356 size(4); 8357 format %{ "MOV$cmp $dst,$src" %} 8358 ins_encode %{ 8359 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 8360 %} 8361 ins_pipe(ialu_reg); 8362 %} 8363 8364 instruct cmovIL_reg_EQNE_U(cmpOpUL cmp, flagsRegUL_EQNE xcc, iRegI dst, iRegI src) %{ 8365 match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src))); 8366 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne); 8367 8368 ins_cost(150); 8369 size(4); 8370 format %{ "MOV$cmp $dst,$src" %} 8371 ins_encode %{ 8372 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 8373 %} 8374 ins_pipe(ialu_reg); 8375 %} 8376 8377 instruct cmovIL_reg_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, iRegI dst, iRegI src) %{ 8378 match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src))); 8379 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt); 8380 8381 ins_cost(150); 8382 size(4); 8383 format %{ "MOV$cmp $dst,$src" %} 8384 ins_encode %{ 8385 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 8386 %} 8387 ins_pipe(ialu_reg); 8388 %} 8389 8390 instruct cmovIL_reg_LEGT_U(cmpOpUL_commute cmp, flagsRegUL_LEGT xcc, iRegI dst, iRegI src) %{ 8391 match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src))); 8392 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt); 8393 8394 ins_cost(150); 8395 size(4); 8396 format %{ "MOV$cmp $dst,$src" %} 8397 ins_encode %{ 8398 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 8399 %} 8400 ins_pipe(ialu_reg); 8401 %} 8402 8403 instruct cmovIL_imm16_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, iRegI dst, immI16 src) %{ 8404 match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src))); 8405 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge); 8406 8407 ins_cost(140); 8408 size(4); 8409 format %{ "MOVW$cmp $dst,$src" %} 8410 ins_encode %{ 8411 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 8412 %} 8413 ins_pipe(ialu_imm); 8414 %} 8415 8416 instruct cmovIL_imm16_LTGE_U(cmpOpUL cmp, flagsRegUL_LTGE xcc, iRegI dst, immI16 src) %{ 8417 match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src))); 8418 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge); 8419 8420 ins_cost(140); 8421 size(4); 8422 format %{ "MOVW$cmp $dst,$src" %} 8423 ins_encode %{ 8424 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 8425 %} 8426 ins_pipe(ialu_imm); 8427 %} 8428 8429 instruct cmovIL_imm16_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, iRegI dst, immI16 src) %{ 8430 match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src))); 8431 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne); 8432 8433 ins_cost(140); 8434 size(4); 8435 format %{ "MOVW$cmp $dst,$src" %} 8436 ins_encode %{ 8437 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 8438 %} 8439 ins_pipe(ialu_imm); 8440 %} 8441 8442 instruct cmovIL_imm16_EQNE_U(cmpOpUL cmp, flagsRegUL_EQNE xcc, iRegI dst, immI16 src) %{ 8443 match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src))); 8444 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne); 8445 8446 ins_cost(140); 8447 size(4); 8448 format %{ "MOVW$cmp $dst,$src" %} 8449 ins_encode %{ 8450 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 8451 %} 8452 ins_pipe(ialu_imm); 8453 %} 8454 8455 instruct cmovIL_imm16_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, iRegI dst, immI16 src) %{ 8456 match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src))); 8457 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt); 8458 8459 ins_cost(140); 8460 size(4); 8461 format %{ "MOVW$cmp $dst,$src" %} 8462 ins_encode %{ 8463 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 8464 %} 8465 ins_pipe(ialu_imm); 8466 %} 8467 8468 instruct cmovIL_imm16_LEGT_U(cmpOpUL_commute cmp, flagsRegUL_LEGT xcc, iRegI dst, immI16 src) %{ 8469 match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src))); 8470 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt); 8471 8472 ins_cost(140); 8473 size(4); 8474 format %{ "MOVW$cmp $dst,$src" %} 8475 ins_encode %{ 8476 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 8477 %} 8478 ins_pipe(ialu_imm); 8479 %} 8480 8481 instruct cmovIL_immMov_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, iRegI dst, immIMov src) %{ 8482 match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src))); 8483 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge); 8484 8485 ins_cost(140); 8486 size(4); 8487 format %{ "MOV$cmp $dst,$src" %} 8488 ins_encode %{ 8489 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 8490 %} 8491 ins_pipe(ialu_imm); 8492 %} 8493 8494 instruct cmovIL_immMov_LTGE_U(cmpOpUL cmp, flagsRegUL_LTGE xcc, iRegI dst, immIMov src) %{ 8495 match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src))); 8496 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge); 8497 8498 ins_cost(140); 8499 size(4); 8500 format %{ "MOV$cmp $dst,$src" %} 8501 ins_encode %{ 8502 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 8503 %} 8504 ins_pipe(ialu_imm); 8505 %} 8506 8507 instruct cmovIL_immMov_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, iRegI dst, immIMov src) %{ 8508 match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src))); 8509 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne); 8510 8511 ins_cost(140); 8512 size(4); 8513 format %{ "MOV$cmp $dst,$src" %} 8514 ins_encode %{ 8515 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 8516 %} 8517 ins_pipe(ialu_imm); 8518 %} 8519 8520 instruct cmovIL_immMov_EQNE_U(cmpOpUL cmp, flagsRegUL_EQNE xcc, iRegI dst, immIMov src) %{ 8521 match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src))); 8522 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne); 8523 8524 ins_cost(140); 8525 size(4); 8526 format %{ "MOV$cmp $dst,$src" %} 8527 ins_encode %{ 8528 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 8529 %} 8530 ins_pipe(ialu_imm); 8531 %} 8532 8533 instruct cmovIL_immMov_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, iRegI dst, immIMov src) %{ 8534 match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src))); 8535 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt); 8536 8537 ins_cost(140); 8538 size(4); 8539 format %{ "MOV$cmp $dst,$src" %} 8540 ins_encode %{ 8541 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 8542 %} 8543 ins_pipe(ialu_imm); 8544 %} 8545 8546 instruct cmovIL_immMov_LEGT_U(cmpOpUL_commute cmp, flagsRegUL_LEGT xcc, iRegI dst, immIMov src) %{ 8547 match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src))); 8548 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt); 8549 8550 ins_cost(140); 8551 size(4); 8552 format %{ "MOV$cmp $dst,$src" %} 8553 ins_encode %{ 8554 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 8555 %} 8556 ins_pipe(ialu_imm); 8557 %} 8558 8559 instruct cmovPL_reg_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, iRegP dst, iRegP src) %{ 8560 match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src))); 8561 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge); 8562 8563 ins_cost(150); 8564 size(4); 8565 format %{ "MOV$cmp $dst,$src" %} 8566 ins_encode %{ 8567 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 8568 %} 8569 ins_pipe(ialu_reg); 8570 %} 8571 8572 instruct cmovPL_reg_LTGE_U(cmpOpUL cmp, flagsRegUL_LTGE xcc, iRegP dst, iRegP src) %{ 8573 match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src))); 8574 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge); 8575 8576 ins_cost(150); 8577 size(4); 8578 format %{ "MOV$cmp $dst,$src" %} 8579 ins_encode %{ 8580 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 8581 %} 8582 ins_pipe(ialu_reg); 8583 %} 8584 8585 instruct cmovPL_reg_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, iRegP dst, iRegP src) %{ 8586 match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src))); 8587 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne); 8588 8589 ins_cost(150); 8590 size(4); 8591 format %{ "MOV$cmp $dst,$src" %} 8592 ins_encode %{ 8593 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 8594 %} 8595 ins_pipe(ialu_reg); 8596 %} 8597 8598 instruct cmovPL_reg_EQNE_U(cmpOpUL cmp, flagsRegUL_EQNE xcc, iRegP dst, iRegP src) %{ 8599 match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src))); 8600 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne); 8601 8602 ins_cost(150); 8603 size(4); 8604 format %{ "MOV$cmp $dst,$src" %} 8605 ins_encode %{ 8606 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 8607 %} 8608 ins_pipe(ialu_reg); 8609 %} 8610 8611 instruct cmovPL_reg_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, iRegP dst, iRegP src) %{ 8612 match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src))); 8613 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt); 8614 8615 ins_cost(150); 8616 size(4); 8617 format %{ "MOV$cmp $dst,$src" %} 8618 ins_encode %{ 8619 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 8620 %} 8621 ins_pipe(ialu_reg); 8622 %} 8623 8624 instruct cmovPL_reg_LEGT_U(cmpOpUL_commute cmp, flagsRegUL_LEGT xcc, iRegP dst, iRegP src) %{ 8625 match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src))); 8626 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt); 8627 8628 ins_cost(150); 8629 size(4); 8630 format %{ "MOV$cmp $dst,$src" %} 8631 ins_encode %{ 8632 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 8633 %} 8634 ins_pipe(ialu_reg); 8635 %} 8636 8637 instruct cmovPL_imm_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, iRegP dst, immP0 src) %{ 8638 match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src))); 8639 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge); 8640 8641 ins_cost(140); 8642 size(4); 8643 format %{ "MOVW$cmp $dst,$src" %} 8644 ins_encode %{ 8645 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 8646 %} 8647 ins_pipe(ialu_imm); 8648 %} 8649 8650 instruct cmovPL_imm_LTGE_U(cmpOpUL cmp, flagsRegUL_LTGE xcc, iRegP dst, immP0 src) %{ 8651 match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src))); 8652 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge); 8653 8654 ins_cost(140); 8655 size(4); 8656 format %{ "MOVW$cmp $dst,$src" %} 8657 ins_encode %{ 8658 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 8659 %} 8660 ins_pipe(ialu_imm); 8661 %} 8662 8663 instruct cmovPL_imm_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, iRegP dst, immP0 src) %{ 8664 match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src))); 8665 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne); 8666 8667 ins_cost(140); 8668 size(4); 8669 format %{ "MOVW$cmp $dst,$src" %} 8670 ins_encode %{ 8671 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 8672 %} 8673 ins_pipe(ialu_imm); 8674 %} 8675 8676 instruct cmovPL_imm_EQNE_U(cmpOpUL cmp, flagsRegUL_EQNE xcc, iRegP dst, immP0 src) %{ 8677 match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src))); 8678 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne); 8679 8680 ins_cost(140); 8681 size(4); 8682 format %{ "MOVW$cmp $dst,$src" %} 8683 ins_encode %{ 8684 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 8685 %} 8686 ins_pipe(ialu_imm); 8687 %} 8688 8689 instruct cmovPL_imm_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, iRegP dst, immP0 src) %{ 8690 match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src))); 8691 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt); 8692 8693 ins_cost(140); 8694 size(4); 8695 format %{ "MOVW$cmp $dst,$src" %} 8696 ins_encode %{ 8697 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 8698 %} 8699 ins_pipe(ialu_imm); 8700 %} 8701 8702 instruct cmovPL_imm_LEGT_U(cmpOpUL_commute cmp, flagsRegUL_LEGT xcc, iRegP dst, immP0 src) %{ 8703 match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src))); 8704 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt); 8705 8706 ins_cost(140); 8707 size(4); 8708 format %{ "MOVW$cmp $dst,$src" %} 8709 ins_encode %{ 8710 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 8711 %} 8712 ins_pipe(ialu_imm); 8713 %} 8714 8715 instruct cmovFL_reg_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, regF dst, regF src) %{ 8716 match(Set dst (CMoveF (Binary cmp xcc) (Binary dst src))); 8717 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge); 8718 ins_cost(150); 8719 size(4); 8720 format %{ "FCPYS$cmp $dst,$src" %} 8721 ins_encode %{ 8722 __ fcpys($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode)); 8723 %} 8724 ins_pipe(int_conditional_float_move); 8725 %} 8726 8727 instruct cmovFL_reg_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, regF dst, regF src) %{ 8728 match(Set dst (CMoveF (Binary cmp xcc) (Binary dst src))); 8729 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne); 8730 ins_cost(150); 8731 size(4); 8732 format %{ "FCPYS$cmp $dst,$src" %} 8733 ins_encode %{ 8734 __ fcpys($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode)); 8735 %} 8736 ins_pipe(int_conditional_float_move); 8737 %} 8738 8739 instruct cmovFL_reg_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, regF dst, regF src) %{ 8740 match(Set dst (CMoveF (Binary cmp xcc) (Binary dst src))); 8741 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt); 8742 ins_cost(150); 8743 size(4); 8744 format %{ "FCPYS$cmp $dst,$src" %} 8745 ins_encode %{ 8746 __ fcpys($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode)); 8747 %} 8748 ins_pipe(int_conditional_float_move); 8749 %} 8750 8751 instruct cmovDL_reg_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, regD dst, regD src) %{ 8752 match(Set dst (CMoveD (Binary cmp xcc) (Binary dst src))); 8753 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge); 8754 8755 ins_cost(150); 8756 size(4); 8757 format %{ "FCPYD$cmp $dst,$src" %} 8758 ins_encode %{ 8759 __ fcpyd($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode)); 8760 %} 8761 ins_pipe(int_conditional_float_move); 8762 %} 8763 8764 instruct cmovDL_reg_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, regD dst, regD src) %{ 8765 match(Set dst (CMoveD (Binary cmp xcc) (Binary dst src))); 8766 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne); 8767 8768 ins_cost(150); 8769 size(4); 8770 format %{ "FCPYD$cmp $dst,$src" %} 8771 ins_encode %{ 8772 __ fcpyd($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode)); 8773 %} 8774 ins_pipe(int_conditional_float_move); 8775 %} 8776 8777 instruct cmovDL_reg_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, regD dst, regD src) %{ 8778 match(Set dst (CMoveD (Binary cmp xcc) (Binary dst src))); 8779 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt); 8780 8781 ins_cost(150); 8782 size(4); 8783 format %{ "FCPYD$cmp $dst,$src" %} 8784 ins_encode %{ 8785 __ fcpyd($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode)); 8786 %} 8787 ins_pipe(int_conditional_float_move); 8788 %} 8789 8790 // ============================================================================ 8791 // Safepoint Instruction 8792 // rather than KILL R12, it would be better to use any reg as 8793 // TEMP. Can't do that at this point because it crashes the compiler 8794 instruct safePoint_poll(iRegP poll, R12RegI tmp, flagsReg icc) %{ 8795 match(SafePoint poll); 8796 effect(USE poll, KILL tmp, KILL icc); 8797 8798 size(4); 8799 format %{ "LDR $tmp,[$poll]\t! Safepoint: poll for GC" %} 8800 ins_encode %{ 8801 __ relocate(relocInfo::poll_type); 8802 __ ldr($tmp$$Register, Address($poll$$Register)); 8803 %} 8804 ins_pipe(loadPollP); 8805 %} 8806 8807 8808 // ============================================================================ 8809 // Call Instructions 8810 // Call Java Static Instruction 8811 instruct CallStaticJavaDirect( method meth ) %{ 8812 match(CallStaticJava); 8813 predicate(! ((CallStaticJavaNode*)n)->is_method_handle_invoke()); 8814 effect(USE meth); 8815 8816 ins_cost(CALL_COST); 8817 format %{ "CALL,static ==> " %} 8818 ins_encode( SetInstMark, Java_Static_Call( meth ), call_epilog, ClearInstMark ); 8819 ins_pipe(simple_call); 8820 %} 8821 8822 // Call Java Static Instruction (method handle version) 8823 instruct CallStaticJavaHandle( method meth ) %{ 8824 match(CallStaticJava); 8825 predicate(((CallStaticJavaNode*)n)->is_method_handle_invoke()); 8826 effect(USE meth); 8827 // FP is saved by all callees (for interpreter stack correction). 8828 // We use it here for a similar purpose, in {preserve,restore}_FP. 8829 8830 ins_cost(CALL_COST); 8831 format %{ "CALL,static/MethodHandle ==> " %} 8832 ins_encode( SetInstMark, preserve_SP, Java_Static_Call( meth ), restore_SP, call_epilog, ClearInstMark ); 8833 ins_pipe(simple_call); 8834 %} 8835 8836 // Call Java Dynamic Instruction 8837 instruct CallDynamicJavaDirect( method meth ) %{ 8838 match(CallDynamicJava); 8839 effect(USE meth); 8840 8841 ins_cost(CALL_COST); 8842 format %{ "MOV_OOP (empty),R_R8\n\t" 8843 "CALL,dynamic ; NOP ==> " %} 8844 ins_encode( SetInstMark, Java_Dynamic_Call( meth ), call_epilog, ClearInstMark ); 8845 ins_pipe(call); 8846 %} 8847 8848 // Call Runtime Instruction 8849 instruct CallRuntimeDirect(method meth) %{ 8850 match(CallRuntime); 8851 effect(USE meth); 8852 ins_cost(CALL_COST); 8853 format %{ "CALL,runtime" %} 8854 ins_encode( SetInstMark, Java_To_Runtime( meth ), 8855 call_epilog, ClearInstMark ); 8856 ins_pipe(simple_call); 8857 %} 8858 8859 // Call runtime without safepoint - same as CallRuntime 8860 instruct CallLeafDirect(method meth) %{ 8861 match(CallLeaf); 8862 effect(USE meth); 8863 ins_cost(CALL_COST); 8864 format %{ "CALL,runtime leaf" %} 8865 // TODO: need save_last_PC here? 8866 ins_encode( SetInstMark, Java_To_Runtime( meth ), 8867 call_epilog, ClearInstMark ); 8868 ins_pipe(simple_call); 8869 %} 8870 8871 // Call runtime without safepoint - same as CallLeaf 8872 instruct CallLeafNoFPDirect(method meth) %{ 8873 match(CallLeafNoFP); 8874 effect(USE meth); 8875 ins_cost(CALL_COST); 8876 format %{ "CALL,runtime leaf nofp" %} 8877 // TODO: need save_last_PC here? 8878 ins_encode( SetInstMark, Java_To_Runtime( meth ), 8879 call_epilog, ClearInstMark ); 8880 ins_pipe(simple_call); 8881 %} 8882 8883 // Tail Call; Jump from runtime stub to Java code. 8884 // Also known as an 'interprocedural jump'. 8885 // Target of jump will eventually return to caller. 8886 // TailJump below removes the return address. 8887 instruct TailCalljmpInd(IPRegP jump_target, inline_cache_regP method_ptr) %{ 8888 match(TailCall jump_target method_ptr); 8889 8890 ins_cost(CALL_COST); 8891 format %{ "MOV Rexception_pc, LR\n\t" 8892 "jump $jump_target \t! $method_ptr holds method" %} 8893 ins_encode %{ 8894 __ mov(Rexception_pc, LR); // this is used only to call 8895 // StubRoutines::forward_exception_entry() 8896 // which expects PC of exception in 8897 // R5. FIXME? 8898 __ jump($jump_target$$Register); 8899 %} 8900 ins_pipe(tail_call); 8901 %} 8902 8903 8904 // Return Instruction 8905 instruct Ret() %{ 8906 match(Return); 8907 8908 format %{ "ret LR" %} 8909 8910 ins_encode %{ 8911 __ ret(LR); 8912 %} 8913 8914 ins_pipe(br); 8915 %} 8916 8917 8918 // Tail Jump; remove the return address; jump to target. 8919 // TailCall above leaves the return address around. 8920 // TailJump is used in only one place, the rethrow_Java stub (fancy_jump=2). 8921 // ex_oop (Exception Oop) is needed in %o0 at the jump. As there would be a 8922 // "restore" before this instruction (in Epilogue), we need to materialize it 8923 // in %i0. 8924 instruct tailjmpInd(IPRegP jump_target, RExceptionRegP ex_oop) %{ 8925 match( TailJump jump_target ex_oop ); 8926 ins_cost(CALL_COST); 8927 format %{ "MOV Rexception_pc, LR\n\t" 8928 "jump $jump_target \t! $ex_oop holds exc. oop" %} 8929 ins_encode %{ 8930 __ mov(Rexception_pc, LR); 8931 __ jump($jump_target$$Register); 8932 %} 8933 ins_pipe(tail_call); 8934 %} 8935 8936 // Forward exception. 8937 instruct ForwardExceptionjmp() 8938 %{ 8939 match(ForwardException); 8940 ins_cost(CALL_COST); 8941 8942 format %{ "b forward_exception_stub" %} 8943 ins_encode %{ 8944 // OK to trash Rtemp, because Rtemp is used by stub 8945 __ jump(StubRoutines::forward_exception_entry(), relocInfo::runtime_call_type, Rtemp); 8946 %} 8947 ins_pipe(tail_call); 8948 %} 8949 8950 // Create exception oop: created by stack-crawling runtime code. 8951 // Created exception is now available to this handler, and is setup 8952 // just prior to jumping to this handler. No code emitted. 8953 instruct CreateException( RExceptionRegP ex_oop ) 8954 %{ 8955 match(Set ex_oop (CreateEx)); 8956 ins_cost(0); 8957 8958 size(0); 8959 // use the following format syntax 8960 format %{ "! exception oop is in Rexception_obj; no code emitted" %} 8961 ins_encode(); 8962 ins_pipe(empty); 8963 %} 8964 8965 8966 // Rethrow exception: 8967 // The exception oop will come in the first argument position. 8968 // Then JUMP (not call) to the rethrow stub code. 8969 instruct RethrowException() 8970 %{ 8971 match(Rethrow); 8972 ins_cost(CALL_COST); 8973 8974 // use the following format syntax 8975 format %{ "b rethrow_stub" %} 8976 ins_encode %{ 8977 Register scratch = R1_tmp; 8978 assert_different_registers(scratch, c_rarg0, LR); 8979 __ jump(OptoRuntime::rethrow_stub(), relocInfo::runtime_call_type, scratch); 8980 %} 8981 ins_pipe(tail_call); 8982 %} 8983 8984 8985 // Die now 8986 instruct ShouldNotReachHere( ) 8987 %{ 8988 match(Halt); 8989 ins_cost(CALL_COST); 8990 8991 // Use the following format syntax 8992 format %{ "ShouldNotReachHere" %} 8993 ins_encode %{ 8994 if (is_reachable()) { 8995 const char* str = __ code_string(_halt_reason); 8996 __ stop(str); 8997 } 8998 %} 8999 ins_pipe(tail_call); 9000 %} 9001 9002 // ============================================================================ 9003 // The 2nd slow-half of a subtype check. Scan the subklass's 2ndary superklass 9004 // array for an instance of the superklass. Set a hidden internal cache on a 9005 // hit (cache is checked with exposed code in gen_subtype_check()). Return 9006 // not zero for a miss or zero for a hit. The encoding ALSO sets flags. 9007 instruct partialSubtypeCheck( R0RegP index, R1RegP sub, R2RegP super, flagsRegP pcc, LRRegP lr ) %{ 9008 match(Set index (PartialSubtypeCheck sub super)); 9009 effect( KILL pcc, KILL lr ); 9010 ins_cost(DEFAULT_COST*10); 9011 format %{ "CALL PartialSubtypeCheck" %} 9012 ins_encode %{ 9013 __ call(StubRoutines::Arm::partial_subtype_check(), relocInfo::runtime_call_type); 9014 %} 9015 ins_pipe(partial_subtype_check_pipe); 9016 %} 9017 9018 /* instruct partialSubtypeCheck_vs_zero( flagsRegP pcc, o1RegP sub, o2RegP super, immP0 zero, o0RegP idx, o7RegP o7 ) %{ */ 9019 /* match(Set pcc (CmpP (PartialSubtypeCheck sub super) zero)); */ 9020 /* ins_pipe(partial_subtype_check_pipe); */ 9021 /* %} */ 9022 9023 9024 // ============================================================================ 9025 // inlined locking and unlocking 9026 9027 instruct cmpFastLock(flagsRegP pcc, iRegP object, iRegP box, iRegP scratch2, iRegP scratch ) 9028 %{ 9029 match(Set pcc (FastLock object box)); 9030 9031 effect(TEMP scratch, TEMP scratch2); 9032 ins_cost(DEFAULT_COST*3); 9033 9034 format %{ "FASTLOCK $object, $box; KILL $scratch, $scratch2" %} 9035 ins_encode %{ 9036 __ fast_lock($object$$Register, $box$$Register, $scratch$$Register, $scratch2$$Register); 9037 %} 9038 ins_pipe(long_memory_op); 9039 %} 9040 9041 instruct cmpFastUnlock(flagsRegP pcc, iRegP object, iRegP box, iRegP scratch2, iRegP scratch ) %{ 9042 match(Set pcc (FastUnlock object box)); 9043 effect(TEMP scratch, TEMP scratch2); 9044 ins_cost(100); 9045 9046 format %{ "FASTUNLOCK $object, $box; KILL $scratch, $scratch2" %} 9047 ins_encode %{ 9048 __ fast_unlock($object$$Register, $box$$Register, $scratch$$Register, $scratch2$$Register); 9049 %} 9050 ins_pipe(long_memory_op); 9051 %} 9052 9053 // Count and Base registers are fixed because the allocator cannot 9054 // kill unknown registers. The encodings are generic. 9055 instruct clear_array(iRegX cnt, iRegP base, iRegI temp, iRegX zero, Universe dummy, flagsReg cpsr) %{ 9056 match(Set dummy (ClearArray cnt base)); 9057 effect(TEMP temp, TEMP zero, KILL cpsr); 9058 ins_cost(300); 9059 format %{ "MOV $zero,0\n" 9060 " MOV $temp,$cnt\n" 9061 "loop: SUBS $temp,$temp,4\t! Count down a dword of bytes\n" 9062 " STR.ge $zero,[$base+$temp]\t! delay slot" 9063 " B.gt loop\t\t! Clearing loop\n" %} 9064 ins_encode %{ 9065 __ mov($zero$$Register, 0); 9066 __ mov($temp$$Register, $cnt$$Register); 9067 Label loop; 9068 __ bind(loop); 9069 __ subs($temp$$Register, $temp$$Register, 4); 9070 __ str($zero$$Register, Address($base$$Register, $temp$$Register), ge); 9071 __ b(loop, gt); 9072 %} 9073 ins_pipe(long_memory_op); 9074 %} 9075 9076 #ifdef XXX 9077 // FIXME: Why R0/R1/R2/R3? 9078 instruct string_compare(R0RegP str1, R1RegP str2, R2RegI cnt1, R3RegI cnt2, iRegI result, 9079 iRegI tmp1, iRegI tmp2, flagsReg ccr) %{ 9080 predicate(!CompactStrings); 9081 match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2))); 9082 effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL ccr, TEMP tmp1, TEMP tmp2); 9083 ins_cost(300); 9084 format %{ "String Compare $str1,$cnt1,$str2,$cnt2 -> $result // TEMP $tmp1, $tmp2" %} 9085 ins_encode( enc_String_Compare(str1, str2, cnt1, cnt2, result, tmp1, tmp2) ); 9086 9087 ins_pipe(long_memory_op); 9088 %} 9089 9090 // FIXME: Why R0/R1/R2? 9091 instruct string_equals(R0RegP str1, R1RegP str2, R2RegI cnt, iRegI result, iRegI tmp1, iRegI tmp2, 9092 flagsReg ccr) %{ 9093 predicate(!CompactStrings); 9094 match(Set result (StrEquals (Binary str1 str2) cnt)); 9095 effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt, TEMP tmp1, TEMP tmp2, TEMP result, KILL ccr); 9096 9097 ins_cost(300); 9098 format %{ "String Equals $str1,$str2,$cnt -> $result // TEMP $tmp1, $tmp2" %} 9099 ins_encode( enc_String_Equals(str1, str2, cnt, result, tmp1, tmp2) ); 9100 ins_pipe(long_memory_op); 9101 %} 9102 9103 // FIXME: Why R0/R1? 9104 instruct array_equals(R0RegP ary1, R1RegP ary2, iRegI tmp1, iRegI tmp2, iRegI tmp3, iRegI result, 9105 flagsReg ccr) %{ 9106 predicate(((AryEqNode*)n)->encoding() == StrIntrinsicNode::UU); 9107 match(Set result (AryEq ary1 ary2)); 9108 effect(USE_KILL ary1, USE_KILL ary2, TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP result, KILL ccr); 9109 9110 ins_cost(300); 9111 format %{ "Array Equals $ary1,$ary2 -> $result // TEMP $tmp1,$tmp2,$tmp3" %} 9112 ins_encode( enc_Array_Equals(ary1, ary2, tmp1, tmp2, tmp3, result)); 9113 ins_pipe(long_memory_op); 9114 %} 9115 #endif 9116 9117 //---------- Zeros Count Instructions ------------------------------------------ 9118 9119 instruct countLeadingZerosI(iRegI dst, iRegI src) %{ 9120 match(Set dst (CountLeadingZerosI src)); 9121 size(4); 9122 format %{ "CLZ_32 $dst,$src" %} 9123 ins_encode %{ 9124 __ clz_32($dst$$Register, $src$$Register); 9125 %} 9126 ins_pipe(ialu_reg); 9127 %} 9128 9129 instruct countLeadingZerosL(iRegI dst, iRegL src, iRegI tmp, flagsReg ccr) %{ 9130 match(Set dst (CountLeadingZerosL src)); 9131 effect(TEMP tmp, TEMP dst, KILL ccr); 9132 size(16); 9133 format %{ "CLZ $dst,$src.hi\n\t" 9134 "TEQ $dst,32\n\t" 9135 "CLZ.eq $tmp,$src.lo\n\t" 9136 "ADD.eq $dst, $dst, $tmp\n\t" %} 9137 ins_encode %{ 9138 __ clz($dst$$Register, $src$$Register->successor()); 9139 __ teq($dst$$Register, 32); 9140 __ clz($tmp$$Register, $src$$Register, eq); 9141 __ add($dst$$Register, $dst$$Register, $tmp$$Register, eq); 9142 %} 9143 ins_pipe(ialu_reg); 9144 %} 9145 9146 instruct countTrailingZerosI(iRegI dst, iRegI src, iRegI tmp) %{ 9147 match(Set dst (CountTrailingZerosI src)); 9148 effect(TEMP tmp); 9149 size(8); 9150 format %{ "RBIT_32 $tmp, $src\n\t" 9151 "CLZ_32 $dst,$tmp" %} 9152 ins_encode %{ 9153 __ rbit_32($tmp$$Register, $src$$Register); 9154 __ clz_32($dst$$Register, $tmp$$Register); 9155 %} 9156 ins_pipe(ialu_reg); 9157 %} 9158 9159 instruct countTrailingZerosL(iRegI dst, iRegL src, iRegI tmp, flagsReg ccr) %{ 9160 match(Set dst (CountTrailingZerosL src)); 9161 effect(TEMP tmp, TEMP dst, KILL ccr); 9162 size(24); 9163 format %{ "RBIT $tmp,$src.lo\n\t" 9164 "CLZ $dst,$tmp\n\t" 9165 "TEQ $dst,32\n\t" 9166 "RBIT $tmp,$src.hi\n\t" 9167 "CLZ.eq $tmp,$tmp\n\t" 9168 "ADD.eq $dst,$dst,$tmp\n\t" %} 9169 ins_encode %{ 9170 __ rbit($tmp$$Register, $src$$Register); 9171 __ clz($dst$$Register, $tmp$$Register); 9172 __ teq($dst$$Register, 32); 9173 __ rbit($tmp$$Register, $src$$Register->successor()); 9174 __ clz($tmp$$Register, $tmp$$Register, eq); 9175 __ add($dst$$Register, $dst$$Register, $tmp$$Register, eq); 9176 %} 9177 ins_pipe(ialu_reg); 9178 %} 9179 9180 9181 //---------- Population Count Instructions ------------------------------------- 9182 9183 instruct popCountI(iRegI dst, iRegI src, regD_low tmp) %{ 9184 predicate(UsePopCountInstruction); 9185 match(Set dst (PopCountI src)); 9186 effect(TEMP tmp); 9187 9188 format %{ "FMSR $tmp,$src\n\t" 9189 "VCNT.8 $tmp,$tmp\n\t" 9190 "VPADDL.U8 $tmp,$tmp\n\t" 9191 "VPADDL.U16 $tmp,$tmp\n\t" 9192 "FMRS $dst,$tmp" %} 9193 size(20); 9194 9195 ins_encode %{ 9196 __ fmsr($tmp$$FloatRegister, $src$$Register); 9197 __ vcnt($tmp$$FloatRegister, $tmp$$FloatRegister); 9198 __ vpaddl($tmp$$FloatRegister, $tmp$$FloatRegister, 8, 0); 9199 __ vpaddl($tmp$$FloatRegister, $tmp$$FloatRegister, 16, 0); 9200 __ fmrs($dst$$Register, $tmp$$FloatRegister); 9201 %} 9202 ins_pipe(ialu_reg); // FIXME 9203 %} 9204 9205 // Note: Long.bitCount(long) returns an int. 9206 instruct popCountL(iRegI dst, iRegL src, regD_low tmp) %{ 9207 predicate(UsePopCountInstruction); 9208 match(Set dst (PopCountL src)); 9209 effect(TEMP tmp); 9210 9211 format %{ "FMDRR $tmp,$src.lo,$src.hi\n\t" 9212 "VCNT.8 $tmp,$tmp\n\t" 9213 "VPADDL.U8 $tmp,$tmp\n\t" 9214 "VPADDL.U16 $tmp,$tmp\n\t" 9215 "VPADDL.U32 $tmp,$tmp\n\t" 9216 "FMRS $dst,$tmp" %} 9217 9218 size(32); 9219 9220 ins_encode %{ 9221 __ fmdrr($tmp$$FloatRegister, $src$$Register, $src$$Register->successor()); 9222 __ vcnt($tmp$$FloatRegister, $tmp$$FloatRegister); 9223 __ vpaddl($tmp$$FloatRegister, $tmp$$FloatRegister, 8, 0); 9224 __ vpaddl($tmp$$FloatRegister, $tmp$$FloatRegister, 16, 0); 9225 __ vpaddl($tmp$$FloatRegister, $tmp$$FloatRegister, 32, 0); 9226 __ fmrs($dst$$Register, $tmp$$FloatRegister); 9227 %} 9228 ins_pipe(ialu_reg); 9229 %} 9230 9231 9232 // ============================================================================ 9233 //------------Bytes reverse-------------------------------------------------- 9234 9235 instruct bytes_reverse_int(iRegI dst, iRegI src) %{ 9236 match(Set dst (ReverseBytesI src)); 9237 9238 size(4); 9239 format %{ "REV32 $dst,$src" %} 9240 ins_encode %{ 9241 __ rev($dst$$Register, $src$$Register); 9242 %} 9243 ins_pipe( iload_mem ); // FIXME 9244 %} 9245 9246 instruct bytes_reverse_long(iRegL dst, iRegL src) %{ 9247 match(Set dst (ReverseBytesL src)); 9248 effect(TEMP dst); 9249 size(8); 9250 format %{ "REV $dst.lo,$src.lo\n\t" 9251 "REV $dst.hi,$src.hi" %} 9252 ins_encode %{ 9253 __ rev($dst$$Register, $src$$Register->successor()); 9254 __ rev($dst$$Register->successor(), $src$$Register); 9255 %} 9256 ins_pipe( iload_mem ); // FIXME 9257 %} 9258 9259 instruct bytes_reverse_unsigned_short(iRegI dst, iRegI src) %{ 9260 match(Set dst (ReverseBytesUS src)); 9261 size(4); 9262 format %{ "REV16 $dst,$src" %} 9263 ins_encode %{ 9264 __ rev16($dst$$Register, $src$$Register); 9265 %} 9266 ins_pipe( iload_mem ); // FIXME 9267 %} 9268 9269 instruct bytes_reverse_short(iRegI dst, iRegI src) %{ 9270 match(Set dst (ReverseBytesS src)); 9271 size(4); 9272 format %{ "REVSH $dst,$src" %} 9273 ins_encode %{ 9274 __ revsh($dst$$Register, $src$$Register); 9275 %} 9276 ins_pipe( iload_mem ); // FIXME 9277 %} 9278 9279 9280 // ====================VECTOR INSTRUCTIONS===================================== 9281 9282 // Load Aligned Packed values into a Double Register 9283 instruct loadV8(vecD dst, memoryD mem) %{ 9284 predicate(n->as_LoadVector()->memory_size() == 8); 9285 match(Set dst (LoadVector mem)); 9286 ins_cost(MEMORY_REF_COST); 9287 size(4); 9288 format %{ "FLDD $mem,$dst\t! load vector (8 bytes)" %} 9289 ins_encode %{ 9290 __ ldr_double($dst$$FloatRegister, $mem$$Address); 9291 %} 9292 ins_pipe(floadD_mem); 9293 %} 9294 9295 // Load Aligned Packed values into a Double Register Pair 9296 instruct loadV16(vecX dst, memoryvld mem) %{ 9297 predicate(n->as_LoadVector()->memory_size() == 16); 9298 match(Set dst (LoadVector mem)); 9299 ins_cost(MEMORY_REF_COST); 9300 size(4); 9301 format %{ "VLD1 $mem,$dst.Q\t! load vector (16 bytes)" %} 9302 ins_encode %{ 9303 __ vld1($dst$$FloatRegister, $mem$$Address, MacroAssembler::VELEM_SIZE_16, 128); 9304 %} 9305 ins_pipe(floadD_mem); // FIXME 9306 %} 9307 9308 // Store Vector in Double register to memory 9309 instruct storeV8(memoryD mem, vecD src) %{ 9310 predicate(n->as_StoreVector()->memory_size() == 8); 9311 match(Set mem (StoreVector mem src)); 9312 ins_cost(MEMORY_REF_COST); 9313 size(4); 9314 format %{ "FSTD $src,$mem\t! store vector (8 bytes)" %} 9315 ins_encode %{ 9316 __ str_double($src$$FloatRegister, $mem$$Address); 9317 %} 9318 ins_pipe(fstoreD_mem_reg); 9319 %} 9320 9321 // Store Vector in Double Register Pair to memory 9322 instruct storeV16(memoryvld mem, vecX src) %{ 9323 predicate(n->as_StoreVector()->memory_size() == 16); 9324 match(Set mem (StoreVector mem src)); 9325 ins_cost(MEMORY_REF_COST); 9326 size(4); 9327 format %{ "VST1 $src,$mem\t! store vector (16 bytes)" %} 9328 ins_encode %{ 9329 __ vst1($src$$FloatRegister, $mem$$Address, MacroAssembler::VELEM_SIZE_16, 128); 9330 %} 9331 ins_pipe(fstoreD_mem_reg); // FIXME 9332 %} 9333 9334 // Replicate scalar to packed byte values in Double register 9335 instruct Repl8B_reg(vecD dst, iRegI src, iRegI tmp) %{ 9336 predicate(n->as_Vector()->length() == 8 && 9337 Matcher::vector_element_basic_type(n) == T_BYTE); 9338 match(Set dst (Replicate src)); 9339 ins_cost(DEFAULT_COST*4); 9340 effect(TEMP tmp); 9341 size(16); 9342 9343 // FIXME: could use PKH instruction instead? 9344 format %{ "LSL $tmp, $src, 24 \n\t" 9345 "OR $tmp, $tmp, ($tmp >> 8) \n\t" 9346 "OR $tmp, $tmp, ($tmp >> 16) \n\t" 9347 "FMDRR $dst,$tmp,$tmp\t" %} 9348 ins_encode %{ 9349 __ mov($tmp$$Register, AsmOperand($src$$Register, lsl, 24)); 9350 __ orr($tmp$$Register, $tmp$$Register, AsmOperand($tmp$$Register, lsr, 8)); 9351 __ orr($tmp$$Register, $tmp$$Register, AsmOperand($tmp$$Register, lsr, 16)); 9352 __ fmdrr($dst$$FloatRegister, $tmp$$Register, $tmp$$Register); 9353 %} 9354 ins_pipe(ialu_reg); // FIXME 9355 %} 9356 9357 // Replicate scalar to packed byte values in Double register 9358 instruct Repl8B_reg_simd(vecD dst, iRegI src) %{ 9359 predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd() && 9360 Matcher::vector_element_basic_type(n) == T_BYTE); 9361 match(Set dst (Replicate src)); 9362 size(4); 9363 9364 format %{ "VDUP.8 $dst,$src\t" %} 9365 ins_encode %{ 9366 bool quad = false; 9367 __ vdupI($dst$$FloatRegister, $src$$Register, 9368 MacroAssembler::VELEM_SIZE_8, quad); 9369 %} 9370 ins_pipe(ialu_reg); // FIXME 9371 %} 9372 9373 // Replicate scalar to packed byte values in Double register pair 9374 instruct Repl16B_reg(vecX dst, iRegI src) %{ 9375 predicate(n->as_Vector()->length_in_bytes() == 16 && 9376 Matcher::vector_element_basic_type(n) == T_BYTE); 9377 match(Set dst (Replicate src)); 9378 size(4); 9379 9380 format %{ "VDUP.8 $dst.Q,$src\t" %} 9381 ins_encode %{ 9382 bool quad = true; 9383 __ vdupI($dst$$FloatRegister, $src$$Register, 9384 MacroAssembler::VELEM_SIZE_8, quad); 9385 %} 9386 ins_pipe(ialu_reg); // FIXME 9387 %} 9388 9389 // Replicate scalar constant to packed byte values in Double register 9390 instruct Repl8B_immI(vecD dst, immI src, iRegI tmp) %{ 9391 predicate(n->as_Vector()->length() == 8 && 9392 Matcher::vector_element_basic_type(n) == T_BYTE); 9393 match(Set dst (Replicate src)); 9394 ins_cost(DEFAULT_COST*2); 9395 effect(TEMP tmp); 9396 size(12); 9397 9398 format %{ "MOV $tmp, Repl4($src))\n\t" 9399 "FMDRR $dst,$tmp,$tmp\t" %} 9400 ins_encode( LdReplImmI(src, dst, tmp, (4), (1)) ); 9401 ins_pipe(loadConFD); // FIXME 9402 %} 9403 9404 // Replicate scalar constant to packed byte values in Double register 9405 // TODO: support negative constants with MVNI? 9406 instruct Repl8B_immU8(vecD dst, immU8 src) %{ 9407 predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd() && 9408 Matcher::vector_element_basic_type(n) == T_BYTE); 9409 match(Set dst (Replicate src)); 9410 size(4); 9411 9412 format %{ "VMOV.U8 $dst,$src" %} 9413 ins_encode %{ 9414 bool quad = false; 9415 __ vmovI($dst$$FloatRegister, $src$$constant, 9416 MacroAssembler::VELEM_SIZE_8, quad); 9417 %} 9418 ins_pipe(loadConFD); // FIXME 9419 %} 9420 9421 // Replicate scalar constant to packed byte values in Double register pair 9422 instruct Repl16B_immU8(vecX dst, immU8 src) %{ 9423 predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd() && 9424 Matcher::vector_element_basic_type(n) == T_BYTE); 9425 match(Set dst (Replicate src)); 9426 size(4); 9427 9428 format %{ "VMOV.U8 $dst.Q,$src" %} 9429 ins_encode %{ 9430 bool quad = true; 9431 __ vmovI($dst$$FloatRegister, $src$$constant, 9432 MacroAssembler::VELEM_SIZE_8, quad); 9433 %} 9434 ins_pipe(loadConFD); // FIXME 9435 %} 9436 9437 // Replicate scalar to packed short/char values into Double register 9438 instruct Repl4S_reg(vecD dst, iRegI src, iRegI tmp) %{ 9439 predicate(n->as_Vector()->length() == 4 && 9440 Matcher::vector_element_basic_type(n) == T_SHORT); 9441 match(Set dst (Replicate src)); 9442 ins_cost(DEFAULT_COST*3); 9443 effect(TEMP tmp); 9444 size(12); 9445 9446 // FIXME: could use PKH instruction instead? 9447 format %{ "LSL $tmp, $src, 16 \n\t" 9448 "OR $tmp, $tmp, ($tmp >> 16) \n\t" 9449 "FMDRR $dst,$tmp,$tmp\t" %} 9450 ins_encode %{ 9451 __ mov($tmp$$Register, AsmOperand($src$$Register, lsl, 16)); 9452 __ orr($tmp$$Register, $tmp$$Register, AsmOperand($tmp$$Register, lsr, 16)); 9453 __ fmdrr($dst$$FloatRegister, $tmp$$Register, $tmp$$Register); 9454 %} 9455 ins_pipe(ialu_reg); // FIXME 9456 %} 9457 9458 // Replicate scalar to packed byte values in Double register 9459 instruct Repl4S_reg_simd(vecD dst, iRegI src) %{ 9460 predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd() && 9461 Matcher::vector_element_basic_type(n) == T_SHORT); 9462 match(Set dst (Replicate src)); 9463 size(4); 9464 9465 format %{ "VDUP.16 $dst,$src\t" %} 9466 ins_encode %{ 9467 bool quad = false; 9468 __ vdupI($dst$$FloatRegister, $src$$Register, 9469 MacroAssembler::VELEM_SIZE_16, quad); 9470 %} 9471 ins_pipe(ialu_reg); // FIXME 9472 %} 9473 9474 // Replicate scalar to packed byte values in Double register pair 9475 instruct Repl8S_reg(vecX dst, iRegI src) %{ 9476 predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd() && 9477 Matcher::vector_element_basic_type(n) == T_SHORT); 9478 match(Set dst (Replicate src)); 9479 size(4); 9480 9481 format %{ "VDUP.16 $dst.Q,$src\t" %} 9482 ins_encode %{ 9483 bool quad = true; 9484 __ vdupI($dst$$FloatRegister, $src$$Register, 9485 MacroAssembler::VELEM_SIZE_16, quad); 9486 %} 9487 ins_pipe(ialu_reg); // FIXME 9488 %} 9489 9490 9491 // Replicate scalar constant to packed short/char values in Double register 9492 instruct Repl4S_immI(vecD dst, immI src, iRegP tmp) %{ 9493 predicate(n->as_Vector()->length() == 4 && 9494 Matcher::vector_element_basic_type(n) == T_SHORT); 9495 match(Set dst (Replicate src)); 9496 effect(TEMP tmp); 9497 size(12); 9498 ins_cost(DEFAULT_COST*4); // FIXME 9499 9500 format %{ "MOV $tmp, Repl2($src))\n\t" 9501 "FMDRR $dst,$tmp,$tmp\t" %} 9502 ins_encode( LdReplImmI(src, dst, tmp, (2), (2)) ); 9503 ins_pipe(loadConFD); // FIXME 9504 %} 9505 9506 // Replicate scalar constant to packed byte values in Double register 9507 instruct Repl4S_immU8(vecD dst, immU8 src) %{ 9508 predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd() && 9509 Matcher::vector_element_basic_type(n) == T_SHORT); 9510 match(Set dst (Replicate src)); 9511 size(4); 9512 9513 format %{ "VMOV.U16 $dst,$src" %} 9514 ins_encode %{ 9515 bool quad = false; 9516 __ vmovI($dst$$FloatRegister, $src$$constant, 9517 MacroAssembler::VELEM_SIZE_16, quad); 9518 %} 9519 ins_pipe(loadConFD); // FIXME 9520 %} 9521 9522 // Replicate scalar constant to packed byte values in Double register pair 9523 instruct Repl8S_immU8(vecX dst, immU8 src) %{ 9524 predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd() && 9525 Matcher::vector_element_basic_type(n) == T_SHORT); 9526 match(Set dst (Replicate src)); 9527 size(4); 9528 9529 format %{ "VMOV.U16 $dst.Q,$src" %} 9530 ins_encode %{ 9531 bool quad = true; 9532 __ vmovI($dst$$FloatRegister, $src$$constant, 9533 MacroAssembler::VELEM_SIZE_16, quad); 9534 %} 9535 ins_pipe(loadConFD); // FIXME 9536 %} 9537 9538 // Replicate scalar to packed int values in Double register 9539 instruct Repl2I_reg(vecD dst, iRegI src) %{ 9540 predicate(n->as_Vector()->length() == 2 && 9541 Matcher::vector_element_basic_type(n) == T_INT); 9542 match(Set dst (Replicate src)); 9543 size(4); 9544 9545 format %{ "FMDRR $dst,$src,$src\t" %} 9546 ins_encode %{ 9547 __ fmdrr($dst$$FloatRegister, $src$$Register, $src$$Register); 9548 %} 9549 ins_pipe(ialu_reg); // FIXME 9550 %} 9551 9552 // Replicate scalar to packed int values in Double register pair 9553 instruct Repl4I_reg(vecX dst, iRegI src) %{ 9554 predicate(n->as_Vector()->length() == 4 && 9555 Matcher::vector_element_basic_type(n) == T_INT); 9556 match(Set dst (Replicate src)); 9557 ins_cost(DEFAULT_COST*2); 9558 size(8); 9559 9560 format %{ "FMDRR $dst.lo,$src,$src\n\t" 9561 "FMDRR $dst.hi,$src,$src" %} 9562 9563 ins_encode %{ 9564 __ fmdrr($dst$$FloatRegister, $src$$Register, $src$$Register); 9565 __ fmdrr($dst$$FloatRegister->successor()->successor(), 9566 $src$$Register, $src$$Register); 9567 %} 9568 ins_pipe(ialu_reg); // FIXME 9569 %} 9570 9571 // Replicate scalar to packed int values in Double register 9572 instruct Repl2I_reg_simd(vecD dst, iRegI src) %{ 9573 predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd() && 9574 Matcher::vector_element_basic_type(n) == T_INT); 9575 match(Set dst (Replicate src)); 9576 size(4); 9577 9578 format %{ "VDUP.32 $dst.D,$src\t" %} 9579 ins_encode %{ 9580 bool quad = false; 9581 __ vdupI($dst$$FloatRegister, $src$$Register, 9582 MacroAssembler::VELEM_SIZE_32, quad); 9583 %} 9584 ins_pipe(ialu_reg); // FIXME 9585 %} 9586 9587 // Replicate scalar to packed int values in Double register pair 9588 instruct Repl4I_reg_simd(vecX dst, iRegI src) %{ 9589 predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd() && 9590 Matcher::vector_element_basic_type(n) == T_INT); 9591 match(Set dst (Replicate src)); 9592 size(4); 9593 9594 format %{ "VDUP.32 $dst.Q,$src\t" %} 9595 ins_encode %{ 9596 bool quad = true; 9597 __ vdupI($dst$$FloatRegister, $src$$Register, 9598 MacroAssembler::VELEM_SIZE_32, quad); 9599 %} 9600 ins_pipe(ialu_reg); // FIXME 9601 %} 9602 9603 9604 // Replicate scalar zero constant to packed int values in Double register 9605 instruct Repl2I_immI(vecD dst, immI src, iRegI tmp) %{ 9606 predicate(n->as_Vector()->length() == 2 && 9607 Matcher::vector_element_basic_type(n) == T_INT); 9608 match(Set dst (Replicate src)); 9609 effect(TEMP tmp); 9610 size(12); 9611 ins_cost(DEFAULT_COST*4); // FIXME 9612 9613 format %{ "MOV $tmp, Repl1($src))\n\t" 9614 "FMDRR $dst,$tmp,$tmp\t" %} 9615 ins_encode( LdReplImmI(src, dst, tmp, (1), (4)) ); 9616 ins_pipe(loadConFD); // FIXME 9617 %} 9618 9619 // Replicate scalar constant to packed byte values in Double register 9620 instruct Repl2I_immU8(vecD dst, immU8 src) %{ 9621 predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd() && 9622 Matcher::vector_element_basic_type(n) == T_INT); 9623 match(Set dst (Replicate src)); 9624 size(4); 9625 9626 format %{ "VMOV.I32 $dst.D,$src" %} 9627 ins_encode %{ 9628 bool quad = false; 9629 __ vmovI($dst$$FloatRegister, $src$$constant, 9630 MacroAssembler::VELEM_SIZE_32, quad); 9631 %} 9632 ins_pipe(loadConFD); // FIXME 9633 %} 9634 9635 // Replicate scalar constant to packed byte values in Double register pair 9636 instruct Repl4I_immU8(vecX dst, immU8 src) %{ 9637 predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd() && 9638 Matcher::vector_element_basic_type(n) == T_INT); 9639 match(Set dst (Replicate src)); 9640 size(4); 9641 9642 format %{ "VMOV.I32 $dst.Q,$src" %} 9643 ins_encode %{ 9644 bool quad = true; 9645 __ vmovI($dst$$FloatRegister, $src$$constant, 9646 MacroAssembler::VELEM_SIZE_32, quad); 9647 %} 9648 ins_pipe(loadConFD); // FIXME 9649 %} 9650 9651 // Replicate scalar to packed byte values in Double register pair 9652 instruct Repl2L_reg(vecX dst, iRegL src) %{ 9653 predicate(n->as_Vector()->length() == 2 && 9654 Matcher::vector_element_basic_type(n) == T_LONG); 9655 match(Set dst (Replicate src)); 9656 size(8); 9657 ins_cost(DEFAULT_COST*2); // FIXME 9658 9659 format %{ "FMDRR $dst.D,$src.lo,$src.hi\t\n" 9660 "FMDRR $dst.D.next,$src.lo,$src.hi" %} 9661 ins_encode %{ 9662 __ fmdrr($dst$$FloatRegister, $src$$Register, $src$$Register->successor()); 9663 __ fmdrr($dst$$FloatRegister->successor()->successor(), 9664 $src$$Register, $src$$Register->successor()); 9665 %} 9666 ins_pipe(ialu_reg); // FIXME 9667 %} 9668 9669 9670 // Replicate scalar to packed float values in Double register 9671 instruct Repl2F_regI(vecD dst, iRegI src) %{ 9672 predicate(n->as_Vector()->length() == 2 && 9673 Matcher::vector_element_basic_type(n) == T_FLOAT); 9674 match(Set dst (Replicate src)); 9675 size(4); 9676 9677 format %{ "FMDRR $dst.D,$src,$src\t" %} 9678 ins_encode %{ 9679 __ fmdrr($dst$$FloatRegister, $src$$Register, $src$$Register); 9680 %} 9681 ins_pipe(ialu_reg); // FIXME 9682 %} 9683 9684 // Replicate scalar to packed float values in Double register 9685 instruct Repl2F_reg_vfp(vecD dst, regF src) %{ 9686 predicate(n->as_Vector()->length() == 2 && 9687 Matcher::vector_element_basic_type(n) == T_FLOAT); 9688 match(Set dst (Replicate src)); 9689 size(4*2); 9690 ins_cost(DEFAULT_COST*2); // FIXME 9691 9692 expand %{ 9693 iRegI tmp; 9694 MoveF2I_reg_reg(tmp, src); 9695 Repl2F_regI(dst,tmp); 9696 %} 9697 %} 9698 9699 // Replicate scalar to packed float values in Double register 9700 instruct Repl2F_reg_simd(vecD dst, regF src) %{ 9701 predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd() && 9702 Matcher::vector_element_basic_type(n) == T_FLOAT); 9703 match(Set dst (Replicate src)); 9704 size(4); 9705 ins_cost(DEFAULT_COST); // FIXME 9706 9707 format %{ "VDUP.32 $dst.D,$src.D\t" %} 9708 ins_encode %{ 9709 bool quad = false; 9710 __ vdupF($dst$$FloatRegister, $src$$FloatRegister, quad); 9711 %} 9712 ins_pipe(ialu_reg); // FIXME 9713 %} 9714 9715 // Replicate scalar to packed float values in Double register pair 9716 instruct Repl4F_reg(vecX dst, regF src, iRegI tmp) %{ 9717 predicate(n->as_Vector()->length() == 4 && 9718 Matcher::vector_element_basic_type(n) == T_FLOAT); 9719 match(Set dst (Replicate src)); 9720 effect(TEMP tmp); 9721 size(4*3); 9722 ins_cost(DEFAULT_COST*3); // FIXME 9723 9724 format %{ "FMRS $tmp,$src\n\t" 9725 "FMDRR $dst.D,$tmp,$tmp\n\t" 9726 "FMDRR $dst.D.next,$tmp,$tmp\t" %} 9727 ins_encode %{ 9728 __ fmrs($tmp$$Register, $src$$FloatRegister); 9729 __ fmdrr($dst$$FloatRegister, $tmp$$Register, $tmp$$Register); 9730 __ fmdrr($dst$$FloatRegister->successor()->successor(), 9731 $tmp$$Register, $tmp$$Register); 9732 %} 9733 ins_pipe(ialu_reg); // FIXME 9734 %} 9735 9736 // Replicate scalar to packed float values in Double register pair 9737 instruct Repl4F_reg_simd(vecX dst, regF src) %{ 9738 predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd() && 9739 Matcher::vector_element_basic_type(n) == T_FLOAT); 9740 match(Set dst (Replicate src)); 9741 size(4); 9742 ins_cost(DEFAULT_COST); // FIXME 9743 9744 format %{ "VDUP.32 $dst.Q,$src.D\t" %} 9745 ins_encode %{ 9746 bool quad = true; 9747 __ vdupF($dst$$FloatRegister, $src$$FloatRegister, quad); 9748 %} 9749 ins_pipe(ialu_reg); // FIXME 9750 %} 9751 9752 // Replicate scalar zero constant to packed float values in Double register 9753 instruct Repl2F_immI(vecD dst, immF src, iRegI tmp) %{ 9754 predicate(n->as_Vector()->length() == 2 && 9755 Matcher::vector_element_basic_type(n) == T_FLOAT); 9756 match(Set dst (Replicate src)); 9757 effect(TEMP tmp); 9758 size(12); 9759 ins_cost(DEFAULT_COST*4); // FIXME 9760 9761 format %{ "MOV $tmp, Repl1($src))\n\t" 9762 "FMDRR $dst,$tmp,$tmp\t" %} 9763 ins_encode( LdReplImmF(src, dst, tmp) ); 9764 ins_pipe(loadConFD); // FIXME 9765 %} 9766 9767 // Replicate scalar to packed double float values in Double register pair 9768 instruct Repl2D_reg(vecX dst, regD src) %{ 9769 predicate(n->as_Vector()->length() == 2 && 9770 Matcher::vector_element_basic_type(n) == T_DOUBLE); 9771 match(Set dst (Replicate src)); 9772 size(4*2); 9773 ins_cost(DEFAULT_COST*2); // FIXME 9774 9775 format %{ "FCPYD $dst.D.a,$src\n\t" 9776 "FCPYD $dst.D.b,$src\t" %} 9777 ins_encode %{ 9778 FloatRegister dsta = $dst$$FloatRegister; 9779 FloatRegister src = $src$$FloatRegister; 9780 __ fcpyd(dsta, src); 9781 FloatRegister dstb = dsta->successor()->successor(); 9782 __ fcpyd(dstb, src); 9783 %} 9784 ins_pipe(ialu_reg); // FIXME 9785 %} 9786 9787 // ====================VECTOR ARITHMETIC======================================= 9788 9789 // --------------------------------- ADD -------------------------------------- 9790 9791 // Bytes vector add 9792 instruct vadd8B_reg(vecD dst, vecD src1, vecD src2) %{ 9793 predicate(n->as_Vector()->length() == 8); 9794 match(Set dst (AddVB src1 src2)); 9795 format %{ "VADD.I8 $dst,$src1,$src2\t! add packed8B" %} 9796 size(4); 9797 ins_encode %{ 9798 bool quad = false; 9799 __ vaddI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 9800 MacroAssembler::VELEM_SIZE_8, quad); 9801 %} 9802 ins_pipe( ialu_reg_reg ); // FIXME 9803 %} 9804 9805 instruct vadd16B_reg(vecX dst, vecX src1, vecX src2) %{ 9806 predicate(n->as_Vector()->length() == 16); 9807 match(Set dst (AddVB src1 src2)); 9808 size(4); 9809 format %{ "VADD.I8 $dst.Q,$src1.Q,$src2.Q\t! add packed16B" %} 9810 ins_encode %{ 9811 bool quad = true; 9812 __ vaddI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 9813 MacroAssembler::VELEM_SIZE_8, quad); 9814 %} 9815 ins_pipe( ialu_reg_reg ); // FIXME 9816 %} 9817 9818 // Shorts/Chars vector add 9819 instruct vadd4S_reg(vecD dst, vecD src1, vecD src2) %{ 9820 predicate(n->as_Vector()->length() == 4); 9821 match(Set dst (AddVS src1 src2)); 9822 size(4); 9823 format %{ "VADD.I16 $dst,$src1,$src2\t! add packed4S" %} 9824 ins_encode %{ 9825 bool quad = false; 9826 __ vaddI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 9827 MacroAssembler::VELEM_SIZE_16, quad); 9828 %} 9829 ins_pipe( ialu_reg_reg ); // FIXME 9830 %} 9831 9832 instruct vadd8S_reg(vecX dst, vecX src1, vecX src2) %{ 9833 predicate(n->as_Vector()->length() == 8); 9834 match(Set dst (AddVS src1 src2)); 9835 size(4); 9836 format %{ "VADD.I16 $dst.Q,$src1.Q,$src2.Q\t! add packed8S" %} 9837 ins_encode %{ 9838 bool quad = true; 9839 __ vaddI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 9840 MacroAssembler::VELEM_SIZE_16, quad); 9841 %} 9842 ins_pipe( ialu_reg_reg ); // FIXME 9843 %} 9844 9845 // Integers vector add 9846 instruct vadd2I_reg(vecD dst, vecD src1, vecD src2) %{ 9847 predicate(n->as_Vector()->length() == 2); 9848 match(Set dst (AddVI src1 src2)); 9849 size(4); 9850 format %{ "VADD.I32 $dst.D,$src1.D,$src2.D\t! add packed2I" %} 9851 ins_encode %{ 9852 bool quad = false; 9853 __ vaddI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 9854 MacroAssembler::VELEM_SIZE_32, quad); 9855 %} 9856 ins_pipe( ialu_reg_reg ); // FIXME 9857 %} 9858 9859 instruct vadd4I_reg(vecX dst, vecX src1, vecX src2) %{ 9860 predicate(n->as_Vector()->length() == 4); 9861 match(Set dst (AddVI src1 src2)); 9862 size(4); 9863 format %{ "VADD.I32 $dst.Q,$src1.Q,$src2.Q\t! add packed4I" %} 9864 ins_encode %{ 9865 bool quad = true; 9866 __ vaddI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 9867 MacroAssembler::VELEM_SIZE_32, quad); 9868 %} 9869 ins_pipe( ialu_reg_reg ); // FIXME 9870 %} 9871 9872 // Longs vector add 9873 instruct vadd2L_reg(vecX dst, vecX src1, vecX src2) %{ 9874 predicate(n->as_Vector()->length() == 2); 9875 match(Set dst (AddVL src1 src2)); 9876 size(4); 9877 format %{ "VADD.I64 $dst.Q,$src1.Q,$src2.Q\t! add packed2L" %} 9878 ins_encode %{ 9879 bool quad = true; 9880 __ vaddI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 9881 MacroAssembler::VELEM_SIZE_64, quad); 9882 %} 9883 ins_pipe( ialu_reg_reg ); // FIXME 9884 %} 9885 9886 // Floats vector add 9887 instruct vadd2F_reg(vecD dst, vecD src1, vecD src2) %{ 9888 predicate(n->as_Vector()->length() == 2 && VM_Version::simd_math_is_compliant()); 9889 match(Set dst (AddVF src1 src2)); 9890 size(4); 9891 format %{ "VADD.F32 $dst,$src1,$src2\t! add packed2F" %} 9892 ins_encode %{ 9893 bool quad = false; 9894 __ vaddF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 9895 MacroAssembler::VFA_SIZE_F32, quad); 9896 %} 9897 ins_pipe( faddD_reg_reg ); // FIXME 9898 %} 9899 9900 instruct vadd2F_reg_vfp(vecD dst, vecD src1, vecD src2) %{ 9901 predicate(n->as_Vector()->length() == 2 && !VM_Version::simd_math_is_compliant()); 9902 match(Set dst (AddVF src1 src2)); 9903 ins_cost(DEFAULT_COST*2); // FIXME 9904 9905 size(4*2); 9906 format %{ "FADDS $dst.a,$src1.a,$src2.a\n\t" 9907 "FADDS $dst.b,$src1.b,$src2.b" %} 9908 ins_encode %{ 9909 __ add_float($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister); 9910 __ add_float($dst$$FloatRegister->successor(), 9911 $src1$$FloatRegister->successor(), 9912 $src2$$FloatRegister->successor()); 9913 %} 9914 9915 ins_pipe(faddF_reg_reg); // FIXME 9916 %} 9917 9918 instruct vadd4F_reg_simd(vecX dst, vecX src1, vecX src2) %{ 9919 predicate(n->as_Vector()->length() == 4 && VM_Version::simd_math_is_compliant()); 9920 match(Set dst (AddVF src1 src2)); 9921 size(4); 9922 format %{ "VADD.F32 $dst.Q,$src1.Q,$src2.Q\t! add packed4F" %} 9923 ins_encode %{ 9924 bool quad = true; 9925 __ vaddF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 9926 MacroAssembler::VFA_SIZE_F32, quad); 9927 %} 9928 ins_pipe( faddD_reg_reg ); // FIXME 9929 %} 9930 9931 instruct vadd4F_reg_vfp(vecX dst, vecX src1, vecX src2) %{ 9932 predicate(n->as_Vector()->length() == 4 && !VM_Version::simd_math_is_compliant()); 9933 match(Set dst (AddVF src1 src2)); 9934 size(4*4); 9935 ins_cost(DEFAULT_COST*4); // FIXME 9936 9937 format %{ "FADDS $dst.a,$src1.a,$src2.a\n\t" 9938 "FADDS $dst.b,$src1.b,$src2.b\n\t" 9939 "FADDS $dst.c,$src1.c,$src2.c\n\t" 9940 "FADDS $dst.d,$src1.d,$src2.d" %} 9941 9942 ins_encode %{ 9943 FloatRegister dsta = $dst$$FloatRegister; 9944 FloatRegister src1a = $src1$$FloatRegister; 9945 FloatRegister src2a = $src2$$FloatRegister; 9946 __ add_float(dsta, src1a, src2a); 9947 FloatRegister dstb = dsta->successor(); 9948 FloatRegister src1b = src1a->successor(); 9949 FloatRegister src2b = src2a->successor(); 9950 __ add_float(dstb, src1b, src2b); 9951 FloatRegister dstc = dstb->successor(); 9952 FloatRegister src1c = src1b->successor(); 9953 FloatRegister src2c = src2b->successor(); 9954 __ add_float(dstc, src1c, src2c); 9955 FloatRegister dstd = dstc->successor(); 9956 FloatRegister src1d = src1c->successor(); 9957 FloatRegister src2d = src2c->successor(); 9958 __ add_float(dstd, src1d, src2d); 9959 %} 9960 9961 ins_pipe(faddF_reg_reg); // FIXME 9962 %} 9963 9964 instruct vadd2D_reg_vfp(vecX dst, vecX src1, vecX src2) %{ 9965 predicate(n->as_Vector()->length() == 2); 9966 match(Set dst (AddVD src1 src2)); 9967 size(4*2); 9968 ins_cost(DEFAULT_COST*2); // FIXME 9969 9970 format %{ "FADDD $dst.a,$src1.a,$src2.a\n\t" 9971 "FADDD $dst.b,$src1.b,$src2.b" %} 9972 9973 ins_encode %{ 9974 FloatRegister dsta = $dst$$FloatRegister; 9975 FloatRegister src1a = $src1$$FloatRegister; 9976 FloatRegister src2a = $src2$$FloatRegister; 9977 __ add_double(dsta, src1a, src2a); 9978 FloatRegister dstb = dsta->successor()->successor(); 9979 FloatRegister src1b = src1a->successor()->successor(); 9980 FloatRegister src2b = src2a->successor()->successor(); 9981 __ add_double(dstb, src1b, src2b); 9982 %} 9983 9984 ins_pipe(faddF_reg_reg); // FIXME 9985 %} 9986 9987 9988 // Bytes vector sub 9989 instruct vsub8B_reg(vecD dst, vecD src1, vecD src2) %{ 9990 predicate(n->as_Vector()->length() == 8); 9991 match(Set dst (SubVB src1 src2)); 9992 size(4); 9993 format %{ "VSUB.I8 $dst,$src1,$src2\t! sub packed8B" %} 9994 ins_encode %{ 9995 bool quad = false; 9996 __ vsubI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 9997 MacroAssembler::VELEM_SIZE_8, quad); 9998 %} 9999 ins_pipe( ialu_reg_reg ); // FIXME 10000 %} 10001 10002 instruct vsub16B_reg(vecX dst, vecX src1, vecX src2) %{ 10003 predicate(n->as_Vector()->length() == 16); 10004 match(Set dst (SubVB src1 src2)); 10005 size(4); 10006 format %{ "VSUB.I8 $dst.Q,$src1.Q,$src2.Q\t! sub packed16B" %} 10007 ins_encode %{ 10008 bool quad = true; 10009 __ vsubI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 10010 MacroAssembler::VELEM_SIZE_8, quad); 10011 %} 10012 ins_pipe( ialu_reg_reg ); // FIXME 10013 %} 10014 10015 // Shorts/Chars vector sub 10016 instruct vsub4S_reg(vecD dst, vecD src1, vecD src2) %{ 10017 predicate(n->as_Vector()->length() == 4); 10018 match(Set dst (SubVS src1 src2)); 10019 size(4); 10020 format %{ "VSUB.I16 $dst,$src1,$src2\t! sub packed4S" %} 10021 ins_encode %{ 10022 bool quad = false; 10023 __ vsubI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 10024 MacroAssembler::VELEM_SIZE_16, quad); 10025 %} 10026 ins_pipe( ialu_reg_reg ); // FIXME 10027 %} 10028 10029 instruct vsub16S_reg(vecX dst, vecX src1, vecX src2) %{ 10030 predicate(n->as_Vector()->length() == 8); 10031 match(Set dst (SubVS src1 src2)); 10032 size(4); 10033 format %{ "VSUB.I16 $dst.Q,$src1.Q,$src2.Q\t! sub packed8S" %} 10034 ins_encode %{ 10035 bool quad = true; 10036 __ vsubI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 10037 MacroAssembler::VELEM_SIZE_16, quad); 10038 %} 10039 ins_pipe( ialu_reg_reg ); // FIXME 10040 %} 10041 10042 // Integers vector sub 10043 instruct vsub2I_reg(vecD dst, vecD src1, vecD src2) %{ 10044 predicate(n->as_Vector()->length() == 2); 10045 match(Set dst (SubVI src1 src2)); 10046 size(4); 10047 format %{ "VSUB.I32 $dst,$src1,$src2\t! sub packed2I" %} 10048 ins_encode %{ 10049 bool quad = false; 10050 __ vsubI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 10051 MacroAssembler::VELEM_SIZE_32, quad); 10052 %} 10053 ins_pipe( ialu_reg_reg ); // FIXME 10054 %} 10055 10056 instruct vsub4I_reg(vecX dst, vecX src1, vecX src2) %{ 10057 predicate(n->as_Vector()->length() == 4); 10058 match(Set dst (SubVI src1 src2)); 10059 size(4); 10060 format %{ "VSUB.I32 $dst.Q,$src1.Q,$src2.Q\t! sub packed4I" %} 10061 ins_encode %{ 10062 bool quad = true; 10063 __ vsubI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 10064 MacroAssembler::VELEM_SIZE_32, quad); 10065 %} 10066 ins_pipe( ialu_reg_reg ); // FIXME 10067 %} 10068 10069 // Longs vector sub 10070 instruct vsub2L_reg(vecX dst, vecX src1, vecX src2) %{ 10071 predicate(n->as_Vector()->length() == 2); 10072 match(Set dst (SubVL src1 src2)); 10073 size(4); 10074 format %{ "VSUB.I64 $dst.Q,$src1.Q,$src2.Q\t! sub packed2L" %} 10075 ins_encode %{ 10076 bool quad = true; 10077 __ vsubI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 10078 MacroAssembler::VELEM_SIZE_64, quad); 10079 %} 10080 ins_pipe( ialu_reg_reg ); // FIXME 10081 %} 10082 10083 // Floats vector sub 10084 instruct vsub2F_reg(vecD dst, vecD src1, vecD src2) %{ 10085 predicate(n->as_Vector()->length() == 2 && VM_Version::simd_math_is_compliant()); 10086 match(Set dst (SubVF src1 src2)); 10087 size(4); 10088 format %{ "VSUB.F32 $dst,$src1,$src2\t! sub packed2F" %} 10089 ins_encode %{ 10090 bool quad = false; 10091 __ vsubF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 10092 MacroAssembler::VFA_SIZE_F32, quad); 10093 %} 10094 ins_pipe( faddF_reg_reg ); // FIXME 10095 %} 10096 10097 instruct vsub2F_reg_vfp(vecD dst, vecD src1, vecD src2) %{ 10098 predicate(n->as_Vector()->length() == 2 && !VM_Version::simd_math_is_compliant()); 10099 match(Set dst (SubVF src1 src2)); 10100 size(4*2); 10101 ins_cost(DEFAULT_COST*2); // FIXME 10102 10103 format %{ "FSUBS $dst.a,$src1.a,$src2.a\n\t" 10104 "FSUBS $dst.b,$src1.b,$src2.b" %} 10105 10106 ins_encode %{ 10107 FloatRegister dsta = $dst$$FloatRegister; 10108 FloatRegister src1a = $src1$$FloatRegister; 10109 FloatRegister src2a = $src2$$FloatRegister; 10110 __ sub_float(dsta, src1a, src2a); 10111 FloatRegister dstb = dsta->successor(); 10112 FloatRegister src1b = src1a->successor(); 10113 FloatRegister src2b = src2a->successor(); 10114 __ sub_float(dstb, src1b, src2b); 10115 %} 10116 10117 ins_pipe(faddF_reg_reg); // FIXME 10118 %} 10119 10120 10121 instruct vsub4F_reg(vecX dst, vecX src1, vecX src2) %{ 10122 predicate(n->as_Vector()->length() == 4 && VM_Version::simd_math_is_compliant()); 10123 match(Set dst (SubVF src1 src2)); 10124 size(4); 10125 format %{ "VSUB.F32 $dst.Q,$src1.Q,$src2.Q\t! sub packed4F" %} 10126 ins_encode %{ 10127 bool quad = true; 10128 __ vsubF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 10129 MacroAssembler::VFA_SIZE_F32, quad); 10130 %} 10131 ins_pipe( faddF_reg_reg ); // FIXME 10132 %} 10133 10134 instruct vsub4F_reg_vfp(vecX dst, vecX src1, vecX src2) %{ 10135 predicate(n->as_Vector()->length() == 4 && !VM_Version::simd_math_is_compliant()); 10136 match(Set dst (SubVF src1 src2)); 10137 size(4*4); 10138 ins_cost(DEFAULT_COST*4); // FIXME 10139 10140 format %{ "FSUBS $dst.a,$src1.a,$src2.a\n\t" 10141 "FSUBS $dst.b,$src1.b,$src2.b\n\t" 10142 "FSUBS $dst.c,$src1.c,$src2.c\n\t" 10143 "FSUBS $dst.d,$src1.d,$src2.d" %} 10144 10145 ins_encode %{ 10146 FloatRegister dsta = $dst$$FloatRegister; 10147 FloatRegister src1a = $src1$$FloatRegister; 10148 FloatRegister src2a = $src2$$FloatRegister; 10149 __ sub_float(dsta, src1a, src2a); 10150 FloatRegister dstb = dsta->successor(); 10151 FloatRegister src1b = src1a->successor(); 10152 FloatRegister src2b = src2a->successor(); 10153 __ sub_float(dstb, src1b, src2b); 10154 FloatRegister dstc = dstb->successor(); 10155 FloatRegister src1c = src1b->successor(); 10156 FloatRegister src2c = src2b->successor(); 10157 __ sub_float(dstc, src1c, src2c); 10158 FloatRegister dstd = dstc->successor(); 10159 FloatRegister src1d = src1c->successor(); 10160 FloatRegister src2d = src2c->successor(); 10161 __ sub_float(dstd, src1d, src2d); 10162 %} 10163 10164 ins_pipe(faddF_reg_reg); // FIXME 10165 %} 10166 10167 instruct vsub2D_reg_vfp(vecX dst, vecX src1, vecX src2) %{ 10168 predicate(n->as_Vector()->length() == 2); 10169 match(Set dst (SubVD src1 src2)); 10170 size(4*2); 10171 ins_cost(DEFAULT_COST*2); // FIXME 10172 10173 format %{ "FSUBD $dst.a,$src1.a,$src2.a\n\t" 10174 "FSUBD $dst.b,$src1.b,$src2.b" %} 10175 10176 ins_encode %{ 10177 FloatRegister dsta = $dst$$FloatRegister; 10178 FloatRegister src1a = $src1$$FloatRegister; 10179 FloatRegister src2a = $src2$$FloatRegister; 10180 __ sub_double(dsta, src1a, src2a); 10181 FloatRegister dstb = dsta->successor()->successor(); 10182 FloatRegister src1b = src1a->successor()->successor(); 10183 FloatRegister src2b = src2a->successor()->successor(); 10184 __ sub_double(dstb, src1b, src2b); 10185 %} 10186 10187 ins_pipe(faddF_reg_reg); // FIXME 10188 %} 10189 10190 // Shorts/Chars vector mul 10191 instruct vmul4S_reg(vecD dst, vecD src1, vecD src2) %{ 10192 predicate(n->as_Vector()->length() == 4); 10193 match(Set dst (MulVS src1 src2)); 10194 size(4); 10195 format %{ "VMUL.I16 $dst,$src1,$src2\t! mul packed4S" %} 10196 ins_encode %{ 10197 __ vmulI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 10198 MacroAssembler::VELEM_SIZE_16, 0); 10199 %} 10200 ins_pipe( ialu_reg_reg ); // FIXME 10201 %} 10202 10203 instruct vmul8S_reg(vecX dst, vecX src1, vecX src2) %{ 10204 predicate(n->as_Vector()->length() == 8); 10205 match(Set dst (MulVS src1 src2)); 10206 size(4); 10207 format %{ "VMUL.I16 $dst.Q,$src1.Q,$src2.Q\t! mul packed8S" %} 10208 ins_encode %{ 10209 __ vmulI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 10210 MacroAssembler::VELEM_SIZE_16, 1); 10211 %} 10212 ins_pipe( ialu_reg_reg ); // FIXME 10213 %} 10214 10215 // Integers vector mul 10216 instruct vmul2I_reg(vecD dst, vecD src1, vecD src2) %{ 10217 predicate(n->as_Vector()->length() == 2); 10218 match(Set dst (MulVI src1 src2)); 10219 size(4); 10220 format %{ "VMUL.I32 $dst,$src1,$src2\t! mul packed2I" %} 10221 ins_encode %{ 10222 __ vmulI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 10223 MacroAssembler::VELEM_SIZE_32, 0); 10224 %} 10225 ins_pipe( ialu_reg_reg ); // FIXME 10226 %} 10227 10228 instruct vmul4I_reg(vecX dst, vecX src1, vecX src2) %{ 10229 predicate(n->as_Vector()->length() == 4); 10230 match(Set dst (MulVI src1 src2)); 10231 size(4); 10232 format %{ "VMUL.I32 $dst.Q,$src1.Q,$src2.Q\t! mul packed4I" %} 10233 ins_encode %{ 10234 __ vmulI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 10235 MacroAssembler::VELEM_SIZE_32, 1); 10236 %} 10237 ins_pipe( ialu_reg_reg ); // FIXME 10238 %} 10239 10240 // Floats vector mul 10241 instruct vmul2F_reg(vecD dst, vecD src1, vecD src2) %{ 10242 predicate(n->as_Vector()->length() == 2 && VM_Version::simd_math_is_compliant()); 10243 match(Set dst (MulVF src1 src2)); 10244 size(4); 10245 format %{ "VMUL.F32 $dst,$src1,$src2\t! mul packed2F" %} 10246 ins_encode %{ 10247 __ vmulF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 10248 MacroAssembler::VFA_SIZE_F32, 0); 10249 %} 10250 ins_pipe( fmulF_reg_reg ); // FIXME 10251 %} 10252 10253 instruct vmul2F_reg_vfp(vecD dst, vecD src1, vecD src2) %{ 10254 predicate(n->as_Vector()->length() == 2 && !VM_Version::simd_math_is_compliant()); 10255 match(Set dst (MulVF src1 src2)); 10256 size(4*2); 10257 ins_cost(DEFAULT_COST*2); // FIXME 10258 10259 format %{ "FMULS $dst.a,$src1.a,$src2.a\n\t" 10260 "FMULS $dst.b,$src1.b,$src2.b" %} 10261 ins_encode %{ 10262 __ mul_float($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister); 10263 __ mul_float($dst$$FloatRegister->successor(), 10264 $src1$$FloatRegister->successor(), 10265 $src2$$FloatRegister->successor()); 10266 %} 10267 10268 ins_pipe(fmulF_reg_reg); // FIXME 10269 %} 10270 10271 instruct vmul4F_reg(vecX dst, vecX src1, vecX src2) %{ 10272 predicate(n->as_Vector()->length() == 4 && VM_Version::simd_math_is_compliant()); 10273 match(Set dst (MulVF src1 src2)); 10274 size(4); 10275 format %{ "VMUL.F32 $dst.Q,$src1.Q,$src2.Q\t! mul packed4F" %} 10276 ins_encode %{ 10277 __ vmulF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 10278 MacroAssembler::VFA_SIZE_F32, 1); 10279 %} 10280 ins_pipe( fmulF_reg_reg ); // FIXME 10281 %} 10282 10283 instruct vmul4F_reg_vfp(vecX dst, vecX src1, vecX src2) %{ 10284 predicate(n->as_Vector()->length() == 4 && !VM_Version::simd_math_is_compliant()); 10285 match(Set dst (MulVF src1 src2)); 10286 size(4*4); 10287 ins_cost(DEFAULT_COST*4); // FIXME 10288 10289 format %{ "FMULS $dst.a,$src1.a,$src2.a\n\t" 10290 "FMULS $dst.b,$src1.b,$src2.b\n\t" 10291 "FMULS $dst.c,$src1.c,$src2.c\n\t" 10292 "FMULS $dst.d,$src1.d,$src2.d" %} 10293 10294 ins_encode %{ 10295 FloatRegister dsta = $dst$$FloatRegister; 10296 FloatRegister src1a = $src1$$FloatRegister; 10297 FloatRegister src2a = $src2$$FloatRegister; 10298 __ mul_float(dsta, src1a, src2a); 10299 FloatRegister dstb = dsta->successor(); 10300 FloatRegister src1b = src1a->successor(); 10301 FloatRegister src2b = src2a->successor(); 10302 __ mul_float(dstb, src1b, src2b); 10303 FloatRegister dstc = dstb->successor(); 10304 FloatRegister src1c = src1b->successor(); 10305 FloatRegister src2c = src2b->successor(); 10306 __ mul_float(dstc, src1c, src2c); 10307 FloatRegister dstd = dstc->successor(); 10308 FloatRegister src1d = src1c->successor(); 10309 FloatRegister src2d = src2c->successor(); 10310 __ mul_float(dstd, src1d, src2d); 10311 %} 10312 10313 ins_pipe(fmulF_reg_reg); // FIXME 10314 %} 10315 10316 instruct vmul2D_reg_vfp(vecX dst, vecX src1, vecX src2) %{ 10317 predicate(n->as_Vector()->length() == 2); 10318 match(Set dst (MulVD src1 src2)); 10319 size(4*2); 10320 ins_cost(DEFAULT_COST*2); // FIXME 10321 10322 format %{ "FMULD $dst.D.a,$src1.D.a,$src2.D.a\n\t" 10323 "FMULD $dst.D.b,$src1.D.b,$src2.D.b" %} 10324 ins_encode %{ 10325 FloatRegister dsta = $dst$$FloatRegister; 10326 FloatRegister src1a = $src1$$FloatRegister; 10327 FloatRegister src2a = $src2$$FloatRegister; 10328 __ mul_double(dsta, src1a, src2a); 10329 FloatRegister dstb = dsta->successor()->successor(); 10330 FloatRegister src1b = src1a->successor()->successor(); 10331 FloatRegister src2b = src2a->successor()->successor(); 10332 __ mul_double(dstb, src1b, src2b); 10333 %} 10334 10335 ins_pipe(fmulD_reg_reg); // FIXME 10336 %} 10337 10338 10339 // Floats vector div 10340 instruct vdiv2F_reg_vfp(vecD dst, vecD src1, vecD src2) %{ 10341 predicate(n->as_Vector()->length() == 2); 10342 match(Set dst (DivVF src1 src2)); 10343 size(4*2); 10344 ins_cost(DEFAULT_COST*2); // FIXME 10345 10346 format %{ "FDIVS $dst.a,$src1.a,$src2.a\n\t" 10347 "FDIVS $dst.b,$src1.b,$src2.b" %} 10348 ins_encode %{ 10349 __ div_float($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister); 10350 __ div_float($dst$$FloatRegister->successor(), 10351 $src1$$FloatRegister->successor(), 10352 $src2$$FloatRegister->successor()); 10353 %} 10354 10355 ins_pipe(fdivF_reg_reg); // FIXME 10356 %} 10357 10358 instruct vdiv4F_reg_vfp(vecX dst, vecX src1, vecX src2) %{ 10359 predicate(n->as_Vector()->length() == 4); 10360 match(Set dst (DivVF src1 src2)); 10361 size(4*4); 10362 ins_cost(DEFAULT_COST*4); // FIXME 10363 10364 format %{ "FDIVS $dst.a,$src1.a,$src2.a\n\t" 10365 "FDIVS $dst.b,$src1.b,$src2.b\n\t" 10366 "FDIVS $dst.c,$src1.c,$src2.c\n\t" 10367 "FDIVS $dst.d,$src1.d,$src2.d" %} 10368 10369 ins_encode %{ 10370 FloatRegister dsta = $dst$$FloatRegister; 10371 FloatRegister src1a = $src1$$FloatRegister; 10372 FloatRegister src2a = $src2$$FloatRegister; 10373 __ div_float(dsta, src1a, src2a); 10374 FloatRegister dstb = dsta->successor(); 10375 FloatRegister src1b = src1a->successor(); 10376 FloatRegister src2b = src2a->successor(); 10377 __ div_float(dstb, src1b, src2b); 10378 FloatRegister dstc = dstb->successor(); 10379 FloatRegister src1c = src1b->successor(); 10380 FloatRegister src2c = src2b->successor(); 10381 __ div_float(dstc, src1c, src2c); 10382 FloatRegister dstd = dstc->successor(); 10383 FloatRegister src1d = src1c->successor(); 10384 FloatRegister src2d = src2c->successor(); 10385 __ div_float(dstd, src1d, src2d); 10386 %} 10387 10388 ins_pipe(fdivF_reg_reg); // FIXME 10389 %} 10390 10391 instruct vdiv2D_reg_vfp(vecX dst, vecX src1, vecX src2) %{ 10392 predicate(n->as_Vector()->length() == 2); 10393 match(Set dst (DivVD src1 src2)); 10394 size(4*2); 10395 ins_cost(DEFAULT_COST*2); // FIXME 10396 10397 format %{ "FDIVD $dst.D.a,$src1.D.a,$src2.D.a\n\t" 10398 "FDIVD $dst.D.b,$src1.D.b,$src2.D.b" %} 10399 ins_encode %{ 10400 FloatRegister dsta = $dst$$FloatRegister; 10401 FloatRegister src1a = $src1$$FloatRegister; 10402 FloatRegister src2a = $src2$$FloatRegister; 10403 __ div_double(dsta, src1a, src2a); 10404 FloatRegister dstb = dsta->successor()->successor(); 10405 FloatRegister src1b = src1a->successor()->successor(); 10406 FloatRegister src2b = src2a->successor()->successor(); 10407 __ div_double(dstb, src1b, src2b); 10408 %} 10409 10410 ins_pipe(fdivD_reg_reg); // FIXME 10411 %} 10412 10413 // --------------------------------- NEG -------------------------------------- 10414 10415 instruct vneg8B_reg(vecD dst, vecD src) %{ 10416 predicate(n->as_Vector()->length_in_bytes() == 8); 10417 effect(DEF dst, USE src); 10418 size(4); 10419 ins_cost(DEFAULT_COST); // FIXME 10420 format %{ "VNEG.S8 $dst.D,$src.D\t! neg packed8B" %} 10421 ins_encode %{ 10422 bool quad = false; 10423 __ vnegI($dst$$FloatRegister, $src$$FloatRegister, 10424 MacroAssembler::VELEM_SIZE_8, quad); 10425 %} 10426 ins_pipe( ialu_reg_reg ); // FIXME 10427 %} 10428 10429 instruct vneg16B_reg(vecX dst, vecX src) %{ 10430 predicate(n->as_Vector()->length_in_bytes() == 16); 10431 effect(DEF dst, USE src); 10432 size(4); 10433 ins_cost(DEFAULT_COST); // FIXME 10434 format %{ "VNEG.S8 $dst.Q,$src.Q\t! neg0 packed16B" %} 10435 ins_encode %{ 10436 bool _float = false; 10437 bool quad = true; 10438 __ vnegI($dst$$FloatRegister, $src$$FloatRegister, 10439 MacroAssembler::VELEM_SIZE_8, quad); 10440 %} 10441 ins_pipe( ialu_reg_reg ); // FIXME 10442 %} 10443 10444 // ------------------------------ ShiftCount ---------------------------------- 10445 10446 instruct vslcntD(vecD dst, iRegI cnt) %{ 10447 predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd()); 10448 match(Set dst (LShiftCntV cnt)); 10449 size(4); 10450 ins_cost(DEFAULT_COST); // FIXME 10451 expand %{ 10452 Repl8B_reg_simd(dst, cnt); 10453 %} 10454 %} 10455 10456 instruct vslcntX(vecX dst, iRegI cnt) %{ 10457 predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd()); 10458 match(Set dst (LShiftCntV cnt)); 10459 size(4); 10460 ins_cost(DEFAULT_COST); // FIXME 10461 expand %{ 10462 Repl16B_reg(dst, cnt); 10463 %} 10464 %} 10465 10466 // Low bits of vector "shift" elements are used, so it 10467 // doesn't matter if we treat it as ints or bytes here. 10468 instruct vsrcntD(vecD dst, iRegI cnt) %{ 10469 predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd()); 10470 match(Set dst (RShiftCntV cnt)); 10471 size(4*2); 10472 ins_cost(DEFAULT_COST*2); // FIXME 10473 10474 format %{ "VDUP.8 $dst.D,$cnt\n\t" 10475 "VNEG.S8 $dst.D,$dst.D\t! neg packed8B" %} 10476 ins_encode %{ 10477 bool quad = false; 10478 __ vdupI($dst$$FloatRegister, $cnt$$Register, 10479 MacroAssembler::VELEM_SIZE_8, quad); 10480 __ vnegI($dst$$FloatRegister, $dst$$FloatRegister, 10481 MacroAssembler::VELEM_SIZE_8, quad); 10482 %} 10483 ins_pipe( ialu_reg_reg ); // FIXME 10484 %} 10485 10486 instruct vsrcntX(vecX dst, iRegI cnt) %{ 10487 predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd()); 10488 match(Set dst (RShiftCntV cnt)); 10489 size(4*2); 10490 ins_cost(DEFAULT_COST*2); // FIXME 10491 format %{ "VDUP.8 $dst.Q,$cnt\n\t" 10492 "VNEG.S8 $dst.Q,$dst.Q\t! neg packed16B" %} 10493 ins_encode %{ 10494 bool quad = true; 10495 __ vdupI($dst$$FloatRegister, $cnt$$Register, 10496 MacroAssembler::VELEM_SIZE_8, quad); 10497 __ vnegI($dst$$FloatRegister, $dst$$FloatRegister, 10498 MacroAssembler::VELEM_SIZE_8, quad); 10499 %} 10500 ins_pipe( ialu_reg_reg ); // FIXME 10501 %} 10502 10503 // ------------------------------ LogicalShift -------------------------------- 10504 10505 // Byte vector logical left/right shift based on sign 10506 instruct vsh8B_reg(vecD dst, vecD src, vecD shift) %{ 10507 predicate(n->as_Vector()->length() == 8); 10508 effect(DEF dst, USE src, USE shift); 10509 size(4); 10510 ins_cost(DEFAULT_COST); // FIXME 10511 format %{ 10512 "VSHL.U8 $dst.D,$src.D,$shift.D\t! logical left/right shift packed8B" 10513 %} 10514 ins_encode %{ 10515 bool quad = false; 10516 __ vshlUI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister, 10517 MacroAssembler::VELEM_SIZE_8, quad); 10518 %} 10519 ins_pipe( ialu_reg_reg ); // FIXME 10520 %} 10521 10522 instruct vsh16B_reg(vecX dst, vecX src, vecX shift) %{ 10523 predicate(n->as_Vector()->length() == 16); 10524 effect(DEF dst, USE src, USE shift); 10525 size(4); 10526 ins_cost(DEFAULT_COST); // FIXME 10527 format %{ 10528 "VSHL.U8 $dst.Q,$src.Q,$shift.Q\t! logical left/right shift packed16B" 10529 %} 10530 ins_encode %{ 10531 bool quad = true; 10532 __ vshlUI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister, 10533 MacroAssembler::VELEM_SIZE_8, quad); 10534 %} 10535 ins_pipe( ialu_reg_reg ); // FIXME 10536 %} 10537 10538 // Shorts/Char vector logical left/right shift based on sign 10539 instruct vsh4S_reg(vecD dst, vecD src, vecD shift) %{ 10540 predicate(n->as_Vector()->length() == 4); 10541 effect(DEF dst, USE src, USE shift); 10542 size(4); 10543 ins_cost(DEFAULT_COST); // FIXME 10544 format %{ 10545 "VSHL.U16 $dst.D,$src.D,$shift.D\t! logical left/right shift packed4S" 10546 %} 10547 ins_encode %{ 10548 bool quad = false; 10549 __ vshlUI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister, 10550 MacroAssembler::VELEM_SIZE_16, quad); 10551 %} 10552 ins_pipe( ialu_reg_reg ); // FIXME 10553 %} 10554 10555 instruct vsh8S_reg(vecX dst, vecX src, vecX shift) %{ 10556 predicate(n->as_Vector()->length() == 8); 10557 effect(DEF dst, USE src, USE shift); 10558 size(4); 10559 ins_cost(DEFAULT_COST); // FIXME 10560 format %{ 10561 "VSHL.U16 $dst.Q,$src.Q,$shift.Q\t! logical left/right shift packed8S" 10562 %} 10563 ins_encode %{ 10564 bool quad = true; 10565 __ vshlUI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister, 10566 MacroAssembler::VELEM_SIZE_16, quad); 10567 %} 10568 ins_pipe( ialu_reg_reg ); // FIXME 10569 %} 10570 10571 // Integers vector logical left/right shift based on sign 10572 instruct vsh2I_reg(vecD dst, vecD src, vecD shift) %{ 10573 predicate(n->as_Vector()->length() == 2); 10574 effect(DEF dst, USE src, USE shift); 10575 size(4); 10576 ins_cost(DEFAULT_COST); // FIXME 10577 format %{ 10578 "VSHL.U32 $dst.D,$src.D,$shift.D\t! logical left/right shift packed2I" 10579 %} 10580 ins_encode %{ 10581 bool quad = false; 10582 __ vshlUI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister, 10583 MacroAssembler::VELEM_SIZE_32, quad); 10584 %} 10585 ins_pipe( ialu_reg_reg ); // FIXME 10586 %} 10587 10588 instruct vsh4I_reg(vecX dst, vecX src, vecX shift) %{ 10589 predicate(n->as_Vector()->length() == 4); 10590 effect(DEF dst, USE src, USE shift); 10591 size(4); 10592 ins_cost(DEFAULT_COST); // FIXME 10593 format %{ 10594 "VSHL.U32 $dst.Q,$src.Q,$shift.Q\t! logical left/right shift packed4I" 10595 %} 10596 ins_encode %{ 10597 bool quad = true; 10598 __ vshlUI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister, 10599 MacroAssembler::VELEM_SIZE_32, quad); 10600 %} 10601 ins_pipe( ialu_reg_reg ); // FIXME 10602 %} 10603 10604 // Longs vector logical left/right shift based on sign 10605 instruct vsh2L_reg(vecX dst, vecX src, vecX shift) %{ 10606 predicate(n->as_Vector()->length() == 2); 10607 effect(DEF dst, USE src, USE shift); 10608 size(4); 10609 ins_cost(DEFAULT_COST); // FIXME 10610 format %{ 10611 "VSHL.U64 $dst.Q,$src.Q,$shift.Q\t! logical left/right shift packed2L" 10612 %} 10613 ins_encode %{ 10614 bool quad = true; 10615 __ vshlUI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister, 10616 MacroAssembler::VELEM_SIZE_64, quad); 10617 %} 10618 ins_pipe( ialu_reg_reg ); // FIXME 10619 %} 10620 10621 // ------------------------------ LogicalLeftShift ---------------------------- 10622 10623 // Byte vector logical left shift 10624 instruct vsl8B_reg(vecD dst, vecD src, vecD shift) %{ 10625 predicate(n->as_Vector()->length() == 8); 10626 match(Set dst (LShiftVB src shift)); 10627 size(4*1); 10628 ins_cost(DEFAULT_COST*1); // FIXME 10629 expand %{ 10630 vsh8B_reg(dst, src, shift); 10631 %} 10632 %} 10633 10634 instruct vsl16B_reg(vecX dst, vecX src, vecX shift) %{ 10635 predicate(n->as_Vector()->length() == 16); 10636 match(Set dst (LShiftVB src shift)); 10637 size(4*1); 10638 ins_cost(DEFAULT_COST*1); // FIXME 10639 expand %{ 10640 vsh16B_reg(dst, src, shift); 10641 %} 10642 %} 10643 10644 instruct vsl8B_immI(vecD dst, vecD src, immI shift) %{ 10645 predicate(n->as_Vector()->length() == 8 && assert_not_var_shift(n)); 10646 match(Set dst (LShiftVB src (LShiftCntV shift))); 10647 size(4); 10648 ins_cost(DEFAULT_COST); // FIXME 10649 format %{ 10650 "VSHL.I8 $dst.D,$src.D,$shift\t! logical left shift packed8B" 10651 %} 10652 ins_encode %{ 10653 bool quad = false; 10654 __ vshli($dst$$FloatRegister, $src$$FloatRegister, 8, $shift$$constant, 10655 quad); 10656 %} 10657 ins_pipe( ialu_reg_reg ); // FIXME 10658 %} 10659 10660 instruct vsl16B_immI(vecX dst, vecX src, immI shift) %{ 10661 predicate(n->as_Vector()->length() == 16 && assert_not_var_shift(n)); 10662 match(Set dst (LShiftVB src (LShiftCntV shift))); 10663 size(4); 10664 ins_cost(DEFAULT_COST); // FIXME 10665 format %{ 10666 "VSHL.I8 $dst.Q,$src.Q,$shift\t! logical left shift packed16B" 10667 %} 10668 ins_encode %{ 10669 bool quad = true; 10670 __ vshli($dst$$FloatRegister, $src$$FloatRegister, 8, $shift$$constant, 10671 quad); 10672 %} 10673 ins_pipe( ialu_reg_reg ); // FIXME 10674 %} 10675 10676 // Shorts/Chars vector logical left shift 10677 instruct vsl4S_reg(vecD dst, vecD src, vecD shift) %{ 10678 predicate(n->as_Vector()->length() == 4); 10679 match(Set dst (LShiftVS src shift)); 10680 size(4*1); 10681 ins_cost(DEFAULT_COST*1); // FIXME 10682 expand %{ 10683 vsh4S_reg(dst, src, shift); 10684 %} 10685 %} 10686 10687 instruct vsl8S_reg(vecX dst, vecX src, vecX shift) %{ 10688 predicate(n->as_Vector()->length() == 8); 10689 match(Set dst (LShiftVS src shift)); 10690 size(4*1); 10691 ins_cost(DEFAULT_COST*1); // FIXME 10692 expand %{ 10693 vsh8S_reg(dst, src, shift); 10694 %} 10695 %} 10696 10697 instruct vsl4S_immI(vecD dst, vecD src, immI shift) %{ 10698 predicate(n->as_Vector()->length() == 4 && assert_not_var_shift(n)); 10699 match(Set dst (LShiftVS src (LShiftCntV shift))); 10700 size(4); 10701 ins_cost(DEFAULT_COST); // FIXME 10702 format %{ 10703 "VSHL.I16 $dst.D,$src.D,$shift\t! logical left shift packed4S" 10704 %} 10705 ins_encode %{ 10706 bool quad = false; 10707 __ vshli($dst$$FloatRegister, $src$$FloatRegister, 16, $shift$$constant, 10708 quad); 10709 %} 10710 ins_pipe( ialu_reg_reg ); // FIXME 10711 %} 10712 10713 instruct vsl8S_immI(vecX dst, vecX src, immI shift) %{ 10714 predicate(n->as_Vector()->length() == 8 && assert_not_var_shift(n)); 10715 match(Set dst (LShiftVS src shift)); 10716 size(4); 10717 ins_cost(DEFAULT_COST); // FIXME 10718 format %{ 10719 "VSHL.I16 $dst.Q,$src.Q,$shift\t! logical left shift packed8S" 10720 %} 10721 ins_encode %{ 10722 bool quad = true; 10723 __ vshli($dst$$FloatRegister, $src$$FloatRegister, 16, $shift$$constant, 10724 quad); 10725 %} 10726 ins_pipe( ialu_reg_reg ); // FIXME 10727 %} 10728 10729 // Integers vector logical left shift 10730 instruct vsl2I_reg(vecD dst, vecD src, vecD shift) %{ 10731 predicate(n->as_Vector()->length() == 2 && VM_Version::has_simd()); 10732 match(Set dst (LShiftVI src shift)); 10733 size(4*1); 10734 ins_cost(DEFAULT_COST*1); // FIXME 10735 expand %{ 10736 vsh2I_reg(dst, src, shift); 10737 %} 10738 %} 10739 10740 instruct vsl4I_reg(vecX dst, vecX src, vecX shift) %{ 10741 predicate(n->as_Vector()->length() == 4 && VM_Version::has_simd()); 10742 match(Set dst (LShiftVI src shift)); 10743 size(4*1); 10744 ins_cost(DEFAULT_COST*1); // FIXME 10745 expand %{ 10746 vsh4I_reg(dst, src, shift); 10747 %} 10748 %} 10749 10750 instruct vsl2I_immI(vecD dst, vecD src, immI shift) %{ 10751 predicate(n->as_Vector()->length() == 2 && 10752 VM_Version::has_simd() && 10753 assert_not_var_shift(n)); 10754 match(Set dst (LShiftVI src (LShiftCntV shift))); 10755 size(4); 10756 ins_cost(DEFAULT_COST); // FIXME 10757 format %{ 10758 "VSHL.I32 $dst.D,$src.D,$shift\t! logical left shift packed2I" 10759 %} 10760 ins_encode %{ 10761 bool quad = false; 10762 __ vshli($dst$$FloatRegister, $src$$FloatRegister, 32, $shift$$constant, 10763 quad); 10764 %} 10765 ins_pipe( ialu_reg_reg ); // FIXME 10766 %} 10767 10768 instruct vsl4I_immI(vecX dst, vecX src, immI shift) %{ 10769 predicate(n->as_Vector()->length() == 4 && 10770 VM_Version::has_simd() && 10771 assert_not_var_shift(n)); 10772 match(Set dst (LShiftVI src (LShiftCntV shift))); 10773 size(4); 10774 ins_cost(DEFAULT_COST); // FIXME 10775 format %{ 10776 "VSHL.I32 $dst.Q,$src.Q,$shift\t! logical left shift packed4I" 10777 %} 10778 ins_encode %{ 10779 bool quad = true; 10780 __ vshli($dst$$FloatRegister, $src$$FloatRegister, 32, $shift$$constant, 10781 quad); 10782 %} 10783 ins_pipe( ialu_reg_reg ); // FIXME 10784 %} 10785 10786 // Longs vector logical left shift 10787 instruct vsl2L_reg(vecX dst, vecX src, vecX shift) %{ 10788 predicate(n->as_Vector()->length() == 2); 10789 match(Set dst (LShiftVL src shift)); 10790 size(4*1); 10791 ins_cost(DEFAULT_COST*1); // FIXME 10792 expand %{ 10793 vsh2L_reg(dst, src, shift); 10794 %} 10795 %} 10796 10797 instruct vsl2L_immI(vecX dst, vecX src, immI shift) %{ 10798 predicate(n->as_Vector()->length() == 2 && assert_not_var_shift(n)); 10799 match(Set dst (LShiftVL src (LShiftCntV shift))); 10800 size(4); 10801 ins_cost(DEFAULT_COST); // FIXME 10802 format %{ 10803 "VSHL.I64 $dst.Q,$src.Q,$shift\t! logical left shift packed2L" 10804 %} 10805 ins_encode %{ 10806 bool quad = true; 10807 __ vshli($dst$$FloatRegister, $src$$FloatRegister, 64, $shift$$constant, 10808 quad); 10809 %} 10810 ins_pipe( ialu_reg_reg ); // FIXME 10811 %} 10812 10813 // ----------------------- LogicalRightShift ----------------------------------- 10814 10815 // Bytes/Shorts vector logical right shift produces incorrect Java result 10816 // for negative data because java code convert short value into int with 10817 // sign extension before a shift. 10818 10819 // Right shift with vector shift count on aarch32 SIMD is implemented as left 10820 // shift by negative shift count value. 10821 // 10822 // Method is_var_shift() denotes that vector shift count is a variable shift: 10823 // 1) for this case, vector shift count should be negated before conducting 10824 // right shifts. E.g., vsrl4S_reg_var rule. 10825 // 2) for the opposite case, vector shift count is generated via RShiftCntV 10826 // rules and is already negated there. Hence, no negation is needed. 10827 // E.g., vsrl4S_reg rule. 10828 10829 // Chars vector logical right shift 10830 instruct vsrl4S_reg(vecD dst, vecD src, vecD shift) %{ 10831 predicate(n->as_Vector()->length() == 4 && !n->as_ShiftV()->is_var_shift()); 10832 match(Set dst (URShiftVS src shift)); 10833 size(4); 10834 ins_cost(DEFAULT_COST); 10835 expand %{ 10836 vsh4S_reg(dst, src, shift); 10837 %} 10838 %} 10839 10840 instruct vsrl4S_reg_var(vecD dst, vecD src, vecD shift, vecD tmp) %{ 10841 predicate(n->as_Vector()->length() == 4 && n->as_ShiftV()->is_var_shift()); 10842 match(Set dst (URShiftVS src shift)); 10843 effect(TEMP tmp); 10844 size(4*2); 10845 ins_cost(DEFAULT_COST*2); 10846 format %{ 10847 "VNEG.S8 $tmp.D,$shift.D\n\t! neg packed8B" 10848 "VSHL.U16 $dst.D,$src.D,$tmp.D\t! logical right shift packed4S" 10849 %} 10850 ins_encode %{ 10851 bool quad = false; 10852 __ vnegI($tmp$$FloatRegister, $shift$$FloatRegister, 10853 MacroAssembler::VELEM_SIZE_8, quad); 10854 __ vshlUI($dst$$FloatRegister, $tmp$$FloatRegister, $src$$FloatRegister, 10855 MacroAssembler::VELEM_SIZE_16, quad); 10856 %} 10857 ins_pipe(ialu_reg_reg); 10858 %} 10859 10860 instruct vsrl8S_reg(vecX dst, vecX src, vecX shift) %{ 10861 predicate(n->as_Vector()->length() == 8 && !n->as_ShiftV()->is_var_shift()); 10862 match(Set dst (URShiftVS src shift)); 10863 size(4); 10864 ins_cost(DEFAULT_COST); 10865 expand %{ 10866 vsh8S_reg(dst, src, shift); 10867 %} 10868 %} 10869 10870 instruct vsrl8S_reg_var(vecX dst, vecX src, vecX shift, vecX tmp) %{ 10871 predicate(n->as_Vector()->length() == 8 && n->as_ShiftV()->is_var_shift()); 10872 match(Set dst (URShiftVS src shift)); 10873 effect(TEMP tmp); 10874 size(4*2); 10875 ins_cost(DEFAULT_COST*2); 10876 format %{ 10877 "VNEG.S8 $tmp.Q,$shift.Q\n\t! neg packed16B" 10878 "VSHL.U16 $dst.Q,$src.Q,$tmp.Q\t! logical right shift packed8S" 10879 %} 10880 ins_encode %{ 10881 bool quad = true; 10882 __ vnegI($tmp$$FloatRegister, $shift$$FloatRegister, 10883 MacroAssembler::VELEM_SIZE_8, quad); 10884 __ vshlUI($dst$$FloatRegister, $tmp$$FloatRegister, $src$$FloatRegister, 10885 MacroAssembler::VELEM_SIZE_16, quad); 10886 %} 10887 ins_pipe(ialu_reg_reg); 10888 %} 10889 10890 instruct vsrl4S_immI(vecD dst, vecD src, immI shift) %{ 10891 predicate(n->as_Vector()->length() == 4 && assert_not_var_shift(n)); 10892 match(Set dst (URShiftVS src (RShiftCntV shift))); 10893 size(4); 10894 ins_cost(DEFAULT_COST); // FIXME 10895 format %{ 10896 "VSHR.U16 $dst.D,$src.D,$shift\t! logical right shift packed4S" 10897 %} 10898 ins_encode %{ 10899 bool quad = false; 10900 __ vshrUI($dst$$FloatRegister, $src$$FloatRegister, 16, $shift$$constant, 10901 quad); 10902 %} 10903 ins_pipe( ialu_reg_reg ); // FIXME 10904 %} 10905 10906 instruct vsrl8S_immI(vecX dst, vecX src, immI shift) %{ 10907 predicate(n->as_Vector()->length() == 8 && assert_not_var_shift(n)); 10908 match(Set dst (URShiftVS src (RShiftCntV shift))); 10909 size(4); 10910 ins_cost(DEFAULT_COST); // FIXME 10911 format %{ 10912 "VSHR.U16 $dst.Q,$src.Q,$shift\t! logical right shift packed8S" 10913 %} 10914 ins_encode %{ 10915 bool quad = true; 10916 __ vshrUI($dst$$FloatRegister, $src$$FloatRegister, 16, $shift$$constant, 10917 quad); 10918 %} 10919 ins_pipe( ialu_reg_reg ); // FIXME 10920 %} 10921 10922 // Integers vector logical right shift 10923 instruct vsrl2I_reg(vecD dst, vecD src, vecD shift) %{ 10924 predicate(n->as_Vector()->length() == 2 && 10925 VM_Version::has_simd() && 10926 !n->as_ShiftV()->is_var_shift()); 10927 match(Set dst (URShiftVI src shift)); 10928 size(4); 10929 ins_cost(DEFAULT_COST); 10930 expand %{ 10931 vsh2I_reg(dst, src, shift); 10932 %} 10933 %} 10934 10935 instruct vsrl2I_reg_var(vecD dst, vecD src, vecD shift, vecD tmp) %{ 10936 predicate(n->as_Vector()->length() == 2 && 10937 VM_Version::has_simd() && 10938 n->as_ShiftV()->is_var_shift()); 10939 match(Set dst (URShiftVI src shift)); 10940 effect(TEMP tmp); 10941 size(4*2); 10942 ins_cost(DEFAULT_COST*2); 10943 format %{ 10944 "VNEG.S8 $tmp.D,$shift.D\n\t! neg packed8B" 10945 "VSHL.U32 $dst.D,$src.D,$tmp.D\t! logical right shift packed2I" 10946 %} 10947 ins_encode %{ 10948 bool quad = false; 10949 __ vnegI($tmp$$FloatRegister, $shift$$FloatRegister, 10950 MacroAssembler::VELEM_SIZE_8, quad); 10951 __ vshlUI($dst$$FloatRegister, $tmp$$FloatRegister, $src$$FloatRegister, 10952 MacroAssembler::VELEM_SIZE_32, quad); 10953 %} 10954 ins_pipe(ialu_reg_reg); 10955 %} 10956 10957 instruct vsrl4I_reg(vecX dst, vecX src, vecX shift) %{ 10958 predicate(n->as_Vector()->length() == 4 && 10959 VM_Version::has_simd() && 10960 !n->as_ShiftV()->is_var_shift()); 10961 match(Set dst (URShiftVI src shift)); 10962 size(4); 10963 ins_cost(DEFAULT_COST); 10964 expand %{ 10965 vsh4I_reg(dst, src, shift); 10966 %} 10967 %} 10968 10969 instruct vsrl4I_reg_var(vecX dst, vecX src, vecX shift, vecX tmp) %{ 10970 predicate(n->as_Vector()->length() == 4 && 10971 VM_Version::has_simd() && 10972 n->as_ShiftV()->is_var_shift()); 10973 match(Set dst (URShiftVI src shift)); 10974 effect(TEMP tmp); 10975 size(4*2); 10976 ins_cost(DEFAULT_COST*2); 10977 format %{ 10978 "VNEG.S8 $tmp.Q,$shift.Q\n\t! neg packed16B" 10979 "VSHL.U32 $dst.Q,$src.Q,$tmp.Q\t! logical right shift packed4I" 10980 %} 10981 ins_encode %{ 10982 bool quad = true; 10983 __ vnegI($tmp$$FloatRegister, $shift$$FloatRegister, 10984 MacroAssembler::VELEM_SIZE_8, quad); 10985 __ vshlUI($dst$$FloatRegister, $tmp$$FloatRegister, $src$$FloatRegister, 10986 MacroAssembler::VELEM_SIZE_32, quad); 10987 %} 10988 ins_pipe(ialu_reg_reg); 10989 %} 10990 10991 instruct vsrl2I_immI(vecD dst, vecD src, immI shift) %{ 10992 predicate(n->as_Vector()->length() == 2 && 10993 VM_Version::has_simd() && 10994 assert_not_var_shift(n)); 10995 match(Set dst (URShiftVI src (RShiftCntV shift))); 10996 size(4); 10997 ins_cost(DEFAULT_COST); // FIXME 10998 format %{ 10999 "VSHR.U32 $dst.D,$src.D,$shift\t! logical right shift packed2I" 11000 %} 11001 ins_encode %{ 11002 bool quad = false; 11003 __ vshrUI($dst$$FloatRegister, $src$$FloatRegister, 32, $shift$$constant, 11004 quad); 11005 %} 11006 ins_pipe( ialu_reg_reg ); // FIXME 11007 %} 11008 11009 instruct vsrl4I_immI(vecX dst, vecX src, immI shift) %{ 11010 predicate(n->as_Vector()->length() == 4 && 11011 VM_Version::has_simd() && 11012 assert_not_var_shift(n)); 11013 match(Set dst (URShiftVI src (RShiftCntV shift))); 11014 size(4); 11015 ins_cost(DEFAULT_COST); // FIXME 11016 format %{ 11017 "VSHR.U32 $dst.Q,$src.Q,$shift\t! logical right shift packed4I" 11018 %} 11019 ins_encode %{ 11020 bool quad = true; 11021 __ vshrUI($dst$$FloatRegister, $src$$FloatRegister, 32, $shift$$constant, 11022 quad); 11023 %} 11024 ins_pipe( ialu_reg_reg ); // FIXME 11025 %} 11026 11027 // Longs vector logical right shift 11028 instruct vsrl2L_reg(vecX dst, vecX src, vecX shift) %{ 11029 predicate(n->as_Vector()->length() == 2 && !n->as_ShiftV()->is_var_shift()); 11030 match(Set dst (URShiftVL src shift)); 11031 size(4); 11032 ins_cost(DEFAULT_COST); 11033 expand %{ 11034 vsh2L_reg(dst, src, shift); 11035 %} 11036 %} 11037 11038 instruct vsrl2L_reg_var(vecX dst, vecX src, vecX shift, vecX tmp) %{ 11039 predicate(n->as_Vector()->length() == 2 && n->as_ShiftV()->is_var_shift()); 11040 match(Set dst (URShiftVL src shift)); 11041 effect(TEMP tmp, DEF dst, USE src, USE shift); 11042 size(4*2); 11043 ins_cost(DEFAULT_COST*2); 11044 format %{ 11045 "VNEG.S8 $tmp.Q,$shift.Q\n\t! neg packed16B" 11046 "VSHL.U64 $dst.Q,$src.Q,$tmp.Q\t! logical right shift packed2L" 11047 %} 11048 ins_encode %{ 11049 bool quad = true; 11050 __ vnegI($tmp$$FloatRegister, $shift$$FloatRegister, 11051 MacroAssembler::VELEM_SIZE_8, quad); 11052 __ vshlUI($dst$$FloatRegister, $tmp$$FloatRegister, $src$$FloatRegister, 11053 MacroAssembler::VELEM_SIZE_64, quad); 11054 %} 11055 ins_pipe(ialu_reg_reg); 11056 %} 11057 11058 instruct vsrl2L_immI(vecX dst, vecX src, immI shift) %{ 11059 predicate(n->as_Vector()->length() == 2 && assert_not_var_shift(n)); 11060 match(Set dst (URShiftVL src (RShiftCntV shift))); 11061 size(4); 11062 ins_cost(DEFAULT_COST); // FIXME 11063 format %{ 11064 "VSHR.U64 $dst.Q,$src.Q,$shift\t! logical right shift packed2L" 11065 %} 11066 ins_encode %{ 11067 bool quad = true; 11068 __ vshrUI($dst$$FloatRegister, $src$$FloatRegister, 64, $shift$$constant, 11069 quad); 11070 %} 11071 ins_pipe( ialu_reg_reg ); // FIXME 11072 %} 11073 11074 // ------------------- ArithmeticRightShift ----------------------------------- 11075 11076 // Bytes vector arithmetic left/right shift based on sign 11077 instruct vsha8B_reg(vecD dst, vecD src, vecD shift) %{ 11078 predicate(n->as_Vector()->length() == 8); 11079 effect(DEF dst, USE src, USE shift); 11080 size(4); 11081 ins_cost(DEFAULT_COST); // FIXME 11082 format %{ 11083 "VSHL.S8 $dst.D,$src.D,$shift.D\t! arithmetic right shift packed8B" 11084 %} 11085 ins_encode %{ 11086 bool quad = false; 11087 __ vshlSI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister, 11088 MacroAssembler::VELEM_SIZE_8, quad); 11089 %} 11090 ins_pipe( ialu_reg_reg ); // FIXME 11091 %} 11092 11093 instruct vsha16B_reg(vecX dst, vecX src, vecX shift) %{ 11094 predicate(n->as_Vector()->length() == 16); 11095 effect(DEF dst, USE src, USE shift); 11096 size(4); 11097 ins_cost(DEFAULT_COST); // FIXME 11098 format %{ 11099 "VSHL.S8 $dst.Q,$src.Q,$shift.Q\t! arithmetic right shift packed16B" 11100 %} 11101 ins_encode %{ 11102 bool quad = true; 11103 __ vshlSI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister, 11104 MacroAssembler::VELEM_SIZE_8, quad); 11105 %} 11106 ins_pipe( ialu_reg_reg ); // FIXME 11107 %} 11108 11109 // Shorts vector arithmetic left/right shift based on sign 11110 instruct vsha4S_reg(vecD dst, vecD src, vecD shift) %{ 11111 predicate(n->as_Vector()->length() == 4); 11112 effect(DEF dst, USE src, USE shift); 11113 size(4); 11114 ins_cost(DEFAULT_COST); // FIXME 11115 format %{ 11116 "VSHL.S16 $dst.D,$src.D,$shift.D\t! arithmetic right shift packed4S" 11117 %} 11118 ins_encode %{ 11119 bool quad = false; 11120 __ vshlSI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister, 11121 MacroAssembler::VELEM_SIZE_16, quad); 11122 %} 11123 ins_pipe( ialu_reg_reg ); // FIXME 11124 %} 11125 11126 instruct vsha8S_reg(vecX dst, vecX src, vecX shift) %{ 11127 predicate(n->as_Vector()->length() == 8); 11128 effect(DEF dst, USE src, USE shift); 11129 size(4); 11130 ins_cost(DEFAULT_COST); // FIXME 11131 format %{ 11132 "VSHL.S16 $dst.Q,$src.Q,$shift.Q\t! arithmetic right shift packed8S" 11133 %} 11134 ins_encode %{ 11135 bool quad = true; 11136 __ vshlSI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister, 11137 MacroAssembler::VELEM_SIZE_16, quad); 11138 %} 11139 ins_pipe( ialu_reg_reg ); // FIXME 11140 %} 11141 11142 // Integers vector arithmetic left/right shift based on sign 11143 instruct vsha2I_reg(vecD dst, vecD src, vecD shift) %{ 11144 predicate(n->as_Vector()->length() == 2); 11145 effect(DEF dst, USE src, USE shift); 11146 size(4); 11147 ins_cost(DEFAULT_COST); // FIXME 11148 format %{ 11149 "VSHL.S32 $dst.D,$src.D,$shift.D\t! arithmetic right shift packed2I" 11150 %} 11151 ins_encode %{ 11152 bool quad = false; 11153 __ vshlSI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister, 11154 MacroAssembler::VELEM_SIZE_32, quad); 11155 %} 11156 ins_pipe( ialu_reg_reg ); // FIXME 11157 %} 11158 11159 instruct vsha4I_reg(vecX dst, vecX src, vecX shift) %{ 11160 predicate(n->as_Vector()->length() == 4); 11161 effect(DEF dst, USE src, USE shift); 11162 size(4); 11163 ins_cost(DEFAULT_COST); // FIXME 11164 format %{ 11165 "VSHL.S32 $dst.Q,$src.Q,$shift.Q\t! arithmetic right shift packed4I" 11166 %} 11167 ins_encode %{ 11168 bool quad = true; 11169 __ vshlSI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister, 11170 MacroAssembler::VELEM_SIZE_32, quad); 11171 %} 11172 ins_pipe( ialu_reg_reg ); // FIXME 11173 %} 11174 11175 // Longs vector arithmetic left/right shift based on sign 11176 instruct vsha2L_reg(vecX dst, vecX src, vecX shift) %{ 11177 predicate(n->as_Vector()->length() == 2); 11178 effect(DEF dst, USE src, USE shift); 11179 size(4); 11180 ins_cost(DEFAULT_COST); // FIXME 11181 format %{ 11182 "VSHL.S64 $dst.Q,$src.Q,$shift.Q\t! arithmetic right shift packed2L" 11183 %} 11184 ins_encode %{ 11185 bool quad = true; 11186 __ vshlSI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister, 11187 MacroAssembler::VELEM_SIZE_64, quad); 11188 %} 11189 ins_pipe( ialu_reg_reg ); // FIXME 11190 %} 11191 11192 // Byte vector arithmetic right shift 11193 instruct vsra8B_reg(vecD dst, vecD src, vecD shift) %{ 11194 predicate(n->as_Vector()->length() == 8 && !n->as_ShiftV()->is_var_shift()); 11195 match(Set dst (RShiftVB src shift)); 11196 size(4); 11197 ins_cost(DEFAULT_COST); // FIXME 11198 expand %{ 11199 vsha8B_reg(dst, src, shift); 11200 %} 11201 %} 11202 11203 instruct vsra8B_reg_var(vecD dst, vecD src, vecD shift, vecD tmp) %{ 11204 predicate(n->as_Vector()->length() == 8 && n->as_ShiftV()->is_var_shift()); 11205 match(Set dst (RShiftVB src shift)); 11206 effect(TEMP tmp); 11207 size(4*2); 11208 ins_cost(DEFAULT_COST*2); 11209 format %{ 11210 "VNEG.S8 $tmp.D,$shift.D\n\t! neg packed8B" 11211 "VSHL.S8 $dst.D,$src.D,$tmp.D\t! arithmetic right shift packed8B" 11212 %} 11213 ins_encode %{ 11214 bool quad = false; 11215 __ vnegI($tmp$$FloatRegister, $shift$$FloatRegister, 11216 MacroAssembler::VELEM_SIZE_8, quad); 11217 __ vshlSI($dst$$FloatRegister, $tmp$$FloatRegister, $src$$FloatRegister, 11218 MacroAssembler::VELEM_SIZE_8, quad); 11219 %} 11220 ins_pipe(ialu_reg_reg); 11221 %} 11222 11223 instruct vsra16B_reg(vecX dst, vecX src, vecX shift) %{ 11224 predicate(n->as_Vector()->length() == 16 && !n->as_ShiftV()->is_var_shift()); 11225 match(Set dst (RShiftVB src shift)); 11226 size(4); 11227 ins_cost(DEFAULT_COST); // FIXME 11228 expand %{ 11229 vsha16B_reg(dst, src, shift); 11230 %} 11231 %} 11232 11233 instruct vsra16B_reg_var(vecX dst, vecX src, vecX shift, vecX tmp) %{ 11234 predicate(n->as_Vector()->length() == 16 && n->as_ShiftV()->is_var_shift()); 11235 match(Set dst (RShiftVB src shift)); 11236 effect(TEMP tmp); 11237 size(4*2); 11238 ins_cost(DEFAULT_COST*2); 11239 format %{ 11240 "VNEG.S8 $tmp.Q,$shift.Q\n\t! neg packed16B" 11241 "VSHL.S8 $dst.Q,$src.Q,$tmp.Q\t! arithmetic right shift packed16B" 11242 %} 11243 ins_encode %{ 11244 bool quad = true; 11245 __ vnegI($tmp$$FloatRegister, $shift$$FloatRegister, 11246 MacroAssembler::VELEM_SIZE_8, quad); 11247 __ vshlSI($dst$$FloatRegister, $tmp$$FloatRegister, $src$$FloatRegister, 11248 MacroAssembler::VELEM_SIZE_8, quad); 11249 %} 11250 ins_pipe(ialu_reg_reg); 11251 %} 11252 11253 instruct vsra8B_immI(vecD dst, vecD src, immI shift) %{ 11254 predicate(n->as_Vector()->length() == 8 && assert_not_var_shift(n)); 11255 match(Set dst (RShiftVB src (RShiftCntV shift))); 11256 size(4); 11257 ins_cost(DEFAULT_COST); // FIXME 11258 format %{ 11259 "VSHR.S8 $dst.D,$src.D,$shift\t! arithmetic right shift packed8B" 11260 %} 11261 ins_encode %{ 11262 bool quad = false; 11263 __ vshrSI($dst$$FloatRegister, $src$$FloatRegister, 8, $shift$$constant, 11264 quad); 11265 %} 11266 ins_pipe( ialu_reg_reg ); // FIXME 11267 %} 11268 11269 instruct vsra16B_immI(vecX dst, vecX src, immI shift) %{ 11270 predicate(n->as_Vector()->length() == 16 && assert_not_var_shift(n)); 11271 match(Set dst (RShiftVB src (RShiftCntV shift))); 11272 size(4); 11273 ins_cost(DEFAULT_COST); // FIXME 11274 format %{ 11275 "VSHR.S8 $dst.Q,$src.Q,$shift\t! arithmetic right shift packed16B" 11276 %} 11277 ins_encode %{ 11278 bool quad = true; 11279 __ vshrSI($dst$$FloatRegister, $src$$FloatRegister, 8, $shift$$constant, 11280 quad); 11281 %} 11282 ins_pipe( ialu_reg_reg ); // FIXME 11283 %} 11284 11285 // Shorts vector arithmetic right shift 11286 instruct vsra4S_reg(vecD dst, vecD src, vecD shift) %{ 11287 predicate(n->as_Vector()->length() == 4 && !n->as_ShiftV()->is_var_shift()); 11288 match(Set dst (RShiftVS src shift)); 11289 size(4); 11290 ins_cost(DEFAULT_COST); // FIXME 11291 expand %{ 11292 vsha4S_reg(dst, src, shift); 11293 %} 11294 %} 11295 11296 instruct vsra4S_reg_var(vecD dst, vecD src, vecD shift, vecD tmp) %{ 11297 predicate(n->as_Vector()->length() == 4 && n->as_ShiftV()->is_var_shift()); 11298 match(Set dst (RShiftVS src shift)); 11299 effect(TEMP tmp); 11300 size(4*2); 11301 ins_cost(DEFAULT_COST*2); 11302 format %{ 11303 "VNEG.S8 $tmp.D,$shift.D\n\t! neg packed8B" 11304 "VSHL.S16 $dst.D,$src.D,$tmp.D\t! arithmetic right shift packed4S" 11305 %} 11306 ins_encode %{ 11307 bool quad = false; 11308 __ vnegI($tmp$$FloatRegister, $shift$$FloatRegister, 11309 MacroAssembler::VELEM_SIZE_8, quad); 11310 __ vshlSI($dst$$FloatRegister, $tmp$$FloatRegister, $src$$FloatRegister, 11311 MacroAssembler::VELEM_SIZE_16, quad); 11312 %} 11313 ins_pipe(ialu_reg_reg); 11314 %} 11315 11316 instruct vsra8S_reg(vecX dst, vecX src, vecX shift) %{ 11317 predicate(n->as_Vector()->length() == 8 && !n->as_ShiftV()->is_var_shift()); 11318 match(Set dst (RShiftVS src shift)); 11319 size(4); 11320 ins_cost(DEFAULT_COST); // FIXME 11321 expand %{ 11322 vsha8S_reg(dst, src, shift); 11323 %} 11324 %} 11325 11326 instruct vsra8S_reg_var(vecX dst, vecX src, vecX shift, vecX tmp) %{ 11327 predicate(n->as_Vector()->length() == 8 && n->as_ShiftV()->is_var_shift()); 11328 match(Set dst (RShiftVS src shift)); 11329 effect(TEMP tmp); 11330 size(4*2); 11331 ins_cost(DEFAULT_COST*2); 11332 format %{ 11333 "VNEG.S8 $tmp.Q,$shift.Q\n\t! neg packed16B" 11334 "VSHL.S16 $dst.Q,$src.Q,$tmp.Q\t! arithmetic right shift packed8S" 11335 %} 11336 ins_encode %{ 11337 bool quad = true; 11338 __ vnegI($tmp$$FloatRegister, $shift$$FloatRegister, 11339 MacroAssembler::VELEM_SIZE_8, quad); 11340 __ vshlSI($dst$$FloatRegister, $tmp$$FloatRegister, $src$$FloatRegister, 11341 MacroAssembler::VELEM_SIZE_16, quad); 11342 %} 11343 ins_pipe(ialu_reg_reg); 11344 %} 11345 11346 instruct vsra4S_immI(vecD dst, vecD src, immI shift) %{ 11347 predicate(n->as_Vector()->length() == 4 && assert_not_var_shift(n)); 11348 match(Set dst (RShiftVS src (RShiftCntV shift))); 11349 size(4); 11350 ins_cost(DEFAULT_COST); // FIXME 11351 format %{ 11352 "VSHR.S16 $dst.D,$src.D,$shift\t! arithmetic right shift packed4S" 11353 %} 11354 ins_encode %{ 11355 bool quad = false; 11356 __ vshrSI($dst$$FloatRegister, $src$$FloatRegister, 16, $shift$$constant, 11357 quad); 11358 %} 11359 ins_pipe( ialu_reg_reg ); // FIXME 11360 %} 11361 11362 instruct vsra8S_immI(vecX dst, vecX src, immI shift) %{ 11363 predicate(n->as_Vector()->length() == 8 && assert_not_var_shift(n)); 11364 match(Set dst (RShiftVS src (RShiftCntV shift))); 11365 size(4); 11366 ins_cost(DEFAULT_COST); // FIXME 11367 format %{ 11368 "VSHR.S16 $dst.Q,$src.Q,$shift\t! arithmetic right shift packed8S" 11369 %} 11370 ins_encode %{ 11371 bool quad = true; 11372 __ vshrSI($dst$$FloatRegister, $src$$FloatRegister, 16, $shift$$constant, 11373 quad); 11374 %} 11375 ins_pipe( ialu_reg_reg ); // FIXME 11376 %} 11377 11378 // Integers vector arithmetic right shift 11379 instruct vsra2I_reg(vecD dst, vecD src, vecD shift) %{ 11380 predicate(n->as_Vector()->length() == 2 && !n->as_ShiftV()->is_var_shift()); 11381 match(Set dst (RShiftVI src shift)); 11382 size(4); 11383 ins_cost(DEFAULT_COST); // FIXME 11384 expand %{ 11385 vsha2I_reg(dst, src, shift); 11386 %} 11387 %} 11388 11389 instruct vsra2I_reg_var(vecD dst, vecD src, vecD shift, vecD tmp) %{ 11390 predicate(n->as_Vector()->length() == 2 && n->as_ShiftV()->is_var_shift()); 11391 match(Set dst (RShiftVI src shift)); 11392 effect(TEMP tmp); 11393 size(4*2); 11394 ins_cost(DEFAULT_COST*2); 11395 format %{ 11396 "VNEG.S8 $tmp.D,$shift.D\n\t! neg packed8B" 11397 "VSHL.S32 $dst.D,$src.D,$tmp.D\t! arithmetic right shift packed2I" 11398 %} 11399 ins_encode %{ 11400 bool quad = false; 11401 __ vnegI($tmp$$FloatRegister, $shift$$FloatRegister, 11402 MacroAssembler::VELEM_SIZE_8, quad); 11403 __ vshlSI($dst$$FloatRegister, $tmp$$FloatRegister, $src$$FloatRegister, 11404 MacroAssembler::VELEM_SIZE_32, quad); 11405 %} 11406 ins_pipe(ialu_reg_reg); 11407 %} 11408 11409 instruct vsra4I_reg(vecX dst, vecX src, vecX shift) %{ 11410 predicate(n->as_Vector()->length() == 4 && !n->as_ShiftV()->is_var_shift()); 11411 match(Set dst (RShiftVI src shift)); 11412 size(4); 11413 ins_cost(DEFAULT_COST); // FIXME 11414 expand %{ 11415 vsha4I_reg(dst, src, shift); 11416 %} 11417 %} 11418 11419 instruct vsra4I_reg_var(vecX dst, vecX src, vecX shift, vecX tmp) %{ 11420 predicate(n->as_Vector()->length() == 4 && n->as_ShiftV()->is_var_shift()); 11421 match(Set dst (RShiftVI src shift)); 11422 effect(TEMP tmp); 11423 size(4*2); 11424 ins_cost(DEFAULT_COST*2); 11425 format %{ 11426 "VNEG.S8 $tmp.Q,$shift.Q\n\t! neg packed16B" 11427 "VSHL.S32 $dst.Q,$src.Q,$tmp.Q\t! arithmetic right shift packed4I" 11428 %} 11429 ins_encode %{ 11430 bool quad = true; 11431 __ vnegI($tmp$$FloatRegister, $shift$$FloatRegister, 11432 MacroAssembler::VELEM_SIZE_8, quad); 11433 __ vshlSI($dst$$FloatRegister, $tmp$$FloatRegister, $src$$FloatRegister, 11434 MacroAssembler::VELEM_SIZE_32, quad); 11435 %} 11436 ins_pipe(ialu_reg_reg); 11437 %} 11438 11439 instruct vsra2I_immI(vecD dst, vecD src, immI shift) %{ 11440 predicate(n->as_Vector()->length() == 2 && assert_not_var_shift(n)); 11441 match(Set dst (RShiftVI src (RShiftCntV shift))); 11442 size(4); 11443 ins_cost(DEFAULT_COST); // FIXME 11444 format %{ 11445 "VSHR.S32 $dst.D,$src.D,$shift\t! arithmetic right shift packed2I" 11446 %} 11447 ins_encode %{ 11448 bool quad = false; 11449 __ vshrSI($dst$$FloatRegister, $src$$FloatRegister, 32, $shift$$constant, 11450 quad); 11451 %} 11452 ins_pipe( ialu_reg_reg ); // FIXME 11453 %} 11454 11455 instruct vsra4I_immI(vecX dst, vecX src, immI shift) %{ 11456 predicate(n->as_Vector()->length() == 4 && assert_not_var_shift(n)); 11457 match(Set dst (RShiftVI src (RShiftCntV shift))); 11458 size(4); 11459 ins_cost(DEFAULT_COST); // FIXME 11460 format %{ 11461 "VSHR.S32 $dst.Q,$src.Q,$shift\t! arithmetic right shift packed4I" 11462 %} 11463 ins_encode %{ 11464 bool quad = true; 11465 __ vshrSI($dst$$FloatRegister, $src$$FloatRegister, 32, $shift$$constant, 11466 quad); 11467 %} 11468 ins_pipe( ialu_reg_reg ); // FIXME 11469 %} 11470 11471 // Longs vector arithmetic right shift 11472 instruct vsra2L_reg(vecX dst, vecX src, vecX shift) %{ 11473 predicate(n->as_Vector()->length() == 2 && !n->as_ShiftV()->is_var_shift()); 11474 match(Set dst (RShiftVL src shift)); 11475 size(4); 11476 ins_cost(DEFAULT_COST); // FIXME 11477 expand %{ 11478 vsha2L_reg(dst, src, shift); 11479 %} 11480 %} 11481 11482 instruct vsra2L_reg_var(vecX dst, vecX src, vecX shift, vecX tmp) %{ 11483 predicate(n->as_Vector()->length() == 2 && n->as_ShiftV()->is_var_shift()); 11484 match(Set dst (RShiftVL src shift)); 11485 effect(TEMP tmp); 11486 size(4*2); 11487 ins_cost(DEFAULT_COST*2); 11488 format %{ 11489 "VNEG.S8 $tmp.Q,$shift.Q\n\t! neg packed16B" 11490 "VSHL.S64 $dst.Q,$src.Q,$tmp.Q\t! arithmetic right shift packed2L" 11491 %} 11492 ins_encode %{ 11493 bool quad = true; 11494 __ vnegI($tmp$$FloatRegister, $shift$$FloatRegister, 11495 MacroAssembler::VELEM_SIZE_8, quad); 11496 __ vshlSI($dst$$FloatRegister, $tmp$$FloatRegister, $src$$FloatRegister, 11497 MacroAssembler::VELEM_SIZE_64, quad); 11498 %} 11499 ins_pipe(ialu_reg_reg); 11500 %} 11501 11502 instruct vsra2L_immI(vecX dst, vecX src, immI shift) %{ 11503 predicate(n->as_Vector()->length() == 2 && assert_not_var_shift(n)); 11504 match(Set dst (RShiftVL src (RShiftCntV shift))); 11505 size(4); 11506 ins_cost(DEFAULT_COST); // FIXME 11507 format %{ 11508 "VSHR.S64 $dst.Q,$src.Q,$shift\t! arithmetic right shift packed2L" 11509 %} 11510 ins_encode %{ 11511 bool quad = true; 11512 __ vshrSI($dst$$FloatRegister, $src$$FloatRegister, 64, $shift$$constant, 11513 quad); 11514 %} 11515 ins_pipe( ialu_reg_reg ); // FIXME 11516 %} 11517 11518 // --------------------------------- AND -------------------------------------- 11519 11520 instruct vandD(vecD dst, vecD src1, vecD src2) %{ 11521 predicate(n->as_Vector()->length_in_bytes() == 8); 11522 match(Set dst (AndV src1 src2)); 11523 format %{ "VAND $dst.D,$src1.D,$src2.D\t! and vectors (8 bytes)" %} 11524 ins_encode %{ 11525 bool quad = false; 11526 __ vandI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 11527 quad); 11528 %} 11529 ins_pipe( ialu_reg_reg ); // FIXME 11530 %} 11531 11532 instruct vandX(vecX dst, vecX src1, vecX src2) %{ 11533 predicate(n->as_Vector()->length_in_bytes() == 16); 11534 match(Set dst (AndV src1 src2)); 11535 format %{ "VAND $dst.Q,$src1.Q,$src2.Q\t! and vectors (16 bytes)" %} 11536 ins_encode %{ 11537 bool quad = true; 11538 __ vandI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 11539 quad); 11540 %} 11541 ins_pipe( ialu_reg_reg ); // FIXME 11542 %} 11543 11544 // --------------------------------- OR --------------------------------------- 11545 11546 instruct vorD(vecD dst, vecD src1, vecD src2) %{ 11547 predicate(n->as_Vector()->length_in_bytes() == 8); 11548 match(Set dst (OrV src1 src2)); 11549 format %{ "VOR $dst.D,$src1.D,$src2.D\t! and vectors (8 bytes)" %} 11550 ins_encode %{ 11551 bool quad = false; 11552 __ vorI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 11553 quad); 11554 %} 11555 ins_pipe( ialu_reg_reg ); // FIXME 11556 %} 11557 11558 instruct vorX(vecX dst, vecX src1, vecX src2) %{ 11559 predicate(n->as_Vector()->length_in_bytes() == 16); 11560 match(Set dst (OrV src1 src2)); 11561 format %{ "VOR $dst.Q,$src1.Q,$src2.Q\t! and vectors (16 bytes)" %} 11562 ins_encode %{ 11563 bool quad = true; 11564 __ vorI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 11565 quad); 11566 %} 11567 ins_pipe( ialu_reg_reg ); // FIXME 11568 %} 11569 11570 // --------------------------------- XOR -------------------------------------- 11571 11572 instruct vxorD(vecD dst, vecD src1, vecD src2) %{ 11573 predicate(n->as_Vector()->length_in_bytes() == 8); 11574 match(Set dst (XorV src1 src2)); 11575 format %{ "VXOR $dst.D,$src1.D,$src2.D\t! and vectors (8 bytes)" %} 11576 ins_encode %{ 11577 bool quad = false; 11578 __ vxorI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 11579 quad); 11580 %} 11581 ins_pipe( ialu_reg_reg ); // FIXME 11582 %} 11583 11584 instruct vxorX(vecX dst, vecX src1, vecX src2) %{ 11585 predicate(n->as_Vector()->length_in_bytes() == 16); 11586 match(Set dst (XorV src1 src2)); 11587 format %{ "VXOR $dst.Q,$src1.Q,$src2.Q\t! and vectors (16 bytes)" %} 11588 ins_encode %{ 11589 bool quad = true; 11590 __ vxorI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 11591 quad); 11592 %} 11593 ins_pipe( ialu_reg_reg ); // FIXME 11594 %} 11595 11596 11597 //----------PEEPHOLE RULES----------------------------------------------------- 11598 // These must follow all instruction definitions as they use the names 11599 // defined in the instructions definitions. 11600 // 11601 // peepmatch ( root_instr_name [preceding_instruction]* ); 11602 // 11603 // peepconstraint %{ 11604 // (instruction_number.operand_name relational_op instruction_number.operand_name 11605 // [, ...] ); 11606 // // instruction numbers are zero-based using left to right order in peepmatch 11607 // 11608 // peepreplace ( instr_name ( [instruction_number.operand_name]* ) ); 11609 // // provide an instruction_number.operand_name for each operand that appears 11610 // // in the replacement instruction's match rule 11611 // 11612 // ---------VM FLAGS--------------------------------------------------------- 11613 // 11614 // All peephole optimizations can be turned off using -XX:-OptoPeephole 11615 // 11616 // Each peephole rule is given an identifying number starting with zero and 11617 // increasing by one in the order seen by the parser. An individual peephole 11618 // can be enabled, and all others disabled, by using -XX:OptoPeepholeAt=# 11619 // on the command-line. 11620 // 11621 // ---------CURRENT LIMITATIONS---------------------------------------------- 11622 // 11623 // Only match adjacent instructions in same basic block 11624 // Only equality constraints 11625 // Only constraints between operands, not (0.dest_reg == EAX_enc) 11626 // Only one replacement instruction 11627 // 11628 // ---------EXAMPLE---------------------------------------------------------- 11629 // 11630 // // pertinent parts of existing instructions in architecture description 11631 // instruct movI(eRegI dst, eRegI src) %{ 11632 // match(Set dst (CopyI src)); 11633 // %} 11634 // 11635 // instruct incI_eReg(eRegI dst, immI1 src, eFlagsReg cr) %{ 11636 // match(Set dst (AddI dst src)); 11637 // effect(KILL cr); 11638 // %} 11639 // 11640 // // Change (inc mov) to lea 11641 // peephole %{ 11642 // // increment preceded by register-register move 11643 // peepmatch ( incI_eReg movI ); 11644 // // require that the destination register of the increment 11645 // // match the destination register of the move 11646 // peepconstraint ( 0.dst == 1.dst ); 11647 // // construct a replacement instruction that sets 11648 // // the destination to ( move's source register + one ) 11649 // peepreplace ( incI_eReg_immI1( 0.dst 1.src 0.src ) ); 11650 // %} 11651 // 11652 11653 // // Change load of spilled value to only a spill 11654 // instruct storeI(memory mem, eRegI src) %{ 11655 // match(Set mem (StoreI mem src)); 11656 // %} 11657 // 11658 // instruct loadI(eRegI dst, memory mem) %{ 11659 // match(Set dst (LoadI mem)); 11660 // %} 11661 // 11662 // peephole %{ 11663 // peepmatch ( loadI storeI ); 11664 // peepconstraint ( 1.src == 0.dst, 1.mem == 0.mem ); 11665 // peepreplace ( storeI( 1.mem 1.mem 1.src ) ); 11666 // %} 11667 11668 //----------SMARTSPILL RULES--------------------------------------------------- 11669 // These must follow all instruction definitions as they use the names 11670 // defined in the instructions definitions. 11671 // 11672 // ARM will probably not have any of these rules due to RISC instruction set. 11673 11674 //----------PIPELINE----------------------------------------------------------- 11675 // Rules which define the behavior of the target architectures pipeline.