1 // 2 // Copyright (c) 2008, 2015, 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 // Does destination need to be loaded in a register then passed to a 63 // branch instruction? 64 extern bool maybe_far_call(const CallNode *n); 65 extern bool maybe_far_call(const MachCallNode *n); 66 static inline bool cache_reachable() { 67 return MacroAssembler::_cache_fully_reachable(); 68 } 69 70 #ifdef AARCH64 71 #define ldr_32 ldr_w 72 #define str_32 str_w 73 #else 74 #define ldr_32 ldr 75 #define str_32 str 76 #define tst_32 tst 77 #define teq_32 teq 78 #endif 79 #if 1 80 extern bool PrintOptoAssembly; 81 #endif 82 83 class c2 { 84 public: 85 static OptoRegPair return_value(int ideal_reg); 86 }; 87 88 class CallStubImpl { 89 90 //-------------------------------------------------------------- 91 //---< Used for optimization in Compile::Shorten_branches >--- 92 //-------------------------------------------------------------- 93 94 public: 95 // Size of call trampoline stub. 96 static uint size_call_trampoline() { 97 return 0; // no call trampolines on this platform 98 } 99 100 // number of relocations needed by a call trampoline stub 101 static uint reloc_call_trampoline() { 102 return 0; // no call trampolines on this platform 103 } 104 }; 105 106 class HandlerImpl { 107 108 public: 109 110 static int emit_exception_handler(CodeBuffer &cbuf); 111 static int emit_deopt_handler(CodeBuffer& cbuf); 112 113 static uint size_exception_handler() { 114 #ifdef AARCH64 115 // ldr_literal; br; (pad); <literal> 116 return 3 * Assembler::InstructionSize + wordSize; 117 #else 118 return ( 3 * 4 ); 119 #endif 120 } 121 122 123 static uint size_deopt_handler() { 124 return ( 9 * 4 ); 125 } 126 127 }; 128 129 %} 130 131 source %{ 132 #define __ _masm. 133 134 static FloatRegister reg_to_FloatRegister_object(int register_encoding); 135 static Register reg_to_register_object(int register_encoding); 136 137 138 // **************************************************************************** 139 140 // REQUIRED FUNCTIONALITY 141 142 // Indicate if the safepoint node needs the polling page as an input. 143 // Since ARM does not have absolute addressing, it does. 144 bool SafePointNode::needs_polling_address_input() { 145 return true; 146 } 147 148 // emit an interrupt that is caught by the debugger (for debugging compiler) 149 void emit_break(CodeBuffer &cbuf) { 150 MacroAssembler _masm(&cbuf); 151 __ breakpoint(); 152 } 153 154 #ifndef PRODUCT 155 void MachBreakpointNode::format( PhaseRegAlloc *, outputStream *st ) const { 156 st->print("TA"); 157 } 158 #endif 159 160 void MachBreakpointNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { 161 emit_break(cbuf); 162 } 163 164 uint MachBreakpointNode::size(PhaseRegAlloc *ra_) const { 165 return MachNode::size(ra_); 166 } 167 168 169 void emit_nop(CodeBuffer &cbuf) { 170 MacroAssembler _masm(&cbuf); 171 __ nop(); 172 } 173 174 175 void emit_call_reloc(CodeBuffer &cbuf, const MachCallNode *n, MachOper *m, RelocationHolder const& rspec) { 176 int ret_addr_offset0 = n->as_MachCall()->ret_addr_offset(); 177 int call_site_offset = cbuf.insts()->mark_off(); 178 MacroAssembler _masm(&cbuf); 179 __ set_inst_mark(); // needed in emit_to_interp_stub() to locate the call 180 address target = (address)m->method(); 181 assert(n->as_MachCall()->entry_point() == target, "sanity"); 182 assert(maybe_far_call(n) == !__ reachable_from_cache(target), "sanity"); 183 assert(cache_reachable() == __ cache_fully_reachable(), "sanity"); 184 185 assert(target != NULL, "need real address"); 186 187 int ret_addr_offset = -1; 188 if (rspec.type() == relocInfo::runtime_call_type) { 189 __ call(target, rspec); 190 ret_addr_offset = __ offset(); 191 } else { 192 // scratches Rtemp 193 ret_addr_offset = __ patchable_call(target, rspec, true); 194 } 195 assert(ret_addr_offset - call_site_offset == ret_addr_offset0, "fix ret_addr_offset()"); 196 } 197 198 //============================================================================= 199 // REQUIRED FUNCTIONALITY for encoding 200 void emit_lo(CodeBuffer &cbuf, int val) { } 201 void emit_hi(CodeBuffer &cbuf, int val) { } 202 203 204 //============================================================================= 205 const RegMask& MachConstantBaseNode::_out_RegMask = PTR_REG_mask(); 206 207 int Compile::ConstantTable::calculate_table_base_offset() const { 208 #ifdef AARCH64 209 return 0; 210 #else 211 int offset = -(size() / 2); 212 // flds, fldd: 8-bit offset multiplied by 4: +/- 1024 213 // ldr, ldrb : 12-bit offset: +/- 4096 214 if (!Assembler::is_simm10(offset)) { 215 offset = Assembler::min_simm10(); 216 } 217 return offset; 218 #endif 219 } 220 221 bool MachConstantBaseNode::requires_postalloc_expand() const { return false; } 222 void MachConstantBaseNode::postalloc_expand(GrowableArray <Node *> *nodes, PhaseRegAlloc *ra_) { 223 ShouldNotReachHere(); 224 } 225 226 void MachConstantBaseNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const { 227 Compile* C = ra_->C; 228 Compile::ConstantTable& constant_table = C->constant_table(); 229 MacroAssembler _masm(&cbuf); 230 231 Register r = as_Register(ra_->get_encode(this)); 232 CodeSection* consts_section = __ code()->consts(); 233 int consts_size = consts_section->align_at_start(consts_section->size()); 234 assert(constant_table.size() == consts_size, "must be: %d == %d", constant_table.size(), consts_size); 235 236 // Materialize the constant table base. 237 address baseaddr = consts_section->start() + -(constant_table.table_base_offset()); 238 RelocationHolder rspec = internal_word_Relocation::spec(baseaddr); 239 __ mov_address(r, baseaddr, rspec); 240 } 241 242 uint MachConstantBaseNode::size(PhaseRegAlloc*) const { 243 #ifdef AARCH64 244 return 5 * Assembler::InstructionSize; 245 #else 246 return 8; 247 #endif 248 } 249 250 #ifndef PRODUCT 251 void MachConstantBaseNode::format(PhaseRegAlloc* ra_, outputStream* st) const { 252 char reg[128]; 253 ra_->dump_register(this, reg); 254 st->print("MOV_SLOW &constanttable,%s\t! constant table base", reg); 255 } 256 #endif 257 258 #ifndef PRODUCT 259 void MachPrologNode::format( PhaseRegAlloc *ra_, outputStream *st ) const { 260 Compile* C = ra_->C; 261 262 for (int i = 0; i < OptoPrologueNops; i++) { 263 st->print_cr("NOP"); st->print("\t"); 264 } 265 #ifdef AARCH64 266 if (OptoPrologueNops <= 0) { 267 st->print_cr("NOP\t! required for safe patching"); 268 st->print("\t"); 269 } 270 #endif 271 272 size_t framesize = C->frame_size_in_bytes(); 273 assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned"); 274 int bangsize = C->bang_size_in_bytes(); 275 // Remove two words for return addr and rbp, 276 framesize -= 2*wordSize; 277 bangsize -= 2*wordSize; 278 279 // Calls to C2R adapters often do not accept exceptional returns. 280 // We require that their callers must bang for them. But be careful, because 281 // some VM calls (such as call site linkage) can use several kilobytes of 282 // stack. But the stack safety zone should account for that. 283 // See bugs 4446381, 4468289, 4497237. 284 if (C->need_stack_bang(bangsize)) { 285 st->print_cr("! stack bang (%d bytes)", bangsize); st->print("\t"); 286 } 287 st->print_cr("PUSH R_FP|R_LR_LR"); st->print("\t"); 288 if (framesize != 0) { 289 st->print ("SUB R_SP, R_SP, " SIZE_FORMAT,framesize); 290 } 291 } 292 #endif 293 294 void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { 295 Compile* C = ra_->C; 296 MacroAssembler _masm(&cbuf); 297 298 for (int i = 0; i < OptoPrologueNops; i++) { 299 __ nop(); 300 } 301 #ifdef AARCH64 302 if (OptoPrologueNops <= 0) { 303 __ nop(); // required for safe patching by patch_verified_entry() 304 } 305 #endif 306 307 size_t framesize = C->frame_size_in_bytes(); 308 assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned"); 309 int bangsize = C->bang_size_in_bytes(); 310 // Remove two words for return addr and fp, 311 framesize -= 2*wordSize; 312 bangsize -= 2*wordSize; 313 314 // Calls to C2R adapters often do not accept exceptional returns. 315 // We require that their callers must bang for them. But be careful, because 316 // some VM calls (such as call site linkage) can use several kilobytes of 317 // stack. But the stack safety zone should account for that. 318 // See bugs 4446381, 4468289, 4497237. 319 if (C->need_stack_bang(bangsize)) { 320 __ arm_stack_overflow_check(bangsize, Rtemp); 321 } 322 323 __ raw_push(FP, LR); 324 if (framesize != 0) { 325 __ sub_slow(SP, SP, framesize); 326 } 327 328 // offset from scratch buffer is not valid 329 if (strcmp(cbuf.name(), "Compile::Fill_buffer") == 0) { 330 C->set_frame_complete( __ offset() ); 331 } 332 333 if (C->has_mach_constant_base_node()) { 334 // NOTE: We set the table base offset here because users might be 335 // emitted before MachConstantBaseNode. 336 Compile::ConstantTable& constant_table = C->constant_table(); 337 constant_table.set_table_base_offset(constant_table.calculate_table_base_offset()); 338 } 339 } 340 341 uint MachPrologNode::size(PhaseRegAlloc *ra_) const { 342 return MachNode::size(ra_); 343 } 344 345 int MachPrologNode::reloc() const { 346 return 10; // a large enough number 347 } 348 349 //============================================================================= 350 #ifndef PRODUCT 351 void MachEpilogNode::format( PhaseRegAlloc *ra_, outputStream *st ) const { 352 Compile* C = ra_->C; 353 354 size_t framesize = C->frame_size_in_bytes(); 355 framesize -= 2*wordSize; 356 357 if (framesize != 0) { 358 st->print("ADD R_SP, R_SP, " SIZE_FORMAT "\n\t",framesize); 359 } 360 st->print("POP R_FP|R_LR_LR"); 361 362 if (do_polling() && ra_->C->is_method_compilation()) { 363 st->print("\n\t"); 364 #ifdef AARCH64 365 if (MacroAssembler::page_reachable_from_cache(os::get_polling_page())) { 366 st->print("ADRP Rtemp, #PollAddr\t! Load Polling address\n\t"); 367 st->print("LDR ZR,[Rtemp + #PollAddr & 0xfff]\t!Poll for Safepointing"); 368 } else { 369 st->print("mov_slow Rtemp, #PollAddr\t! Load Polling address\n\t"); 370 st->print("LDR ZR,[Rtemp]\t!Poll for Safepointing"); 371 } 372 #else 373 st->print("MOV Rtemp, #PollAddr\t! Load Polling address\n\t"); 374 st->print("LDR Rtemp,[Rtemp]\t!Poll for Safepointing"); 375 #endif 376 } 377 } 378 #endif 379 380 void MachEpilogNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { 381 MacroAssembler _masm(&cbuf); 382 Compile* C = ra_->C; 383 384 size_t framesize = C->frame_size_in_bytes(); 385 framesize -= 2*wordSize; 386 if (framesize != 0) { 387 __ add_slow(SP, SP, framesize); 388 } 389 __ raw_pop(FP, LR); 390 391 // If this does safepoint polling, then do it here 392 if (do_polling() && ra_->C->is_method_compilation()) { 393 #ifdef AARCH64 394 if (false && MacroAssembler::page_reachable_from_cache(os::get_polling_page())) { 395 /* FIXME: TODO 396 __ relocate(relocInfo::xxx); 397 __ adrp(Rtemp, (intptr_t)os::get_polling_page()); 398 __ relocate(relocInfo::poll_return_type); 399 int offset = os::get_polling_page() & 0xfff; 400 __ ldr(ZR, Address(Rtemp + offset)); 401 */ 402 } else { 403 __ mov_address(Rtemp, (address)os::get_polling_page(), symbolic_Relocation::polling_page_reference); 404 __ relocate(relocInfo::poll_return_type); 405 __ ldr(ZR, Address(Rtemp)); 406 } 407 #else 408 // mov_slow here is usually one or two instruction 409 __ mov_address(Rtemp, (address)os::get_polling_page(), symbolic_Relocation::polling_page_reference); 410 __ relocate(relocInfo::poll_return_type); 411 __ ldr(Rtemp, Address(Rtemp)); 412 #endif 413 } 414 } 415 416 uint MachEpilogNode::size(PhaseRegAlloc *ra_) const { 417 #ifdef AARCH64 418 // allow for added alignment nop from mov_address bind_literal 419 return MachNode::size(ra_) + 1 * Assembler::InstructionSize; 420 #else 421 return MachNode::size(ra_); 422 #endif 423 } 424 425 int MachEpilogNode::reloc() const { 426 return 16; // a large enough number 427 } 428 429 const Pipeline * MachEpilogNode::pipeline() const { 430 return MachNode::pipeline_class(); 431 } 432 433 int MachEpilogNode::safepoint_offset() const { 434 assert( do_polling(), "no return for this epilog node"); 435 // return MacroAssembler::size_of_sethi(os::get_polling_page()); 436 Unimplemented(); 437 return 0; 438 } 439 440 //============================================================================= 441 442 // Figure out which register class each belongs in: rc_int, rc_float, rc_stack 443 enum RC { rc_bad, rc_int, rc_float, rc_stack }; 444 static enum RC rc_class( OptoReg::Name reg ) { 445 if (!OptoReg::is_valid(reg)) return rc_bad; 446 if (OptoReg::is_stack(reg)) return rc_stack; 447 VMReg r = OptoReg::as_VMReg(reg); 448 if (r->is_Register()) return rc_int; 449 assert(r->is_FloatRegister(), "must be"); 450 return rc_float; 451 } 452 453 static inline bool is_iRegLd_memhd(OptoReg::Name src_first, OptoReg::Name src_second, int offset) { 454 #ifdef AARCH64 455 return is_memoryHD(offset); 456 #else 457 int rlo = Matcher::_regEncode[src_first]; 458 int rhi = Matcher::_regEncode[src_second]; 459 if (!((rlo&1)==0 && (rlo+1 == rhi))) { 460 tty->print_cr("CAUGHT BAD LDRD/STRD"); 461 } 462 return (rlo&1)==0 && (rlo+1 == rhi) && is_memoryHD(offset); 463 #endif 464 } 465 466 uint MachSpillCopyNode::implementation( CodeBuffer *cbuf, 467 PhaseRegAlloc *ra_, 468 bool do_size, 469 outputStream* st ) const { 470 // Get registers to move 471 OptoReg::Name src_second = ra_->get_reg_second(in(1)); 472 OptoReg::Name src_first = ra_->get_reg_first(in(1)); 473 OptoReg::Name dst_second = ra_->get_reg_second(this ); 474 OptoReg::Name dst_first = ra_->get_reg_first(this ); 475 476 enum RC src_second_rc = rc_class(src_second); 477 enum RC src_first_rc = rc_class(src_first); 478 enum RC dst_second_rc = rc_class(dst_second); 479 enum RC dst_first_rc = rc_class(dst_first); 480 481 assert( OptoReg::is_valid(src_first) && OptoReg::is_valid(dst_first), "must move at least 1 register" ); 482 483 // Generate spill code! 484 int size = 0; 485 486 if (src_first == dst_first && src_second == dst_second) 487 return size; // Self copy, no move 488 489 #ifdef TODO 490 if (bottom_type()->isa_vect() != NULL) { 491 } 492 #endif 493 494 // Shared code does not expect instruction set capability based bailouts here. 495 // Handle offset unreachable bailout with minimal change in shared code. 496 // Bailout only for real instruction emit. 497 // This requires a single comment change in shared code. ( see output.cpp "Normal" instruction case ) 498 499 MacroAssembler _masm(cbuf); 500 501 // -------------------------------------- 502 // Check for mem-mem move. Load into unused float registers and fall into 503 // the float-store case. 504 if (src_first_rc == rc_stack && dst_first_rc == rc_stack) { 505 int offset = ra_->reg2offset(src_first); 506 if (cbuf && !is_memoryfp(offset)) { 507 ra_->C->record_method_not_compilable("unable to handle large constant offsets"); 508 return 0; 509 } else { 510 if (src_second_rc != rc_bad) { 511 assert((src_first&1)==0 && src_first+1 == src_second, "pair of registers must be aligned/contiguous"); 512 src_first = OptoReg::Name(R_mem_copy_lo_num); 513 src_second = OptoReg::Name(R_mem_copy_hi_num); 514 src_first_rc = rc_float; 515 src_second_rc = rc_float; 516 if (cbuf) { 517 __ ldr_double(Rmemcopy, Address(SP, offset)); 518 } else if (!do_size) { 519 st->print(LDR_DOUBLE " R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(src_first),offset); 520 } 521 } else { 522 src_first = OptoReg::Name(R_mem_copy_lo_num); 523 src_first_rc = rc_float; 524 if (cbuf) { 525 __ ldr_float(Rmemcopy, Address(SP, offset)); 526 } else if (!do_size) { 527 st->print(LDR_FLOAT " R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(src_first),offset); 528 } 529 } 530 size += 4; 531 } 532 } 533 534 if (src_second_rc == rc_stack && dst_second_rc == rc_stack) { 535 Unimplemented(); 536 } 537 538 // -------------------------------------- 539 // Check for integer reg-reg copy 540 if (src_first_rc == rc_int && dst_first_rc == rc_int) { 541 // Else normal reg-reg copy 542 assert( src_second != dst_first, "smashed second before evacuating it" ); 543 if (cbuf) { 544 __ mov(reg_to_register_object(Matcher::_regEncode[dst_first]), reg_to_register_object(Matcher::_regEncode[src_first])); 545 #ifndef PRODUCT 546 } else if (!do_size) { 547 st->print("MOV R_%s, R_%s\t# spill", 548 Matcher::regName[dst_first], 549 Matcher::regName[src_first]); 550 #endif 551 } 552 #ifdef AARCH64 553 if (src_first+1 == src_second && dst_first+1 == dst_second) { 554 return size + 4; 555 } 556 #endif 557 size += 4; 558 } 559 560 // Check for integer store 561 if (src_first_rc == rc_int && dst_first_rc == rc_stack) { 562 int offset = ra_->reg2offset(dst_first); 563 if (cbuf && !is_memoryI(offset)) { 564 ra_->C->record_method_not_compilable("unable to handle large constant offsets"); 565 return 0; 566 } else { 567 if (src_second_rc != rc_bad && is_iRegLd_memhd(src_first, src_second, offset)) { 568 assert((src_first&1)==0 && src_first+1 == src_second, "pair of registers must be aligned/contiguous"); 569 if (cbuf) { 570 __ str_64(reg_to_register_object(Matcher::_regEncode[src_first]), Address(SP, offset)); 571 #ifndef PRODUCT 572 } else if (!do_size) { 573 if (size != 0) st->print("\n\t"); 574 st->print(STR_64 " R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(src_first), offset); 575 #endif 576 } 577 return size + 4; 578 } else { 579 if (cbuf) { 580 __ str_32(reg_to_register_object(Matcher::_regEncode[src_first]), Address(SP, offset)); 581 #ifndef PRODUCT 582 } else if (!do_size) { 583 if (size != 0) st->print("\n\t"); 584 st->print(STR_32 " R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(src_first), offset); 585 #endif 586 } 587 } 588 } 589 size += 4; 590 } 591 592 // Check for integer load 593 if (dst_first_rc == rc_int && src_first_rc == rc_stack) { 594 int offset = ra_->reg2offset(src_first); 595 if (cbuf && !is_memoryI(offset)) { 596 ra_->C->record_method_not_compilable("unable to handle large constant offsets"); 597 return 0; 598 } else { 599 if (src_second_rc != rc_bad && is_iRegLd_memhd(dst_first, dst_second, offset)) { 600 assert((src_first&1)==0 && src_first+1 == src_second, "pair of registers must be aligned/contiguous"); 601 if (cbuf) { 602 __ ldr_64(reg_to_register_object(Matcher::_regEncode[dst_first]), Address(SP, offset)); 603 #ifndef PRODUCT 604 } else if (!do_size) { 605 if (size != 0) st->print("\n\t"); 606 st->print(LDR_64 " R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(dst_first), offset); 607 #endif 608 } 609 return size + 4; 610 } else { 611 if (cbuf) { 612 __ ldr_32(reg_to_register_object(Matcher::_regEncode[dst_first]), Address(SP, offset)); 613 #ifndef PRODUCT 614 } else if (!do_size) { 615 if (size != 0) st->print("\n\t"); 616 st->print(LDR_32 " R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(dst_first), offset); 617 #endif 618 } 619 } 620 } 621 size += 4; 622 } 623 624 // Check for float reg-reg copy 625 if (src_first_rc == rc_float && dst_first_rc == rc_float) { 626 if (src_second_rc != rc_bad) { 627 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"); 628 if (cbuf) { 629 __ mov_double(reg_to_FloatRegister_object(Matcher::_regEncode[dst_first]), reg_to_FloatRegister_object(Matcher::_regEncode[src_first])); 630 #ifndef PRODUCT 631 } else if (!do_size) { 632 st->print(MOV_DOUBLE " R_%s, R_%s\t# spill", 633 Matcher::regName[dst_first], 634 Matcher::regName[src_first]); 635 #endif 636 } 637 return 4; 638 } 639 if (cbuf) { 640 __ mov_float(reg_to_FloatRegister_object(Matcher::_regEncode[dst_first]), reg_to_FloatRegister_object(Matcher::_regEncode[src_first])); 641 #ifndef PRODUCT 642 } else if (!do_size) { 643 st->print(MOV_FLOAT " R_%s, R_%s\t# spill", 644 Matcher::regName[dst_first], 645 Matcher::regName[src_first]); 646 #endif 647 } 648 size = 4; 649 } 650 651 // Check for float store 652 if (src_first_rc == rc_float && dst_first_rc == rc_stack) { 653 int offset = ra_->reg2offset(dst_first); 654 if (cbuf && !is_memoryfp(offset)) { 655 ra_->C->record_method_not_compilable("unable to handle large constant offsets"); 656 return 0; 657 } else { 658 // Further check for aligned-adjacent pair, so we can use a double store 659 if (src_second_rc != rc_bad) { 660 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"); 661 if (cbuf) { 662 __ str_double(reg_to_FloatRegister_object(Matcher::_regEncode[src_first]), Address(SP, offset)); 663 #ifndef PRODUCT 664 } else if (!do_size) { 665 if (size != 0) st->print("\n\t"); 666 st->print(STR_DOUBLE " R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(src_first),offset); 667 #endif 668 } 669 return size + 4; 670 } else { 671 if (cbuf) { 672 __ str_float(reg_to_FloatRegister_object(Matcher::_regEncode[src_first]), Address(SP, offset)); 673 #ifndef PRODUCT 674 } else if (!do_size) { 675 if (size != 0) st->print("\n\t"); 676 st->print(STR_FLOAT " R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(src_first),offset); 677 #endif 678 } 679 } 680 } 681 size += 4; 682 } 683 684 // Check for float load 685 if (dst_first_rc == rc_float && src_first_rc == rc_stack) { 686 int offset = ra_->reg2offset(src_first); 687 if (cbuf && !is_memoryfp(offset)) { 688 ra_->C->record_method_not_compilable("unable to handle large constant offsets"); 689 return 0; 690 } else { 691 // Further check for aligned-adjacent pair, so we can use a double store 692 if (src_second_rc != rc_bad) { 693 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"); 694 if (cbuf) { 695 __ ldr_double(reg_to_FloatRegister_object(Matcher::_regEncode[dst_first]), Address(SP, offset)); 696 #ifndef PRODUCT 697 } else if (!do_size) { 698 if (size != 0) st->print("\n\t"); 699 st->print(LDR_DOUBLE " R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(dst_first),offset); 700 #endif 701 } 702 return size + 4; 703 } else { 704 if (cbuf) { 705 __ ldr_float(reg_to_FloatRegister_object(Matcher::_regEncode[dst_first]), Address(SP, offset)); 706 #ifndef PRODUCT 707 } else if (!do_size) { 708 if (size != 0) st->print("\n\t"); 709 st->print(LDR_FLOAT " R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(dst_first),offset); 710 #endif 711 } 712 } 713 } 714 size += 4; 715 } 716 717 // check for int reg -> float reg move 718 if (src_first_rc == rc_int && dst_first_rc == rc_float) { 719 // Further check for aligned-adjacent pair, so we can use a single instruction 720 if (src_second_rc != rc_bad) { 721 assert((dst_first&1)==0 && dst_first+1 == dst_second, "pairs of registers must be aligned/contiguous"); 722 assert((src_first&1)==0 && src_first+1 == src_second, "pairs of registers must be aligned/contiguous"); 723 assert(src_second_rc == rc_int && dst_second_rc == rc_float, "unsupported"); 724 if (cbuf) { 725 #ifdef AARCH64 726 __ fmov_dx(reg_to_FloatRegister_object(Matcher::_regEncode[dst_first]), reg_to_register_object(Matcher::_regEncode[src_first])); 727 #else 728 __ 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])); 729 #endif 730 #ifndef PRODUCT 731 } else if (!do_size) { 732 if (size != 0) st->print("\n\t"); 733 #ifdef AARCH64 734 st->print("FMOV_DX R_%s, R_%s\t! spill",OptoReg::regname(dst_first), OptoReg::regname(src_first)); 735 #else 736 st->print("FMDRR R_%s, R_%s, R_%s\t! spill",OptoReg::regname(dst_first), OptoReg::regname(src_first), OptoReg::regname(src_second)); 737 #endif 738 #endif 739 } 740 return size + 4; 741 } else { 742 if (cbuf) { 743 __ fmsr(reg_to_FloatRegister_object(Matcher::_regEncode[dst_first]), reg_to_register_object(Matcher::_regEncode[src_first])); 744 #ifndef PRODUCT 745 } else if (!do_size) { 746 if (size != 0) st->print("\n\t"); 747 st->print(FMSR " R_%s, R_%s\t! spill",OptoReg::regname(dst_first), OptoReg::regname(src_first)); 748 #endif 749 } 750 size += 4; 751 } 752 } 753 754 // check for float reg -> int reg move 755 if (src_first_rc == rc_float && dst_first_rc == rc_int) { 756 // Further check for aligned-adjacent pair, so we can use a single instruction 757 if (src_second_rc != rc_bad) { 758 assert((src_first&1)==0 && src_first+1 == src_second, "pairs of registers must be aligned/contiguous"); 759 assert((dst_first&1)==0 && dst_first+1 == dst_second, "pairs of registers must be aligned/contiguous"); 760 assert(src_second_rc == rc_float && dst_second_rc == rc_int, "unsupported"); 761 if (cbuf) { 762 #ifdef AARCH64 763 __ fmov_xd(reg_to_register_object(Matcher::_regEncode[dst_first]), reg_to_FloatRegister_object(Matcher::_regEncode[src_first])); 764 #else 765 __ 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])); 766 #endif 767 #ifndef PRODUCT 768 } else if (!do_size) { 769 if (size != 0) st->print("\n\t"); 770 #ifdef AARCH64 771 st->print("FMOV_XD R_%s, R_%s\t! spill",OptoReg::regname(dst_first), OptoReg::regname(src_first)); 772 #else 773 st->print("FMRRD R_%s, R_%s, R_%s\t! spill",OptoReg::regname(dst_first), OptoReg::regname(dst_second), OptoReg::regname(src_first)); 774 #endif 775 #endif 776 } 777 return size + 4; 778 } else { 779 if (cbuf) { 780 __ fmrs(reg_to_register_object(Matcher::_regEncode[dst_first]), reg_to_FloatRegister_object(Matcher::_regEncode[src_first])); 781 #ifndef PRODUCT 782 } else if (!do_size) { 783 if (size != 0) st->print("\n\t"); 784 st->print(FMRS " R_%s, R_%s\t! spill",OptoReg::regname(dst_first), OptoReg::regname(src_first)); 785 #endif 786 } 787 size += 4; 788 } 789 } 790 791 // -------------------------------------------------------------------- 792 // Check for hi bits still needing moving. Only happens for misaligned 793 // arguments to native calls. 794 if (src_second == dst_second) 795 return size; // Self copy; no move 796 assert( src_second_rc != rc_bad && dst_second_rc != rc_bad, "src_second & dst_second cannot be Bad" ); 797 798 #ifndef AARCH64 799 // Check for integer reg-reg copy. Hi bits are stuck up in the top 800 // 32-bits of a 64-bit register, but are needed in low bits of another 801 // register (else it's a hi-bits-to-hi-bits copy which should have 802 // happened already as part of a 64-bit move) 803 if (src_second_rc == rc_int && dst_second_rc == rc_int) { 804 if (cbuf) { 805 __ mov(reg_to_register_object(Matcher::_regEncode[dst_second]), reg_to_register_object(Matcher::_regEncode[src_second])); 806 #ifndef PRODUCT 807 } else if (!do_size) { 808 if (size != 0) st->print("\n\t"); 809 st->print("MOV R_%s, R_%s\t# spill high", 810 Matcher::regName[dst_second], 811 Matcher::regName[src_second]); 812 #endif 813 } 814 return size+4; 815 } 816 817 // Check for high word integer store 818 if (src_second_rc == rc_int && dst_second_rc == rc_stack) { 819 int offset = ra_->reg2offset(dst_second); 820 821 if (cbuf && !is_memoryP(offset)) { 822 ra_->C->record_method_not_compilable("unable to handle large constant offsets"); 823 return 0; 824 } else { 825 if (cbuf) { 826 __ str(reg_to_register_object(Matcher::_regEncode[src_second]), Address(SP, offset)); 827 #ifndef PRODUCT 828 } else if (!do_size) { 829 if (size != 0) st->print("\n\t"); 830 st->print("STR R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(src_second), offset); 831 #endif 832 } 833 } 834 return size + 4; 835 } 836 837 // Check for high word integer load 838 if (dst_second_rc == rc_int && src_second_rc == rc_stack) { 839 int offset = ra_->reg2offset(src_second); 840 if (cbuf && !is_memoryP(offset)) { 841 ra_->C->record_method_not_compilable("unable to handle large constant offsets"); 842 return 0; 843 } else { 844 if (cbuf) { 845 __ ldr(reg_to_register_object(Matcher::_regEncode[dst_second]), Address(SP, offset)); 846 #ifndef PRODUCT 847 } else if (!do_size) { 848 if (size != 0) st->print("\n\t"); 849 st->print("LDR R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(dst_second), offset); 850 #endif 851 } 852 } 853 return size + 4; 854 } 855 #endif 856 857 Unimplemented(); 858 return 0; // Mute compiler 859 } 860 861 #ifndef PRODUCT 862 void MachSpillCopyNode::format( PhaseRegAlloc *ra_, outputStream *st ) const { 863 implementation( NULL, ra_, false, st ); 864 } 865 #endif 866 867 void MachSpillCopyNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { 868 implementation( &cbuf, ra_, false, NULL ); 869 } 870 871 uint MachSpillCopyNode::size(PhaseRegAlloc *ra_) const { 872 return implementation( NULL, ra_, true, NULL ); 873 } 874 875 //============================================================================= 876 #ifndef PRODUCT 877 void MachNopNode::format( PhaseRegAlloc *, outputStream *st ) const { 878 st->print("NOP \t# %d bytes pad for loops and calls", 4 * _count); 879 } 880 #endif 881 882 void MachNopNode::emit(CodeBuffer &cbuf, PhaseRegAlloc * ) const { 883 MacroAssembler _masm(&cbuf); 884 for(int i = 0; i < _count; i += 1) { 885 __ nop(); 886 } 887 } 888 889 uint MachNopNode::size(PhaseRegAlloc *ra_) const { 890 return 4 * _count; 891 } 892 893 894 //============================================================================= 895 #ifndef PRODUCT 896 void BoxLockNode::format( PhaseRegAlloc *ra_, outputStream *st ) const { 897 int offset = ra_->reg2offset(in_RegMask(0).find_first_elem()); 898 int reg = ra_->get_reg_first(this); 899 st->print("ADD %s,R_SP+#%d",Matcher::regName[reg], offset); 900 } 901 #endif 902 903 void BoxLockNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { 904 MacroAssembler _masm(&cbuf); 905 int offset = ra_->reg2offset(in_RegMask(0).find_first_elem()); 906 int reg = ra_->get_encode(this); 907 Register dst = reg_to_register_object(reg); 908 909 if (is_aimm(offset)) { 910 __ add(dst, SP, offset); 911 } else { 912 __ mov_slow(dst, offset); 913 #ifdef AARCH64 914 __ add(dst, SP, dst, ex_lsl); 915 #else 916 __ add(dst, SP, dst); 917 #endif 918 } 919 } 920 921 uint BoxLockNode::size(PhaseRegAlloc *ra_) const { 922 // BoxLockNode is not a MachNode, so we can't just call MachNode::size(ra_) 923 assert(ra_ == ra_->C->regalloc(), "sanity"); 924 return ra_->C->scratch_emit_size(this); 925 } 926 927 //============================================================================= 928 #ifndef PRODUCT 929 #ifdef AARCH64 930 #define R_RTEMP "R_R16" 931 #else 932 #define R_RTEMP "R_R12" 933 #endif 934 void MachUEPNode::format( PhaseRegAlloc *ra_, outputStream *st ) const { 935 st->print_cr("\nUEP:"); 936 if (UseCompressedClassPointers) { 937 st->print_cr("\tLDR_w " R_RTEMP ",[R_R0 + oopDesc::klass_offset_in_bytes]\t! Inline cache check"); 938 st->print_cr("\tdecode_klass " R_RTEMP); 939 } else { 940 st->print_cr("\tLDR " R_RTEMP ",[R_R0 + oopDesc::klass_offset_in_bytes]\t! Inline cache check"); 941 } 942 st->print_cr("\tCMP " R_RTEMP ",R_R8" ); 943 st->print ("\tB.NE SharedRuntime::handle_ic_miss_stub"); 944 } 945 #endif 946 947 void MachUEPNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { 948 MacroAssembler _masm(&cbuf); 949 Register iCache = reg_to_register_object(Matcher::inline_cache_reg_encode()); 950 assert(iCache == Ricklass, "should be"); 951 Register receiver = R0; 952 953 __ load_klass(Rtemp, receiver); 954 __ cmp(Rtemp, iCache); 955 #ifdef AARCH64 956 Label match; 957 __ b(match, eq); 958 __ jump(SharedRuntime::get_ic_miss_stub(), relocInfo::runtime_call_type, Rtemp); 959 __ bind(match); 960 #else 961 __ jump(SharedRuntime::get_ic_miss_stub(), relocInfo::runtime_call_type, noreg, ne); 962 #endif 963 } 964 965 uint MachUEPNode::size(PhaseRegAlloc *ra_) const { 966 return MachNode::size(ra_); 967 } 968 969 970 //============================================================================= 971 972 // Emit exception handler code. 973 int HandlerImpl::emit_exception_handler(CodeBuffer& cbuf) { 974 MacroAssembler _masm(&cbuf); 975 976 address base = __ start_a_stub(size_exception_handler()); 977 if (base == NULL) { 978 ciEnv::current()->record_failure("CodeCache is full"); 979 return 0; // CodeBuffer::expand failed 980 } 981 982 int offset = __ offset(); 983 984 // OK to trash LR, because exception blob will kill it 985 __ jump(OptoRuntime::exception_blob()->entry_point(), relocInfo::runtime_call_type, LR_tmp); 986 987 assert(__ offset() - offset <= (int) size_exception_handler(), "overflow"); 988 989 __ end_a_stub(); 990 991 return offset; 992 } 993 994 int HandlerImpl::emit_deopt_handler(CodeBuffer& cbuf) { 995 // Can't use any of the current frame's registers as we may have deopted 996 // at a poll and everything can be live. 997 MacroAssembler _masm(&cbuf); 998 999 address base = __ start_a_stub(size_deopt_handler()); 1000 if (base == NULL) { 1001 ciEnv::current()->record_failure("CodeCache is full"); 1002 return 0; // CodeBuffer::expand failed 1003 } 1004 1005 int offset = __ offset(); 1006 address deopt_pc = __ pc(); 1007 1008 #ifdef AARCH64 1009 // See LR saved by caller in sharedRuntime_arm.cpp 1010 // see also hse1 ws 1011 // see also LIR_Assembler::emit_deopt_handler 1012 1013 __ raw_push(LR, LR); // preserve LR in both slots 1014 __ mov_relative_address(LR, deopt_pc); 1015 __ str(LR, Address(SP, 1 * wordSize)); // save deopt PC 1016 // OK to kill LR, because deopt blob will restore it from SP[0] 1017 __ jump(SharedRuntime::deopt_blob()->unpack(), relocInfo::runtime_call_type, LR_tmp); 1018 #else 1019 __ sub(SP, SP, wordSize); // make room for saved PC 1020 __ push(LR); // save LR that may be live when we get here 1021 __ mov_relative_address(LR, deopt_pc); 1022 __ str(LR, Address(SP, wordSize)); // save deopt PC 1023 __ pop(LR); // restore LR 1024 __ jump(SharedRuntime::deopt_blob()->unpack(), relocInfo::runtime_call_type, noreg); 1025 #endif 1026 1027 assert(__ offset() - offset <= (int) size_deopt_handler(), "overflow"); 1028 1029 __ end_a_stub(); 1030 return offset; 1031 } 1032 1033 const bool Matcher::match_rule_supported(int opcode) { 1034 if (!has_match_rule(opcode)) 1035 return false; 1036 1037 switch (opcode) { 1038 case Op_PopCountI: 1039 case Op_PopCountL: 1040 if (!UsePopCountInstruction) 1041 return false; 1042 break; 1043 case Op_LShiftCntV: 1044 case Op_RShiftCntV: 1045 case Op_AddVB: 1046 case Op_AddVS: 1047 case Op_AddVI: 1048 case Op_AddVL: 1049 case Op_SubVB: 1050 case Op_SubVS: 1051 case Op_SubVI: 1052 case Op_SubVL: 1053 case Op_MulVS: 1054 case Op_MulVI: 1055 case Op_LShiftVB: 1056 case Op_LShiftVS: 1057 case Op_LShiftVI: 1058 case Op_LShiftVL: 1059 case Op_RShiftVB: 1060 case Op_RShiftVS: 1061 case Op_RShiftVI: 1062 case Op_RShiftVL: 1063 case Op_URShiftVB: 1064 case Op_URShiftVS: 1065 case Op_URShiftVI: 1066 case Op_URShiftVL: 1067 case Op_AndV: 1068 case Op_OrV: 1069 case Op_XorV: 1070 return VM_Version::has_simd(); 1071 case Op_LoadVector: 1072 case Op_StoreVector: 1073 case Op_AddVF: 1074 case Op_SubVF: 1075 case Op_MulVF: 1076 #ifdef AARCH64 1077 return VM_Version::has_simd(); 1078 #else 1079 return VM_Version::has_vfp() || VM_Version::has_simd(); 1080 #endif 1081 case Op_AddVD: 1082 case Op_SubVD: 1083 case Op_MulVD: 1084 case Op_DivVF: 1085 case Op_DivVD: 1086 #ifdef AARCH64 1087 return VM_Version::has_simd(); 1088 #else 1089 return VM_Version::has_vfp(); 1090 #endif 1091 } 1092 1093 return true; // Per default match rules are supported. 1094 } 1095 1096 const bool Matcher::match_rule_supported_vector(int opcode, int vlen) { 1097 1098 // TODO 1099 // identify extra cases that we might want to provide match rules for 1100 // e.g. Op_ vector nodes and other intrinsics while guarding with vlen 1101 bool ret_value = match_rule_supported(opcode); 1102 // Add rules here. 1103 1104 return ret_value; // Per default match rules are supported. 1105 } 1106 1107 const bool Matcher::has_predicated_vectors(void) { 1108 return false; 1109 } 1110 1111 const int Matcher::float_pressure(int default_pressure_threshold) { 1112 return default_pressure_threshold; 1113 } 1114 1115 int Matcher::regnum_to_fpu_offset(int regnum) { 1116 return regnum - 32; // The FP registers are in the second chunk 1117 } 1118 1119 // Vector width in bytes 1120 const int Matcher::vector_width_in_bytes(BasicType bt) { 1121 return MaxVectorSize; 1122 } 1123 1124 // Vector ideal reg corresponding to specified size in bytes 1125 const int Matcher::vector_ideal_reg(int size) { 1126 assert(MaxVectorSize >= size, ""); 1127 switch(size) { 1128 case 8: return Op_VecD; 1129 case 16: return Op_VecX; 1130 } 1131 ShouldNotReachHere(); 1132 return 0; 1133 } 1134 1135 const int Matcher::vector_shift_count_ideal_reg(int size) { 1136 return vector_ideal_reg(size); 1137 } 1138 1139 // Limits on vector size (number of elements) loaded into vector. 1140 const int Matcher::max_vector_size(const BasicType bt) { 1141 assert(is_java_primitive(bt), "only primitive type vectors"); 1142 return vector_width_in_bytes(bt)/type2aelembytes(bt); 1143 } 1144 1145 const int Matcher::min_vector_size(const BasicType bt) { 1146 assert(is_java_primitive(bt), "only primitive type vectors"); 1147 return 8/type2aelembytes(bt); 1148 } 1149 1150 // ARM doesn't support misaligned vectors store/load. 1151 const bool Matcher::misaligned_vectors_ok() { 1152 return false; 1153 } 1154 1155 // ARM doesn't support AES intrinsics 1156 const bool Matcher::pass_original_key_for_aes() { 1157 return false; 1158 } 1159 1160 const bool Matcher::convL2FSupported(void) { 1161 #ifdef AARCH64 1162 return true; 1163 #else 1164 return false; 1165 #endif 1166 } 1167 1168 // Is this branch offset short enough that a short branch can be used? 1169 // 1170 // NOTE: If the platform does not provide any short branch variants, then 1171 // this method should return false for offset 0. 1172 bool Matcher::is_short_branch_offset(int rule, int br_size, int offset) { 1173 // The passed offset is relative to address of the branch. 1174 // On ARM a branch displacement is calculated relative to address 1175 // of the branch + 8. 1176 // 1177 // offset -= 8; 1178 // return (Assembler::is_simm24(offset)); 1179 return false; 1180 } 1181 1182 const bool Matcher::isSimpleConstant64(jlong value) { 1183 // Will one (StoreL ConL) be cheaper than two (StoreI ConI)?. 1184 #ifdef AARCH64 1185 return (value == 0); 1186 #else 1187 return false; 1188 #endif 1189 } 1190 1191 // No scaling for the parameter the ClearArray node. 1192 const bool Matcher::init_array_count_is_in_bytes = true; 1193 1194 #ifdef AARCH64 1195 const int Matcher::long_cmove_cost() { return 1; } 1196 #else 1197 // Needs 2 CMOV's for longs. 1198 const int Matcher::long_cmove_cost() { return 2; } 1199 #endif 1200 1201 #ifdef AARCH64 1202 const int Matcher::float_cmove_cost() { return 1; } 1203 #else 1204 // CMOVF/CMOVD are expensive on ARM. 1205 const int Matcher::float_cmove_cost() { return ConditionalMoveLimit; } 1206 #endif 1207 1208 // Does the CPU require late expand (see block.cpp for description of late expand)? 1209 const bool Matcher::require_postalloc_expand = false; 1210 1211 // Do we need to mask the count passed to shift instructions or does 1212 // the cpu only look at the lower 5/6 bits anyway? 1213 // FIXME: does this handle vector shifts as well? 1214 #ifdef AARCH64 1215 const bool Matcher::need_masked_shift_count = false; 1216 #else 1217 const bool Matcher::need_masked_shift_count = true; 1218 #endif 1219 1220 const bool Matcher::convi2l_type_required = true; 1221 1222 // Should the Matcher clone shifts on addressing modes, expecting them 1223 // to be subsumed into complex addressing expressions or compute them 1224 // into registers? 1225 bool Matcher::clone_address_expressions(AddPNode* m, Matcher::MStack& mstack, VectorSet& address_visited) { 1226 return clone_base_plus_offset_address(m, mstack, address_visited); 1227 } 1228 1229 void Compile::reshape_address(AddPNode* addp) { 1230 } 1231 1232 bool Matcher::narrow_oop_use_complex_address() { 1233 NOT_LP64(ShouldNotCallThis()); 1234 assert(UseCompressedOops, "only for compressed oops code"); 1235 return false; 1236 } 1237 1238 bool Matcher::narrow_klass_use_complex_address() { 1239 NOT_LP64(ShouldNotCallThis()); 1240 assert(UseCompressedClassPointers, "only for compressed klass code"); 1241 return false; 1242 } 1243 1244 bool Matcher::const_oop_prefer_decode() { 1245 NOT_LP64(ShouldNotCallThis()); 1246 return true; 1247 } 1248 1249 bool Matcher::const_klass_prefer_decode() { 1250 NOT_LP64(ShouldNotCallThis()); 1251 return true; 1252 } 1253 1254 // Is it better to copy float constants, or load them directly from memory? 1255 // Intel can load a float constant from a direct address, requiring no 1256 // extra registers. Most RISCs will have to materialize an address into a 1257 // register first, so they would do better to copy the constant from stack. 1258 const bool Matcher::rematerialize_float_constants = false; 1259 1260 // If CPU can load and store mis-aligned doubles directly then no fixup is 1261 // needed. Else we split the double into 2 integer pieces and move it 1262 // piece-by-piece. Only happens when passing doubles into C code as the 1263 // Java calling convention forces doubles to be aligned. 1264 #ifdef AARCH64 1265 // On stack replacement support: 1266 // We don't need Load[DL]_unaligned support, because interpreter stack 1267 // has correct alignment 1268 const bool Matcher::misaligned_doubles_ok = true; 1269 #else 1270 const bool Matcher::misaligned_doubles_ok = false; 1271 #endif 1272 1273 // No-op on ARM. 1274 void Matcher::pd_implicit_null_fixup(MachNode *node, uint idx) { 1275 } 1276 1277 // Advertise here if the CPU requires explicit rounding operations 1278 // to implement the UseStrictFP mode. 1279 const bool Matcher::strict_fp_requires_explicit_rounding = false; 1280 1281 // Are floats converted to double when stored to stack during deoptimization? 1282 // ARM does not handle callee-save floats. 1283 bool Matcher::float_in_double() { 1284 return false; 1285 } 1286 1287 // Do ints take an entire long register or just half? 1288 // Note that we if-def off of _LP64. 1289 // The relevant question is how the int is callee-saved. In _LP64 1290 // the whole long is written but de-opt'ing will have to extract 1291 // the relevant 32 bits, in not-_LP64 only the low 32 bits is written. 1292 #ifdef _LP64 1293 const bool Matcher::int_in_long = true; 1294 #else 1295 const bool Matcher::int_in_long = false; 1296 #endif 1297 1298 // Return whether or not this register is ever used as an argument. This 1299 // function is used on startup to build the trampoline stubs in generateOptoStub. 1300 // Registers not mentioned will be killed by the VM call in the trampoline, and 1301 // arguments in those registers not be available to the callee. 1302 bool Matcher::can_be_java_arg( int reg ) { 1303 #ifdef AARCH64 1304 if (reg >= R_R0_num && reg < R_R8_num) return true; 1305 if (reg >= R_V0_num && reg <= R_V7b_num && ((reg & 3) < 2)) return true; 1306 #else 1307 if (reg == R_R0_num || 1308 reg == R_R1_num || 1309 reg == R_R2_num || 1310 reg == R_R3_num) return true; 1311 1312 if (reg >= R_S0_num && 1313 reg <= R_S13_num) return true; 1314 #endif 1315 return false; 1316 } 1317 1318 bool Matcher::is_spillable_arg( int reg ) { 1319 return can_be_java_arg(reg); 1320 } 1321 1322 bool Matcher::use_asm_for_ldiv_by_con( jlong divisor ) { 1323 return false; 1324 } 1325 1326 // Register for DIVI projection of divmodI 1327 RegMask Matcher::divI_proj_mask() { 1328 ShouldNotReachHere(); 1329 return RegMask(); 1330 } 1331 1332 // Register for MODI projection of divmodI 1333 RegMask Matcher::modI_proj_mask() { 1334 ShouldNotReachHere(); 1335 return RegMask(); 1336 } 1337 1338 // Register for DIVL projection of divmodL 1339 RegMask Matcher::divL_proj_mask() { 1340 ShouldNotReachHere(); 1341 return RegMask(); 1342 } 1343 1344 // Register for MODL projection of divmodL 1345 RegMask Matcher::modL_proj_mask() { 1346 ShouldNotReachHere(); 1347 return RegMask(); 1348 } 1349 1350 const RegMask Matcher::method_handle_invoke_SP_save_mask() { 1351 return FP_REGP_mask(); 1352 } 1353 1354 bool maybe_far_call(const CallNode *n) { 1355 return !MacroAssembler::_reachable_from_cache(n->as_Call()->entry_point()); 1356 } 1357 1358 bool maybe_far_call(const MachCallNode *n) { 1359 return !MacroAssembler::_reachable_from_cache(n->as_MachCall()->entry_point()); 1360 } 1361 1362 %} 1363 1364 //----------ENCODING BLOCK----------------------------------------------------- 1365 // This block specifies the encoding classes used by the compiler to output 1366 // byte streams. Encoding classes are parameterized macros used by 1367 // Machine Instruction Nodes in order to generate the bit encoding of the 1368 // instruction. Operands specify their base encoding interface with the 1369 // interface keyword. There are currently supported four interfaces, 1370 // REG_INTER, CONST_INTER, MEMORY_INTER, & COND_INTER. REG_INTER causes an 1371 // operand to generate a function which returns its register number when 1372 // queried. CONST_INTER causes an operand to generate a function which 1373 // returns the value of the constant when queried. MEMORY_INTER causes an 1374 // operand to generate four functions which return the Base Register, the 1375 // Index Register, the Scale Value, and the Offset Value of the operand when 1376 // queried. COND_INTER causes an operand to generate six functions which 1377 // return the encoding code (ie - encoding bits for the instruction) 1378 // associated with each basic boolean condition for a conditional instruction. 1379 // 1380 // Instructions specify two basic values for encoding. Again, a function 1381 // is available to check if the constant displacement is an oop. They use the 1382 // ins_encode keyword to specify their encoding classes (which must be 1383 // a sequence of enc_class names, and their parameters, specified in 1384 // the encoding block), and they use the 1385 // opcode keyword to specify, in order, their primary, secondary, and 1386 // tertiary opcode. Only the opcode sections which a particular instruction 1387 // needs for encoding need to be specified. 1388 encode %{ 1389 enc_class call_epilog %{ 1390 // nothing 1391 %} 1392 1393 enc_class Java_To_Runtime (method meth) %{ 1394 // CALL directly to the runtime 1395 emit_call_reloc(cbuf, as_MachCall(), $meth, runtime_call_Relocation::spec()); 1396 %} 1397 1398 enc_class Java_Static_Call (method meth) %{ 1399 // CALL to fixup routine. Fixup routine uses ScopeDesc info to determine 1400 // who we intended to call. 1401 1402 if ( !_method) { 1403 emit_call_reloc(cbuf, as_MachCall(), $meth, runtime_call_Relocation::spec()); 1404 } else { 1405 int method_index = resolved_method_index(cbuf); 1406 RelocationHolder rspec = _optimized_virtual ? opt_virtual_call_Relocation::spec(method_index) 1407 : static_call_Relocation::spec(method_index); 1408 emit_call_reloc(cbuf, as_MachCall(), $meth, rspec); 1409 1410 // Emit stubs for static call. 1411 address stub = CompiledStaticCall::emit_to_interp_stub(cbuf); 1412 if (stub == NULL) { 1413 ciEnv::current()->record_failure("CodeCache is full"); 1414 return; 1415 } 1416 } 1417 %} 1418 1419 enc_class save_last_PC %{ 1420 // preserve mark 1421 address mark = cbuf.insts()->mark(); 1422 debug_only(int off0 = cbuf.insts_size()); 1423 MacroAssembler _masm(&cbuf); 1424 int ret_addr_offset = as_MachCall()->ret_addr_offset(); 1425 __ adr(LR, mark + ret_addr_offset); 1426 __ str(LR, Address(Rthread, JavaThread::last_Java_pc_offset())); 1427 debug_only(int off1 = cbuf.insts_size()); 1428 assert(off1 - off0 == 2 * Assembler::InstructionSize, "correct size prediction"); 1429 // restore mark 1430 cbuf.insts()->set_mark(mark); 1431 %} 1432 1433 enc_class preserve_SP %{ 1434 // preserve mark 1435 address mark = cbuf.insts()->mark(); 1436 debug_only(int off0 = cbuf.insts_size()); 1437 MacroAssembler _masm(&cbuf); 1438 // FP is preserved across all calls, even compiled calls. 1439 // Use it to preserve SP in places where the callee might change the SP. 1440 __ mov(Rmh_SP_save, SP); 1441 debug_only(int off1 = cbuf.insts_size()); 1442 assert(off1 - off0 == 4, "correct size prediction"); 1443 // restore mark 1444 cbuf.insts()->set_mark(mark); 1445 %} 1446 1447 enc_class restore_SP %{ 1448 MacroAssembler _masm(&cbuf); 1449 __ mov(SP, Rmh_SP_save); 1450 %} 1451 1452 enc_class Java_Dynamic_Call (method meth) %{ 1453 MacroAssembler _masm(&cbuf); 1454 Register R8_ic_reg = reg_to_register_object(Matcher::inline_cache_reg_encode()); 1455 assert(R8_ic_reg == Ricklass, "should be"); 1456 __ set_inst_mark(); 1457 #ifdef AARCH64 1458 // TODO: see C1 LIR_Assembler::ic_call() 1459 InlinedAddress oop_literal((address)Universe::non_oop_word()); 1460 int offset = __ offset(); 1461 int fixed_size = mov_oop_size * 4; 1462 if (VM_Version::prefer_moves_over_load_literal()) { 1463 uintptr_t val = (uintptr_t)Universe::non_oop_word(); 1464 __ movz(R8_ic_reg, (val >> 0) & 0xffff, 0); 1465 __ movk(R8_ic_reg, (val >> 16) & 0xffff, 16); 1466 __ movk(R8_ic_reg, (val >> 32) & 0xffff, 32); 1467 __ movk(R8_ic_reg, (val >> 48) & 0xffff, 48); 1468 } else { 1469 __ ldr_literal(R8_ic_reg, oop_literal); 1470 } 1471 assert(__ offset() - offset == fixed_size, "bad mov_oop size"); 1472 #else 1473 __ movw(R8_ic_reg, ((unsigned int)Universe::non_oop_word()) & 0xffff); 1474 __ movt(R8_ic_reg, ((unsigned int)Universe::non_oop_word()) >> 16); 1475 #endif 1476 address virtual_call_oop_addr = __ inst_mark(); 1477 // CALL to fixup routine. Fixup routine uses ScopeDesc info to determine 1478 // who we intended to call. 1479 int method_index = resolved_method_index(cbuf); 1480 __ relocate(virtual_call_Relocation::spec(virtual_call_oop_addr, method_index)); 1481 emit_call_reloc(cbuf, as_MachCall(), $meth, RelocationHolder::none); 1482 #ifdef AARCH64 1483 if (!VM_Version::prefer_moves_over_load_literal()) { 1484 Label skip_literal; 1485 __ b(skip_literal); 1486 int off2 = __ offset(); 1487 __ bind_literal(oop_literal); 1488 if (__ offset() - off2 == wordSize) { 1489 // no padding, so insert nop for worst-case sizing 1490 __ nop(); 1491 } 1492 __ bind(skip_literal); 1493 } 1494 #endif 1495 %} 1496 1497 enc_class LdReplImmI(immI src, regD dst, iRegI tmp, int cnt, int wth) %{ 1498 // FIXME: load from constant table? 1499 // Load a constant replicated "count" times with width "width" 1500 int count = $cnt$$constant; 1501 int width = $wth$$constant; 1502 assert(count*width == 4, "sanity"); 1503 int val = $src$$constant; 1504 if (width < 4) { 1505 int bit_width = width * 8; 1506 val &= (((int)1) << bit_width) - 1; // mask off sign bits 1507 for (int i = 0; i < count - 1; i++) { 1508 val |= (val << bit_width); 1509 } 1510 } 1511 MacroAssembler _masm(&cbuf); 1512 1513 if (val == -1) { 1514 __ mvn($tmp$$Register, 0); 1515 } else if (val == 0) { 1516 __ mov($tmp$$Register, 0); 1517 } else { 1518 __ movw($tmp$$Register, val & 0xffff); 1519 __ movt($tmp$$Register, (unsigned int)val >> 16); 1520 } 1521 __ fmdrr($dst$$FloatRegister, $tmp$$Register, $tmp$$Register); 1522 %} 1523 1524 enc_class LdReplImmF(immF src, regD dst, iRegI tmp) %{ 1525 // Replicate float con 2 times and pack into vector (8 bytes) in regD. 1526 float fval = $src$$constant; 1527 int val = *((int*)&fval); 1528 MacroAssembler _masm(&cbuf); 1529 1530 if (val == -1) { 1531 __ mvn($tmp$$Register, 0); 1532 } else if (val == 0) { 1533 __ mov($tmp$$Register, 0); 1534 } else { 1535 __ movw($tmp$$Register, val & 0xffff); 1536 __ movt($tmp$$Register, (unsigned int)val >> 16); 1537 } 1538 __ fmdrr($dst$$FloatRegister, $tmp$$Register, $tmp$$Register); 1539 %} 1540 1541 enc_class enc_String_Compare(R0RegP str1, R1RegP str2, R2RegI cnt1, R3RegI cnt2, iRegI result, iRegI tmp1, iRegI tmp2) %{ 1542 Label Ldone, Lloop; 1543 MacroAssembler _masm(&cbuf); 1544 1545 Register str1_reg = $str1$$Register; 1546 Register str2_reg = $str2$$Register; 1547 Register cnt1_reg = $cnt1$$Register; // int 1548 Register cnt2_reg = $cnt2$$Register; // int 1549 Register tmp1_reg = $tmp1$$Register; 1550 Register tmp2_reg = $tmp2$$Register; 1551 Register result_reg = $result$$Register; 1552 1553 assert_different_registers(str1_reg, str2_reg, cnt1_reg, cnt2_reg, tmp1_reg, tmp2_reg); 1554 1555 // Compute the minimum of the string lengths(str1_reg) and the 1556 // difference of the string lengths (stack) 1557 1558 // See if the lengths are different, and calculate min in str1_reg. 1559 // Stash diff in tmp2 in case we need it for a tie-breaker. 1560 __ subs_32(tmp2_reg, cnt1_reg, cnt2_reg); 1561 #ifdef AARCH64 1562 Label Lskip; 1563 __ _lsl_w(cnt1_reg, cnt1_reg, exact_log2(sizeof(jchar))); // scale the limit 1564 __ b(Lskip, mi); 1565 __ _lsl_w(cnt1_reg, cnt2_reg, exact_log2(sizeof(jchar))); // scale the limit 1566 __ bind(Lskip); 1567 #else 1568 __ mov(cnt1_reg, AsmOperand(cnt1_reg, lsl, exact_log2(sizeof(jchar)))); // scale the limit 1569 __ mov(cnt1_reg, AsmOperand(cnt2_reg, lsl, exact_log2(sizeof(jchar))), pl); // scale the limit 1570 #endif 1571 1572 // reallocate cnt1_reg, cnt2_reg, result_reg 1573 // Note: limit_reg holds the string length pre-scaled by 2 1574 Register limit_reg = cnt1_reg; 1575 Register chr2_reg = cnt2_reg; 1576 Register chr1_reg = tmp1_reg; 1577 // str{12} are the base pointers 1578 1579 // Is the minimum length zero? 1580 __ cmp_32(limit_reg, 0); 1581 if (result_reg != tmp2_reg) { 1582 __ mov(result_reg, tmp2_reg, eq); 1583 } 1584 __ b(Ldone, eq); 1585 1586 // Load first characters 1587 __ ldrh(chr1_reg, Address(str1_reg, 0)); 1588 __ ldrh(chr2_reg, Address(str2_reg, 0)); 1589 1590 // Compare first characters 1591 __ subs(chr1_reg, chr1_reg, chr2_reg); 1592 if (result_reg != chr1_reg) { 1593 __ mov(result_reg, chr1_reg, ne); 1594 } 1595 __ b(Ldone, ne); 1596 1597 { 1598 // Check after comparing first character to see if strings are equivalent 1599 // Check if the strings start at same location 1600 __ cmp(str1_reg, str2_reg); 1601 // Check if the length difference is zero 1602 __ cond_cmp(tmp2_reg, 0, eq); 1603 __ mov(result_reg, 0, eq); // result is zero 1604 __ b(Ldone, eq); 1605 // Strings might not be equal 1606 } 1607 1608 __ subs(chr1_reg, limit_reg, 1 * sizeof(jchar)); 1609 if (result_reg != tmp2_reg) { 1610 __ mov(result_reg, tmp2_reg, eq); 1611 } 1612 __ b(Ldone, eq); 1613 1614 // Shift str1_reg and str2_reg to the end of the arrays, negate limit 1615 __ add(str1_reg, str1_reg, limit_reg); 1616 __ add(str2_reg, str2_reg, limit_reg); 1617 __ neg(limit_reg, chr1_reg); // limit = -(limit-2) 1618 1619 // Compare the rest of the characters 1620 __ bind(Lloop); 1621 __ ldrh(chr1_reg, Address(str1_reg, limit_reg)); 1622 __ ldrh(chr2_reg, Address(str2_reg, limit_reg)); 1623 __ subs(chr1_reg, chr1_reg, chr2_reg); 1624 if (result_reg != chr1_reg) { 1625 __ mov(result_reg, chr1_reg, ne); 1626 } 1627 __ b(Ldone, ne); 1628 1629 __ adds(limit_reg, limit_reg, sizeof(jchar)); 1630 __ b(Lloop, ne); 1631 1632 // If strings are equal up to min length, return the length difference. 1633 if (result_reg != tmp2_reg) { 1634 __ mov(result_reg, tmp2_reg); 1635 } 1636 1637 // Otherwise, return the difference between the first mismatched chars. 1638 __ bind(Ldone); 1639 %} 1640 1641 enc_class enc_String_Equals(R0RegP str1, R1RegP str2, R2RegI cnt, iRegI result, iRegI tmp1, iRegI tmp2) %{ 1642 Label Lword_loop, Lpost_word, Lchar, Lchar_loop, Ldone, Lequal; 1643 MacroAssembler _masm(&cbuf); 1644 1645 Register str1_reg = $str1$$Register; 1646 Register str2_reg = $str2$$Register; 1647 Register cnt_reg = $cnt$$Register; // int 1648 Register tmp1_reg = $tmp1$$Register; 1649 Register tmp2_reg = $tmp2$$Register; 1650 Register result_reg = $result$$Register; 1651 1652 assert_different_registers(str1_reg, str2_reg, cnt_reg, tmp1_reg, tmp2_reg, result_reg); 1653 1654 __ cmp(str1_reg, str2_reg); //same char[] ? 1655 __ b(Lequal, eq); 1656 1657 __ cbz_32(cnt_reg, Lequal); // count == 0 1658 1659 //rename registers 1660 Register limit_reg = cnt_reg; 1661 Register chr1_reg = tmp1_reg; 1662 Register chr2_reg = tmp2_reg; 1663 1664 __ logical_shift_left(limit_reg, limit_reg, exact_log2(sizeof(jchar))); 1665 1666 //check for alignment and position the pointers to the ends 1667 __ orr(chr1_reg, str1_reg, str2_reg); 1668 __ tst(chr1_reg, 0x3); 1669 1670 // notZero means at least one not 4-byte aligned. 1671 // We could optimize the case when both arrays are not aligned 1672 // but it is not frequent case and it requires additional checks. 1673 __ b(Lchar, ne); 1674 1675 // Compare char[] arrays aligned to 4 bytes. 1676 __ char_arrays_equals(str1_reg, str2_reg, limit_reg, result_reg, 1677 chr1_reg, chr2_reg, Ldone); 1678 1679 __ b(Lequal); // equal 1680 1681 // char by char compare 1682 __ bind(Lchar); 1683 __ mov(result_reg, 0); 1684 __ add(str1_reg, limit_reg, str1_reg); 1685 __ add(str2_reg, limit_reg, str2_reg); 1686 __ neg(limit_reg, limit_reg); //negate count 1687 1688 // Lchar_loop 1689 __ bind(Lchar_loop); 1690 __ ldrh(chr1_reg, Address(str1_reg, limit_reg)); 1691 __ ldrh(chr2_reg, Address(str2_reg, limit_reg)); 1692 __ cmp(chr1_reg, chr2_reg); 1693 __ b(Ldone, ne); 1694 __ adds(limit_reg, limit_reg, sizeof(jchar)); 1695 __ b(Lchar_loop, ne); 1696 1697 __ bind(Lequal); 1698 __ mov(result_reg, 1); //equal 1699 1700 __ bind(Ldone); 1701 %} 1702 1703 enc_class enc_Array_Equals(R0RegP ary1, R1RegP ary2, iRegI tmp1, iRegI tmp2, iRegI tmp3, iRegI result) %{ 1704 Label Lvector, Ldone, Lloop, Lequal; 1705 MacroAssembler _masm(&cbuf); 1706 1707 Register ary1_reg = $ary1$$Register; 1708 Register ary2_reg = $ary2$$Register; 1709 Register tmp1_reg = $tmp1$$Register; 1710 Register tmp2_reg = $tmp2$$Register; 1711 Register tmp3_reg = $tmp3$$Register; 1712 Register result_reg = $result$$Register; 1713 1714 assert_different_registers(ary1_reg, ary2_reg, tmp1_reg, tmp2_reg, tmp3_reg, result_reg); 1715 1716 int length_offset = arrayOopDesc::length_offset_in_bytes(); 1717 int base_offset = arrayOopDesc::base_offset_in_bytes(T_CHAR); 1718 1719 // return true if the same array 1720 #ifdef AARCH64 1721 __ cmp(ary1_reg, ary2_reg); 1722 __ b(Lequal, eq); 1723 1724 __ mov(result_reg, 0); 1725 1726 __ cbz(ary1_reg, Ldone); // not equal 1727 1728 __ cbz(ary2_reg, Ldone); // not equal 1729 #else 1730 __ teq(ary1_reg, ary2_reg); 1731 __ mov(result_reg, 1, eq); 1732 __ b(Ldone, eq); // equal 1733 1734 __ tst(ary1_reg, ary1_reg); 1735 __ mov(result_reg, 0, eq); 1736 __ b(Ldone, eq); // not equal 1737 1738 __ tst(ary2_reg, ary2_reg); 1739 __ mov(result_reg, 0, eq); 1740 __ b(Ldone, eq); // not equal 1741 #endif 1742 1743 //load the lengths of arrays 1744 __ ldr_s32(tmp1_reg, Address(ary1_reg, length_offset)); // int 1745 __ ldr_s32(tmp2_reg, Address(ary2_reg, length_offset)); // int 1746 1747 // return false if the two arrays are not equal length 1748 #ifdef AARCH64 1749 __ cmp_w(tmp1_reg, tmp2_reg); 1750 __ b(Ldone, ne); // not equal 1751 1752 __ cbz_w(tmp1_reg, Lequal); // zero-length arrays are equal 1753 #else 1754 __ teq_32(tmp1_reg, tmp2_reg); 1755 __ mov(result_reg, 0, ne); 1756 __ b(Ldone, ne); // not equal 1757 1758 __ tst(tmp1_reg, tmp1_reg); 1759 __ mov(result_reg, 1, eq); 1760 __ b(Ldone, eq); // zero-length arrays are equal 1761 #endif 1762 1763 // load array addresses 1764 __ add(ary1_reg, ary1_reg, base_offset); 1765 __ add(ary2_reg, ary2_reg, base_offset); 1766 1767 // renaming registers 1768 Register chr1_reg = tmp3_reg; // for characters in ary1 1769 Register chr2_reg = tmp2_reg; // for characters in ary2 1770 Register limit_reg = tmp1_reg; // length 1771 1772 // set byte count 1773 __ logical_shift_left_32(limit_reg, limit_reg, exact_log2(sizeof(jchar))); 1774 1775 // Compare char[] arrays aligned to 4 bytes. 1776 __ char_arrays_equals(ary1_reg, ary2_reg, limit_reg, result_reg, 1777 chr1_reg, chr2_reg, Ldone); 1778 __ bind(Lequal); 1779 __ mov(result_reg, 1); //equal 1780 1781 __ bind(Ldone); 1782 %} 1783 %} 1784 1785 //----------FRAME-------------------------------------------------------------- 1786 // Definition of frame structure and management information. 1787 // 1788 // S T A C K L A Y O U T Allocators stack-slot number 1789 // | (to get allocators register number 1790 // G Owned by | | v add VMRegImpl::stack0) 1791 // r CALLER | | 1792 // o | +--------+ pad to even-align allocators stack-slot 1793 // w V | pad0 | numbers; owned by CALLER 1794 // t -----------+--------+----> Matcher::_in_arg_limit, unaligned 1795 // h ^ | in | 5 1796 // | | args | 4 Holes in incoming args owned by SELF 1797 // | | | | 3 1798 // | | +--------+ 1799 // V | | old out| Empty on Intel, window on Sparc 1800 // | old |preserve| Must be even aligned. 1801 // | SP-+--------+----> Matcher::_old_SP, 8 (or 16 in LP64)-byte aligned 1802 // | | in | 3 area for Intel ret address 1803 // Owned by |preserve| Empty on Sparc. 1804 // SELF +--------+ 1805 // | | pad2 | 2 pad to align old SP 1806 // | +--------+ 1 1807 // | | locks | 0 1808 // | +--------+----> VMRegImpl::stack0, 8 (or 16 in LP64)-byte aligned 1809 // | | pad1 | 11 pad to align new SP 1810 // | +--------+ 1811 // | | | 10 1812 // | | spills | 9 spills 1813 // V | | 8 (pad0 slot for callee) 1814 // -----------+--------+----> Matcher::_out_arg_limit, unaligned 1815 // ^ | out | 7 1816 // | | args | 6 Holes in outgoing args owned by CALLEE 1817 // Owned by +--------+ 1818 // CALLEE | new out| 6 Empty on Intel, window on Sparc 1819 // | new |preserve| Must be even-aligned. 1820 // | SP-+--------+----> Matcher::_new_SP, even aligned 1821 // | | | 1822 // 1823 // Note 1: Only region 8-11 is determined by the allocator. Region 0-5 is 1824 // known from SELF's arguments and the Java calling convention. 1825 // Region 6-7 is determined per call site. 1826 // Note 2: If the calling convention leaves holes in the incoming argument 1827 // area, those holes are owned by SELF. Holes in the outgoing area 1828 // are owned by the CALLEE. Holes should not be nessecary in the 1829 // incoming area, as the Java calling convention is completely under 1830 // the control of the AD file. Doubles can be sorted and packed to 1831 // avoid holes. Holes in the outgoing arguments may be nessecary for 1832 // varargs C calling conventions. 1833 // Note 3: Region 0-3 is even aligned, with pad2 as needed. Region 3-5 is 1834 // even aligned with pad0 as needed. 1835 // Region 6 is even aligned. Region 6-7 is NOT even aligned; 1836 // region 6-11 is even aligned; it may be padded out more so that 1837 // the region from SP to FP meets the minimum stack alignment. 1838 1839 frame %{ 1840 // What direction does stack grow in (assumed to be same for native & Java) 1841 stack_direction(TOWARDS_LOW); 1842 1843 // These two registers define part of the calling convention 1844 // between compiled code and the interpreter. 1845 inline_cache_reg(R_Ricklass); // Inline Cache Register or Method* for I2C 1846 interpreter_method_oop_reg(R_Rmethod); // Method Oop Register when calling interpreter 1847 1848 // Optional: name the operand used by cisc-spilling to access [stack_pointer + offset] 1849 cisc_spilling_operand_name(indOffset); 1850 1851 // Number of stack slots consumed by a Monitor enter 1852 sync_stack_slots(1 * VMRegImpl::slots_per_word); 1853 1854 // Compiled code's Frame Pointer 1855 #ifdef AARCH64 1856 frame_pointer(R_SP); 1857 #else 1858 frame_pointer(R_R13); 1859 #endif 1860 1861 // Stack alignment requirement 1862 stack_alignment(StackAlignmentInBytes); 1863 // LP64: Alignment size in bytes (128-bit -> 16 bytes) 1864 // !LP64: Alignment size in bytes (64-bit -> 8 bytes) 1865 1866 // Number of stack slots between incoming argument block and the start of 1867 // a new frame. The PROLOG must add this many slots to the stack. The 1868 // EPILOG must remove this many slots. 1869 // FP + LR 1870 in_preserve_stack_slots(2 * VMRegImpl::slots_per_word); 1871 1872 // Number of outgoing stack slots killed above the out_preserve_stack_slots 1873 // for calls to C. Supports the var-args backing area for register parms. 1874 // ADLC doesn't support parsing expressions, so I folded the math by hand. 1875 varargs_C_out_slots_killed( 0); 1876 1877 // The after-PROLOG location of the return address. Location of 1878 // return address specifies a type (REG or STACK) and a number 1879 // representing the register number (i.e. - use a register name) or 1880 // stack slot. 1881 // Ret Addr is on stack in slot 0 if no locks or verification or alignment. 1882 // Otherwise, it is above the locks and verification slot and alignment word 1883 return_addr(STACK - 1*VMRegImpl::slots_per_word + 1884 round_to((Compile::current()->in_preserve_stack_slots() + 1885 Compile::current()->fixed_slots()), 1886 stack_alignment_in_slots())); 1887 1888 // Body of function which returns an OptoRegs array locating 1889 // arguments either in registers or in stack slots for calling 1890 // java 1891 calling_convention %{ 1892 (void) SharedRuntime::java_calling_convention(sig_bt, regs, length, is_outgoing); 1893 1894 %} 1895 1896 // Body of function which returns an OptoRegs array locating 1897 // arguments either in registers or in stack slots for callin 1898 // C. 1899 c_calling_convention %{ 1900 // This is obviously always outgoing 1901 (void) SharedRuntime::c_calling_convention(sig_bt, regs, /*regs2=*/NULL, length); 1902 %} 1903 1904 // Location of compiled Java return values. Same as C 1905 return_value %{ 1906 return c2::return_value(ideal_reg); 1907 %} 1908 1909 %} 1910 1911 //----------ATTRIBUTES--------------------------------------------------------- 1912 //----------Instruction Attributes--------------------------------------------- 1913 ins_attrib ins_cost(DEFAULT_COST); // Required cost attribute 1914 ins_attrib ins_size(32); // Required size attribute (in bits) 1915 ins_attrib ins_short_branch(0); // Required flag: is this instruction a 1916 // non-matching short branch variant of some 1917 // long branch? 1918 1919 //----------OPERANDS----------------------------------------------------------- 1920 // Operand definitions must precede instruction definitions for correct parsing 1921 // in the ADLC because operands constitute user defined types which are used in 1922 // instruction definitions. 1923 1924 //----------Simple Operands---------------------------------------------------- 1925 // Immediate Operands 1926 // Integer Immediate: 32-bit 1927 operand immI() %{ 1928 match(ConI); 1929 1930 op_cost(0); 1931 // formats are generated automatically for constants and base registers 1932 format %{ %} 1933 interface(CONST_INTER); 1934 %} 1935 1936 // Integer Immediate: 8-bit unsigned - for VMOV 1937 operand immU8() %{ 1938 predicate(0 <= n->get_int() && (n->get_int() <= 255)); 1939 match(ConI); 1940 op_cost(0); 1941 1942 format %{ %} 1943 interface(CONST_INTER); 1944 %} 1945 1946 // Integer Immediate: 16-bit 1947 operand immI16() %{ 1948 predicate((n->get_int() >> 16) == 0 && VM_Version::supports_movw()); 1949 match(ConI); 1950 op_cost(0); 1951 1952 format %{ %} 1953 interface(CONST_INTER); 1954 %} 1955 1956 #ifndef AARCH64 1957 // Integer Immediate: offset for half and double word loads and stores 1958 operand immIHD() %{ 1959 predicate(is_memoryHD(n->get_int())); 1960 match(ConI); 1961 op_cost(0); 1962 format %{ %} 1963 interface(CONST_INTER); 1964 %} 1965 1966 // Integer Immediate: offset for fp loads and stores 1967 operand immIFP() %{ 1968 predicate(is_memoryfp(n->get_int()) && ((n->get_int() & 3) == 0)); 1969 match(ConI); 1970 op_cost(0); 1971 1972 format %{ %} 1973 interface(CONST_INTER); 1974 %} 1975 #endif 1976 1977 // Valid scale values for addressing modes and shifts 1978 operand immU5() %{ 1979 predicate(0 <= n->get_int() && (n->get_int() <= 31)); 1980 match(ConI); 1981 op_cost(0); 1982 1983 format %{ %} 1984 interface(CONST_INTER); 1985 %} 1986 1987 // Integer Immediate: 6-bit 1988 operand immU6Big() %{ 1989 predicate(n->get_int() >= 32 && n->get_int() <= 63); 1990 match(ConI); 1991 op_cost(0); 1992 format %{ %} 1993 interface(CONST_INTER); 1994 %} 1995 1996 // Integer Immediate: 0-bit 1997 operand immI0() %{ 1998 predicate(n->get_int() == 0); 1999 match(ConI); 2000 op_cost(0); 2001 2002 format %{ %} 2003 interface(CONST_INTER); 2004 %} 2005 2006 // Integer Immediate: the value 1 2007 operand immI_1() %{ 2008 predicate(n->get_int() == 1); 2009 match(ConI); 2010 op_cost(0); 2011 2012 format %{ %} 2013 interface(CONST_INTER); 2014 %} 2015 2016 // Integer Immediate: the value 2 2017 operand immI_2() %{ 2018 predicate(n->get_int() == 2); 2019 match(ConI); 2020 op_cost(0); 2021 2022 format %{ %} 2023 interface(CONST_INTER); 2024 %} 2025 2026 // Integer Immediate: the value 3 2027 operand immI_3() %{ 2028 predicate(n->get_int() == 3); 2029 match(ConI); 2030 op_cost(0); 2031 2032 format %{ %} 2033 interface(CONST_INTER); 2034 %} 2035 2036 // Integer Immediate: the value 4 2037 operand immI_4() %{ 2038 predicate(n->get_int() == 4); 2039 match(ConI); 2040 op_cost(0); 2041 2042 format %{ %} 2043 interface(CONST_INTER); 2044 %} 2045 2046 // Integer Immediate: the value 8 2047 operand immI_8() %{ 2048 predicate(n->get_int() == 8); 2049 match(ConI); 2050 op_cost(0); 2051 2052 format %{ %} 2053 interface(CONST_INTER); 2054 %} 2055 2056 // Int Immediate non-negative 2057 operand immU31() 2058 %{ 2059 predicate(n->get_int() >= 0); 2060 match(ConI); 2061 2062 op_cost(0); 2063 format %{ %} 2064 interface(CONST_INTER); 2065 %} 2066 2067 // Integer Immediate: the values 32-63 2068 operand immI_32_63() %{ 2069 predicate(n->get_int() >= 32 && n->get_int() <= 63); 2070 match(ConI); 2071 op_cost(0); 2072 2073 format %{ %} 2074 interface(CONST_INTER); 2075 %} 2076 2077 // Immediates for special shifts (sign extend) 2078 2079 // Integer Immediate: the value 16 2080 operand immI_16() %{ 2081 predicate(n->get_int() == 16); 2082 match(ConI); 2083 op_cost(0); 2084 2085 format %{ %} 2086 interface(CONST_INTER); 2087 %} 2088 2089 // Integer Immediate: the value 24 2090 operand immI_24() %{ 2091 predicate(n->get_int() == 24); 2092 match(ConI); 2093 op_cost(0); 2094 2095 format %{ %} 2096 interface(CONST_INTER); 2097 %} 2098 2099 // Integer Immediate: the value 255 2100 operand immI_255() %{ 2101 predicate( n->get_int() == 255 ); 2102 match(ConI); 2103 op_cost(0); 2104 2105 format %{ %} 2106 interface(CONST_INTER); 2107 %} 2108 2109 // Integer Immediate: the value 65535 2110 operand immI_65535() %{ 2111 predicate(n->get_int() == 65535); 2112 match(ConI); 2113 op_cost(0); 2114 2115 format %{ %} 2116 interface(CONST_INTER); 2117 %} 2118 2119 // Integer Immediates for arithmetic instructions 2120 2121 operand aimmI() %{ 2122 predicate(is_aimm(n->get_int())); 2123 match(ConI); 2124 op_cost(0); 2125 2126 format %{ %} 2127 interface(CONST_INTER); 2128 %} 2129 2130 operand aimmIneg() %{ 2131 predicate(is_aimm(-n->get_int())); 2132 match(ConI); 2133 op_cost(0); 2134 2135 format %{ %} 2136 interface(CONST_INTER); 2137 %} 2138 2139 operand aimmU31() %{ 2140 predicate((0 <= n->get_int()) && is_aimm(n->get_int())); 2141 match(ConI); 2142 op_cost(0); 2143 2144 format %{ %} 2145 interface(CONST_INTER); 2146 %} 2147 2148 // Integer Immediates for logical instructions 2149 2150 operand limmI() %{ 2151 predicate(is_limmI(n->get_int())); 2152 match(ConI); 2153 op_cost(0); 2154 2155 format %{ %} 2156 interface(CONST_INTER); 2157 %} 2158 2159 operand limmIlow8() %{ 2160 predicate(is_limmI_low(n->get_int(), 8)); 2161 match(ConI); 2162 op_cost(0); 2163 2164 format %{ %} 2165 interface(CONST_INTER); 2166 %} 2167 2168 operand limmU31() %{ 2169 predicate(0 <= n->get_int() && is_limmI(n->get_int())); 2170 match(ConI); 2171 op_cost(0); 2172 2173 format %{ %} 2174 interface(CONST_INTER); 2175 %} 2176 2177 operand limmIn() %{ 2178 predicate(is_limmI(~n->get_int())); 2179 match(ConI); 2180 op_cost(0); 2181 2182 format %{ %} 2183 interface(CONST_INTER); 2184 %} 2185 2186 #ifdef AARCH64 2187 // Long Immediate: for logical instruction 2188 operand limmL() %{ 2189 predicate(is_limmL(n->get_long())); 2190 match(ConL); 2191 op_cost(0); 2192 2193 format %{ %} 2194 interface(CONST_INTER); 2195 %} 2196 2197 operand limmLn() %{ 2198 predicate(is_limmL(~n->get_long())); 2199 match(ConL); 2200 op_cost(0); 2201 2202 format %{ %} 2203 interface(CONST_INTER); 2204 %} 2205 2206 // Long Immediate: for arithmetic instruction 2207 operand aimmL() %{ 2208 predicate(is_aimm(n->get_long())); 2209 match(ConL); 2210 op_cost(0); 2211 2212 format %{ %} 2213 interface(CONST_INTER); 2214 %} 2215 2216 operand aimmLneg() %{ 2217 predicate(is_aimm(-n->get_long())); 2218 match(ConL); 2219 op_cost(0); 2220 2221 format %{ %} 2222 interface(CONST_INTER); 2223 %} 2224 #endif // AARCH64 2225 2226 // Long Immediate: the value FF 2227 operand immL_FF() %{ 2228 predicate( n->get_long() == 0xFFL ); 2229 match(ConL); 2230 op_cost(0); 2231 2232 format %{ %} 2233 interface(CONST_INTER); 2234 %} 2235 2236 // Long Immediate: the value FFFF 2237 operand immL_FFFF() %{ 2238 predicate( n->get_long() == 0xFFFFL ); 2239 match(ConL); 2240 op_cost(0); 2241 2242 format %{ %} 2243 interface(CONST_INTER); 2244 %} 2245 2246 // Pointer Immediate: 32 or 64-bit 2247 operand immP() %{ 2248 match(ConP); 2249 2250 op_cost(5); 2251 // formats are generated automatically for constants and base registers 2252 format %{ %} 2253 interface(CONST_INTER); 2254 %} 2255 2256 operand immP0() %{ 2257 predicate(n->get_ptr() == 0); 2258 match(ConP); 2259 op_cost(0); 2260 2261 format %{ %} 2262 interface(CONST_INTER); 2263 %} 2264 2265 operand immP_poll() %{ 2266 predicate(n->get_ptr() != 0 && n->get_ptr() == (intptr_t)os::get_polling_page()); 2267 match(ConP); 2268 2269 // formats are generated automatically for constants and base registers 2270 format %{ %} 2271 interface(CONST_INTER); 2272 %} 2273 2274 // Pointer Immediate 2275 operand immN() 2276 %{ 2277 match(ConN); 2278 2279 op_cost(10); 2280 format %{ %} 2281 interface(CONST_INTER); 2282 %} 2283 2284 operand immNKlass() 2285 %{ 2286 match(ConNKlass); 2287 2288 op_cost(10); 2289 format %{ %} 2290 interface(CONST_INTER); 2291 %} 2292 2293 // NULL Pointer Immediate 2294 operand immN0() 2295 %{ 2296 predicate(n->get_narrowcon() == 0); 2297 match(ConN); 2298 2299 op_cost(0); 2300 format %{ %} 2301 interface(CONST_INTER); 2302 %} 2303 2304 operand immL() %{ 2305 match(ConL); 2306 op_cost(40); 2307 // formats are generated automatically for constants and base registers 2308 format %{ %} 2309 interface(CONST_INTER); 2310 %} 2311 2312 operand immL0() %{ 2313 predicate(n->get_long() == 0L); 2314 match(ConL); 2315 op_cost(0); 2316 // formats are generated automatically for constants and base registers 2317 format %{ %} 2318 interface(CONST_INTER); 2319 %} 2320 2321 // Long Immediate: 16-bit 2322 operand immL16() %{ 2323 predicate(n->get_long() >= 0 && n->get_long() < (1<<16) && VM_Version::supports_movw()); 2324 match(ConL); 2325 op_cost(0); 2326 2327 format %{ %} 2328 interface(CONST_INTER); 2329 %} 2330 2331 // Long Immediate: low 32-bit mask 2332 operand immL_32bits() %{ 2333 predicate(n->get_long() == 0xFFFFFFFFL); 2334 match(ConL); 2335 op_cost(0); 2336 2337 format %{ %} 2338 interface(CONST_INTER); 2339 %} 2340 2341 // Double Immediate 2342 operand immD() %{ 2343 match(ConD); 2344 2345 op_cost(40); 2346 format %{ %} 2347 interface(CONST_INTER); 2348 %} 2349 2350 // Double Immediate: +0.0d. 2351 operand immD0() %{ 2352 predicate(jlong_cast(n->getd()) == 0); 2353 2354 match(ConD); 2355 op_cost(0); 2356 format %{ %} 2357 interface(CONST_INTER); 2358 %} 2359 2360 operand imm8D() %{ 2361 predicate(Assembler::double_num(n->getd()).can_be_imm8()); 2362 match(ConD); 2363 2364 op_cost(0); 2365 format %{ %} 2366 interface(CONST_INTER); 2367 %} 2368 2369 // Float Immediate 2370 operand immF() %{ 2371 match(ConF); 2372 2373 op_cost(20); 2374 format %{ %} 2375 interface(CONST_INTER); 2376 %} 2377 2378 // Float Immediate: +0.0f 2379 operand immF0() %{ 2380 predicate(jint_cast(n->getf()) == 0); 2381 match(ConF); 2382 2383 op_cost(0); 2384 format %{ %} 2385 interface(CONST_INTER); 2386 %} 2387 2388 // Float Immediate: encoded as 8 bits 2389 operand imm8F() %{ 2390 predicate(Assembler::float_num(n->getf()).can_be_imm8()); 2391 match(ConF); 2392 2393 op_cost(0); 2394 format %{ %} 2395 interface(CONST_INTER); 2396 %} 2397 2398 // Integer Register Operands 2399 // Integer Register 2400 operand iRegI() %{ 2401 constraint(ALLOC_IN_RC(int_reg)); 2402 match(RegI); 2403 match(R0RegI); 2404 match(R1RegI); 2405 match(R2RegI); 2406 match(R3RegI); 2407 #ifdef AARCH64 2408 match(ZRRegI); 2409 #else 2410 match(R12RegI); 2411 #endif 2412 2413 format %{ %} 2414 interface(REG_INTER); 2415 %} 2416 2417 // Pointer Register 2418 operand iRegP() %{ 2419 constraint(ALLOC_IN_RC(ptr_reg)); 2420 match(RegP); 2421 match(R0RegP); 2422 match(R1RegP); 2423 match(R2RegP); 2424 match(RExceptionRegP); 2425 match(R8RegP); 2426 match(R9RegP); 2427 match(RthreadRegP); // FIXME: move to sp_ptr_RegP? 2428 match(R12RegP); 2429 match(LRRegP); 2430 2431 match(sp_ptr_RegP); 2432 match(store_ptr_RegP); 2433 2434 format %{ %} 2435 interface(REG_INTER); 2436 %} 2437 2438 // GPRs + Rthread + SP 2439 operand sp_ptr_RegP() %{ 2440 constraint(ALLOC_IN_RC(sp_ptr_reg)); 2441 match(RegP); 2442 match(iRegP); 2443 match(SPRegP); // FIXME: check cost 2444 2445 format %{ %} 2446 interface(REG_INTER); 2447 %} 2448 2449 #ifdef AARCH64 2450 // Like sp_ptr_reg, but exclude regs (Aarch64 SP) that can't be 2451 // stored directly. Includes ZR, so can't be used as a destination. 2452 operand store_ptr_RegP() %{ 2453 constraint(ALLOC_IN_RC(store_ptr_reg)); 2454 match(RegP); 2455 match(iRegP); 2456 match(ZRRegP); 2457 2458 format %{ %} 2459 interface(REG_INTER); 2460 %} 2461 2462 operand store_RegI() %{ 2463 constraint(ALLOC_IN_RC(store_reg)); 2464 match(RegI); 2465 match(iRegI); 2466 match(ZRRegI); 2467 2468 format %{ %} 2469 interface(REG_INTER); 2470 %} 2471 2472 operand store_RegL() %{ 2473 constraint(ALLOC_IN_RC(store_ptr_reg)); 2474 match(RegL); 2475 match(iRegL); 2476 match(ZRRegL); 2477 2478 format %{ %} 2479 interface(REG_INTER); 2480 %} 2481 2482 operand store_RegN() %{ 2483 constraint(ALLOC_IN_RC(store_reg)); 2484 match(RegN); 2485 match(iRegN); 2486 match(ZRRegN); 2487 2488 format %{ %} 2489 interface(REG_INTER); 2490 %} 2491 #endif 2492 2493 operand R0RegP() %{ 2494 constraint(ALLOC_IN_RC(R0_regP)); 2495 match(iRegP); 2496 2497 format %{ %} 2498 interface(REG_INTER); 2499 %} 2500 2501 operand R1RegP() %{ 2502 constraint(ALLOC_IN_RC(R1_regP)); 2503 match(iRegP); 2504 2505 format %{ %} 2506 interface(REG_INTER); 2507 %} 2508 2509 operand R2RegP() %{ 2510 constraint(ALLOC_IN_RC(R2_regP)); 2511 match(iRegP); 2512 2513 format %{ %} 2514 interface(REG_INTER); 2515 %} 2516 2517 operand RExceptionRegP() %{ 2518 constraint(ALLOC_IN_RC(Rexception_regP)); 2519 match(iRegP); 2520 2521 format %{ %} 2522 interface(REG_INTER); 2523 %} 2524 2525 operand RthreadRegP() %{ 2526 constraint(ALLOC_IN_RC(Rthread_regP)); 2527 match(iRegP); 2528 2529 format %{ %} 2530 interface(REG_INTER); 2531 %} 2532 2533 operand IPRegP() %{ 2534 constraint(ALLOC_IN_RC(IP_regP)); 2535 match(iRegP); 2536 2537 format %{ %} 2538 interface(REG_INTER); 2539 %} 2540 2541 operand LRRegP() %{ 2542 constraint(ALLOC_IN_RC(LR_regP)); 2543 match(iRegP); 2544 2545 format %{ %} 2546 interface(REG_INTER); 2547 %} 2548 2549 operand R0RegI() %{ 2550 constraint(ALLOC_IN_RC(R0_regI)); 2551 match(iRegI); 2552 2553 format %{ %} 2554 interface(REG_INTER); 2555 %} 2556 2557 operand R1RegI() %{ 2558 constraint(ALLOC_IN_RC(R1_regI)); 2559 match(iRegI); 2560 2561 format %{ %} 2562 interface(REG_INTER); 2563 %} 2564 2565 operand R2RegI() %{ 2566 constraint(ALLOC_IN_RC(R2_regI)); 2567 match(iRegI); 2568 2569 format %{ %} 2570 interface(REG_INTER); 2571 %} 2572 2573 operand R3RegI() %{ 2574 constraint(ALLOC_IN_RC(R3_regI)); 2575 match(iRegI); 2576 2577 format %{ %} 2578 interface(REG_INTER); 2579 %} 2580 2581 #ifndef AARCH64 2582 operand R12RegI() %{ 2583 constraint(ALLOC_IN_RC(R12_regI)); 2584 match(iRegI); 2585 2586 format %{ %} 2587 interface(REG_INTER); 2588 %} 2589 #endif 2590 2591 // Long Register 2592 operand iRegL() %{ 2593 constraint(ALLOC_IN_RC(long_reg)); 2594 match(RegL); 2595 #ifdef AARCH64 2596 match(iRegLd); 2597 #else 2598 match(R0R1RegL); 2599 match(R2R3RegL); 2600 #endif 2601 //match(iRegLex); 2602 2603 format %{ %} 2604 interface(REG_INTER); 2605 %} 2606 2607 operand iRegLd() %{ 2608 constraint(ALLOC_IN_RC(long_reg_align)); 2609 match(iRegL); // FIXME: allows unaligned R11/R12? 2610 2611 format %{ %} 2612 interface(REG_INTER); 2613 %} 2614 2615 #ifndef AARCH64 2616 // first long arg, or return value 2617 operand R0R1RegL() %{ 2618 constraint(ALLOC_IN_RC(R0R1_regL)); 2619 match(iRegL); 2620 2621 format %{ %} 2622 interface(REG_INTER); 2623 %} 2624 2625 operand R2R3RegL() %{ 2626 constraint(ALLOC_IN_RC(R2R3_regL)); 2627 match(iRegL); 2628 2629 format %{ %} 2630 interface(REG_INTER); 2631 %} 2632 #endif 2633 2634 // Condition Code Flag Register 2635 operand flagsReg() %{ 2636 constraint(ALLOC_IN_RC(int_flags)); 2637 match(RegFlags); 2638 2639 format %{ "apsr" %} 2640 interface(REG_INTER); 2641 %} 2642 2643 // Result of compare to 0 (TST) 2644 operand flagsReg_EQNELTGE() %{ 2645 constraint(ALLOC_IN_RC(int_flags)); 2646 match(RegFlags); 2647 2648 format %{ "apsr_EQNELTGE" %} 2649 interface(REG_INTER); 2650 %} 2651 2652 // Condition Code Register, unsigned comparisons. 2653 operand flagsRegU() %{ 2654 constraint(ALLOC_IN_RC(int_flags)); 2655 match(RegFlags); 2656 #ifdef TODO 2657 match(RegFlagsP); 2658 #endif 2659 2660 format %{ "apsr_U" %} 2661 interface(REG_INTER); 2662 %} 2663 2664 // Condition Code Register, pointer comparisons. 2665 operand flagsRegP() %{ 2666 constraint(ALLOC_IN_RC(int_flags)); 2667 match(RegFlags); 2668 2669 format %{ "apsr_P" %} 2670 interface(REG_INTER); 2671 %} 2672 2673 // Condition Code Register, long comparisons. 2674 #ifndef AARCH64 2675 operand flagsRegL_LTGE() %{ 2676 constraint(ALLOC_IN_RC(int_flags)); 2677 match(RegFlags); 2678 2679 format %{ "apsr_L_LTGE" %} 2680 interface(REG_INTER); 2681 %} 2682 2683 operand flagsRegL_EQNE() %{ 2684 constraint(ALLOC_IN_RC(int_flags)); 2685 match(RegFlags); 2686 2687 format %{ "apsr_L_EQNE" %} 2688 interface(REG_INTER); 2689 %} 2690 2691 operand flagsRegL_LEGT() %{ 2692 constraint(ALLOC_IN_RC(int_flags)); 2693 match(RegFlags); 2694 2695 format %{ "apsr_L_LEGT" %} 2696 interface(REG_INTER); 2697 %} 2698 #endif 2699 2700 // Condition Code Register, floating comparisons, unordered same as "less". 2701 operand flagsRegF() %{ 2702 constraint(ALLOC_IN_RC(float_flags)); 2703 match(RegFlags); 2704 2705 format %{ "fpscr_F" %} 2706 interface(REG_INTER); 2707 %} 2708 2709 // Vectors 2710 operand vecD() %{ 2711 constraint(ALLOC_IN_RC(actual_dflt_reg)); 2712 match(VecD); 2713 2714 format %{ %} 2715 interface(REG_INTER); 2716 %} 2717 2718 operand vecX() %{ 2719 constraint(ALLOC_IN_RC(vectorx_reg)); 2720 match(VecX); 2721 2722 format %{ %} 2723 interface(REG_INTER); 2724 %} 2725 2726 operand regD() %{ 2727 constraint(ALLOC_IN_RC(actual_dflt_reg)); 2728 match(RegD); 2729 match(regD_low); 2730 2731 format %{ %} 2732 interface(REG_INTER); 2733 %} 2734 2735 operand regF() %{ 2736 constraint(ALLOC_IN_RC(sflt_reg)); 2737 match(RegF); 2738 2739 format %{ %} 2740 interface(REG_INTER); 2741 %} 2742 2743 operand regD_low() %{ 2744 constraint(ALLOC_IN_RC(dflt_low_reg)); 2745 match(RegD); 2746 2747 format %{ %} 2748 interface(REG_INTER); 2749 %} 2750 2751 // Special Registers 2752 2753 // Method Register 2754 operand inline_cache_regP(iRegP reg) %{ 2755 constraint(ALLOC_IN_RC(Ricklass_regP)); 2756 match(reg); 2757 format %{ %} 2758 interface(REG_INTER); 2759 %} 2760 2761 operand interpreter_method_oop_regP(iRegP reg) %{ 2762 constraint(ALLOC_IN_RC(Rmethod_regP)); 2763 match(reg); 2764 format %{ %} 2765 interface(REG_INTER); 2766 %} 2767 2768 2769 //----------Complex Operands--------------------------------------------------- 2770 // Indirect Memory Reference 2771 operand indirect(sp_ptr_RegP reg) %{ 2772 constraint(ALLOC_IN_RC(sp_ptr_reg)); 2773 match(reg); 2774 2775 op_cost(100); 2776 format %{ "[$reg]" %} 2777 interface(MEMORY_INTER) %{ 2778 base($reg); 2779 #ifdef AARCH64 2780 index(0xff); // 0xff => no index 2781 #else 2782 index(0xf); // PC => no index 2783 #endif 2784 scale(0x0); 2785 disp(0x0); 2786 %} 2787 %} 2788 2789 #ifdef AARCH64 2790 // Indirect with scaled*1 uimm12 offset 2791 operand indOffsetU12ScaleB(sp_ptr_RegP reg, immUL12 offset) %{ 2792 constraint(ALLOC_IN_RC(sp_ptr_reg)); 2793 match(AddP reg offset); 2794 2795 op_cost(100); 2796 format %{ "[$reg + $offset]" %} 2797 interface(MEMORY_INTER) %{ 2798 base($reg); 2799 #ifdef AARCH64 2800 index(0xff); // 0xff => no index 2801 #else 2802 index(0xf); // PC => no index 2803 #endif 2804 scale(0x0); 2805 disp($offset); 2806 %} 2807 %} 2808 2809 // Indirect with scaled*2 uimm12 offset 2810 operand indOffsetU12ScaleS(sp_ptr_RegP reg, immUL12x2 offset) %{ 2811 constraint(ALLOC_IN_RC(sp_ptr_reg)); 2812 match(AddP reg offset); 2813 2814 op_cost(100); 2815 format %{ "[$reg + $offset]" %} 2816 interface(MEMORY_INTER) %{ 2817 base($reg); 2818 #ifdef AARCH64 2819 index(0xff); // 0xff => no index 2820 #else 2821 index(0xf); // PC => no index 2822 #endif 2823 scale(0x0); 2824 disp($offset); 2825 %} 2826 %} 2827 2828 // Indirect with scaled*4 uimm12 offset 2829 operand indOffsetU12ScaleI(sp_ptr_RegP reg, immUL12x4 offset) %{ 2830 constraint(ALLOC_IN_RC(sp_ptr_reg)); 2831 match(AddP reg offset); 2832 2833 op_cost(100); 2834 format %{ "[$reg + $offset]" %} 2835 interface(MEMORY_INTER) %{ 2836 base($reg); 2837 #ifdef AARCH64 2838 index(0xff); // 0xff => no index 2839 #else 2840 index(0xf); // PC => no index 2841 #endif 2842 scale(0x0); 2843 disp($offset); 2844 %} 2845 %} 2846 2847 // Indirect with scaled*8 uimm12 offset 2848 operand indOffsetU12ScaleL(sp_ptr_RegP reg, immUL12x8 offset) %{ 2849 constraint(ALLOC_IN_RC(sp_ptr_reg)); 2850 match(AddP reg offset); 2851 2852 op_cost(100); 2853 format %{ "[$reg + $offset]" %} 2854 interface(MEMORY_INTER) %{ 2855 base($reg); 2856 #ifdef AARCH64 2857 index(0xff); // 0xff => no index 2858 #else 2859 index(0xf); // PC => no index 2860 #endif 2861 scale(0x0); 2862 disp($offset); 2863 %} 2864 %} 2865 2866 // Indirect with scaled*16 uimm12 offset 2867 operand indOffsetU12ScaleQ(sp_ptr_RegP reg, immUL12x16 offset) %{ 2868 constraint(ALLOC_IN_RC(sp_ptr_reg)); 2869 match(AddP reg offset); 2870 2871 op_cost(100); 2872 format %{ "[$reg + $offset]" %} 2873 interface(MEMORY_INTER) %{ 2874 base($reg); 2875 #ifdef AARCH64 2876 index(0xff); // 0xff => no index 2877 #else 2878 index(0xf); // PC => no index 2879 #endif 2880 scale(0x0); 2881 disp($offset); 2882 %} 2883 %} 2884 2885 #else // ! AARCH64 2886 2887 // Indirect with Offset in ]-4096, 4096[ 2888 operand indOffset12(sp_ptr_RegP reg, immI12 offset) %{ 2889 constraint(ALLOC_IN_RC(sp_ptr_reg)); 2890 match(AddP reg offset); 2891 2892 op_cost(100); 2893 format %{ "[$reg + $offset]" %} 2894 interface(MEMORY_INTER) %{ 2895 base($reg); 2896 #ifdef AARCH64 2897 index(0xff); // 0xff => no index 2898 #else 2899 index(0xf); // PC => no index 2900 #endif 2901 scale(0x0); 2902 disp($offset); 2903 %} 2904 %} 2905 2906 // Indirect with offset for float load/store 2907 operand indOffsetFP(sp_ptr_RegP reg, immIFP offset) %{ 2908 constraint(ALLOC_IN_RC(sp_ptr_reg)); 2909 match(AddP reg offset); 2910 2911 op_cost(100); 2912 format %{ "[$reg + $offset]" %} 2913 interface(MEMORY_INTER) %{ 2914 base($reg); 2915 #ifdef AARCH64 2916 index(0xff); // 0xff => no index 2917 #else 2918 index(0xf); // PC => no index 2919 #endif 2920 scale(0x0); 2921 disp($offset); 2922 %} 2923 %} 2924 2925 // Indirect with Offset for half and double words 2926 operand indOffsetHD(sp_ptr_RegP reg, immIHD offset) %{ 2927 constraint(ALLOC_IN_RC(sp_ptr_reg)); 2928 match(AddP reg offset); 2929 2930 op_cost(100); 2931 format %{ "[$reg + $offset]" %} 2932 interface(MEMORY_INTER) %{ 2933 base($reg); 2934 #ifdef AARCH64 2935 index(0xff); // 0xff => no index 2936 #else 2937 index(0xf); // PC => no index 2938 #endif 2939 scale(0x0); 2940 disp($offset); 2941 %} 2942 %} 2943 2944 // Indirect with Offset and Offset+4 in ]-1024, 1024[ 2945 operand indOffsetFPx2(sp_ptr_RegP reg, immX10x2 offset) %{ 2946 constraint(ALLOC_IN_RC(sp_ptr_reg)); 2947 match(AddP reg offset); 2948 2949 op_cost(100); 2950 format %{ "[$reg + $offset]" %} 2951 interface(MEMORY_INTER) %{ 2952 base($reg); 2953 #ifdef AARCH64 2954 index(0xff); // 0xff => no index 2955 #else 2956 index(0xf); // PC => no index 2957 #endif 2958 scale(0x0); 2959 disp($offset); 2960 %} 2961 %} 2962 2963 // Indirect with Offset and Offset+4 in ]-4096, 4096[ 2964 operand indOffset12x2(sp_ptr_RegP reg, immI12x2 offset) %{ 2965 constraint(ALLOC_IN_RC(sp_ptr_reg)); 2966 match(AddP reg offset); 2967 2968 op_cost(100); 2969 format %{ "[$reg + $offset]" %} 2970 interface(MEMORY_INTER) %{ 2971 base($reg); 2972 #ifdef AARCH64 2973 index(0xff); // 0xff => no index 2974 #else 2975 index(0xf); // PC => no index 2976 #endif 2977 scale(0x0); 2978 disp($offset); 2979 %} 2980 %} 2981 #endif // !AARCH64 2982 2983 // Indirect with Register Index 2984 operand indIndex(iRegP addr, iRegX index) %{ 2985 constraint(ALLOC_IN_RC(ptr_reg)); 2986 match(AddP addr index); 2987 2988 op_cost(100); 2989 format %{ "[$addr + $index]" %} 2990 interface(MEMORY_INTER) %{ 2991 base($addr); 2992 index($index); 2993 scale(0x0); 2994 disp(0x0); 2995 %} 2996 %} 2997 2998 #ifdef AARCH64 2999 // Indirect Memory Times Scale Plus Index Register 3000 operand indIndexScaleS(iRegP addr, iRegX index, immI_1 scale) %{ 3001 constraint(ALLOC_IN_RC(ptr_reg)); 3002 match(AddP addr (LShiftX index scale)); 3003 3004 op_cost(100); 3005 format %{"[$addr + $index << $scale]" %} 3006 interface(MEMORY_INTER) %{ 3007 base($addr); 3008 index($index); 3009 scale($scale); 3010 disp(0x0); 3011 %} 3012 %} 3013 3014 // Indirect Memory Times Scale Plus 32-bit Index Register 3015 operand indIndexIScaleS(iRegP addr, iRegI index, immI_1 scale) %{ 3016 constraint(ALLOC_IN_RC(ptr_reg)); 3017 match(AddP addr (LShiftX (ConvI2L index) scale)); 3018 3019 op_cost(100); 3020 format %{"[$addr + $index.w << $scale]" %} 3021 interface(MEMORY_INTER) %{ 3022 base($addr); 3023 index($index); 3024 scale($scale); 3025 disp(0x7fffffff); // sxtw 3026 %} 3027 %} 3028 3029 // Indirect Memory Times Scale Plus Index Register 3030 operand indIndexScaleI(iRegP addr, iRegX index, immI_2 scale) %{ 3031 constraint(ALLOC_IN_RC(ptr_reg)); 3032 match(AddP addr (LShiftX index scale)); 3033 3034 op_cost(100); 3035 format %{"[$addr + $index << $scale]" %} 3036 interface(MEMORY_INTER) %{ 3037 base($addr); 3038 index($index); 3039 scale($scale); 3040 disp(0x0); 3041 %} 3042 %} 3043 3044 // Indirect Memory Times Scale Plus 32-bit Index Register 3045 operand indIndexIScaleI(iRegP addr, iRegI index, immI_2 scale) %{ 3046 constraint(ALLOC_IN_RC(ptr_reg)); 3047 match(AddP addr (LShiftX (ConvI2L index) scale)); 3048 3049 op_cost(100); 3050 format %{"[$addr + $index.w << $scale]" %} 3051 interface(MEMORY_INTER) %{ 3052 base($addr); 3053 index($index); 3054 scale($scale); 3055 disp(0x7fffffff); // sxtw 3056 %} 3057 %} 3058 3059 // Indirect Memory Times Scale Plus Index Register 3060 operand indIndexScaleL(iRegP addr, iRegX index, immI_3 scale) %{ 3061 constraint(ALLOC_IN_RC(ptr_reg)); 3062 match(AddP addr (LShiftX index scale)); 3063 3064 op_cost(100); 3065 format %{"[$addr + $index << $scale]" %} 3066 interface(MEMORY_INTER) %{ 3067 base($addr); 3068 index($index); 3069 scale($scale); 3070 disp(0x0); 3071 %} 3072 %} 3073 3074 // Indirect Memory Times Scale Plus 32-bit Index Register 3075 operand indIndexIScaleL(iRegP addr, iRegI index, immI_3 scale) %{ 3076 constraint(ALLOC_IN_RC(ptr_reg)); 3077 match(AddP addr (LShiftX (ConvI2L index) scale)); 3078 3079 op_cost(100); 3080 format %{"[$addr + $index.w << $scale]" %} 3081 interface(MEMORY_INTER) %{ 3082 base($addr); 3083 index($index); 3084 scale($scale); 3085 disp(0x7fffffff); // sxtw 3086 %} 3087 %} 3088 3089 // Indirect Memory Times Scale Plus Index Register 3090 operand indIndexScaleQ(iRegP addr, iRegX index, immI_4 scale) %{ 3091 constraint(ALLOC_IN_RC(ptr_reg)); 3092 match(AddP addr (LShiftX index scale)); 3093 3094 op_cost(100); 3095 format %{"[$addr + $index << $scale]" %} 3096 interface(MEMORY_INTER) %{ 3097 base($addr); 3098 index($index); 3099 scale($scale); 3100 disp(0x0); 3101 %} 3102 %} 3103 3104 // Indirect Memory Times Scale Plus 32-bit Index Register 3105 operand indIndexIScaleQ(iRegP addr, iRegI index, immI_4 scale) %{ 3106 constraint(ALLOC_IN_RC(ptr_reg)); 3107 match(AddP addr (LShiftX (ConvI2L index) scale)); 3108 3109 op_cost(100); 3110 format %{"[$addr + $index.w << $scale]" %} 3111 interface(MEMORY_INTER) %{ 3112 base($addr); 3113 index($index); 3114 scale($scale); 3115 disp(0x7fffffff); // sxtw 3116 %} 3117 %} 3118 #else 3119 // Indirect Memory Times Scale Plus Index Register 3120 operand indIndexScale(iRegP addr, iRegX index, immU5 scale) %{ 3121 constraint(ALLOC_IN_RC(ptr_reg)); 3122 match(AddP addr (LShiftX index scale)); 3123 3124 op_cost(100); 3125 format %{"[$addr + $index << $scale]" %} 3126 interface(MEMORY_INTER) %{ 3127 base($addr); 3128 index($index); 3129 scale($scale); 3130 disp(0x0); 3131 %} 3132 %} 3133 #endif 3134 3135 // Operands for expressing Control Flow 3136 // NOTE: Label is a predefined operand which should not be redefined in 3137 // the AD file. It is generically handled within the ADLC. 3138 3139 //----------Conditional Branch Operands---------------------------------------- 3140 // Comparison Op - This is the operation of the comparison, and is limited to 3141 // the following set of codes: 3142 // L (<), LE (<=), G (>), GE (>=), E (==), NE (!=) 3143 // 3144 // Other attributes of the comparison, such as unsignedness, are specified 3145 // by the comparison instruction that sets a condition code flags register. 3146 // That result is represented by a flags operand whose subtype is appropriate 3147 // to the unsignedness (etc.) of the comparison. 3148 // 3149 // Later, the instruction which matches both the Comparison Op (a Bool) and 3150 // the flags (produced by the Cmp) specifies the coding of the comparison op 3151 // by matching a specific subtype of Bool operand below, such as cmpOpU. 3152 3153 operand cmpOp() %{ 3154 match(Bool); 3155 3156 format %{ "" %} 3157 interface(COND_INTER) %{ 3158 equal(0x0); 3159 not_equal(0x1); 3160 less(0xb); 3161 greater_equal(0xa); 3162 less_equal(0xd); 3163 greater(0xc); 3164 overflow(0x0); // unsupported/unimplemented 3165 no_overflow(0x0); // unsupported/unimplemented 3166 %} 3167 %} 3168 3169 // integer comparison with 0, signed 3170 operand cmpOp0() %{ 3171 match(Bool); 3172 3173 format %{ "" %} 3174 interface(COND_INTER) %{ 3175 equal(0x0); 3176 not_equal(0x1); 3177 less(0x4); 3178 greater_equal(0x5); 3179 less_equal(0xd); // unsupported 3180 greater(0xc); // unsupported 3181 overflow(0x0); // unsupported/unimplemented 3182 no_overflow(0x0); // unsupported/unimplemented 3183 %} 3184 %} 3185 3186 // Comparison Op, unsigned 3187 operand cmpOpU() %{ 3188 match(Bool); 3189 3190 format %{ "u" %} 3191 interface(COND_INTER) %{ 3192 equal(0x0); 3193 not_equal(0x1); 3194 less(0x3); 3195 greater_equal(0x2); 3196 less_equal(0x9); 3197 greater(0x8); 3198 overflow(0x0); // unsupported/unimplemented 3199 no_overflow(0x0); // unsupported/unimplemented 3200 %} 3201 %} 3202 3203 // Comparison Op, pointer (same as unsigned) 3204 operand cmpOpP() %{ 3205 match(Bool); 3206 3207 format %{ "p" %} 3208 interface(COND_INTER) %{ 3209 equal(0x0); 3210 not_equal(0x1); 3211 less(0x3); 3212 greater_equal(0x2); 3213 less_equal(0x9); 3214 greater(0x8); 3215 overflow(0x0); // unsupported/unimplemented 3216 no_overflow(0x0); // unsupported/unimplemented 3217 %} 3218 %} 3219 3220 operand cmpOpL() %{ 3221 match(Bool); 3222 3223 format %{ "L" %} 3224 interface(COND_INTER) %{ 3225 equal(0x0); 3226 not_equal(0x1); 3227 less(0xb); 3228 greater_equal(0xa); 3229 less_equal(0xd); 3230 greater(0xc); 3231 overflow(0x0); // unsupported/unimplemented 3232 no_overflow(0x0); // unsupported/unimplemented 3233 %} 3234 %} 3235 3236 operand cmpOpL_commute() %{ 3237 match(Bool); 3238 3239 format %{ "L" %} 3240 interface(COND_INTER) %{ 3241 equal(0x0); 3242 not_equal(0x1); 3243 less(0xc); 3244 greater_equal(0xd); 3245 less_equal(0xa); 3246 greater(0xb); 3247 overflow(0x0); // unsupported/unimplemented 3248 no_overflow(0x0); // unsupported/unimplemented 3249 %} 3250 %} 3251 3252 //----------OPERAND CLASSES---------------------------------------------------- 3253 // Operand Classes are groups of operands that are used to simplify 3254 // instruction definitions by not requiring the AD writer to specify separate 3255 // instructions for every form of operand when the instruction accepts 3256 // multiple operand types with the same basic encoding and format. The classic 3257 // case of this is memory operands. 3258 #ifdef AARCH64 3259 opclass memoryB(indirect, indIndex, indOffsetU12ScaleB); 3260 opclass memoryS(indirect, indIndex, indIndexScaleS, indIndexIScaleS, indOffsetU12ScaleS); 3261 opclass memoryI(indirect, indIndex, indIndexScaleI, indIndexIScaleI, indOffsetU12ScaleI); 3262 opclass memoryL(indirect, indIndex, indIndexScaleL, indIndexIScaleL, indOffsetU12ScaleL); 3263 opclass memoryP(indirect, indIndex, indIndexScaleL, indIndexIScaleL, indOffsetU12ScaleL); 3264 opclass memoryQ(indirect, indIndex, indIndexScaleQ, indIndexIScaleQ, indOffsetU12ScaleQ); 3265 opclass memoryF(indirect, indIndex, indIndexScaleI, indIndexIScaleI, indOffsetU12ScaleI); 3266 opclass memoryD(indirect, indIndex, indIndexScaleL, indIndexIScaleL, indOffsetU12ScaleL); 3267 3268 opclass memoryScaledS(indIndexScaleS, indIndexIScaleS); 3269 opclass memoryScaledI(indIndexScaleI, indIndexIScaleI); 3270 opclass memoryScaledL(indIndexScaleL, indIndexIScaleL); 3271 opclass memoryScaledP(indIndexScaleL, indIndexIScaleL); 3272 opclass memoryScaledQ(indIndexScaleQ, indIndexIScaleQ); 3273 opclass memoryScaledF(indIndexScaleI, indIndexIScaleI); 3274 opclass memoryScaledD(indIndexScaleL, indIndexIScaleL); 3275 // when ldrex/strex is used: 3276 opclass memoryex ( indirect ); 3277 opclass indIndexMemory( indIndex ); 3278 opclass memoryvld ( indirect /* , write back mode not implemented */ ); 3279 3280 #else 3281 3282 opclass memoryI ( indirect, indOffset12, indIndex, indIndexScale ); 3283 opclass memoryP ( indirect, indOffset12, indIndex, indIndexScale ); 3284 opclass memoryF ( indirect, indOffsetFP ); 3285 opclass memoryF2 ( indirect, indOffsetFPx2 ); 3286 opclass memoryD ( indirect, indOffsetFP ); 3287 opclass memoryfp( indirect, indOffsetFP ); 3288 opclass memoryB ( indirect, indIndex, indOffsetHD ); 3289 opclass memoryS ( indirect, indIndex, indOffsetHD ); 3290 opclass memoryL ( indirect, indIndex, indOffsetHD ); 3291 3292 opclass memoryScaledI(indIndexScale); 3293 opclass memoryScaledP(indIndexScale); 3294 3295 // when ldrex/strex is used: 3296 opclass memoryex ( indirect ); 3297 opclass indIndexMemory( indIndex ); 3298 opclass memorylong ( indirect, indOffset12x2 ); 3299 opclass memoryvld ( indirect /* , write back mode not implemented */ ); 3300 #endif 3301 3302 //----------PIPELINE----------------------------------------------------------- 3303 pipeline %{ 3304 3305 //----------ATTRIBUTES--------------------------------------------------------- 3306 attributes %{ 3307 fixed_size_instructions; // Fixed size instructions 3308 max_instructions_per_bundle = 4; // Up to 4 instructions per bundle 3309 instruction_unit_size = 4; // An instruction is 4 bytes long 3310 instruction_fetch_unit_size = 16; // The processor fetches one line 3311 instruction_fetch_units = 1; // of 16 bytes 3312 3313 // List of nop instructions 3314 nops( Nop_A0, Nop_A1, Nop_MS, Nop_FA, Nop_BR ); 3315 %} 3316 3317 //----------RESOURCES---------------------------------------------------------- 3318 // Resources are the functional units available to the machine 3319 resources(A0, A1, MS, BR, FA, FM, IDIV, FDIV, IALU = A0 | A1); 3320 3321 //----------PIPELINE DESCRIPTION----------------------------------------------- 3322 // Pipeline Description specifies the stages in the machine's pipeline 3323 3324 pipe_desc(A, P, F, B, I, J, S, R, E, C, M, W, X, T, D); 3325 3326 //----------PIPELINE CLASSES--------------------------------------------------- 3327 // Pipeline Classes describe the stages in which input and output are 3328 // referenced by the hardware pipeline. 3329 3330 // Integer ALU reg-reg operation 3331 pipe_class ialu_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{ 3332 single_instruction; 3333 dst : E(write); 3334 src1 : R(read); 3335 src2 : R(read); 3336 IALU : R; 3337 %} 3338 3339 // Integer ALU reg-reg long operation 3340 pipe_class ialu_reg_reg_2(iRegL dst, iRegL src1, iRegL src2) %{ 3341 instruction_count(2); 3342 dst : E(write); 3343 src1 : R(read); 3344 src2 : R(read); 3345 IALU : R; 3346 IALU : R; 3347 %} 3348 3349 // Integer ALU reg-reg long dependent operation 3350 pipe_class ialu_reg_reg_2_dep(iRegL dst, iRegL src1, iRegL src2, flagsReg cr) %{ 3351 instruction_count(1); multiple_bundles; 3352 dst : E(write); 3353 src1 : R(read); 3354 src2 : R(read); 3355 cr : E(write); 3356 IALU : R(2); 3357 %} 3358 3359 // Integer ALU reg-imm operaion 3360 pipe_class ialu_reg_imm(iRegI dst, iRegI src1) %{ 3361 single_instruction; 3362 dst : E(write); 3363 src1 : R(read); 3364 IALU : R; 3365 %} 3366 3367 // Integer ALU reg-reg operation with condition code 3368 pipe_class ialu_cc_reg_reg(iRegI dst, iRegI src1, iRegI src2, flagsReg cr) %{ 3369 single_instruction; 3370 dst : E(write); 3371 cr : E(write); 3372 src1 : R(read); 3373 src2 : R(read); 3374 IALU : R; 3375 %} 3376 3377 // Integer ALU zero-reg operation 3378 pipe_class ialu_zero_reg(iRegI dst, immI0 zero, iRegI src2) %{ 3379 single_instruction; 3380 dst : E(write); 3381 src2 : R(read); 3382 IALU : R; 3383 %} 3384 3385 // Integer ALU zero-reg operation with condition code only 3386 pipe_class ialu_cconly_zero_reg(flagsReg cr, iRegI src) %{ 3387 single_instruction; 3388 cr : E(write); 3389 src : R(read); 3390 IALU : R; 3391 %} 3392 3393 // Integer ALU reg-reg operation with condition code only 3394 pipe_class ialu_cconly_reg_reg(flagsReg cr, iRegI src1, iRegI src2) %{ 3395 single_instruction; 3396 cr : E(write); 3397 src1 : R(read); 3398 src2 : R(read); 3399 IALU : R; 3400 %} 3401 3402 // Integer ALU reg-imm operation with condition code only 3403 pipe_class ialu_cconly_reg_imm(flagsReg cr, iRegI src1) %{ 3404 single_instruction; 3405 cr : E(write); 3406 src1 : R(read); 3407 IALU : R; 3408 %} 3409 3410 // Integer ALU reg-reg-zero operation with condition code only 3411 pipe_class ialu_cconly_reg_reg_zero(flagsReg cr, iRegI src1, iRegI src2, immI0 zero) %{ 3412 single_instruction; 3413 cr : E(write); 3414 src1 : R(read); 3415 src2 : R(read); 3416 IALU : R; 3417 %} 3418 3419 // Integer ALU reg-imm-zero operation with condition code only 3420 pipe_class ialu_cconly_reg_imm_zero(flagsReg cr, iRegI src1, immI0 zero) %{ 3421 single_instruction; 3422 cr : E(write); 3423 src1 : R(read); 3424 IALU : R; 3425 %} 3426 3427 // Integer ALU reg-reg operation with condition code, src1 modified 3428 pipe_class ialu_cc_rwreg_reg(flagsReg cr, iRegI src1, iRegI src2) %{ 3429 single_instruction; 3430 cr : E(write); 3431 src1 : E(write); 3432 src1 : R(read); 3433 src2 : R(read); 3434 IALU : R; 3435 %} 3436 3437 pipe_class cmpL_reg(iRegI dst, iRegL src1, iRegL src2, flagsReg cr ) %{ 3438 multiple_bundles; 3439 dst : E(write)+4; 3440 cr : E(write); 3441 src1 : R(read); 3442 src2 : R(read); 3443 IALU : R(3); 3444 BR : R(2); 3445 %} 3446 3447 // Integer ALU operation 3448 pipe_class ialu_none(iRegI dst) %{ 3449 single_instruction; 3450 dst : E(write); 3451 IALU : R; 3452 %} 3453 3454 // Integer ALU reg operation 3455 pipe_class ialu_reg(iRegI dst, iRegI src) %{ 3456 single_instruction; may_have_no_code; 3457 dst : E(write); 3458 src : R(read); 3459 IALU : R; 3460 %} 3461 3462 // Integer ALU reg conditional operation 3463 // This instruction has a 1 cycle stall, and cannot execute 3464 // in the same cycle as the instruction setting the condition 3465 // code. We kludge this by pretending to read the condition code 3466 // 1 cycle earlier, and by marking the functional units as busy 3467 // for 2 cycles with the result available 1 cycle later than 3468 // is really the case. 3469 pipe_class ialu_reg_flags( iRegI op2_out, iRegI op2_in, iRegI op1, flagsReg cr ) %{ 3470 single_instruction; 3471 op2_out : C(write); 3472 op1 : R(read); 3473 cr : R(read); // This is really E, with a 1 cycle stall 3474 BR : R(2); 3475 MS : R(2); 3476 %} 3477 3478 // Integer ALU reg operation 3479 pipe_class ialu_move_reg_L_to_I(iRegI dst, iRegL src) %{ 3480 single_instruction; may_have_no_code; 3481 dst : E(write); 3482 src : R(read); 3483 IALU : R; 3484 %} 3485 pipe_class ialu_move_reg_I_to_L(iRegL dst, iRegI src) %{ 3486 single_instruction; may_have_no_code; 3487 dst : E(write); 3488 src : R(read); 3489 IALU : R; 3490 %} 3491 3492 // Two integer ALU reg operations 3493 pipe_class ialu_reg_2(iRegL dst, iRegL src) %{ 3494 instruction_count(2); 3495 dst : E(write); 3496 src : R(read); 3497 A0 : R; 3498 A1 : R; 3499 %} 3500 3501 // Two integer ALU reg operations 3502 pipe_class ialu_move_reg_L_to_L(iRegL dst, iRegL src) %{ 3503 instruction_count(2); may_have_no_code; 3504 dst : E(write); 3505 src : R(read); 3506 A0 : R; 3507 A1 : R; 3508 %} 3509 3510 // Integer ALU imm operation 3511 pipe_class ialu_imm(iRegI dst) %{ 3512 single_instruction; 3513 dst : E(write); 3514 IALU : R; 3515 %} 3516 3517 pipe_class ialu_imm_n(iRegI dst) %{ 3518 single_instruction; 3519 dst : E(write); 3520 IALU : R; 3521 %} 3522 3523 // Integer ALU reg-reg with carry operation 3524 pipe_class ialu_reg_reg_cy(iRegI dst, iRegI src1, iRegI src2, iRegI cy) %{ 3525 single_instruction; 3526 dst : E(write); 3527 src1 : R(read); 3528 src2 : R(read); 3529 IALU : R; 3530 %} 3531 3532 // Integer ALU cc operation 3533 pipe_class ialu_cc(iRegI dst, flagsReg cc) %{ 3534 single_instruction; 3535 dst : E(write); 3536 cc : R(read); 3537 IALU : R; 3538 %} 3539 3540 // Integer ALU cc / second IALU operation 3541 pipe_class ialu_reg_ialu( iRegI dst, iRegI src ) %{ 3542 instruction_count(1); multiple_bundles; 3543 dst : E(write)+1; 3544 src : R(read); 3545 IALU : R; 3546 %} 3547 3548 // Integer ALU cc / second IALU operation 3549 pipe_class ialu_reg_reg_ialu( iRegI dst, iRegI p, iRegI q ) %{ 3550 instruction_count(1); multiple_bundles; 3551 dst : E(write)+1; 3552 p : R(read); 3553 q : R(read); 3554 IALU : R; 3555 %} 3556 3557 // Integer ALU hi-lo-reg operation 3558 pipe_class ialu_hi_lo_reg(iRegI dst, immI src) %{ 3559 instruction_count(1); multiple_bundles; 3560 dst : E(write)+1; 3561 IALU : R(2); 3562 %} 3563 3564 // Long Constant 3565 pipe_class loadConL( iRegL dst, immL src ) %{ 3566 instruction_count(2); multiple_bundles; 3567 dst : E(write)+1; 3568 IALU : R(2); 3569 IALU : R(2); 3570 %} 3571 3572 // Pointer Constant 3573 pipe_class loadConP( iRegP dst, immP src ) %{ 3574 instruction_count(0); multiple_bundles; 3575 fixed_latency(6); 3576 %} 3577 3578 // Polling Address 3579 pipe_class loadConP_poll( iRegP dst, immP_poll src ) %{ 3580 dst : E(write); 3581 IALU : R; 3582 %} 3583 3584 // Long Constant small 3585 pipe_class loadConLlo( iRegL dst, immL src ) %{ 3586 instruction_count(2); 3587 dst : E(write); 3588 IALU : R; 3589 IALU : R; 3590 %} 3591 3592 // [PHH] This is wrong for 64-bit. See LdImmF/D. 3593 pipe_class loadConFD(regF dst, immF src, iRegP tmp) %{ 3594 instruction_count(1); multiple_bundles; 3595 src : R(read); 3596 dst : M(write)+1; 3597 IALU : R; 3598 MS : E; 3599 %} 3600 3601 // Integer ALU nop operation 3602 pipe_class ialu_nop() %{ 3603 single_instruction; 3604 IALU : R; 3605 %} 3606 3607 // Integer ALU nop operation 3608 pipe_class ialu_nop_A0() %{ 3609 single_instruction; 3610 A0 : R; 3611 %} 3612 3613 // Integer ALU nop operation 3614 pipe_class ialu_nop_A1() %{ 3615 single_instruction; 3616 A1 : R; 3617 %} 3618 3619 // Integer Multiply reg-reg operation 3620 pipe_class imul_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{ 3621 single_instruction; 3622 dst : E(write); 3623 src1 : R(read); 3624 src2 : R(read); 3625 MS : R(5); 3626 %} 3627 3628 pipe_class mulL_reg_reg(iRegL dst, iRegL src1, iRegL src2) %{ 3629 single_instruction; 3630 dst : E(write)+4; 3631 src1 : R(read); 3632 src2 : R(read); 3633 MS : R(6); 3634 %} 3635 3636 // Integer Divide reg-reg 3637 pipe_class sdiv_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI temp, flagsReg cr) %{ 3638 instruction_count(1); multiple_bundles; 3639 dst : E(write); 3640 temp : E(write); 3641 src1 : R(read); 3642 src2 : R(read); 3643 temp : R(read); 3644 MS : R(38); 3645 %} 3646 3647 // Long Divide 3648 pipe_class divL_reg_reg(iRegL dst, iRegL src1, iRegL src2) %{ 3649 dst : E(write)+71; 3650 src1 : R(read); 3651 src2 : R(read)+1; 3652 MS : R(70); 3653 %} 3654 3655 // Floating Point Add Float 3656 pipe_class faddF_reg_reg(regF dst, regF src1, regF src2) %{ 3657 single_instruction; 3658 dst : X(write); 3659 src1 : E(read); 3660 src2 : E(read); 3661 FA : R; 3662 %} 3663 3664 // Floating Point Add Double 3665 pipe_class faddD_reg_reg(regD dst, regD src1, regD src2) %{ 3666 single_instruction; 3667 dst : X(write); 3668 src1 : E(read); 3669 src2 : E(read); 3670 FA : R; 3671 %} 3672 3673 // Floating Point Conditional Move based on integer flags 3674 pipe_class int_conditional_float_move (cmpOp cmp, flagsReg cr, regF dst, regF src) %{ 3675 single_instruction; 3676 dst : X(write); 3677 src : E(read); 3678 cr : R(read); 3679 FA : R(2); 3680 BR : R(2); 3681 %} 3682 3683 // Floating Point Conditional Move based on integer flags 3684 pipe_class int_conditional_double_move (cmpOp cmp, flagsReg cr, regD dst, regD src) %{ 3685 single_instruction; 3686 dst : X(write); 3687 src : E(read); 3688 cr : R(read); 3689 FA : R(2); 3690 BR : R(2); 3691 %} 3692 3693 // Floating Point Multiply Float 3694 pipe_class fmulF_reg_reg(regF dst, regF src1, regF src2) %{ 3695 single_instruction; 3696 dst : X(write); 3697 src1 : E(read); 3698 src2 : E(read); 3699 FM : R; 3700 %} 3701 3702 // Floating Point Multiply Double 3703 pipe_class fmulD_reg_reg(regD dst, regD src1, regD src2) %{ 3704 single_instruction; 3705 dst : X(write); 3706 src1 : E(read); 3707 src2 : E(read); 3708 FM : R; 3709 %} 3710 3711 // Floating Point Divide Float 3712 pipe_class fdivF_reg_reg(regF dst, regF src1, regF src2) %{ 3713 single_instruction; 3714 dst : X(write); 3715 src1 : E(read); 3716 src2 : E(read); 3717 FM : R; 3718 FDIV : C(14); 3719 %} 3720 3721 // Floating Point Divide Double 3722 pipe_class fdivD_reg_reg(regD dst, regD src1, regD src2) %{ 3723 single_instruction; 3724 dst : X(write); 3725 src1 : E(read); 3726 src2 : E(read); 3727 FM : R; 3728 FDIV : C(17); 3729 %} 3730 3731 // Floating Point Move/Negate/Abs Float 3732 pipe_class faddF_reg(regF dst, regF src) %{ 3733 single_instruction; 3734 dst : W(write); 3735 src : E(read); 3736 FA : R(1); 3737 %} 3738 3739 // Floating Point Move/Negate/Abs Double 3740 pipe_class faddD_reg(regD dst, regD src) %{ 3741 single_instruction; 3742 dst : W(write); 3743 src : E(read); 3744 FA : R; 3745 %} 3746 3747 // Floating Point Convert F->D 3748 pipe_class fcvtF2D(regD dst, regF src) %{ 3749 single_instruction; 3750 dst : X(write); 3751 src : E(read); 3752 FA : R; 3753 %} 3754 3755 // Floating Point Convert I->D 3756 pipe_class fcvtI2D(regD dst, regF src) %{ 3757 single_instruction; 3758 dst : X(write); 3759 src : E(read); 3760 FA : R; 3761 %} 3762 3763 // Floating Point Convert LHi->D 3764 pipe_class fcvtLHi2D(regD dst, regD src) %{ 3765 single_instruction; 3766 dst : X(write); 3767 src : E(read); 3768 FA : R; 3769 %} 3770 3771 // Floating Point Convert L->D 3772 pipe_class fcvtL2D(regD dst, iRegL src) %{ 3773 single_instruction; 3774 dst : X(write); 3775 src : E(read); 3776 FA : R; 3777 %} 3778 3779 // Floating Point Convert L->F 3780 pipe_class fcvtL2F(regF dst, iRegL src) %{ 3781 single_instruction; 3782 dst : X(write); 3783 src : E(read); 3784 FA : R; 3785 %} 3786 3787 // Floating Point Convert D->F 3788 pipe_class fcvtD2F(regD dst, regF src) %{ 3789 single_instruction; 3790 dst : X(write); 3791 src : E(read); 3792 FA : R; 3793 %} 3794 3795 // Floating Point Convert I->L 3796 pipe_class fcvtI2L(regD dst, regF src) %{ 3797 single_instruction; 3798 dst : X(write); 3799 src : E(read); 3800 FA : R; 3801 %} 3802 3803 // Floating Point Convert D->F 3804 pipe_class fcvtD2I(iRegI dst, regD src, flagsReg cr) %{ 3805 instruction_count(1); multiple_bundles; 3806 dst : X(write)+6; 3807 src : E(read); 3808 FA : R; 3809 %} 3810 3811 // Floating Point Convert D->L 3812 pipe_class fcvtD2L(regD dst, regD src, flagsReg cr) %{ 3813 instruction_count(1); multiple_bundles; 3814 dst : X(write)+6; 3815 src : E(read); 3816 FA : R; 3817 %} 3818 3819 // Floating Point Convert F->I 3820 pipe_class fcvtF2I(regF dst, regF src, flagsReg cr) %{ 3821 instruction_count(1); multiple_bundles; 3822 dst : X(write)+6; 3823 src : E(read); 3824 FA : R; 3825 %} 3826 3827 // Floating Point Convert F->L 3828 pipe_class fcvtF2L(regD dst, regF src, flagsReg cr) %{ 3829 instruction_count(1); multiple_bundles; 3830 dst : X(write)+6; 3831 src : E(read); 3832 FA : R; 3833 %} 3834 3835 // Floating Point Convert I->F 3836 pipe_class fcvtI2F(regF dst, regF src) %{ 3837 single_instruction; 3838 dst : X(write); 3839 src : E(read); 3840 FA : R; 3841 %} 3842 3843 // Floating Point Compare 3844 pipe_class faddF_fcc_reg_reg_zero(flagsRegF cr, regF src1, regF src2, immI0 zero) %{ 3845 single_instruction; 3846 cr : X(write); 3847 src1 : E(read); 3848 src2 : E(read); 3849 FA : R; 3850 %} 3851 3852 // Floating Point Compare 3853 pipe_class faddD_fcc_reg_reg_zero(flagsRegF cr, regD src1, regD src2, immI0 zero) %{ 3854 single_instruction; 3855 cr : X(write); 3856 src1 : E(read); 3857 src2 : E(read); 3858 FA : R; 3859 %} 3860 3861 // Floating Add Nop 3862 pipe_class fadd_nop() %{ 3863 single_instruction; 3864 FA : R; 3865 %} 3866 3867 // Integer Store to Memory 3868 pipe_class istore_mem_reg(memoryI mem, iRegI src) %{ 3869 single_instruction; 3870 mem : R(read); 3871 src : C(read); 3872 MS : R; 3873 %} 3874 3875 // Integer Store to Memory 3876 pipe_class istore_mem_spORreg(memoryI mem, sp_ptr_RegP src) %{ 3877 single_instruction; 3878 mem : R(read); 3879 src : C(read); 3880 MS : R; 3881 %} 3882 3883 // Float Store 3884 pipe_class fstoreF_mem_reg(memoryF mem, RegF src) %{ 3885 single_instruction; 3886 mem : R(read); 3887 src : C(read); 3888 MS : R; 3889 %} 3890 3891 // Float Store 3892 pipe_class fstoreF_mem_zero(memoryF mem, immF0 src) %{ 3893 single_instruction; 3894 mem : R(read); 3895 MS : R; 3896 %} 3897 3898 // Double Store 3899 pipe_class fstoreD_mem_reg(memoryD mem, RegD src) %{ 3900 instruction_count(1); 3901 mem : R(read); 3902 src : C(read); 3903 MS : R; 3904 %} 3905 3906 // Double Store 3907 pipe_class fstoreD_mem_zero(memoryD mem, immD0 src) %{ 3908 single_instruction; 3909 mem : R(read); 3910 MS : R; 3911 %} 3912 3913 // Integer Load (when sign bit propagation not needed) 3914 pipe_class iload_mem(iRegI dst, memoryI mem) %{ 3915 single_instruction; 3916 mem : R(read); 3917 dst : C(write); 3918 MS : R; 3919 %} 3920 3921 // Integer Load (when sign bit propagation or masking is needed) 3922 pipe_class iload_mask_mem(iRegI dst, memoryI mem) %{ 3923 single_instruction; 3924 mem : R(read); 3925 dst : M(write); 3926 MS : R; 3927 %} 3928 3929 // Float Load 3930 pipe_class floadF_mem(regF dst, memoryF mem) %{ 3931 single_instruction; 3932 mem : R(read); 3933 dst : M(write); 3934 MS : R; 3935 %} 3936 3937 // Float Load 3938 pipe_class floadD_mem(regD dst, memoryD mem) %{ 3939 instruction_count(1); multiple_bundles; // Again, unaligned argument is only multiple case 3940 mem : R(read); 3941 dst : M(write); 3942 MS : R; 3943 %} 3944 3945 // Memory Nop 3946 pipe_class mem_nop() %{ 3947 single_instruction; 3948 MS : R; 3949 %} 3950 3951 pipe_class sethi(iRegP dst, immI src) %{ 3952 single_instruction; 3953 dst : E(write); 3954 IALU : R; 3955 %} 3956 3957 pipe_class loadPollP(iRegP poll) %{ 3958 single_instruction; 3959 poll : R(read); 3960 MS : R; 3961 %} 3962 3963 pipe_class br(Universe br, label labl) %{ 3964 single_instruction_with_delay_slot; 3965 BR : R; 3966 %} 3967 3968 pipe_class br_cc(Universe br, cmpOp cmp, flagsReg cr, label labl) %{ 3969 single_instruction_with_delay_slot; 3970 cr : E(read); 3971 BR : R; 3972 %} 3973 3974 pipe_class br_reg(Universe br, cmpOp cmp, iRegI op1, label labl) %{ 3975 single_instruction_with_delay_slot; 3976 op1 : E(read); 3977 BR : R; 3978 MS : R; 3979 %} 3980 3981 pipe_class br_nop() %{ 3982 single_instruction; 3983 BR : R; 3984 %} 3985 3986 pipe_class simple_call(method meth) %{ 3987 instruction_count(2); multiple_bundles; force_serialization; 3988 fixed_latency(100); 3989 BR : R(1); 3990 MS : R(1); 3991 A0 : R(1); 3992 %} 3993 3994 pipe_class compiled_call(method meth) %{ 3995 instruction_count(1); multiple_bundles; force_serialization; 3996 fixed_latency(100); 3997 MS : R(1); 3998 %} 3999 4000 pipe_class call(method meth) %{ 4001 instruction_count(0); multiple_bundles; force_serialization; 4002 fixed_latency(100); 4003 %} 4004 4005 pipe_class tail_call(Universe ignore, label labl) %{ 4006 single_instruction; has_delay_slot; 4007 fixed_latency(100); 4008 BR : R(1); 4009 MS : R(1); 4010 %} 4011 4012 pipe_class ret(Universe ignore) %{ 4013 single_instruction; has_delay_slot; 4014 BR : R(1); 4015 MS : R(1); 4016 %} 4017 4018 // The real do-nothing guy 4019 pipe_class empty( ) %{ 4020 instruction_count(0); 4021 %} 4022 4023 pipe_class long_memory_op() %{ 4024 instruction_count(0); multiple_bundles; force_serialization; 4025 fixed_latency(25); 4026 MS : R(1); 4027 %} 4028 4029 // Check-cast 4030 pipe_class partial_subtype_check_pipe(Universe ignore, iRegP array, iRegP match ) %{ 4031 array : R(read); 4032 match : R(read); 4033 IALU : R(2); 4034 BR : R(2); 4035 MS : R; 4036 %} 4037 4038 // Convert FPU flags into +1,0,-1 4039 pipe_class floating_cmp( iRegI dst, regF src1, regF src2 ) %{ 4040 src1 : E(read); 4041 src2 : E(read); 4042 dst : E(write); 4043 FA : R; 4044 MS : R(2); 4045 BR : R(2); 4046 %} 4047 4048 // Compare for p < q, and conditionally add y 4049 pipe_class cadd_cmpltmask( iRegI p, iRegI q, iRegI y ) %{ 4050 p : E(read); 4051 q : E(read); 4052 y : E(read); 4053 IALU : R(3) 4054 %} 4055 4056 // Perform a compare, then move conditionally in a branch delay slot. 4057 pipe_class min_max( iRegI src2, iRegI srcdst ) %{ 4058 src2 : E(read); 4059 srcdst : E(read); 4060 IALU : R; 4061 BR : R; 4062 %} 4063 4064 // Define the class for the Nop node 4065 define %{ 4066 MachNop = ialu_nop; 4067 %} 4068 4069 %} 4070 4071 //----------INSTRUCTIONS------------------------------------------------------- 4072 4073 //------------Special Nop instructions for bundling - no match rules----------- 4074 // Nop using the A0 functional unit 4075 instruct Nop_A0() %{ 4076 ins_pipe(ialu_nop_A0); 4077 %} 4078 4079 // Nop using the A1 functional unit 4080 instruct Nop_A1( ) %{ 4081 ins_pipe(ialu_nop_A1); 4082 %} 4083 4084 // Nop using the memory functional unit 4085 instruct Nop_MS( ) %{ 4086 ins_pipe(mem_nop); 4087 %} 4088 4089 // Nop using the floating add functional unit 4090 instruct Nop_FA( ) %{ 4091 ins_pipe(fadd_nop); 4092 %} 4093 4094 // Nop using the branch functional unit 4095 instruct Nop_BR( ) %{ 4096 ins_pipe(br_nop); 4097 %} 4098 4099 //----------Load/Store/Move Instructions--------------------------------------- 4100 //----------Load Instructions-------------------------------------------------- 4101 // Load Byte (8bit signed) 4102 instruct loadB(iRegI dst, memoryB mem) %{ 4103 match(Set dst (LoadB mem)); 4104 ins_cost(MEMORY_REF_COST); 4105 4106 size(4); 4107 format %{ "LDRSB $dst,$mem\t! byte -> int" %} 4108 ins_encode %{ 4109 // High 32 bits are harmlessly set on Aarch64 4110 __ ldrsb($dst$$Register, $mem$$Address); 4111 %} 4112 ins_pipe(iload_mask_mem); 4113 %} 4114 4115 // Load Byte (8bit signed) into a Long Register 4116 instruct loadB2L(iRegL dst, memoryB mem) %{ 4117 match(Set dst (ConvI2L (LoadB mem))); 4118 ins_cost(MEMORY_REF_COST); 4119 4120 #ifdef AARCH64 4121 size(4); 4122 format %{ "LDRSB $dst,$mem\t! byte -> long" %} 4123 ins_encode %{ 4124 __ ldrsb($dst$$Register, $mem$$Address); 4125 %} 4126 #else 4127 size(8); 4128 format %{ "LDRSB $dst.lo,$mem\t! byte -> long\n\t" 4129 "ASR $dst.hi,$dst.lo,31" %} 4130 ins_encode %{ 4131 __ ldrsb($dst$$Register, $mem$$Address); 4132 __ mov($dst$$Register->successor(), AsmOperand($dst$$Register, asr, 31)); 4133 %} 4134 #endif 4135 ins_pipe(iload_mask_mem); 4136 %} 4137 4138 // Load Unsigned Byte (8bit UNsigned) into an int reg 4139 instruct loadUB(iRegI dst, memoryB mem) %{ 4140 match(Set dst (LoadUB mem)); 4141 ins_cost(MEMORY_REF_COST); 4142 4143 size(4); 4144 format %{ "LDRB $dst,$mem\t! ubyte -> int" %} 4145 ins_encode %{ 4146 __ ldrb($dst$$Register, $mem$$Address); 4147 %} 4148 ins_pipe(iload_mem); 4149 %} 4150 4151 // Load Unsigned Byte (8bit UNsigned) into a Long Register 4152 instruct loadUB2L(iRegL dst, memoryB mem) %{ 4153 match(Set dst (ConvI2L (LoadUB mem))); 4154 ins_cost(MEMORY_REF_COST); 4155 4156 #ifdef AARCH64 4157 size(4); 4158 format %{ "LDRB $dst,$mem\t! ubyte -> long" %} 4159 ins_encode %{ 4160 __ ldrb($dst$$Register, $mem$$Address); 4161 %} 4162 #else 4163 size(8); 4164 format %{ "LDRB $dst.lo,$mem\t! ubyte -> long\n\t" 4165 "MOV $dst.hi,0" %} 4166 ins_encode %{ 4167 __ ldrb($dst$$Register, $mem$$Address); 4168 __ mov($dst$$Register->successor(), 0); 4169 %} 4170 #endif 4171 ins_pipe(iload_mem); 4172 %} 4173 4174 // Load Unsigned Byte (8 bit UNsigned) with immediate mask into Long Register 4175 instruct loadUB2L_limmI(iRegL dst, memoryB mem, limmIlow8 mask) %{ 4176 match(Set dst (ConvI2L (AndI (LoadUB mem) mask))); 4177 4178 #ifdef AARCH64 4179 ins_cost(MEMORY_REF_COST + DEFAULT_COST); 4180 size(8); 4181 format %{ "LDRB $dst,$mem\t! ubyte -> long\n\t" 4182 "AND $dst,$dst,$mask" %} 4183 ins_encode %{ 4184 __ ldrb($dst$$Register, $mem$$Address); 4185 __ andr($dst$$Register, $dst$$Register, limmI_low($mask$$constant, 8)); 4186 %} 4187 #else 4188 ins_cost(MEMORY_REF_COST + 2*DEFAULT_COST); 4189 size(12); 4190 format %{ "LDRB $dst.lo,$mem\t! ubyte -> long\n\t" 4191 "MOV $dst.hi,0\n\t" 4192 "AND $dst.lo,$dst.lo,$mask" %} 4193 ins_encode %{ 4194 __ ldrb($dst$$Register, $mem$$Address); 4195 __ mov($dst$$Register->successor(), 0); 4196 __ andr($dst$$Register, $dst$$Register, limmI_low($mask$$constant, 8)); 4197 %} 4198 #endif 4199 ins_pipe(iload_mem); 4200 %} 4201 4202 // Load Short (16bit signed) 4203 #ifdef AARCH64 4204 // XXX This variant shouldn't be necessary if 6217251 is implemented 4205 instruct loadSoff(iRegI dst, memoryScaledS mem, aimmX off, iRegP tmp) %{ 4206 match(Set dst (LoadS (AddP mem off))); 4207 ins_cost(MEMORY_REF_COST + DEFAULT_COST); // assume shift/sign-extend is free 4208 effect(TEMP tmp); 4209 size(4 * 2); 4210 4211 format %{ "LDRSH $dst,$mem+$off\t! short temp=$tmp" %} 4212 ins_encode %{ 4213 Register base = reg_to_register_object($mem$$base); 4214 __ add($tmp$$Register, base, $off$$constant); 4215 Address nmem = Address::make_raw($tmp$$reg, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none); 4216 __ ldrsh($dst$$Register, nmem); 4217 %} 4218 ins_pipe(iload_mask_mem); 4219 %} 4220 #endif 4221 4222 instruct loadS(iRegI dst, memoryS mem) %{ 4223 match(Set dst (LoadS mem)); 4224 ins_cost(MEMORY_REF_COST); 4225 4226 size(4); 4227 format %{ "LDRSH $dst,$mem\t! short" %} 4228 ins_encode %{ 4229 __ ldrsh($dst$$Register, $mem$$Address); 4230 %} 4231 ins_pipe(iload_mask_mem); 4232 %} 4233 4234 // Load Short (16 bit signed) to Byte (8 bit signed) 4235 instruct loadS2B(iRegI dst, memoryS mem, immI_24 twentyfour) %{ 4236 match(Set dst (RShiftI (LShiftI (LoadS mem) twentyfour) twentyfour)); 4237 ins_cost(MEMORY_REF_COST); 4238 4239 size(4); 4240 4241 format %{ "LDRSB $dst,$mem\t! short -> byte" %} 4242 ins_encode %{ 4243 // High 32 bits are harmlessly set on Aarch64 4244 __ ldrsb($dst$$Register, $mem$$Address); 4245 %} 4246 ins_pipe(iload_mask_mem); 4247 %} 4248 4249 // Load Short (16bit signed) into a Long Register 4250 instruct loadS2L(iRegL dst, memoryS mem) %{ 4251 match(Set dst (ConvI2L (LoadS mem))); 4252 ins_cost(MEMORY_REF_COST); 4253 4254 #ifdef AARCH64 4255 size(4); 4256 format %{ "LDRSH $dst,$mem\t! short -> long" %} 4257 ins_encode %{ 4258 __ ldrsh($dst$$Register, $mem$$Address); 4259 %} 4260 #else 4261 size(8); 4262 format %{ "LDRSH $dst.lo,$mem\t! short -> long\n\t" 4263 "ASR $dst.hi,$dst.lo,31" %} 4264 ins_encode %{ 4265 __ ldrsh($dst$$Register, $mem$$Address); 4266 __ mov($dst$$Register->successor(), AsmOperand($dst$$Register, asr, 31)); 4267 %} 4268 #endif 4269 ins_pipe(iload_mask_mem); 4270 %} 4271 4272 // Load Unsigned Short/Char (16bit UNsigned) 4273 4274 #ifdef AARCH64 4275 // XXX This variant shouldn't be necessary if 6217251 is implemented 4276 instruct loadUSoff(iRegI dst, memoryScaledS mem, aimmX off, iRegP tmp) %{ 4277 match(Set dst (LoadUS (AddP mem off))); 4278 ins_cost(MEMORY_REF_COST + DEFAULT_COST); // assume shift/sign-extend is free 4279 effect(TEMP tmp); 4280 size(4 * 2); 4281 4282 format %{ "LDRH $dst,$mem+$off\t! ushort/char temp=$tmp" %} 4283 ins_encode %{ 4284 Register base = reg_to_register_object($mem$$base); 4285 __ add($tmp$$Register, base, $off$$constant); 4286 Address nmem = Address::make_raw($tmp$$reg, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none); 4287 __ ldrh($dst$$Register, nmem); 4288 %} 4289 ins_pipe(iload_mem); 4290 %} 4291 #endif 4292 4293 instruct loadUS(iRegI dst, memoryS mem) %{ 4294 match(Set dst (LoadUS mem)); 4295 ins_cost(MEMORY_REF_COST); 4296 4297 size(4); 4298 format %{ "LDRH $dst,$mem\t! ushort/char" %} 4299 ins_encode %{ 4300 __ ldrh($dst$$Register, $mem$$Address); 4301 %} 4302 ins_pipe(iload_mem); 4303 %} 4304 4305 // Load Unsigned Short/Char (16 bit UNsigned) to Byte (8 bit signed) 4306 instruct loadUS2B(iRegI dst, memoryB mem, immI_24 twentyfour) %{ 4307 match(Set dst (RShiftI (LShiftI (LoadUS mem) twentyfour) twentyfour)); 4308 ins_cost(MEMORY_REF_COST); 4309 4310 size(4); 4311 format %{ "LDRSB $dst,$mem\t! ushort -> byte" %} 4312 ins_encode %{ 4313 __ ldrsb($dst$$Register, $mem$$Address); 4314 %} 4315 ins_pipe(iload_mask_mem); 4316 %} 4317 4318 // Load Unsigned Short/Char (16bit UNsigned) into a Long Register 4319 instruct loadUS2L(iRegL dst, memoryS mem) %{ 4320 match(Set dst (ConvI2L (LoadUS mem))); 4321 ins_cost(MEMORY_REF_COST); 4322 4323 #ifdef AARCH64 4324 size(4); 4325 format %{ "LDRH $dst,$mem\t! short -> long" %} 4326 ins_encode %{ 4327 __ ldrh($dst$$Register, $mem$$Address); 4328 %} 4329 #else 4330 size(8); 4331 format %{ "LDRH $dst.lo,$mem\t! short -> long\n\t" 4332 "MOV $dst.hi, 0" %} 4333 ins_encode %{ 4334 __ ldrh($dst$$Register, $mem$$Address); 4335 __ mov($dst$$Register->successor(), 0); 4336 %} 4337 #endif 4338 ins_pipe(iload_mem); 4339 %} 4340 4341 // Load Unsigned Short/Char (16bit UNsigned) with mask 0xFF into a Long Register 4342 instruct loadUS2L_immI_255(iRegL dst, memoryB mem, immI_255 mask) %{ 4343 match(Set dst (ConvI2L (AndI (LoadUS mem) mask))); 4344 ins_cost(MEMORY_REF_COST); 4345 4346 #ifdef AARCH64 4347 size(4); 4348 format %{ "LDRB $dst,$mem" %} 4349 ins_encode %{ 4350 __ ldrb($dst$$Register, $mem$$Address); 4351 %} 4352 #else 4353 size(8); 4354 format %{ "LDRB $dst.lo,$mem\t! \n\t" 4355 "MOV $dst.hi, 0" %} 4356 ins_encode %{ 4357 __ ldrb($dst$$Register, $mem$$Address); 4358 __ mov($dst$$Register->successor(), 0); 4359 %} 4360 #endif 4361 ins_pipe(iload_mem); 4362 %} 4363 4364 // Load Unsigned Short/Char (16bit UNsigned) with a immediate mask into a Long Register 4365 instruct loadUS2L_limmI(iRegL dst, memoryS mem, limmI mask) %{ 4366 match(Set dst (ConvI2L (AndI (LoadUS mem) mask))); 4367 #ifdef AARCH64 4368 ins_cost(MEMORY_REF_COST + 1*DEFAULT_COST); 4369 4370 size(8); 4371 format %{ "LDRH $dst,$mem\t! ushort/char & mask -> long\n\t" 4372 "AND $dst,$dst,$mask" %} 4373 ins_encode %{ 4374 __ ldrh($dst$$Register, $mem$$Address); 4375 __ andr($dst$$Register, $dst$$Register, (uintx)$mask$$constant); 4376 %} 4377 #else 4378 ins_cost(MEMORY_REF_COST + 2*DEFAULT_COST); 4379 4380 size(12); 4381 format %{ "LDRH $dst,$mem\t! ushort/char & mask -> long\n\t" 4382 "MOV $dst.hi, 0\n\t" 4383 "AND $dst,$dst,$mask" %} 4384 ins_encode %{ 4385 __ ldrh($dst$$Register, $mem$$Address); 4386 __ mov($dst$$Register->successor(), 0); 4387 __ andr($dst$$Register, $dst$$Register, $mask$$constant); 4388 %} 4389 #endif 4390 ins_pipe(iload_mem); 4391 %} 4392 4393 // Load Integer 4394 4395 #ifdef AARCH64 4396 // XXX This variant shouldn't be necessary if 6217251 is implemented 4397 instruct loadIoff(iRegI dst, memoryScaledI mem, aimmX off, iRegP tmp) %{ 4398 match(Set dst (LoadI (AddP mem off))); 4399 ins_cost(MEMORY_REF_COST + DEFAULT_COST); // assume shift/sign-extend is free 4400 effect(TEMP tmp); 4401 size(4 * 2); 4402 4403 format %{ "ldr_s32 $dst,$mem+$off\t! int temp=$tmp" %} 4404 ins_encode %{ 4405 Register base = reg_to_register_object($mem$$base); 4406 __ add($tmp$$Register, base, $off$$constant); 4407 Address nmem = Address::make_raw($tmp$$reg, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none); 4408 __ ldr_s32($dst$$Register, nmem); 4409 %} 4410 ins_pipe(iload_mem); 4411 %} 4412 #endif 4413 4414 instruct loadI(iRegI dst, memoryI mem) %{ 4415 match(Set dst (LoadI mem)); 4416 ins_cost(MEMORY_REF_COST); 4417 4418 size(4); 4419 format %{ "ldr_s32 $dst,$mem\t! int" %} 4420 ins_encode %{ 4421 __ ldr_s32($dst$$Register, $mem$$Address); 4422 %} 4423 ins_pipe(iload_mem); 4424 %} 4425 4426 // Load Integer to Byte (8 bit signed) 4427 instruct loadI2B(iRegI dst, memoryS mem, immI_24 twentyfour) %{ 4428 match(Set dst (RShiftI (LShiftI (LoadI mem) twentyfour) twentyfour)); 4429 ins_cost(MEMORY_REF_COST); 4430 4431 size(4); 4432 4433 format %{ "LDRSB $dst,$mem\t! int -> byte" %} 4434 ins_encode %{ 4435 __ ldrsb($dst$$Register, $mem$$Address); 4436 %} 4437 ins_pipe(iload_mask_mem); 4438 %} 4439 4440 // Load Integer to Unsigned Byte (8 bit UNsigned) 4441 instruct loadI2UB(iRegI dst, memoryB mem, immI_255 mask) %{ 4442 match(Set dst (AndI (LoadI mem) mask)); 4443 ins_cost(MEMORY_REF_COST); 4444 4445 size(4); 4446 4447 format %{ "LDRB $dst,$mem\t! int -> ubyte" %} 4448 ins_encode %{ 4449 __ ldrb($dst$$Register, $mem$$Address); 4450 %} 4451 ins_pipe(iload_mask_mem); 4452 %} 4453 4454 // Load Integer to Short (16 bit signed) 4455 instruct loadI2S(iRegI dst, memoryS mem, immI_16 sixteen) %{ 4456 match(Set dst (RShiftI (LShiftI (LoadI mem) sixteen) sixteen)); 4457 ins_cost(MEMORY_REF_COST); 4458 4459 size(4); 4460 format %{ "LDRSH $dst,$mem\t! int -> short" %} 4461 ins_encode %{ 4462 __ ldrsh($dst$$Register, $mem$$Address); 4463 %} 4464 ins_pipe(iload_mask_mem); 4465 %} 4466 4467 // Load Integer to Unsigned Short (16 bit UNsigned) 4468 instruct loadI2US(iRegI dst, memoryS mem, immI_65535 mask) %{ 4469 match(Set dst (AndI (LoadI mem) mask)); 4470 ins_cost(MEMORY_REF_COST); 4471 4472 size(4); 4473 format %{ "LDRH $dst,$mem\t! int -> ushort/char" %} 4474 ins_encode %{ 4475 __ ldrh($dst$$Register, $mem$$Address); 4476 %} 4477 ins_pipe(iload_mask_mem); 4478 %} 4479 4480 // Load Integer into a Long Register 4481 instruct loadI2L(iRegL dst, memoryI mem) %{ 4482 match(Set dst (ConvI2L (LoadI mem))); 4483 #ifdef AARCH64 4484 ins_cost(MEMORY_REF_COST); 4485 4486 size(4); 4487 format %{ "LDRSW $dst.lo,$mem\t! int -> long" %} 4488 ins_encode %{ 4489 __ ldr_s32($dst$$Register, $mem$$Address); 4490 %} 4491 #else 4492 ins_cost(MEMORY_REF_COST); 4493 4494 size(8); 4495 format %{ "LDR $dst.lo,$mem\t! int -> long\n\t" 4496 "ASR $dst.hi,$dst.lo,31\t! int->long" %} 4497 ins_encode %{ 4498 __ ldr($dst$$Register, $mem$$Address); 4499 __ mov($dst$$Register->successor(), AsmOperand($dst$$Register, asr, 31)); 4500 %} 4501 #endif 4502 ins_pipe(iload_mask_mem); 4503 %} 4504 4505 // Load Integer with mask 0xFF into a Long Register 4506 instruct loadI2L_immI_255(iRegL dst, memoryB mem, immI_255 mask) %{ 4507 match(Set dst (ConvI2L (AndI (LoadI mem) mask))); 4508 #ifdef AARCH64 4509 ins_cost(MEMORY_REF_COST); 4510 4511 size(4); 4512 format %{ "LDRB $dst.lo,$mem\t! int & 0xFF -> long" %} 4513 ins_encode %{ 4514 __ ldrb($dst$$Register, $mem$$Address); 4515 %} 4516 #else 4517 ins_cost(MEMORY_REF_COST); 4518 4519 size(8); 4520 format %{ "LDRB $dst.lo,$mem\t! int & 0xFF -> long\n\t" 4521 "MOV $dst.hi, 0" %} 4522 ins_encode %{ 4523 __ ldrb($dst$$Register, $mem$$Address); 4524 __ mov($dst$$Register->successor(), 0); 4525 %} 4526 #endif 4527 ins_pipe(iload_mem); 4528 %} 4529 4530 // Load Integer with mask 0xFFFF into a Long Register 4531 instruct loadI2L_immI_65535(iRegL dst, memoryS mem, immI_65535 mask) %{ 4532 match(Set dst (ConvI2L (AndI (LoadI mem) mask))); 4533 ins_cost(MEMORY_REF_COST); 4534 4535 #ifdef AARCH64 4536 size(4); 4537 format %{ "LDRH $dst,$mem\t! int & 0xFFFF -> long" %} 4538 ins_encode %{ 4539 __ ldrh($dst$$Register, $mem$$Address); 4540 %} 4541 #else 4542 size(8); 4543 format %{ "LDRH $dst,$mem\t! int & 0xFFFF -> long\n\t" 4544 "MOV $dst.hi, 0" %} 4545 ins_encode %{ 4546 __ ldrh($dst$$Register, $mem$$Address); 4547 __ mov($dst$$Register->successor(), 0); 4548 %} 4549 #endif 4550 ins_pipe(iload_mask_mem); 4551 %} 4552 4553 #ifdef AARCH64 4554 // Load Integer with an immediate mask into a Long Register 4555 instruct loadI2L_limmI(iRegL dst, memoryI mem, limmI mask) %{ 4556 match(Set dst (ConvI2L (AndI (LoadI mem) mask))); 4557 ins_cost(MEMORY_REF_COST + 1*DEFAULT_COST); 4558 4559 size(8); 4560 format %{ "LDRSW $dst,$mem\t! int -> long\n\t" 4561 "AND $dst,$dst,$mask" %} 4562 4563 ins_encode %{ 4564 __ ldr_s32($dst$$Register, $mem$$Address); 4565 __ andr($dst$$Register, $dst$$Register, (uintx)$mask$$constant); 4566 %} 4567 ins_pipe(iload_mem); 4568 %} 4569 #else 4570 // Load Integer with a 31-bit immediate mask into a Long Register 4571 instruct loadI2L_limmU31(iRegL dst, memoryI mem, limmU31 mask) %{ 4572 match(Set dst (ConvI2L (AndI (LoadI mem) mask))); 4573 ins_cost(MEMORY_REF_COST + 2*DEFAULT_COST); 4574 4575 size(12); 4576 format %{ "LDR $dst.lo,$mem\t! int -> long\n\t" 4577 "MOV $dst.hi, 0\n\t" 4578 "AND $dst,$dst,$mask" %} 4579 4580 ins_encode %{ 4581 __ ldr($dst$$Register, $mem$$Address); 4582 __ mov($dst$$Register->successor(), 0); 4583 __ andr($dst$$Register, $dst$$Register, $mask$$constant); 4584 %} 4585 ins_pipe(iload_mem); 4586 %} 4587 #endif 4588 4589 #ifdef AARCH64 4590 // Load Integer with mask into a Long Register 4591 // FIXME: use signedRegI mask, remove tmp? 4592 instruct loadI2L_immI(iRegL dst, memoryI mem, immI mask, iRegI tmp) %{ 4593 match(Set dst (ConvI2L (AndI (LoadI mem) mask))); 4594 effect(TEMP dst, TEMP tmp); 4595 4596 ins_cost(MEMORY_REF_COST + 3*DEFAULT_COST); 4597 format %{ "LDRSW $mem,$dst\t! int & 31-bit mask -> long\n\t" 4598 "MOV_SLOW $tmp,$mask\n\t" 4599 "AND $dst,$tmp,$dst" %} 4600 ins_encode %{ 4601 __ ldrsw($dst$$Register, $mem$$Address); 4602 __ mov_slow($tmp$$Register, $mask$$constant); 4603 __ andr($dst$$Register, $dst$$Register, $tmp$$Register); 4604 %} 4605 ins_pipe(iload_mem); 4606 %} 4607 #else 4608 // Load Integer with a 31-bit mask into a Long Register 4609 // FIXME: use iRegI mask, remove tmp? 4610 instruct loadI2L_immU31(iRegL dst, memoryI mem, immU31 mask, iRegI tmp) %{ 4611 match(Set dst (ConvI2L (AndI (LoadI mem) mask))); 4612 effect(TEMP dst, TEMP tmp); 4613 4614 ins_cost(MEMORY_REF_COST + 4*DEFAULT_COST); 4615 size(20); 4616 format %{ "LDR $mem,$dst\t! int & 31-bit mask -> long\n\t" 4617 "MOV $dst.hi, 0\n\t" 4618 "MOV_SLOW $tmp,$mask\n\t" 4619 "AND $dst,$tmp,$dst" %} 4620 ins_encode %{ 4621 __ ldr($dst$$Register, $mem$$Address); 4622 __ mov($dst$$Register->successor(), 0); 4623 __ mov_slow($tmp$$Register, $mask$$constant); 4624 __ andr($dst$$Register, $dst$$Register, $tmp$$Register); 4625 %} 4626 ins_pipe(iload_mem); 4627 %} 4628 #endif 4629 4630 // Load Unsigned Integer into a Long Register 4631 instruct loadUI2L(iRegL dst, memoryI mem, immL_32bits mask) %{ 4632 match(Set dst (AndL (ConvI2L (LoadI mem)) mask)); 4633 ins_cost(MEMORY_REF_COST); 4634 4635 #ifdef AARCH64 4636 //size(4); 4637 format %{ "LDR_w $dst,$mem\t! uint -> long" %} 4638 ins_encode %{ 4639 __ ldr_w($dst$$Register, $mem$$Address); 4640 %} 4641 #else 4642 size(8); 4643 format %{ "LDR $dst.lo,$mem\t! uint -> long\n\t" 4644 "MOV $dst.hi,0" %} 4645 ins_encode %{ 4646 __ ldr($dst$$Register, $mem$$Address); 4647 __ mov($dst$$Register->successor(), 0); 4648 %} 4649 #endif 4650 ins_pipe(iload_mem); 4651 %} 4652 4653 // Load Long 4654 4655 #ifdef AARCH64 4656 // XXX This variant shouldn't be necessary if 6217251 is implemented 4657 instruct loadLoff(iRegLd dst, memoryScaledL mem, aimmX off, iRegP tmp) %{ 4658 match(Set dst (LoadL (AddP mem off))); 4659 ins_cost(MEMORY_REF_COST + DEFAULT_COST); // assume shift/sign-extend is free 4660 effect(TEMP tmp); 4661 size(4 * 2); 4662 4663 format %{ "LDR $dst,$mem+$off\t! long temp=$tmp" %} 4664 ins_encode %{ 4665 Register base = reg_to_register_object($mem$$base); 4666 __ add($tmp$$Register, base, $off$$constant); 4667 Address nmem = Address::make_raw($tmp$$reg, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none); 4668 __ ldr($dst$$Register, nmem); 4669 %} 4670 ins_pipe(iload_mem); 4671 %} 4672 #endif 4673 4674 instruct loadL(iRegLd dst, memoryL mem ) %{ 4675 #ifdef AARCH64 4676 // already atomic for Aarch64 4677 #else 4678 predicate(!((LoadLNode*)n)->require_atomic_access()); 4679 #endif 4680 match(Set dst (LoadL mem)); 4681 effect(TEMP dst); 4682 ins_cost(MEMORY_REF_COST); 4683 4684 size(4); 4685 format %{ "ldr_64 $dst,$mem\t! long" %} 4686 ins_encode %{ 4687 __ ldr_64($dst$$Register, $mem$$Address); 4688 %} 4689 ins_pipe(iload_mem); 4690 %} 4691 4692 #ifndef AARCH64 4693 instruct loadL_2instr(iRegL dst, memorylong mem ) %{ 4694 predicate(!((LoadLNode*)n)->require_atomic_access()); 4695 match(Set dst (LoadL mem)); 4696 ins_cost(MEMORY_REF_COST + DEFAULT_COST); 4697 4698 size(8); 4699 format %{ "LDR $dst.lo,$mem \t! long order of instrs reversed if $dst.lo == base($mem)\n\t" 4700 "LDR $dst.hi,$mem+4 or $mem" %} 4701 ins_encode %{ 4702 Address Amemlo = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none); 4703 Address Amemhi = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp + 4, relocInfo::none); 4704 4705 if ($dst$$Register == reg_to_register_object($mem$$base)) { 4706 __ ldr($dst$$Register->successor(), Amemhi); 4707 __ ldr($dst$$Register, Amemlo); 4708 } else { 4709 __ ldr($dst$$Register, Amemlo); 4710 __ ldr($dst$$Register->successor(), Amemhi); 4711 } 4712 %} 4713 ins_pipe(iload_mem); 4714 %} 4715 4716 instruct loadL_volatile(iRegL dst, indirect mem ) %{ 4717 predicate(((LoadLNode*)n)->require_atomic_access()); 4718 match(Set dst (LoadL mem)); 4719 ins_cost(MEMORY_REF_COST); 4720 4721 size(4); 4722 format %{ "LDMIA $dst,$mem\t! long" %} 4723 ins_encode %{ 4724 // FIXME: why is ldmia considered atomic? Should be ldrexd 4725 RegisterSet set($dst$$Register); 4726 set = set | reg_to_register_object($dst$$reg + 1); 4727 __ ldmia(reg_to_register_object($mem$$base), set); 4728 %} 4729 ins_pipe(iload_mem); 4730 %} 4731 4732 instruct loadL_volatile_fp(iRegL dst, memoryD mem ) %{ 4733 predicate(((LoadLNode*)n)->require_atomic_access()); 4734 match(Set dst (LoadL mem)); 4735 ins_cost(MEMORY_REF_COST); 4736 4737 size(8); 4738 format %{ "FLDD S14, $mem" 4739 "FMRRD $dst, S14\t! long \n't" %} 4740 ins_encode %{ 4741 __ fldd(S14, $mem$$Address); 4742 __ fmrrd($dst$$Register, $dst$$Register->successor(), S14); 4743 %} 4744 ins_pipe(iload_mem); 4745 %} 4746 4747 instruct loadL_unaligned(iRegL dst, memorylong mem ) %{ 4748 match(Set dst (LoadL_unaligned mem)); 4749 ins_cost(MEMORY_REF_COST); 4750 4751 size(8); 4752 format %{ "LDR $dst.lo,$mem\t! long order of instrs reversed if $dst.lo == base($mem)\n\t" 4753 "LDR $dst.hi,$mem+4" %} 4754 ins_encode %{ 4755 Address Amemlo = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none); 4756 Address Amemhi = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp + 4, relocInfo::none); 4757 4758 if ($dst$$Register == reg_to_register_object($mem$$base)) { 4759 __ ldr($dst$$Register->successor(), Amemhi); 4760 __ ldr($dst$$Register, Amemlo); 4761 } else { 4762 __ ldr($dst$$Register, Amemlo); 4763 __ ldr($dst$$Register->successor(), Amemhi); 4764 } 4765 %} 4766 ins_pipe(iload_mem); 4767 %} 4768 #endif // !AARCH64 4769 4770 // Load Range 4771 instruct loadRange(iRegI dst, memoryI mem) %{ 4772 match(Set dst (LoadRange mem)); 4773 ins_cost(MEMORY_REF_COST); 4774 4775 size(4); 4776 format %{ "LDR_u32 $dst,$mem\t! range" %} 4777 ins_encode %{ 4778 __ ldr_u32($dst$$Register, $mem$$Address); 4779 %} 4780 ins_pipe(iload_mem); 4781 %} 4782 4783 // Load Pointer 4784 4785 #ifdef AARCH64 4786 // XXX This variant shouldn't be necessary if 6217251 is implemented 4787 instruct loadPoff(iRegP dst, memoryScaledP mem, aimmX off, iRegP tmp) %{ 4788 match(Set dst (LoadP (AddP mem off))); 4789 ins_cost(MEMORY_REF_COST + DEFAULT_COST); // assume shift/sign-extend is free 4790 effect(TEMP tmp); 4791 size(4 * 2); 4792 4793 format %{ "LDR $dst,$mem+$off\t! ptr temp=$tmp" %} 4794 ins_encode %{ 4795 Register base = reg_to_register_object($mem$$base); 4796 __ add($tmp$$Register, base, $off$$constant); 4797 Address nmem = Address::make_raw($tmp$$reg, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none); 4798 __ ldr($dst$$Register, nmem); 4799 %} 4800 ins_pipe(iload_mem); 4801 %} 4802 #endif 4803 4804 instruct loadP(iRegP dst, memoryP mem) %{ 4805 match(Set dst (LoadP mem)); 4806 ins_cost(MEMORY_REF_COST); 4807 size(4); 4808 4809 format %{ "LDR $dst,$mem\t! ptr" %} 4810 ins_encode %{ 4811 __ ldr($dst$$Register, $mem$$Address); 4812 %} 4813 ins_pipe(iload_mem); 4814 %} 4815 4816 #ifdef XXX 4817 // FIXME XXXX 4818 //instruct loadSP(iRegP dst, memoryP mem) %{ 4819 instruct loadSP(SPRegP dst, memoryP mem, iRegP tmp) %{ 4820 match(Set dst (LoadP mem)); 4821 effect(TEMP tmp); 4822 ins_cost(MEMORY_REF_COST+1); 4823 size(8); 4824 4825 format %{ "LDR $tmp,$mem\t! ptr\n\t" 4826 "MOV $dst,$tmp\t! ptr" %} 4827 ins_encode %{ 4828 __ ldr($tmp$$Register, $mem$$Address); 4829 __ mov($dst$$Register, $tmp$$Register); 4830 %} 4831 ins_pipe(iload_mem); 4832 %} 4833 #endif 4834 4835 #ifdef _LP64 4836 // Load Compressed Pointer 4837 4838 // XXX This variant shouldn't be necessary if 6217251 is implemented 4839 instruct loadNoff(iRegN dst, memoryScaledI mem, aimmX off, iRegP tmp) %{ 4840 match(Set dst (LoadN (AddP mem off))); 4841 ins_cost(MEMORY_REF_COST + DEFAULT_COST); // assume shift/sign-extend is free 4842 effect(TEMP tmp); 4843 size(4 * 2); 4844 4845 format %{ "ldr_u32 $dst,$mem+$off\t! compressed ptr temp=$tmp" %} 4846 ins_encode %{ 4847 Register base = reg_to_register_object($mem$$base); 4848 __ add($tmp$$Register, base, $off$$constant); 4849 Address nmem = Address::make_raw($tmp$$reg, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none); 4850 __ ldr_u32($dst$$Register, nmem); 4851 %} 4852 ins_pipe(iload_mem); 4853 %} 4854 4855 instruct loadN(iRegN dst, memoryI mem) %{ 4856 match(Set dst (LoadN mem)); 4857 ins_cost(MEMORY_REF_COST); 4858 size(4); 4859 4860 format %{ "ldr_u32 $dst,$mem\t! compressed ptr" %} 4861 ins_encode %{ 4862 __ ldr_u32($dst$$Register, $mem$$Address); 4863 %} 4864 ins_pipe(iload_mem); 4865 %} 4866 #endif 4867 4868 // Load Klass Pointer 4869 instruct loadKlass(iRegP dst, memoryI mem) %{ 4870 match(Set dst (LoadKlass mem)); 4871 ins_cost(MEMORY_REF_COST); 4872 size(4); 4873 4874 format %{ "LDR $dst,$mem\t! klass ptr" %} 4875 ins_encode %{ 4876 __ ldr($dst$$Register, $mem$$Address); 4877 %} 4878 ins_pipe(iload_mem); 4879 %} 4880 4881 #ifdef _LP64 4882 // Load narrow Klass Pointer 4883 instruct loadNKlass(iRegN dst, memoryI mem) %{ 4884 match(Set dst (LoadNKlass mem)); 4885 ins_cost(MEMORY_REF_COST); 4886 size(4); 4887 4888 format %{ "ldr_u32 $dst,$mem\t! compressed klass ptr" %} 4889 ins_encode %{ 4890 __ ldr_u32($dst$$Register, $mem$$Address); 4891 %} 4892 ins_pipe(iload_mem); 4893 %} 4894 #endif 4895 4896 #ifdef AARCH64 4897 // XXX This variant shouldn't be necessary if 6217251 is implemented 4898 instruct loadDoff(regD dst, memoryScaledD mem, aimmX off, iRegP tmp) %{ 4899 match(Set dst (LoadD (AddP mem off))); 4900 ins_cost(MEMORY_REF_COST + DEFAULT_COST); // assume shift/sign-extend is free 4901 effect(TEMP tmp); 4902 size(4 * 2); 4903 4904 format %{ "ldr $dst,$mem+$off\t! double temp=$tmp" %} 4905 ins_encode %{ 4906 Register base = reg_to_register_object($mem$$base); 4907 __ add($tmp$$Register, base, $off$$constant); 4908 Address nmem = Address::make_raw($tmp$$reg, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none); 4909 __ ldr_d($dst$$FloatRegister, nmem); 4910 %} 4911 ins_pipe(floadD_mem); 4912 %} 4913 #endif 4914 4915 instruct loadD(regD dst, memoryD mem) %{ 4916 match(Set dst (LoadD mem)); 4917 ins_cost(MEMORY_REF_COST); 4918 4919 size(4); 4920 // FIXME: needs to be atomic, but ARMv7 A.R.M. guarantees 4921 // only LDREXD and STREXD are 64-bit single-copy atomic 4922 format %{ "FLDD $dst,$mem" %} 4923 ins_encode %{ 4924 __ ldr_double($dst$$FloatRegister, $mem$$Address); 4925 %} 4926 ins_pipe(floadD_mem); 4927 %} 4928 4929 #ifndef AARCH64 4930 // Load Double - UNaligned 4931 instruct loadD_unaligned(regD_low dst, memoryF2 mem ) %{ 4932 match(Set dst (LoadD_unaligned mem)); 4933 ins_cost(MEMORY_REF_COST*2+DEFAULT_COST); 4934 size(8); 4935 format %{ "FLDS $dst.lo,$mem\t! misaligned double\n" 4936 "\tFLDS $dst.hi,$mem+4\t!" %} 4937 ins_encode %{ 4938 Address Amemlo = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none); 4939 Address Amemhi = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp + 4, relocInfo::none); 4940 __ flds($dst$$FloatRegister, Amemlo); 4941 __ flds($dst$$FloatRegister->successor(), Amemhi); 4942 %} 4943 ins_pipe(iload_mem); 4944 %} 4945 #endif 4946 4947 #ifdef AARCH64 4948 // XXX This variant shouldn't be necessary if 6217251 is implemented 4949 instruct loadFoff(regF dst, memoryScaledF mem, aimmX off, iRegP tmp) %{ 4950 match(Set dst (LoadF (AddP mem off))); 4951 ins_cost(MEMORY_REF_COST + DEFAULT_COST); // assume shift/sign-extend is free 4952 effect(TEMP tmp); 4953 size(4 * 2); 4954 4955 format %{ "ldr $dst,$mem+$off\t! float temp=$tmp" %} 4956 ins_encode %{ 4957 Register base = reg_to_register_object($mem$$base); 4958 __ add($tmp$$Register, base, $off$$constant); 4959 Address nmem = Address::make_raw($tmp$$reg, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none); 4960 __ ldr_s($dst$$FloatRegister, nmem); 4961 %} 4962 ins_pipe(floadF_mem); 4963 %} 4964 #endif 4965 4966 instruct loadF(regF dst, memoryF mem) %{ 4967 match(Set dst (LoadF mem)); 4968 4969 ins_cost(MEMORY_REF_COST); 4970 size(4); 4971 format %{ "FLDS $dst,$mem" %} 4972 ins_encode %{ 4973 __ ldr_float($dst$$FloatRegister, $mem$$Address); 4974 %} 4975 ins_pipe(floadF_mem); 4976 %} 4977 4978 #ifdef AARCH64 4979 instruct load_limmI(iRegI dst, limmI src) %{ 4980 match(Set dst src); 4981 ins_cost(DEFAULT_COST + 1); // + 1 because MOV is preferred 4982 format %{ "ORR_w $dst, ZR, $src\t! int" %} 4983 ins_encode %{ 4984 __ orr_w($dst$$Register, ZR, (uintx)$src$$constant); 4985 %} 4986 ins_pipe(ialu_imm); 4987 %} 4988 #endif 4989 4990 // // Load Constant 4991 instruct loadConI( iRegI dst, immI src ) %{ 4992 match(Set dst src); 4993 ins_cost(DEFAULT_COST * 3/2); 4994 format %{ "MOV_SLOW $dst, $src" %} 4995 ins_encode %{ 4996 __ mov_slow($dst$$Register, $src$$constant); 4997 %} 4998 ins_pipe(ialu_hi_lo_reg); 4999 %} 5000 5001 instruct loadConIMov( iRegI dst, immIMov src ) %{ 5002 match(Set dst src); 5003 size(4); 5004 format %{ "MOV $dst, $src" %} 5005 ins_encode %{ 5006 __ mov($dst$$Register, $src$$constant); 5007 %} 5008 ins_pipe(ialu_imm); 5009 %} 5010 5011 #ifndef AARCH64 5012 instruct loadConIMovn( iRegI dst, immIRotn src ) %{ 5013 match(Set dst src); 5014 size(4); 5015 format %{ "MVN $dst, ~$src" %} 5016 ins_encode %{ 5017 __ mvn($dst$$Register, ~$src$$constant); 5018 %} 5019 ins_pipe(ialu_imm_n); 5020 %} 5021 #endif 5022 5023 instruct loadConI16( iRegI dst, immI16 src ) %{ 5024 match(Set dst src); 5025 size(4); 5026 #ifdef AARCH64 5027 format %{ "MOVZ_w $dst, $src" %} 5028 #else 5029 format %{ "MOVW $dst, $src" %} 5030 #endif 5031 ins_encode %{ 5032 #ifdef AARCH64 5033 __ mov_w($dst$$Register, $src$$constant); 5034 #else 5035 __ movw($dst$$Register, $src$$constant); 5036 #endif 5037 %} 5038 ins_pipe(ialu_imm_n); 5039 %} 5040 5041 instruct loadConP(iRegP dst, immP src) %{ 5042 match(Set dst src); 5043 ins_cost(DEFAULT_COST * 3/2); 5044 format %{ "MOV_SLOW $dst,$src\t!ptr" %} 5045 ins_encode %{ 5046 relocInfo::relocType constant_reloc = _opnds[1]->constant_reloc(); 5047 intptr_t val = $src$$constant; 5048 if (constant_reloc == relocInfo::oop_type) { 5049 __ mov_oop($dst$$Register, (jobject)val); 5050 } else if (constant_reloc == relocInfo::metadata_type) { 5051 __ mov_metadata($dst$$Register, (Metadata*)val); 5052 } else { 5053 __ mov_slow($dst$$Register, val); 5054 } 5055 %} 5056 ins_pipe(loadConP); 5057 %} 5058 5059 5060 instruct loadConP_poll(iRegP dst, immP_poll src) %{ 5061 match(Set dst src); 5062 ins_cost(DEFAULT_COST); 5063 format %{ "MOV_SLOW $dst,$src\t!ptr" %} 5064 ins_encode %{ 5065 __ mov_slow($dst$$Register, $src$$constant); 5066 %} 5067 ins_pipe(loadConP_poll); 5068 %} 5069 5070 #ifdef AARCH64 5071 instruct loadConP0(iRegP dst, immP0 src) %{ 5072 match(Set dst src); 5073 ins_cost(DEFAULT_COST); 5074 format %{ "MOV $dst,ZR\t!ptr" %} 5075 ins_encode %{ 5076 __ mov($dst$$Register, ZR); 5077 %} 5078 ins_pipe(ialu_none); 5079 %} 5080 5081 instruct loadConN(iRegN dst, immN src) %{ 5082 match(Set dst src); 5083 ins_cost(DEFAULT_COST * 3/2); 5084 format %{ "SET $dst,$src\t! compressed ptr" %} 5085 ins_encode %{ 5086 Register dst = $dst$$Register; 5087 // FIXME: use $constanttablebase? 5088 __ set_narrow_oop(dst, (jobject)$src$$constant); 5089 %} 5090 ins_pipe(ialu_hi_lo_reg); 5091 %} 5092 5093 instruct loadConN0(iRegN dst, immN0 src) %{ 5094 match(Set dst src); 5095 ins_cost(DEFAULT_COST); 5096 format %{ "MOV $dst,ZR\t! compressed ptr" %} 5097 ins_encode %{ 5098 __ mov($dst$$Register, ZR); 5099 %} 5100 ins_pipe(ialu_none); 5101 %} 5102 5103 instruct loadConNKlass(iRegN dst, immNKlass src) %{ 5104 match(Set dst src); 5105 ins_cost(DEFAULT_COST * 3/2); 5106 format %{ "SET $dst,$src\t! compressed klass ptr" %} 5107 ins_encode %{ 5108 Register dst = $dst$$Register; 5109 // FIXME: use $constanttablebase? 5110 __ set_narrow_klass(dst, (Klass*)$src$$constant); 5111 %} 5112 ins_pipe(ialu_hi_lo_reg); 5113 %} 5114 5115 instruct load_limmL(iRegL dst, limmL src) %{ 5116 match(Set dst src); 5117 ins_cost(DEFAULT_COST); 5118 format %{ "ORR $dst, ZR, $src\t! long" %} 5119 ins_encode %{ 5120 __ orr($dst$$Register, ZR, (uintx)$src$$constant); 5121 %} 5122 ins_pipe(loadConL); 5123 %} 5124 instruct load_immLMov(iRegL dst, immLMov src) %{ 5125 match(Set dst src); 5126 ins_cost(DEFAULT_COST); 5127 format %{ "MOV $dst, $src\t! long" %} 5128 ins_encode %{ 5129 __ mov($dst$$Register, $src$$constant); 5130 %} 5131 ins_pipe(loadConL); 5132 %} 5133 instruct loadConL(iRegL dst, immL src) %{ 5134 match(Set dst src); 5135 ins_cost(DEFAULT_COST * 4); // worst case 5136 format %{ "mov_slow $dst, $src\t! long" %} 5137 ins_encode %{ 5138 // FIXME: use $constanttablebase? 5139 __ mov_slow($dst$$Register, $src$$constant); 5140 %} 5141 ins_pipe(loadConL); 5142 %} 5143 #else 5144 instruct loadConL(iRegL dst, immL src) %{ 5145 match(Set dst src); 5146 ins_cost(DEFAULT_COST * 4); 5147 format %{ "MOV_SLOW $dst.lo, $src & 0x0FFFFFFFFL \t! long\n\t" 5148 "MOV_SLOW $dst.hi, $src >> 32" %} 5149 ins_encode %{ 5150 __ mov_slow(reg_to_register_object($dst$$reg), $src$$constant & 0x0FFFFFFFFL); 5151 __ mov_slow(reg_to_register_object($dst$$reg + 1), ((julong)($src$$constant)) >> 32); 5152 %} 5153 ins_pipe(loadConL); 5154 %} 5155 5156 instruct loadConL16( iRegL dst, immL16 src ) %{ 5157 match(Set dst src); 5158 ins_cost(DEFAULT_COST * 2); 5159 5160 size(8); 5161 format %{ "MOVW $dst.lo, $src \n\t" 5162 "MOVW $dst.hi, 0 \n\t" %} 5163 ins_encode %{ 5164 __ movw($dst$$Register, $src$$constant); 5165 __ movw($dst$$Register->successor(), 0); 5166 %} 5167 ins_pipe(ialu_imm); 5168 %} 5169 #endif 5170 5171 instruct loadConF_imm8(regF dst, imm8F src) %{ 5172 match(Set dst src); 5173 ins_cost(DEFAULT_COST); 5174 size(4); 5175 5176 format %{ "FCONSTS $dst, $src"%} 5177 5178 ins_encode %{ 5179 __ fconsts($dst$$FloatRegister, Assembler::float_num($src$$constant).imm8()); 5180 %} 5181 ins_pipe(loadConFD); // FIXME 5182 %} 5183 5184 #ifdef AARCH64 5185 instruct loadIConF(iRegI dst, immF src) %{ 5186 match(Set dst src); 5187 ins_cost(DEFAULT_COST * 2); 5188 5189 format %{ "MOV_SLOW $dst, $src\t! loadIConF" %} 5190 5191 ins_encode %{ 5192 // FIXME revisit once 6961697 is in 5193 union { 5194 jfloat f; 5195 int i; 5196 } v; 5197 v.f = $src$$constant; 5198 __ mov_slow($dst$$Register, v.i); 5199 %} 5200 ins_pipe(ialu_imm); 5201 %} 5202 #endif 5203 5204 instruct loadConF(regF dst, immF src, iRegI tmp) %{ 5205 match(Set dst src); 5206 ins_cost(DEFAULT_COST * 2); 5207 effect(TEMP tmp); 5208 size(3*4); 5209 5210 format %{ "MOV_SLOW $tmp, $src\n\t" 5211 "FMSR $dst, $tmp"%} 5212 5213 ins_encode %{ 5214 // FIXME revisit once 6961697 is in 5215 union { 5216 jfloat f; 5217 int i; 5218 } v; 5219 v.f = $src$$constant; 5220 __ mov_slow($tmp$$Register, v.i); 5221 __ fmsr($dst$$FloatRegister, $tmp$$Register); 5222 %} 5223 ins_pipe(loadConFD); // FIXME 5224 %} 5225 5226 instruct loadConD_imm8(regD dst, imm8D src) %{ 5227 match(Set dst src); 5228 ins_cost(DEFAULT_COST); 5229 size(4); 5230 5231 format %{ "FCONSTD $dst, $src"%} 5232 5233 ins_encode %{ 5234 __ fconstd($dst$$FloatRegister, Assembler::double_num($src$$constant).imm8()); 5235 %} 5236 ins_pipe(loadConFD); // FIXME 5237 %} 5238 5239 instruct loadConD(regD dst, immD src, iRegP tmp) %{ 5240 match(Set dst src); 5241 effect(TEMP tmp); 5242 ins_cost(MEMORY_REF_COST); 5243 format %{ "FLDD $dst, [$constanttablebase + $constantoffset]\t! load from constant table: double=$src" %} 5244 5245 ins_encode %{ 5246 Register r = $constanttablebase; 5247 int offset = $constantoffset($src); 5248 if (!is_memoryD(offset)) { // can't use a predicate 5249 // in load constant instructs 5250 __ add_slow($tmp$$Register, r, offset); 5251 r = $tmp$$Register; 5252 offset = 0; 5253 } 5254 __ ldr_double($dst$$FloatRegister, Address(r, offset)); 5255 %} 5256 ins_pipe(loadConFD); 5257 %} 5258 5259 // Prefetch instructions. 5260 // Must be safe to execute with invalid address (cannot fault). 5261 5262 instruct prefetchAlloc_mp( memoryP mem ) %{ 5263 predicate(os::is_MP()); 5264 match( PrefetchAllocation mem ); 5265 ins_cost(MEMORY_REF_COST); 5266 size(4); 5267 5268 format %{ "PLDW $mem\t! Prefetch allocation" %} 5269 ins_encode %{ 5270 #ifdef AARCH64 5271 __ prfm(pstl1keep, $mem$$Address); 5272 #else 5273 __ pldw($mem$$Address); 5274 #endif 5275 %} 5276 ins_pipe(iload_mem); 5277 %} 5278 5279 instruct prefetchAlloc_sp( memoryP mem ) %{ 5280 predicate(!os::is_MP()); 5281 match( PrefetchAllocation mem ); 5282 ins_cost(MEMORY_REF_COST); 5283 size(4); 5284 5285 format %{ "PLD $mem\t! Prefetch allocation" %} 5286 ins_encode %{ 5287 #ifdef AARCH64 5288 __ prfm(pstl1keep, $mem$$Address); 5289 #else 5290 __ pld($mem$$Address); 5291 #endif 5292 %} 5293 ins_pipe(iload_mem); 5294 %} 5295 5296 //----------Store Instructions------------------------------------------------- 5297 // Store Byte 5298 instruct storeB(memoryB mem, store_RegI src) %{ 5299 match(Set mem (StoreB mem src)); 5300 ins_cost(MEMORY_REF_COST); 5301 5302 size(4); 5303 format %{ "STRB $src,$mem\t! byte" %} 5304 ins_encode %{ 5305 __ strb($src$$Register, $mem$$Address); 5306 %} 5307 ins_pipe(istore_mem_reg); 5308 %} 5309 5310 instruct storeCM(memoryB mem, store_RegI src) %{ 5311 match(Set mem (StoreCM mem src)); 5312 ins_cost(MEMORY_REF_COST); 5313 5314 size(4); 5315 format %{ "STRB $src,$mem\t! CMS card-mark byte" %} 5316 ins_encode %{ 5317 __ strb($src$$Register, $mem$$Address); 5318 %} 5319 ins_pipe(istore_mem_reg); 5320 %} 5321 5322 // Store Char/Short 5323 5324 #ifdef AARCH64 5325 // XXX This variant shouldn't be necessary if 6217251 is implemented 5326 instruct storeCoff(store_RegI src, memoryScaledS mem, aimmX off, iRegP tmp) %{ 5327 match(Set mem (StoreC (AddP mem off) src)); 5328 ins_cost(MEMORY_REF_COST + DEFAULT_COST); // assume shift/sign-extend is free 5329 effect(TEMP tmp); 5330 size(4 * 2); 5331 5332 format %{ "STRH $src,$mem+$off\t! short temp=$tmp" %} 5333 ins_encode %{ 5334 Register base = reg_to_register_object($mem$$base); 5335 __ add($tmp$$Register, base, $off$$constant); 5336 Address nmem = Address::make_raw($tmp$$reg, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none); 5337 __ strh($src$$Register, nmem); 5338 %} 5339 ins_pipe(istore_mem_reg); 5340 %} 5341 #endif 5342 5343 instruct storeC(memoryS mem, store_RegI src) %{ 5344 match(Set mem (StoreC mem src)); 5345 ins_cost(MEMORY_REF_COST); 5346 5347 size(4); 5348 format %{ "STRH $src,$mem\t! short" %} 5349 ins_encode %{ 5350 __ strh($src$$Register, $mem$$Address); 5351 %} 5352 ins_pipe(istore_mem_reg); 5353 %} 5354 5355 // Store Integer 5356 5357 #ifdef AARCH64 5358 // XXX This variant shouldn't be necessary if 6217251 is implemented 5359 instruct storeIoff(store_RegI src, memoryScaledI mem, aimmX off, iRegP tmp) %{ 5360 match(Set mem (StoreI (AddP mem off) src)); 5361 ins_cost(MEMORY_REF_COST + DEFAULT_COST); // assume shift/sign-extend is free 5362 effect(TEMP tmp); 5363 size(4 * 2); 5364 5365 format %{ "str_32 $src,$mem+$off\t! int temp=$tmp" %} 5366 ins_encode %{ 5367 Register base = reg_to_register_object($mem$$base); 5368 __ add($tmp$$Register, base, $off$$constant); 5369 Address nmem = Address::make_raw($tmp$$reg, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none); 5370 __ str_32($src$$Register, nmem); 5371 %} 5372 ins_pipe(istore_mem_reg); 5373 %} 5374 #endif 5375 5376 instruct storeI(memoryI mem, store_RegI src) %{ 5377 match(Set mem (StoreI mem src)); 5378 ins_cost(MEMORY_REF_COST); 5379 5380 size(4); 5381 format %{ "str_32 $src,$mem" %} 5382 ins_encode %{ 5383 __ str_32($src$$Register, $mem$$Address); 5384 %} 5385 ins_pipe(istore_mem_reg); 5386 %} 5387 5388 // Store Long 5389 5390 #ifdef AARCH64 5391 // XXX This variant shouldn't be necessary if 6217251 is implemented 5392 instruct storeLoff(store_RegLd src, memoryScaledL mem, aimmX off, iRegP tmp) %{ 5393 match(Set mem (StoreL (AddP mem off) src)); 5394 ins_cost(MEMORY_REF_COST + DEFAULT_COST); // assume shift/sign-extend is free 5395 effect(TEMP tmp); 5396 size(4 * 2); 5397 5398 format %{ "str_64 $src,$mem+$off\t! long temp=$tmp" %} 5399 ins_encode %{ 5400 Register base = reg_to_register_object($mem$$base); 5401 __ add($tmp$$Register, base, $off$$constant); 5402 Address nmem = Address::make_raw($tmp$$reg, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none); 5403 __ str_64($src$$Register, nmem); 5404 %} 5405 ins_pipe(istore_mem_reg); 5406 %} 5407 #endif 5408 5409 instruct storeL(memoryL mem, store_RegLd src) %{ 5410 #ifdef AARCH64 5411 // already atomic for Aarch64 5412 #else 5413 predicate(!((StoreLNode*)n)->require_atomic_access()); 5414 #endif 5415 match(Set mem (StoreL mem src)); 5416 ins_cost(MEMORY_REF_COST); 5417 5418 size(4); 5419 format %{ "str_64 $src,$mem\t! long\n\t" %} 5420 5421 ins_encode %{ 5422 __ str_64($src$$Register, $mem$$Address); 5423 %} 5424 ins_pipe(istore_mem_reg); 5425 %} 5426 5427 #ifndef AARCH64 5428 instruct storeL_2instr(memorylong mem, iRegL src) %{ 5429 predicate(!((StoreLNode*)n)->require_atomic_access()); 5430 match(Set mem (StoreL mem src)); 5431 ins_cost(MEMORY_REF_COST + DEFAULT_COST); 5432 5433 size(8); 5434 format %{ "STR $src.lo,$mem\t! long\n\t" 5435 "STR $src.hi,$mem+4" %} 5436 5437 ins_encode %{ 5438 Address Amemlo = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none); 5439 Address Amemhi = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp + 4, relocInfo::none); 5440 __ str($src$$Register, Amemlo); 5441 __ str($src$$Register->successor(), Amemhi); 5442 %} 5443 ins_pipe(istore_mem_reg); 5444 %} 5445 5446 instruct storeL_volatile(indirect mem, iRegL src) %{ 5447 predicate(((StoreLNode*)n)->require_atomic_access()); 5448 match(Set mem (StoreL mem src)); 5449 ins_cost(MEMORY_REF_COST); 5450 size(4); 5451 format %{ "STMIA $src,$mem\t! long" %} 5452 ins_encode %{ 5453 // FIXME: why is stmia considered atomic? Should be strexd 5454 RegisterSet set($src$$Register); 5455 set = set | reg_to_register_object($src$$reg + 1); 5456 __ stmia(reg_to_register_object($mem$$base), set); 5457 %} 5458 ins_pipe(istore_mem_reg); 5459 %} 5460 #endif // !AARCH64 5461 5462 #ifndef AARCH64 5463 instruct storeL_volatile_fp(memoryD mem, iRegL src) %{ 5464 predicate(((StoreLNode*)n)->require_atomic_access()); 5465 match(Set mem (StoreL mem src)); 5466 ins_cost(MEMORY_REF_COST); 5467 size(8); 5468 format %{ "FMDRR S14, $src\t! long \n\t" 5469 "FSTD S14, $mem" %} 5470 ins_encode %{ 5471 __ fmdrr(S14, $src$$Register, $src$$Register->successor()); 5472 __ fstd(S14, $mem$$Address); 5473 %} 5474 ins_pipe(istore_mem_reg); 5475 %} 5476 #endif 5477 5478 #ifdef XXX 5479 // Move SP Pointer 5480 //instruct movSP(sp_ptr_RegP dst, SPRegP src) %{ 5481 //instruct movSP(iRegP dst, SPRegP src) %{ 5482 instruct movSP(store_ptr_RegP dst, SPRegP src) %{ 5483 match(Set dst src); 5484 //predicate(!_kids[1]->_leaf->is_Proj() || _kids[1]->_leaf->as_Proj()->_con == TypeFunc::FramePtr); 5485 ins_cost(MEMORY_REF_COST); 5486 size(4); 5487 5488 format %{ "MOV $dst,$src\t! SP ptr\n\t" %} 5489 ins_encode %{ 5490 assert(false, "XXX1 got here"); 5491 __ mov($dst$$Register, SP); 5492 __ mov($dst$$Register, $src$$Register); 5493 %} 5494 ins_pipe(ialu_reg); 5495 %} 5496 #endif 5497 5498 #ifdef AARCH64 5499 // FIXME 5500 // Store SP Pointer 5501 instruct storeSP(memoryP mem, SPRegP src, iRegP tmp) %{ 5502 match(Set mem (StoreP mem src)); 5503 predicate(_kids[1]->_leaf->is_Proj() && _kids[1]->_leaf->as_Proj()->_con == TypeFunc::FramePtr); 5504 // Multiple StoreP rules, different only in register mask. 5505 // Matcher makes the last always valid. The others will 5506 // only be valid if they cost less than the last valid 5507 // rule. So cost(rule1) < cost(rule2) < cost(last) 5508 // Unlike immediates, register constraints are not checked 5509 // at match time. 5510 ins_cost(MEMORY_REF_COST+DEFAULT_COST+4); 5511 effect(TEMP tmp); 5512 size(8); 5513 5514 format %{ "MOV $tmp,$src\t! SP ptr\n\t" 5515 "STR $tmp,$mem\t! SP ptr" %} 5516 ins_encode %{ 5517 assert($src$$Register == SP, "SP expected"); 5518 __ mov($tmp$$Register, $src$$Register); 5519 __ str($tmp$$Register, $mem$$Address); 5520 %} 5521 ins_pipe(istore_mem_spORreg); // FIXME 5522 %} 5523 #endif // AARCH64 5524 5525 // Store Pointer 5526 5527 #ifdef AARCH64 5528 // XXX This variant shouldn't be necessary if 6217251 is implemented 5529 instruct storePoff(store_ptr_RegP src, memoryScaledP mem, aimmX off, iRegP tmp) %{ 5530 predicate(!_kids[1]->_leaf->is_Proj() || _kids[1]->_leaf->as_Proj()->_con != TypeFunc::FramePtr); 5531 match(Set mem (StoreP (AddP mem off) src)); 5532 ins_cost(MEMORY_REF_COST + DEFAULT_COST); // assume shift/sign-extend is free 5533 effect(TEMP tmp); 5534 size(4 * 2); 5535 5536 format %{ "STR $src,$mem+$off\t! ptr temp=$tmp" %} 5537 ins_encode %{ 5538 Register base = reg_to_register_object($mem$$base); 5539 __ add($tmp$$Register, base, $off$$constant); 5540 Address nmem = Address::make_raw($tmp$$reg, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none); 5541 __ str($src$$Register, nmem); 5542 %} 5543 ins_pipe(istore_mem_reg); 5544 %} 5545 #endif 5546 5547 instruct storeP(memoryP mem, store_ptr_RegP src) %{ 5548 match(Set mem (StoreP mem src)); 5549 #ifdef AARCH64 5550 predicate(!_kids[1]->_leaf->is_Proj() || _kids[1]->_leaf->as_Proj()->_con != TypeFunc::FramePtr); 5551 #endif 5552 ins_cost(MEMORY_REF_COST); 5553 size(4); 5554 5555 format %{ "STR $src,$mem\t! ptr" %} 5556 ins_encode %{ 5557 __ str($src$$Register, $mem$$Address); 5558 %} 5559 ins_pipe(istore_mem_spORreg); 5560 %} 5561 5562 #ifdef AARCH64 5563 // Store NULL Pointer 5564 instruct storeP0(memoryP mem, immP0 src) %{ 5565 match(Set mem (StoreP mem src)); 5566 ins_cost(MEMORY_REF_COST); 5567 size(4); 5568 5569 format %{ "STR ZR,$mem\t! ptr" %} 5570 ins_encode %{ 5571 __ str(ZR, $mem$$Address); 5572 %} 5573 ins_pipe(istore_mem_spORreg); 5574 %} 5575 #endif // AARCH64 5576 5577 #ifdef _LP64 5578 // Store Compressed Pointer 5579 5580 #ifdef AARCH64 5581 // XXX This variant shouldn't be necessary if 6217251 is implemented 5582 instruct storeNoff(store_RegN src, memoryScaledI mem, aimmX off, iRegP tmp) %{ 5583 match(Set mem (StoreN (AddP mem off) src)); 5584 ins_cost(MEMORY_REF_COST + DEFAULT_COST); // assume shift/sign-extend is free 5585 effect(TEMP tmp); 5586 size(4 * 2); 5587 5588 format %{ "str_32 $src,$mem+$off\t! compressed ptr temp=$tmp" %} 5589 ins_encode %{ 5590 Register base = reg_to_register_object($mem$$base); 5591 __ add($tmp$$Register, base, $off$$constant); 5592 Address nmem = Address::make_raw($tmp$$reg, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none); 5593 __ str_32($src$$Register, nmem); 5594 %} 5595 ins_pipe(istore_mem_reg); 5596 %} 5597 #endif 5598 5599 instruct storeN(memoryI mem, store_RegN src) %{ 5600 match(Set mem (StoreN mem src)); 5601 ins_cost(MEMORY_REF_COST); 5602 size(4); 5603 5604 format %{ "str_32 $src,$mem\t! compressed ptr" %} 5605 ins_encode %{ 5606 __ str_32($src$$Register, $mem$$Address); 5607 %} 5608 ins_pipe(istore_mem_reg); 5609 %} 5610 5611 #ifdef AARCH64 5612 // Store NULL Pointer 5613 instruct storeN0(memoryI mem, immN0 src) %{ 5614 match(Set mem (StoreN mem src)); 5615 ins_cost(MEMORY_REF_COST); 5616 size(4); 5617 5618 format %{ "str_32 ZR,$mem\t! compressed ptr" %} 5619 ins_encode %{ 5620 __ str_32(ZR, $mem$$Address); 5621 %} 5622 ins_pipe(istore_mem_reg); 5623 %} 5624 #endif 5625 5626 // Store Compressed Klass Pointer 5627 instruct storeNKlass(memoryI mem, store_RegN src) %{ 5628 match(Set mem (StoreNKlass mem src)); 5629 ins_cost(MEMORY_REF_COST); 5630 size(4); 5631 5632 format %{ "str_32 $src,$mem\t! compressed klass ptr" %} 5633 ins_encode %{ 5634 __ str_32($src$$Register, $mem$$Address); 5635 %} 5636 ins_pipe(istore_mem_reg); 5637 %} 5638 #endif 5639 5640 // Store Double 5641 5642 #ifdef AARCH64 5643 // XXX This variant shouldn't be necessary if 6217251 is implemented 5644 instruct storeDoff(regD src, memoryScaledD mem, aimmX off, iRegP tmp) %{ 5645 match(Set mem (StoreD (AddP mem off) src)); 5646 ins_cost(MEMORY_REF_COST + DEFAULT_COST); // assume shift/sign-extend is free 5647 effect(TEMP tmp); 5648 size(4 * 2); 5649 5650 format %{ "STR $src,$mem+$off\t! double temp=$tmp" %} 5651 ins_encode %{ 5652 Register base = reg_to_register_object($mem$$base); 5653 __ add($tmp$$Register, base, $off$$constant); 5654 Address nmem = Address::make_raw($tmp$$reg, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none); 5655 __ str_d($src$$FloatRegister, nmem); 5656 %} 5657 ins_pipe(fstoreD_mem_reg); 5658 %} 5659 #endif 5660 5661 instruct storeD(memoryD mem, regD src) %{ 5662 match(Set mem (StoreD mem src)); 5663 ins_cost(MEMORY_REF_COST); 5664 5665 size(4); 5666 // FIXME: needs to be atomic, but ARMv7 A.R.M. guarantees 5667 // only LDREXD and STREXD are 64-bit single-copy atomic 5668 format %{ "FSTD $src,$mem" %} 5669 ins_encode %{ 5670 __ str_double($src$$FloatRegister, $mem$$Address); 5671 %} 5672 ins_pipe(fstoreD_mem_reg); 5673 %} 5674 5675 #ifdef AARCH64 5676 instruct movI2F(regF dst, iRegI src) %{ 5677 match(Set dst src); 5678 size(4); 5679 5680 format %{ "FMOV_sw $dst,$src\t! movI2F" %} 5681 ins_encode %{ 5682 __ fmov_sw($dst$$FloatRegister, $src$$Register); 5683 %} 5684 ins_pipe(ialu_reg); // FIXME 5685 %} 5686 5687 instruct movF2I(iRegI dst, regF src) %{ 5688 match(Set dst src); 5689 size(4); 5690 5691 format %{ "FMOV_ws $dst,$src\t! movF2I" %} 5692 ins_encode %{ 5693 __ fmov_ws($dst$$Register, $src$$FloatRegister); 5694 %} 5695 ins_pipe(ialu_reg); // FIXME 5696 %} 5697 #endif 5698 5699 // Store Float 5700 5701 #ifdef AARCH64 5702 // XXX This variant shouldn't be necessary if 6217251 is implemented 5703 instruct storeFoff(regF src, memoryScaledF mem, aimmX off, iRegP tmp) %{ 5704 match(Set mem (StoreF (AddP mem off) src)); 5705 ins_cost(MEMORY_REF_COST + DEFAULT_COST); // assume shift/sign-extend is free 5706 effect(TEMP tmp); 5707 size(4 * 2); 5708 5709 format %{ "str_s $src,$mem+$off\t! float temp=$tmp" %} 5710 ins_encode %{ 5711 Register base = reg_to_register_object($mem$$base); 5712 __ add($tmp$$Register, base, $off$$constant); 5713 Address nmem = Address::make_raw($tmp$$reg, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none); 5714 __ str_s($src$$FloatRegister, nmem); 5715 %} 5716 ins_pipe(fstoreF_mem_reg); 5717 %} 5718 #endif 5719 5720 instruct storeF( memoryF mem, regF src) %{ 5721 match(Set mem (StoreF mem src)); 5722 ins_cost(MEMORY_REF_COST); 5723 5724 size(4); 5725 format %{ "FSTS $src,$mem" %} 5726 ins_encode %{ 5727 __ str_float($src$$FloatRegister, $mem$$Address); 5728 %} 5729 ins_pipe(fstoreF_mem_reg); 5730 %} 5731 5732 #ifdef AARCH64 5733 // Convert oop pointer into compressed form 5734 instruct encodeHeapOop(iRegN dst, iRegP src, flagsReg ccr) %{ 5735 predicate(n->bottom_type()->make_ptr()->ptr() != TypePtr::NotNull); 5736 match(Set dst (EncodeP src)); 5737 effect(KILL ccr); 5738 format %{ "encode_heap_oop $dst, $src" %} 5739 ins_encode %{ 5740 __ encode_heap_oop($dst$$Register, $src$$Register); 5741 %} 5742 ins_pipe(ialu_reg); 5743 %} 5744 5745 instruct encodeHeapOop_not_null(iRegN dst, iRegP src) %{ 5746 predicate(n->bottom_type()->make_ptr()->ptr() == TypePtr::NotNull); 5747 match(Set dst (EncodeP src)); 5748 format %{ "encode_heap_oop_not_null $dst, $src" %} 5749 ins_encode %{ 5750 __ encode_heap_oop_not_null($dst$$Register, $src$$Register); 5751 %} 5752 ins_pipe(ialu_reg); 5753 %} 5754 5755 instruct decodeHeapOop(iRegP dst, iRegN src, flagsReg ccr) %{ 5756 predicate(n->bottom_type()->is_oopptr()->ptr() != TypePtr::NotNull && 5757 n->bottom_type()->is_oopptr()->ptr() != TypePtr::Constant); 5758 match(Set dst (DecodeN src)); 5759 effect(KILL ccr); 5760 format %{ "decode_heap_oop $dst, $src" %} 5761 ins_encode %{ 5762 __ decode_heap_oop($dst$$Register, $src$$Register); 5763 %} 5764 ins_pipe(ialu_reg); 5765 %} 5766 5767 instruct decodeHeapOop_not_null(iRegP dst, iRegN src) %{ 5768 predicate(n->bottom_type()->is_oopptr()->ptr() == TypePtr::NotNull || 5769 n->bottom_type()->is_oopptr()->ptr() == TypePtr::Constant); 5770 match(Set dst (DecodeN src)); 5771 format %{ "decode_heap_oop_not_null $dst, $src" %} 5772 ins_encode %{ 5773 __ decode_heap_oop_not_null($dst$$Register, $src$$Register); 5774 %} 5775 ins_pipe(ialu_reg); 5776 %} 5777 5778 instruct encodeKlass_not_null(iRegN dst, iRegP src) %{ 5779 match(Set dst (EncodePKlass src)); 5780 format %{ "encode_klass_not_null $dst, $src" %} 5781 ins_encode %{ 5782 __ encode_klass_not_null($dst$$Register, $src$$Register); 5783 %} 5784 ins_pipe(ialu_reg); 5785 %} 5786 5787 instruct decodeKlass_not_null(iRegP dst, iRegN src) %{ 5788 match(Set dst (DecodeNKlass src)); 5789 format %{ "decode_klass_not_null $dst, $src" %} 5790 ins_encode %{ 5791 __ decode_klass_not_null($dst$$Register, $src$$Register); 5792 %} 5793 ins_pipe(ialu_reg); 5794 %} 5795 #endif // AARCH64 5796 5797 //----------MemBar Instructions----------------------------------------------- 5798 // Memory barrier flavors 5799 5800 // TODO: take advantage of Aarch64 load-acquire, store-release, etc 5801 // pattern-match out unnecessary membars 5802 instruct membar_storestore() %{ 5803 match(MemBarStoreStore); 5804 ins_cost(4*MEMORY_REF_COST); 5805 5806 size(4); 5807 format %{ "MEMBAR-storestore" %} 5808 ins_encode %{ 5809 __ membar(MacroAssembler::Membar_mask_bits(MacroAssembler::StoreStore), noreg); 5810 %} 5811 ins_pipe(long_memory_op); 5812 %} 5813 5814 instruct membar_acquire() %{ 5815 match(MemBarAcquire); 5816 match(LoadFence); 5817 ins_cost(4*MEMORY_REF_COST); 5818 5819 size(4); 5820 format %{ "MEMBAR-acquire" %} 5821 ins_encode %{ 5822 __ membar(MacroAssembler::Membar_mask_bits(MacroAssembler::LoadLoad | MacroAssembler::LoadStore), noreg); 5823 %} 5824 ins_pipe(long_memory_op); 5825 %} 5826 5827 instruct membar_acquire_lock() %{ 5828 match(MemBarAcquireLock); 5829 ins_cost(0); 5830 5831 size(0); 5832 format %{ "!MEMBAR-acquire (CAS in prior FastLock so empty encoding)" %} 5833 ins_encode( ); 5834 ins_pipe(empty); 5835 %} 5836 5837 instruct membar_release() %{ 5838 match(MemBarRelease); 5839 match(StoreFence); 5840 ins_cost(4*MEMORY_REF_COST); 5841 5842 size(4); 5843 format %{ "MEMBAR-release" %} 5844 ins_encode %{ 5845 __ membar(MacroAssembler::Membar_mask_bits(MacroAssembler::StoreStore | MacroAssembler::LoadStore), noreg); 5846 %} 5847 ins_pipe(long_memory_op); 5848 %} 5849 5850 instruct membar_release_lock() %{ 5851 match(MemBarReleaseLock); 5852 ins_cost(0); 5853 5854 size(0); 5855 format %{ "!MEMBAR-release (CAS in succeeding FastUnlock so empty encoding)" %} 5856 ins_encode( ); 5857 ins_pipe(empty); 5858 %} 5859 5860 instruct membar_volatile() %{ 5861 match(MemBarVolatile); 5862 ins_cost(4*MEMORY_REF_COST); 5863 5864 size(4); 5865 format %{ "MEMBAR-volatile" %} 5866 ins_encode %{ 5867 __ membar(MacroAssembler::StoreLoad, noreg); 5868 %} 5869 ins_pipe(long_memory_op); 5870 %} 5871 5872 instruct unnecessary_membar_volatile() %{ 5873 match(MemBarVolatile); 5874 predicate(Matcher::post_store_load_barrier(n)); 5875 ins_cost(0); 5876 5877 size(0); 5878 format %{ "!MEMBAR-volatile (unnecessary so empty encoding)" %} 5879 ins_encode( ); 5880 ins_pipe(empty); 5881 %} 5882 5883 //----------Register Move Instructions----------------------------------------- 5884 // instruct roundDouble_nop(regD dst) %{ 5885 // match(Set dst (RoundDouble dst)); 5886 // ins_pipe(empty); 5887 // %} 5888 5889 5890 // instruct roundFloat_nop(regF dst) %{ 5891 // match(Set dst (RoundFloat dst)); 5892 // ins_pipe(empty); 5893 // %} 5894 5895 5896 #ifdef AARCH64 5897 // 0 constant in register 5898 instruct zrImmI0(ZRRegI dst, immI0 imm) %{ 5899 match(Set dst imm); 5900 size(0); 5901 ins_cost(0); 5902 5903 format %{ "! ZR (int 0)" %} 5904 ins_encode( /*empty encoding*/ ); 5905 ins_pipe(ialu_none); 5906 %} 5907 5908 // 0 constant in register 5909 instruct zrImmL0(ZRRegL dst, immL0 imm) %{ 5910 match(Set dst imm); 5911 size(0); 5912 ins_cost(0); 5913 5914 format %{ "! ZR (long 0)" %} 5915 ins_encode( /*empty encoding*/ ); 5916 ins_pipe(ialu_none); 5917 %} 5918 5919 #ifdef XXX 5920 // 0 constant in register 5921 instruct zrImmN0(ZRRegN dst, immN0 imm) %{ 5922 match(Set dst imm); 5923 size(0); 5924 ins_cost(0); 5925 5926 format %{ "! ZR (compressed pointer NULL)" %} 5927 ins_encode( /*empty encoding*/ ); 5928 ins_pipe(ialu_none); 5929 %} 5930 5931 // 0 constant in register 5932 instruct zrImmP0(ZRRegP dst, immP0 imm) %{ 5933 match(Set dst imm); 5934 size(0); 5935 ins_cost(0); 5936 5937 format %{ "! ZR (NULL)" %} 5938 ins_encode( /*empty encoding*/ ); 5939 ins_pipe(ialu_none); 5940 %} 5941 #endif 5942 #endif // AARCH64 5943 5944 // Cast Index to Pointer for unsafe natives 5945 instruct castX2P(iRegX src, iRegP dst) %{ 5946 match(Set dst (CastX2P src)); 5947 5948 format %{ "MOV $dst,$src\t! IntX->Ptr if $dst != $src" %} 5949 ins_encode %{ 5950 if ($dst$$Register != $src$$Register) { 5951 __ mov($dst$$Register, $src$$Register); 5952 } 5953 %} 5954 ins_pipe(ialu_reg); 5955 %} 5956 5957 // Cast Pointer to Index for unsafe natives 5958 instruct castP2X(iRegP src, iRegX dst) %{ 5959 match(Set dst (CastP2X src)); 5960 5961 format %{ "MOV $dst,$src\t! Ptr->IntX if $dst != $src" %} 5962 ins_encode %{ 5963 if ($dst$$Register != $src$$Register) { 5964 __ mov($dst$$Register, $src$$Register); 5965 } 5966 %} 5967 ins_pipe(ialu_reg); 5968 %} 5969 5970 #ifndef AARCH64 5971 //----------Conditional Move--------------------------------------------------- 5972 // Conditional move 5973 instruct cmovIP_reg(cmpOpP cmp, flagsRegP pcc, iRegI dst, iRegI src) %{ 5974 match(Set dst (CMoveI (Binary cmp pcc) (Binary dst src))); 5975 ins_cost(150); 5976 size(4); 5977 format %{ "MOV$cmp $dst,$src\t! int" %} 5978 ins_encode %{ 5979 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 5980 %} 5981 ins_pipe(ialu_reg); 5982 %} 5983 #endif 5984 5985 #ifdef AARCH64 5986 instruct cmovI_reg3(cmpOp cmp, flagsReg icc, iRegI dst, iRegI src1, iRegI src2) %{ 5987 match(Set dst (CMoveI (Binary cmp icc) (Binary src2 src1))); 5988 ins_cost(150); 5989 size(4); 5990 format %{ "CSEL $dst,$src1,$src2,$cmp\t! int" %} 5991 ins_encode %{ 5992 __ csel($dst$$Register, $src1$$Register, $src2$$Register, (AsmCondition)($cmp$$cmpcode)); 5993 %} 5994 ins_pipe(ialu_reg); 5995 %} 5996 5997 instruct cmovL_reg3(cmpOp cmp, flagsReg icc, iRegL dst, iRegL src1, iRegL src2) %{ 5998 match(Set dst (CMoveL (Binary cmp icc) (Binary src2 src1))); 5999 ins_cost(150); 6000 size(4); 6001 format %{ "CSEL $dst,$src1,$src2,$cmp\t! long" %} 6002 ins_encode %{ 6003 __ csel($dst$$Register, $src1$$Register, $src2$$Register, (AsmCondition)($cmp$$cmpcode)); 6004 %} 6005 ins_pipe(ialu_reg); 6006 %} 6007 6008 instruct cmovP_reg3(cmpOp cmp, flagsReg icc, iRegP dst, iRegP src1, iRegP src2) %{ 6009 match(Set dst (CMoveP (Binary cmp icc) (Binary src2 src1))); 6010 ins_cost(150); 6011 size(4); 6012 format %{ "CSEL $dst,$src1,$src2,$cmp\t! ptr" %} 6013 ins_encode %{ 6014 __ csel($dst$$Register, $src1$$Register, $src2$$Register, (AsmCondition)($cmp$$cmpcode)); 6015 %} 6016 ins_pipe(ialu_reg); 6017 %} 6018 6019 instruct cmovN_reg3(cmpOp cmp, flagsReg icc, iRegN dst, iRegN src1, iRegN src2) %{ 6020 match(Set dst (CMoveN (Binary cmp icc) (Binary src2 src1))); 6021 ins_cost(150); 6022 size(4); 6023 format %{ "CSEL $dst,$src1,$src2,$cmp\t! compressed ptr" %} 6024 ins_encode %{ 6025 __ csel($dst$$Register, $src1$$Register, $src2$$Register, (AsmCondition)($cmp$$cmpcode)); 6026 %} 6027 ins_pipe(ialu_reg); 6028 %} 6029 6030 instruct cmovIP_reg3(cmpOpP cmp, flagsRegP icc, iRegI dst, iRegI src1, iRegI src2) %{ 6031 match(Set dst (CMoveI (Binary cmp icc) (Binary src2 src1))); 6032 ins_cost(150); 6033 size(4); 6034 format %{ "CSEL $dst,$src1,$src2,$cmp\t! int" %} 6035 ins_encode %{ 6036 __ csel($dst$$Register, $src1$$Register, $src2$$Register, (AsmCondition)($cmp$$cmpcode)); 6037 %} 6038 ins_pipe(ialu_reg); 6039 %} 6040 6041 instruct cmovLP_reg3(cmpOpP cmp, flagsRegP icc, iRegL dst, iRegL src1, iRegL src2) %{ 6042 match(Set dst (CMoveL (Binary cmp icc) (Binary src2 src1))); 6043 ins_cost(150); 6044 size(4); 6045 format %{ "CSEL $dst,$src1,$src2,$cmp\t! long" %} 6046 ins_encode %{ 6047 __ csel($dst$$Register, $src1$$Register, $src2$$Register, (AsmCondition)($cmp$$cmpcode)); 6048 %} 6049 ins_pipe(ialu_reg); 6050 %} 6051 6052 instruct cmovPP_reg3(cmpOpP cmp, flagsRegP icc, iRegP dst, iRegP src1, iRegP src2) %{ 6053 match(Set dst (CMoveP (Binary cmp icc) (Binary src2 src1))); 6054 ins_cost(150); 6055 size(4); 6056 format %{ "CSEL $dst,$src1,$src2,$cmp\t! ptr" %} 6057 ins_encode %{ 6058 __ csel($dst$$Register, $src1$$Register, $src2$$Register, (AsmCondition)($cmp$$cmpcode)); 6059 %} 6060 ins_pipe(ialu_reg); 6061 %} 6062 6063 instruct cmovNP_reg3(cmpOpP cmp, flagsRegP icc, iRegN dst, iRegN src1, iRegN src2) %{ 6064 match(Set dst (CMoveN (Binary cmp icc) (Binary src2 src1))); 6065 ins_cost(150); 6066 size(4); 6067 format %{ "CSEL $dst,$src1,$src2,$cmp\t! compressed ptr" %} 6068 ins_encode %{ 6069 __ csel($dst$$Register, $src1$$Register, $src2$$Register, (AsmCondition)($cmp$$cmpcode)); 6070 %} 6071 ins_pipe(ialu_reg); 6072 %} 6073 6074 instruct cmovIU_reg3(cmpOpU cmp, flagsRegU icc, iRegI dst, iRegI src1, iRegI src2) %{ 6075 match(Set dst (CMoveI (Binary cmp icc) (Binary src2 src1))); 6076 ins_cost(150); 6077 size(4); 6078 format %{ "CSEL $dst,$src1,$src2,$cmp\t! int" %} 6079 ins_encode %{ 6080 __ csel($dst$$Register, $src1$$Register, $src2$$Register, (AsmCondition)($cmp$$cmpcode)); 6081 %} 6082 ins_pipe(ialu_reg); 6083 %} 6084 6085 instruct cmovLU_reg3(cmpOpU cmp, flagsRegU icc, iRegL dst, iRegL src1, iRegL src2) %{ 6086 match(Set dst (CMoveL (Binary cmp icc) (Binary src2 src1))); 6087 ins_cost(150); 6088 size(4); 6089 format %{ "CSEL $dst,$src1,$src2,$cmp\t! long" %} 6090 ins_encode %{ 6091 __ csel($dst$$Register, $src1$$Register, $src2$$Register, (AsmCondition)($cmp$$cmpcode)); 6092 %} 6093 ins_pipe(ialu_reg); 6094 %} 6095 6096 instruct cmovPU_reg3(cmpOpU cmp, flagsRegU icc, iRegP dst, iRegP src1, iRegP src2) %{ 6097 match(Set dst (CMoveP (Binary cmp icc) (Binary src2 src1))); 6098 ins_cost(150); 6099 size(4); 6100 format %{ "CSEL $dst,$src1,$src2,$cmp\t! ptr" %} 6101 ins_encode %{ 6102 __ csel($dst$$Register, $src1$$Register, $src2$$Register, (AsmCondition)($cmp$$cmpcode)); 6103 %} 6104 ins_pipe(ialu_reg); 6105 %} 6106 6107 instruct cmovNU_reg3(cmpOpU cmp, flagsRegU icc, iRegN dst, iRegN src1, iRegN src2) %{ 6108 match(Set dst (CMoveN (Binary cmp icc) (Binary src2 src1))); 6109 ins_cost(150); 6110 size(4); 6111 format %{ "CSEL $dst,$src1,$src2,$cmp\t! compressed ptr" %} 6112 ins_encode %{ 6113 __ csel($dst$$Register, $src1$$Register, $src2$$Register, (AsmCondition)($cmp$$cmpcode)); 6114 %} 6115 ins_pipe(ialu_reg); 6116 %} 6117 6118 instruct cmovIZ_reg3(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegI dst, iRegI src1, iRegI src2) %{ 6119 match(Set dst (CMoveI (Binary cmp icc) (Binary src2 src1))); 6120 ins_cost(150); 6121 size(4); 6122 format %{ "CSEL $dst,$src1,$src2,$cmp\t! int" %} 6123 ins_encode %{ 6124 __ csel($dst$$Register, $src1$$Register, $src2$$Register, (AsmCondition)($cmp$$cmpcode)); 6125 %} 6126 ins_pipe(ialu_reg); 6127 %} 6128 6129 instruct cmovLZ_reg3(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegL dst, iRegL src1, iRegL src2) %{ 6130 match(Set dst (CMoveL (Binary cmp icc) (Binary src2 src1))); 6131 ins_cost(150); 6132 size(4); 6133 format %{ "CSEL $dst,$src1,$src2,$cmp\t! long" %} 6134 ins_encode %{ 6135 __ csel($dst$$Register, $src1$$Register, $src2$$Register, (AsmCondition)($cmp$$cmpcode)); 6136 %} 6137 ins_pipe(ialu_reg); 6138 %} 6139 6140 instruct cmovPZ_reg3(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegP dst, iRegP src1, iRegP src2) %{ 6141 match(Set dst (CMoveP (Binary cmp icc) (Binary src2 src1))); 6142 ins_cost(150); 6143 size(4); 6144 format %{ "CSEL $dst,$src1,$src2,$cmp\t! ptr" %} 6145 ins_encode %{ 6146 __ csel($dst$$Register, $src1$$Register, $src2$$Register, (AsmCondition)($cmp$$cmpcode)); 6147 %} 6148 ins_pipe(ialu_reg); 6149 %} 6150 6151 instruct cmovNZ_reg3(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegN dst, iRegN src1, iRegN src2) %{ 6152 match(Set dst (CMoveN (Binary cmp icc) (Binary src2 src1))); 6153 ins_cost(150); 6154 size(4); 6155 format %{ "CSEL $dst,$src1,$src2,$cmp\t! compressed ptr" %} 6156 ins_encode %{ 6157 __ csel($dst$$Register, $src1$$Register, $src2$$Register, (AsmCondition)($cmp$$cmpcode)); 6158 %} 6159 ins_pipe(ialu_reg); 6160 %} 6161 #endif // AARCH64 6162 6163 #ifndef AARCH64 6164 instruct cmovIP_immMov(cmpOpP cmp, flagsRegP pcc, iRegI dst, immIMov src) %{ 6165 match(Set dst (CMoveI (Binary cmp pcc) (Binary dst src))); 6166 ins_cost(140); 6167 size(4); 6168 format %{ "MOV$cmp $dst,$src" %} 6169 ins_encode %{ 6170 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 6171 %} 6172 ins_pipe(ialu_imm); 6173 %} 6174 6175 instruct cmovIP_imm16(cmpOpP cmp, flagsRegP pcc, iRegI dst, immI16 src) %{ 6176 match(Set dst (CMoveI (Binary cmp pcc) (Binary dst src))); 6177 ins_cost(140); 6178 size(4); 6179 format %{ "MOVw$cmp $dst,$src" %} 6180 ins_encode %{ 6181 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 6182 %} 6183 ins_pipe(ialu_imm); 6184 %} 6185 #endif 6186 6187 instruct cmovI_reg(cmpOp cmp, flagsReg icc, iRegI dst, iRegI src) %{ 6188 match(Set dst (CMoveI (Binary cmp icc) (Binary dst src))); 6189 ins_cost(150); 6190 size(4); 6191 format %{ "MOV$cmp $dst,$src" %} 6192 ins_encode %{ 6193 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 6194 %} 6195 ins_pipe(ialu_reg); 6196 %} 6197 6198 #ifdef AARCH64 6199 instruct cmovL_reg(cmpOp cmp, flagsReg icc, iRegL dst, iRegL src) %{ 6200 match(Set dst (CMoveL (Binary cmp icc) (Binary dst src))); 6201 ins_cost(150); 6202 size(4); 6203 format %{ "MOV$cmp $dst,$src\t! long" %} 6204 ins_encode %{ 6205 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 6206 %} 6207 ins_pipe(ialu_reg); 6208 %} 6209 #endif 6210 6211 #ifndef AARCH64 6212 instruct cmovI_immMov(cmpOp cmp, flagsReg icc, iRegI dst, immIMov src) %{ 6213 match(Set dst (CMoveI (Binary cmp icc) (Binary dst src))); 6214 ins_cost(140); 6215 size(4); 6216 format %{ "MOV$cmp $dst,$src" %} 6217 ins_encode %{ 6218 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 6219 %} 6220 ins_pipe(ialu_imm); 6221 %} 6222 6223 instruct cmovII_imm16(cmpOp cmp, flagsReg icc, iRegI dst, immI16 src) %{ 6224 match(Set dst (CMoveI (Binary cmp icc) (Binary dst src))); 6225 ins_cost(140); 6226 size(4); 6227 format %{ "MOVw$cmp $dst,$src" %} 6228 ins_encode %{ 6229 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 6230 %} 6231 ins_pipe(ialu_imm); 6232 %} 6233 #endif 6234 6235 instruct cmovII_reg_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegI dst, iRegI src) %{ 6236 match(Set dst (CMoveI (Binary cmp icc) (Binary dst src))); 6237 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || 6238 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne || 6239 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || 6240 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge); 6241 ins_cost(150); 6242 size(4); 6243 format %{ "MOV$cmp $dst,$src" %} 6244 ins_encode %{ 6245 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 6246 %} 6247 ins_pipe(ialu_reg); 6248 %} 6249 6250 #ifndef AARCH64 6251 instruct cmovII_immMov_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegI dst, immIMov src) %{ 6252 match(Set dst (CMoveI (Binary cmp icc) (Binary dst src))); 6253 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || 6254 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne || 6255 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || 6256 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge); 6257 ins_cost(140); 6258 size(4); 6259 format %{ "MOV$cmp $dst,$src" %} 6260 ins_encode %{ 6261 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 6262 %} 6263 ins_pipe(ialu_imm); 6264 %} 6265 6266 instruct cmovII_imm16_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegI dst, immI16 src) %{ 6267 match(Set dst (CMoveI (Binary cmp icc) (Binary dst src))); 6268 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || 6269 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne || 6270 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || 6271 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge); 6272 ins_cost(140); 6273 size(4); 6274 format %{ "MOVW$cmp $dst,$src" %} 6275 ins_encode %{ 6276 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 6277 %} 6278 ins_pipe(ialu_imm); 6279 %} 6280 #endif 6281 6282 instruct cmovIIu_reg(cmpOpU cmp, flagsRegU icc, iRegI dst, iRegI src) %{ 6283 match(Set dst (CMoveI (Binary cmp icc) (Binary dst src))); 6284 ins_cost(150); 6285 size(4); 6286 format %{ "MOV$cmp $dst,$src" %} 6287 ins_encode %{ 6288 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 6289 %} 6290 ins_pipe(ialu_reg); 6291 %} 6292 6293 #ifndef AARCH64 6294 instruct cmovIIu_immMov(cmpOpU cmp, flagsRegU icc, iRegI dst, immIMov src) %{ 6295 match(Set dst (CMoveI (Binary cmp icc) (Binary dst src))); 6296 ins_cost(140); 6297 size(4); 6298 format %{ "MOV$cmp $dst,$src" %} 6299 ins_encode %{ 6300 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 6301 %} 6302 ins_pipe(ialu_imm); 6303 %} 6304 6305 instruct cmovIIu_imm16(cmpOpU cmp, flagsRegU icc, iRegI dst, immI16 src) %{ 6306 match(Set dst (CMoveI (Binary cmp icc) (Binary dst src))); 6307 ins_cost(140); 6308 size(4); 6309 format %{ "MOVW$cmp $dst,$src" %} 6310 ins_encode %{ 6311 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 6312 %} 6313 ins_pipe(ialu_imm); 6314 %} 6315 #endif 6316 6317 // Conditional move 6318 instruct cmovPP_reg(cmpOpP cmp, flagsRegP pcc, iRegP dst, iRegP src) %{ 6319 match(Set dst (CMoveP (Binary cmp pcc) (Binary dst src))); 6320 ins_cost(150); 6321 size(4); 6322 format %{ "MOV$cmp $dst,$src" %} 6323 ins_encode %{ 6324 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 6325 %} 6326 ins_pipe(ialu_reg); 6327 %} 6328 6329 instruct cmovPP_imm(cmpOpP cmp, flagsRegP pcc, iRegP dst, immP0 src) %{ 6330 match(Set dst (CMoveP (Binary cmp pcc) (Binary dst src))); 6331 ins_cost(140); 6332 size(4); 6333 #ifdef AARCH64 6334 format %{ "MOV$cmp $dst,ZR" %} 6335 #else 6336 format %{ "MOV$cmp $dst,$src" %} 6337 #endif 6338 ins_encode %{ 6339 #ifdef AARCH64 6340 __ mov($dst$$Register, ZR, (AsmCondition)($cmp$$cmpcode)); 6341 #else 6342 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 6343 #endif 6344 %} 6345 ins_pipe(ialu_imm); 6346 %} 6347 6348 // This instruction also works with CmpN so we don't need cmovPN_reg. 6349 instruct cmovPI_reg(cmpOp cmp, flagsReg icc, iRegP dst, iRegP src) %{ 6350 match(Set dst (CMoveP (Binary cmp icc) (Binary dst src))); 6351 ins_cost(150); 6352 6353 size(4); 6354 format %{ "MOV$cmp $dst,$src\t! ptr" %} 6355 ins_encode %{ 6356 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 6357 %} 6358 ins_pipe(ialu_reg); 6359 %} 6360 6361 instruct cmovPI_reg_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegP dst, iRegP src) %{ 6362 match(Set dst (CMoveP (Binary cmp icc) (Binary dst src))); 6363 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || 6364 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne || 6365 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || 6366 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge); 6367 ins_cost(150); 6368 6369 size(4); 6370 format %{ "MOV$cmp $dst,$src\t! ptr" %} 6371 ins_encode %{ 6372 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 6373 %} 6374 ins_pipe(ialu_reg); 6375 %} 6376 6377 instruct cmovPIu_reg(cmpOpU cmp, flagsRegU icc, iRegP dst, iRegP src) %{ 6378 match(Set dst (CMoveP (Binary cmp icc) (Binary dst src))); 6379 ins_cost(150); 6380 6381 size(4); 6382 format %{ "MOV$cmp $dst,$src\t! ptr" %} 6383 ins_encode %{ 6384 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 6385 %} 6386 ins_pipe(ialu_reg); 6387 %} 6388 6389 instruct cmovPI_imm(cmpOp cmp, flagsReg icc, iRegP dst, immP0 src) %{ 6390 match(Set dst (CMoveP (Binary cmp icc) (Binary dst src))); 6391 ins_cost(140); 6392 6393 size(4); 6394 #ifdef AARCH64 6395 format %{ "MOV$cmp $dst,ZR\t! ptr" %} 6396 #else 6397 format %{ "MOV$cmp $dst,$src\t! ptr" %} 6398 #endif 6399 ins_encode %{ 6400 #ifdef AARCH64 6401 __ mov($dst$$Register, ZR, (AsmCondition)($cmp$$cmpcode)); 6402 #else 6403 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 6404 #endif 6405 %} 6406 ins_pipe(ialu_imm); 6407 %} 6408 6409 instruct cmovPI_imm_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegP dst, immP0 src) %{ 6410 match(Set dst (CMoveP (Binary cmp icc) (Binary dst src))); 6411 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || 6412 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne || 6413 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || 6414 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge); 6415 ins_cost(140); 6416 6417 size(4); 6418 #ifdef AARCH64 6419 format %{ "MOV$cmp $dst,ZR\t! ptr" %} 6420 #else 6421 format %{ "MOV$cmp $dst,$src\t! ptr" %} 6422 #endif 6423 ins_encode %{ 6424 #ifdef AARCH64 6425 __ mov($dst$$Register, ZR, (AsmCondition)($cmp$$cmpcode)); 6426 #else 6427 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 6428 #endif 6429 %} 6430 ins_pipe(ialu_imm); 6431 %} 6432 6433 instruct cmovPIu_imm(cmpOpU cmp, flagsRegU icc, iRegP dst, immP0 src) %{ 6434 match(Set dst (CMoveP (Binary cmp icc) (Binary dst src))); 6435 ins_cost(140); 6436 6437 size(4); 6438 #ifdef AARCH64 6439 format %{ "MOV$cmp $dst,ZR\t! ptr" %} 6440 #else 6441 format %{ "MOV$cmp $dst,$src\t! ptr" %} 6442 #endif 6443 ins_encode %{ 6444 #ifdef AARCH64 6445 __ mov($dst$$Register, ZR, (AsmCondition)($cmp$$cmpcode)); 6446 #else 6447 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 6448 #endif 6449 %} 6450 ins_pipe(ialu_imm); 6451 %} 6452 6453 #ifdef AARCH64 6454 // Conditional move 6455 instruct cmovF_reg(cmpOp cmp, flagsReg icc, regF dst, regF src1, regF src2) %{ 6456 match(Set dst (CMoveF (Binary cmp icc) (Binary src2 src1))); 6457 ins_cost(150); 6458 size(4); 6459 format %{ "FCSEL_s $dst,$src1,$src2,$cmp" %} 6460 ins_encode %{ 6461 __ fcsel_s($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, (AsmCondition)($cmp$$cmpcode)); 6462 %} 6463 ins_pipe(int_conditional_float_move); 6464 %} 6465 6466 instruct cmovD_reg(cmpOp cmp, flagsReg icc, regD dst, regD src1, regD src2) %{ 6467 match(Set dst (CMoveD (Binary cmp icc) (Binary src2 src1))); 6468 ins_cost(150); 6469 size(4); 6470 format %{ "FCSEL_d $dst,$src1,$src2,$cmp" %} 6471 ins_encode %{ 6472 __ fcsel_d($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, (AsmCondition)($cmp$$cmpcode)); 6473 %} 6474 ins_pipe(int_conditional_float_move); 6475 %} 6476 6477 instruct cmovFP_reg(cmpOpP cmp, flagsRegP icc, regF dst, regF src1, regF src2) %{ 6478 match(Set dst (CMoveF (Binary cmp icc) (Binary src2 src1))); 6479 ins_cost(150); 6480 size(4); 6481 format %{ "FCSEL_s $dst,$src1,$src2,$cmp" %} 6482 ins_encode %{ 6483 __ fcsel_s($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, (AsmCondition)($cmp$$cmpcode)); 6484 %} 6485 ins_pipe(int_conditional_float_move); 6486 %} 6487 6488 instruct cmovDP_reg(cmpOpP cmp, flagsRegP icc, regD dst, regD src1, regD src2) %{ 6489 match(Set dst (CMoveD (Binary cmp icc) (Binary src2 src1))); 6490 ins_cost(150); 6491 size(4); 6492 format %{ "FCSEL_d $dst,$src1,$src2,$cmp" %} 6493 ins_encode %{ 6494 __ fcsel_d($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, (AsmCondition)($cmp$$cmpcode)); 6495 %} 6496 ins_pipe(int_conditional_float_move); 6497 %} 6498 6499 instruct cmovFU_reg(cmpOpU cmp, flagsRegU icc, regF dst, regF src1, regF src2) %{ 6500 match(Set dst (CMoveF (Binary cmp icc) (Binary src2 src1))); 6501 ins_cost(150); 6502 size(4); 6503 format %{ "FCSEL_s $dst,$src1,$src2,$cmp" %} 6504 ins_encode %{ 6505 __ fcsel_s($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, (AsmCondition)($cmp$$cmpcode)); 6506 %} 6507 ins_pipe(int_conditional_float_move); 6508 %} 6509 6510 instruct cmovDU_reg(cmpOpU cmp, flagsRegU icc, regD dst, regD src1, regD src2) %{ 6511 match(Set dst (CMoveD (Binary cmp icc) (Binary src2 src1))); 6512 ins_cost(150); 6513 size(4); 6514 format %{ "FCSEL_d $dst,$src1,$src2,$cmp" %} 6515 ins_encode %{ 6516 __ fcsel_d($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, (AsmCondition)($cmp$$cmpcode)); 6517 %} 6518 ins_pipe(int_conditional_float_move); 6519 %} 6520 6521 instruct cmovFZ_reg(cmpOp0 cmp, flagsReg_EQNELTGE icc, regF dst, regF src1, regF src2) %{ 6522 match(Set dst (CMoveF (Binary cmp icc) (Binary src2 src1))); 6523 ins_cost(150); 6524 size(4); 6525 format %{ "FCSEL_s $dst,$src1,$src2,$cmp" %} 6526 ins_encode %{ 6527 __ fcsel_s($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, (AsmCondition)($cmp$$cmpcode)); 6528 %} 6529 ins_pipe(int_conditional_float_move); 6530 %} 6531 6532 instruct cmovDZ_reg(cmpOp0 cmp, flagsReg_EQNELTGE icc, regD dst, regD src1, regD src2) %{ 6533 match(Set dst (CMoveD (Binary cmp icc) (Binary src2 src1))); 6534 ins_cost(150); 6535 size(4); 6536 format %{ "FCSEL_d $dst,$src1,$src2,$cmp" %} 6537 ins_encode %{ 6538 __ fcsel_d($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, (AsmCondition)($cmp$$cmpcode)); 6539 %} 6540 ins_pipe(int_conditional_float_move); 6541 %} 6542 6543 #else // !AARCH64 6544 6545 // Conditional move 6546 instruct cmovFP_reg(cmpOpP cmp, flagsRegP pcc, regF dst, regF src) %{ 6547 match(Set dst (CMoveF (Binary cmp pcc) (Binary dst src))); 6548 ins_cost(150); 6549 size(4); 6550 format %{ "FCPYS$cmp $dst,$src" %} 6551 ins_encode %{ 6552 __ fcpys($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode)); 6553 %} 6554 ins_pipe(int_conditional_float_move); 6555 %} 6556 6557 instruct cmovFI_reg(cmpOp cmp, flagsReg icc, regF dst, regF src) %{ 6558 match(Set dst (CMoveF (Binary cmp icc) (Binary dst src))); 6559 ins_cost(150); 6560 6561 size(4); 6562 format %{ "FCPYS$cmp $dst,$src" %} 6563 ins_encode %{ 6564 __ fcpys($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode)); 6565 %} 6566 ins_pipe(int_conditional_float_move); 6567 %} 6568 6569 instruct cmovFI_reg_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, regF dst, regF src) %{ 6570 match(Set dst (CMoveF (Binary cmp icc) (Binary dst src))); 6571 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || 6572 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne || 6573 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || 6574 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge); 6575 ins_cost(150); 6576 6577 size(4); 6578 format %{ "FCPYS$cmp $dst,$src" %} 6579 ins_encode %{ 6580 __ fcpys($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode)); 6581 %} 6582 ins_pipe(int_conditional_float_move); 6583 %} 6584 6585 instruct cmovFIu_reg(cmpOpU cmp, flagsRegU icc, regF dst, regF src) %{ 6586 match(Set dst (CMoveF (Binary cmp icc) (Binary dst src))); 6587 ins_cost(150); 6588 6589 size(4); 6590 format %{ "FCPYS$cmp $dst,$src" %} 6591 ins_encode %{ 6592 __ fcpys($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode)); 6593 %} 6594 ins_pipe(int_conditional_float_move); 6595 %} 6596 6597 // Conditional move 6598 instruct cmovDP_reg(cmpOpP cmp, flagsRegP pcc, regD dst, regD src) %{ 6599 match(Set dst (CMoveD (Binary cmp pcc) (Binary dst src))); 6600 ins_cost(150); 6601 size(4); 6602 format %{ "FCPYD$cmp $dst,$src" %} 6603 ins_encode %{ 6604 __ fcpyd($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode)); 6605 %} 6606 ins_pipe(int_conditional_double_move); 6607 %} 6608 6609 instruct cmovDI_reg(cmpOp cmp, flagsReg icc, regD dst, regD src) %{ 6610 match(Set dst (CMoveD (Binary cmp icc) (Binary dst src))); 6611 ins_cost(150); 6612 6613 size(4); 6614 format %{ "FCPYD$cmp $dst,$src" %} 6615 ins_encode %{ 6616 __ fcpyd($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode)); 6617 %} 6618 ins_pipe(int_conditional_double_move); 6619 %} 6620 6621 instruct cmovDI_reg_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, regD dst, regD src) %{ 6622 match(Set dst (CMoveD (Binary cmp icc) (Binary dst src))); 6623 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); 6624 ins_cost(150); 6625 6626 size(4); 6627 format %{ "FCPYD$cmp $dst,$src" %} 6628 ins_encode %{ 6629 __ fcpyd($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode)); 6630 %} 6631 ins_pipe(int_conditional_double_move); 6632 %} 6633 6634 instruct cmovDIu_reg(cmpOpU cmp, flagsRegU icc, regD dst, regD src) %{ 6635 match(Set dst (CMoveD (Binary cmp icc) (Binary dst src))); 6636 ins_cost(150); 6637 6638 size(4); 6639 format %{ "FCPYD$cmp $dst,$src" %} 6640 ins_encode %{ 6641 __ fcpyd($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode)); 6642 %} 6643 ins_pipe(int_conditional_double_move); 6644 %} 6645 6646 // Conditional move 6647 instruct cmovLP_reg(cmpOpP cmp, flagsRegP pcc, iRegL dst, iRegL src) %{ 6648 match(Set dst (CMoveL (Binary cmp pcc) (Binary dst src))); 6649 ins_cost(150); 6650 6651 size(8); 6652 format %{ "MOV$cmp $dst.lo,$src.lo\t! long\n\t" 6653 "MOV$cmp $dst.hi,$src.hi" %} 6654 ins_encode %{ 6655 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 6656 __ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode)); 6657 %} 6658 ins_pipe(ialu_reg); 6659 %} 6660 6661 // TODO: try immLRot2 instead, (0, $con$$constant) becomes 6662 // (hi($con$$constant), lo($con$$constant)) becomes 6663 instruct cmovLP_immRot(cmpOpP cmp, flagsRegP pcc, iRegL dst, immLlowRot src) %{ 6664 match(Set dst (CMoveL (Binary cmp pcc) (Binary dst src))); 6665 ins_cost(140); 6666 6667 size(8); 6668 format %{ "MOV$cmp $dst.lo,$src\t! long\n\t" 6669 "MOV$cmp $dst.hi,0" %} 6670 ins_encode %{ 6671 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 6672 __ mov($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode)); 6673 %} 6674 ins_pipe(ialu_imm); 6675 %} 6676 6677 instruct cmovLP_imm16(cmpOpP cmp, flagsRegP pcc, iRegL dst, immL16 src) %{ 6678 match(Set dst (CMoveL (Binary cmp pcc) (Binary dst src))); 6679 ins_cost(140); 6680 6681 size(8); 6682 format %{ "MOV$cmp $dst.lo,$src\t! long\n\t" 6683 "MOV$cmp $dst.hi,0" %} 6684 ins_encode %{ 6685 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 6686 __ mov($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode)); 6687 %} 6688 ins_pipe(ialu_imm); 6689 %} 6690 6691 instruct cmovLI_reg(cmpOp cmp, flagsReg icc, iRegL dst, iRegL src) %{ 6692 match(Set dst (CMoveL (Binary cmp icc) (Binary dst src))); 6693 ins_cost(150); 6694 6695 size(8); 6696 format %{ "MOV$cmp $dst.lo,$src.lo\t! long\n\t" 6697 "MOV$cmp $dst.hi,$src.hi" %} 6698 ins_encode %{ 6699 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 6700 __ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode)); 6701 %} 6702 ins_pipe(ialu_reg); 6703 %} 6704 6705 instruct cmovLI_reg_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegL dst, iRegL src) %{ 6706 match(Set dst (CMoveL (Binary cmp icc) (Binary dst src))); 6707 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || 6708 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne || 6709 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || 6710 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge); 6711 ins_cost(150); 6712 6713 size(8); 6714 format %{ "MOV$cmp $dst.lo,$src.lo\t! long\n\t" 6715 "MOV$cmp $dst.hi,$src.hi" %} 6716 ins_encode %{ 6717 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 6718 __ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode)); 6719 %} 6720 ins_pipe(ialu_reg); 6721 %} 6722 6723 // TODO: try immLRot2 instead, (0, $con$$constant) becomes 6724 // (hi($con$$constant), lo($con$$constant)) becomes 6725 instruct cmovLI_immRot(cmpOp cmp, flagsReg icc, iRegL dst, immLlowRot src) %{ 6726 match(Set dst (CMoveL (Binary cmp icc) (Binary dst src))); 6727 ins_cost(140); 6728 6729 size(8); 6730 format %{ "MOV$cmp $dst.lo,$src\t! long\n\t" 6731 "MOV$cmp $dst.hi,0" %} 6732 ins_encode %{ 6733 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 6734 __ mov($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode)); 6735 %} 6736 ins_pipe(ialu_imm); 6737 %} 6738 6739 // TODO: try immLRot2 instead, (0, $con$$constant) becomes 6740 // (hi($con$$constant), lo($con$$constant)) becomes 6741 instruct cmovLI_immRot_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegL dst, immLlowRot src) %{ 6742 match(Set dst (CMoveL (Binary cmp icc) (Binary dst src))); 6743 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || 6744 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne || 6745 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || 6746 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge); 6747 ins_cost(140); 6748 6749 size(8); 6750 format %{ "MOV$cmp $dst.lo,$src\t! long\n\t" 6751 "MOV$cmp $dst.hi,0" %} 6752 ins_encode %{ 6753 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 6754 __ mov($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode)); 6755 %} 6756 ins_pipe(ialu_imm); 6757 %} 6758 6759 instruct cmovLI_imm16(cmpOp cmp, flagsReg icc, iRegL dst, immL16 src) %{ 6760 match(Set dst (CMoveL (Binary cmp icc) (Binary dst src))); 6761 ins_cost(140); 6762 6763 size(8); 6764 format %{ "MOV$cmp $dst.lo,$src\t! long\n\t" 6765 "MOV$cmp $dst.hi,0" %} 6766 ins_encode %{ 6767 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 6768 __ movw($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode)); 6769 %} 6770 ins_pipe(ialu_imm); 6771 %} 6772 6773 instruct cmovLI_imm16_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegL dst, immL16 src) %{ 6774 match(Set dst (CMoveL (Binary cmp icc) (Binary dst src))); 6775 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || 6776 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne || 6777 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || 6778 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge); 6779 ins_cost(140); 6780 6781 size(8); 6782 format %{ "MOV$cmp $dst.lo,$src\t! long\n\t" 6783 "MOV$cmp $dst.hi,0" %} 6784 ins_encode %{ 6785 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 6786 __ movw($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode)); 6787 %} 6788 ins_pipe(ialu_imm); 6789 %} 6790 6791 instruct cmovLIu_reg(cmpOpU cmp, flagsRegU icc, iRegL dst, iRegL src) %{ 6792 match(Set dst (CMoveL (Binary cmp icc) (Binary dst src))); 6793 ins_cost(150); 6794 6795 size(8); 6796 format %{ "MOV$cmp $dst.lo,$src.lo\t! long\n\t" 6797 "MOV$cmp $dst.hi,$src.hi" %} 6798 ins_encode %{ 6799 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 6800 __ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode)); 6801 %} 6802 ins_pipe(ialu_reg); 6803 %} 6804 #endif // !AARCH64 6805 6806 6807 //----------OS and Locking Instructions---------------------------------------- 6808 6809 // This name is KNOWN by the ADLC and cannot be changed. 6810 // The ADLC forces a 'TypeRawPtr::BOTTOM' output type 6811 // for this guy. 6812 instruct tlsLoadP(RthreadRegP dst) %{ 6813 match(Set dst (ThreadLocal)); 6814 6815 size(0); 6816 ins_cost(0); 6817 format %{ "! TLS is in $dst" %} 6818 ins_encode( /*empty encoding*/ ); 6819 ins_pipe(ialu_none); 6820 %} 6821 6822 instruct checkCastPP( iRegP dst ) %{ 6823 match(Set dst (CheckCastPP dst)); 6824 6825 size(0); 6826 format %{ "! checkcastPP of $dst" %} 6827 ins_encode( /*empty encoding*/ ); 6828 ins_pipe(empty); 6829 %} 6830 6831 6832 instruct castPP( iRegP dst ) %{ 6833 match(Set dst (CastPP dst)); 6834 format %{ "! castPP of $dst" %} 6835 ins_encode( /*empty encoding*/ ); 6836 ins_pipe(empty); 6837 %} 6838 6839 instruct castII( iRegI dst ) %{ 6840 match(Set dst (CastII dst)); 6841 format %{ "! castII of $dst" %} 6842 ins_encode( /*empty encoding*/ ); 6843 ins_cost(0); 6844 ins_pipe(empty); 6845 %} 6846 6847 //----------Arithmetic Instructions-------------------------------------------- 6848 // Addition Instructions 6849 // Register Addition 6850 instruct addI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{ 6851 match(Set dst (AddI src1 src2)); 6852 6853 size(4); 6854 format %{ "add_32 $dst,$src1,$src2\t! int" %} 6855 ins_encode %{ 6856 __ add_32($dst$$Register, $src1$$Register, $src2$$Register); 6857 %} 6858 ins_pipe(ialu_reg_reg); 6859 %} 6860 6861 #ifndef AARCH64 6862 instruct addshlI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 6863 match(Set dst (AddI (LShiftI src1 src2) src3)); 6864 6865 size(4); 6866 format %{ "add_32 $dst,$src3,$src1<<$src2\t! int" %} 6867 ins_encode %{ 6868 __ add_32($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsl, $src2$$Register)); 6869 %} 6870 ins_pipe(ialu_reg_reg); 6871 %} 6872 #endif 6873 6874 #ifdef AARCH64 6875 #ifdef TODO 6876 instruct addshlL_reg_imm_reg(iRegL dst, iRegL src1, immU6 src2, iRegL src3) %{ 6877 match(Set dst (AddL (LShiftL src1 src2) src3)); 6878 6879 size(4); 6880 format %{ "ADD $dst,$src3,$src1<<$src2\t! long" %} 6881 ins_encode %{ 6882 __ add($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsl, $src2$$constant)); 6883 %} 6884 ins_pipe(ialu_reg_reg); 6885 %} 6886 #endif 6887 #endif 6888 6889 instruct addshlI_reg_imm_reg(iRegI dst, iRegI src1, immU5 src2, iRegI src3) %{ 6890 match(Set dst (AddI (LShiftI src1 src2) src3)); 6891 6892 size(4); 6893 format %{ "add_32 $dst,$src3,$src1<<$src2\t! int" %} 6894 ins_encode %{ 6895 __ add_32($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsl, $src2$$constant)); 6896 %} 6897 ins_pipe(ialu_reg_reg); 6898 %} 6899 6900 #ifndef AARCH64 6901 instruct addsarI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 6902 match(Set dst (AddI (RShiftI src1 src2) src3)); 6903 6904 size(4); 6905 format %{ "add_32 $dst,$src3,$src1>>$src2\t! int" %} 6906 ins_encode %{ 6907 __ add_32($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, asr, $src2$$Register)); 6908 %} 6909 ins_pipe(ialu_reg_reg); 6910 %} 6911 #endif 6912 6913 instruct addsarI_reg_imm_reg(iRegI dst, iRegI src1, immU5 src2, iRegI src3) %{ 6914 match(Set dst (AddI (RShiftI src1 src2) src3)); 6915 6916 size(4); 6917 format %{ "add_32 $dst,$src3,$src1>>$src2\t! int" %} 6918 ins_encode %{ 6919 __ add_32($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, asr, $src2$$constant)); 6920 %} 6921 ins_pipe(ialu_reg_reg); 6922 %} 6923 6924 #ifndef AARCH64 6925 instruct addshrI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 6926 match(Set dst (AddI (URShiftI src1 src2) src3)); 6927 6928 size(4); 6929 format %{ "add_32 $dst,$src3,$src1>>>$src2\t! int" %} 6930 ins_encode %{ 6931 __ add_32($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsr, $src2$$Register)); 6932 %} 6933 ins_pipe(ialu_reg_reg); 6934 %} 6935 #endif 6936 6937 instruct addshrI_reg_imm_reg(iRegI dst, iRegI src1, immU5 src2, iRegI src3) %{ 6938 match(Set dst (AddI (URShiftI src1 src2) src3)); 6939 6940 size(4); 6941 format %{ "add_32 $dst,$src3,$src1>>>$src2\t! int" %} 6942 ins_encode %{ 6943 __ add_32($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsr, $src2$$constant)); 6944 %} 6945 ins_pipe(ialu_reg_reg); 6946 %} 6947 6948 // Immediate Addition 6949 instruct addI_reg_aimmI(iRegI dst, iRegI src1, aimmI src2) %{ 6950 match(Set dst (AddI src1 src2)); 6951 6952 size(4); 6953 format %{ "add_32 $dst,$src1,$src2\t! int" %} 6954 ins_encode %{ 6955 __ add_32($dst$$Register, $src1$$Register, $src2$$constant); 6956 %} 6957 ins_pipe(ialu_reg_imm); 6958 %} 6959 6960 // Pointer Register Addition 6961 instruct addP_reg_reg(iRegP dst, iRegP src1, iRegX src2) %{ 6962 match(Set dst (AddP src1 src2)); 6963 6964 size(4); 6965 format %{ "ADD $dst,$src1,$src2\t! ptr" %} 6966 ins_encode %{ 6967 __ add($dst$$Register, $src1$$Register, $src2$$Register); 6968 %} 6969 ins_pipe(ialu_reg_reg); 6970 %} 6971 6972 #ifdef AARCH64 6973 // unshifted I2L operand 6974 operand unshiftedI2L(iRegI src2) %{ 6975 //constraint(ALLOC_IN_RC(sp_ptr_reg)); 6976 match(ConvI2L src2); 6977 6978 op_cost(1); 6979 format %{ "$src2.w" %} 6980 interface(MEMORY_INTER) %{ 6981 base($src2); 6982 index(0xff); 6983 scale(0x0); 6984 disp(0x0); 6985 %} 6986 %} 6987 6988 // shifted I2L operand 6989 operand shiftedI2L(iRegI src2, immI_0_4 src3) %{ 6990 //constraint(ALLOC_IN_RC(sp_ptr_reg)); 6991 match(LShiftX (ConvI2L src2) src3); 6992 6993 op_cost(1); 6994 format %{ "$src2.w << $src3" %} 6995 interface(MEMORY_INTER) %{ 6996 base($src2); 6997 index(0xff); 6998 scale($src3); 6999 disp(0x0); 7000 %} 7001 %} 7002 7003 opclass shiftedRegI(shiftedI2L, unshiftedI2L); 7004 7005 instruct shlL_reg_regI(iRegL dst, iRegI src1, immU6 src2) %{ 7006 match(Set dst (LShiftL (ConvI2L src1) src2)); 7007 7008 size(4); 7009 format %{ "LSL $dst,$src1.w,$src2\t! ptr" %} 7010 ins_encode %{ 7011 int c = $src2$$constant; 7012 int r = 64 - c; 7013 int s = 31; 7014 if (s >= r) { 7015 s = r - 1; 7016 } 7017 __ sbfm($dst$$Register, $src1$$Register, r, s); 7018 %} 7019 ins_pipe(ialu_reg_reg); 7020 %} 7021 7022 instruct addP_reg_regI(iRegP dst, iRegP src1, shiftedRegI src2) %{ 7023 match(Set dst (AddP src1 src2)); 7024 7025 ins_cost(DEFAULT_COST * 3/2); 7026 size(4); 7027 format %{ "ADD $dst,$src1,$src2, sxtw\t! ptr" %} 7028 ins_encode %{ 7029 Register base = reg_to_register_object($src2$$base); 7030 __ add($dst$$Register, $src1$$Register, base, ex_sxtw, $src2$$scale); 7031 %} 7032 ins_pipe(ialu_reg_reg); 7033 %} 7034 #endif 7035 7036 // shifted iRegX operand 7037 operand shiftedX(iRegX src2, shimmX src3) %{ 7038 //constraint(ALLOC_IN_RC(sp_ptr_reg)); 7039 match(LShiftX src2 src3); 7040 7041 op_cost(1); 7042 format %{ "$src2 << $src3" %} 7043 interface(MEMORY_INTER) %{ 7044 base($src2); 7045 index(0xff); 7046 scale($src3); 7047 disp(0x0); 7048 %} 7049 %} 7050 7051 instruct addshlP_reg_reg_imm(iRegP dst, iRegP src1, shiftedX src2) %{ 7052 match(Set dst (AddP src1 src2)); 7053 7054 ins_cost(DEFAULT_COST * 3/2); 7055 size(4); 7056 format %{ "ADD $dst,$src1,$src2\t! ptr" %} 7057 ins_encode %{ 7058 Register base = reg_to_register_object($src2$$base); 7059 __ add($dst$$Register, $src1$$Register, AsmOperand(base, lsl, $src2$$scale)); 7060 %} 7061 ins_pipe(ialu_reg_reg); 7062 %} 7063 7064 // Pointer Immediate Addition 7065 instruct addP_reg_aimmX(iRegP dst, iRegP src1, aimmX src2) %{ 7066 match(Set dst (AddP src1 src2)); 7067 7068 size(4); 7069 format %{ "ADD $dst,$src1,$src2\t! ptr" %} 7070 ins_encode %{ 7071 __ add($dst$$Register, $src1$$Register, $src2$$constant); 7072 %} 7073 ins_pipe(ialu_reg_imm); 7074 %} 7075 7076 // Long Addition 7077 #ifdef AARCH64 7078 instruct addL_reg_reg(iRegL dst, iRegL src1, iRegL src2) %{ 7079 match(Set dst (AddL src1 src2)); 7080 size(4); 7081 format %{ "ADD $dst,$src1,$src2\t! long" %} 7082 ins_encode %{ 7083 __ add($dst$$Register, $src1$$Register, $src2$$Register); 7084 %} 7085 ins_pipe(ialu_reg_reg); 7086 %} 7087 7088 instruct addL_reg_regI(iRegL dst, iRegL src1, shiftedRegI src2) %{ 7089 match(Set dst (AddL src1 src2)); 7090 7091 ins_cost(DEFAULT_COST * 3/2); 7092 size(4); 7093 format %{ "ADD $dst,$src1,$src2, sxtw\t! long" %} 7094 ins_encode %{ 7095 Register base = reg_to_register_object($src2$$base); 7096 __ add($dst$$Register, $src1$$Register, base, ex_sxtw, $src2$$scale); 7097 %} 7098 ins_pipe(ialu_reg_reg); 7099 %} 7100 #else 7101 instruct addL_reg_reg(iRegL dst, iRegL src1, iRegL src2, flagsReg ccr) %{ 7102 match(Set dst (AddL src1 src2)); 7103 effect(KILL ccr); 7104 size(8); 7105 format %{ "ADDS $dst.lo,$src1.lo,$src2.lo\t! long\n\t" 7106 "ADC $dst.hi,$src1.hi,$src2.hi" %} 7107 ins_encode %{ 7108 __ adds($dst$$Register, $src1$$Register, $src2$$Register); 7109 __ adc($dst$$Register->successor(), $src1$$Register->successor(), $src2$$Register->successor()); 7110 %} 7111 ins_pipe(ialu_reg_reg); 7112 %} 7113 #endif 7114 7115 #ifdef AARCH64 7116 // Immediate Addition 7117 instruct addL_reg_aimm(iRegL dst, iRegL src1, aimmL src2) %{ 7118 match(Set dst (AddL src1 src2)); 7119 7120 size(4); 7121 format %{ "ADD $dst,$src1,$src2\t! long" %} 7122 ins_encode %{ 7123 __ add($dst$$Register, $src1$$Register, $src2$$constant); 7124 %} 7125 ins_pipe(ialu_reg_imm); 7126 %} 7127 7128 instruct addL_reg_immLneg(iRegL dst, iRegL src1, aimmLneg src2) %{ 7129 match(Set dst (SubL src1 src2)); 7130 7131 size(4); 7132 format %{ "ADD $dst,$src1,-($src2)\t! long" %} 7133 ins_encode %{ 7134 __ add($dst$$Register, $src1$$Register, -$src2$$constant); 7135 %} 7136 ins_pipe(ialu_reg_imm); 7137 %} 7138 #else 7139 // TODO 7140 #endif 7141 7142 #ifndef AARCH64 7143 // TODO: try immLRot2 instead, (0, $con$$constant) becomes 7144 // (hi($con$$constant), lo($con$$constant)) becomes 7145 instruct addL_reg_immRot(iRegL dst, iRegL src1, immLlowRot con, flagsReg ccr) %{ 7146 match(Set dst (AddL src1 con)); 7147 effect(KILL ccr); 7148 size(8); 7149 format %{ "ADDS $dst.lo,$src1.lo,$con\t! long\n\t" 7150 "ADC $dst.hi,$src1.hi,0" %} 7151 ins_encode %{ 7152 __ adds($dst$$Register, $src1$$Register, $con$$constant); 7153 __ adc($dst$$Register->successor(), $src1$$Register->successor(), 0); 7154 %} 7155 ins_pipe(ialu_reg_imm); 7156 %} 7157 #endif 7158 7159 //----------Conditional_store-------------------------------------------------- 7160 // Conditional-store of the updated heap-top. 7161 // Used during allocation of the shared heap. 7162 // Sets flags (EQ) on success. 7163 7164 // TODO: optimize out barriers with AArch64 load-acquire/store-release 7165 // LoadP-locked. 7166 instruct loadPLocked(iRegP dst, memoryex mem) %{ 7167 match(Set dst (LoadPLocked mem)); 7168 size(4); 7169 format %{ "LDREX $dst,$mem" %} 7170 ins_encode %{ 7171 #ifdef AARCH64 7172 Register base = reg_to_register_object($mem$$base); 7173 __ ldxr($dst$$Register, base); 7174 #else 7175 __ ldrex($dst$$Register,$mem$$Address); 7176 #endif 7177 %} 7178 ins_pipe(iload_mem); 7179 %} 7180 7181 instruct storePConditional( memoryex heap_top_ptr, iRegP oldval, iRegP newval, iRegI tmp, flagsRegP pcc ) %{ 7182 predicate(_kids[1]->_kids[0]->_leaf->Opcode() == Op_LoadPLocked); // only works in conjunction with a LoadPLocked node 7183 match(Set pcc (StorePConditional heap_top_ptr (Binary oldval newval))); 7184 effect( TEMP tmp ); 7185 size(8); 7186 format %{ "STREX $tmp,$newval,$heap_top_ptr\n\t" 7187 "CMP $tmp, 0" %} 7188 ins_encode %{ 7189 #ifdef AARCH64 7190 Register base = reg_to_register_object($heap_top_ptr$$base); 7191 __ stxr($tmp$$Register, $newval$$Register, base); 7192 #else 7193 __ strex($tmp$$Register, $newval$$Register, $heap_top_ptr$$Address); 7194 #endif 7195 __ cmp($tmp$$Register, 0); 7196 %} 7197 ins_pipe( long_memory_op ); 7198 %} 7199 7200 // Conditional-store of an intx value. 7201 instruct storeXConditional( memoryex mem, iRegX oldval, iRegX newval, iRegX tmp, flagsReg icc ) %{ 7202 #ifdef AARCH64 7203 match(Set icc (StoreLConditional mem (Binary oldval newval))); 7204 effect( TEMP tmp ); 7205 size(28); 7206 format %{ "loop:\n\t" 7207 "LDXR $tmp, $mem\t! If $oldval==[$mem] Then store $newval into [$mem], DOESN'T set $newval=[$mem] in any case\n\t" 7208 "SUBS $tmp, $tmp, $oldval\n\t" 7209 "B.ne done\n\t" 7210 "STXR $tmp, $newval, $mem\n\t" 7211 "CBNZ_w $tmp, loop\n\t" 7212 "CMP $tmp, 0\n\t" 7213 "done:\n\t" 7214 "membar LoadStore|LoadLoad" %} 7215 #else 7216 match(Set icc (StoreIConditional mem (Binary oldval newval))); 7217 effect( TEMP tmp ); 7218 size(28); 7219 format %{ "loop: \n\t" 7220 "LDREX $tmp, $mem\t! If $oldval==[$mem] Then store $newval into [$mem], DOESN'T set $newval=[$mem] in any case\n\t" 7221 "XORS $tmp,$tmp, $oldval\n\t" 7222 "STREX.eq $tmp, $newval, $mem\n\t" 7223 "CMP.eq $tmp, 1 \n\t" 7224 "B.eq loop \n\t" 7225 "TEQ $tmp, 0\n\t" 7226 "membar LoadStore|LoadLoad" %} 7227 #endif 7228 ins_encode %{ 7229 Label loop; 7230 __ bind(loop); 7231 #ifdef AARCH64 7232 // FIXME: use load-acquire/store-release, remove membar? 7233 Label done; 7234 Register base = reg_to_register_object($mem$$base); 7235 __ ldxr($tmp$$Register, base); 7236 __ subs($tmp$$Register, $tmp$$Register, $oldval$$Register); 7237 __ b(done, ne); 7238 __ stxr($tmp$$Register, $newval$$Register, base); 7239 __ cbnz_w($tmp$$Register, loop); 7240 __ cmp($tmp$$Register, 0); 7241 __ bind(done); 7242 #else 7243 __ ldrex($tmp$$Register, $mem$$Address); 7244 __ eors($tmp$$Register, $tmp$$Register, $oldval$$Register); 7245 __ strex($tmp$$Register, $newval$$Register, $mem$$Address, eq); 7246 __ cmp($tmp$$Register, 1, eq); 7247 __ b(loop, eq); 7248 __ teq($tmp$$Register, 0); 7249 #endif 7250 // used by biased locking only. Requires a membar. 7251 __ membar(MacroAssembler::Membar_mask_bits(MacroAssembler::LoadStore | MacroAssembler::LoadLoad), noreg); 7252 %} 7253 ins_pipe( long_memory_op ); 7254 %} 7255 7256 // No flag versions for CompareAndSwap{P,I,L} because matcher can't match them 7257 7258 #ifdef AARCH64 7259 // TODO: if combined with membar, elide membar and use 7260 // load-acquire/store-release if appropriate 7261 instruct compareAndSwapL_bool(memoryex mem, iRegL oldval, iRegL newval, iRegI res, iRegI tmp, flagsReg ccr) %{ 7262 match(Set res (CompareAndSwapL mem (Binary oldval newval))); 7263 effect( KILL ccr, TEMP tmp); 7264 size(24); 7265 format %{ "loop:\n\t" 7266 "LDXR $tmp, $mem\t! If $oldval==[$mem] Then store $newval into [$mem]\n\t" 7267 "CMP $tmp, $oldval\n\t" 7268 "B.ne done\n\t" 7269 "STXR $tmp, $newval, $mem\n\t" 7270 "CBNZ_w $tmp, loop\n\t" 7271 "done:\n\t" 7272 "CSET_w $res, eq" %} 7273 ins_encode %{ 7274 Register base = reg_to_register_object($mem$$base); 7275 Label loop, done; 7276 __ bind(loop); 7277 __ ldxr($tmp$$Register, base); 7278 __ cmp($tmp$$Register, $oldval$$Register); 7279 __ b(done, ne); 7280 __ stxr($tmp$$Register, $newval$$Register, base); 7281 __ cbnz_w($tmp$$Register, loop); 7282 __ bind(done); 7283 __ cset_w($res$$Register, eq); 7284 %} 7285 ins_pipe( long_memory_op ); 7286 %} 7287 7288 instruct compareAndSwapI_bool(memoryex mem, iRegI oldval, iRegI newval, iRegI res, iRegI tmp, flagsReg ccr) %{ 7289 match(Set res (CompareAndSwapI mem (Binary oldval newval))); 7290 effect( KILL ccr, TEMP tmp); 7291 size(24); 7292 format %{ "loop:\n\t" 7293 "LDXR_w $tmp, $mem\t! If $oldval==[$mem] Then store $newval into [$mem]\n\t" 7294 "CMP_w $tmp, $oldval\n\t" 7295 "B.ne done\n\t" 7296 "STXR_w $tmp, $newval, $mem\n\t" 7297 "CBNZ_w $tmp, loop\n\t" 7298 "done:\n\t" 7299 "CSET_w $res, eq" %} 7300 ins_encode %{ 7301 Register base = reg_to_register_object($mem$$base); 7302 Label loop, done; 7303 __ bind(loop); 7304 __ ldxr_w($tmp$$Register, base); 7305 __ cmp_w($tmp$$Register, $oldval$$Register); 7306 __ b(done, ne); 7307 __ stxr_w($tmp$$Register, $newval$$Register, base); 7308 __ cbnz_w($tmp$$Register, loop); 7309 __ bind(done); 7310 __ cset_w($res$$Register, eq); 7311 %} 7312 ins_pipe( long_memory_op ); 7313 %} 7314 7315 // tmp must use iRegI instead of iRegN until 8051805 is fixed. 7316 instruct compareAndSwapN_bool(memoryex mem, iRegN oldval, iRegN newval, iRegI res, iRegI tmp, flagsReg ccr) %{ 7317 match(Set res (CompareAndSwapN mem (Binary oldval newval))); 7318 effect( KILL ccr, TEMP tmp); 7319 size(24); 7320 format %{ "loop:\n\t" 7321 "LDXR_w $tmp, $mem\t! If $oldval==[$mem] Then store $newval into [$mem]\n\t" 7322 "CMP_w $tmp, $oldval\n\t" 7323 "B.ne done\n\t" 7324 "STXR_w $tmp, $newval, $mem\n\t" 7325 "CBNZ_w $tmp, loop\n\t" 7326 "done:\n\t" 7327 "CSET_w $res, eq" %} 7328 ins_encode %{ 7329 Register base = reg_to_register_object($mem$$base); 7330 Label loop, done; 7331 __ bind(loop); 7332 __ ldxr_w($tmp$$Register, base); 7333 __ cmp_w($tmp$$Register, $oldval$$Register); 7334 __ b(done, ne); 7335 __ stxr_w($tmp$$Register, $newval$$Register, base); 7336 __ cbnz_w($tmp$$Register, loop); 7337 __ bind(done); 7338 __ cset_w($res$$Register, eq); 7339 %} 7340 ins_pipe( long_memory_op ); 7341 %} 7342 7343 instruct compareAndSwapP_bool(memoryex mem, iRegP oldval, iRegP newval, iRegI res, iRegI tmp, flagsReg ccr) %{ 7344 match(Set res (CompareAndSwapP mem (Binary oldval newval))); 7345 effect( KILL ccr, TEMP tmp); 7346 size(24); 7347 format %{ "loop:\n\t" 7348 "LDXR $tmp, $mem\t! If $oldval==[$mem] Then store $newval into [$mem]\n\t" 7349 "CMP $tmp, $oldval\n\t" 7350 "B.ne done\n\t" 7351 "STXR $tmp, $newval, $mem\n\t" 7352 "CBNZ_w $tmp, loop\n\t" 7353 "done:\n\t" 7354 "CSET_w $res, eq" %} 7355 ins_encode %{ 7356 Register base = reg_to_register_object($mem$$base); 7357 Label loop, done; 7358 __ bind(loop); 7359 __ ldxr($tmp$$Register, base); 7360 __ cmp($tmp$$Register, $oldval$$Register); 7361 __ b(done, ne); 7362 __ stxr($tmp$$Register, $newval$$Register, base); 7363 __ cbnz_w($tmp$$Register, loop); 7364 __ bind(done); 7365 __ cset_w($res$$Register, eq); 7366 %} 7367 ins_pipe( long_memory_op ); 7368 %} 7369 #else // !AARCH64 7370 instruct compareAndSwapL_bool(memoryex mem, iRegL oldval, iRegLd newval, iRegI res, iRegLd tmp, flagsReg ccr ) %{ 7371 match(Set res (CompareAndSwapL mem (Binary oldval newval))); 7372 effect( KILL ccr, TEMP tmp); 7373 size(32); 7374 format %{ "loop: \n\t" 7375 "LDREXD $tmp, $mem\t! If $oldval==[$mem] Then store $newval into [$mem]\n\t" 7376 "CMP $tmp.lo, $oldval.lo\n\t" 7377 "CMP.eq $tmp.hi, $oldval.hi\n\t" 7378 "STREXD.eq $tmp, $newval, $mem\n\t" 7379 "MOV.ne $tmp, 0 \n\t" 7380 "XORS.eq $tmp,$tmp, 1 \n\t" 7381 "B.eq loop \n\t" 7382 "MOV $res, $tmp" %} 7383 ins_encode %{ 7384 Label loop; 7385 __ bind(loop); 7386 __ ldrexd($tmp$$Register, $mem$$Address); 7387 __ cmp($tmp$$Register, $oldval$$Register); 7388 __ cmp($tmp$$Register->successor(), $oldval$$Register->successor(), eq); 7389 __ strexd($tmp$$Register, $newval$$Register, $mem$$Address, eq); 7390 __ mov($tmp$$Register, 0, ne); 7391 __ eors($tmp$$Register, $tmp$$Register, 1, eq); 7392 __ b(loop, eq); 7393 __ mov($res$$Register, $tmp$$Register); 7394 %} 7395 ins_pipe( long_memory_op ); 7396 %} 7397 7398 7399 instruct compareAndSwapI_bool(memoryex mem, iRegI oldval, iRegI newval, iRegI res, iRegI tmp, flagsReg ccr ) %{ 7400 match(Set res (CompareAndSwapI mem (Binary oldval newval))); 7401 effect( KILL ccr, TEMP tmp); 7402 size(28); 7403 format %{ "loop: \n\t" 7404 "LDREX $tmp, $mem\t! If $oldval==[$mem] Then store $newval into [$mem]\n\t" 7405 "CMP $tmp, $oldval\n\t" 7406 "STREX.eq $tmp, $newval, $mem\n\t" 7407 "MOV.ne $tmp, 0 \n\t" 7408 "XORS.eq $tmp,$tmp, 1 \n\t" 7409 "B.eq loop \n\t" 7410 "MOV $res, $tmp" %} 7411 7412 ins_encode %{ 7413 Label loop; 7414 __ bind(loop); 7415 __ ldrex($tmp$$Register,$mem$$Address); 7416 __ cmp($tmp$$Register, $oldval$$Register); 7417 __ strex($tmp$$Register, $newval$$Register, $mem$$Address, eq); 7418 __ mov($tmp$$Register, 0, ne); 7419 __ eors($tmp$$Register, $tmp$$Register, 1, eq); 7420 __ b(loop, eq); 7421 __ mov($res$$Register, $tmp$$Register); 7422 %} 7423 ins_pipe( long_memory_op ); 7424 %} 7425 7426 instruct compareAndSwapP_bool(memoryex mem, iRegP oldval, iRegP newval, iRegI res, iRegI tmp, flagsReg ccr ) %{ 7427 match(Set res (CompareAndSwapP mem (Binary oldval newval))); 7428 effect( KILL ccr, TEMP tmp); 7429 size(28); 7430 format %{ "loop: \n\t" 7431 "LDREX $tmp, $mem\t! If $oldval==[$mem] Then store $newval into [$mem]\n\t" 7432 "CMP $tmp, $oldval\n\t" 7433 "STREX.eq $tmp, $newval, $mem\n\t" 7434 "MOV.ne $tmp, 0 \n\t" 7435 "EORS.eq $tmp,$tmp, 1 \n\t" 7436 "B.eq loop \n\t" 7437 "MOV $res, $tmp" %} 7438 7439 ins_encode %{ 7440 Label loop; 7441 __ bind(loop); 7442 __ ldrex($tmp$$Register,$mem$$Address); 7443 __ cmp($tmp$$Register, $oldval$$Register); 7444 __ strex($tmp$$Register, $newval$$Register, $mem$$Address, eq); 7445 __ mov($tmp$$Register, 0, ne); 7446 __ eors($tmp$$Register, $tmp$$Register, 1, eq); 7447 __ b(loop, eq); 7448 __ mov($res$$Register, $tmp$$Register); 7449 %} 7450 ins_pipe( long_memory_op ); 7451 %} 7452 #endif // !AARCH64 7453 7454 #ifdef AARCH64 7455 instruct xaddI_aimmI_no_res(memoryex mem, aimmI add, Universe dummy, iRegI tmp1, iRegI tmp2) %{ 7456 predicate(n->as_LoadStore()->result_not_used()); 7457 match(Set dummy (GetAndAddI mem add)); 7458 effect(TEMP tmp1, TEMP tmp2); 7459 size(16); 7460 format %{ "loop:\n\t" 7461 "LDXR_w $tmp1, $mem\n\t" 7462 "ADD_w $tmp1, $tmp1, $add\n\t" 7463 "STXR_w $tmp2, $tmp1, $mem\n\t" 7464 "CBNZ_w $tmp2, loop" %} 7465 7466 ins_encode %{ 7467 Label loop; 7468 Register base = reg_to_register_object($mem$$base); 7469 __ bind(loop); 7470 __ ldxr_w($tmp1$$Register, base); 7471 __ add_w($tmp1$$Register, $tmp1$$Register, $add$$constant); 7472 __ stxr_w($tmp2$$Register, $tmp1$$Register, base); 7473 __ cbnz_w($tmp2$$Register, loop); 7474 %} 7475 ins_pipe( long_memory_op ); 7476 %} 7477 #else 7478 instruct xaddI_aimmI_no_res(memoryex mem, aimmI add, Universe dummy, iRegI tmp1, iRegI tmp2, flagsReg ccr) %{ 7479 predicate(n->as_LoadStore()->result_not_used()); 7480 match(Set dummy (GetAndAddI mem add)); 7481 effect(KILL ccr, TEMP tmp1, TEMP tmp2); 7482 size(20); 7483 format %{ "loop: \n\t" 7484 "LDREX $tmp1, $mem\n\t" 7485 "ADD $tmp1, $tmp1, $add\n\t" 7486 "STREX $tmp2, $tmp1, $mem\n\t" 7487 "CMP $tmp2, 0 \n\t" 7488 "B.ne loop \n\t" %} 7489 7490 ins_encode %{ 7491 Label loop; 7492 __ bind(loop); 7493 __ ldrex($tmp1$$Register,$mem$$Address); 7494 __ add($tmp1$$Register, $tmp1$$Register, $add$$constant); 7495 __ strex($tmp2$$Register, $tmp1$$Register, $mem$$Address); 7496 __ cmp($tmp2$$Register, 0); 7497 __ b(loop, ne); 7498 %} 7499 ins_pipe( long_memory_op ); 7500 %} 7501 #endif 7502 7503 #ifdef AARCH64 7504 instruct xaddI_reg_no_res(memoryex mem, iRegI add, Universe dummy, iRegI tmp1, iRegI tmp2) %{ 7505 predicate(n->as_LoadStore()->result_not_used()); 7506 match(Set dummy (GetAndAddI mem add)); 7507 effect(TEMP tmp1, TEMP tmp2); 7508 size(16); 7509 format %{ "loop:\n\t" 7510 "LDXR_w $tmp1, $mem\n\t" 7511 "ADD_w $tmp1, $tmp1, $add\n\t" 7512 "STXR_w $tmp2, $tmp1, $mem\n\t" 7513 "CBNZ_w $tmp2, loop" %} 7514 7515 ins_encode %{ 7516 Label loop; 7517 Register base = reg_to_register_object($mem$$base); 7518 __ bind(loop); 7519 __ ldxr_w($tmp1$$Register, base); 7520 __ add_w($tmp1$$Register, $tmp1$$Register, $add$$Register); 7521 __ stxr_w($tmp2$$Register, $tmp1$$Register, base); 7522 __ cbnz_w($tmp2$$Register, loop); 7523 %} 7524 ins_pipe( long_memory_op ); 7525 %} 7526 #else 7527 instruct xaddI_reg_no_res(memoryex mem, iRegI add, Universe dummy, iRegI tmp1, iRegI tmp2, flagsReg ccr) %{ 7528 predicate(n->as_LoadStore()->result_not_used()); 7529 match(Set dummy (GetAndAddI mem add)); 7530 effect(KILL ccr, TEMP tmp1, TEMP tmp2); 7531 size(20); 7532 format %{ "loop: \n\t" 7533 "LDREX $tmp1, $mem\n\t" 7534 "ADD $tmp1, $tmp1, $add\n\t" 7535 "STREX $tmp2, $tmp1, $mem\n\t" 7536 "CMP $tmp2, 0 \n\t" 7537 "B.ne loop \n\t" %} 7538 7539 ins_encode %{ 7540 Label loop; 7541 __ bind(loop); 7542 __ ldrex($tmp1$$Register,$mem$$Address); 7543 __ add($tmp1$$Register, $tmp1$$Register, $add$$Register); 7544 __ strex($tmp2$$Register, $tmp1$$Register, $mem$$Address); 7545 __ cmp($tmp2$$Register, 0); 7546 __ b(loop, ne); 7547 %} 7548 ins_pipe( long_memory_op ); 7549 %} 7550 #endif 7551 7552 #ifdef AARCH64 7553 instruct xaddI_aimmI(memoryex mem, aimmI add, iRegI res, iRegI tmp1, iRegI tmp2) %{ 7554 match(Set res (GetAndAddI mem add)); 7555 effect(TEMP tmp1, TEMP tmp2, TEMP res); 7556 size(16); 7557 format %{ "loop:\n\t" 7558 "LDXR_w $res, $mem\n\t" 7559 "ADD_w $tmp1, $res, $add\n\t" 7560 "STXR_w $tmp2, $tmp1, $mem\n\t" 7561 "CBNZ_w $tmp2, loop" %} 7562 7563 ins_encode %{ 7564 Label loop; 7565 Register base = reg_to_register_object($mem$$base); 7566 __ bind(loop); 7567 __ ldxr_w($res$$Register, base); 7568 __ add_w($tmp1$$Register, $res$$Register, $add$$constant); 7569 __ stxr_w($tmp2$$Register, $tmp1$$Register, base); 7570 __ cbnz_w($tmp2$$Register, loop); 7571 %} 7572 ins_pipe( long_memory_op ); 7573 %} 7574 #else 7575 instruct xaddI_aimmI(memoryex mem, aimmI add, iRegI res, iRegI tmp1, iRegI tmp2, flagsReg ccr) %{ 7576 match(Set res (GetAndAddI mem add)); 7577 effect(KILL ccr, TEMP tmp1, TEMP tmp2, TEMP res); 7578 size(20); 7579 format %{ "loop: \n\t" 7580 "LDREX $res, $mem\n\t" 7581 "ADD $tmp1, $res, $add\n\t" 7582 "STREX $tmp2, $tmp1, $mem\n\t" 7583 "CMP $tmp2, 0 \n\t" 7584 "B.ne loop \n\t" %} 7585 7586 ins_encode %{ 7587 Label loop; 7588 __ bind(loop); 7589 __ ldrex($res$$Register,$mem$$Address); 7590 __ add($tmp1$$Register, $res$$Register, $add$$constant); 7591 __ strex($tmp2$$Register, $tmp1$$Register, $mem$$Address); 7592 __ cmp($tmp2$$Register, 0); 7593 __ b(loop, ne); 7594 %} 7595 ins_pipe( long_memory_op ); 7596 %} 7597 #endif 7598 7599 #ifdef AARCH64 7600 instruct xaddI_reg(memoryex mem, iRegI add, iRegI res, iRegI tmp1, iRegI tmp2) %{ 7601 match(Set res (GetAndAddI mem add)); 7602 effect(TEMP tmp1, TEMP tmp2, TEMP res); 7603 size(16); 7604 format %{ "loop:\n\t" 7605 "LDXR_w $res, $mem\n\t" 7606 "ADD_w $tmp1, $res, $add\n\t" 7607 "STXR_w $tmp2, $tmp1, $mem\n\t" 7608 "CBNZ_w $tmp2, loop" %} 7609 7610 ins_encode %{ 7611 Label loop; 7612 Register base = reg_to_register_object($mem$$base); 7613 __ bind(loop); 7614 __ ldxr_w($res$$Register, base); 7615 __ add_w($tmp1$$Register, $res$$Register, $add$$Register); 7616 __ stxr_w($tmp2$$Register, $tmp1$$Register, base); 7617 __ cbnz_w($tmp2$$Register, loop); 7618 %} 7619 ins_pipe( long_memory_op ); 7620 %} 7621 #else 7622 instruct xaddI_reg(memoryex mem, iRegI add, iRegI res, iRegI tmp1, iRegI tmp2, flagsReg ccr) %{ 7623 match(Set res (GetAndAddI mem add)); 7624 effect(KILL ccr, TEMP tmp1, TEMP tmp2, TEMP res); 7625 size(20); 7626 format %{ "loop: \n\t" 7627 "LDREX $res, $mem\n\t" 7628 "ADD $tmp1, $res, $add\n\t" 7629 "STREX $tmp2, $tmp1, $mem\n\t" 7630 "CMP $tmp2, 0 \n\t" 7631 "B.ne loop \n\t" %} 7632 7633 ins_encode %{ 7634 Label loop; 7635 __ bind(loop); 7636 __ ldrex($res$$Register,$mem$$Address); 7637 __ add($tmp1$$Register, $res$$Register, $add$$Register); 7638 __ strex($tmp2$$Register, $tmp1$$Register, $mem$$Address); 7639 __ cmp($tmp2$$Register, 0); 7640 __ b(loop, ne); 7641 %} 7642 ins_pipe( long_memory_op ); 7643 %} 7644 #endif 7645 7646 #ifdef AARCH64 7647 instruct xaddL_reg_no_res(memoryex mem, iRegL add, Universe dummy, iRegL tmp1, iRegI tmp2) %{ 7648 predicate(n->as_LoadStore()->result_not_used()); 7649 match(Set dummy (GetAndAddL mem add)); 7650 effect(TEMP tmp1, TEMP tmp2); 7651 size(16); 7652 format %{ "loop:\n\t" 7653 "LDXR $tmp1, $mem\n\t" 7654 "ADD $tmp1, $tmp1, $add\n\t" 7655 "STXR $tmp2, $tmp1, $mem\n\t" 7656 "CBNZ_w $tmp2, loop" %} 7657 7658 ins_encode %{ 7659 Label loop; 7660 Register base = reg_to_register_object($mem$$base); 7661 __ bind(loop); 7662 __ ldxr($tmp1$$Register, base); 7663 __ add($tmp1$$Register, $tmp1$$Register, $add$$Register); 7664 __ stxr($tmp2$$Register, $tmp1$$Register, base); 7665 __ cbnz_w($tmp2$$Register, loop); 7666 %} 7667 ins_pipe( long_memory_op ); 7668 %} 7669 #else 7670 instruct xaddL_reg_no_res(memoryex mem, iRegL add, Universe dummy, iRegLd tmp1, iRegI tmp2, flagsReg ccr) %{ 7671 predicate(n->as_LoadStore()->result_not_used()); 7672 match(Set dummy (GetAndAddL mem add)); 7673 effect( KILL ccr, TEMP tmp1, TEMP tmp2); 7674 size(24); 7675 format %{ "loop: \n\t" 7676 "LDREXD $tmp1, $mem\n\t" 7677 "ADDS $tmp1.lo, $tmp1.lo, $add.lo\n\t" 7678 "ADC $tmp1.hi, $tmp1.hi, $add.hi\n\t" 7679 "STREXD $tmp2, $tmp1, $mem\n\t" 7680 "CMP $tmp2, 0 \n\t" 7681 "B.ne loop \n\t" %} 7682 7683 ins_encode %{ 7684 Label loop; 7685 __ bind(loop); 7686 __ ldrexd($tmp1$$Register, $mem$$Address); 7687 __ adds($tmp1$$Register, $tmp1$$Register, $add$$Register); 7688 __ adc($tmp1$$Register->successor(), $tmp1$$Register->successor(), $add$$Register->successor()); 7689 __ strexd($tmp2$$Register, $tmp1$$Register, $mem$$Address); 7690 __ cmp($tmp2$$Register, 0); 7691 __ b(loop, ne); 7692 %} 7693 ins_pipe( long_memory_op ); 7694 %} 7695 #endif 7696 7697 #ifdef AARCH64 7698 instruct xaddL_imm_no_res(memoryex mem, aimmL add, Universe dummy, iRegL tmp1, iRegI tmp2) %{ 7699 predicate(n->as_LoadStore()->result_not_used()); 7700 match(Set dummy (GetAndAddL mem add)); 7701 effect(TEMP tmp1, TEMP tmp2); 7702 size(16); 7703 format %{ "loop:\n\t" 7704 "LDXR $tmp1, $mem\n\t" 7705 "ADD $tmp1, $tmp1, $add\n\t" 7706 "STXR $tmp2, $tmp1, $mem\n\t" 7707 "CBNZ_w $tmp2, loop" %} 7708 7709 ins_encode %{ 7710 Label loop; 7711 Register base = reg_to_register_object($mem$$base); 7712 __ bind(loop); 7713 __ ldxr($tmp1$$Register, base); 7714 __ add($tmp1$$Register, $tmp1$$Register, $add$$constant); 7715 __ stxr($tmp2$$Register, $tmp1$$Register, base); 7716 __ cbnz_w($tmp2$$Register, loop); 7717 %} 7718 ins_pipe( long_memory_op ); 7719 %} 7720 #else 7721 // TODO: try immLRot2 instead, (0, $con$$constant) becomes 7722 // (hi($con$$constant), lo($con$$constant)) becomes 7723 instruct xaddL_immRot_no_res(memoryex mem, immLlowRot add, Universe dummy, iRegLd tmp1, iRegI tmp2, flagsReg ccr) %{ 7724 predicate(n->as_LoadStore()->result_not_used()); 7725 match(Set dummy (GetAndAddL mem add)); 7726 effect( KILL ccr, TEMP tmp1, TEMP tmp2); 7727 size(24); 7728 format %{ "loop: \n\t" 7729 "LDREXD $tmp1, $mem\n\t" 7730 "ADDS $tmp1.lo, $tmp1.lo, $add\n\t" 7731 "ADC $tmp1.hi, $tmp1.hi, 0\n\t" 7732 "STREXD $tmp2, $tmp1, $mem\n\t" 7733 "CMP $tmp2, 0 \n\t" 7734 "B.ne loop \n\t" %} 7735 7736 ins_encode %{ 7737 Label loop; 7738 __ bind(loop); 7739 __ ldrexd($tmp1$$Register, $mem$$Address); 7740 __ adds($tmp1$$Register, $tmp1$$Register, $add$$constant); 7741 __ adc($tmp1$$Register->successor(), $tmp1$$Register->successor(), 0); 7742 __ strexd($tmp2$$Register, $tmp1$$Register, $mem$$Address); 7743 __ cmp($tmp2$$Register, 0); 7744 __ b(loop, ne); 7745 %} 7746 ins_pipe( long_memory_op ); 7747 %} 7748 #endif 7749 7750 #ifdef AARCH64 7751 instruct xaddL_reg(memoryex mem, iRegL add, iRegL res, iRegL tmp1, iRegI tmp2) %{ 7752 match(Set res (GetAndAddL mem add)); 7753 effect(TEMP tmp1, TEMP tmp2, TEMP res); 7754 size(16); 7755 format %{ "loop:\n\t" 7756 "LDXR $res, $mem\n\t" 7757 "ADD $tmp1, $res, $add\n\t" 7758 "STXR $tmp2, $tmp1, $mem\n\t" 7759 "CBNZ_w $tmp2, loop" %} 7760 7761 ins_encode %{ 7762 Label loop; 7763 Register base = reg_to_register_object($mem$$base); 7764 __ bind(loop); 7765 __ ldxr($res$$Register, base); 7766 __ add($tmp1$$Register, $res$$Register, $add$$Register); 7767 __ stxr($tmp2$$Register, $tmp1$$Register, base); 7768 __ cbnz_w($tmp2$$Register, loop); 7769 %} 7770 ins_pipe( long_memory_op ); 7771 %} 7772 #else 7773 instruct xaddL_reg(memoryex mem, iRegL add, iRegLd res, iRegLd tmp1, iRegI tmp2, flagsReg ccr) %{ 7774 match(Set res (GetAndAddL mem add)); 7775 effect( KILL ccr, TEMP tmp1, TEMP tmp2, TEMP res); 7776 size(24); 7777 format %{ "loop: \n\t" 7778 "LDREXD $res, $mem\n\t" 7779 "ADDS $tmp1.lo, $res.lo, $add.lo\n\t" 7780 "ADC $tmp1.hi, $res.hi, $add.hi\n\t" 7781 "STREXD $tmp2, $tmp1, $mem\n\t" 7782 "CMP $tmp2, 0 \n\t" 7783 "B.ne loop \n\t" %} 7784 7785 ins_encode %{ 7786 Label loop; 7787 __ bind(loop); 7788 __ ldrexd($res$$Register, $mem$$Address); 7789 __ adds($tmp1$$Register, $res$$Register, $add$$Register); 7790 __ adc($tmp1$$Register->successor(), $res$$Register->successor(), $add$$Register->successor()); 7791 __ strexd($tmp2$$Register, $tmp1$$Register, $mem$$Address); 7792 __ cmp($tmp2$$Register, 0); 7793 __ b(loop, ne); 7794 %} 7795 ins_pipe( long_memory_op ); 7796 %} 7797 #endif 7798 7799 #ifdef AARCH64 7800 instruct xaddL_imm(memoryex mem, aimmL add, iRegL res, iRegL tmp1, iRegI tmp2) %{ 7801 match(Set res (GetAndAddL mem add)); 7802 effect(TEMP tmp1, TEMP tmp2, TEMP res); 7803 size(16); 7804 format %{ "loop:\n\t" 7805 "LDXR $res, $mem\n\t" 7806 "ADD $tmp1, $res, $add\n\t" 7807 "STXR $tmp2, $tmp1, $mem\n\t" 7808 "CBNZ_w $tmp2, loop" %} 7809 7810 ins_encode %{ 7811 Label loop; 7812 Register base = reg_to_register_object($mem$$base); 7813 __ bind(loop); 7814 __ ldxr($res$$Register, base); 7815 __ add($tmp1$$Register, $res$$Register, $add$$constant); 7816 __ stxr($tmp2$$Register, $tmp1$$Register, base); 7817 __ cbnz_w($tmp2$$Register, loop); 7818 %} 7819 ins_pipe( long_memory_op ); 7820 %} 7821 #else 7822 // TODO: try immLRot2 instead, (0, $con$$constant) becomes 7823 // (hi($con$$constant), lo($con$$constant)) becomes 7824 instruct xaddL_immRot(memoryex mem, immLlowRot add, iRegLd res, iRegLd tmp1, iRegI tmp2, flagsReg ccr) %{ 7825 match(Set res (GetAndAddL mem add)); 7826 effect( KILL ccr, TEMP tmp1, TEMP tmp2, TEMP res); 7827 size(24); 7828 format %{ "loop: \n\t" 7829 "LDREXD $res, $mem\n\t" 7830 "ADDS $tmp1.lo, $res.lo, $add\n\t" 7831 "ADC $tmp1.hi, $res.hi, 0\n\t" 7832 "STREXD $tmp2, $tmp1, $mem\n\t" 7833 "CMP $tmp2, 0 \n\t" 7834 "B.ne loop \n\t" %} 7835 7836 ins_encode %{ 7837 Label loop; 7838 __ bind(loop); 7839 __ ldrexd($res$$Register, $mem$$Address); 7840 __ adds($tmp1$$Register, $res$$Register, $add$$constant); 7841 __ adc($tmp1$$Register->successor(), $res$$Register->successor(), 0); 7842 __ strexd($tmp2$$Register, $tmp1$$Register, $mem$$Address); 7843 __ cmp($tmp2$$Register, 0); 7844 __ b(loop, ne); 7845 %} 7846 ins_pipe( long_memory_op ); 7847 %} 7848 #endif 7849 7850 #ifdef AARCH64 7851 instruct xchgI(memoryex mem, iRegI newval, iRegI res, iRegI tmp) %{ 7852 match(Set res (GetAndSetI mem newval)); 7853 effect(TEMP tmp, TEMP res); 7854 size(12); 7855 format %{ "loop:\n\t" 7856 "LDXR_w $res, $mem\n\t" 7857 "STXR_w $tmp, $newval, $mem\n\t" 7858 "CBNZ_w $tmp, loop" %} 7859 7860 ins_encode %{ 7861 Label loop; 7862 Register base = reg_to_register_object($mem$$base); 7863 __ bind(loop); 7864 __ ldxr_w($res$$Register, base); 7865 __ stxr_w($tmp$$Register, $newval$$Register, base); 7866 __ cbnz_w($tmp$$Register, loop); 7867 %} 7868 ins_pipe( long_memory_op ); 7869 %} 7870 7871 #ifdef XXX 7872 // Disabled until 8051805 is fixed. 7873 instruct xchgN(memoryex mem, iRegN newval, iRegN res, iRegN tmp) %{ 7874 match(Set res (GetAndSetN mem newval)); 7875 effect(TEMP tmp, TEMP res); 7876 size(12); 7877 format %{ "loop:\n\t" 7878 "LDXR_w $res, $mem\n\t" 7879 "STXR_w $tmp, $newval, $mem\n\t" 7880 "CBNZ_w $tmp, loop" %} 7881 7882 ins_encode %{ 7883 Label loop; 7884 Register base = reg_to_register_object($mem$$base); 7885 __ bind(loop); 7886 __ ldxr_w($res$$Register, base); 7887 __ stxr_w($tmp$$Register, $newval$$Register, base); 7888 __ cbnz_w($tmp$$Register, loop); 7889 %} 7890 ins_pipe( long_memory_op ); 7891 %} 7892 #endif 7893 #else 7894 instruct xchgI(memoryex mem, iRegI newval, iRegI res, iRegI tmp, flagsReg ccr) %{ 7895 match(Set res (GetAndSetI mem newval)); 7896 effect(KILL ccr, TEMP tmp, TEMP res); 7897 size(16); 7898 format %{ "loop: \n\t" 7899 "LDREX $res, $mem\n\t" 7900 "STREX $tmp, $newval, $mem\n\t" 7901 "CMP $tmp, 0 \n\t" 7902 "B.ne loop \n\t" %} 7903 7904 ins_encode %{ 7905 Label loop; 7906 __ bind(loop); 7907 __ ldrex($res$$Register,$mem$$Address); 7908 __ strex($tmp$$Register, $newval$$Register, $mem$$Address); 7909 __ cmp($tmp$$Register, 0); 7910 __ b(loop, ne); 7911 %} 7912 ins_pipe( long_memory_op ); 7913 %} 7914 #endif 7915 7916 #ifdef AARCH64 7917 instruct xchgL(memoryex mem, iRegL newval, iRegL res, iRegI tmp) %{ 7918 match(Set res (GetAndSetL mem newval)); 7919 effect(TEMP tmp, TEMP res); 7920 size(12); 7921 format %{ "loop:\n\t" 7922 "LDXR $res, $mem\n\t" 7923 "STXR $tmp, $newval, $mem\n\t" 7924 "CBNZ_w $tmp, loop" %} 7925 7926 ins_encode %{ 7927 Label loop; 7928 Register base = reg_to_register_object($mem$$base); 7929 __ bind(loop); 7930 __ ldxr($res$$Register, base); 7931 __ stxr($tmp$$Register, $newval$$Register, base); 7932 __ cbnz_w($tmp$$Register, loop); 7933 %} 7934 ins_pipe( long_memory_op ); 7935 %} 7936 #else 7937 instruct xchgL(memoryex mem, iRegLd newval, iRegLd res, iRegI tmp, flagsReg ccr) %{ 7938 match(Set res (GetAndSetL mem newval)); 7939 effect( KILL ccr, TEMP tmp, TEMP res); 7940 size(16); 7941 format %{ "loop: \n\t" 7942 "LDREXD $res, $mem\n\t" 7943 "STREXD $tmp, $newval, $mem\n\t" 7944 "CMP $tmp, 0 \n\t" 7945 "B.ne loop \n\t" %} 7946 7947 ins_encode %{ 7948 Label loop; 7949 __ bind(loop); 7950 __ ldrexd($res$$Register, $mem$$Address); 7951 __ strexd($tmp$$Register, $newval$$Register, $mem$$Address); 7952 __ cmp($tmp$$Register, 0); 7953 __ b(loop, ne); 7954 %} 7955 ins_pipe( long_memory_op ); 7956 %} 7957 #endif // !AARCH64 7958 7959 #ifdef AARCH64 7960 instruct xchgP(memoryex mem, iRegP newval, iRegP res, iRegI tmp) %{ 7961 match(Set res (GetAndSetP mem newval)); 7962 effect(TEMP tmp, TEMP res); 7963 size(12); 7964 format %{ "loop:\n\t" 7965 "LDREX $res, $mem\n\t" 7966 "STREX $tmp, $newval, $mem\n\t" 7967 "CBNZ_w $tmp, loop" %} 7968 7969 ins_encode %{ 7970 Label loop; 7971 Register base = reg_to_register_object($mem$$base); 7972 __ bind(loop); 7973 __ ldrex($res$$Register, base); 7974 __ strex($tmp$$Register, $newval$$Register, base); 7975 __ cbnz_w($tmp$$Register, loop); 7976 %} 7977 ins_pipe( long_memory_op ); 7978 %} 7979 #else 7980 instruct xchgP(memoryex mem, iRegP newval, iRegP res, iRegI tmp, flagsReg ccr) %{ 7981 match(Set res (GetAndSetP mem newval)); 7982 effect(KILL ccr, TEMP tmp, TEMP res); 7983 size(16); 7984 format %{ "loop: \n\t" 7985 "LDREX $res, $mem\n\t" 7986 "STREX $tmp, $newval, $mem\n\t" 7987 "CMP $tmp, 0 \n\t" 7988 "B.ne loop \n\t" %} 7989 7990 ins_encode %{ 7991 Label loop; 7992 __ bind(loop); 7993 __ ldrex($res$$Register,$mem$$Address); 7994 __ strex($tmp$$Register, $newval$$Register, $mem$$Address); 7995 __ cmp($tmp$$Register, 0); 7996 __ b(loop, ne); 7997 %} 7998 ins_pipe( long_memory_op ); 7999 %} 8000 #endif // !AARCH64 8001 8002 //--------------------- 8003 // Subtraction Instructions 8004 // Register Subtraction 8005 instruct subI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{ 8006 match(Set dst (SubI src1 src2)); 8007 8008 size(4); 8009 format %{ "sub_32 $dst,$src1,$src2\t! int" %} 8010 ins_encode %{ 8011 __ sub_32($dst$$Register, $src1$$Register, $src2$$Register); 8012 %} 8013 ins_pipe(ialu_reg_reg); 8014 %} 8015 8016 #ifndef AARCH64 8017 instruct subshlI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 8018 match(Set dst (SubI src1 (LShiftI src2 src3))); 8019 8020 size(4); 8021 format %{ "SUB $dst,$src1,$src2<<$src3" %} 8022 ins_encode %{ 8023 __ sub($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$Register)); 8024 %} 8025 ins_pipe(ialu_reg_reg); 8026 %} 8027 #endif 8028 8029 instruct subshlI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{ 8030 match(Set dst (SubI src1 (LShiftI src2 src3))); 8031 8032 size(4); 8033 format %{ "sub_32 $dst,$src1,$src2<<$src3\t! int" %} 8034 ins_encode %{ 8035 __ sub_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$constant)); 8036 %} 8037 ins_pipe(ialu_reg_reg); 8038 %} 8039 8040 #ifndef AARCH64 8041 instruct subsarI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 8042 match(Set dst (SubI src1 (RShiftI src2 src3))); 8043 8044 size(4); 8045 format %{ "SUB $dst,$src1,$src2>>$src3" %} 8046 ins_encode %{ 8047 __ sub($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$Register)); 8048 %} 8049 ins_pipe(ialu_reg_reg); 8050 %} 8051 #endif 8052 8053 instruct subsarI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{ 8054 match(Set dst (SubI src1 (RShiftI src2 src3))); 8055 8056 size(4); 8057 format %{ "sub_32 $dst,$src1,$src2>>$src3\t! int" %} 8058 ins_encode %{ 8059 __ sub_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$constant)); 8060 %} 8061 ins_pipe(ialu_reg_reg); 8062 %} 8063 8064 #ifndef AARCH64 8065 instruct subshrI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 8066 match(Set dst (SubI src1 (URShiftI src2 src3))); 8067 8068 size(4); 8069 format %{ "SUB $dst,$src1,$src2>>>$src3" %} 8070 ins_encode %{ 8071 __ sub($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$Register)); 8072 %} 8073 ins_pipe(ialu_reg_reg); 8074 %} 8075 #endif 8076 8077 instruct subshrI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{ 8078 match(Set dst (SubI src1 (URShiftI src2 src3))); 8079 8080 size(4); 8081 format %{ "sub_32 $dst,$src1,$src2>>>$src3\t! int" %} 8082 ins_encode %{ 8083 __ sub_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$constant)); 8084 %} 8085 ins_pipe(ialu_reg_reg); 8086 %} 8087 8088 #ifndef AARCH64 8089 instruct rsbshlI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 8090 match(Set dst (SubI (LShiftI src1 src2) src3)); 8091 8092 size(4); 8093 format %{ "RSB $dst,$src3,$src1<<$src2" %} 8094 ins_encode %{ 8095 __ rsb($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsl, $src2$$Register)); 8096 %} 8097 ins_pipe(ialu_reg_reg); 8098 %} 8099 8100 instruct rsbshlI_reg_imm_reg(iRegI dst, iRegI src1, immU5 src2, iRegI src3) %{ 8101 match(Set dst (SubI (LShiftI src1 src2) src3)); 8102 8103 size(4); 8104 format %{ "RSB $dst,$src3,$src1<<$src2" %} 8105 ins_encode %{ 8106 __ rsb($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsl, $src2$$constant)); 8107 %} 8108 ins_pipe(ialu_reg_reg); 8109 %} 8110 8111 instruct rsbsarI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 8112 match(Set dst (SubI (RShiftI src1 src2) src3)); 8113 8114 size(4); 8115 format %{ "RSB $dst,$src3,$src1>>$src2" %} 8116 ins_encode %{ 8117 __ rsb($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, asr, $src2$$Register)); 8118 %} 8119 ins_pipe(ialu_reg_reg); 8120 %} 8121 8122 instruct rsbsarI_reg_imm_reg(iRegI dst, iRegI src1, immU5 src2, iRegI src3) %{ 8123 match(Set dst (SubI (RShiftI src1 src2) src3)); 8124 8125 size(4); 8126 format %{ "RSB $dst,$src3,$src1>>$src2" %} 8127 ins_encode %{ 8128 __ rsb($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, asr, $src2$$constant)); 8129 %} 8130 ins_pipe(ialu_reg_reg); 8131 %} 8132 8133 instruct rsbshrI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 8134 match(Set dst (SubI (URShiftI src1 src2) src3)); 8135 8136 size(4); 8137 format %{ "RSB $dst,$src3,$src1>>>$src2" %} 8138 ins_encode %{ 8139 __ rsb($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsr, $src2$$Register)); 8140 %} 8141 ins_pipe(ialu_reg_reg); 8142 %} 8143 8144 instruct rsbshrI_reg_imm_reg(iRegI dst, iRegI src1, immU5 src2, iRegI src3) %{ 8145 match(Set dst (SubI (URShiftI src1 src2) src3)); 8146 8147 size(4); 8148 format %{ "RSB $dst,$src3,$src1>>>$src2" %} 8149 ins_encode %{ 8150 __ rsb($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsr, $src2$$constant)); 8151 %} 8152 ins_pipe(ialu_reg_reg); 8153 %} 8154 #endif 8155 8156 // Immediate Subtraction 8157 instruct subI_reg_aimmI(iRegI dst, iRegI src1, aimmI src2) %{ 8158 match(Set dst (SubI src1 src2)); 8159 8160 size(4); 8161 format %{ "sub_32 $dst,$src1,$src2\t! int" %} 8162 ins_encode %{ 8163 __ sub_32($dst$$Register, $src1$$Register, $src2$$constant); 8164 %} 8165 ins_pipe(ialu_reg_imm); 8166 %} 8167 8168 instruct subI_reg_immRotneg(iRegI dst, iRegI src1, aimmIneg src2) %{ 8169 match(Set dst (AddI src1 src2)); 8170 8171 size(4); 8172 format %{ "sub_32 $dst,$src1,-($src2)\t! int" %} 8173 ins_encode %{ 8174 __ sub_32($dst$$Register, $src1$$Register, -$src2$$constant); 8175 %} 8176 ins_pipe(ialu_reg_imm); 8177 %} 8178 8179 #ifndef AARCH64 8180 instruct subI_immRot_reg(iRegI dst, immIRot src1, iRegI src2) %{ 8181 match(Set dst (SubI src1 src2)); 8182 8183 size(4); 8184 format %{ "RSB $dst,$src2,src1" %} 8185 ins_encode %{ 8186 __ rsb($dst$$Register, $src2$$Register, $src1$$constant); 8187 %} 8188 ins_pipe(ialu_zero_reg); 8189 %} 8190 #endif 8191 8192 // Register Subtraction 8193 #ifdef AARCH64 8194 instruct subL_reg_reg(iRegL dst, iRegL src1, iRegL src2) %{ 8195 match(Set dst (SubL src1 src2)); 8196 8197 size(4); 8198 format %{ "SUB $dst,$src1,$src2\t! long" %} 8199 ins_encode %{ 8200 __ sub($dst$$Register, $src1$$Register, $src2$$Register); 8201 %} 8202 ins_pipe(ialu_reg_reg); 8203 %} 8204 #else 8205 instruct subL_reg_reg(iRegL dst, iRegL src1, iRegL src2, flagsReg icc ) %{ 8206 match(Set dst (SubL src1 src2)); 8207 effect (KILL icc); 8208 8209 size(8); 8210 format %{ "SUBS $dst.lo,$src1.lo,$src2.lo\t! long\n\t" 8211 "SBC $dst.hi,$src1.hi,$src2.hi" %} 8212 ins_encode %{ 8213 __ subs($dst$$Register, $src1$$Register, $src2$$Register); 8214 __ sbc($dst$$Register->successor(), $src1$$Register->successor(), $src2$$Register->successor()); 8215 %} 8216 ins_pipe(ialu_reg_reg); 8217 %} 8218 #endif 8219 8220 #ifdef AARCH64 8221 // Immediate Subtraction 8222 instruct subL_reg_aimm(iRegL dst, iRegL src1, aimmL src2) %{ 8223 match(Set dst (SubL src1 src2)); 8224 8225 size(4); 8226 format %{ "SUB $dst,$src1,$src2\t! long" %} 8227 ins_encode %{ 8228 __ sub($dst$$Register, $src1$$Register, $src2$$constant); 8229 %} 8230 ins_pipe(ialu_reg_imm); 8231 %} 8232 8233 instruct subL_reg_immLneg(iRegL dst, iRegL src1, aimmLneg src2) %{ 8234 match(Set dst (AddL src1 src2)); 8235 8236 size(4); 8237 format %{ "SUB $dst,$src1,-($src2)\t! long" %} 8238 ins_encode %{ 8239 __ sub($dst$$Register, $src1$$Register, -$src2$$constant); 8240 %} 8241 ins_pipe(ialu_reg_imm); 8242 %} 8243 #else 8244 // TODO 8245 #endif 8246 8247 #ifndef AARCH64 8248 // Immediate Subtraction 8249 // TODO: try immLRot2 instead, (0, $con$$constant) becomes 8250 // (hi($con$$constant), lo($con$$constant)) becomes 8251 instruct subL_reg_immRot(iRegL dst, iRegL src1, immLlowRot con, flagsReg icc) %{ 8252 match(Set dst (SubL src1 con)); 8253 effect (KILL icc); 8254 8255 size(8); 8256 format %{ "SUB $dst.lo,$src1.lo,$con\t! long\n\t" 8257 "SBC $dst.hi,$src1.hi,0" %} 8258 ins_encode %{ 8259 __ subs($dst$$Register, $src1$$Register, $con$$constant); 8260 __ sbc($dst$$Register->successor(), $src1$$Register->successor(), 0); 8261 %} 8262 ins_pipe(ialu_reg_imm); 8263 %} 8264 8265 // Long negation 8266 instruct negL_reg_reg(iRegL dst, immL0 zero, iRegL src2, flagsReg icc) %{ 8267 match(Set dst (SubL zero src2)); 8268 effect (KILL icc); 8269 8270 size(8); 8271 format %{ "RSBS $dst.lo,$src2.lo,0\t! long\n\t" 8272 "RSC $dst.hi,$src2.hi,0" %} 8273 ins_encode %{ 8274 __ rsbs($dst$$Register, $src2$$Register, 0); 8275 __ rsc($dst$$Register->successor(), $src2$$Register->successor(), 0); 8276 %} 8277 ins_pipe(ialu_zero_reg); 8278 %} 8279 #endif // !AARCH64 8280 8281 // Multiplication Instructions 8282 // Integer Multiplication 8283 // Register Multiplication 8284 instruct mulI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{ 8285 match(Set dst (MulI src1 src2)); 8286 8287 size(4); 8288 format %{ "mul_32 $dst,$src1,$src2" %} 8289 ins_encode %{ 8290 __ mul_32($dst$$Register, $src1$$Register, $src2$$Register); 8291 %} 8292 ins_pipe(imul_reg_reg); 8293 %} 8294 8295 #ifdef AARCH64 8296 instruct mulL_reg_reg(iRegL dst, iRegL src1, iRegL src2) %{ 8297 match(Set dst (MulL src1 src2)); 8298 size(4); 8299 format %{ "MUL $dst,$src1,$src2\t! long" %} 8300 ins_encode %{ 8301 __ mul($dst$$Register, $src1$$Register, $src2$$Register); 8302 %} 8303 ins_pipe(imul_reg_reg); 8304 %} 8305 #else 8306 instruct mulL_lo1_hi2(iRegL dst, iRegL src1, iRegL src2) %{ 8307 effect(DEF dst, USE src1, USE src2); 8308 size(4); 8309 format %{ "MUL $dst.hi,$src1.lo,$src2.hi\t! long" %} 8310 ins_encode %{ 8311 __ mul($dst$$Register->successor(), $src1$$Register, $src2$$Register->successor()); 8312 %} 8313 ins_pipe(imul_reg_reg); 8314 %} 8315 8316 instruct mulL_hi1_lo2(iRegL dst, iRegL src1, iRegL src2) %{ 8317 effect(USE_DEF dst, USE src1, USE src2); 8318 size(8); 8319 format %{ "MLA $dst.hi,$src1.hi,$src2.lo,$dst.hi\t! long\n\t" 8320 "MOV $dst.lo, 0"%} 8321 ins_encode %{ 8322 __ mla($dst$$Register->successor(), $src1$$Register->successor(), $src2$$Register, $dst$$Register->successor()); 8323 __ mov($dst$$Register, 0); 8324 %} 8325 ins_pipe(imul_reg_reg); 8326 %} 8327 8328 instruct mulL_lo1_lo2(iRegL dst, iRegL src1, iRegL src2) %{ 8329 effect(USE_DEF dst, USE src1, USE src2); 8330 size(4); 8331 format %{ "UMLAL $dst.lo,$dst.hi,$src1,$src2\t! long" %} 8332 ins_encode %{ 8333 __ umlal($dst$$Register, $dst$$Register->successor(), $src1$$Register, $src2$$Register); 8334 %} 8335 ins_pipe(imul_reg_reg); 8336 %} 8337 8338 instruct mulL_reg_reg(iRegL dst, iRegL src1, iRegL src2) %{ 8339 match(Set dst (MulL src1 src2)); 8340 8341 expand %{ 8342 mulL_lo1_hi2(dst, src1, src2); 8343 mulL_hi1_lo2(dst, src1, src2); 8344 mulL_lo1_lo2(dst, src1, src2); 8345 %} 8346 %} 8347 #endif // !AARCH64 8348 8349 // Integer Division 8350 // Register Division 8351 #ifdef AARCH64 8352 instruct divI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{ 8353 match(Set dst (DivI src1 src2)); 8354 8355 size(4); 8356 format %{ "SDIV $dst,$src1,$src2\t! 32-bit" %} 8357 ins_encode %{ 8358 __ sdiv_w($dst$$Register, $src1$$Register, $src2$$Register); 8359 %} 8360 ins_pipe(ialu_reg_reg); // FIXME 8361 %} 8362 #else 8363 instruct divI_reg_reg(R1RegI dst, R0RegI src1, R2RegI src2, LRRegP lr, flagsReg ccr) %{ 8364 match(Set dst (DivI src1 src2)); 8365 effect( KILL ccr, KILL src1, KILL src2, KILL lr); 8366 ins_cost((2+71)*DEFAULT_COST); 8367 8368 format %{ "DIV $dst,$src1,$src2 ! call to StubRoutines::Arm::idiv_irem_entry()" %} 8369 ins_encode %{ 8370 __ call(StubRoutines::Arm::idiv_irem_entry(), relocInfo::runtime_call_type); 8371 %} 8372 ins_pipe(sdiv_reg_reg); 8373 %} 8374 #endif 8375 8376 // Register Long Division 8377 #ifdef AARCH64 8378 instruct divL_reg_reg(iRegL dst, iRegL src1, iRegL src2) %{ 8379 match(Set dst (DivL src1 src2)); 8380 8381 size(4); 8382 format %{ "SDIV $dst,$src1,$src2" %} 8383 ins_encode %{ 8384 __ sdiv($dst$$Register, $src1$$Register, $src2$$Register); 8385 %} 8386 ins_pipe(ialu_reg_reg); // FIXME 8387 %} 8388 #else 8389 instruct divL_reg_reg(R0R1RegL dst, R2R3RegL src1, R0R1RegL src2) %{ 8390 match(Set dst (DivL src1 src2)); 8391 effect(CALL); 8392 ins_cost(DEFAULT_COST*71); 8393 format %{ "DIVL $src1,$src2,$dst\t! long ! call to SharedRuntime::ldiv" %} 8394 ins_encode %{ 8395 address target = CAST_FROM_FN_PTR(address, SharedRuntime::ldiv); 8396 __ call(target, relocInfo::runtime_call_type); 8397 %} 8398 ins_pipe(divL_reg_reg); 8399 %} 8400 #endif 8401 8402 // Integer Remainder 8403 // Register Remainder 8404 #ifdef AARCH64 8405 #ifdef TODO 8406 instruct msubI_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 8407 match(Set dst (SubI src1 (MulI src2 src3))); 8408 8409 size(4); 8410 format %{ "MSUB $dst,$src2,$src3,$src1\t! 32-bit\n\t" %} 8411 ins_encode %{ 8412 __ msub_w($dst$$Register, $src2$$Register, $src3$$Register, $src1$$Register); 8413 %} 8414 ins_pipe(ialu_reg_reg); // FIXME 8415 %} 8416 #endif 8417 8418 instruct modI_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI temp) %{ 8419 match(Set dst (ModI src1 src2)); 8420 effect(TEMP temp); 8421 8422 size(8); 8423 format %{ "SDIV $temp,$src1,$src2\t! 32-bit\n\t" 8424 "MSUB $dst,$src2,$temp,$src1\t! 32-bit\n\t" %} 8425 ins_encode %{ 8426 __ sdiv_w($temp$$Register, $src1$$Register, $src2$$Register); 8427 __ msub_w($dst$$Register, $src2$$Register, $temp$$Register, $src1$$Register); 8428 %} 8429 ins_pipe(ialu_reg_reg); // FIXME 8430 %} 8431 #else 8432 instruct modI_reg_reg(R0RegI dst, R0RegI src1, R2RegI src2, R1RegI temp, LRRegP lr, flagsReg ccr ) %{ 8433 match(Set dst (ModI src1 src2)); 8434 effect( KILL ccr, KILL temp, KILL src2, KILL lr); 8435 8436 format %{ "MODI $dst,$src1,$src2\t ! call to StubRoutines::Arm::idiv_irem_entry" %} 8437 ins_encode %{ 8438 __ call(StubRoutines::Arm::idiv_irem_entry(), relocInfo::runtime_call_type); 8439 %} 8440 ins_pipe(sdiv_reg_reg); 8441 %} 8442 #endif 8443 8444 // Register Long Remainder 8445 #ifdef AARCH64 8446 instruct modL_reg_reg(iRegL dst, iRegL src1, iRegL src2, iRegL temp) %{ 8447 match(Set dst (ModL src1 src2)); 8448 effect(TEMP temp); 8449 8450 size(8); 8451 format %{ "SDIV $temp,$src1,$src2\n\t" 8452 "MSUB $dst,$src2,$temp,$src1" %} 8453 ins_encode %{ 8454 __ sdiv($temp$$Register, $src1$$Register, $src2$$Register); 8455 __ msub($dst$$Register, $src2$$Register, $temp$$Register, $src1$$Register); 8456 %} 8457 ins_pipe(ialu_reg_reg); // FIXME 8458 %} 8459 #else 8460 instruct modL_reg_reg(R0R1RegL dst, R2R3RegL src1, R0R1RegL src2) %{ 8461 match(Set dst (ModL src1 src2)); 8462 effect(CALL); 8463 ins_cost(MEMORY_REF_COST); // FIXME 8464 format %{ "modL $dst,$src1,$src2\t ! call to SharedRuntime::lrem" %} 8465 ins_encode %{ 8466 address target = CAST_FROM_FN_PTR(address, SharedRuntime::lrem); 8467 __ call(target, relocInfo::runtime_call_type); 8468 %} 8469 ins_pipe(divL_reg_reg); 8470 %} 8471 #endif 8472 8473 // Integer Shift Instructions 8474 8475 // Register Shift Left 8476 instruct shlI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{ 8477 match(Set dst (LShiftI src1 src2)); 8478 8479 size(4); 8480 #ifdef AARCH64 8481 format %{ "LSLV $dst,$src1,$src2\t! int" %} 8482 ins_encode %{ 8483 __ lslv_w($dst$$Register, $src1$$Register, $src2$$Register); 8484 %} 8485 #else 8486 format %{ "LSL $dst,$src1,$src2 \n\t" %} 8487 ins_encode %{ 8488 __ mov($dst$$Register, AsmOperand($src1$$Register, lsl, $src2$$Register)); 8489 %} 8490 #endif 8491 ins_pipe(ialu_reg_reg); 8492 %} 8493 8494 // Register Shift Left Immediate 8495 instruct shlI_reg_imm5(iRegI dst, iRegI src1, immU5 src2) %{ 8496 match(Set dst (LShiftI src1 src2)); 8497 8498 size(4); 8499 #ifdef AARCH64 8500 format %{ "LSL_w $dst,$src1,$src2\t! int" %} 8501 ins_encode %{ 8502 __ _lsl($dst$$Register, $src1$$Register, $src2$$constant); 8503 %} 8504 #else 8505 format %{ "LSL $dst,$src1,$src2\t! int" %} 8506 ins_encode %{ 8507 __ logical_shift_left($dst$$Register, $src1$$Register, $src2$$constant); 8508 %} 8509 #endif 8510 ins_pipe(ialu_reg_imm); 8511 %} 8512 8513 #ifndef AARCH64 8514 instruct shlL_reg_reg_merge_hi(iRegL dst, iRegL src1, iRegI src2) %{ 8515 effect(USE_DEF dst, USE src1, USE src2); 8516 size(4); 8517 format %{"OR $dst.hi,$dst.hi,($src1.hi << $src2)" %} 8518 ins_encode %{ 8519 __ orr($dst$$Register->successor(), $dst$$Register->successor(), AsmOperand($src1$$Register->successor(), lsl, $src2$$Register)); 8520 %} 8521 ins_pipe(ialu_reg_reg); 8522 %} 8523 8524 instruct shlL_reg_reg_merge_lo(iRegL dst, iRegL src1, iRegI src2) %{ 8525 effect(USE_DEF dst, USE src1, USE src2); 8526 size(4); 8527 format %{ "LSL $dst.lo,$src1.lo,$src2 \n\t" %} 8528 ins_encode %{ 8529 __ mov($dst$$Register, AsmOperand($src1$$Register, lsl, $src2$$Register)); 8530 %} 8531 ins_pipe(ialu_reg_reg); 8532 %} 8533 8534 instruct shlL_reg_reg_overlap(iRegL dst, iRegL src1, iRegI src2, flagsReg ccr) %{ 8535 effect(DEF dst, USE src1, USE src2, KILL ccr); 8536 size(16); 8537 format %{ "SUBS $dst.hi,$src2,32 \n\t" 8538 "LSLpl $dst.hi,$src1.lo,$dst.hi \n\t" 8539 "RSBmi $dst.hi,$dst.hi,0 \n\t" 8540 "LSRmi $dst.hi,$src1.lo,$dst.hi" %} 8541 8542 ins_encode %{ 8543 // $src1$$Register and $dst$$Register->successor() can't be the same 8544 __ subs($dst$$Register->successor(), $src2$$Register, 32); 8545 __ mov($dst$$Register->successor(), AsmOperand($src1$$Register, lsl, $dst$$Register->successor()), pl); 8546 __ rsb($dst$$Register->successor(), $dst$$Register->successor(), 0, mi); 8547 __ mov($dst$$Register->successor(), AsmOperand($src1$$Register, lsr, $dst$$Register->successor()), mi); 8548 %} 8549 ins_pipe(ialu_reg_reg); 8550 %} 8551 #endif // !AARCH64 8552 8553 instruct shlL_reg_reg(iRegL dst, iRegL src1, iRegI src2) %{ 8554 match(Set dst (LShiftL src1 src2)); 8555 8556 #ifdef AARCH64 8557 size(4); 8558 format %{ "LSLV $dst,$src1,$src2\t! long" %} 8559 ins_encode %{ 8560 __ lslv($dst$$Register, $src1$$Register, $src2$$Register); 8561 %} 8562 ins_pipe(ialu_reg_reg); 8563 #else 8564 expand %{ 8565 flagsReg ccr; 8566 shlL_reg_reg_overlap(dst, src1, src2, ccr); 8567 shlL_reg_reg_merge_hi(dst, src1, src2); 8568 shlL_reg_reg_merge_lo(dst, src1, src2); 8569 %} 8570 #endif 8571 %} 8572 8573 #ifdef AARCH64 8574 instruct shlL_reg_imm6(iRegL dst, iRegL src1, immU6 src2) %{ 8575 match(Set dst (LShiftL src1 src2)); 8576 8577 size(4); 8578 format %{ "LSL $dst,$src1,$src2\t! long" %} 8579 ins_encode %{ 8580 __ logical_shift_left($dst$$Register, $src1$$Register, $src2$$constant); 8581 %} 8582 ins_pipe(ialu_reg_imm); 8583 %} 8584 #else 8585 // Register Shift Left Immediate 8586 instruct shlL_reg_imm6(iRegL dst, iRegL src1, immU6Big src2) %{ 8587 match(Set dst (LShiftL src1 src2)); 8588 8589 size(8); 8590 format %{ "LSL $dst.hi,$src1.lo,$src2-32\t! or mov if $src2==32\n\t" 8591 "MOV $dst.lo, 0" %} 8592 ins_encode %{ 8593 if ($src2$$constant == 32) { 8594 __ mov($dst$$Register->successor(), $src1$$Register); 8595 } else { 8596 __ mov($dst$$Register->successor(), AsmOperand($src1$$Register, lsl, $src2$$constant-32)); 8597 } 8598 __ mov($dst$$Register, 0); 8599 %} 8600 ins_pipe(ialu_reg_imm); 8601 %} 8602 8603 instruct shlL_reg_imm5(iRegL dst, iRegL src1, immU5 src2) %{ 8604 match(Set dst (LShiftL src1 src2)); 8605 8606 size(12); 8607 format %{ "LSL $dst.hi,$src1.lo,$src2\n\t" 8608 "OR $dst.hi, $dst.hi, $src1.lo >> 32-$src2\n\t" 8609 "LSL $dst.lo,$src1.lo,$src2" %} 8610 ins_encode %{ 8611 // The order of the following 3 instructions matters: src1.lo and 8612 // dst.hi can't overlap but src.hi and dst.hi can. 8613 __ mov($dst$$Register->successor(), AsmOperand($src1$$Register->successor(), lsl, $src2$$constant)); 8614 __ orr($dst$$Register->successor(), $dst$$Register->successor(), AsmOperand($src1$$Register, lsr, 32-$src2$$constant)); 8615 __ mov($dst$$Register, AsmOperand($src1$$Register, lsl, $src2$$constant)); 8616 %} 8617 ins_pipe(ialu_reg_imm); 8618 %} 8619 #endif // !AARCH64 8620 8621 // Register Arithmetic Shift Right 8622 instruct sarI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{ 8623 match(Set dst (RShiftI src1 src2)); 8624 size(4); 8625 #ifdef AARCH64 8626 format %{ "ASRV $dst,$src1,$src2\t! int" %} 8627 ins_encode %{ 8628 __ asrv_w($dst$$Register, $src1$$Register, $src2$$Register); 8629 %} 8630 #else 8631 format %{ "ASR $dst,$src1,$src2\t! int" %} 8632 ins_encode %{ 8633 __ mov($dst$$Register, AsmOperand($src1$$Register, asr, $src2$$Register)); 8634 %} 8635 #endif 8636 ins_pipe(ialu_reg_reg); 8637 %} 8638 8639 // Register Arithmetic Shift Right Immediate 8640 instruct sarI_reg_imm5(iRegI dst, iRegI src1, immU5 src2) %{ 8641 match(Set dst (RShiftI src1 src2)); 8642 8643 size(4); 8644 #ifdef AARCH64 8645 format %{ "ASR_w $dst,$src1,$src2" %} 8646 ins_encode %{ 8647 __ _asr_w($dst$$Register, $src1$$Register, $src2$$constant); 8648 %} 8649 #else 8650 format %{ "ASR $dst,$src1,$src2" %} 8651 ins_encode %{ 8652 __ mov($dst$$Register, AsmOperand($src1$$Register, asr, $src2$$constant)); 8653 %} 8654 #endif 8655 ins_pipe(ialu_reg_imm); 8656 %} 8657 8658 #ifndef AARCH64 8659 // Register Shift Right Arithmetic Long 8660 instruct sarL_reg_reg_merge_lo(iRegL dst, iRegL src1, iRegI src2) %{ 8661 effect(USE_DEF dst, USE src1, USE src2); 8662 size(4); 8663 format %{ "OR $dst.lo,$dst.lo,($src1.lo >> $src2)" %} 8664 ins_encode %{ 8665 __ orr($dst$$Register, $dst$$Register, AsmOperand($src1$$Register, lsr, $src2$$Register)); 8666 %} 8667 ins_pipe(ialu_reg_reg); 8668 %} 8669 8670 instruct sarL_reg_reg_merge_hi(iRegL dst, iRegL src1, iRegI src2) %{ 8671 effect(USE_DEF dst, USE src1, USE src2); 8672 size(4); 8673 format %{ "ASR $dst.hi,$src1.hi,$src2 \n\t" %} 8674 ins_encode %{ 8675 __ mov($dst$$Register->successor(), AsmOperand($src1$$Register->successor(), asr, $src2$$Register)); 8676 %} 8677 ins_pipe(ialu_reg_reg); 8678 %} 8679 8680 instruct sarL_reg_reg_overlap(iRegL dst, iRegL src1, iRegI src2, flagsReg ccr) %{ 8681 effect(DEF dst, USE src1, USE src2, KILL ccr); 8682 size(16); 8683 format %{ "SUBS $dst.lo,$src2,32 \n\t" 8684 "ASRpl $dst.lo,$src1.hi,$dst.lo \n\t" 8685 "RSBmi $dst.lo,$dst.lo,0 \n\t" 8686 "LSLmi $dst.lo,$src1.hi,$dst.lo" %} 8687 8688 ins_encode %{ 8689 // $src1$$Register->successor() and $dst$$Register can't be the same 8690 __ subs($dst$$Register, $src2$$Register, 32); 8691 __ mov($dst$$Register, AsmOperand($src1$$Register->successor(), asr, $dst$$Register), pl); 8692 __ rsb($dst$$Register, $dst$$Register, 0, mi); 8693 __ mov($dst$$Register, AsmOperand($src1$$Register->successor(), lsl, $dst$$Register), mi); 8694 %} 8695 ins_pipe(ialu_reg_reg); 8696 %} 8697 #endif // !AARCH64 8698 8699 instruct sarL_reg_reg(iRegL dst, iRegL src1, iRegI src2) %{ 8700 match(Set dst (RShiftL src1 src2)); 8701 8702 #ifdef AARCH64 8703 size(4); 8704 format %{ "ASRV $dst,$src1,$src2\t! long" %} 8705 ins_encode %{ 8706 __ asrv($dst$$Register, $src1$$Register, $src2$$Register); 8707 %} 8708 ins_pipe(ialu_reg_reg); 8709 #else 8710 expand %{ 8711 flagsReg ccr; 8712 sarL_reg_reg_overlap(dst, src1, src2, ccr); 8713 sarL_reg_reg_merge_lo(dst, src1, src2); 8714 sarL_reg_reg_merge_hi(dst, src1, src2); 8715 %} 8716 #endif 8717 %} 8718 8719 // Register Shift Left Immediate 8720 #ifdef AARCH64 8721 instruct sarL_reg_imm6(iRegL dst, iRegL src1, immU6 src2) %{ 8722 match(Set dst (RShiftL src1 src2)); 8723 8724 size(4); 8725 format %{ "ASR $dst,$src1,$src2\t! long" %} 8726 ins_encode %{ 8727 __ _asr($dst$$Register, $src1$$Register, $src2$$constant); 8728 %} 8729 ins_pipe(ialu_reg_imm); 8730 %} 8731 #else 8732 instruct sarL_reg_imm6(iRegL dst, iRegL src1, immU6Big src2) %{ 8733 match(Set dst (RShiftL src1 src2)); 8734 8735 size(8); 8736 format %{ "ASR $dst.lo,$src1.hi,$src2-32\t! or mov if $src2==32\n\t" 8737 "ASR $dst.hi,$src1.hi, $src2" %} 8738 ins_encode %{ 8739 if ($src2$$constant == 32) { 8740 __ mov($dst$$Register, $src1$$Register->successor()); 8741 } else{ 8742 __ mov($dst$$Register, AsmOperand($src1$$Register->successor(), asr, $src2$$constant-32)); 8743 } 8744 __ mov($dst$$Register->successor(), AsmOperand($src1$$Register->successor(), asr, 0)); 8745 %} 8746 8747 ins_pipe(ialu_reg_imm); 8748 %} 8749 8750 instruct sarL_reg_imm5(iRegL dst, iRegL src1, immU5 src2) %{ 8751 match(Set dst (RShiftL src1 src2)); 8752 size(12); 8753 format %{ "LSR $dst.lo,$src1.lo,$src2\n\t" 8754 "OR $dst.lo, $dst.lo, $src1.hi << 32-$src2\n\t" 8755 "ASR $dst.hi,$src1.hi,$src2" %} 8756 ins_encode %{ 8757 // The order of the following 3 instructions matters: src1.lo and 8758 // dst.hi can't overlap but src.hi and dst.hi can. 8759 __ mov($dst$$Register, AsmOperand($src1$$Register, lsr, $src2$$constant)); 8760 __ orr($dst$$Register, $dst$$Register, AsmOperand($src1$$Register->successor(), lsl, 32-$src2$$constant)); 8761 __ mov($dst$$Register->successor(), AsmOperand($src1$$Register->successor(), asr, $src2$$constant)); 8762 %} 8763 ins_pipe(ialu_reg_imm); 8764 %} 8765 #endif 8766 8767 // Register Shift Right 8768 instruct shrI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{ 8769 match(Set dst (URShiftI src1 src2)); 8770 size(4); 8771 #ifdef AARCH64 8772 format %{ "LSRV $dst,$src1,$src2\t! int" %} 8773 ins_encode %{ 8774 __ lsrv_w($dst$$Register, $src1$$Register, $src2$$Register); 8775 %} 8776 #else 8777 format %{ "LSR $dst,$src1,$src2\t! int" %} 8778 ins_encode %{ 8779 __ mov($dst$$Register, AsmOperand($src1$$Register, lsr, $src2$$Register)); 8780 %} 8781 #endif 8782 ins_pipe(ialu_reg_reg); 8783 %} 8784 8785 // Register Shift Right Immediate 8786 instruct shrI_reg_imm5(iRegI dst, iRegI src1, immU5 src2) %{ 8787 match(Set dst (URShiftI src1 src2)); 8788 8789 size(4); 8790 #ifdef AARCH64 8791 format %{ "LSR_w $dst,$src1,$src2" %} 8792 ins_encode %{ 8793 __ _lsr_w($dst$$Register, $src1$$Register, $src2$$constant); 8794 %} 8795 #else 8796 format %{ "LSR $dst,$src1,$src2" %} 8797 ins_encode %{ 8798 __ mov($dst$$Register, AsmOperand($src1$$Register, lsr, $src2$$constant)); 8799 %} 8800 #endif 8801 ins_pipe(ialu_reg_imm); 8802 %} 8803 8804 #ifndef AARCH64 8805 // Register Shift Right 8806 instruct shrL_reg_reg_merge_lo(iRegL dst, iRegL src1, iRegI src2) %{ 8807 effect(USE_DEF dst, USE src1, USE src2); 8808 size(4); 8809 format %{ "OR $dst.lo,$dst,($src1.lo >>> $src2)" %} 8810 ins_encode %{ 8811 __ orr($dst$$Register, $dst$$Register, AsmOperand($src1$$Register, lsr, $src2$$Register)); 8812 %} 8813 ins_pipe(ialu_reg_reg); 8814 %} 8815 8816 instruct shrL_reg_reg_merge_hi(iRegL dst, iRegL src1, iRegI src2) %{ 8817 effect(USE_DEF dst, USE src1, USE src2); 8818 size(4); 8819 format %{ "LSR $dst.hi,$src1.hi,$src2 \n\t" %} 8820 ins_encode %{ 8821 __ mov($dst$$Register->successor(), AsmOperand($src1$$Register->successor(), lsr, $src2$$Register)); 8822 %} 8823 ins_pipe(ialu_reg_reg); 8824 %} 8825 8826 instruct shrL_reg_reg_overlap(iRegL dst, iRegL src1, iRegI src2, flagsReg ccr) %{ 8827 effect(DEF dst, USE src1, USE src2, KILL ccr); 8828 size(16); 8829 format %{ "SUBS $dst,$src2,32 \n\t" 8830 "LSRpl $dst,$src1.hi,$dst \n\t" 8831 "RSBmi $dst,$dst,0 \n\t" 8832 "LSLmi $dst,$src1.hi,$dst" %} 8833 8834 ins_encode %{ 8835 // $src1$$Register->successor() and $dst$$Register can't be the same 8836 __ subs($dst$$Register, $src2$$Register, 32); 8837 __ mov($dst$$Register, AsmOperand($src1$$Register->successor(), lsr, $dst$$Register), pl); 8838 __ rsb($dst$$Register, $dst$$Register, 0, mi); 8839 __ mov($dst$$Register, AsmOperand($src1$$Register->successor(), lsl, $dst$$Register), mi); 8840 %} 8841 ins_pipe(ialu_reg_reg); 8842 %} 8843 #endif // !AARCH64 8844 8845 instruct shrL_reg_reg(iRegL dst, iRegL src1, iRegI src2) %{ 8846 match(Set dst (URShiftL src1 src2)); 8847 8848 #ifdef AARCH64 8849 size(4); 8850 format %{ "LSRV $dst,$src1,$src2\t! long" %} 8851 ins_encode %{ 8852 __ lsrv($dst$$Register, $src1$$Register, $src2$$Register); 8853 %} 8854 ins_pipe(ialu_reg_reg); 8855 #else 8856 expand %{ 8857 flagsReg ccr; 8858 shrL_reg_reg_overlap(dst, src1, src2, ccr); 8859 shrL_reg_reg_merge_lo(dst, src1, src2); 8860 shrL_reg_reg_merge_hi(dst, src1, src2); 8861 %} 8862 #endif 8863 %} 8864 8865 // Register Shift Right Immediate 8866 #ifdef AARCH64 8867 instruct shrL_reg_imm6(iRegL dst, iRegL src1, immU6 src2) %{ 8868 match(Set dst (URShiftL src1 src2)); 8869 8870 size(4); 8871 format %{ "LSR $dst,$src1,$src2" %} 8872 ins_encode %{ 8873 __ _lsr($dst$$Register, $src1$$Register, $src2$$constant); 8874 %} 8875 ins_pipe(ialu_reg_imm); 8876 %} 8877 #else 8878 instruct shrL_reg_imm6(iRegL dst, iRegL src1, immU6Big src2) %{ 8879 match(Set dst (URShiftL src1 src2)); 8880 8881 size(8); 8882 format %{ "LSR $dst.lo,$src1.hi,$src2-32\t! or mov if $src2==32\n\t" 8883 "MOV $dst.hi, 0" %} 8884 ins_encode %{ 8885 if ($src2$$constant == 32) { 8886 __ mov($dst$$Register, $src1$$Register->successor()); 8887 } else { 8888 __ mov($dst$$Register, AsmOperand($src1$$Register->successor(), lsr, $src2$$constant-32)); 8889 } 8890 __ mov($dst$$Register->successor(), 0); 8891 %} 8892 8893 ins_pipe(ialu_reg_imm); 8894 %} 8895 8896 instruct shrL_reg_imm5(iRegL dst, iRegL src1, immU5 src2) %{ 8897 match(Set dst (URShiftL src1 src2)); 8898 8899 size(12); 8900 format %{ "LSR $dst.lo,$src1.lo,$src2\n\t" 8901 "OR $dst.lo, $dst.lo, $src1.hi << 32-$src2\n\t" 8902 "LSR $dst.hi,$src1.hi,$src2" %} 8903 ins_encode %{ 8904 // The order of the following 3 instructions matters: src1.lo and 8905 // dst.hi can't overlap but src.hi and dst.hi can. 8906 __ mov($dst$$Register, AsmOperand($src1$$Register, lsr, $src2$$constant)); 8907 __ orr($dst$$Register, $dst$$Register, AsmOperand($src1$$Register->successor(), lsl, 32-$src2$$constant)); 8908 __ mov($dst$$Register->successor(), AsmOperand($src1$$Register->successor(), lsr, $src2$$constant)); 8909 %} 8910 ins_pipe(ialu_reg_imm); 8911 %} 8912 #endif // !AARCH64 8913 8914 8915 instruct shrP_reg_imm5(iRegX dst, iRegP src1, immU5 src2) %{ 8916 match(Set dst (URShiftI (CastP2X src1) src2)); 8917 size(4); 8918 format %{ "LSR $dst,$src1,$src2\t! Cast ptr $src1 to int and shift" %} 8919 ins_encode %{ 8920 __ logical_shift_right($dst$$Register, $src1$$Register, $src2$$constant); 8921 %} 8922 ins_pipe(ialu_reg_imm); 8923 %} 8924 8925 //----------Floating Point Arithmetic Instructions----------------------------- 8926 8927 // Add float single precision 8928 instruct addF_reg_reg(regF dst, regF src1, regF src2) %{ 8929 match(Set dst (AddF src1 src2)); 8930 8931 size(4); 8932 format %{ "FADDS $dst,$src1,$src2" %} 8933 ins_encode %{ 8934 __ add_float($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister); 8935 %} 8936 8937 ins_pipe(faddF_reg_reg); 8938 %} 8939 8940 // Add float double precision 8941 instruct addD_reg_reg(regD dst, regD src1, regD src2) %{ 8942 match(Set dst (AddD src1 src2)); 8943 8944 size(4); 8945 format %{ "FADDD $dst,$src1,$src2" %} 8946 ins_encode %{ 8947 __ add_double($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister); 8948 %} 8949 8950 ins_pipe(faddD_reg_reg); 8951 %} 8952 8953 // Sub float single precision 8954 instruct subF_reg_reg(regF dst, regF src1, regF src2) %{ 8955 match(Set dst (SubF src1 src2)); 8956 8957 size(4); 8958 format %{ "FSUBS $dst,$src1,$src2" %} 8959 ins_encode %{ 8960 __ sub_float($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister); 8961 %} 8962 ins_pipe(faddF_reg_reg); 8963 %} 8964 8965 // Sub float double precision 8966 instruct subD_reg_reg(regD dst, regD src1, regD src2) %{ 8967 match(Set dst (SubD src1 src2)); 8968 8969 size(4); 8970 format %{ "FSUBD $dst,$src1,$src2" %} 8971 ins_encode %{ 8972 __ sub_double($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister); 8973 %} 8974 ins_pipe(faddD_reg_reg); 8975 %} 8976 8977 // Mul float single precision 8978 instruct mulF_reg_reg(regF dst, regF src1, regF src2) %{ 8979 match(Set dst (MulF src1 src2)); 8980 8981 size(4); 8982 format %{ "FMULS $dst,$src1,$src2" %} 8983 ins_encode %{ 8984 __ mul_float($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister); 8985 %} 8986 8987 ins_pipe(fmulF_reg_reg); 8988 %} 8989 8990 // Mul float double precision 8991 instruct mulD_reg_reg(regD dst, regD src1, regD src2) %{ 8992 match(Set dst (MulD src1 src2)); 8993 8994 size(4); 8995 format %{ "FMULD $dst,$src1,$src2" %} 8996 ins_encode %{ 8997 __ mul_double($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister); 8998 %} 8999 9000 ins_pipe(fmulD_reg_reg); 9001 %} 9002 9003 // Div float single precision 9004 instruct divF_reg_reg(regF dst, regF src1, regF src2) %{ 9005 match(Set dst (DivF src1 src2)); 9006 9007 size(4); 9008 format %{ "FDIVS $dst,$src1,$src2" %} 9009 ins_encode %{ 9010 __ div_float($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister); 9011 %} 9012 9013 ins_pipe(fdivF_reg_reg); 9014 %} 9015 9016 // Div float double precision 9017 instruct divD_reg_reg(regD dst, regD src1, regD src2) %{ 9018 match(Set dst (DivD src1 src2)); 9019 9020 size(4); 9021 format %{ "FDIVD $dst,$src1,$src2" %} 9022 ins_encode %{ 9023 __ div_double($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister); 9024 %} 9025 9026 ins_pipe(fdivD_reg_reg); 9027 %} 9028 9029 // Absolute float double precision 9030 instruct absD_reg(regD dst, regD src) %{ 9031 match(Set dst (AbsD src)); 9032 9033 size(4); 9034 format %{ "FABSd $dst,$src" %} 9035 ins_encode %{ 9036 __ abs_double($dst$$FloatRegister, $src$$FloatRegister); 9037 %} 9038 ins_pipe(faddD_reg); 9039 %} 9040 9041 // Absolute float single precision 9042 instruct absF_reg(regF dst, regF src) %{ 9043 match(Set dst (AbsF src)); 9044 format %{ "FABSs $dst,$src" %} 9045 ins_encode %{ 9046 __ abs_float($dst$$FloatRegister, $src$$FloatRegister); 9047 %} 9048 ins_pipe(faddF_reg); 9049 %} 9050 9051 instruct negF_reg(regF dst, regF src) %{ 9052 match(Set dst (NegF src)); 9053 9054 size(4); 9055 format %{ "FNEGs $dst,$src" %} 9056 ins_encode %{ 9057 __ neg_float($dst$$FloatRegister, $src$$FloatRegister); 9058 %} 9059 ins_pipe(faddF_reg); 9060 %} 9061 9062 instruct negD_reg(regD dst, regD src) %{ 9063 match(Set dst (NegD src)); 9064 9065 format %{ "FNEGd $dst,$src" %} 9066 ins_encode %{ 9067 __ neg_double($dst$$FloatRegister, $src$$FloatRegister); 9068 %} 9069 ins_pipe(faddD_reg); 9070 %} 9071 9072 // Sqrt float double precision 9073 instruct sqrtF_reg_reg(regF dst, regF src) %{ 9074 match(Set dst (ConvD2F (SqrtD (ConvF2D src)))); 9075 9076 size(4); 9077 format %{ "FSQRTS $dst,$src" %} 9078 ins_encode %{ 9079 __ sqrt_float($dst$$FloatRegister, $src$$FloatRegister); 9080 %} 9081 ins_pipe(fdivF_reg_reg); 9082 %} 9083 9084 // Sqrt float double precision 9085 instruct sqrtD_reg_reg(regD dst, regD src) %{ 9086 match(Set dst (SqrtD src)); 9087 9088 size(4); 9089 format %{ "FSQRTD $dst,$src" %} 9090 ins_encode %{ 9091 __ sqrt_double($dst$$FloatRegister, $src$$FloatRegister); 9092 %} 9093 ins_pipe(fdivD_reg_reg); 9094 %} 9095 9096 //----------Logical Instructions----------------------------------------------- 9097 // And Instructions 9098 // Register And 9099 instruct andI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{ 9100 match(Set dst (AndI src1 src2)); 9101 9102 size(4); 9103 format %{ "and_32 $dst,$src1,$src2" %} 9104 ins_encode %{ 9105 __ and_32($dst$$Register, $src1$$Register, $src2$$Register); 9106 %} 9107 ins_pipe(ialu_reg_reg); 9108 %} 9109 9110 #ifndef AARCH64 9111 instruct andshlI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 9112 match(Set dst (AndI src1 (LShiftI src2 src3))); 9113 9114 size(4); 9115 format %{ "AND $dst,$src1,$src2<<$src3" %} 9116 ins_encode %{ 9117 __ andr($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$Register)); 9118 %} 9119 ins_pipe(ialu_reg_reg); 9120 %} 9121 #endif 9122 9123 instruct andshlI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{ 9124 match(Set dst (AndI src1 (LShiftI src2 src3))); 9125 9126 size(4); 9127 format %{ "and_32 $dst,$src1,$src2<<$src3" %} 9128 ins_encode %{ 9129 __ and_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$constant)); 9130 %} 9131 ins_pipe(ialu_reg_reg); 9132 %} 9133 9134 #ifndef AARCH64 9135 instruct andsarI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 9136 match(Set dst (AndI src1 (RShiftI src2 src3))); 9137 9138 size(4); 9139 format %{ "AND $dst,$src1,$src2>>$src3" %} 9140 ins_encode %{ 9141 __ andr($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$Register)); 9142 %} 9143 ins_pipe(ialu_reg_reg); 9144 %} 9145 #endif 9146 9147 instruct andsarI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{ 9148 match(Set dst (AndI src1 (RShiftI src2 src3))); 9149 9150 size(4); 9151 format %{ "and_32 $dst,$src1,$src2>>$src3" %} 9152 ins_encode %{ 9153 __ and_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$constant)); 9154 %} 9155 ins_pipe(ialu_reg_reg); 9156 %} 9157 9158 #ifndef AARCH64 9159 instruct andshrI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 9160 match(Set dst (AndI src1 (URShiftI src2 src3))); 9161 9162 size(4); 9163 format %{ "AND $dst,$src1,$src2>>>$src3" %} 9164 ins_encode %{ 9165 __ andr($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$Register)); 9166 %} 9167 ins_pipe(ialu_reg_reg); 9168 %} 9169 #endif 9170 9171 instruct andshrI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{ 9172 match(Set dst (AndI src1 (URShiftI src2 src3))); 9173 9174 size(4); 9175 format %{ "and_32 $dst,$src1,$src2>>>$src3" %} 9176 ins_encode %{ 9177 __ and_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$constant)); 9178 %} 9179 ins_pipe(ialu_reg_reg); 9180 %} 9181 9182 // Immediate And 9183 instruct andI_reg_limm(iRegI dst, iRegI src1, limmI src2) %{ 9184 match(Set dst (AndI src1 src2)); 9185 9186 size(4); 9187 format %{ "and_32 $dst,$src1,$src2\t! int" %} 9188 ins_encode %{ 9189 __ and_32($dst$$Register, $src1$$Register, $src2$$constant); 9190 %} 9191 ins_pipe(ialu_reg_imm); 9192 %} 9193 9194 #ifndef AARCH64 9195 instruct andI_reg_limmn(iRegI dst, iRegI src1, limmIn src2) %{ 9196 match(Set dst (AndI src1 src2)); 9197 9198 size(4); 9199 format %{ "bic $dst,$src1,~$src2\t! int" %} 9200 ins_encode %{ 9201 __ bic($dst$$Register, $src1$$Register, ~$src2$$constant); 9202 %} 9203 ins_pipe(ialu_reg_imm); 9204 %} 9205 #endif 9206 9207 // Register And Long 9208 instruct andL_reg_reg(iRegL dst, iRegL src1, iRegL src2) %{ 9209 match(Set dst (AndL src1 src2)); 9210 9211 ins_cost(DEFAULT_COST); 9212 #ifdef AARCH64 9213 size(4); 9214 format %{ "AND $dst,$src1,$src2\t! long" %} 9215 ins_encode %{ 9216 __ andr($dst$$Register, $src1$$Register, $src2$$Register); 9217 %} 9218 #else 9219 size(8); 9220 format %{ "AND $dst,$src1,$src2\t! long" %} 9221 ins_encode %{ 9222 __ andr($dst$$Register, $src1$$Register, $src2$$Register); 9223 __ andr($dst$$Register->successor(), $src1$$Register->successor(), $src2$$Register->successor()); 9224 %} 9225 #endif 9226 ins_pipe(ialu_reg_reg); 9227 %} 9228 9229 #ifdef AARCH64 9230 // Immediate And 9231 instruct andL_reg_limm(iRegL dst, iRegL src1, limmL src2) %{ 9232 match(Set dst (AndL src1 src2)); 9233 9234 size(4); 9235 format %{ "AND $dst,$src1,$src2\t! long" %} 9236 ins_encode %{ 9237 __ andr($dst$$Register, $src1$$Register, (uintx)$src2$$constant); 9238 %} 9239 ins_pipe(ialu_reg_imm); 9240 %} 9241 #else 9242 // TODO: try immLRot2 instead, (0, $con$$constant) becomes 9243 // (hi($con$$constant), lo($con$$constant)) becomes 9244 instruct andL_reg_immRot(iRegL dst, iRegL src1, immLlowRot con) %{ 9245 match(Set dst (AndL src1 con)); 9246 ins_cost(DEFAULT_COST); 9247 size(8); 9248 format %{ "AND $dst,$src1,$con\t! long" %} 9249 ins_encode %{ 9250 __ andr($dst$$Register, $src1$$Register, $con$$constant); 9251 __ andr($dst$$Register->successor(), $src1$$Register->successor(), 0); 9252 %} 9253 ins_pipe(ialu_reg_imm); 9254 %} 9255 #endif 9256 9257 // Or Instructions 9258 // Register Or 9259 instruct orI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{ 9260 match(Set dst (OrI src1 src2)); 9261 9262 size(4); 9263 format %{ "orr_32 $dst,$src1,$src2\t! int" %} 9264 ins_encode %{ 9265 __ orr_32($dst$$Register, $src1$$Register, $src2$$Register); 9266 %} 9267 ins_pipe(ialu_reg_reg); 9268 %} 9269 9270 #ifndef AARCH64 9271 instruct orshlI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 9272 match(Set dst (OrI src1 (LShiftI src2 src3))); 9273 9274 size(4); 9275 format %{ "OR $dst,$src1,$src2<<$src3" %} 9276 ins_encode %{ 9277 __ orr($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$Register)); 9278 %} 9279 ins_pipe(ialu_reg_reg); 9280 %} 9281 #endif 9282 9283 instruct orshlI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{ 9284 match(Set dst (OrI src1 (LShiftI src2 src3))); 9285 9286 size(4); 9287 format %{ "orr_32 $dst,$src1,$src2<<$src3" %} 9288 ins_encode %{ 9289 __ orr_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$constant)); 9290 %} 9291 ins_pipe(ialu_reg_reg); 9292 %} 9293 9294 #ifndef AARCH64 9295 instruct orsarI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 9296 match(Set dst (OrI src1 (RShiftI src2 src3))); 9297 9298 size(4); 9299 format %{ "OR $dst,$src1,$src2>>$src3" %} 9300 ins_encode %{ 9301 __ orr($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$Register)); 9302 %} 9303 ins_pipe(ialu_reg_reg); 9304 %} 9305 #endif 9306 9307 instruct orsarI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{ 9308 match(Set dst (OrI src1 (RShiftI src2 src3))); 9309 9310 size(4); 9311 format %{ "orr_32 $dst,$src1,$src2>>$src3" %} 9312 ins_encode %{ 9313 __ orr_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$constant)); 9314 %} 9315 ins_pipe(ialu_reg_reg); 9316 %} 9317 9318 #ifndef AARCH64 9319 instruct orshrI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 9320 match(Set dst (OrI src1 (URShiftI src2 src3))); 9321 9322 size(4); 9323 format %{ "OR $dst,$src1,$src2>>>$src3" %} 9324 ins_encode %{ 9325 __ orr($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$Register)); 9326 %} 9327 ins_pipe(ialu_reg_reg); 9328 %} 9329 #endif 9330 9331 instruct orshrI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{ 9332 match(Set dst (OrI src1 (URShiftI src2 src3))); 9333 9334 size(4); 9335 format %{ "orr_32 $dst,$src1,$src2>>>$src3" %} 9336 ins_encode %{ 9337 __ orr_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$constant)); 9338 %} 9339 ins_pipe(ialu_reg_reg); 9340 %} 9341 9342 // Immediate Or 9343 instruct orI_reg_limm(iRegI dst, iRegI src1, limmI src2) %{ 9344 match(Set dst (OrI src1 src2)); 9345 9346 size(4); 9347 format %{ "orr_32 $dst,$src1,$src2" %} 9348 ins_encode %{ 9349 __ orr_32($dst$$Register, $src1$$Register, $src2$$constant); 9350 %} 9351 ins_pipe(ialu_reg_imm); 9352 %} 9353 // TODO: orn_32 with limmIn 9354 9355 // Register Or Long 9356 instruct orL_reg_reg(iRegL dst, iRegL src1, iRegL src2) %{ 9357 match(Set dst (OrL src1 src2)); 9358 9359 ins_cost(DEFAULT_COST); 9360 #ifdef AARCH64 9361 size(4); 9362 format %{ "OR $dst,$src1,$src2\t! long" %} 9363 ins_encode %{ 9364 __ orr($dst$$Register, $src1$$Register, $src2$$Register); 9365 %} 9366 #else 9367 size(8); 9368 format %{ "OR $dst.lo,$src1.lo,$src2.lo\t! long\n\t" 9369 "OR $dst.hi,$src1.hi,$src2.hi" %} 9370 ins_encode %{ 9371 __ orr($dst$$Register, $src1$$Register, $src2$$Register); 9372 __ orr($dst$$Register->successor(), $src1$$Register->successor(), $src2$$Register->successor()); 9373 %} 9374 #endif 9375 ins_pipe(ialu_reg_reg); 9376 %} 9377 9378 #ifdef AARCH64 9379 instruct orL_reg_limm(iRegL dst, iRegL src1, limmL src2) %{ 9380 match(Set dst (OrL src1 src2)); 9381 9382 size(4); 9383 format %{ "ORR $dst,$src1,$src2\t! long" %} 9384 ins_encode %{ 9385 __ orr($dst$$Register, $src1$$Register, (uintx)$src2$$constant); 9386 %} 9387 ins_pipe(ialu_reg_imm); 9388 %} 9389 #else 9390 // TODO: try immLRot2 instead, (0, $con$$constant) becomes 9391 // (hi($con$$constant), lo($con$$constant)) becomes 9392 instruct orL_reg_immRot(iRegL dst, iRegL src1, immLlowRot con) %{ 9393 match(Set dst (OrL src1 con)); 9394 ins_cost(DEFAULT_COST); 9395 size(8); 9396 format %{ "OR $dst.lo,$src1.lo,$con\t! long\n\t" 9397 "OR $dst.hi,$src1.hi,$con" %} 9398 ins_encode %{ 9399 __ orr($dst$$Register, $src1$$Register, $con$$constant); 9400 __ orr($dst$$Register->successor(), $src1$$Register->successor(), 0); 9401 %} 9402 ins_pipe(ialu_reg_imm); 9403 %} 9404 #endif 9405 9406 #ifdef TODO 9407 // Use SPRegP to match Rthread (TLS register) without spilling. 9408 // Use store_ptr_RegP to match Rthread (TLS register) without spilling. 9409 // Use sp_ptr_RegP to match Rthread (TLS register) without spilling. 9410 instruct orI_reg_castP2X(iRegI dst, iRegI src1, sp_ptr_RegP src2) %{ 9411 match(Set dst (OrI src1 (CastP2X src2))); 9412 size(4); 9413 format %{ "OR $dst,$src1,$src2" %} 9414 ins_encode %{ 9415 __ orr($dst$$Register, $src1$$Register, $src2$$Register); 9416 %} 9417 ins_pipe(ialu_reg_reg); 9418 %} 9419 #endif 9420 9421 // Xor Instructions 9422 // Register Xor 9423 instruct xorI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{ 9424 match(Set dst (XorI src1 src2)); 9425 9426 size(4); 9427 format %{ "eor_32 $dst,$src1,$src2" %} 9428 ins_encode %{ 9429 __ eor_32($dst$$Register, $src1$$Register, $src2$$Register); 9430 %} 9431 ins_pipe(ialu_reg_reg); 9432 %} 9433 9434 #ifndef AARCH64 9435 instruct xorshlI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 9436 match(Set dst (XorI src1 (LShiftI src2 src3))); 9437 9438 size(4); 9439 format %{ "XOR $dst,$src1,$src2<<$src3" %} 9440 ins_encode %{ 9441 __ eor($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$Register)); 9442 %} 9443 ins_pipe(ialu_reg_reg); 9444 %} 9445 #endif 9446 9447 instruct xorshlI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{ 9448 match(Set dst (XorI src1 (LShiftI src2 src3))); 9449 9450 size(4); 9451 format %{ "eor_32 $dst,$src1,$src2<<$src3" %} 9452 ins_encode %{ 9453 __ eor_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$constant)); 9454 %} 9455 ins_pipe(ialu_reg_reg); 9456 %} 9457 9458 #ifndef AARCH64 9459 instruct xorsarI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 9460 match(Set dst (XorI src1 (RShiftI src2 src3))); 9461 9462 size(4); 9463 format %{ "XOR $dst,$src1,$src2>>$src3" %} 9464 ins_encode %{ 9465 __ eor($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$Register)); 9466 %} 9467 ins_pipe(ialu_reg_reg); 9468 %} 9469 #endif 9470 9471 instruct xorsarI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{ 9472 match(Set dst (XorI src1 (RShiftI src2 src3))); 9473 9474 size(4); 9475 format %{ "eor_32 $dst,$src1,$src2>>$src3" %} 9476 ins_encode %{ 9477 __ eor_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$constant)); 9478 %} 9479 ins_pipe(ialu_reg_reg); 9480 %} 9481 9482 #ifndef AARCH64 9483 instruct xorshrI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 9484 match(Set dst (XorI src1 (URShiftI src2 src3))); 9485 9486 size(4); 9487 format %{ "XOR $dst,$src1,$src2>>>$src3" %} 9488 ins_encode %{ 9489 __ eor($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$Register)); 9490 %} 9491 ins_pipe(ialu_reg_reg); 9492 %} 9493 #endif 9494 9495 instruct xorshrI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{ 9496 match(Set dst (XorI src1 (URShiftI src2 src3))); 9497 9498 size(4); 9499 format %{ "eor_32 $dst,$src1,$src2>>>$src3" %} 9500 ins_encode %{ 9501 __ eor_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$constant)); 9502 %} 9503 ins_pipe(ialu_reg_reg); 9504 %} 9505 9506 // Immediate Xor 9507 instruct xorI_reg_imm(iRegI dst, iRegI src1, limmI src2) %{ 9508 match(Set dst (XorI src1 src2)); 9509 9510 size(4); 9511 format %{ "eor_32 $dst,$src1,$src2" %} 9512 ins_encode %{ 9513 __ eor_32($dst$$Register, $src1$$Register, $src2$$constant); 9514 %} 9515 ins_pipe(ialu_reg_imm); 9516 %} 9517 9518 // Register Xor Long 9519 instruct xorL_reg_reg(iRegL dst, iRegL src1, iRegL src2) %{ 9520 match(Set dst (XorL src1 src2)); 9521 ins_cost(DEFAULT_COST); 9522 #ifdef AARCH64 9523 size(4); 9524 format %{ "XOR $dst,$src1,$src2\t! long" %} 9525 ins_encode %{ 9526 __ eor($dst$$Register, $src1$$Register, $src2$$Register); 9527 %} 9528 #else 9529 size(8); 9530 format %{ "XOR $dst.hi,$src1.hi,$src2.hi\t! long\n\t" 9531 "XOR $dst.lo,$src1.lo,$src2.lo\t! long" %} 9532 ins_encode %{ 9533 __ eor($dst$$Register, $src1$$Register, $src2$$Register); 9534 __ eor($dst$$Register->successor(), $src1$$Register->successor(), $src2$$Register->successor()); 9535 %} 9536 #endif 9537 ins_pipe(ialu_reg_reg); 9538 %} 9539 9540 #ifdef AARCH64 9541 instruct xorL_reg_limmL(iRegL dst, iRegL src1, limmL con) %{ 9542 match(Set dst (XorL src1 con)); 9543 ins_cost(DEFAULT_COST); 9544 size(4); 9545 format %{ "EOR $dst,$src1,$con\t! long" %} 9546 ins_encode %{ 9547 __ eor($dst$$Register, $src1$$Register, (uintx)$con$$constant); 9548 %} 9549 ins_pipe(ialu_reg_imm); 9550 %} 9551 #else 9552 // TODO: try immLRot2 instead, (0, $con$$constant) becomes 9553 // (hi($con$$constant), lo($con$$constant)) becomes 9554 instruct xorL_reg_immRot(iRegL dst, iRegL src1, immLlowRot con) %{ 9555 match(Set dst (XorL src1 con)); 9556 ins_cost(DEFAULT_COST); 9557 size(8); 9558 format %{ "XOR $dst.hi,$src1.hi,$con\t! long\n\t" 9559 "XOR $dst.lo,$src1.lo,0\t! long" %} 9560 ins_encode %{ 9561 __ eor($dst$$Register, $src1$$Register, $con$$constant); 9562 __ eor($dst$$Register->successor(), $src1$$Register->successor(), 0); 9563 %} 9564 ins_pipe(ialu_reg_imm); 9565 %} 9566 #endif // AARCH64 9567 9568 //----------Convert to Boolean------------------------------------------------- 9569 instruct convI2B( iRegI dst, iRegI src, flagsReg ccr ) %{ 9570 match(Set dst (Conv2B src)); 9571 effect(KILL ccr); 9572 #ifdef AARCH64 9573 size(8); 9574 ins_cost(DEFAULT_COST*2); 9575 format %{ "cmp_32 $src,ZR\n\t" 9576 "cset_w $dst, ne" %} 9577 ins_encode %{ 9578 __ cmp_32($src$$Register, ZR); 9579 __ cset_w($dst$$Register, ne); 9580 %} 9581 #else 9582 size(12); 9583 ins_cost(DEFAULT_COST*2); 9584 format %{ "TST $src,$src \n\t" 9585 "MOV $dst, 0 \n\t" 9586 "MOV.ne $dst, 1" %} 9587 ins_encode %{ // FIXME: can do better? 9588 __ tst($src$$Register, $src$$Register); 9589 __ mov($dst$$Register, 0); 9590 __ mov($dst$$Register, 1, ne); 9591 %} 9592 #endif 9593 ins_pipe(ialu_reg_ialu); 9594 %} 9595 9596 instruct convP2B( iRegI dst, iRegP src, flagsReg ccr ) %{ 9597 match(Set dst (Conv2B src)); 9598 effect(KILL ccr); 9599 #ifdef AARCH64 9600 size(8); 9601 ins_cost(DEFAULT_COST*2); 9602 format %{ "CMP $src,ZR\n\t" 9603 "cset $dst, ne" %} 9604 ins_encode %{ 9605 __ cmp($src$$Register, ZR); 9606 __ cset($dst$$Register, ne); 9607 %} 9608 #else 9609 size(12); 9610 ins_cost(DEFAULT_COST*2); 9611 format %{ "TST $src,$src \n\t" 9612 "MOV $dst, 0 \n\t" 9613 "MOV.ne $dst, 1" %} 9614 ins_encode %{ 9615 __ tst($src$$Register, $src$$Register); 9616 __ mov($dst$$Register, 0); 9617 __ mov($dst$$Register, 1, ne); 9618 %} 9619 #endif 9620 ins_pipe(ialu_reg_ialu); 9621 %} 9622 9623 instruct cmpLTMask_reg_reg( iRegI dst, iRegI p, iRegI q, flagsReg ccr ) %{ 9624 match(Set dst (CmpLTMask p q)); 9625 effect( KILL ccr ); 9626 #ifdef AARCH64 9627 size(8); 9628 ins_cost(DEFAULT_COST*2); 9629 format %{ "CMP_w $p,$q\n\t" 9630 "CSETM_w $dst, lt" %} 9631 ins_encode %{ 9632 __ cmp_w($p$$Register, $q$$Register); 9633 __ csetm_w($dst$$Register, lt); 9634 %} 9635 #else 9636 ins_cost(DEFAULT_COST*3); 9637 format %{ "CMP $p,$q\n\t" 9638 "MOV $dst, #0\n\t" 9639 "MOV.lt $dst, #-1" %} 9640 ins_encode %{ 9641 __ cmp($p$$Register, $q$$Register); 9642 __ mov($dst$$Register, 0); 9643 __ mvn($dst$$Register, 0, lt); 9644 %} 9645 #endif 9646 ins_pipe(ialu_reg_reg_ialu); 9647 %} 9648 9649 instruct cmpLTMask_reg_imm( iRegI dst, iRegI p, aimmI q, flagsReg ccr ) %{ 9650 match(Set dst (CmpLTMask p q)); 9651 effect( KILL ccr ); 9652 #ifdef AARCH64 9653 size(8); 9654 ins_cost(DEFAULT_COST*2); 9655 format %{ "CMP_w $p,$q\n\t" 9656 "CSETM_w $dst, lt" %} 9657 ins_encode %{ 9658 __ cmp_w($p$$Register, $q$$constant); 9659 __ csetm_w($dst$$Register, lt); 9660 %} 9661 #else 9662 ins_cost(DEFAULT_COST*3); 9663 format %{ "CMP $p,$q\n\t" 9664 "MOV $dst, #0\n\t" 9665 "MOV.lt $dst, #-1" %} 9666 ins_encode %{ 9667 __ cmp($p$$Register, $q$$constant); 9668 __ mov($dst$$Register, 0); 9669 __ mvn($dst$$Register, 0, lt); 9670 %} 9671 #endif 9672 ins_pipe(ialu_reg_reg_ialu); 9673 %} 9674 9675 #ifdef AARCH64 9676 instruct cadd_cmpLTMask3( iRegI dst, iRegI p, iRegI q, iRegI y, iRegI x, flagsReg ccr ) %{ 9677 match(Set dst (AddI (AndI (CmpLTMask p q) y) x)); 9678 effect( TEMP dst, KILL ccr ); 9679 size(12); 9680 ins_cost(DEFAULT_COST*3); 9681 format %{ "CMP_w $p,$q\n\t" 9682 "ADD_w $dst,$y,$x\n\t" 9683 "CSEL_w $dst,$dst,$x,lt" %} 9684 ins_encode %{ 9685 __ cmp_w($p$$Register, $q$$Register); 9686 __ add_w($dst$$Register, $y$$Register, $x$$Register); 9687 __ csel_w($dst$$Register, $dst$$Register, $x$$Register, lt); 9688 %} 9689 ins_pipe( cadd_cmpltmask ); 9690 %} 9691 #else 9692 instruct cadd_cmpLTMask3( iRegI p, iRegI q, iRegI y, iRegI z, flagsReg ccr ) %{ 9693 match(Set z (AddI (AndI (CmpLTMask p q) y) z)); 9694 effect( KILL ccr ); 9695 ins_cost(DEFAULT_COST*2); 9696 format %{ "CMP $p,$q\n\t" 9697 "ADD.lt $z,$y,$z" %} 9698 ins_encode %{ 9699 __ cmp($p$$Register, $q$$Register); 9700 __ add($z$$Register, $y$$Register, $z$$Register, lt); 9701 %} 9702 ins_pipe( cadd_cmpltmask ); 9703 %} 9704 #endif 9705 9706 #ifdef AARCH64 9707 instruct cadd_cmpLTMask4( iRegI dst, iRegI p, aimmI q, iRegI y, iRegI x, flagsReg ccr ) %{ 9708 match(Set dst (AddI (AndI (CmpLTMask p q) y) x)); 9709 effect( TEMP dst, KILL ccr ); 9710 size(12); 9711 ins_cost(DEFAULT_COST*3); 9712 format %{ "CMP_w $p,$q\n\t" 9713 "ADD_w $dst,$y,$x\n\t" 9714 "CSEL_w $dst,$dst,$x,lt" %} 9715 ins_encode %{ 9716 __ cmp_w($p$$Register, $q$$constant); 9717 __ add_w($dst$$Register, $y$$Register, $x$$Register); 9718 __ csel_w($dst$$Register, $dst$$Register, $x$$Register, lt); 9719 %} 9720 ins_pipe( cadd_cmpltmask ); 9721 %} 9722 #else 9723 // FIXME: remove unused "dst" 9724 instruct cadd_cmpLTMask4( iRegI dst, iRegI p, aimmI q, iRegI y, iRegI z, flagsReg ccr ) %{ 9725 match(Set z (AddI (AndI (CmpLTMask p q) y) z)); 9726 effect( KILL ccr ); 9727 ins_cost(DEFAULT_COST*2); 9728 format %{ "CMP $p,$q\n\t" 9729 "ADD.lt $z,$y,$z" %} 9730 ins_encode %{ 9731 __ cmp($p$$Register, $q$$constant); 9732 __ add($z$$Register, $y$$Register, $z$$Register, lt); 9733 %} 9734 ins_pipe( cadd_cmpltmask ); 9735 %} 9736 #endif // !AARCH64 9737 9738 #ifdef AARCH64 9739 instruct cadd_cmpLTMask( iRegI dst, iRegI p, iRegI q, iRegI y, flagsReg ccr ) %{ 9740 match(Set dst (AddI (AndI (CmpLTMask p q) y) (SubI p q))); 9741 effect( TEMP dst, KILL ccr ); 9742 size(12); 9743 ins_cost(DEFAULT_COST*3); 9744 format %{ "SUBS_w $p,$p,$q\n\t" 9745 "ADD_w $dst,$y,$p\n\t" 9746 "CSEL_w $dst,$dst,$p,lt" %} 9747 ins_encode %{ 9748 __ subs_w($p$$Register, $p$$Register, $q$$Register); 9749 __ add_w($dst$$Register, $y$$Register, $p$$Register); 9750 __ csel_w($dst$$Register, $dst$$Register, $p$$Register, lt); 9751 %} 9752 ins_pipe( cadd_cmpltmask ); // FIXME 9753 %} 9754 #else 9755 instruct cadd_cmpLTMask( iRegI p, iRegI q, iRegI y, flagsReg ccr ) %{ 9756 match(Set p (AddI (AndI (CmpLTMask p q) y) (SubI p q))); 9757 effect( KILL ccr ); 9758 ins_cost(DEFAULT_COST*2); 9759 format %{ "SUBS $p,$p,$q\n\t" 9760 "ADD.lt $p,$y,$p" %} 9761 ins_encode %{ 9762 __ subs($p$$Register, $p$$Register, $q$$Register); 9763 __ add($p$$Register, $y$$Register, $p$$Register, lt); 9764 %} 9765 ins_pipe( cadd_cmpltmask ); 9766 %} 9767 #endif 9768 9769 //----------Arithmetic Conversion Instructions--------------------------------- 9770 // The conversions operations are all Alpha sorted. Please keep it that way! 9771 9772 instruct convD2F_reg(regF dst, regD src) %{ 9773 match(Set dst (ConvD2F src)); 9774 size(4); 9775 format %{ "FCVTSD $dst,$src" %} 9776 ins_encode %{ 9777 __ convert_d2f($dst$$FloatRegister, $src$$FloatRegister); 9778 %} 9779 ins_pipe(fcvtD2F); 9780 %} 9781 9782 // Convert a double to an int in a float register. 9783 // If the double is a NAN, stuff a zero in instead. 9784 9785 #ifdef AARCH64 9786 instruct convD2I_reg_reg(iRegI dst, regD src) %{ 9787 match(Set dst (ConvD2I src)); 9788 ins_cost(DEFAULT_COST*2 + MEMORY_REF_COST*2 + BRANCH_COST); // FIXME 9789 format %{ "FCVTZS_wd $dst, $src" %} 9790 ins_encode %{ 9791 __ fcvtzs_wd($dst$$Register, $src$$FloatRegister); 9792 %} 9793 ins_pipe(fcvtD2I); 9794 %} 9795 9796 instruct convD2L_reg_reg(iRegL dst, regD src) %{ 9797 match(Set dst (ConvD2L src)); 9798 ins_cost(DEFAULT_COST*2 + MEMORY_REF_COST*2 + BRANCH_COST); // FIXME 9799 format %{ "FCVTZS_xd $dst, $src" %} 9800 ins_encode %{ 9801 __ fcvtzs_xd($dst$$Register, $src$$FloatRegister); 9802 %} 9803 ins_pipe(fcvtD2L); 9804 %} 9805 #else 9806 instruct convD2I_reg_reg(iRegI dst, regD src, regF tmp) %{ 9807 match(Set dst (ConvD2I src)); 9808 effect( TEMP tmp ); 9809 ins_cost(DEFAULT_COST*2 + MEMORY_REF_COST*2 + BRANCH_COST); // FIXME 9810 format %{ "FTOSIZD $tmp,$src\n\t" 9811 "FMRS $dst, $tmp" %} 9812 ins_encode %{ 9813 __ ftosizd($tmp$$FloatRegister, $src$$FloatRegister); 9814 __ fmrs($dst$$Register, $tmp$$FloatRegister); 9815 %} 9816 ins_pipe(fcvtD2I); 9817 %} 9818 #endif 9819 9820 // Convert a double to a long in a double register. 9821 // If the double is a NAN, stuff a zero in instead. 9822 9823 #ifndef AARCH64 9824 // Double to Long conversion 9825 instruct convD2L_reg(R0R1RegL dst, regD src) %{ 9826 match(Set dst (ConvD2L src)); 9827 effect(CALL); 9828 ins_cost(MEMORY_REF_COST); // FIXME 9829 format %{ "convD2L $dst,$src\t ! call to SharedRuntime::d2l" %} 9830 ins_encode %{ 9831 #ifndef __ABI_HARD__ 9832 __ fmrrd($dst$$Register, $dst$$Register->successor(), $src$$FloatRegister); 9833 #else 9834 if ($src$$FloatRegister != D0) { 9835 __ mov_double(D0, $src$$FloatRegister); 9836 } 9837 #endif 9838 address target = CAST_FROM_FN_PTR(address, SharedRuntime::d2l); 9839 __ call(target, relocInfo::runtime_call_type); 9840 %} 9841 ins_pipe(fcvtD2L); 9842 %} 9843 #endif 9844 9845 instruct convF2D_reg(regD dst, regF src) %{ 9846 match(Set dst (ConvF2D src)); 9847 size(4); 9848 format %{ "FCVTDS $dst,$src" %} 9849 ins_encode %{ 9850 __ convert_f2d($dst$$FloatRegister, $src$$FloatRegister); 9851 %} 9852 ins_pipe(fcvtF2D); 9853 %} 9854 9855 #ifdef AARCH64 9856 instruct convF2I_reg_reg(iRegI dst, regF src) %{ 9857 match(Set dst (ConvF2I src)); 9858 ins_cost(DEFAULT_COST*2 + MEMORY_REF_COST*2 + BRANCH_COST); // FIXME 9859 size(4); 9860 format %{ "FCVTZS_ws $dst, $src" %} 9861 ins_encode %{ 9862 __ fcvtzs_ws($dst$$Register, $src$$FloatRegister); 9863 %} 9864 ins_pipe(fcvtF2I); 9865 %} 9866 9867 instruct convF2L_reg_reg(iRegL dst, regF src) %{ 9868 match(Set dst (ConvF2L src)); 9869 ins_cost(DEFAULT_COST*2 + MEMORY_REF_COST*2 + BRANCH_COST); // FIXME 9870 size(4); 9871 format %{ "FCVTZS_xs $dst, $src" %} 9872 ins_encode %{ 9873 __ fcvtzs_xs($dst$$Register, $src$$FloatRegister); 9874 %} 9875 ins_pipe(fcvtF2L); 9876 %} 9877 #else 9878 instruct convF2I_reg_reg(iRegI dst, regF src, regF tmp) %{ 9879 match(Set dst (ConvF2I src)); 9880 effect( TEMP tmp ); 9881 ins_cost(DEFAULT_COST*2 + MEMORY_REF_COST*2 + BRANCH_COST); // FIXME 9882 size(8); 9883 format %{ "FTOSIZS $tmp,$src\n\t" 9884 "FMRS $dst, $tmp" %} 9885 ins_encode %{ 9886 __ ftosizs($tmp$$FloatRegister, $src$$FloatRegister); 9887 __ fmrs($dst$$Register, $tmp$$FloatRegister); 9888 %} 9889 ins_pipe(fcvtF2I); 9890 %} 9891 9892 // Float to Long conversion 9893 instruct convF2L_reg(R0R1RegL dst, regF src, R0RegI arg1) %{ 9894 match(Set dst (ConvF2L src)); 9895 ins_cost(DEFAULT_COST*2 + MEMORY_REF_COST*2 + BRANCH_COST); // FIXME 9896 effect(CALL); 9897 format %{ "convF2L $dst,$src\t! call to SharedRuntime::f2l" %} 9898 ins_encode %{ 9899 #ifndef __ABI_HARD__ 9900 __ fmrs($arg1$$Register, $src$$FloatRegister); 9901 #else 9902 if($src$$FloatRegister != S0) { 9903 __ mov_float(S0, $src$$FloatRegister); 9904 } 9905 #endif 9906 address target = CAST_FROM_FN_PTR(address, SharedRuntime::f2l); 9907 __ call(target, relocInfo::runtime_call_type); 9908 %} 9909 ins_pipe(fcvtF2L); 9910 %} 9911 #endif 9912 9913 #ifdef AARCH64 9914 instruct convI2D_reg_reg(iRegI src, regD dst) %{ 9915 match(Set dst (ConvI2D src)); 9916 ins_cost(DEFAULT_COST + MEMORY_REF_COST); // FIXME 9917 size(4); 9918 format %{ "SCVTF_dw $dst,$src" %} 9919 ins_encode %{ 9920 __ scvtf_dw($dst$$FloatRegister, $src$$Register); 9921 %} 9922 ins_pipe(fcvtI2D); 9923 %} 9924 #else 9925 instruct convI2D_reg_reg(iRegI src, regD_low dst) %{ 9926 match(Set dst (ConvI2D src)); 9927 ins_cost(DEFAULT_COST + MEMORY_REF_COST); // FIXME 9928 size(8); 9929 format %{ "FMSR $dst,$src \n\t" 9930 "FSITOD $dst $dst"%} 9931 ins_encode %{ 9932 __ fmsr($dst$$FloatRegister, $src$$Register); 9933 __ fsitod($dst$$FloatRegister, $dst$$FloatRegister); 9934 %} 9935 ins_pipe(fcvtI2D); 9936 %} 9937 #endif 9938 9939 instruct convI2F_reg_reg( regF dst, iRegI src ) %{ 9940 match(Set dst (ConvI2F src)); 9941 ins_cost(DEFAULT_COST + MEMORY_REF_COST); // FIXME 9942 #ifdef AARCH64 9943 size(4); 9944 format %{ "SCVTF_sw $dst,$src" %} 9945 ins_encode %{ 9946 __ scvtf_sw($dst$$FloatRegister, $src$$Register); 9947 %} 9948 #else 9949 size(8); 9950 format %{ "FMSR $dst,$src \n\t" 9951 "FSITOS $dst, $dst"%} 9952 ins_encode %{ 9953 __ fmsr($dst$$FloatRegister, $src$$Register); 9954 __ fsitos($dst$$FloatRegister, $dst$$FloatRegister); 9955 %} 9956 #endif 9957 ins_pipe(fcvtI2F); 9958 %} 9959 9960 instruct convI2L_reg(iRegL dst, iRegI src) %{ 9961 match(Set dst (ConvI2L src)); 9962 #ifdef AARCH64 9963 size(4); 9964 format %{ "SXTW $dst,$src\t! int->long" %} 9965 ins_encode %{ 9966 __ sxtw($dst$$Register, $src$$Register); 9967 %} 9968 #else 9969 size(8); 9970 format %{ "MOV $dst.lo, $src \n\t" 9971 "ASR $dst.hi,$src,31\t! int->long" %} 9972 ins_encode %{ 9973 __ mov($dst$$Register, $src$$Register); 9974 __ mov($dst$$Register->successor(), AsmOperand($src$$Register, asr, 31)); 9975 %} 9976 #endif 9977 ins_pipe(ialu_reg_reg); 9978 %} 9979 9980 // Zero-extend convert int to long 9981 instruct convI2L_reg_zex(iRegL dst, iRegI src, immL_32bits mask ) %{ 9982 match(Set dst (AndL (ConvI2L src) mask) ); 9983 #ifdef AARCH64 9984 size(4); 9985 format %{ "mov_w $dst,$src\t! zero-extend int to long" %} 9986 ins_encode %{ 9987 __ mov_w($dst$$Register, $src$$Register); 9988 %} 9989 #else 9990 size(8); 9991 format %{ "MOV $dst.lo,$src.lo\t! zero-extend int to long\n\t" 9992 "MOV $dst.hi, 0"%} 9993 ins_encode %{ 9994 __ mov($dst$$Register, $src$$Register); 9995 __ mov($dst$$Register->successor(), 0); 9996 %} 9997 #endif 9998 ins_pipe(ialu_reg_reg); 9999 %} 10000 10001 // Zero-extend long 10002 instruct zerox_long(iRegL dst, iRegL src, immL_32bits mask ) %{ 10003 match(Set dst (AndL src mask) ); 10004 #ifdef AARCH64 10005 size(4); 10006 format %{ "mov_w $dst,$src\t! zero-extend long" %} 10007 ins_encode %{ 10008 __ mov_w($dst$$Register, $src$$Register); 10009 %} 10010 #else 10011 size(8); 10012 format %{ "MOV $dst.lo,$src.lo\t! zero-extend long\n\t" 10013 "MOV $dst.hi, 0"%} 10014 ins_encode %{ 10015 __ mov($dst$$Register, $src$$Register); 10016 __ mov($dst$$Register->successor(), 0); 10017 %} 10018 #endif 10019 ins_pipe(ialu_reg_reg); 10020 %} 10021 10022 instruct MoveF2I_reg_reg(iRegI dst, regF src) %{ 10023 match(Set dst (MoveF2I src)); 10024 effect(DEF dst, USE src); 10025 ins_cost(MEMORY_REF_COST); // FIXME 10026 10027 size(4); 10028 format %{ "FMRS $dst,$src\t! MoveF2I" %} 10029 ins_encode %{ 10030 __ fmrs($dst$$Register, $src$$FloatRegister); 10031 %} 10032 ins_pipe(iload_mem); // FIXME 10033 %} 10034 10035 instruct MoveI2F_reg_reg(regF dst, iRegI src) %{ 10036 match(Set dst (MoveI2F src)); 10037 ins_cost(MEMORY_REF_COST); // FIXME 10038 10039 size(4); 10040 format %{ "FMSR $dst,$src\t! MoveI2F" %} 10041 ins_encode %{ 10042 __ fmsr($dst$$FloatRegister, $src$$Register); 10043 %} 10044 ins_pipe(iload_mem); // FIXME 10045 %} 10046 10047 instruct MoveD2L_reg_reg(iRegL dst, regD src) %{ 10048 match(Set dst (MoveD2L src)); 10049 effect(DEF dst, USE src); 10050 ins_cost(MEMORY_REF_COST); // FIXME 10051 10052 size(4); 10053 #ifdef AARCH64 10054 format %{ "FMOV_xd $dst,$src\t! MoveD2L" %} 10055 ins_encode %{ 10056 __ fmov_xd($dst$$Register, $src$$FloatRegister); 10057 %} 10058 #else 10059 format %{ "FMRRD $dst,$src\t! MoveD2L" %} 10060 ins_encode %{ 10061 __ fmrrd($dst$$Register, $dst$$Register->successor(), $src$$FloatRegister); 10062 %} 10063 #endif 10064 ins_pipe(iload_mem); // FIXME 10065 %} 10066 10067 instruct MoveL2D_reg_reg(regD dst, iRegL src) %{ 10068 match(Set dst (MoveL2D src)); 10069 effect(DEF dst, USE src); 10070 ins_cost(MEMORY_REF_COST); // FIXME 10071 10072 size(4); 10073 #ifdef AARCH64 10074 format %{ "FMOV_dx $dst,$src\t! MoveL2D" %} 10075 ins_encode %{ 10076 __ fmov_dx($dst$$FloatRegister, $src$$Register); 10077 %} 10078 #else 10079 format %{ "FMDRR $dst,$src\t! MoveL2D" %} 10080 ins_encode %{ 10081 __ fmdrr($dst$$FloatRegister, $src$$Register, $src$$Register->successor()); 10082 %} 10083 #endif 10084 ins_pipe(ialu_reg_reg); // FIXME 10085 %} 10086 10087 //----------- 10088 // Long to Double conversion 10089 10090 #ifdef AARCH64 10091 instruct convL2D(regD dst, iRegL src) %{ 10092 match(Set dst (ConvL2D src)); 10093 ins_cost(DEFAULT_COST*2 + MEMORY_REF_COST*2 + BRANCH_COST); // FIXME 10094 size(4); 10095 format %{ "SCVTF_dx $dst, $src" %} 10096 ins_encode %{ 10097 __ scvtf_dx($dst$$FloatRegister, $src$$Register); 10098 %} 10099 ins_pipe(fcvtL2D); 10100 %} 10101 10102 instruct convL2F(regF dst, iRegL src) %{ 10103 match(Set dst (ConvL2F src)); 10104 ins_cost(DEFAULT_COST*2 + MEMORY_REF_COST*2 + BRANCH_COST); // FIXME 10105 size(4); 10106 format %{ "SCVTF_sx $dst, $src" %} 10107 ins_encode %{ 10108 __ scvtf_sx($dst$$FloatRegister, $src$$Register); 10109 %} 10110 ins_pipe(fcvtL2F); 10111 %} 10112 #else 10113 // Magic constant, 0x43300000 10114 instruct loadConI_x43300000(iRegI dst) %{ 10115 effect(DEF dst); 10116 size(8); 10117 format %{ "MOV_SLOW $dst,0x43300000\t! 2^52" %} 10118 ins_encode %{ 10119 __ mov_slow($dst$$Register, 0x43300000); 10120 %} 10121 ins_pipe(ialu_none); 10122 %} 10123 10124 // Magic constant, 0x41f00000 10125 instruct loadConI_x41f00000(iRegI dst) %{ 10126 effect(DEF dst); 10127 size(8); 10128 format %{ "MOV_SLOW $dst, 0x41f00000\t! 2^32" %} 10129 ins_encode %{ 10130 __ mov_slow($dst$$Register, 0x41f00000); 10131 %} 10132 ins_pipe(ialu_none); 10133 %} 10134 10135 instruct loadConI_x0(iRegI dst) %{ 10136 effect(DEF dst); 10137 size(4); 10138 format %{ "MOV $dst, 0x0\t! 0" %} 10139 ins_encode %{ 10140 __ mov($dst$$Register, 0); 10141 %} 10142 ins_pipe(ialu_none); 10143 %} 10144 10145 // Construct a double from two float halves 10146 instruct regDHi_regDLo_to_regD(regD_low dst, regD_low src1, regD_low src2) %{ 10147 effect(DEF dst, USE src1, USE src2); 10148 size(8); 10149 format %{ "FCPYS $dst.hi,$src1.hi\n\t" 10150 "FCPYS $dst.lo,$src2.lo" %} 10151 ins_encode %{ 10152 __ fcpys($dst$$FloatRegister->successor(), $src1$$FloatRegister->successor()); 10153 __ fcpys($dst$$FloatRegister, $src2$$FloatRegister); 10154 %} 10155 ins_pipe(faddD_reg_reg); 10156 %} 10157 10158 #ifndef AARCH64 10159 // Convert integer in high half of a double register (in the lower half of 10160 // the double register file) to double 10161 instruct convI2D_regDHi_regD(regD dst, regD_low src) %{ 10162 effect(DEF dst, USE src); 10163 size(4); 10164 format %{ "FSITOD $dst,$src" %} 10165 ins_encode %{ 10166 __ fsitod($dst$$FloatRegister, $src$$FloatRegister->successor()); 10167 %} 10168 ins_pipe(fcvtLHi2D); 10169 %} 10170 #endif 10171 10172 // Add float double precision 10173 instruct addD_regD_regD(regD dst, regD src1, regD src2) %{ 10174 effect(DEF dst, USE src1, USE src2); 10175 size(4); 10176 format %{ "FADDD $dst,$src1,$src2" %} 10177 ins_encode %{ 10178 __ add_double($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister); 10179 %} 10180 ins_pipe(faddD_reg_reg); 10181 %} 10182 10183 // Sub float double precision 10184 instruct subD_regD_regD(regD dst, regD src1, regD src2) %{ 10185 effect(DEF dst, USE src1, USE src2); 10186 size(4); 10187 format %{ "FSUBD $dst,$src1,$src2" %} 10188 ins_encode %{ 10189 __ sub_double($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister); 10190 %} 10191 ins_pipe(faddD_reg_reg); 10192 %} 10193 10194 // Mul float double precision 10195 instruct mulD_regD_regD(regD dst, regD src1, regD src2) %{ 10196 effect(DEF dst, USE src1, USE src2); 10197 size(4); 10198 format %{ "FMULD $dst,$src1,$src2" %} 10199 ins_encode %{ 10200 __ mul_double($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister); 10201 %} 10202 ins_pipe(fmulD_reg_reg); 10203 %} 10204 10205 instruct regL_to_regD(regD dst, iRegL src) %{ 10206 // No match rule to avoid chain rule match. 10207 effect(DEF dst, USE src); 10208 ins_cost(MEMORY_REF_COST); 10209 size(4); 10210 format %{ "FMDRR $dst,$src\t! regL to regD" %} 10211 ins_encode %{ 10212 __ fmdrr($dst$$FloatRegister, $src$$Register, $src$$Register->successor()); 10213 %} 10214 ins_pipe(ialu_reg_reg); // FIXME 10215 %} 10216 10217 instruct regI_regI_to_regD(regD dst, iRegI src1, iRegI src2) %{ 10218 // No match rule to avoid chain rule match. 10219 effect(DEF dst, USE src1, USE src2); 10220 ins_cost(MEMORY_REF_COST); 10221 size(4); 10222 format %{ "FMDRR $dst,$src1,$src2\t! regI,regI to regD" %} 10223 ins_encode %{ 10224 __ fmdrr($dst$$FloatRegister, $src1$$Register, $src2$$Register); 10225 %} 10226 ins_pipe(ialu_reg_reg); // FIXME 10227 %} 10228 10229 instruct convL2D_reg_slow_fxtof(regD dst, iRegL src) %{ 10230 match(Set dst (ConvL2D src)); 10231 ins_cost(DEFAULT_COST*8 + MEMORY_REF_COST*6); // FIXME 10232 10233 expand %{ 10234 regD_low tmpsrc; 10235 iRegI ix43300000; 10236 iRegI ix41f00000; 10237 iRegI ix0; 10238 regD_low dx43300000; 10239 regD dx41f00000; 10240 regD tmp1; 10241 regD_low tmp2; 10242 regD tmp3; 10243 regD tmp4; 10244 10245 regL_to_regD(tmpsrc, src); 10246 10247 loadConI_x43300000(ix43300000); 10248 loadConI_x41f00000(ix41f00000); 10249 loadConI_x0(ix0); 10250 10251 regI_regI_to_regD(dx43300000, ix0, ix43300000); 10252 regI_regI_to_regD(dx41f00000, ix0, ix41f00000); 10253 10254 convI2D_regDHi_regD(tmp1, tmpsrc); 10255 regDHi_regDLo_to_regD(tmp2, dx43300000, tmpsrc); 10256 subD_regD_regD(tmp3, tmp2, dx43300000); 10257 mulD_regD_regD(tmp4, tmp1, dx41f00000); 10258 addD_regD_regD(dst, tmp3, tmp4); 10259 %} 10260 %} 10261 #endif // !AARCH64 10262 10263 instruct convL2I_reg(iRegI dst, iRegL src) %{ 10264 match(Set dst (ConvL2I src)); 10265 size(4); 10266 #ifdef AARCH64 10267 format %{ "MOV_w $dst,$src\t! long->int" %} 10268 ins_encode %{ 10269 __ mov_w($dst$$Register, $src$$Register); 10270 %} 10271 #else 10272 format %{ "MOV $dst,$src.lo\t! long->int" %} 10273 ins_encode %{ 10274 __ mov($dst$$Register, $src$$Register); 10275 %} 10276 #endif 10277 ins_pipe(ialu_move_reg_I_to_L); 10278 %} 10279 10280 #ifndef AARCH64 10281 // Register Shift Right Immediate 10282 instruct shrL_reg_imm6_L2I(iRegI dst, iRegL src, immI_32_63 cnt) %{ 10283 match(Set dst (ConvL2I (RShiftL src cnt))); 10284 size(4); 10285 format %{ "ASR $dst,$src.hi,($cnt - 32)\t! long->int or mov if $cnt==32" %} 10286 ins_encode %{ 10287 if ($cnt$$constant == 32) { 10288 __ mov($dst$$Register, $src$$Register->successor()); 10289 } else { 10290 __ mov($dst$$Register, AsmOperand($src$$Register->successor(), asr, $cnt$$constant - 32)); 10291 } 10292 %} 10293 ins_pipe(ialu_reg_imm); 10294 %} 10295 #endif 10296 10297 10298 //----------Control Flow Instructions------------------------------------------ 10299 // Compare Instructions 10300 // Compare Integers 10301 instruct compI_iReg(flagsReg icc, iRegI op1, iRegI op2) %{ 10302 match(Set icc (CmpI op1 op2)); 10303 effect( DEF icc, USE op1, USE op2 ); 10304 10305 size(4); 10306 format %{ "cmp_32 $op1,$op2\t! int" %} 10307 ins_encode %{ 10308 __ cmp_32($op1$$Register, $op2$$Register); 10309 %} 10310 ins_pipe(ialu_cconly_reg_reg); 10311 %} 10312 10313 #ifdef _LP64 10314 // Compare compressed pointers 10315 instruct compN_reg2(flagsRegU icc, iRegN op1, iRegN op2) %{ 10316 match(Set icc (CmpN op1 op2)); 10317 effect( DEF icc, USE op1, USE op2 ); 10318 10319 size(4); 10320 format %{ "cmp_32 $op1,$op2\t! int" %} 10321 ins_encode %{ 10322 __ cmp_32($op1$$Register, $op2$$Register); 10323 %} 10324 ins_pipe(ialu_cconly_reg_reg); 10325 %} 10326 #endif 10327 10328 instruct compU_iReg(flagsRegU icc, iRegI op1, iRegI op2) %{ 10329 match(Set icc (CmpU op1 op2)); 10330 10331 size(4); 10332 format %{ "cmp_32 $op1,$op2\t! unsigned int" %} 10333 ins_encode %{ 10334 __ cmp_32($op1$$Register, $op2$$Register); 10335 %} 10336 ins_pipe(ialu_cconly_reg_reg); 10337 %} 10338 10339 instruct compI_iReg_immneg(flagsReg icc, iRegI op1, aimmIneg op2) %{ 10340 match(Set icc (CmpI op1 op2)); 10341 effect( DEF icc, USE op1 ); 10342 10343 size(4); 10344 format %{ "cmn_32 $op1,-$op2\t! int" %} 10345 ins_encode %{ 10346 __ cmn_32($op1$$Register, -$op2$$constant); 10347 %} 10348 ins_pipe(ialu_cconly_reg_imm); 10349 %} 10350 10351 instruct compI_iReg_imm(flagsReg icc, iRegI op1, aimmI op2) %{ 10352 match(Set icc (CmpI op1 op2)); 10353 effect( DEF icc, USE op1 ); 10354 10355 size(4); 10356 format %{ "cmp_32 $op1,$op2\t! int" %} 10357 ins_encode %{ 10358 __ cmp_32($op1$$Register, $op2$$constant); 10359 %} 10360 ins_pipe(ialu_cconly_reg_imm); 10361 %} 10362 10363 instruct testI_reg_reg( flagsReg_EQNELTGE icc, iRegI op1, iRegI op2, immI0 zero ) %{ 10364 match(Set icc (CmpI (AndI op1 op2) zero)); 10365 size(4); 10366 format %{ "tst_32 $op2,$op1" %} 10367 10368 ins_encode %{ 10369 __ tst_32($op1$$Register, $op2$$Register); 10370 %} 10371 ins_pipe(ialu_cconly_reg_reg_zero); 10372 %} 10373 10374 #ifndef AARCH64 10375 instruct testshlI_reg_reg_reg( flagsReg_EQNELTGE icc, iRegI op1, iRegI op2, iRegI op3, immI0 zero ) %{ 10376 match(Set icc (CmpI (AndI op1 (LShiftI op2 op3)) zero)); 10377 size(4); 10378 format %{ "TST $op2,$op1<<$op3" %} 10379 10380 ins_encode %{ 10381 __ tst($op1$$Register, AsmOperand($op2$$Register, lsl, $op3$$Register)); 10382 %} 10383 ins_pipe(ialu_cconly_reg_reg_zero); 10384 %} 10385 #endif 10386 10387 instruct testshlI_reg_reg_imm( flagsReg_EQNELTGE icc, iRegI op1, iRegI op2, immU5 op3, immI0 zero ) %{ 10388 match(Set icc (CmpI (AndI op1 (LShiftI op2 op3)) zero)); 10389 size(4); 10390 format %{ "tst_32 $op2,$op1<<$op3" %} 10391 10392 ins_encode %{ 10393 __ tst_32($op1$$Register, AsmOperand($op2$$Register, lsl, $op3$$constant)); 10394 %} 10395 ins_pipe(ialu_cconly_reg_reg_zero); 10396 %} 10397 10398 #ifndef AARCH64 10399 instruct testsarI_reg_reg_reg( flagsReg_EQNELTGE icc, iRegI op1, iRegI op2, iRegI op3, immI0 zero ) %{ 10400 match(Set icc (CmpI (AndI op1 (RShiftI op2 op3)) zero)); 10401 size(4); 10402 format %{ "TST $op2,$op1<<$op3" %} 10403 10404 ins_encode %{ 10405 __ tst($op1$$Register, AsmOperand($op2$$Register, asr, $op3$$Register)); 10406 %} 10407 ins_pipe(ialu_cconly_reg_reg_zero); 10408 %} 10409 #endif 10410 10411 instruct testsarI_reg_reg_imm( flagsReg_EQNELTGE icc, iRegI op1, iRegI op2, immU5 op3, immI0 zero ) %{ 10412 match(Set icc (CmpI (AndI op1 (RShiftI op2 op3)) zero)); 10413 size(4); 10414 format %{ "tst_32 $op2,$op1<<$op3" %} 10415 10416 ins_encode %{ 10417 __ tst_32($op1$$Register, AsmOperand($op2$$Register, asr, $op3$$constant)); 10418 %} 10419 ins_pipe(ialu_cconly_reg_reg_zero); 10420 %} 10421 10422 #ifndef AARCH64 10423 instruct testshrI_reg_reg_reg( flagsReg_EQNELTGE icc, iRegI op1, iRegI op2, iRegI op3, immI0 zero ) %{ 10424 match(Set icc (CmpI (AndI op1 (URShiftI op2 op3)) zero)); 10425 size(4); 10426 format %{ "TST $op2,$op1<<$op3" %} 10427 10428 ins_encode %{ 10429 __ tst($op1$$Register, AsmOperand($op2$$Register, lsr, $op3$$Register)); 10430 %} 10431 ins_pipe(ialu_cconly_reg_reg_zero); 10432 %} 10433 #endif 10434 10435 instruct testshrI_reg_reg_imm( flagsReg_EQNELTGE icc, iRegI op1, iRegI op2, immU5 op3, immI0 zero ) %{ 10436 match(Set icc (CmpI (AndI op1 (URShiftI op2 op3)) zero)); 10437 size(4); 10438 format %{ "tst_32 $op2,$op1<<$op3" %} 10439 10440 ins_encode %{ 10441 __ tst_32($op1$$Register, AsmOperand($op2$$Register, lsr, $op3$$constant)); 10442 %} 10443 ins_pipe(ialu_cconly_reg_reg_zero); 10444 %} 10445 10446 instruct testI_reg_imm( flagsReg_EQNELTGE icc, iRegI op1, limmI op2, immI0 zero ) %{ 10447 match(Set icc (CmpI (AndI op1 op2) zero)); 10448 size(4); 10449 format %{ "tst_32 $op2,$op1" %} 10450 10451 ins_encode %{ 10452 __ tst_32($op1$$Register, $op2$$constant); 10453 %} 10454 ins_pipe(ialu_cconly_reg_imm_zero); 10455 %} 10456 10457 #ifdef AARCH64 10458 instruct compL_reg_reg(flagsReg xcc, iRegL op1, iRegL op2) 10459 %{ 10460 match(Set xcc (CmpL op1 op2)); 10461 effect( DEF xcc, USE op1, USE op2 ); 10462 10463 size(4); 10464 format %{ "CMP $op1,$op2\t! long" %} 10465 ins_encode %{ 10466 __ cmp($op1$$Register, $op2$$Register); 10467 %} 10468 ins_pipe(ialu_cconly_reg_reg); 10469 %} 10470 #else 10471 instruct compL_reg_reg_LTGE(flagsRegL_LTGE xcc, iRegL op1, iRegL op2, iRegL tmp) %{ 10472 match(Set xcc (CmpL op1 op2)); 10473 effect( DEF xcc, USE op1, USE op2, TEMP tmp ); 10474 10475 size(8); 10476 format %{ "SUBS $tmp,$op1.low,$op2.low\t\t! long\n\t" 10477 "SBCS $tmp,$op1.hi,$op2.hi" %} 10478 ins_encode %{ 10479 __ subs($tmp$$Register, $op1$$Register, $op2$$Register); 10480 __ sbcs($tmp$$Register->successor(), $op1$$Register->successor(), $op2$$Register->successor()); 10481 %} 10482 ins_pipe(ialu_cconly_reg_reg); 10483 %} 10484 #endif 10485 10486 #ifdef AARCH64 10487 instruct compL_reg_con(flagsReg xcc, iRegL op1, aimmL con) %{ 10488 match(Set xcc (CmpL op1 con)); 10489 effect( DEF xcc, USE op1, USE con ); 10490 10491 size(8); 10492 format %{ "CMP $op1,$con\t\t! long" %} 10493 ins_encode %{ 10494 __ cmp($op1$$Register, $con$$constant); 10495 %} 10496 10497 ins_pipe(ialu_cconly_reg_imm); 10498 %} 10499 #else 10500 instruct compL_reg_reg_EQNE(flagsRegL_EQNE xcc, iRegL op1, iRegL op2) %{ 10501 match(Set xcc (CmpL op1 op2)); 10502 effect( DEF xcc, USE op1, USE op2 ); 10503 10504 size(8); 10505 format %{ "TEQ $op1.hi,$op2.hi\t\t! long\n\t" 10506 "TEQ.eq $op1.lo,$op2.lo" %} 10507 ins_encode %{ 10508 __ teq($op1$$Register->successor(), $op2$$Register->successor()); 10509 __ teq($op1$$Register, $op2$$Register, eq); 10510 %} 10511 ins_pipe(ialu_cconly_reg_reg); 10512 %} 10513 10514 instruct compL_reg_reg_LEGT(flagsRegL_LEGT xcc, iRegL op1, iRegL op2, iRegL tmp) %{ 10515 match(Set xcc (CmpL op1 op2)); 10516 effect( DEF xcc, USE op1, USE op2, TEMP tmp ); 10517 10518 size(8); 10519 format %{ "SUBS $tmp,$op2.low,$op1.low\t\t! long\n\t" 10520 "SBCS $tmp,$op2.hi,$op1.hi" %} 10521 ins_encode %{ 10522 __ subs($tmp$$Register, $op2$$Register, $op1$$Register); 10523 __ sbcs($tmp$$Register->successor(), $op2$$Register->successor(), $op1$$Register->successor()); 10524 %} 10525 ins_pipe(ialu_cconly_reg_reg); 10526 %} 10527 10528 // TODO: try immLRot2 instead, (0, $con$$constant) becomes 10529 // (hi($con$$constant), lo($con$$constant)) becomes 10530 instruct compL_reg_con_LTGE(flagsRegL_LTGE xcc, iRegL op1, immLlowRot con, iRegL tmp) %{ 10531 match(Set xcc (CmpL op1 con)); 10532 effect( DEF xcc, USE op1, USE con, TEMP tmp ); 10533 10534 size(8); 10535 format %{ "SUBS $tmp,$op1.low,$con\t\t! long\n\t" 10536 "SBCS $tmp,$op1.hi,0" %} 10537 ins_encode %{ 10538 __ subs($tmp$$Register, $op1$$Register, $con$$constant); 10539 __ sbcs($tmp$$Register->successor(), $op1$$Register->successor(), 0); 10540 %} 10541 10542 ins_pipe(ialu_cconly_reg_reg); 10543 %} 10544 10545 // TODO: try immLRot2 instead, (0, $con$$constant) becomes 10546 // (hi($con$$constant), lo($con$$constant)) becomes 10547 instruct compL_reg_con_EQNE(flagsRegL_EQNE xcc, iRegL op1, immLlowRot con) %{ 10548 match(Set xcc (CmpL op1 con)); 10549 effect( DEF xcc, USE op1, USE con ); 10550 10551 size(8); 10552 format %{ "TEQ $op1.hi,0\t\t! long\n\t" 10553 "TEQ.eq $op1.lo,$con" %} 10554 ins_encode %{ 10555 __ teq($op1$$Register->successor(), 0); 10556 __ teq($op1$$Register, $con$$constant, eq); 10557 %} 10558 10559 ins_pipe(ialu_cconly_reg_reg); 10560 %} 10561 10562 // TODO: try immLRot2 instead, (0, $con$$constant) becomes 10563 // (hi($con$$constant), lo($con$$constant)) becomes 10564 instruct compL_reg_con_LEGT(flagsRegL_LEGT xcc, iRegL op1, immLlowRot con, iRegL tmp) %{ 10565 match(Set xcc (CmpL op1 con)); 10566 effect( DEF xcc, USE op1, USE con, TEMP tmp ); 10567 10568 size(8); 10569 format %{ "RSBS $tmp,$op1.low,$con\t\t! long\n\t" 10570 "RSCS $tmp,$op1.hi,0" %} 10571 ins_encode %{ 10572 __ rsbs($tmp$$Register, $op1$$Register, $con$$constant); 10573 __ rscs($tmp$$Register->successor(), $op1$$Register->successor(), 0); 10574 %} 10575 10576 ins_pipe(ialu_cconly_reg_reg); 10577 %} 10578 #endif 10579 10580 /* instruct testL_reg_reg(flagsRegL xcc, iRegL op1, iRegL op2, immL0 zero) %{ */ 10581 /* match(Set xcc (CmpL (AndL op1 op2) zero)); */ 10582 /* ins_encode %{ */ 10583 /* __ stop("testL_reg_reg unimplemented"); */ 10584 /* %} */ 10585 /* ins_pipe(ialu_cconly_reg_reg); */ 10586 /* %} */ 10587 10588 /* // useful for checking the alignment of a pointer: */ 10589 /* instruct testL_reg_con(flagsRegL xcc, iRegL op1, immLlowRot con, immL0 zero) %{ */ 10590 /* match(Set xcc (CmpL (AndL op1 con) zero)); */ 10591 /* ins_encode %{ */ 10592 /* __ stop("testL_reg_con unimplemented"); */ 10593 /* %} */ 10594 /* ins_pipe(ialu_cconly_reg_reg); */ 10595 /* %} */ 10596 10597 instruct compU_iReg_imm(flagsRegU icc, iRegI op1, aimmU31 op2 ) %{ 10598 match(Set icc (CmpU op1 op2)); 10599 10600 size(4); 10601 format %{ "cmp_32 $op1,$op2\t! unsigned" %} 10602 ins_encode %{ 10603 __ cmp_32($op1$$Register, $op2$$constant); 10604 %} 10605 ins_pipe(ialu_cconly_reg_imm); 10606 %} 10607 10608 // Compare Pointers 10609 instruct compP_iRegP(flagsRegP pcc, iRegP op1, iRegP op2 ) %{ 10610 match(Set pcc (CmpP op1 op2)); 10611 10612 size(4); 10613 format %{ "CMP $op1,$op2\t! ptr" %} 10614 ins_encode %{ 10615 __ cmp($op1$$Register, $op2$$Register); 10616 %} 10617 ins_pipe(ialu_cconly_reg_reg); 10618 %} 10619 10620 instruct compP_iRegP_imm(flagsRegP pcc, iRegP op1, aimmP op2 ) %{ 10621 match(Set pcc (CmpP op1 op2)); 10622 10623 size(4); 10624 format %{ "CMP $op1,$op2\t! ptr" %} 10625 ins_encode %{ 10626 assert($op2$$constant == 0 || _opnds[2]->constant_reloc() == relocInfo::none, "reloc in cmp?"); 10627 __ cmp($op1$$Register, $op2$$constant); 10628 %} 10629 ins_pipe(ialu_cconly_reg_imm); 10630 %} 10631 10632 //----------Max and Min-------------------------------------------------------- 10633 // Min Instructions 10634 // Conditional move for min 10635 instruct cmovI_reg_lt( iRegI op2, iRegI op1, flagsReg icc ) %{ 10636 effect( USE_DEF op2, USE op1, USE icc ); 10637 10638 size(4); 10639 format %{ "MOV.lt $op2,$op1\t! min" %} 10640 ins_encode %{ 10641 __ mov($op2$$Register, $op1$$Register, lt); 10642 %} 10643 ins_pipe(ialu_reg_flags); 10644 %} 10645 10646 // Min Register with Register. 10647 instruct minI_eReg(iRegI op1, iRegI op2) %{ 10648 match(Set op2 (MinI op1 op2)); 10649 ins_cost(DEFAULT_COST*2); 10650 expand %{ 10651 flagsReg icc; 10652 compI_iReg(icc,op1,op2); 10653 cmovI_reg_lt(op2,op1,icc); 10654 %} 10655 %} 10656 10657 // Max Instructions 10658 // Conditional move for max 10659 instruct cmovI_reg_gt( iRegI op2, iRegI op1, flagsReg icc ) %{ 10660 effect( USE_DEF op2, USE op1, USE icc ); 10661 format %{ "MOV.gt $op2,$op1\t! max" %} 10662 ins_encode %{ 10663 __ mov($op2$$Register, $op1$$Register, gt); 10664 %} 10665 ins_pipe(ialu_reg_flags); 10666 %} 10667 10668 // Max Register with Register 10669 instruct maxI_eReg(iRegI op1, iRegI op2) %{ 10670 match(Set op2 (MaxI op1 op2)); 10671 ins_cost(DEFAULT_COST*2); 10672 expand %{ 10673 flagsReg icc; 10674 compI_iReg(icc,op1,op2); 10675 cmovI_reg_gt(op2,op1,icc); 10676 %} 10677 %} 10678 10679 10680 //----------Float Compares---------------------------------------------------- 10681 // Compare floating, generate condition code 10682 instruct cmpF_cc(flagsRegF fcc, flagsReg icc, regF src1, regF src2) %{ 10683 match(Set icc (CmpF src1 src2)); 10684 effect(KILL fcc); 10685 10686 #ifdef AARCH64 10687 size(4); 10688 format %{ "FCMP_s $src1,$src2" %} 10689 ins_encode %{ 10690 __ fcmp_s($src1$$FloatRegister, $src2$$FloatRegister); 10691 %} 10692 #else 10693 size(8); 10694 format %{ "FCMPs $src1,$src2\n\t" 10695 "FMSTAT" %} 10696 ins_encode %{ 10697 __ fcmps($src1$$FloatRegister, $src2$$FloatRegister); 10698 __ fmstat(); 10699 %} 10700 #endif 10701 ins_pipe(faddF_fcc_reg_reg_zero); 10702 %} 10703 10704 instruct cmpF0_cc(flagsRegF fcc, flagsReg icc, regF src1, immF0 src2) %{ 10705 match(Set icc (CmpF src1 src2)); 10706 effect(KILL fcc); 10707 10708 #ifdef AARCH64 10709 size(4); 10710 format %{ "FCMP0_s $src1" %} 10711 ins_encode %{ 10712 __ fcmp0_s($src1$$FloatRegister); 10713 %} 10714 #else 10715 size(8); 10716 format %{ "FCMPs $src1,$src2\n\t" 10717 "FMSTAT" %} 10718 ins_encode %{ 10719 __ fcmpzs($src1$$FloatRegister); 10720 __ fmstat(); 10721 %} 10722 #endif 10723 ins_pipe(faddF_fcc_reg_reg_zero); 10724 %} 10725 10726 instruct cmpD_cc(flagsRegF fcc, flagsReg icc, regD src1, regD src2) %{ 10727 match(Set icc (CmpD src1 src2)); 10728 effect(KILL fcc); 10729 10730 #ifdef AARCH64 10731 size(4); 10732 format %{ "FCMP_d $src1,$src2" %} 10733 ins_encode %{ 10734 __ fcmp_d($src1$$FloatRegister, $src2$$FloatRegister); 10735 %} 10736 #else 10737 size(8); 10738 format %{ "FCMPd $src1,$src2 \n\t" 10739 "FMSTAT" %} 10740 ins_encode %{ 10741 __ fcmpd($src1$$FloatRegister, $src2$$FloatRegister); 10742 __ fmstat(); 10743 %} 10744 #endif 10745 ins_pipe(faddD_fcc_reg_reg_zero); 10746 %} 10747 10748 instruct cmpD0_cc(flagsRegF fcc, flagsReg icc, regD src1, immD0 src2) %{ 10749 match(Set icc (CmpD src1 src2)); 10750 effect(KILL fcc); 10751 10752 #ifdef AARCH64 10753 size(8); 10754 format %{ "FCMP0_d $src1" %} 10755 ins_encode %{ 10756 __ fcmp0_d($src1$$FloatRegister); 10757 %} 10758 #else 10759 size(8); 10760 format %{ "FCMPZd $src1,$src2 \n\t" 10761 "FMSTAT" %} 10762 ins_encode %{ 10763 __ fcmpzd($src1$$FloatRegister); 10764 __ fmstat(); 10765 %} 10766 #endif 10767 ins_pipe(faddD_fcc_reg_reg_zero); 10768 %} 10769 10770 #ifdef AARCH64 10771 // Compare floating, generate -1,0,1 10772 instruct cmpF_reg(iRegI dst, regF src1, regF src2, flagsReg icc) %{ 10773 match(Set dst (CmpF3 src1 src2)); 10774 // effect(KILL fcc); // nobody cares if flagsRegF is killed 10775 effect(KILL icc); 10776 ins_cost(DEFAULT_COST*3); // FIXME 10777 size(12); 10778 format %{ "FCMP_s $src1,$src2\n\t" 10779 "CSET $dst, gt\n\t" 10780 "CSINV $dst, $dst, ZR, ge" %} 10781 ins_encode %{ 10782 Register dst = $dst$$Register; 10783 __ fcmp_s($src1$$FloatRegister, $src2$$FloatRegister); 10784 __ cset(dst, gt); // 1 if '>', else 0 10785 __ csinv(dst, dst, ZR, ge); // previous value if '>=', else -1 10786 %} 10787 ins_pipe( floating_cmp ); // FIXME 10788 %} 10789 10790 // Compare floating, generate -1,0,1 10791 instruct cmpD_reg(iRegI dst, regD src1, regD src2, flagsReg icc) %{ 10792 match(Set dst (CmpD3 src1 src2)); 10793 // effect(KILL fcc); // nobody cares if flagsRegF is killed 10794 effect(KILL icc); 10795 ins_cost(DEFAULT_COST*3); // FIXME 10796 size(12); 10797 format %{ "FCMP_d $src1,$src2\n\t" 10798 "CSET $dst, gt\n\t" 10799 "CSINV $dst, $dst, ZR, ge" %} 10800 ins_encode %{ 10801 Register dst = $dst$$Register; 10802 __ fcmp_d($src1$$FloatRegister, $src2$$FloatRegister); 10803 __ cset(dst, gt); // 1 if '>', else 0 10804 __ csinv(dst, dst, ZR, ge); // previous value if '>=', else -1 10805 %} 10806 ins_pipe( floating_cmp ); // FIXME 10807 %} 10808 10809 // Compare floating, generate -1,0,1 10810 instruct cmpF0_reg(iRegI dst, regF src1, immF0 src2, flagsReg icc) %{ 10811 match(Set dst (CmpF3 src1 src2)); 10812 // effect(KILL fcc); // nobody cares if flagsRegF is killed 10813 effect(KILL icc); 10814 ins_cost(DEFAULT_COST*3); // FIXME 10815 size(12); 10816 format %{ "FCMP0_s $src1\n\t" 10817 "CSET $dst, gt\n\t" 10818 "CSINV $dst, $dst, ZR, ge" %} 10819 ins_encode %{ 10820 Register dst = $dst$$Register; 10821 __ fcmp0_s($src1$$FloatRegister); 10822 __ cset(dst, gt); // 1 if '>', else 0 10823 __ csinv(dst, dst, ZR, ge); // previous value if '>=', else -1 10824 %} 10825 ins_pipe( floating_cmp ); // FIXME 10826 %} 10827 10828 // Compare floating, generate -1,0,1 10829 instruct cmpD0_reg(iRegI dst, regD src1, immD0 src2, flagsReg icc) %{ 10830 match(Set dst (CmpD3 src1 src2)); 10831 // effect(KILL fcc); // nobody cares if flagsRegF is killed 10832 effect(KILL icc); 10833 ins_cost(DEFAULT_COST*3); // FIXME 10834 size(12); 10835 format %{ "FCMP0_d $src1\n\t" 10836 "CSET $dst, gt\n\t" 10837 "CSINV $dst, $dst, ZR, ge" %} 10838 ins_encode %{ 10839 Register dst = $dst$$Register; 10840 __ fcmp0_d($src1$$FloatRegister); 10841 __ cset(dst, gt); // 1 if '>', else 0 10842 __ csinv(dst, dst, ZR, ge); // previous value if '>=', else -1 10843 %} 10844 ins_pipe( floating_cmp ); // FIXME 10845 %} 10846 #else 10847 // Compare floating, generate -1,0,1 10848 instruct cmpF_reg(iRegI dst, regF src1, regF src2, flagsRegF fcc) %{ 10849 match(Set dst (CmpF3 src1 src2)); 10850 effect(KILL fcc); 10851 ins_cost(DEFAULT_COST*3+BRANCH_COST*3); // FIXME 10852 size(20); 10853 // same number of instructions as code using conditional moves but 10854 // doesn't kill integer condition register 10855 format %{ "FCMPs $dst,$src1,$src2 \n\t" 10856 "VMRS $dst, FPSCR \n\t" 10857 "OR $dst, $dst, 0x08000000 \n\t" 10858 "EOR $dst, $dst, $dst << 3 \n\t" 10859 "MOV $dst, $dst >> 30" %} 10860 ins_encode %{ 10861 __ fcmps($src1$$FloatRegister, $src2$$FloatRegister); 10862 __ floating_cmp($dst$$Register); 10863 %} 10864 ins_pipe( floating_cmp ); 10865 %} 10866 10867 instruct cmpF0_reg(iRegI dst, regF src1, immF0 src2, flagsRegF fcc) %{ 10868 match(Set dst (CmpF3 src1 src2)); 10869 effect(KILL fcc); 10870 ins_cost(DEFAULT_COST*3+BRANCH_COST*3); // FIXME 10871 size(20); 10872 // same number of instructions as code using conditional moves but 10873 // doesn't kill integer condition register 10874 format %{ "FCMPZs $dst,$src1,$src2 \n\t" 10875 "VMRS $dst, FPSCR \n\t" 10876 "OR $dst, $dst, 0x08000000 \n\t" 10877 "EOR $dst, $dst, $dst << 3 \n\t" 10878 "MOV $dst, $dst >> 30" %} 10879 ins_encode %{ 10880 __ fcmpzs($src1$$FloatRegister); 10881 __ floating_cmp($dst$$Register); 10882 %} 10883 ins_pipe( floating_cmp ); 10884 %} 10885 10886 instruct cmpD_reg(iRegI dst, regD src1, regD src2, flagsRegF fcc) %{ 10887 match(Set dst (CmpD3 src1 src2)); 10888 effect(KILL fcc); 10889 ins_cost(DEFAULT_COST*3+BRANCH_COST*3); // FIXME 10890 size(20); 10891 // same number of instructions as code using conditional moves but 10892 // doesn't kill integer condition register 10893 format %{ "FCMPd $dst,$src1,$src2 \n\t" 10894 "VMRS $dst, FPSCR \n\t" 10895 "OR $dst, $dst, 0x08000000 \n\t" 10896 "EOR $dst, $dst, $dst << 3 \n\t" 10897 "MOV $dst, $dst >> 30" %} 10898 ins_encode %{ 10899 __ fcmpd($src1$$FloatRegister, $src2$$FloatRegister); 10900 __ floating_cmp($dst$$Register); 10901 %} 10902 ins_pipe( floating_cmp ); 10903 %} 10904 10905 instruct cmpD0_reg(iRegI dst, regD src1, immD0 src2, flagsRegF fcc) %{ 10906 match(Set dst (CmpD3 src1 src2)); 10907 effect(KILL fcc); 10908 ins_cost(DEFAULT_COST*3+BRANCH_COST*3); // FIXME 10909 size(20); 10910 // same number of instructions as code using conditional moves but 10911 // doesn't kill integer condition register 10912 format %{ "FCMPZd $dst,$src1,$src2 \n\t" 10913 "VMRS $dst, FPSCR \n\t" 10914 "OR $dst, $dst, 0x08000000 \n\t" 10915 "EOR $dst, $dst, $dst << 3 \n\t" 10916 "MOV $dst, $dst >> 30" %} 10917 ins_encode %{ 10918 __ fcmpzd($src1$$FloatRegister); 10919 __ floating_cmp($dst$$Register); 10920 %} 10921 ins_pipe( floating_cmp ); 10922 %} 10923 #endif // !AARCH64 10924 10925 //----------Branches--------------------------------------------------------- 10926 // Jump 10927 // (compare 'operand indIndex' and 'instruct addP_reg_reg' above) 10928 // FIXME 10929 instruct jumpXtnd(iRegX switch_val, iRegP tmp) %{ 10930 match(Jump switch_val); 10931 effect(TEMP tmp); 10932 ins_cost(350); 10933 format %{ "ADD $tmp, $constanttablebase, $switch_val\n\t" 10934 "LDR $tmp,[$tmp + $constantoffset]\n\t" 10935 "BX $tmp" %} 10936 size(20); 10937 ins_encode %{ 10938 Register table_reg; 10939 Register label_reg = $tmp$$Register; 10940 if (constant_offset() == 0) { 10941 table_reg = $constanttablebase; 10942 __ ldr(label_reg, Address(table_reg, $switch_val$$Register)); 10943 } else { 10944 table_reg = $tmp$$Register; 10945 int offset = $constantoffset; 10946 if (is_memoryP(offset)) { 10947 __ add(table_reg, $constanttablebase, $switch_val$$Register); 10948 __ ldr(label_reg, Address(table_reg, offset)); 10949 } else { 10950 __ mov_slow(table_reg, $constantoffset); 10951 __ add(table_reg, $constanttablebase, table_reg); 10952 __ ldr(label_reg, Address(table_reg, $switch_val$$Register)); 10953 } 10954 } 10955 __ jump(label_reg); // ldr + b better than ldr to PC for branch predictor? 10956 // __ ldr(PC, Address($table$$Register, $switch_val$$Register)); 10957 %} 10958 ins_pipe(ialu_reg_reg); 10959 %} 10960 10961 // // Direct Branch. 10962 instruct branch(label labl) %{ 10963 match(Goto); 10964 effect(USE labl); 10965 10966 size(4); 10967 ins_cost(BRANCH_COST); 10968 format %{ "B $labl" %} 10969 ins_encode %{ 10970 __ b(*($labl$$label)); 10971 %} 10972 ins_pipe(br); 10973 %} 10974 10975 // Conditional Direct Branch 10976 instruct branchCon(cmpOp cmp, flagsReg icc, label labl) %{ 10977 match(If cmp icc); 10978 effect(USE labl); 10979 10980 size(4); 10981 ins_cost(BRANCH_COST); 10982 format %{ "B$cmp $icc,$labl" %} 10983 ins_encode %{ 10984 __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode)); 10985 %} 10986 ins_pipe(br_cc); 10987 %} 10988 10989 #ifdef ARM 10990 instruct branchCon_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, label labl) %{ 10991 match(If cmp icc); 10992 effect(USE labl); 10993 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); 10994 10995 size(4); 10996 ins_cost(BRANCH_COST); 10997 format %{ "B$cmp $icc,$labl" %} 10998 ins_encode %{ 10999 __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode)); 11000 %} 11001 ins_pipe(br_cc); 11002 %} 11003 #endif 11004 11005 #ifdef AARCH64 11006 instruct cbzI(cmpOp cmp, iRegI op1, immI0 op2, label labl) %{ 11007 match(If cmp (CmpI op1 op2)); 11008 effect(USE labl); 11009 predicate(_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || 11010 _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne); 11011 size(4); 11012 ins_cost(BRANCH_COST); 11013 format %{ "CB{N}Z $op1, $labl\t! int $cmp" %} 11014 ins_encode %{ 11015 if ($cmp$$cmpcode == eq) { 11016 __ cbz_w($op1$$Register, *($labl$$label)); 11017 } else { 11018 __ cbnz_w($op1$$Register, *($labl$$label)); 11019 } 11020 %} 11021 ins_pipe(br_cc); // FIXME 11022 %} 11023 11024 instruct cbzP(cmpOpP cmp, iRegP op1, immP0 op2, label labl) %{ 11025 match(If cmp (CmpP op1 op2)); 11026 effect(USE labl); 11027 predicate(_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || 11028 _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne); 11029 size(4); 11030 ins_cost(BRANCH_COST); 11031 format %{ "CB{N}Z $op1, $labl\t! ptr $cmp" %} 11032 ins_encode %{ 11033 if ($cmp$$cmpcode == eq) { 11034 __ cbz($op1$$Register, *($labl$$label)); 11035 } else { 11036 __ cbnz($op1$$Register, *($labl$$label)); 11037 } 11038 %} 11039 ins_pipe(br_cc); // FIXME 11040 %} 11041 11042 instruct cbzL(cmpOpL cmp, iRegL op1, immL0 op2, label labl) %{ 11043 match(If cmp (CmpL op1 op2)); 11044 effect(USE labl); 11045 predicate(_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || 11046 _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne); 11047 size(4); 11048 ins_cost(BRANCH_COST); 11049 format %{ "CB{N}Z $op1, $labl\t! long $cmp" %} 11050 ins_encode %{ 11051 if ($cmp$$cmpcode == eq) { 11052 __ cbz($op1$$Register, *($labl$$label)); 11053 } else { 11054 __ cbnz($op1$$Register, *($labl$$label)); 11055 } 11056 %} 11057 ins_pipe(br_cc); // FIXME 11058 %} 11059 #endif 11060 11061 instruct branchConU(cmpOpU cmp, flagsRegU icc, label labl) %{ 11062 match(If cmp icc); 11063 effect(USE labl); 11064 11065 size(4); 11066 ins_cost(BRANCH_COST); 11067 format %{ "B$cmp $icc,$labl" %} 11068 ins_encode %{ 11069 __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode)); 11070 %} 11071 ins_pipe(br_cc); 11072 %} 11073 11074 instruct branchConP(cmpOpP cmp, flagsRegP pcc, label labl) %{ 11075 match(If cmp pcc); 11076 effect(USE labl); 11077 11078 size(4); 11079 ins_cost(BRANCH_COST); 11080 format %{ "B$cmp $pcc,$labl" %} 11081 ins_encode %{ 11082 __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode)); 11083 %} 11084 ins_pipe(br_cc); 11085 %} 11086 11087 #ifndef AARCH64 11088 instruct branchConL_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, label labl) %{ 11089 match(If cmp xcc); 11090 effect(USE labl); 11091 predicate( _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge ); 11092 11093 size(4); 11094 ins_cost(BRANCH_COST); 11095 format %{ "B$cmp $xcc,$labl" %} 11096 ins_encode %{ 11097 __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode)); 11098 %} 11099 ins_pipe(br_cc); 11100 %} 11101 11102 instruct branchConL_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, label labl) %{ 11103 match(If cmp xcc); 11104 effect(USE labl); 11105 predicate( _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ); 11106 11107 size(4); 11108 ins_cost(BRANCH_COST); 11109 format %{ "B$cmp $xcc,$labl" %} 11110 ins_encode %{ 11111 __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode)); 11112 %} 11113 ins_pipe(br_cc); 11114 %} 11115 11116 instruct branchConL_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, label labl) %{ 11117 match(If cmp xcc); 11118 effect(USE labl); 11119 predicate( _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le ); 11120 11121 size(4); 11122 ins_cost(BRANCH_COST); 11123 format %{ "B$cmp $xcc,$labl" %} 11124 ins_encode %{ 11125 __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode)); 11126 %} 11127 ins_pipe(br_cc); 11128 %} 11129 #endif 11130 11131 instruct branchLoopEnd(cmpOp cmp, flagsReg icc, label labl) %{ 11132 match(CountedLoopEnd cmp icc); 11133 effect(USE labl); 11134 11135 size(4); 11136 ins_cost(BRANCH_COST); 11137 format %{ "B$cmp $icc,$labl\t! Loop end" %} 11138 ins_encode %{ 11139 __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode)); 11140 %} 11141 ins_pipe(br_cc); 11142 %} 11143 11144 // instruct branchLoopEndU(cmpOpU cmp, flagsRegU icc, label labl) %{ 11145 // match(CountedLoopEnd cmp icc); 11146 // ins_pipe(br_cc); 11147 // %} 11148 11149 // ============================================================================ 11150 // Long Compare 11151 // 11152 // Currently we hold longs in 2 registers. Comparing such values efficiently 11153 // is tricky. The flavor of compare used depends on whether we are testing 11154 // for LT, LE, or EQ. For a simple LT test we can check just the sign bit. 11155 // The GE test is the negated LT test. The LE test can be had by commuting 11156 // the operands (yielding a GE test) and then negating; negate again for the 11157 // GT test. The EQ test is done by ORcc'ing the high and low halves, and the 11158 // NE test is negated from that. 11159 11160 // Due to a shortcoming in the ADLC, it mixes up expressions like: 11161 // (foo (CmpI (CmpL X Y) 0)) and (bar (CmpI (CmpL X 0L) 0)). Note the 11162 // difference between 'Y' and '0L'. The tree-matches for the CmpI sections 11163 // are collapsed internally in the ADLC's dfa-gen code. The match for 11164 // (CmpI (CmpL X Y) 0) is silently replaced with (CmpI (CmpL X 0L) 0) and the 11165 // foo match ends up with the wrong leaf. One fix is to not match both 11166 // reg-reg and reg-zero forms of long-compare. This is unfortunate because 11167 // both forms beat the trinary form of long-compare and both are very useful 11168 // on Intel which has so few registers. 11169 11170 // instruct branchCon_long(cmpOp cmp, flagsRegL xcc, label labl) %{ 11171 // match(If cmp xcc); 11172 // ins_pipe(br_cc); 11173 // %} 11174 11175 // Manifest a CmpL3 result in an integer register. Very painful. 11176 // This is the test to avoid. 11177 #ifdef AARCH64 11178 instruct cmpL3_reg_reg(iRegI dst, iRegL src1, iRegL src2, flagsReg ccr) %{ 11179 match(Set dst (CmpL3 src1 src2)); 11180 // effect(KILL fcc); // nobody cares if flagsRegF is killed 11181 effect(KILL ccr); 11182 ins_cost(DEFAULT_COST*3); // FIXME 11183 size(12); 11184 format %{ "CMP $src1,$src2\n\t" 11185 "CSET $dst, gt\n\t" 11186 "CSINV $dst, $dst, ZR, ge" %} 11187 ins_encode %{ 11188 Register dst = $dst$$Register; 11189 __ cmp($src1$$Register, $src2$$Register); 11190 __ cset(dst, gt); // 1 if '>', else 0 11191 __ csinv(dst, dst, ZR, ge); // previous value if '>=', else -1 11192 %} 11193 ins_pipe( ialu_cconly_reg_reg ); // FIXME 11194 %} 11195 // TODO cmpL3_reg_imm 11196 #else 11197 instruct cmpL3_reg_reg(iRegI dst, iRegL src1, iRegL src2, flagsReg ccr ) %{ 11198 match(Set dst (CmpL3 src1 src2) ); 11199 effect( KILL ccr ); 11200 ins_cost(6*DEFAULT_COST); // FIXME 11201 size(32); 11202 format %{ 11203 "CMP $src1.hi, $src2.hi\t\t! long\n" 11204 "\tMOV.gt $dst, 1\n" 11205 "\tmvn.lt $dst, 0\n" 11206 "\tB.ne done\n" 11207 "\tSUBS $dst, $src1.lo, $src2.lo\n" 11208 "\tMOV.hi $dst, 1\n" 11209 "\tmvn.lo $dst, 0\n" 11210 "done:" %} 11211 ins_encode %{ 11212 Label done; 11213 __ cmp($src1$$Register->successor(), $src2$$Register->successor()); 11214 __ mov($dst$$Register, 1, gt); 11215 __ mvn($dst$$Register, 0, lt); 11216 __ b(done, ne); 11217 __ subs($dst$$Register, $src1$$Register, $src2$$Register); 11218 __ mov($dst$$Register, 1, hi); 11219 __ mvn($dst$$Register, 0, lo); 11220 __ bind(done); 11221 %} 11222 ins_pipe(cmpL_reg); 11223 %} 11224 #endif 11225 11226 #ifndef AARCH64 11227 // Conditional move 11228 instruct cmovLL_reg_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, iRegL dst, iRegL src) %{ 11229 match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src))); 11230 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge ); 11231 11232 ins_cost(150); 11233 size(8); 11234 format %{ "MOV$cmp $dst.lo,$src.lo\t! long\n\t" 11235 "MOV$cmp $dst,$src.hi" %} 11236 ins_encode %{ 11237 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 11238 __ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode)); 11239 %} 11240 ins_pipe(ialu_reg); 11241 %} 11242 11243 instruct cmovLL_reg_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, iRegL dst, iRegL src) %{ 11244 match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src))); 11245 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ); 11246 11247 ins_cost(150); 11248 size(8); 11249 format %{ "MOV$cmp $dst.lo,$src.lo\t! long\n\t" 11250 "MOV$cmp $dst,$src.hi" %} 11251 ins_encode %{ 11252 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 11253 __ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode)); 11254 %} 11255 ins_pipe(ialu_reg); 11256 %} 11257 11258 instruct cmovLL_reg_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, iRegL dst, iRegL src) %{ 11259 match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src))); 11260 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt ); 11261 11262 ins_cost(150); 11263 size(8); 11264 format %{ "MOV$cmp $dst.lo,$src.lo\t! long\n\t" 11265 "MOV$cmp $dst,$src.hi" %} 11266 ins_encode %{ 11267 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 11268 __ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode)); 11269 %} 11270 ins_pipe(ialu_reg); 11271 %} 11272 11273 instruct cmovLL_imm_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, iRegL dst, immL0 src) %{ 11274 match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src))); 11275 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge ); 11276 ins_cost(140); 11277 size(8); 11278 format %{ "MOV$cmp $dst.lo,0\t! long\n\t" 11279 "MOV$cmp $dst,0" %} 11280 ins_encode %{ 11281 __ mov($dst$$Register, 0, (AsmCondition)($cmp$$cmpcode)); 11282 __ mov($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode)); 11283 %} 11284 ins_pipe(ialu_imm); 11285 %} 11286 11287 instruct cmovLL_imm_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, iRegL dst, immL0 src) %{ 11288 match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src))); 11289 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ); 11290 ins_cost(140); 11291 size(8); 11292 format %{ "MOV$cmp $dst.lo,0\t! long\n\t" 11293 "MOV$cmp $dst,0" %} 11294 ins_encode %{ 11295 __ mov($dst$$Register, 0, (AsmCondition)($cmp$$cmpcode)); 11296 __ mov($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode)); 11297 %} 11298 ins_pipe(ialu_imm); 11299 %} 11300 11301 instruct cmovLL_imm_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, iRegL dst, immL0 src) %{ 11302 match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src))); 11303 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt ); 11304 ins_cost(140); 11305 size(8); 11306 format %{ "MOV$cmp $dst.lo,0\t! long\n\t" 11307 "MOV$cmp $dst,0" %} 11308 ins_encode %{ 11309 __ mov($dst$$Register, 0, (AsmCondition)($cmp$$cmpcode)); 11310 __ mov($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode)); 11311 %} 11312 ins_pipe(ialu_imm); 11313 %} 11314 #endif // !AARCH64 11315 11316 #ifndef AARCH64 11317 instruct cmovIL_reg_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, iRegI dst, iRegI src) %{ 11318 match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src))); 11319 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge ); 11320 11321 ins_cost(150); 11322 size(4); 11323 format %{ "MOV$cmp $dst,$src" %} 11324 ins_encode %{ 11325 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 11326 %} 11327 ins_pipe(ialu_reg); 11328 %} 11329 11330 instruct cmovIL_reg_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, iRegI dst, iRegI src) %{ 11331 match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src))); 11332 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ); 11333 11334 ins_cost(150); 11335 size(4); 11336 format %{ "MOV$cmp $dst,$src" %} 11337 ins_encode %{ 11338 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 11339 %} 11340 ins_pipe(ialu_reg); 11341 %} 11342 11343 instruct cmovIL_reg_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, iRegI dst, iRegI src) %{ 11344 match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src))); 11345 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt ); 11346 11347 ins_cost(150); 11348 size(4); 11349 format %{ "MOV$cmp $dst,$src" %} 11350 ins_encode %{ 11351 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 11352 %} 11353 ins_pipe(ialu_reg); 11354 %} 11355 #endif // !AARCH64 11356 11357 #ifndef AARCH64 11358 instruct cmovIL_imm_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, iRegI dst, immI16 src) %{ 11359 match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src))); 11360 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge ); 11361 11362 ins_cost(140); 11363 format %{ "MOVW$cmp $dst,$src" %} 11364 ins_encode %{ 11365 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 11366 %} 11367 ins_pipe(ialu_imm); 11368 %} 11369 11370 instruct cmovIL_imm_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, iRegI dst, immI16 src) %{ 11371 match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src))); 11372 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ); 11373 11374 ins_cost(140); 11375 format %{ "MOVW$cmp $dst,$src" %} 11376 ins_encode %{ 11377 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 11378 %} 11379 ins_pipe(ialu_imm); 11380 %} 11381 11382 instruct cmovIL_imm_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, iRegI dst, immI16 src) %{ 11383 match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src))); 11384 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt ); 11385 11386 ins_cost(140); 11387 format %{ "MOVW$cmp $dst,$src" %} 11388 ins_encode %{ 11389 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 11390 %} 11391 ins_pipe(ialu_imm); 11392 %} 11393 11394 instruct cmovPL_reg_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, iRegP dst, iRegP src) %{ 11395 match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src))); 11396 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge ); 11397 11398 ins_cost(150); 11399 size(4); 11400 format %{ "MOV$cmp $dst,$src" %} 11401 ins_encode %{ 11402 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 11403 %} 11404 ins_pipe(ialu_reg); 11405 %} 11406 11407 instruct cmovPL_reg_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, iRegP dst, iRegP src) %{ 11408 match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src))); 11409 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ); 11410 11411 ins_cost(150); 11412 size(4); 11413 format %{ "MOV$cmp $dst,$src" %} 11414 ins_encode %{ 11415 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 11416 %} 11417 ins_pipe(ialu_reg); 11418 %} 11419 11420 instruct cmovPL_reg_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, iRegP dst, iRegP src) %{ 11421 match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src))); 11422 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt ); 11423 11424 ins_cost(150); 11425 size(4); 11426 format %{ "MOV$cmp $dst,$src" %} 11427 ins_encode %{ 11428 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 11429 %} 11430 ins_pipe(ialu_reg); 11431 %} 11432 11433 instruct cmovPL_imm_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, iRegP dst, immP0 src) %{ 11434 match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src))); 11435 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge ); 11436 11437 ins_cost(140); 11438 format %{ "MOVW$cmp $dst,$src" %} 11439 ins_encode %{ 11440 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 11441 %} 11442 ins_pipe(ialu_imm); 11443 %} 11444 11445 instruct cmovPL_imm_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, iRegP dst, immP0 src) %{ 11446 match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src))); 11447 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ); 11448 11449 ins_cost(140); 11450 format %{ "MOVW$cmp $dst,$src" %} 11451 ins_encode %{ 11452 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 11453 %} 11454 ins_pipe(ialu_imm); 11455 %} 11456 11457 instruct cmovPL_imm_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, iRegP dst, immP0 src) %{ 11458 match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src))); 11459 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt ); 11460 11461 ins_cost(140); 11462 format %{ "MOVW$cmp $dst,$src" %} 11463 ins_encode %{ 11464 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 11465 %} 11466 ins_pipe(ialu_imm); 11467 %} 11468 11469 instruct cmovFL_reg_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, regF dst, regF src) %{ 11470 match(Set dst (CMoveF (Binary cmp xcc) (Binary dst src))); 11471 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge ); 11472 ins_cost(150); 11473 size(4); 11474 format %{ "FCPYS$cmp $dst,$src" %} 11475 ins_encode %{ 11476 __ fcpys($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode)); 11477 %} 11478 ins_pipe(int_conditional_float_move); 11479 %} 11480 11481 instruct cmovFL_reg_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, regF dst, regF src) %{ 11482 match(Set dst (CMoveF (Binary cmp xcc) (Binary dst src))); 11483 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ); 11484 ins_cost(150); 11485 size(4); 11486 format %{ "FCPYS$cmp $dst,$src" %} 11487 ins_encode %{ 11488 __ fcpys($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode)); 11489 %} 11490 ins_pipe(int_conditional_float_move); 11491 %} 11492 11493 instruct cmovFL_reg_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, regF dst, regF src) %{ 11494 match(Set dst (CMoveF (Binary cmp xcc) (Binary dst src))); 11495 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt ); 11496 ins_cost(150); 11497 size(4); 11498 format %{ "FCPYS$cmp $dst,$src" %} 11499 ins_encode %{ 11500 __ fcpys($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode)); 11501 %} 11502 ins_pipe(int_conditional_float_move); 11503 %} 11504 11505 instruct cmovDL_reg_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, regD dst, regD src) %{ 11506 match(Set dst (CMoveD (Binary cmp xcc) (Binary dst src))); 11507 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge ); 11508 11509 ins_cost(150); 11510 size(4); 11511 format %{ "FCPYD$cmp $dst,$src" %} 11512 ins_encode %{ 11513 __ fcpyd($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode)); 11514 %} 11515 ins_pipe(int_conditional_float_move); 11516 %} 11517 11518 instruct cmovDL_reg_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, regD dst, regD src) %{ 11519 match(Set dst (CMoveD (Binary cmp xcc) (Binary dst src))); 11520 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ); 11521 11522 ins_cost(150); 11523 size(4); 11524 format %{ "FCPYD$cmp $dst,$src" %} 11525 ins_encode %{ 11526 __ fcpyd($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode)); 11527 %} 11528 ins_pipe(int_conditional_float_move); 11529 %} 11530 11531 instruct cmovDL_reg_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, regD dst, regD src) %{ 11532 match(Set dst (CMoveD (Binary cmp xcc) (Binary dst src))); 11533 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt ); 11534 11535 ins_cost(150); 11536 size(4); 11537 format %{ "FCPYD$cmp $dst,$src" %} 11538 ins_encode %{ 11539 __ fcpyd($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode)); 11540 %} 11541 ins_pipe(int_conditional_float_move); 11542 %} 11543 #endif // !AARCH64 11544 11545 // ============================================================================ 11546 // Safepoint Instruction 11547 #ifdef AARCH64 11548 instruct safePoint_poll(iRegP poll, flagsReg icc, RtempRegP tmp) %{ 11549 match(SafePoint poll); 11550 // The handler stub kills Rtemp 11551 effect(USE poll, KILL tmp, KILL icc); 11552 11553 size(4); 11554 format %{ "LDR ZR,[$poll]\t! Safepoint: poll for GC" %} 11555 ins_encode %{ 11556 __ relocate(relocInfo::poll_type); 11557 __ ldr(ZR, Address($poll$$Register)); 11558 %} 11559 ins_pipe(loadPollP); 11560 %} 11561 #else 11562 // rather than KILL R12, it would be better to use any reg as 11563 // TEMP. Can't do that at this point because it crashes the compiler 11564 instruct safePoint_poll(iRegP poll, R12RegI tmp, flagsReg icc) %{ 11565 match(SafePoint poll); 11566 effect(USE poll, KILL tmp, KILL icc); 11567 11568 size(4); 11569 format %{ "LDR $tmp,[$poll]\t! Safepoint: poll for GC" %} 11570 ins_encode %{ 11571 __ relocate(relocInfo::poll_type); 11572 __ ldr($tmp$$Register, Address($poll$$Register)); 11573 %} 11574 ins_pipe(loadPollP); 11575 %} 11576 #endif 11577 11578 11579 // ============================================================================ 11580 // Call Instructions 11581 // Call Java Static Instruction 11582 instruct CallStaticJavaDirect( method meth ) %{ 11583 match(CallStaticJava); 11584 predicate(! ((CallStaticJavaNode*)n)->is_method_handle_invoke()); 11585 effect(USE meth); 11586 11587 ins_cost(CALL_COST); 11588 format %{ "CALL,static ==> " %} 11589 ins_encode( Java_Static_Call( meth ), call_epilog ); 11590 ins_pipe(simple_call); 11591 %} 11592 11593 // Call Java Static Instruction (method handle version) 11594 instruct CallStaticJavaHandle( method meth ) %{ 11595 match(CallStaticJava); 11596 predicate(((CallStaticJavaNode*)n)->is_method_handle_invoke()); 11597 effect(USE meth); 11598 // FP is saved by all callees (for interpreter stack correction). 11599 // We use it here for a similar purpose, in {preserve,restore}_FP. 11600 11601 ins_cost(CALL_COST); 11602 format %{ "CALL,static/MethodHandle ==> " %} 11603 ins_encode( preserve_SP, Java_Static_Call( meth ), restore_SP, call_epilog ); 11604 ins_pipe(simple_call); 11605 %} 11606 11607 // Call Java Dynamic Instruction 11608 instruct CallDynamicJavaDirect( method meth ) %{ 11609 match(CallDynamicJava); 11610 effect(USE meth); 11611 11612 ins_cost(CALL_COST); 11613 format %{ "MOV_OOP (empty),R_R8\n\t" 11614 "CALL,dynamic ; NOP ==> " %} 11615 ins_encode( Java_Dynamic_Call( meth ), call_epilog ); 11616 ins_pipe(call); 11617 %} 11618 11619 // Call Runtime Instruction 11620 instruct CallRuntimeDirect(method meth) %{ 11621 match(CallRuntime); 11622 effect(USE meth); 11623 ins_cost(CALL_COST); 11624 format %{ "CALL,runtime" %} 11625 #ifdef AARCH64 11626 ins_encode( save_last_PC, Java_To_Runtime( meth ), 11627 call_epilog ); 11628 #else 11629 ins_encode( Java_To_Runtime( meth ), 11630 call_epilog ); 11631 #endif 11632 ins_pipe(simple_call); 11633 %} 11634 11635 // Call runtime without safepoint - same as CallRuntime 11636 instruct CallLeafDirect(method meth) %{ 11637 match(CallLeaf); 11638 effect(USE meth); 11639 ins_cost(CALL_COST); 11640 format %{ "CALL,runtime leaf" %} 11641 // TODO: ned save_last_PC here? 11642 ins_encode( Java_To_Runtime( meth ), 11643 call_epilog ); 11644 ins_pipe(simple_call); 11645 %} 11646 11647 // Call runtime without safepoint - same as CallLeaf 11648 instruct CallLeafNoFPDirect(method meth) %{ 11649 match(CallLeafNoFP); 11650 effect(USE meth); 11651 ins_cost(CALL_COST); 11652 format %{ "CALL,runtime leaf nofp" %} 11653 // TODO: ned save_last_PC here? 11654 ins_encode( Java_To_Runtime( meth ), 11655 call_epilog ); 11656 ins_pipe(simple_call); 11657 %} 11658 11659 // Tail Call; Jump from runtime stub to Java code. 11660 // Also known as an 'interprocedural jump'. 11661 // Target of jump will eventually return to caller. 11662 // TailJump below removes the return address. 11663 instruct TailCalljmpInd(IPRegP jump_target, inline_cache_regP method_oop) %{ 11664 match(TailCall jump_target method_oop ); 11665 11666 ins_cost(CALL_COST); 11667 format %{ "MOV Rexception_pc, LR\n\t" 11668 "jump $jump_target \t! $method_oop holds method oop" %} 11669 ins_encode %{ 11670 __ mov(Rexception_pc, LR); // this is used only to call 11671 // StubRoutines::forward_exception_entry() 11672 // which expects PC of exception in 11673 // R5. FIXME? 11674 __ jump($jump_target$$Register); 11675 %} 11676 ins_pipe(tail_call); 11677 %} 11678 11679 11680 // Return Instruction 11681 instruct Ret() %{ 11682 match(Return); 11683 11684 format %{ "ret LR" %} 11685 11686 ins_encode %{ 11687 __ ret(LR); 11688 %} 11689 11690 ins_pipe(br); 11691 %} 11692 11693 11694 // Tail Jump; remove the return address; jump to target. 11695 // TailCall above leaves the return address around. 11696 // TailJump is used in only one place, the rethrow_Java stub (fancy_jump=2). 11697 // ex_oop (Exception Oop) is needed in %o0 at the jump. As there would be a 11698 // "restore" before this instruction (in Epilogue), we need to materialize it 11699 // in %i0. 11700 instruct tailjmpInd(IPRegP jump_target, RExceptionRegP ex_oop) %{ 11701 match( TailJump jump_target ex_oop ); 11702 ins_cost(CALL_COST); 11703 format %{ "MOV Rexception_pc, LR\n\t" 11704 "jump $jump_target \t! $ex_oop holds exc. oop" %} 11705 ins_encode %{ 11706 __ mov(Rexception_pc, LR); 11707 __ jump($jump_target$$Register); 11708 %} 11709 ins_pipe(tail_call); 11710 %} 11711 11712 // Create exception oop: created by stack-crawling runtime code. 11713 // Created exception is now available to this handler, and is setup 11714 // just prior to jumping to this handler. No code emitted. 11715 instruct CreateException( RExceptionRegP ex_oop ) 11716 %{ 11717 match(Set ex_oop (CreateEx)); 11718 ins_cost(0); 11719 11720 size(0); 11721 // use the following format syntax 11722 format %{ "! exception oop is in Rexception_obj; no code emitted" %} 11723 ins_encode(); 11724 ins_pipe(empty); 11725 %} 11726 11727 11728 // Rethrow exception: 11729 // The exception oop will come in the first argument position. 11730 // Then JUMP (not call) to the rethrow stub code. 11731 instruct RethrowException() 11732 %{ 11733 match(Rethrow); 11734 ins_cost(CALL_COST); 11735 11736 // use the following format syntax 11737 format %{ "b rethrow_stub" %} 11738 ins_encode %{ 11739 Register scratch = R1_tmp; 11740 assert_different_registers(scratch, c_rarg0, LR); 11741 __ jump(OptoRuntime::rethrow_stub(), relocInfo::runtime_call_type, scratch); 11742 %} 11743 ins_pipe(tail_call); 11744 %} 11745 11746 11747 // Die now 11748 instruct ShouldNotReachHere( ) 11749 %{ 11750 match(Halt); 11751 ins_cost(CALL_COST); 11752 11753 size(4); 11754 // Use the following format syntax 11755 format %{ "breakpoint ; ShouldNotReachHere" %} 11756 ins_encode %{ 11757 __ breakpoint(); 11758 %} 11759 ins_pipe(tail_call); 11760 %} 11761 11762 // ============================================================================ 11763 // The 2nd slow-half of a subtype check. Scan the subklass's 2ndary superklass 11764 // array for an instance of the superklass. Set a hidden internal cache on a 11765 // hit (cache is checked with exposed code in gen_subtype_check()). Return 11766 // not zero for a miss or zero for a hit. The encoding ALSO sets flags. 11767 instruct partialSubtypeCheck( R0RegP index, R1RegP sub, R2RegP super, flagsRegP pcc, LRRegP lr ) %{ 11768 match(Set index (PartialSubtypeCheck sub super)); 11769 effect( KILL pcc, KILL lr ); 11770 ins_cost(DEFAULT_COST*10); 11771 format %{ "CALL PartialSubtypeCheck" %} 11772 ins_encode %{ 11773 __ call(StubRoutines::Arm::partial_subtype_check(), relocInfo::runtime_call_type); 11774 %} 11775 ins_pipe(partial_subtype_check_pipe); 11776 %} 11777 11778 /* instruct partialSubtypeCheck_vs_zero( flagsRegP pcc, o1RegP sub, o2RegP super, immP0 zero, o0RegP idx, o7RegP o7 ) %{ */ 11779 /* match(Set pcc (CmpP (PartialSubtypeCheck sub super) zero)); */ 11780 /* ins_pipe(partial_subtype_check_pipe); */ 11781 /* %} */ 11782 11783 11784 // ============================================================================ 11785 // inlined locking and unlocking 11786 11787 #ifdef AARCH64 11788 instruct cmpFastLock(flagsRegP pcc, iRegP object, iRegP box, iRegP scratch2, iRegP scratch, iRegP scratch3 ) 11789 #else 11790 instruct cmpFastLock(flagsRegP pcc, iRegP object, iRegP box, iRegP scratch2, iRegP scratch ) 11791 #endif 11792 %{ 11793 match(Set pcc (FastLock object box)); 11794 11795 #ifdef AARCH64 11796 effect(TEMP scratch, TEMP scratch2, TEMP scratch3); 11797 #else 11798 effect(TEMP scratch, TEMP scratch2); 11799 #endif 11800 ins_cost(100); 11801 11802 #ifdef AARCH64 11803 format %{ "FASTLOCK $object, $box; KILL $scratch, $scratch2, $scratch3" %} 11804 ins_encode %{ 11805 __ fast_lock($object$$Register, $box$$Register, $scratch$$Register, $scratch2$$Register, $scratch3$$Register); 11806 %} 11807 #else 11808 format %{ "FASTLOCK $object, $box; KILL $scratch, $scratch2" %} 11809 ins_encode %{ 11810 __ fast_lock($object$$Register, $box$$Register, $scratch$$Register, $scratch2$$Register); 11811 %} 11812 #endif 11813 ins_pipe(long_memory_op); 11814 %} 11815 11816 11817 #ifdef AARCH64 11818 instruct cmpFastUnlock(flagsRegP pcc, iRegP object, iRegP box, iRegP scratch2, iRegP scratch, iRegP scratch3 ) %{ 11819 match(Set pcc (FastUnlock object box)); 11820 effect(TEMP scratch, TEMP scratch2, TEMP scratch3); 11821 ins_cost(100); 11822 11823 format %{ "FASTUNLOCK $object, $box; KILL $scratch, $scratch2, $scratch3" %} 11824 ins_encode %{ 11825 __ fast_unlock($object$$Register, $box$$Register, $scratch$$Register, $scratch2$$Register, $scratch3$$Register); 11826 %} 11827 ins_pipe(long_memory_op); 11828 %} 11829 #else 11830 instruct cmpFastUnlock(flagsRegP pcc, iRegP object, iRegP box, iRegP scratch2, iRegP scratch ) %{ 11831 match(Set pcc (FastUnlock object box)); 11832 effect(TEMP scratch, TEMP scratch2); 11833 ins_cost(100); 11834 11835 format %{ "FASTUNLOCK $object, $box; KILL $scratch, $scratch2" %} 11836 ins_encode %{ 11837 __ fast_unlock($object$$Register, $box$$Register, $scratch$$Register, $scratch2$$Register); 11838 %} 11839 ins_pipe(long_memory_op); 11840 %} 11841 #endif 11842 11843 #ifdef AARCH64 11844 // TODO: add version that takes immI cnt? 11845 instruct clear_array(iRegX cnt, iRegP base, iRegP ptr, iRegX temp, Universe dummy, flagsReg cpsr) %{ 11846 match(Set dummy (ClearArray cnt base)); 11847 effect(TEMP temp, TEMP ptr, KILL cpsr); 11848 ins_cost(300); 11849 format %{ 11850 " MOV $temp,$cnt\n" 11851 " ADD $ptr,$base,$cnt\n" 11852 " SUBS $temp,$temp,16\t! Count down dword pair in bytes\n" 11853 " B.lt done16\n" 11854 "loop: STP ZR,ZR,[$ptr,-16]!\n" 11855 " SUBS $temp,$temp,16\t! Count down dword pair in bytes\n" 11856 " B.ge loop\t! Clearing loop\n" 11857 "done16: ADDS $temp,$temp,8\t! Room for 1 more long?\n" 11858 " B.lt done\n" 11859 " STR ZR,[$base+$temp]\n" 11860 "done:" 11861 %} 11862 ins_encode %{ 11863 // TODO: preload? 11864 __ mov($temp$$Register, $cnt$$Register); 11865 __ add($ptr$$Register, $base$$Register, $cnt$$Register); 11866 Label loop, done, done16; 11867 __ subs($temp$$Register, $temp$$Register, 16); 11868 __ b(done16, lt); 11869 __ bind(loop); 11870 __ stp(ZR, ZR, Address($ptr$$Register, -16, pre_indexed)); 11871 __ subs($temp$$Register, $temp$$Register, 16); 11872 __ b(loop, ge); 11873 __ bind(done16); 11874 __ adds($temp$$Register, $temp$$Register, 8); 11875 __ b(done, lt); 11876 // $temp should be 0 here 11877 __ str(ZR, Address($base$$Register, $temp$$Register)); 11878 __ bind(done); 11879 %} 11880 ins_pipe(long_memory_op); 11881 %} 11882 #else 11883 // Count and Base registers are fixed because the allocator cannot 11884 // kill unknown registers. The encodings are generic. 11885 instruct clear_array(iRegX cnt, iRegP base, iRegI temp, iRegX zero, Universe dummy, flagsReg cpsr) %{ 11886 match(Set dummy (ClearArray cnt base)); 11887 effect(TEMP temp, TEMP zero, KILL cpsr); 11888 ins_cost(300); 11889 format %{ "MOV $zero,0\n" 11890 " MOV $temp,$cnt\n" 11891 "loop: SUBS $temp,$temp,4\t! Count down a dword of bytes\n" 11892 " STR.ge $zero,[$base+$temp]\t! delay slot" 11893 " B.gt loop\t\t! Clearing loop\n" %} 11894 ins_encode %{ 11895 __ mov($zero$$Register, 0); 11896 __ mov($temp$$Register, $cnt$$Register); 11897 Label(loop); 11898 __ bind(loop); 11899 __ subs($temp$$Register, $temp$$Register, 4); 11900 __ str($zero$$Register, Address($base$$Register, $temp$$Register), ge); 11901 __ b(loop, gt); 11902 %} 11903 ins_pipe(long_memory_op); 11904 %} 11905 #endif 11906 11907 #ifdef XXX 11908 // FIXME: Why R0/R1/R2/R3? 11909 instruct string_compare(R0RegP str1, R1RegP str2, R2RegI cnt1, R3RegI cnt2, iRegI result, 11910 iRegI tmp1, iRegI tmp2, flagsReg ccr) %{ 11911 predicate(!CompactStrings); 11912 match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2))); 11913 effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL ccr, TEMP tmp1, TEMP tmp2); 11914 ins_cost(300); 11915 format %{ "String Compare $str1,$cnt1,$str2,$cnt2 -> $result // TEMP $tmp1, $tmp2" %} 11916 ins_encode( enc_String_Compare(str1, str2, cnt1, cnt2, result, tmp1, tmp2) ); 11917 11918 ins_pipe(long_memory_op); 11919 %} 11920 11921 // FIXME: Why R0/R1/R2? 11922 instruct string_equals(R0RegP str1, R1RegP str2, R2RegI cnt, iRegI result, iRegI tmp1, iRegI tmp2, 11923 flagsReg ccr) %{ 11924 predicate(!CompactStrings); 11925 match(Set result (StrEquals (Binary str1 str2) cnt)); 11926 effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt, TEMP tmp1, TEMP tmp2, TEMP result, KILL ccr); 11927 11928 ins_cost(300); 11929 format %{ "String Equals $str1,$str2,$cnt -> $result // TEMP $tmp1, $tmp2" %} 11930 ins_encode( enc_String_Equals(str1, str2, cnt, result, tmp1, tmp2) ); 11931 ins_pipe(long_memory_op); 11932 %} 11933 11934 // FIXME: Why R0/R1? 11935 instruct array_equals(R0RegP ary1, R1RegP ary2, iRegI tmp1, iRegI tmp2, iRegI tmp3, iRegI result, 11936 flagsReg ccr) %{ 11937 predicate(((AryEqNode*)n)->encoding() == StrIntrinsicNode::UU); 11938 match(Set result (AryEq ary1 ary2)); 11939 effect(USE_KILL ary1, USE_KILL ary2, TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP result, KILL ccr); 11940 11941 ins_cost(300); 11942 format %{ "Array Equals $ary1,$ary2 -> $result // TEMP $tmp1,$tmp2,$tmp3" %} 11943 ins_encode( enc_Array_Equals(ary1, ary2, tmp1, tmp2, tmp3, result)); 11944 ins_pipe(long_memory_op); 11945 %} 11946 #endif 11947 11948 //---------- Zeros Count Instructions ------------------------------------------ 11949 11950 instruct countLeadingZerosI(iRegI dst, iRegI src) %{ 11951 match(Set dst (CountLeadingZerosI src)); 11952 size(4); 11953 format %{ "CLZ_32 $dst,$src" %} 11954 ins_encode %{ 11955 __ clz_32($dst$$Register, $src$$Register); 11956 %} 11957 ins_pipe(ialu_reg); 11958 %} 11959 11960 #ifdef AARCH64 11961 instruct countLeadingZerosL(iRegI dst, iRegL src) %{ 11962 match(Set dst (CountLeadingZerosL src)); 11963 size(4); 11964 format %{ "CLZ $dst,$src" %} 11965 ins_encode %{ 11966 __ clz($dst$$Register, $src$$Register); 11967 %} 11968 ins_pipe(ialu_reg); 11969 %} 11970 #else 11971 instruct countLeadingZerosL(iRegI dst, iRegL src, iRegI tmp, flagsReg ccr) %{ 11972 match(Set dst (CountLeadingZerosL src)); 11973 effect(TEMP tmp, TEMP dst, KILL ccr); 11974 size(16); 11975 format %{ "CLZ $dst,$src.hi\n\t" 11976 "TEQ $dst,32\n\t" 11977 "CLZ.eq $tmp,$src.lo\n\t" 11978 "ADD.eq $dst, $dst, $tmp\n\t" %} 11979 ins_encode %{ 11980 __ clz($dst$$Register, $src$$Register->successor()); 11981 __ teq($dst$$Register, 32); 11982 __ clz($tmp$$Register, $src$$Register, eq); 11983 __ add($dst$$Register, $dst$$Register, $tmp$$Register, eq); 11984 %} 11985 ins_pipe(ialu_reg); 11986 %} 11987 #endif 11988 11989 instruct countTrailingZerosI(iRegI dst, iRegI src, iRegI tmp) %{ 11990 match(Set dst (CountTrailingZerosI src)); 11991 effect(TEMP tmp); 11992 size(8); 11993 format %{ "RBIT_32 $tmp, $src\n\t" 11994 "CLZ_32 $dst,$tmp" %} 11995 ins_encode %{ 11996 __ rbit_32($tmp$$Register, $src$$Register); 11997 __ clz_32($dst$$Register, $tmp$$Register); 11998 %} 11999 ins_pipe(ialu_reg); 12000 %} 12001 12002 #ifdef AARCH64 12003 instruct countTrailingZerosL(iRegI dst, iRegL src, iRegL tmp) %{ 12004 match(Set dst (CountTrailingZerosL src)); 12005 effect(TEMP tmp); 12006 size(8); 12007 format %{ "RBIT $tmp, $src\n\t" 12008 "CLZ $dst,$tmp" %} 12009 ins_encode %{ 12010 __ rbit($tmp$$Register, $src$$Register); 12011 __ clz($dst$$Register, $tmp$$Register); 12012 %} 12013 ins_pipe(ialu_reg); 12014 %} 12015 #else 12016 instruct countTrailingZerosL(iRegI dst, iRegL src, iRegI tmp, flagsReg ccr) %{ 12017 match(Set dst (CountTrailingZerosL src)); 12018 effect(TEMP tmp, TEMP dst, KILL ccr); 12019 size(24); 12020 format %{ "RBIT $tmp,$src.lo\n\t" 12021 "CLZ $dst,$tmp\n\t" 12022 "TEQ $dst,32\n\t" 12023 "RBIT $tmp,$src.hi\n\t" 12024 "CLZ.eq $tmp,$tmp\n\t" 12025 "ADD.eq $dst,$dst,$tmp\n\t" %} 12026 ins_encode %{ 12027 __ rbit($tmp$$Register, $src$$Register); 12028 __ clz($dst$$Register, $tmp$$Register); 12029 __ teq($dst$$Register, 32); 12030 __ rbit($tmp$$Register, $src$$Register->successor()); 12031 __ clz($tmp$$Register, $tmp$$Register, eq); 12032 __ add($dst$$Register, $dst$$Register, $tmp$$Register, eq); 12033 %} 12034 ins_pipe(ialu_reg); 12035 %} 12036 #endif 12037 12038 12039 //---------- Population Count Instructions ------------------------------------- 12040 12041 #ifdef AARCH64 12042 instruct popCountI(iRegI dst, iRegI src, regD_low tmp) %{ 12043 predicate(UsePopCountInstruction); 12044 match(Set dst (PopCountI src)); 12045 effect(TEMP tmp); 12046 size(20); 12047 12048 format %{ "MOV_W $dst,$src\n\t" 12049 "FMOV_dx $tmp,$dst\n\t" 12050 "VCNT $tmp.8B,$tmp.8B\n\t" 12051 "ADDV $tmp.B,$tmp.8B\n\t" 12052 "FMRS $dst,$tmp" %} 12053 12054 ins_encode %{ 12055 __ mov_w($dst$$Register, $src$$Register); 12056 __ fmov_dx($tmp$$FloatRegister, $dst$$Register); 12057 int quad = 0; 12058 int cnt_size = 0; // VELEM_SIZE_8 12059 __ vcnt($tmp$$FloatRegister, $tmp$$FloatRegister, quad, cnt_size); 12060 int add_size = 0; // VELEM_SIZE_8 12061 __ addv($tmp$$FloatRegister, $tmp$$FloatRegister, quad, add_size); 12062 __ fmrs($dst$$Register, $tmp$$FloatRegister); 12063 %} 12064 ins_pipe(ialu_reg); // FIXME 12065 %} 12066 #else 12067 instruct popCountI(iRegI dst, iRegI src, regD_low tmp) %{ 12068 predicate(UsePopCountInstruction); 12069 match(Set dst (PopCountI src)); 12070 effect(TEMP tmp); 12071 12072 format %{ "FMSR $tmp,$src\n\t" 12073 "VCNT.8 $tmp,$tmp\n\t" 12074 "VPADDL.U8 $tmp,$tmp\n\t" 12075 "VPADDL.U16 $tmp,$tmp\n\t" 12076 "FMRS $dst,$tmp" %} 12077 size(20); 12078 12079 ins_encode %{ 12080 __ fmsr($tmp$$FloatRegister, $src$$Register); 12081 __ vcnt($tmp$$FloatRegister, $tmp$$FloatRegister); 12082 __ vpaddl($tmp$$FloatRegister, $tmp$$FloatRegister, 8, 0); 12083 __ vpaddl($tmp$$FloatRegister, $tmp$$FloatRegister, 16, 0); 12084 __ fmrs($dst$$Register, $tmp$$FloatRegister); 12085 %} 12086 ins_pipe(ialu_reg); // FIXME 12087 %} 12088 #endif 12089 12090 #ifdef AARCH64 12091 instruct popCountL(iRegI dst, iRegL src, regD tmp) %{ 12092 predicate(UsePopCountInstruction); 12093 match(Set dst (PopCountL src)); 12094 effect(TEMP tmp); 12095 size(16); 12096 12097 format %{ "FMOV_dx $tmp,$src\n\t" 12098 "VCNT $tmp.8B,$tmp.8B\n\t" 12099 "ADDV $tmp.B,$tmp.8B\n\t" 12100 "FMOV_ws $dst,$tmp" %} 12101 12102 ins_encode %{ 12103 __ fmov_dx($tmp$$FloatRegister, $src$$Register); 12104 int quad = 0; 12105 int cnt_size = 0; 12106 __ vcnt($tmp$$FloatRegister, $tmp$$FloatRegister, quad, cnt_size); 12107 int add_size = 0; 12108 __ addv($tmp$$FloatRegister, $tmp$$FloatRegister, quad, add_size); 12109 __ fmov_ws($dst$$Register, $tmp$$FloatRegister); 12110 %} 12111 ins_pipe(ialu_reg); // FIXME 12112 %} 12113 #else 12114 // Note: Long.bitCount(long) returns an int. 12115 instruct popCountL(iRegI dst, iRegL src, regD_low tmp) %{ 12116 predicate(UsePopCountInstruction); 12117 match(Set dst (PopCountL src)); 12118 effect(TEMP tmp); 12119 12120 format %{ "FMDRR $tmp,$src.lo,$src.hi\n\t" 12121 "VCNT.8 $tmp,$tmp\n\t" 12122 "VPADDL.U8 $tmp,$tmp\n\t" 12123 "VPADDL.U16 $tmp,$tmp\n\t" 12124 "VPADDL.U32 $tmp,$tmp\n\t" 12125 "FMRS $dst,$tmp" %} 12126 12127 size(32); 12128 12129 ins_encode %{ 12130 __ fmdrr($tmp$$FloatRegister, $src$$Register, $src$$Register->successor()); 12131 __ vcnt($tmp$$FloatRegister, $tmp$$FloatRegister); 12132 __ vpaddl($tmp$$FloatRegister, $tmp$$FloatRegister, 8, 0); 12133 __ vpaddl($tmp$$FloatRegister, $tmp$$FloatRegister, 16, 0); 12134 __ vpaddl($tmp$$FloatRegister, $tmp$$FloatRegister, 32, 0); 12135 __ fmrs($dst$$Register, $tmp$$FloatRegister); 12136 %} 12137 ins_pipe(ialu_reg); 12138 %} 12139 #endif 12140 12141 12142 // ============================================================================ 12143 //------------Bytes reverse-------------------------------------------------- 12144 12145 instruct bytes_reverse_int(iRegI dst, iRegI src) %{ 12146 match(Set dst (ReverseBytesI src)); 12147 12148 size(4); 12149 format %{ "REV32 $dst,$src" %} 12150 ins_encode %{ 12151 #ifdef AARCH64 12152 __ rev_w($dst$$Register, $src$$Register); 12153 // high 32 bits zeroed, not sign extended 12154 #else 12155 __ rev($dst$$Register, $src$$Register); 12156 #endif 12157 %} 12158 ins_pipe( iload_mem ); // FIXME 12159 %} 12160 12161 instruct bytes_reverse_long(iRegL dst, iRegL src) %{ 12162 match(Set dst (ReverseBytesL src)); 12163 #ifdef AARCH64 12164 //size(4); 12165 format %{ "REV $dst,$src" %} 12166 ins_encode %{ 12167 __ rev($dst$$Register, $src$$Register); 12168 %} 12169 ins_pipe(ialu_reg_reg); // FIXME 12170 #else 12171 effect(TEMP dst); 12172 size(8); 12173 format %{ "REV $dst.lo,$src.lo\n\t" 12174 "REV $dst.hi,$src.hi" %} 12175 ins_encode %{ 12176 __ rev($dst$$Register, $src$$Register->successor()); 12177 __ rev($dst$$Register->successor(), $src$$Register); 12178 %} 12179 ins_pipe( iload_mem ); // FIXME 12180 #endif 12181 %} 12182 12183 instruct bytes_reverse_unsigned_short(iRegI dst, iRegI src) %{ 12184 match(Set dst (ReverseBytesUS src)); 12185 #ifdef AARCH64 12186 size(4); 12187 format %{ "REV16_W $dst,$src" %} 12188 ins_encode %{ 12189 __ rev16_w($dst$$Register, $src$$Register); 12190 // high 32 bits zeroed 12191 %} 12192 #else 12193 size(4); 12194 format %{ "REV16 $dst,$src" %} 12195 ins_encode %{ 12196 __ rev16($dst$$Register, $src$$Register); 12197 %} 12198 #endif 12199 ins_pipe( iload_mem ); // FIXME 12200 %} 12201 12202 instruct bytes_reverse_short(iRegI dst, iRegI src) %{ 12203 match(Set dst (ReverseBytesS src)); 12204 #ifdef AARCH64 12205 size(8); 12206 format %{ "REV16_W $dst,$src\n\t" 12207 "SIGN_EXT16 $dst" %} 12208 ins_encode %{ 12209 __ rev16_w($dst$$Register, $src$$Register); 12210 __ sign_extend($dst$$Register, $dst$$Register, 16); 12211 %} 12212 #else 12213 size(4); 12214 format %{ "REVSH $dst,$src" %} 12215 ins_encode %{ 12216 __ revsh($dst$$Register, $src$$Register); 12217 %} 12218 #endif 12219 ins_pipe( iload_mem ); // FIXME 12220 %} 12221 12222 12223 // ====================VECTOR INSTRUCTIONS===================================== 12224 12225 // Load Aligned Packed values into a Double Register 12226 instruct loadV8(vecD dst, memoryD mem) %{ 12227 predicate(n->as_LoadVector()->memory_size() == 8); 12228 match(Set dst (LoadVector mem)); 12229 ins_cost(MEMORY_REF_COST); 12230 size(4); 12231 format %{ "FLDD $mem,$dst\t! load vector (8 bytes)" %} 12232 ins_encode %{ 12233 __ ldr_double($dst$$FloatRegister, $mem$$Address); 12234 %} 12235 ins_pipe(floadD_mem); 12236 %} 12237 12238 // Load Aligned Packed values into a Double Register Pair 12239 instruct loadV16(vecX dst, memoryvld mem) %{ 12240 predicate(n->as_LoadVector()->memory_size() == 16); 12241 match(Set dst (LoadVector mem)); 12242 ins_cost(MEMORY_REF_COST); 12243 size(4); 12244 format %{ "VLD1 $mem,$dst.Q\t! load vector (16 bytes)" %} 12245 ins_encode %{ 12246 __ vld1($dst$$FloatRegister, $mem$$Address, MacroAssembler::VELEM_SIZE_16, 128); 12247 %} 12248 ins_pipe(floadD_mem); // FIXME 12249 %} 12250 12251 // Store Vector in Double register to memory 12252 instruct storeV8(memoryD mem, vecD src) %{ 12253 predicate(n->as_StoreVector()->memory_size() == 8); 12254 match(Set mem (StoreVector mem src)); 12255 ins_cost(MEMORY_REF_COST); 12256 size(4); 12257 format %{ "FSTD $src,$mem\t! store vector (8 bytes)" %} 12258 ins_encode %{ 12259 __ str_double($src$$FloatRegister, $mem$$Address); 12260 %} 12261 ins_pipe(fstoreD_mem_reg); 12262 %} 12263 12264 // Store Vector in Double Register Pair to memory 12265 instruct storeV16(memoryvld mem, vecX src) %{ 12266 predicate(n->as_StoreVector()->memory_size() == 16); 12267 match(Set mem (StoreVector mem src)); 12268 ins_cost(MEMORY_REF_COST); 12269 size(4); 12270 format %{ "VST1 $src,$mem\t! store vector (16 bytes)" %} 12271 ins_encode %{ 12272 __ vst1($src$$FloatRegister, $mem$$Address, MacroAssembler::VELEM_SIZE_16, 128); 12273 %} 12274 ins_pipe(fstoreD_mem_reg); // FIXME 12275 %} 12276 12277 #ifndef AARCH64 12278 // Replicate scalar to packed byte values in Double register 12279 instruct Repl8B_reg(vecD dst, iRegI src, iRegI tmp) %{ 12280 predicate(n->as_Vector()->length() == 8); 12281 match(Set dst (ReplicateB src)); 12282 ins_cost(DEFAULT_COST*4); 12283 effect(TEMP tmp); 12284 size(16); 12285 12286 // FIXME: could use PKH instruction instead? 12287 format %{ "LSL $tmp, $src, 24 \n\t" 12288 "OR $tmp, $tmp, ($tmp >> 8) \n\t" 12289 "OR $tmp, $tmp, ($tmp >> 16) \n\t" 12290 "FMDRR $dst,$tmp,$tmp\t" %} 12291 ins_encode %{ 12292 __ mov($tmp$$Register, AsmOperand($src$$Register, lsl, 24)); 12293 __ orr($tmp$$Register, $tmp$$Register, AsmOperand($tmp$$Register, lsr, 8)); 12294 __ orr($tmp$$Register, $tmp$$Register, AsmOperand($tmp$$Register, lsr, 16)); 12295 __ fmdrr($dst$$FloatRegister, $tmp$$Register, $tmp$$Register); 12296 %} 12297 ins_pipe(ialu_reg); // FIXME 12298 %} 12299 #endif /* !AARCH64 */ 12300 12301 // Replicate scalar to packed byte values in Double register 12302 instruct Repl8B_reg_simd(vecD dst, iRegI src) %{ 12303 predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd()); 12304 match(Set dst (ReplicateB src)); 12305 size(4); 12306 12307 format %{ "VDUP.8 $dst,$src\t" %} 12308 ins_encode %{ 12309 bool quad = false; 12310 __ vdupI($dst$$FloatRegister, $src$$Register, 12311 MacroAssembler::VELEM_SIZE_8, quad); 12312 %} 12313 ins_pipe(ialu_reg); // FIXME 12314 %} 12315 12316 // Replicate scalar to packed byte values in Double register pair 12317 instruct Repl16B_reg(vecX dst, iRegI src) %{ 12318 predicate(n->as_Vector()->length_in_bytes() == 16); 12319 match(Set dst (ReplicateB src)); 12320 size(4); 12321 12322 format %{ "VDUP.8 $dst.Q,$src\t" %} 12323 ins_encode %{ 12324 bool quad = true; 12325 __ vdupI($dst$$FloatRegister, $src$$Register, 12326 MacroAssembler::VELEM_SIZE_8, quad); 12327 %} 12328 ins_pipe(ialu_reg); // FIXME 12329 %} 12330 12331 #ifndef AARCH64 12332 // Replicate scalar constant to packed byte values in Double register 12333 instruct Repl8B_immI(vecD dst, immI src, iRegI tmp) %{ 12334 predicate(n->as_Vector()->length() == 8); 12335 match(Set dst (ReplicateB src)); 12336 ins_cost(DEFAULT_COST*2); 12337 effect(TEMP tmp); 12338 size(12); 12339 12340 format %{ "MOV $tmp, Repl4($src))\n\t" 12341 "FMDRR $dst,$tmp,$tmp\t" %} 12342 ins_encode( LdReplImmI(src, dst, tmp, (4), (1)) ); 12343 ins_pipe(loadConFD); // FIXME 12344 %} 12345 #endif /* !AARCH64 */ 12346 12347 // Replicate scalar constant to packed byte values in Double register 12348 // TODO: support negative constants with MVNI? 12349 instruct Repl8B_immU8(vecD dst, immU8 src) %{ 12350 predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd()); 12351 match(Set dst (ReplicateB src)); 12352 size(4); 12353 12354 format %{ "VMOV.U8 $dst,$src" %} 12355 ins_encode %{ 12356 bool quad = false; 12357 __ vmovI($dst$$FloatRegister, $src$$constant, 12358 MacroAssembler::VELEM_SIZE_8, quad); 12359 %} 12360 ins_pipe(loadConFD); // FIXME 12361 %} 12362 12363 // Replicate scalar constant to packed byte values in Double register pair 12364 instruct Repl16B_immU8(vecX dst, immU8 src) %{ 12365 predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd()); 12366 match(Set dst (ReplicateB src)); 12367 size(4); 12368 12369 format %{ "VMOV.U8 $dst.Q,$src" %} 12370 ins_encode %{ 12371 bool quad = true; 12372 __ vmovI($dst$$FloatRegister, $src$$constant, 12373 MacroAssembler::VELEM_SIZE_8, quad); 12374 %} 12375 ins_pipe(loadConFD); // FIXME 12376 %} 12377 12378 #ifndef AARCH64 12379 // Replicate scalar to packed short/char values into Double register 12380 instruct Repl4S_reg(vecD dst, iRegI src, iRegI tmp) %{ 12381 predicate(n->as_Vector()->length() == 4); 12382 match(Set dst (ReplicateS src)); 12383 ins_cost(DEFAULT_COST*3); 12384 effect(TEMP tmp); 12385 size(12); 12386 12387 // FIXME: could use PKH instruction instead? 12388 format %{ "LSL $tmp, $src, 16 \n\t" 12389 "OR $tmp, $tmp, ($tmp >> 16) \n\t" 12390 "FMDRR $dst,$tmp,$tmp\t" %} 12391 ins_encode %{ 12392 __ mov($tmp$$Register, AsmOperand($src$$Register, lsl, 16)); 12393 __ orr($tmp$$Register, $tmp$$Register, AsmOperand($tmp$$Register, lsr, 16)); 12394 __ fmdrr($dst$$FloatRegister, $tmp$$Register, $tmp$$Register); 12395 %} 12396 ins_pipe(ialu_reg); // FIXME 12397 %} 12398 #endif /* !AARCH64 */ 12399 12400 // Replicate scalar to packed byte values in Double register 12401 instruct Repl4S_reg_simd(vecD dst, iRegI src) %{ 12402 predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd()); 12403 match(Set dst (ReplicateS src)); 12404 size(4); 12405 12406 format %{ "VDUP.16 $dst,$src\t" %} 12407 ins_encode %{ 12408 bool quad = false; 12409 __ vdupI($dst$$FloatRegister, $src$$Register, 12410 MacroAssembler::VELEM_SIZE_16, quad); 12411 %} 12412 ins_pipe(ialu_reg); // FIXME 12413 %} 12414 12415 // Replicate scalar to packed byte values in Double register pair 12416 instruct Repl8S_reg(vecX dst, iRegI src) %{ 12417 predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd()); 12418 match(Set dst (ReplicateS src)); 12419 size(4); 12420 12421 format %{ "VDUP.16 $dst.Q,$src\t" %} 12422 ins_encode %{ 12423 bool quad = true; 12424 __ vdupI($dst$$FloatRegister, $src$$Register, 12425 MacroAssembler::VELEM_SIZE_16, quad); 12426 %} 12427 ins_pipe(ialu_reg); // FIXME 12428 %} 12429 12430 12431 #ifndef AARCH64 12432 // Replicate scalar constant to packed short/char values in Double register 12433 instruct Repl4S_immI(vecD dst, immI src, iRegP tmp) %{ 12434 predicate(n->as_Vector()->length() == 4); 12435 match(Set dst (ReplicateS src)); 12436 effect(TEMP tmp); 12437 size(12); 12438 ins_cost(DEFAULT_COST*4); // FIXME 12439 12440 format %{ "MOV $tmp, Repl2($src))\n\t" 12441 "FMDRR $dst,$tmp,$tmp\t" %} 12442 ins_encode( LdReplImmI(src, dst, tmp, (2), (2)) ); 12443 ins_pipe(loadConFD); // FIXME 12444 %} 12445 #endif /* !AARCH64 */ 12446 12447 // Replicate scalar constant to packed byte values in Double register 12448 instruct Repl4S_immU8(vecD dst, immU8 src) %{ 12449 predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd()); 12450 match(Set dst (ReplicateS src)); 12451 size(4); 12452 12453 format %{ "VMOV.U16 $dst,$src" %} 12454 ins_encode %{ 12455 bool quad = false; 12456 __ vmovI($dst$$FloatRegister, $src$$constant, 12457 MacroAssembler::VELEM_SIZE_16, quad); 12458 %} 12459 ins_pipe(loadConFD); // FIXME 12460 %} 12461 12462 // Replicate scalar constant to packed byte values in Double register pair 12463 instruct Repl8S_immU8(vecX dst, immU8 src) %{ 12464 predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd()); 12465 match(Set dst (ReplicateS src)); 12466 size(4); 12467 12468 format %{ "VMOV.U16 $dst.Q,$src" %} 12469 ins_encode %{ 12470 bool quad = true; 12471 __ vmovI($dst$$FloatRegister, $src$$constant, 12472 MacroAssembler::VELEM_SIZE_16, quad); 12473 %} 12474 ins_pipe(loadConFD); // FIXME 12475 %} 12476 12477 #ifndef AARCH64 12478 // Replicate scalar to packed int values in Double register 12479 instruct Repl2I_reg(vecD dst, iRegI src) %{ 12480 predicate(n->as_Vector()->length() == 2); 12481 match(Set dst (ReplicateI src)); 12482 size(4); 12483 12484 format %{ "FMDRR $dst,$src,$src\t" %} 12485 ins_encode %{ 12486 __ fmdrr($dst$$FloatRegister, $src$$Register, $src$$Register); 12487 %} 12488 ins_pipe(ialu_reg); // FIXME 12489 %} 12490 12491 // Replicate scalar to packed int values in Double register pair 12492 instruct Repl4I_reg(vecX dst, iRegI src) %{ 12493 predicate(n->as_Vector()->length() == 4); 12494 match(Set dst (ReplicateI src)); 12495 ins_cost(DEFAULT_COST*2); 12496 size(8); 12497 12498 format %{ "FMDRR $dst.lo,$src,$src\n\t" 12499 "FMDRR $dst.hi,$src,$src" %} 12500 12501 ins_encode %{ 12502 __ fmdrr($dst$$FloatRegister, $src$$Register, $src$$Register); 12503 __ fmdrr($dst$$FloatRegister->successor()->successor(), 12504 $src$$Register, $src$$Register); 12505 %} 12506 ins_pipe(ialu_reg); // FIXME 12507 %} 12508 #endif /* !AARCH64 */ 12509 12510 // Replicate scalar to packed int values in Double register 12511 instruct Repl2I_reg_simd(vecD dst, iRegI src) %{ 12512 predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd()); 12513 match(Set dst (ReplicateI src)); 12514 size(4); 12515 12516 format %{ "VDUP.32 $dst.D,$src\t" %} 12517 ins_encode %{ 12518 bool quad = false; 12519 __ vdupI($dst$$FloatRegister, $src$$Register, 12520 MacroAssembler::VELEM_SIZE_32, quad); 12521 %} 12522 ins_pipe(ialu_reg); // FIXME 12523 %} 12524 12525 // Replicate scalar to packed int values in Double register pair 12526 instruct Repl4I_reg_simd(vecX dst, iRegI src) %{ 12527 predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd()); 12528 match(Set dst (ReplicateI src)); 12529 size(4); 12530 12531 format %{ "VDUP.32 $dst.Q,$src\t" %} 12532 ins_encode %{ 12533 bool quad = true; 12534 __ vdupI($dst$$FloatRegister, $src$$Register, 12535 MacroAssembler::VELEM_SIZE_32, quad); 12536 %} 12537 ins_pipe(ialu_reg); // FIXME 12538 %} 12539 12540 12541 #ifndef AARCH64 12542 // Replicate scalar zero constant to packed int values in Double register 12543 instruct Repl2I_immI(vecD dst, immI src, iRegI tmp) %{ 12544 predicate(n->as_Vector()->length() == 2); 12545 match(Set dst (ReplicateI src)); 12546 effect(TEMP tmp); 12547 size(12); 12548 ins_cost(DEFAULT_COST*4); // FIXME 12549 12550 format %{ "MOV $tmp, Repl1($src))\n\t" 12551 "FMDRR $dst,$tmp,$tmp\t" %} 12552 ins_encode( LdReplImmI(src, dst, tmp, (1), (4)) ); 12553 ins_pipe(loadConFD); // FIXME 12554 %} 12555 #endif /* !AARCH64 */ 12556 12557 // Replicate scalar constant to packed byte values in Double register 12558 instruct Repl2I_immU8(vecD dst, immU8 src) %{ 12559 predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd()); 12560 match(Set dst (ReplicateI src)); 12561 size(4); 12562 12563 format %{ "VMOV.I32 $dst.D,$src" %} 12564 ins_encode %{ 12565 bool quad = false; 12566 __ vmovI($dst$$FloatRegister, $src$$constant, 12567 MacroAssembler::VELEM_SIZE_32, quad); 12568 %} 12569 ins_pipe(loadConFD); // FIXME 12570 %} 12571 12572 // Replicate scalar constant to packed byte values in Double register pair 12573 instruct Repl4I_immU8(vecX dst, immU8 src) %{ 12574 predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd()); 12575 match(Set dst (ReplicateI src)); 12576 size(4); 12577 12578 format %{ "VMOV.I32 $dst.Q,$src" %} 12579 ins_encode %{ 12580 bool quad = true; 12581 __ vmovI($dst$$FloatRegister, $src$$constant, 12582 MacroAssembler::VELEM_SIZE_32, quad); 12583 %} 12584 ins_pipe(loadConFD); // FIXME 12585 %} 12586 12587 #ifdef AARCH64 12588 // Replicate scalar to packed byte values in Double register pair 12589 instruct Repl2L_reg(vecX dst, iRegL src) %{ 12590 predicate(n->as_Vector()->length() == 2); 12591 match(Set dst (ReplicateL src)); 12592 size(4*1); 12593 ins_cost(DEFAULT_COST*1); // FIXME 12594 12595 format %{ "VDUP.2D $dst.Q,$src\t" %} 12596 ins_encode %{ 12597 bool quad = true; 12598 __ vdupI($dst$$FloatRegister, $src$$Register, 12599 MacroAssembler::VELEM_SIZE_64, quad); 12600 %} 12601 ins_pipe(ialu_reg); // FIXME 12602 %} 12603 #else /* !AARCH64 */ 12604 // Replicate scalar to packed byte values in Double register pair 12605 instruct Repl2L_reg(vecX dst, iRegL src) %{ 12606 predicate(n->as_Vector()->length() == 2); 12607 match(Set dst (ReplicateL src)); 12608 size(8); 12609 ins_cost(DEFAULT_COST*2); // FIXME 12610 12611 format %{ "FMDRR $dst.D,$src.lo,$src.hi\t\n" 12612 "FMDRR $dst.D.next,$src.lo,$src.hi" %} 12613 ins_encode %{ 12614 __ fmdrr($dst$$FloatRegister, $src$$Register, $src$$Register->successor()); 12615 __ fmdrr($dst$$FloatRegister->successor()->successor(), 12616 $src$$Register, $src$$Register->successor()); 12617 %} 12618 ins_pipe(ialu_reg); // FIXME 12619 %} 12620 12621 12622 // Replicate scalar to packed float values in Double register 12623 instruct Repl2F_regI(vecD dst, iRegI src) %{ 12624 predicate(n->as_Vector()->length() == 2); 12625 match(Set dst (ReplicateF src)); 12626 size(4); 12627 12628 format %{ "FMDRR $dst.D,$src,$src\t" %} 12629 ins_encode %{ 12630 __ fmdrr($dst$$FloatRegister, $src$$Register, $src$$Register); 12631 %} 12632 ins_pipe(ialu_reg); // FIXME 12633 %} 12634 12635 // Replicate scalar to packed float values in Double register 12636 instruct Repl2F_reg_vfp(vecD dst, regF src) %{ 12637 predicate(n->as_Vector()->length() == 2); 12638 match(Set dst (ReplicateF src)); 12639 size(4*2); 12640 ins_cost(DEFAULT_COST*2); // FIXME 12641 12642 expand %{ 12643 iRegI tmp; 12644 MoveF2I_reg_reg(tmp, src); 12645 Repl2F_regI(dst,tmp); 12646 %} 12647 %} 12648 #endif /* !AARCH64 */ 12649 12650 // Replicate scalar to packed float values in Double register 12651 instruct Repl2F_reg_simd(vecD dst, regF src) %{ 12652 predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd()); 12653 match(Set dst (ReplicateF src)); 12654 size(4); 12655 ins_cost(DEFAULT_COST); // FIXME 12656 12657 format %{ "VDUP.32 $dst.D,$src.D\t" %} 12658 ins_encode %{ 12659 bool quad = false; 12660 __ vdupF($dst$$FloatRegister, $src$$FloatRegister, quad); 12661 %} 12662 ins_pipe(ialu_reg); // FIXME 12663 %} 12664 12665 #ifndef AARCH64 12666 // Replicate scalar to packed float values in Double register pair 12667 instruct Repl4F_reg(vecX dst, regF src, iRegI tmp) %{ 12668 predicate(n->as_Vector()->length() == 4); 12669 match(Set dst (ReplicateF src)); 12670 effect(TEMP tmp); 12671 size(4*3); 12672 ins_cost(DEFAULT_COST*3); // FIXME 12673 12674 format %{ "FMRS $tmp,$src\n\t" 12675 "FMDRR $dst.D,$tmp,$tmp\n\t" 12676 "FMDRR $dst.D.next,$tmp,$tmp\t" %} 12677 ins_encode %{ 12678 __ fmrs($tmp$$Register, $src$$FloatRegister); 12679 __ fmdrr($dst$$FloatRegister, $tmp$$Register, $tmp$$Register); 12680 __ fmdrr($dst$$FloatRegister->successor()->successor(), 12681 $tmp$$Register, $tmp$$Register); 12682 %} 12683 ins_pipe(ialu_reg); // FIXME 12684 %} 12685 #endif /* !AARCH64 */ 12686 12687 // Replicate scalar to packed float values in Double register pair 12688 instruct Repl4F_reg_simd(vecX dst, regF src) %{ 12689 predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd()); 12690 match(Set dst (ReplicateF src)); 12691 size(4); 12692 ins_cost(DEFAULT_COST); // FIXME 12693 12694 format %{ "VDUP.32 $dst.Q,$src.D\t" %} 12695 ins_encode %{ 12696 bool quad = true; 12697 __ vdupF($dst$$FloatRegister, $src$$FloatRegister, quad); 12698 %} 12699 ins_pipe(ialu_reg); // FIXME 12700 %} 12701 12702 #ifndef AARCH64 12703 // Replicate scalar zero constant to packed float values in Double register 12704 instruct Repl2F_immI(vecD dst, immF src, iRegI tmp) %{ 12705 predicate(n->as_Vector()->length() == 2); 12706 match(Set dst (ReplicateF src)); 12707 effect(TEMP tmp); 12708 size(12); 12709 ins_cost(DEFAULT_COST*4); // FIXME 12710 12711 format %{ "MOV $tmp, Repl1($src))\n\t" 12712 "FMDRR $dst,$tmp,$tmp\t" %} 12713 ins_encode( LdReplImmF(src, dst, tmp) ); 12714 ins_pipe(loadConFD); // FIXME 12715 %} 12716 #endif /* !AAARCH64 */ 12717 12718 // Replicate scalar to packed double float values in Double register pair 12719 instruct Repl2D_reg(vecX dst, regD src) %{ 12720 #ifdef AARCH64 12721 predicate(n->as_Vector()->length() == 2 && VM_Version::has_simd()); 12722 match(Set dst (ReplicateD src)); 12723 size(4*1); 12724 ins_cost(DEFAULT_COST*1); // FIXME 12725 12726 format %{ "VDUP $dst.2D,$src\t" %} 12727 ins_encode %{ 12728 bool quad = true; 12729 __ vdupD($dst$$FloatRegister, $src$$FloatRegister, quad); 12730 %} 12731 #else 12732 predicate(n->as_Vector()->length() == 2); 12733 match(Set dst (ReplicateD src)); 12734 size(4*2); 12735 ins_cost(DEFAULT_COST*2); // FIXME 12736 12737 format %{ "FCPYD $dst.D.a,$src\n\t" 12738 "FCPYD $dst.D.b,$src\t" %} 12739 ins_encode %{ 12740 FloatRegister dsta = $dst$$FloatRegister; 12741 FloatRegister src = $src$$FloatRegister; 12742 __ fcpyd(dsta, src); 12743 FloatRegister dstb = dsta->successor()->successor(); 12744 __ fcpyd(dstb, src); 12745 %} 12746 #endif 12747 ins_pipe(ialu_reg); // FIXME 12748 %} 12749 12750 // ====================VECTOR ARITHMETIC======================================= 12751 12752 // --------------------------------- ADD -------------------------------------- 12753 12754 // Bytes vector add 12755 instruct vadd8B_reg(vecD dst, vecD src1, vecD src2) %{ 12756 predicate(n->as_Vector()->length() == 8); 12757 match(Set dst (AddVB src1 src2)); 12758 format %{ "VADD.I8 $dst,$src1,$src2\t! add packed8B" %} 12759 size(4); 12760 ins_encode %{ 12761 bool quad = false; 12762 __ vaddI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 12763 MacroAssembler::VELEM_SIZE_8, quad); 12764 %} 12765 ins_pipe( ialu_reg_reg ); // FIXME 12766 %} 12767 12768 instruct vadd16B_reg(vecX dst, vecX src1, vecX src2) %{ 12769 predicate(n->as_Vector()->length() == 16); 12770 match(Set dst (AddVB src1 src2)); 12771 size(4); 12772 format %{ "VADD.I8 $dst.Q,$src1.Q,$src2.Q\t! add packed16B" %} 12773 ins_encode %{ 12774 bool quad = true; 12775 __ vaddI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 12776 MacroAssembler::VELEM_SIZE_8, quad); 12777 %} 12778 ins_pipe( ialu_reg_reg ); // FIXME 12779 %} 12780 12781 // Shorts/Chars vector add 12782 instruct vadd4S_reg(vecD dst, vecD src1, vecD src2) %{ 12783 predicate(n->as_Vector()->length() == 4); 12784 match(Set dst (AddVS src1 src2)); 12785 size(4); 12786 format %{ "VADD.I16 $dst,$src1,$src2\t! add packed4S" %} 12787 ins_encode %{ 12788 bool quad = false; 12789 __ vaddI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 12790 MacroAssembler::VELEM_SIZE_16, quad); 12791 %} 12792 ins_pipe( ialu_reg_reg ); // FIXME 12793 %} 12794 12795 instruct vadd8S_reg(vecX dst, vecX src1, vecX src2) %{ 12796 predicate(n->as_Vector()->length() == 8); 12797 match(Set dst (AddVS src1 src2)); 12798 size(4); 12799 format %{ "VADD.I16 $dst.Q,$src1.Q,$src2.Q\t! add packed8S" %} 12800 ins_encode %{ 12801 bool quad = true; 12802 __ vaddI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 12803 MacroAssembler::VELEM_SIZE_16, quad); 12804 %} 12805 ins_pipe( ialu_reg_reg ); // FIXME 12806 %} 12807 12808 // Integers vector add 12809 instruct vadd2I_reg(vecD dst, vecD src1, vecD src2) %{ 12810 predicate(n->as_Vector()->length() == 2); 12811 match(Set dst (AddVI src1 src2)); 12812 size(4); 12813 format %{ "VADD.I32 $dst.D,$src1.D,$src2.D\t! add packed2I" %} 12814 ins_encode %{ 12815 bool quad = false; 12816 __ vaddI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 12817 MacroAssembler::VELEM_SIZE_32, quad); 12818 %} 12819 ins_pipe( ialu_reg_reg ); // FIXME 12820 %} 12821 12822 instruct vadd4I_reg(vecX dst, vecX src1, vecX src2) %{ 12823 predicate(n->as_Vector()->length() == 4); 12824 match(Set dst (AddVI src1 src2)); 12825 size(4); 12826 format %{ "VADD.I32 $dst.Q,$src1.Q,$src2.Q\t! add packed4I" %} 12827 ins_encode %{ 12828 bool quad = true; 12829 __ vaddI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 12830 MacroAssembler::VELEM_SIZE_32, quad); 12831 %} 12832 ins_pipe( ialu_reg_reg ); // FIXME 12833 %} 12834 12835 // Longs vector add 12836 instruct vadd2L_reg(vecX dst, vecX src1, vecX src2) %{ 12837 predicate(n->as_Vector()->length() == 2); 12838 match(Set dst (AddVL src1 src2)); 12839 size(4); 12840 format %{ "VADD.I64 $dst.Q,$src1.Q,$src2.Q\t! add packed2L" %} 12841 ins_encode %{ 12842 bool quad = true; 12843 __ vaddI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 12844 MacroAssembler::VELEM_SIZE_64, quad); 12845 %} 12846 ins_pipe( ialu_reg_reg ); // FIXME 12847 %} 12848 12849 // Floats vector add 12850 instruct vadd2F_reg(vecD dst, vecD src1, vecD src2) %{ 12851 predicate(n->as_Vector()->length() == 2 && VM_Version::simd_math_is_compliant()); 12852 match(Set dst (AddVF src1 src2)); 12853 size(4); 12854 format %{ "VADD.F32 $dst,$src1,$src2\t! add packed2F" %} 12855 ins_encode %{ 12856 bool quad = false; 12857 __ vaddF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 12858 MacroAssembler::VFA_SIZE_F32, quad); 12859 %} 12860 ins_pipe( faddD_reg_reg ); // FIXME 12861 %} 12862 12863 #ifndef AARCH64 12864 instruct vadd2F_reg_vfp(vecD dst, vecD src1, vecD src2) %{ 12865 predicate(n->as_Vector()->length() == 2 && !VM_Version::simd_math_is_compliant()); 12866 match(Set dst (AddVF src1 src2)); 12867 ins_cost(DEFAULT_COST*2); // FIXME 12868 12869 size(4*2); 12870 format %{ "FADDS $dst.a,$src1.a,$src2.a\n\t" 12871 "FADDS $dst.b,$src1.b,$src2.b" %} 12872 ins_encode %{ 12873 __ add_float($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister); 12874 __ add_float($dst$$FloatRegister->successor(), 12875 $src1$$FloatRegister->successor(), 12876 $src2$$FloatRegister->successor()); 12877 %} 12878 12879 ins_pipe(faddF_reg_reg); // FIXME 12880 %} 12881 #endif 12882 12883 instruct vadd4F_reg_simd(vecX dst, vecX src1, vecX src2) %{ 12884 predicate(n->as_Vector()->length() == 4 && VM_Version::simd_math_is_compliant()); 12885 match(Set dst (AddVF src1 src2)); 12886 size(4); 12887 format %{ "VADD.F32 $dst.Q,$src1.Q,$src2.Q\t! add packed4F" %} 12888 ins_encode %{ 12889 bool quad = true; 12890 __ vaddF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 12891 MacroAssembler::VFA_SIZE_F32, quad); 12892 %} 12893 ins_pipe( faddD_reg_reg ); // FIXME 12894 %} 12895 12896 #ifdef AARCH64 12897 instruct vadd2D_reg_simd(vecX dst, vecX src1, vecX src2) %{ 12898 predicate(n->as_Vector()->length() == 2 && VM_Version::simd_math_is_compliant()); 12899 match(Set dst (AddVD src1 src2)); 12900 size(4); 12901 format %{ "VADD.F64 $dst.Q,$src1.Q,$src2.Q\t! add packed2D" %} 12902 ins_encode %{ 12903 bool quad = true; 12904 __ vaddF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 12905 MacroAssembler::VFA_SIZE_F64, quad); 12906 %} 12907 ins_pipe( faddD_reg_reg ); // FIXME 12908 %} 12909 #else 12910 instruct vadd4F_reg_vfp(vecX dst, vecX src1, vecX src2) %{ 12911 predicate(n->as_Vector()->length() == 4 && !VM_Version::simd_math_is_compliant()); 12912 match(Set dst (AddVF src1 src2)); 12913 size(4*4); 12914 ins_cost(DEFAULT_COST*4); // FIXME 12915 12916 format %{ "FADDS $dst.a,$src1.a,$src2.a\n\t" 12917 "FADDS $dst.b,$src1.b,$src2.b\n\t" 12918 "FADDS $dst.c,$src1.c,$src2.c\n\t" 12919 "FADDS $dst.d,$src1.d,$src2.d" %} 12920 12921 ins_encode %{ 12922 FloatRegister dsta = $dst$$FloatRegister; 12923 FloatRegister src1a = $src1$$FloatRegister; 12924 FloatRegister src2a = $src2$$FloatRegister; 12925 __ add_float(dsta, src1a, src2a); 12926 FloatRegister dstb = dsta->successor(); 12927 FloatRegister src1b = src1a->successor(); 12928 FloatRegister src2b = src2a->successor(); 12929 __ add_float(dstb, src1b, src2b); 12930 FloatRegister dstc = dstb->successor(); 12931 FloatRegister src1c = src1b->successor(); 12932 FloatRegister src2c = src2b->successor(); 12933 __ add_float(dstc, src1c, src2c); 12934 FloatRegister dstd = dstc->successor(); 12935 FloatRegister src1d = src1c->successor(); 12936 FloatRegister src2d = src2c->successor(); 12937 __ add_float(dstd, src1d, src2d); 12938 %} 12939 12940 ins_pipe(faddF_reg_reg); // FIXME 12941 %} 12942 12943 instruct vadd2D_reg_vfp(vecX dst, vecX src1, vecX src2) %{ 12944 predicate(n->as_Vector()->length() == 2); 12945 match(Set dst (AddVD src1 src2)); 12946 size(4*2); 12947 ins_cost(DEFAULT_COST*2); // FIXME 12948 12949 format %{ "FADDD $dst.a,$src1.a,$src2.a\n\t" 12950 "FADDD $dst.b,$src1.b,$src2.b" %} 12951 12952 ins_encode %{ 12953 FloatRegister dsta = $dst$$FloatRegister; 12954 FloatRegister src1a = $src1$$FloatRegister; 12955 FloatRegister src2a = $src2$$FloatRegister; 12956 __ add_double(dsta, src1a, src2a); 12957 FloatRegister dstb = dsta->successor()->successor(); 12958 FloatRegister src1b = src1a->successor()->successor(); 12959 FloatRegister src2b = src2a->successor()->successor(); 12960 __ add_double(dstb, src1b, src2b); 12961 %} 12962 12963 ins_pipe(faddF_reg_reg); // FIXME 12964 %} 12965 #endif 12966 12967 12968 // Bytes vector sub 12969 instruct vsub8B_reg(vecD dst, vecD src1, vecD src2) %{ 12970 predicate(n->as_Vector()->length() == 8); 12971 match(Set dst (SubVB src1 src2)); 12972 size(4); 12973 format %{ "VSUB.I8 $dst,$src1,$src2\t! sub packed8B" %} 12974 ins_encode %{ 12975 bool quad = false; 12976 __ vsubI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 12977 MacroAssembler::VELEM_SIZE_8, quad); 12978 %} 12979 ins_pipe( ialu_reg_reg ); // FIXME 12980 %} 12981 12982 instruct vsub16B_reg(vecX dst, vecX src1, vecX src2) %{ 12983 predicate(n->as_Vector()->length() == 16); 12984 match(Set dst (SubVB src1 src2)); 12985 size(4); 12986 format %{ "VSUB.I8 $dst.Q,$src1.Q,$src2.Q\t! sub packed16B" %} 12987 ins_encode %{ 12988 bool quad = true; 12989 __ vsubI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 12990 MacroAssembler::VELEM_SIZE_8, quad); 12991 %} 12992 ins_pipe( ialu_reg_reg ); // FIXME 12993 %} 12994 12995 // Shorts/Chars vector sub 12996 instruct vsub4S_reg(vecD dst, vecD src1, vecD src2) %{ 12997 predicate(n->as_Vector()->length() == 4); 12998 match(Set dst (SubVS src1 src2)); 12999 size(4); 13000 format %{ "VSUB.I16 $dst,$src1,$src2\t! sub packed4S" %} 13001 ins_encode %{ 13002 bool quad = false; 13003 __ vsubI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 13004 MacroAssembler::VELEM_SIZE_16, quad); 13005 %} 13006 ins_pipe( ialu_reg_reg ); // FIXME 13007 %} 13008 13009 instruct vsub16S_reg(vecX dst, vecX src1, vecX src2) %{ 13010 predicate(n->as_Vector()->length() == 8); 13011 match(Set dst (SubVS src1 src2)); 13012 size(4); 13013 format %{ "VSUB.I16 $dst.Q,$src1.Q,$src2.Q\t! sub packed8S" %} 13014 ins_encode %{ 13015 bool quad = true; 13016 __ vsubI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 13017 MacroAssembler::VELEM_SIZE_16, quad); 13018 %} 13019 ins_pipe( ialu_reg_reg ); // FIXME 13020 %} 13021 13022 // Integers vector sub 13023 instruct vsub2I_reg(vecD dst, vecD src1, vecD src2) %{ 13024 predicate(n->as_Vector()->length() == 2); 13025 match(Set dst (SubVI src1 src2)); 13026 size(4); 13027 format %{ "VSUB.I32 $dst,$src1,$src2\t! sub packed2I" %} 13028 ins_encode %{ 13029 bool quad = false; 13030 __ vsubI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 13031 MacroAssembler::VELEM_SIZE_32, quad); 13032 %} 13033 ins_pipe( ialu_reg_reg ); // FIXME 13034 %} 13035 13036 instruct vsub4I_reg(vecX dst, vecX src1, vecX src2) %{ 13037 predicate(n->as_Vector()->length() == 4); 13038 match(Set dst (SubVI src1 src2)); 13039 size(4); 13040 format %{ "VSUB.I32 $dst.Q,$src1.Q,$src2.Q\t! sub packed4I" %} 13041 ins_encode %{ 13042 bool quad = true; 13043 __ vsubI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 13044 MacroAssembler::VELEM_SIZE_32, quad); 13045 %} 13046 ins_pipe( ialu_reg_reg ); // FIXME 13047 %} 13048 13049 // Longs vector sub 13050 instruct vsub2L_reg(vecX dst, vecX src1, vecX src2) %{ 13051 predicate(n->as_Vector()->length() == 2); 13052 match(Set dst (SubVL src1 src2)); 13053 size(4); 13054 format %{ "VSUB.I64 $dst.Q,$src1.Q,$src2.Q\t! sub packed2L" %} 13055 ins_encode %{ 13056 bool quad = true; 13057 __ vsubI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 13058 MacroAssembler::VELEM_SIZE_64, quad); 13059 %} 13060 ins_pipe( ialu_reg_reg ); // FIXME 13061 %} 13062 13063 // Floats vector sub 13064 instruct vsub2F_reg(vecD dst, vecD src1, vecD src2) %{ 13065 predicate(n->as_Vector()->length() == 2 && VM_Version::simd_math_is_compliant()); 13066 match(Set dst (SubVF src1 src2)); 13067 size(4); 13068 format %{ "VSUB.F32 $dst,$src1,$src2\t! sub packed2F" %} 13069 ins_encode %{ 13070 bool quad = false; 13071 __ vsubF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 13072 MacroAssembler::VFA_SIZE_F32, quad); 13073 %} 13074 ins_pipe( faddF_reg_reg ); // FIXME 13075 %} 13076 13077 #ifndef AARCH64 13078 instruct vsub2F_reg_vfp(vecD dst, vecD src1, vecD src2) %{ 13079 predicate(n->as_Vector()->length() == 2 && !VM_Version::simd_math_is_compliant()); 13080 match(Set dst (SubVF src1 src2)); 13081 size(4*2); 13082 ins_cost(DEFAULT_COST*2); // FIXME 13083 13084 format %{ "FSUBS $dst.a,$src1.a,$src2.a\n\t" 13085 "FSUBS $dst.b,$src1.b,$src2.b" %} 13086 13087 ins_encode %{ 13088 FloatRegister dsta = $dst$$FloatRegister; 13089 FloatRegister src1a = $src1$$FloatRegister; 13090 FloatRegister src2a = $src2$$FloatRegister; 13091 __ sub_float(dsta, src1a, src2a); 13092 FloatRegister dstb = dsta->successor(); 13093 FloatRegister src1b = src1a->successor(); 13094 FloatRegister src2b = src2a->successor(); 13095 __ sub_float(dstb, src1b, src2b); 13096 %} 13097 13098 ins_pipe(faddF_reg_reg); // FIXME 13099 %} 13100 #endif 13101 13102 13103 instruct vsub4F_reg(vecX dst, vecX src1, vecX src2) %{ 13104 predicate(n->as_Vector()->length() == 4 && VM_Version::simd_math_is_compliant()); 13105 match(Set dst (SubVF src1 src2)); 13106 size(4); 13107 format %{ "VSUB.F32 $dst.Q,$src1.Q,$src2.Q\t! sub packed4F" %} 13108 ins_encode %{ 13109 bool quad = true; 13110 __ vsubF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 13111 MacroAssembler::VFA_SIZE_F32, quad); 13112 %} 13113 ins_pipe( faddF_reg_reg ); // FIXME 13114 %} 13115 13116 #ifdef AARCH64 13117 instruct vsub2D_reg_simd(vecX dst, vecX src1, vecX src2) %{ 13118 predicate(n->as_Vector()->length() == 2 && VM_Version::simd_math_is_compliant()); 13119 match(Set dst (SubVD src1 src2)); 13120 size(4); 13121 format %{ "VSUB.F64 $dst.Q,$src1.Q,$src2.Q\t! add packed2D" %} 13122 ins_encode %{ 13123 bool quad = true; 13124 __ vsubF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 13125 MacroAssembler::VFA_SIZE_F64, quad); 13126 %} 13127 ins_pipe( faddD_reg_reg ); // FIXME 13128 %} 13129 #else 13130 instruct vsub4F_reg_vfp(vecX dst, vecX src1, vecX src2) %{ 13131 predicate(n->as_Vector()->length() == 4 && !VM_Version::simd_math_is_compliant()); 13132 match(Set dst (SubVF src1 src2)); 13133 size(4*4); 13134 ins_cost(DEFAULT_COST*4); // FIXME 13135 13136 format %{ "FSUBS $dst.a,$src1.a,$src2.a\n\t" 13137 "FSUBS $dst.b,$src1.b,$src2.b\n\t" 13138 "FSUBS $dst.c,$src1.c,$src2.c\n\t" 13139 "FSUBS $dst.d,$src1.d,$src2.d" %} 13140 13141 ins_encode %{ 13142 FloatRegister dsta = $dst$$FloatRegister; 13143 FloatRegister src1a = $src1$$FloatRegister; 13144 FloatRegister src2a = $src2$$FloatRegister; 13145 __ sub_float(dsta, src1a, src2a); 13146 FloatRegister dstb = dsta->successor(); 13147 FloatRegister src1b = src1a->successor(); 13148 FloatRegister src2b = src2a->successor(); 13149 __ sub_float(dstb, src1b, src2b); 13150 FloatRegister dstc = dstb->successor(); 13151 FloatRegister src1c = src1b->successor(); 13152 FloatRegister src2c = src2b->successor(); 13153 __ sub_float(dstc, src1c, src2c); 13154 FloatRegister dstd = dstc->successor(); 13155 FloatRegister src1d = src1c->successor(); 13156 FloatRegister src2d = src2c->successor(); 13157 __ sub_float(dstd, src1d, src2d); 13158 %} 13159 13160 ins_pipe(faddF_reg_reg); // FIXME 13161 %} 13162 13163 instruct vsub2D_reg_vfp(vecX dst, vecX src1, vecX src2) %{ 13164 predicate(n->as_Vector()->length() == 2); 13165 match(Set dst (SubVD src1 src2)); 13166 size(4*2); 13167 ins_cost(DEFAULT_COST*2); // FIXME 13168 13169 format %{ "FSUBD $dst.a,$src1.a,$src2.a\n\t" 13170 "FSUBD $dst.b,$src1.b,$src2.b" %} 13171 13172 ins_encode %{ 13173 FloatRegister dsta = $dst$$FloatRegister; 13174 FloatRegister src1a = $src1$$FloatRegister; 13175 FloatRegister src2a = $src2$$FloatRegister; 13176 __ sub_double(dsta, src1a, src2a); 13177 FloatRegister dstb = dsta->successor()->successor(); 13178 FloatRegister src1b = src1a->successor()->successor(); 13179 FloatRegister src2b = src2a->successor()->successor(); 13180 __ sub_double(dstb, src1b, src2b); 13181 %} 13182 13183 ins_pipe(faddF_reg_reg); // FIXME 13184 %} 13185 #endif 13186 13187 // Shorts/Chars vector mul 13188 instruct vmul4S_reg(vecD dst, vecD src1, vecD src2) %{ 13189 predicate(n->as_Vector()->length() == 4); 13190 match(Set dst (MulVS src1 src2)); 13191 size(4); 13192 format %{ "VMUL.I16 $dst,$src1,$src2\t! mul packed4S" %} 13193 ins_encode %{ 13194 __ vmulI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 13195 MacroAssembler::VELEM_SIZE_16, 0); 13196 %} 13197 ins_pipe( ialu_reg_reg ); // FIXME 13198 %} 13199 13200 instruct vmul8S_reg(vecX dst, vecX src1, vecX src2) %{ 13201 predicate(n->as_Vector()->length() == 8); 13202 match(Set dst (MulVS src1 src2)); 13203 size(4); 13204 format %{ "VMUL.I16 $dst.Q,$src1.Q,$src2.Q\t! mul packed8S" %} 13205 ins_encode %{ 13206 __ vmulI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 13207 MacroAssembler::VELEM_SIZE_16, 1); 13208 %} 13209 ins_pipe( ialu_reg_reg ); // FIXME 13210 %} 13211 13212 // Integers vector mul 13213 instruct vmul2I_reg(vecD dst, vecD src1, vecD src2) %{ 13214 predicate(n->as_Vector()->length() == 2); 13215 match(Set dst (MulVI src1 src2)); 13216 size(4); 13217 format %{ "VMUL.I32 $dst,$src1,$src2\t! mul packed2I" %} 13218 ins_encode %{ 13219 __ vmulI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 13220 MacroAssembler::VELEM_SIZE_32, 0); 13221 %} 13222 ins_pipe( ialu_reg_reg ); // FIXME 13223 %} 13224 13225 instruct vmul4I_reg(vecX dst, vecX src1, vecX src2) %{ 13226 predicate(n->as_Vector()->length() == 4); 13227 match(Set dst (MulVI src1 src2)); 13228 size(4); 13229 format %{ "VMUL.I32 $dst.Q,$src1.Q,$src2.Q\t! mul packed4I" %} 13230 ins_encode %{ 13231 __ vmulI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 13232 MacroAssembler::VELEM_SIZE_32, 1); 13233 %} 13234 ins_pipe( ialu_reg_reg ); // FIXME 13235 %} 13236 13237 // Floats vector mul 13238 instruct vmul2F_reg(vecD dst, vecD src1, vecD src2) %{ 13239 predicate(n->as_Vector()->length() == 2 && VM_Version::simd_math_is_compliant()); 13240 match(Set dst (MulVF src1 src2)); 13241 size(4); 13242 format %{ "VMUL.F32 $dst,$src1,$src2\t! mul packed2F" %} 13243 ins_encode %{ 13244 __ vmulF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 13245 MacroAssembler::VFA_SIZE_F32, 0); 13246 %} 13247 ins_pipe( fmulF_reg_reg ); // FIXME 13248 %} 13249 13250 #ifndef AARCH64 13251 instruct vmul2F_reg_vfp(vecD dst, vecD src1, vecD src2) %{ 13252 predicate(n->as_Vector()->length() == 2 && !VM_Version::simd_math_is_compliant()); 13253 match(Set dst (MulVF src1 src2)); 13254 size(4*2); 13255 ins_cost(DEFAULT_COST*2); // FIXME 13256 13257 format %{ "FMULS $dst.a,$src1.a,$src2.a\n\t" 13258 "FMULS $dst.b,$src1.b,$src2.b" %} 13259 ins_encode %{ 13260 __ mul_float($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister); 13261 __ mul_float($dst$$FloatRegister->successor(), 13262 $src1$$FloatRegister->successor(), 13263 $src2$$FloatRegister->successor()); 13264 %} 13265 13266 ins_pipe(fmulF_reg_reg); // FIXME 13267 %} 13268 #endif 13269 13270 instruct vmul4F_reg(vecX dst, vecX src1, vecX src2) %{ 13271 predicate(n->as_Vector()->length() == 4 && VM_Version::simd_math_is_compliant()); 13272 match(Set dst (MulVF src1 src2)); 13273 size(4); 13274 format %{ "VMUL.F32 $dst.Q,$src1.Q,$src2.Q\t! mul packed4F" %} 13275 ins_encode %{ 13276 __ vmulF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 13277 MacroAssembler::VFA_SIZE_F32, 1); 13278 %} 13279 ins_pipe( fmulF_reg_reg ); // FIXME 13280 %} 13281 13282 #ifndef AARCH64 13283 instruct vmul4F_reg_vfp(vecX dst, vecX src1, vecX src2) %{ 13284 predicate(n->as_Vector()->length() == 4 && !VM_Version::simd_math_is_compliant()); 13285 match(Set dst (MulVF src1 src2)); 13286 size(4*4); 13287 ins_cost(DEFAULT_COST*4); // FIXME 13288 13289 format %{ "FMULS $dst.a,$src1.a,$src2.a\n\t" 13290 "FMULS $dst.b,$src1.b,$src2.b\n\t" 13291 "FMULS $dst.c,$src1.c,$src2.c\n\t" 13292 "FMULS $dst.d,$src1.d,$src2.d" %} 13293 13294 ins_encode %{ 13295 FloatRegister dsta = $dst$$FloatRegister; 13296 FloatRegister src1a = $src1$$FloatRegister; 13297 FloatRegister src2a = $src2$$FloatRegister; 13298 __ mul_float(dsta, src1a, src2a); 13299 FloatRegister dstb = dsta->successor(); 13300 FloatRegister src1b = src1a->successor(); 13301 FloatRegister src2b = src2a->successor(); 13302 __ mul_float(dstb, src1b, src2b); 13303 FloatRegister dstc = dstb->successor(); 13304 FloatRegister src1c = src1b->successor(); 13305 FloatRegister src2c = src2b->successor(); 13306 __ mul_float(dstc, src1c, src2c); 13307 FloatRegister dstd = dstc->successor(); 13308 FloatRegister src1d = src1c->successor(); 13309 FloatRegister src2d = src2c->successor(); 13310 __ mul_float(dstd, src1d, src2d); 13311 %} 13312 13313 ins_pipe(fmulF_reg_reg); // FIXME 13314 %} 13315 #endif 13316 13317 #ifdef AARCH64 13318 instruct vmul2D_reg(vecX dst, vecX src1, vecX src2) %{ 13319 predicate(n->as_Vector()->length() == 2 && VM_Version::has_simd()); 13320 match(Set dst (MulVD src1 src2)); 13321 size(4*1); 13322 ins_cost(DEFAULT_COST*1); // FIXME 13323 13324 format %{ "FMUL.2D $dst,$src1,$src2\t! double[2]" %} 13325 ins_encode %{ 13326 int quad = 1; 13327 __ vmulF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 13328 MacroAssembler::VFA_SIZE_F64, quad); 13329 %} 13330 13331 ins_pipe(fdivF_reg_reg); // FIXME 13332 %} 13333 #else 13334 instruct vmul2D_reg_vfp(vecX dst, vecX src1, vecX src2) %{ 13335 predicate(n->as_Vector()->length() == 2); 13336 match(Set dst (MulVD src1 src2)); 13337 size(4*2); 13338 ins_cost(DEFAULT_COST*2); // FIXME 13339 13340 format %{ "FMULD $dst.D.a,$src1.D.a,$src2.D.a\n\t" 13341 "FMULD $dst.D.b,$src1.D.b,$src2.D.b" %} 13342 ins_encode %{ 13343 FloatRegister dsta = $dst$$FloatRegister; 13344 FloatRegister src1a = $src1$$FloatRegister; 13345 FloatRegister src2a = $src2$$FloatRegister; 13346 __ mul_double(dsta, src1a, src2a); 13347 FloatRegister dstb = dsta->successor()->successor(); 13348 FloatRegister src1b = src1a->successor()->successor(); 13349 FloatRegister src2b = src2a->successor()->successor(); 13350 __ mul_double(dstb, src1b, src2b); 13351 %} 13352 13353 ins_pipe(fmulD_reg_reg); // FIXME 13354 %} 13355 #endif 13356 13357 13358 // Floats vector div 13359 instruct vdiv2F_reg_vfp(vecD dst, vecD src1, vecD src2) %{ 13360 predicate(n->as_Vector()->length() == 2); 13361 match(Set dst (DivVF src1 src2)); 13362 #ifdef AARCH64 13363 size(4*1); 13364 ins_cost(DEFAULT_COST*1); // FIXME 13365 13366 format %{ "FDIV.2S $dst,$src1,$src2\t! float[2]" %} 13367 ins_encode %{ 13368 int quad = 0; 13369 __ vdivF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 13370 MacroAssembler::VFA_SIZE_F32, quad); 13371 %} 13372 13373 ins_pipe(fdivF_reg_reg); // FIXME 13374 #else 13375 size(4*2); 13376 ins_cost(DEFAULT_COST*2); // FIXME 13377 13378 format %{ "FDIVS $dst.a,$src1.a,$src2.a\n\t" 13379 "FDIVS $dst.b,$src1.b,$src2.b" %} 13380 ins_encode %{ 13381 __ div_float($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister); 13382 __ div_float($dst$$FloatRegister->successor(), 13383 $src1$$FloatRegister->successor(), 13384 $src2$$FloatRegister->successor()); 13385 %} 13386 13387 ins_pipe(fdivF_reg_reg); // FIXME 13388 #endif 13389 %} 13390 13391 instruct vdiv4F_reg_vfp(vecX dst, vecX src1, vecX src2) %{ 13392 predicate(n->as_Vector()->length() == 4); 13393 match(Set dst (DivVF src1 src2)); 13394 #ifdef AARCH64 13395 size(4*1); 13396 ins_cost(DEFAULT_COST*1); // FIXME 13397 13398 format %{ "FDIV.4S $dst,$src1,$src2\t! float[4]" %} 13399 ins_encode %{ 13400 int quad = 1; 13401 __ vdivF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 13402 MacroAssembler::VFA_SIZE_F32, quad); 13403 %} 13404 13405 ins_pipe(fdivF_reg_reg); // FIXME 13406 #else 13407 size(4*4); 13408 ins_cost(DEFAULT_COST*4); // FIXME 13409 13410 format %{ "FDIVS $dst.a,$src1.a,$src2.a\n\t" 13411 "FDIVS $dst.b,$src1.b,$src2.b\n\t" 13412 "FDIVS $dst.c,$src1.c,$src2.c\n\t" 13413 "FDIVS $dst.d,$src1.d,$src2.d" %} 13414 13415 ins_encode %{ 13416 FloatRegister dsta = $dst$$FloatRegister; 13417 FloatRegister src1a = $src1$$FloatRegister; 13418 FloatRegister src2a = $src2$$FloatRegister; 13419 __ div_float(dsta, src1a, src2a); 13420 FloatRegister dstb = dsta->successor(); 13421 FloatRegister src1b = src1a->successor(); 13422 FloatRegister src2b = src2a->successor(); 13423 __ div_float(dstb, src1b, src2b); 13424 FloatRegister dstc = dstb->successor(); 13425 FloatRegister src1c = src1b->successor(); 13426 FloatRegister src2c = src2b->successor(); 13427 __ div_float(dstc, src1c, src2c); 13428 FloatRegister dstd = dstc->successor(); 13429 FloatRegister src1d = src1c->successor(); 13430 FloatRegister src2d = src2c->successor(); 13431 __ div_float(dstd, src1d, src2d); 13432 %} 13433 13434 ins_pipe(fdivF_reg_reg); // FIXME 13435 #endif 13436 %} 13437 13438 #ifdef AARCH64 13439 instruct vdiv2D_reg(vecX dst, vecX src1, vecX src2) %{ 13440 predicate(n->as_Vector()->length() == 2 && VM_Version::has_simd()); 13441 match(Set dst (DivVD src1 src2)); 13442 size(4*1); 13443 ins_cost(DEFAULT_COST*1); // FIXME 13444 13445 format %{ "FDIV.2D $dst,$src1,$src2\t! double[2]" %} 13446 ins_encode %{ 13447 int quad = 1; 13448 __ vdivF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 13449 MacroAssembler::VFA_SIZE_F64, quad); 13450 %} 13451 13452 ins_pipe(fdivF_reg_reg); // FIXME 13453 %} 13454 #else 13455 instruct vdiv2D_reg_vfp(vecX dst, vecX src1, vecX src2) %{ 13456 predicate(n->as_Vector()->length() == 2); 13457 match(Set dst (DivVD src1 src2)); 13458 size(4*2); 13459 ins_cost(DEFAULT_COST*2); // FIXME 13460 13461 format %{ "FDIVD $dst.D.a,$src1.D.a,$src2.D.a\n\t" 13462 "FDIVD $dst.D.b,$src1.D.b,$src2.D.b" %} 13463 ins_encode %{ 13464 FloatRegister dsta = $dst$$FloatRegister; 13465 FloatRegister src1a = $src1$$FloatRegister; 13466 FloatRegister src2a = $src2$$FloatRegister; 13467 __ div_double(dsta, src1a, src2a); 13468 FloatRegister dstb = dsta->successor()->successor(); 13469 FloatRegister src1b = src1a->successor()->successor(); 13470 FloatRegister src2b = src2a->successor()->successor(); 13471 __ div_double(dstb, src1b, src2b); 13472 %} 13473 13474 ins_pipe(fdivD_reg_reg); // FIXME 13475 %} 13476 #endif 13477 13478 // --------------------------------- NEG -------------------------------------- 13479 13480 instruct vneg8B_reg(vecD dst, vecD src) %{ 13481 predicate(n->as_Vector()->length_in_bytes() == 8); 13482 effect(DEF dst, USE src); 13483 size(4); 13484 ins_cost(DEFAULT_COST); // FIXME 13485 format %{ "VNEG.S8 $dst.D,$src.D\t! neg packed8B" %} 13486 ins_encode %{ 13487 bool quad = false; 13488 __ vnegI($dst$$FloatRegister, $src$$FloatRegister, 13489 MacroAssembler::VELEM_SIZE_8, quad); 13490 %} 13491 ins_pipe( ialu_reg_reg ); // FIXME 13492 %} 13493 13494 instruct vneg16B_reg(vecX dst, vecX src) %{ 13495 predicate(n->as_Vector()->length_in_bytes() == 16); 13496 effect(DEF dst, USE src); 13497 size(4); 13498 ins_cost(DEFAULT_COST); // FIXME 13499 format %{ "VNEG.S8 $dst.Q,$src.Q\t! neg0 packed16B" %} 13500 ins_encode %{ 13501 bool _float = false; 13502 bool quad = true; 13503 __ vnegI($dst$$FloatRegister, $src$$FloatRegister, 13504 MacroAssembler::VELEM_SIZE_8, quad); 13505 %} 13506 ins_pipe( ialu_reg_reg ); // FIXME 13507 %} 13508 13509 // ------------------------------ Shift --------------------------------------- 13510 13511 instruct vslcntD(vecD dst, iRegI cnt) %{ 13512 predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd()); 13513 match(Set dst (LShiftCntV cnt)); 13514 size(4); 13515 ins_cost(DEFAULT_COST); // FIXME 13516 expand %{ 13517 Repl8B_reg_simd(dst, cnt); 13518 %} 13519 %} 13520 13521 instruct vslcntX(vecX dst, iRegI cnt) %{ 13522 predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd()); 13523 match(Set dst (LShiftCntV cnt)); 13524 size(4); 13525 ins_cost(DEFAULT_COST); // FIXME 13526 expand %{ 13527 Repl16B_reg(dst, cnt); 13528 %} 13529 %} 13530 13531 // Low bits of vector "shift" elements are used, so it 13532 // doesn't matter if we treat it as ints or bytes here. 13533 instruct vsrcntD(vecD dst, iRegI cnt) %{ 13534 predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd()); 13535 match(Set dst (RShiftCntV cnt)); 13536 size(4*2); 13537 ins_cost(DEFAULT_COST*2); // FIXME 13538 13539 format %{ "VDUP.8 $dst.D,$cnt\n\t" 13540 "VNEG.S8 $dst.D,$dst.D\t! neg packed8B" %} 13541 ins_encode %{ 13542 bool quad = false; 13543 __ vdupI($dst$$FloatRegister, $cnt$$Register, 13544 MacroAssembler::VELEM_SIZE_8, quad); 13545 __ vnegI($dst$$FloatRegister, $dst$$FloatRegister, 13546 MacroAssembler::VELEM_SIZE_8, quad); 13547 %} 13548 ins_pipe( ialu_reg_reg ); // FIXME 13549 %} 13550 13551 instruct vsrcntX(vecX dst, iRegI cnt) %{ 13552 predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd()); 13553 match(Set dst (RShiftCntV cnt)); 13554 size(4*2); 13555 ins_cost(DEFAULT_COST*2); // FIXME 13556 format %{ "VDUP.8 $dst.Q,$cnt\n\t" 13557 "VNEG.S8 $dst.Q,$dst.Q\t! neg packed16B" %} 13558 ins_encode %{ 13559 bool quad = true; 13560 __ vdupI($dst$$FloatRegister, $cnt$$Register, 13561 MacroAssembler::VELEM_SIZE_8, quad); 13562 __ vnegI($dst$$FloatRegister, $dst$$FloatRegister, 13563 MacroAssembler::VELEM_SIZE_8, quad); 13564 %} 13565 ins_pipe( ialu_reg_reg ); // FIXME 13566 %} 13567 13568 // Byte vector logical left/right shift based on sign 13569 instruct vsh8B_reg(vecD dst, vecD src, vecD shift) %{ 13570 predicate(n->as_Vector()->length() == 8); 13571 effect(DEF dst, USE src, USE shift); 13572 size(4); 13573 ins_cost(DEFAULT_COST); // FIXME 13574 format %{ 13575 "VSHL.U8 $dst.D,$src.D,$shift.D\t! logical left/right shift packed8B" 13576 %} 13577 ins_encode %{ 13578 bool quad = false; 13579 __ vshlUI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister, 13580 MacroAssembler::VELEM_SIZE_8, quad); 13581 %} 13582 ins_pipe( ialu_reg_reg ); // FIXME 13583 %} 13584 13585 instruct vsh16B_reg(vecX dst, vecX src, vecX shift) %{ 13586 predicate(n->as_Vector()->length() == 16); 13587 effect(DEF dst, USE src, USE shift); 13588 size(4); 13589 ins_cost(DEFAULT_COST); // FIXME 13590 format %{ 13591 "VSHL.U8 $dst.Q,$src.Q,$shift.Q\t! logical left/right shift packed16B" 13592 %} 13593 ins_encode %{ 13594 bool quad = true; 13595 __ vshlUI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister, 13596 MacroAssembler::VELEM_SIZE_8, quad); 13597 %} 13598 ins_pipe( ialu_reg_reg ); // FIXME 13599 %} 13600 13601 // Shorts/Char vector logical left/right shift based on sign 13602 instruct vsh4S_reg(vecD dst, vecD src, vecD shift) %{ 13603 predicate(n->as_Vector()->length() == 4); 13604 effect(DEF dst, USE src, USE shift); 13605 size(4); 13606 ins_cost(DEFAULT_COST); // FIXME 13607 format %{ 13608 "VSHL.U16 $dst.D,$src.D,$shift.D\t! logical left/right shift packed4S" 13609 %} 13610 ins_encode %{ 13611 bool quad = false; 13612 __ vshlUI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister, 13613 MacroAssembler::VELEM_SIZE_16, quad); 13614 %} 13615 ins_pipe( ialu_reg_reg ); // FIXME 13616 %} 13617 13618 instruct vsh8S_reg(vecX dst, vecX src, vecX shift) %{ 13619 predicate(n->as_Vector()->length() == 8); 13620 effect(DEF dst, USE src, USE shift); 13621 size(4); 13622 ins_cost(DEFAULT_COST); // FIXME 13623 format %{ 13624 "VSHL.U16 $dst.Q,$src.Q,$shift.Q\t! logical left/right shift packed8S" 13625 %} 13626 ins_encode %{ 13627 bool quad = true; 13628 __ vshlUI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister, 13629 MacroAssembler::VELEM_SIZE_16, quad); 13630 %} 13631 ins_pipe( ialu_reg_reg ); // FIXME 13632 %} 13633 13634 // Integers vector logical left/right shift based on sign 13635 instruct vsh2I_reg(vecD dst, vecD src, vecD shift) %{ 13636 predicate(n->as_Vector()->length() == 2); 13637 effect(DEF dst, USE src, USE shift); 13638 size(4); 13639 ins_cost(DEFAULT_COST); // FIXME 13640 format %{ 13641 "VSHL.U32 $dst.D,$src.D,$shift.D\t! logical left/right shift packed2I" 13642 %} 13643 ins_encode %{ 13644 bool quad = false; 13645 __ vshlUI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister, 13646 MacroAssembler::VELEM_SIZE_32, quad); 13647 %} 13648 ins_pipe( ialu_reg_reg ); // FIXME 13649 %} 13650 13651 instruct vsh4I_reg(vecX dst, vecX src, vecX shift) %{ 13652 predicate(n->as_Vector()->length() == 4); 13653 effect(DEF dst, USE src, USE shift); 13654 size(4); 13655 ins_cost(DEFAULT_COST); // FIXME 13656 format %{ 13657 "VSHL.U32 $dst.Q,$src.Q,$shift.Q\t! logical left/right shift packed4I" 13658 %} 13659 ins_encode %{ 13660 bool quad = true; 13661 __ vshlUI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister, 13662 MacroAssembler::VELEM_SIZE_32, quad); 13663 %} 13664 ins_pipe( ialu_reg_reg ); // FIXME 13665 %} 13666 13667 // Longs vector logical left/right shift based on sign 13668 instruct vsh2L_reg(vecX dst, vecX src, vecX shift) %{ 13669 predicate(n->as_Vector()->length() == 2); 13670 effect(DEF dst, USE src, USE shift); 13671 size(4); 13672 ins_cost(DEFAULT_COST); // FIXME 13673 format %{ 13674 "VSHL.U64 $dst.Q,$src.Q,$shift.Q\t! logical left/right shift packed2L" 13675 %} 13676 ins_encode %{ 13677 bool quad = true; 13678 __ vshlUI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister, 13679 MacroAssembler::VELEM_SIZE_64, quad); 13680 %} 13681 ins_pipe( ialu_reg_reg ); // FIXME 13682 %} 13683 13684 // ------------------------------ LeftShift ----------------------------------- 13685 13686 // Byte vector left shift 13687 instruct vsl8B_reg(vecD dst, vecD src, vecD shift) %{ 13688 predicate(n->as_Vector()->length() == 8); 13689 match(Set dst (LShiftVB src shift)); 13690 size(4*1); 13691 ins_cost(DEFAULT_COST*1); // FIXME 13692 expand %{ 13693 vsh8B_reg(dst, src, shift); 13694 %} 13695 %} 13696 13697 instruct vsl16B_reg(vecX dst, vecX src, vecX shift) %{ 13698 predicate(n->as_Vector()->length() == 16); 13699 match(Set dst (LShiftVB src shift)); 13700 size(4*1); 13701 ins_cost(DEFAULT_COST*1); // FIXME 13702 expand %{ 13703 vsh16B_reg(dst, src, shift); 13704 %} 13705 %} 13706 13707 instruct vsl8B_immI(vecD dst, vecD src, immI shift) %{ 13708 predicate(n->as_Vector()->length() == 8); 13709 match(Set dst (LShiftVB src shift)); 13710 size(4); 13711 ins_cost(DEFAULT_COST); // FIXME 13712 format %{ 13713 "VSHL.I8 $dst.D,$src.D,$shift\t! logical left shift packed8B" 13714 %} 13715 ins_encode %{ 13716 bool quad = false; 13717 __ vshli($dst$$FloatRegister, $src$$FloatRegister, 8, $shift$$constant, 13718 quad); 13719 %} 13720 ins_pipe( ialu_reg_reg ); // FIXME 13721 %} 13722 13723 instruct vsl16B_immI(vecX dst, vecX src, immI shift) %{ 13724 predicate(n->as_Vector()->length() == 16); 13725 match(Set dst (LShiftVB src shift)); 13726 size(4); 13727 ins_cost(DEFAULT_COST); // FIXME 13728 format %{ 13729 "VSHL.I8 $dst.Q,$src.Q,$shift\t! logical left shift packed16B" 13730 %} 13731 ins_encode %{ 13732 bool quad = true; 13733 __ vshli($dst$$FloatRegister, $src$$FloatRegister, 8, $shift$$constant, 13734 quad); 13735 %} 13736 ins_pipe( ialu_reg_reg ); // FIXME 13737 %} 13738 13739 // Shorts/Chars vector logical left/right shift 13740 instruct vsl4S_reg(vecD dst, vecD src, vecD shift) %{ 13741 predicate(n->as_Vector()->length() == 4); 13742 match(Set dst (LShiftVS src shift)); 13743 match(Set dst (URShiftVS src shift)); 13744 size(4*1); 13745 ins_cost(DEFAULT_COST*1); // FIXME 13746 expand %{ 13747 vsh4S_reg(dst, src, shift); 13748 %} 13749 %} 13750 13751 instruct vsl8S_reg(vecX dst, vecX src, vecX shift) %{ 13752 predicate(n->as_Vector()->length() == 8); 13753 match(Set dst (LShiftVS src shift)); 13754 match(Set dst (URShiftVS src shift)); 13755 size(4*1); 13756 ins_cost(DEFAULT_COST*1); // FIXME 13757 expand %{ 13758 vsh8S_reg(dst, src, shift); 13759 %} 13760 %} 13761 13762 instruct vsl4S_immI(vecD dst, vecD src, immI shift) %{ 13763 predicate(n->as_Vector()->length() == 4); 13764 match(Set dst (LShiftVS src shift)); 13765 size(4); 13766 ins_cost(DEFAULT_COST); // FIXME 13767 format %{ 13768 "VSHL.I16 $dst.D,$src.D,$shift\t! logical left shift packed4S" 13769 %} 13770 ins_encode %{ 13771 bool quad = false; 13772 __ vshli($dst$$FloatRegister, $src$$FloatRegister, 16, $shift$$constant, 13773 quad); 13774 %} 13775 ins_pipe( ialu_reg_reg ); // FIXME 13776 %} 13777 13778 instruct vsl8S_immI(vecX dst, vecX src, immI shift) %{ 13779 predicate(n->as_Vector()->length() == 8); 13780 match(Set dst (LShiftVS src shift)); 13781 size(4); 13782 ins_cost(DEFAULT_COST); // FIXME 13783 format %{ 13784 "VSHL.I16 $dst.Q,$src.Q,$shift\t! logical left shift packed8S" 13785 %} 13786 ins_encode %{ 13787 bool quad = true; 13788 __ vshli($dst$$FloatRegister, $src$$FloatRegister, 16, $shift$$constant, 13789 quad); 13790 %} 13791 ins_pipe( ialu_reg_reg ); // FIXME 13792 %} 13793 13794 // Integers vector logical left/right shift 13795 instruct vsl2I_reg(vecD dst, vecD src, vecD shift) %{ 13796 predicate(n->as_Vector()->length() == 2 && VM_Version::has_simd()); 13797 match(Set dst (LShiftVI src shift)); 13798 match(Set dst (URShiftVI src shift)); 13799 size(4*1); 13800 ins_cost(DEFAULT_COST*1); // FIXME 13801 expand %{ 13802 vsh2I_reg(dst, src, shift); 13803 %} 13804 %} 13805 13806 instruct vsl4I_reg(vecX dst, vecX src, vecX shift) %{ 13807 predicate(n->as_Vector()->length() == 4 && VM_Version::has_simd()); 13808 match(Set dst (LShiftVI src shift)); 13809 match(Set dst (URShiftVI src shift)); 13810 size(4*1); 13811 ins_cost(DEFAULT_COST*1); // FIXME 13812 expand %{ 13813 vsh4I_reg(dst, src, shift); 13814 %} 13815 %} 13816 13817 instruct vsl2I_immI(vecD dst, vecD src, immI shift) %{ 13818 predicate(n->as_Vector()->length() == 2 && VM_Version::has_simd()); 13819 match(Set dst (LShiftVI src shift)); 13820 size(4); 13821 ins_cost(DEFAULT_COST); // FIXME 13822 format %{ 13823 "VSHL.I32 $dst.D,$src.D,$shift\t! logical left shift packed2I" 13824 %} 13825 ins_encode %{ 13826 bool quad = false; 13827 __ vshli($dst$$FloatRegister, $src$$FloatRegister, 32, $shift$$constant, 13828 quad); 13829 %} 13830 ins_pipe( ialu_reg_reg ); // FIXME 13831 %} 13832 13833 instruct vsl4I_immI(vecX dst, vecX src, immI shift) %{ 13834 predicate(n->as_Vector()->length() == 4 && VM_Version::has_simd()); 13835 match(Set dst (LShiftVI src shift)); 13836 size(4); 13837 ins_cost(DEFAULT_COST); // FIXME 13838 format %{ 13839 "VSHL.I32 $dst.Q,$src.Q,$shift\t! logical left shift packed4I" 13840 %} 13841 ins_encode %{ 13842 bool quad = true; 13843 __ vshli($dst$$FloatRegister, $src$$FloatRegister, 32, $shift$$constant, 13844 quad); 13845 %} 13846 ins_pipe( ialu_reg_reg ); // FIXME 13847 %} 13848 13849 // Longs vector logical left/right shift 13850 instruct vsl2L_reg(vecX dst, vecX src, vecX shift) %{ 13851 predicate(n->as_Vector()->length() == 2); 13852 match(Set dst (LShiftVL src shift)); 13853 match(Set dst (URShiftVL src shift)); 13854 size(4*1); 13855 ins_cost(DEFAULT_COST*1); // FIXME 13856 expand %{ 13857 vsh2L_reg(dst, src, shift); 13858 %} 13859 %} 13860 13861 instruct vsl2L_immI(vecX dst, vecX src, immI shift) %{ 13862 predicate(n->as_Vector()->length() == 2); 13863 match(Set dst (LShiftVL src shift)); 13864 size(4); 13865 ins_cost(DEFAULT_COST); // FIXME 13866 format %{ 13867 "VSHL.I64 $dst.Q,$src.Q,$shift\t! logical left shift packed2L" 13868 %} 13869 ins_encode %{ 13870 bool quad = true; 13871 __ vshli($dst$$FloatRegister, $src$$FloatRegister, 64, $shift$$constant, 13872 quad); 13873 %} 13874 ins_pipe( ialu_reg_reg ); // FIXME 13875 %} 13876 13877 // ----------------------- LogicalRightShift ----------------------------------- 13878 13879 // Bytes/Shorts vector logical right shift produces incorrect Java result 13880 // for negative data because java code convert short value into int with 13881 // sign extension before a shift. 13882 13883 // Chars vector logical right shift 13884 instruct vsrl4S_immI(vecD dst, vecD src, immI shift) %{ 13885 predicate(n->as_Vector()->length() == 4); 13886 match(Set dst (URShiftVS src shift)); 13887 size(4); 13888 ins_cost(DEFAULT_COST); // FIXME 13889 format %{ 13890 "VSHR.U16 $dst.D,$src.D,$shift\t! logical right shift packed4S" 13891 %} 13892 ins_encode %{ 13893 bool quad = false; 13894 __ vshrUI($dst$$FloatRegister, $src$$FloatRegister, 16, $shift$$constant, 13895 quad); 13896 %} 13897 ins_pipe( ialu_reg_reg ); // FIXME 13898 %} 13899 13900 instruct vsrl8S_immI(vecX dst, vecX src, immI shift) %{ 13901 predicate(n->as_Vector()->length() == 8); 13902 match(Set dst (URShiftVS src shift)); 13903 size(4); 13904 ins_cost(DEFAULT_COST); // FIXME 13905 format %{ 13906 "VSHR.U16 $dst.Q,$src.Q,$shift\t! logical right shift packed8S" 13907 %} 13908 ins_encode %{ 13909 bool quad = true; 13910 __ vshrUI($dst$$FloatRegister, $src$$FloatRegister, 16, $shift$$constant, 13911 quad); 13912 %} 13913 ins_pipe( ialu_reg_reg ); // FIXME 13914 %} 13915 13916 // Integers vector logical right shift 13917 instruct vsrl2I_immI(vecD dst, vecD src, immI shift) %{ 13918 predicate(n->as_Vector()->length() == 2 && VM_Version::has_simd()); 13919 match(Set dst (URShiftVI src shift)); 13920 size(4); 13921 ins_cost(DEFAULT_COST); // FIXME 13922 format %{ 13923 "VSHR.U32 $dst.D,$src.D,$shift\t! logical right shift packed2I" 13924 %} 13925 ins_encode %{ 13926 bool quad = false; 13927 __ vshrUI($dst$$FloatRegister, $src$$FloatRegister, 32, $shift$$constant, 13928 quad); 13929 %} 13930 ins_pipe( ialu_reg_reg ); // FIXME 13931 %} 13932 13933 instruct vsrl4I_immI(vecX dst, vecX src, immI shift) %{ 13934 predicate(n->as_Vector()->length() == 4 && VM_Version::has_simd()); 13935 match(Set dst (URShiftVI src shift)); 13936 size(4); 13937 ins_cost(DEFAULT_COST); // FIXME 13938 format %{ 13939 "VSHR.U32 $dst.Q,$src.Q,$shift\t! logical right shift packed4I" 13940 %} 13941 ins_encode %{ 13942 bool quad = true; 13943 __ vshrUI($dst$$FloatRegister, $src$$FloatRegister, 32, $shift$$constant, 13944 quad); 13945 %} 13946 ins_pipe( ialu_reg_reg ); // FIXME 13947 %} 13948 13949 // Longs vector logical right shift 13950 instruct vsrl2L_immI(vecX dst, vecX src, immI shift) %{ 13951 predicate(n->as_Vector()->length() == 2); 13952 match(Set dst (URShiftVL src shift)); 13953 size(4); 13954 ins_cost(DEFAULT_COST); // FIXME 13955 format %{ 13956 "VSHR.U64 $dst.Q,$src.Q,$shift\t! logical right shift packed2L" 13957 %} 13958 ins_encode %{ 13959 bool quad = true; 13960 __ vshrUI($dst$$FloatRegister, $src$$FloatRegister, 64, $shift$$constant, 13961 quad); 13962 %} 13963 ins_pipe( ialu_reg_reg ); // FIXME 13964 %} 13965 13966 // ------------------- ArithmeticRightShift ----------------------------------- 13967 13968 // Bytes vector arithmetic left/right shift based on sign 13969 instruct vsha8B_reg(vecD dst, vecD src, vecD shift) %{ 13970 predicate(n->as_Vector()->length() == 8); 13971 effect(DEF dst, USE src, USE shift); 13972 size(4); 13973 ins_cost(DEFAULT_COST); // FIXME 13974 format %{ 13975 "VSHL.S8 $dst.D,$src.D,$shift.D\t! arithmetic right shift packed8B" 13976 %} 13977 ins_encode %{ 13978 bool quad = false; 13979 __ vshlSI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister, 13980 MacroAssembler::VELEM_SIZE_8, quad); 13981 %} 13982 ins_pipe( ialu_reg_reg ); // FIXME 13983 %} 13984 13985 instruct vsha16B_reg(vecX dst, vecX src, vecX shift) %{ 13986 predicate(n->as_Vector()->length() == 16); 13987 effect(DEF dst, USE src, USE shift); 13988 size(4); 13989 ins_cost(DEFAULT_COST); // FIXME 13990 format %{ 13991 "VSHL.S8 $dst.Q,$src.Q,$shift.Q\t! arithmetic right shift packed16B" 13992 %} 13993 ins_encode %{ 13994 bool quad = true; 13995 __ vshlSI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister, 13996 MacroAssembler::VELEM_SIZE_8, quad); 13997 %} 13998 ins_pipe( ialu_reg_reg ); // FIXME 13999 %} 14000 14001 // Shorts vector arithmetic left/right shift based on sign 14002 instruct vsha4S_reg(vecD dst, vecD src, vecD shift) %{ 14003 predicate(n->as_Vector()->length() == 4); 14004 effect(DEF dst, USE src, USE shift); 14005 size(4); 14006 ins_cost(DEFAULT_COST); // FIXME 14007 format %{ 14008 "VSHL.S16 $dst.D,$src.D,$shift.D\t! arithmetic right shift packed4S" 14009 %} 14010 ins_encode %{ 14011 bool quad = false; 14012 __ vshlSI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister, 14013 MacroAssembler::VELEM_SIZE_16, quad); 14014 %} 14015 ins_pipe( ialu_reg_reg ); // FIXME 14016 %} 14017 14018 instruct vsha8S_reg(vecX dst, vecX src, vecX shift) %{ 14019 predicate(n->as_Vector()->length() == 8); 14020 effect(DEF dst, USE src, USE shift); 14021 size(4); 14022 ins_cost(DEFAULT_COST); // FIXME 14023 format %{ 14024 "VSHL.S16 $dst.Q,$src.Q,$shift.Q\t! arithmetic right shift packed8S" 14025 %} 14026 ins_encode %{ 14027 bool quad = true; 14028 __ vshlSI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister, 14029 MacroAssembler::VELEM_SIZE_16, quad); 14030 %} 14031 ins_pipe( ialu_reg_reg ); // FIXME 14032 %} 14033 14034 // Integers vector arithmetic left/right shift based on sign 14035 instruct vsha2I_reg(vecD dst, vecD src, vecD shift) %{ 14036 predicate(n->as_Vector()->length() == 2); 14037 effect(DEF dst, USE src, USE shift); 14038 size(4); 14039 ins_cost(DEFAULT_COST); // FIXME 14040 format %{ 14041 "VSHL.S32 $dst.D,$src.D,$shift.D\t! arithmetic right shift packed2I" 14042 %} 14043 ins_encode %{ 14044 bool quad = false; 14045 __ vshlSI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister, 14046 MacroAssembler::VELEM_SIZE_32, quad); 14047 %} 14048 ins_pipe( ialu_reg_reg ); // FIXME 14049 %} 14050 14051 instruct vsha4I_reg(vecX dst, vecX src, vecX shift) %{ 14052 predicate(n->as_Vector()->length() == 4); 14053 effect(DEF dst, USE src, USE shift); 14054 size(4); 14055 ins_cost(DEFAULT_COST); // FIXME 14056 format %{ 14057 "VSHL.S32 $dst.Q,$src.Q,$shift.Q\t! arithmetic right shift packed4I" 14058 %} 14059 ins_encode %{ 14060 bool quad = true; 14061 __ vshlSI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister, 14062 MacroAssembler::VELEM_SIZE_32, quad); 14063 %} 14064 ins_pipe( ialu_reg_reg ); // FIXME 14065 %} 14066 14067 // Longs vector arithmetic left/right shift based on sign 14068 instruct vsha2L_reg(vecX dst, vecX src, vecX shift) %{ 14069 predicate(n->as_Vector()->length() == 2); 14070 effect(DEF dst, USE src, USE shift); 14071 size(4); 14072 ins_cost(DEFAULT_COST); // FIXME 14073 format %{ 14074 "VSHL.S64 $dst.Q,$src.Q,$shift.Q\t! arithmetic right shift packed2L" 14075 %} 14076 ins_encode %{ 14077 bool quad = true; 14078 __ vshlSI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister, 14079 MacroAssembler::VELEM_SIZE_64, quad); 14080 %} 14081 ins_pipe( ialu_reg_reg ); // FIXME 14082 %} 14083 14084 // Byte vector arithmetic right shift 14085 14086 instruct vsra8B_reg(vecD dst, vecD src, vecD shift) %{ 14087 predicate(n->as_Vector()->length() == 8); 14088 match(Set dst (RShiftVB src shift)); 14089 size(4); 14090 ins_cost(DEFAULT_COST); // FIXME 14091 expand %{ 14092 vsha8B_reg(dst, src, shift); 14093 %} 14094 %} 14095 14096 instruct vsrl16B_reg(vecX dst, vecX src, vecX shift) %{ 14097 predicate(n->as_Vector()->length() == 16); 14098 match(Set dst (RShiftVB src shift)); 14099 size(4); 14100 ins_cost(DEFAULT_COST); // FIXME 14101 expand %{ 14102 vsha16B_reg(dst, src, shift); 14103 %} 14104 %} 14105 14106 instruct vsrl8B_immI(vecD dst, vecD src, immI shift) %{ 14107 predicate(n->as_Vector()->length() == 8); 14108 match(Set dst (RShiftVB src shift)); 14109 size(4); 14110 ins_cost(DEFAULT_COST); // FIXME 14111 format %{ 14112 "VSHR.S8 $dst.D,$src.D,$shift\t! logical right shift packed8B" 14113 %} 14114 ins_encode %{ 14115 bool quad = false; 14116 __ vshrSI($dst$$FloatRegister, $src$$FloatRegister, 8, $shift$$constant, 14117 quad); 14118 %} 14119 ins_pipe( ialu_reg_reg ); // FIXME 14120 %} 14121 14122 instruct vsrl16B_immI(vecX dst, vecX src, immI shift) %{ 14123 predicate(n->as_Vector()->length() == 16); 14124 match(Set dst (RShiftVB src shift)); 14125 size(4); 14126 ins_cost(DEFAULT_COST); // FIXME 14127 format %{ 14128 "VSHR.S8 $dst.Q,$src.Q,$shift\t! logical right shift packed16B" 14129 %} 14130 ins_encode %{ 14131 bool quad = true; 14132 __ vshrSI($dst$$FloatRegister, $src$$FloatRegister, 8, $shift$$constant, 14133 quad); 14134 %} 14135 ins_pipe( ialu_reg_reg ); // FIXME 14136 %} 14137 14138 // Shorts vector arithmetic right shift 14139 instruct vsra4S_reg(vecD dst, vecD src, vecD shift) %{ 14140 predicate(n->as_Vector()->length() == 4); 14141 match(Set dst (RShiftVS src shift)); 14142 size(4); 14143 ins_cost(DEFAULT_COST); // FIXME 14144 expand %{ 14145 vsha4S_reg(dst, src, shift); 14146 %} 14147 %} 14148 14149 instruct vsra8S_reg(vecX dst, vecX src, vecX shift) %{ 14150 predicate(n->as_Vector()->length() == 8); 14151 match(Set dst (RShiftVS src shift)); 14152 size(4); 14153 ins_cost(DEFAULT_COST); // FIXME 14154 expand %{ 14155 vsha8S_reg(dst, src, shift); 14156 %} 14157 %} 14158 14159 instruct vsra4S_immI(vecD dst, vecD src, immI shift) %{ 14160 predicate(n->as_Vector()->length() == 4); 14161 match(Set dst (RShiftVS src shift)); 14162 size(4); 14163 ins_cost(DEFAULT_COST); // FIXME 14164 format %{ 14165 "VSHR.S16 $dst.D,$src.D,$shift\t! logical right shift packed4S" 14166 %} 14167 ins_encode %{ 14168 bool quad = false; 14169 __ vshrSI($dst$$FloatRegister, $src$$FloatRegister, 16, $shift$$constant, 14170 quad); 14171 %} 14172 ins_pipe( ialu_reg_reg ); // FIXME 14173 %} 14174 14175 instruct vsra8S_immI(vecX dst, vecX src, immI shift) %{ 14176 predicate(n->as_Vector()->length() == 8); 14177 match(Set dst (RShiftVS src shift)); 14178 size(4); 14179 ins_cost(DEFAULT_COST); // FIXME 14180 format %{ 14181 "VSHR.S16 $dst.Q,$src.Q,$shift\t! logical right shift packed8S" 14182 %} 14183 ins_encode %{ 14184 bool quad = true; 14185 __ vshrSI($dst$$FloatRegister, $src$$FloatRegister, 16, $shift$$constant, 14186 quad); 14187 %} 14188 ins_pipe( ialu_reg_reg ); // FIXME 14189 %} 14190 14191 // Integers vector arithmetic right shift 14192 instruct vsra2I_reg(vecD dst, vecD src, vecD shift) %{ 14193 predicate(n->as_Vector()->length() == 2); 14194 match(Set dst (RShiftVI src shift)); 14195 size(4); 14196 ins_cost(DEFAULT_COST); // FIXME 14197 expand %{ 14198 vsha2I_reg(dst, src, shift); 14199 %} 14200 %} 14201 14202 instruct vsra4I_reg(vecX dst, vecX src, vecX shift) %{ 14203 predicate(n->as_Vector()->length() == 4); 14204 match(Set dst (RShiftVI src shift)); 14205 size(4); 14206 ins_cost(DEFAULT_COST); // FIXME 14207 expand %{ 14208 vsha4I_reg(dst, src, shift); 14209 %} 14210 %} 14211 14212 instruct vsra2I_immI(vecD dst, vecD src, immI shift) %{ 14213 predicate(n->as_Vector()->length() == 2); 14214 match(Set dst (RShiftVI src shift)); 14215 size(4); 14216 ins_cost(DEFAULT_COST); // FIXME 14217 format %{ 14218 "VSHR.S32 $dst.D,$src.D,$shift\t! logical right shift packed2I" 14219 %} 14220 ins_encode %{ 14221 bool quad = false; 14222 __ vshrSI($dst$$FloatRegister, $src$$FloatRegister, 32, $shift$$constant, 14223 quad); 14224 %} 14225 ins_pipe( ialu_reg_reg ); // FIXME 14226 %} 14227 14228 instruct vsra4I_immI(vecX dst, vecX src, immI shift) %{ 14229 predicate(n->as_Vector()->length() == 4); 14230 match(Set dst (RShiftVI src shift)); 14231 size(4); 14232 ins_cost(DEFAULT_COST); // FIXME 14233 format %{ 14234 "VSHR.S32 $dst.Q,$src.Q,$shift\t! logical right shift packed4I" 14235 %} 14236 ins_encode %{ 14237 bool quad = true; 14238 __ vshrSI($dst$$FloatRegister, $src$$FloatRegister, 32, $shift$$constant, 14239 quad); 14240 %} 14241 ins_pipe( ialu_reg_reg ); // FIXME 14242 %} 14243 14244 // Longs vector arithmetic right shift 14245 instruct vsra2L_reg(vecX dst, vecX src, vecX shift) %{ 14246 predicate(n->as_Vector()->length() == 2); 14247 match(Set dst (RShiftVL src shift)); 14248 size(4); 14249 ins_cost(DEFAULT_COST); // FIXME 14250 expand %{ 14251 vsha2L_reg(dst, src, shift); 14252 %} 14253 %} 14254 14255 instruct vsra2L_immI(vecX dst, vecX src, immI shift) %{ 14256 predicate(n->as_Vector()->length() == 2); 14257 match(Set dst (RShiftVL src shift)); 14258 size(4); 14259 ins_cost(DEFAULT_COST); // FIXME 14260 format %{ 14261 "VSHR.S64 $dst.Q,$src.Q,$shift\t! logical right shift packed2L" 14262 %} 14263 ins_encode %{ 14264 bool quad = true; 14265 __ vshrSI($dst$$FloatRegister, $src$$FloatRegister, 64, $shift$$constant, 14266 quad); 14267 %} 14268 ins_pipe( ialu_reg_reg ); // FIXME 14269 %} 14270 14271 // --------------------------------- AND -------------------------------------- 14272 14273 instruct vandD(vecD dst, vecD src1, vecD src2) %{ 14274 predicate(n->as_Vector()->length_in_bytes() == 8); 14275 match(Set dst (AndV src1 src2)); 14276 format %{ "VAND $dst.D,$src1.D,$src2.D\t! and vectors (8 bytes)" %} 14277 ins_encode %{ 14278 bool quad = false; 14279 __ vandI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 14280 quad); 14281 %} 14282 ins_pipe( ialu_reg_reg ); // FIXME 14283 %} 14284 14285 instruct vandX(vecX dst, vecX src1, vecX src2) %{ 14286 predicate(n->as_Vector()->length_in_bytes() == 16); 14287 match(Set dst (AndV src1 src2)); 14288 format %{ "VAND $dst.Q,$src1.Q,$src2.Q\t! and vectors (16 bytes)" %} 14289 ins_encode %{ 14290 bool quad = true; 14291 __ vandI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 14292 quad); 14293 %} 14294 ins_pipe( ialu_reg_reg ); // FIXME 14295 %} 14296 14297 // --------------------------------- OR --------------------------------------- 14298 14299 instruct vorD(vecD dst, vecD src1, vecD src2) %{ 14300 predicate(n->as_Vector()->length_in_bytes() == 8); 14301 match(Set dst (OrV src1 src2)); 14302 format %{ "VOR $dst.D,$src1.D,$src2.D\t! and vectors (8 bytes)" %} 14303 ins_encode %{ 14304 bool quad = false; 14305 __ vorI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 14306 quad); 14307 %} 14308 ins_pipe( ialu_reg_reg ); // FIXME 14309 %} 14310 14311 instruct vorX(vecX dst, vecX src1, vecX src2) %{ 14312 predicate(n->as_Vector()->length_in_bytes() == 16); 14313 match(Set dst (OrV src1 src2)); 14314 format %{ "VOR $dst.Q,$src1.Q,$src2.Q\t! and vectors (16 bytes)" %} 14315 ins_encode %{ 14316 bool quad = true; 14317 __ vorI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 14318 quad); 14319 %} 14320 ins_pipe( ialu_reg_reg ); // FIXME 14321 %} 14322 14323 // --------------------------------- XOR -------------------------------------- 14324 14325 instruct vxorD(vecD dst, vecD src1, vecD src2) %{ 14326 predicate(n->as_Vector()->length_in_bytes() == 8); 14327 match(Set dst (XorV src1 src2)); 14328 format %{ "VXOR $dst.D,$src1.D,$src2.D\t! and vectors (8 bytes)" %} 14329 ins_encode %{ 14330 bool quad = false; 14331 __ vxorI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 14332 quad); 14333 %} 14334 ins_pipe( ialu_reg_reg ); // FIXME 14335 %} 14336 14337 instruct vxorX(vecX dst, vecX src1, vecX src2) %{ 14338 predicate(n->as_Vector()->length_in_bytes() == 16); 14339 match(Set dst (XorV src1 src2)); 14340 format %{ "VXOR $dst.Q,$src1.Q,$src2.Q\t! and vectors (16 bytes)" %} 14341 ins_encode %{ 14342 bool quad = true; 14343 __ vxorI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 14344 quad); 14345 %} 14346 ins_pipe( ialu_reg_reg ); // FIXME 14347 %} 14348 14349 14350 //----------PEEPHOLE RULES----------------------------------------------------- 14351 // These must follow all instruction definitions as they use the names 14352 // defined in the instructions definitions. 14353 // 14354 // peepmatch ( root_instr_name [preceding_instruction]* ); 14355 // 14356 // peepconstraint %{ 14357 // (instruction_number.operand_name relational_op instruction_number.operand_name 14358 // [, ...] ); 14359 // // instruction numbers are zero-based using left to right order in peepmatch 14360 // 14361 // peepreplace ( instr_name ( [instruction_number.operand_name]* ) ); 14362 // // provide an instruction_number.operand_name for each operand that appears 14363 // // in the replacement instruction's match rule 14364 // 14365 // ---------VM FLAGS--------------------------------------------------------- 14366 // 14367 // All peephole optimizations can be turned off using -XX:-OptoPeephole 14368 // 14369 // Each peephole rule is given an identifying number starting with zero and 14370 // increasing by one in the order seen by the parser. An individual peephole 14371 // can be enabled, and all others disabled, by using -XX:OptoPeepholeAt=# 14372 // on the command-line. 14373 // 14374 // ---------CURRENT LIMITATIONS---------------------------------------------- 14375 // 14376 // Only match adjacent instructions in same basic block 14377 // Only equality constraints 14378 // Only constraints between operands, not (0.dest_reg == EAX_enc) 14379 // Only one replacement instruction 14380 // 14381 // ---------EXAMPLE---------------------------------------------------------- 14382 // 14383 // // pertinent parts of existing instructions in architecture description 14384 // instruct movI(eRegI dst, eRegI src) %{ 14385 // match(Set dst (CopyI src)); 14386 // %} 14387 // 14388 // instruct incI_eReg(eRegI dst, immI1 src, eFlagsReg cr) %{ 14389 // match(Set dst (AddI dst src)); 14390 // effect(KILL cr); 14391 // %} 14392 // 14393 // // Change (inc mov) to lea 14394 // peephole %{ 14395 // // increment preceeded by register-register move 14396 // peepmatch ( incI_eReg movI ); 14397 // // require that the destination register of the increment 14398 // // match the destination register of the move 14399 // peepconstraint ( 0.dst == 1.dst ); 14400 // // construct a replacement instruction that sets 14401 // // the destination to ( move's source register + one ) 14402 // peepreplace ( incI_eReg_immI1( 0.dst 1.src 0.src ) ); 14403 // %} 14404 // 14405 14406 // // Change load of spilled value to only a spill 14407 // instruct storeI(memory mem, eRegI src) %{ 14408 // match(Set mem (StoreI mem src)); 14409 // %} 14410 // 14411 // instruct loadI(eRegI dst, memory mem) %{ 14412 // match(Set dst (LoadI mem)); 14413 // %} 14414 // 14415 // peephole %{ 14416 // peepmatch ( loadI storeI ); 14417 // peepconstraint ( 1.src == 0.dst, 1.mem == 0.mem ); 14418 // peepreplace ( storeI( 1.mem 1.mem 1.src ) ); 14419 // %} 14420 14421 //----------SMARTSPILL RULES--------------------------------------------------- 14422 // These must follow all instruction definitions as they use the names 14423 // defined in the instructions definitions. 14424 // 14425 // ARM will probably not have any of these rules due to RISC instruction set. 14426 14427 //----------PIPELINE----------------------------------------------------------- 14428 // Rules which define the behavior of the target architectures pipeline.