1 // 2 // Copyright (c) 2008, 2017, 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 uint 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 uint 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 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 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 align_up((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 2699 operand flagsRegUL_LTGE() %{ 2700 constraint(ALLOC_IN_RC(int_flags)); 2701 match(RegFlags); 2702 2703 format %{ "apsr_UL_LTGE" %} 2704 interface(REG_INTER); 2705 %} 2706 2707 operand flagsRegUL_EQNE() %{ 2708 constraint(ALLOC_IN_RC(int_flags)); 2709 match(RegFlags); 2710 2711 format %{ "apsr_UL_EQNE" %} 2712 interface(REG_INTER); 2713 %} 2714 2715 operand flagsRegUL_LEGT() %{ 2716 constraint(ALLOC_IN_RC(int_flags)); 2717 match(RegFlags); 2718 2719 format %{ "apsr_UL_LEGT" %} 2720 interface(REG_INTER); 2721 %} 2722 #endif 2723 2724 // Condition Code Register, floating comparisons, unordered same as "less". 2725 operand flagsRegF() %{ 2726 constraint(ALLOC_IN_RC(float_flags)); 2727 match(RegFlags); 2728 2729 format %{ "fpscr_F" %} 2730 interface(REG_INTER); 2731 %} 2732 2733 // Vectors 2734 operand vecD() %{ 2735 constraint(ALLOC_IN_RC(actual_dflt_reg)); 2736 match(VecD); 2737 2738 format %{ %} 2739 interface(REG_INTER); 2740 %} 2741 2742 operand vecX() %{ 2743 constraint(ALLOC_IN_RC(vectorx_reg)); 2744 match(VecX); 2745 2746 format %{ %} 2747 interface(REG_INTER); 2748 %} 2749 2750 operand regD() %{ 2751 constraint(ALLOC_IN_RC(actual_dflt_reg)); 2752 match(RegD); 2753 match(regD_low); 2754 2755 format %{ %} 2756 interface(REG_INTER); 2757 %} 2758 2759 operand regF() %{ 2760 constraint(ALLOC_IN_RC(sflt_reg)); 2761 match(RegF); 2762 2763 format %{ %} 2764 interface(REG_INTER); 2765 %} 2766 2767 operand regD_low() %{ 2768 constraint(ALLOC_IN_RC(dflt_low_reg)); 2769 match(RegD); 2770 2771 format %{ %} 2772 interface(REG_INTER); 2773 %} 2774 2775 // Special Registers 2776 2777 // Method Register 2778 operand inline_cache_regP(iRegP reg) %{ 2779 constraint(ALLOC_IN_RC(Ricklass_regP)); 2780 match(reg); 2781 format %{ %} 2782 interface(REG_INTER); 2783 %} 2784 2785 operand interpreter_method_oop_regP(iRegP reg) %{ 2786 constraint(ALLOC_IN_RC(Rmethod_regP)); 2787 match(reg); 2788 format %{ %} 2789 interface(REG_INTER); 2790 %} 2791 2792 2793 //----------Complex Operands--------------------------------------------------- 2794 // Indirect Memory Reference 2795 operand indirect(sp_ptr_RegP reg) %{ 2796 constraint(ALLOC_IN_RC(sp_ptr_reg)); 2797 match(reg); 2798 2799 op_cost(100); 2800 format %{ "[$reg]" %} 2801 interface(MEMORY_INTER) %{ 2802 base($reg); 2803 #ifdef AARCH64 2804 index(0xff); // 0xff => no index 2805 #else 2806 index(0xf); // PC => no index 2807 #endif 2808 scale(0x0); 2809 disp(0x0); 2810 %} 2811 %} 2812 2813 #ifdef AARCH64 2814 // Indirect with scaled*1 uimm12 offset 2815 operand indOffsetU12ScaleB(sp_ptr_RegP reg, immUL12 offset) %{ 2816 constraint(ALLOC_IN_RC(sp_ptr_reg)); 2817 match(AddP reg offset); 2818 2819 op_cost(100); 2820 format %{ "[$reg + $offset]" %} 2821 interface(MEMORY_INTER) %{ 2822 base($reg); 2823 #ifdef AARCH64 2824 index(0xff); // 0xff => no index 2825 #else 2826 index(0xf); // PC => no index 2827 #endif 2828 scale(0x0); 2829 disp($offset); 2830 %} 2831 %} 2832 2833 // Indirect with scaled*2 uimm12 offset 2834 operand indOffsetU12ScaleS(sp_ptr_RegP reg, immUL12x2 offset) %{ 2835 constraint(ALLOC_IN_RC(sp_ptr_reg)); 2836 match(AddP reg offset); 2837 2838 op_cost(100); 2839 format %{ "[$reg + $offset]" %} 2840 interface(MEMORY_INTER) %{ 2841 base($reg); 2842 #ifdef AARCH64 2843 index(0xff); // 0xff => no index 2844 #else 2845 index(0xf); // PC => no index 2846 #endif 2847 scale(0x0); 2848 disp($offset); 2849 %} 2850 %} 2851 2852 // Indirect with scaled*4 uimm12 offset 2853 operand indOffsetU12ScaleI(sp_ptr_RegP reg, immUL12x4 offset) %{ 2854 constraint(ALLOC_IN_RC(sp_ptr_reg)); 2855 match(AddP reg offset); 2856 2857 op_cost(100); 2858 format %{ "[$reg + $offset]" %} 2859 interface(MEMORY_INTER) %{ 2860 base($reg); 2861 #ifdef AARCH64 2862 index(0xff); // 0xff => no index 2863 #else 2864 index(0xf); // PC => no index 2865 #endif 2866 scale(0x0); 2867 disp($offset); 2868 %} 2869 %} 2870 2871 // Indirect with scaled*8 uimm12 offset 2872 operand indOffsetU12ScaleL(sp_ptr_RegP reg, immUL12x8 offset) %{ 2873 constraint(ALLOC_IN_RC(sp_ptr_reg)); 2874 match(AddP reg offset); 2875 2876 op_cost(100); 2877 format %{ "[$reg + $offset]" %} 2878 interface(MEMORY_INTER) %{ 2879 base($reg); 2880 #ifdef AARCH64 2881 index(0xff); // 0xff => no index 2882 #else 2883 index(0xf); // PC => no index 2884 #endif 2885 scale(0x0); 2886 disp($offset); 2887 %} 2888 %} 2889 2890 // Indirect with scaled*16 uimm12 offset 2891 operand indOffsetU12ScaleQ(sp_ptr_RegP reg, immUL12x16 offset) %{ 2892 constraint(ALLOC_IN_RC(sp_ptr_reg)); 2893 match(AddP reg offset); 2894 2895 op_cost(100); 2896 format %{ "[$reg + $offset]" %} 2897 interface(MEMORY_INTER) %{ 2898 base($reg); 2899 #ifdef AARCH64 2900 index(0xff); // 0xff => no index 2901 #else 2902 index(0xf); // PC => no index 2903 #endif 2904 scale(0x0); 2905 disp($offset); 2906 %} 2907 %} 2908 2909 #else // ! AARCH64 2910 2911 // Indirect with Offset in ]-4096, 4096[ 2912 operand indOffset12(sp_ptr_RegP reg, immI12 offset) %{ 2913 constraint(ALLOC_IN_RC(sp_ptr_reg)); 2914 match(AddP reg offset); 2915 2916 op_cost(100); 2917 format %{ "[$reg + $offset]" %} 2918 interface(MEMORY_INTER) %{ 2919 base($reg); 2920 #ifdef AARCH64 2921 index(0xff); // 0xff => no index 2922 #else 2923 index(0xf); // PC => no index 2924 #endif 2925 scale(0x0); 2926 disp($offset); 2927 %} 2928 %} 2929 2930 // Indirect with offset for float load/store 2931 operand indOffsetFP(sp_ptr_RegP reg, immIFP offset) %{ 2932 constraint(ALLOC_IN_RC(sp_ptr_reg)); 2933 match(AddP reg offset); 2934 2935 op_cost(100); 2936 format %{ "[$reg + $offset]" %} 2937 interface(MEMORY_INTER) %{ 2938 base($reg); 2939 #ifdef AARCH64 2940 index(0xff); // 0xff => no index 2941 #else 2942 index(0xf); // PC => no index 2943 #endif 2944 scale(0x0); 2945 disp($offset); 2946 %} 2947 %} 2948 2949 // Indirect with Offset for half and double words 2950 operand indOffsetHD(sp_ptr_RegP reg, immIHD offset) %{ 2951 constraint(ALLOC_IN_RC(sp_ptr_reg)); 2952 match(AddP reg offset); 2953 2954 op_cost(100); 2955 format %{ "[$reg + $offset]" %} 2956 interface(MEMORY_INTER) %{ 2957 base($reg); 2958 #ifdef AARCH64 2959 index(0xff); // 0xff => no index 2960 #else 2961 index(0xf); // PC => no index 2962 #endif 2963 scale(0x0); 2964 disp($offset); 2965 %} 2966 %} 2967 2968 // Indirect with Offset and Offset+4 in ]-1024, 1024[ 2969 operand indOffsetFPx2(sp_ptr_RegP reg, immX10x2 offset) %{ 2970 constraint(ALLOC_IN_RC(sp_ptr_reg)); 2971 match(AddP reg offset); 2972 2973 op_cost(100); 2974 format %{ "[$reg + $offset]" %} 2975 interface(MEMORY_INTER) %{ 2976 base($reg); 2977 #ifdef AARCH64 2978 index(0xff); // 0xff => no index 2979 #else 2980 index(0xf); // PC => no index 2981 #endif 2982 scale(0x0); 2983 disp($offset); 2984 %} 2985 %} 2986 2987 // Indirect with Offset and Offset+4 in ]-4096, 4096[ 2988 operand indOffset12x2(sp_ptr_RegP reg, immI12x2 offset) %{ 2989 constraint(ALLOC_IN_RC(sp_ptr_reg)); 2990 match(AddP reg offset); 2991 2992 op_cost(100); 2993 format %{ "[$reg + $offset]" %} 2994 interface(MEMORY_INTER) %{ 2995 base($reg); 2996 #ifdef AARCH64 2997 index(0xff); // 0xff => no index 2998 #else 2999 index(0xf); // PC => no index 3000 #endif 3001 scale(0x0); 3002 disp($offset); 3003 %} 3004 %} 3005 #endif // !AARCH64 3006 3007 // Indirect with Register Index 3008 operand indIndex(iRegP addr, iRegX index) %{ 3009 constraint(ALLOC_IN_RC(ptr_reg)); 3010 match(AddP addr index); 3011 3012 op_cost(100); 3013 format %{ "[$addr + $index]" %} 3014 interface(MEMORY_INTER) %{ 3015 base($addr); 3016 index($index); 3017 scale(0x0); 3018 disp(0x0); 3019 %} 3020 %} 3021 3022 #ifdef AARCH64 3023 // Indirect Memory Times Scale Plus Index Register 3024 operand indIndexScaleS(iRegP addr, iRegX index, immI_1 scale) %{ 3025 constraint(ALLOC_IN_RC(ptr_reg)); 3026 match(AddP addr (LShiftX index scale)); 3027 3028 op_cost(100); 3029 format %{"[$addr + $index << $scale]" %} 3030 interface(MEMORY_INTER) %{ 3031 base($addr); 3032 index($index); 3033 scale($scale); 3034 disp(0x0); 3035 %} 3036 %} 3037 3038 // Indirect Memory Times Scale Plus 32-bit Index Register 3039 operand indIndexIScaleS(iRegP addr, iRegI index, immI_1 scale) %{ 3040 constraint(ALLOC_IN_RC(ptr_reg)); 3041 match(AddP addr (LShiftX (ConvI2L index) scale)); 3042 3043 op_cost(100); 3044 format %{"[$addr + $index.w << $scale]" %} 3045 interface(MEMORY_INTER) %{ 3046 base($addr); 3047 index($index); 3048 scale($scale); 3049 disp(0x7fffffff); // sxtw 3050 %} 3051 %} 3052 3053 // Indirect Memory Times Scale Plus Index Register 3054 operand indIndexScaleI(iRegP addr, iRegX index, immI_2 scale) %{ 3055 constraint(ALLOC_IN_RC(ptr_reg)); 3056 match(AddP addr (LShiftX index scale)); 3057 3058 op_cost(100); 3059 format %{"[$addr + $index << $scale]" %} 3060 interface(MEMORY_INTER) %{ 3061 base($addr); 3062 index($index); 3063 scale($scale); 3064 disp(0x0); 3065 %} 3066 %} 3067 3068 // Indirect Memory Times Scale Plus 32-bit Index Register 3069 operand indIndexIScaleI(iRegP addr, iRegI index, immI_2 scale) %{ 3070 constraint(ALLOC_IN_RC(ptr_reg)); 3071 match(AddP addr (LShiftX (ConvI2L index) scale)); 3072 3073 op_cost(100); 3074 format %{"[$addr + $index.w << $scale]" %} 3075 interface(MEMORY_INTER) %{ 3076 base($addr); 3077 index($index); 3078 scale($scale); 3079 disp(0x7fffffff); // sxtw 3080 %} 3081 %} 3082 3083 // Indirect Memory Times Scale Plus Index Register 3084 operand indIndexScaleL(iRegP addr, iRegX index, immI_3 scale) %{ 3085 constraint(ALLOC_IN_RC(ptr_reg)); 3086 match(AddP addr (LShiftX index scale)); 3087 3088 op_cost(100); 3089 format %{"[$addr + $index << $scale]" %} 3090 interface(MEMORY_INTER) %{ 3091 base($addr); 3092 index($index); 3093 scale($scale); 3094 disp(0x0); 3095 %} 3096 %} 3097 3098 // Indirect Memory Times Scale Plus 32-bit Index Register 3099 operand indIndexIScaleL(iRegP addr, iRegI index, immI_3 scale) %{ 3100 constraint(ALLOC_IN_RC(ptr_reg)); 3101 match(AddP addr (LShiftX (ConvI2L index) scale)); 3102 3103 op_cost(100); 3104 format %{"[$addr + $index.w << $scale]" %} 3105 interface(MEMORY_INTER) %{ 3106 base($addr); 3107 index($index); 3108 scale($scale); 3109 disp(0x7fffffff); // sxtw 3110 %} 3111 %} 3112 3113 // Indirect Memory Times Scale Plus Index Register 3114 operand indIndexScaleQ(iRegP addr, iRegX index, immI_4 scale) %{ 3115 constraint(ALLOC_IN_RC(ptr_reg)); 3116 match(AddP addr (LShiftX index scale)); 3117 3118 op_cost(100); 3119 format %{"[$addr + $index << $scale]" %} 3120 interface(MEMORY_INTER) %{ 3121 base($addr); 3122 index($index); 3123 scale($scale); 3124 disp(0x0); 3125 %} 3126 %} 3127 3128 // Indirect Memory Times Scale Plus 32-bit Index Register 3129 operand indIndexIScaleQ(iRegP addr, iRegI index, immI_4 scale) %{ 3130 constraint(ALLOC_IN_RC(ptr_reg)); 3131 match(AddP addr (LShiftX (ConvI2L index) scale)); 3132 3133 op_cost(100); 3134 format %{"[$addr + $index.w << $scale]" %} 3135 interface(MEMORY_INTER) %{ 3136 base($addr); 3137 index($index); 3138 scale($scale); 3139 disp(0x7fffffff); // sxtw 3140 %} 3141 %} 3142 #else 3143 // Indirect Memory Times Scale Plus Index Register 3144 operand indIndexScale(iRegP addr, iRegX index, immU5 scale) %{ 3145 constraint(ALLOC_IN_RC(ptr_reg)); 3146 match(AddP addr (LShiftX index scale)); 3147 3148 op_cost(100); 3149 format %{"[$addr + $index << $scale]" %} 3150 interface(MEMORY_INTER) %{ 3151 base($addr); 3152 index($index); 3153 scale($scale); 3154 disp(0x0); 3155 %} 3156 %} 3157 #endif 3158 3159 // Operands for expressing Control Flow 3160 // NOTE: Label is a predefined operand which should not be redefined in 3161 // the AD file. It is generically handled within the ADLC. 3162 3163 //----------Conditional Branch Operands---------------------------------------- 3164 // Comparison Op - This is the operation of the comparison, and is limited to 3165 // the following set of codes: 3166 // L (<), LE (<=), G (>), GE (>=), E (==), NE (!=) 3167 // 3168 // Other attributes of the comparison, such as unsignedness, are specified 3169 // by the comparison instruction that sets a condition code flags register. 3170 // That result is represented by a flags operand whose subtype is appropriate 3171 // to the unsignedness (etc.) of the comparison. 3172 // 3173 // Later, the instruction which matches both the Comparison Op (a Bool) and 3174 // the flags (produced by the Cmp) specifies the coding of the comparison op 3175 // by matching a specific subtype of Bool operand below, such as cmpOpU. 3176 3177 operand cmpOp() %{ 3178 match(Bool); 3179 3180 format %{ "" %} 3181 interface(COND_INTER) %{ 3182 equal(0x0); 3183 not_equal(0x1); 3184 less(0xb); 3185 greater_equal(0xa); 3186 less_equal(0xd); 3187 greater(0xc); 3188 overflow(0x0); // unsupported/unimplemented 3189 no_overflow(0x0); // unsupported/unimplemented 3190 %} 3191 %} 3192 3193 // integer comparison with 0, signed 3194 operand cmpOp0() %{ 3195 match(Bool); 3196 3197 format %{ "" %} 3198 interface(COND_INTER) %{ 3199 equal(0x0); 3200 not_equal(0x1); 3201 less(0x4); 3202 greater_equal(0x5); 3203 less_equal(0xd); // unsupported 3204 greater(0xc); // unsupported 3205 overflow(0x0); // unsupported/unimplemented 3206 no_overflow(0x0); // unsupported/unimplemented 3207 %} 3208 %} 3209 3210 // Comparison Op, unsigned 3211 operand cmpOpU() %{ 3212 match(Bool); 3213 3214 format %{ "u" %} 3215 interface(COND_INTER) %{ 3216 equal(0x0); 3217 not_equal(0x1); 3218 less(0x3); 3219 greater_equal(0x2); 3220 less_equal(0x9); 3221 greater(0x8); 3222 overflow(0x0); // unsupported/unimplemented 3223 no_overflow(0x0); // unsupported/unimplemented 3224 %} 3225 %} 3226 3227 // Comparison Op, pointer (same as unsigned) 3228 operand cmpOpP() %{ 3229 match(Bool); 3230 3231 format %{ "p" %} 3232 interface(COND_INTER) %{ 3233 equal(0x0); 3234 not_equal(0x1); 3235 less(0x3); 3236 greater_equal(0x2); 3237 less_equal(0x9); 3238 greater(0x8); 3239 overflow(0x0); // unsupported/unimplemented 3240 no_overflow(0x0); // unsupported/unimplemented 3241 %} 3242 %} 3243 3244 operand cmpOpL() %{ 3245 match(Bool); 3246 3247 format %{ "L" %} 3248 interface(COND_INTER) %{ 3249 equal(0x0); 3250 not_equal(0x1); 3251 less(0xb); 3252 greater_equal(0xa); 3253 less_equal(0xd); 3254 greater(0xc); 3255 overflow(0x0); // unsupported/unimplemented 3256 no_overflow(0x0); // unsupported/unimplemented 3257 %} 3258 %} 3259 3260 operand cmpOpL_commute() %{ 3261 match(Bool); 3262 3263 format %{ "L" %} 3264 interface(COND_INTER) %{ 3265 equal(0x0); 3266 not_equal(0x1); 3267 less(0xc); 3268 greater_equal(0xd); 3269 less_equal(0xa); 3270 greater(0xb); 3271 overflow(0x0); // unsupported/unimplemented 3272 no_overflow(0x0); // unsupported/unimplemented 3273 %} 3274 %} 3275 3276 operand cmpOpUL() %{ 3277 match(Bool); 3278 3279 format %{ "UL" %} 3280 interface(COND_INTER) %{ 3281 equal(0x0); 3282 not_equal(0x1); 3283 less(0x3); 3284 greater_equal(0x2); 3285 less_equal(0x9); 3286 greater(0x8); 3287 overflow(0x0); // unsupported/unimplemented 3288 no_overflow(0x0); // unsupported/unimplemented 3289 %} 3290 %} 3291 3292 operand cmpOpUL_commute() %{ 3293 match(Bool); 3294 3295 format %{ "UL" %} 3296 interface(COND_INTER) %{ 3297 equal(0x0); 3298 not_equal(0x1); 3299 less(0x8); 3300 greater_equal(0x9); 3301 less_equal(0x2); 3302 greater(0x3); 3303 overflow(0x0); // unsupported/unimplemented 3304 no_overflow(0x0); // unsupported/unimplemented 3305 %} 3306 %} 3307 3308 3309 //----------OPERAND CLASSES---------------------------------------------------- 3310 // Operand Classes are groups of operands that are used to simplify 3311 // instruction definitions by not requiring the AD writer to specify separate 3312 // instructions for every form of operand when the instruction accepts 3313 // multiple operand types with the same basic encoding and format. The classic 3314 // case of this is memory operands. 3315 #ifdef AARCH64 3316 opclass memoryB(indirect, indIndex, indOffsetU12ScaleB); 3317 opclass memoryS(indirect, indIndex, indIndexScaleS, indIndexIScaleS, indOffsetU12ScaleS); 3318 opclass memoryI(indirect, indIndex, indIndexScaleI, indIndexIScaleI, indOffsetU12ScaleI); 3319 opclass memoryL(indirect, indIndex, indIndexScaleL, indIndexIScaleL, indOffsetU12ScaleL); 3320 opclass memoryP(indirect, indIndex, indIndexScaleL, indIndexIScaleL, indOffsetU12ScaleL); 3321 opclass memoryQ(indirect, indIndex, indIndexScaleQ, indIndexIScaleQ, indOffsetU12ScaleQ); 3322 opclass memoryF(indirect, indIndex, indIndexScaleI, indIndexIScaleI, indOffsetU12ScaleI); 3323 opclass memoryD(indirect, indIndex, indIndexScaleL, indIndexIScaleL, indOffsetU12ScaleL); 3324 3325 opclass memoryScaledS(indIndexScaleS, indIndexIScaleS); 3326 opclass memoryScaledI(indIndexScaleI, indIndexIScaleI); 3327 opclass memoryScaledL(indIndexScaleL, indIndexIScaleL); 3328 opclass memoryScaledP(indIndexScaleL, indIndexIScaleL); 3329 opclass memoryScaledQ(indIndexScaleQ, indIndexIScaleQ); 3330 opclass memoryScaledF(indIndexScaleI, indIndexIScaleI); 3331 opclass memoryScaledD(indIndexScaleL, indIndexIScaleL); 3332 // when ldrex/strex is used: 3333 opclass memoryex ( indirect ); 3334 opclass indIndexMemory( indIndex ); 3335 opclass memoryvld ( indirect /* , write back mode not implemented */ ); 3336 3337 #else 3338 3339 opclass memoryI ( indirect, indOffset12, indIndex, indIndexScale ); 3340 opclass memoryP ( indirect, indOffset12, indIndex, indIndexScale ); 3341 opclass memoryF ( indirect, indOffsetFP ); 3342 opclass memoryF2 ( indirect, indOffsetFPx2 ); 3343 opclass memoryD ( indirect, indOffsetFP ); 3344 opclass memoryfp( indirect, indOffsetFP ); 3345 opclass memoryB ( indirect, indIndex, indOffsetHD ); 3346 opclass memoryS ( indirect, indIndex, indOffsetHD ); 3347 opclass memoryL ( indirect, indIndex, indOffsetHD ); 3348 3349 opclass memoryScaledI(indIndexScale); 3350 opclass memoryScaledP(indIndexScale); 3351 3352 // when ldrex/strex is used: 3353 opclass memoryex ( indirect ); 3354 opclass indIndexMemory( indIndex ); 3355 opclass memorylong ( indirect, indOffset12x2 ); 3356 opclass memoryvld ( indirect /* , write back mode not implemented */ ); 3357 #endif 3358 3359 //----------PIPELINE----------------------------------------------------------- 3360 pipeline %{ 3361 3362 //----------ATTRIBUTES--------------------------------------------------------- 3363 attributes %{ 3364 fixed_size_instructions; // Fixed size instructions 3365 max_instructions_per_bundle = 4; // Up to 4 instructions per bundle 3366 instruction_unit_size = 4; // An instruction is 4 bytes long 3367 instruction_fetch_unit_size = 16; // The processor fetches one line 3368 instruction_fetch_units = 1; // of 16 bytes 3369 3370 // List of nop instructions 3371 nops( Nop_A0, Nop_A1, Nop_MS, Nop_FA, Nop_BR ); 3372 %} 3373 3374 //----------RESOURCES---------------------------------------------------------- 3375 // Resources are the functional units available to the machine 3376 resources(A0, A1, MS, BR, FA, FM, IDIV, FDIV, IALU = A0 | A1); 3377 3378 //----------PIPELINE DESCRIPTION----------------------------------------------- 3379 // Pipeline Description specifies the stages in the machine's pipeline 3380 3381 pipe_desc(A, P, F, B, I, J, S, R, E, C, M, W, X, T, D); 3382 3383 //----------PIPELINE CLASSES--------------------------------------------------- 3384 // Pipeline Classes describe the stages in which input and output are 3385 // referenced by the hardware pipeline. 3386 3387 // Integer ALU reg-reg operation 3388 pipe_class ialu_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{ 3389 single_instruction; 3390 dst : E(write); 3391 src1 : R(read); 3392 src2 : R(read); 3393 IALU : R; 3394 %} 3395 3396 // Integer ALU reg-reg long operation 3397 pipe_class ialu_reg_reg_2(iRegL dst, iRegL src1, iRegL src2) %{ 3398 instruction_count(2); 3399 dst : E(write); 3400 src1 : R(read); 3401 src2 : R(read); 3402 IALU : R; 3403 IALU : R; 3404 %} 3405 3406 // Integer ALU reg-reg long dependent operation 3407 pipe_class ialu_reg_reg_2_dep(iRegL dst, iRegL src1, iRegL src2, flagsReg cr) %{ 3408 instruction_count(1); multiple_bundles; 3409 dst : E(write); 3410 src1 : R(read); 3411 src2 : R(read); 3412 cr : E(write); 3413 IALU : R(2); 3414 %} 3415 3416 // Integer ALU reg-imm operaion 3417 pipe_class ialu_reg_imm(iRegI dst, iRegI src1) %{ 3418 single_instruction; 3419 dst : E(write); 3420 src1 : R(read); 3421 IALU : R; 3422 %} 3423 3424 // Integer ALU reg-reg operation with condition code 3425 pipe_class ialu_cc_reg_reg(iRegI dst, iRegI src1, iRegI src2, flagsReg cr) %{ 3426 single_instruction; 3427 dst : E(write); 3428 cr : E(write); 3429 src1 : R(read); 3430 src2 : R(read); 3431 IALU : R; 3432 %} 3433 3434 // Integer ALU zero-reg operation 3435 pipe_class ialu_zero_reg(iRegI dst, immI0 zero, iRegI src2) %{ 3436 single_instruction; 3437 dst : E(write); 3438 src2 : R(read); 3439 IALU : R; 3440 %} 3441 3442 // Integer ALU zero-reg operation with condition code only 3443 pipe_class ialu_cconly_zero_reg(flagsReg cr, iRegI src) %{ 3444 single_instruction; 3445 cr : E(write); 3446 src : R(read); 3447 IALU : R; 3448 %} 3449 3450 // Integer ALU reg-reg operation with condition code only 3451 pipe_class ialu_cconly_reg_reg(flagsReg cr, iRegI src1, iRegI src2) %{ 3452 single_instruction; 3453 cr : E(write); 3454 src1 : R(read); 3455 src2 : R(read); 3456 IALU : R; 3457 %} 3458 3459 // Integer ALU reg-imm operation with condition code only 3460 pipe_class ialu_cconly_reg_imm(flagsReg cr, iRegI src1) %{ 3461 single_instruction; 3462 cr : E(write); 3463 src1 : R(read); 3464 IALU : R; 3465 %} 3466 3467 // Integer ALU reg-reg-zero operation with condition code only 3468 pipe_class ialu_cconly_reg_reg_zero(flagsReg cr, iRegI src1, iRegI src2, immI0 zero) %{ 3469 single_instruction; 3470 cr : E(write); 3471 src1 : R(read); 3472 src2 : R(read); 3473 IALU : R; 3474 %} 3475 3476 // Integer ALU reg-imm-zero operation with condition code only 3477 pipe_class ialu_cconly_reg_imm_zero(flagsReg cr, iRegI src1, immI0 zero) %{ 3478 single_instruction; 3479 cr : E(write); 3480 src1 : R(read); 3481 IALU : R; 3482 %} 3483 3484 // Integer ALU reg-reg operation with condition code, src1 modified 3485 pipe_class ialu_cc_rwreg_reg(flagsReg cr, iRegI src1, iRegI src2) %{ 3486 single_instruction; 3487 cr : E(write); 3488 src1 : E(write); 3489 src1 : R(read); 3490 src2 : R(read); 3491 IALU : R; 3492 %} 3493 3494 pipe_class cmpL_reg(iRegI dst, iRegL src1, iRegL src2, flagsReg cr ) %{ 3495 multiple_bundles; 3496 dst : E(write)+4; 3497 cr : E(write); 3498 src1 : R(read); 3499 src2 : R(read); 3500 IALU : R(3); 3501 BR : R(2); 3502 %} 3503 3504 // Integer ALU operation 3505 pipe_class ialu_none(iRegI dst) %{ 3506 single_instruction; 3507 dst : E(write); 3508 IALU : R; 3509 %} 3510 3511 // Integer ALU reg operation 3512 pipe_class ialu_reg(iRegI dst, iRegI src) %{ 3513 single_instruction; may_have_no_code; 3514 dst : E(write); 3515 src : R(read); 3516 IALU : R; 3517 %} 3518 3519 // Integer ALU reg conditional operation 3520 // This instruction has a 1 cycle stall, and cannot execute 3521 // in the same cycle as the instruction setting the condition 3522 // code. We kludge this by pretending to read the condition code 3523 // 1 cycle earlier, and by marking the functional units as busy 3524 // for 2 cycles with the result available 1 cycle later than 3525 // is really the case. 3526 pipe_class ialu_reg_flags( iRegI op2_out, iRegI op2_in, iRegI op1, flagsReg cr ) %{ 3527 single_instruction; 3528 op2_out : C(write); 3529 op1 : R(read); 3530 cr : R(read); // This is really E, with a 1 cycle stall 3531 BR : R(2); 3532 MS : R(2); 3533 %} 3534 3535 // Integer ALU reg operation 3536 pipe_class ialu_move_reg_L_to_I(iRegI dst, iRegL src) %{ 3537 single_instruction; may_have_no_code; 3538 dst : E(write); 3539 src : R(read); 3540 IALU : R; 3541 %} 3542 pipe_class ialu_move_reg_I_to_L(iRegL dst, iRegI src) %{ 3543 single_instruction; may_have_no_code; 3544 dst : E(write); 3545 src : R(read); 3546 IALU : R; 3547 %} 3548 3549 // Two integer ALU reg operations 3550 pipe_class ialu_reg_2(iRegL dst, iRegL src) %{ 3551 instruction_count(2); 3552 dst : E(write); 3553 src : R(read); 3554 A0 : R; 3555 A1 : R; 3556 %} 3557 3558 // Two integer ALU reg operations 3559 pipe_class ialu_move_reg_L_to_L(iRegL dst, iRegL src) %{ 3560 instruction_count(2); may_have_no_code; 3561 dst : E(write); 3562 src : R(read); 3563 A0 : R; 3564 A1 : R; 3565 %} 3566 3567 // Integer ALU imm operation 3568 pipe_class ialu_imm(iRegI dst) %{ 3569 single_instruction; 3570 dst : E(write); 3571 IALU : R; 3572 %} 3573 3574 pipe_class ialu_imm_n(iRegI dst) %{ 3575 single_instruction; 3576 dst : E(write); 3577 IALU : R; 3578 %} 3579 3580 // Integer ALU reg-reg with carry operation 3581 pipe_class ialu_reg_reg_cy(iRegI dst, iRegI src1, iRegI src2, iRegI cy) %{ 3582 single_instruction; 3583 dst : E(write); 3584 src1 : R(read); 3585 src2 : R(read); 3586 IALU : R; 3587 %} 3588 3589 // Integer ALU cc operation 3590 pipe_class ialu_cc(iRegI dst, flagsReg cc) %{ 3591 single_instruction; 3592 dst : E(write); 3593 cc : R(read); 3594 IALU : R; 3595 %} 3596 3597 // Integer ALU cc / second IALU operation 3598 pipe_class ialu_reg_ialu( iRegI dst, iRegI src ) %{ 3599 instruction_count(1); multiple_bundles; 3600 dst : E(write)+1; 3601 src : R(read); 3602 IALU : R; 3603 %} 3604 3605 // Integer ALU cc / second IALU operation 3606 pipe_class ialu_reg_reg_ialu( iRegI dst, iRegI p, iRegI q ) %{ 3607 instruction_count(1); multiple_bundles; 3608 dst : E(write)+1; 3609 p : R(read); 3610 q : R(read); 3611 IALU : R; 3612 %} 3613 3614 // Integer ALU hi-lo-reg operation 3615 pipe_class ialu_hi_lo_reg(iRegI dst, immI src) %{ 3616 instruction_count(1); multiple_bundles; 3617 dst : E(write)+1; 3618 IALU : R(2); 3619 %} 3620 3621 // Long Constant 3622 pipe_class loadConL( iRegL dst, immL src ) %{ 3623 instruction_count(2); multiple_bundles; 3624 dst : E(write)+1; 3625 IALU : R(2); 3626 IALU : R(2); 3627 %} 3628 3629 // Pointer Constant 3630 pipe_class loadConP( iRegP dst, immP src ) %{ 3631 instruction_count(0); multiple_bundles; 3632 fixed_latency(6); 3633 %} 3634 3635 // Polling Address 3636 pipe_class loadConP_poll( iRegP dst, immP_poll src ) %{ 3637 dst : E(write); 3638 IALU : R; 3639 %} 3640 3641 // Long Constant small 3642 pipe_class loadConLlo( iRegL dst, immL src ) %{ 3643 instruction_count(2); 3644 dst : E(write); 3645 IALU : R; 3646 IALU : R; 3647 %} 3648 3649 // [PHH] This is wrong for 64-bit. See LdImmF/D. 3650 pipe_class loadConFD(regF dst, immF src, iRegP tmp) %{ 3651 instruction_count(1); multiple_bundles; 3652 src : R(read); 3653 dst : M(write)+1; 3654 IALU : R; 3655 MS : E; 3656 %} 3657 3658 // Integer ALU nop operation 3659 pipe_class ialu_nop() %{ 3660 single_instruction; 3661 IALU : R; 3662 %} 3663 3664 // Integer ALU nop operation 3665 pipe_class ialu_nop_A0() %{ 3666 single_instruction; 3667 A0 : R; 3668 %} 3669 3670 // Integer ALU nop operation 3671 pipe_class ialu_nop_A1() %{ 3672 single_instruction; 3673 A1 : R; 3674 %} 3675 3676 // Integer Multiply reg-reg operation 3677 pipe_class imul_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{ 3678 single_instruction; 3679 dst : E(write); 3680 src1 : R(read); 3681 src2 : R(read); 3682 MS : R(5); 3683 %} 3684 3685 pipe_class mulL_reg_reg(iRegL dst, iRegL src1, iRegL src2) %{ 3686 single_instruction; 3687 dst : E(write)+4; 3688 src1 : R(read); 3689 src2 : R(read); 3690 MS : R(6); 3691 %} 3692 3693 // Integer Divide reg-reg 3694 pipe_class sdiv_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI temp, flagsReg cr) %{ 3695 instruction_count(1); multiple_bundles; 3696 dst : E(write); 3697 temp : E(write); 3698 src1 : R(read); 3699 src2 : R(read); 3700 temp : R(read); 3701 MS : R(38); 3702 %} 3703 3704 // Long Divide 3705 pipe_class divL_reg_reg(iRegL dst, iRegL src1, iRegL src2) %{ 3706 dst : E(write)+71; 3707 src1 : R(read); 3708 src2 : R(read)+1; 3709 MS : R(70); 3710 %} 3711 3712 // Floating Point Add Float 3713 pipe_class faddF_reg_reg(regF dst, regF src1, regF src2) %{ 3714 single_instruction; 3715 dst : X(write); 3716 src1 : E(read); 3717 src2 : E(read); 3718 FA : R; 3719 %} 3720 3721 // Floating Point Add Double 3722 pipe_class faddD_reg_reg(regD dst, regD src1, regD src2) %{ 3723 single_instruction; 3724 dst : X(write); 3725 src1 : E(read); 3726 src2 : E(read); 3727 FA : R; 3728 %} 3729 3730 // Floating Point Conditional Move based on integer flags 3731 pipe_class int_conditional_float_move (cmpOp cmp, flagsReg cr, regF dst, regF src) %{ 3732 single_instruction; 3733 dst : X(write); 3734 src : E(read); 3735 cr : R(read); 3736 FA : R(2); 3737 BR : R(2); 3738 %} 3739 3740 // Floating Point Conditional Move based on integer flags 3741 pipe_class int_conditional_double_move (cmpOp cmp, flagsReg cr, regD dst, regD src) %{ 3742 single_instruction; 3743 dst : X(write); 3744 src : E(read); 3745 cr : R(read); 3746 FA : R(2); 3747 BR : R(2); 3748 %} 3749 3750 // Floating Point Multiply Float 3751 pipe_class fmulF_reg_reg(regF dst, regF src1, regF src2) %{ 3752 single_instruction; 3753 dst : X(write); 3754 src1 : E(read); 3755 src2 : E(read); 3756 FM : R; 3757 %} 3758 3759 // Floating Point Multiply Double 3760 pipe_class fmulD_reg_reg(regD dst, regD src1, regD src2) %{ 3761 single_instruction; 3762 dst : X(write); 3763 src1 : E(read); 3764 src2 : E(read); 3765 FM : R; 3766 %} 3767 3768 // Floating Point Divide Float 3769 pipe_class fdivF_reg_reg(regF dst, regF src1, regF src2) %{ 3770 single_instruction; 3771 dst : X(write); 3772 src1 : E(read); 3773 src2 : E(read); 3774 FM : R; 3775 FDIV : C(14); 3776 %} 3777 3778 // Floating Point Divide Double 3779 pipe_class fdivD_reg_reg(regD dst, regD src1, regD src2) %{ 3780 single_instruction; 3781 dst : X(write); 3782 src1 : E(read); 3783 src2 : E(read); 3784 FM : R; 3785 FDIV : C(17); 3786 %} 3787 3788 // Floating Point Move/Negate/Abs Float 3789 pipe_class faddF_reg(regF dst, regF src) %{ 3790 single_instruction; 3791 dst : W(write); 3792 src : E(read); 3793 FA : R(1); 3794 %} 3795 3796 // Floating Point Move/Negate/Abs Double 3797 pipe_class faddD_reg(regD dst, regD src) %{ 3798 single_instruction; 3799 dst : W(write); 3800 src : E(read); 3801 FA : R; 3802 %} 3803 3804 // Floating Point Convert F->D 3805 pipe_class fcvtF2D(regD dst, regF src) %{ 3806 single_instruction; 3807 dst : X(write); 3808 src : E(read); 3809 FA : R; 3810 %} 3811 3812 // Floating Point Convert I->D 3813 pipe_class fcvtI2D(regD dst, regF src) %{ 3814 single_instruction; 3815 dst : X(write); 3816 src : E(read); 3817 FA : R; 3818 %} 3819 3820 // Floating Point Convert LHi->D 3821 pipe_class fcvtLHi2D(regD dst, regD src) %{ 3822 single_instruction; 3823 dst : X(write); 3824 src : E(read); 3825 FA : R; 3826 %} 3827 3828 // Floating Point Convert L->D 3829 pipe_class fcvtL2D(regD dst, iRegL src) %{ 3830 single_instruction; 3831 dst : X(write); 3832 src : E(read); 3833 FA : R; 3834 %} 3835 3836 // Floating Point Convert L->F 3837 pipe_class fcvtL2F(regF dst, iRegL src) %{ 3838 single_instruction; 3839 dst : X(write); 3840 src : E(read); 3841 FA : R; 3842 %} 3843 3844 // Floating Point Convert D->F 3845 pipe_class fcvtD2F(regD dst, regF src) %{ 3846 single_instruction; 3847 dst : X(write); 3848 src : E(read); 3849 FA : R; 3850 %} 3851 3852 // Floating Point Convert I->L 3853 pipe_class fcvtI2L(regD dst, regF src) %{ 3854 single_instruction; 3855 dst : X(write); 3856 src : E(read); 3857 FA : R; 3858 %} 3859 3860 // Floating Point Convert D->F 3861 pipe_class fcvtD2I(iRegI dst, regD src, flagsReg cr) %{ 3862 instruction_count(1); multiple_bundles; 3863 dst : X(write)+6; 3864 src : E(read); 3865 FA : R; 3866 %} 3867 3868 // Floating Point Convert D->L 3869 pipe_class fcvtD2L(regD dst, regD src, flagsReg cr) %{ 3870 instruction_count(1); multiple_bundles; 3871 dst : X(write)+6; 3872 src : E(read); 3873 FA : R; 3874 %} 3875 3876 // Floating Point Convert F->I 3877 pipe_class fcvtF2I(regF dst, regF src, flagsReg cr) %{ 3878 instruction_count(1); multiple_bundles; 3879 dst : X(write)+6; 3880 src : E(read); 3881 FA : R; 3882 %} 3883 3884 // Floating Point Convert F->L 3885 pipe_class fcvtF2L(regD dst, regF src, flagsReg cr) %{ 3886 instruction_count(1); multiple_bundles; 3887 dst : X(write)+6; 3888 src : E(read); 3889 FA : R; 3890 %} 3891 3892 // Floating Point Convert I->F 3893 pipe_class fcvtI2F(regF dst, regF src) %{ 3894 single_instruction; 3895 dst : X(write); 3896 src : E(read); 3897 FA : R; 3898 %} 3899 3900 // Floating Point Compare 3901 pipe_class faddF_fcc_reg_reg_zero(flagsRegF cr, regF src1, regF src2, immI0 zero) %{ 3902 single_instruction; 3903 cr : X(write); 3904 src1 : E(read); 3905 src2 : E(read); 3906 FA : R; 3907 %} 3908 3909 // Floating Point Compare 3910 pipe_class faddD_fcc_reg_reg_zero(flagsRegF cr, regD src1, regD src2, immI0 zero) %{ 3911 single_instruction; 3912 cr : X(write); 3913 src1 : E(read); 3914 src2 : E(read); 3915 FA : R; 3916 %} 3917 3918 // Floating Add Nop 3919 pipe_class fadd_nop() %{ 3920 single_instruction; 3921 FA : R; 3922 %} 3923 3924 // Integer Store to Memory 3925 pipe_class istore_mem_reg(memoryI mem, iRegI src) %{ 3926 single_instruction; 3927 mem : R(read); 3928 src : C(read); 3929 MS : R; 3930 %} 3931 3932 // Integer Store to Memory 3933 pipe_class istore_mem_spORreg(memoryI mem, sp_ptr_RegP src) %{ 3934 single_instruction; 3935 mem : R(read); 3936 src : C(read); 3937 MS : R; 3938 %} 3939 3940 // Float Store 3941 pipe_class fstoreF_mem_reg(memoryF mem, RegF src) %{ 3942 single_instruction; 3943 mem : R(read); 3944 src : C(read); 3945 MS : R; 3946 %} 3947 3948 // Float Store 3949 pipe_class fstoreF_mem_zero(memoryF mem, immF0 src) %{ 3950 single_instruction; 3951 mem : R(read); 3952 MS : R; 3953 %} 3954 3955 // Double Store 3956 pipe_class fstoreD_mem_reg(memoryD mem, RegD src) %{ 3957 instruction_count(1); 3958 mem : R(read); 3959 src : C(read); 3960 MS : R; 3961 %} 3962 3963 // Double Store 3964 pipe_class fstoreD_mem_zero(memoryD mem, immD0 src) %{ 3965 single_instruction; 3966 mem : R(read); 3967 MS : R; 3968 %} 3969 3970 // Integer Load (when sign bit propagation not needed) 3971 pipe_class iload_mem(iRegI dst, memoryI mem) %{ 3972 single_instruction; 3973 mem : R(read); 3974 dst : C(write); 3975 MS : R; 3976 %} 3977 3978 // Integer Load (when sign bit propagation or masking is needed) 3979 pipe_class iload_mask_mem(iRegI dst, memoryI mem) %{ 3980 single_instruction; 3981 mem : R(read); 3982 dst : M(write); 3983 MS : R; 3984 %} 3985 3986 // Float Load 3987 pipe_class floadF_mem(regF dst, memoryF mem) %{ 3988 single_instruction; 3989 mem : R(read); 3990 dst : M(write); 3991 MS : R; 3992 %} 3993 3994 // Float Load 3995 pipe_class floadD_mem(regD dst, memoryD mem) %{ 3996 instruction_count(1); multiple_bundles; // Again, unaligned argument is only multiple case 3997 mem : R(read); 3998 dst : M(write); 3999 MS : R; 4000 %} 4001 4002 // Memory Nop 4003 pipe_class mem_nop() %{ 4004 single_instruction; 4005 MS : R; 4006 %} 4007 4008 pipe_class sethi(iRegP dst, immI src) %{ 4009 single_instruction; 4010 dst : E(write); 4011 IALU : R; 4012 %} 4013 4014 pipe_class loadPollP(iRegP poll) %{ 4015 single_instruction; 4016 poll : R(read); 4017 MS : R; 4018 %} 4019 4020 pipe_class br(Universe br, label labl) %{ 4021 single_instruction_with_delay_slot; 4022 BR : R; 4023 %} 4024 4025 pipe_class br_cc(Universe br, cmpOp cmp, flagsReg cr, label labl) %{ 4026 single_instruction_with_delay_slot; 4027 cr : E(read); 4028 BR : R; 4029 %} 4030 4031 pipe_class br_reg(Universe br, cmpOp cmp, iRegI op1, label labl) %{ 4032 single_instruction_with_delay_slot; 4033 op1 : E(read); 4034 BR : R; 4035 MS : R; 4036 %} 4037 4038 pipe_class br_nop() %{ 4039 single_instruction; 4040 BR : R; 4041 %} 4042 4043 pipe_class simple_call(method meth) %{ 4044 instruction_count(2); multiple_bundles; force_serialization; 4045 fixed_latency(100); 4046 BR : R(1); 4047 MS : R(1); 4048 A0 : R(1); 4049 %} 4050 4051 pipe_class compiled_call(method meth) %{ 4052 instruction_count(1); multiple_bundles; force_serialization; 4053 fixed_latency(100); 4054 MS : R(1); 4055 %} 4056 4057 pipe_class call(method meth) %{ 4058 instruction_count(0); multiple_bundles; force_serialization; 4059 fixed_latency(100); 4060 %} 4061 4062 pipe_class tail_call(Universe ignore, label labl) %{ 4063 single_instruction; has_delay_slot; 4064 fixed_latency(100); 4065 BR : R(1); 4066 MS : R(1); 4067 %} 4068 4069 pipe_class ret(Universe ignore) %{ 4070 single_instruction; has_delay_slot; 4071 BR : R(1); 4072 MS : R(1); 4073 %} 4074 4075 // The real do-nothing guy 4076 pipe_class empty( ) %{ 4077 instruction_count(0); 4078 %} 4079 4080 pipe_class long_memory_op() %{ 4081 instruction_count(0); multiple_bundles; force_serialization; 4082 fixed_latency(25); 4083 MS : R(1); 4084 %} 4085 4086 // Check-cast 4087 pipe_class partial_subtype_check_pipe(Universe ignore, iRegP array, iRegP match ) %{ 4088 array : R(read); 4089 match : R(read); 4090 IALU : R(2); 4091 BR : R(2); 4092 MS : R; 4093 %} 4094 4095 // Convert FPU flags into +1,0,-1 4096 pipe_class floating_cmp( iRegI dst, regF src1, regF src2 ) %{ 4097 src1 : E(read); 4098 src2 : E(read); 4099 dst : E(write); 4100 FA : R; 4101 MS : R(2); 4102 BR : R(2); 4103 %} 4104 4105 // Compare for p < q, and conditionally add y 4106 pipe_class cadd_cmpltmask( iRegI p, iRegI q, iRegI y ) %{ 4107 p : E(read); 4108 q : E(read); 4109 y : E(read); 4110 IALU : R(3) 4111 %} 4112 4113 // Perform a compare, then move conditionally in a branch delay slot. 4114 pipe_class min_max( iRegI src2, iRegI srcdst ) %{ 4115 src2 : E(read); 4116 srcdst : E(read); 4117 IALU : R; 4118 BR : R; 4119 %} 4120 4121 // Define the class for the Nop node 4122 define %{ 4123 MachNop = ialu_nop; 4124 %} 4125 4126 %} 4127 4128 //----------INSTRUCTIONS------------------------------------------------------- 4129 4130 //------------Special Nop instructions for bundling - no match rules----------- 4131 // Nop using the A0 functional unit 4132 instruct Nop_A0() %{ 4133 ins_pipe(ialu_nop_A0); 4134 %} 4135 4136 // Nop using the A1 functional unit 4137 instruct Nop_A1( ) %{ 4138 ins_pipe(ialu_nop_A1); 4139 %} 4140 4141 // Nop using the memory functional unit 4142 instruct Nop_MS( ) %{ 4143 ins_pipe(mem_nop); 4144 %} 4145 4146 // Nop using the floating add functional unit 4147 instruct Nop_FA( ) %{ 4148 ins_pipe(fadd_nop); 4149 %} 4150 4151 // Nop using the branch functional unit 4152 instruct Nop_BR( ) %{ 4153 ins_pipe(br_nop); 4154 %} 4155 4156 //----------Load/Store/Move Instructions--------------------------------------- 4157 //----------Load Instructions-------------------------------------------------- 4158 // Load Byte (8bit signed) 4159 instruct loadB(iRegI dst, memoryB mem) %{ 4160 match(Set dst (LoadB mem)); 4161 ins_cost(MEMORY_REF_COST); 4162 4163 size(4); 4164 format %{ "LDRSB $dst,$mem\t! byte -> int" %} 4165 ins_encode %{ 4166 // High 32 bits are harmlessly set on Aarch64 4167 __ ldrsb($dst$$Register, $mem$$Address); 4168 %} 4169 ins_pipe(iload_mask_mem); 4170 %} 4171 4172 // Load Byte (8bit signed) into a Long Register 4173 instruct loadB2L(iRegL dst, memoryB mem) %{ 4174 match(Set dst (ConvI2L (LoadB mem))); 4175 ins_cost(MEMORY_REF_COST); 4176 4177 #ifdef AARCH64 4178 size(4); 4179 format %{ "LDRSB $dst,$mem\t! byte -> long" %} 4180 ins_encode %{ 4181 __ ldrsb($dst$$Register, $mem$$Address); 4182 %} 4183 #else 4184 size(8); 4185 format %{ "LDRSB $dst.lo,$mem\t! byte -> long\n\t" 4186 "ASR $dst.hi,$dst.lo,31" %} 4187 ins_encode %{ 4188 __ ldrsb($dst$$Register, $mem$$Address); 4189 __ mov($dst$$Register->successor(), AsmOperand($dst$$Register, asr, 31)); 4190 %} 4191 #endif 4192 ins_pipe(iload_mask_mem); 4193 %} 4194 4195 // Load Unsigned Byte (8bit UNsigned) into an int reg 4196 instruct loadUB(iRegI dst, memoryB mem) %{ 4197 match(Set dst (LoadUB mem)); 4198 ins_cost(MEMORY_REF_COST); 4199 4200 size(4); 4201 format %{ "LDRB $dst,$mem\t! ubyte -> int" %} 4202 ins_encode %{ 4203 __ ldrb($dst$$Register, $mem$$Address); 4204 %} 4205 ins_pipe(iload_mem); 4206 %} 4207 4208 // Load Unsigned Byte (8bit UNsigned) into a Long Register 4209 instruct loadUB2L(iRegL dst, memoryB mem) %{ 4210 match(Set dst (ConvI2L (LoadUB mem))); 4211 ins_cost(MEMORY_REF_COST); 4212 4213 #ifdef AARCH64 4214 size(4); 4215 format %{ "LDRB $dst,$mem\t! ubyte -> long" %} 4216 ins_encode %{ 4217 __ ldrb($dst$$Register, $mem$$Address); 4218 %} 4219 #else 4220 size(8); 4221 format %{ "LDRB $dst.lo,$mem\t! ubyte -> long\n\t" 4222 "MOV $dst.hi,0" %} 4223 ins_encode %{ 4224 __ ldrb($dst$$Register, $mem$$Address); 4225 __ mov($dst$$Register->successor(), 0); 4226 %} 4227 #endif 4228 ins_pipe(iload_mem); 4229 %} 4230 4231 // Load Unsigned Byte (8 bit UNsigned) with immediate mask into Long Register 4232 instruct loadUB2L_limmI(iRegL dst, memoryB mem, limmIlow8 mask) %{ 4233 match(Set dst (ConvI2L (AndI (LoadUB mem) mask))); 4234 4235 #ifdef AARCH64 4236 ins_cost(MEMORY_REF_COST + DEFAULT_COST); 4237 size(8); 4238 format %{ "LDRB $dst,$mem\t! ubyte -> long\n\t" 4239 "AND $dst,$dst,$mask" %} 4240 ins_encode %{ 4241 __ ldrb($dst$$Register, $mem$$Address); 4242 __ andr($dst$$Register, $dst$$Register, limmI_low($mask$$constant, 8)); 4243 %} 4244 #else 4245 ins_cost(MEMORY_REF_COST + 2*DEFAULT_COST); 4246 size(12); 4247 format %{ "LDRB $dst.lo,$mem\t! ubyte -> long\n\t" 4248 "MOV $dst.hi,0\n\t" 4249 "AND $dst.lo,$dst.lo,$mask" %} 4250 ins_encode %{ 4251 __ ldrb($dst$$Register, $mem$$Address); 4252 __ mov($dst$$Register->successor(), 0); 4253 __ andr($dst$$Register, $dst$$Register, limmI_low($mask$$constant, 8)); 4254 %} 4255 #endif 4256 ins_pipe(iload_mem); 4257 %} 4258 4259 // Load Short (16bit signed) 4260 #ifdef AARCH64 4261 // XXX This variant shouldn't be necessary if 6217251 is implemented 4262 instruct loadSoff(iRegI dst, memoryScaledS mem, aimmX off, iRegP tmp) %{ 4263 match(Set dst (LoadS (AddP mem off))); 4264 ins_cost(MEMORY_REF_COST + DEFAULT_COST); // assume shift/sign-extend is free 4265 effect(TEMP tmp); 4266 size(4 * 2); 4267 4268 format %{ "LDRSH $dst,$mem+$off\t! short temp=$tmp" %} 4269 ins_encode %{ 4270 Register base = reg_to_register_object($mem$$base); 4271 __ add($tmp$$Register, base, $off$$constant); 4272 Address nmem = Address::make_raw($tmp$$reg, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none); 4273 __ ldrsh($dst$$Register, nmem); 4274 %} 4275 ins_pipe(iload_mask_mem); 4276 %} 4277 #endif 4278 4279 instruct loadS(iRegI dst, memoryS mem) %{ 4280 match(Set dst (LoadS mem)); 4281 ins_cost(MEMORY_REF_COST); 4282 4283 size(4); 4284 format %{ "LDRSH $dst,$mem\t! short" %} 4285 ins_encode %{ 4286 __ ldrsh($dst$$Register, $mem$$Address); 4287 %} 4288 ins_pipe(iload_mask_mem); 4289 %} 4290 4291 // Load Short (16 bit signed) to Byte (8 bit signed) 4292 instruct loadS2B(iRegI dst, memoryS mem, immI_24 twentyfour) %{ 4293 match(Set dst (RShiftI (LShiftI (LoadS mem) twentyfour) twentyfour)); 4294 ins_cost(MEMORY_REF_COST); 4295 4296 size(4); 4297 4298 format %{ "LDRSB $dst,$mem\t! short -> byte" %} 4299 ins_encode %{ 4300 // High 32 bits are harmlessly set on Aarch64 4301 __ ldrsb($dst$$Register, $mem$$Address); 4302 %} 4303 ins_pipe(iload_mask_mem); 4304 %} 4305 4306 // Load Short (16bit signed) into a Long Register 4307 instruct loadS2L(iRegL dst, memoryS mem) %{ 4308 match(Set dst (ConvI2L (LoadS mem))); 4309 ins_cost(MEMORY_REF_COST); 4310 4311 #ifdef AARCH64 4312 size(4); 4313 format %{ "LDRSH $dst,$mem\t! short -> long" %} 4314 ins_encode %{ 4315 __ ldrsh($dst$$Register, $mem$$Address); 4316 %} 4317 #else 4318 size(8); 4319 format %{ "LDRSH $dst.lo,$mem\t! short -> long\n\t" 4320 "ASR $dst.hi,$dst.lo,31" %} 4321 ins_encode %{ 4322 __ ldrsh($dst$$Register, $mem$$Address); 4323 __ mov($dst$$Register->successor(), AsmOperand($dst$$Register, asr, 31)); 4324 %} 4325 #endif 4326 ins_pipe(iload_mask_mem); 4327 %} 4328 4329 // Load Unsigned Short/Char (16bit UNsigned) 4330 4331 #ifdef AARCH64 4332 // XXX This variant shouldn't be necessary if 6217251 is implemented 4333 instruct loadUSoff(iRegI dst, memoryScaledS mem, aimmX off, iRegP tmp) %{ 4334 match(Set dst (LoadUS (AddP mem off))); 4335 ins_cost(MEMORY_REF_COST + DEFAULT_COST); // assume shift/sign-extend is free 4336 effect(TEMP tmp); 4337 size(4 * 2); 4338 4339 format %{ "LDRH $dst,$mem+$off\t! ushort/char temp=$tmp" %} 4340 ins_encode %{ 4341 Register base = reg_to_register_object($mem$$base); 4342 __ add($tmp$$Register, base, $off$$constant); 4343 Address nmem = Address::make_raw($tmp$$reg, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none); 4344 __ ldrh($dst$$Register, nmem); 4345 %} 4346 ins_pipe(iload_mem); 4347 %} 4348 #endif 4349 4350 instruct loadUS(iRegI dst, memoryS mem) %{ 4351 match(Set dst (LoadUS mem)); 4352 ins_cost(MEMORY_REF_COST); 4353 4354 size(4); 4355 format %{ "LDRH $dst,$mem\t! ushort/char" %} 4356 ins_encode %{ 4357 __ ldrh($dst$$Register, $mem$$Address); 4358 %} 4359 ins_pipe(iload_mem); 4360 %} 4361 4362 // Load Unsigned Short/Char (16 bit UNsigned) to Byte (8 bit signed) 4363 instruct loadUS2B(iRegI dst, memoryB mem, immI_24 twentyfour) %{ 4364 match(Set dst (RShiftI (LShiftI (LoadUS mem) twentyfour) twentyfour)); 4365 ins_cost(MEMORY_REF_COST); 4366 4367 size(4); 4368 format %{ "LDRSB $dst,$mem\t! ushort -> byte" %} 4369 ins_encode %{ 4370 __ ldrsb($dst$$Register, $mem$$Address); 4371 %} 4372 ins_pipe(iload_mask_mem); 4373 %} 4374 4375 // Load Unsigned Short/Char (16bit UNsigned) into a Long Register 4376 instruct loadUS2L(iRegL dst, memoryS mem) %{ 4377 match(Set dst (ConvI2L (LoadUS mem))); 4378 ins_cost(MEMORY_REF_COST); 4379 4380 #ifdef AARCH64 4381 size(4); 4382 format %{ "LDRH $dst,$mem\t! short -> long" %} 4383 ins_encode %{ 4384 __ ldrh($dst$$Register, $mem$$Address); 4385 %} 4386 #else 4387 size(8); 4388 format %{ "LDRH $dst.lo,$mem\t! short -> long\n\t" 4389 "MOV $dst.hi, 0" %} 4390 ins_encode %{ 4391 __ ldrh($dst$$Register, $mem$$Address); 4392 __ mov($dst$$Register->successor(), 0); 4393 %} 4394 #endif 4395 ins_pipe(iload_mem); 4396 %} 4397 4398 // Load Unsigned Short/Char (16bit UNsigned) with mask 0xFF into a Long Register 4399 instruct loadUS2L_immI_255(iRegL dst, memoryB mem, immI_255 mask) %{ 4400 match(Set dst (ConvI2L (AndI (LoadUS mem) mask))); 4401 ins_cost(MEMORY_REF_COST); 4402 4403 #ifdef AARCH64 4404 size(4); 4405 format %{ "LDRB $dst,$mem" %} 4406 ins_encode %{ 4407 __ ldrb($dst$$Register, $mem$$Address); 4408 %} 4409 #else 4410 size(8); 4411 format %{ "LDRB $dst.lo,$mem\t! \n\t" 4412 "MOV $dst.hi, 0" %} 4413 ins_encode %{ 4414 __ ldrb($dst$$Register, $mem$$Address); 4415 __ mov($dst$$Register->successor(), 0); 4416 %} 4417 #endif 4418 ins_pipe(iload_mem); 4419 %} 4420 4421 // Load Unsigned Short/Char (16bit UNsigned) with a immediate mask into a Long Register 4422 instruct loadUS2L_limmI(iRegL dst, memoryS mem, limmI mask) %{ 4423 match(Set dst (ConvI2L (AndI (LoadUS mem) mask))); 4424 #ifdef AARCH64 4425 ins_cost(MEMORY_REF_COST + 1*DEFAULT_COST); 4426 4427 size(8); 4428 format %{ "LDRH $dst,$mem\t! ushort/char & mask -> long\n\t" 4429 "AND $dst,$dst,$mask" %} 4430 ins_encode %{ 4431 __ ldrh($dst$$Register, $mem$$Address); 4432 __ andr($dst$$Register, $dst$$Register, (uintx)$mask$$constant); 4433 %} 4434 #else 4435 ins_cost(MEMORY_REF_COST + 2*DEFAULT_COST); 4436 4437 size(12); 4438 format %{ "LDRH $dst,$mem\t! ushort/char & mask -> long\n\t" 4439 "MOV $dst.hi, 0\n\t" 4440 "AND $dst,$dst,$mask" %} 4441 ins_encode %{ 4442 __ ldrh($dst$$Register, $mem$$Address); 4443 __ mov($dst$$Register->successor(), 0); 4444 __ andr($dst$$Register, $dst$$Register, $mask$$constant); 4445 %} 4446 #endif 4447 ins_pipe(iload_mem); 4448 %} 4449 4450 // Load Integer 4451 4452 #ifdef AARCH64 4453 // XXX This variant shouldn't be necessary if 6217251 is implemented 4454 instruct loadIoff(iRegI dst, memoryScaledI mem, aimmX off, iRegP tmp) %{ 4455 match(Set dst (LoadI (AddP mem off))); 4456 ins_cost(MEMORY_REF_COST + DEFAULT_COST); // assume shift/sign-extend is free 4457 effect(TEMP tmp); 4458 size(4 * 2); 4459 4460 format %{ "ldr_s32 $dst,$mem+$off\t! int temp=$tmp" %} 4461 ins_encode %{ 4462 Register base = reg_to_register_object($mem$$base); 4463 __ add($tmp$$Register, base, $off$$constant); 4464 Address nmem = Address::make_raw($tmp$$reg, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none); 4465 __ ldr_s32($dst$$Register, nmem); 4466 %} 4467 ins_pipe(iload_mem); 4468 %} 4469 #endif 4470 4471 instruct loadI(iRegI dst, memoryI mem) %{ 4472 match(Set dst (LoadI mem)); 4473 ins_cost(MEMORY_REF_COST); 4474 4475 size(4); 4476 format %{ "ldr_s32 $dst,$mem\t! int" %} 4477 ins_encode %{ 4478 __ ldr_s32($dst$$Register, $mem$$Address); 4479 %} 4480 ins_pipe(iload_mem); 4481 %} 4482 4483 // Load Integer to Byte (8 bit signed) 4484 instruct loadI2B(iRegI dst, memoryS mem, immI_24 twentyfour) %{ 4485 match(Set dst (RShiftI (LShiftI (LoadI mem) twentyfour) twentyfour)); 4486 ins_cost(MEMORY_REF_COST); 4487 4488 size(4); 4489 4490 format %{ "LDRSB $dst,$mem\t! int -> byte" %} 4491 ins_encode %{ 4492 __ ldrsb($dst$$Register, $mem$$Address); 4493 %} 4494 ins_pipe(iload_mask_mem); 4495 %} 4496 4497 // Load Integer to Unsigned Byte (8 bit UNsigned) 4498 instruct loadI2UB(iRegI dst, memoryB mem, immI_255 mask) %{ 4499 match(Set dst (AndI (LoadI mem) mask)); 4500 ins_cost(MEMORY_REF_COST); 4501 4502 size(4); 4503 4504 format %{ "LDRB $dst,$mem\t! int -> ubyte" %} 4505 ins_encode %{ 4506 __ ldrb($dst$$Register, $mem$$Address); 4507 %} 4508 ins_pipe(iload_mask_mem); 4509 %} 4510 4511 // Load Integer to Short (16 bit signed) 4512 instruct loadI2S(iRegI dst, memoryS mem, immI_16 sixteen) %{ 4513 match(Set dst (RShiftI (LShiftI (LoadI mem) sixteen) sixteen)); 4514 ins_cost(MEMORY_REF_COST); 4515 4516 size(4); 4517 format %{ "LDRSH $dst,$mem\t! int -> short" %} 4518 ins_encode %{ 4519 __ ldrsh($dst$$Register, $mem$$Address); 4520 %} 4521 ins_pipe(iload_mask_mem); 4522 %} 4523 4524 // Load Integer to Unsigned Short (16 bit UNsigned) 4525 instruct loadI2US(iRegI dst, memoryS mem, immI_65535 mask) %{ 4526 match(Set dst (AndI (LoadI mem) mask)); 4527 ins_cost(MEMORY_REF_COST); 4528 4529 size(4); 4530 format %{ "LDRH $dst,$mem\t! int -> ushort/char" %} 4531 ins_encode %{ 4532 __ ldrh($dst$$Register, $mem$$Address); 4533 %} 4534 ins_pipe(iload_mask_mem); 4535 %} 4536 4537 // Load Integer into a Long Register 4538 instruct loadI2L(iRegL dst, memoryI mem) %{ 4539 match(Set dst (ConvI2L (LoadI mem))); 4540 #ifdef AARCH64 4541 ins_cost(MEMORY_REF_COST); 4542 4543 size(4); 4544 format %{ "LDRSW $dst.lo,$mem\t! int -> long" %} 4545 ins_encode %{ 4546 __ ldr_s32($dst$$Register, $mem$$Address); 4547 %} 4548 #else 4549 ins_cost(MEMORY_REF_COST); 4550 4551 size(8); 4552 format %{ "LDR $dst.lo,$mem\t! int -> long\n\t" 4553 "ASR $dst.hi,$dst.lo,31\t! int->long" %} 4554 ins_encode %{ 4555 __ ldr($dst$$Register, $mem$$Address); 4556 __ mov($dst$$Register->successor(), AsmOperand($dst$$Register, asr, 31)); 4557 %} 4558 #endif 4559 ins_pipe(iload_mask_mem); 4560 %} 4561 4562 // Load Integer with mask 0xFF into a Long Register 4563 instruct loadI2L_immI_255(iRegL dst, memoryB mem, immI_255 mask) %{ 4564 match(Set dst (ConvI2L (AndI (LoadI mem) mask))); 4565 #ifdef AARCH64 4566 ins_cost(MEMORY_REF_COST); 4567 4568 size(4); 4569 format %{ "LDRB $dst.lo,$mem\t! int & 0xFF -> long" %} 4570 ins_encode %{ 4571 __ ldrb($dst$$Register, $mem$$Address); 4572 %} 4573 #else 4574 ins_cost(MEMORY_REF_COST); 4575 4576 size(8); 4577 format %{ "LDRB $dst.lo,$mem\t! int & 0xFF -> long\n\t" 4578 "MOV $dst.hi, 0" %} 4579 ins_encode %{ 4580 __ ldrb($dst$$Register, $mem$$Address); 4581 __ mov($dst$$Register->successor(), 0); 4582 %} 4583 #endif 4584 ins_pipe(iload_mem); 4585 %} 4586 4587 // Load Integer with mask 0xFFFF into a Long Register 4588 instruct loadI2L_immI_65535(iRegL dst, memoryS mem, immI_65535 mask) %{ 4589 match(Set dst (ConvI2L (AndI (LoadI mem) mask))); 4590 ins_cost(MEMORY_REF_COST); 4591 4592 #ifdef AARCH64 4593 size(4); 4594 format %{ "LDRH $dst,$mem\t! int & 0xFFFF -> long" %} 4595 ins_encode %{ 4596 __ ldrh($dst$$Register, $mem$$Address); 4597 %} 4598 #else 4599 size(8); 4600 format %{ "LDRH $dst,$mem\t! int & 0xFFFF -> long\n\t" 4601 "MOV $dst.hi, 0" %} 4602 ins_encode %{ 4603 __ ldrh($dst$$Register, $mem$$Address); 4604 __ mov($dst$$Register->successor(), 0); 4605 %} 4606 #endif 4607 ins_pipe(iload_mask_mem); 4608 %} 4609 4610 #ifdef AARCH64 4611 // Load Integer with an immediate mask into a Long Register 4612 instruct loadI2L_limmI(iRegL dst, memoryI mem, limmI mask) %{ 4613 match(Set dst (ConvI2L (AndI (LoadI mem) mask))); 4614 ins_cost(MEMORY_REF_COST + 1*DEFAULT_COST); 4615 4616 size(8); 4617 format %{ "LDRSW $dst,$mem\t! int -> long\n\t" 4618 "AND $dst,$dst,$mask" %} 4619 4620 ins_encode %{ 4621 __ ldr_s32($dst$$Register, $mem$$Address); 4622 __ andr($dst$$Register, $dst$$Register, (uintx)$mask$$constant); 4623 %} 4624 ins_pipe(iload_mem); 4625 %} 4626 #else 4627 // Load Integer with a 31-bit immediate mask into a Long Register 4628 instruct loadI2L_limmU31(iRegL dst, memoryI mem, limmU31 mask) %{ 4629 match(Set dst (ConvI2L (AndI (LoadI mem) mask))); 4630 ins_cost(MEMORY_REF_COST + 2*DEFAULT_COST); 4631 4632 size(12); 4633 format %{ "LDR $dst.lo,$mem\t! int -> long\n\t" 4634 "MOV $dst.hi, 0\n\t" 4635 "AND $dst,$dst,$mask" %} 4636 4637 ins_encode %{ 4638 __ ldr($dst$$Register, $mem$$Address); 4639 __ mov($dst$$Register->successor(), 0); 4640 __ andr($dst$$Register, $dst$$Register, $mask$$constant); 4641 %} 4642 ins_pipe(iload_mem); 4643 %} 4644 #endif 4645 4646 #ifdef AARCH64 4647 // Load Integer with mask into a Long Register 4648 // FIXME: use signedRegI mask, remove tmp? 4649 instruct loadI2L_immI(iRegL dst, memoryI mem, immI mask, iRegI tmp) %{ 4650 match(Set dst (ConvI2L (AndI (LoadI mem) mask))); 4651 effect(TEMP dst, TEMP tmp); 4652 4653 ins_cost(MEMORY_REF_COST + 3*DEFAULT_COST); 4654 format %{ "LDRSW $mem,$dst\t! int & 31-bit mask -> long\n\t" 4655 "MOV_SLOW $tmp,$mask\n\t" 4656 "AND $dst,$tmp,$dst" %} 4657 ins_encode %{ 4658 __ ldrsw($dst$$Register, $mem$$Address); 4659 __ mov_slow($tmp$$Register, $mask$$constant); 4660 __ andr($dst$$Register, $dst$$Register, $tmp$$Register); 4661 %} 4662 ins_pipe(iload_mem); 4663 %} 4664 #else 4665 // Load Integer with a 31-bit mask into a Long Register 4666 // FIXME: use iRegI mask, remove tmp? 4667 instruct loadI2L_immU31(iRegL dst, memoryI mem, immU31 mask, iRegI tmp) %{ 4668 match(Set dst (ConvI2L (AndI (LoadI mem) mask))); 4669 effect(TEMP dst, TEMP tmp); 4670 4671 ins_cost(MEMORY_REF_COST + 4*DEFAULT_COST); 4672 size(20); 4673 format %{ "LDR $mem,$dst\t! int & 31-bit mask -> long\n\t" 4674 "MOV $dst.hi, 0\n\t" 4675 "MOV_SLOW $tmp,$mask\n\t" 4676 "AND $dst,$tmp,$dst" %} 4677 ins_encode %{ 4678 __ ldr($dst$$Register, $mem$$Address); 4679 __ mov($dst$$Register->successor(), 0); 4680 __ mov_slow($tmp$$Register, $mask$$constant); 4681 __ andr($dst$$Register, $dst$$Register, $tmp$$Register); 4682 %} 4683 ins_pipe(iload_mem); 4684 %} 4685 #endif 4686 4687 // Load Unsigned Integer into a Long Register 4688 instruct loadUI2L(iRegL dst, memoryI mem, immL_32bits mask) %{ 4689 match(Set dst (AndL (ConvI2L (LoadI mem)) mask)); 4690 ins_cost(MEMORY_REF_COST); 4691 4692 #ifdef AARCH64 4693 //size(4); 4694 format %{ "LDR_w $dst,$mem\t! uint -> long" %} 4695 ins_encode %{ 4696 __ ldr_w($dst$$Register, $mem$$Address); 4697 %} 4698 #else 4699 size(8); 4700 format %{ "LDR $dst.lo,$mem\t! uint -> long\n\t" 4701 "MOV $dst.hi,0" %} 4702 ins_encode %{ 4703 __ ldr($dst$$Register, $mem$$Address); 4704 __ mov($dst$$Register->successor(), 0); 4705 %} 4706 #endif 4707 ins_pipe(iload_mem); 4708 %} 4709 4710 // Load Long 4711 4712 #ifdef AARCH64 4713 // XXX This variant shouldn't be necessary if 6217251 is implemented 4714 instruct loadLoff(iRegLd dst, memoryScaledL mem, aimmX off, iRegP tmp) %{ 4715 match(Set dst (LoadL (AddP mem off))); 4716 ins_cost(MEMORY_REF_COST + DEFAULT_COST); // assume shift/sign-extend is free 4717 effect(TEMP tmp); 4718 size(4 * 2); 4719 4720 format %{ "LDR $dst,$mem+$off\t! long temp=$tmp" %} 4721 ins_encode %{ 4722 Register base = reg_to_register_object($mem$$base); 4723 __ add($tmp$$Register, base, $off$$constant); 4724 Address nmem = Address::make_raw($tmp$$reg, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none); 4725 __ ldr($dst$$Register, nmem); 4726 %} 4727 ins_pipe(iload_mem); 4728 %} 4729 #endif 4730 4731 instruct loadL(iRegLd dst, memoryL mem ) %{ 4732 #ifdef AARCH64 4733 // already atomic for Aarch64 4734 #else 4735 predicate(!((LoadLNode*)n)->require_atomic_access()); 4736 #endif 4737 match(Set dst (LoadL mem)); 4738 effect(TEMP dst); 4739 ins_cost(MEMORY_REF_COST); 4740 4741 size(4); 4742 format %{ "ldr_64 $dst,$mem\t! long" %} 4743 ins_encode %{ 4744 __ ldr_64($dst$$Register, $mem$$Address); 4745 %} 4746 ins_pipe(iload_mem); 4747 %} 4748 4749 #ifndef AARCH64 4750 instruct loadL_2instr(iRegL dst, memorylong mem ) %{ 4751 predicate(!((LoadLNode*)n)->require_atomic_access()); 4752 match(Set dst (LoadL mem)); 4753 ins_cost(MEMORY_REF_COST + DEFAULT_COST); 4754 4755 size(8); 4756 format %{ "LDR $dst.lo,$mem \t! long order of instrs reversed if $dst.lo == base($mem)\n\t" 4757 "LDR $dst.hi,$mem+4 or $mem" %} 4758 ins_encode %{ 4759 Address Amemlo = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none); 4760 Address Amemhi = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp + 4, relocInfo::none); 4761 4762 if ($dst$$Register == reg_to_register_object($mem$$base)) { 4763 __ ldr($dst$$Register->successor(), Amemhi); 4764 __ ldr($dst$$Register, Amemlo); 4765 } else { 4766 __ ldr($dst$$Register, Amemlo); 4767 __ ldr($dst$$Register->successor(), Amemhi); 4768 } 4769 %} 4770 ins_pipe(iload_mem); 4771 %} 4772 4773 instruct loadL_volatile(iRegL dst, indirect mem ) %{ 4774 predicate(((LoadLNode*)n)->require_atomic_access()); 4775 match(Set dst (LoadL mem)); 4776 ins_cost(MEMORY_REF_COST); 4777 4778 size(4); 4779 format %{ "LDMIA $dst,$mem\t! long" %} 4780 ins_encode %{ 4781 // FIXME: why is ldmia considered atomic? Should be ldrexd 4782 RegisterSet set($dst$$Register); 4783 set = set | reg_to_register_object($dst$$reg + 1); 4784 __ ldmia(reg_to_register_object($mem$$base), set); 4785 %} 4786 ins_pipe(iload_mem); 4787 %} 4788 4789 instruct loadL_volatile_fp(iRegL dst, memoryD mem ) %{ 4790 predicate(((LoadLNode*)n)->require_atomic_access()); 4791 match(Set dst (LoadL mem)); 4792 ins_cost(MEMORY_REF_COST); 4793 4794 size(8); 4795 format %{ "FLDD S14, $mem" 4796 "FMRRD $dst, S14\t! long \n't" %} 4797 ins_encode %{ 4798 __ fldd(S14, $mem$$Address); 4799 __ fmrrd($dst$$Register, $dst$$Register->successor(), S14); 4800 %} 4801 ins_pipe(iload_mem); 4802 %} 4803 4804 instruct loadL_unaligned(iRegL dst, memorylong mem ) %{ 4805 match(Set dst (LoadL_unaligned mem)); 4806 ins_cost(MEMORY_REF_COST); 4807 4808 size(8); 4809 format %{ "LDR $dst.lo,$mem\t! long order of instrs reversed if $dst.lo == base($mem)\n\t" 4810 "LDR $dst.hi,$mem+4" %} 4811 ins_encode %{ 4812 Address Amemlo = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none); 4813 Address Amemhi = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp + 4, relocInfo::none); 4814 4815 if ($dst$$Register == reg_to_register_object($mem$$base)) { 4816 __ ldr($dst$$Register->successor(), Amemhi); 4817 __ ldr($dst$$Register, Amemlo); 4818 } else { 4819 __ ldr($dst$$Register, Amemlo); 4820 __ ldr($dst$$Register->successor(), Amemhi); 4821 } 4822 %} 4823 ins_pipe(iload_mem); 4824 %} 4825 #endif // !AARCH64 4826 4827 // Load Range 4828 instruct loadRange(iRegI dst, memoryI mem) %{ 4829 match(Set dst (LoadRange mem)); 4830 ins_cost(MEMORY_REF_COST); 4831 4832 size(4); 4833 format %{ "LDR_u32 $dst,$mem\t! range" %} 4834 ins_encode %{ 4835 __ ldr_u32($dst$$Register, $mem$$Address); 4836 %} 4837 ins_pipe(iload_mem); 4838 %} 4839 4840 // Load Pointer 4841 4842 #ifdef AARCH64 4843 // XXX This variant shouldn't be necessary if 6217251 is implemented 4844 instruct loadPoff(iRegP dst, memoryScaledP mem, aimmX off, iRegP tmp) %{ 4845 match(Set dst (LoadP (AddP mem off))); 4846 ins_cost(MEMORY_REF_COST + DEFAULT_COST); // assume shift/sign-extend is free 4847 effect(TEMP tmp); 4848 size(4 * 2); 4849 4850 format %{ "LDR $dst,$mem+$off\t! ptr temp=$tmp" %} 4851 ins_encode %{ 4852 Register base = reg_to_register_object($mem$$base); 4853 __ add($tmp$$Register, base, $off$$constant); 4854 Address nmem = Address::make_raw($tmp$$reg, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none); 4855 __ ldr($dst$$Register, nmem); 4856 %} 4857 ins_pipe(iload_mem); 4858 %} 4859 #endif 4860 4861 instruct loadP(iRegP dst, memoryP mem) %{ 4862 match(Set dst (LoadP mem)); 4863 ins_cost(MEMORY_REF_COST); 4864 size(4); 4865 4866 format %{ "LDR $dst,$mem\t! ptr" %} 4867 ins_encode %{ 4868 __ ldr($dst$$Register, $mem$$Address); 4869 %} 4870 ins_pipe(iload_mem); 4871 %} 4872 4873 #ifdef XXX 4874 // FIXME XXXX 4875 //instruct loadSP(iRegP dst, memoryP mem) %{ 4876 instruct loadSP(SPRegP dst, memoryP mem, iRegP tmp) %{ 4877 match(Set dst (LoadP mem)); 4878 effect(TEMP tmp); 4879 ins_cost(MEMORY_REF_COST+1); 4880 size(8); 4881 4882 format %{ "LDR $tmp,$mem\t! ptr\n\t" 4883 "MOV $dst,$tmp\t! ptr" %} 4884 ins_encode %{ 4885 __ ldr($tmp$$Register, $mem$$Address); 4886 __ mov($dst$$Register, $tmp$$Register); 4887 %} 4888 ins_pipe(iload_mem); 4889 %} 4890 #endif 4891 4892 #ifdef _LP64 4893 // Load Compressed Pointer 4894 4895 // XXX This variant shouldn't be necessary if 6217251 is implemented 4896 instruct loadNoff(iRegN dst, memoryScaledI mem, aimmX off, iRegP tmp) %{ 4897 match(Set dst (LoadN (AddP mem off))); 4898 ins_cost(MEMORY_REF_COST + DEFAULT_COST); // assume shift/sign-extend is free 4899 effect(TEMP tmp); 4900 size(4 * 2); 4901 4902 format %{ "ldr_u32 $dst,$mem+$off\t! compressed ptr temp=$tmp" %} 4903 ins_encode %{ 4904 Register base = reg_to_register_object($mem$$base); 4905 __ add($tmp$$Register, base, $off$$constant); 4906 Address nmem = Address::make_raw($tmp$$reg, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none); 4907 __ ldr_u32($dst$$Register, nmem); 4908 %} 4909 ins_pipe(iload_mem); 4910 %} 4911 4912 instruct loadN(iRegN dst, memoryI mem) %{ 4913 match(Set dst (LoadN mem)); 4914 ins_cost(MEMORY_REF_COST); 4915 size(4); 4916 4917 format %{ "ldr_u32 $dst,$mem\t! compressed ptr" %} 4918 ins_encode %{ 4919 __ ldr_u32($dst$$Register, $mem$$Address); 4920 %} 4921 ins_pipe(iload_mem); 4922 %} 4923 #endif 4924 4925 // Load Klass Pointer 4926 instruct loadKlass(iRegP dst, memoryI mem) %{ 4927 match(Set dst (LoadKlass mem)); 4928 ins_cost(MEMORY_REF_COST); 4929 size(4); 4930 4931 format %{ "LDR $dst,$mem\t! klass ptr" %} 4932 ins_encode %{ 4933 __ ldr($dst$$Register, $mem$$Address); 4934 %} 4935 ins_pipe(iload_mem); 4936 %} 4937 4938 #ifdef _LP64 4939 // Load narrow Klass Pointer 4940 instruct loadNKlass(iRegN dst, memoryI mem) %{ 4941 match(Set dst (LoadNKlass mem)); 4942 ins_cost(MEMORY_REF_COST); 4943 size(4); 4944 4945 format %{ "ldr_u32 $dst,$mem\t! compressed klass ptr" %} 4946 ins_encode %{ 4947 __ ldr_u32($dst$$Register, $mem$$Address); 4948 %} 4949 ins_pipe(iload_mem); 4950 %} 4951 #endif 4952 4953 #ifdef AARCH64 4954 // XXX This variant shouldn't be necessary if 6217251 is implemented 4955 instruct loadDoff(regD dst, memoryScaledD mem, aimmX off, iRegP tmp) %{ 4956 match(Set dst (LoadD (AddP mem off))); 4957 ins_cost(MEMORY_REF_COST + DEFAULT_COST); // assume shift/sign-extend is free 4958 effect(TEMP tmp); 4959 size(4 * 2); 4960 4961 format %{ "ldr $dst,$mem+$off\t! double temp=$tmp" %} 4962 ins_encode %{ 4963 Register base = reg_to_register_object($mem$$base); 4964 __ add($tmp$$Register, base, $off$$constant); 4965 Address nmem = Address::make_raw($tmp$$reg, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none); 4966 __ ldr_d($dst$$FloatRegister, nmem); 4967 %} 4968 ins_pipe(floadD_mem); 4969 %} 4970 #endif 4971 4972 instruct loadD(regD dst, memoryD mem) %{ 4973 match(Set dst (LoadD mem)); 4974 ins_cost(MEMORY_REF_COST); 4975 4976 size(4); 4977 // FIXME: needs to be atomic, but ARMv7 A.R.M. guarantees 4978 // only LDREXD and STREXD are 64-bit single-copy atomic 4979 format %{ "FLDD $dst,$mem" %} 4980 ins_encode %{ 4981 __ ldr_double($dst$$FloatRegister, $mem$$Address); 4982 %} 4983 ins_pipe(floadD_mem); 4984 %} 4985 4986 #ifndef AARCH64 4987 // Load Double - UNaligned 4988 instruct loadD_unaligned(regD_low dst, memoryF2 mem ) %{ 4989 match(Set dst (LoadD_unaligned mem)); 4990 ins_cost(MEMORY_REF_COST*2+DEFAULT_COST); 4991 size(8); 4992 format %{ "FLDS $dst.lo,$mem\t! misaligned double\n" 4993 "\tFLDS $dst.hi,$mem+4\t!" %} 4994 ins_encode %{ 4995 Address Amemlo = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none); 4996 Address Amemhi = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp + 4, relocInfo::none); 4997 __ flds($dst$$FloatRegister, Amemlo); 4998 __ flds($dst$$FloatRegister->successor(), Amemhi); 4999 %} 5000 ins_pipe(iload_mem); 5001 %} 5002 #endif 5003 5004 #ifdef AARCH64 5005 // XXX This variant shouldn't be necessary if 6217251 is implemented 5006 instruct loadFoff(regF dst, memoryScaledF mem, aimmX off, iRegP tmp) %{ 5007 match(Set dst (LoadF (AddP mem off))); 5008 ins_cost(MEMORY_REF_COST + DEFAULT_COST); // assume shift/sign-extend is free 5009 effect(TEMP tmp); 5010 size(4 * 2); 5011 5012 format %{ "ldr $dst,$mem+$off\t! float temp=$tmp" %} 5013 ins_encode %{ 5014 Register base = reg_to_register_object($mem$$base); 5015 __ add($tmp$$Register, base, $off$$constant); 5016 Address nmem = Address::make_raw($tmp$$reg, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none); 5017 __ ldr_s($dst$$FloatRegister, nmem); 5018 %} 5019 ins_pipe(floadF_mem); 5020 %} 5021 #endif 5022 5023 instruct loadF(regF dst, memoryF mem) %{ 5024 match(Set dst (LoadF mem)); 5025 5026 ins_cost(MEMORY_REF_COST); 5027 size(4); 5028 format %{ "FLDS $dst,$mem" %} 5029 ins_encode %{ 5030 __ ldr_float($dst$$FloatRegister, $mem$$Address); 5031 %} 5032 ins_pipe(floadF_mem); 5033 %} 5034 5035 #ifdef AARCH64 5036 instruct load_limmI(iRegI dst, limmI src) %{ 5037 match(Set dst src); 5038 ins_cost(DEFAULT_COST + 1); // + 1 because MOV is preferred 5039 format %{ "ORR_w $dst, ZR, $src\t! int" %} 5040 ins_encode %{ 5041 __ orr_w($dst$$Register, ZR, (uintx)$src$$constant); 5042 %} 5043 ins_pipe(ialu_imm); 5044 %} 5045 #endif 5046 5047 // // Load Constant 5048 instruct loadConI( iRegI dst, immI src ) %{ 5049 match(Set dst src); 5050 ins_cost(DEFAULT_COST * 3/2); 5051 format %{ "MOV_SLOW $dst, $src" %} 5052 ins_encode %{ 5053 __ mov_slow($dst$$Register, $src$$constant); 5054 %} 5055 ins_pipe(ialu_hi_lo_reg); 5056 %} 5057 5058 instruct loadConIMov( iRegI dst, immIMov src ) %{ 5059 match(Set dst src); 5060 size(4); 5061 format %{ "MOV $dst, $src" %} 5062 ins_encode %{ 5063 __ mov($dst$$Register, $src$$constant); 5064 %} 5065 ins_pipe(ialu_imm); 5066 %} 5067 5068 #ifndef AARCH64 5069 instruct loadConIMovn( iRegI dst, immIRotn src ) %{ 5070 match(Set dst src); 5071 size(4); 5072 format %{ "MVN $dst, ~$src" %} 5073 ins_encode %{ 5074 __ mvn($dst$$Register, ~$src$$constant); 5075 %} 5076 ins_pipe(ialu_imm_n); 5077 %} 5078 #endif 5079 5080 instruct loadConI16( iRegI dst, immI16 src ) %{ 5081 match(Set dst src); 5082 size(4); 5083 #ifdef AARCH64 5084 format %{ "MOVZ_w $dst, $src" %} 5085 #else 5086 format %{ "MOVW $dst, $src" %} 5087 #endif 5088 ins_encode %{ 5089 #ifdef AARCH64 5090 __ mov_w($dst$$Register, $src$$constant); 5091 #else 5092 __ movw($dst$$Register, $src$$constant); 5093 #endif 5094 %} 5095 ins_pipe(ialu_imm_n); 5096 %} 5097 5098 instruct loadConP(iRegP dst, immP src) %{ 5099 match(Set dst src); 5100 ins_cost(DEFAULT_COST * 3/2); 5101 format %{ "MOV_SLOW $dst,$src\t!ptr" %} 5102 ins_encode %{ 5103 relocInfo::relocType constant_reloc = _opnds[1]->constant_reloc(); 5104 intptr_t val = $src$$constant; 5105 if (constant_reloc == relocInfo::oop_type) { 5106 __ mov_oop($dst$$Register, (jobject)val); 5107 } else if (constant_reloc == relocInfo::metadata_type) { 5108 __ mov_metadata($dst$$Register, (Metadata*)val); 5109 } else { 5110 __ mov_slow($dst$$Register, val); 5111 } 5112 %} 5113 ins_pipe(loadConP); 5114 %} 5115 5116 5117 instruct loadConP_poll(iRegP dst, immP_poll src) %{ 5118 match(Set dst src); 5119 ins_cost(DEFAULT_COST); 5120 format %{ "MOV_SLOW $dst,$src\t!ptr" %} 5121 ins_encode %{ 5122 __ mov_slow($dst$$Register, $src$$constant); 5123 %} 5124 ins_pipe(loadConP_poll); 5125 %} 5126 5127 #ifdef AARCH64 5128 instruct loadConP0(iRegP dst, immP0 src) %{ 5129 match(Set dst src); 5130 ins_cost(DEFAULT_COST); 5131 format %{ "MOV $dst,ZR\t!ptr" %} 5132 ins_encode %{ 5133 __ mov($dst$$Register, ZR); 5134 %} 5135 ins_pipe(ialu_none); 5136 %} 5137 5138 instruct loadConN(iRegN dst, immN src) %{ 5139 match(Set dst src); 5140 ins_cost(DEFAULT_COST * 3/2); 5141 format %{ "SET $dst,$src\t! compressed ptr" %} 5142 ins_encode %{ 5143 Register dst = $dst$$Register; 5144 // FIXME: use $constanttablebase? 5145 __ set_narrow_oop(dst, (jobject)$src$$constant); 5146 %} 5147 ins_pipe(ialu_hi_lo_reg); 5148 %} 5149 5150 instruct loadConN0(iRegN dst, immN0 src) %{ 5151 match(Set dst src); 5152 ins_cost(DEFAULT_COST); 5153 format %{ "MOV $dst,ZR\t! compressed ptr" %} 5154 ins_encode %{ 5155 __ mov($dst$$Register, ZR); 5156 %} 5157 ins_pipe(ialu_none); 5158 %} 5159 5160 instruct loadConNKlass(iRegN dst, immNKlass src) %{ 5161 match(Set dst src); 5162 ins_cost(DEFAULT_COST * 3/2); 5163 format %{ "SET $dst,$src\t! compressed klass ptr" %} 5164 ins_encode %{ 5165 Register dst = $dst$$Register; 5166 // FIXME: use $constanttablebase? 5167 __ set_narrow_klass(dst, (Klass*)$src$$constant); 5168 %} 5169 ins_pipe(ialu_hi_lo_reg); 5170 %} 5171 5172 instruct load_limmL(iRegL dst, limmL src) %{ 5173 match(Set dst src); 5174 ins_cost(DEFAULT_COST); 5175 format %{ "ORR $dst, ZR, $src\t! long" %} 5176 ins_encode %{ 5177 __ orr($dst$$Register, ZR, (uintx)$src$$constant); 5178 %} 5179 ins_pipe(loadConL); 5180 %} 5181 instruct load_immLMov(iRegL dst, immLMov src) %{ 5182 match(Set dst src); 5183 ins_cost(DEFAULT_COST); 5184 format %{ "MOV $dst, $src\t! long" %} 5185 ins_encode %{ 5186 __ mov($dst$$Register, $src$$constant); 5187 %} 5188 ins_pipe(loadConL); 5189 %} 5190 instruct loadConL(iRegL dst, immL src) %{ 5191 match(Set dst src); 5192 ins_cost(DEFAULT_COST * 4); // worst case 5193 format %{ "mov_slow $dst, $src\t! long" %} 5194 ins_encode %{ 5195 // FIXME: use $constanttablebase? 5196 __ mov_slow($dst$$Register, $src$$constant); 5197 %} 5198 ins_pipe(loadConL); 5199 %} 5200 #else 5201 instruct loadConL(iRegL dst, immL src) %{ 5202 match(Set dst src); 5203 ins_cost(DEFAULT_COST * 4); 5204 format %{ "MOV_SLOW $dst.lo, $src & 0x0FFFFFFFFL \t! long\n\t" 5205 "MOV_SLOW $dst.hi, $src >> 32" %} 5206 ins_encode %{ 5207 __ mov_slow(reg_to_register_object($dst$$reg), $src$$constant & 0x0FFFFFFFFL); 5208 __ mov_slow(reg_to_register_object($dst$$reg + 1), ((julong)($src$$constant)) >> 32); 5209 %} 5210 ins_pipe(loadConL); 5211 %} 5212 5213 instruct loadConL16( iRegL dst, immL16 src ) %{ 5214 match(Set dst src); 5215 ins_cost(DEFAULT_COST * 2); 5216 5217 size(8); 5218 format %{ "MOVW $dst.lo, $src \n\t" 5219 "MOVW $dst.hi, 0 \n\t" %} 5220 ins_encode %{ 5221 __ movw($dst$$Register, $src$$constant); 5222 __ movw($dst$$Register->successor(), 0); 5223 %} 5224 ins_pipe(ialu_imm); 5225 %} 5226 #endif 5227 5228 instruct loadConF_imm8(regF dst, imm8F src) %{ 5229 match(Set dst src); 5230 ins_cost(DEFAULT_COST); 5231 size(4); 5232 5233 format %{ "FCONSTS $dst, $src"%} 5234 5235 ins_encode %{ 5236 __ fconsts($dst$$FloatRegister, Assembler::float_num($src$$constant).imm8()); 5237 %} 5238 ins_pipe(loadConFD); // FIXME 5239 %} 5240 5241 #ifdef AARCH64 5242 instruct loadIConF(iRegI dst, immF src) %{ 5243 match(Set dst src); 5244 ins_cost(DEFAULT_COST * 2); 5245 5246 format %{ "MOV_SLOW $dst, $src\t! loadIConF" %} 5247 5248 ins_encode %{ 5249 // FIXME revisit once 6961697 is in 5250 union { 5251 jfloat f; 5252 int i; 5253 } v; 5254 v.f = $src$$constant; 5255 __ mov_slow($dst$$Register, v.i); 5256 %} 5257 ins_pipe(ialu_imm); 5258 %} 5259 #endif 5260 5261 instruct loadConF(regF dst, immF src, iRegI tmp) %{ 5262 match(Set dst src); 5263 ins_cost(DEFAULT_COST * 2); 5264 effect(TEMP tmp); 5265 size(3*4); 5266 5267 format %{ "MOV_SLOW $tmp, $src\n\t" 5268 "FMSR $dst, $tmp"%} 5269 5270 ins_encode %{ 5271 // FIXME revisit once 6961697 is in 5272 union { 5273 jfloat f; 5274 int i; 5275 } v; 5276 v.f = $src$$constant; 5277 __ mov_slow($tmp$$Register, v.i); 5278 __ fmsr($dst$$FloatRegister, $tmp$$Register); 5279 %} 5280 ins_pipe(loadConFD); // FIXME 5281 %} 5282 5283 instruct loadConD_imm8(regD dst, imm8D src) %{ 5284 match(Set dst src); 5285 ins_cost(DEFAULT_COST); 5286 size(4); 5287 5288 format %{ "FCONSTD $dst, $src"%} 5289 5290 ins_encode %{ 5291 __ fconstd($dst$$FloatRegister, Assembler::double_num($src$$constant).imm8()); 5292 %} 5293 ins_pipe(loadConFD); // FIXME 5294 %} 5295 5296 instruct loadConD(regD dst, immD src, iRegP tmp) %{ 5297 match(Set dst src); 5298 effect(TEMP tmp); 5299 ins_cost(MEMORY_REF_COST); 5300 format %{ "FLDD $dst, [$constanttablebase + $constantoffset]\t! load from constant table: double=$src" %} 5301 5302 ins_encode %{ 5303 Register r = $constanttablebase; 5304 int offset = $constantoffset($src); 5305 if (!is_memoryD(offset)) { // can't use a predicate 5306 // in load constant instructs 5307 __ add_slow($tmp$$Register, r, offset); 5308 r = $tmp$$Register; 5309 offset = 0; 5310 } 5311 __ ldr_double($dst$$FloatRegister, Address(r, offset)); 5312 %} 5313 ins_pipe(loadConFD); 5314 %} 5315 5316 // Prefetch instructions. 5317 // Must be safe to execute with invalid address (cannot fault). 5318 5319 instruct prefetchAlloc_mp( memoryP mem ) %{ 5320 predicate(os::is_MP()); 5321 match( PrefetchAllocation mem ); 5322 ins_cost(MEMORY_REF_COST); 5323 size(4); 5324 5325 format %{ "PLDW $mem\t! Prefetch allocation" %} 5326 ins_encode %{ 5327 #ifdef AARCH64 5328 __ prfm(pstl1keep, $mem$$Address); 5329 #else 5330 __ pldw($mem$$Address); 5331 #endif 5332 %} 5333 ins_pipe(iload_mem); 5334 %} 5335 5336 instruct prefetchAlloc_sp( memoryP mem ) %{ 5337 predicate(!os::is_MP()); 5338 match( PrefetchAllocation mem ); 5339 ins_cost(MEMORY_REF_COST); 5340 size(4); 5341 5342 format %{ "PLD $mem\t! Prefetch allocation" %} 5343 ins_encode %{ 5344 #ifdef AARCH64 5345 __ prfm(pstl1keep, $mem$$Address); 5346 #else 5347 __ pld($mem$$Address); 5348 #endif 5349 %} 5350 ins_pipe(iload_mem); 5351 %} 5352 5353 //----------Store Instructions------------------------------------------------- 5354 // Store Byte 5355 instruct storeB(memoryB mem, store_RegI src) %{ 5356 match(Set mem (StoreB mem src)); 5357 ins_cost(MEMORY_REF_COST); 5358 5359 size(4); 5360 format %{ "STRB $src,$mem\t! byte" %} 5361 ins_encode %{ 5362 __ strb($src$$Register, $mem$$Address); 5363 %} 5364 ins_pipe(istore_mem_reg); 5365 %} 5366 5367 instruct storeCM(memoryB mem, store_RegI src) %{ 5368 match(Set mem (StoreCM mem src)); 5369 ins_cost(MEMORY_REF_COST); 5370 5371 size(4); 5372 format %{ "STRB $src,$mem\t! CMS card-mark byte" %} 5373 ins_encode %{ 5374 __ strb($src$$Register, $mem$$Address); 5375 %} 5376 ins_pipe(istore_mem_reg); 5377 %} 5378 5379 // Store Char/Short 5380 5381 #ifdef AARCH64 5382 // XXX This variant shouldn't be necessary if 6217251 is implemented 5383 instruct storeCoff(store_RegI src, memoryScaledS mem, aimmX off, iRegP tmp) %{ 5384 match(Set mem (StoreC (AddP mem off) src)); 5385 ins_cost(MEMORY_REF_COST + DEFAULT_COST); // assume shift/sign-extend is free 5386 effect(TEMP tmp); 5387 size(4 * 2); 5388 5389 format %{ "STRH $src,$mem+$off\t! short temp=$tmp" %} 5390 ins_encode %{ 5391 Register base = reg_to_register_object($mem$$base); 5392 __ add($tmp$$Register, base, $off$$constant); 5393 Address nmem = Address::make_raw($tmp$$reg, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none); 5394 __ strh($src$$Register, nmem); 5395 %} 5396 ins_pipe(istore_mem_reg); 5397 %} 5398 #endif 5399 5400 instruct storeC(memoryS mem, store_RegI src) %{ 5401 match(Set mem (StoreC mem src)); 5402 ins_cost(MEMORY_REF_COST); 5403 5404 size(4); 5405 format %{ "STRH $src,$mem\t! short" %} 5406 ins_encode %{ 5407 __ strh($src$$Register, $mem$$Address); 5408 %} 5409 ins_pipe(istore_mem_reg); 5410 %} 5411 5412 // Store Integer 5413 5414 #ifdef AARCH64 5415 // XXX This variant shouldn't be necessary if 6217251 is implemented 5416 instruct storeIoff(store_RegI src, memoryScaledI mem, aimmX off, iRegP tmp) %{ 5417 match(Set mem (StoreI (AddP mem off) src)); 5418 ins_cost(MEMORY_REF_COST + DEFAULT_COST); // assume shift/sign-extend is free 5419 effect(TEMP tmp); 5420 size(4 * 2); 5421 5422 format %{ "str_32 $src,$mem+$off\t! int temp=$tmp" %} 5423 ins_encode %{ 5424 Register base = reg_to_register_object($mem$$base); 5425 __ add($tmp$$Register, base, $off$$constant); 5426 Address nmem = Address::make_raw($tmp$$reg, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none); 5427 __ str_32($src$$Register, nmem); 5428 %} 5429 ins_pipe(istore_mem_reg); 5430 %} 5431 #endif 5432 5433 instruct storeI(memoryI mem, store_RegI src) %{ 5434 match(Set mem (StoreI mem src)); 5435 ins_cost(MEMORY_REF_COST); 5436 5437 size(4); 5438 format %{ "str_32 $src,$mem" %} 5439 ins_encode %{ 5440 __ str_32($src$$Register, $mem$$Address); 5441 %} 5442 ins_pipe(istore_mem_reg); 5443 %} 5444 5445 // Store Long 5446 5447 #ifdef AARCH64 5448 // XXX This variant shouldn't be necessary if 6217251 is implemented 5449 instruct storeLoff(store_RegLd src, memoryScaledL mem, aimmX off, iRegP tmp) %{ 5450 match(Set mem (StoreL (AddP mem off) src)); 5451 ins_cost(MEMORY_REF_COST + DEFAULT_COST); // assume shift/sign-extend is free 5452 effect(TEMP tmp); 5453 size(4 * 2); 5454 5455 format %{ "str_64 $src,$mem+$off\t! long temp=$tmp" %} 5456 ins_encode %{ 5457 Register base = reg_to_register_object($mem$$base); 5458 __ add($tmp$$Register, base, $off$$constant); 5459 Address nmem = Address::make_raw($tmp$$reg, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none); 5460 __ str_64($src$$Register, nmem); 5461 %} 5462 ins_pipe(istore_mem_reg); 5463 %} 5464 #endif 5465 5466 instruct storeL(memoryL mem, store_RegLd src) %{ 5467 #ifdef AARCH64 5468 // already atomic for Aarch64 5469 #else 5470 predicate(!((StoreLNode*)n)->require_atomic_access()); 5471 #endif 5472 match(Set mem (StoreL mem src)); 5473 ins_cost(MEMORY_REF_COST); 5474 5475 size(4); 5476 format %{ "str_64 $src,$mem\t! long\n\t" %} 5477 5478 ins_encode %{ 5479 __ str_64($src$$Register, $mem$$Address); 5480 %} 5481 ins_pipe(istore_mem_reg); 5482 %} 5483 5484 #ifndef AARCH64 5485 instruct storeL_2instr(memorylong mem, iRegL src) %{ 5486 predicate(!((StoreLNode*)n)->require_atomic_access()); 5487 match(Set mem (StoreL mem src)); 5488 ins_cost(MEMORY_REF_COST + DEFAULT_COST); 5489 5490 size(8); 5491 format %{ "STR $src.lo,$mem\t! long\n\t" 5492 "STR $src.hi,$mem+4" %} 5493 5494 ins_encode %{ 5495 Address Amemlo = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none); 5496 Address Amemhi = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp + 4, relocInfo::none); 5497 __ str($src$$Register, Amemlo); 5498 __ str($src$$Register->successor(), Amemhi); 5499 %} 5500 ins_pipe(istore_mem_reg); 5501 %} 5502 5503 instruct storeL_volatile(indirect mem, iRegL src) %{ 5504 predicate(((StoreLNode*)n)->require_atomic_access()); 5505 match(Set mem (StoreL mem src)); 5506 ins_cost(MEMORY_REF_COST); 5507 size(4); 5508 format %{ "STMIA $src,$mem\t! long" %} 5509 ins_encode %{ 5510 // FIXME: why is stmia considered atomic? Should be strexd 5511 RegisterSet set($src$$Register); 5512 set = set | reg_to_register_object($src$$reg + 1); 5513 __ stmia(reg_to_register_object($mem$$base), set); 5514 %} 5515 ins_pipe(istore_mem_reg); 5516 %} 5517 #endif // !AARCH64 5518 5519 #ifndef AARCH64 5520 instruct storeL_volatile_fp(memoryD mem, iRegL src) %{ 5521 predicate(((StoreLNode*)n)->require_atomic_access()); 5522 match(Set mem (StoreL mem src)); 5523 ins_cost(MEMORY_REF_COST); 5524 size(8); 5525 format %{ "FMDRR S14, $src\t! long \n\t" 5526 "FSTD S14, $mem" %} 5527 ins_encode %{ 5528 __ fmdrr(S14, $src$$Register, $src$$Register->successor()); 5529 __ fstd(S14, $mem$$Address); 5530 %} 5531 ins_pipe(istore_mem_reg); 5532 %} 5533 #endif 5534 5535 #ifdef XXX 5536 // Move SP Pointer 5537 //instruct movSP(sp_ptr_RegP dst, SPRegP src) %{ 5538 //instruct movSP(iRegP dst, SPRegP src) %{ 5539 instruct movSP(store_ptr_RegP dst, SPRegP src) %{ 5540 match(Set dst src); 5541 //predicate(!_kids[1]->_leaf->is_Proj() || _kids[1]->_leaf->as_Proj()->_con == TypeFunc::FramePtr); 5542 ins_cost(MEMORY_REF_COST); 5543 size(4); 5544 5545 format %{ "MOV $dst,$src\t! SP ptr\n\t" %} 5546 ins_encode %{ 5547 assert(false, "XXX1 got here"); 5548 __ mov($dst$$Register, SP); 5549 __ mov($dst$$Register, $src$$Register); 5550 %} 5551 ins_pipe(ialu_reg); 5552 %} 5553 #endif 5554 5555 #ifdef AARCH64 5556 // FIXME 5557 // Store SP Pointer 5558 instruct storeSP(memoryP mem, SPRegP src, iRegP tmp) %{ 5559 match(Set mem (StoreP mem src)); 5560 predicate(_kids[1]->_leaf->is_Proj() && _kids[1]->_leaf->as_Proj()->_con == TypeFunc::FramePtr); 5561 // Multiple StoreP rules, different only in register mask. 5562 // Matcher makes the last always valid. The others will 5563 // only be valid if they cost less than the last valid 5564 // rule. So cost(rule1) < cost(rule2) < cost(last) 5565 // Unlike immediates, register constraints are not checked 5566 // at match time. 5567 ins_cost(MEMORY_REF_COST+DEFAULT_COST+4); 5568 effect(TEMP tmp); 5569 size(8); 5570 5571 format %{ "MOV $tmp,$src\t! SP ptr\n\t" 5572 "STR $tmp,$mem\t! SP ptr" %} 5573 ins_encode %{ 5574 assert($src$$Register == SP, "SP expected"); 5575 __ mov($tmp$$Register, $src$$Register); 5576 __ str($tmp$$Register, $mem$$Address); 5577 %} 5578 ins_pipe(istore_mem_spORreg); // FIXME 5579 %} 5580 #endif // AARCH64 5581 5582 // Store Pointer 5583 5584 #ifdef AARCH64 5585 // XXX This variant shouldn't be necessary if 6217251 is implemented 5586 instruct storePoff(store_ptr_RegP src, memoryScaledP mem, aimmX off, iRegP tmp) %{ 5587 predicate(!_kids[1]->_leaf->is_Proj() || _kids[1]->_leaf->as_Proj()->_con != TypeFunc::FramePtr); 5588 match(Set mem (StoreP (AddP mem off) src)); 5589 ins_cost(MEMORY_REF_COST + DEFAULT_COST); // assume shift/sign-extend is free 5590 effect(TEMP tmp); 5591 size(4 * 2); 5592 5593 format %{ "STR $src,$mem+$off\t! ptr temp=$tmp" %} 5594 ins_encode %{ 5595 Register base = reg_to_register_object($mem$$base); 5596 __ add($tmp$$Register, base, $off$$constant); 5597 Address nmem = Address::make_raw($tmp$$reg, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none); 5598 __ str($src$$Register, nmem); 5599 %} 5600 ins_pipe(istore_mem_reg); 5601 %} 5602 #endif 5603 5604 instruct storeP(memoryP mem, store_ptr_RegP src) %{ 5605 match(Set mem (StoreP mem src)); 5606 #ifdef AARCH64 5607 predicate(!_kids[1]->_leaf->is_Proj() || _kids[1]->_leaf->as_Proj()->_con != TypeFunc::FramePtr); 5608 #endif 5609 ins_cost(MEMORY_REF_COST); 5610 size(4); 5611 5612 format %{ "STR $src,$mem\t! ptr" %} 5613 ins_encode %{ 5614 __ str($src$$Register, $mem$$Address); 5615 %} 5616 ins_pipe(istore_mem_spORreg); 5617 %} 5618 5619 #ifdef AARCH64 5620 // Store NULL Pointer 5621 instruct storeP0(memoryP mem, immP0 src) %{ 5622 match(Set mem (StoreP mem src)); 5623 ins_cost(MEMORY_REF_COST); 5624 size(4); 5625 5626 format %{ "STR ZR,$mem\t! ptr" %} 5627 ins_encode %{ 5628 __ str(ZR, $mem$$Address); 5629 %} 5630 ins_pipe(istore_mem_spORreg); 5631 %} 5632 #endif // AARCH64 5633 5634 #ifdef _LP64 5635 // Store Compressed Pointer 5636 5637 #ifdef AARCH64 5638 // XXX This variant shouldn't be necessary if 6217251 is implemented 5639 instruct storeNoff(store_RegN src, memoryScaledI mem, aimmX off, iRegP tmp) %{ 5640 match(Set mem (StoreN (AddP mem off) src)); 5641 ins_cost(MEMORY_REF_COST + DEFAULT_COST); // assume shift/sign-extend is free 5642 effect(TEMP tmp); 5643 size(4 * 2); 5644 5645 format %{ "str_32 $src,$mem+$off\t! compressed ptr temp=$tmp" %} 5646 ins_encode %{ 5647 Register base = reg_to_register_object($mem$$base); 5648 __ add($tmp$$Register, base, $off$$constant); 5649 Address nmem = Address::make_raw($tmp$$reg, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none); 5650 __ str_32($src$$Register, nmem); 5651 %} 5652 ins_pipe(istore_mem_reg); 5653 %} 5654 #endif 5655 5656 instruct storeN(memoryI mem, store_RegN src) %{ 5657 match(Set mem (StoreN mem src)); 5658 ins_cost(MEMORY_REF_COST); 5659 size(4); 5660 5661 format %{ "str_32 $src,$mem\t! compressed ptr" %} 5662 ins_encode %{ 5663 __ str_32($src$$Register, $mem$$Address); 5664 %} 5665 ins_pipe(istore_mem_reg); 5666 %} 5667 5668 #ifdef AARCH64 5669 // Store NULL Pointer 5670 instruct storeN0(memoryI mem, immN0 src) %{ 5671 match(Set mem (StoreN mem src)); 5672 ins_cost(MEMORY_REF_COST); 5673 size(4); 5674 5675 format %{ "str_32 ZR,$mem\t! compressed ptr" %} 5676 ins_encode %{ 5677 __ str_32(ZR, $mem$$Address); 5678 %} 5679 ins_pipe(istore_mem_reg); 5680 %} 5681 #endif 5682 5683 // Store Compressed Klass Pointer 5684 instruct storeNKlass(memoryI mem, store_RegN src) %{ 5685 match(Set mem (StoreNKlass mem src)); 5686 ins_cost(MEMORY_REF_COST); 5687 size(4); 5688 5689 format %{ "str_32 $src,$mem\t! compressed klass ptr" %} 5690 ins_encode %{ 5691 __ str_32($src$$Register, $mem$$Address); 5692 %} 5693 ins_pipe(istore_mem_reg); 5694 %} 5695 #endif 5696 5697 // Store Double 5698 5699 #ifdef AARCH64 5700 // XXX This variant shouldn't be necessary if 6217251 is implemented 5701 instruct storeDoff(regD src, memoryScaledD mem, aimmX off, iRegP tmp) %{ 5702 match(Set mem (StoreD (AddP mem off) src)); 5703 ins_cost(MEMORY_REF_COST + DEFAULT_COST); // assume shift/sign-extend is free 5704 effect(TEMP tmp); 5705 size(4 * 2); 5706 5707 format %{ "STR $src,$mem+$off\t! double temp=$tmp" %} 5708 ins_encode %{ 5709 Register base = reg_to_register_object($mem$$base); 5710 __ add($tmp$$Register, base, $off$$constant); 5711 Address nmem = Address::make_raw($tmp$$reg, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none); 5712 __ str_d($src$$FloatRegister, nmem); 5713 %} 5714 ins_pipe(fstoreD_mem_reg); 5715 %} 5716 #endif 5717 5718 instruct storeD(memoryD mem, regD src) %{ 5719 match(Set mem (StoreD mem src)); 5720 ins_cost(MEMORY_REF_COST); 5721 5722 size(4); 5723 // FIXME: needs to be atomic, but ARMv7 A.R.M. guarantees 5724 // only LDREXD and STREXD are 64-bit single-copy atomic 5725 format %{ "FSTD $src,$mem" %} 5726 ins_encode %{ 5727 __ str_double($src$$FloatRegister, $mem$$Address); 5728 %} 5729 ins_pipe(fstoreD_mem_reg); 5730 %} 5731 5732 #ifdef AARCH64 5733 instruct movI2F(regF dst, iRegI src) %{ 5734 match(Set dst src); 5735 size(4); 5736 5737 format %{ "FMOV_sw $dst,$src\t! movI2F" %} 5738 ins_encode %{ 5739 __ fmov_sw($dst$$FloatRegister, $src$$Register); 5740 %} 5741 ins_pipe(ialu_reg); // FIXME 5742 %} 5743 5744 instruct movF2I(iRegI dst, regF src) %{ 5745 match(Set dst src); 5746 size(4); 5747 5748 format %{ "FMOV_ws $dst,$src\t! movF2I" %} 5749 ins_encode %{ 5750 __ fmov_ws($dst$$Register, $src$$FloatRegister); 5751 %} 5752 ins_pipe(ialu_reg); // FIXME 5753 %} 5754 #endif 5755 5756 // Store Float 5757 5758 #ifdef AARCH64 5759 // XXX This variant shouldn't be necessary if 6217251 is implemented 5760 instruct storeFoff(regF src, memoryScaledF mem, aimmX off, iRegP tmp) %{ 5761 match(Set mem (StoreF (AddP mem off) src)); 5762 ins_cost(MEMORY_REF_COST + DEFAULT_COST); // assume shift/sign-extend is free 5763 effect(TEMP tmp); 5764 size(4 * 2); 5765 5766 format %{ "str_s $src,$mem+$off\t! float temp=$tmp" %} 5767 ins_encode %{ 5768 Register base = reg_to_register_object($mem$$base); 5769 __ add($tmp$$Register, base, $off$$constant); 5770 Address nmem = Address::make_raw($tmp$$reg, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none); 5771 __ str_s($src$$FloatRegister, nmem); 5772 %} 5773 ins_pipe(fstoreF_mem_reg); 5774 %} 5775 #endif 5776 5777 instruct storeF( memoryF mem, regF src) %{ 5778 match(Set mem (StoreF mem src)); 5779 ins_cost(MEMORY_REF_COST); 5780 5781 size(4); 5782 format %{ "FSTS $src,$mem" %} 5783 ins_encode %{ 5784 __ str_float($src$$FloatRegister, $mem$$Address); 5785 %} 5786 ins_pipe(fstoreF_mem_reg); 5787 %} 5788 5789 #ifdef AARCH64 5790 // Convert oop pointer into compressed form 5791 instruct encodeHeapOop(iRegN dst, iRegP src, flagsReg ccr) %{ 5792 predicate(n->bottom_type()->make_ptr()->ptr() != TypePtr::NotNull); 5793 match(Set dst (EncodeP src)); 5794 effect(KILL ccr); 5795 format %{ "encode_heap_oop $dst, $src" %} 5796 ins_encode %{ 5797 __ encode_heap_oop($dst$$Register, $src$$Register); 5798 %} 5799 ins_pipe(ialu_reg); 5800 %} 5801 5802 instruct encodeHeapOop_not_null(iRegN dst, iRegP src) %{ 5803 predicate(n->bottom_type()->make_ptr()->ptr() == TypePtr::NotNull); 5804 match(Set dst (EncodeP src)); 5805 format %{ "encode_heap_oop_not_null $dst, $src" %} 5806 ins_encode %{ 5807 __ encode_heap_oop_not_null($dst$$Register, $src$$Register); 5808 %} 5809 ins_pipe(ialu_reg); 5810 %} 5811 5812 instruct decodeHeapOop(iRegP dst, iRegN src, flagsReg ccr) %{ 5813 predicate(n->bottom_type()->is_oopptr()->ptr() != TypePtr::NotNull && 5814 n->bottom_type()->is_oopptr()->ptr() != TypePtr::Constant); 5815 match(Set dst (DecodeN src)); 5816 effect(KILL ccr); 5817 format %{ "decode_heap_oop $dst, $src" %} 5818 ins_encode %{ 5819 __ decode_heap_oop($dst$$Register, $src$$Register); 5820 %} 5821 ins_pipe(ialu_reg); 5822 %} 5823 5824 instruct decodeHeapOop_not_null(iRegP dst, iRegN src) %{ 5825 predicate(n->bottom_type()->is_oopptr()->ptr() == TypePtr::NotNull || 5826 n->bottom_type()->is_oopptr()->ptr() == TypePtr::Constant); 5827 match(Set dst (DecodeN src)); 5828 format %{ "decode_heap_oop_not_null $dst, $src" %} 5829 ins_encode %{ 5830 __ decode_heap_oop_not_null($dst$$Register, $src$$Register); 5831 %} 5832 ins_pipe(ialu_reg); 5833 %} 5834 5835 instruct encodeKlass_not_null(iRegN dst, iRegP src) %{ 5836 match(Set dst (EncodePKlass src)); 5837 format %{ "encode_klass_not_null $dst, $src" %} 5838 ins_encode %{ 5839 __ encode_klass_not_null($dst$$Register, $src$$Register); 5840 %} 5841 ins_pipe(ialu_reg); 5842 %} 5843 5844 instruct decodeKlass_not_null(iRegP dst, iRegN src) %{ 5845 match(Set dst (DecodeNKlass src)); 5846 format %{ "decode_klass_not_null $dst, $src" %} 5847 ins_encode %{ 5848 __ decode_klass_not_null($dst$$Register, $src$$Register); 5849 %} 5850 ins_pipe(ialu_reg); 5851 %} 5852 #endif // AARCH64 5853 5854 //----------MemBar Instructions----------------------------------------------- 5855 // Memory barrier flavors 5856 5857 // TODO: take advantage of Aarch64 load-acquire, store-release, etc 5858 // pattern-match out unnecessary membars 5859 instruct membar_storestore() %{ 5860 match(MemBarStoreStore); 5861 ins_cost(4*MEMORY_REF_COST); 5862 5863 size(4); 5864 format %{ "MEMBAR-storestore" %} 5865 ins_encode %{ 5866 __ membar(MacroAssembler::Membar_mask_bits(MacroAssembler::StoreStore), noreg); 5867 %} 5868 ins_pipe(long_memory_op); 5869 %} 5870 5871 instruct membar_acquire() %{ 5872 match(MemBarAcquire); 5873 match(LoadFence); 5874 ins_cost(4*MEMORY_REF_COST); 5875 5876 size(4); 5877 format %{ "MEMBAR-acquire" %} 5878 ins_encode %{ 5879 __ membar(MacroAssembler::Membar_mask_bits(MacroAssembler::LoadLoad | MacroAssembler::LoadStore), noreg); 5880 %} 5881 ins_pipe(long_memory_op); 5882 %} 5883 5884 instruct membar_acquire_lock() %{ 5885 match(MemBarAcquireLock); 5886 ins_cost(0); 5887 5888 size(0); 5889 format %{ "!MEMBAR-acquire (CAS in prior FastLock so empty encoding)" %} 5890 ins_encode( ); 5891 ins_pipe(empty); 5892 %} 5893 5894 instruct membar_release() %{ 5895 match(MemBarRelease); 5896 match(StoreFence); 5897 ins_cost(4*MEMORY_REF_COST); 5898 5899 size(4); 5900 format %{ "MEMBAR-release" %} 5901 ins_encode %{ 5902 __ membar(MacroAssembler::Membar_mask_bits(MacroAssembler::StoreStore | MacroAssembler::LoadStore), noreg); 5903 %} 5904 ins_pipe(long_memory_op); 5905 %} 5906 5907 instruct membar_release_lock() %{ 5908 match(MemBarReleaseLock); 5909 ins_cost(0); 5910 5911 size(0); 5912 format %{ "!MEMBAR-release (CAS in succeeding FastUnlock so empty encoding)" %} 5913 ins_encode( ); 5914 ins_pipe(empty); 5915 %} 5916 5917 instruct membar_volatile() %{ 5918 match(MemBarVolatile); 5919 ins_cost(4*MEMORY_REF_COST); 5920 5921 size(4); 5922 format %{ "MEMBAR-volatile" %} 5923 ins_encode %{ 5924 __ membar(MacroAssembler::StoreLoad, noreg); 5925 %} 5926 ins_pipe(long_memory_op); 5927 %} 5928 5929 instruct unnecessary_membar_volatile() %{ 5930 match(MemBarVolatile); 5931 predicate(Matcher::post_store_load_barrier(n)); 5932 ins_cost(0); 5933 5934 size(0); 5935 format %{ "!MEMBAR-volatile (unnecessary so empty encoding)" %} 5936 ins_encode( ); 5937 ins_pipe(empty); 5938 %} 5939 5940 //----------Register Move Instructions----------------------------------------- 5941 // instruct roundDouble_nop(regD dst) %{ 5942 // match(Set dst (RoundDouble dst)); 5943 // ins_pipe(empty); 5944 // %} 5945 5946 5947 // instruct roundFloat_nop(regF dst) %{ 5948 // match(Set dst (RoundFloat dst)); 5949 // ins_pipe(empty); 5950 // %} 5951 5952 5953 #ifdef AARCH64 5954 // 0 constant in register 5955 instruct zrImmI0(ZRRegI dst, immI0 imm) %{ 5956 match(Set dst imm); 5957 size(0); 5958 ins_cost(0); 5959 5960 format %{ "! ZR (int 0)" %} 5961 ins_encode( /*empty encoding*/ ); 5962 ins_pipe(ialu_none); 5963 %} 5964 5965 // 0 constant in register 5966 instruct zrImmL0(ZRRegL dst, immL0 imm) %{ 5967 match(Set dst imm); 5968 size(0); 5969 ins_cost(0); 5970 5971 format %{ "! ZR (long 0)" %} 5972 ins_encode( /*empty encoding*/ ); 5973 ins_pipe(ialu_none); 5974 %} 5975 5976 #ifdef XXX 5977 // 0 constant in register 5978 instruct zrImmN0(ZRRegN dst, immN0 imm) %{ 5979 match(Set dst imm); 5980 size(0); 5981 ins_cost(0); 5982 5983 format %{ "! ZR (compressed pointer NULL)" %} 5984 ins_encode( /*empty encoding*/ ); 5985 ins_pipe(ialu_none); 5986 %} 5987 5988 // 0 constant in register 5989 instruct zrImmP0(ZRRegP dst, immP0 imm) %{ 5990 match(Set dst imm); 5991 size(0); 5992 ins_cost(0); 5993 5994 format %{ "! ZR (NULL)" %} 5995 ins_encode( /*empty encoding*/ ); 5996 ins_pipe(ialu_none); 5997 %} 5998 #endif 5999 #endif // AARCH64 6000 6001 // Cast Index to Pointer for unsafe natives 6002 instruct castX2P(iRegX src, iRegP dst) %{ 6003 match(Set dst (CastX2P src)); 6004 6005 format %{ "MOV $dst,$src\t! IntX->Ptr if $dst != $src" %} 6006 ins_encode %{ 6007 if ($dst$$Register != $src$$Register) { 6008 __ mov($dst$$Register, $src$$Register); 6009 } 6010 %} 6011 ins_pipe(ialu_reg); 6012 %} 6013 6014 // Cast Pointer to Index for unsafe natives 6015 instruct castP2X(iRegP src, iRegX dst) %{ 6016 match(Set dst (CastP2X src)); 6017 6018 format %{ "MOV $dst,$src\t! Ptr->IntX if $dst != $src" %} 6019 ins_encode %{ 6020 if ($dst$$Register != $src$$Register) { 6021 __ mov($dst$$Register, $src$$Register); 6022 } 6023 %} 6024 ins_pipe(ialu_reg); 6025 %} 6026 6027 #ifndef AARCH64 6028 //----------Conditional Move--------------------------------------------------- 6029 // Conditional move 6030 instruct cmovIP_reg(cmpOpP cmp, flagsRegP pcc, iRegI dst, iRegI src) %{ 6031 match(Set dst (CMoveI (Binary cmp pcc) (Binary dst src))); 6032 ins_cost(150); 6033 size(4); 6034 format %{ "MOV$cmp $dst,$src\t! int" %} 6035 ins_encode %{ 6036 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 6037 %} 6038 ins_pipe(ialu_reg); 6039 %} 6040 #endif 6041 6042 #ifdef AARCH64 6043 instruct cmovI_reg3(cmpOp cmp, flagsReg icc, iRegI dst, iRegI src1, iRegI src2) %{ 6044 match(Set dst (CMoveI (Binary cmp icc) (Binary src2 src1))); 6045 ins_cost(150); 6046 size(4); 6047 format %{ "CSEL $dst,$src1,$src2,$cmp\t! int" %} 6048 ins_encode %{ 6049 __ csel($dst$$Register, $src1$$Register, $src2$$Register, (AsmCondition)($cmp$$cmpcode)); 6050 %} 6051 ins_pipe(ialu_reg); 6052 %} 6053 6054 instruct cmovL_reg3(cmpOp cmp, flagsReg icc, iRegL dst, iRegL src1, iRegL src2) %{ 6055 match(Set dst (CMoveL (Binary cmp icc) (Binary src2 src1))); 6056 ins_cost(150); 6057 size(4); 6058 format %{ "CSEL $dst,$src1,$src2,$cmp\t! long" %} 6059 ins_encode %{ 6060 __ csel($dst$$Register, $src1$$Register, $src2$$Register, (AsmCondition)($cmp$$cmpcode)); 6061 %} 6062 ins_pipe(ialu_reg); 6063 %} 6064 6065 instruct cmovP_reg3(cmpOp cmp, flagsReg icc, iRegP dst, iRegP src1, iRegP src2) %{ 6066 match(Set dst (CMoveP (Binary cmp icc) (Binary src2 src1))); 6067 ins_cost(150); 6068 size(4); 6069 format %{ "CSEL $dst,$src1,$src2,$cmp\t! ptr" %} 6070 ins_encode %{ 6071 __ csel($dst$$Register, $src1$$Register, $src2$$Register, (AsmCondition)($cmp$$cmpcode)); 6072 %} 6073 ins_pipe(ialu_reg); 6074 %} 6075 6076 instruct cmovN_reg3(cmpOp cmp, flagsReg icc, iRegN dst, iRegN src1, iRegN src2) %{ 6077 match(Set dst (CMoveN (Binary cmp icc) (Binary src2 src1))); 6078 ins_cost(150); 6079 size(4); 6080 format %{ "CSEL $dst,$src1,$src2,$cmp\t! compressed ptr" %} 6081 ins_encode %{ 6082 __ csel($dst$$Register, $src1$$Register, $src2$$Register, (AsmCondition)($cmp$$cmpcode)); 6083 %} 6084 ins_pipe(ialu_reg); 6085 %} 6086 6087 instruct cmovIP_reg3(cmpOpP cmp, flagsRegP icc, iRegI dst, iRegI src1, iRegI src2) %{ 6088 match(Set dst (CMoveI (Binary cmp icc) (Binary src2 src1))); 6089 ins_cost(150); 6090 size(4); 6091 format %{ "CSEL $dst,$src1,$src2,$cmp\t! int" %} 6092 ins_encode %{ 6093 __ csel($dst$$Register, $src1$$Register, $src2$$Register, (AsmCondition)($cmp$$cmpcode)); 6094 %} 6095 ins_pipe(ialu_reg); 6096 %} 6097 6098 instruct cmovLP_reg3(cmpOpP cmp, flagsRegP icc, iRegL dst, iRegL src1, iRegL src2) %{ 6099 match(Set dst (CMoveL (Binary cmp icc) (Binary src2 src1))); 6100 ins_cost(150); 6101 size(4); 6102 format %{ "CSEL $dst,$src1,$src2,$cmp\t! long" %} 6103 ins_encode %{ 6104 __ csel($dst$$Register, $src1$$Register, $src2$$Register, (AsmCondition)($cmp$$cmpcode)); 6105 %} 6106 ins_pipe(ialu_reg); 6107 %} 6108 6109 instruct cmovPP_reg3(cmpOpP cmp, flagsRegP icc, iRegP dst, iRegP src1, iRegP src2) %{ 6110 match(Set dst (CMoveP (Binary cmp icc) (Binary src2 src1))); 6111 ins_cost(150); 6112 size(4); 6113 format %{ "CSEL $dst,$src1,$src2,$cmp\t! ptr" %} 6114 ins_encode %{ 6115 __ csel($dst$$Register, $src1$$Register, $src2$$Register, (AsmCondition)($cmp$$cmpcode)); 6116 %} 6117 ins_pipe(ialu_reg); 6118 %} 6119 6120 instruct cmovNP_reg3(cmpOpP cmp, flagsRegP icc, iRegN dst, iRegN src1, iRegN src2) %{ 6121 match(Set dst (CMoveN (Binary cmp icc) (Binary src2 src1))); 6122 ins_cost(150); 6123 size(4); 6124 format %{ "CSEL $dst,$src1,$src2,$cmp\t! compressed ptr" %} 6125 ins_encode %{ 6126 __ csel($dst$$Register, $src1$$Register, $src2$$Register, (AsmCondition)($cmp$$cmpcode)); 6127 %} 6128 ins_pipe(ialu_reg); 6129 %} 6130 6131 instruct cmovIU_reg3(cmpOpU cmp, flagsRegU icc, iRegI dst, iRegI src1, iRegI src2) %{ 6132 match(Set dst (CMoveI (Binary cmp icc) (Binary src2 src1))); 6133 ins_cost(150); 6134 size(4); 6135 format %{ "CSEL $dst,$src1,$src2,$cmp\t! int" %} 6136 ins_encode %{ 6137 __ csel($dst$$Register, $src1$$Register, $src2$$Register, (AsmCondition)($cmp$$cmpcode)); 6138 %} 6139 ins_pipe(ialu_reg); 6140 %} 6141 6142 instruct cmovLU_reg3(cmpOpU cmp, flagsRegU icc, iRegL dst, iRegL src1, iRegL src2) %{ 6143 match(Set dst (CMoveL (Binary cmp icc) (Binary src2 src1))); 6144 ins_cost(150); 6145 size(4); 6146 format %{ "CSEL $dst,$src1,$src2,$cmp\t! long" %} 6147 ins_encode %{ 6148 __ csel($dst$$Register, $src1$$Register, $src2$$Register, (AsmCondition)($cmp$$cmpcode)); 6149 %} 6150 ins_pipe(ialu_reg); 6151 %} 6152 6153 instruct cmovPU_reg3(cmpOpU cmp, flagsRegU icc, iRegP dst, iRegP src1, iRegP src2) %{ 6154 match(Set dst (CMoveP (Binary cmp icc) (Binary src2 src1))); 6155 ins_cost(150); 6156 size(4); 6157 format %{ "CSEL $dst,$src1,$src2,$cmp\t! ptr" %} 6158 ins_encode %{ 6159 __ csel($dst$$Register, $src1$$Register, $src2$$Register, (AsmCondition)($cmp$$cmpcode)); 6160 %} 6161 ins_pipe(ialu_reg); 6162 %} 6163 6164 instruct cmovNU_reg3(cmpOpU cmp, flagsRegU icc, iRegN dst, iRegN src1, iRegN src2) %{ 6165 match(Set dst (CMoveN (Binary cmp icc) (Binary src2 src1))); 6166 ins_cost(150); 6167 size(4); 6168 format %{ "CSEL $dst,$src1,$src2,$cmp\t! compressed ptr" %} 6169 ins_encode %{ 6170 __ csel($dst$$Register, $src1$$Register, $src2$$Register, (AsmCondition)($cmp$$cmpcode)); 6171 %} 6172 ins_pipe(ialu_reg); 6173 %} 6174 6175 instruct cmovIZ_reg3(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegI dst, iRegI src1, iRegI src2) %{ 6176 match(Set dst (CMoveI (Binary cmp icc) (Binary src2 src1))); 6177 ins_cost(150); 6178 size(4); 6179 format %{ "CSEL $dst,$src1,$src2,$cmp\t! int" %} 6180 ins_encode %{ 6181 __ csel($dst$$Register, $src1$$Register, $src2$$Register, (AsmCondition)($cmp$$cmpcode)); 6182 %} 6183 ins_pipe(ialu_reg); 6184 %} 6185 6186 instruct cmovLZ_reg3(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegL dst, iRegL src1, iRegL src2) %{ 6187 match(Set dst (CMoveL (Binary cmp icc) (Binary src2 src1))); 6188 ins_cost(150); 6189 size(4); 6190 format %{ "CSEL $dst,$src1,$src2,$cmp\t! long" %} 6191 ins_encode %{ 6192 __ csel($dst$$Register, $src1$$Register, $src2$$Register, (AsmCondition)($cmp$$cmpcode)); 6193 %} 6194 ins_pipe(ialu_reg); 6195 %} 6196 6197 instruct cmovPZ_reg3(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegP dst, iRegP src1, iRegP src2) %{ 6198 match(Set dst (CMoveP (Binary cmp icc) (Binary src2 src1))); 6199 ins_cost(150); 6200 size(4); 6201 format %{ "CSEL $dst,$src1,$src2,$cmp\t! ptr" %} 6202 ins_encode %{ 6203 __ csel($dst$$Register, $src1$$Register, $src2$$Register, (AsmCondition)($cmp$$cmpcode)); 6204 %} 6205 ins_pipe(ialu_reg); 6206 %} 6207 6208 instruct cmovNZ_reg3(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegN dst, iRegN src1, iRegN src2) %{ 6209 match(Set dst (CMoveN (Binary cmp icc) (Binary src2 src1))); 6210 ins_cost(150); 6211 size(4); 6212 format %{ "CSEL $dst,$src1,$src2,$cmp\t! compressed ptr" %} 6213 ins_encode %{ 6214 __ csel($dst$$Register, $src1$$Register, $src2$$Register, (AsmCondition)($cmp$$cmpcode)); 6215 %} 6216 ins_pipe(ialu_reg); 6217 %} 6218 #endif // AARCH64 6219 6220 #ifndef AARCH64 6221 instruct cmovIP_immMov(cmpOpP cmp, flagsRegP pcc, iRegI dst, immIMov src) %{ 6222 match(Set dst (CMoveI (Binary cmp pcc) (Binary dst src))); 6223 ins_cost(140); 6224 size(4); 6225 format %{ "MOV$cmp $dst,$src" %} 6226 ins_encode %{ 6227 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 6228 %} 6229 ins_pipe(ialu_imm); 6230 %} 6231 6232 instruct cmovIP_imm16(cmpOpP cmp, flagsRegP pcc, iRegI dst, immI16 src) %{ 6233 match(Set dst (CMoveI (Binary cmp pcc) (Binary dst src))); 6234 ins_cost(140); 6235 size(4); 6236 format %{ "MOVw$cmp $dst,$src" %} 6237 ins_encode %{ 6238 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 6239 %} 6240 ins_pipe(ialu_imm); 6241 %} 6242 #endif 6243 6244 instruct cmovI_reg(cmpOp cmp, flagsReg icc, iRegI dst, iRegI src) %{ 6245 match(Set dst (CMoveI (Binary cmp icc) (Binary dst src))); 6246 ins_cost(150); 6247 size(4); 6248 format %{ "MOV$cmp $dst,$src" %} 6249 ins_encode %{ 6250 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 6251 %} 6252 ins_pipe(ialu_reg); 6253 %} 6254 6255 #ifdef AARCH64 6256 instruct cmovL_reg(cmpOp cmp, flagsReg icc, iRegL dst, iRegL src) %{ 6257 match(Set dst (CMoveL (Binary cmp icc) (Binary dst src))); 6258 ins_cost(150); 6259 size(4); 6260 format %{ "MOV$cmp $dst,$src\t! long" %} 6261 ins_encode %{ 6262 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 6263 %} 6264 ins_pipe(ialu_reg); 6265 %} 6266 #endif 6267 6268 #ifndef AARCH64 6269 instruct cmovI_immMov(cmpOp cmp, flagsReg icc, iRegI dst, immIMov src) %{ 6270 match(Set dst (CMoveI (Binary cmp icc) (Binary dst src))); 6271 ins_cost(140); 6272 size(4); 6273 format %{ "MOV$cmp $dst,$src" %} 6274 ins_encode %{ 6275 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 6276 %} 6277 ins_pipe(ialu_imm); 6278 %} 6279 6280 instruct cmovII_imm16(cmpOp cmp, flagsReg icc, iRegI dst, immI16 src) %{ 6281 match(Set dst (CMoveI (Binary cmp icc) (Binary dst src))); 6282 ins_cost(140); 6283 size(4); 6284 format %{ "MOVw$cmp $dst,$src" %} 6285 ins_encode %{ 6286 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 6287 %} 6288 ins_pipe(ialu_imm); 6289 %} 6290 #endif 6291 6292 instruct cmovII_reg_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegI dst, iRegI src) %{ 6293 match(Set dst (CMoveI (Binary cmp icc) (Binary dst src))); 6294 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || 6295 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne || 6296 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || 6297 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge); 6298 ins_cost(150); 6299 size(4); 6300 format %{ "MOV$cmp $dst,$src" %} 6301 ins_encode %{ 6302 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 6303 %} 6304 ins_pipe(ialu_reg); 6305 %} 6306 6307 #ifndef AARCH64 6308 instruct cmovII_immMov_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegI dst, immIMov src) %{ 6309 match(Set dst (CMoveI (Binary cmp icc) (Binary dst src))); 6310 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || 6311 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne || 6312 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || 6313 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge); 6314 ins_cost(140); 6315 size(4); 6316 format %{ "MOV$cmp $dst,$src" %} 6317 ins_encode %{ 6318 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 6319 %} 6320 ins_pipe(ialu_imm); 6321 %} 6322 6323 instruct cmovII_imm16_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegI dst, immI16 src) %{ 6324 match(Set dst (CMoveI (Binary cmp icc) (Binary dst src))); 6325 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || 6326 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne || 6327 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || 6328 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge); 6329 ins_cost(140); 6330 size(4); 6331 format %{ "MOVW$cmp $dst,$src" %} 6332 ins_encode %{ 6333 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 6334 %} 6335 ins_pipe(ialu_imm); 6336 %} 6337 #endif 6338 6339 instruct cmovIIu_reg(cmpOpU cmp, flagsRegU icc, iRegI dst, iRegI src) %{ 6340 match(Set dst (CMoveI (Binary cmp icc) (Binary dst src))); 6341 ins_cost(150); 6342 size(4); 6343 format %{ "MOV$cmp $dst,$src" %} 6344 ins_encode %{ 6345 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 6346 %} 6347 ins_pipe(ialu_reg); 6348 %} 6349 6350 #ifndef AARCH64 6351 instruct cmovIIu_immMov(cmpOpU cmp, flagsRegU icc, iRegI dst, immIMov src) %{ 6352 match(Set dst (CMoveI (Binary cmp icc) (Binary dst src))); 6353 ins_cost(140); 6354 size(4); 6355 format %{ "MOV$cmp $dst,$src" %} 6356 ins_encode %{ 6357 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 6358 %} 6359 ins_pipe(ialu_imm); 6360 %} 6361 6362 instruct cmovIIu_imm16(cmpOpU cmp, flagsRegU icc, iRegI dst, immI16 src) %{ 6363 match(Set dst (CMoveI (Binary cmp icc) (Binary dst src))); 6364 ins_cost(140); 6365 size(4); 6366 format %{ "MOVW$cmp $dst,$src" %} 6367 ins_encode %{ 6368 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 6369 %} 6370 ins_pipe(ialu_imm); 6371 %} 6372 #endif 6373 6374 // Conditional move 6375 instruct cmovPP_reg(cmpOpP cmp, flagsRegP pcc, iRegP dst, iRegP src) %{ 6376 match(Set dst (CMoveP (Binary cmp pcc) (Binary dst src))); 6377 ins_cost(150); 6378 size(4); 6379 format %{ "MOV$cmp $dst,$src" %} 6380 ins_encode %{ 6381 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 6382 %} 6383 ins_pipe(ialu_reg); 6384 %} 6385 6386 instruct cmovPP_imm(cmpOpP cmp, flagsRegP pcc, iRegP dst, immP0 src) %{ 6387 match(Set dst (CMoveP (Binary cmp pcc) (Binary dst src))); 6388 ins_cost(140); 6389 size(4); 6390 #ifdef AARCH64 6391 format %{ "MOV$cmp $dst,ZR" %} 6392 #else 6393 format %{ "MOV$cmp $dst,$src" %} 6394 #endif 6395 ins_encode %{ 6396 #ifdef AARCH64 6397 __ mov($dst$$Register, ZR, (AsmCondition)($cmp$$cmpcode)); 6398 #else 6399 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 6400 #endif 6401 %} 6402 ins_pipe(ialu_imm); 6403 %} 6404 6405 // This instruction also works with CmpN so we don't need cmovPN_reg. 6406 instruct cmovPI_reg(cmpOp cmp, flagsReg icc, iRegP dst, iRegP src) %{ 6407 match(Set dst (CMoveP (Binary cmp icc) (Binary dst src))); 6408 ins_cost(150); 6409 6410 size(4); 6411 format %{ "MOV$cmp $dst,$src\t! ptr" %} 6412 ins_encode %{ 6413 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 6414 %} 6415 ins_pipe(ialu_reg); 6416 %} 6417 6418 instruct cmovPI_reg_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegP dst, iRegP src) %{ 6419 match(Set dst (CMoveP (Binary cmp icc) (Binary dst src))); 6420 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || 6421 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne || 6422 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || 6423 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge); 6424 ins_cost(150); 6425 6426 size(4); 6427 format %{ "MOV$cmp $dst,$src\t! ptr" %} 6428 ins_encode %{ 6429 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 6430 %} 6431 ins_pipe(ialu_reg); 6432 %} 6433 6434 instruct cmovPIu_reg(cmpOpU cmp, flagsRegU icc, iRegP dst, iRegP src) %{ 6435 match(Set dst (CMoveP (Binary cmp icc) (Binary dst src))); 6436 ins_cost(150); 6437 6438 size(4); 6439 format %{ "MOV$cmp $dst,$src\t! ptr" %} 6440 ins_encode %{ 6441 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 6442 %} 6443 ins_pipe(ialu_reg); 6444 %} 6445 6446 instruct cmovPI_imm(cmpOp cmp, flagsReg icc, iRegP dst, immP0 src) %{ 6447 match(Set dst (CMoveP (Binary cmp icc) (Binary dst src))); 6448 ins_cost(140); 6449 6450 size(4); 6451 #ifdef AARCH64 6452 format %{ "MOV$cmp $dst,ZR\t! ptr" %} 6453 #else 6454 format %{ "MOV$cmp $dst,$src\t! ptr" %} 6455 #endif 6456 ins_encode %{ 6457 #ifdef AARCH64 6458 __ mov($dst$$Register, ZR, (AsmCondition)($cmp$$cmpcode)); 6459 #else 6460 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 6461 #endif 6462 %} 6463 ins_pipe(ialu_imm); 6464 %} 6465 6466 instruct cmovPI_imm_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegP dst, immP0 src) %{ 6467 match(Set dst (CMoveP (Binary cmp icc) (Binary dst src))); 6468 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || 6469 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne || 6470 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || 6471 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge); 6472 ins_cost(140); 6473 6474 size(4); 6475 #ifdef AARCH64 6476 format %{ "MOV$cmp $dst,ZR\t! ptr" %} 6477 #else 6478 format %{ "MOV$cmp $dst,$src\t! ptr" %} 6479 #endif 6480 ins_encode %{ 6481 #ifdef AARCH64 6482 __ mov($dst$$Register, ZR, (AsmCondition)($cmp$$cmpcode)); 6483 #else 6484 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 6485 #endif 6486 %} 6487 ins_pipe(ialu_imm); 6488 %} 6489 6490 instruct cmovPIu_imm(cmpOpU cmp, flagsRegU icc, iRegP dst, immP0 src) %{ 6491 match(Set dst (CMoveP (Binary cmp icc) (Binary dst src))); 6492 ins_cost(140); 6493 6494 size(4); 6495 #ifdef AARCH64 6496 format %{ "MOV$cmp $dst,ZR\t! ptr" %} 6497 #else 6498 format %{ "MOV$cmp $dst,$src\t! ptr" %} 6499 #endif 6500 ins_encode %{ 6501 #ifdef AARCH64 6502 __ mov($dst$$Register, ZR, (AsmCondition)($cmp$$cmpcode)); 6503 #else 6504 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 6505 #endif 6506 %} 6507 ins_pipe(ialu_imm); 6508 %} 6509 6510 #ifdef AARCH64 6511 // Conditional move 6512 instruct cmovF_reg(cmpOp cmp, flagsReg icc, regF dst, regF src1, regF src2) %{ 6513 match(Set dst (CMoveF (Binary cmp icc) (Binary src2 src1))); 6514 ins_cost(150); 6515 size(4); 6516 format %{ "FCSEL_s $dst,$src1,$src2,$cmp" %} 6517 ins_encode %{ 6518 __ fcsel_s($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, (AsmCondition)($cmp$$cmpcode)); 6519 %} 6520 ins_pipe(int_conditional_float_move); 6521 %} 6522 6523 instruct cmovD_reg(cmpOp cmp, flagsReg icc, regD dst, regD src1, regD src2) %{ 6524 match(Set dst (CMoveD (Binary cmp icc) (Binary src2 src1))); 6525 ins_cost(150); 6526 size(4); 6527 format %{ "FCSEL_d $dst,$src1,$src2,$cmp" %} 6528 ins_encode %{ 6529 __ fcsel_d($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, (AsmCondition)($cmp$$cmpcode)); 6530 %} 6531 ins_pipe(int_conditional_float_move); 6532 %} 6533 6534 instruct cmovFP_reg(cmpOpP cmp, flagsRegP icc, regF dst, regF src1, regF src2) %{ 6535 match(Set dst (CMoveF (Binary cmp icc) (Binary src2 src1))); 6536 ins_cost(150); 6537 size(4); 6538 format %{ "FCSEL_s $dst,$src1,$src2,$cmp" %} 6539 ins_encode %{ 6540 __ fcsel_s($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, (AsmCondition)($cmp$$cmpcode)); 6541 %} 6542 ins_pipe(int_conditional_float_move); 6543 %} 6544 6545 instruct cmovDP_reg(cmpOpP cmp, flagsRegP icc, regD dst, regD src1, regD src2) %{ 6546 match(Set dst (CMoveD (Binary cmp icc) (Binary src2 src1))); 6547 ins_cost(150); 6548 size(4); 6549 format %{ "FCSEL_d $dst,$src1,$src2,$cmp" %} 6550 ins_encode %{ 6551 __ fcsel_d($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, (AsmCondition)($cmp$$cmpcode)); 6552 %} 6553 ins_pipe(int_conditional_float_move); 6554 %} 6555 6556 instruct cmovFU_reg(cmpOpU cmp, flagsRegU icc, regF dst, regF src1, regF src2) %{ 6557 match(Set dst (CMoveF (Binary cmp icc) (Binary src2 src1))); 6558 ins_cost(150); 6559 size(4); 6560 format %{ "FCSEL_s $dst,$src1,$src2,$cmp" %} 6561 ins_encode %{ 6562 __ fcsel_s($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, (AsmCondition)($cmp$$cmpcode)); 6563 %} 6564 ins_pipe(int_conditional_float_move); 6565 %} 6566 6567 instruct cmovDU_reg(cmpOpU cmp, flagsRegU icc, regD dst, regD src1, regD src2) %{ 6568 match(Set dst (CMoveD (Binary cmp icc) (Binary src2 src1))); 6569 ins_cost(150); 6570 size(4); 6571 format %{ "FCSEL_d $dst,$src1,$src2,$cmp" %} 6572 ins_encode %{ 6573 __ fcsel_d($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, (AsmCondition)($cmp$$cmpcode)); 6574 %} 6575 ins_pipe(int_conditional_float_move); 6576 %} 6577 6578 instruct cmovFZ_reg(cmpOp0 cmp, flagsReg_EQNELTGE icc, regF dst, regF src1, regF src2) %{ 6579 match(Set dst (CMoveF (Binary cmp icc) (Binary src2 src1))); 6580 ins_cost(150); 6581 size(4); 6582 format %{ "FCSEL_s $dst,$src1,$src2,$cmp" %} 6583 ins_encode %{ 6584 __ fcsel_s($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, (AsmCondition)($cmp$$cmpcode)); 6585 %} 6586 ins_pipe(int_conditional_float_move); 6587 %} 6588 6589 instruct cmovDZ_reg(cmpOp0 cmp, flagsReg_EQNELTGE icc, regD dst, regD src1, regD src2) %{ 6590 match(Set dst (CMoveD (Binary cmp icc) (Binary src2 src1))); 6591 ins_cost(150); 6592 size(4); 6593 format %{ "FCSEL_d $dst,$src1,$src2,$cmp" %} 6594 ins_encode %{ 6595 __ fcsel_d($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, (AsmCondition)($cmp$$cmpcode)); 6596 %} 6597 ins_pipe(int_conditional_float_move); 6598 %} 6599 6600 #else // !AARCH64 6601 6602 // Conditional move 6603 instruct cmovFP_reg(cmpOpP cmp, flagsRegP pcc, regF dst, regF src) %{ 6604 match(Set dst (CMoveF (Binary cmp pcc) (Binary dst src))); 6605 ins_cost(150); 6606 size(4); 6607 format %{ "FCPYS$cmp $dst,$src" %} 6608 ins_encode %{ 6609 __ fcpys($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode)); 6610 %} 6611 ins_pipe(int_conditional_float_move); 6612 %} 6613 6614 instruct cmovFI_reg(cmpOp cmp, flagsReg icc, regF dst, regF src) %{ 6615 match(Set dst (CMoveF (Binary cmp icc) (Binary dst src))); 6616 ins_cost(150); 6617 6618 size(4); 6619 format %{ "FCPYS$cmp $dst,$src" %} 6620 ins_encode %{ 6621 __ fcpys($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode)); 6622 %} 6623 ins_pipe(int_conditional_float_move); 6624 %} 6625 6626 instruct cmovFI_reg_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, regF dst, regF src) %{ 6627 match(Set dst (CMoveF (Binary cmp icc) (Binary dst src))); 6628 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || 6629 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne || 6630 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || 6631 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge); 6632 ins_cost(150); 6633 6634 size(4); 6635 format %{ "FCPYS$cmp $dst,$src" %} 6636 ins_encode %{ 6637 __ fcpys($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode)); 6638 %} 6639 ins_pipe(int_conditional_float_move); 6640 %} 6641 6642 instruct cmovFIu_reg(cmpOpU cmp, flagsRegU icc, regF dst, regF src) %{ 6643 match(Set dst (CMoveF (Binary cmp icc) (Binary dst src))); 6644 ins_cost(150); 6645 6646 size(4); 6647 format %{ "FCPYS$cmp $dst,$src" %} 6648 ins_encode %{ 6649 __ fcpys($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode)); 6650 %} 6651 ins_pipe(int_conditional_float_move); 6652 %} 6653 6654 // Conditional move 6655 instruct cmovDP_reg(cmpOpP cmp, flagsRegP pcc, regD dst, regD src) %{ 6656 match(Set dst (CMoveD (Binary cmp pcc) (Binary dst src))); 6657 ins_cost(150); 6658 size(4); 6659 format %{ "FCPYD$cmp $dst,$src" %} 6660 ins_encode %{ 6661 __ fcpyd($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode)); 6662 %} 6663 ins_pipe(int_conditional_double_move); 6664 %} 6665 6666 instruct cmovDI_reg(cmpOp cmp, flagsReg icc, regD dst, regD src) %{ 6667 match(Set dst (CMoveD (Binary cmp icc) (Binary dst src))); 6668 ins_cost(150); 6669 6670 size(4); 6671 format %{ "FCPYD$cmp $dst,$src" %} 6672 ins_encode %{ 6673 __ fcpyd($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode)); 6674 %} 6675 ins_pipe(int_conditional_double_move); 6676 %} 6677 6678 instruct cmovDI_reg_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, regD dst, regD src) %{ 6679 match(Set dst (CMoveD (Binary cmp icc) (Binary dst src))); 6680 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); 6681 ins_cost(150); 6682 6683 size(4); 6684 format %{ "FCPYD$cmp $dst,$src" %} 6685 ins_encode %{ 6686 __ fcpyd($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode)); 6687 %} 6688 ins_pipe(int_conditional_double_move); 6689 %} 6690 6691 instruct cmovDIu_reg(cmpOpU cmp, flagsRegU icc, regD dst, regD src) %{ 6692 match(Set dst (CMoveD (Binary cmp icc) (Binary dst src))); 6693 ins_cost(150); 6694 6695 size(4); 6696 format %{ "FCPYD$cmp $dst,$src" %} 6697 ins_encode %{ 6698 __ fcpyd($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode)); 6699 %} 6700 ins_pipe(int_conditional_double_move); 6701 %} 6702 6703 // Conditional move 6704 instruct cmovLP_reg(cmpOpP cmp, flagsRegP pcc, iRegL dst, iRegL src) %{ 6705 match(Set dst (CMoveL (Binary cmp pcc) (Binary dst src))); 6706 ins_cost(150); 6707 6708 size(8); 6709 format %{ "MOV$cmp $dst.lo,$src.lo\t! long\n\t" 6710 "MOV$cmp $dst.hi,$src.hi" %} 6711 ins_encode %{ 6712 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 6713 __ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode)); 6714 %} 6715 ins_pipe(ialu_reg); 6716 %} 6717 6718 // TODO: try immLRot2 instead, (0, $con$$constant) becomes 6719 // (hi($con$$constant), lo($con$$constant)) becomes 6720 instruct cmovLP_immRot(cmpOpP cmp, flagsRegP pcc, iRegL dst, immLlowRot src) %{ 6721 match(Set dst (CMoveL (Binary cmp pcc) (Binary dst src))); 6722 ins_cost(140); 6723 6724 size(8); 6725 format %{ "MOV$cmp $dst.lo,$src\t! long\n\t" 6726 "MOV$cmp $dst.hi,0" %} 6727 ins_encode %{ 6728 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 6729 __ mov($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode)); 6730 %} 6731 ins_pipe(ialu_imm); 6732 %} 6733 6734 instruct cmovLP_imm16(cmpOpP cmp, flagsRegP pcc, iRegL dst, immL16 src) %{ 6735 match(Set dst (CMoveL (Binary cmp pcc) (Binary dst src))); 6736 ins_cost(140); 6737 6738 size(8); 6739 format %{ "MOV$cmp $dst.lo,$src\t! long\n\t" 6740 "MOV$cmp $dst.hi,0" %} 6741 ins_encode %{ 6742 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 6743 __ mov($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode)); 6744 %} 6745 ins_pipe(ialu_imm); 6746 %} 6747 6748 instruct cmovLI_reg(cmpOp cmp, flagsReg icc, iRegL dst, iRegL src) %{ 6749 match(Set dst (CMoveL (Binary cmp icc) (Binary dst src))); 6750 ins_cost(150); 6751 6752 size(8); 6753 format %{ "MOV$cmp $dst.lo,$src.lo\t! long\n\t" 6754 "MOV$cmp $dst.hi,$src.hi" %} 6755 ins_encode %{ 6756 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 6757 __ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode)); 6758 %} 6759 ins_pipe(ialu_reg); 6760 %} 6761 6762 instruct cmovLI_reg_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegL dst, iRegL src) %{ 6763 match(Set dst (CMoveL (Binary cmp icc) (Binary dst src))); 6764 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || 6765 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne || 6766 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || 6767 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge); 6768 ins_cost(150); 6769 6770 size(8); 6771 format %{ "MOV$cmp $dst.lo,$src.lo\t! long\n\t" 6772 "MOV$cmp $dst.hi,$src.hi" %} 6773 ins_encode %{ 6774 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 6775 __ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode)); 6776 %} 6777 ins_pipe(ialu_reg); 6778 %} 6779 6780 // TODO: try immLRot2 instead, (0, $con$$constant) becomes 6781 // (hi($con$$constant), lo($con$$constant)) becomes 6782 instruct cmovLI_immRot(cmpOp cmp, flagsReg icc, iRegL dst, immLlowRot src) %{ 6783 match(Set dst (CMoveL (Binary cmp icc) (Binary dst src))); 6784 ins_cost(140); 6785 6786 size(8); 6787 format %{ "MOV$cmp $dst.lo,$src\t! long\n\t" 6788 "MOV$cmp $dst.hi,0" %} 6789 ins_encode %{ 6790 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 6791 __ mov($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode)); 6792 %} 6793 ins_pipe(ialu_imm); 6794 %} 6795 6796 // TODO: try immLRot2 instead, (0, $con$$constant) becomes 6797 // (hi($con$$constant), lo($con$$constant)) becomes 6798 instruct cmovLI_immRot_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegL dst, immLlowRot src) %{ 6799 match(Set dst (CMoveL (Binary cmp icc) (Binary dst src))); 6800 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || 6801 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne || 6802 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || 6803 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge); 6804 ins_cost(140); 6805 6806 size(8); 6807 format %{ "MOV$cmp $dst.lo,$src\t! long\n\t" 6808 "MOV$cmp $dst.hi,0" %} 6809 ins_encode %{ 6810 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 6811 __ mov($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode)); 6812 %} 6813 ins_pipe(ialu_imm); 6814 %} 6815 6816 instruct cmovLI_imm16(cmpOp cmp, flagsReg icc, iRegL dst, immL16 src) %{ 6817 match(Set dst (CMoveL (Binary cmp icc) (Binary dst src))); 6818 ins_cost(140); 6819 6820 size(8); 6821 format %{ "MOV$cmp $dst.lo,$src\t! long\n\t" 6822 "MOV$cmp $dst.hi,0" %} 6823 ins_encode %{ 6824 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 6825 __ movw($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode)); 6826 %} 6827 ins_pipe(ialu_imm); 6828 %} 6829 6830 instruct cmovLI_imm16_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegL dst, immL16 src) %{ 6831 match(Set dst (CMoveL (Binary cmp icc) (Binary dst src))); 6832 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || 6833 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne || 6834 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || 6835 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge); 6836 ins_cost(140); 6837 6838 size(8); 6839 format %{ "MOV$cmp $dst.lo,$src\t! long\n\t" 6840 "MOV$cmp $dst.hi,0" %} 6841 ins_encode %{ 6842 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 6843 __ movw($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode)); 6844 %} 6845 ins_pipe(ialu_imm); 6846 %} 6847 6848 instruct cmovLIu_reg(cmpOpU cmp, flagsRegU icc, iRegL dst, iRegL src) %{ 6849 match(Set dst (CMoveL (Binary cmp icc) (Binary dst src))); 6850 ins_cost(150); 6851 6852 size(8); 6853 format %{ "MOV$cmp $dst.lo,$src.lo\t! long\n\t" 6854 "MOV$cmp $dst.hi,$src.hi" %} 6855 ins_encode %{ 6856 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 6857 __ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode)); 6858 %} 6859 ins_pipe(ialu_reg); 6860 %} 6861 #endif // !AARCH64 6862 6863 6864 //----------OS and Locking Instructions---------------------------------------- 6865 6866 // This name is KNOWN by the ADLC and cannot be changed. 6867 // The ADLC forces a 'TypeRawPtr::BOTTOM' output type 6868 // for this guy. 6869 instruct tlsLoadP(RthreadRegP dst) %{ 6870 match(Set dst (ThreadLocal)); 6871 6872 size(0); 6873 ins_cost(0); 6874 format %{ "! TLS is in $dst" %} 6875 ins_encode( /*empty encoding*/ ); 6876 ins_pipe(ialu_none); 6877 %} 6878 6879 instruct checkCastPP( iRegP dst ) %{ 6880 match(Set dst (CheckCastPP dst)); 6881 6882 size(0); 6883 format %{ "! checkcastPP of $dst" %} 6884 ins_encode( /*empty encoding*/ ); 6885 ins_pipe(empty); 6886 %} 6887 6888 6889 instruct castPP( iRegP dst ) %{ 6890 match(Set dst (CastPP dst)); 6891 format %{ "! castPP of $dst" %} 6892 ins_encode( /*empty encoding*/ ); 6893 ins_pipe(empty); 6894 %} 6895 6896 instruct castII( iRegI dst ) %{ 6897 match(Set dst (CastII dst)); 6898 format %{ "! castII of $dst" %} 6899 ins_encode( /*empty encoding*/ ); 6900 ins_cost(0); 6901 ins_pipe(empty); 6902 %} 6903 6904 //----------Arithmetic Instructions-------------------------------------------- 6905 // Addition Instructions 6906 // Register Addition 6907 instruct addI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{ 6908 match(Set dst (AddI src1 src2)); 6909 6910 size(4); 6911 format %{ "add_32 $dst,$src1,$src2\t! int" %} 6912 ins_encode %{ 6913 __ add_32($dst$$Register, $src1$$Register, $src2$$Register); 6914 %} 6915 ins_pipe(ialu_reg_reg); 6916 %} 6917 6918 #ifndef AARCH64 6919 instruct addshlI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 6920 match(Set dst (AddI (LShiftI src1 src2) src3)); 6921 6922 size(4); 6923 format %{ "add_32 $dst,$src3,$src1<<$src2\t! int" %} 6924 ins_encode %{ 6925 __ add_32($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsl, $src2$$Register)); 6926 %} 6927 ins_pipe(ialu_reg_reg); 6928 %} 6929 #endif 6930 6931 #ifdef AARCH64 6932 #ifdef TODO 6933 instruct addshlL_reg_imm_reg(iRegL dst, iRegL src1, immU6 src2, iRegL src3) %{ 6934 match(Set dst (AddL (LShiftL src1 src2) src3)); 6935 6936 size(4); 6937 format %{ "ADD $dst,$src3,$src1<<$src2\t! long" %} 6938 ins_encode %{ 6939 __ add($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsl, $src2$$constant)); 6940 %} 6941 ins_pipe(ialu_reg_reg); 6942 %} 6943 #endif 6944 #endif 6945 6946 instruct addshlI_reg_imm_reg(iRegI dst, iRegI src1, immU5 src2, iRegI src3) %{ 6947 match(Set dst (AddI (LShiftI src1 src2) src3)); 6948 6949 size(4); 6950 format %{ "add_32 $dst,$src3,$src1<<$src2\t! int" %} 6951 ins_encode %{ 6952 __ add_32($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsl, $src2$$constant)); 6953 %} 6954 ins_pipe(ialu_reg_reg); 6955 %} 6956 6957 #ifndef AARCH64 6958 instruct addsarI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 6959 match(Set dst (AddI (RShiftI src1 src2) src3)); 6960 6961 size(4); 6962 format %{ "add_32 $dst,$src3,$src1>>$src2\t! int" %} 6963 ins_encode %{ 6964 __ add_32($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, asr, $src2$$Register)); 6965 %} 6966 ins_pipe(ialu_reg_reg); 6967 %} 6968 #endif 6969 6970 instruct addsarI_reg_imm_reg(iRegI dst, iRegI src1, immU5 src2, iRegI src3) %{ 6971 match(Set dst (AddI (RShiftI src1 src2) src3)); 6972 6973 size(4); 6974 format %{ "add_32 $dst,$src3,$src1>>$src2\t! int" %} 6975 ins_encode %{ 6976 __ add_32($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, asr, $src2$$constant)); 6977 %} 6978 ins_pipe(ialu_reg_reg); 6979 %} 6980 6981 #ifndef AARCH64 6982 instruct addshrI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 6983 match(Set dst (AddI (URShiftI src1 src2) src3)); 6984 6985 size(4); 6986 format %{ "add_32 $dst,$src3,$src1>>>$src2\t! int" %} 6987 ins_encode %{ 6988 __ add_32($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsr, $src2$$Register)); 6989 %} 6990 ins_pipe(ialu_reg_reg); 6991 %} 6992 #endif 6993 6994 instruct addshrI_reg_imm_reg(iRegI dst, iRegI src1, immU5 src2, iRegI src3) %{ 6995 match(Set dst (AddI (URShiftI src1 src2) src3)); 6996 6997 size(4); 6998 format %{ "add_32 $dst,$src3,$src1>>>$src2\t! int" %} 6999 ins_encode %{ 7000 __ add_32($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsr, $src2$$constant)); 7001 %} 7002 ins_pipe(ialu_reg_reg); 7003 %} 7004 7005 // Immediate Addition 7006 instruct addI_reg_aimmI(iRegI dst, iRegI src1, aimmI src2) %{ 7007 match(Set dst (AddI src1 src2)); 7008 7009 size(4); 7010 format %{ "add_32 $dst,$src1,$src2\t! int" %} 7011 ins_encode %{ 7012 __ add_32($dst$$Register, $src1$$Register, $src2$$constant); 7013 %} 7014 ins_pipe(ialu_reg_imm); 7015 %} 7016 7017 // Pointer Register Addition 7018 instruct addP_reg_reg(iRegP dst, iRegP src1, iRegX src2) %{ 7019 match(Set dst (AddP src1 src2)); 7020 7021 size(4); 7022 format %{ "ADD $dst,$src1,$src2\t! ptr" %} 7023 ins_encode %{ 7024 __ add($dst$$Register, $src1$$Register, $src2$$Register); 7025 %} 7026 ins_pipe(ialu_reg_reg); 7027 %} 7028 7029 #ifdef AARCH64 7030 // unshifted I2L operand 7031 operand unshiftedI2L(iRegI src2) %{ 7032 //constraint(ALLOC_IN_RC(sp_ptr_reg)); 7033 match(ConvI2L src2); 7034 7035 op_cost(1); 7036 format %{ "$src2.w" %} 7037 interface(MEMORY_INTER) %{ 7038 base($src2); 7039 index(0xff); 7040 scale(0x0); 7041 disp(0x0); 7042 %} 7043 %} 7044 7045 // shifted I2L operand 7046 operand shiftedI2L(iRegI src2, immI_0_4 src3) %{ 7047 //constraint(ALLOC_IN_RC(sp_ptr_reg)); 7048 match(LShiftX (ConvI2L src2) src3); 7049 7050 op_cost(1); 7051 format %{ "$src2.w << $src3" %} 7052 interface(MEMORY_INTER) %{ 7053 base($src2); 7054 index(0xff); 7055 scale($src3); 7056 disp(0x0); 7057 %} 7058 %} 7059 7060 opclass shiftedRegI(shiftedI2L, unshiftedI2L); 7061 7062 instruct shlL_reg_regI(iRegL dst, iRegI src1, immU6 src2) %{ 7063 match(Set dst (LShiftL (ConvI2L src1) src2)); 7064 7065 size(4); 7066 format %{ "LSL $dst,$src1.w,$src2\t! ptr" %} 7067 ins_encode %{ 7068 int c = $src2$$constant; 7069 int r = 64 - c; 7070 int s = 31; 7071 if (s >= r) { 7072 s = r - 1; 7073 } 7074 __ sbfm($dst$$Register, $src1$$Register, r, s); 7075 %} 7076 ins_pipe(ialu_reg_reg); 7077 %} 7078 7079 instruct addP_reg_regI(iRegP dst, iRegP src1, shiftedRegI src2) %{ 7080 match(Set dst (AddP src1 src2)); 7081 7082 ins_cost(DEFAULT_COST * 3/2); 7083 size(4); 7084 format %{ "ADD $dst,$src1,$src2, sxtw\t! ptr" %} 7085 ins_encode %{ 7086 Register base = reg_to_register_object($src2$$base); 7087 __ add($dst$$Register, $src1$$Register, base, ex_sxtw, $src2$$scale); 7088 %} 7089 ins_pipe(ialu_reg_reg); 7090 %} 7091 #endif 7092 7093 // shifted iRegX operand 7094 operand shiftedX(iRegX src2, shimmX src3) %{ 7095 //constraint(ALLOC_IN_RC(sp_ptr_reg)); 7096 match(LShiftX src2 src3); 7097 7098 op_cost(1); 7099 format %{ "$src2 << $src3" %} 7100 interface(MEMORY_INTER) %{ 7101 base($src2); 7102 index(0xff); 7103 scale($src3); 7104 disp(0x0); 7105 %} 7106 %} 7107 7108 instruct addshlP_reg_reg_imm(iRegP dst, iRegP src1, shiftedX src2) %{ 7109 match(Set dst (AddP src1 src2)); 7110 7111 ins_cost(DEFAULT_COST * 3/2); 7112 size(4); 7113 format %{ "ADD $dst,$src1,$src2\t! ptr" %} 7114 ins_encode %{ 7115 Register base = reg_to_register_object($src2$$base); 7116 __ add($dst$$Register, $src1$$Register, AsmOperand(base, lsl, $src2$$scale)); 7117 %} 7118 ins_pipe(ialu_reg_reg); 7119 %} 7120 7121 // Pointer Immediate Addition 7122 instruct addP_reg_aimmX(iRegP dst, iRegP src1, aimmX src2) %{ 7123 match(Set dst (AddP src1 src2)); 7124 7125 size(4); 7126 format %{ "ADD $dst,$src1,$src2\t! ptr" %} 7127 ins_encode %{ 7128 __ add($dst$$Register, $src1$$Register, $src2$$constant); 7129 %} 7130 ins_pipe(ialu_reg_imm); 7131 %} 7132 7133 // Long Addition 7134 #ifdef AARCH64 7135 instruct addL_reg_reg(iRegL dst, iRegL src1, iRegL src2) %{ 7136 match(Set dst (AddL src1 src2)); 7137 size(4); 7138 format %{ "ADD $dst,$src1,$src2\t! long" %} 7139 ins_encode %{ 7140 __ add($dst$$Register, $src1$$Register, $src2$$Register); 7141 %} 7142 ins_pipe(ialu_reg_reg); 7143 %} 7144 7145 instruct addL_reg_regI(iRegL dst, iRegL src1, shiftedRegI src2) %{ 7146 match(Set dst (AddL src1 src2)); 7147 7148 ins_cost(DEFAULT_COST * 3/2); 7149 size(4); 7150 format %{ "ADD $dst,$src1,$src2, sxtw\t! long" %} 7151 ins_encode %{ 7152 Register base = reg_to_register_object($src2$$base); 7153 __ add($dst$$Register, $src1$$Register, base, ex_sxtw, $src2$$scale); 7154 %} 7155 ins_pipe(ialu_reg_reg); 7156 %} 7157 #else 7158 instruct addL_reg_reg(iRegL dst, iRegL src1, iRegL src2, flagsReg ccr) %{ 7159 match(Set dst (AddL src1 src2)); 7160 effect(KILL ccr); 7161 size(8); 7162 format %{ "ADDS $dst.lo,$src1.lo,$src2.lo\t! long\n\t" 7163 "ADC $dst.hi,$src1.hi,$src2.hi" %} 7164 ins_encode %{ 7165 __ adds($dst$$Register, $src1$$Register, $src2$$Register); 7166 __ adc($dst$$Register->successor(), $src1$$Register->successor(), $src2$$Register->successor()); 7167 %} 7168 ins_pipe(ialu_reg_reg); 7169 %} 7170 #endif 7171 7172 #ifdef AARCH64 7173 // Immediate Addition 7174 instruct addL_reg_aimm(iRegL dst, iRegL src1, aimmL src2) %{ 7175 match(Set dst (AddL src1 src2)); 7176 7177 size(4); 7178 format %{ "ADD $dst,$src1,$src2\t! long" %} 7179 ins_encode %{ 7180 __ add($dst$$Register, $src1$$Register, $src2$$constant); 7181 %} 7182 ins_pipe(ialu_reg_imm); 7183 %} 7184 7185 instruct addL_reg_immLneg(iRegL dst, iRegL src1, aimmLneg src2) %{ 7186 match(Set dst (SubL src1 src2)); 7187 7188 size(4); 7189 format %{ "ADD $dst,$src1,-($src2)\t! long" %} 7190 ins_encode %{ 7191 __ add($dst$$Register, $src1$$Register, -$src2$$constant); 7192 %} 7193 ins_pipe(ialu_reg_imm); 7194 %} 7195 #else 7196 // TODO 7197 #endif 7198 7199 #ifndef AARCH64 7200 // TODO: try immLRot2 instead, (0, $con$$constant) becomes 7201 // (hi($con$$constant), lo($con$$constant)) becomes 7202 instruct addL_reg_immRot(iRegL dst, iRegL src1, immLlowRot con, flagsReg ccr) %{ 7203 match(Set dst (AddL src1 con)); 7204 effect(KILL ccr); 7205 size(8); 7206 format %{ "ADDS $dst.lo,$src1.lo,$con\t! long\n\t" 7207 "ADC $dst.hi,$src1.hi,0" %} 7208 ins_encode %{ 7209 __ adds($dst$$Register, $src1$$Register, $con$$constant); 7210 __ adc($dst$$Register->successor(), $src1$$Register->successor(), 0); 7211 %} 7212 ins_pipe(ialu_reg_imm); 7213 %} 7214 #endif 7215 7216 //----------Conditional_store-------------------------------------------------- 7217 // Conditional-store of the updated heap-top. 7218 // Used during allocation of the shared heap. 7219 // Sets flags (EQ) on success. 7220 7221 // TODO: optimize out barriers with AArch64 load-acquire/store-release 7222 // LoadP-locked. 7223 instruct loadPLocked(iRegP dst, memoryex mem) %{ 7224 match(Set dst (LoadPLocked mem)); 7225 size(4); 7226 format %{ "LDREX $dst,$mem" %} 7227 ins_encode %{ 7228 #ifdef AARCH64 7229 Register base = reg_to_register_object($mem$$base); 7230 __ ldxr($dst$$Register, base); 7231 #else 7232 __ ldrex($dst$$Register,$mem$$Address); 7233 #endif 7234 %} 7235 ins_pipe(iload_mem); 7236 %} 7237 7238 instruct storePConditional( memoryex heap_top_ptr, iRegP oldval, iRegP newval, iRegI tmp, flagsRegP pcc ) %{ 7239 predicate(_kids[1]->_kids[0]->_leaf->Opcode() == Op_LoadPLocked); // only works in conjunction with a LoadPLocked node 7240 match(Set pcc (StorePConditional heap_top_ptr (Binary oldval newval))); 7241 effect( TEMP tmp ); 7242 size(8); 7243 format %{ "STREX $tmp,$newval,$heap_top_ptr\n\t" 7244 "CMP $tmp, 0" %} 7245 ins_encode %{ 7246 #ifdef AARCH64 7247 Register base = reg_to_register_object($heap_top_ptr$$base); 7248 __ stxr($tmp$$Register, $newval$$Register, base); 7249 #else 7250 __ strex($tmp$$Register, $newval$$Register, $heap_top_ptr$$Address); 7251 #endif 7252 __ cmp($tmp$$Register, 0); 7253 %} 7254 ins_pipe( long_memory_op ); 7255 %} 7256 7257 // Conditional-store of an intx value. 7258 instruct storeXConditional( memoryex mem, iRegX oldval, iRegX newval, iRegX tmp, flagsReg icc ) %{ 7259 #ifdef AARCH64 7260 match(Set icc (StoreLConditional mem (Binary oldval newval))); 7261 effect( TEMP tmp ); 7262 size(28); 7263 format %{ "loop:\n\t" 7264 "LDXR $tmp, $mem\t! If $oldval==[$mem] Then store $newval into [$mem], DOESN'T set $newval=[$mem] in any case\n\t" 7265 "SUBS $tmp, $tmp, $oldval\n\t" 7266 "B.ne done\n\t" 7267 "STXR $tmp, $newval, $mem\n\t" 7268 "CBNZ_w $tmp, loop\n\t" 7269 "CMP $tmp, 0\n\t" 7270 "done:\n\t" 7271 "membar LoadStore|LoadLoad" %} 7272 #else 7273 match(Set icc (StoreIConditional mem (Binary oldval newval))); 7274 effect( TEMP tmp ); 7275 size(28); 7276 format %{ "loop: \n\t" 7277 "LDREX $tmp, $mem\t! If $oldval==[$mem] Then store $newval into [$mem], DOESN'T set $newval=[$mem] in any case\n\t" 7278 "XORS $tmp,$tmp, $oldval\n\t" 7279 "STREX.eq $tmp, $newval, $mem\n\t" 7280 "CMP.eq $tmp, 1 \n\t" 7281 "B.eq loop \n\t" 7282 "TEQ $tmp, 0\n\t" 7283 "membar LoadStore|LoadLoad" %} 7284 #endif 7285 ins_encode %{ 7286 Label loop; 7287 __ bind(loop); 7288 #ifdef AARCH64 7289 // FIXME: use load-acquire/store-release, remove membar? 7290 Label done; 7291 Register base = reg_to_register_object($mem$$base); 7292 __ ldxr($tmp$$Register, base); 7293 __ subs($tmp$$Register, $tmp$$Register, $oldval$$Register); 7294 __ b(done, ne); 7295 __ stxr($tmp$$Register, $newval$$Register, base); 7296 __ cbnz_w($tmp$$Register, loop); 7297 __ cmp($tmp$$Register, 0); 7298 __ bind(done); 7299 #else 7300 __ ldrex($tmp$$Register, $mem$$Address); 7301 __ eors($tmp$$Register, $tmp$$Register, $oldval$$Register); 7302 __ strex($tmp$$Register, $newval$$Register, $mem$$Address, eq); 7303 __ cmp($tmp$$Register, 1, eq); 7304 __ b(loop, eq); 7305 __ teq($tmp$$Register, 0); 7306 #endif 7307 // used by biased locking only. Requires a membar. 7308 __ membar(MacroAssembler::Membar_mask_bits(MacroAssembler::LoadStore | MacroAssembler::LoadLoad), noreg); 7309 %} 7310 ins_pipe( long_memory_op ); 7311 %} 7312 7313 // No flag versions for CompareAndSwap{P,I,L} because matcher can't match them 7314 7315 #ifdef AARCH64 7316 // TODO: if combined with membar, elide membar and use 7317 // load-acquire/store-release if appropriate 7318 instruct compareAndSwapL_bool(memoryex mem, iRegL oldval, iRegL newval, iRegI res, iRegI tmp, flagsReg ccr) %{ 7319 match(Set res (CompareAndSwapL mem (Binary oldval newval))); 7320 effect( KILL ccr, TEMP tmp); 7321 size(24); 7322 format %{ "loop:\n\t" 7323 "LDXR $tmp, $mem\t! If $oldval==[$mem] Then store $newval into [$mem]\n\t" 7324 "CMP $tmp, $oldval\n\t" 7325 "B.ne done\n\t" 7326 "STXR $tmp, $newval, $mem\n\t" 7327 "CBNZ_w $tmp, loop\n\t" 7328 "done:\n\t" 7329 "CSET_w $res, eq" %} 7330 ins_encode %{ 7331 Register base = reg_to_register_object($mem$$base); 7332 Label loop, done; 7333 __ bind(loop); 7334 __ ldxr($tmp$$Register, base); 7335 __ cmp($tmp$$Register, $oldval$$Register); 7336 __ b(done, ne); 7337 __ stxr($tmp$$Register, $newval$$Register, base); 7338 __ cbnz_w($tmp$$Register, loop); 7339 __ bind(done); 7340 __ cset_w($res$$Register, eq); 7341 %} 7342 ins_pipe( long_memory_op ); 7343 %} 7344 7345 instruct compareAndSwapI_bool(memoryex mem, iRegI oldval, iRegI newval, iRegI res, iRegI tmp, flagsReg ccr) %{ 7346 match(Set res (CompareAndSwapI mem (Binary oldval newval))); 7347 effect( KILL ccr, TEMP tmp); 7348 size(24); 7349 format %{ "loop:\n\t" 7350 "LDXR_w $tmp, $mem\t! If $oldval==[$mem] Then store $newval into [$mem]\n\t" 7351 "CMP_w $tmp, $oldval\n\t" 7352 "B.ne done\n\t" 7353 "STXR_w $tmp, $newval, $mem\n\t" 7354 "CBNZ_w $tmp, loop\n\t" 7355 "done:\n\t" 7356 "CSET_w $res, eq" %} 7357 ins_encode %{ 7358 Register base = reg_to_register_object($mem$$base); 7359 Label loop, done; 7360 __ bind(loop); 7361 __ ldxr_w($tmp$$Register, base); 7362 __ cmp_w($tmp$$Register, $oldval$$Register); 7363 __ b(done, ne); 7364 __ stxr_w($tmp$$Register, $newval$$Register, base); 7365 __ cbnz_w($tmp$$Register, loop); 7366 __ bind(done); 7367 __ cset_w($res$$Register, eq); 7368 %} 7369 ins_pipe( long_memory_op ); 7370 %} 7371 7372 // tmp must use iRegI instead of iRegN until 8051805 is fixed. 7373 instruct compareAndSwapN_bool(memoryex mem, iRegN oldval, iRegN newval, iRegI res, iRegI tmp, flagsReg ccr) %{ 7374 match(Set res (CompareAndSwapN mem (Binary oldval newval))); 7375 effect( KILL ccr, TEMP tmp); 7376 size(24); 7377 format %{ "loop:\n\t" 7378 "LDXR_w $tmp, $mem\t! If $oldval==[$mem] Then store $newval into [$mem]\n\t" 7379 "CMP_w $tmp, $oldval\n\t" 7380 "B.ne done\n\t" 7381 "STXR_w $tmp, $newval, $mem\n\t" 7382 "CBNZ_w $tmp, loop\n\t" 7383 "done:\n\t" 7384 "CSET_w $res, eq" %} 7385 ins_encode %{ 7386 Register base = reg_to_register_object($mem$$base); 7387 Label loop, done; 7388 __ bind(loop); 7389 __ ldxr_w($tmp$$Register, base); 7390 __ cmp_w($tmp$$Register, $oldval$$Register); 7391 __ b(done, ne); 7392 __ stxr_w($tmp$$Register, $newval$$Register, base); 7393 __ cbnz_w($tmp$$Register, loop); 7394 __ bind(done); 7395 __ cset_w($res$$Register, eq); 7396 %} 7397 ins_pipe( long_memory_op ); 7398 %} 7399 7400 instruct compareAndSwapP_bool(memoryex mem, iRegP oldval, iRegP newval, iRegI res, iRegI tmp, flagsReg ccr) %{ 7401 match(Set res (CompareAndSwapP mem (Binary oldval newval))); 7402 effect( KILL ccr, TEMP tmp); 7403 size(24); 7404 format %{ "loop:\n\t" 7405 "LDXR $tmp, $mem\t! If $oldval==[$mem] Then store $newval into [$mem]\n\t" 7406 "CMP $tmp, $oldval\n\t" 7407 "B.ne done\n\t" 7408 "STXR $tmp, $newval, $mem\n\t" 7409 "CBNZ_w $tmp, loop\n\t" 7410 "done:\n\t" 7411 "CSET_w $res, eq" %} 7412 ins_encode %{ 7413 Register base = reg_to_register_object($mem$$base); 7414 Label loop, done; 7415 __ bind(loop); 7416 __ ldxr($tmp$$Register, base); 7417 __ cmp($tmp$$Register, $oldval$$Register); 7418 __ b(done, ne); 7419 __ stxr($tmp$$Register, $newval$$Register, base); 7420 __ cbnz_w($tmp$$Register, loop); 7421 __ bind(done); 7422 __ cset_w($res$$Register, eq); 7423 %} 7424 ins_pipe( long_memory_op ); 7425 %} 7426 #else // !AARCH64 7427 instruct compareAndSwapL_bool(memoryex mem, iRegL oldval, iRegLd newval, iRegI res, iRegLd tmp, flagsReg ccr ) %{ 7428 match(Set res (CompareAndSwapL mem (Binary oldval newval))); 7429 effect( KILL ccr, TEMP tmp); 7430 size(32); 7431 format %{ "loop: \n\t" 7432 "LDREXD $tmp, $mem\t! If $oldval==[$mem] Then store $newval into [$mem]\n\t" 7433 "CMP $tmp.lo, $oldval.lo\n\t" 7434 "CMP.eq $tmp.hi, $oldval.hi\n\t" 7435 "STREXD.eq $tmp, $newval, $mem\n\t" 7436 "MOV.ne $tmp, 0 \n\t" 7437 "XORS.eq $tmp,$tmp, 1 \n\t" 7438 "B.eq loop \n\t" 7439 "MOV $res, $tmp" %} 7440 ins_encode %{ 7441 Label loop; 7442 __ bind(loop); 7443 __ ldrexd($tmp$$Register, $mem$$Address); 7444 __ cmp($tmp$$Register, $oldval$$Register); 7445 __ cmp($tmp$$Register->successor(), $oldval$$Register->successor(), eq); 7446 __ strexd($tmp$$Register, $newval$$Register, $mem$$Address, eq); 7447 __ mov($tmp$$Register, 0, ne); 7448 __ eors($tmp$$Register, $tmp$$Register, 1, eq); 7449 __ b(loop, eq); 7450 __ mov($res$$Register, $tmp$$Register); 7451 %} 7452 ins_pipe( long_memory_op ); 7453 %} 7454 7455 7456 instruct compareAndSwapI_bool(memoryex mem, iRegI oldval, iRegI newval, iRegI res, iRegI tmp, flagsReg ccr ) %{ 7457 match(Set res (CompareAndSwapI mem (Binary oldval newval))); 7458 effect( KILL ccr, TEMP tmp); 7459 size(28); 7460 format %{ "loop: \n\t" 7461 "LDREX $tmp, $mem\t! If $oldval==[$mem] Then store $newval into [$mem]\n\t" 7462 "CMP $tmp, $oldval\n\t" 7463 "STREX.eq $tmp, $newval, $mem\n\t" 7464 "MOV.ne $tmp, 0 \n\t" 7465 "XORS.eq $tmp,$tmp, 1 \n\t" 7466 "B.eq loop \n\t" 7467 "MOV $res, $tmp" %} 7468 7469 ins_encode %{ 7470 Label loop; 7471 __ bind(loop); 7472 __ ldrex($tmp$$Register,$mem$$Address); 7473 __ cmp($tmp$$Register, $oldval$$Register); 7474 __ strex($tmp$$Register, $newval$$Register, $mem$$Address, eq); 7475 __ mov($tmp$$Register, 0, ne); 7476 __ eors($tmp$$Register, $tmp$$Register, 1, eq); 7477 __ b(loop, eq); 7478 __ mov($res$$Register, $tmp$$Register); 7479 %} 7480 ins_pipe( long_memory_op ); 7481 %} 7482 7483 instruct compareAndSwapP_bool(memoryex mem, iRegP oldval, iRegP newval, iRegI res, iRegI tmp, flagsReg ccr ) %{ 7484 match(Set res (CompareAndSwapP mem (Binary oldval newval))); 7485 effect( KILL ccr, TEMP tmp); 7486 size(28); 7487 format %{ "loop: \n\t" 7488 "LDREX $tmp, $mem\t! If $oldval==[$mem] Then store $newval into [$mem]\n\t" 7489 "CMP $tmp, $oldval\n\t" 7490 "STREX.eq $tmp, $newval, $mem\n\t" 7491 "MOV.ne $tmp, 0 \n\t" 7492 "EORS.eq $tmp,$tmp, 1 \n\t" 7493 "B.eq loop \n\t" 7494 "MOV $res, $tmp" %} 7495 7496 ins_encode %{ 7497 Label loop; 7498 __ bind(loop); 7499 __ ldrex($tmp$$Register,$mem$$Address); 7500 __ cmp($tmp$$Register, $oldval$$Register); 7501 __ strex($tmp$$Register, $newval$$Register, $mem$$Address, eq); 7502 __ mov($tmp$$Register, 0, ne); 7503 __ eors($tmp$$Register, $tmp$$Register, 1, eq); 7504 __ b(loop, eq); 7505 __ mov($res$$Register, $tmp$$Register); 7506 %} 7507 ins_pipe( long_memory_op ); 7508 %} 7509 #endif // !AARCH64 7510 7511 #ifdef AARCH64 7512 instruct xaddI_aimmI_no_res(memoryex mem, aimmI add, Universe dummy, iRegI tmp1, iRegI tmp2) %{ 7513 predicate(n->as_LoadStore()->result_not_used()); 7514 match(Set dummy (GetAndAddI mem add)); 7515 effect(TEMP tmp1, TEMP tmp2); 7516 size(16); 7517 format %{ "loop:\n\t" 7518 "LDXR_w $tmp1, $mem\n\t" 7519 "ADD_w $tmp1, $tmp1, $add\n\t" 7520 "STXR_w $tmp2, $tmp1, $mem\n\t" 7521 "CBNZ_w $tmp2, loop" %} 7522 7523 ins_encode %{ 7524 Label loop; 7525 Register base = reg_to_register_object($mem$$base); 7526 __ bind(loop); 7527 __ ldxr_w($tmp1$$Register, base); 7528 __ add_w($tmp1$$Register, $tmp1$$Register, $add$$constant); 7529 __ stxr_w($tmp2$$Register, $tmp1$$Register, base); 7530 __ cbnz_w($tmp2$$Register, loop); 7531 %} 7532 ins_pipe( long_memory_op ); 7533 %} 7534 #else 7535 instruct xaddI_aimmI_no_res(memoryex mem, aimmI add, Universe dummy, iRegI tmp1, iRegI tmp2, flagsReg ccr) %{ 7536 predicate(n->as_LoadStore()->result_not_used()); 7537 match(Set dummy (GetAndAddI mem add)); 7538 effect(KILL ccr, TEMP tmp1, TEMP tmp2); 7539 size(20); 7540 format %{ "loop: \n\t" 7541 "LDREX $tmp1, $mem\n\t" 7542 "ADD $tmp1, $tmp1, $add\n\t" 7543 "STREX $tmp2, $tmp1, $mem\n\t" 7544 "CMP $tmp2, 0 \n\t" 7545 "B.ne loop \n\t" %} 7546 7547 ins_encode %{ 7548 Label loop; 7549 __ bind(loop); 7550 __ ldrex($tmp1$$Register,$mem$$Address); 7551 __ add($tmp1$$Register, $tmp1$$Register, $add$$constant); 7552 __ strex($tmp2$$Register, $tmp1$$Register, $mem$$Address); 7553 __ cmp($tmp2$$Register, 0); 7554 __ b(loop, ne); 7555 %} 7556 ins_pipe( long_memory_op ); 7557 %} 7558 #endif 7559 7560 #ifdef AARCH64 7561 instruct xaddI_reg_no_res(memoryex mem, iRegI add, Universe dummy, iRegI tmp1, iRegI tmp2) %{ 7562 predicate(n->as_LoadStore()->result_not_used()); 7563 match(Set dummy (GetAndAddI mem add)); 7564 effect(TEMP tmp1, TEMP tmp2); 7565 size(16); 7566 format %{ "loop:\n\t" 7567 "LDXR_w $tmp1, $mem\n\t" 7568 "ADD_w $tmp1, $tmp1, $add\n\t" 7569 "STXR_w $tmp2, $tmp1, $mem\n\t" 7570 "CBNZ_w $tmp2, loop" %} 7571 7572 ins_encode %{ 7573 Label loop; 7574 Register base = reg_to_register_object($mem$$base); 7575 __ bind(loop); 7576 __ ldxr_w($tmp1$$Register, base); 7577 __ add_w($tmp1$$Register, $tmp1$$Register, $add$$Register); 7578 __ stxr_w($tmp2$$Register, $tmp1$$Register, base); 7579 __ cbnz_w($tmp2$$Register, loop); 7580 %} 7581 ins_pipe( long_memory_op ); 7582 %} 7583 #else 7584 instruct xaddI_reg_no_res(memoryex mem, iRegI add, Universe dummy, iRegI tmp1, iRegI tmp2, flagsReg ccr) %{ 7585 predicate(n->as_LoadStore()->result_not_used()); 7586 match(Set dummy (GetAndAddI mem add)); 7587 effect(KILL ccr, TEMP tmp1, TEMP tmp2); 7588 size(20); 7589 format %{ "loop: \n\t" 7590 "LDREX $tmp1, $mem\n\t" 7591 "ADD $tmp1, $tmp1, $add\n\t" 7592 "STREX $tmp2, $tmp1, $mem\n\t" 7593 "CMP $tmp2, 0 \n\t" 7594 "B.ne loop \n\t" %} 7595 7596 ins_encode %{ 7597 Label loop; 7598 __ bind(loop); 7599 __ ldrex($tmp1$$Register,$mem$$Address); 7600 __ add($tmp1$$Register, $tmp1$$Register, $add$$Register); 7601 __ strex($tmp2$$Register, $tmp1$$Register, $mem$$Address); 7602 __ cmp($tmp2$$Register, 0); 7603 __ b(loop, ne); 7604 %} 7605 ins_pipe( long_memory_op ); 7606 %} 7607 #endif 7608 7609 #ifdef AARCH64 7610 instruct xaddI_aimmI(memoryex mem, aimmI add, iRegI res, iRegI tmp1, iRegI tmp2) %{ 7611 match(Set res (GetAndAddI mem add)); 7612 effect(TEMP tmp1, TEMP tmp2, TEMP res); 7613 size(16); 7614 format %{ "loop:\n\t" 7615 "LDXR_w $res, $mem\n\t" 7616 "ADD_w $tmp1, $res, $add\n\t" 7617 "STXR_w $tmp2, $tmp1, $mem\n\t" 7618 "CBNZ_w $tmp2, loop" %} 7619 7620 ins_encode %{ 7621 Label loop; 7622 Register base = reg_to_register_object($mem$$base); 7623 __ bind(loop); 7624 __ ldxr_w($res$$Register, base); 7625 __ add_w($tmp1$$Register, $res$$Register, $add$$constant); 7626 __ stxr_w($tmp2$$Register, $tmp1$$Register, base); 7627 __ cbnz_w($tmp2$$Register, loop); 7628 %} 7629 ins_pipe( long_memory_op ); 7630 %} 7631 #else 7632 instruct xaddI_aimmI(memoryex mem, aimmI add, iRegI res, iRegI tmp1, iRegI tmp2, flagsReg ccr) %{ 7633 match(Set res (GetAndAddI mem add)); 7634 effect(KILL ccr, TEMP tmp1, TEMP tmp2, TEMP res); 7635 size(20); 7636 format %{ "loop: \n\t" 7637 "LDREX $res, $mem\n\t" 7638 "ADD $tmp1, $res, $add\n\t" 7639 "STREX $tmp2, $tmp1, $mem\n\t" 7640 "CMP $tmp2, 0 \n\t" 7641 "B.ne loop \n\t" %} 7642 7643 ins_encode %{ 7644 Label loop; 7645 __ bind(loop); 7646 __ ldrex($res$$Register,$mem$$Address); 7647 __ add($tmp1$$Register, $res$$Register, $add$$constant); 7648 __ strex($tmp2$$Register, $tmp1$$Register, $mem$$Address); 7649 __ cmp($tmp2$$Register, 0); 7650 __ b(loop, ne); 7651 %} 7652 ins_pipe( long_memory_op ); 7653 %} 7654 #endif 7655 7656 #ifdef AARCH64 7657 instruct xaddI_reg(memoryex mem, iRegI add, iRegI res, iRegI tmp1, iRegI tmp2) %{ 7658 match(Set res (GetAndAddI mem add)); 7659 effect(TEMP tmp1, TEMP tmp2, TEMP res); 7660 size(16); 7661 format %{ "loop:\n\t" 7662 "LDXR_w $res, $mem\n\t" 7663 "ADD_w $tmp1, $res, $add\n\t" 7664 "STXR_w $tmp2, $tmp1, $mem\n\t" 7665 "CBNZ_w $tmp2, loop" %} 7666 7667 ins_encode %{ 7668 Label loop; 7669 Register base = reg_to_register_object($mem$$base); 7670 __ bind(loop); 7671 __ ldxr_w($res$$Register, base); 7672 __ add_w($tmp1$$Register, $res$$Register, $add$$Register); 7673 __ stxr_w($tmp2$$Register, $tmp1$$Register, base); 7674 __ cbnz_w($tmp2$$Register, loop); 7675 %} 7676 ins_pipe( long_memory_op ); 7677 %} 7678 #else 7679 instruct xaddI_reg(memoryex mem, iRegI add, iRegI res, iRegI tmp1, iRegI tmp2, flagsReg ccr) %{ 7680 match(Set res (GetAndAddI mem add)); 7681 effect(KILL ccr, TEMP tmp1, TEMP tmp2, TEMP res); 7682 size(20); 7683 format %{ "loop: \n\t" 7684 "LDREX $res, $mem\n\t" 7685 "ADD $tmp1, $res, $add\n\t" 7686 "STREX $tmp2, $tmp1, $mem\n\t" 7687 "CMP $tmp2, 0 \n\t" 7688 "B.ne loop \n\t" %} 7689 7690 ins_encode %{ 7691 Label loop; 7692 __ bind(loop); 7693 __ ldrex($res$$Register,$mem$$Address); 7694 __ add($tmp1$$Register, $res$$Register, $add$$Register); 7695 __ strex($tmp2$$Register, $tmp1$$Register, $mem$$Address); 7696 __ cmp($tmp2$$Register, 0); 7697 __ b(loop, ne); 7698 %} 7699 ins_pipe( long_memory_op ); 7700 %} 7701 #endif 7702 7703 #ifdef AARCH64 7704 instruct xaddL_reg_no_res(memoryex mem, iRegL add, Universe dummy, iRegL tmp1, iRegI tmp2) %{ 7705 predicate(n->as_LoadStore()->result_not_used()); 7706 match(Set dummy (GetAndAddL mem add)); 7707 effect(TEMP tmp1, TEMP tmp2); 7708 size(16); 7709 format %{ "loop:\n\t" 7710 "LDXR $tmp1, $mem\n\t" 7711 "ADD $tmp1, $tmp1, $add\n\t" 7712 "STXR $tmp2, $tmp1, $mem\n\t" 7713 "CBNZ_w $tmp2, loop" %} 7714 7715 ins_encode %{ 7716 Label loop; 7717 Register base = reg_to_register_object($mem$$base); 7718 __ bind(loop); 7719 __ ldxr($tmp1$$Register, base); 7720 __ add($tmp1$$Register, $tmp1$$Register, $add$$Register); 7721 __ stxr($tmp2$$Register, $tmp1$$Register, base); 7722 __ cbnz_w($tmp2$$Register, loop); 7723 %} 7724 ins_pipe( long_memory_op ); 7725 %} 7726 #else 7727 instruct xaddL_reg_no_res(memoryex mem, iRegL add, Universe dummy, iRegLd tmp1, iRegI tmp2, flagsReg ccr) %{ 7728 predicate(n->as_LoadStore()->result_not_used()); 7729 match(Set dummy (GetAndAddL mem add)); 7730 effect( KILL ccr, TEMP tmp1, TEMP tmp2); 7731 size(24); 7732 format %{ "loop: \n\t" 7733 "LDREXD $tmp1, $mem\n\t" 7734 "ADDS $tmp1.lo, $tmp1.lo, $add.lo\n\t" 7735 "ADC $tmp1.hi, $tmp1.hi, $add.hi\n\t" 7736 "STREXD $tmp2, $tmp1, $mem\n\t" 7737 "CMP $tmp2, 0 \n\t" 7738 "B.ne loop \n\t" %} 7739 7740 ins_encode %{ 7741 Label loop; 7742 __ bind(loop); 7743 __ ldrexd($tmp1$$Register, $mem$$Address); 7744 __ adds($tmp1$$Register, $tmp1$$Register, $add$$Register); 7745 __ adc($tmp1$$Register->successor(), $tmp1$$Register->successor(), $add$$Register->successor()); 7746 __ strexd($tmp2$$Register, $tmp1$$Register, $mem$$Address); 7747 __ cmp($tmp2$$Register, 0); 7748 __ b(loop, ne); 7749 %} 7750 ins_pipe( long_memory_op ); 7751 %} 7752 #endif 7753 7754 #ifdef AARCH64 7755 instruct xaddL_imm_no_res(memoryex mem, aimmL add, Universe dummy, iRegL tmp1, iRegI tmp2) %{ 7756 predicate(n->as_LoadStore()->result_not_used()); 7757 match(Set dummy (GetAndAddL mem add)); 7758 effect(TEMP tmp1, TEMP tmp2); 7759 size(16); 7760 format %{ "loop:\n\t" 7761 "LDXR $tmp1, $mem\n\t" 7762 "ADD $tmp1, $tmp1, $add\n\t" 7763 "STXR $tmp2, $tmp1, $mem\n\t" 7764 "CBNZ_w $tmp2, loop" %} 7765 7766 ins_encode %{ 7767 Label loop; 7768 Register base = reg_to_register_object($mem$$base); 7769 __ bind(loop); 7770 __ ldxr($tmp1$$Register, base); 7771 __ add($tmp1$$Register, $tmp1$$Register, $add$$constant); 7772 __ stxr($tmp2$$Register, $tmp1$$Register, base); 7773 __ cbnz_w($tmp2$$Register, loop); 7774 %} 7775 ins_pipe( long_memory_op ); 7776 %} 7777 #else 7778 // TODO: try immLRot2 instead, (0, $con$$constant) becomes 7779 // (hi($con$$constant), lo($con$$constant)) becomes 7780 instruct xaddL_immRot_no_res(memoryex mem, immLlowRot add, Universe dummy, iRegLd tmp1, iRegI tmp2, flagsReg ccr) %{ 7781 predicate(n->as_LoadStore()->result_not_used()); 7782 match(Set dummy (GetAndAddL mem add)); 7783 effect( KILL ccr, TEMP tmp1, TEMP tmp2); 7784 size(24); 7785 format %{ "loop: \n\t" 7786 "LDREXD $tmp1, $mem\n\t" 7787 "ADDS $tmp1.lo, $tmp1.lo, $add\n\t" 7788 "ADC $tmp1.hi, $tmp1.hi, 0\n\t" 7789 "STREXD $tmp2, $tmp1, $mem\n\t" 7790 "CMP $tmp2, 0 \n\t" 7791 "B.ne loop \n\t" %} 7792 7793 ins_encode %{ 7794 Label loop; 7795 __ bind(loop); 7796 __ ldrexd($tmp1$$Register, $mem$$Address); 7797 __ adds($tmp1$$Register, $tmp1$$Register, $add$$constant); 7798 __ adc($tmp1$$Register->successor(), $tmp1$$Register->successor(), 0); 7799 __ strexd($tmp2$$Register, $tmp1$$Register, $mem$$Address); 7800 __ cmp($tmp2$$Register, 0); 7801 __ b(loop, ne); 7802 %} 7803 ins_pipe( long_memory_op ); 7804 %} 7805 #endif 7806 7807 #ifdef AARCH64 7808 instruct xaddL_reg(memoryex mem, iRegL add, iRegL res, iRegL tmp1, iRegI tmp2) %{ 7809 match(Set res (GetAndAddL mem add)); 7810 effect(TEMP tmp1, TEMP tmp2, TEMP res); 7811 size(16); 7812 format %{ "loop:\n\t" 7813 "LDXR $res, $mem\n\t" 7814 "ADD $tmp1, $res, $add\n\t" 7815 "STXR $tmp2, $tmp1, $mem\n\t" 7816 "CBNZ_w $tmp2, loop" %} 7817 7818 ins_encode %{ 7819 Label loop; 7820 Register base = reg_to_register_object($mem$$base); 7821 __ bind(loop); 7822 __ ldxr($res$$Register, base); 7823 __ add($tmp1$$Register, $res$$Register, $add$$Register); 7824 __ stxr($tmp2$$Register, $tmp1$$Register, base); 7825 __ cbnz_w($tmp2$$Register, loop); 7826 %} 7827 ins_pipe( long_memory_op ); 7828 %} 7829 #else 7830 instruct xaddL_reg(memoryex mem, iRegL add, iRegLd res, iRegLd tmp1, iRegI tmp2, flagsReg ccr) %{ 7831 match(Set res (GetAndAddL mem add)); 7832 effect( KILL ccr, TEMP tmp1, TEMP tmp2, TEMP res); 7833 size(24); 7834 format %{ "loop: \n\t" 7835 "LDREXD $res, $mem\n\t" 7836 "ADDS $tmp1.lo, $res.lo, $add.lo\n\t" 7837 "ADC $tmp1.hi, $res.hi, $add.hi\n\t" 7838 "STREXD $tmp2, $tmp1, $mem\n\t" 7839 "CMP $tmp2, 0 \n\t" 7840 "B.ne loop \n\t" %} 7841 7842 ins_encode %{ 7843 Label loop; 7844 __ bind(loop); 7845 __ ldrexd($res$$Register, $mem$$Address); 7846 __ adds($tmp1$$Register, $res$$Register, $add$$Register); 7847 __ adc($tmp1$$Register->successor(), $res$$Register->successor(), $add$$Register->successor()); 7848 __ strexd($tmp2$$Register, $tmp1$$Register, $mem$$Address); 7849 __ cmp($tmp2$$Register, 0); 7850 __ b(loop, ne); 7851 %} 7852 ins_pipe( long_memory_op ); 7853 %} 7854 #endif 7855 7856 #ifdef AARCH64 7857 instruct xaddL_imm(memoryex mem, aimmL add, iRegL res, iRegL tmp1, iRegI tmp2) %{ 7858 match(Set res (GetAndAddL mem add)); 7859 effect(TEMP tmp1, TEMP tmp2, TEMP res); 7860 size(16); 7861 format %{ "loop:\n\t" 7862 "LDXR $res, $mem\n\t" 7863 "ADD $tmp1, $res, $add\n\t" 7864 "STXR $tmp2, $tmp1, $mem\n\t" 7865 "CBNZ_w $tmp2, loop" %} 7866 7867 ins_encode %{ 7868 Label loop; 7869 Register base = reg_to_register_object($mem$$base); 7870 __ bind(loop); 7871 __ ldxr($res$$Register, base); 7872 __ add($tmp1$$Register, $res$$Register, $add$$constant); 7873 __ stxr($tmp2$$Register, $tmp1$$Register, base); 7874 __ cbnz_w($tmp2$$Register, loop); 7875 %} 7876 ins_pipe( long_memory_op ); 7877 %} 7878 #else 7879 // TODO: try immLRot2 instead, (0, $con$$constant) becomes 7880 // (hi($con$$constant), lo($con$$constant)) becomes 7881 instruct xaddL_immRot(memoryex mem, immLlowRot add, iRegLd res, iRegLd tmp1, iRegI tmp2, flagsReg ccr) %{ 7882 match(Set res (GetAndAddL mem add)); 7883 effect( KILL ccr, TEMP tmp1, TEMP tmp2, TEMP res); 7884 size(24); 7885 format %{ "loop: \n\t" 7886 "LDREXD $res, $mem\n\t" 7887 "ADDS $tmp1.lo, $res.lo, $add\n\t" 7888 "ADC $tmp1.hi, $res.hi, 0\n\t" 7889 "STREXD $tmp2, $tmp1, $mem\n\t" 7890 "CMP $tmp2, 0 \n\t" 7891 "B.ne loop \n\t" %} 7892 7893 ins_encode %{ 7894 Label loop; 7895 __ bind(loop); 7896 __ ldrexd($res$$Register, $mem$$Address); 7897 __ adds($tmp1$$Register, $res$$Register, $add$$constant); 7898 __ adc($tmp1$$Register->successor(), $res$$Register->successor(), 0); 7899 __ strexd($tmp2$$Register, $tmp1$$Register, $mem$$Address); 7900 __ cmp($tmp2$$Register, 0); 7901 __ b(loop, ne); 7902 %} 7903 ins_pipe( long_memory_op ); 7904 %} 7905 #endif 7906 7907 #ifdef AARCH64 7908 instruct xchgI(memoryex mem, iRegI newval, iRegI res, iRegI tmp) %{ 7909 match(Set res (GetAndSetI mem newval)); 7910 effect(TEMP tmp, TEMP res); 7911 size(12); 7912 format %{ "loop:\n\t" 7913 "LDXR_w $res, $mem\n\t" 7914 "STXR_w $tmp, $newval, $mem\n\t" 7915 "CBNZ_w $tmp, loop" %} 7916 7917 ins_encode %{ 7918 Label loop; 7919 Register base = reg_to_register_object($mem$$base); 7920 __ bind(loop); 7921 __ ldxr_w($res$$Register, base); 7922 __ stxr_w($tmp$$Register, $newval$$Register, base); 7923 __ cbnz_w($tmp$$Register, loop); 7924 %} 7925 ins_pipe( long_memory_op ); 7926 %} 7927 7928 #ifdef XXX 7929 // Disabled until 8051805 is fixed. 7930 instruct xchgN(memoryex mem, iRegN newval, iRegN res, iRegN tmp) %{ 7931 match(Set res (GetAndSetN mem newval)); 7932 effect(TEMP tmp, TEMP res); 7933 size(12); 7934 format %{ "loop:\n\t" 7935 "LDXR_w $res, $mem\n\t" 7936 "STXR_w $tmp, $newval, $mem\n\t" 7937 "CBNZ_w $tmp, loop" %} 7938 7939 ins_encode %{ 7940 Label loop; 7941 Register base = reg_to_register_object($mem$$base); 7942 __ bind(loop); 7943 __ ldxr_w($res$$Register, base); 7944 __ stxr_w($tmp$$Register, $newval$$Register, base); 7945 __ cbnz_w($tmp$$Register, loop); 7946 %} 7947 ins_pipe( long_memory_op ); 7948 %} 7949 #endif 7950 #else 7951 instruct xchgI(memoryex mem, iRegI newval, iRegI res, iRegI tmp, flagsReg ccr) %{ 7952 match(Set res (GetAndSetI mem newval)); 7953 effect(KILL ccr, TEMP tmp, TEMP res); 7954 size(16); 7955 format %{ "loop: \n\t" 7956 "LDREX $res, $mem\n\t" 7957 "STREX $tmp, $newval, $mem\n\t" 7958 "CMP $tmp, 0 \n\t" 7959 "B.ne loop \n\t" %} 7960 7961 ins_encode %{ 7962 Label loop; 7963 __ bind(loop); 7964 __ ldrex($res$$Register,$mem$$Address); 7965 __ strex($tmp$$Register, $newval$$Register, $mem$$Address); 7966 __ cmp($tmp$$Register, 0); 7967 __ b(loop, ne); 7968 %} 7969 ins_pipe( long_memory_op ); 7970 %} 7971 #endif 7972 7973 #ifdef AARCH64 7974 instruct xchgL(memoryex mem, iRegL newval, iRegL res, iRegI tmp) %{ 7975 match(Set res (GetAndSetL mem newval)); 7976 effect(TEMP tmp, TEMP res); 7977 size(12); 7978 format %{ "loop:\n\t" 7979 "LDXR $res, $mem\n\t" 7980 "STXR $tmp, $newval, $mem\n\t" 7981 "CBNZ_w $tmp, loop" %} 7982 7983 ins_encode %{ 7984 Label loop; 7985 Register base = reg_to_register_object($mem$$base); 7986 __ bind(loop); 7987 __ ldxr($res$$Register, base); 7988 __ stxr($tmp$$Register, $newval$$Register, base); 7989 __ cbnz_w($tmp$$Register, loop); 7990 %} 7991 ins_pipe( long_memory_op ); 7992 %} 7993 #else 7994 instruct xchgL(memoryex mem, iRegLd newval, iRegLd res, iRegI tmp, flagsReg ccr) %{ 7995 match(Set res (GetAndSetL mem newval)); 7996 effect( KILL ccr, TEMP tmp, TEMP res); 7997 size(16); 7998 format %{ "loop: \n\t" 7999 "LDREXD $res, $mem\n\t" 8000 "STREXD $tmp, $newval, $mem\n\t" 8001 "CMP $tmp, 0 \n\t" 8002 "B.ne loop \n\t" %} 8003 8004 ins_encode %{ 8005 Label loop; 8006 __ bind(loop); 8007 __ ldrexd($res$$Register, $mem$$Address); 8008 __ strexd($tmp$$Register, $newval$$Register, $mem$$Address); 8009 __ cmp($tmp$$Register, 0); 8010 __ b(loop, ne); 8011 %} 8012 ins_pipe( long_memory_op ); 8013 %} 8014 #endif // !AARCH64 8015 8016 #ifdef AARCH64 8017 instruct xchgP(memoryex mem, iRegP newval, iRegP res, iRegI tmp) %{ 8018 match(Set res (GetAndSetP mem newval)); 8019 effect(TEMP tmp, TEMP res); 8020 size(12); 8021 format %{ "loop:\n\t" 8022 "LDREX $res, $mem\n\t" 8023 "STREX $tmp, $newval, $mem\n\t" 8024 "CBNZ_w $tmp, loop" %} 8025 8026 ins_encode %{ 8027 Label loop; 8028 Register base = reg_to_register_object($mem$$base); 8029 __ bind(loop); 8030 __ ldrex($res$$Register, base); 8031 __ strex($tmp$$Register, $newval$$Register, base); 8032 __ cbnz_w($tmp$$Register, loop); 8033 %} 8034 ins_pipe( long_memory_op ); 8035 %} 8036 #else 8037 instruct xchgP(memoryex mem, iRegP newval, iRegP res, iRegI tmp, flagsReg ccr) %{ 8038 match(Set res (GetAndSetP mem newval)); 8039 effect(KILL ccr, TEMP tmp, TEMP res); 8040 size(16); 8041 format %{ "loop: \n\t" 8042 "LDREX $res, $mem\n\t" 8043 "STREX $tmp, $newval, $mem\n\t" 8044 "CMP $tmp, 0 \n\t" 8045 "B.ne loop \n\t" %} 8046 8047 ins_encode %{ 8048 Label loop; 8049 __ bind(loop); 8050 __ ldrex($res$$Register,$mem$$Address); 8051 __ strex($tmp$$Register, $newval$$Register, $mem$$Address); 8052 __ cmp($tmp$$Register, 0); 8053 __ b(loop, ne); 8054 %} 8055 ins_pipe( long_memory_op ); 8056 %} 8057 #endif // !AARCH64 8058 8059 //--------------------- 8060 // Subtraction Instructions 8061 // Register Subtraction 8062 instruct subI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{ 8063 match(Set dst (SubI src1 src2)); 8064 8065 size(4); 8066 format %{ "sub_32 $dst,$src1,$src2\t! int" %} 8067 ins_encode %{ 8068 __ sub_32($dst$$Register, $src1$$Register, $src2$$Register); 8069 %} 8070 ins_pipe(ialu_reg_reg); 8071 %} 8072 8073 #ifndef AARCH64 8074 instruct subshlI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 8075 match(Set dst (SubI src1 (LShiftI src2 src3))); 8076 8077 size(4); 8078 format %{ "SUB $dst,$src1,$src2<<$src3" %} 8079 ins_encode %{ 8080 __ sub($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$Register)); 8081 %} 8082 ins_pipe(ialu_reg_reg); 8083 %} 8084 #endif 8085 8086 instruct subshlI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{ 8087 match(Set dst (SubI src1 (LShiftI src2 src3))); 8088 8089 size(4); 8090 format %{ "sub_32 $dst,$src1,$src2<<$src3\t! int" %} 8091 ins_encode %{ 8092 __ sub_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$constant)); 8093 %} 8094 ins_pipe(ialu_reg_reg); 8095 %} 8096 8097 #ifndef AARCH64 8098 instruct subsarI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 8099 match(Set dst (SubI src1 (RShiftI src2 src3))); 8100 8101 size(4); 8102 format %{ "SUB $dst,$src1,$src2>>$src3" %} 8103 ins_encode %{ 8104 __ sub($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$Register)); 8105 %} 8106 ins_pipe(ialu_reg_reg); 8107 %} 8108 #endif 8109 8110 instruct subsarI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{ 8111 match(Set dst (SubI src1 (RShiftI src2 src3))); 8112 8113 size(4); 8114 format %{ "sub_32 $dst,$src1,$src2>>$src3\t! int" %} 8115 ins_encode %{ 8116 __ sub_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$constant)); 8117 %} 8118 ins_pipe(ialu_reg_reg); 8119 %} 8120 8121 #ifndef AARCH64 8122 instruct subshrI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 8123 match(Set dst (SubI src1 (URShiftI src2 src3))); 8124 8125 size(4); 8126 format %{ "SUB $dst,$src1,$src2>>>$src3" %} 8127 ins_encode %{ 8128 __ sub($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$Register)); 8129 %} 8130 ins_pipe(ialu_reg_reg); 8131 %} 8132 #endif 8133 8134 instruct subshrI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{ 8135 match(Set dst (SubI src1 (URShiftI src2 src3))); 8136 8137 size(4); 8138 format %{ "sub_32 $dst,$src1,$src2>>>$src3\t! int" %} 8139 ins_encode %{ 8140 __ sub_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$constant)); 8141 %} 8142 ins_pipe(ialu_reg_reg); 8143 %} 8144 8145 #ifndef AARCH64 8146 instruct rsbshlI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 8147 match(Set dst (SubI (LShiftI src1 src2) src3)); 8148 8149 size(4); 8150 format %{ "RSB $dst,$src3,$src1<<$src2" %} 8151 ins_encode %{ 8152 __ rsb($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsl, $src2$$Register)); 8153 %} 8154 ins_pipe(ialu_reg_reg); 8155 %} 8156 8157 instruct rsbshlI_reg_imm_reg(iRegI dst, iRegI src1, immU5 src2, iRegI src3) %{ 8158 match(Set dst (SubI (LShiftI src1 src2) src3)); 8159 8160 size(4); 8161 format %{ "RSB $dst,$src3,$src1<<$src2" %} 8162 ins_encode %{ 8163 __ rsb($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsl, $src2$$constant)); 8164 %} 8165 ins_pipe(ialu_reg_reg); 8166 %} 8167 8168 instruct rsbsarI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 8169 match(Set dst (SubI (RShiftI src1 src2) src3)); 8170 8171 size(4); 8172 format %{ "RSB $dst,$src3,$src1>>$src2" %} 8173 ins_encode %{ 8174 __ rsb($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, asr, $src2$$Register)); 8175 %} 8176 ins_pipe(ialu_reg_reg); 8177 %} 8178 8179 instruct rsbsarI_reg_imm_reg(iRegI dst, iRegI src1, immU5 src2, iRegI src3) %{ 8180 match(Set dst (SubI (RShiftI src1 src2) src3)); 8181 8182 size(4); 8183 format %{ "RSB $dst,$src3,$src1>>$src2" %} 8184 ins_encode %{ 8185 __ rsb($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, asr, $src2$$constant)); 8186 %} 8187 ins_pipe(ialu_reg_reg); 8188 %} 8189 8190 instruct rsbshrI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 8191 match(Set dst (SubI (URShiftI src1 src2) src3)); 8192 8193 size(4); 8194 format %{ "RSB $dst,$src3,$src1>>>$src2" %} 8195 ins_encode %{ 8196 __ rsb($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsr, $src2$$Register)); 8197 %} 8198 ins_pipe(ialu_reg_reg); 8199 %} 8200 8201 instruct rsbshrI_reg_imm_reg(iRegI dst, iRegI src1, immU5 src2, iRegI src3) %{ 8202 match(Set dst (SubI (URShiftI src1 src2) src3)); 8203 8204 size(4); 8205 format %{ "RSB $dst,$src3,$src1>>>$src2" %} 8206 ins_encode %{ 8207 __ rsb($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsr, $src2$$constant)); 8208 %} 8209 ins_pipe(ialu_reg_reg); 8210 %} 8211 #endif 8212 8213 // Immediate Subtraction 8214 instruct subI_reg_aimmI(iRegI dst, iRegI src1, aimmI src2) %{ 8215 match(Set dst (SubI src1 src2)); 8216 8217 size(4); 8218 format %{ "sub_32 $dst,$src1,$src2\t! int" %} 8219 ins_encode %{ 8220 __ sub_32($dst$$Register, $src1$$Register, $src2$$constant); 8221 %} 8222 ins_pipe(ialu_reg_imm); 8223 %} 8224 8225 instruct subI_reg_immRotneg(iRegI dst, iRegI src1, aimmIneg src2) %{ 8226 match(Set dst (AddI src1 src2)); 8227 8228 size(4); 8229 format %{ "sub_32 $dst,$src1,-($src2)\t! int" %} 8230 ins_encode %{ 8231 __ sub_32($dst$$Register, $src1$$Register, -$src2$$constant); 8232 %} 8233 ins_pipe(ialu_reg_imm); 8234 %} 8235 8236 #ifndef AARCH64 8237 instruct subI_immRot_reg(iRegI dst, immIRot src1, iRegI src2) %{ 8238 match(Set dst (SubI src1 src2)); 8239 8240 size(4); 8241 format %{ "RSB $dst,$src2,src1" %} 8242 ins_encode %{ 8243 __ rsb($dst$$Register, $src2$$Register, $src1$$constant); 8244 %} 8245 ins_pipe(ialu_zero_reg); 8246 %} 8247 #endif 8248 8249 // Register Subtraction 8250 #ifdef AARCH64 8251 instruct subL_reg_reg(iRegL dst, iRegL src1, iRegL src2) %{ 8252 match(Set dst (SubL src1 src2)); 8253 8254 size(4); 8255 format %{ "SUB $dst,$src1,$src2\t! long" %} 8256 ins_encode %{ 8257 __ sub($dst$$Register, $src1$$Register, $src2$$Register); 8258 %} 8259 ins_pipe(ialu_reg_reg); 8260 %} 8261 #else 8262 instruct subL_reg_reg(iRegL dst, iRegL src1, iRegL src2, flagsReg icc ) %{ 8263 match(Set dst (SubL src1 src2)); 8264 effect (KILL icc); 8265 8266 size(8); 8267 format %{ "SUBS $dst.lo,$src1.lo,$src2.lo\t! long\n\t" 8268 "SBC $dst.hi,$src1.hi,$src2.hi" %} 8269 ins_encode %{ 8270 __ subs($dst$$Register, $src1$$Register, $src2$$Register); 8271 __ sbc($dst$$Register->successor(), $src1$$Register->successor(), $src2$$Register->successor()); 8272 %} 8273 ins_pipe(ialu_reg_reg); 8274 %} 8275 #endif 8276 8277 #ifdef AARCH64 8278 // Immediate Subtraction 8279 instruct subL_reg_aimm(iRegL dst, iRegL src1, aimmL src2) %{ 8280 match(Set dst (SubL src1 src2)); 8281 8282 size(4); 8283 format %{ "SUB $dst,$src1,$src2\t! long" %} 8284 ins_encode %{ 8285 __ sub($dst$$Register, $src1$$Register, $src2$$constant); 8286 %} 8287 ins_pipe(ialu_reg_imm); 8288 %} 8289 8290 instruct subL_reg_immLneg(iRegL dst, iRegL src1, aimmLneg src2) %{ 8291 match(Set dst (AddL src1 src2)); 8292 8293 size(4); 8294 format %{ "SUB $dst,$src1,-($src2)\t! long" %} 8295 ins_encode %{ 8296 __ sub($dst$$Register, $src1$$Register, -$src2$$constant); 8297 %} 8298 ins_pipe(ialu_reg_imm); 8299 %} 8300 #else 8301 // TODO 8302 #endif 8303 8304 #ifndef AARCH64 8305 // Immediate Subtraction 8306 // TODO: try immLRot2 instead, (0, $con$$constant) becomes 8307 // (hi($con$$constant), lo($con$$constant)) becomes 8308 instruct subL_reg_immRot(iRegL dst, iRegL src1, immLlowRot con, flagsReg icc) %{ 8309 match(Set dst (SubL src1 con)); 8310 effect (KILL icc); 8311 8312 size(8); 8313 format %{ "SUB $dst.lo,$src1.lo,$con\t! long\n\t" 8314 "SBC $dst.hi,$src1.hi,0" %} 8315 ins_encode %{ 8316 __ subs($dst$$Register, $src1$$Register, $con$$constant); 8317 __ sbc($dst$$Register->successor(), $src1$$Register->successor(), 0); 8318 %} 8319 ins_pipe(ialu_reg_imm); 8320 %} 8321 8322 // Long negation 8323 instruct negL_reg_reg(iRegL dst, immL0 zero, iRegL src2, flagsReg icc) %{ 8324 match(Set dst (SubL zero src2)); 8325 effect (KILL icc); 8326 8327 size(8); 8328 format %{ "RSBS $dst.lo,$src2.lo,0\t! long\n\t" 8329 "RSC $dst.hi,$src2.hi,0" %} 8330 ins_encode %{ 8331 __ rsbs($dst$$Register, $src2$$Register, 0); 8332 __ rsc($dst$$Register->successor(), $src2$$Register->successor(), 0); 8333 %} 8334 ins_pipe(ialu_zero_reg); 8335 %} 8336 #endif // !AARCH64 8337 8338 // Multiplication Instructions 8339 // Integer Multiplication 8340 // Register Multiplication 8341 instruct mulI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{ 8342 match(Set dst (MulI src1 src2)); 8343 8344 size(4); 8345 format %{ "mul_32 $dst,$src1,$src2" %} 8346 ins_encode %{ 8347 __ mul_32($dst$$Register, $src1$$Register, $src2$$Register); 8348 %} 8349 ins_pipe(imul_reg_reg); 8350 %} 8351 8352 #ifdef AARCH64 8353 instruct mulL_reg_reg(iRegL dst, iRegL src1, iRegL src2) %{ 8354 match(Set dst (MulL src1 src2)); 8355 size(4); 8356 format %{ "MUL $dst,$src1,$src2\t! long" %} 8357 ins_encode %{ 8358 __ mul($dst$$Register, $src1$$Register, $src2$$Register); 8359 %} 8360 ins_pipe(imul_reg_reg); 8361 %} 8362 #else 8363 instruct mulL_lo1_hi2(iRegL dst, iRegL src1, iRegL src2) %{ 8364 effect(DEF dst, USE src1, USE src2); 8365 size(4); 8366 format %{ "MUL $dst.hi,$src1.lo,$src2.hi\t! long" %} 8367 ins_encode %{ 8368 __ mul($dst$$Register->successor(), $src1$$Register, $src2$$Register->successor()); 8369 %} 8370 ins_pipe(imul_reg_reg); 8371 %} 8372 8373 instruct mulL_hi1_lo2(iRegL dst, iRegL src1, iRegL src2) %{ 8374 effect(USE_DEF dst, USE src1, USE src2); 8375 size(8); 8376 format %{ "MLA $dst.hi,$src1.hi,$src2.lo,$dst.hi\t! long\n\t" 8377 "MOV $dst.lo, 0"%} 8378 ins_encode %{ 8379 __ mla($dst$$Register->successor(), $src1$$Register->successor(), $src2$$Register, $dst$$Register->successor()); 8380 __ mov($dst$$Register, 0); 8381 %} 8382 ins_pipe(imul_reg_reg); 8383 %} 8384 8385 instruct mulL_lo1_lo2(iRegL dst, iRegL src1, iRegL src2) %{ 8386 effect(USE_DEF dst, USE src1, USE src2); 8387 size(4); 8388 format %{ "UMLAL $dst.lo,$dst.hi,$src1,$src2\t! long" %} 8389 ins_encode %{ 8390 __ umlal($dst$$Register, $dst$$Register->successor(), $src1$$Register, $src2$$Register); 8391 %} 8392 ins_pipe(imul_reg_reg); 8393 %} 8394 8395 instruct mulL_reg_reg(iRegL dst, iRegL src1, iRegL src2) %{ 8396 match(Set dst (MulL src1 src2)); 8397 8398 expand %{ 8399 mulL_lo1_hi2(dst, src1, src2); 8400 mulL_hi1_lo2(dst, src1, src2); 8401 mulL_lo1_lo2(dst, src1, src2); 8402 %} 8403 %} 8404 #endif // !AARCH64 8405 8406 // Integer Division 8407 // Register Division 8408 #ifdef AARCH64 8409 instruct divI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{ 8410 match(Set dst (DivI src1 src2)); 8411 8412 size(4); 8413 format %{ "SDIV $dst,$src1,$src2\t! 32-bit" %} 8414 ins_encode %{ 8415 __ sdiv_w($dst$$Register, $src1$$Register, $src2$$Register); 8416 %} 8417 ins_pipe(ialu_reg_reg); // FIXME 8418 %} 8419 #else 8420 instruct divI_reg_reg(R1RegI dst, R0RegI src1, R2RegI src2, LRRegP lr, flagsReg ccr) %{ 8421 match(Set dst (DivI src1 src2)); 8422 effect( KILL ccr, KILL src1, KILL src2, KILL lr); 8423 ins_cost((2+71)*DEFAULT_COST); 8424 8425 format %{ "DIV $dst,$src1,$src2 ! call to StubRoutines::Arm::idiv_irem_entry()" %} 8426 ins_encode %{ 8427 __ call(StubRoutines::Arm::idiv_irem_entry(), relocInfo::runtime_call_type); 8428 %} 8429 ins_pipe(sdiv_reg_reg); 8430 %} 8431 #endif 8432 8433 // Register Long Division 8434 #ifdef AARCH64 8435 instruct divL_reg_reg(iRegL dst, iRegL src1, iRegL src2) %{ 8436 match(Set dst (DivL src1 src2)); 8437 8438 size(4); 8439 format %{ "SDIV $dst,$src1,$src2" %} 8440 ins_encode %{ 8441 __ sdiv($dst$$Register, $src1$$Register, $src2$$Register); 8442 %} 8443 ins_pipe(ialu_reg_reg); // FIXME 8444 %} 8445 #else 8446 instruct divL_reg_reg(R0R1RegL dst, R2R3RegL src1, R0R1RegL src2) %{ 8447 match(Set dst (DivL src1 src2)); 8448 effect(CALL); 8449 ins_cost(DEFAULT_COST*71); 8450 format %{ "DIVL $src1,$src2,$dst\t! long ! call to SharedRuntime::ldiv" %} 8451 ins_encode %{ 8452 address target = CAST_FROM_FN_PTR(address, SharedRuntime::ldiv); 8453 __ call(target, relocInfo::runtime_call_type); 8454 %} 8455 ins_pipe(divL_reg_reg); 8456 %} 8457 #endif 8458 8459 // Integer Remainder 8460 // Register Remainder 8461 #ifdef AARCH64 8462 #ifdef TODO 8463 instruct msubI_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 8464 match(Set dst (SubI src1 (MulI src2 src3))); 8465 8466 size(4); 8467 format %{ "MSUB $dst,$src2,$src3,$src1\t! 32-bit\n\t" %} 8468 ins_encode %{ 8469 __ msub_w($dst$$Register, $src2$$Register, $src3$$Register, $src1$$Register); 8470 %} 8471 ins_pipe(ialu_reg_reg); // FIXME 8472 %} 8473 #endif 8474 8475 instruct modI_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI temp) %{ 8476 match(Set dst (ModI src1 src2)); 8477 effect(TEMP temp); 8478 8479 size(8); 8480 format %{ "SDIV $temp,$src1,$src2\t! 32-bit\n\t" 8481 "MSUB $dst,$src2,$temp,$src1\t! 32-bit\n\t" %} 8482 ins_encode %{ 8483 __ sdiv_w($temp$$Register, $src1$$Register, $src2$$Register); 8484 __ msub_w($dst$$Register, $src2$$Register, $temp$$Register, $src1$$Register); 8485 %} 8486 ins_pipe(ialu_reg_reg); // FIXME 8487 %} 8488 #else 8489 instruct modI_reg_reg(R0RegI dst, R0RegI src1, R2RegI src2, R1RegI temp, LRRegP lr, flagsReg ccr ) %{ 8490 match(Set dst (ModI src1 src2)); 8491 effect( KILL ccr, KILL temp, KILL src2, KILL lr); 8492 8493 format %{ "MODI $dst,$src1,$src2\t ! call to StubRoutines::Arm::idiv_irem_entry" %} 8494 ins_encode %{ 8495 __ call(StubRoutines::Arm::idiv_irem_entry(), relocInfo::runtime_call_type); 8496 %} 8497 ins_pipe(sdiv_reg_reg); 8498 %} 8499 #endif 8500 8501 // Register Long Remainder 8502 #ifdef AARCH64 8503 instruct modL_reg_reg(iRegL dst, iRegL src1, iRegL src2, iRegL temp) %{ 8504 match(Set dst (ModL src1 src2)); 8505 effect(TEMP temp); 8506 8507 size(8); 8508 format %{ "SDIV $temp,$src1,$src2\n\t" 8509 "MSUB $dst,$src2,$temp,$src1" %} 8510 ins_encode %{ 8511 __ sdiv($temp$$Register, $src1$$Register, $src2$$Register); 8512 __ msub($dst$$Register, $src2$$Register, $temp$$Register, $src1$$Register); 8513 %} 8514 ins_pipe(ialu_reg_reg); // FIXME 8515 %} 8516 #else 8517 instruct modL_reg_reg(R0R1RegL dst, R2R3RegL src1, R0R1RegL src2) %{ 8518 match(Set dst (ModL src1 src2)); 8519 effect(CALL); 8520 ins_cost(MEMORY_REF_COST); // FIXME 8521 format %{ "modL $dst,$src1,$src2\t ! call to SharedRuntime::lrem" %} 8522 ins_encode %{ 8523 address target = CAST_FROM_FN_PTR(address, SharedRuntime::lrem); 8524 __ call(target, relocInfo::runtime_call_type); 8525 %} 8526 ins_pipe(divL_reg_reg); 8527 %} 8528 #endif 8529 8530 // Integer Shift Instructions 8531 8532 // Register Shift Left 8533 instruct shlI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{ 8534 match(Set dst (LShiftI src1 src2)); 8535 8536 size(4); 8537 #ifdef AARCH64 8538 format %{ "LSLV $dst,$src1,$src2\t! int" %} 8539 ins_encode %{ 8540 __ lslv_w($dst$$Register, $src1$$Register, $src2$$Register); 8541 %} 8542 #else 8543 format %{ "LSL $dst,$src1,$src2 \n\t" %} 8544 ins_encode %{ 8545 __ mov($dst$$Register, AsmOperand($src1$$Register, lsl, $src2$$Register)); 8546 %} 8547 #endif 8548 ins_pipe(ialu_reg_reg); 8549 %} 8550 8551 // Register Shift Left Immediate 8552 instruct shlI_reg_imm5(iRegI dst, iRegI src1, immU5 src2) %{ 8553 match(Set dst (LShiftI src1 src2)); 8554 8555 size(4); 8556 #ifdef AARCH64 8557 format %{ "LSL_w $dst,$src1,$src2\t! int" %} 8558 ins_encode %{ 8559 __ _lsl($dst$$Register, $src1$$Register, $src2$$constant); 8560 %} 8561 #else 8562 format %{ "LSL $dst,$src1,$src2\t! int" %} 8563 ins_encode %{ 8564 __ logical_shift_left($dst$$Register, $src1$$Register, $src2$$constant); 8565 %} 8566 #endif 8567 ins_pipe(ialu_reg_imm); 8568 %} 8569 8570 #ifndef AARCH64 8571 instruct shlL_reg_reg_merge_hi(iRegL dst, iRegL src1, iRegI src2) %{ 8572 effect(USE_DEF dst, USE src1, USE src2); 8573 size(4); 8574 format %{"OR $dst.hi,$dst.hi,($src1.hi << $src2)" %} 8575 ins_encode %{ 8576 __ orr($dst$$Register->successor(), $dst$$Register->successor(), AsmOperand($src1$$Register->successor(), lsl, $src2$$Register)); 8577 %} 8578 ins_pipe(ialu_reg_reg); 8579 %} 8580 8581 instruct shlL_reg_reg_merge_lo(iRegL dst, iRegL src1, iRegI src2) %{ 8582 effect(USE_DEF dst, USE src1, USE src2); 8583 size(4); 8584 format %{ "LSL $dst.lo,$src1.lo,$src2 \n\t" %} 8585 ins_encode %{ 8586 __ mov($dst$$Register, AsmOperand($src1$$Register, lsl, $src2$$Register)); 8587 %} 8588 ins_pipe(ialu_reg_reg); 8589 %} 8590 8591 instruct shlL_reg_reg_overlap(iRegL dst, iRegL src1, iRegI src2, flagsReg ccr) %{ 8592 effect(DEF dst, USE src1, USE src2, KILL ccr); 8593 size(16); 8594 format %{ "SUBS $dst.hi,$src2,32 \n\t" 8595 "LSLpl $dst.hi,$src1.lo,$dst.hi \n\t" 8596 "RSBmi $dst.hi,$dst.hi,0 \n\t" 8597 "LSRmi $dst.hi,$src1.lo,$dst.hi" %} 8598 8599 ins_encode %{ 8600 // $src1$$Register and $dst$$Register->successor() can't be the same 8601 __ subs($dst$$Register->successor(), $src2$$Register, 32); 8602 __ mov($dst$$Register->successor(), AsmOperand($src1$$Register, lsl, $dst$$Register->successor()), pl); 8603 __ rsb($dst$$Register->successor(), $dst$$Register->successor(), 0, mi); 8604 __ mov($dst$$Register->successor(), AsmOperand($src1$$Register, lsr, $dst$$Register->successor()), mi); 8605 %} 8606 ins_pipe(ialu_reg_reg); 8607 %} 8608 #endif // !AARCH64 8609 8610 instruct shlL_reg_reg(iRegL dst, iRegL src1, iRegI src2) %{ 8611 match(Set dst (LShiftL src1 src2)); 8612 8613 #ifdef AARCH64 8614 size(4); 8615 format %{ "LSLV $dst,$src1,$src2\t! long" %} 8616 ins_encode %{ 8617 __ lslv($dst$$Register, $src1$$Register, $src2$$Register); 8618 %} 8619 ins_pipe(ialu_reg_reg); 8620 #else 8621 expand %{ 8622 flagsReg ccr; 8623 shlL_reg_reg_overlap(dst, src1, src2, ccr); 8624 shlL_reg_reg_merge_hi(dst, src1, src2); 8625 shlL_reg_reg_merge_lo(dst, src1, src2); 8626 %} 8627 #endif 8628 %} 8629 8630 #ifdef AARCH64 8631 instruct shlL_reg_imm6(iRegL dst, iRegL src1, immU6 src2) %{ 8632 match(Set dst (LShiftL src1 src2)); 8633 8634 size(4); 8635 format %{ "LSL $dst,$src1,$src2\t! long" %} 8636 ins_encode %{ 8637 __ logical_shift_left($dst$$Register, $src1$$Register, $src2$$constant); 8638 %} 8639 ins_pipe(ialu_reg_imm); 8640 %} 8641 #else 8642 // Register Shift Left Immediate 8643 instruct shlL_reg_imm6(iRegL dst, iRegL src1, immU6Big src2) %{ 8644 match(Set dst (LShiftL src1 src2)); 8645 8646 size(8); 8647 format %{ "LSL $dst.hi,$src1.lo,$src2-32\t! or mov if $src2==32\n\t" 8648 "MOV $dst.lo, 0" %} 8649 ins_encode %{ 8650 if ($src2$$constant == 32) { 8651 __ mov($dst$$Register->successor(), $src1$$Register); 8652 } else { 8653 __ mov($dst$$Register->successor(), AsmOperand($src1$$Register, lsl, $src2$$constant-32)); 8654 } 8655 __ mov($dst$$Register, 0); 8656 %} 8657 ins_pipe(ialu_reg_imm); 8658 %} 8659 8660 instruct shlL_reg_imm5(iRegL dst, iRegL src1, immU5 src2) %{ 8661 match(Set dst (LShiftL src1 src2)); 8662 8663 size(12); 8664 format %{ "LSL $dst.hi,$src1.lo,$src2\n\t" 8665 "OR $dst.hi, $dst.hi, $src1.lo >> 32-$src2\n\t" 8666 "LSL $dst.lo,$src1.lo,$src2" %} 8667 ins_encode %{ 8668 // The order of the following 3 instructions matters: src1.lo and 8669 // dst.hi can't overlap but src.hi and dst.hi can. 8670 __ mov($dst$$Register->successor(), AsmOperand($src1$$Register->successor(), lsl, $src2$$constant)); 8671 __ orr($dst$$Register->successor(), $dst$$Register->successor(), AsmOperand($src1$$Register, lsr, 32-$src2$$constant)); 8672 __ mov($dst$$Register, AsmOperand($src1$$Register, lsl, $src2$$constant)); 8673 %} 8674 ins_pipe(ialu_reg_imm); 8675 %} 8676 #endif // !AARCH64 8677 8678 // Register Arithmetic Shift Right 8679 instruct sarI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{ 8680 match(Set dst (RShiftI src1 src2)); 8681 size(4); 8682 #ifdef AARCH64 8683 format %{ "ASRV $dst,$src1,$src2\t! int" %} 8684 ins_encode %{ 8685 __ asrv_w($dst$$Register, $src1$$Register, $src2$$Register); 8686 %} 8687 #else 8688 format %{ "ASR $dst,$src1,$src2\t! int" %} 8689 ins_encode %{ 8690 __ mov($dst$$Register, AsmOperand($src1$$Register, asr, $src2$$Register)); 8691 %} 8692 #endif 8693 ins_pipe(ialu_reg_reg); 8694 %} 8695 8696 // Register Arithmetic Shift Right Immediate 8697 instruct sarI_reg_imm5(iRegI dst, iRegI src1, immU5 src2) %{ 8698 match(Set dst (RShiftI src1 src2)); 8699 8700 size(4); 8701 #ifdef AARCH64 8702 format %{ "ASR_w $dst,$src1,$src2" %} 8703 ins_encode %{ 8704 __ _asr_w($dst$$Register, $src1$$Register, $src2$$constant); 8705 %} 8706 #else 8707 format %{ "ASR $dst,$src1,$src2" %} 8708 ins_encode %{ 8709 __ mov($dst$$Register, AsmOperand($src1$$Register, asr, $src2$$constant)); 8710 %} 8711 #endif 8712 ins_pipe(ialu_reg_imm); 8713 %} 8714 8715 #ifndef AARCH64 8716 // Register Shift Right Arithmetic Long 8717 instruct sarL_reg_reg_merge_lo(iRegL dst, iRegL src1, iRegI src2) %{ 8718 effect(USE_DEF dst, USE src1, USE src2); 8719 size(4); 8720 format %{ "OR $dst.lo,$dst.lo,($src1.lo >> $src2)" %} 8721 ins_encode %{ 8722 __ orr($dst$$Register, $dst$$Register, AsmOperand($src1$$Register, lsr, $src2$$Register)); 8723 %} 8724 ins_pipe(ialu_reg_reg); 8725 %} 8726 8727 instruct sarL_reg_reg_merge_hi(iRegL dst, iRegL src1, iRegI src2) %{ 8728 effect(USE_DEF dst, USE src1, USE src2); 8729 size(4); 8730 format %{ "ASR $dst.hi,$src1.hi,$src2 \n\t" %} 8731 ins_encode %{ 8732 __ mov($dst$$Register->successor(), AsmOperand($src1$$Register->successor(), asr, $src2$$Register)); 8733 %} 8734 ins_pipe(ialu_reg_reg); 8735 %} 8736 8737 instruct sarL_reg_reg_overlap(iRegL dst, iRegL src1, iRegI src2, flagsReg ccr) %{ 8738 effect(DEF dst, USE src1, USE src2, KILL ccr); 8739 size(16); 8740 format %{ "SUBS $dst.lo,$src2,32 \n\t" 8741 "ASRpl $dst.lo,$src1.hi,$dst.lo \n\t" 8742 "RSBmi $dst.lo,$dst.lo,0 \n\t" 8743 "LSLmi $dst.lo,$src1.hi,$dst.lo" %} 8744 8745 ins_encode %{ 8746 // $src1$$Register->successor() and $dst$$Register can't be the same 8747 __ subs($dst$$Register, $src2$$Register, 32); 8748 __ mov($dst$$Register, AsmOperand($src1$$Register->successor(), asr, $dst$$Register), pl); 8749 __ rsb($dst$$Register, $dst$$Register, 0, mi); 8750 __ mov($dst$$Register, AsmOperand($src1$$Register->successor(), lsl, $dst$$Register), mi); 8751 %} 8752 ins_pipe(ialu_reg_reg); 8753 %} 8754 #endif // !AARCH64 8755 8756 instruct sarL_reg_reg(iRegL dst, iRegL src1, iRegI src2) %{ 8757 match(Set dst (RShiftL src1 src2)); 8758 8759 #ifdef AARCH64 8760 size(4); 8761 format %{ "ASRV $dst,$src1,$src2\t! long" %} 8762 ins_encode %{ 8763 __ asrv($dst$$Register, $src1$$Register, $src2$$Register); 8764 %} 8765 ins_pipe(ialu_reg_reg); 8766 #else 8767 expand %{ 8768 flagsReg ccr; 8769 sarL_reg_reg_overlap(dst, src1, src2, ccr); 8770 sarL_reg_reg_merge_lo(dst, src1, src2); 8771 sarL_reg_reg_merge_hi(dst, src1, src2); 8772 %} 8773 #endif 8774 %} 8775 8776 // Register Shift Left Immediate 8777 #ifdef AARCH64 8778 instruct sarL_reg_imm6(iRegL dst, iRegL src1, immU6 src2) %{ 8779 match(Set dst (RShiftL src1 src2)); 8780 8781 size(4); 8782 format %{ "ASR $dst,$src1,$src2\t! long" %} 8783 ins_encode %{ 8784 __ _asr($dst$$Register, $src1$$Register, $src2$$constant); 8785 %} 8786 ins_pipe(ialu_reg_imm); 8787 %} 8788 #else 8789 instruct sarL_reg_imm6(iRegL dst, iRegL src1, immU6Big src2) %{ 8790 match(Set dst (RShiftL src1 src2)); 8791 8792 size(8); 8793 format %{ "ASR $dst.lo,$src1.hi,$src2-32\t! or mov if $src2==32\n\t" 8794 "ASR $dst.hi,$src1.hi, $src2" %} 8795 ins_encode %{ 8796 if ($src2$$constant == 32) { 8797 __ mov($dst$$Register, $src1$$Register->successor()); 8798 } else{ 8799 __ mov($dst$$Register, AsmOperand($src1$$Register->successor(), asr, $src2$$constant-32)); 8800 } 8801 __ mov($dst$$Register->successor(), AsmOperand($src1$$Register->successor(), asr, 0)); 8802 %} 8803 8804 ins_pipe(ialu_reg_imm); 8805 %} 8806 8807 instruct sarL_reg_imm5(iRegL dst, iRegL src1, immU5 src2) %{ 8808 match(Set dst (RShiftL src1 src2)); 8809 size(12); 8810 format %{ "LSR $dst.lo,$src1.lo,$src2\n\t" 8811 "OR $dst.lo, $dst.lo, $src1.hi << 32-$src2\n\t" 8812 "ASR $dst.hi,$src1.hi,$src2" %} 8813 ins_encode %{ 8814 // The order of the following 3 instructions matters: src1.lo and 8815 // dst.hi can't overlap but src.hi and dst.hi can. 8816 __ mov($dst$$Register, AsmOperand($src1$$Register, lsr, $src2$$constant)); 8817 __ orr($dst$$Register, $dst$$Register, AsmOperand($src1$$Register->successor(), lsl, 32-$src2$$constant)); 8818 __ mov($dst$$Register->successor(), AsmOperand($src1$$Register->successor(), asr, $src2$$constant)); 8819 %} 8820 ins_pipe(ialu_reg_imm); 8821 %} 8822 #endif 8823 8824 // Register Shift Right 8825 instruct shrI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{ 8826 match(Set dst (URShiftI src1 src2)); 8827 size(4); 8828 #ifdef AARCH64 8829 format %{ "LSRV $dst,$src1,$src2\t! int" %} 8830 ins_encode %{ 8831 __ lsrv_w($dst$$Register, $src1$$Register, $src2$$Register); 8832 %} 8833 #else 8834 format %{ "LSR $dst,$src1,$src2\t! int" %} 8835 ins_encode %{ 8836 __ mov($dst$$Register, AsmOperand($src1$$Register, lsr, $src2$$Register)); 8837 %} 8838 #endif 8839 ins_pipe(ialu_reg_reg); 8840 %} 8841 8842 // Register Shift Right Immediate 8843 instruct shrI_reg_imm5(iRegI dst, iRegI src1, immU5 src2) %{ 8844 match(Set dst (URShiftI src1 src2)); 8845 8846 size(4); 8847 #ifdef AARCH64 8848 format %{ "LSR_w $dst,$src1,$src2" %} 8849 ins_encode %{ 8850 __ _lsr_w($dst$$Register, $src1$$Register, $src2$$constant); 8851 %} 8852 #else 8853 format %{ "LSR $dst,$src1,$src2" %} 8854 ins_encode %{ 8855 __ mov($dst$$Register, AsmOperand($src1$$Register, lsr, $src2$$constant)); 8856 %} 8857 #endif 8858 ins_pipe(ialu_reg_imm); 8859 %} 8860 8861 #ifndef AARCH64 8862 // Register Shift Right 8863 instruct shrL_reg_reg_merge_lo(iRegL dst, iRegL src1, iRegI src2) %{ 8864 effect(USE_DEF dst, USE src1, USE src2); 8865 size(4); 8866 format %{ "OR $dst.lo,$dst,($src1.lo >>> $src2)" %} 8867 ins_encode %{ 8868 __ orr($dst$$Register, $dst$$Register, AsmOperand($src1$$Register, lsr, $src2$$Register)); 8869 %} 8870 ins_pipe(ialu_reg_reg); 8871 %} 8872 8873 instruct shrL_reg_reg_merge_hi(iRegL dst, iRegL src1, iRegI src2) %{ 8874 effect(USE_DEF dst, USE src1, USE src2); 8875 size(4); 8876 format %{ "LSR $dst.hi,$src1.hi,$src2 \n\t" %} 8877 ins_encode %{ 8878 __ mov($dst$$Register->successor(), AsmOperand($src1$$Register->successor(), lsr, $src2$$Register)); 8879 %} 8880 ins_pipe(ialu_reg_reg); 8881 %} 8882 8883 instruct shrL_reg_reg_overlap(iRegL dst, iRegL src1, iRegI src2, flagsReg ccr) %{ 8884 effect(DEF dst, USE src1, USE src2, KILL ccr); 8885 size(16); 8886 format %{ "SUBS $dst,$src2,32 \n\t" 8887 "LSRpl $dst,$src1.hi,$dst \n\t" 8888 "RSBmi $dst,$dst,0 \n\t" 8889 "LSLmi $dst,$src1.hi,$dst" %} 8890 8891 ins_encode %{ 8892 // $src1$$Register->successor() and $dst$$Register can't be the same 8893 __ subs($dst$$Register, $src2$$Register, 32); 8894 __ mov($dst$$Register, AsmOperand($src1$$Register->successor(), lsr, $dst$$Register), pl); 8895 __ rsb($dst$$Register, $dst$$Register, 0, mi); 8896 __ mov($dst$$Register, AsmOperand($src1$$Register->successor(), lsl, $dst$$Register), mi); 8897 %} 8898 ins_pipe(ialu_reg_reg); 8899 %} 8900 #endif // !AARCH64 8901 8902 instruct shrL_reg_reg(iRegL dst, iRegL src1, iRegI src2) %{ 8903 match(Set dst (URShiftL src1 src2)); 8904 8905 #ifdef AARCH64 8906 size(4); 8907 format %{ "LSRV $dst,$src1,$src2\t! long" %} 8908 ins_encode %{ 8909 __ lsrv($dst$$Register, $src1$$Register, $src2$$Register); 8910 %} 8911 ins_pipe(ialu_reg_reg); 8912 #else 8913 expand %{ 8914 flagsReg ccr; 8915 shrL_reg_reg_overlap(dst, src1, src2, ccr); 8916 shrL_reg_reg_merge_lo(dst, src1, src2); 8917 shrL_reg_reg_merge_hi(dst, src1, src2); 8918 %} 8919 #endif 8920 %} 8921 8922 // Register Shift Right Immediate 8923 #ifdef AARCH64 8924 instruct shrL_reg_imm6(iRegL dst, iRegL src1, immU6 src2) %{ 8925 match(Set dst (URShiftL src1 src2)); 8926 8927 size(4); 8928 format %{ "LSR $dst,$src1,$src2" %} 8929 ins_encode %{ 8930 __ _lsr($dst$$Register, $src1$$Register, $src2$$constant); 8931 %} 8932 ins_pipe(ialu_reg_imm); 8933 %} 8934 #else 8935 instruct shrL_reg_imm6(iRegL dst, iRegL src1, immU6Big src2) %{ 8936 match(Set dst (URShiftL src1 src2)); 8937 8938 size(8); 8939 format %{ "LSR $dst.lo,$src1.hi,$src2-32\t! or mov if $src2==32\n\t" 8940 "MOV $dst.hi, 0" %} 8941 ins_encode %{ 8942 if ($src2$$constant == 32) { 8943 __ mov($dst$$Register, $src1$$Register->successor()); 8944 } else { 8945 __ mov($dst$$Register, AsmOperand($src1$$Register->successor(), lsr, $src2$$constant-32)); 8946 } 8947 __ mov($dst$$Register->successor(), 0); 8948 %} 8949 8950 ins_pipe(ialu_reg_imm); 8951 %} 8952 8953 instruct shrL_reg_imm5(iRegL dst, iRegL src1, immU5 src2) %{ 8954 match(Set dst (URShiftL src1 src2)); 8955 8956 size(12); 8957 format %{ "LSR $dst.lo,$src1.lo,$src2\n\t" 8958 "OR $dst.lo, $dst.lo, $src1.hi << 32-$src2\n\t" 8959 "LSR $dst.hi,$src1.hi,$src2" %} 8960 ins_encode %{ 8961 // The order of the following 3 instructions matters: src1.lo and 8962 // dst.hi can't overlap but src.hi and dst.hi can. 8963 __ mov($dst$$Register, AsmOperand($src1$$Register, lsr, $src2$$constant)); 8964 __ orr($dst$$Register, $dst$$Register, AsmOperand($src1$$Register->successor(), lsl, 32-$src2$$constant)); 8965 __ mov($dst$$Register->successor(), AsmOperand($src1$$Register->successor(), lsr, $src2$$constant)); 8966 %} 8967 ins_pipe(ialu_reg_imm); 8968 %} 8969 #endif // !AARCH64 8970 8971 8972 instruct shrP_reg_imm5(iRegX dst, iRegP src1, immU5 src2) %{ 8973 match(Set dst (URShiftI (CastP2X src1) src2)); 8974 size(4); 8975 format %{ "LSR $dst,$src1,$src2\t! Cast ptr $src1 to int and shift" %} 8976 ins_encode %{ 8977 __ logical_shift_right($dst$$Register, $src1$$Register, $src2$$constant); 8978 %} 8979 ins_pipe(ialu_reg_imm); 8980 %} 8981 8982 //----------Floating Point Arithmetic Instructions----------------------------- 8983 8984 // Add float single precision 8985 instruct addF_reg_reg(regF dst, regF src1, regF src2) %{ 8986 match(Set dst (AddF src1 src2)); 8987 8988 size(4); 8989 format %{ "FADDS $dst,$src1,$src2" %} 8990 ins_encode %{ 8991 __ add_float($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister); 8992 %} 8993 8994 ins_pipe(faddF_reg_reg); 8995 %} 8996 8997 // Add float double precision 8998 instruct addD_reg_reg(regD dst, regD src1, regD src2) %{ 8999 match(Set dst (AddD src1 src2)); 9000 9001 size(4); 9002 format %{ "FADDD $dst,$src1,$src2" %} 9003 ins_encode %{ 9004 __ add_double($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister); 9005 %} 9006 9007 ins_pipe(faddD_reg_reg); 9008 %} 9009 9010 // Sub float single precision 9011 instruct subF_reg_reg(regF dst, regF src1, regF src2) %{ 9012 match(Set dst (SubF src1 src2)); 9013 9014 size(4); 9015 format %{ "FSUBS $dst,$src1,$src2" %} 9016 ins_encode %{ 9017 __ sub_float($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister); 9018 %} 9019 ins_pipe(faddF_reg_reg); 9020 %} 9021 9022 // Sub float double precision 9023 instruct subD_reg_reg(regD dst, regD src1, regD src2) %{ 9024 match(Set dst (SubD src1 src2)); 9025 9026 size(4); 9027 format %{ "FSUBD $dst,$src1,$src2" %} 9028 ins_encode %{ 9029 __ sub_double($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister); 9030 %} 9031 ins_pipe(faddD_reg_reg); 9032 %} 9033 9034 // Mul float single precision 9035 instruct mulF_reg_reg(regF dst, regF src1, regF src2) %{ 9036 match(Set dst (MulF src1 src2)); 9037 9038 size(4); 9039 format %{ "FMULS $dst,$src1,$src2" %} 9040 ins_encode %{ 9041 __ mul_float($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister); 9042 %} 9043 9044 ins_pipe(fmulF_reg_reg); 9045 %} 9046 9047 // Mul float double precision 9048 instruct mulD_reg_reg(regD dst, regD src1, regD src2) %{ 9049 match(Set dst (MulD src1 src2)); 9050 9051 size(4); 9052 format %{ "FMULD $dst,$src1,$src2" %} 9053 ins_encode %{ 9054 __ mul_double($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister); 9055 %} 9056 9057 ins_pipe(fmulD_reg_reg); 9058 %} 9059 9060 // Div float single precision 9061 instruct divF_reg_reg(regF dst, regF src1, regF src2) %{ 9062 match(Set dst (DivF src1 src2)); 9063 9064 size(4); 9065 format %{ "FDIVS $dst,$src1,$src2" %} 9066 ins_encode %{ 9067 __ div_float($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister); 9068 %} 9069 9070 ins_pipe(fdivF_reg_reg); 9071 %} 9072 9073 // Div float double precision 9074 instruct divD_reg_reg(regD dst, regD src1, regD src2) %{ 9075 match(Set dst (DivD src1 src2)); 9076 9077 size(4); 9078 format %{ "FDIVD $dst,$src1,$src2" %} 9079 ins_encode %{ 9080 __ div_double($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister); 9081 %} 9082 9083 ins_pipe(fdivD_reg_reg); 9084 %} 9085 9086 // Absolute float double precision 9087 instruct absD_reg(regD dst, regD src) %{ 9088 match(Set dst (AbsD src)); 9089 9090 size(4); 9091 format %{ "FABSd $dst,$src" %} 9092 ins_encode %{ 9093 __ abs_double($dst$$FloatRegister, $src$$FloatRegister); 9094 %} 9095 ins_pipe(faddD_reg); 9096 %} 9097 9098 // Absolute float single precision 9099 instruct absF_reg(regF dst, regF src) %{ 9100 match(Set dst (AbsF src)); 9101 format %{ "FABSs $dst,$src" %} 9102 ins_encode %{ 9103 __ abs_float($dst$$FloatRegister, $src$$FloatRegister); 9104 %} 9105 ins_pipe(faddF_reg); 9106 %} 9107 9108 instruct negF_reg(regF dst, regF src) %{ 9109 match(Set dst (NegF src)); 9110 9111 size(4); 9112 format %{ "FNEGs $dst,$src" %} 9113 ins_encode %{ 9114 __ neg_float($dst$$FloatRegister, $src$$FloatRegister); 9115 %} 9116 ins_pipe(faddF_reg); 9117 %} 9118 9119 instruct negD_reg(regD dst, regD src) %{ 9120 match(Set dst (NegD src)); 9121 9122 format %{ "FNEGd $dst,$src" %} 9123 ins_encode %{ 9124 __ neg_double($dst$$FloatRegister, $src$$FloatRegister); 9125 %} 9126 ins_pipe(faddD_reg); 9127 %} 9128 9129 // Sqrt float double precision 9130 instruct sqrtF_reg_reg(regF dst, regF src) %{ 9131 match(Set dst (ConvD2F (SqrtD (ConvF2D src)))); 9132 9133 size(4); 9134 format %{ "FSQRTS $dst,$src" %} 9135 ins_encode %{ 9136 __ sqrt_float($dst$$FloatRegister, $src$$FloatRegister); 9137 %} 9138 ins_pipe(fdivF_reg_reg); 9139 %} 9140 9141 // Sqrt float double precision 9142 instruct sqrtD_reg_reg(regD dst, regD src) %{ 9143 match(Set dst (SqrtD src)); 9144 9145 size(4); 9146 format %{ "FSQRTD $dst,$src" %} 9147 ins_encode %{ 9148 __ sqrt_double($dst$$FloatRegister, $src$$FloatRegister); 9149 %} 9150 ins_pipe(fdivD_reg_reg); 9151 %} 9152 9153 //----------Logical Instructions----------------------------------------------- 9154 // And Instructions 9155 // Register And 9156 instruct andI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{ 9157 match(Set dst (AndI src1 src2)); 9158 9159 size(4); 9160 format %{ "and_32 $dst,$src1,$src2" %} 9161 ins_encode %{ 9162 __ and_32($dst$$Register, $src1$$Register, $src2$$Register); 9163 %} 9164 ins_pipe(ialu_reg_reg); 9165 %} 9166 9167 #ifndef AARCH64 9168 instruct andshlI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 9169 match(Set dst (AndI src1 (LShiftI src2 src3))); 9170 9171 size(4); 9172 format %{ "AND $dst,$src1,$src2<<$src3" %} 9173 ins_encode %{ 9174 __ andr($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$Register)); 9175 %} 9176 ins_pipe(ialu_reg_reg); 9177 %} 9178 #endif 9179 9180 instruct andshlI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{ 9181 match(Set dst (AndI src1 (LShiftI src2 src3))); 9182 9183 size(4); 9184 format %{ "and_32 $dst,$src1,$src2<<$src3" %} 9185 ins_encode %{ 9186 __ and_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$constant)); 9187 %} 9188 ins_pipe(ialu_reg_reg); 9189 %} 9190 9191 #ifndef AARCH64 9192 instruct andsarI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 9193 match(Set dst (AndI src1 (RShiftI src2 src3))); 9194 9195 size(4); 9196 format %{ "AND $dst,$src1,$src2>>$src3" %} 9197 ins_encode %{ 9198 __ andr($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$Register)); 9199 %} 9200 ins_pipe(ialu_reg_reg); 9201 %} 9202 #endif 9203 9204 instruct andsarI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{ 9205 match(Set dst (AndI src1 (RShiftI src2 src3))); 9206 9207 size(4); 9208 format %{ "and_32 $dst,$src1,$src2>>$src3" %} 9209 ins_encode %{ 9210 __ and_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$constant)); 9211 %} 9212 ins_pipe(ialu_reg_reg); 9213 %} 9214 9215 #ifndef AARCH64 9216 instruct andshrI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 9217 match(Set dst (AndI src1 (URShiftI src2 src3))); 9218 9219 size(4); 9220 format %{ "AND $dst,$src1,$src2>>>$src3" %} 9221 ins_encode %{ 9222 __ andr($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$Register)); 9223 %} 9224 ins_pipe(ialu_reg_reg); 9225 %} 9226 #endif 9227 9228 instruct andshrI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{ 9229 match(Set dst (AndI src1 (URShiftI src2 src3))); 9230 9231 size(4); 9232 format %{ "and_32 $dst,$src1,$src2>>>$src3" %} 9233 ins_encode %{ 9234 __ and_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$constant)); 9235 %} 9236 ins_pipe(ialu_reg_reg); 9237 %} 9238 9239 // Immediate And 9240 instruct andI_reg_limm(iRegI dst, iRegI src1, limmI src2) %{ 9241 match(Set dst (AndI src1 src2)); 9242 9243 size(4); 9244 format %{ "and_32 $dst,$src1,$src2\t! int" %} 9245 ins_encode %{ 9246 __ and_32($dst$$Register, $src1$$Register, $src2$$constant); 9247 %} 9248 ins_pipe(ialu_reg_imm); 9249 %} 9250 9251 #ifndef AARCH64 9252 instruct andI_reg_limmn(iRegI dst, iRegI src1, limmIn src2) %{ 9253 match(Set dst (AndI src1 src2)); 9254 9255 size(4); 9256 format %{ "bic $dst,$src1,~$src2\t! int" %} 9257 ins_encode %{ 9258 __ bic($dst$$Register, $src1$$Register, ~$src2$$constant); 9259 %} 9260 ins_pipe(ialu_reg_imm); 9261 %} 9262 #endif 9263 9264 // Register And Long 9265 instruct andL_reg_reg(iRegL dst, iRegL src1, iRegL src2) %{ 9266 match(Set dst (AndL src1 src2)); 9267 9268 ins_cost(DEFAULT_COST); 9269 #ifdef AARCH64 9270 size(4); 9271 format %{ "AND $dst,$src1,$src2\t! long" %} 9272 ins_encode %{ 9273 __ andr($dst$$Register, $src1$$Register, $src2$$Register); 9274 %} 9275 #else 9276 size(8); 9277 format %{ "AND $dst,$src1,$src2\t! long" %} 9278 ins_encode %{ 9279 __ andr($dst$$Register, $src1$$Register, $src2$$Register); 9280 __ andr($dst$$Register->successor(), $src1$$Register->successor(), $src2$$Register->successor()); 9281 %} 9282 #endif 9283 ins_pipe(ialu_reg_reg); 9284 %} 9285 9286 #ifdef AARCH64 9287 // Immediate And 9288 instruct andL_reg_limm(iRegL dst, iRegL src1, limmL src2) %{ 9289 match(Set dst (AndL src1 src2)); 9290 9291 size(4); 9292 format %{ "AND $dst,$src1,$src2\t! long" %} 9293 ins_encode %{ 9294 __ andr($dst$$Register, $src1$$Register, (uintx)$src2$$constant); 9295 %} 9296 ins_pipe(ialu_reg_imm); 9297 %} 9298 #else 9299 // TODO: try immLRot2 instead, (0, $con$$constant) becomes 9300 // (hi($con$$constant), lo($con$$constant)) becomes 9301 instruct andL_reg_immRot(iRegL dst, iRegL src1, immLlowRot con) %{ 9302 match(Set dst (AndL src1 con)); 9303 ins_cost(DEFAULT_COST); 9304 size(8); 9305 format %{ "AND $dst,$src1,$con\t! long" %} 9306 ins_encode %{ 9307 __ andr($dst$$Register, $src1$$Register, $con$$constant); 9308 __ andr($dst$$Register->successor(), $src1$$Register->successor(), 0); 9309 %} 9310 ins_pipe(ialu_reg_imm); 9311 %} 9312 #endif 9313 9314 // Or Instructions 9315 // Register Or 9316 instruct orI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{ 9317 match(Set dst (OrI src1 src2)); 9318 9319 size(4); 9320 format %{ "orr_32 $dst,$src1,$src2\t! int" %} 9321 ins_encode %{ 9322 __ orr_32($dst$$Register, $src1$$Register, $src2$$Register); 9323 %} 9324 ins_pipe(ialu_reg_reg); 9325 %} 9326 9327 #ifndef AARCH64 9328 instruct orshlI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 9329 match(Set dst (OrI src1 (LShiftI src2 src3))); 9330 9331 size(4); 9332 format %{ "OR $dst,$src1,$src2<<$src3" %} 9333 ins_encode %{ 9334 __ orr($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$Register)); 9335 %} 9336 ins_pipe(ialu_reg_reg); 9337 %} 9338 #endif 9339 9340 instruct orshlI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{ 9341 match(Set dst (OrI src1 (LShiftI src2 src3))); 9342 9343 size(4); 9344 format %{ "orr_32 $dst,$src1,$src2<<$src3" %} 9345 ins_encode %{ 9346 __ orr_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$constant)); 9347 %} 9348 ins_pipe(ialu_reg_reg); 9349 %} 9350 9351 #ifndef AARCH64 9352 instruct orsarI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 9353 match(Set dst (OrI src1 (RShiftI src2 src3))); 9354 9355 size(4); 9356 format %{ "OR $dst,$src1,$src2>>$src3" %} 9357 ins_encode %{ 9358 __ orr($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$Register)); 9359 %} 9360 ins_pipe(ialu_reg_reg); 9361 %} 9362 #endif 9363 9364 instruct orsarI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{ 9365 match(Set dst (OrI src1 (RShiftI src2 src3))); 9366 9367 size(4); 9368 format %{ "orr_32 $dst,$src1,$src2>>$src3" %} 9369 ins_encode %{ 9370 __ orr_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$constant)); 9371 %} 9372 ins_pipe(ialu_reg_reg); 9373 %} 9374 9375 #ifndef AARCH64 9376 instruct orshrI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 9377 match(Set dst (OrI src1 (URShiftI src2 src3))); 9378 9379 size(4); 9380 format %{ "OR $dst,$src1,$src2>>>$src3" %} 9381 ins_encode %{ 9382 __ orr($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$Register)); 9383 %} 9384 ins_pipe(ialu_reg_reg); 9385 %} 9386 #endif 9387 9388 instruct orshrI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{ 9389 match(Set dst (OrI src1 (URShiftI src2 src3))); 9390 9391 size(4); 9392 format %{ "orr_32 $dst,$src1,$src2>>>$src3" %} 9393 ins_encode %{ 9394 __ orr_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$constant)); 9395 %} 9396 ins_pipe(ialu_reg_reg); 9397 %} 9398 9399 // Immediate Or 9400 instruct orI_reg_limm(iRegI dst, iRegI src1, limmI src2) %{ 9401 match(Set dst (OrI src1 src2)); 9402 9403 size(4); 9404 format %{ "orr_32 $dst,$src1,$src2" %} 9405 ins_encode %{ 9406 __ orr_32($dst$$Register, $src1$$Register, $src2$$constant); 9407 %} 9408 ins_pipe(ialu_reg_imm); 9409 %} 9410 // TODO: orn_32 with limmIn 9411 9412 // Register Or Long 9413 instruct orL_reg_reg(iRegL dst, iRegL src1, iRegL src2) %{ 9414 match(Set dst (OrL src1 src2)); 9415 9416 ins_cost(DEFAULT_COST); 9417 #ifdef AARCH64 9418 size(4); 9419 format %{ "OR $dst,$src1,$src2\t! long" %} 9420 ins_encode %{ 9421 __ orr($dst$$Register, $src1$$Register, $src2$$Register); 9422 %} 9423 #else 9424 size(8); 9425 format %{ "OR $dst.lo,$src1.lo,$src2.lo\t! long\n\t" 9426 "OR $dst.hi,$src1.hi,$src2.hi" %} 9427 ins_encode %{ 9428 __ orr($dst$$Register, $src1$$Register, $src2$$Register); 9429 __ orr($dst$$Register->successor(), $src1$$Register->successor(), $src2$$Register->successor()); 9430 %} 9431 #endif 9432 ins_pipe(ialu_reg_reg); 9433 %} 9434 9435 #ifdef AARCH64 9436 instruct orL_reg_limm(iRegL dst, iRegL src1, limmL src2) %{ 9437 match(Set dst (OrL src1 src2)); 9438 9439 size(4); 9440 format %{ "ORR $dst,$src1,$src2\t! long" %} 9441 ins_encode %{ 9442 __ orr($dst$$Register, $src1$$Register, (uintx)$src2$$constant); 9443 %} 9444 ins_pipe(ialu_reg_imm); 9445 %} 9446 #else 9447 // TODO: try immLRot2 instead, (0, $con$$constant) becomes 9448 // (hi($con$$constant), lo($con$$constant)) becomes 9449 instruct orL_reg_immRot(iRegL dst, iRegL src1, immLlowRot con) %{ 9450 match(Set dst (OrL src1 con)); 9451 ins_cost(DEFAULT_COST); 9452 size(8); 9453 format %{ "OR $dst.lo,$src1.lo,$con\t! long\n\t" 9454 "OR $dst.hi,$src1.hi,$con" %} 9455 ins_encode %{ 9456 __ orr($dst$$Register, $src1$$Register, $con$$constant); 9457 __ orr($dst$$Register->successor(), $src1$$Register->successor(), 0); 9458 %} 9459 ins_pipe(ialu_reg_imm); 9460 %} 9461 #endif 9462 9463 #ifdef TODO 9464 // Use SPRegP to match Rthread (TLS register) without spilling. 9465 // Use store_ptr_RegP to match Rthread (TLS register) without spilling. 9466 // Use sp_ptr_RegP to match Rthread (TLS register) without spilling. 9467 instruct orI_reg_castP2X(iRegI dst, iRegI src1, sp_ptr_RegP src2) %{ 9468 match(Set dst (OrI src1 (CastP2X src2))); 9469 size(4); 9470 format %{ "OR $dst,$src1,$src2" %} 9471 ins_encode %{ 9472 __ orr($dst$$Register, $src1$$Register, $src2$$Register); 9473 %} 9474 ins_pipe(ialu_reg_reg); 9475 %} 9476 #endif 9477 9478 // Xor Instructions 9479 // Register Xor 9480 instruct xorI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{ 9481 match(Set dst (XorI src1 src2)); 9482 9483 size(4); 9484 format %{ "eor_32 $dst,$src1,$src2" %} 9485 ins_encode %{ 9486 __ eor_32($dst$$Register, $src1$$Register, $src2$$Register); 9487 %} 9488 ins_pipe(ialu_reg_reg); 9489 %} 9490 9491 #ifndef AARCH64 9492 instruct xorshlI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 9493 match(Set dst (XorI src1 (LShiftI src2 src3))); 9494 9495 size(4); 9496 format %{ "XOR $dst,$src1,$src2<<$src3" %} 9497 ins_encode %{ 9498 __ eor($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$Register)); 9499 %} 9500 ins_pipe(ialu_reg_reg); 9501 %} 9502 #endif 9503 9504 instruct xorshlI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{ 9505 match(Set dst (XorI src1 (LShiftI src2 src3))); 9506 9507 size(4); 9508 format %{ "eor_32 $dst,$src1,$src2<<$src3" %} 9509 ins_encode %{ 9510 __ eor_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$constant)); 9511 %} 9512 ins_pipe(ialu_reg_reg); 9513 %} 9514 9515 #ifndef AARCH64 9516 instruct xorsarI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 9517 match(Set dst (XorI src1 (RShiftI src2 src3))); 9518 9519 size(4); 9520 format %{ "XOR $dst,$src1,$src2>>$src3" %} 9521 ins_encode %{ 9522 __ eor($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$Register)); 9523 %} 9524 ins_pipe(ialu_reg_reg); 9525 %} 9526 #endif 9527 9528 instruct xorsarI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{ 9529 match(Set dst (XorI src1 (RShiftI src2 src3))); 9530 9531 size(4); 9532 format %{ "eor_32 $dst,$src1,$src2>>$src3" %} 9533 ins_encode %{ 9534 __ eor_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$constant)); 9535 %} 9536 ins_pipe(ialu_reg_reg); 9537 %} 9538 9539 #ifndef AARCH64 9540 instruct xorshrI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 9541 match(Set dst (XorI src1 (URShiftI src2 src3))); 9542 9543 size(4); 9544 format %{ "XOR $dst,$src1,$src2>>>$src3" %} 9545 ins_encode %{ 9546 __ eor($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$Register)); 9547 %} 9548 ins_pipe(ialu_reg_reg); 9549 %} 9550 #endif 9551 9552 instruct xorshrI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{ 9553 match(Set dst (XorI src1 (URShiftI src2 src3))); 9554 9555 size(4); 9556 format %{ "eor_32 $dst,$src1,$src2>>>$src3" %} 9557 ins_encode %{ 9558 __ eor_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$constant)); 9559 %} 9560 ins_pipe(ialu_reg_reg); 9561 %} 9562 9563 // Immediate Xor 9564 instruct xorI_reg_imm(iRegI dst, iRegI src1, limmI src2) %{ 9565 match(Set dst (XorI src1 src2)); 9566 9567 size(4); 9568 format %{ "eor_32 $dst,$src1,$src2" %} 9569 ins_encode %{ 9570 __ eor_32($dst$$Register, $src1$$Register, $src2$$constant); 9571 %} 9572 ins_pipe(ialu_reg_imm); 9573 %} 9574 9575 // Register Xor Long 9576 instruct xorL_reg_reg(iRegL dst, iRegL src1, iRegL src2) %{ 9577 match(Set dst (XorL src1 src2)); 9578 ins_cost(DEFAULT_COST); 9579 #ifdef AARCH64 9580 size(4); 9581 format %{ "XOR $dst,$src1,$src2\t! long" %} 9582 ins_encode %{ 9583 __ eor($dst$$Register, $src1$$Register, $src2$$Register); 9584 %} 9585 #else 9586 size(8); 9587 format %{ "XOR $dst.hi,$src1.hi,$src2.hi\t! long\n\t" 9588 "XOR $dst.lo,$src1.lo,$src2.lo\t! long" %} 9589 ins_encode %{ 9590 __ eor($dst$$Register, $src1$$Register, $src2$$Register); 9591 __ eor($dst$$Register->successor(), $src1$$Register->successor(), $src2$$Register->successor()); 9592 %} 9593 #endif 9594 ins_pipe(ialu_reg_reg); 9595 %} 9596 9597 #ifdef AARCH64 9598 instruct xorL_reg_limmL(iRegL dst, iRegL src1, limmL con) %{ 9599 match(Set dst (XorL src1 con)); 9600 ins_cost(DEFAULT_COST); 9601 size(4); 9602 format %{ "EOR $dst,$src1,$con\t! long" %} 9603 ins_encode %{ 9604 __ eor($dst$$Register, $src1$$Register, (uintx)$con$$constant); 9605 %} 9606 ins_pipe(ialu_reg_imm); 9607 %} 9608 #else 9609 // TODO: try immLRot2 instead, (0, $con$$constant) becomes 9610 // (hi($con$$constant), lo($con$$constant)) becomes 9611 instruct xorL_reg_immRot(iRegL dst, iRegL src1, immLlowRot con) %{ 9612 match(Set dst (XorL src1 con)); 9613 ins_cost(DEFAULT_COST); 9614 size(8); 9615 format %{ "XOR $dst.hi,$src1.hi,$con\t! long\n\t" 9616 "XOR $dst.lo,$src1.lo,0\t! long" %} 9617 ins_encode %{ 9618 __ eor($dst$$Register, $src1$$Register, $con$$constant); 9619 __ eor($dst$$Register->successor(), $src1$$Register->successor(), 0); 9620 %} 9621 ins_pipe(ialu_reg_imm); 9622 %} 9623 #endif // AARCH64 9624 9625 //----------Convert to Boolean------------------------------------------------- 9626 instruct convI2B( iRegI dst, iRegI src, flagsReg ccr ) %{ 9627 match(Set dst (Conv2B src)); 9628 effect(KILL ccr); 9629 #ifdef AARCH64 9630 size(8); 9631 ins_cost(DEFAULT_COST*2); 9632 format %{ "cmp_32 $src,ZR\n\t" 9633 "cset_w $dst, ne" %} 9634 ins_encode %{ 9635 __ cmp_32($src$$Register, ZR); 9636 __ cset_w($dst$$Register, ne); 9637 %} 9638 #else 9639 size(12); 9640 ins_cost(DEFAULT_COST*2); 9641 format %{ "TST $src,$src \n\t" 9642 "MOV $dst, 0 \n\t" 9643 "MOV.ne $dst, 1" %} 9644 ins_encode %{ // FIXME: can do better? 9645 __ tst($src$$Register, $src$$Register); 9646 __ mov($dst$$Register, 0); 9647 __ mov($dst$$Register, 1, ne); 9648 %} 9649 #endif 9650 ins_pipe(ialu_reg_ialu); 9651 %} 9652 9653 instruct convP2B( iRegI dst, iRegP src, flagsReg ccr ) %{ 9654 match(Set dst (Conv2B src)); 9655 effect(KILL ccr); 9656 #ifdef AARCH64 9657 size(8); 9658 ins_cost(DEFAULT_COST*2); 9659 format %{ "CMP $src,ZR\n\t" 9660 "cset $dst, ne" %} 9661 ins_encode %{ 9662 __ cmp($src$$Register, ZR); 9663 __ cset($dst$$Register, ne); 9664 %} 9665 #else 9666 size(12); 9667 ins_cost(DEFAULT_COST*2); 9668 format %{ "TST $src,$src \n\t" 9669 "MOV $dst, 0 \n\t" 9670 "MOV.ne $dst, 1" %} 9671 ins_encode %{ 9672 __ tst($src$$Register, $src$$Register); 9673 __ mov($dst$$Register, 0); 9674 __ mov($dst$$Register, 1, ne); 9675 %} 9676 #endif 9677 ins_pipe(ialu_reg_ialu); 9678 %} 9679 9680 instruct cmpLTMask_reg_reg( iRegI dst, iRegI p, iRegI q, flagsReg ccr ) %{ 9681 match(Set dst (CmpLTMask p q)); 9682 effect( KILL ccr ); 9683 #ifdef AARCH64 9684 size(8); 9685 ins_cost(DEFAULT_COST*2); 9686 format %{ "CMP_w $p,$q\n\t" 9687 "CSETM_w $dst, lt" %} 9688 ins_encode %{ 9689 __ cmp_w($p$$Register, $q$$Register); 9690 __ csetm_w($dst$$Register, lt); 9691 %} 9692 #else 9693 ins_cost(DEFAULT_COST*3); 9694 format %{ "CMP $p,$q\n\t" 9695 "MOV $dst, #0\n\t" 9696 "MOV.lt $dst, #-1" %} 9697 ins_encode %{ 9698 __ cmp($p$$Register, $q$$Register); 9699 __ mov($dst$$Register, 0); 9700 __ mvn($dst$$Register, 0, lt); 9701 %} 9702 #endif 9703 ins_pipe(ialu_reg_reg_ialu); 9704 %} 9705 9706 instruct cmpLTMask_reg_imm( iRegI dst, iRegI p, aimmI q, flagsReg ccr ) %{ 9707 match(Set dst (CmpLTMask p q)); 9708 effect( KILL ccr ); 9709 #ifdef AARCH64 9710 size(8); 9711 ins_cost(DEFAULT_COST*2); 9712 format %{ "CMP_w $p,$q\n\t" 9713 "CSETM_w $dst, lt" %} 9714 ins_encode %{ 9715 __ cmp_w($p$$Register, $q$$constant); 9716 __ csetm_w($dst$$Register, lt); 9717 %} 9718 #else 9719 ins_cost(DEFAULT_COST*3); 9720 format %{ "CMP $p,$q\n\t" 9721 "MOV $dst, #0\n\t" 9722 "MOV.lt $dst, #-1" %} 9723 ins_encode %{ 9724 __ cmp($p$$Register, $q$$constant); 9725 __ mov($dst$$Register, 0); 9726 __ mvn($dst$$Register, 0, lt); 9727 %} 9728 #endif 9729 ins_pipe(ialu_reg_reg_ialu); 9730 %} 9731 9732 #ifdef AARCH64 9733 instruct cadd_cmpLTMask3( iRegI dst, iRegI p, iRegI q, iRegI y, iRegI x, flagsReg ccr ) %{ 9734 match(Set dst (AddI (AndI (CmpLTMask p q) y) x)); 9735 effect( TEMP dst, KILL ccr ); 9736 size(12); 9737 ins_cost(DEFAULT_COST*3); 9738 format %{ "CMP_w $p,$q\n\t" 9739 "ADD_w $dst,$y,$x\n\t" 9740 "CSEL_w $dst,$dst,$x,lt" %} 9741 ins_encode %{ 9742 __ cmp_w($p$$Register, $q$$Register); 9743 __ add_w($dst$$Register, $y$$Register, $x$$Register); 9744 __ csel_w($dst$$Register, $dst$$Register, $x$$Register, lt); 9745 %} 9746 ins_pipe( cadd_cmpltmask ); 9747 %} 9748 #else 9749 instruct cadd_cmpLTMask3( iRegI p, iRegI q, iRegI y, iRegI z, flagsReg ccr ) %{ 9750 match(Set z (AddI (AndI (CmpLTMask p q) y) z)); 9751 effect( KILL ccr ); 9752 ins_cost(DEFAULT_COST*2); 9753 format %{ "CMP $p,$q\n\t" 9754 "ADD.lt $z,$y,$z" %} 9755 ins_encode %{ 9756 __ cmp($p$$Register, $q$$Register); 9757 __ add($z$$Register, $y$$Register, $z$$Register, lt); 9758 %} 9759 ins_pipe( cadd_cmpltmask ); 9760 %} 9761 #endif 9762 9763 #ifdef AARCH64 9764 instruct cadd_cmpLTMask4( iRegI dst, iRegI p, aimmI q, iRegI y, iRegI x, flagsReg ccr ) %{ 9765 match(Set dst (AddI (AndI (CmpLTMask p q) y) x)); 9766 effect( TEMP dst, KILL ccr ); 9767 size(12); 9768 ins_cost(DEFAULT_COST*3); 9769 format %{ "CMP_w $p,$q\n\t" 9770 "ADD_w $dst,$y,$x\n\t" 9771 "CSEL_w $dst,$dst,$x,lt" %} 9772 ins_encode %{ 9773 __ cmp_w($p$$Register, $q$$constant); 9774 __ add_w($dst$$Register, $y$$Register, $x$$Register); 9775 __ csel_w($dst$$Register, $dst$$Register, $x$$Register, lt); 9776 %} 9777 ins_pipe( cadd_cmpltmask ); 9778 %} 9779 #else 9780 // FIXME: remove unused "dst" 9781 instruct cadd_cmpLTMask4( iRegI dst, iRegI p, aimmI q, iRegI y, iRegI z, flagsReg ccr ) %{ 9782 match(Set z (AddI (AndI (CmpLTMask p q) y) z)); 9783 effect( KILL ccr ); 9784 ins_cost(DEFAULT_COST*2); 9785 format %{ "CMP $p,$q\n\t" 9786 "ADD.lt $z,$y,$z" %} 9787 ins_encode %{ 9788 __ cmp($p$$Register, $q$$constant); 9789 __ add($z$$Register, $y$$Register, $z$$Register, lt); 9790 %} 9791 ins_pipe( cadd_cmpltmask ); 9792 %} 9793 #endif // !AARCH64 9794 9795 #ifdef AARCH64 9796 instruct cadd_cmpLTMask( iRegI dst, iRegI p, iRegI q, iRegI y, flagsReg ccr ) %{ 9797 match(Set dst (AddI (AndI (CmpLTMask p q) y) (SubI p q))); 9798 effect( TEMP dst, KILL ccr ); 9799 size(12); 9800 ins_cost(DEFAULT_COST*3); 9801 format %{ "SUBS_w $p,$p,$q\n\t" 9802 "ADD_w $dst,$y,$p\n\t" 9803 "CSEL_w $dst,$dst,$p,lt" %} 9804 ins_encode %{ 9805 __ subs_w($p$$Register, $p$$Register, $q$$Register); 9806 __ add_w($dst$$Register, $y$$Register, $p$$Register); 9807 __ csel_w($dst$$Register, $dst$$Register, $p$$Register, lt); 9808 %} 9809 ins_pipe( cadd_cmpltmask ); // FIXME 9810 %} 9811 #else 9812 instruct cadd_cmpLTMask( iRegI p, iRegI q, iRegI y, flagsReg ccr ) %{ 9813 match(Set p (AddI (AndI (CmpLTMask p q) y) (SubI p q))); 9814 effect( KILL ccr ); 9815 ins_cost(DEFAULT_COST*2); 9816 format %{ "SUBS $p,$p,$q\n\t" 9817 "ADD.lt $p,$y,$p" %} 9818 ins_encode %{ 9819 __ subs($p$$Register, $p$$Register, $q$$Register); 9820 __ add($p$$Register, $y$$Register, $p$$Register, lt); 9821 %} 9822 ins_pipe( cadd_cmpltmask ); 9823 %} 9824 #endif 9825 9826 //----------Arithmetic Conversion Instructions--------------------------------- 9827 // The conversions operations are all Alpha sorted. Please keep it that way! 9828 9829 instruct convD2F_reg(regF dst, regD src) %{ 9830 match(Set dst (ConvD2F src)); 9831 size(4); 9832 format %{ "FCVTSD $dst,$src" %} 9833 ins_encode %{ 9834 __ convert_d2f($dst$$FloatRegister, $src$$FloatRegister); 9835 %} 9836 ins_pipe(fcvtD2F); 9837 %} 9838 9839 // Convert a double to an int in a float register. 9840 // If the double is a NAN, stuff a zero in instead. 9841 9842 #ifdef AARCH64 9843 instruct convD2I_reg_reg(iRegI dst, regD src) %{ 9844 match(Set dst (ConvD2I src)); 9845 ins_cost(DEFAULT_COST*2 + MEMORY_REF_COST*2 + BRANCH_COST); // FIXME 9846 format %{ "FCVTZS_wd $dst, $src" %} 9847 ins_encode %{ 9848 __ fcvtzs_wd($dst$$Register, $src$$FloatRegister); 9849 %} 9850 ins_pipe(fcvtD2I); 9851 %} 9852 9853 instruct convD2L_reg_reg(iRegL dst, regD src) %{ 9854 match(Set dst (ConvD2L src)); 9855 ins_cost(DEFAULT_COST*2 + MEMORY_REF_COST*2 + BRANCH_COST); // FIXME 9856 format %{ "FCVTZS_xd $dst, $src" %} 9857 ins_encode %{ 9858 __ fcvtzs_xd($dst$$Register, $src$$FloatRegister); 9859 %} 9860 ins_pipe(fcvtD2L); 9861 %} 9862 #else 9863 instruct convD2I_reg_reg(iRegI dst, regD src, regF tmp) %{ 9864 match(Set dst (ConvD2I src)); 9865 effect( TEMP tmp ); 9866 ins_cost(DEFAULT_COST*2 + MEMORY_REF_COST*2 + BRANCH_COST); // FIXME 9867 format %{ "FTOSIZD $tmp,$src\n\t" 9868 "FMRS $dst, $tmp" %} 9869 ins_encode %{ 9870 __ ftosizd($tmp$$FloatRegister, $src$$FloatRegister); 9871 __ fmrs($dst$$Register, $tmp$$FloatRegister); 9872 %} 9873 ins_pipe(fcvtD2I); 9874 %} 9875 #endif 9876 9877 // Convert a double to a long in a double register. 9878 // If the double is a NAN, stuff a zero in instead. 9879 9880 #ifndef AARCH64 9881 // Double to Long conversion 9882 instruct convD2L_reg(R0R1RegL dst, regD src) %{ 9883 match(Set dst (ConvD2L src)); 9884 effect(CALL); 9885 ins_cost(MEMORY_REF_COST); // FIXME 9886 format %{ "convD2L $dst,$src\t ! call to SharedRuntime::d2l" %} 9887 ins_encode %{ 9888 #ifndef __ABI_HARD__ 9889 __ fmrrd($dst$$Register, $dst$$Register->successor(), $src$$FloatRegister); 9890 #else 9891 if ($src$$FloatRegister != D0) { 9892 __ mov_double(D0, $src$$FloatRegister); 9893 } 9894 #endif 9895 address target = CAST_FROM_FN_PTR(address, SharedRuntime::d2l); 9896 __ call(target, relocInfo::runtime_call_type); 9897 %} 9898 ins_pipe(fcvtD2L); 9899 %} 9900 #endif 9901 9902 instruct convF2D_reg(regD dst, regF src) %{ 9903 match(Set dst (ConvF2D src)); 9904 size(4); 9905 format %{ "FCVTDS $dst,$src" %} 9906 ins_encode %{ 9907 __ convert_f2d($dst$$FloatRegister, $src$$FloatRegister); 9908 %} 9909 ins_pipe(fcvtF2D); 9910 %} 9911 9912 #ifdef AARCH64 9913 instruct convF2I_reg_reg(iRegI dst, regF src) %{ 9914 match(Set dst (ConvF2I src)); 9915 ins_cost(DEFAULT_COST*2 + MEMORY_REF_COST*2 + BRANCH_COST); // FIXME 9916 size(4); 9917 format %{ "FCVTZS_ws $dst, $src" %} 9918 ins_encode %{ 9919 __ fcvtzs_ws($dst$$Register, $src$$FloatRegister); 9920 %} 9921 ins_pipe(fcvtF2I); 9922 %} 9923 9924 instruct convF2L_reg_reg(iRegL dst, regF src) %{ 9925 match(Set dst (ConvF2L src)); 9926 ins_cost(DEFAULT_COST*2 + MEMORY_REF_COST*2 + BRANCH_COST); // FIXME 9927 size(4); 9928 format %{ "FCVTZS_xs $dst, $src" %} 9929 ins_encode %{ 9930 __ fcvtzs_xs($dst$$Register, $src$$FloatRegister); 9931 %} 9932 ins_pipe(fcvtF2L); 9933 %} 9934 #else 9935 instruct convF2I_reg_reg(iRegI dst, regF src, regF tmp) %{ 9936 match(Set dst (ConvF2I src)); 9937 effect( TEMP tmp ); 9938 ins_cost(DEFAULT_COST*2 + MEMORY_REF_COST*2 + BRANCH_COST); // FIXME 9939 size(8); 9940 format %{ "FTOSIZS $tmp,$src\n\t" 9941 "FMRS $dst, $tmp" %} 9942 ins_encode %{ 9943 __ ftosizs($tmp$$FloatRegister, $src$$FloatRegister); 9944 __ fmrs($dst$$Register, $tmp$$FloatRegister); 9945 %} 9946 ins_pipe(fcvtF2I); 9947 %} 9948 9949 // Float to Long conversion 9950 instruct convF2L_reg(R0R1RegL dst, regF src, R0RegI arg1) %{ 9951 match(Set dst (ConvF2L src)); 9952 ins_cost(DEFAULT_COST*2 + MEMORY_REF_COST*2 + BRANCH_COST); // FIXME 9953 effect(CALL); 9954 format %{ "convF2L $dst,$src\t! call to SharedRuntime::f2l" %} 9955 ins_encode %{ 9956 #ifndef __ABI_HARD__ 9957 __ fmrs($arg1$$Register, $src$$FloatRegister); 9958 #else 9959 if($src$$FloatRegister != S0) { 9960 __ mov_float(S0, $src$$FloatRegister); 9961 } 9962 #endif 9963 address target = CAST_FROM_FN_PTR(address, SharedRuntime::f2l); 9964 __ call(target, relocInfo::runtime_call_type); 9965 %} 9966 ins_pipe(fcvtF2L); 9967 %} 9968 #endif 9969 9970 #ifdef AARCH64 9971 instruct convI2D_reg_reg(iRegI src, regD dst) %{ 9972 match(Set dst (ConvI2D src)); 9973 ins_cost(DEFAULT_COST + MEMORY_REF_COST); // FIXME 9974 size(4); 9975 format %{ "SCVTF_dw $dst,$src" %} 9976 ins_encode %{ 9977 __ scvtf_dw($dst$$FloatRegister, $src$$Register); 9978 %} 9979 ins_pipe(fcvtI2D); 9980 %} 9981 #else 9982 instruct convI2D_reg_reg(iRegI src, regD_low dst) %{ 9983 match(Set dst (ConvI2D src)); 9984 ins_cost(DEFAULT_COST + MEMORY_REF_COST); // FIXME 9985 size(8); 9986 format %{ "FMSR $dst,$src \n\t" 9987 "FSITOD $dst $dst"%} 9988 ins_encode %{ 9989 __ fmsr($dst$$FloatRegister, $src$$Register); 9990 __ fsitod($dst$$FloatRegister, $dst$$FloatRegister); 9991 %} 9992 ins_pipe(fcvtI2D); 9993 %} 9994 #endif 9995 9996 instruct convI2F_reg_reg( regF dst, iRegI src ) %{ 9997 match(Set dst (ConvI2F src)); 9998 ins_cost(DEFAULT_COST + MEMORY_REF_COST); // FIXME 9999 #ifdef AARCH64 10000 size(4); 10001 format %{ "SCVTF_sw $dst,$src" %} 10002 ins_encode %{ 10003 __ scvtf_sw($dst$$FloatRegister, $src$$Register); 10004 %} 10005 #else 10006 size(8); 10007 format %{ "FMSR $dst,$src \n\t" 10008 "FSITOS $dst, $dst"%} 10009 ins_encode %{ 10010 __ fmsr($dst$$FloatRegister, $src$$Register); 10011 __ fsitos($dst$$FloatRegister, $dst$$FloatRegister); 10012 %} 10013 #endif 10014 ins_pipe(fcvtI2F); 10015 %} 10016 10017 instruct convI2L_reg(iRegL dst, iRegI src) %{ 10018 match(Set dst (ConvI2L src)); 10019 #ifdef AARCH64 10020 size(4); 10021 format %{ "SXTW $dst,$src\t! int->long" %} 10022 ins_encode %{ 10023 __ sxtw($dst$$Register, $src$$Register); 10024 %} 10025 #else 10026 size(8); 10027 format %{ "MOV $dst.lo, $src \n\t" 10028 "ASR $dst.hi,$src,31\t! int->long" %} 10029 ins_encode %{ 10030 __ mov($dst$$Register, $src$$Register); 10031 __ mov($dst$$Register->successor(), AsmOperand($src$$Register, asr, 31)); 10032 %} 10033 #endif 10034 ins_pipe(ialu_reg_reg); 10035 %} 10036 10037 // Zero-extend convert int to long 10038 instruct convI2L_reg_zex(iRegL dst, iRegI src, immL_32bits mask ) %{ 10039 match(Set dst (AndL (ConvI2L src) mask) ); 10040 #ifdef AARCH64 10041 size(4); 10042 format %{ "mov_w $dst,$src\t! zero-extend int to long" %} 10043 ins_encode %{ 10044 __ mov_w($dst$$Register, $src$$Register); 10045 %} 10046 #else 10047 size(8); 10048 format %{ "MOV $dst.lo,$src.lo\t! zero-extend int to long\n\t" 10049 "MOV $dst.hi, 0"%} 10050 ins_encode %{ 10051 __ mov($dst$$Register, $src$$Register); 10052 __ mov($dst$$Register->successor(), 0); 10053 %} 10054 #endif 10055 ins_pipe(ialu_reg_reg); 10056 %} 10057 10058 // Zero-extend long 10059 instruct zerox_long(iRegL dst, iRegL src, immL_32bits mask ) %{ 10060 match(Set dst (AndL src mask) ); 10061 #ifdef AARCH64 10062 size(4); 10063 format %{ "mov_w $dst,$src\t! zero-extend long" %} 10064 ins_encode %{ 10065 __ mov_w($dst$$Register, $src$$Register); 10066 %} 10067 #else 10068 size(8); 10069 format %{ "MOV $dst.lo,$src.lo\t! zero-extend long\n\t" 10070 "MOV $dst.hi, 0"%} 10071 ins_encode %{ 10072 __ mov($dst$$Register, $src$$Register); 10073 __ mov($dst$$Register->successor(), 0); 10074 %} 10075 #endif 10076 ins_pipe(ialu_reg_reg); 10077 %} 10078 10079 instruct MoveF2I_reg_reg(iRegI dst, regF src) %{ 10080 match(Set dst (MoveF2I src)); 10081 effect(DEF dst, USE src); 10082 ins_cost(MEMORY_REF_COST); // FIXME 10083 10084 size(4); 10085 format %{ "FMRS $dst,$src\t! MoveF2I" %} 10086 ins_encode %{ 10087 __ fmrs($dst$$Register, $src$$FloatRegister); 10088 %} 10089 ins_pipe(iload_mem); // FIXME 10090 %} 10091 10092 instruct MoveI2F_reg_reg(regF dst, iRegI src) %{ 10093 match(Set dst (MoveI2F src)); 10094 ins_cost(MEMORY_REF_COST); // FIXME 10095 10096 size(4); 10097 format %{ "FMSR $dst,$src\t! MoveI2F" %} 10098 ins_encode %{ 10099 __ fmsr($dst$$FloatRegister, $src$$Register); 10100 %} 10101 ins_pipe(iload_mem); // FIXME 10102 %} 10103 10104 instruct MoveD2L_reg_reg(iRegL dst, regD src) %{ 10105 match(Set dst (MoveD2L src)); 10106 effect(DEF dst, USE src); 10107 ins_cost(MEMORY_REF_COST); // FIXME 10108 10109 size(4); 10110 #ifdef AARCH64 10111 format %{ "FMOV_xd $dst,$src\t! MoveD2L" %} 10112 ins_encode %{ 10113 __ fmov_xd($dst$$Register, $src$$FloatRegister); 10114 %} 10115 #else 10116 format %{ "FMRRD $dst,$src\t! MoveD2L" %} 10117 ins_encode %{ 10118 __ fmrrd($dst$$Register, $dst$$Register->successor(), $src$$FloatRegister); 10119 %} 10120 #endif 10121 ins_pipe(iload_mem); // FIXME 10122 %} 10123 10124 instruct MoveL2D_reg_reg(regD dst, iRegL src) %{ 10125 match(Set dst (MoveL2D src)); 10126 effect(DEF dst, USE src); 10127 ins_cost(MEMORY_REF_COST); // FIXME 10128 10129 size(4); 10130 #ifdef AARCH64 10131 format %{ "FMOV_dx $dst,$src\t! MoveL2D" %} 10132 ins_encode %{ 10133 __ fmov_dx($dst$$FloatRegister, $src$$Register); 10134 %} 10135 #else 10136 format %{ "FMDRR $dst,$src\t! MoveL2D" %} 10137 ins_encode %{ 10138 __ fmdrr($dst$$FloatRegister, $src$$Register, $src$$Register->successor()); 10139 %} 10140 #endif 10141 ins_pipe(ialu_reg_reg); // FIXME 10142 %} 10143 10144 //----------- 10145 // Long to Double conversion 10146 10147 #ifdef AARCH64 10148 instruct convL2D(regD dst, iRegL src) %{ 10149 match(Set dst (ConvL2D src)); 10150 ins_cost(DEFAULT_COST*2 + MEMORY_REF_COST*2 + BRANCH_COST); // FIXME 10151 size(4); 10152 format %{ "SCVTF_dx $dst, $src" %} 10153 ins_encode %{ 10154 __ scvtf_dx($dst$$FloatRegister, $src$$Register); 10155 %} 10156 ins_pipe(fcvtL2D); 10157 %} 10158 10159 instruct convL2F(regF dst, iRegL src) %{ 10160 match(Set dst (ConvL2F src)); 10161 ins_cost(DEFAULT_COST*2 + MEMORY_REF_COST*2 + BRANCH_COST); // FIXME 10162 size(4); 10163 format %{ "SCVTF_sx $dst, $src" %} 10164 ins_encode %{ 10165 __ scvtf_sx($dst$$FloatRegister, $src$$Register); 10166 %} 10167 ins_pipe(fcvtL2F); 10168 %} 10169 #else 10170 // Magic constant, 0x43300000 10171 instruct loadConI_x43300000(iRegI dst) %{ 10172 effect(DEF dst); 10173 size(8); 10174 format %{ "MOV_SLOW $dst,0x43300000\t! 2^52" %} 10175 ins_encode %{ 10176 __ mov_slow($dst$$Register, 0x43300000); 10177 %} 10178 ins_pipe(ialu_none); 10179 %} 10180 10181 // Magic constant, 0x41f00000 10182 instruct loadConI_x41f00000(iRegI dst) %{ 10183 effect(DEF dst); 10184 size(8); 10185 format %{ "MOV_SLOW $dst, 0x41f00000\t! 2^32" %} 10186 ins_encode %{ 10187 __ mov_slow($dst$$Register, 0x41f00000); 10188 %} 10189 ins_pipe(ialu_none); 10190 %} 10191 10192 instruct loadConI_x0(iRegI dst) %{ 10193 effect(DEF dst); 10194 size(4); 10195 format %{ "MOV $dst, 0x0\t! 0" %} 10196 ins_encode %{ 10197 __ mov($dst$$Register, 0); 10198 %} 10199 ins_pipe(ialu_none); 10200 %} 10201 10202 // Construct a double from two float halves 10203 instruct regDHi_regDLo_to_regD(regD_low dst, regD_low src1, regD_low src2) %{ 10204 effect(DEF dst, USE src1, USE src2); 10205 size(8); 10206 format %{ "FCPYS $dst.hi,$src1.hi\n\t" 10207 "FCPYS $dst.lo,$src2.lo" %} 10208 ins_encode %{ 10209 __ fcpys($dst$$FloatRegister->successor(), $src1$$FloatRegister->successor()); 10210 __ fcpys($dst$$FloatRegister, $src2$$FloatRegister); 10211 %} 10212 ins_pipe(faddD_reg_reg); 10213 %} 10214 10215 #ifndef AARCH64 10216 // Convert integer in high half of a double register (in the lower half of 10217 // the double register file) to double 10218 instruct convI2D_regDHi_regD(regD dst, regD_low src) %{ 10219 effect(DEF dst, USE src); 10220 size(4); 10221 format %{ "FSITOD $dst,$src" %} 10222 ins_encode %{ 10223 __ fsitod($dst$$FloatRegister, $src$$FloatRegister->successor()); 10224 %} 10225 ins_pipe(fcvtLHi2D); 10226 %} 10227 #endif 10228 10229 // Add float double precision 10230 instruct addD_regD_regD(regD dst, regD src1, regD src2) %{ 10231 effect(DEF dst, USE src1, USE src2); 10232 size(4); 10233 format %{ "FADDD $dst,$src1,$src2" %} 10234 ins_encode %{ 10235 __ add_double($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister); 10236 %} 10237 ins_pipe(faddD_reg_reg); 10238 %} 10239 10240 // Sub float double precision 10241 instruct subD_regD_regD(regD dst, regD src1, regD src2) %{ 10242 effect(DEF dst, USE src1, USE src2); 10243 size(4); 10244 format %{ "FSUBD $dst,$src1,$src2" %} 10245 ins_encode %{ 10246 __ sub_double($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister); 10247 %} 10248 ins_pipe(faddD_reg_reg); 10249 %} 10250 10251 // Mul float double precision 10252 instruct mulD_regD_regD(regD dst, regD src1, regD src2) %{ 10253 effect(DEF dst, USE src1, USE src2); 10254 size(4); 10255 format %{ "FMULD $dst,$src1,$src2" %} 10256 ins_encode %{ 10257 __ mul_double($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister); 10258 %} 10259 ins_pipe(fmulD_reg_reg); 10260 %} 10261 10262 instruct regL_to_regD(regD dst, iRegL src) %{ 10263 // No match rule to avoid chain rule match. 10264 effect(DEF dst, USE src); 10265 ins_cost(MEMORY_REF_COST); 10266 size(4); 10267 format %{ "FMDRR $dst,$src\t! regL to regD" %} 10268 ins_encode %{ 10269 __ fmdrr($dst$$FloatRegister, $src$$Register, $src$$Register->successor()); 10270 %} 10271 ins_pipe(ialu_reg_reg); // FIXME 10272 %} 10273 10274 instruct regI_regI_to_regD(regD dst, iRegI src1, iRegI src2) %{ 10275 // No match rule to avoid chain rule match. 10276 effect(DEF dst, USE src1, USE src2); 10277 ins_cost(MEMORY_REF_COST); 10278 size(4); 10279 format %{ "FMDRR $dst,$src1,$src2\t! regI,regI to regD" %} 10280 ins_encode %{ 10281 __ fmdrr($dst$$FloatRegister, $src1$$Register, $src2$$Register); 10282 %} 10283 ins_pipe(ialu_reg_reg); // FIXME 10284 %} 10285 10286 instruct convL2D_reg_slow_fxtof(regD dst, iRegL src) %{ 10287 match(Set dst (ConvL2D src)); 10288 ins_cost(DEFAULT_COST*8 + MEMORY_REF_COST*6); // FIXME 10289 10290 expand %{ 10291 regD_low tmpsrc; 10292 iRegI ix43300000; 10293 iRegI ix41f00000; 10294 iRegI ix0; 10295 regD_low dx43300000; 10296 regD dx41f00000; 10297 regD tmp1; 10298 regD_low tmp2; 10299 regD tmp3; 10300 regD tmp4; 10301 10302 regL_to_regD(tmpsrc, src); 10303 10304 loadConI_x43300000(ix43300000); 10305 loadConI_x41f00000(ix41f00000); 10306 loadConI_x0(ix0); 10307 10308 regI_regI_to_regD(dx43300000, ix0, ix43300000); 10309 regI_regI_to_regD(dx41f00000, ix0, ix41f00000); 10310 10311 convI2D_regDHi_regD(tmp1, tmpsrc); 10312 regDHi_regDLo_to_regD(tmp2, dx43300000, tmpsrc); 10313 subD_regD_regD(tmp3, tmp2, dx43300000); 10314 mulD_regD_regD(tmp4, tmp1, dx41f00000); 10315 addD_regD_regD(dst, tmp3, tmp4); 10316 %} 10317 %} 10318 #endif // !AARCH64 10319 10320 instruct convL2I_reg(iRegI dst, iRegL src) %{ 10321 match(Set dst (ConvL2I src)); 10322 size(4); 10323 #ifdef AARCH64 10324 format %{ "MOV_w $dst,$src\t! long->int" %} 10325 ins_encode %{ 10326 __ mov_w($dst$$Register, $src$$Register); 10327 %} 10328 #else 10329 format %{ "MOV $dst,$src.lo\t! long->int" %} 10330 ins_encode %{ 10331 __ mov($dst$$Register, $src$$Register); 10332 %} 10333 #endif 10334 ins_pipe(ialu_move_reg_I_to_L); 10335 %} 10336 10337 #ifndef AARCH64 10338 // Register Shift Right Immediate 10339 instruct shrL_reg_imm6_L2I(iRegI dst, iRegL src, immI_32_63 cnt) %{ 10340 match(Set dst (ConvL2I (RShiftL src cnt))); 10341 size(4); 10342 format %{ "ASR $dst,$src.hi,($cnt - 32)\t! long->int or mov if $cnt==32" %} 10343 ins_encode %{ 10344 if ($cnt$$constant == 32) { 10345 __ mov($dst$$Register, $src$$Register->successor()); 10346 } else { 10347 __ mov($dst$$Register, AsmOperand($src$$Register->successor(), asr, $cnt$$constant - 32)); 10348 } 10349 %} 10350 ins_pipe(ialu_reg_imm); 10351 %} 10352 #endif 10353 10354 10355 //----------Control Flow Instructions------------------------------------------ 10356 // Compare Instructions 10357 // Compare Integers 10358 instruct compI_iReg(flagsReg icc, iRegI op1, iRegI op2) %{ 10359 match(Set icc (CmpI op1 op2)); 10360 effect( DEF icc, USE op1, USE op2 ); 10361 10362 size(4); 10363 format %{ "cmp_32 $op1,$op2\t! int" %} 10364 ins_encode %{ 10365 __ cmp_32($op1$$Register, $op2$$Register); 10366 %} 10367 ins_pipe(ialu_cconly_reg_reg); 10368 %} 10369 10370 #ifdef _LP64 10371 // Compare compressed pointers 10372 instruct compN_reg2(flagsRegU icc, iRegN op1, iRegN op2) %{ 10373 match(Set icc (CmpN op1 op2)); 10374 effect( DEF icc, USE op1, USE op2 ); 10375 10376 size(4); 10377 format %{ "cmp_32 $op1,$op2\t! int" %} 10378 ins_encode %{ 10379 __ cmp_32($op1$$Register, $op2$$Register); 10380 %} 10381 ins_pipe(ialu_cconly_reg_reg); 10382 %} 10383 #endif 10384 10385 instruct compU_iReg(flagsRegU icc, iRegI op1, iRegI op2) %{ 10386 match(Set icc (CmpU op1 op2)); 10387 10388 size(4); 10389 format %{ "cmp_32 $op1,$op2\t! unsigned int" %} 10390 ins_encode %{ 10391 __ cmp_32($op1$$Register, $op2$$Register); 10392 %} 10393 ins_pipe(ialu_cconly_reg_reg); 10394 %} 10395 10396 instruct compI_iReg_immneg(flagsReg icc, iRegI op1, aimmIneg op2) %{ 10397 match(Set icc (CmpI op1 op2)); 10398 effect( DEF icc, USE op1 ); 10399 10400 size(4); 10401 format %{ "cmn_32 $op1,-$op2\t! int" %} 10402 ins_encode %{ 10403 __ cmn_32($op1$$Register, -$op2$$constant); 10404 %} 10405 ins_pipe(ialu_cconly_reg_imm); 10406 %} 10407 10408 instruct compI_iReg_imm(flagsReg icc, iRegI op1, aimmI op2) %{ 10409 match(Set icc (CmpI op1 op2)); 10410 effect( DEF icc, USE op1 ); 10411 10412 size(4); 10413 format %{ "cmp_32 $op1,$op2\t! int" %} 10414 ins_encode %{ 10415 __ cmp_32($op1$$Register, $op2$$constant); 10416 %} 10417 ins_pipe(ialu_cconly_reg_imm); 10418 %} 10419 10420 instruct testI_reg_reg( flagsReg_EQNELTGE icc, iRegI op1, iRegI op2, immI0 zero ) %{ 10421 match(Set icc (CmpI (AndI op1 op2) zero)); 10422 size(4); 10423 format %{ "tst_32 $op2,$op1" %} 10424 10425 ins_encode %{ 10426 __ tst_32($op1$$Register, $op2$$Register); 10427 %} 10428 ins_pipe(ialu_cconly_reg_reg_zero); 10429 %} 10430 10431 #ifndef AARCH64 10432 instruct testshlI_reg_reg_reg( flagsReg_EQNELTGE icc, iRegI op1, iRegI op2, iRegI op3, immI0 zero ) %{ 10433 match(Set icc (CmpI (AndI op1 (LShiftI op2 op3)) zero)); 10434 size(4); 10435 format %{ "TST $op2,$op1<<$op3" %} 10436 10437 ins_encode %{ 10438 __ tst($op1$$Register, AsmOperand($op2$$Register, lsl, $op3$$Register)); 10439 %} 10440 ins_pipe(ialu_cconly_reg_reg_zero); 10441 %} 10442 #endif 10443 10444 instruct testshlI_reg_reg_imm( flagsReg_EQNELTGE icc, iRegI op1, iRegI op2, immU5 op3, immI0 zero ) %{ 10445 match(Set icc (CmpI (AndI op1 (LShiftI op2 op3)) zero)); 10446 size(4); 10447 format %{ "tst_32 $op2,$op1<<$op3" %} 10448 10449 ins_encode %{ 10450 __ tst_32($op1$$Register, AsmOperand($op2$$Register, lsl, $op3$$constant)); 10451 %} 10452 ins_pipe(ialu_cconly_reg_reg_zero); 10453 %} 10454 10455 #ifndef AARCH64 10456 instruct testsarI_reg_reg_reg( flagsReg_EQNELTGE icc, iRegI op1, iRegI op2, iRegI op3, immI0 zero ) %{ 10457 match(Set icc (CmpI (AndI op1 (RShiftI op2 op3)) zero)); 10458 size(4); 10459 format %{ "TST $op2,$op1<<$op3" %} 10460 10461 ins_encode %{ 10462 __ tst($op1$$Register, AsmOperand($op2$$Register, asr, $op3$$Register)); 10463 %} 10464 ins_pipe(ialu_cconly_reg_reg_zero); 10465 %} 10466 #endif 10467 10468 instruct testsarI_reg_reg_imm( flagsReg_EQNELTGE icc, iRegI op1, iRegI op2, immU5 op3, immI0 zero ) %{ 10469 match(Set icc (CmpI (AndI op1 (RShiftI op2 op3)) zero)); 10470 size(4); 10471 format %{ "tst_32 $op2,$op1<<$op3" %} 10472 10473 ins_encode %{ 10474 __ tst_32($op1$$Register, AsmOperand($op2$$Register, asr, $op3$$constant)); 10475 %} 10476 ins_pipe(ialu_cconly_reg_reg_zero); 10477 %} 10478 10479 #ifndef AARCH64 10480 instruct testshrI_reg_reg_reg( flagsReg_EQNELTGE icc, iRegI op1, iRegI op2, iRegI op3, immI0 zero ) %{ 10481 match(Set icc (CmpI (AndI op1 (URShiftI op2 op3)) zero)); 10482 size(4); 10483 format %{ "TST $op2,$op1<<$op3" %} 10484 10485 ins_encode %{ 10486 __ tst($op1$$Register, AsmOperand($op2$$Register, lsr, $op3$$Register)); 10487 %} 10488 ins_pipe(ialu_cconly_reg_reg_zero); 10489 %} 10490 #endif 10491 10492 instruct testshrI_reg_reg_imm( flagsReg_EQNELTGE icc, iRegI op1, iRegI op2, immU5 op3, immI0 zero ) %{ 10493 match(Set icc (CmpI (AndI op1 (URShiftI op2 op3)) zero)); 10494 size(4); 10495 format %{ "tst_32 $op2,$op1<<$op3" %} 10496 10497 ins_encode %{ 10498 __ tst_32($op1$$Register, AsmOperand($op2$$Register, lsr, $op3$$constant)); 10499 %} 10500 ins_pipe(ialu_cconly_reg_reg_zero); 10501 %} 10502 10503 instruct testI_reg_imm( flagsReg_EQNELTGE icc, iRegI op1, limmI op2, immI0 zero ) %{ 10504 match(Set icc (CmpI (AndI op1 op2) zero)); 10505 size(4); 10506 format %{ "tst_32 $op2,$op1" %} 10507 10508 ins_encode %{ 10509 __ tst_32($op1$$Register, $op2$$constant); 10510 %} 10511 ins_pipe(ialu_cconly_reg_imm_zero); 10512 %} 10513 10514 #ifdef AARCH64 10515 instruct compL_reg_reg(flagsReg xcc, iRegL op1, iRegL op2) 10516 %{ 10517 match(Set xcc (CmpL op1 op2)); 10518 effect( DEF xcc, USE op1, USE op2 ); 10519 10520 size(4); 10521 format %{ "CMP $op1,$op2\t! long" %} 10522 ins_encode %{ 10523 __ cmp($op1$$Register, $op2$$Register); 10524 %} 10525 ins_pipe(ialu_cconly_reg_reg); 10526 %} 10527 10528 instruct compUL_iReg(flagsRegU xcc, iRegL op1, iRegL op2) %{ 10529 match(Set xcc (CmpUL op1 op2)); 10530 10531 size(4); 10532 format %{ "CMP $op1,$op2\t! unsigned long" %} 10533 ins_encode %{ 10534 __ cmp($op1$$Register, $op2$$Register); 10535 %} 10536 ins_pipe(ialu_cconly_reg_reg); 10537 %} 10538 #else 10539 instruct compL_reg_reg_LTGE(flagsRegL_LTGE xcc, iRegL op1, iRegL op2, iRegL tmp) %{ 10540 match(Set xcc (CmpL op1 op2)); 10541 effect( DEF xcc, USE op1, USE op2, TEMP tmp ); 10542 10543 size(8); 10544 format %{ "SUBS $tmp,$op1.low,$op2.low\t\t! long\n\t" 10545 "SBCS $tmp,$op1.hi,$op2.hi" %} 10546 ins_encode %{ 10547 __ subs($tmp$$Register, $op1$$Register, $op2$$Register); 10548 __ sbcs($tmp$$Register->successor(), $op1$$Register->successor(), $op2$$Register->successor()); 10549 %} 10550 ins_pipe(ialu_cconly_reg_reg); 10551 %} 10552 10553 instruct compUL_reg_reg_LTGE(flagsRegUL_LTGE xcc, iRegL op1, iRegL op2, iRegL tmp) %{ 10554 match(Set xcc (CmpUL op1 op2)); 10555 effect(DEF xcc, USE op1, USE op2, TEMP tmp); 10556 10557 size(8); 10558 format %{ "SUBS $tmp,$op1.low,$op2.low\t\t! unsigned long\n\t" 10559 "SBCS $tmp,$op1.hi,$op2.hi" %} 10560 ins_encode %{ 10561 __ subs($tmp$$Register, $op1$$Register, $op2$$Register); 10562 __ sbcs($tmp$$Register->successor(), $op1$$Register->successor(), $op2$$Register->successor()); 10563 %} 10564 ins_pipe(ialu_cconly_reg_reg); 10565 %} 10566 #endif 10567 10568 #ifdef AARCH64 10569 instruct compL_reg_con(flagsReg xcc, iRegL op1, aimmL con) %{ 10570 match(Set xcc (CmpL op1 con)); 10571 effect( DEF xcc, USE op1, USE con ); 10572 10573 size(8); 10574 format %{ "CMP $op1,$con\t\t! long" %} 10575 ins_encode %{ 10576 __ cmp($op1$$Register, $con$$constant); 10577 %} 10578 10579 ins_pipe(ialu_cconly_reg_imm); 10580 %} 10581 10582 instruct compUL_reg_con(flagsRegU xcc, iRegL op1, aimmL con) %{ 10583 match(Set xcc (CmpUL op1 con)); 10584 effect(DEF xcc, USE op1, USE con); 10585 10586 size(8); 10587 format %{ "CMP $op1,$con\t\t! unsigned long" %} 10588 ins_encode %{ 10589 __ cmp($op1$$Register, $con$$constant); 10590 %} 10591 10592 ins_pipe(ialu_cconly_reg_imm); 10593 %} 10594 #else 10595 instruct compL_reg_reg_EQNE(flagsRegL_EQNE xcc, iRegL op1, iRegL op2) %{ 10596 match(Set xcc (CmpL op1 op2)); 10597 effect( DEF xcc, USE op1, USE op2 ); 10598 10599 size(8); 10600 format %{ "TEQ $op1.hi,$op2.hi\t\t! long\n\t" 10601 "TEQ.eq $op1.lo,$op2.lo" %} 10602 ins_encode %{ 10603 __ teq($op1$$Register->successor(), $op2$$Register->successor()); 10604 __ teq($op1$$Register, $op2$$Register, eq); 10605 %} 10606 ins_pipe(ialu_cconly_reg_reg); 10607 %} 10608 10609 instruct compL_reg_reg_LEGT(flagsRegL_LEGT xcc, iRegL op1, iRegL op2, iRegL tmp) %{ 10610 match(Set xcc (CmpL op1 op2)); 10611 effect( DEF xcc, USE op1, USE op2, TEMP tmp ); 10612 10613 size(8); 10614 format %{ "SUBS $tmp,$op2.low,$op1.low\t\t! long\n\t" 10615 "SBCS $tmp,$op2.hi,$op1.hi" %} 10616 ins_encode %{ 10617 __ subs($tmp$$Register, $op2$$Register, $op1$$Register); 10618 __ sbcs($tmp$$Register->successor(), $op2$$Register->successor(), $op1$$Register->successor()); 10619 %} 10620 ins_pipe(ialu_cconly_reg_reg); 10621 %} 10622 10623 // TODO: try immLRot2 instead, (0, $con$$constant) becomes 10624 // (hi($con$$constant), lo($con$$constant)) becomes 10625 instruct compL_reg_con_LTGE(flagsRegL_LTGE xcc, iRegL op1, immLlowRot con, iRegL tmp) %{ 10626 match(Set xcc (CmpL op1 con)); 10627 effect( DEF xcc, USE op1, USE con, TEMP tmp ); 10628 10629 size(8); 10630 format %{ "SUBS $tmp,$op1.low,$con\t\t! long\n\t" 10631 "SBCS $tmp,$op1.hi,0" %} 10632 ins_encode %{ 10633 __ subs($tmp$$Register, $op1$$Register, $con$$constant); 10634 __ sbcs($tmp$$Register->successor(), $op1$$Register->successor(), 0); 10635 %} 10636 10637 ins_pipe(ialu_cconly_reg_reg); 10638 %} 10639 10640 // TODO: try immLRot2 instead, (0, $con$$constant) becomes 10641 // (hi($con$$constant), lo($con$$constant)) becomes 10642 instruct compL_reg_con_EQNE(flagsRegL_EQNE xcc, iRegL op1, immLlowRot con) %{ 10643 match(Set xcc (CmpL op1 con)); 10644 effect( DEF xcc, USE op1, USE con ); 10645 10646 size(8); 10647 format %{ "TEQ $op1.hi,0\t\t! long\n\t" 10648 "TEQ.eq $op1.lo,$con" %} 10649 ins_encode %{ 10650 __ teq($op1$$Register->successor(), 0); 10651 __ teq($op1$$Register, $con$$constant, eq); 10652 %} 10653 10654 ins_pipe(ialu_cconly_reg_reg); 10655 %} 10656 10657 // TODO: try immLRot2 instead, (0, $con$$constant) becomes 10658 // (hi($con$$constant), lo($con$$constant)) becomes 10659 instruct compL_reg_con_LEGT(flagsRegL_LEGT xcc, iRegL op1, immLlowRot con, iRegL tmp) %{ 10660 match(Set xcc (CmpL op1 con)); 10661 effect( DEF xcc, USE op1, USE con, TEMP tmp ); 10662 10663 size(8); 10664 format %{ "RSBS $tmp,$op1.low,$con\t\t! long\n\t" 10665 "RSCS $tmp,$op1.hi,0" %} 10666 ins_encode %{ 10667 __ rsbs($tmp$$Register, $op1$$Register, $con$$constant); 10668 __ rscs($tmp$$Register->successor(), $op1$$Register->successor(), 0); 10669 %} 10670 10671 ins_pipe(ialu_cconly_reg_reg); 10672 %} 10673 10674 instruct compUL_reg_reg_EQNE(flagsRegUL_EQNE xcc, iRegL op1, iRegL op2) %{ 10675 match(Set xcc (CmpUL op1 op2)); 10676 effect(DEF xcc, USE op1, USE op2); 10677 10678 size(8); 10679 format %{ "TEQ $op1.hi,$op2.hi\t\t! unsigned long\n\t" 10680 "TEQ.eq $op1.lo,$op2.lo" %} 10681 ins_encode %{ 10682 __ teq($op1$$Register->successor(), $op2$$Register->successor()); 10683 __ teq($op1$$Register, $op2$$Register, eq); 10684 %} 10685 ins_pipe(ialu_cconly_reg_reg); 10686 %} 10687 10688 instruct compUL_reg_reg_LEGT(flagsRegUL_LEGT xcc, iRegL op1, iRegL op2, iRegL tmp) %{ 10689 match(Set xcc (CmpUL op1 op2)); 10690 effect(DEF xcc, USE op1, USE op2, TEMP tmp); 10691 10692 size(8); 10693 format %{ "SUBS $tmp,$op2.low,$op1.low\t\t! unsigned long\n\t" 10694 "SBCS $tmp,$op2.hi,$op1.hi" %} 10695 ins_encode %{ 10696 __ subs($tmp$$Register, $op2$$Register, $op1$$Register); 10697 __ sbcs($tmp$$Register->successor(), $op2$$Register->successor(), $op1$$Register->successor()); 10698 %} 10699 ins_pipe(ialu_cconly_reg_reg); 10700 %} 10701 10702 // TODO: try immLRot2 instead, (0, $con$$constant) becomes 10703 // (hi($con$$constant), lo($con$$constant)) becomes 10704 instruct compUL_reg_con_LTGE(flagsRegUL_LTGE xcc, iRegL op1, immLlowRot con, iRegL tmp) %{ 10705 match(Set xcc (CmpUL op1 con)); 10706 effect(DEF xcc, USE op1, USE con, TEMP tmp); 10707 10708 size(8); 10709 format %{ "SUBS $tmp,$op1.low,$con\t\t! unsigned long\n\t" 10710 "SBCS $tmp,$op1.hi,0" %} 10711 ins_encode %{ 10712 __ subs($tmp$$Register, $op1$$Register, $con$$constant); 10713 __ sbcs($tmp$$Register->successor(), $op1$$Register->successor(), 0); 10714 %} 10715 10716 ins_pipe(ialu_cconly_reg_reg); 10717 %} 10718 10719 // TODO: try immLRot2 instead, (0, $con$$constant) becomes 10720 // (hi($con$$constant), lo($con$$constant)) becomes 10721 instruct compUL_reg_con_EQNE(flagsRegUL_EQNE xcc, iRegL op1, immLlowRot con) %{ 10722 match(Set xcc (CmpUL op1 con)); 10723 effect(DEF xcc, USE op1, USE con); 10724 10725 size(8); 10726 format %{ "TEQ $op1.hi,0\t\t! unsigned long\n\t" 10727 "TEQ.eq $op1.lo,$con" %} 10728 ins_encode %{ 10729 __ teq($op1$$Register->successor(), 0); 10730 __ teq($op1$$Register, $con$$constant, eq); 10731 %} 10732 10733 ins_pipe(ialu_cconly_reg_reg); 10734 %} 10735 10736 // TODO: try immLRot2 instead, (0, $con$$constant) becomes 10737 // (hi($con$$constant), lo($con$$constant)) becomes 10738 instruct compUL_reg_con_LEGT(flagsRegUL_LEGT xcc, iRegL op1, immLlowRot con, iRegL tmp) %{ 10739 match(Set xcc (CmpUL op1 con)); 10740 effect(DEF xcc, USE op1, USE con, TEMP tmp); 10741 10742 size(8); 10743 format %{ "RSBS $tmp,$op1.low,$con\t\t! unsigned long\n\t" 10744 "RSCS $tmp,$op1.hi,0" %} 10745 ins_encode %{ 10746 __ rsbs($tmp$$Register, $op1$$Register, $con$$constant); 10747 __ rscs($tmp$$Register->successor(), $op1$$Register->successor(), 0); 10748 %} 10749 10750 ins_pipe(ialu_cconly_reg_reg); 10751 %} 10752 #endif 10753 10754 /* instruct testL_reg_reg(flagsRegL xcc, iRegL op1, iRegL op2, immL0 zero) %{ */ 10755 /* match(Set xcc (CmpL (AndL op1 op2) zero)); */ 10756 /* ins_encode %{ */ 10757 /* __ stop("testL_reg_reg unimplemented"); */ 10758 /* %} */ 10759 /* ins_pipe(ialu_cconly_reg_reg); */ 10760 /* %} */ 10761 10762 /* // useful for checking the alignment of a pointer: */ 10763 /* instruct testL_reg_con(flagsRegL xcc, iRegL op1, immLlowRot con, immL0 zero) %{ */ 10764 /* match(Set xcc (CmpL (AndL op1 con) zero)); */ 10765 /* ins_encode %{ */ 10766 /* __ stop("testL_reg_con unimplemented"); */ 10767 /* %} */ 10768 /* ins_pipe(ialu_cconly_reg_reg); */ 10769 /* %} */ 10770 10771 instruct compU_iReg_imm(flagsRegU icc, iRegI op1, aimmU31 op2 ) %{ 10772 match(Set icc (CmpU op1 op2)); 10773 10774 size(4); 10775 format %{ "cmp_32 $op1,$op2\t! unsigned" %} 10776 ins_encode %{ 10777 __ cmp_32($op1$$Register, $op2$$constant); 10778 %} 10779 ins_pipe(ialu_cconly_reg_imm); 10780 %} 10781 10782 // Compare Pointers 10783 instruct compP_iRegP(flagsRegP pcc, iRegP op1, iRegP op2 ) %{ 10784 match(Set pcc (CmpP op1 op2)); 10785 10786 size(4); 10787 format %{ "CMP $op1,$op2\t! ptr" %} 10788 ins_encode %{ 10789 __ cmp($op1$$Register, $op2$$Register); 10790 %} 10791 ins_pipe(ialu_cconly_reg_reg); 10792 %} 10793 10794 instruct compP_iRegP_imm(flagsRegP pcc, iRegP op1, aimmP op2 ) %{ 10795 match(Set pcc (CmpP op1 op2)); 10796 10797 size(4); 10798 format %{ "CMP $op1,$op2\t! ptr" %} 10799 ins_encode %{ 10800 assert($op2$$constant == 0 || _opnds[2]->constant_reloc() == relocInfo::none, "reloc in cmp?"); 10801 __ cmp($op1$$Register, $op2$$constant); 10802 %} 10803 ins_pipe(ialu_cconly_reg_imm); 10804 %} 10805 10806 //----------Max and Min-------------------------------------------------------- 10807 // Min Instructions 10808 // Conditional move for min 10809 instruct cmovI_reg_lt( iRegI op2, iRegI op1, flagsReg icc ) %{ 10810 effect( USE_DEF op2, USE op1, USE icc ); 10811 10812 size(4); 10813 format %{ "MOV.lt $op2,$op1\t! min" %} 10814 ins_encode %{ 10815 __ mov($op2$$Register, $op1$$Register, lt); 10816 %} 10817 ins_pipe(ialu_reg_flags); 10818 %} 10819 10820 // Min Register with Register. 10821 instruct minI_eReg(iRegI op1, iRegI op2) %{ 10822 match(Set op2 (MinI op1 op2)); 10823 ins_cost(DEFAULT_COST*2); 10824 expand %{ 10825 flagsReg icc; 10826 compI_iReg(icc,op1,op2); 10827 cmovI_reg_lt(op2,op1,icc); 10828 %} 10829 %} 10830 10831 // Max Instructions 10832 // Conditional move for max 10833 instruct cmovI_reg_gt( iRegI op2, iRegI op1, flagsReg icc ) %{ 10834 effect( USE_DEF op2, USE op1, USE icc ); 10835 format %{ "MOV.gt $op2,$op1\t! max" %} 10836 ins_encode %{ 10837 __ mov($op2$$Register, $op1$$Register, gt); 10838 %} 10839 ins_pipe(ialu_reg_flags); 10840 %} 10841 10842 // Max Register with Register 10843 instruct maxI_eReg(iRegI op1, iRegI op2) %{ 10844 match(Set op2 (MaxI op1 op2)); 10845 ins_cost(DEFAULT_COST*2); 10846 expand %{ 10847 flagsReg icc; 10848 compI_iReg(icc,op1,op2); 10849 cmovI_reg_gt(op2,op1,icc); 10850 %} 10851 %} 10852 10853 10854 //----------Float Compares---------------------------------------------------- 10855 // Compare floating, generate condition code 10856 instruct cmpF_cc(flagsRegF fcc, flagsReg icc, regF src1, regF src2) %{ 10857 match(Set icc (CmpF src1 src2)); 10858 effect(KILL fcc); 10859 10860 #ifdef AARCH64 10861 size(4); 10862 format %{ "FCMP_s $src1,$src2" %} 10863 ins_encode %{ 10864 __ fcmp_s($src1$$FloatRegister, $src2$$FloatRegister); 10865 %} 10866 #else 10867 size(8); 10868 format %{ "FCMPs $src1,$src2\n\t" 10869 "FMSTAT" %} 10870 ins_encode %{ 10871 __ fcmps($src1$$FloatRegister, $src2$$FloatRegister); 10872 __ fmstat(); 10873 %} 10874 #endif 10875 ins_pipe(faddF_fcc_reg_reg_zero); 10876 %} 10877 10878 instruct cmpF0_cc(flagsRegF fcc, flagsReg icc, regF src1, immF0 src2) %{ 10879 match(Set icc (CmpF src1 src2)); 10880 effect(KILL fcc); 10881 10882 #ifdef AARCH64 10883 size(4); 10884 format %{ "FCMP0_s $src1" %} 10885 ins_encode %{ 10886 __ fcmp0_s($src1$$FloatRegister); 10887 %} 10888 #else 10889 size(8); 10890 format %{ "FCMPs $src1,$src2\n\t" 10891 "FMSTAT" %} 10892 ins_encode %{ 10893 __ fcmpzs($src1$$FloatRegister); 10894 __ fmstat(); 10895 %} 10896 #endif 10897 ins_pipe(faddF_fcc_reg_reg_zero); 10898 %} 10899 10900 instruct cmpD_cc(flagsRegF fcc, flagsReg icc, regD src1, regD src2) %{ 10901 match(Set icc (CmpD src1 src2)); 10902 effect(KILL fcc); 10903 10904 #ifdef AARCH64 10905 size(4); 10906 format %{ "FCMP_d $src1,$src2" %} 10907 ins_encode %{ 10908 __ fcmp_d($src1$$FloatRegister, $src2$$FloatRegister); 10909 %} 10910 #else 10911 size(8); 10912 format %{ "FCMPd $src1,$src2 \n\t" 10913 "FMSTAT" %} 10914 ins_encode %{ 10915 __ fcmpd($src1$$FloatRegister, $src2$$FloatRegister); 10916 __ fmstat(); 10917 %} 10918 #endif 10919 ins_pipe(faddD_fcc_reg_reg_zero); 10920 %} 10921 10922 instruct cmpD0_cc(flagsRegF fcc, flagsReg icc, regD src1, immD0 src2) %{ 10923 match(Set icc (CmpD src1 src2)); 10924 effect(KILL fcc); 10925 10926 #ifdef AARCH64 10927 size(8); 10928 format %{ "FCMP0_d $src1" %} 10929 ins_encode %{ 10930 __ fcmp0_d($src1$$FloatRegister); 10931 %} 10932 #else 10933 size(8); 10934 format %{ "FCMPZd $src1,$src2 \n\t" 10935 "FMSTAT" %} 10936 ins_encode %{ 10937 __ fcmpzd($src1$$FloatRegister); 10938 __ fmstat(); 10939 %} 10940 #endif 10941 ins_pipe(faddD_fcc_reg_reg_zero); 10942 %} 10943 10944 #ifdef AARCH64 10945 // Compare floating, generate -1,0,1 10946 instruct cmpF_reg(iRegI dst, regF src1, regF src2, flagsReg icc) %{ 10947 match(Set dst (CmpF3 src1 src2)); 10948 // effect(KILL fcc); // nobody cares if flagsRegF is killed 10949 effect(KILL icc); 10950 ins_cost(DEFAULT_COST*3); // FIXME 10951 size(12); 10952 format %{ "FCMP_s $src1,$src2\n\t" 10953 "CSET $dst, gt\n\t" 10954 "CSINV $dst, $dst, ZR, ge" %} 10955 ins_encode %{ 10956 Register dst = $dst$$Register; 10957 __ fcmp_s($src1$$FloatRegister, $src2$$FloatRegister); 10958 __ cset(dst, gt); // 1 if '>', else 0 10959 __ csinv(dst, dst, ZR, ge); // previous value if '>=', else -1 10960 %} 10961 ins_pipe( floating_cmp ); // FIXME 10962 %} 10963 10964 // Compare floating, generate -1,0,1 10965 instruct cmpD_reg(iRegI dst, regD src1, regD src2, flagsReg icc) %{ 10966 match(Set dst (CmpD3 src1 src2)); 10967 // effect(KILL fcc); // nobody cares if flagsRegF is killed 10968 effect(KILL icc); 10969 ins_cost(DEFAULT_COST*3); // FIXME 10970 size(12); 10971 format %{ "FCMP_d $src1,$src2\n\t" 10972 "CSET $dst, gt\n\t" 10973 "CSINV $dst, $dst, ZR, ge" %} 10974 ins_encode %{ 10975 Register dst = $dst$$Register; 10976 __ fcmp_d($src1$$FloatRegister, $src2$$FloatRegister); 10977 __ cset(dst, gt); // 1 if '>', else 0 10978 __ csinv(dst, dst, ZR, ge); // previous value if '>=', else -1 10979 %} 10980 ins_pipe( floating_cmp ); // FIXME 10981 %} 10982 10983 // Compare floating, generate -1,0,1 10984 instruct cmpF0_reg(iRegI dst, regF src1, immF0 src2, flagsReg icc) %{ 10985 match(Set dst (CmpF3 src1 src2)); 10986 // effect(KILL fcc); // nobody cares if flagsRegF is killed 10987 effect(KILL icc); 10988 ins_cost(DEFAULT_COST*3); // FIXME 10989 size(12); 10990 format %{ "FCMP0_s $src1\n\t" 10991 "CSET $dst, gt\n\t" 10992 "CSINV $dst, $dst, ZR, ge" %} 10993 ins_encode %{ 10994 Register dst = $dst$$Register; 10995 __ fcmp0_s($src1$$FloatRegister); 10996 __ cset(dst, gt); // 1 if '>', else 0 10997 __ csinv(dst, dst, ZR, ge); // previous value if '>=', else -1 10998 %} 10999 ins_pipe( floating_cmp ); // FIXME 11000 %} 11001 11002 // Compare floating, generate -1,0,1 11003 instruct cmpD0_reg(iRegI dst, regD src1, immD0 src2, flagsReg icc) %{ 11004 match(Set dst (CmpD3 src1 src2)); 11005 // effect(KILL fcc); // nobody cares if flagsRegF is killed 11006 effect(KILL icc); 11007 ins_cost(DEFAULT_COST*3); // FIXME 11008 size(12); 11009 format %{ "FCMP0_d $src1\n\t" 11010 "CSET $dst, gt\n\t" 11011 "CSINV $dst, $dst, ZR, ge" %} 11012 ins_encode %{ 11013 Register dst = $dst$$Register; 11014 __ fcmp0_d($src1$$FloatRegister); 11015 __ cset(dst, gt); // 1 if '>', else 0 11016 __ csinv(dst, dst, ZR, ge); // previous value if '>=', else -1 11017 %} 11018 ins_pipe( floating_cmp ); // FIXME 11019 %} 11020 #else 11021 // Compare floating, generate -1,0,1 11022 instruct cmpF_reg(iRegI dst, regF src1, regF src2, flagsRegF fcc) %{ 11023 match(Set dst (CmpF3 src1 src2)); 11024 effect(KILL fcc); 11025 ins_cost(DEFAULT_COST*3+BRANCH_COST*3); // FIXME 11026 size(20); 11027 // same number of instructions as code using conditional moves but 11028 // doesn't kill integer condition register 11029 format %{ "FCMPs $dst,$src1,$src2 \n\t" 11030 "VMRS $dst, FPSCR \n\t" 11031 "OR $dst, $dst, 0x08000000 \n\t" 11032 "EOR $dst, $dst, $dst << 3 \n\t" 11033 "MOV $dst, $dst >> 30" %} 11034 ins_encode %{ 11035 __ fcmps($src1$$FloatRegister, $src2$$FloatRegister); 11036 __ floating_cmp($dst$$Register); 11037 %} 11038 ins_pipe( floating_cmp ); 11039 %} 11040 11041 instruct cmpF0_reg(iRegI dst, regF src1, immF0 src2, flagsRegF fcc) %{ 11042 match(Set dst (CmpF3 src1 src2)); 11043 effect(KILL fcc); 11044 ins_cost(DEFAULT_COST*3+BRANCH_COST*3); // FIXME 11045 size(20); 11046 // same number of instructions as code using conditional moves but 11047 // doesn't kill integer condition register 11048 format %{ "FCMPZs $dst,$src1,$src2 \n\t" 11049 "VMRS $dst, FPSCR \n\t" 11050 "OR $dst, $dst, 0x08000000 \n\t" 11051 "EOR $dst, $dst, $dst << 3 \n\t" 11052 "MOV $dst, $dst >> 30" %} 11053 ins_encode %{ 11054 __ fcmpzs($src1$$FloatRegister); 11055 __ floating_cmp($dst$$Register); 11056 %} 11057 ins_pipe( floating_cmp ); 11058 %} 11059 11060 instruct cmpD_reg(iRegI dst, regD src1, regD src2, flagsRegF fcc) %{ 11061 match(Set dst (CmpD3 src1 src2)); 11062 effect(KILL fcc); 11063 ins_cost(DEFAULT_COST*3+BRANCH_COST*3); // FIXME 11064 size(20); 11065 // same number of instructions as code using conditional moves but 11066 // doesn't kill integer condition register 11067 format %{ "FCMPd $dst,$src1,$src2 \n\t" 11068 "VMRS $dst, FPSCR \n\t" 11069 "OR $dst, $dst, 0x08000000 \n\t" 11070 "EOR $dst, $dst, $dst << 3 \n\t" 11071 "MOV $dst, $dst >> 30" %} 11072 ins_encode %{ 11073 __ fcmpd($src1$$FloatRegister, $src2$$FloatRegister); 11074 __ floating_cmp($dst$$Register); 11075 %} 11076 ins_pipe( floating_cmp ); 11077 %} 11078 11079 instruct cmpD0_reg(iRegI dst, regD src1, immD0 src2, flagsRegF fcc) %{ 11080 match(Set dst (CmpD3 src1 src2)); 11081 effect(KILL fcc); 11082 ins_cost(DEFAULT_COST*3+BRANCH_COST*3); // FIXME 11083 size(20); 11084 // same number of instructions as code using conditional moves but 11085 // doesn't kill integer condition register 11086 format %{ "FCMPZd $dst,$src1,$src2 \n\t" 11087 "VMRS $dst, FPSCR \n\t" 11088 "OR $dst, $dst, 0x08000000 \n\t" 11089 "EOR $dst, $dst, $dst << 3 \n\t" 11090 "MOV $dst, $dst >> 30" %} 11091 ins_encode %{ 11092 __ fcmpzd($src1$$FloatRegister); 11093 __ floating_cmp($dst$$Register); 11094 %} 11095 ins_pipe( floating_cmp ); 11096 %} 11097 #endif // !AARCH64 11098 11099 //----------Branches--------------------------------------------------------- 11100 // Jump 11101 // (compare 'operand indIndex' and 'instruct addP_reg_reg' above) 11102 // FIXME 11103 instruct jumpXtnd(iRegX switch_val, iRegP tmp) %{ 11104 match(Jump switch_val); 11105 effect(TEMP tmp); 11106 ins_cost(350); 11107 format %{ "ADD $tmp, $constanttablebase, $switch_val\n\t" 11108 "LDR $tmp,[$tmp + $constantoffset]\n\t" 11109 "BX $tmp" %} 11110 size(20); 11111 ins_encode %{ 11112 Register table_reg; 11113 Register label_reg = $tmp$$Register; 11114 if (constant_offset() == 0) { 11115 table_reg = $constanttablebase; 11116 __ ldr(label_reg, Address(table_reg, $switch_val$$Register)); 11117 } else { 11118 table_reg = $tmp$$Register; 11119 int offset = $constantoffset; 11120 if (is_memoryP(offset)) { 11121 __ add(table_reg, $constanttablebase, $switch_val$$Register); 11122 __ ldr(label_reg, Address(table_reg, offset)); 11123 } else { 11124 __ mov_slow(table_reg, $constantoffset); 11125 __ add(table_reg, $constanttablebase, table_reg); 11126 __ ldr(label_reg, Address(table_reg, $switch_val$$Register)); 11127 } 11128 } 11129 __ jump(label_reg); // ldr + b better than ldr to PC for branch predictor? 11130 // __ ldr(PC, Address($table$$Register, $switch_val$$Register)); 11131 %} 11132 ins_pipe(ialu_reg_reg); 11133 %} 11134 11135 // // Direct Branch. 11136 instruct branch(label labl) %{ 11137 match(Goto); 11138 effect(USE labl); 11139 11140 size(4); 11141 ins_cost(BRANCH_COST); 11142 format %{ "B $labl" %} 11143 ins_encode %{ 11144 __ b(*($labl$$label)); 11145 %} 11146 ins_pipe(br); 11147 %} 11148 11149 // Conditional Direct Branch 11150 instruct branchCon(cmpOp cmp, flagsReg icc, label labl) %{ 11151 match(If cmp icc); 11152 effect(USE labl); 11153 11154 size(4); 11155 ins_cost(BRANCH_COST); 11156 format %{ "B$cmp $icc,$labl" %} 11157 ins_encode %{ 11158 __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode)); 11159 %} 11160 ins_pipe(br_cc); 11161 %} 11162 11163 #ifdef ARM 11164 instruct branchCon_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, label labl) %{ 11165 match(If cmp icc); 11166 effect(USE labl); 11167 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); 11168 11169 size(4); 11170 ins_cost(BRANCH_COST); 11171 format %{ "B$cmp $icc,$labl" %} 11172 ins_encode %{ 11173 __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode)); 11174 %} 11175 ins_pipe(br_cc); 11176 %} 11177 #endif 11178 11179 #ifdef AARCH64 11180 instruct cbzI(cmpOp cmp, iRegI op1, immI0 op2, label labl) %{ 11181 match(If cmp (CmpI op1 op2)); 11182 effect(USE labl); 11183 predicate(_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || 11184 _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne); 11185 size(4); 11186 ins_cost(BRANCH_COST); 11187 format %{ "CB{N}Z $op1, $labl\t! int $cmp" %} 11188 ins_encode %{ 11189 if ($cmp$$cmpcode == eq) { 11190 __ cbz_w($op1$$Register, *($labl$$label)); 11191 } else { 11192 __ cbnz_w($op1$$Register, *($labl$$label)); 11193 } 11194 %} 11195 ins_pipe(br_cc); // FIXME 11196 %} 11197 11198 instruct cbzP(cmpOpP cmp, iRegP op1, immP0 op2, label labl) %{ 11199 match(If cmp (CmpP op1 op2)); 11200 effect(USE labl); 11201 predicate(_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || 11202 _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne); 11203 size(4); 11204 ins_cost(BRANCH_COST); 11205 format %{ "CB{N}Z $op1, $labl\t! ptr $cmp" %} 11206 ins_encode %{ 11207 if ($cmp$$cmpcode == eq) { 11208 __ cbz($op1$$Register, *($labl$$label)); 11209 } else { 11210 __ cbnz($op1$$Register, *($labl$$label)); 11211 } 11212 %} 11213 ins_pipe(br_cc); // FIXME 11214 %} 11215 11216 instruct cbzL(cmpOpL cmp, iRegL op1, immL0 op2, label labl) %{ 11217 match(If cmp (CmpL op1 op2)); 11218 effect(USE labl); 11219 predicate(_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || 11220 _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne); 11221 size(4); 11222 ins_cost(BRANCH_COST); 11223 format %{ "CB{N}Z $op1, $labl\t! long $cmp" %} 11224 ins_encode %{ 11225 if ($cmp$$cmpcode == eq) { 11226 __ cbz($op1$$Register, *($labl$$label)); 11227 } else { 11228 __ cbnz($op1$$Register, *($labl$$label)); 11229 } 11230 %} 11231 ins_pipe(br_cc); // FIXME 11232 %} 11233 #endif 11234 11235 instruct branchConU(cmpOpU cmp, flagsRegU icc, label labl) %{ 11236 match(If cmp icc); 11237 effect(USE labl); 11238 11239 size(4); 11240 ins_cost(BRANCH_COST); 11241 format %{ "B$cmp $icc,$labl" %} 11242 ins_encode %{ 11243 __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode)); 11244 %} 11245 ins_pipe(br_cc); 11246 %} 11247 11248 instruct branchConP(cmpOpP cmp, flagsRegP pcc, label labl) %{ 11249 match(If cmp pcc); 11250 effect(USE labl); 11251 11252 size(4); 11253 ins_cost(BRANCH_COST); 11254 format %{ "B$cmp $pcc,$labl" %} 11255 ins_encode %{ 11256 __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode)); 11257 %} 11258 ins_pipe(br_cc); 11259 %} 11260 11261 #ifndef AARCH64 11262 instruct branchConL_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, label labl) %{ 11263 match(If cmp xcc); 11264 effect(USE labl); 11265 predicate( _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge ); 11266 11267 size(4); 11268 ins_cost(BRANCH_COST); 11269 format %{ "B$cmp $xcc,$labl" %} 11270 ins_encode %{ 11271 __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode)); 11272 %} 11273 ins_pipe(br_cc); 11274 %} 11275 11276 instruct branchConL_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, label labl) %{ 11277 match(If cmp xcc); 11278 effect(USE labl); 11279 predicate( _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ); 11280 11281 size(4); 11282 ins_cost(BRANCH_COST); 11283 format %{ "B$cmp $xcc,$labl" %} 11284 ins_encode %{ 11285 __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode)); 11286 %} 11287 ins_pipe(br_cc); 11288 %} 11289 11290 instruct branchConL_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, label labl) %{ 11291 match(If cmp xcc); 11292 effect(USE labl); 11293 predicate( _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le ); 11294 11295 size(4); 11296 ins_cost(BRANCH_COST); 11297 format %{ "B$cmp $xcc,$labl" %} 11298 ins_encode %{ 11299 __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode)); 11300 %} 11301 ins_pipe(br_cc); 11302 %} 11303 11304 instruct branchConUL_LTGE(cmpOpUL cmp, flagsRegUL_LTGE xcc, label labl) %{ 11305 match(If cmp xcc); 11306 effect(USE labl); 11307 predicate(_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge); 11308 11309 size(4); 11310 ins_cost(BRANCH_COST); 11311 format %{ "B$cmp $xcc,$labl" %} 11312 ins_encode %{ 11313 __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode)); 11314 %} 11315 ins_pipe(br_cc); 11316 %} 11317 11318 instruct branchConUL_EQNE(cmpOpUL cmp, flagsRegUL_EQNE xcc, label labl) %{ 11319 match(If cmp xcc); 11320 effect(USE labl); 11321 predicate(_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne); 11322 11323 size(4); 11324 ins_cost(BRANCH_COST); 11325 format %{ "B$cmp $xcc,$labl" %} 11326 ins_encode %{ 11327 __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode)); 11328 %} 11329 ins_pipe(br_cc); 11330 %} 11331 11332 instruct branchConUL_LEGT(cmpOpUL_commute cmp, flagsRegUL_LEGT xcc, label labl) %{ 11333 match(If cmp xcc); 11334 effect(USE labl); 11335 predicate(_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le); 11336 11337 size(4); 11338 ins_cost(BRANCH_COST); 11339 format %{ "B$cmp $xcc,$labl" %} 11340 ins_encode %{ 11341 __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode)); 11342 %} 11343 ins_pipe(br_cc); 11344 %} 11345 #endif 11346 11347 instruct branchLoopEnd(cmpOp cmp, flagsReg icc, label labl) %{ 11348 match(CountedLoopEnd cmp icc); 11349 effect(USE labl); 11350 11351 size(4); 11352 ins_cost(BRANCH_COST); 11353 format %{ "B$cmp $icc,$labl\t! Loop end" %} 11354 ins_encode %{ 11355 __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode)); 11356 %} 11357 ins_pipe(br_cc); 11358 %} 11359 11360 // instruct branchLoopEndU(cmpOpU cmp, flagsRegU icc, label labl) %{ 11361 // match(CountedLoopEnd cmp icc); 11362 // ins_pipe(br_cc); 11363 // %} 11364 11365 // ============================================================================ 11366 // Long Compare 11367 // 11368 // Currently we hold longs in 2 registers. Comparing such values efficiently 11369 // is tricky. The flavor of compare used depends on whether we are testing 11370 // for LT, LE, or EQ. For a simple LT test we can check just the sign bit. 11371 // The GE test is the negated LT test. The LE test can be had by commuting 11372 // the operands (yielding a GE test) and then negating; negate again for the 11373 // GT test. The EQ test is done by ORcc'ing the high and low halves, and the 11374 // NE test is negated from that. 11375 11376 // Due to a shortcoming in the ADLC, it mixes up expressions like: 11377 // (foo (CmpI (CmpL X Y) 0)) and (bar (CmpI (CmpL X 0L) 0)). Note the 11378 // difference between 'Y' and '0L'. The tree-matches for the CmpI sections 11379 // are collapsed internally in the ADLC's dfa-gen code. The match for 11380 // (CmpI (CmpL X Y) 0) is silently replaced with (CmpI (CmpL X 0L) 0) and the 11381 // foo match ends up with the wrong leaf. One fix is to not match both 11382 // reg-reg and reg-zero forms of long-compare. This is unfortunate because 11383 // both forms beat the trinary form of long-compare and both are very useful 11384 // on Intel which has so few registers. 11385 11386 // instruct branchCon_long(cmpOp cmp, flagsRegL xcc, label labl) %{ 11387 // match(If cmp xcc); 11388 // ins_pipe(br_cc); 11389 // %} 11390 11391 // Manifest a CmpL3 result in an integer register. Very painful. 11392 // This is the test to avoid. 11393 #ifdef AARCH64 11394 instruct cmpL3_reg_reg(iRegI dst, iRegL src1, iRegL src2, flagsReg ccr) %{ 11395 match(Set dst (CmpL3 src1 src2)); 11396 // effect(KILL fcc); // nobody cares if flagsRegF is killed 11397 effect(KILL ccr); 11398 ins_cost(DEFAULT_COST*3); // FIXME 11399 size(12); 11400 format %{ "CMP $src1,$src2\n\t" 11401 "CSET $dst, gt\n\t" 11402 "CSINV $dst, $dst, ZR, ge" %} 11403 ins_encode %{ 11404 Register dst = $dst$$Register; 11405 __ cmp($src1$$Register, $src2$$Register); 11406 __ cset(dst, gt); // 1 if '>', else 0 11407 __ csinv(dst, dst, ZR, ge); // previous value if '>=', else -1 11408 %} 11409 ins_pipe( ialu_cconly_reg_reg ); // FIXME 11410 %} 11411 // TODO cmpL3_reg_imm 11412 #else 11413 instruct cmpL3_reg_reg(iRegI dst, iRegL src1, iRegL src2, flagsReg ccr ) %{ 11414 match(Set dst (CmpL3 src1 src2) ); 11415 effect( KILL ccr ); 11416 ins_cost(6*DEFAULT_COST); // FIXME 11417 size(32); 11418 format %{ 11419 "CMP $src1.hi, $src2.hi\t\t! long\n" 11420 "\tMOV.gt $dst, 1\n" 11421 "\tmvn.lt $dst, 0\n" 11422 "\tB.ne done\n" 11423 "\tSUBS $dst, $src1.lo, $src2.lo\n" 11424 "\tMOV.hi $dst, 1\n" 11425 "\tmvn.lo $dst, 0\n" 11426 "done:" %} 11427 ins_encode %{ 11428 Label done; 11429 __ cmp($src1$$Register->successor(), $src2$$Register->successor()); 11430 __ mov($dst$$Register, 1, gt); 11431 __ mvn($dst$$Register, 0, lt); 11432 __ b(done, ne); 11433 __ subs($dst$$Register, $src1$$Register, $src2$$Register); 11434 __ mov($dst$$Register, 1, hi); 11435 __ mvn($dst$$Register, 0, lo); 11436 __ bind(done); 11437 %} 11438 ins_pipe(cmpL_reg); 11439 %} 11440 #endif 11441 11442 #ifndef AARCH64 11443 // Conditional move 11444 instruct cmovLL_reg_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, iRegL dst, iRegL src) %{ 11445 match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src))); 11446 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge ); 11447 11448 ins_cost(150); 11449 size(8); 11450 format %{ "MOV$cmp $dst.lo,$src.lo\t! long\n\t" 11451 "MOV$cmp $dst,$src.hi" %} 11452 ins_encode %{ 11453 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 11454 __ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode)); 11455 %} 11456 ins_pipe(ialu_reg); 11457 %} 11458 11459 instruct cmovLL_reg_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, iRegL dst, iRegL src) %{ 11460 match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src))); 11461 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ); 11462 11463 ins_cost(150); 11464 size(8); 11465 format %{ "MOV$cmp $dst.lo,$src.lo\t! long\n\t" 11466 "MOV$cmp $dst,$src.hi" %} 11467 ins_encode %{ 11468 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 11469 __ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode)); 11470 %} 11471 ins_pipe(ialu_reg); 11472 %} 11473 11474 instruct cmovLL_reg_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, iRegL dst, iRegL src) %{ 11475 match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src))); 11476 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt ); 11477 11478 ins_cost(150); 11479 size(8); 11480 format %{ "MOV$cmp $dst.lo,$src.lo\t! long\n\t" 11481 "MOV$cmp $dst,$src.hi" %} 11482 ins_encode %{ 11483 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 11484 __ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode)); 11485 %} 11486 ins_pipe(ialu_reg); 11487 %} 11488 11489 instruct cmovLL_imm_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, iRegL dst, immL0 src) %{ 11490 match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src))); 11491 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge ); 11492 ins_cost(140); 11493 size(8); 11494 format %{ "MOV$cmp $dst.lo,0\t! long\n\t" 11495 "MOV$cmp $dst,0" %} 11496 ins_encode %{ 11497 __ mov($dst$$Register, 0, (AsmCondition)($cmp$$cmpcode)); 11498 __ mov($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode)); 11499 %} 11500 ins_pipe(ialu_imm); 11501 %} 11502 11503 instruct cmovLL_imm_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, iRegL dst, immL0 src) %{ 11504 match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src))); 11505 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ); 11506 ins_cost(140); 11507 size(8); 11508 format %{ "MOV$cmp $dst.lo,0\t! long\n\t" 11509 "MOV$cmp $dst,0" %} 11510 ins_encode %{ 11511 __ mov($dst$$Register, 0, (AsmCondition)($cmp$$cmpcode)); 11512 __ mov($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode)); 11513 %} 11514 ins_pipe(ialu_imm); 11515 %} 11516 11517 instruct cmovLL_imm_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, iRegL dst, immL0 src) %{ 11518 match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src))); 11519 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt ); 11520 ins_cost(140); 11521 size(8); 11522 format %{ "MOV$cmp $dst.lo,0\t! long\n\t" 11523 "MOV$cmp $dst,0" %} 11524 ins_encode %{ 11525 __ mov($dst$$Register, 0, (AsmCondition)($cmp$$cmpcode)); 11526 __ mov($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode)); 11527 %} 11528 ins_pipe(ialu_imm); 11529 %} 11530 #endif // !AARCH64 11531 11532 #ifndef AARCH64 11533 instruct cmovIL_reg_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, iRegI dst, iRegI src) %{ 11534 match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src))); 11535 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge ); 11536 11537 ins_cost(150); 11538 size(4); 11539 format %{ "MOV$cmp $dst,$src" %} 11540 ins_encode %{ 11541 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 11542 %} 11543 ins_pipe(ialu_reg); 11544 %} 11545 11546 instruct cmovIL_reg_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, iRegI dst, iRegI src) %{ 11547 match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src))); 11548 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ); 11549 11550 ins_cost(150); 11551 size(4); 11552 format %{ "MOV$cmp $dst,$src" %} 11553 ins_encode %{ 11554 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 11555 %} 11556 ins_pipe(ialu_reg); 11557 %} 11558 11559 instruct cmovIL_reg_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, iRegI dst, iRegI src) %{ 11560 match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src))); 11561 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt ); 11562 11563 ins_cost(150); 11564 size(4); 11565 format %{ "MOV$cmp $dst,$src" %} 11566 ins_encode %{ 11567 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 11568 %} 11569 ins_pipe(ialu_reg); 11570 %} 11571 #endif // !AARCH64 11572 11573 #ifndef AARCH64 11574 instruct cmovIL_imm_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, iRegI dst, immI16 src) %{ 11575 match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src))); 11576 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge ); 11577 11578 ins_cost(140); 11579 format %{ "MOVW$cmp $dst,$src" %} 11580 ins_encode %{ 11581 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 11582 %} 11583 ins_pipe(ialu_imm); 11584 %} 11585 11586 instruct cmovIL_imm_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, iRegI dst, immI16 src) %{ 11587 match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src))); 11588 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ); 11589 11590 ins_cost(140); 11591 format %{ "MOVW$cmp $dst,$src" %} 11592 ins_encode %{ 11593 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 11594 %} 11595 ins_pipe(ialu_imm); 11596 %} 11597 11598 instruct cmovIL_imm_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, iRegI dst, immI16 src) %{ 11599 match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src))); 11600 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt ); 11601 11602 ins_cost(140); 11603 format %{ "MOVW$cmp $dst,$src" %} 11604 ins_encode %{ 11605 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 11606 %} 11607 ins_pipe(ialu_imm); 11608 %} 11609 11610 instruct cmovPL_reg_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, iRegP dst, iRegP src) %{ 11611 match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src))); 11612 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge ); 11613 11614 ins_cost(150); 11615 size(4); 11616 format %{ "MOV$cmp $dst,$src" %} 11617 ins_encode %{ 11618 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 11619 %} 11620 ins_pipe(ialu_reg); 11621 %} 11622 11623 instruct cmovPL_reg_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, iRegP dst, iRegP src) %{ 11624 match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src))); 11625 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ); 11626 11627 ins_cost(150); 11628 size(4); 11629 format %{ "MOV$cmp $dst,$src" %} 11630 ins_encode %{ 11631 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 11632 %} 11633 ins_pipe(ialu_reg); 11634 %} 11635 11636 instruct cmovPL_reg_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, iRegP dst, iRegP src) %{ 11637 match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src))); 11638 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt ); 11639 11640 ins_cost(150); 11641 size(4); 11642 format %{ "MOV$cmp $dst,$src" %} 11643 ins_encode %{ 11644 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 11645 %} 11646 ins_pipe(ialu_reg); 11647 %} 11648 11649 instruct cmovPL_imm_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, iRegP dst, immP0 src) %{ 11650 match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src))); 11651 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge ); 11652 11653 ins_cost(140); 11654 format %{ "MOVW$cmp $dst,$src" %} 11655 ins_encode %{ 11656 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 11657 %} 11658 ins_pipe(ialu_imm); 11659 %} 11660 11661 instruct cmovPL_imm_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, iRegP dst, immP0 src) %{ 11662 match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src))); 11663 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ); 11664 11665 ins_cost(140); 11666 format %{ "MOVW$cmp $dst,$src" %} 11667 ins_encode %{ 11668 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 11669 %} 11670 ins_pipe(ialu_imm); 11671 %} 11672 11673 instruct cmovPL_imm_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, iRegP dst, immP0 src) %{ 11674 match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src))); 11675 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt ); 11676 11677 ins_cost(140); 11678 format %{ "MOVW$cmp $dst,$src" %} 11679 ins_encode %{ 11680 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 11681 %} 11682 ins_pipe(ialu_imm); 11683 %} 11684 11685 instruct cmovFL_reg_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, regF dst, regF src) %{ 11686 match(Set dst (CMoveF (Binary cmp xcc) (Binary dst src))); 11687 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge ); 11688 ins_cost(150); 11689 size(4); 11690 format %{ "FCPYS$cmp $dst,$src" %} 11691 ins_encode %{ 11692 __ fcpys($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode)); 11693 %} 11694 ins_pipe(int_conditional_float_move); 11695 %} 11696 11697 instruct cmovFL_reg_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, regF dst, regF src) %{ 11698 match(Set dst (CMoveF (Binary cmp xcc) (Binary dst src))); 11699 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ); 11700 ins_cost(150); 11701 size(4); 11702 format %{ "FCPYS$cmp $dst,$src" %} 11703 ins_encode %{ 11704 __ fcpys($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode)); 11705 %} 11706 ins_pipe(int_conditional_float_move); 11707 %} 11708 11709 instruct cmovFL_reg_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, regF dst, regF src) %{ 11710 match(Set dst (CMoveF (Binary cmp xcc) (Binary dst src))); 11711 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt ); 11712 ins_cost(150); 11713 size(4); 11714 format %{ "FCPYS$cmp $dst,$src" %} 11715 ins_encode %{ 11716 __ fcpys($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode)); 11717 %} 11718 ins_pipe(int_conditional_float_move); 11719 %} 11720 11721 instruct cmovDL_reg_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, regD dst, regD src) %{ 11722 match(Set dst (CMoveD (Binary cmp xcc) (Binary dst src))); 11723 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge ); 11724 11725 ins_cost(150); 11726 size(4); 11727 format %{ "FCPYD$cmp $dst,$src" %} 11728 ins_encode %{ 11729 __ fcpyd($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode)); 11730 %} 11731 ins_pipe(int_conditional_float_move); 11732 %} 11733 11734 instruct cmovDL_reg_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, regD dst, regD src) %{ 11735 match(Set dst (CMoveD (Binary cmp xcc) (Binary dst src))); 11736 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ); 11737 11738 ins_cost(150); 11739 size(4); 11740 format %{ "FCPYD$cmp $dst,$src" %} 11741 ins_encode %{ 11742 __ fcpyd($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode)); 11743 %} 11744 ins_pipe(int_conditional_float_move); 11745 %} 11746 11747 instruct cmovDL_reg_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, regD dst, regD src) %{ 11748 match(Set dst (CMoveD (Binary cmp xcc) (Binary dst src))); 11749 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt ); 11750 11751 ins_cost(150); 11752 size(4); 11753 format %{ "FCPYD$cmp $dst,$src" %} 11754 ins_encode %{ 11755 __ fcpyd($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode)); 11756 %} 11757 ins_pipe(int_conditional_float_move); 11758 %} 11759 #endif // !AARCH64 11760 11761 // ============================================================================ 11762 // Safepoint Instruction 11763 #ifdef AARCH64 11764 instruct safePoint_poll(iRegP poll, flagsReg icc, RtempRegP tmp) %{ 11765 match(SafePoint poll); 11766 // The handler stub kills Rtemp 11767 effect(USE poll, KILL tmp, KILL icc); 11768 11769 size(4); 11770 format %{ "LDR ZR,[$poll]\t! Safepoint: poll for GC" %} 11771 ins_encode %{ 11772 __ relocate(relocInfo::poll_type); 11773 __ ldr(ZR, Address($poll$$Register)); 11774 %} 11775 ins_pipe(loadPollP); 11776 %} 11777 #else 11778 // rather than KILL R12, it would be better to use any reg as 11779 // TEMP. Can't do that at this point because it crashes the compiler 11780 instruct safePoint_poll(iRegP poll, R12RegI tmp, flagsReg icc) %{ 11781 match(SafePoint poll); 11782 effect(USE poll, KILL tmp, KILL icc); 11783 11784 size(4); 11785 format %{ "LDR $tmp,[$poll]\t! Safepoint: poll for GC" %} 11786 ins_encode %{ 11787 __ relocate(relocInfo::poll_type); 11788 __ ldr($tmp$$Register, Address($poll$$Register)); 11789 %} 11790 ins_pipe(loadPollP); 11791 %} 11792 #endif 11793 11794 11795 // ============================================================================ 11796 // Call Instructions 11797 // Call Java Static Instruction 11798 instruct CallStaticJavaDirect( method meth ) %{ 11799 match(CallStaticJava); 11800 predicate(! ((CallStaticJavaNode*)n)->is_method_handle_invoke()); 11801 effect(USE meth); 11802 11803 ins_cost(CALL_COST); 11804 format %{ "CALL,static ==> " %} 11805 ins_encode( Java_Static_Call( meth ), call_epilog ); 11806 ins_pipe(simple_call); 11807 %} 11808 11809 // Call Java Static Instruction (method handle version) 11810 instruct CallStaticJavaHandle( method meth ) %{ 11811 match(CallStaticJava); 11812 predicate(((CallStaticJavaNode*)n)->is_method_handle_invoke()); 11813 effect(USE meth); 11814 // FP is saved by all callees (for interpreter stack correction). 11815 // We use it here for a similar purpose, in {preserve,restore}_FP. 11816 11817 ins_cost(CALL_COST); 11818 format %{ "CALL,static/MethodHandle ==> " %} 11819 ins_encode( preserve_SP, Java_Static_Call( meth ), restore_SP, call_epilog ); 11820 ins_pipe(simple_call); 11821 %} 11822 11823 // Call Java Dynamic Instruction 11824 instruct CallDynamicJavaDirect( method meth ) %{ 11825 match(CallDynamicJava); 11826 effect(USE meth); 11827 11828 ins_cost(CALL_COST); 11829 format %{ "MOV_OOP (empty),R_R8\n\t" 11830 "CALL,dynamic ; NOP ==> " %} 11831 ins_encode( Java_Dynamic_Call( meth ), call_epilog ); 11832 ins_pipe(call); 11833 %} 11834 11835 // Call Runtime Instruction 11836 instruct CallRuntimeDirect(method meth) %{ 11837 match(CallRuntime); 11838 effect(USE meth); 11839 ins_cost(CALL_COST); 11840 format %{ "CALL,runtime" %} 11841 #ifdef AARCH64 11842 ins_encode( save_last_PC, Java_To_Runtime( meth ), 11843 call_epilog ); 11844 #else 11845 ins_encode( Java_To_Runtime( meth ), 11846 call_epilog ); 11847 #endif 11848 ins_pipe(simple_call); 11849 %} 11850 11851 // Call runtime without safepoint - same as CallRuntime 11852 instruct CallLeafDirect(method meth) %{ 11853 match(CallLeaf); 11854 effect(USE meth); 11855 ins_cost(CALL_COST); 11856 format %{ "CALL,runtime leaf" %} 11857 // TODO: ned save_last_PC here? 11858 ins_encode( Java_To_Runtime( meth ), 11859 call_epilog ); 11860 ins_pipe(simple_call); 11861 %} 11862 11863 // Call runtime without safepoint - same as CallLeaf 11864 instruct CallLeafNoFPDirect(method meth) %{ 11865 match(CallLeafNoFP); 11866 effect(USE meth); 11867 ins_cost(CALL_COST); 11868 format %{ "CALL,runtime leaf nofp" %} 11869 // TODO: ned save_last_PC here? 11870 ins_encode( Java_To_Runtime( meth ), 11871 call_epilog ); 11872 ins_pipe(simple_call); 11873 %} 11874 11875 // Tail Call; Jump from runtime stub to Java code. 11876 // Also known as an 'interprocedural jump'. 11877 // Target of jump will eventually return to caller. 11878 // TailJump below removes the return address. 11879 instruct TailCalljmpInd(IPRegP jump_target, inline_cache_regP method_oop) %{ 11880 match(TailCall jump_target method_oop ); 11881 11882 ins_cost(CALL_COST); 11883 format %{ "MOV Rexception_pc, LR\n\t" 11884 "jump $jump_target \t! $method_oop holds method oop" %} 11885 ins_encode %{ 11886 __ mov(Rexception_pc, LR); // this is used only to call 11887 // StubRoutines::forward_exception_entry() 11888 // which expects PC of exception in 11889 // R5. FIXME? 11890 __ jump($jump_target$$Register); 11891 %} 11892 ins_pipe(tail_call); 11893 %} 11894 11895 11896 // Return Instruction 11897 instruct Ret() %{ 11898 match(Return); 11899 11900 format %{ "ret LR" %} 11901 11902 ins_encode %{ 11903 __ ret(LR); 11904 %} 11905 11906 ins_pipe(br); 11907 %} 11908 11909 11910 // Tail Jump; remove the return address; jump to target. 11911 // TailCall above leaves the return address around. 11912 // TailJump is used in only one place, the rethrow_Java stub (fancy_jump=2). 11913 // ex_oop (Exception Oop) is needed in %o0 at the jump. As there would be a 11914 // "restore" before this instruction (in Epilogue), we need to materialize it 11915 // in %i0. 11916 instruct tailjmpInd(IPRegP jump_target, RExceptionRegP ex_oop) %{ 11917 match( TailJump jump_target ex_oop ); 11918 ins_cost(CALL_COST); 11919 format %{ "MOV Rexception_pc, LR\n\t" 11920 "jump $jump_target \t! $ex_oop holds exc. oop" %} 11921 ins_encode %{ 11922 __ mov(Rexception_pc, LR); 11923 __ jump($jump_target$$Register); 11924 %} 11925 ins_pipe(tail_call); 11926 %} 11927 11928 // Create exception oop: created by stack-crawling runtime code. 11929 // Created exception is now available to this handler, and is setup 11930 // just prior to jumping to this handler. No code emitted. 11931 instruct CreateException( RExceptionRegP ex_oop ) 11932 %{ 11933 match(Set ex_oop (CreateEx)); 11934 ins_cost(0); 11935 11936 size(0); 11937 // use the following format syntax 11938 format %{ "! exception oop is in Rexception_obj; no code emitted" %} 11939 ins_encode(); 11940 ins_pipe(empty); 11941 %} 11942 11943 11944 // Rethrow exception: 11945 // The exception oop will come in the first argument position. 11946 // Then JUMP (not call) to the rethrow stub code. 11947 instruct RethrowException() 11948 %{ 11949 match(Rethrow); 11950 ins_cost(CALL_COST); 11951 11952 // use the following format syntax 11953 format %{ "b rethrow_stub" %} 11954 ins_encode %{ 11955 Register scratch = R1_tmp; 11956 assert_different_registers(scratch, c_rarg0, LR); 11957 __ jump(OptoRuntime::rethrow_stub(), relocInfo::runtime_call_type, scratch); 11958 %} 11959 ins_pipe(tail_call); 11960 %} 11961 11962 11963 // Die now 11964 instruct ShouldNotReachHere( ) 11965 %{ 11966 match(Halt); 11967 ins_cost(CALL_COST); 11968 11969 size(4); 11970 // Use the following format syntax 11971 format %{ "ShouldNotReachHere" %} 11972 ins_encode %{ 11973 #ifdef AARCH64 11974 __ dpcs1(0xdead); 11975 #else 11976 __ udf(0xdead); 11977 #endif 11978 %} 11979 ins_pipe(tail_call); 11980 %} 11981 11982 // ============================================================================ 11983 // The 2nd slow-half of a subtype check. Scan the subklass's 2ndary superklass 11984 // array for an instance of the superklass. Set a hidden internal cache on a 11985 // hit (cache is checked with exposed code in gen_subtype_check()). Return 11986 // not zero for a miss or zero for a hit. The encoding ALSO sets flags. 11987 instruct partialSubtypeCheck( R0RegP index, R1RegP sub, R2RegP super, flagsRegP pcc, LRRegP lr ) %{ 11988 match(Set index (PartialSubtypeCheck sub super)); 11989 effect( KILL pcc, KILL lr ); 11990 ins_cost(DEFAULT_COST*10); 11991 format %{ "CALL PartialSubtypeCheck" %} 11992 ins_encode %{ 11993 __ call(StubRoutines::Arm::partial_subtype_check(), relocInfo::runtime_call_type); 11994 %} 11995 ins_pipe(partial_subtype_check_pipe); 11996 %} 11997 11998 /* instruct partialSubtypeCheck_vs_zero( flagsRegP pcc, o1RegP sub, o2RegP super, immP0 zero, o0RegP idx, o7RegP o7 ) %{ */ 11999 /* match(Set pcc (CmpP (PartialSubtypeCheck sub super) zero)); */ 12000 /* ins_pipe(partial_subtype_check_pipe); */ 12001 /* %} */ 12002 12003 12004 // ============================================================================ 12005 // inlined locking and unlocking 12006 12007 #ifdef AARCH64 12008 instruct cmpFastLock(flagsRegP pcc, iRegP object, iRegP box, iRegP scratch2, iRegP scratch, iRegP scratch3 ) 12009 #else 12010 instruct cmpFastLock(flagsRegP pcc, iRegP object, iRegP box, iRegP scratch2, iRegP scratch ) 12011 #endif 12012 %{ 12013 match(Set pcc (FastLock object box)); 12014 12015 #ifdef AARCH64 12016 effect(TEMP scratch, TEMP scratch2, TEMP scratch3); 12017 #else 12018 effect(TEMP scratch, TEMP scratch2); 12019 #endif 12020 ins_cost(100); 12021 12022 #ifdef AARCH64 12023 format %{ "FASTLOCK $object, $box; KILL $scratch, $scratch2, $scratch3" %} 12024 ins_encode %{ 12025 __ fast_lock($object$$Register, $box$$Register, $scratch$$Register, $scratch2$$Register, $scratch3$$Register); 12026 %} 12027 #else 12028 format %{ "FASTLOCK $object, $box; KILL $scratch, $scratch2" %} 12029 ins_encode %{ 12030 __ fast_lock($object$$Register, $box$$Register, $scratch$$Register, $scratch2$$Register); 12031 %} 12032 #endif 12033 ins_pipe(long_memory_op); 12034 %} 12035 12036 12037 #ifdef AARCH64 12038 instruct cmpFastUnlock(flagsRegP pcc, iRegP object, iRegP box, iRegP scratch2, iRegP scratch, iRegP scratch3 ) %{ 12039 match(Set pcc (FastUnlock object box)); 12040 effect(TEMP scratch, TEMP scratch2, TEMP scratch3); 12041 ins_cost(100); 12042 12043 format %{ "FASTUNLOCK $object, $box; KILL $scratch, $scratch2, $scratch3" %} 12044 ins_encode %{ 12045 __ fast_unlock($object$$Register, $box$$Register, $scratch$$Register, $scratch2$$Register, $scratch3$$Register); 12046 %} 12047 ins_pipe(long_memory_op); 12048 %} 12049 #else 12050 instruct cmpFastUnlock(flagsRegP pcc, iRegP object, iRegP box, iRegP scratch2, iRegP scratch ) %{ 12051 match(Set pcc (FastUnlock object box)); 12052 effect(TEMP scratch, TEMP scratch2); 12053 ins_cost(100); 12054 12055 format %{ "FASTUNLOCK $object, $box; KILL $scratch, $scratch2" %} 12056 ins_encode %{ 12057 __ fast_unlock($object$$Register, $box$$Register, $scratch$$Register, $scratch2$$Register); 12058 %} 12059 ins_pipe(long_memory_op); 12060 %} 12061 #endif 12062 12063 #ifdef AARCH64 12064 // TODO: add version that takes immI cnt? 12065 instruct clear_array(iRegX cnt, iRegP base, iRegP ptr, iRegX temp, Universe dummy, flagsReg cpsr) %{ 12066 match(Set dummy (ClearArray cnt base)); 12067 effect(TEMP temp, TEMP ptr, KILL cpsr); 12068 ins_cost(300); 12069 format %{ 12070 " MOV $temp,$cnt\n" 12071 " ADD $ptr,$base,$cnt\n" 12072 " SUBS $temp,$temp,16\t! Count down dword pair in bytes\n" 12073 " B.lt done16\n" 12074 "loop: STP ZR,ZR,[$ptr,-16]!\n" 12075 " SUBS $temp,$temp,16\t! Count down dword pair in bytes\n" 12076 " B.ge loop\t! Clearing loop\n" 12077 "done16: ADDS $temp,$temp,8\t! Room for 1 more long?\n" 12078 " B.lt done\n" 12079 " STR ZR,[$base+$temp]\n" 12080 "done:" 12081 %} 12082 ins_encode %{ 12083 // TODO: preload? 12084 __ mov($temp$$Register, $cnt$$Register); 12085 __ add($ptr$$Register, $base$$Register, $cnt$$Register); 12086 Label loop, done, done16; 12087 __ subs($temp$$Register, $temp$$Register, 16); 12088 __ b(done16, lt); 12089 __ bind(loop); 12090 __ stp(ZR, ZR, Address($ptr$$Register, -16, pre_indexed)); 12091 __ subs($temp$$Register, $temp$$Register, 16); 12092 __ b(loop, ge); 12093 __ bind(done16); 12094 __ adds($temp$$Register, $temp$$Register, 8); 12095 __ b(done, lt); 12096 // $temp should be 0 here 12097 __ str(ZR, Address($base$$Register, $temp$$Register)); 12098 __ bind(done); 12099 %} 12100 ins_pipe(long_memory_op); 12101 %} 12102 #else 12103 // Count and Base registers are fixed because the allocator cannot 12104 // kill unknown registers. The encodings are generic. 12105 instruct clear_array(iRegX cnt, iRegP base, iRegI temp, iRegX zero, Universe dummy, flagsReg cpsr) %{ 12106 match(Set dummy (ClearArray cnt base)); 12107 effect(TEMP temp, TEMP zero, KILL cpsr); 12108 ins_cost(300); 12109 format %{ "MOV $zero,0\n" 12110 " MOV $temp,$cnt\n" 12111 "loop: SUBS $temp,$temp,4\t! Count down a dword of bytes\n" 12112 " STR.ge $zero,[$base+$temp]\t! delay slot" 12113 " B.gt loop\t\t! Clearing loop\n" %} 12114 ins_encode %{ 12115 __ mov($zero$$Register, 0); 12116 __ mov($temp$$Register, $cnt$$Register); 12117 Label(loop); 12118 __ bind(loop); 12119 __ subs($temp$$Register, $temp$$Register, 4); 12120 __ str($zero$$Register, Address($base$$Register, $temp$$Register), ge); 12121 __ b(loop, gt); 12122 %} 12123 ins_pipe(long_memory_op); 12124 %} 12125 #endif 12126 12127 #ifdef XXX 12128 // FIXME: Why R0/R1/R2/R3? 12129 instruct string_compare(R0RegP str1, R1RegP str2, R2RegI cnt1, R3RegI cnt2, iRegI result, 12130 iRegI tmp1, iRegI tmp2, flagsReg ccr) %{ 12131 predicate(!CompactStrings); 12132 match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2))); 12133 effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL ccr, TEMP tmp1, TEMP tmp2); 12134 ins_cost(300); 12135 format %{ "String Compare $str1,$cnt1,$str2,$cnt2 -> $result // TEMP $tmp1, $tmp2" %} 12136 ins_encode( enc_String_Compare(str1, str2, cnt1, cnt2, result, tmp1, tmp2) ); 12137 12138 ins_pipe(long_memory_op); 12139 %} 12140 12141 // FIXME: Why R0/R1/R2? 12142 instruct string_equals(R0RegP str1, R1RegP str2, R2RegI cnt, iRegI result, iRegI tmp1, iRegI tmp2, 12143 flagsReg ccr) %{ 12144 predicate(!CompactStrings); 12145 match(Set result (StrEquals (Binary str1 str2) cnt)); 12146 effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt, TEMP tmp1, TEMP tmp2, TEMP result, KILL ccr); 12147 12148 ins_cost(300); 12149 format %{ "String Equals $str1,$str2,$cnt -> $result // TEMP $tmp1, $tmp2" %} 12150 ins_encode( enc_String_Equals(str1, str2, cnt, result, tmp1, tmp2) ); 12151 ins_pipe(long_memory_op); 12152 %} 12153 12154 // FIXME: Why R0/R1? 12155 instruct array_equals(R0RegP ary1, R1RegP ary2, iRegI tmp1, iRegI tmp2, iRegI tmp3, iRegI result, 12156 flagsReg ccr) %{ 12157 predicate(((AryEqNode*)n)->encoding() == StrIntrinsicNode::UU); 12158 match(Set result (AryEq ary1 ary2)); 12159 effect(USE_KILL ary1, USE_KILL ary2, TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP result, KILL ccr); 12160 12161 ins_cost(300); 12162 format %{ "Array Equals $ary1,$ary2 -> $result // TEMP $tmp1,$tmp2,$tmp3" %} 12163 ins_encode( enc_Array_Equals(ary1, ary2, tmp1, tmp2, tmp3, result)); 12164 ins_pipe(long_memory_op); 12165 %} 12166 #endif 12167 12168 //---------- Zeros Count Instructions ------------------------------------------ 12169 12170 instruct countLeadingZerosI(iRegI dst, iRegI src) %{ 12171 match(Set dst (CountLeadingZerosI src)); 12172 size(4); 12173 format %{ "CLZ_32 $dst,$src" %} 12174 ins_encode %{ 12175 __ clz_32($dst$$Register, $src$$Register); 12176 %} 12177 ins_pipe(ialu_reg); 12178 %} 12179 12180 #ifdef AARCH64 12181 instruct countLeadingZerosL(iRegI dst, iRegL src) %{ 12182 match(Set dst (CountLeadingZerosL src)); 12183 size(4); 12184 format %{ "CLZ $dst,$src" %} 12185 ins_encode %{ 12186 __ clz($dst$$Register, $src$$Register); 12187 %} 12188 ins_pipe(ialu_reg); 12189 %} 12190 #else 12191 instruct countLeadingZerosL(iRegI dst, iRegL src, iRegI tmp, flagsReg ccr) %{ 12192 match(Set dst (CountLeadingZerosL src)); 12193 effect(TEMP tmp, TEMP dst, KILL ccr); 12194 size(16); 12195 format %{ "CLZ $dst,$src.hi\n\t" 12196 "TEQ $dst,32\n\t" 12197 "CLZ.eq $tmp,$src.lo\n\t" 12198 "ADD.eq $dst, $dst, $tmp\n\t" %} 12199 ins_encode %{ 12200 __ clz($dst$$Register, $src$$Register->successor()); 12201 __ teq($dst$$Register, 32); 12202 __ clz($tmp$$Register, $src$$Register, eq); 12203 __ add($dst$$Register, $dst$$Register, $tmp$$Register, eq); 12204 %} 12205 ins_pipe(ialu_reg); 12206 %} 12207 #endif 12208 12209 instruct countTrailingZerosI(iRegI dst, iRegI src, iRegI tmp) %{ 12210 match(Set dst (CountTrailingZerosI src)); 12211 effect(TEMP tmp); 12212 size(8); 12213 format %{ "RBIT_32 $tmp, $src\n\t" 12214 "CLZ_32 $dst,$tmp" %} 12215 ins_encode %{ 12216 __ rbit_32($tmp$$Register, $src$$Register); 12217 __ clz_32($dst$$Register, $tmp$$Register); 12218 %} 12219 ins_pipe(ialu_reg); 12220 %} 12221 12222 #ifdef AARCH64 12223 instruct countTrailingZerosL(iRegI dst, iRegL src, iRegL tmp) %{ 12224 match(Set dst (CountTrailingZerosL src)); 12225 effect(TEMP tmp); 12226 size(8); 12227 format %{ "RBIT $tmp, $src\n\t" 12228 "CLZ $dst,$tmp" %} 12229 ins_encode %{ 12230 __ rbit($tmp$$Register, $src$$Register); 12231 __ clz($dst$$Register, $tmp$$Register); 12232 %} 12233 ins_pipe(ialu_reg); 12234 %} 12235 #else 12236 instruct countTrailingZerosL(iRegI dst, iRegL src, iRegI tmp, flagsReg ccr) %{ 12237 match(Set dst (CountTrailingZerosL src)); 12238 effect(TEMP tmp, TEMP dst, KILL ccr); 12239 size(24); 12240 format %{ "RBIT $tmp,$src.lo\n\t" 12241 "CLZ $dst,$tmp\n\t" 12242 "TEQ $dst,32\n\t" 12243 "RBIT $tmp,$src.hi\n\t" 12244 "CLZ.eq $tmp,$tmp\n\t" 12245 "ADD.eq $dst,$dst,$tmp\n\t" %} 12246 ins_encode %{ 12247 __ rbit($tmp$$Register, $src$$Register); 12248 __ clz($dst$$Register, $tmp$$Register); 12249 __ teq($dst$$Register, 32); 12250 __ rbit($tmp$$Register, $src$$Register->successor()); 12251 __ clz($tmp$$Register, $tmp$$Register, eq); 12252 __ add($dst$$Register, $dst$$Register, $tmp$$Register, eq); 12253 %} 12254 ins_pipe(ialu_reg); 12255 %} 12256 #endif 12257 12258 12259 //---------- Population Count Instructions ------------------------------------- 12260 12261 #ifdef AARCH64 12262 instruct popCountI(iRegI dst, iRegI src, regD_low tmp) %{ 12263 predicate(UsePopCountInstruction); 12264 match(Set dst (PopCountI src)); 12265 effect(TEMP tmp); 12266 size(20); 12267 12268 format %{ "MOV_W $dst,$src\n\t" 12269 "FMOV_dx $tmp,$dst\n\t" 12270 "VCNT $tmp.8B,$tmp.8B\n\t" 12271 "ADDV $tmp.B,$tmp.8B\n\t" 12272 "FMRS $dst,$tmp" %} 12273 12274 ins_encode %{ 12275 __ mov_w($dst$$Register, $src$$Register); 12276 __ fmov_dx($tmp$$FloatRegister, $dst$$Register); 12277 int quad = 0; 12278 int cnt_size = 0; // VELEM_SIZE_8 12279 __ vcnt($tmp$$FloatRegister, $tmp$$FloatRegister, quad, cnt_size); 12280 int add_size = 0; // VELEM_SIZE_8 12281 __ addv($tmp$$FloatRegister, $tmp$$FloatRegister, quad, add_size); 12282 __ fmrs($dst$$Register, $tmp$$FloatRegister); 12283 %} 12284 ins_pipe(ialu_reg); // FIXME 12285 %} 12286 #else 12287 instruct popCountI(iRegI dst, iRegI src, regD_low tmp) %{ 12288 predicate(UsePopCountInstruction); 12289 match(Set dst (PopCountI src)); 12290 effect(TEMP tmp); 12291 12292 format %{ "FMSR $tmp,$src\n\t" 12293 "VCNT.8 $tmp,$tmp\n\t" 12294 "VPADDL.U8 $tmp,$tmp\n\t" 12295 "VPADDL.U16 $tmp,$tmp\n\t" 12296 "FMRS $dst,$tmp" %} 12297 size(20); 12298 12299 ins_encode %{ 12300 __ fmsr($tmp$$FloatRegister, $src$$Register); 12301 __ vcnt($tmp$$FloatRegister, $tmp$$FloatRegister); 12302 __ vpaddl($tmp$$FloatRegister, $tmp$$FloatRegister, 8, 0); 12303 __ vpaddl($tmp$$FloatRegister, $tmp$$FloatRegister, 16, 0); 12304 __ fmrs($dst$$Register, $tmp$$FloatRegister); 12305 %} 12306 ins_pipe(ialu_reg); // FIXME 12307 %} 12308 #endif 12309 12310 #ifdef AARCH64 12311 instruct popCountL(iRegI dst, iRegL src, regD tmp) %{ 12312 predicate(UsePopCountInstruction); 12313 match(Set dst (PopCountL src)); 12314 effect(TEMP tmp); 12315 size(16); 12316 12317 format %{ "FMOV_dx $tmp,$src\n\t" 12318 "VCNT $tmp.8B,$tmp.8B\n\t" 12319 "ADDV $tmp.B,$tmp.8B\n\t" 12320 "FMOV_ws $dst,$tmp" %} 12321 12322 ins_encode %{ 12323 __ fmov_dx($tmp$$FloatRegister, $src$$Register); 12324 int quad = 0; 12325 int cnt_size = 0; 12326 __ vcnt($tmp$$FloatRegister, $tmp$$FloatRegister, quad, cnt_size); 12327 int add_size = 0; 12328 __ addv($tmp$$FloatRegister, $tmp$$FloatRegister, quad, add_size); 12329 __ fmov_ws($dst$$Register, $tmp$$FloatRegister); 12330 %} 12331 ins_pipe(ialu_reg); // FIXME 12332 %} 12333 #else 12334 // Note: Long.bitCount(long) returns an int. 12335 instruct popCountL(iRegI dst, iRegL src, regD_low tmp) %{ 12336 predicate(UsePopCountInstruction); 12337 match(Set dst (PopCountL src)); 12338 effect(TEMP tmp); 12339 12340 format %{ "FMDRR $tmp,$src.lo,$src.hi\n\t" 12341 "VCNT.8 $tmp,$tmp\n\t" 12342 "VPADDL.U8 $tmp,$tmp\n\t" 12343 "VPADDL.U16 $tmp,$tmp\n\t" 12344 "VPADDL.U32 $tmp,$tmp\n\t" 12345 "FMRS $dst,$tmp" %} 12346 12347 size(32); 12348 12349 ins_encode %{ 12350 __ fmdrr($tmp$$FloatRegister, $src$$Register, $src$$Register->successor()); 12351 __ vcnt($tmp$$FloatRegister, $tmp$$FloatRegister); 12352 __ vpaddl($tmp$$FloatRegister, $tmp$$FloatRegister, 8, 0); 12353 __ vpaddl($tmp$$FloatRegister, $tmp$$FloatRegister, 16, 0); 12354 __ vpaddl($tmp$$FloatRegister, $tmp$$FloatRegister, 32, 0); 12355 __ fmrs($dst$$Register, $tmp$$FloatRegister); 12356 %} 12357 ins_pipe(ialu_reg); 12358 %} 12359 #endif 12360 12361 12362 // ============================================================================ 12363 //------------Bytes reverse-------------------------------------------------- 12364 12365 instruct bytes_reverse_int(iRegI dst, iRegI src) %{ 12366 match(Set dst (ReverseBytesI src)); 12367 12368 size(4); 12369 format %{ "REV32 $dst,$src" %} 12370 ins_encode %{ 12371 #ifdef AARCH64 12372 __ rev_w($dst$$Register, $src$$Register); 12373 // high 32 bits zeroed, not sign extended 12374 #else 12375 __ rev($dst$$Register, $src$$Register); 12376 #endif 12377 %} 12378 ins_pipe( iload_mem ); // FIXME 12379 %} 12380 12381 instruct bytes_reverse_long(iRegL dst, iRegL src) %{ 12382 match(Set dst (ReverseBytesL src)); 12383 #ifdef AARCH64 12384 //size(4); 12385 format %{ "REV $dst,$src" %} 12386 ins_encode %{ 12387 __ rev($dst$$Register, $src$$Register); 12388 %} 12389 ins_pipe(ialu_reg_reg); // FIXME 12390 #else 12391 effect(TEMP dst); 12392 size(8); 12393 format %{ "REV $dst.lo,$src.lo\n\t" 12394 "REV $dst.hi,$src.hi" %} 12395 ins_encode %{ 12396 __ rev($dst$$Register, $src$$Register->successor()); 12397 __ rev($dst$$Register->successor(), $src$$Register); 12398 %} 12399 ins_pipe( iload_mem ); // FIXME 12400 #endif 12401 %} 12402 12403 instruct bytes_reverse_unsigned_short(iRegI dst, iRegI src) %{ 12404 match(Set dst (ReverseBytesUS src)); 12405 #ifdef AARCH64 12406 size(4); 12407 format %{ "REV16_W $dst,$src" %} 12408 ins_encode %{ 12409 __ rev16_w($dst$$Register, $src$$Register); 12410 // high 32 bits zeroed 12411 %} 12412 #else 12413 size(4); 12414 format %{ "REV16 $dst,$src" %} 12415 ins_encode %{ 12416 __ rev16($dst$$Register, $src$$Register); 12417 %} 12418 #endif 12419 ins_pipe( iload_mem ); // FIXME 12420 %} 12421 12422 instruct bytes_reverse_short(iRegI dst, iRegI src) %{ 12423 match(Set dst (ReverseBytesS src)); 12424 #ifdef AARCH64 12425 size(8); 12426 format %{ "REV16_W $dst,$src\n\t" 12427 "SIGN_EXT16 $dst" %} 12428 ins_encode %{ 12429 __ rev16_w($dst$$Register, $src$$Register); 12430 __ sign_extend($dst$$Register, $dst$$Register, 16); 12431 %} 12432 #else 12433 size(4); 12434 format %{ "REVSH $dst,$src" %} 12435 ins_encode %{ 12436 __ revsh($dst$$Register, $src$$Register); 12437 %} 12438 #endif 12439 ins_pipe( iload_mem ); // FIXME 12440 %} 12441 12442 12443 // ====================VECTOR INSTRUCTIONS===================================== 12444 12445 // Load Aligned Packed values into a Double Register 12446 instruct loadV8(vecD dst, memoryD mem) %{ 12447 predicate(n->as_LoadVector()->memory_size() == 8); 12448 match(Set dst (LoadVector mem)); 12449 ins_cost(MEMORY_REF_COST); 12450 size(4); 12451 format %{ "FLDD $mem,$dst\t! load vector (8 bytes)" %} 12452 ins_encode %{ 12453 __ ldr_double($dst$$FloatRegister, $mem$$Address); 12454 %} 12455 ins_pipe(floadD_mem); 12456 %} 12457 12458 // Load Aligned Packed values into a Double Register Pair 12459 instruct loadV16(vecX dst, memoryvld mem) %{ 12460 predicate(n->as_LoadVector()->memory_size() == 16); 12461 match(Set dst (LoadVector mem)); 12462 ins_cost(MEMORY_REF_COST); 12463 size(4); 12464 format %{ "VLD1 $mem,$dst.Q\t! load vector (16 bytes)" %} 12465 ins_encode %{ 12466 __ vld1($dst$$FloatRegister, $mem$$Address, MacroAssembler::VELEM_SIZE_16, 128); 12467 %} 12468 ins_pipe(floadD_mem); // FIXME 12469 %} 12470 12471 // Store Vector in Double register to memory 12472 instruct storeV8(memoryD mem, vecD src) %{ 12473 predicate(n->as_StoreVector()->memory_size() == 8); 12474 match(Set mem (StoreVector mem src)); 12475 ins_cost(MEMORY_REF_COST); 12476 size(4); 12477 format %{ "FSTD $src,$mem\t! store vector (8 bytes)" %} 12478 ins_encode %{ 12479 __ str_double($src$$FloatRegister, $mem$$Address); 12480 %} 12481 ins_pipe(fstoreD_mem_reg); 12482 %} 12483 12484 // Store Vector in Double Register Pair to memory 12485 instruct storeV16(memoryvld mem, vecX src) %{ 12486 predicate(n->as_StoreVector()->memory_size() == 16); 12487 match(Set mem (StoreVector mem src)); 12488 ins_cost(MEMORY_REF_COST); 12489 size(4); 12490 format %{ "VST1 $src,$mem\t! store vector (16 bytes)" %} 12491 ins_encode %{ 12492 __ vst1($src$$FloatRegister, $mem$$Address, MacroAssembler::VELEM_SIZE_16, 128); 12493 %} 12494 ins_pipe(fstoreD_mem_reg); // FIXME 12495 %} 12496 12497 #ifndef AARCH64 12498 // Replicate scalar to packed byte values in Double register 12499 instruct Repl8B_reg(vecD dst, iRegI src, iRegI tmp) %{ 12500 predicate(n->as_Vector()->length() == 8); 12501 match(Set dst (ReplicateB src)); 12502 ins_cost(DEFAULT_COST*4); 12503 effect(TEMP tmp); 12504 size(16); 12505 12506 // FIXME: could use PKH instruction instead? 12507 format %{ "LSL $tmp, $src, 24 \n\t" 12508 "OR $tmp, $tmp, ($tmp >> 8) \n\t" 12509 "OR $tmp, $tmp, ($tmp >> 16) \n\t" 12510 "FMDRR $dst,$tmp,$tmp\t" %} 12511 ins_encode %{ 12512 __ mov($tmp$$Register, AsmOperand($src$$Register, lsl, 24)); 12513 __ orr($tmp$$Register, $tmp$$Register, AsmOperand($tmp$$Register, lsr, 8)); 12514 __ orr($tmp$$Register, $tmp$$Register, AsmOperand($tmp$$Register, lsr, 16)); 12515 __ fmdrr($dst$$FloatRegister, $tmp$$Register, $tmp$$Register); 12516 %} 12517 ins_pipe(ialu_reg); // FIXME 12518 %} 12519 #endif /* !AARCH64 */ 12520 12521 // Replicate scalar to packed byte values in Double register 12522 instruct Repl8B_reg_simd(vecD dst, iRegI src) %{ 12523 predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd()); 12524 match(Set dst (ReplicateB src)); 12525 size(4); 12526 12527 format %{ "VDUP.8 $dst,$src\t" %} 12528 ins_encode %{ 12529 bool quad = false; 12530 __ vdupI($dst$$FloatRegister, $src$$Register, 12531 MacroAssembler::VELEM_SIZE_8, quad); 12532 %} 12533 ins_pipe(ialu_reg); // FIXME 12534 %} 12535 12536 // Replicate scalar to packed byte values in Double register pair 12537 instruct Repl16B_reg(vecX dst, iRegI src) %{ 12538 predicate(n->as_Vector()->length_in_bytes() == 16); 12539 match(Set dst (ReplicateB src)); 12540 size(4); 12541 12542 format %{ "VDUP.8 $dst.Q,$src\t" %} 12543 ins_encode %{ 12544 bool quad = true; 12545 __ vdupI($dst$$FloatRegister, $src$$Register, 12546 MacroAssembler::VELEM_SIZE_8, quad); 12547 %} 12548 ins_pipe(ialu_reg); // FIXME 12549 %} 12550 12551 #ifndef AARCH64 12552 // Replicate scalar constant to packed byte values in Double register 12553 instruct Repl8B_immI(vecD dst, immI src, iRegI tmp) %{ 12554 predicate(n->as_Vector()->length() == 8); 12555 match(Set dst (ReplicateB src)); 12556 ins_cost(DEFAULT_COST*2); 12557 effect(TEMP tmp); 12558 size(12); 12559 12560 format %{ "MOV $tmp, Repl4($src))\n\t" 12561 "FMDRR $dst,$tmp,$tmp\t" %} 12562 ins_encode( LdReplImmI(src, dst, tmp, (4), (1)) ); 12563 ins_pipe(loadConFD); // FIXME 12564 %} 12565 #endif /* !AARCH64 */ 12566 12567 // Replicate scalar constant to packed byte values in Double register 12568 // TODO: support negative constants with MVNI? 12569 instruct Repl8B_immU8(vecD dst, immU8 src) %{ 12570 predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd()); 12571 match(Set dst (ReplicateB src)); 12572 size(4); 12573 12574 format %{ "VMOV.U8 $dst,$src" %} 12575 ins_encode %{ 12576 bool quad = false; 12577 __ vmovI($dst$$FloatRegister, $src$$constant, 12578 MacroAssembler::VELEM_SIZE_8, quad); 12579 %} 12580 ins_pipe(loadConFD); // FIXME 12581 %} 12582 12583 // Replicate scalar constant to packed byte values in Double register pair 12584 instruct Repl16B_immU8(vecX dst, immU8 src) %{ 12585 predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd()); 12586 match(Set dst (ReplicateB src)); 12587 size(4); 12588 12589 format %{ "VMOV.U8 $dst.Q,$src" %} 12590 ins_encode %{ 12591 bool quad = true; 12592 __ vmovI($dst$$FloatRegister, $src$$constant, 12593 MacroAssembler::VELEM_SIZE_8, quad); 12594 %} 12595 ins_pipe(loadConFD); // FIXME 12596 %} 12597 12598 #ifndef AARCH64 12599 // Replicate scalar to packed short/char values into Double register 12600 instruct Repl4S_reg(vecD dst, iRegI src, iRegI tmp) %{ 12601 predicate(n->as_Vector()->length() == 4); 12602 match(Set dst (ReplicateS src)); 12603 ins_cost(DEFAULT_COST*3); 12604 effect(TEMP tmp); 12605 size(12); 12606 12607 // FIXME: could use PKH instruction instead? 12608 format %{ "LSL $tmp, $src, 16 \n\t" 12609 "OR $tmp, $tmp, ($tmp >> 16) \n\t" 12610 "FMDRR $dst,$tmp,$tmp\t" %} 12611 ins_encode %{ 12612 __ mov($tmp$$Register, AsmOperand($src$$Register, lsl, 16)); 12613 __ orr($tmp$$Register, $tmp$$Register, AsmOperand($tmp$$Register, lsr, 16)); 12614 __ fmdrr($dst$$FloatRegister, $tmp$$Register, $tmp$$Register); 12615 %} 12616 ins_pipe(ialu_reg); // FIXME 12617 %} 12618 #endif /* !AARCH64 */ 12619 12620 // Replicate scalar to packed byte values in Double register 12621 instruct Repl4S_reg_simd(vecD dst, iRegI src) %{ 12622 predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd()); 12623 match(Set dst (ReplicateS src)); 12624 size(4); 12625 12626 format %{ "VDUP.16 $dst,$src\t" %} 12627 ins_encode %{ 12628 bool quad = false; 12629 __ vdupI($dst$$FloatRegister, $src$$Register, 12630 MacroAssembler::VELEM_SIZE_16, quad); 12631 %} 12632 ins_pipe(ialu_reg); // FIXME 12633 %} 12634 12635 // Replicate scalar to packed byte values in Double register pair 12636 instruct Repl8S_reg(vecX dst, iRegI src) %{ 12637 predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd()); 12638 match(Set dst (ReplicateS src)); 12639 size(4); 12640 12641 format %{ "VDUP.16 $dst.Q,$src\t" %} 12642 ins_encode %{ 12643 bool quad = true; 12644 __ vdupI($dst$$FloatRegister, $src$$Register, 12645 MacroAssembler::VELEM_SIZE_16, quad); 12646 %} 12647 ins_pipe(ialu_reg); // FIXME 12648 %} 12649 12650 12651 #ifndef AARCH64 12652 // Replicate scalar constant to packed short/char values in Double register 12653 instruct Repl4S_immI(vecD dst, immI src, iRegP tmp) %{ 12654 predicate(n->as_Vector()->length() == 4); 12655 match(Set dst (ReplicateS src)); 12656 effect(TEMP tmp); 12657 size(12); 12658 ins_cost(DEFAULT_COST*4); // FIXME 12659 12660 format %{ "MOV $tmp, Repl2($src))\n\t" 12661 "FMDRR $dst,$tmp,$tmp\t" %} 12662 ins_encode( LdReplImmI(src, dst, tmp, (2), (2)) ); 12663 ins_pipe(loadConFD); // FIXME 12664 %} 12665 #endif /* !AARCH64 */ 12666 12667 // Replicate scalar constant to packed byte values in Double register 12668 instruct Repl4S_immU8(vecD dst, immU8 src) %{ 12669 predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd()); 12670 match(Set dst (ReplicateS src)); 12671 size(4); 12672 12673 format %{ "VMOV.U16 $dst,$src" %} 12674 ins_encode %{ 12675 bool quad = false; 12676 __ vmovI($dst$$FloatRegister, $src$$constant, 12677 MacroAssembler::VELEM_SIZE_16, quad); 12678 %} 12679 ins_pipe(loadConFD); // FIXME 12680 %} 12681 12682 // Replicate scalar constant to packed byte values in Double register pair 12683 instruct Repl8S_immU8(vecX dst, immU8 src) %{ 12684 predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd()); 12685 match(Set dst (ReplicateS src)); 12686 size(4); 12687 12688 format %{ "VMOV.U16 $dst.Q,$src" %} 12689 ins_encode %{ 12690 bool quad = true; 12691 __ vmovI($dst$$FloatRegister, $src$$constant, 12692 MacroAssembler::VELEM_SIZE_16, quad); 12693 %} 12694 ins_pipe(loadConFD); // FIXME 12695 %} 12696 12697 #ifndef AARCH64 12698 // Replicate scalar to packed int values in Double register 12699 instruct Repl2I_reg(vecD dst, iRegI src) %{ 12700 predicate(n->as_Vector()->length() == 2); 12701 match(Set dst (ReplicateI src)); 12702 size(4); 12703 12704 format %{ "FMDRR $dst,$src,$src\t" %} 12705 ins_encode %{ 12706 __ fmdrr($dst$$FloatRegister, $src$$Register, $src$$Register); 12707 %} 12708 ins_pipe(ialu_reg); // FIXME 12709 %} 12710 12711 // Replicate scalar to packed int values in Double register pair 12712 instruct Repl4I_reg(vecX dst, iRegI src) %{ 12713 predicate(n->as_Vector()->length() == 4); 12714 match(Set dst (ReplicateI src)); 12715 ins_cost(DEFAULT_COST*2); 12716 size(8); 12717 12718 format %{ "FMDRR $dst.lo,$src,$src\n\t" 12719 "FMDRR $dst.hi,$src,$src" %} 12720 12721 ins_encode %{ 12722 __ fmdrr($dst$$FloatRegister, $src$$Register, $src$$Register); 12723 __ fmdrr($dst$$FloatRegister->successor()->successor(), 12724 $src$$Register, $src$$Register); 12725 %} 12726 ins_pipe(ialu_reg); // FIXME 12727 %} 12728 #endif /* !AARCH64 */ 12729 12730 // Replicate scalar to packed int values in Double register 12731 instruct Repl2I_reg_simd(vecD dst, iRegI src) %{ 12732 predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd()); 12733 match(Set dst (ReplicateI src)); 12734 size(4); 12735 12736 format %{ "VDUP.32 $dst.D,$src\t" %} 12737 ins_encode %{ 12738 bool quad = false; 12739 __ vdupI($dst$$FloatRegister, $src$$Register, 12740 MacroAssembler::VELEM_SIZE_32, quad); 12741 %} 12742 ins_pipe(ialu_reg); // FIXME 12743 %} 12744 12745 // Replicate scalar to packed int values in Double register pair 12746 instruct Repl4I_reg_simd(vecX dst, iRegI src) %{ 12747 predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd()); 12748 match(Set dst (ReplicateI src)); 12749 size(4); 12750 12751 format %{ "VDUP.32 $dst.Q,$src\t" %} 12752 ins_encode %{ 12753 bool quad = true; 12754 __ vdupI($dst$$FloatRegister, $src$$Register, 12755 MacroAssembler::VELEM_SIZE_32, quad); 12756 %} 12757 ins_pipe(ialu_reg); // FIXME 12758 %} 12759 12760 12761 #ifndef AARCH64 12762 // Replicate scalar zero constant to packed int values in Double register 12763 instruct Repl2I_immI(vecD dst, immI src, iRegI tmp) %{ 12764 predicate(n->as_Vector()->length() == 2); 12765 match(Set dst (ReplicateI src)); 12766 effect(TEMP tmp); 12767 size(12); 12768 ins_cost(DEFAULT_COST*4); // FIXME 12769 12770 format %{ "MOV $tmp, Repl1($src))\n\t" 12771 "FMDRR $dst,$tmp,$tmp\t" %} 12772 ins_encode( LdReplImmI(src, dst, tmp, (1), (4)) ); 12773 ins_pipe(loadConFD); // FIXME 12774 %} 12775 #endif /* !AARCH64 */ 12776 12777 // Replicate scalar constant to packed byte values in Double register 12778 instruct Repl2I_immU8(vecD dst, immU8 src) %{ 12779 predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd()); 12780 match(Set dst (ReplicateI src)); 12781 size(4); 12782 12783 format %{ "VMOV.I32 $dst.D,$src" %} 12784 ins_encode %{ 12785 bool quad = false; 12786 __ vmovI($dst$$FloatRegister, $src$$constant, 12787 MacroAssembler::VELEM_SIZE_32, quad); 12788 %} 12789 ins_pipe(loadConFD); // FIXME 12790 %} 12791 12792 // Replicate scalar constant to packed byte values in Double register pair 12793 instruct Repl4I_immU8(vecX dst, immU8 src) %{ 12794 predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd()); 12795 match(Set dst (ReplicateI src)); 12796 size(4); 12797 12798 format %{ "VMOV.I32 $dst.Q,$src" %} 12799 ins_encode %{ 12800 bool quad = true; 12801 __ vmovI($dst$$FloatRegister, $src$$constant, 12802 MacroAssembler::VELEM_SIZE_32, quad); 12803 %} 12804 ins_pipe(loadConFD); // FIXME 12805 %} 12806 12807 #ifdef AARCH64 12808 // Replicate scalar to packed byte values in Double register pair 12809 instruct Repl2L_reg(vecX dst, iRegL src) %{ 12810 predicate(n->as_Vector()->length() == 2); 12811 match(Set dst (ReplicateL src)); 12812 size(4*1); 12813 ins_cost(DEFAULT_COST*1); // FIXME 12814 12815 format %{ "VDUP.2D $dst.Q,$src\t" %} 12816 ins_encode %{ 12817 bool quad = true; 12818 __ vdupI($dst$$FloatRegister, $src$$Register, 12819 MacroAssembler::VELEM_SIZE_64, quad); 12820 %} 12821 ins_pipe(ialu_reg); // FIXME 12822 %} 12823 #else /* !AARCH64 */ 12824 // Replicate scalar to packed byte values in Double register pair 12825 instruct Repl2L_reg(vecX dst, iRegL src) %{ 12826 predicate(n->as_Vector()->length() == 2); 12827 match(Set dst (ReplicateL src)); 12828 size(8); 12829 ins_cost(DEFAULT_COST*2); // FIXME 12830 12831 format %{ "FMDRR $dst.D,$src.lo,$src.hi\t\n" 12832 "FMDRR $dst.D.next,$src.lo,$src.hi" %} 12833 ins_encode %{ 12834 __ fmdrr($dst$$FloatRegister, $src$$Register, $src$$Register->successor()); 12835 __ fmdrr($dst$$FloatRegister->successor()->successor(), 12836 $src$$Register, $src$$Register->successor()); 12837 %} 12838 ins_pipe(ialu_reg); // FIXME 12839 %} 12840 12841 12842 // Replicate scalar to packed float values in Double register 12843 instruct Repl2F_regI(vecD dst, iRegI src) %{ 12844 predicate(n->as_Vector()->length() == 2); 12845 match(Set dst (ReplicateF src)); 12846 size(4); 12847 12848 format %{ "FMDRR $dst.D,$src,$src\t" %} 12849 ins_encode %{ 12850 __ fmdrr($dst$$FloatRegister, $src$$Register, $src$$Register); 12851 %} 12852 ins_pipe(ialu_reg); // FIXME 12853 %} 12854 12855 // Replicate scalar to packed float values in Double register 12856 instruct Repl2F_reg_vfp(vecD dst, regF src) %{ 12857 predicate(n->as_Vector()->length() == 2); 12858 match(Set dst (ReplicateF src)); 12859 size(4*2); 12860 ins_cost(DEFAULT_COST*2); // FIXME 12861 12862 expand %{ 12863 iRegI tmp; 12864 MoveF2I_reg_reg(tmp, src); 12865 Repl2F_regI(dst,tmp); 12866 %} 12867 %} 12868 #endif /* !AARCH64 */ 12869 12870 // Replicate scalar to packed float values in Double register 12871 instruct Repl2F_reg_simd(vecD dst, regF src) %{ 12872 predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd()); 12873 match(Set dst (ReplicateF src)); 12874 size(4); 12875 ins_cost(DEFAULT_COST); // FIXME 12876 12877 format %{ "VDUP.32 $dst.D,$src.D\t" %} 12878 ins_encode %{ 12879 bool quad = false; 12880 __ vdupF($dst$$FloatRegister, $src$$FloatRegister, quad); 12881 %} 12882 ins_pipe(ialu_reg); // FIXME 12883 %} 12884 12885 #ifndef AARCH64 12886 // Replicate scalar to packed float values in Double register pair 12887 instruct Repl4F_reg(vecX dst, regF src, iRegI tmp) %{ 12888 predicate(n->as_Vector()->length() == 4); 12889 match(Set dst (ReplicateF src)); 12890 effect(TEMP tmp); 12891 size(4*3); 12892 ins_cost(DEFAULT_COST*3); // FIXME 12893 12894 format %{ "FMRS $tmp,$src\n\t" 12895 "FMDRR $dst.D,$tmp,$tmp\n\t" 12896 "FMDRR $dst.D.next,$tmp,$tmp\t" %} 12897 ins_encode %{ 12898 __ fmrs($tmp$$Register, $src$$FloatRegister); 12899 __ fmdrr($dst$$FloatRegister, $tmp$$Register, $tmp$$Register); 12900 __ fmdrr($dst$$FloatRegister->successor()->successor(), 12901 $tmp$$Register, $tmp$$Register); 12902 %} 12903 ins_pipe(ialu_reg); // FIXME 12904 %} 12905 #endif /* !AARCH64 */ 12906 12907 // Replicate scalar to packed float values in Double register pair 12908 instruct Repl4F_reg_simd(vecX dst, regF src) %{ 12909 predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd()); 12910 match(Set dst (ReplicateF src)); 12911 size(4); 12912 ins_cost(DEFAULT_COST); // FIXME 12913 12914 format %{ "VDUP.32 $dst.Q,$src.D\t" %} 12915 ins_encode %{ 12916 bool quad = true; 12917 __ vdupF($dst$$FloatRegister, $src$$FloatRegister, quad); 12918 %} 12919 ins_pipe(ialu_reg); // FIXME 12920 %} 12921 12922 #ifndef AARCH64 12923 // Replicate scalar zero constant to packed float values in Double register 12924 instruct Repl2F_immI(vecD dst, immF src, iRegI tmp) %{ 12925 predicate(n->as_Vector()->length() == 2); 12926 match(Set dst (ReplicateF src)); 12927 effect(TEMP tmp); 12928 size(12); 12929 ins_cost(DEFAULT_COST*4); // FIXME 12930 12931 format %{ "MOV $tmp, Repl1($src))\n\t" 12932 "FMDRR $dst,$tmp,$tmp\t" %} 12933 ins_encode( LdReplImmF(src, dst, tmp) ); 12934 ins_pipe(loadConFD); // FIXME 12935 %} 12936 #endif /* !AAARCH64 */ 12937 12938 // Replicate scalar to packed double float values in Double register pair 12939 instruct Repl2D_reg(vecX dst, regD src) %{ 12940 #ifdef AARCH64 12941 predicate(n->as_Vector()->length() == 2 && VM_Version::has_simd()); 12942 match(Set dst (ReplicateD src)); 12943 size(4*1); 12944 ins_cost(DEFAULT_COST*1); // FIXME 12945 12946 format %{ "VDUP $dst.2D,$src\t" %} 12947 ins_encode %{ 12948 bool quad = true; 12949 __ vdupD($dst$$FloatRegister, $src$$FloatRegister, quad); 12950 %} 12951 #else 12952 predicate(n->as_Vector()->length() == 2); 12953 match(Set dst (ReplicateD src)); 12954 size(4*2); 12955 ins_cost(DEFAULT_COST*2); // FIXME 12956 12957 format %{ "FCPYD $dst.D.a,$src\n\t" 12958 "FCPYD $dst.D.b,$src\t" %} 12959 ins_encode %{ 12960 FloatRegister dsta = $dst$$FloatRegister; 12961 FloatRegister src = $src$$FloatRegister; 12962 __ fcpyd(dsta, src); 12963 FloatRegister dstb = dsta->successor()->successor(); 12964 __ fcpyd(dstb, src); 12965 %} 12966 #endif 12967 ins_pipe(ialu_reg); // FIXME 12968 %} 12969 12970 // ====================VECTOR ARITHMETIC======================================= 12971 12972 // --------------------------------- ADD -------------------------------------- 12973 12974 // Bytes vector add 12975 instruct vadd8B_reg(vecD dst, vecD src1, vecD src2) %{ 12976 predicate(n->as_Vector()->length() == 8); 12977 match(Set dst (AddVB src1 src2)); 12978 format %{ "VADD.I8 $dst,$src1,$src2\t! add packed8B" %} 12979 size(4); 12980 ins_encode %{ 12981 bool quad = false; 12982 __ vaddI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 12983 MacroAssembler::VELEM_SIZE_8, quad); 12984 %} 12985 ins_pipe( ialu_reg_reg ); // FIXME 12986 %} 12987 12988 instruct vadd16B_reg(vecX dst, vecX src1, vecX src2) %{ 12989 predicate(n->as_Vector()->length() == 16); 12990 match(Set dst (AddVB src1 src2)); 12991 size(4); 12992 format %{ "VADD.I8 $dst.Q,$src1.Q,$src2.Q\t! add packed16B" %} 12993 ins_encode %{ 12994 bool quad = true; 12995 __ vaddI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 12996 MacroAssembler::VELEM_SIZE_8, quad); 12997 %} 12998 ins_pipe( ialu_reg_reg ); // FIXME 12999 %} 13000 13001 // Shorts/Chars vector add 13002 instruct vadd4S_reg(vecD dst, vecD src1, vecD src2) %{ 13003 predicate(n->as_Vector()->length() == 4); 13004 match(Set dst (AddVS src1 src2)); 13005 size(4); 13006 format %{ "VADD.I16 $dst,$src1,$src2\t! add packed4S" %} 13007 ins_encode %{ 13008 bool quad = false; 13009 __ vaddI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 13010 MacroAssembler::VELEM_SIZE_16, quad); 13011 %} 13012 ins_pipe( ialu_reg_reg ); // FIXME 13013 %} 13014 13015 instruct vadd8S_reg(vecX dst, vecX src1, vecX src2) %{ 13016 predicate(n->as_Vector()->length() == 8); 13017 match(Set dst (AddVS src1 src2)); 13018 size(4); 13019 format %{ "VADD.I16 $dst.Q,$src1.Q,$src2.Q\t! add packed8S" %} 13020 ins_encode %{ 13021 bool quad = true; 13022 __ vaddI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 13023 MacroAssembler::VELEM_SIZE_16, quad); 13024 %} 13025 ins_pipe( ialu_reg_reg ); // FIXME 13026 %} 13027 13028 // Integers vector add 13029 instruct vadd2I_reg(vecD dst, vecD src1, vecD src2) %{ 13030 predicate(n->as_Vector()->length() == 2); 13031 match(Set dst (AddVI src1 src2)); 13032 size(4); 13033 format %{ "VADD.I32 $dst.D,$src1.D,$src2.D\t! add packed2I" %} 13034 ins_encode %{ 13035 bool quad = false; 13036 __ vaddI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 13037 MacroAssembler::VELEM_SIZE_32, quad); 13038 %} 13039 ins_pipe( ialu_reg_reg ); // FIXME 13040 %} 13041 13042 instruct vadd4I_reg(vecX dst, vecX src1, vecX src2) %{ 13043 predicate(n->as_Vector()->length() == 4); 13044 match(Set dst (AddVI src1 src2)); 13045 size(4); 13046 format %{ "VADD.I32 $dst.Q,$src1.Q,$src2.Q\t! add packed4I" %} 13047 ins_encode %{ 13048 bool quad = true; 13049 __ vaddI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 13050 MacroAssembler::VELEM_SIZE_32, quad); 13051 %} 13052 ins_pipe( ialu_reg_reg ); // FIXME 13053 %} 13054 13055 // Longs vector add 13056 instruct vadd2L_reg(vecX dst, vecX src1, vecX src2) %{ 13057 predicate(n->as_Vector()->length() == 2); 13058 match(Set dst (AddVL src1 src2)); 13059 size(4); 13060 format %{ "VADD.I64 $dst.Q,$src1.Q,$src2.Q\t! add packed2L" %} 13061 ins_encode %{ 13062 bool quad = true; 13063 __ vaddI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 13064 MacroAssembler::VELEM_SIZE_64, quad); 13065 %} 13066 ins_pipe( ialu_reg_reg ); // FIXME 13067 %} 13068 13069 // Floats vector add 13070 instruct vadd2F_reg(vecD dst, vecD src1, vecD src2) %{ 13071 predicate(n->as_Vector()->length() == 2 && VM_Version::simd_math_is_compliant()); 13072 match(Set dst (AddVF src1 src2)); 13073 size(4); 13074 format %{ "VADD.F32 $dst,$src1,$src2\t! add packed2F" %} 13075 ins_encode %{ 13076 bool quad = false; 13077 __ vaddF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 13078 MacroAssembler::VFA_SIZE_F32, quad); 13079 %} 13080 ins_pipe( faddD_reg_reg ); // FIXME 13081 %} 13082 13083 #ifndef AARCH64 13084 instruct vadd2F_reg_vfp(vecD dst, vecD src1, vecD src2) %{ 13085 predicate(n->as_Vector()->length() == 2 && !VM_Version::simd_math_is_compliant()); 13086 match(Set dst (AddVF src1 src2)); 13087 ins_cost(DEFAULT_COST*2); // FIXME 13088 13089 size(4*2); 13090 format %{ "FADDS $dst.a,$src1.a,$src2.a\n\t" 13091 "FADDS $dst.b,$src1.b,$src2.b" %} 13092 ins_encode %{ 13093 __ add_float($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister); 13094 __ add_float($dst$$FloatRegister->successor(), 13095 $src1$$FloatRegister->successor(), 13096 $src2$$FloatRegister->successor()); 13097 %} 13098 13099 ins_pipe(faddF_reg_reg); // FIXME 13100 %} 13101 #endif 13102 13103 instruct vadd4F_reg_simd(vecX dst, vecX src1, vecX src2) %{ 13104 predicate(n->as_Vector()->length() == 4 && VM_Version::simd_math_is_compliant()); 13105 match(Set dst (AddVF src1 src2)); 13106 size(4); 13107 format %{ "VADD.F32 $dst.Q,$src1.Q,$src2.Q\t! add packed4F" %} 13108 ins_encode %{ 13109 bool quad = true; 13110 __ vaddF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 13111 MacroAssembler::VFA_SIZE_F32, quad); 13112 %} 13113 ins_pipe( faddD_reg_reg ); // FIXME 13114 %} 13115 13116 #ifdef AARCH64 13117 instruct vadd2D_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 (AddVD src1 src2)); 13120 size(4); 13121 format %{ "VADD.F64 $dst.Q,$src1.Q,$src2.Q\t! add packed2D" %} 13122 ins_encode %{ 13123 bool quad = true; 13124 __ vaddF($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 vadd4F_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 (AddVF src1 src2)); 13133 size(4*4); 13134 ins_cost(DEFAULT_COST*4); // FIXME 13135 13136 format %{ "FADDS $dst.a,$src1.a,$src2.a\n\t" 13137 "FADDS $dst.b,$src1.b,$src2.b\n\t" 13138 "FADDS $dst.c,$src1.c,$src2.c\n\t" 13139 "FADDS $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 __ add_float(dsta, src1a, src2a); 13146 FloatRegister dstb = dsta->successor(); 13147 FloatRegister src1b = src1a->successor(); 13148 FloatRegister src2b = src2a->successor(); 13149 __ add_float(dstb, src1b, src2b); 13150 FloatRegister dstc = dstb->successor(); 13151 FloatRegister src1c = src1b->successor(); 13152 FloatRegister src2c = src2b->successor(); 13153 __ add_float(dstc, src1c, src2c); 13154 FloatRegister dstd = dstc->successor(); 13155 FloatRegister src1d = src1c->successor(); 13156 FloatRegister src2d = src2c->successor(); 13157 __ add_float(dstd, src1d, src2d); 13158 %} 13159 13160 ins_pipe(faddF_reg_reg); // FIXME 13161 %} 13162 13163 instruct vadd2D_reg_vfp(vecX dst, vecX src1, vecX src2) %{ 13164 predicate(n->as_Vector()->length() == 2); 13165 match(Set dst (AddVD src1 src2)); 13166 size(4*2); 13167 ins_cost(DEFAULT_COST*2); // FIXME 13168 13169 format %{ "FADDD $dst.a,$src1.a,$src2.a\n\t" 13170 "FADDD $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 __ add_double(dsta, src1a, src2a); 13177 FloatRegister dstb = dsta->successor()->successor(); 13178 FloatRegister src1b = src1a->successor()->successor(); 13179 FloatRegister src2b = src2a->successor()->successor(); 13180 __ add_double(dstb, src1b, src2b); 13181 %} 13182 13183 ins_pipe(faddF_reg_reg); // FIXME 13184 %} 13185 #endif 13186 13187 13188 // Bytes vector sub 13189 instruct vsub8B_reg(vecD dst, vecD src1, vecD src2) %{ 13190 predicate(n->as_Vector()->length() == 8); 13191 match(Set dst (SubVB src1 src2)); 13192 size(4); 13193 format %{ "VSUB.I8 $dst,$src1,$src2\t! sub packed8B" %} 13194 ins_encode %{ 13195 bool quad = false; 13196 __ vsubI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 13197 MacroAssembler::VELEM_SIZE_8, quad); 13198 %} 13199 ins_pipe( ialu_reg_reg ); // FIXME 13200 %} 13201 13202 instruct vsub16B_reg(vecX dst, vecX src1, vecX src2) %{ 13203 predicate(n->as_Vector()->length() == 16); 13204 match(Set dst (SubVB src1 src2)); 13205 size(4); 13206 format %{ "VSUB.I8 $dst.Q,$src1.Q,$src2.Q\t! sub packed16B" %} 13207 ins_encode %{ 13208 bool quad = true; 13209 __ vsubI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 13210 MacroAssembler::VELEM_SIZE_8, quad); 13211 %} 13212 ins_pipe( ialu_reg_reg ); // FIXME 13213 %} 13214 13215 // Shorts/Chars vector sub 13216 instruct vsub4S_reg(vecD dst, vecD src1, vecD src2) %{ 13217 predicate(n->as_Vector()->length() == 4); 13218 match(Set dst (SubVS src1 src2)); 13219 size(4); 13220 format %{ "VSUB.I16 $dst,$src1,$src2\t! sub packed4S" %} 13221 ins_encode %{ 13222 bool quad = false; 13223 __ vsubI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 13224 MacroAssembler::VELEM_SIZE_16, quad); 13225 %} 13226 ins_pipe( ialu_reg_reg ); // FIXME 13227 %} 13228 13229 instruct vsub16S_reg(vecX dst, vecX src1, vecX src2) %{ 13230 predicate(n->as_Vector()->length() == 8); 13231 match(Set dst (SubVS src1 src2)); 13232 size(4); 13233 format %{ "VSUB.I16 $dst.Q,$src1.Q,$src2.Q\t! sub packed8S" %} 13234 ins_encode %{ 13235 bool quad = true; 13236 __ vsubI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 13237 MacroAssembler::VELEM_SIZE_16, quad); 13238 %} 13239 ins_pipe( ialu_reg_reg ); // FIXME 13240 %} 13241 13242 // Integers vector sub 13243 instruct vsub2I_reg(vecD dst, vecD src1, vecD src2) %{ 13244 predicate(n->as_Vector()->length() == 2); 13245 match(Set dst (SubVI src1 src2)); 13246 size(4); 13247 format %{ "VSUB.I32 $dst,$src1,$src2\t! sub packed2I" %} 13248 ins_encode %{ 13249 bool quad = false; 13250 __ vsubI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 13251 MacroAssembler::VELEM_SIZE_32, quad); 13252 %} 13253 ins_pipe( ialu_reg_reg ); // FIXME 13254 %} 13255 13256 instruct vsub4I_reg(vecX dst, vecX src1, vecX src2) %{ 13257 predicate(n->as_Vector()->length() == 4); 13258 match(Set dst (SubVI src1 src2)); 13259 size(4); 13260 format %{ "VSUB.I32 $dst.Q,$src1.Q,$src2.Q\t! sub packed4I" %} 13261 ins_encode %{ 13262 bool quad = true; 13263 __ vsubI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 13264 MacroAssembler::VELEM_SIZE_32, quad); 13265 %} 13266 ins_pipe( ialu_reg_reg ); // FIXME 13267 %} 13268 13269 // Longs vector sub 13270 instruct vsub2L_reg(vecX dst, vecX src1, vecX src2) %{ 13271 predicate(n->as_Vector()->length() == 2); 13272 match(Set dst (SubVL src1 src2)); 13273 size(4); 13274 format %{ "VSUB.I64 $dst.Q,$src1.Q,$src2.Q\t! sub packed2L" %} 13275 ins_encode %{ 13276 bool quad = true; 13277 __ vsubI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 13278 MacroAssembler::VELEM_SIZE_64, quad); 13279 %} 13280 ins_pipe( ialu_reg_reg ); // FIXME 13281 %} 13282 13283 // Floats vector sub 13284 instruct vsub2F_reg(vecD dst, vecD src1, vecD src2) %{ 13285 predicate(n->as_Vector()->length() == 2 && VM_Version::simd_math_is_compliant()); 13286 match(Set dst (SubVF src1 src2)); 13287 size(4); 13288 format %{ "VSUB.F32 $dst,$src1,$src2\t! sub packed2F" %} 13289 ins_encode %{ 13290 bool quad = false; 13291 __ vsubF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 13292 MacroAssembler::VFA_SIZE_F32, quad); 13293 %} 13294 ins_pipe( faddF_reg_reg ); // FIXME 13295 %} 13296 13297 #ifndef AARCH64 13298 instruct vsub2F_reg_vfp(vecD dst, vecD src1, vecD src2) %{ 13299 predicate(n->as_Vector()->length() == 2 && !VM_Version::simd_math_is_compliant()); 13300 match(Set dst (SubVF src1 src2)); 13301 size(4*2); 13302 ins_cost(DEFAULT_COST*2); // FIXME 13303 13304 format %{ "FSUBS $dst.a,$src1.a,$src2.a\n\t" 13305 "FSUBS $dst.b,$src1.b,$src2.b" %} 13306 13307 ins_encode %{ 13308 FloatRegister dsta = $dst$$FloatRegister; 13309 FloatRegister src1a = $src1$$FloatRegister; 13310 FloatRegister src2a = $src2$$FloatRegister; 13311 __ sub_float(dsta, src1a, src2a); 13312 FloatRegister dstb = dsta->successor(); 13313 FloatRegister src1b = src1a->successor(); 13314 FloatRegister src2b = src2a->successor(); 13315 __ sub_float(dstb, src1b, src2b); 13316 %} 13317 13318 ins_pipe(faddF_reg_reg); // FIXME 13319 %} 13320 #endif 13321 13322 13323 instruct vsub4F_reg(vecX dst, vecX src1, vecX src2) %{ 13324 predicate(n->as_Vector()->length() == 4 && VM_Version::simd_math_is_compliant()); 13325 match(Set dst (SubVF src1 src2)); 13326 size(4); 13327 format %{ "VSUB.F32 $dst.Q,$src1.Q,$src2.Q\t! sub packed4F" %} 13328 ins_encode %{ 13329 bool quad = true; 13330 __ vsubF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 13331 MacroAssembler::VFA_SIZE_F32, quad); 13332 %} 13333 ins_pipe( faddF_reg_reg ); // FIXME 13334 %} 13335 13336 #ifdef AARCH64 13337 instruct vsub2D_reg_simd(vecX dst, vecX src1, vecX src2) %{ 13338 predicate(n->as_Vector()->length() == 2 && VM_Version::simd_math_is_compliant()); 13339 match(Set dst (SubVD src1 src2)); 13340 size(4); 13341 format %{ "VSUB.F64 $dst.Q,$src1.Q,$src2.Q\t! add packed2D" %} 13342 ins_encode %{ 13343 bool quad = true; 13344 __ vsubF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 13345 MacroAssembler::VFA_SIZE_F64, quad); 13346 %} 13347 ins_pipe( faddD_reg_reg ); // FIXME 13348 %} 13349 #else 13350 instruct vsub4F_reg_vfp(vecX dst, vecX src1, vecX src2) %{ 13351 predicate(n->as_Vector()->length() == 4 && !VM_Version::simd_math_is_compliant()); 13352 match(Set dst (SubVF src1 src2)); 13353 size(4*4); 13354 ins_cost(DEFAULT_COST*4); // FIXME 13355 13356 format %{ "FSUBS $dst.a,$src1.a,$src2.a\n\t" 13357 "FSUBS $dst.b,$src1.b,$src2.b\n\t" 13358 "FSUBS $dst.c,$src1.c,$src2.c\n\t" 13359 "FSUBS $dst.d,$src1.d,$src2.d" %} 13360 13361 ins_encode %{ 13362 FloatRegister dsta = $dst$$FloatRegister; 13363 FloatRegister src1a = $src1$$FloatRegister; 13364 FloatRegister src2a = $src2$$FloatRegister; 13365 __ sub_float(dsta, src1a, src2a); 13366 FloatRegister dstb = dsta->successor(); 13367 FloatRegister src1b = src1a->successor(); 13368 FloatRegister src2b = src2a->successor(); 13369 __ sub_float(dstb, src1b, src2b); 13370 FloatRegister dstc = dstb->successor(); 13371 FloatRegister src1c = src1b->successor(); 13372 FloatRegister src2c = src2b->successor(); 13373 __ sub_float(dstc, src1c, src2c); 13374 FloatRegister dstd = dstc->successor(); 13375 FloatRegister src1d = src1c->successor(); 13376 FloatRegister src2d = src2c->successor(); 13377 __ sub_float(dstd, src1d, src2d); 13378 %} 13379 13380 ins_pipe(faddF_reg_reg); // FIXME 13381 %} 13382 13383 instruct vsub2D_reg_vfp(vecX dst, vecX src1, vecX src2) %{ 13384 predicate(n->as_Vector()->length() == 2); 13385 match(Set dst (SubVD src1 src2)); 13386 size(4*2); 13387 ins_cost(DEFAULT_COST*2); // FIXME 13388 13389 format %{ "FSUBD $dst.a,$src1.a,$src2.a\n\t" 13390 "FSUBD $dst.b,$src1.b,$src2.b" %} 13391 13392 ins_encode %{ 13393 FloatRegister dsta = $dst$$FloatRegister; 13394 FloatRegister src1a = $src1$$FloatRegister; 13395 FloatRegister src2a = $src2$$FloatRegister; 13396 __ sub_double(dsta, src1a, src2a); 13397 FloatRegister dstb = dsta->successor()->successor(); 13398 FloatRegister src1b = src1a->successor()->successor(); 13399 FloatRegister src2b = src2a->successor()->successor(); 13400 __ sub_double(dstb, src1b, src2b); 13401 %} 13402 13403 ins_pipe(faddF_reg_reg); // FIXME 13404 %} 13405 #endif 13406 13407 // Shorts/Chars vector mul 13408 instruct vmul4S_reg(vecD dst, vecD src1, vecD src2) %{ 13409 predicate(n->as_Vector()->length() == 4); 13410 match(Set dst (MulVS src1 src2)); 13411 size(4); 13412 format %{ "VMUL.I16 $dst,$src1,$src2\t! mul packed4S" %} 13413 ins_encode %{ 13414 __ vmulI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 13415 MacroAssembler::VELEM_SIZE_16, 0); 13416 %} 13417 ins_pipe( ialu_reg_reg ); // FIXME 13418 %} 13419 13420 instruct vmul8S_reg(vecX dst, vecX src1, vecX src2) %{ 13421 predicate(n->as_Vector()->length() == 8); 13422 match(Set dst (MulVS src1 src2)); 13423 size(4); 13424 format %{ "VMUL.I16 $dst.Q,$src1.Q,$src2.Q\t! mul packed8S" %} 13425 ins_encode %{ 13426 __ vmulI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 13427 MacroAssembler::VELEM_SIZE_16, 1); 13428 %} 13429 ins_pipe( ialu_reg_reg ); // FIXME 13430 %} 13431 13432 // Integers vector mul 13433 instruct vmul2I_reg(vecD dst, vecD src1, vecD src2) %{ 13434 predicate(n->as_Vector()->length() == 2); 13435 match(Set dst (MulVI src1 src2)); 13436 size(4); 13437 format %{ "VMUL.I32 $dst,$src1,$src2\t! mul packed2I" %} 13438 ins_encode %{ 13439 __ vmulI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 13440 MacroAssembler::VELEM_SIZE_32, 0); 13441 %} 13442 ins_pipe( ialu_reg_reg ); // FIXME 13443 %} 13444 13445 instruct vmul4I_reg(vecX dst, vecX src1, vecX src2) %{ 13446 predicate(n->as_Vector()->length() == 4); 13447 match(Set dst (MulVI src1 src2)); 13448 size(4); 13449 format %{ "VMUL.I32 $dst.Q,$src1.Q,$src2.Q\t! mul packed4I" %} 13450 ins_encode %{ 13451 __ vmulI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 13452 MacroAssembler::VELEM_SIZE_32, 1); 13453 %} 13454 ins_pipe( ialu_reg_reg ); // FIXME 13455 %} 13456 13457 // Floats vector mul 13458 instruct vmul2F_reg(vecD dst, vecD src1, vecD src2) %{ 13459 predicate(n->as_Vector()->length() == 2 && VM_Version::simd_math_is_compliant()); 13460 match(Set dst (MulVF src1 src2)); 13461 size(4); 13462 format %{ "VMUL.F32 $dst,$src1,$src2\t! mul packed2F" %} 13463 ins_encode %{ 13464 __ vmulF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 13465 MacroAssembler::VFA_SIZE_F32, 0); 13466 %} 13467 ins_pipe( fmulF_reg_reg ); // FIXME 13468 %} 13469 13470 #ifndef AARCH64 13471 instruct vmul2F_reg_vfp(vecD dst, vecD src1, vecD src2) %{ 13472 predicate(n->as_Vector()->length() == 2 && !VM_Version::simd_math_is_compliant()); 13473 match(Set dst (MulVF src1 src2)); 13474 size(4*2); 13475 ins_cost(DEFAULT_COST*2); // FIXME 13476 13477 format %{ "FMULS $dst.a,$src1.a,$src2.a\n\t" 13478 "FMULS $dst.b,$src1.b,$src2.b" %} 13479 ins_encode %{ 13480 __ mul_float($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister); 13481 __ mul_float($dst$$FloatRegister->successor(), 13482 $src1$$FloatRegister->successor(), 13483 $src2$$FloatRegister->successor()); 13484 %} 13485 13486 ins_pipe(fmulF_reg_reg); // FIXME 13487 %} 13488 #endif 13489 13490 instruct vmul4F_reg(vecX dst, vecX src1, vecX src2) %{ 13491 predicate(n->as_Vector()->length() == 4 && VM_Version::simd_math_is_compliant()); 13492 match(Set dst (MulVF src1 src2)); 13493 size(4); 13494 format %{ "VMUL.F32 $dst.Q,$src1.Q,$src2.Q\t! mul packed4F" %} 13495 ins_encode %{ 13496 __ vmulF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 13497 MacroAssembler::VFA_SIZE_F32, 1); 13498 %} 13499 ins_pipe( fmulF_reg_reg ); // FIXME 13500 %} 13501 13502 #ifndef AARCH64 13503 instruct vmul4F_reg_vfp(vecX dst, vecX src1, vecX src2) %{ 13504 predicate(n->as_Vector()->length() == 4 && !VM_Version::simd_math_is_compliant()); 13505 match(Set dst (MulVF src1 src2)); 13506 size(4*4); 13507 ins_cost(DEFAULT_COST*4); // FIXME 13508 13509 format %{ "FMULS $dst.a,$src1.a,$src2.a\n\t" 13510 "FMULS $dst.b,$src1.b,$src2.b\n\t" 13511 "FMULS $dst.c,$src1.c,$src2.c\n\t" 13512 "FMULS $dst.d,$src1.d,$src2.d" %} 13513 13514 ins_encode %{ 13515 FloatRegister dsta = $dst$$FloatRegister; 13516 FloatRegister src1a = $src1$$FloatRegister; 13517 FloatRegister src2a = $src2$$FloatRegister; 13518 __ mul_float(dsta, src1a, src2a); 13519 FloatRegister dstb = dsta->successor(); 13520 FloatRegister src1b = src1a->successor(); 13521 FloatRegister src2b = src2a->successor(); 13522 __ mul_float(dstb, src1b, src2b); 13523 FloatRegister dstc = dstb->successor(); 13524 FloatRegister src1c = src1b->successor(); 13525 FloatRegister src2c = src2b->successor(); 13526 __ mul_float(dstc, src1c, src2c); 13527 FloatRegister dstd = dstc->successor(); 13528 FloatRegister src1d = src1c->successor(); 13529 FloatRegister src2d = src2c->successor(); 13530 __ mul_float(dstd, src1d, src2d); 13531 %} 13532 13533 ins_pipe(fmulF_reg_reg); // FIXME 13534 %} 13535 #endif 13536 13537 #ifdef AARCH64 13538 instruct vmul2D_reg(vecX dst, vecX src1, vecX src2) %{ 13539 predicate(n->as_Vector()->length() == 2 && VM_Version::has_simd()); 13540 match(Set dst (MulVD src1 src2)); 13541 size(4*1); 13542 ins_cost(DEFAULT_COST*1); // FIXME 13543 13544 format %{ "FMUL.2D $dst,$src1,$src2\t! double[2]" %} 13545 ins_encode %{ 13546 int quad = 1; 13547 __ vmulF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 13548 MacroAssembler::VFA_SIZE_F64, quad); 13549 %} 13550 13551 ins_pipe(fdivF_reg_reg); // FIXME 13552 %} 13553 #else 13554 instruct vmul2D_reg_vfp(vecX dst, vecX src1, vecX src2) %{ 13555 predicate(n->as_Vector()->length() == 2); 13556 match(Set dst (MulVD src1 src2)); 13557 size(4*2); 13558 ins_cost(DEFAULT_COST*2); // FIXME 13559 13560 format %{ "FMULD $dst.D.a,$src1.D.a,$src2.D.a\n\t" 13561 "FMULD $dst.D.b,$src1.D.b,$src2.D.b" %} 13562 ins_encode %{ 13563 FloatRegister dsta = $dst$$FloatRegister; 13564 FloatRegister src1a = $src1$$FloatRegister; 13565 FloatRegister src2a = $src2$$FloatRegister; 13566 __ mul_double(dsta, src1a, src2a); 13567 FloatRegister dstb = dsta->successor()->successor(); 13568 FloatRegister src1b = src1a->successor()->successor(); 13569 FloatRegister src2b = src2a->successor()->successor(); 13570 __ mul_double(dstb, src1b, src2b); 13571 %} 13572 13573 ins_pipe(fmulD_reg_reg); // FIXME 13574 %} 13575 #endif 13576 13577 13578 // Floats vector div 13579 instruct vdiv2F_reg_vfp(vecD dst, vecD src1, vecD src2) %{ 13580 predicate(n->as_Vector()->length() == 2); 13581 match(Set dst (DivVF src1 src2)); 13582 #ifdef AARCH64 13583 size(4*1); 13584 ins_cost(DEFAULT_COST*1); // FIXME 13585 13586 format %{ "FDIV.2S $dst,$src1,$src2\t! float[2]" %} 13587 ins_encode %{ 13588 int quad = 0; 13589 __ vdivF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 13590 MacroAssembler::VFA_SIZE_F32, quad); 13591 %} 13592 13593 ins_pipe(fdivF_reg_reg); // FIXME 13594 #else 13595 size(4*2); 13596 ins_cost(DEFAULT_COST*2); // FIXME 13597 13598 format %{ "FDIVS $dst.a,$src1.a,$src2.a\n\t" 13599 "FDIVS $dst.b,$src1.b,$src2.b" %} 13600 ins_encode %{ 13601 __ div_float($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister); 13602 __ div_float($dst$$FloatRegister->successor(), 13603 $src1$$FloatRegister->successor(), 13604 $src2$$FloatRegister->successor()); 13605 %} 13606 13607 ins_pipe(fdivF_reg_reg); // FIXME 13608 #endif 13609 %} 13610 13611 instruct vdiv4F_reg_vfp(vecX dst, vecX src1, vecX src2) %{ 13612 predicate(n->as_Vector()->length() == 4); 13613 match(Set dst (DivVF src1 src2)); 13614 #ifdef AARCH64 13615 size(4*1); 13616 ins_cost(DEFAULT_COST*1); // FIXME 13617 13618 format %{ "FDIV.4S $dst,$src1,$src2\t! float[4]" %} 13619 ins_encode %{ 13620 int quad = 1; 13621 __ vdivF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 13622 MacroAssembler::VFA_SIZE_F32, quad); 13623 %} 13624 13625 ins_pipe(fdivF_reg_reg); // FIXME 13626 #else 13627 size(4*4); 13628 ins_cost(DEFAULT_COST*4); // FIXME 13629 13630 format %{ "FDIVS $dst.a,$src1.a,$src2.a\n\t" 13631 "FDIVS $dst.b,$src1.b,$src2.b\n\t" 13632 "FDIVS $dst.c,$src1.c,$src2.c\n\t" 13633 "FDIVS $dst.d,$src1.d,$src2.d" %} 13634 13635 ins_encode %{ 13636 FloatRegister dsta = $dst$$FloatRegister; 13637 FloatRegister src1a = $src1$$FloatRegister; 13638 FloatRegister src2a = $src2$$FloatRegister; 13639 __ div_float(dsta, src1a, src2a); 13640 FloatRegister dstb = dsta->successor(); 13641 FloatRegister src1b = src1a->successor(); 13642 FloatRegister src2b = src2a->successor(); 13643 __ div_float(dstb, src1b, src2b); 13644 FloatRegister dstc = dstb->successor(); 13645 FloatRegister src1c = src1b->successor(); 13646 FloatRegister src2c = src2b->successor(); 13647 __ div_float(dstc, src1c, src2c); 13648 FloatRegister dstd = dstc->successor(); 13649 FloatRegister src1d = src1c->successor(); 13650 FloatRegister src2d = src2c->successor(); 13651 __ div_float(dstd, src1d, src2d); 13652 %} 13653 13654 ins_pipe(fdivF_reg_reg); // FIXME 13655 #endif 13656 %} 13657 13658 #ifdef AARCH64 13659 instruct vdiv2D_reg(vecX dst, vecX src1, vecX src2) %{ 13660 predicate(n->as_Vector()->length() == 2 && VM_Version::has_simd()); 13661 match(Set dst (DivVD src1 src2)); 13662 size(4*1); 13663 ins_cost(DEFAULT_COST*1); // FIXME 13664 13665 format %{ "FDIV.2D $dst,$src1,$src2\t! double[2]" %} 13666 ins_encode %{ 13667 int quad = 1; 13668 __ vdivF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 13669 MacroAssembler::VFA_SIZE_F64, quad); 13670 %} 13671 13672 ins_pipe(fdivF_reg_reg); // FIXME 13673 %} 13674 #else 13675 instruct vdiv2D_reg_vfp(vecX dst, vecX src1, vecX src2) %{ 13676 predicate(n->as_Vector()->length() == 2); 13677 match(Set dst (DivVD src1 src2)); 13678 size(4*2); 13679 ins_cost(DEFAULT_COST*2); // FIXME 13680 13681 format %{ "FDIVD $dst.D.a,$src1.D.a,$src2.D.a\n\t" 13682 "FDIVD $dst.D.b,$src1.D.b,$src2.D.b" %} 13683 ins_encode %{ 13684 FloatRegister dsta = $dst$$FloatRegister; 13685 FloatRegister src1a = $src1$$FloatRegister; 13686 FloatRegister src2a = $src2$$FloatRegister; 13687 __ div_double(dsta, src1a, src2a); 13688 FloatRegister dstb = dsta->successor()->successor(); 13689 FloatRegister src1b = src1a->successor()->successor(); 13690 FloatRegister src2b = src2a->successor()->successor(); 13691 __ div_double(dstb, src1b, src2b); 13692 %} 13693 13694 ins_pipe(fdivD_reg_reg); // FIXME 13695 %} 13696 #endif 13697 13698 // --------------------------------- NEG -------------------------------------- 13699 13700 instruct vneg8B_reg(vecD dst, vecD src) %{ 13701 predicate(n->as_Vector()->length_in_bytes() == 8); 13702 effect(DEF dst, USE src); 13703 size(4); 13704 ins_cost(DEFAULT_COST); // FIXME 13705 format %{ "VNEG.S8 $dst.D,$src.D\t! neg packed8B" %} 13706 ins_encode %{ 13707 bool quad = false; 13708 __ vnegI($dst$$FloatRegister, $src$$FloatRegister, 13709 MacroAssembler::VELEM_SIZE_8, quad); 13710 %} 13711 ins_pipe( ialu_reg_reg ); // FIXME 13712 %} 13713 13714 instruct vneg16B_reg(vecX dst, vecX src) %{ 13715 predicate(n->as_Vector()->length_in_bytes() == 16); 13716 effect(DEF dst, USE src); 13717 size(4); 13718 ins_cost(DEFAULT_COST); // FIXME 13719 format %{ "VNEG.S8 $dst.Q,$src.Q\t! neg0 packed16B" %} 13720 ins_encode %{ 13721 bool _float = false; 13722 bool quad = true; 13723 __ vnegI($dst$$FloatRegister, $src$$FloatRegister, 13724 MacroAssembler::VELEM_SIZE_8, quad); 13725 %} 13726 ins_pipe( ialu_reg_reg ); // FIXME 13727 %} 13728 13729 // ------------------------------ Shift --------------------------------------- 13730 13731 instruct vslcntD(vecD dst, iRegI cnt) %{ 13732 predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd()); 13733 match(Set dst (LShiftCntV cnt)); 13734 size(4); 13735 ins_cost(DEFAULT_COST); // FIXME 13736 expand %{ 13737 Repl8B_reg_simd(dst, cnt); 13738 %} 13739 %} 13740 13741 instruct vslcntX(vecX dst, iRegI cnt) %{ 13742 predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd()); 13743 match(Set dst (LShiftCntV cnt)); 13744 size(4); 13745 ins_cost(DEFAULT_COST); // FIXME 13746 expand %{ 13747 Repl16B_reg(dst, cnt); 13748 %} 13749 %} 13750 13751 // Low bits of vector "shift" elements are used, so it 13752 // doesn't matter if we treat it as ints or bytes here. 13753 instruct vsrcntD(vecD dst, iRegI cnt) %{ 13754 predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd()); 13755 match(Set dst (RShiftCntV cnt)); 13756 size(4*2); 13757 ins_cost(DEFAULT_COST*2); // FIXME 13758 13759 format %{ "VDUP.8 $dst.D,$cnt\n\t" 13760 "VNEG.S8 $dst.D,$dst.D\t! neg packed8B" %} 13761 ins_encode %{ 13762 bool quad = false; 13763 __ vdupI($dst$$FloatRegister, $cnt$$Register, 13764 MacroAssembler::VELEM_SIZE_8, quad); 13765 __ vnegI($dst$$FloatRegister, $dst$$FloatRegister, 13766 MacroAssembler::VELEM_SIZE_8, quad); 13767 %} 13768 ins_pipe( ialu_reg_reg ); // FIXME 13769 %} 13770 13771 instruct vsrcntX(vecX dst, iRegI cnt) %{ 13772 predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd()); 13773 match(Set dst (RShiftCntV cnt)); 13774 size(4*2); 13775 ins_cost(DEFAULT_COST*2); // FIXME 13776 format %{ "VDUP.8 $dst.Q,$cnt\n\t" 13777 "VNEG.S8 $dst.Q,$dst.Q\t! neg packed16B" %} 13778 ins_encode %{ 13779 bool quad = true; 13780 __ vdupI($dst$$FloatRegister, $cnt$$Register, 13781 MacroAssembler::VELEM_SIZE_8, quad); 13782 __ vnegI($dst$$FloatRegister, $dst$$FloatRegister, 13783 MacroAssembler::VELEM_SIZE_8, quad); 13784 %} 13785 ins_pipe( ialu_reg_reg ); // FIXME 13786 %} 13787 13788 // Byte vector logical left/right shift based on sign 13789 instruct vsh8B_reg(vecD dst, vecD src, vecD shift) %{ 13790 predicate(n->as_Vector()->length() == 8); 13791 effect(DEF dst, USE src, USE shift); 13792 size(4); 13793 ins_cost(DEFAULT_COST); // FIXME 13794 format %{ 13795 "VSHL.U8 $dst.D,$src.D,$shift.D\t! logical left/right shift packed8B" 13796 %} 13797 ins_encode %{ 13798 bool quad = false; 13799 __ vshlUI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister, 13800 MacroAssembler::VELEM_SIZE_8, quad); 13801 %} 13802 ins_pipe( ialu_reg_reg ); // FIXME 13803 %} 13804 13805 instruct vsh16B_reg(vecX dst, vecX src, vecX shift) %{ 13806 predicate(n->as_Vector()->length() == 16); 13807 effect(DEF dst, USE src, USE shift); 13808 size(4); 13809 ins_cost(DEFAULT_COST); // FIXME 13810 format %{ 13811 "VSHL.U8 $dst.Q,$src.Q,$shift.Q\t! logical left/right shift packed16B" 13812 %} 13813 ins_encode %{ 13814 bool quad = true; 13815 __ vshlUI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister, 13816 MacroAssembler::VELEM_SIZE_8, quad); 13817 %} 13818 ins_pipe( ialu_reg_reg ); // FIXME 13819 %} 13820 13821 // Shorts/Char vector logical left/right shift based on sign 13822 instruct vsh4S_reg(vecD dst, vecD src, vecD shift) %{ 13823 predicate(n->as_Vector()->length() == 4); 13824 effect(DEF dst, USE src, USE shift); 13825 size(4); 13826 ins_cost(DEFAULT_COST); // FIXME 13827 format %{ 13828 "VSHL.U16 $dst.D,$src.D,$shift.D\t! logical left/right shift packed4S" 13829 %} 13830 ins_encode %{ 13831 bool quad = false; 13832 __ vshlUI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister, 13833 MacroAssembler::VELEM_SIZE_16, quad); 13834 %} 13835 ins_pipe( ialu_reg_reg ); // FIXME 13836 %} 13837 13838 instruct vsh8S_reg(vecX dst, vecX src, vecX shift) %{ 13839 predicate(n->as_Vector()->length() == 8); 13840 effect(DEF dst, USE src, USE shift); 13841 size(4); 13842 ins_cost(DEFAULT_COST); // FIXME 13843 format %{ 13844 "VSHL.U16 $dst.Q,$src.Q,$shift.Q\t! logical left/right shift packed8S" 13845 %} 13846 ins_encode %{ 13847 bool quad = true; 13848 __ vshlUI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister, 13849 MacroAssembler::VELEM_SIZE_16, quad); 13850 %} 13851 ins_pipe( ialu_reg_reg ); // FIXME 13852 %} 13853 13854 // Integers vector logical left/right shift based on sign 13855 instruct vsh2I_reg(vecD dst, vecD src, vecD shift) %{ 13856 predicate(n->as_Vector()->length() == 2); 13857 effect(DEF dst, USE src, USE shift); 13858 size(4); 13859 ins_cost(DEFAULT_COST); // FIXME 13860 format %{ 13861 "VSHL.U32 $dst.D,$src.D,$shift.D\t! logical left/right shift packed2I" 13862 %} 13863 ins_encode %{ 13864 bool quad = false; 13865 __ vshlUI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister, 13866 MacroAssembler::VELEM_SIZE_32, quad); 13867 %} 13868 ins_pipe( ialu_reg_reg ); // FIXME 13869 %} 13870 13871 instruct vsh4I_reg(vecX dst, vecX src, vecX shift) %{ 13872 predicate(n->as_Vector()->length() == 4); 13873 effect(DEF dst, USE src, USE shift); 13874 size(4); 13875 ins_cost(DEFAULT_COST); // FIXME 13876 format %{ 13877 "VSHL.U32 $dst.Q,$src.Q,$shift.Q\t! logical left/right shift packed4I" 13878 %} 13879 ins_encode %{ 13880 bool quad = true; 13881 __ vshlUI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister, 13882 MacroAssembler::VELEM_SIZE_32, quad); 13883 %} 13884 ins_pipe( ialu_reg_reg ); // FIXME 13885 %} 13886 13887 // Longs vector logical left/right shift based on sign 13888 instruct vsh2L_reg(vecX dst, vecX src, vecX shift) %{ 13889 predicate(n->as_Vector()->length() == 2); 13890 effect(DEF dst, USE src, USE shift); 13891 size(4); 13892 ins_cost(DEFAULT_COST); // FIXME 13893 format %{ 13894 "VSHL.U64 $dst.Q,$src.Q,$shift.Q\t! logical left/right shift packed2L" 13895 %} 13896 ins_encode %{ 13897 bool quad = true; 13898 __ vshlUI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister, 13899 MacroAssembler::VELEM_SIZE_64, quad); 13900 %} 13901 ins_pipe( ialu_reg_reg ); // FIXME 13902 %} 13903 13904 // ------------------------------ LeftShift ----------------------------------- 13905 13906 // Byte vector left shift 13907 instruct vsl8B_reg(vecD dst, vecD src, vecD shift) %{ 13908 predicate(n->as_Vector()->length() == 8); 13909 match(Set dst (LShiftVB src shift)); 13910 size(4*1); 13911 ins_cost(DEFAULT_COST*1); // FIXME 13912 expand %{ 13913 vsh8B_reg(dst, src, shift); 13914 %} 13915 %} 13916 13917 instruct vsl16B_reg(vecX dst, vecX src, vecX shift) %{ 13918 predicate(n->as_Vector()->length() == 16); 13919 match(Set dst (LShiftVB src shift)); 13920 size(4*1); 13921 ins_cost(DEFAULT_COST*1); // FIXME 13922 expand %{ 13923 vsh16B_reg(dst, src, shift); 13924 %} 13925 %} 13926 13927 instruct vsl8B_immI(vecD dst, vecD src, immI shift) %{ 13928 predicate(n->as_Vector()->length() == 8); 13929 match(Set dst (LShiftVB src shift)); 13930 size(4); 13931 ins_cost(DEFAULT_COST); // FIXME 13932 format %{ 13933 "VSHL.I8 $dst.D,$src.D,$shift\t! logical left shift packed8B" 13934 %} 13935 ins_encode %{ 13936 bool quad = false; 13937 __ vshli($dst$$FloatRegister, $src$$FloatRegister, 8, $shift$$constant, 13938 quad); 13939 %} 13940 ins_pipe( ialu_reg_reg ); // FIXME 13941 %} 13942 13943 instruct vsl16B_immI(vecX dst, vecX src, immI shift) %{ 13944 predicate(n->as_Vector()->length() == 16); 13945 match(Set dst (LShiftVB src shift)); 13946 size(4); 13947 ins_cost(DEFAULT_COST); // FIXME 13948 format %{ 13949 "VSHL.I8 $dst.Q,$src.Q,$shift\t! logical left shift packed16B" 13950 %} 13951 ins_encode %{ 13952 bool quad = true; 13953 __ vshli($dst$$FloatRegister, $src$$FloatRegister, 8, $shift$$constant, 13954 quad); 13955 %} 13956 ins_pipe( ialu_reg_reg ); // FIXME 13957 %} 13958 13959 // Shorts/Chars vector logical left/right shift 13960 instruct vsl4S_reg(vecD dst, vecD src, vecD shift) %{ 13961 predicate(n->as_Vector()->length() == 4); 13962 match(Set dst (LShiftVS src shift)); 13963 match(Set dst (URShiftVS src shift)); 13964 size(4*1); 13965 ins_cost(DEFAULT_COST*1); // FIXME 13966 expand %{ 13967 vsh4S_reg(dst, src, shift); 13968 %} 13969 %} 13970 13971 instruct vsl8S_reg(vecX dst, vecX src, vecX shift) %{ 13972 predicate(n->as_Vector()->length() == 8); 13973 match(Set dst (LShiftVS src shift)); 13974 match(Set dst (URShiftVS src shift)); 13975 size(4*1); 13976 ins_cost(DEFAULT_COST*1); // FIXME 13977 expand %{ 13978 vsh8S_reg(dst, src, shift); 13979 %} 13980 %} 13981 13982 instruct vsl4S_immI(vecD dst, vecD src, immI shift) %{ 13983 predicate(n->as_Vector()->length() == 4); 13984 match(Set dst (LShiftVS src shift)); 13985 size(4); 13986 ins_cost(DEFAULT_COST); // FIXME 13987 format %{ 13988 "VSHL.I16 $dst.D,$src.D,$shift\t! logical left shift packed4S" 13989 %} 13990 ins_encode %{ 13991 bool quad = false; 13992 __ vshli($dst$$FloatRegister, $src$$FloatRegister, 16, $shift$$constant, 13993 quad); 13994 %} 13995 ins_pipe( ialu_reg_reg ); // FIXME 13996 %} 13997 13998 instruct vsl8S_immI(vecX dst, vecX src, immI shift) %{ 13999 predicate(n->as_Vector()->length() == 8); 14000 match(Set dst (LShiftVS src shift)); 14001 size(4); 14002 ins_cost(DEFAULT_COST); // FIXME 14003 format %{ 14004 "VSHL.I16 $dst.Q,$src.Q,$shift\t! logical left shift packed8S" 14005 %} 14006 ins_encode %{ 14007 bool quad = true; 14008 __ vshli($dst$$FloatRegister, $src$$FloatRegister, 16, $shift$$constant, 14009 quad); 14010 %} 14011 ins_pipe( ialu_reg_reg ); // FIXME 14012 %} 14013 14014 // Integers vector logical left/right shift 14015 instruct vsl2I_reg(vecD dst, vecD src, vecD shift) %{ 14016 predicate(n->as_Vector()->length() == 2 && VM_Version::has_simd()); 14017 match(Set dst (LShiftVI src shift)); 14018 match(Set dst (URShiftVI src shift)); 14019 size(4*1); 14020 ins_cost(DEFAULT_COST*1); // FIXME 14021 expand %{ 14022 vsh2I_reg(dst, src, shift); 14023 %} 14024 %} 14025 14026 instruct vsl4I_reg(vecX dst, vecX src, vecX shift) %{ 14027 predicate(n->as_Vector()->length() == 4 && VM_Version::has_simd()); 14028 match(Set dst (LShiftVI src shift)); 14029 match(Set dst (URShiftVI src shift)); 14030 size(4*1); 14031 ins_cost(DEFAULT_COST*1); // FIXME 14032 expand %{ 14033 vsh4I_reg(dst, src, shift); 14034 %} 14035 %} 14036 14037 instruct vsl2I_immI(vecD dst, vecD src, immI shift) %{ 14038 predicate(n->as_Vector()->length() == 2 && VM_Version::has_simd()); 14039 match(Set dst (LShiftVI src shift)); 14040 size(4); 14041 ins_cost(DEFAULT_COST); // FIXME 14042 format %{ 14043 "VSHL.I32 $dst.D,$src.D,$shift\t! logical left shift packed2I" 14044 %} 14045 ins_encode %{ 14046 bool quad = false; 14047 __ vshli($dst$$FloatRegister, $src$$FloatRegister, 32, $shift$$constant, 14048 quad); 14049 %} 14050 ins_pipe( ialu_reg_reg ); // FIXME 14051 %} 14052 14053 instruct vsl4I_immI(vecX dst, vecX src, immI shift) %{ 14054 predicate(n->as_Vector()->length() == 4 && VM_Version::has_simd()); 14055 match(Set dst (LShiftVI src shift)); 14056 size(4); 14057 ins_cost(DEFAULT_COST); // FIXME 14058 format %{ 14059 "VSHL.I32 $dst.Q,$src.Q,$shift\t! logical left shift packed4I" 14060 %} 14061 ins_encode %{ 14062 bool quad = true; 14063 __ vshli($dst$$FloatRegister, $src$$FloatRegister, 32, $shift$$constant, 14064 quad); 14065 %} 14066 ins_pipe( ialu_reg_reg ); // FIXME 14067 %} 14068 14069 // Longs vector logical left/right shift 14070 instruct vsl2L_reg(vecX dst, vecX src, vecX shift) %{ 14071 predicate(n->as_Vector()->length() == 2); 14072 match(Set dst (LShiftVL src shift)); 14073 match(Set dst (URShiftVL src shift)); 14074 size(4*1); 14075 ins_cost(DEFAULT_COST*1); // FIXME 14076 expand %{ 14077 vsh2L_reg(dst, src, shift); 14078 %} 14079 %} 14080 14081 instruct vsl2L_immI(vecX dst, vecX src, immI shift) %{ 14082 predicate(n->as_Vector()->length() == 2); 14083 match(Set dst (LShiftVL src shift)); 14084 size(4); 14085 ins_cost(DEFAULT_COST); // FIXME 14086 format %{ 14087 "VSHL.I64 $dst.Q,$src.Q,$shift\t! logical left shift packed2L" 14088 %} 14089 ins_encode %{ 14090 bool quad = true; 14091 __ vshli($dst$$FloatRegister, $src$$FloatRegister, 64, $shift$$constant, 14092 quad); 14093 %} 14094 ins_pipe( ialu_reg_reg ); // FIXME 14095 %} 14096 14097 // ----------------------- LogicalRightShift ----------------------------------- 14098 14099 // Bytes/Shorts vector logical right shift produces incorrect Java result 14100 // for negative data because java code convert short value into int with 14101 // sign extension before a shift. 14102 14103 // Chars vector logical right shift 14104 instruct vsrl4S_immI(vecD dst, vecD src, immI shift) %{ 14105 predicate(n->as_Vector()->length() == 4); 14106 match(Set dst (URShiftVS src shift)); 14107 size(4); 14108 ins_cost(DEFAULT_COST); // FIXME 14109 format %{ 14110 "VSHR.U16 $dst.D,$src.D,$shift\t! logical right shift packed4S" 14111 %} 14112 ins_encode %{ 14113 bool quad = false; 14114 __ vshrUI($dst$$FloatRegister, $src$$FloatRegister, 16, $shift$$constant, 14115 quad); 14116 %} 14117 ins_pipe( ialu_reg_reg ); // FIXME 14118 %} 14119 14120 instruct vsrl8S_immI(vecX dst, vecX src, immI shift) %{ 14121 predicate(n->as_Vector()->length() == 8); 14122 match(Set dst (URShiftVS src shift)); 14123 size(4); 14124 ins_cost(DEFAULT_COST); // FIXME 14125 format %{ 14126 "VSHR.U16 $dst.Q,$src.Q,$shift\t! logical right shift packed8S" 14127 %} 14128 ins_encode %{ 14129 bool quad = true; 14130 __ vshrUI($dst$$FloatRegister, $src$$FloatRegister, 16, $shift$$constant, 14131 quad); 14132 %} 14133 ins_pipe( ialu_reg_reg ); // FIXME 14134 %} 14135 14136 // Integers vector logical right shift 14137 instruct vsrl2I_immI(vecD dst, vecD src, immI shift) %{ 14138 predicate(n->as_Vector()->length() == 2 && VM_Version::has_simd()); 14139 match(Set dst (URShiftVI src shift)); 14140 size(4); 14141 ins_cost(DEFAULT_COST); // FIXME 14142 format %{ 14143 "VSHR.U32 $dst.D,$src.D,$shift\t! logical right shift packed2I" 14144 %} 14145 ins_encode %{ 14146 bool quad = false; 14147 __ vshrUI($dst$$FloatRegister, $src$$FloatRegister, 32, $shift$$constant, 14148 quad); 14149 %} 14150 ins_pipe( ialu_reg_reg ); // FIXME 14151 %} 14152 14153 instruct vsrl4I_immI(vecX dst, vecX src, immI shift) %{ 14154 predicate(n->as_Vector()->length() == 4 && VM_Version::has_simd()); 14155 match(Set dst (URShiftVI src shift)); 14156 size(4); 14157 ins_cost(DEFAULT_COST); // FIXME 14158 format %{ 14159 "VSHR.U32 $dst.Q,$src.Q,$shift\t! logical right shift packed4I" 14160 %} 14161 ins_encode %{ 14162 bool quad = true; 14163 __ vshrUI($dst$$FloatRegister, $src$$FloatRegister, 32, $shift$$constant, 14164 quad); 14165 %} 14166 ins_pipe( ialu_reg_reg ); // FIXME 14167 %} 14168 14169 // Longs vector logical right shift 14170 instruct vsrl2L_immI(vecX dst, vecX src, immI shift) %{ 14171 predicate(n->as_Vector()->length() == 2); 14172 match(Set dst (URShiftVL src shift)); 14173 size(4); 14174 ins_cost(DEFAULT_COST); // FIXME 14175 format %{ 14176 "VSHR.U64 $dst.Q,$src.Q,$shift\t! logical right shift packed2L" 14177 %} 14178 ins_encode %{ 14179 bool quad = true; 14180 __ vshrUI($dst$$FloatRegister, $src$$FloatRegister, 64, $shift$$constant, 14181 quad); 14182 %} 14183 ins_pipe( ialu_reg_reg ); // FIXME 14184 %} 14185 14186 // ------------------- ArithmeticRightShift ----------------------------------- 14187 14188 // Bytes vector arithmetic left/right shift based on sign 14189 instruct vsha8B_reg(vecD dst, vecD src, vecD shift) %{ 14190 predicate(n->as_Vector()->length() == 8); 14191 effect(DEF dst, USE src, USE shift); 14192 size(4); 14193 ins_cost(DEFAULT_COST); // FIXME 14194 format %{ 14195 "VSHL.S8 $dst.D,$src.D,$shift.D\t! arithmetic right shift packed8B" 14196 %} 14197 ins_encode %{ 14198 bool quad = false; 14199 __ vshlSI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister, 14200 MacroAssembler::VELEM_SIZE_8, quad); 14201 %} 14202 ins_pipe( ialu_reg_reg ); // FIXME 14203 %} 14204 14205 instruct vsha16B_reg(vecX dst, vecX src, vecX shift) %{ 14206 predicate(n->as_Vector()->length() == 16); 14207 effect(DEF dst, USE src, USE shift); 14208 size(4); 14209 ins_cost(DEFAULT_COST); // FIXME 14210 format %{ 14211 "VSHL.S8 $dst.Q,$src.Q,$shift.Q\t! arithmetic right shift packed16B" 14212 %} 14213 ins_encode %{ 14214 bool quad = true; 14215 __ vshlSI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister, 14216 MacroAssembler::VELEM_SIZE_8, quad); 14217 %} 14218 ins_pipe( ialu_reg_reg ); // FIXME 14219 %} 14220 14221 // Shorts vector arithmetic left/right shift based on sign 14222 instruct vsha4S_reg(vecD dst, vecD src, vecD shift) %{ 14223 predicate(n->as_Vector()->length() == 4); 14224 effect(DEF dst, USE src, USE shift); 14225 size(4); 14226 ins_cost(DEFAULT_COST); // FIXME 14227 format %{ 14228 "VSHL.S16 $dst.D,$src.D,$shift.D\t! arithmetic right shift packed4S" 14229 %} 14230 ins_encode %{ 14231 bool quad = false; 14232 __ vshlSI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister, 14233 MacroAssembler::VELEM_SIZE_16, quad); 14234 %} 14235 ins_pipe( ialu_reg_reg ); // FIXME 14236 %} 14237 14238 instruct vsha8S_reg(vecX dst, vecX src, vecX shift) %{ 14239 predicate(n->as_Vector()->length() == 8); 14240 effect(DEF dst, USE src, USE shift); 14241 size(4); 14242 ins_cost(DEFAULT_COST); // FIXME 14243 format %{ 14244 "VSHL.S16 $dst.Q,$src.Q,$shift.Q\t! arithmetic right shift packed8S" 14245 %} 14246 ins_encode %{ 14247 bool quad = true; 14248 __ vshlSI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister, 14249 MacroAssembler::VELEM_SIZE_16, quad); 14250 %} 14251 ins_pipe( ialu_reg_reg ); // FIXME 14252 %} 14253 14254 // Integers vector arithmetic left/right shift based on sign 14255 instruct vsha2I_reg(vecD dst, vecD src, vecD shift) %{ 14256 predicate(n->as_Vector()->length() == 2); 14257 effect(DEF dst, USE src, USE shift); 14258 size(4); 14259 ins_cost(DEFAULT_COST); // FIXME 14260 format %{ 14261 "VSHL.S32 $dst.D,$src.D,$shift.D\t! arithmetic right shift packed2I" 14262 %} 14263 ins_encode %{ 14264 bool quad = false; 14265 __ vshlSI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister, 14266 MacroAssembler::VELEM_SIZE_32, quad); 14267 %} 14268 ins_pipe( ialu_reg_reg ); // FIXME 14269 %} 14270 14271 instruct vsha4I_reg(vecX dst, vecX src, vecX shift) %{ 14272 predicate(n->as_Vector()->length() == 4); 14273 effect(DEF dst, USE src, USE shift); 14274 size(4); 14275 ins_cost(DEFAULT_COST); // FIXME 14276 format %{ 14277 "VSHL.S32 $dst.Q,$src.Q,$shift.Q\t! arithmetic right shift packed4I" 14278 %} 14279 ins_encode %{ 14280 bool quad = true; 14281 __ vshlSI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister, 14282 MacroAssembler::VELEM_SIZE_32, quad); 14283 %} 14284 ins_pipe( ialu_reg_reg ); // FIXME 14285 %} 14286 14287 // Longs vector arithmetic left/right shift based on sign 14288 instruct vsha2L_reg(vecX dst, vecX src, vecX shift) %{ 14289 predicate(n->as_Vector()->length() == 2); 14290 effect(DEF dst, USE src, USE shift); 14291 size(4); 14292 ins_cost(DEFAULT_COST); // FIXME 14293 format %{ 14294 "VSHL.S64 $dst.Q,$src.Q,$shift.Q\t! arithmetic right shift packed2L" 14295 %} 14296 ins_encode %{ 14297 bool quad = true; 14298 __ vshlSI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister, 14299 MacroAssembler::VELEM_SIZE_64, quad); 14300 %} 14301 ins_pipe( ialu_reg_reg ); // FIXME 14302 %} 14303 14304 // Byte vector arithmetic right shift 14305 14306 instruct vsra8B_reg(vecD dst, vecD src, vecD shift) %{ 14307 predicate(n->as_Vector()->length() == 8); 14308 match(Set dst (RShiftVB src shift)); 14309 size(4); 14310 ins_cost(DEFAULT_COST); // FIXME 14311 expand %{ 14312 vsha8B_reg(dst, src, shift); 14313 %} 14314 %} 14315 14316 instruct vsrl16B_reg(vecX dst, vecX src, vecX shift) %{ 14317 predicate(n->as_Vector()->length() == 16); 14318 match(Set dst (RShiftVB src shift)); 14319 size(4); 14320 ins_cost(DEFAULT_COST); // FIXME 14321 expand %{ 14322 vsha16B_reg(dst, src, shift); 14323 %} 14324 %} 14325 14326 instruct vsrl8B_immI(vecD dst, vecD src, immI shift) %{ 14327 predicate(n->as_Vector()->length() == 8); 14328 match(Set dst (RShiftVB src shift)); 14329 size(4); 14330 ins_cost(DEFAULT_COST); // FIXME 14331 format %{ 14332 "VSHR.S8 $dst.D,$src.D,$shift\t! logical right shift packed8B" 14333 %} 14334 ins_encode %{ 14335 bool quad = false; 14336 __ vshrSI($dst$$FloatRegister, $src$$FloatRegister, 8, $shift$$constant, 14337 quad); 14338 %} 14339 ins_pipe( ialu_reg_reg ); // FIXME 14340 %} 14341 14342 instruct vsrl16B_immI(vecX dst, vecX src, immI shift) %{ 14343 predicate(n->as_Vector()->length() == 16); 14344 match(Set dst (RShiftVB src shift)); 14345 size(4); 14346 ins_cost(DEFAULT_COST); // FIXME 14347 format %{ 14348 "VSHR.S8 $dst.Q,$src.Q,$shift\t! logical right shift packed16B" 14349 %} 14350 ins_encode %{ 14351 bool quad = true; 14352 __ vshrSI($dst$$FloatRegister, $src$$FloatRegister, 8, $shift$$constant, 14353 quad); 14354 %} 14355 ins_pipe( ialu_reg_reg ); // FIXME 14356 %} 14357 14358 // Shorts vector arithmetic right shift 14359 instruct vsra4S_reg(vecD dst, vecD src, vecD shift) %{ 14360 predicate(n->as_Vector()->length() == 4); 14361 match(Set dst (RShiftVS src shift)); 14362 size(4); 14363 ins_cost(DEFAULT_COST); // FIXME 14364 expand %{ 14365 vsha4S_reg(dst, src, shift); 14366 %} 14367 %} 14368 14369 instruct vsra8S_reg(vecX dst, vecX src, vecX shift) %{ 14370 predicate(n->as_Vector()->length() == 8); 14371 match(Set dst (RShiftVS src shift)); 14372 size(4); 14373 ins_cost(DEFAULT_COST); // FIXME 14374 expand %{ 14375 vsha8S_reg(dst, src, shift); 14376 %} 14377 %} 14378 14379 instruct vsra4S_immI(vecD dst, vecD src, immI shift) %{ 14380 predicate(n->as_Vector()->length() == 4); 14381 match(Set dst (RShiftVS src shift)); 14382 size(4); 14383 ins_cost(DEFAULT_COST); // FIXME 14384 format %{ 14385 "VSHR.S16 $dst.D,$src.D,$shift\t! logical right shift packed4S" 14386 %} 14387 ins_encode %{ 14388 bool quad = false; 14389 __ vshrSI($dst$$FloatRegister, $src$$FloatRegister, 16, $shift$$constant, 14390 quad); 14391 %} 14392 ins_pipe( ialu_reg_reg ); // FIXME 14393 %} 14394 14395 instruct vsra8S_immI(vecX dst, vecX src, immI shift) %{ 14396 predicate(n->as_Vector()->length() == 8); 14397 match(Set dst (RShiftVS src shift)); 14398 size(4); 14399 ins_cost(DEFAULT_COST); // FIXME 14400 format %{ 14401 "VSHR.S16 $dst.Q,$src.Q,$shift\t! logical right shift packed8S" 14402 %} 14403 ins_encode %{ 14404 bool quad = true; 14405 __ vshrSI($dst$$FloatRegister, $src$$FloatRegister, 16, $shift$$constant, 14406 quad); 14407 %} 14408 ins_pipe( ialu_reg_reg ); // FIXME 14409 %} 14410 14411 // Integers vector arithmetic right shift 14412 instruct vsra2I_reg(vecD dst, vecD src, vecD shift) %{ 14413 predicate(n->as_Vector()->length() == 2); 14414 match(Set dst (RShiftVI src shift)); 14415 size(4); 14416 ins_cost(DEFAULT_COST); // FIXME 14417 expand %{ 14418 vsha2I_reg(dst, src, shift); 14419 %} 14420 %} 14421 14422 instruct vsra4I_reg(vecX dst, vecX src, vecX shift) %{ 14423 predicate(n->as_Vector()->length() == 4); 14424 match(Set dst (RShiftVI src shift)); 14425 size(4); 14426 ins_cost(DEFAULT_COST); // FIXME 14427 expand %{ 14428 vsha4I_reg(dst, src, shift); 14429 %} 14430 %} 14431 14432 instruct vsra2I_immI(vecD dst, vecD src, immI shift) %{ 14433 predicate(n->as_Vector()->length() == 2); 14434 match(Set dst (RShiftVI src shift)); 14435 size(4); 14436 ins_cost(DEFAULT_COST); // FIXME 14437 format %{ 14438 "VSHR.S32 $dst.D,$src.D,$shift\t! logical right shift packed2I" 14439 %} 14440 ins_encode %{ 14441 bool quad = false; 14442 __ vshrSI($dst$$FloatRegister, $src$$FloatRegister, 32, $shift$$constant, 14443 quad); 14444 %} 14445 ins_pipe( ialu_reg_reg ); // FIXME 14446 %} 14447 14448 instruct vsra4I_immI(vecX dst, vecX src, immI shift) %{ 14449 predicate(n->as_Vector()->length() == 4); 14450 match(Set dst (RShiftVI src shift)); 14451 size(4); 14452 ins_cost(DEFAULT_COST); // FIXME 14453 format %{ 14454 "VSHR.S32 $dst.Q,$src.Q,$shift\t! logical right shift packed4I" 14455 %} 14456 ins_encode %{ 14457 bool quad = true; 14458 __ vshrSI($dst$$FloatRegister, $src$$FloatRegister, 32, $shift$$constant, 14459 quad); 14460 %} 14461 ins_pipe( ialu_reg_reg ); // FIXME 14462 %} 14463 14464 // Longs vector arithmetic right shift 14465 instruct vsra2L_reg(vecX dst, vecX src, vecX shift) %{ 14466 predicate(n->as_Vector()->length() == 2); 14467 match(Set dst (RShiftVL src shift)); 14468 size(4); 14469 ins_cost(DEFAULT_COST); // FIXME 14470 expand %{ 14471 vsha2L_reg(dst, src, shift); 14472 %} 14473 %} 14474 14475 instruct vsra2L_immI(vecX dst, vecX src, immI shift) %{ 14476 predicate(n->as_Vector()->length() == 2); 14477 match(Set dst (RShiftVL src shift)); 14478 size(4); 14479 ins_cost(DEFAULT_COST); // FIXME 14480 format %{ 14481 "VSHR.S64 $dst.Q,$src.Q,$shift\t! logical right shift packed2L" 14482 %} 14483 ins_encode %{ 14484 bool quad = true; 14485 __ vshrSI($dst$$FloatRegister, $src$$FloatRegister, 64, $shift$$constant, 14486 quad); 14487 %} 14488 ins_pipe( ialu_reg_reg ); // FIXME 14489 %} 14490 14491 // --------------------------------- AND -------------------------------------- 14492 14493 instruct vandD(vecD dst, vecD src1, vecD src2) %{ 14494 predicate(n->as_Vector()->length_in_bytes() == 8); 14495 match(Set dst (AndV src1 src2)); 14496 format %{ "VAND $dst.D,$src1.D,$src2.D\t! and vectors (8 bytes)" %} 14497 ins_encode %{ 14498 bool quad = false; 14499 __ vandI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 14500 quad); 14501 %} 14502 ins_pipe( ialu_reg_reg ); // FIXME 14503 %} 14504 14505 instruct vandX(vecX dst, vecX src1, vecX src2) %{ 14506 predicate(n->as_Vector()->length_in_bytes() == 16); 14507 match(Set dst (AndV src1 src2)); 14508 format %{ "VAND $dst.Q,$src1.Q,$src2.Q\t! and vectors (16 bytes)" %} 14509 ins_encode %{ 14510 bool quad = true; 14511 __ vandI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 14512 quad); 14513 %} 14514 ins_pipe( ialu_reg_reg ); // FIXME 14515 %} 14516 14517 // --------------------------------- OR --------------------------------------- 14518 14519 instruct vorD(vecD dst, vecD src1, vecD src2) %{ 14520 predicate(n->as_Vector()->length_in_bytes() == 8); 14521 match(Set dst (OrV src1 src2)); 14522 format %{ "VOR $dst.D,$src1.D,$src2.D\t! and vectors (8 bytes)" %} 14523 ins_encode %{ 14524 bool quad = false; 14525 __ vorI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 14526 quad); 14527 %} 14528 ins_pipe( ialu_reg_reg ); // FIXME 14529 %} 14530 14531 instruct vorX(vecX dst, vecX src1, vecX src2) %{ 14532 predicate(n->as_Vector()->length_in_bytes() == 16); 14533 match(Set dst (OrV src1 src2)); 14534 format %{ "VOR $dst.Q,$src1.Q,$src2.Q\t! and vectors (16 bytes)" %} 14535 ins_encode %{ 14536 bool quad = true; 14537 __ vorI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 14538 quad); 14539 %} 14540 ins_pipe( ialu_reg_reg ); // FIXME 14541 %} 14542 14543 // --------------------------------- XOR -------------------------------------- 14544 14545 instruct vxorD(vecD dst, vecD src1, vecD src2) %{ 14546 predicate(n->as_Vector()->length_in_bytes() == 8); 14547 match(Set dst (XorV src1 src2)); 14548 format %{ "VXOR $dst.D,$src1.D,$src2.D\t! and vectors (8 bytes)" %} 14549 ins_encode %{ 14550 bool quad = false; 14551 __ vxorI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 14552 quad); 14553 %} 14554 ins_pipe( ialu_reg_reg ); // FIXME 14555 %} 14556 14557 instruct vxorX(vecX dst, vecX src1, vecX src2) %{ 14558 predicate(n->as_Vector()->length_in_bytes() == 16); 14559 match(Set dst (XorV src1 src2)); 14560 format %{ "VXOR $dst.Q,$src1.Q,$src2.Q\t! and vectors (16 bytes)" %} 14561 ins_encode %{ 14562 bool quad = true; 14563 __ vxorI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 14564 quad); 14565 %} 14566 ins_pipe( ialu_reg_reg ); // FIXME 14567 %} 14568 14569 14570 //----------PEEPHOLE RULES----------------------------------------------------- 14571 // These must follow all instruction definitions as they use the names 14572 // defined in the instructions definitions. 14573 // 14574 // peepmatch ( root_instr_name [preceding_instruction]* ); 14575 // 14576 // peepconstraint %{ 14577 // (instruction_number.operand_name relational_op instruction_number.operand_name 14578 // [, ...] ); 14579 // // instruction numbers are zero-based using left to right order in peepmatch 14580 // 14581 // peepreplace ( instr_name ( [instruction_number.operand_name]* ) ); 14582 // // provide an instruction_number.operand_name for each operand that appears 14583 // // in the replacement instruction's match rule 14584 // 14585 // ---------VM FLAGS--------------------------------------------------------- 14586 // 14587 // All peephole optimizations can be turned off using -XX:-OptoPeephole 14588 // 14589 // Each peephole rule is given an identifying number starting with zero and 14590 // increasing by one in the order seen by the parser. An individual peephole 14591 // can be enabled, and all others disabled, by using -XX:OptoPeepholeAt=# 14592 // on the command-line. 14593 // 14594 // ---------CURRENT LIMITATIONS---------------------------------------------- 14595 // 14596 // Only match adjacent instructions in same basic block 14597 // Only equality constraints 14598 // Only constraints between operands, not (0.dest_reg == EAX_enc) 14599 // Only one replacement instruction 14600 // 14601 // ---------EXAMPLE---------------------------------------------------------- 14602 // 14603 // // pertinent parts of existing instructions in architecture description 14604 // instruct movI(eRegI dst, eRegI src) %{ 14605 // match(Set dst (CopyI src)); 14606 // %} 14607 // 14608 // instruct incI_eReg(eRegI dst, immI1 src, eFlagsReg cr) %{ 14609 // match(Set dst (AddI dst src)); 14610 // effect(KILL cr); 14611 // %} 14612 // 14613 // // Change (inc mov) to lea 14614 // peephole %{ 14615 // // increment preceeded by register-register move 14616 // peepmatch ( incI_eReg movI ); 14617 // // require that the destination register of the increment 14618 // // match the destination register of the move 14619 // peepconstraint ( 0.dst == 1.dst ); 14620 // // construct a replacement instruction that sets 14621 // // the destination to ( move's source register + one ) 14622 // peepreplace ( incI_eReg_immI1( 0.dst 1.src 0.src ) ); 14623 // %} 14624 // 14625 14626 // // Change load of spilled value to only a spill 14627 // instruct storeI(memory mem, eRegI src) %{ 14628 // match(Set mem (StoreI mem src)); 14629 // %} 14630 // 14631 // instruct loadI(eRegI dst, memory mem) %{ 14632 // match(Set dst (LoadI mem)); 14633 // %} 14634 // 14635 // peephole %{ 14636 // peepmatch ( loadI storeI ); 14637 // peepconstraint ( 1.src == 0.dst, 1.mem == 0.mem ); 14638 // peepreplace ( storeI( 1.mem 1.mem 1.src ) ); 14639 // %} 14640 14641 //----------SMARTSPILL RULES--------------------------------------------------- 14642 // These must follow all instruction definitions as they use the names 14643 // defined in the instructions definitions. 14644 // 14645 // ARM will probably not have any of these rules due to RISC instruction set. 14646 14647 //----------PIPELINE----------------------------------------------------------- 14648 // Rules which define the behavior of the target architectures pipeline.