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// 37definitions %{ 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 54source_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? 64extern bool maybe_far_call(const CallNode *n); 65extern bool maybe_far_call(const MachCallNode *n); 66static 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 80extern bool PrintOptoAssembly; 81#endif 82 83class c2 { 84public: 85 static OptoRegPair return_value(int ideal_reg); 86}; 87 88class 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 106class 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 131source %{ 132#define __ _masm. 133 134static FloatRegister reg_to_FloatRegister_object(int register_encoding); 135static 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. 144bool SafePointNode::needs_polling_address_input() { 145 return true; 146} 147 148// emit an interrupt that is caught by the debugger (for debugging compiler) 149void emit_break(CodeBuffer &cbuf) { 150 MacroAssembler _masm(&cbuf); 151 __ breakpoint(); 152} 153 154#ifndef PRODUCT 155void MachBreakpointNode::format( PhaseRegAlloc *, outputStream *st ) const { 156 st->print("TA"); 157} 158#endif 159 160void MachBreakpointNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { 161 emit_break(cbuf); 162} 163 164uint MachBreakpointNode::size(PhaseRegAlloc *ra_) const { 165 return MachNode::size(ra_); 166} 167 168 169void emit_nop(CodeBuffer &cbuf) { 170 MacroAssembler _masm(&cbuf); 171 __ nop(); 172} 173 174 175void 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 200void emit_lo(CodeBuffer &cbuf, int val) { } 201void emit_hi(CodeBuffer &cbuf, int val) { } 202 203 204//============================================================================= 205const RegMask& MachConstantBaseNode::_out_RegMask = PTR_REG_mask(); 206 207int 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 221bool MachConstantBaseNode::requires_postalloc_expand() const { return false; } 222void MachConstantBaseNode::postalloc_expand(GrowableArray <Node *> *nodes, PhaseRegAlloc *ra_) { 223 ShouldNotReachHere(); 224} 225 226void 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 242uint MachConstantBaseNode::size(PhaseRegAlloc*) const { 243#ifdef AARCH64 244 return 5 * Assembler::InstructionSize; 245#else 246 return 8; 247#endif 248} 249 250#ifndef PRODUCT 251void 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 259void 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 294void 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 341uint MachPrologNode::size(PhaseRegAlloc *ra_) const { 342 return MachNode::size(ra_); 343} 344 345int MachPrologNode::reloc() const { 346 return 10; // a large enough number 347} 348 349//============================================================================= 350#ifndef PRODUCT 351void 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 380void 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 416uint 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 425int MachEpilogNode::reloc() const { 426 return 16; // a large enough number 427} 428 429const Pipeline * MachEpilogNode::pipeline() const { 430 return MachNode::pipeline_class(); 431} 432 433int 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 443enum RC { rc_bad, rc_int, rc_float, rc_stack }; 444static 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 453static 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 466uint 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 862void MachSpillCopyNode::format( PhaseRegAlloc *ra_, outputStream *st ) const { 863 implementation( NULL, ra_, false, st ); 864} 865#endif 866 867void MachSpillCopyNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { 868 implementation( &cbuf, ra_, false, NULL ); 869} 870 871uint MachSpillCopyNode::size(PhaseRegAlloc *ra_) const { 872 return implementation( NULL, ra_, true, NULL ); 873} 874 875//============================================================================= 876#ifndef PRODUCT 877void MachNopNode::format( PhaseRegAlloc *, outputStream *st ) const { 878 st->print("NOP \t# %d bytes pad for loops and calls", 4 * _count); 879} 880#endif 881 882void MachNopNode::emit(CodeBuffer &cbuf, PhaseRegAlloc * ) const { 883 MacroAssembler _masm(&cbuf); 884 for(int i = 0; i < _count; i += 1) { 885 __ nop(); 886 } 887} 888 889uint MachNopNode::size(PhaseRegAlloc *ra_) const { 890 return 4 * _count; 891} 892 893 894//============================================================================= 895#ifndef PRODUCT 896void 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 903void 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 921uint 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 934void 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 947void 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 965uint MachUEPNode::size(PhaseRegAlloc *ra_) const { 966 return MachNode::size(ra_); 967} 968 969 970//============================================================================= 971 972// Emit exception handler code. 973int 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 994int 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 1033const 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 1096const 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 1107const bool Matcher::has_predicated_vectors(void) { 1108 return false; 1109} 1110 1111const int Matcher::float_pressure(int default_pressure_threshold) { 1112 return default_pressure_threshold; 1113} 1114 1115int 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 1120const int Matcher::vector_width_in_bytes(BasicType bt) { 1121 return MaxVectorSize; 1122} 1123 1124// Vector ideal reg corresponding to specified size in bytes 1125const 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 1135const 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. 1140const 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 1145const 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. 1151const bool Matcher::misaligned_vectors_ok() { 1152 return false; 1153} 1154 1155// ARM doesn't support AES intrinsics 1156const bool Matcher::pass_original_key_for_aes() { 1157 return false; 1158} 1159 1160const 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. 1172bool 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 1182const 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. 1192const bool Matcher::init_array_count_is_in_bytes = true; 1193 1194#ifdef AARCH64 1195const int Matcher::long_cmove_cost() { return 1; } 1196#else 1197// Needs 2 CMOV's for longs. 1198const int Matcher::long_cmove_cost() { return 2; } 1199#endif 1200 1201#ifdef AARCH64 1202const int Matcher::float_cmove_cost() { return 1; } 1203#else 1204// CMOVF/CMOVD are expensive on ARM. 1205const 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)? 1209const 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 1215const bool Matcher::need_masked_shift_count = false; 1216#else 1217const bool Matcher::need_masked_shift_count = true; 1218#endif 1219 1220const 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? 1225bool 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 1229void Compile::reshape_address(AddPNode* addp) { 1230} 1231 1232bool Matcher::narrow_oop_use_complex_address() { 1233 NOT_LP64(ShouldNotCallThis()); 1234 assert(UseCompressedOops, "only for compressed oops code"); 1235 return false; 1236} 1237 1238bool Matcher::narrow_klass_use_complex_address() { 1239 NOT_LP64(ShouldNotCallThis()); 1240 assert(UseCompressedClassPointers, "only for compressed klass code"); 1241 return false; 1242} 1243 1244bool Matcher::const_oop_prefer_decode() { 1245 NOT_LP64(ShouldNotCallThis()); 1246 return true; 1247} 1248 1249bool 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. 1258const 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 1268const bool Matcher::misaligned_doubles_ok = true; 1269#else 1270const bool Matcher::misaligned_doubles_ok = false; 1271#endif 1272 1273// No-op on ARM. 1274void 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. 1279const 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. 1283bool 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 1293const bool Matcher::int_in_long = true; 1294#else 1295const 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. 1302bool 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 1318bool Matcher::is_spillable_arg( int reg ) { 1319 return can_be_java_arg(reg); 1320} 1321 1322bool Matcher::use_asm_for_ldiv_by_con( jlong divisor ) { 1323 return false; 1324} 1325 1326// Register for DIVI projection of divmodI 1327RegMask Matcher::divI_proj_mask() { 1328 ShouldNotReachHere(); 1329 return RegMask(); 1330} 1331 1332// Register for MODI projection of divmodI 1333RegMask Matcher::modI_proj_mask() { 1334 ShouldNotReachHere(); 1335 return RegMask(); 1336} 1337 1338// Register for DIVL projection of divmodL 1339RegMask Matcher::divL_proj_mask() { 1340 ShouldNotReachHere(); 1341 return RegMask(); 1342} 1343 1344// Register for MODL projection of divmodL 1345RegMask Matcher::modL_proj_mask() { 1346 ShouldNotReachHere(); 1347 return RegMask(); 1348} 1349 1350const RegMask Matcher::method_handle_invoke_SP_save_mask() { 1351 return FP_REGP_mask(); 1352} 1353 1354bool maybe_far_call(const CallNode *n) { 1355 return !MacroAssembler::_reachable_from_cache(n->as_Call()->entry_point()); 1356} 1357 1358bool 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. 1388encode %{ 1389 enc_class call_epilog %{ 1390 // nothing 1391 %} 1392 1393 enc_class Java_To_Runtime (method meth) %{ 1394 // CALL directly to the runtime 1395 emit_call_reloc(cbuf, as_MachCall(), $meth, runtime_call_Relocation::spec()); 1396 %} 1397 1398 enc_class Java_Static_Call (method meth) %{ 1399 // CALL to fixup routine. Fixup routine uses ScopeDesc info to determine 1400 // who we intended to call. 1401 1402 if ( !_method) { 1403 emit_call_reloc(cbuf, as_MachCall(), $meth, runtime_call_Relocation::spec()); 1404 } else { 1405 int method_index = resolved_method_index(cbuf); 1406 RelocationHolder rspec = _optimized_virtual ? opt_virtual_call_Relocation::spec(method_index) 1407 : static_call_Relocation::spec(method_index); 1408 emit_call_reloc(cbuf, as_MachCall(), $meth, rspec); 1409 1410 // Emit stubs for static call. 1411 address stub = CompiledStaticCall::emit_to_interp_stub(cbuf); 1412 if (stub == NULL) { 1413 ciEnv::current()->record_failure("CodeCache is full"); 1414 return; 1415 } 1416 } 1417 %} 1418 1419 enc_class save_last_PC %{ 1420 // preserve mark 1421 address mark = cbuf.insts()->mark(); 1422 debug_only(int off0 = cbuf.insts_size()); 1423 MacroAssembler _masm(&cbuf); 1424 int ret_addr_offset = as_MachCall()->ret_addr_offset(); 1425 __ adr(LR, mark + ret_addr_offset); 1426 __ str(LR, Address(Rthread, JavaThread::last_Java_pc_offset())); 1427 debug_only(int off1 = cbuf.insts_size()); 1428 assert(off1 - off0 == 2 * Assembler::InstructionSize, "correct size prediction"); 1429 // restore mark 1430 cbuf.insts()->set_mark(mark); 1431 %} 1432 1433 enc_class preserve_SP %{ 1434 // preserve mark 1435 address mark = cbuf.insts()->mark(); 1436 debug_only(int off0 = cbuf.insts_size()); 1437 MacroAssembler _masm(&cbuf); 1438 // FP is preserved across all calls, even compiled calls. 1439 // Use it to preserve SP in places where the callee might change the SP. 1440 __ mov(Rmh_SP_save, SP); 1441 debug_only(int off1 = cbuf.insts_size()); 1442 assert(off1 - off0 == 4, "correct size prediction"); 1443 // restore mark 1444 cbuf.insts()->set_mark(mark); 1445 %} 1446 1447 enc_class restore_SP %{ 1448 MacroAssembler _masm(&cbuf); 1449 __ mov(SP, Rmh_SP_save); 1450 %} 1451 1452 enc_class Java_Dynamic_Call (method meth) %{ 1453 MacroAssembler _masm(&cbuf); 1454 Register R8_ic_reg = reg_to_register_object(Matcher::inline_cache_reg_encode()); 1455 assert(R8_ic_reg == Ricklass, "should be"); 1456 __ set_inst_mark(); 1457#ifdef AARCH64 1458// TODO: see C1 LIR_Assembler::ic_call() 1459 InlinedAddress oop_literal((address)Universe::non_oop_word()); 1460 int offset = __ offset(); 1461 int fixed_size = mov_oop_size * 4; 1462 if (VM_Version::prefer_moves_over_load_literal()) { 1463 uintptr_t val = (uintptr_t)Universe::non_oop_word(); 1464 __ movz(R8_ic_reg, (val >> 0) & 0xffff, 0); 1465 __ movk(R8_ic_reg, (val >> 16) & 0xffff, 16); 1466 __ movk(R8_ic_reg, (val >> 32) & 0xffff, 32); 1467 __ movk(R8_ic_reg, (val >> 48) & 0xffff, 48); 1468 } else { 1469 __ ldr_literal(R8_ic_reg, oop_literal); 1470 } 1471 assert(__ offset() - offset == fixed_size, "bad mov_oop size"); 1472#else 1473 __ movw(R8_ic_reg, ((unsigned int)Universe::non_oop_word()) & 0xffff); 1474 __ movt(R8_ic_reg, ((unsigned int)Universe::non_oop_word()) >> 16); 1475#endif 1476 address virtual_call_oop_addr = __ inst_mark(); 1477 // CALL to fixup routine. Fixup routine uses ScopeDesc info to determine 1478 // who we intended to call. 1479 int method_index = resolved_method_index(cbuf); 1480 __ relocate(virtual_call_Relocation::spec(virtual_call_oop_addr, method_index)); 1481 emit_call_reloc(cbuf, as_MachCall(), $meth, RelocationHolder::none); 1482#ifdef AARCH64 1483 if (!VM_Version::prefer_moves_over_load_literal()) { 1484 Label skip_literal; 1485 __ b(skip_literal); 1486 int off2 = __ offset(); 1487 __ bind_literal(oop_literal); 1488 if (__ offset() - off2 == wordSize) { 1489 // no padding, so insert nop for worst-case sizing 1490 __ nop(); 1491 } 1492 __ bind(skip_literal); 1493 } 1494#endif 1495 %} 1496 1497 enc_class LdReplImmI(immI src, regD dst, iRegI tmp, int cnt, int wth) %{ 1498 // FIXME: load from constant table? 1499 // Load a constant replicated "count" times with width "width" 1500 int count = $cnt$$constant; 1501 int width = $wth$$constant; 1502 assert(count*width == 4, "sanity"); 1503 int val = $src$$constant; 1504 if (width < 4) { 1505 int bit_width = width * 8; 1506 val &= (((int)1) << bit_width) - 1; // mask off sign bits 1507 for (int i = 0; i < count - 1; i++) { 1508 val |= (val << bit_width); 1509 } 1510 } 1511 MacroAssembler _masm(&cbuf); 1512 1513 if (val == -1) { 1514 __ mvn($tmp$$Register, 0); 1515 } else if (val == 0) { 1516 __ mov($tmp$$Register, 0); 1517 } else { 1518 __ movw($tmp$$Register, val & 0xffff); 1519 __ movt($tmp$$Register, (unsigned int)val >> 16); 1520 } 1521 __ fmdrr($dst$$FloatRegister, $tmp$$Register, $tmp$$Register); 1522 %} 1523 1524 enc_class LdReplImmF(immF src, regD dst, iRegI tmp) %{ 1525 // Replicate float con 2 times and pack into vector (8 bytes) in regD. 1526 float fval = $src$$constant; 1527 int val = *((int*)&fval); 1528 MacroAssembler _masm(&cbuf); 1529 1530 if (val == -1) { 1531 __ mvn($tmp$$Register, 0); 1532 } else if (val == 0) { 1533 __ mov($tmp$$Register, 0); 1534 } else { 1535 __ movw($tmp$$Register, val & 0xffff); 1536 __ movt($tmp$$Register, (unsigned int)val >> 16); 1537 } 1538 __ fmdrr($dst$$FloatRegister, $tmp$$Register, $tmp$$Register); 1539 %} 1540 1541 enc_class enc_String_Compare(R0RegP str1, R1RegP str2, R2RegI cnt1, R3RegI cnt2, iRegI result, iRegI tmp1, iRegI tmp2) %{ 1542 Label Ldone, Lloop; 1543 MacroAssembler _masm(&cbuf); 1544 1545 Register str1_reg = $str1$$Register; 1546 Register str2_reg = $str2$$Register; 1547 Register cnt1_reg = $cnt1$$Register; // int 1548 Register cnt2_reg = $cnt2$$Register; // int 1549 Register tmp1_reg = $tmp1$$Register; 1550 Register tmp2_reg = $tmp2$$Register; 1551 Register result_reg = $result$$Register; 1552 1553 assert_different_registers(str1_reg, str2_reg, cnt1_reg, cnt2_reg, tmp1_reg, tmp2_reg); 1554 1555 // Compute the minimum of the string lengths(str1_reg) and the 1556 // difference of the string lengths (stack) 1557 1558 // See if the lengths are different, and calculate min in str1_reg. 1559 // Stash diff in tmp2 in case we need it for a tie-breaker. 1560 __ subs_32(tmp2_reg, cnt1_reg, cnt2_reg); 1561#ifdef AARCH64 1562 Label Lskip; 1563 __ _lsl_w(cnt1_reg, cnt1_reg, exact_log2(sizeof(jchar))); // scale the limit 1564 __ b(Lskip, mi); 1565 __ _lsl_w(cnt1_reg, cnt2_reg, exact_log2(sizeof(jchar))); // scale the limit 1566 __ bind(Lskip); 1567#else 1568 __ mov(cnt1_reg, AsmOperand(cnt1_reg, lsl, exact_log2(sizeof(jchar)))); // scale the limit 1569 __ mov(cnt1_reg, AsmOperand(cnt2_reg, lsl, exact_log2(sizeof(jchar))), pl); // scale the limit 1570#endif 1571 1572 // reallocate cnt1_reg, cnt2_reg, result_reg 1573 // Note: limit_reg holds the string length pre-scaled by 2 1574 Register limit_reg = cnt1_reg; 1575 Register chr2_reg = cnt2_reg; 1576 Register chr1_reg = tmp1_reg; 1577 // str{12} are the base pointers 1578 1579 // Is the minimum length zero? 1580 __ cmp_32(limit_reg, 0); 1581 if (result_reg != tmp2_reg) { 1582 __ mov(result_reg, tmp2_reg, eq); 1583 } 1584 __ b(Ldone, eq); 1585 1586 // Load first characters 1587 __ ldrh(chr1_reg, Address(str1_reg, 0)); 1588 __ ldrh(chr2_reg, Address(str2_reg, 0)); 1589 1590 // Compare first characters 1591 __ subs(chr1_reg, chr1_reg, chr2_reg); 1592 if (result_reg != chr1_reg) { 1593 __ mov(result_reg, chr1_reg, ne); 1594 } 1595 __ b(Ldone, ne); 1596 1597 { 1598 // Check after comparing first character to see if strings are equivalent 1599 // Check if the strings start at same location 1600 __ cmp(str1_reg, str2_reg); 1601 // Check if the length difference is zero 1602 __ cond_cmp(tmp2_reg, 0, eq); 1603 __ mov(result_reg, 0, eq); // result is zero 1604 __ b(Ldone, eq); 1605 // Strings might not be equal 1606 } 1607 1608 __ subs(chr1_reg, limit_reg, 1 * sizeof(jchar)); 1609 if (result_reg != tmp2_reg) { 1610 __ mov(result_reg, tmp2_reg, eq); 1611 } 1612 __ b(Ldone, eq); 1613 1614 // Shift str1_reg and str2_reg to the end of the arrays, negate limit 1615 __ add(str1_reg, str1_reg, limit_reg); 1616 __ add(str2_reg, str2_reg, limit_reg); 1617 __ neg(limit_reg, chr1_reg); // limit = -(limit-2) 1618 1619 // Compare the rest of the characters 1620 __ bind(Lloop); 1621 __ ldrh(chr1_reg, Address(str1_reg, limit_reg)); 1622 __ ldrh(chr2_reg, Address(str2_reg, limit_reg)); 1623 __ subs(chr1_reg, chr1_reg, chr2_reg); 1624 if (result_reg != chr1_reg) { 1625 __ mov(result_reg, chr1_reg, ne); 1626 } 1627 __ b(Ldone, ne); 1628 1629 __ adds(limit_reg, limit_reg, sizeof(jchar)); 1630 __ b(Lloop, ne); 1631 1632 // If strings are equal up to min length, return the length difference. 1633 if (result_reg != tmp2_reg) { 1634 __ mov(result_reg, tmp2_reg); 1635 } 1636 1637 // Otherwise, return the difference between the first mismatched chars. 1638 __ bind(Ldone); 1639 %} 1640 1641 enc_class enc_String_Equals(R0RegP str1, R1RegP str2, R2RegI cnt, iRegI result, iRegI tmp1, iRegI tmp2) %{ 1642 Label Lword_loop, Lpost_word, Lchar, Lchar_loop, Ldone, Lequal; 1643 MacroAssembler _masm(&cbuf); 1644 1645 Register str1_reg = $str1$$Register; 1646 Register str2_reg = $str2$$Register; 1647 Register cnt_reg = $cnt$$Register; // int 1648 Register tmp1_reg = $tmp1$$Register; 1649 Register tmp2_reg = $tmp2$$Register; 1650 Register result_reg = $result$$Register; 1651 1652 assert_different_registers(str1_reg, str2_reg, cnt_reg, tmp1_reg, tmp2_reg, result_reg); 1653 1654 __ cmp(str1_reg, str2_reg); //same char[] ? 1655 __ b(Lequal, eq); 1656 1657 __ cbz_32(cnt_reg, Lequal); // count == 0 1658 1659 //rename registers 1660 Register limit_reg = cnt_reg; 1661 Register chr1_reg = tmp1_reg; 1662 Register chr2_reg = tmp2_reg; 1663 1664 __ logical_shift_left(limit_reg, limit_reg, exact_log2(sizeof(jchar))); 1665 1666 //check for alignment and position the pointers to the ends 1667 __ orr(chr1_reg, str1_reg, str2_reg); 1668 __ tst(chr1_reg, 0x3); 1669 1670 // notZero means at least one not 4-byte aligned. 1671 // We could optimize the case when both arrays are not aligned 1672 // but it is not frequent case and it requires additional checks. 1673 __ b(Lchar, ne); 1674 1675 // Compare char[] arrays aligned to 4 bytes. 1676 __ char_arrays_equals(str1_reg, str2_reg, limit_reg, result_reg, 1677 chr1_reg, chr2_reg, Ldone); 1678 1679 __ b(Lequal); // equal 1680 1681 // char by char compare 1682 __ bind(Lchar); 1683 __ mov(result_reg, 0); 1684 __ add(str1_reg, limit_reg, str1_reg); 1685 __ add(str2_reg, limit_reg, str2_reg); 1686 __ neg(limit_reg, limit_reg); //negate count 1687 1688 // Lchar_loop 1689 __ bind(Lchar_loop); 1690 __ ldrh(chr1_reg, Address(str1_reg, limit_reg)); 1691 __ ldrh(chr2_reg, Address(str2_reg, limit_reg)); 1692 __ cmp(chr1_reg, chr2_reg); 1693 __ b(Ldone, ne); 1694 __ adds(limit_reg, limit_reg, sizeof(jchar)); 1695 __ b(Lchar_loop, ne); 1696 1697 __ bind(Lequal); 1698 __ mov(result_reg, 1); //equal 1699 1700 __ bind(Ldone); 1701 %} 1702 1703 enc_class enc_Array_Equals(R0RegP ary1, R1RegP ary2, iRegI tmp1, iRegI tmp2, iRegI tmp3, iRegI result) %{ 1704 Label Lvector, Ldone, Lloop, Lequal; 1705 MacroAssembler _masm(&cbuf); 1706 1707 Register ary1_reg = $ary1$$Register; 1708 Register ary2_reg = $ary2$$Register; 1709 Register tmp1_reg = $tmp1$$Register; 1710 Register tmp2_reg = $tmp2$$Register; 1711 Register tmp3_reg = $tmp3$$Register; 1712 Register result_reg = $result$$Register; 1713 1714 assert_different_registers(ary1_reg, ary2_reg, tmp1_reg, tmp2_reg, tmp3_reg, result_reg); 1715 1716 int length_offset = arrayOopDesc::length_offset_in_bytes(); 1717 int base_offset = arrayOopDesc::base_offset_in_bytes(T_CHAR); 1718 1719 // return true if the same array 1720#ifdef AARCH64 1721 __ cmp(ary1_reg, ary2_reg); 1722 __ b(Lequal, eq); 1723 1724 __ mov(result_reg, 0); 1725 1726 __ cbz(ary1_reg, Ldone); // not equal 1727 1728 __ cbz(ary2_reg, Ldone); // not equal 1729#else 1730 __ teq(ary1_reg, ary2_reg); 1731 __ mov(result_reg, 1, eq); 1732 __ b(Ldone, eq); // equal 1733 1734 __ tst(ary1_reg, ary1_reg); 1735 __ mov(result_reg, 0, eq); 1736 __ b(Ldone, eq); // not equal 1737 1738 __ tst(ary2_reg, ary2_reg); 1739 __ mov(result_reg, 0, eq); 1740 __ b(Ldone, eq); // not equal 1741#endif 1742 1743 //load the lengths of arrays 1744 __ ldr_s32(tmp1_reg, Address(ary1_reg, length_offset)); // int 1745 __ ldr_s32(tmp2_reg, Address(ary2_reg, length_offset)); // int 1746 1747 // return false if the two arrays are not equal length 1748#ifdef AARCH64 1749 __ cmp_w(tmp1_reg, tmp2_reg); 1750 __ b(Ldone, ne); // not equal 1751 1752 __ cbz_w(tmp1_reg, Lequal); // zero-length arrays are equal 1753#else 1754 __ teq_32(tmp1_reg, tmp2_reg); 1755 __ mov(result_reg, 0, ne); 1756 __ b(Ldone, ne); // not equal 1757 1758 __ tst(tmp1_reg, tmp1_reg); 1759 __ mov(result_reg, 1, eq); 1760 __ b(Ldone, eq); // zero-length arrays are equal 1761#endif 1762 1763 // load array addresses 1764 __ add(ary1_reg, ary1_reg, base_offset); 1765 __ add(ary2_reg, ary2_reg, base_offset); 1766 1767 // renaming registers 1768 Register chr1_reg = tmp3_reg; // for characters in ary1 1769 Register chr2_reg = tmp2_reg; // for characters in ary2 1770 Register limit_reg = tmp1_reg; // length 1771 1772 // set byte count 1773 __ logical_shift_left_32(limit_reg, limit_reg, exact_log2(sizeof(jchar))); 1774 1775 // Compare char[] arrays aligned to 4 bytes. 1776 __ char_arrays_equals(ary1_reg, ary2_reg, limit_reg, result_reg, 1777 chr1_reg, chr2_reg, Ldone); 1778 __ bind(Lequal); 1779 __ mov(result_reg, 1); //equal 1780 1781 __ bind(Ldone); 1782 %} 1783%} 1784 1785//----------FRAME-------------------------------------------------------------- 1786// Definition of frame structure and management information. 1787// 1788// S T A C K L A Y O U T Allocators stack-slot number 1789// | (to get allocators register number 1790// G Owned by | | v add VMRegImpl::stack0) 1791// r CALLER | | 1792// o | +--------+ pad to even-align allocators stack-slot 1793// w V | pad0 | numbers; owned by CALLER 1794// t -----------+--------+----> Matcher::_in_arg_limit, unaligned 1795// h ^ | in | 5 1796// | | args | 4 Holes in incoming args owned by SELF 1797// | | | | 3 1798// | | +--------+ 1799// V | | old out| Empty on Intel, window on Sparc 1800// | old |preserve| Must be even aligned. 1801// | SP-+--------+----> Matcher::_old_SP, 8 (or 16 in LP64)-byte aligned 1802// | | in | 3 area for Intel ret address 1803// Owned by |preserve| Empty on Sparc. 1804// SELF +--------+ 1805// | | pad2 | 2 pad to align old SP 1806// | +--------+ 1 1807// | | locks | 0 1808// | +--------+----> VMRegImpl::stack0, 8 (or 16 in LP64)-byte aligned 1809// | | pad1 | 11 pad to align new SP 1810// | +--------+ 1811// | | | 10 1812// | | spills | 9 spills 1813// V | | 8 (pad0 slot for callee) 1814// -----------+--------+----> Matcher::_out_arg_limit, unaligned 1815// ^ | out | 7 1816// | | args | 6 Holes in outgoing args owned by CALLEE 1817// Owned by +--------+ 1818// CALLEE | new out| 6 Empty on Intel, window on Sparc 1819// | new |preserve| Must be even-aligned. 1820// | SP-+--------+----> Matcher::_new_SP, even aligned 1821// | | | 1822// 1823// Note 1: Only region 8-11 is determined by the allocator. Region 0-5 is 1824// known from SELF's arguments and the Java calling convention. 1825// Region 6-7 is determined per call site. 1826// Note 2: If the calling convention leaves holes in the incoming argument 1827// area, those holes are owned by SELF. Holes in the outgoing area 1828// are owned by the CALLEE. Holes should not be nessecary in the 1829// incoming area, as the Java calling convention is completely under 1830// the control of the AD file. Doubles can be sorted and packed to 1831// avoid holes. Holes in the outgoing arguments may be nessecary for 1832// varargs C calling conventions. 1833// Note 3: Region 0-3 is even aligned, with pad2 as needed. Region 3-5 is 1834// even aligned with pad0 as needed. 1835// Region 6 is even aligned. Region 6-7 is NOT even aligned; 1836// region 6-11 is even aligned; it may be padded out more so that 1837// the region from SP to FP meets the minimum stack alignment. 1838 1839frame %{ 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--------------------------------------------- 1913ins_attrib ins_cost(DEFAULT_COST); // Required cost attribute 1914ins_attrib ins_size(32); // Required size attribute (in bits) 1915ins_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 1927operand 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 1937operand 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 1947operand 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 1958operand 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 1967operand 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 1978operand 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 1988operand 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 1997operand 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 2007operand 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 2017operand 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 2027operand 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 2037operand 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 2047operand 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 2057operand 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 2068operand 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 2080operand 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 2090operand 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 2100operand 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 2110operand 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 2121operand aimmI() %{ 2122 predicate(is_aimm(n->get_int())); 2123 match(ConI); 2124 op_cost(0); 2125 2126 format %{ %} 2127 interface(CONST_INTER); 2128%} 2129 2130operand aimmIneg() %{ 2131 predicate(is_aimm(-n->get_int())); 2132 match(ConI); 2133 op_cost(0); 2134 2135 format %{ %} 2136 interface(CONST_INTER); 2137%} 2138 2139operand 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 2150operand limmI() %{ 2151 predicate(is_limmI(n->get_int())); 2152 match(ConI); 2153 op_cost(0); 2154 2155 format %{ %} 2156 interface(CONST_INTER); 2157%} 2158 2159operand 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 2168operand 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 2177operand 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 2188operand limmL() %{ 2189 predicate(is_limmL(n->get_long())); 2190 match(ConL); 2191 op_cost(0); 2192 2193 format %{ %} 2194 interface(CONST_INTER); 2195%} 2196 2197operand 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 2207operand aimmL() %{ 2208 predicate(is_aimm(n->get_long())); 2209 match(ConL); 2210 op_cost(0); 2211 2212 format %{ %} 2213 interface(CONST_INTER); 2214%} 2215 2216operand 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 2227operand 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 2237operand 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 2247operand 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 2256operand immP0() %{ 2257 predicate(n->get_ptr() == 0); 2258 match(ConP); 2259 op_cost(0); 2260 2261 format %{ %} 2262 interface(CONST_INTER); 2263%} 2264 2265operand 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 2275operand immN() 2276%{ 2277 match(ConN); 2278 2279 op_cost(10); 2280 format %{ %} 2281 interface(CONST_INTER); 2282%} 2283 2284operand immNKlass() 2285%{ 2286 match(ConNKlass); 2287 2288 op_cost(10); 2289 format %{ %} 2290 interface(CONST_INTER); 2291%} 2292 2293// NULL Pointer Immediate 2294operand immN0() 2295%{ 2296 predicate(n->get_narrowcon() == 0); 2297 match(ConN); 2298 2299 op_cost(0); 2300 format %{ %} 2301 interface(CONST_INTER); 2302%} 2303 2304operand 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 2312operand 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 2322operand 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 2332operand 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 2342operand immD() %{ 2343 match(ConD); 2344 2345 op_cost(40); 2346 format %{ %} 2347 interface(CONST_INTER); 2348%} 2349 2350// Double Immediate: +0.0d. 2351operand immD0() %{ 2352 predicate(jlong_cast(n->getd()) == 0); 2353 2354 match(ConD); 2355 op_cost(0); 2356 format %{ %} 2357 interface(CONST_INTER); 2358%} 2359 2360operand 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 2370operand immF() %{ 2371 match(ConF); 2372 2373 op_cost(20); 2374 format %{ %} 2375 interface(CONST_INTER); 2376%} 2377 2378// Float Immediate: +0.0f 2379operand 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 2389operand 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 2400operand 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 2418operand 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 2439operand 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. 2452operand 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 2462operand 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 2472operand 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 2482operand 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 2493operand R0RegP() %{ 2494 constraint(ALLOC_IN_RC(R0_regP)); 2495 match(iRegP); 2496 2497 format %{ %} 2498 interface(REG_INTER); 2499%} 2500 2501operand R1RegP() %{ 2502 constraint(ALLOC_IN_RC(R1_regP)); 2503 match(iRegP); 2504 2505 format %{ %} 2506 interface(REG_INTER); 2507%} 2508 2509operand R2RegP() %{ 2510 constraint(ALLOC_IN_RC(R2_regP)); 2511 match(iRegP); 2512 2513 format %{ %} 2514 interface(REG_INTER); 2515%} 2516 2517operand RExceptionRegP() %{ 2518 constraint(ALLOC_IN_RC(Rexception_regP)); 2519 match(iRegP); 2520 2521 format %{ %} 2522 interface(REG_INTER); 2523%} 2524 2525operand RthreadRegP() %{ 2526 constraint(ALLOC_IN_RC(Rthread_regP)); 2527 match(iRegP); 2528 2529 format %{ %} 2530 interface(REG_INTER); 2531%} 2532 2533operand IPRegP() %{ 2534 constraint(ALLOC_IN_RC(IP_regP)); 2535 match(iRegP); 2536 2537 format %{ %} 2538 interface(REG_INTER); 2539%} 2540 2541operand LRRegP() %{ 2542 constraint(ALLOC_IN_RC(LR_regP)); 2543 match(iRegP); 2544 2545 format %{ %} 2546 interface(REG_INTER); 2547%} 2548 2549operand R0RegI() %{ 2550 constraint(ALLOC_IN_RC(R0_regI)); 2551 match(iRegI); 2552 2553 format %{ %} 2554 interface(REG_INTER); 2555%} 2556 2557operand R1RegI() %{ 2558 constraint(ALLOC_IN_RC(R1_regI)); 2559 match(iRegI); 2560 2561 format %{ %} 2562 interface(REG_INTER); 2563%} 2564 2565operand R2RegI() %{ 2566 constraint(ALLOC_IN_RC(R2_regI)); 2567 match(iRegI); 2568 2569 format %{ %} 2570 interface(REG_INTER); 2571%} 2572 2573operand R3RegI() %{ 2574 constraint(ALLOC_IN_RC(R3_regI)); 2575 match(iRegI); 2576 2577 format %{ %} 2578 interface(REG_INTER); 2579%} 2580 2581#ifndef AARCH64 2582operand 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 2592operand 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 2607operand 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 2617operand R0R1RegL() %{ 2618 constraint(ALLOC_IN_RC(R0R1_regL)); 2619 match(iRegL); 2620 2621 format %{ %} 2622 interface(REG_INTER); 2623%} 2624 2625operand 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 2635operand 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) 2644operand 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. 2653operand 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. 2665operand 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 2675operand flagsRegL_LTGE() %{ 2676 constraint(ALLOC_IN_RC(int_flags)); 2677 match(RegFlags); 2678 2679 format %{ "apsr_L_LTGE" %} 2680 interface(REG_INTER); 2681%} 2682 2683operand flagsRegL_EQNE() %{ 2684 constraint(ALLOC_IN_RC(int_flags)); 2685 match(RegFlags); 2686 2687 format %{ "apsr_L_EQNE" %} 2688 interface(REG_INTER); 2689%} 2690 2691operand flagsRegL_LEGT() %{ 2692 constraint(ALLOC_IN_RC(int_flags)); 2693 match(RegFlags); 2694 2695 format %{ "apsr_L_LEGT" %} 2696 interface(REG_INTER); 2697%} 2698 2699operand flagsRegUL_LTGE() %{ 2700 constraint(ALLOC_IN_RC(int_flags)); 2701 match(RegFlags); 2702 2703 format %{ "apsr_UL_LTGE" %} 2704 interface(REG_INTER); 2705%} 2706 2707operand flagsRegUL_EQNE() %{ 2708 constraint(ALLOC_IN_RC(int_flags)); 2709 match(RegFlags); 2710 2711 format %{ "apsr_UL_EQNE" %} 2712 interface(REG_INTER); 2713%} 2714 2715operand 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". 2725operand flagsRegF() %{ 2726 constraint(ALLOC_IN_RC(float_flags)); 2727 match(RegFlags); 2728 2729 format %{ "fpscr_F" %} 2730 interface(REG_INTER); 2731%} 2732 2733// Vectors 2734operand vecD() %{ 2735 constraint(ALLOC_IN_RC(actual_dflt_reg)); 2736 match(VecD); 2737 2738 format %{ %} 2739 interface(REG_INTER); 2740%} 2741 2742operand vecX() %{ 2743 constraint(ALLOC_IN_RC(vectorx_reg)); 2744 match(VecX); 2745 2746 format %{ %} 2747 interface(REG_INTER); 2748%} 2749 2750operand 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 2759operand regF() %{ 2760 constraint(ALLOC_IN_RC(sflt_reg)); 2761 match(RegF); 2762 2763 format %{ %} 2764 interface(REG_INTER); 2765%} 2766 2767operand 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 2778operand inline_cache_regP(iRegP reg) %{ 2779 constraint(ALLOC_IN_RC(Ricklass_regP)); 2780 match(reg); 2781 format %{ %} 2782 interface(REG_INTER); 2783%} 2784 2785operand 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 2795operand 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 2815operand 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 2834operand 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 2853operand 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 2872operand 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 2891operand 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[ 2912operand 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 2931operand 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 2950operand 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[ 2969operand 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[ 2988operand 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 3008operand 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 3024operand 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 3039operand 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 3054operand 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 3069operand 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 3084operand 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 3099operand 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 3114operand 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 3129operand 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 3144operand 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 3177operand 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 3194operand 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 3211operand 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) 3228operand 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 3244operand 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 3260operand 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 3276operand 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 3292operand 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 3316opclass memoryB(indirect, indIndex, indOffsetU12ScaleB); 3317opclass memoryS(indirect, indIndex, indIndexScaleS, indIndexIScaleS, indOffsetU12ScaleS); 3318opclass memoryI(indirect, indIndex, indIndexScaleI, indIndexIScaleI, indOffsetU12ScaleI); 3319opclass memoryL(indirect, indIndex, indIndexScaleL, indIndexIScaleL, indOffsetU12ScaleL); 3320opclass memoryP(indirect, indIndex, indIndexScaleL, indIndexIScaleL, indOffsetU12ScaleL); 3321opclass memoryQ(indirect, indIndex, indIndexScaleQ, indIndexIScaleQ, indOffsetU12ScaleQ); 3322opclass memoryF(indirect, indIndex, indIndexScaleI, indIndexIScaleI, indOffsetU12ScaleI); 3323opclass memoryD(indirect, indIndex, indIndexScaleL, indIndexIScaleL, indOffsetU12ScaleL); 3324 3325opclass memoryScaledS(indIndexScaleS, indIndexIScaleS); 3326opclass memoryScaledI(indIndexScaleI, indIndexIScaleI); 3327opclass memoryScaledL(indIndexScaleL, indIndexIScaleL); 3328opclass memoryScaledP(indIndexScaleL, indIndexIScaleL); 3329opclass memoryScaledQ(indIndexScaleQ, indIndexIScaleQ); 3330opclass memoryScaledF(indIndexScaleI, indIndexIScaleI); 3331opclass memoryScaledD(indIndexScaleL, indIndexIScaleL); 3332// when ldrex/strex is used: 3333opclass memoryex ( indirect ); 3334opclass indIndexMemory( indIndex ); 3335opclass memoryvld ( indirect /* , write back mode not implemented */ ); 3336 3337#else 3338 3339opclass memoryI ( indirect, indOffset12, indIndex, indIndexScale ); 3340opclass memoryP ( indirect, indOffset12, indIndex, indIndexScale ); 3341opclass memoryF ( indirect, indOffsetFP ); 3342opclass memoryF2 ( indirect, indOffsetFPx2 ); 3343opclass memoryD ( indirect, indOffsetFP ); 3344opclass memoryfp( indirect, indOffsetFP ); 3345opclass memoryB ( indirect, indIndex, indOffsetHD ); 3346opclass memoryS ( indirect, indIndex, indOffsetHD ); 3347opclass memoryL ( indirect, indIndex, indOffsetHD ); 3348 3349opclass memoryScaledI(indIndexScale); 3350opclass memoryScaledP(indIndexScale); 3351 3352// when ldrex/strex is used: 3353opclass memoryex ( indirect ); 3354opclass indIndexMemory( indIndex ); 3355opclass memorylong ( indirect, indOffset12x2 ); 3356opclass memoryvld ( indirect /* , write back mode not implemented */ ); 3357#endif 3358 3359//----------PIPELINE----------------------------------------------------------- 3360pipeline %{ 3361 3362//----------ATTRIBUTES--------------------------------------------------------- 3363attributes %{ 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 3376resources(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 3381pipe_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 3388pipe_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 3397pipe_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 3407pipe_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 3417pipe_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 3425pipe_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 3435pipe_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 3443pipe_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 3451pipe_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 3460pipe_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 3468pipe_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 3477pipe_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 3485pipe_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 3494pipe_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 3505pipe_class ialu_none(iRegI dst) %{ 3506 single_instruction; 3507 dst : E(write); 3508 IALU : R; 3509%} 3510 3511// Integer ALU reg operation 3512pipe_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. 3526pipe_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 3536pipe_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%} 3542pipe_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 3550pipe_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 3559pipe_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 3568pipe_class ialu_imm(iRegI dst) %{ 3569 single_instruction; 3570 dst : E(write); 3571 IALU : R; 3572%} 3573 3574pipe_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 3581pipe_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 3590pipe_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 3598pipe_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 3606pipe_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 3615pipe_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 3622pipe_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 3630pipe_class loadConP( iRegP dst, immP src ) %{ 3631 instruction_count(0); multiple_bundles; 3632 fixed_latency(6); 3633%} 3634 3635// Polling Address 3636pipe_class loadConP_poll( iRegP dst, immP_poll src ) %{ 3637 dst : E(write); 3638 IALU : R; 3639%} 3640 3641// Long Constant small 3642pipe_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. 3650pipe_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 3659pipe_class ialu_nop() %{ 3660 single_instruction; 3661 IALU : R; 3662%} 3663 3664// Integer ALU nop operation 3665pipe_class ialu_nop_A0() %{ 3666 single_instruction; 3667 A0 : R; 3668%} 3669 3670// Integer ALU nop operation 3671pipe_class ialu_nop_A1() %{ 3672 single_instruction; 3673 A1 : R; 3674%} 3675 3676// Integer Multiply reg-reg operation 3677pipe_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 3685pipe_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 3694pipe_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 3705pipe_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 3713pipe_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 3722pipe_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 3731pipe_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 3741pipe_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 3751pipe_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 3760pipe_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 3769pipe_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 3779pipe_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 3789pipe_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 3797pipe_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 3805pipe_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 3813pipe_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 3821pipe_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 3829pipe_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 3837pipe_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 3845pipe_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 3853pipe_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 3861pipe_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 3869pipe_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 3877pipe_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 3885pipe_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 3893pipe_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 3901pipe_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 3910pipe_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 3919pipe_class fadd_nop() %{ 3920 single_instruction; 3921 FA : R; 3922%} 3923 3924// Integer Store to Memory 3925pipe_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 3933pipe_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 3941pipe_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 3949pipe_class fstoreF_mem_zero(memoryF mem, immF0 src) %{ 3950 single_instruction; 3951 mem : R(read); 3952 MS : R; 3953%} 3954 3955// Double Store 3956pipe_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 3964pipe_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) 3971pipe_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) 3979pipe_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 3987pipe_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 3995pipe_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 4003pipe_class mem_nop() %{ 4004 single_instruction; 4005 MS : R; 4006%} 4007 4008pipe_class sethi(iRegP dst, immI src) %{ 4009 single_instruction; 4010 dst : E(write); 4011 IALU : R; 4012%} 4013 4014pipe_class loadPollP(iRegP poll) %{ 4015 single_instruction; 4016 poll : R(read); 4017 MS : R; 4018%} 4019 4020pipe_class br(Universe br, label labl) %{ 4021 single_instruction_with_delay_slot; 4022 BR : R; 4023%} 4024 4025pipe_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 4031pipe_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 4038pipe_class br_nop() %{ 4039 single_instruction; 4040 BR : R; 4041%} 4042 4043pipe_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 4051pipe_class compiled_call(method meth) %{ 4052 instruction_count(1); multiple_bundles; force_serialization; 4053 fixed_latency(100); 4054 MS : R(1); 4055%} 4056 4057pipe_class call(method meth) %{ 4058 instruction_count(0); multiple_bundles; force_serialization; 4059 fixed_latency(100); 4060%} 4061 4062pipe_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 4069pipe_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 4076pipe_class empty( ) %{ 4077 instruction_count(0); 4078%} 4079 4080pipe_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 4087pipe_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 4096pipe_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 4106pipe_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. 4114pipe_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 4122define %{ 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 4132instruct Nop_A0() %{ 4133 ins_pipe(ialu_nop_A0); 4134%} 4135 4136// Nop using the A1 functional unit 4137instruct Nop_A1( ) %{ 4138 ins_pipe(ialu_nop_A1); 4139%} 4140 4141// Nop using the memory functional unit 4142instruct Nop_MS( ) %{ 4143 ins_pipe(mem_nop); 4144%} 4145 4146// Nop using the floating add functional unit 4147instruct Nop_FA( ) %{ 4148 ins_pipe(fadd_nop); 4149%} 4150 4151// Nop using the branch functional unit 4152instruct Nop_BR( ) %{ 4153 ins_pipe(br_nop); 4154%} 4155 4156//----------Load/Store/Move Instructions--------------------------------------- 4157//----------Load Instructions-------------------------------------------------- 4158// Load Byte (8bit signed) 4159instruct 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 4173instruct 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 4196instruct 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 4209instruct 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 4232instruct 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 4262instruct 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 4279instruct 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) 4292instruct 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 4307instruct 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 4333instruct 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 4350instruct 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) 4363instruct 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 4376instruct 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 4399instruct 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 4422instruct 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 4454instruct 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 4471instruct 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) 4484instruct 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) 4498instruct 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) 4512instruct 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) 4525instruct 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 4538instruct 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 4563instruct 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 4588instruct 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 4612instruct 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 4628instruct 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? 4649instruct 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? 4667instruct 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 4688instruct 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 4714instruct 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 4731instruct 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 4750instruct 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 4773instruct 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 4789instruct 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 4804instruct 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 4828instruct 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 4844instruct 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 4861instruct 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) %{ 4876instruct 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 4896instruct 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 4912instruct 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 4926instruct 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 4940instruct 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 4955instruct 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 4972instruct 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 4988instruct 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 5006instruct 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 5023instruct 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 5036instruct 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 5048instruct 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 5058instruct 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 5069instruct 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 5080instruct 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 5098instruct 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 5117instruct 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 5128instruct 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 5138instruct 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 5150instruct 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 5160instruct 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 5172instruct 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%} 5181instruct 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%} 5190instruct 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 5201instruct 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 5213instruct 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 5228instruct 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 5242instruct 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 5261instruct 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 5283instruct 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 5296instruct 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 5319instruct 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 5336instruct 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 5355instruct 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 5367instruct 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 5383instruct 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 5400instruct 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 5416instruct 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 5433instruct 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 5449instruct 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 5466instruct 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 5485instruct 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 5503instruct 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 5520instruct 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) %{ 5539instruct 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 5558instruct 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 5586instruct 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 5604instruct 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 5621instruct 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 5639instruct 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 5656instruct 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 5670instruct 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 5684instruct 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 5701instruct 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 5718instruct 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 5733instruct 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 5744instruct 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 5760instruct 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 5777instruct 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 5791instruct 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 5802instruct 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 5812instruct 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 5824instruct 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 5835instruct 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 5844instruct 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 5859instruct 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 5871instruct 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 5884instruct 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 5894instruct 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 5907instruct 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 5917instruct 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 5929instruct 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 5955instruct 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 5966instruct 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 5978instruct 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 5989instruct 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 6002instruct 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 6015instruct 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 6030instruct 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 6043instruct 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 6054instruct 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 6065instruct 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 6076instruct 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 6087instruct 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 6098instruct 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 6109instruct 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 6120instruct 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 6131instruct 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 6142instruct 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 6153instruct 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 6164instruct 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 6175instruct 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 6186instruct 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 6197instruct 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 6208instruct 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 6221instruct 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 6232instruct 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 6244instruct 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 6256instruct 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 6269instruct 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 6280instruct 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 6292instruct 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 6308instruct 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 6323instruct 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 6339instruct 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 6351instruct 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 6362instruct 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 6375instruct 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 6386instruct 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. 6406instruct 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 6418instruct 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 6434instruct 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 6446instruct 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 6466instruct 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 6490instruct 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 6512instruct 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 6523instruct 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 6534instruct 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 6545instruct 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 6556instruct 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 6567instruct 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 6578instruct 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 6589instruct 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 6603instruct 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 6614instruct 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 6626instruct 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 6642instruct 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 6655instruct 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 6666instruct 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 6678instruct 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 6691instruct 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 6704instruct 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 6720instruct 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 6734instruct 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 6748instruct 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 6762instruct 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 6782instruct 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 6798instruct 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 6816instruct 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 6830instruct 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 6848instruct 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. 6869instruct 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 6879instruct 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 6889instruct 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 6896instruct 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 6907instruct 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 6919instruct 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 6933instruct 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 6946instruct 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 6958instruct 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 6970instruct 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 6982instruct 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 6994instruct 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 7006instruct 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 7018instruct 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 7031operand 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 7046operand 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 7060opclass shiftedRegI(shiftedI2L, unshiftedI2L); 7061 7062instruct 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 7079instruct 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 7094operand 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 7108instruct 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 7122instruct 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 7135instruct 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 7145instruct 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 7158instruct 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 7174instruct 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 7185instruct 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 7202instruct 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. 7223instruct 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 7238instruct 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. 7258instruct 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 7318instruct 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 7345instruct 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. 7373instruct 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 7400instruct 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 7427instruct 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 7456instruct 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 7483instruct 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 7512instruct 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 7535instruct 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 7561instruct 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 7584instruct 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 7610instruct 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 7632instruct 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 7657instruct 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 7679instruct 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 7704instruct 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 7727instruct 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 7755instruct 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 7780instruct 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 7808instruct 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 7830instruct 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 7857instruct 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 7881instruct 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 7908instruct 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. 7930instruct 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 7951instruct 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 7974instruct 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 7994instruct 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 8017instruct 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 8037instruct 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 8062instruct 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 8074instruct 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 8086instruct 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 8098instruct 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 8110instruct 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 8122instruct 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 8134instruct 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 8146instruct 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 8157instruct 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 8168instruct 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 8179instruct 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 8190instruct 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 8201instruct 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 8214instruct 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 8225instruct 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 8237instruct 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 8251instruct 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 8262instruct 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 8279instruct 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 8290instruct 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 8308instruct 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 8323instruct 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 8341instruct 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 8353instruct 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 8363instruct 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 8373instruct 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 8385instruct 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 8395instruct 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 8409instruct 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 8420instruct 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 8435instruct 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 8446instruct 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 8463instruct 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 8475instruct 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 8489instruct 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 8503instruct 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 8517instruct 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 8533instruct 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 8552instruct 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 8571instruct 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 8581instruct 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 8591instruct 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 8610instruct 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 8631instruct 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 8643instruct 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 8660instruct 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 8679instruct 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 8697instruct 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 8717instruct 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 8727instruct 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 8737instruct 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 8756instruct 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 8778instruct 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 8789instruct 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 8807instruct 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 8825instruct 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 8843instruct 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 8863instruct 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 8873instruct 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 8883instruct 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 8902instruct 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 8924instruct 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 8935instruct 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 8953instruct 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 8972instruct 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 8985instruct 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 8998instruct 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 9011instruct 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 9023instruct 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 9035instruct 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 9048instruct 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 9061instruct 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 9074instruct 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 9087instruct 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 9099instruct 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 9108instruct 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 9119instruct 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 9130instruct 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 9142instruct 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 9156instruct 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 9168instruct 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 9180instruct 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 9192instruct 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 9204instruct 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 9216instruct 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 9228instruct 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 9240instruct 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 9252instruct 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 9265instruct 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 9288instruct 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 9301instruct 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 9316instruct 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 9328instruct 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 9340instruct 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 9352instruct 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 9364instruct 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 9376instruct 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 9388instruct 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 9400instruct 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 9413instruct 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 9436instruct 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 9449instruct 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. 9467instruct 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 9480instruct 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 9492instruct 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 9504instruct 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 9516instruct 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 9528instruct 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 9540instruct 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 9552instruct 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 9564instruct 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 9576instruct 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 9598instruct 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 9611instruct 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------------------------------------------------- 9626instruct 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 9653instruct 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 9680instruct 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 9706instruct 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 9733instruct 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 9749instruct 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 9764instruct 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" 9781instruct 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 9796instruct 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 9812instruct 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 9829instruct 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 9843instruct 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 9853instruct 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 9863instruct 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 9882instruct 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 9902instruct 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 9913instruct 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 9924instruct 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 9935instruct 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 9950instruct 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 9971instruct 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 9982instruct 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 9996instruct 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 10017instruct 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 10038instruct 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 10059instruct 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 10079instruct 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 10092instruct 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 10104instruct 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 10124instruct 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 10148instruct 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 10159instruct 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 10171instruct 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 10182instruct 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 10192instruct 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 10203instruct 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 10218instruct 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 10230instruct 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 10241instruct 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 10252instruct 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 10262instruct 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 10274instruct 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 10286instruct 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 10320instruct 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 10339instruct 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 10358instruct 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 10372instruct 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 10385instruct 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 10396instruct 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 10408instruct 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 10420instruct 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 10432instruct 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 10444instruct 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 10456instruct 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 10468instruct 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 10480instruct 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 10492instruct 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 10503instruct 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 10515instruct 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 10528instruct 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 10539instruct 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 10553instruct 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 10569instruct 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 10582instruct 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 10595instruct 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 10609instruct 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 10625instruct 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 10642instruct 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 10659instruct 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 10674instruct 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 10688instruct 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 10704instruct 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 10721instruct 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 10738instruct 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 10771instruct 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 10783instruct 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 10794instruct 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 10809instruct 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. 10821instruct 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 10833instruct 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 10843instruct 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 10856instruct 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 10878instruct 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 10900instruct 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 10922instruct 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 10946instruct 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 10965instruct 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 10984instruct 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 11003instruct 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 11022instruct 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 11041instruct 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 11060instruct 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 11079instruct 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 11103instruct 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. 11136instruct 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 11150instruct 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 11164instruct 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 11180instruct 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 11198instruct 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 11216instruct 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 11235instruct 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 11248instruct 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 11262instruct 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 11276instruct 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 11290instruct 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 11304instruct 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 11318instruct 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 11332instruct 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 11347instruct 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 11394instruct 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 11413instruct 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 11444instruct 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 11459instruct 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 11474instruct 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 11489instruct 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 11503instruct 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 11517instruct 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 11533instruct 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 11546instruct 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 11559instruct 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 11574instruct 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 11586instruct 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 11598instruct 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 11610instruct 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 11623instruct 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 11636instruct 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 11649instruct 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 11661instruct 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 11673instruct 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 11685instruct 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 11697instruct 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 11709instruct 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 11721instruct 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 11734instruct 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 11747instruct 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 11764instruct 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 11780instruct 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 11798instruct 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) 11810instruct 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 11824instruct 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 11836instruct 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 11852instruct 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 11864instruct 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. 11879instruct 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 11897instruct 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. 11916instruct 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. 11931instruct 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. 11947instruct 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 11964instruct ShouldNotReachHere( ) 11965%{ 11966 match(Halt); 11967 ins_cost(CALL_COST); 11968 11969 // Use the following format syntax 11970 format %{ "ShouldNotReachHere" %} 11971 ins_encode %{ 11972 if (is_reachable()) { 11973#ifdef AARCH64 11974 __ dpcs1(0xdead); 11975#else 11976 __ udf(0xdead); 11977#endif 11978 } 11979 %} 11980 ins_pipe(tail_call); 11981%} 11982 11983// ============================================================================ 11984// The 2nd slow-half of a subtype check. Scan the subklass's 2ndary superklass 11985// array for an instance of the superklass. Set a hidden internal cache on a 11986// hit (cache is checked with exposed code in gen_subtype_check()). Return 11987// not zero for a miss or zero for a hit. The encoding ALSO sets flags. 11988instruct partialSubtypeCheck( R0RegP index, R1RegP sub, R2RegP super, flagsRegP pcc, LRRegP lr ) %{ 11989 match(Set index (PartialSubtypeCheck sub super)); 11990 effect( KILL pcc, KILL lr ); 11991 ins_cost(DEFAULT_COST*10); 11992 format %{ "CALL PartialSubtypeCheck" %} 11993 ins_encode %{ 11994 __ call(StubRoutines::Arm::partial_subtype_check(), relocInfo::runtime_call_type); 11995 %} 11996 ins_pipe(partial_subtype_check_pipe); 11997%} 11998 11999/* instruct partialSubtypeCheck_vs_zero( flagsRegP pcc, o1RegP sub, o2RegP super, immP0 zero, o0RegP idx, o7RegP o7 ) %{ */ 12000/* match(Set pcc (CmpP (PartialSubtypeCheck sub super) zero)); */ 12001/* ins_pipe(partial_subtype_check_pipe); */ 12002/* %} */ 12003 12004 12005// ============================================================================ 12006// inlined locking and unlocking 12007 12008#ifdef AARCH64 12009instruct cmpFastLock(flagsRegP pcc, iRegP object, iRegP box, iRegP scratch2, iRegP scratch, iRegP scratch3 ) 12010#else 12011instruct cmpFastLock(flagsRegP pcc, iRegP object, iRegP box, iRegP scratch2, iRegP scratch ) 12012#endif 12013%{ 12014 match(Set pcc (FastLock object box)); 12015 12016#ifdef AARCH64 12017 effect(TEMP scratch, TEMP scratch2, TEMP scratch3); 12018#else 12019 predicate(!(UseBiasedLocking && !UseOptoBiasInlining)); 12020 effect(TEMP scratch, TEMP scratch2); 12021#endif 12022 ins_cost(DEFAULT_COST*3); 12023 12024#ifdef AARCH64 12025 format %{ "FASTLOCK $object, $box; KILL $scratch, $scratch2, $scratch3" %} 12026 ins_encode %{ 12027 __ fast_lock($object$$Register, $box$$Register, $scratch$$Register, $scratch2$$Register, $scratch3$$Register); 12028 %} 12029#else 12030 format %{ "FASTLOCK $object, $box; KILL $scratch, $scratch2" %} 12031 ins_encode %{ 12032 __ fast_lock($object$$Register, $box$$Register, $scratch$$Register, $scratch2$$Register); 12033 %} 12034#endif 12035 ins_pipe(long_memory_op); 12036%} 12037 12038 12039#ifdef AARCH64 12040instruct cmpFastUnlock(flagsRegP pcc, iRegP object, iRegP box, iRegP scratch2, iRegP scratch, iRegP scratch3 ) %{ 12041 match(Set pcc (FastUnlock object box)); 12042 effect(TEMP scratch, TEMP scratch2, TEMP scratch3); 12043 ins_cost(100); 12044 12045 format %{ "FASTUNLOCK $object, $box; KILL $scratch, $scratch2, $scratch3" %} 12046 ins_encode %{ 12047 __ fast_unlock($object$$Register, $box$$Register, $scratch$$Register, $scratch2$$Register, $scratch3$$Register); 12048 %} 12049 ins_pipe(long_memory_op); 12050%} 12051#else 12052instruct cmpFastLock_noBiasInline(flagsRegP pcc, iRegP object, iRegP box, iRegP scratch2, 12053 iRegP scratch, iRegP scratch3) %{ 12054 match(Set pcc (FastLock object box)); 12055 predicate(UseBiasedLocking && !UseOptoBiasInlining); 12056 12057 effect(TEMP scratch, TEMP scratch2, TEMP scratch3); 12058 ins_cost(DEFAULT_COST*5); 12059 12060 format %{ "FASTLOCK $object, $box; KILL $scratch, $scratch2, $scratch3" %} 12061 ins_encode %{ 12062 __ fast_lock($object$$Register, $box$$Register, $scratch$$Register, $scratch2$$Register, $scratch3$$Register); 12063 %} 12064 ins_pipe(long_memory_op); 12065%} 12066 12067instruct cmpFastUnlock(flagsRegP pcc, iRegP object, iRegP box, iRegP scratch2, iRegP scratch ) %{ 12068 match(Set pcc (FastUnlock object box)); 12069 effect(TEMP scratch, TEMP scratch2); 12070 ins_cost(100); 12071 12072 format %{ "FASTUNLOCK $object, $box; KILL $scratch, $scratch2" %} 12073 ins_encode %{ 12074 __ fast_unlock($object$$Register, $box$$Register, $scratch$$Register, $scratch2$$Register); 12075 %} 12076 ins_pipe(long_memory_op); 12077%} 12078#endif 12079 12080#ifdef AARCH64 12081// TODO: add version that takes immI cnt? 12082instruct clear_array(iRegX cnt, iRegP base, iRegP ptr, iRegX temp, Universe dummy, flagsReg cpsr) %{ 12083 match(Set dummy (ClearArray cnt base)); 12084 effect(TEMP temp, TEMP ptr, KILL cpsr); 12085 ins_cost(300); 12086 format %{ 12087 " MOV $temp,$cnt\n" 12088 " ADD $ptr,$base,$cnt\n" 12089 " SUBS $temp,$temp,16\t! Count down dword pair in bytes\n" 12090 " B.lt done16\n" 12091 "loop: STP ZR,ZR,[$ptr,-16]!\n" 12092 " SUBS $temp,$temp,16\t! Count down dword pair in bytes\n" 12093 " B.ge loop\t! Clearing loop\n" 12094 "done16: ADDS $temp,$temp,8\t! Room for 1 more long?\n" 12095 " B.lt done\n" 12096 " STR ZR,[$base+$temp]\n" 12097 "done:" 12098 %} 12099 ins_encode %{ 12100 // TODO: preload? 12101 __ mov($temp$$Register, $cnt$$Register); 12102 __ add($ptr$$Register, $base$$Register, $cnt$$Register); 12103 Label loop, done, done16; 12104 __ subs($temp$$Register, $temp$$Register, 16); 12105 __ b(done16, lt); 12106 __ bind(loop); 12107 __ stp(ZR, ZR, Address($ptr$$Register, -16, pre_indexed)); 12108 __ subs($temp$$Register, $temp$$Register, 16); 12109 __ b(loop, ge); 12110 __ bind(done16); 12111 __ adds($temp$$Register, $temp$$Register, 8); 12112 __ b(done, lt); 12113 // $temp should be 0 here 12114 __ str(ZR, Address($base$$Register, $temp$$Register)); 12115 __ bind(done); 12116 %} 12117 ins_pipe(long_memory_op); 12118%} 12119#else 12120// Count and Base registers are fixed because the allocator cannot 12121// kill unknown registers. The encodings are generic. 12122instruct clear_array(iRegX cnt, iRegP base, iRegI temp, iRegX zero, Universe dummy, flagsReg cpsr) %{ 12123 match(Set dummy (ClearArray cnt base)); 12124 effect(TEMP temp, TEMP zero, KILL cpsr); 12125 ins_cost(300); 12126 format %{ "MOV $zero,0\n" 12127 " MOV $temp,$cnt\n" 12128 "loop: SUBS $temp,$temp,4\t! Count down a dword of bytes\n" 12129 " STR.ge $zero,[$base+$temp]\t! delay slot" 12130 " B.gt loop\t\t! Clearing loop\n" %} 12131 ins_encode %{ 12132 __ mov($zero$$Register, 0); 12133 __ mov($temp$$Register, $cnt$$Register); 12134 Label(loop); 12135 __ bind(loop); 12136 __ subs($temp$$Register, $temp$$Register, 4); 12137 __ str($zero$$Register, Address($base$$Register, $temp$$Register), ge); 12138 __ b(loop, gt); 12139 %} 12140 ins_pipe(long_memory_op); 12141%} 12142#endif 12143 12144#ifdef XXX 12145// FIXME: Why R0/R1/R2/R3? 12146instruct string_compare(R0RegP str1, R1RegP str2, R2RegI cnt1, R3RegI cnt2, iRegI result, 12147 iRegI tmp1, iRegI tmp2, flagsReg ccr) %{ 12148 predicate(!CompactStrings); 12149 match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2))); 12150 effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL ccr, TEMP tmp1, TEMP tmp2); 12151 ins_cost(300); 12152 format %{ "String Compare $str1,$cnt1,$str2,$cnt2 -> $result // TEMP $tmp1, $tmp2" %} 12153 ins_encode( enc_String_Compare(str1, str2, cnt1, cnt2, result, tmp1, tmp2) ); 12154 12155 ins_pipe(long_memory_op); 12156%} 12157 12158// FIXME: Why R0/R1/R2? 12159instruct string_equals(R0RegP str1, R1RegP str2, R2RegI cnt, iRegI result, iRegI tmp1, iRegI tmp2, 12160 flagsReg ccr) %{ 12161 predicate(!CompactStrings); 12162 match(Set result (StrEquals (Binary str1 str2) cnt)); 12163 effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt, TEMP tmp1, TEMP tmp2, TEMP result, KILL ccr); 12164 12165 ins_cost(300); 12166 format %{ "String Equals $str1,$str2,$cnt -> $result // TEMP $tmp1, $tmp2" %} 12167 ins_encode( enc_String_Equals(str1, str2, cnt, result, tmp1, tmp2) ); 12168 ins_pipe(long_memory_op); 12169%} 12170 12171// FIXME: Why R0/R1? 12172instruct array_equals(R0RegP ary1, R1RegP ary2, iRegI tmp1, iRegI tmp2, iRegI tmp3, iRegI result, 12173 flagsReg ccr) %{ 12174 predicate(((AryEqNode*)n)->encoding() == StrIntrinsicNode::UU); 12175 match(Set result (AryEq ary1 ary2)); 12176 effect(USE_KILL ary1, USE_KILL ary2, TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP result, KILL ccr); 12177 12178 ins_cost(300); 12179 format %{ "Array Equals $ary1,$ary2 -> $result // TEMP $tmp1,$tmp2,$tmp3" %} 12180 ins_encode( enc_Array_Equals(ary1, ary2, tmp1, tmp2, tmp3, result)); 12181 ins_pipe(long_memory_op); 12182%} 12183#endif 12184 12185//---------- Zeros Count Instructions ------------------------------------------ 12186 12187instruct countLeadingZerosI(iRegI dst, iRegI src) %{ 12188 match(Set dst (CountLeadingZerosI src)); 12189 size(4); 12190 format %{ "CLZ_32 $dst,$src" %} 12191 ins_encode %{ 12192 __ clz_32($dst$$Register, $src$$Register); 12193 %} 12194 ins_pipe(ialu_reg); 12195%} 12196 12197#ifdef AARCH64 12198instruct countLeadingZerosL(iRegI dst, iRegL src) %{ 12199 match(Set dst (CountLeadingZerosL src)); 12200 size(4); 12201 format %{ "CLZ $dst,$src" %} 12202 ins_encode %{ 12203 __ clz($dst$$Register, $src$$Register); 12204 %} 12205 ins_pipe(ialu_reg); 12206%} 12207#else 12208instruct countLeadingZerosL(iRegI dst, iRegL src, iRegI tmp, flagsReg ccr) %{ 12209 match(Set dst (CountLeadingZerosL src)); 12210 effect(TEMP tmp, TEMP dst, KILL ccr); 12211 size(16); 12212 format %{ "CLZ $dst,$src.hi\n\t" 12213 "TEQ $dst,32\n\t" 12214 "CLZ.eq $tmp,$src.lo\n\t" 12215 "ADD.eq $dst, $dst, $tmp\n\t" %} 12216 ins_encode %{ 12217 __ clz($dst$$Register, $src$$Register->successor()); 12218 __ teq($dst$$Register, 32); 12219 __ clz($tmp$$Register, $src$$Register, eq); 12220 __ add($dst$$Register, $dst$$Register, $tmp$$Register, eq); 12221 %} 12222 ins_pipe(ialu_reg); 12223%} 12224#endif 12225 12226instruct countTrailingZerosI(iRegI dst, iRegI src, iRegI tmp) %{ 12227 match(Set dst (CountTrailingZerosI src)); 12228 effect(TEMP tmp); 12229 size(8); 12230 format %{ "RBIT_32 $tmp, $src\n\t" 12231 "CLZ_32 $dst,$tmp" %} 12232 ins_encode %{ 12233 __ rbit_32($tmp$$Register, $src$$Register); 12234 __ clz_32($dst$$Register, $tmp$$Register); 12235 %} 12236 ins_pipe(ialu_reg); 12237%} 12238 12239#ifdef AARCH64 12240instruct countTrailingZerosL(iRegI dst, iRegL src, iRegL tmp) %{ 12241 match(Set dst (CountTrailingZerosL src)); 12242 effect(TEMP tmp); 12243 size(8); 12244 format %{ "RBIT $tmp, $src\n\t" 12245 "CLZ $dst,$tmp" %} 12246 ins_encode %{ 12247 __ rbit($tmp$$Register, $src$$Register); 12248 __ clz($dst$$Register, $tmp$$Register); 12249 %} 12250 ins_pipe(ialu_reg); 12251%} 12252#else 12253instruct countTrailingZerosL(iRegI dst, iRegL src, iRegI tmp, flagsReg ccr) %{ 12254 match(Set dst (CountTrailingZerosL src)); 12255 effect(TEMP tmp, TEMP dst, KILL ccr); 12256 size(24); 12257 format %{ "RBIT $tmp,$src.lo\n\t" 12258 "CLZ $dst,$tmp\n\t" 12259 "TEQ $dst,32\n\t" 12260 "RBIT $tmp,$src.hi\n\t" 12261 "CLZ.eq $tmp,$tmp\n\t" 12262 "ADD.eq $dst,$dst,$tmp\n\t" %} 12263 ins_encode %{ 12264 __ rbit($tmp$$Register, $src$$Register); 12265 __ clz($dst$$Register, $tmp$$Register); 12266 __ teq($dst$$Register, 32); 12267 __ rbit($tmp$$Register, $src$$Register->successor()); 12268 __ clz($tmp$$Register, $tmp$$Register, eq); 12269 __ add($dst$$Register, $dst$$Register, $tmp$$Register, eq); 12270 %} 12271 ins_pipe(ialu_reg); 12272%} 12273#endif 12274 12275 12276//---------- Population Count Instructions ------------------------------------- 12277 12278#ifdef AARCH64 12279instruct popCountI(iRegI dst, iRegI src, regD_low tmp) %{ 12280 predicate(UsePopCountInstruction); 12281 match(Set dst (PopCountI src)); 12282 effect(TEMP tmp); 12283 size(20); 12284 12285 format %{ "MOV_W $dst,$src\n\t" 12286 "FMOV_dx $tmp,$dst\n\t" 12287 "VCNT $tmp.8B,$tmp.8B\n\t" 12288 "ADDV $tmp.B,$tmp.8B\n\t" 12289 "FMRS $dst,$tmp" %} 12290 12291 ins_encode %{ 12292 __ mov_w($dst$$Register, $src$$Register); 12293 __ fmov_dx($tmp$$FloatRegister, $dst$$Register); 12294 int quad = 0; 12295 int cnt_size = 0; // VELEM_SIZE_8 12296 __ vcnt($tmp$$FloatRegister, $tmp$$FloatRegister, quad, cnt_size); 12297 int add_size = 0; // VELEM_SIZE_8 12298 __ addv($tmp$$FloatRegister, $tmp$$FloatRegister, quad, add_size); 12299 __ fmrs($dst$$Register, $tmp$$FloatRegister); 12300 %} 12301 ins_pipe(ialu_reg); // FIXME 12302%} 12303#else 12304instruct popCountI(iRegI dst, iRegI src, regD_low tmp) %{ 12305 predicate(UsePopCountInstruction); 12306 match(Set dst (PopCountI src)); 12307 effect(TEMP tmp); 12308 12309 format %{ "FMSR $tmp,$src\n\t" 12310 "VCNT.8 $tmp,$tmp\n\t" 12311 "VPADDL.U8 $tmp,$tmp\n\t" 12312 "VPADDL.U16 $tmp,$tmp\n\t" 12313 "FMRS $dst,$tmp" %} 12314 size(20); 12315 12316 ins_encode %{ 12317 __ fmsr($tmp$$FloatRegister, $src$$Register); 12318 __ vcnt($tmp$$FloatRegister, $tmp$$FloatRegister); 12319 __ vpaddl($tmp$$FloatRegister, $tmp$$FloatRegister, 8, 0); 12320 __ vpaddl($tmp$$FloatRegister, $tmp$$FloatRegister, 16, 0); 12321 __ fmrs($dst$$Register, $tmp$$FloatRegister); 12322 %} 12323 ins_pipe(ialu_reg); // FIXME 12324%} 12325#endif 12326 12327#ifdef AARCH64 12328instruct popCountL(iRegI dst, iRegL src, regD tmp) %{ 12329 predicate(UsePopCountInstruction); 12330 match(Set dst (PopCountL src)); 12331 effect(TEMP tmp); 12332 size(16); 12333 12334 format %{ "FMOV_dx $tmp,$src\n\t" 12335 "VCNT $tmp.8B,$tmp.8B\n\t" 12336 "ADDV $tmp.B,$tmp.8B\n\t" 12337 "FMOV_ws $dst,$tmp" %} 12338 12339 ins_encode %{ 12340 __ fmov_dx($tmp$$FloatRegister, $src$$Register); 12341 int quad = 0; 12342 int cnt_size = 0; 12343 __ vcnt($tmp$$FloatRegister, $tmp$$FloatRegister, quad, cnt_size); 12344 int add_size = 0; 12345 __ addv($tmp$$FloatRegister, $tmp$$FloatRegister, quad, add_size); 12346 __ fmov_ws($dst$$Register, $tmp$$FloatRegister); 12347 %} 12348 ins_pipe(ialu_reg); // FIXME 12349%} 12350#else 12351// Note: Long.bitCount(long) returns an int. 12352instruct popCountL(iRegI dst, iRegL src, regD_low tmp) %{ 12353 predicate(UsePopCountInstruction); 12354 match(Set dst (PopCountL src)); 12355 effect(TEMP tmp); 12356 12357 format %{ "FMDRR $tmp,$src.lo,$src.hi\n\t" 12358 "VCNT.8 $tmp,$tmp\n\t" 12359 "VPADDL.U8 $tmp,$tmp\n\t" 12360 "VPADDL.U16 $tmp,$tmp\n\t" 12361 "VPADDL.U32 $tmp,$tmp\n\t" 12362 "FMRS $dst,$tmp" %} 12363 12364 size(32); 12365 12366 ins_encode %{ 12367 __ fmdrr($tmp$$FloatRegister, $src$$Register, $src$$Register->successor()); 12368 __ vcnt($tmp$$FloatRegister, $tmp$$FloatRegister); 12369 __ vpaddl($tmp$$FloatRegister, $tmp$$FloatRegister, 8, 0); 12370 __ vpaddl($tmp$$FloatRegister, $tmp$$FloatRegister, 16, 0); 12371 __ vpaddl($tmp$$FloatRegister, $tmp$$FloatRegister, 32, 0); 12372 __ fmrs($dst$$Register, $tmp$$FloatRegister); 12373 %} 12374 ins_pipe(ialu_reg); 12375%} 12376#endif 12377 12378 12379// ============================================================================ 12380//------------Bytes reverse-------------------------------------------------- 12381 12382instruct bytes_reverse_int(iRegI dst, iRegI src) %{ 12383 match(Set dst (ReverseBytesI src)); 12384 12385 size(4); 12386 format %{ "REV32 $dst,$src" %} 12387 ins_encode %{ 12388#ifdef AARCH64 12389 __ rev_w($dst$$Register, $src$$Register); 12390 // high 32 bits zeroed, not sign extended 12391#else 12392 __ rev($dst$$Register, $src$$Register); 12393#endif 12394 %} 12395 ins_pipe( iload_mem ); // FIXME 12396%} 12397 12398instruct bytes_reverse_long(iRegL dst, iRegL src) %{ 12399 match(Set dst (ReverseBytesL src)); 12400#ifdef AARCH64 12401//size(4); 12402 format %{ "REV $dst,$src" %} 12403 ins_encode %{ 12404 __ rev($dst$$Register, $src$$Register); 12405 %} 12406 ins_pipe(ialu_reg_reg); // FIXME 12407#else 12408 effect(TEMP dst); 12409 size(8); 12410 format %{ "REV $dst.lo,$src.lo\n\t" 12411 "REV $dst.hi,$src.hi" %} 12412 ins_encode %{ 12413 __ rev($dst$$Register, $src$$Register->successor()); 12414 __ rev($dst$$Register->successor(), $src$$Register); 12415 %} 12416 ins_pipe( iload_mem ); // FIXME 12417#endif 12418%} 12419 12420instruct bytes_reverse_unsigned_short(iRegI dst, iRegI src) %{ 12421 match(Set dst (ReverseBytesUS src)); 12422#ifdef AARCH64 12423 size(4); 12424 format %{ "REV16_W $dst,$src" %} 12425 ins_encode %{ 12426 __ rev16_w($dst$$Register, $src$$Register); 12427 // high 32 bits zeroed 12428 %} 12429#else 12430 size(4); 12431 format %{ "REV16 $dst,$src" %} 12432 ins_encode %{ 12433 __ rev16($dst$$Register, $src$$Register); 12434 %} 12435#endif 12436 ins_pipe( iload_mem ); // FIXME 12437%} 12438 12439instruct bytes_reverse_short(iRegI dst, iRegI src) %{ 12440 match(Set dst (ReverseBytesS src)); 12441#ifdef AARCH64 12442 size(8); 12443 format %{ "REV16_W $dst,$src\n\t" 12444 "SIGN_EXT16 $dst" %} 12445 ins_encode %{ 12446 __ rev16_w($dst$$Register, $src$$Register); 12447 __ sign_extend($dst$$Register, $dst$$Register, 16); 12448 %} 12449#else 12450 size(4); 12451 format %{ "REVSH $dst,$src" %} 12452 ins_encode %{ 12453 __ revsh($dst$$Register, $src$$Register); 12454 %} 12455#endif 12456 ins_pipe( iload_mem ); // FIXME 12457%} 12458 12459 12460// ====================VECTOR INSTRUCTIONS===================================== 12461 12462// Load Aligned Packed values into a Double Register 12463instruct loadV8(vecD dst, memoryD mem) %{ 12464 predicate(n->as_LoadVector()->memory_size() == 8); 12465 match(Set dst (LoadVector mem)); 12466 ins_cost(MEMORY_REF_COST); 12467 size(4); 12468 format %{ "FLDD $mem,$dst\t! load vector (8 bytes)" %} 12469 ins_encode %{ 12470 __ ldr_double($dst$$FloatRegister, $mem$$Address); 12471 %} 12472 ins_pipe(floadD_mem); 12473%} 12474 12475// Load Aligned Packed values into a Double Register Pair 12476instruct loadV16(vecX dst, memoryvld mem) %{ 12477 predicate(n->as_LoadVector()->memory_size() == 16); 12478 match(Set dst (LoadVector mem)); 12479 ins_cost(MEMORY_REF_COST); 12480 size(4); 12481 format %{ "VLD1 $mem,$dst.Q\t! load vector (16 bytes)" %} 12482 ins_encode %{ 12483 __ vld1($dst$$FloatRegister, $mem$$Address, MacroAssembler::VELEM_SIZE_16, 128); 12484 %} 12485 ins_pipe(floadD_mem); // FIXME 12486%} 12487 12488// Store Vector in Double register to memory 12489instruct storeV8(memoryD mem, vecD src) %{ 12490 predicate(n->as_StoreVector()->memory_size() == 8); 12491 match(Set mem (StoreVector mem src)); 12492 ins_cost(MEMORY_REF_COST); 12493 size(4); 12494 format %{ "FSTD $src,$mem\t! store vector (8 bytes)" %} 12495 ins_encode %{ 12496 __ str_double($src$$FloatRegister, $mem$$Address); 12497 %} 12498 ins_pipe(fstoreD_mem_reg); 12499%} 12500 12501// Store Vector in Double Register Pair to memory 12502instruct storeV16(memoryvld mem, vecX src) %{ 12503 predicate(n->as_StoreVector()->memory_size() == 16); 12504 match(Set mem (StoreVector mem src)); 12505 ins_cost(MEMORY_REF_COST); 12506 size(4); 12507 format %{ "VST1 $src,$mem\t! store vector (16 bytes)" %} 12508 ins_encode %{ 12509 __ vst1($src$$FloatRegister, $mem$$Address, MacroAssembler::VELEM_SIZE_16, 128); 12510 %} 12511 ins_pipe(fstoreD_mem_reg); // FIXME 12512%} 12513 12514#ifndef AARCH64 12515// Replicate scalar to packed byte values in Double register 12516instruct Repl8B_reg(vecD dst, iRegI src, iRegI tmp) %{ 12517 predicate(n->as_Vector()->length() == 8); 12518 match(Set dst (ReplicateB src)); 12519 ins_cost(DEFAULT_COST*4); 12520 effect(TEMP tmp); 12521 size(16); 12522 12523 // FIXME: could use PKH instruction instead? 12524 format %{ "LSL $tmp, $src, 24 \n\t" 12525 "OR $tmp, $tmp, ($tmp >> 8) \n\t" 12526 "OR $tmp, $tmp, ($tmp >> 16) \n\t" 12527 "FMDRR $dst,$tmp,$tmp\t" %} 12528 ins_encode %{ 12529 __ mov($tmp$$Register, AsmOperand($src$$Register, lsl, 24)); 12530 __ orr($tmp$$Register, $tmp$$Register, AsmOperand($tmp$$Register, lsr, 8)); 12531 __ orr($tmp$$Register, $tmp$$Register, AsmOperand($tmp$$Register, lsr, 16)); 12532 __ fmdrr($dst$$FloatRegister, $tmp$$Register, $tmp$$Register); 12533 %} 12534 ins_pipe(ialu_reg); // FIXME 12535%} 12536#endif /* !AARCH64 */ 12537 12538// Replicate scalar to packed byte values in Double register 12539instruct Repl8B_reg_simd(vecD dst, iRegI src) %{ 12540 predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd()); 12541 match(Set dst (ReplicateB src)); 12542 size(4); 12543 12544 format %{ "VDUP.8 $dst,$src\t" %} 12545 ins_encode %{ 12546 bool quad = false; 12547 __ vdupI($dst$$FloatRegister, $src$$Register, 12548 MacroAssembler::VELEM_SIZE_8, quad); 12549 %} 12550 ins_pipe(ialu_reg); // FIXME 12551%} 12552 12553// Replicate scalar to packed byte values in Double register pair 12554instruct Repl16B_reg(vecX dst, iRegI src) %{ 12555 predicate(n->as_Vector()->length_in_bytes() == 16); 12556 match(Set dst (ReplicateB src)); 12557 size(4); 12558 12559 format %{ "VDUP.8 $dst.Q,$src\t" %} 12560 ins_encode %{ 12561 bool quad = true; 12562 __ vdupI($dst$$FloatRegister, $src$$Register, 12563 MacroAssembler::VELEM_SIZE_8, quad); 12564 %} 12565 ins_pipe(ialu_reg); // FIXME 12566%} 12567 12568#ifndef AARCH64 12569// Replicate scalar constant to packed byte values in Double register 12570instruct Repl8B_immI(vecD dst, immI src, iRegI tmp) %{ 12571 predicate(n->as_Vector()->length() == 8); 12572 match(Set dst (ReplicateB src)); 12573 ins_cost(DEFAULT_COST*2); 12574 effect(TEMP tmp); 12575 size(12); 12576 12577 format %{ "MOV $tmp, Repl4($src))\n\t" 12578 "FMDRR $dst,$tmp,$tmp\t" %} 12579 ins_encode( LdReplImmI(src, dst, tmp, (4), (1)) ); 12580 ins_pipe(loadConFD); // FIXME 12581%} 12582#endif /* !AARCH64 */ 12583 12584// Replicate scalar constant to packed byte values in Double register 12585// TODO: support negative constants with MVNI? 12586instruct Repl8B_immU8(vecD dst, immU8 src) %{ 12587 predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd()); 12588 match(Set dst (ReplicateB src)); 12589 size(4); 12590 12591 format %{ "VMOV.U8 $dst,$src" %} 12592 ins_encode %{ 12593 bool quad = false; 12594 __ vmovI($dst$$FloatRegister, $src$$constant, 12595 MacroAssembler::VELEM_SIZE_8, quad); 12596 %} 12597 ins_pipe(loadConFD); // FIXME 12598%} 12599 12600// Replicate scalar constant to packed byte values in Double register pair 12601instruct Repl16B_immU8(vecX dst, immU8 src) %{ 12602 predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd()); 12603 match(Set dst (ReplicateB src)); 12604 size(4); 12605 12606 format %{ "VMOV.U8 $dst.Q,$src" %} 12607 ins_encode %{ 12608 bool quad = true; 12609 __ vmovI($dst$$FloatRegister, $src$$constant, 12610 MacroAssembler::VELEM_SIZE_8, quad); 12611 %} 12612 ins_pipe(loadConFD); // FIXME 12613%} 12614 12615#ifndef AARCH64 12616// Replicate scalar to packed short/char values into Double register 12617instruct Repl4S_reg(vecD dst, iRegI src, iRegI tmp) %{ 12618 predicate(n->as_Vector()->length() == 4); 12619 match(Set dst (ReplicateS src)); 12620 ins_cost(DEFAULT_COST*3); 12621 effect(TEMP tmp); 12622 size(12); 12623 12624 // FIXME: could use PKH instruction instead? 12625 format %{ "LSL $tmp, $src, 16 \n\t" 12626 "OR $tmp, $tmp, ($tmp >> 16) \n\t" 12627 "FMDRR $dst,$tmp,$tmp\t" %} 12628 ins_encode %{ 12629 __ mov($tmp$$Register, AsmOperand($src$$Register, lsl, 16)); 12630 __ orr($tmp$$Register, $tmp$$Register, AsmOperand($tmp$$Register, lsr, 16)); 12631 __ fmdrr($dst$$FloatRegister, $tmp$$Register, $tmp$$Register); 12632 %} 12633 ins_pipe(ialu_reg); // FIXME 12634%} 12635#endif /* !AARCH64 */ 12636 12637// Replicate scalar to packed byte values in Double register 12638instruct Repl4S_reg_simd(vecD dst, iRegI src) %{ 12639 predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd()); 12640 match(Set dst (ReplicateS src)); 12641 size(4); 12642 12643 format %{ "VDUP.16 $dst,$src\t" %} 12644 ins_encode %{ 12645 bool quad = false; 12646 __ vdupI($dst$$FloatRegister, $src$$Register, 12647 MacroAssembler::VELEM_SIZE_16, quad); 12648 %} 12649 ins_pipe(ialu_reg); // FIXME 12650%} 12651 12652// Replicate scalar to packed byte values in Double register pair 12653instruct Repl8S_reg(vecX dst, iRegI src) %{ 12654 predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd()); 12655 match(Set dst (ReplicateS src)); 12656 size(4); 12657 12658 format %{ "VDUP.16 $dst.Q,$src\t" %} 12659 ins_encode %{ 12660 bool quad = true; 12661 __ vdupI($dst$$FloatRegister, $src$$Register, 12662 MacroAssembler::VELEM_SIZE_16, quad); 12663 %} 12664 ins_pipe(ialu_reg); // FIXME 12665%} 12666 12667 12668#ifndef AARCH64 12669// Replicate scalar constant to packed short/char values in Double register 12670instruct Repl4S_immI(vecD dst, immI src, iRegP tmp) %{ 12671 predicate(n->as_Vector()->length() == 4); 12672 match(Set dst (ReplicateS src)); 12673 effect(TEMP tmp); 12674 size(12); 12675 ins_cost(DEFAULT_COST*4); // FIXME 12676 12677 format %{ "MOV $tmp, Repl2($src))\n\t" 12678 "FMDRR $dst,$tmp,$tmp\t" %} 12679 ins_encode( LdReplImmI(src, dst, tmp, (2), (2)) ); 12680 ins_pipe(loadConFD); // FIXME 12681%} 12682#endif /* !AARCH64 */ 12683 12684// Replicate scalar constant to packed byte values in Double register 12685instruct Repl4S_immU8(vecD dst, immU8 src) %{ 12686 predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd()); 12687 match(Set dst (ReplicateS src)); 12688 size(4); 12689 12690 format %{ "VMOV.U16 $dst,$src" %} 12691 ins_encode %{ 12692 bool quad = false; 12693 __ vmovI($dst$$FloatRegister, $src$$constant, 12694 MacroAssembler::VELEM_SIZE_16, quad); 12695 %} 12696 ins_pipe(loadConFD); // FIXME 12697%} 12698 12699// Replicate scalar constant to packed byte values in Double register pair 12700instruct Repl8S_immU8(vecX dst, immU8 src) %{ 12701 predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd()); 12702 match(Set dst (ReplicateS src)); 12703 size(4); 12704 12705 format %{ "VMOV.U16 $dst.Q,$src" %} 12706 ins_encode %{ 12707 bool quad = true; 12708 __ vmovI($dst$$FloatRegister, $src$$constant, 12709 MacroAssembler::VELEM_SIZE_16, quad); 12710 %} 12711 ins_pipe(loadConFD); // FIXME 12712%} 12713 12714#ifndef AARCH64 12715// Replicate scalar to packed int values in Double register 12716instruct Repl2I_reg(vecD dst, iRegI src) %{ 12717 predicate(n->as_Vector()->length() == 2); 12718 match(Set dst (ReplicateI src)); 12719 size(4); 12720 12721 format %{ "FMDRR $dst,$src,$src\t" %} 12722 ins_encode %{ 12723 __ fmdrr($dst$$FloatRegister, $src$$Register, $src$$Register); 12724 %} 12725 ins_pipe(ialu_reg); // FIXME 12726%} 12727 12728// Replicate scalar to packed int values in Double register pair 12729instruct Repl4I_reg(vecX dst, iRegI src) %{ 12730 predicate(n->as_Vector()->length() == 4); 12731 match(Set dst (ReplicateI src)); 12732 ins_cost(DEFAULT_COST*2); 12733 size(8); 12734 12735 format %{ "FMDRR $dst.lo,$src,$src\n\t" 12736 "FMDRR $dst.hi,$src,$src" %} 12737 12738 ins_encode %{ 12739 __ fmdrr($dst$$FloatRegister, $src$$Register, $src$$Register); 12740 __ fmdrr($dst$$FloatRegister->successor()->successor(), 12741 $src$$Register, $src$$Register); 12742 %} 12743 ins_pipe(ialu_reg); // FIXME 12744%} 12745#endif /* !AARCH64 */ 12746 12747// Replicate scalar to packed int values in Double register 12748instruct Repl2I_reg_simd(vecD dst, iRegI src) %{ 12749 predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd()); 12750 match(Set dst (ReplicateI src)); 12751 size(4); 12752 12753 format %{ "VDUP.32 $dst.D,$src\t" %} 12754 ins_encode %{ 12755 bool quad = false; 12756 __ vdupI($dst$$FloatRegister, $src$$Register, 12757 MacroAssembler::VELEM_SIZE_32, quad); 12758 %} 12759 ins_pipe(ialu_reg); // FIXME 12760%} 12761 12762// Replicate scalar to packed int values in Double register pair 12763instruct Repl4I_reg_simd(vecX dst, iRegI src) %{ 12764 predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd()); 12765 match(Set dst (ReplicateI src)); 12766 size(4); 12767 12768 format %{ "VDUP.32 $dst.Q,$src\t" %} 12769 ins_encode %{ 12770 bool quad = true; 12771 __ vdupI($dst$$FloatRegister, $src$$Register, 12772 MacroAssembler::VELEM_SIZE_32, quad); 12773 %} 12774 ins_pipe(ialu_reg); // FIXME 12775%} 12776 12777 12778#ifndef AARCH64 12779// Replicate scalar zero constant to packed int values in Double register 12780instruct Repl2I_immI(vecD dst, immI src, iRegI tmp) %{ 12781 predicate(n->as_Vector()->length() == 2); 12782 match(Set dst (ReplicateI src)); 12783 effect(TEMP tmp); 12784 size(12); 12785 ins_cost(DEFAULT_COST*4); // FIXME 12786 12787 format %{ "MOV $tmp, Repl1($src))\n\t" 12788 "FMDRR $dst,$tmp,$tmp\t" %} 12789 ins_encode( LdReplImmI(src, dst, tmp, (1), (4)) ); 12790 ins_pipe(loadConFD); // FIXME 12791%} 12792#endif /* !AARCH64 */ 12793 12794// Replicate scalar constant to packed byte values in Double register 12795instruct Repl2I_immU8(vecD dst, immU8 src) %{ 12796 predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd()); 12797 match(Set dst (ReplicateI src)); 12798 size(4); 12799 12800 format %{ "VMOV.I32 $dst.D,$src" %} 12801 ins_encode %{ 12802 bool quad = false; 12803 __ vmovI($dst$$FloatRegister, $src$$constant, 12804 MacroAssembler::VELEM_SIZE_32, quad); 12805 %} 12806 ins_pipe(loadConFD); // FIXME 12807%} 12808 12809// Replicate scalar constant to packed byte values in Double register pair 12810instruct Repl4I_immU8(vecX dst, immU8 src) %{ 12811 predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd()); 12812 match(Set dst (ReplicateI src)); 12813 size(4); 12814 12815 format %{ "VMOV.I32 $dst.Q,$src" %} 12816 ins_encode %{ 12817 bool quad = true; 12818 __ vmovI($dst$$FloatRegister, $src$$constant, 12819 MacroAssembler::VELEM_SIZE_32, quad); 12820 %} 12821 ins_pipe(loadConFD); // FIXME 12822%} 12823 12824#ifdef AARCH64 12825// Replicate scalar to packed byte values in Double register pair 12826instruct Repl2L_reg(vecX dst, iRegL src) %{ 12827 predicate(n->as_Vector()->length() == 2); 12828 match(Set dst (ReplicateL src)); 12829 size(4*1); 12830 ins_cost(DEFAULT_COST*1); // FIXME 12831 12832 format %{ "VDUP.2D $dst.Q,$src\t" %} 12833 ins_encode %{ 12834 bool quad = true; 12835 __ vdupI($dst$$FloatRegister, $src$$Register, 12836 MacroAssembler::VELEM_SIZE_64, quad); 12837 %} 12838 ins_pipe(ialu_reg); // FIXME 12839%} 12840#else /* !AARCH64 */ 12841// Replicate scalar to packed byte values in Double register pair 12842instruct Repl2L_reg(vecX dst, iRegL src) %{ 12843 predicate(n->as_Vector()->length() == 2); 12844 match(Set dst (ReplicateL src)); 12845 size(8); 12846 ins_cost(DEFAULT_COST*2); // FIXME 12847 12848 format %{ "FMDRR $dst.D,$src.lo,$src.hi\t\n" 12849 "FMDRR $dst.D.next,$src.lo,$src.hi" %} 12850 ins_encode %{ 12851 __ fmdrr($dst$$FloatRegister, $src$$Register, $src$$Register->successor()); 12852 __ fmdrr($dst$$FloatRegister->successor()->successor(), 12853 $src$$Register, $src$$Register->successor()); 12854 %} 12855 ins_pipe(ialu_reg); // FIXME 12856%} 12857 12858 12859// Replicate scalar to packed float values in Double register 12860instruct Repl2F_regI(vecD dst, iRegI src) %{ 12861 predicate(n->as_Vector()->length() == 2); 12862 match(Set dst (ReplicateF src)); 12863 size(4); 12864 12865 format %{ "FMDRR $dst.D,$src,$src\t" %} 12866 ins_encode %{ 12867 __ fmdrr($dst$$FloatRegister, $src$$Register, $src$$Register); 12868 %} 12869 ins_pipe(ialu_reg); // FIXME 12870%} 12871 12872// Replicate scalar to packed float values in Double register 12873instruct Repl2F_reg_vfp(vecD dst, regF src) %{ 12874 predicate(n->as_Vector()->length() == 2); 12875 match(Set dst (ReplicateF src)); 12876 size(4*2); 12877 ins_cost(DEFAULT_COST*2); // FIXME 12878 12879 expand %{ 12880 iRegI tmp; 12881 MoveF2I_reg_reg(tmp, src); 12882 Repl2F_regI(dst,tmp); 12883 %} 12884%} 12885#endif /* !AARCH64 */ 12886 12887// Replicate scalar to packed float values in Double register 12888instruct Repl2F_reg_simd(vecD dst, regF src) %{ 12889 predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd()); 12890 match(Set dst (ReplicateF src)); 12891 size(4); 12892 ins_cost(DEFAULT_COST); // FIXME 12893 12894 format %{ "VDUP.32 $dst.D,$src.D\t" %} 12895 ins_encode %{ 12896 bool quad = false; 12897 __ vdupF($dst$$FloatRegister, $src$$FloatRegister, quad); 12898 %} 12899 ins_pipe(ialu_reg); // FIXME 12900%} 12901 12902#ifndef AARCH64 12903// Replicate scalar to packed float values in Double register pair 12904instruct Repl4F_reg(vecX dst, regF src, iRegI tmp) %{ 12905 predicate(n->as_Vector()->length() == 4); 12906 match(Set dst (ReplicateF src)); 12907 effect(TEMP tmp); 12908 size(4*3); 12909 ins_cost(DEFAULT_COST*3); // FIXME 12910 12911 format %{ "FMRS $tmp,$src\n\t" 12912 "FMDRR $dst.D,$tmp,$tmp\n\t" 12913 "FMDRR $dst.D.next,$tmp,$tmp\t" %} 12914 ins_encode %{ 12915 __ fmrs($tmp$$Register, $src$$FloatRegister); 12916 __ fmdrr($dst$$FloatRegister, $tmp$$Register, $tmp$$Register); 12917 __ fmdrr($dst$$FloatRegister->successor()->successor(), 12918 $tmp$$Register, $tmp$$Register); 12919 %} 12920 ins_pipe(ialu_reg); // FIXME 12921%} 12922#endif /* !AARCH64 */ 12923 12924// Replicate scalar to packed float values in Double register pair 12925instruct Repl4F_reg_simd(vecX dst, regF src) %{ 12926 predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd()); 12927 match(Set dst (ReplicateF src)); 12928 size(4); 12929 ins_cost(DEFAULT_COST); // FIXME 12930 12931 format %{ "VDUP.32 $dst.Q,$src.D\t" %} 12932 ins_encode %{ 12933 bool quad = true; 12934 __ vdupF($dst$$FloatRegister, $src$$FloatRegister, quad); 12935 %} 12936 ins_pipe(ialu_reg); // FIXME 12937%} 12938 12939#ifndef AARCH64 12940// Replicate scalar zero constant to packed float values in Double register 12941instruct Repl2F_immI(vecD dst, immF src, iRegI tmp) %{ 12942 predicate(n->as_Vector()->length() == 2); 12943 match(Set dst (ReplicateF src)); 12944 effect(TEMP tmp); 12945 size(12); 12946 ins_cost(DEFAULT_COST*4); // FIXME 12947 12948 format %{ "MOV $tmp, Repl1($src))\n\t" 12949 "FMDRR $dst,$tmp,$tmp\t" %} 12950 ins_encode( LdReplImmF(src, dst, tmp) ); 12951 ins_pipe(loadConFD); // FIXME 12952%} 12953#endif /* !AAARCH64 */ 12954 12955// Replicate scalar to packed double float values in Double register pair 12956instruct Repl2D_reg(vecX dst, regD src) %{ 12957#ifdef AARCH64 12958 predicate(n->as_Vector()->length() == 2 && VM_Version::has_simd()); 12959 match(Set dst (ReplicateD src)); 12960 size(4*1); 12961 ins_cost(DEFAULT_COST*1); // FIXME 12962 12963 format %{ "VDUP $dst.2D,$src\t" %} 12964 ins_encode %{ 12965 bool quad = true; 12966 __ vdupD($dst$$FloatRegister, $src$$FloatRegister, quad); 12967 %} 12968#else 12969 predicate(n->as_Vector()->length() == 2); 12970 match(Set dst (ReplicateD src)); 12971 size(4*2); 12972 ins_cost(DEFAULT_COST*2); // FIXME 12973 12974 format %{ "FCPYD $dst.D.a,$src\n\t" 12975 "FCPYD $dst.D.b,$src\t" %} 12976 ins_encode %{ 12977 FloatRegister dsta = $dst$$FloatRegister; 12978 FloatRegister src = $src$$FloatRegister; 12979 __ fcpyd(dsta, src); 12980 FloatRegister dstb = dsta->successor()->successor(); 12981 __ fcpyd(dstb, src); 12982 %} 12983#endif 12984 ins_pipe(ialu_reg); // FIXME 12985%} 12986 12987// ====================VECTOR ARITHMETIC======================================= 12988 12989// --------------------------------- ADD -------------------------------------- 12990 12991// Bytes vector add 12992instruct vadd8B_reg(vecD dst, vecD src1, vecD src2) %{ 12993 predicate(n->as_Vector()->length() == 8); 12994 match(Set dst (AddVB src1 src2)); 12995 format %{ "VADD.I8 $dst,$src1,$src2\t! add packed8B" %} 12996 size(4); 12997 ins_encode %{ 12998 bool quad = false; 12999 __ vaddI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 13000 MacroAssembler::VELEM_SIZE_8, quad); 13001 %} 13002 ins_pipe( ialu_reg_reg ); // FIXME 13003%} 13004 13005instruct vadd16B_reg(vecX dst, vecX src1, vecX src2) %{ 13006 predicate(n->as_Vector()->length() == 16); 13007 match(Set dst (AddVB src1 src2)); 13008 size(4); 13009 format %{ "VADD.I8 $dst.Q,$src1.Q,$src2.Q\t! add packed16B" %} 13010 ins_encode %{ 13011 bool quad = true; 13012 __ vaddI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 13013 MacroAssembler::VELEM_SIZE_8, quad); 13014 %} 13015 ins_pipe( ialu_reg_reg ); // FIXME 13016%} 13017 13018// Shorts/Chars vector add 13019instruct vadd4S_reg(vecD dst, vecD src1, vecD src2) %{ 13020 predicate(n->as_Vector()->length() == 4); 13021 match(Set dst (AddVS src1 src2)); 13022 size(4); 13023 format %{ "VADD.I16 $dst,$src1,$src2\t! add packed4S" %} 13024 ins_encode %{ 13025 bool quad = false; 13026 __ vaddI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 13027 MacroAssembler::VELEM_SIZE_16, quad); 13028 %} 13029 ins_pipe( ialu_reg_reg ); // FIXME 13030%} 13031 13032instruct vadd8S_reg(vecX dst, vecX src1, vecX src2) %{ 13033 predicate(n->as_Vector()->length() == 8); 13034 match(Set dst (AddVS src1 src2)); 13035 size(4); 13036 format %{ "VADD.I16 $dst.Q,$src1.Q,$src2.Q\t! add packed8S" %} 13037 ins_encode %{ 13038 bool quad = true; 13039 __ vaddI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 13040 MacroAssembler::VELEM_SIZE_16, quad); 13041 %} 13042 ins_pipe( ialu_reg_reg ); // FIXME 13043%} 13044 13045// Integers vector add 13046instruct vadd2I_reg(vecD dst, vecD src1, vecD src2) %{ 13047 predicate(n->as_Vector()->length() == 2); 13048 match(Set dst (AddVI src1 src2)); 13049 size(4); 13050 format %{ "VADD.I32 $dst.D,$src1.D,$src2.D\t! add packed2I" %} 13051 ins_encode %{ 13052 bool quad = false; 13053 __ vaddI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 13054 MacroAssembler::VELEM_SIZE_32, quad); 13055 %} 13056 ins_pipe( ialu_reg_reg ); // FIXME 13057%} 13058 13059instruct vadd4I_reg(vecX dst, vecX src1, vecX src2) %{ 13060 predicate(n->as_Vector()->length() == 4); 13061 match(Set dst (AddVI src1 src2)); 13062 size(4); 13063 format %{ "VADD.I32 $dst.Q,$src1.Q,$src2.Q\t! add packed4I" %} 13064 ins_encode %{ 13065 bool quad = true; 13066 __ vaddI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 13067 MacroAssembler::VELEM_SIZE_32, quad); 13068 %} 13069 ins_pipe( ialu_reg_reg ); // FIXME 13070%} 13071 13072// Longs vector add 13073instruct vadd2L_reg(vecX dst, vecX src1, vecX src2) %{ 13074 predicate(n->as_Vector()->length() == 2); 13075 match(Set dst (AddVL src1 src2)); 13076 size(4); 13077 format %{ "VADD.I64 $dst.Q,$src1.Q,$src2.Q\t! add packed2L" %} 13078 ins_encode %{ 13079 bool quad = true; 13080 __ vaddI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 13081 MacroAssembler::VELEM_SIZE_64, quad); 13082 %} 13083 ins_pipe( ialu_reg_reg ); // FIXME 13084%} 13085 13086// Floats vector add 13087instruct vadd2F_reg(vecD dst, vecD src1, vecD src2) %{ 13088 predicate(n->as_Vector()->length() == 2 && VM_Version::simd_math_is_compliant()); 13089 match(Set dst (AddVF src1 src2)); 13090 size(4); 13091 format %{ "VADD.F32 $dst,$src1,$src2\t! add packed2F" %} 13092 ins_encode %{ 13093 bool quad = false; 13094 __ vaddF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 13095 MacroAssembler::VFA_SIZE_F32, quad); 13096 %} 13097 ins_pipe( faddD_reg_reg ); // FIXME 13098%} 13099 13100#ifndef AARCH64 13101instruct vadd2F_reg_vfp(vecD dst, vecD src1, vecD src2) %{ 13102 predicate(n->as_Vector()->length() == 2 && !VM_Version::simd_math_is_compliant()); 13103 match(Set dst (AddVF src1 src2)); 13104 ins_cost(DEFAULT_COST*2); // FIXME 13105 13106 size(4*2); 13107 format %{ "FADDS $dst.a,$src1.a,$src2.a\n\t" 13108 "FADDS $dst.b,$src1.b,$src2.b" %} 13109 ins_encode %{ 13110 __ add_float($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister); 13111 __ add_float($dst$$FloatRegister->successor(), 13112 $src1$$FloatRegister->successor(), 13113 $src2$$FloatRegister->successor()); 13114 %} 13115 13116 ins_pipe(faddF_reg_reg); // FIXME 13117%} 13118#endif 13119 13120instruct vadd4F_reg_simd(vecX dst, vecX src1, vecX src2) %{ 13121 predicate(n->as_Vector()->length() == 4 && VM_Version::simd_math_is_compliant()); 13122 match(Set dst (AddVF src1 src2)); 13123 size(4); 13124 format %{ "VADD.F32 $dst.Q,$src1.Q,$src2.Q\t! add packed4F" %} 13125 ins_encode %{ 13126 bool quad = true; 13127 __ vaddF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 13128 MacroAssembler::VFA_SIZE_F32, quad); 13129 %} 13130 ins_pipe( faddD_reg_reg ); // FIXME 13131%} 13132 13133#ifdef AARCH64 13134instruct vadd2D_reg_simd(vecX dst, vecX src1, vecX src2) %{ 13135 predicate(n->as_Vector()->length() == 2 && VM_Version::simd_math_is_compliant()); 13136 match(Set dst (AddVD src1 src2)); 13137 size(4); 13138 format %{ "VADD.F64 $dst.Q,$src1.Q,$src2.Q\t! add packed2D" %} 13139 ins_encode %{ 13140 bool quad = true; 13141 __ vaddF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 13142 MacroAssembler::VFA_SIZE_F64, quad); 13143 %} 13144 ins_pipe( faddD_reg_reg ); // FIXME 13145%} 13146#else 13147instruct vadd4F_reg_vfp(vecX dst, vecX src1, vecX src2) %{ 13148 predicate(n->as_Vector()->length() == 4 && !VM_Version::simd_math_is_compliant()); 13149 match(Set dst (AddVF src1 src2)); 13150 size(4*4); 13151 ins_cost(DEFAULT_COST*4); // FIXME 13152 13153 format %{ "FADDS $dst.a,$src1.a,$src2.a\n\t" 13154 "FADDS $dst.b,$src1.b,$src2.b\n\t" 13155 "FADDS $dst.c,$src1.c,$src2.c\n\t" 13156 "FADDS $dst.d,$src1.d,$src2.d" %} 13157 13158 ins_encode %{ 13159 FloatRegister dsta = $dst$$FloatRegister; 13160 FloatRegister src1a = $src1$$FloatRegister; 13161 FloatRegister src2a = $src2$$FloatRegister; 13162 __ add_float(dsta, src1a, src2a); 13163 FloatRegister dstb = dsta->successor(); 13164 FloatRegister src1b = src1a->successor(); 13165 FloatRegister src2b = src2a->successor(); 13166 __ add_float(dstb, src1b, src2b); 13167 FloatRegister dstc = dstb->successor(); 13168 FloatRegister src1c = src1b->successor(); 13169 FloatRegister src2c = src2b->successor(); 13170 __ add_float(dstc, src1c, src2c); 13171 FloatRegister dstd = dstc->successor(); 13172 FloatRegister src1d = src1c->successor(); 13173 FloatRegister src2d = src2c->successor(); 13174 __ add_float(dstd, src1d, src2d); 13175 %} 13176 13177 ins_pipe(faddF_reg_reg); // FIXME 13178%} 13179 13180instruct vadd2D_reg_vfp(vecX dst, vecX src1, vecX src2) %{ 13181 predicate(n->as_Vector()->length() == 2); 13182 match(Set dst (AddVD src1 src2)); 13183 size(4*2); 13184 ins_cost(DEFAULT_COST*2); // FIXME 13185 13186 format %{ "FADDD $dst.a,$src1.a,$src2.a\n\t" 13187 "FADDD $dst.b,$src1.b,$src2.b" %} 13188 13189 ins_encode %{ 13190 FloatRegister dsta = $dst$$FloatRegister; 13191 FloatRegister src1a = $src1$$FloatRegister; 13192 FloatRegister src2a = $src2$$FloatRegister; 13193 __ add_double(dsta, src1a, src2a); 13194 FloatRegister dstb = dsta->successor()->successor(); 13195 FloatRegister src1b = src1a->successor()->successor(); 13196 FloatRegister src2b = src2a->successor()->successor(); 13197 __ add_double(dstb, src1b, src2b); 13198 %} 13199 13200 ins_pipe(faddF_reg_reg); // FIXME 13201%} 13202#endif 13203 13204 13205// Bytes vector sub 13206instruct vsub8B_reg(vecD dst, vecD src1, vecD src2) %{ 13207 predicate(n->as_Vector()->length() == 8); 13208 match(Set dst (SubVB src1 src2)); 13209 size(4); 13210 format %{ "VSUB.I8 $dst,$src1,$src2\t! sub packed8B" %} 13211 ins_encode %{ 13212 bool quad = false; 13213 __ vsubI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 13214 MacroAssembler::VELEM_SIZE_8, quad); 13215 %} 13216 ins_pipe( ialu_reg_reg ); // FIXME 13217%} 13218 13219instruct vsub16B_reg(vecX dst, vecX src1, vecX src2) %{ 13220 predicate(n->as_Vector()->length() == 16); 13221 match(Set dst (SubVB src1 src2)); 13222 size(4); 13223 format %{ "VSUB.I8 $dst.Q,$src1.Q,$src2.Q\t! sub packed16B" %} 13224 ins_encode %{ 13225 bool quad = true; 13226 __ vsubI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 13227 MacroAssembler::VELEM_SIZE_8, quad); 13228 %} 13229 ins_pipe( ialu_reg_reg ); // FIXME 13230%} 13231 13232// Shorts/Chars vector sub 13233instruct vsub4S_reg(vecD dst, vecD src1, vecD src2) %{ 13234 predicate(n->as_Vector()->length() == 4); 13235 match(Set dst (SubVS src1 src2)); 13236 size(4); 13237 format %{ "VSUB.I16 $dst,$src1,$src2\t! sub packed4S" %} 13238 ins_encode %{ 13239 bool quad = false; 13240 __ vsubI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 13241 MacroAssembler::VELEM_SIZE_16, quad); 13242 %} 13243 ins_pipe( ialu_reg_reg ); // FIXME 13244%} 13245 13246instruct vsub16S_reg(vecX dst, vecX src1, vecX src2) %{ 13247 predicate(n->as_Vector()->length() == 8); 13248 match(Set dst (SubVS src1 src2)); 13249 size(4); 13250 format %{ "VSUB.I16 $dst.Q,$src1.Q,$src2.Q\t! sub packed8S" %} 13251 ins_encode %{ 13252 bool quad = true; 13253 __ vsubI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 13254 MacroAssembler::VELEM_SIZE_16, quad); 13255 %} 13256 ins_pipe( ialu_reg_reg ); // FIXME 13257%} 13258 13259// Integers vector sub 13260instruct vsub2I_reg(vecD dst, vecD src1, vecD src2) %{ 13261 predicate(n->as_Vector()->length() == 2); 13262 match(Set dst (SubVI src1 src2)); 13263 size(4); 13264 format %{ "VSUB.I32 $dst,$src1,$src2\t! sub packed2I" %} 13265 ins_encode %{ 13266 bool quad = false; 13267 __ vsubI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 13268 MacroAssembler::VELEM_SIZE_32, quad); 13269 %} 13270 ins_pipe( ialu_reg_reg ); // FIXME 13271%} 13272 13273instruct vsub4I_reg(vecX dst, vecX src1, vecX src2) %{ 13274 predicate(n->as_Vector()->length() == 4); 13275 match(Set dst (SubVI src1 src2)); 13276 size(4); 13277 format %{ "VSUB.I32 $dst.Q,$src1.Q,$src2.Q\t! sub packed4I" %} 13278 ins_encode %{ 13279 bool quad = true; 13280 __ vsubI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 13281 MacroAssembler::VELEM_SIZE_32, quad); 13282 %} 13283 ins_pipe( ialu_reg_reg ); // FIXME 13284%} 13285 13286// Longs vector sub 13287instruct vsub2L_reg(vecX dst, vecX src1, vecX src2) %{ 13288 predicate(n->as_Vector()->length() == 2); 13289 match(Set dst (SubVL src1 src2)); 13290 size(4); 13291 format %{ "VSUB.I64 $dst.Q,$src1.Q,$src2.Q\t! sub packed2L" %} 13292 ins_encode %{ 13293 bool quad = true; 13294 __ vsubI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 13295 MacroAssembler::VELEM_SIZE_64, quad); 13296 %} 13297 ins_pipe( ialu_reg_reg ); // FIXME 13298%} 13299 13300// Floats vector sub 13301instruct vsub2F_reg(vecD dst, vecD src1, vecD src2) %{ 13302 predicate(n->as_Vector()->length() == 2 && VM_Version::simd_math_is_compliant()); 13303 match(Set dst (SubVF src1 src2)); 13304 size(4); 13305 format %{ "VSUB.F32 $dst,$src1,$src2\t! sub packed2F" %} 13306 ins_encode %{ 13307 bool quad = false; 13308 __ vsubF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 13309 MacroAssembler::VFA_SIZE_F32, quad); 13310 %} 13311 ins_pipe( faddF_reg_reg ); // FIXME 13312%} 13313 13314#ifndef AARCH64 13315instruct vsub2F_reg_vfp(vecD dst, vecD src1, vecD src2) %{ 13316 predicate(n->as_Vector()->length() == 2 && !VM_Version::simd_math_is_compliant()); 13317 match(Set dst (SubVF src1 src2)); 13318 size(4*2); 13319 ins_cost(DEFAULT_COST*2); // FIXME 13320 13321 format %{ "FSUBS $dst.a,$src1.a,$src2.a\n\t" 13322 "FSUBS $dst.b,$src1.b,$src2.b" %} 13323 13324 ins_encode %{ 13325 FloatRegister dsta = $dst$$FloatRegister; 13326 FloatRegister src1a = $src1$$FloatRegister; 13327 FloatRegister src2a = $src2$$FloatRegister; 13328 __ sub_float(dsta, src1a, src2a); 13329 FloatRegister dstb = dsta->successor(); 13330 FloatRegister src1b = src1a->successor(); 13331 FloatRegister src2b = src2a->successor(); 13332 __ sub_float(dstb, src1b, src2b); 13333 %} 13334 13335 ins_pipe(faddF_reg_reg); // FIXME 13336%} 13337#endif 13338 13339 13340instruct vsub4F_reg(vecX dst, vecX src1, vecX src2) %{ 13341 predicate(n->as_Vector()->length() == 4 && VM_Version::simd_math_is_compliant()); 13342 match(Set dst (SubVF src1 src2)); 13343 size(4); 13344 format %{ "VSUB.F32 $dst.Q,$src1.Q,$src2.Q\t! sub packed4F" %} 13345 ins_encode %{ 13346 bool quad = true; 13347 __ vsubF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 13348 MacroAssembler::VFA_SIZE_F32, quad); 13349 %} 13350 ins_pipe( faddF_reg_reg ); // FIXME 13351%} 13352 13353#ifdef AARCH64 13354instruct vsub2D_reg_simd(vecX dst, vecX src1, vecX src2) %{ 13355 predicate(n->as_Vector()->length() == 2 && VM_Version::simd_math_is_compliant()); 13356 match(Set dst (SubVD src1 src2)); 13357 size(4); 13358 format %{ "VSUB.F64 $dst.Q,$src1.Q,$src2.Q\t! add packed2D" %} 13359 ins_encode %{ 13360 bool quad = true; 13361 __ vsubF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 13362 MacroAssembler::VFA_SIZE_F64, quad); 13363 %} 13364 ins_pipe( faddD_reg_reg ); // FIXME 13365%} 13366#else 13367instruct vsub4F_reg_vfp(vecX dst, vecX src1, vecX src2) %{ 13368 predicate(n->as_Vector()->length() == 4 && !VM_Version::simd_math_is_compliant()); 13369 match(Set dst (SubVF src1 src2)); 13370 size(4*4); 13371 ins_cost(DEFAULT_COST*4); // FIXME 13372 13373 format %{ "FSUBS $dst.a,$src1.a,$src2.a\n\t" 13374 "FSUBS $dst.b,$src1.b,$src2.b\n\t" 13375 "FSUBS $dst.c,$src1.c,$src2.c\n\t" 13376 "FSUBS $dst.d,$src1.d,$src2.d" %} 13377 13378 ins_encode %{ 13379 FloatRegister dsta = $dst$$FloatRegister; 13380 FloatRegister src1a = $src1$$FloatRegister; 13381 FloatRegister src2a = $src2$$FloatRegister; 13382 __ sub_float(dsta, src1a, src2a); 13383 FloatRegister dstb = dsta->successor(); 13384 FloatRegister src1b = src1a->successor(); 13385 FloatRegister src2b = src2a->successor(); 13386 __ sub_float(dstb, src1b, src2b); 13387 FloatRegister dstc = dstb->successor(); 13388 FloatRegister src1c = src1b->successor(); 13389 FloatRegister src2c = src2b->successor(); 13390 __ sub_float(dstc, src1c, src2c); 13391 FloatRegister dstd = dstc->successor(); 13392 FloatRegister src1d = src1c->successor(); 13393 FloatRegister src2d = src2c->successor(); 13394 __ sub_float(dstd, src1d, src2d); 13395 %} 13396 13397 ins_pipe(faddF_reg_reg); // FIXME 13398%} 13399 13400instruct vsub2D_reg_vfp(vecX dst, vecX src1, vecX src2) %{ 13401 predicate(n->as_Vector()->length() == 2); 13402 match(Set dst (SubVD src1 src2)); 13403 size(4*2); 13404 ins_cost(DEFAULT_COST*2); // FIXME 13405 13406 format %{ "FSUBD $dst.a,$src1.a,$src2.a\n\t" 13407 "FSUBD $dst.b,$src1.b,$src2.b" %} 13408 13409 ins_encode %{ 13410 FloatRegister dsta = $dst$$FloatRegister; 13411 FloatRegister src1a = $src1$$FloatRegister; 13412 FloatRegister src2a = $src2$$FloatRegister; 13413 __ sub_double(dsta, src1a, src2a); 13414 FloatRegister dstb = dsta->successor()->successor(); 13415 FloatRegister src1b = src1a->successor()->successor(); 13416 FloatRegister src2b = src2a->successor()->successor(); 13417 __ sub_double(dstb, src1b, src2b); 13418 %} 13419 13420 ins_pipe(faddF_reg_reg); // FIXME 13421%} 13422#endif 13423 13424// Shorts/Chars vector mul 13425instruct vmul4S_reg(vecD dst, vecD src1, vecD src2) %{ 13426 predicate(n->as_Vector()->length() == 4); 13427 match(Set dst (MulVS src1 src2)); 13428 size(4); 13429 format %{ "VMUL.I16 $dst,$src1,$src2\t! mul packed4S" %} 13430 ins_encode %{ 13431 __ vmulI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 13432 MacroAssembler::VELEM_SIZE_16, 0); 13433 %} 13434 ins_pipe( ialu_reg_reg ); // FIXME 13435%} 13436 13437instruct vmul8S_reg(vecX dst, vecX src1, vecX src2) %{ 13438 predicate(n->as_Vector()->length() == 8); 13439 match(Set dst (MulVS src1 src2)); 13440 size(4); 13441 format %{ "VMUL.I16 $dst.Q,$src1.Q,$src2.Q\t! mul packed8S" %} 13442 ins_encode %{ 13443 __ vmulI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 13444 MacroAssembler::VELEM_SIZE_16, 1); 13445 %} 13446 ins_pipe( ialu_reg_reg ); // FIXME 13447%} 13448 13449// Integers vector mul 13450instruct vmul2I_reg(vecD dst, vecD src1, vecD src2) %{ 13451 predicate(n->as_Vector()->length() == 2); 13452 match(Set dst (MulVI src1 src2)); 13453 size(4); 13454 format %{ "VMUL.I32 $dst,$src1,$src2\t! mul packed2I" %} 13455 ins_encode %{ 13456 __ vmulI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 13457 MacroAssembler::VELEM_SIZE_32, 0); 13458 %} 13459 ins_pipe( ialu_reg_reg ); // FIXME 13460%} 13461 13462instruct vmul4I_reg(vecX dst, vecX src1, vecX src2) %{ 13463 predicate(n->as_Vector()->length() == 4); 13464 match(Set dst (MulVI src1 src2)); 13465 size(4); 13466 format %{ "VMUL.I32 $dst.Q,$src1.Q,$src2.Q\t! mul packed4I" %} 13467 ins_encode %{ 13468 __ vmulI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 13469 MacroAssembler::VELEM_SIZE_32, 1); 13470 %} 13471 ins_pipe( ialu_reg_reg ); // FIXME 13472%} 13473 13474// Floats vector mul 13475instruct vmul2F_reg(vecD dst, vecD src1, vecD src2) %{ 13476 predicate(n->as_Vector()->length() == 2 && VM_Version::simd_math_is_compliant()); 13477 match(Set dst (MulVF src1 src2)); 13478 size(4); 13479 format %{ "VMUL.F32 $dst,$src1,$src2\t! mul packed2F" %} 13480 ins_encode %{ 13481 __ vmulF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 13482 MacroAssembler::VFA_SIZE_F32, 0); 13483 %} 13484 ins_pipe( fmulF_reg_reg ); // FIXME 13485%} 13486 13487#ifndef AARCH64 13488instruct vmul2F_reg_vfp(vecD dst, vecD src1, vecD src2) %{ 13489 predicate(n->as_Vector()->length() == 2 && !VM_Version::simd_math_is_compliant()); 13490 match(Set dst (MulVF src1 src2)); 13491 size(4*2); 13492 ins_cost(DEFAULT_COST*2); // FIXME 13493 13494 format %{ "FMULS $dst.a,$src1.a,$src2.a\n\t" 13495 "FMULS $dst.b,$src1.b,$src2.b" %} 13496 ins_encode %{ 13497 __ mul_float($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister); 13498 __ mul_float($dst$$FloatRegister->successor(), 13499 $src1$$FloatRegister->successor(), 13500 $src2$$FloatRegister->successor()); 13501 %} 13502 13503 ins_pipe(fmulF_reg_reg); // FIXME 13504%} 13505#endif 13506 13507instruct vmul4F_reg(vecX dst, vecX src1, vecX src2) %{ 13508 predicate(n->as_Vector()->length() == 4 && VM_Version::simd_math_is_compliant()); 13509 match(Set dst (MulVF src1 src2)); 13510 size(4); 13511 format %{ "VMUL.F32 $dst.Q,$src1.Q,$src2.Q\t! mul packed4F" %} 13512 ins_encode %{ 13513 __ vmulF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 13514 MacroAssembler::VFA_SIZE_F32, 1); 13515 %} 13516 ins_pipe( fmulF_reg_reg ); // FIXME 13517%} 13518 13519#ifndef AARCH64 13520instruct vmul4F_reg_vfp(vecX dst, vecX src1, vecX src2) %{ 13521 predicate(n->as_Vector()->length() == 4 && !VM_Version::simd_math_is_compliant()); 13522 match(Set dst (MulVF src1 src2)); 13523 size(4*4); 13524 ins_cost(DEFAULT_COST*4); // FIXME 13525 13526 format %{ "FMULS $dst.a,$src1.a,$src2.a\n\t" 13527 "FMULS $dst.b,$src1.b,$src2.b\n\t" 13528 "FMULS $dst.c,$src1.c,$src2.c\n\t" 13529 "FMULS $dst.d,$src1.d,$src2.d" %} 13530 13531 ins_encode %{ 13532 FloatRegister dsta = $dst$$FloatRegister; 13533 FloatRegister src1a = $src1$$FloatRegister; 13534 FloatRegister src2a = $src2$$FloatRegister; 13535 __ mul_float(dsta, src1a, src2a); 13536 FloatRegister dstb = dsta->successor(); 13537 FloatRegister src1b = src1a->successor(); 13538 FloatRegister src2b = src2a->successor(); 13539 __ mul_float(dstb, src1b, src2b); 13540 FloatRegister dstc = dstb->successor(); 13541 FloatRegister src1c = src1b->successor(); 13542 FloatRegister src2c = src2b->successor(); 13543 __ mul_float(dstc, src1c, src2c); 13544 FloatRegister dstd = dstc->successor(); 13545 FloatRegister src1d = src1c->successor(); 13546 FloatRegister src2d = src2c->successor(); 13547 __ mul_float(dstd, src1d, src2d); 13548 %} 13549 13550 ins_pipe(fmulF_reg_reg); // FIXME 13551%} 13552#endif 13553 13554#ifdef AARCH64 13555instruct vmul2D_reg(vecX dst, vecX src1, vecX src2) %{ 13556 predicate(n->as_Vector()->length() == 2 && VM_Version::has_simd()); 13557 match(Set dst (MulVD src1 src2)); 13558 size(4*1); 13559 ins_cost(DEFAULT_COST*1); // FIXME 13560 13561 format %{ "FMUL.2D $dst,$src1,$src2\t! double[2]" %} 13562 ins_encode %{ 13563 int quad = 1; 13564 __ vmulF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 13565 MacroAssembler::VFA_SIZE_F64, quad); 13566 %} 13567 13568 ins_pipe(fdivF_reg_reg); // FIXME 13569%} 13570#else 13571instruct vmul2D_reg_vfp(vecX dst, vecX src1, vecX src2) %{ 13572 predicate(n->as_Vector()->length() == 2); 13573 match(Set dst (MulVD src1 src2)); 13574 size(4*2); 13575 ins_cost(DEFAULT_COST*2); // FIXME 13576 13577 format %{ "FMULD $dst.D.a,$src1.D.a,$src2.D.a\n\t" 13578 "FMULD $dst.D.b,$src1.D.b,$src2.D.b" %} 13579 ins_encode %{ 13580 FloatRegister dsta = $dst$$FloatRegister; 13581 FloatRegister src1a = $src1$$FloatRegister; 13582 FloatRegister src2a = $src2$$FloatRegister; 13583 __ mul_double(dsta, src1a, src2a); 13584 FloatRegister dstb = dsta->successor()->successor(); 13585 FloatRegister src1b = src1a->successor()->successor(); 13586 FloatRegister src2b = src2a->successor()->successor(); 13587 __ mul_double(dstb, src1b, src2b); 13588 %} 13589 13590 ins_pipe(fmulD_reg_reg); // FIXME 13591%} 13592#endif 13593 13594 13595// Floats vector div 13596instruct vdiv2F_reg_vfp(vecD dst, vecD src1, vecD src2) %{ 13597 predicate(n->as_Vector()->length() == 2); 13598 match(Set dst (DivVF src1 src2)); 13599#ifdef AARCH64 13600 size(4*1); 13601 ins_cost(DEFAULT_COST*1); // FIXME 13602 13603 format %{ "FDIV.2S $dst,$src1,$src2\t! float[2]" %} 13604 ins_encode %{ 13605 int quad = 0; 13606 __ vdivF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 13607 MacroAssembler::VFA_SIZE_F32, quad); 13608 %} 13609 13610 ins_pipe(fdivF_reg_reg); // FIXME 13611#else 13612 size(4*2); 13613 ins_cost(DEFAULT_COST*2); // FIXME 13614 13615 format %{ "FDIVS $dst.a,$src1.a,$src2.a\n\t" 13616 "FDIVS $dst.b,$src1.b,$src2.b" %} 13617 ins_encode %{ 13618 __ div_float($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister); 13619 __ div_float($dst$$FloatRegister->successor(), 13620 $src1$$FloatRegister->successor(), 13621 $src2$$FloatRegister->successor()); 13622 %} 13623 13624 ins_pipe(fdivF_reg_reg); // FIXME 13625#endif 13626%} 13627 13628instruct vdiv4F_reg_vfp(vecX dst, vecX src1, vecX src2) %{ 13629 predicate(n->as_Vector()->length() == 4); 13630 match(Set dst (DivVF src1 src2)); 13631#ifdef AARCH64 13632 size(4*1); 13633 ins_cost(DEFAULT_COST*1); // FIXME 13634 13635 format %{ "FDIV.4S $dst,$src1,$src2\t! float[4]" %} 13636 ins_encode %{ 13637 int quad = 1; 13638 __ vdivF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 13639 MacroAssembler::VFA_SIZE_F32, quad); 13640 %} 13641 13642 ins_pipe(fdivF_reg_reg); // FIXME 13643#else 13644 size(4*4); 13645 ins_cost(DEFAULT_COST*4); // FIXME 13646 13647 format %{ "FDIVS $dst.a,$src1.a,$src2.a\n\t" 13648 "FDIVS $dst.b,$src1.b,$src2.b\n\t" 13649 "FDIVS $dst.c,$src1.c,$src2.c\n\t" 13650 "FDIVS $dst.d,$src1.d,$src2.d" %} 13651 13652 ins_encode %{ 13653 FloatRegister dsta = $dst$$FloatRegister; 13654 FloatRegister src1a = $src1$$FloatRegister; 13655 FloatRegister src2a = $src2$$FloatRegister; 13656 __ div_float(dsta, src1a, src2a); 13657 FloatRegister dstb = dsta->successor(); 13658 FloatRegister src1b = src1a->successor(); 13659 FloatRegister src2b = src2a->successor(); 13660 __ div_float(dstb, src1b, src2b); 13661 FloatRegister dstc = dstb->successor(); 13662 FloatRegister src1c = src1b->successor(); 13663 FloatRegister src2c = src2b->successor(); 13664 __ div_float(dstc, src1c, src2c); 13665 FloatRegister dstd = dstc->successor(); 13666 FloatRegister src1d = src1c->successor(); 13667 FloatRegister src2d = src2c->successor(); 13668 __ div_float(dstd, src1d, src2d); 13669 %} 13670 13671 ins_pipe(fdivF_reg_reg); // FIXME 13672#endif 13673%} 13674 13675#ifdef AARCH64 13676instruct vdiv2D_reg(vecX dst, vecX src1, vecX src2) %{ 13677 predicate(n->as_Vector()->length() == 2 && VM_Version::has_simd()); 13678 match(Set dst (DivVD src1 src2)); 13679 size(4*1); 13680 ins_cost(DEFAULT_COST*1); // FIXME 13681 13682 format %{ "FDIV.2D $dst,$src1,$src2\t! double[2]" %} 13683 ins_encode %{ 13684 int quad = 1; 13685 __ vdivF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 13686 MacroAssembler::VFA_SIZE_F64, quad); 13687 %} 13688 13689 ins_pipe(fdivF_reg_reg); // FIXME 13690%} 13691#else 13692instruct vdiv2D_reg_vfp(vecX dst, vecX src1, vecX src2) %{ 13693 predicate(n->as_Vector()->length() == 2); 13694 match(Set dst (DivVD src1 src2)); 13695 size(4*2); 13696 ins_cost(DEFAULT_COST*2); // FIXME 13697 13698 format %{ "FDIVD $dst.D.a,$src1.D.a,$src2.D.a\n\t" 13699 "FDIVD $dst.D.b,$src1.D.b,$src2.D.b" %} 13700 ins_encode %{ 13701 FloatRegister dsta = $dst$$FloatRegister; 13702 FloatRegister src1a = $src1$$FloatRegister; 13703 FloatRegister src2a = $src2$$FloatRegister; 13704 __ div_double(dsta, src1a, src2a); 13705 FloatRegister dstb = dsta->successor()->successor(); 13706 FloatRegister src1b = src1a->successor()->successor(); 13707 FloatRegister src2b = src2a->successor()->successor(); 13708 __ div_double(dstb, src1b, src2b); 13709 %} 13710 13711 ins_pipe(fdivD_reg_reg); // FIXME 13712%} 13713#endif 13714 13715// --------------------------------- NEG -------------------------------------- 13716 13717instruct vneg8B_reg(vecD dst, vecD src) %{ 13718 predicate(n->as_Vector()->length_in_bytes() == 8); 13719 effect(DEF dst, USE src); 13720 size(4); 13721 ins_cost(DEFAULT_COST); // FIXME 13722 format %{ "VNEG.S8 $dst.D,$src.D\t! neg packed8B" %} 13723 ins_encode %{ 13724 bool quad = false; 13725 __ vnegI($dst$$FloatRegister, $src$$FloatRegister, 13726 MacroAssembler::VELEM_SIZE_8, quad); 13727 %} 13728 ins_pipe( ialu_reg_reg ); // FIXME 13729%} 13730 13731instruct vneg16B_reg(vecX dst, vecX src) %{ 13732 predicate(n->as_Vector()->length_in_bytes() == 16); 13733 effect(DEF dst, USE src); 13734 size(4); 13735 ins_cost(DEFAULT_COST); // FIXME 13736 format %{ "VNEG.S8 $dst.Q,$src.Q\t! neg0 packed16B" %} 13737 ins_encode %{ 13738 bool _float = false; 13739 bool quad = true; 13740 __ vnegI($dst$$FloatRegister, $src$$FloatRegister, 13741 MacroAssembler::VELEM_SIZE_8, quad); 13742 %} 13743 ins_pipe( ialu_reg_reg ); // FIXME 13744%} 13745 13746// ------------------------------ Shift --------------------------------------- 13747 13748instruct vslcntD(vecD dst, iRegI cnt) %{ 13749 predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd()); 13750 match(Set dst (LShiftCntV cnt)); 13751 size(4); 13752 ins_cost(DEFAULT_COST); // FIXME 13753 expand %{ 13754 Repl8B_reg_simd(dst, cnt); 13755 %} 13756%} 13757 13758instruct vslcntX(vecX dst, iRegI cnt) %{ 13759 predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd()); 13760 match(Set dst (LShiftCntV cnt)); 13761 size(4); 13762 ins_cost(DEFAULT_COST); // FIXME 13763 expand %{ 13764 Repl16B_reg(dst, cnt); 13765 %} 13766%} 13767 13768// Low bits of vector "shift" elements are used, so it 13769// doesn't matter if we treat it as ints or bytes here. 13770instruct vsrcntD(vecD dst, iRegI cnt) %{ 13771 predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd()); 13772 match(Set dst (RShiftCntV cnt)); 13773 size(4*2); 13774 ins_cost(DEFAULT_COST*2); // FIXME 13775 13776 format %{ "VDUP.8 $dst.D,$cnt\n\t" 13777 "VNEG.S8 $dst.D,$dst.D\t! neg packed8B" %} 13778 ins_encode %{ 13779 bool quad = false; 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 13788instruct vsrcntX(vecX dst, iRegI cnt) %{ 13789 predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd()); 13790 match(Set dst (RShiftCntV cnt)); 13791 size(4*2); 13792 ins_cost(DEFAULT_COST*2); // FIXME 13793 format %{ "VDUP.8 $dst.Q,$cnt\n\t" 13794 "VNEG.S8 $dst.Q,$dst.Q\t! neg packed16B" %} 13795 ins_encode %{ 13796 bool quad = true; 13797 __ vdupI($dst$$FloatRegister, $cnt$$Register, 13798 MacroAssembler::VELEM_SIZE_8, quad); 13799 __ vnegI($dst$$FloatRegister, $dst$$FloatRegister, 13800 MacroAssembler::VELEM_SIZE_8, quad); 13801 %} 13802 ins_pipe( ialu_reg_reg ); // FIXME 13803%} 13804 13805// Byte vector logical left/right shift based on sign 13806instruct vsh8B_reg(vecD dst, vecD src, vecD shift) %{ 13807 predicate(n->as_Vector()->length() == 8); 13808 effect(DEF dst, USE src, USE shift); 13809 size(4); 13810 ins_cost(DEFAULT_COST); // FIXME 13811 format %{ 13812 "VSHL.U8 $dst.D,$src.D,$shift.D\t! logical left/right shift packed8B" 13813 %} 13814 ins_encode %{ 13815 bool quad = false; 13816 __ vshlUI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister, 13817 MacroAssembler::VELEM_SIZE_8, quad); 13818 %} 13819 ins_pipe( ialu_reg_reg ); // FIXME 13820%} 13821 13822instruct vsh16B_reg(vecX dst, vecX src, vecX shift) %{ 13823 predicate(n->as_Vector()->length() == 16); 13824 effect(DEF dst, USE src, USE shift); 13825 size(4); 13826 ins_cost(DEFAULT_COST); // FIXME 13827 format %{ 13828 "VSHL.U8 $dst.Q,$src.Q,$shift.Q\t! logical left/right shift packed16B" 13829 %} 13830 ins_encode %{ 13831 bool quad = true; 13832 __ vshlUI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister, 13833 MacroAssembler::VELEM_SIZE_8, quad); 13834 %} 13835 ins_pipe( ialu_reg_reg ); // FIXME 13836%} 13837 13838// Shorts/Char vector logical left/right shift based on sign 13839instruct vsh4S_reg(vecD dst, vecD src, vecD shift) %{ 13840 predicate(n->as_Vector()->length() == 4); 13841 effect(DEF dst, USE src, USE shift); 13842 size(4); 13843 ins_cost(DEFAULT_COST); // FIXME 13844 format %{ 13845 "VSHL.U16 $dst.D,$src.D,$shift.D\t! logical left/right shift packed4S" 13846 %} 13847 ins_encode %{ 13848 bool quad = false; 13849 __ vshlUI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister, 13850 MacroAssembler::VELEM_SIZE_16, quad); 13851 %} 13852 ins_pipe( ialu_reg_reg ); // FIXME 13853%} 13854 13855instruct vsh8S_reg(vecX dst, vecX src, vecX shift) %{ 13856 predicate(n->as_Vector()->length() == 8); 13857 effect(DEF dst, USE src, USE shift); 13858 size(4); 13859 ins_cost(DEFAULT_COST); // FIXME 13860 format %{ 13861 "VSHL.U16 $dst.Q,$src.Q,$shift.Q\t! logical left/right shift packed8S" 13862 %} 13863 ins_encode %{ 13864 bool quad = true; 13865 __ vshlUI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister, 13866 MacroAssembler::VELEM_SIZE_16, quad); 13867 %} 13868 ins_pipe( ialu_reg_reg ); // FIXME 13869%} 13870 13871// Integers vector logical left/right shift based on sign 13872instruct vsh2I_reg(vecD dst, vecD src, vecD shift) %{ 13873 predicate(n->as_Vector()->length() == 2); 13874 effect(DEF dst, USE src, USE shift); 13875 size(4); 13876 ins_cost(DEFAULT_COST); // FIXME 13877 format %{ 13878 "VSHL.U32 $dst.D,$src.D,$shift.D\t! logical left/right shift packed2I" 13879 %} 13880 ins_encode %{ 13881 bool quad = false; 13882 __ vshlUI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister, 13883 MacroAssembler::VELEM_SIZE_32, quad); 13884 %} 13885 ins_pipe( ialu_reg_reg ); // FIXME 13886%} 13887 13888instruct vsh4I_reg(vecX dst, vecX src, vecX shift) %{ 13889 predicate(n->as_Vector()->length() == 4); 13890 effect(DEF dst, USE src, USE shift); 13891 size(4); 13892 ins_cost(DEFAULT_COST); // FIXME 13893 format %{ 13894 "VSHL.U32 $dst.Q,$src.Q,$shift.Q\t! logical left/right shift packed4I" 13895 %} 13896 ins_encode %{ 13897 bool quad = true; 13898 __ vshlUI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister, 13899 MacroAssembler::VELEM_SIZE_32, quad); 13900 %} 13901 ins_pipe( ialu_reg_reg ); // FIXME 13902%} 13903 13904// Longs vector logical left/right shift based on sign 13905instruct vsh2L_reg(vecX dst, vecX src, vecX shift) %{ 13906 predicate(n->as_Vector()->length() == 2); 13907 effect(DEF dst, USE src, USE shift); 13908 size(4); 13909 ins_cost(DEFAULT_COST); // FIXME 13910 format %{ 13911 "VSHL.U64 $dst.Q,$src.Q,$shift.Q\t! logical left/right shift packed2L" 13912 %} 13913 ins_encode %{ 13914 bool quad = true; 13915 __ vshlUI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister, 13916 MacroAssembler::VELEM_SIZE_64, quad); 13917 %} 13918 ins_pipe( ialu_reg_reg ); // FIXME 13919%} 13920 13921// ------------------------------ LeftShift ----------------------------------- 13922 13923// Byte vector left shift 13924instruct vsl8B_reg(vecD dst, vecD src, vecD shift) %{ 13925 predicate(n->as_Vector()->length() == 8); 13926 match(Set dst (LShiftVB src shift)); 13927 size(4*1); 13928 ins_cost(DEFAULT_COST*1); // FIXME 13929 expand %{ 13930 vsh8B_reg(dst, src, shift); 13931 %} 13932%} 13933 13934instruct vsl16B_reg(vecX dst, vecX src, vecX shift) %{ 13935 predicate(n->as_Vector()->length() == 16); 13936 match(Set dst (LShiftVB src shift)); 13937 size(4*1); 13938 ins_cost(DEFAULT_COST*1); // FIXME 13939 expand %{ 13940 vsh16B_reg(dst, src, shift); 13941 %} 13942%} 13943 13944instruct vsl8B_immI(vecD dst, vecD src, immI shift) %{ 13945 predicate(n->as_Vector()->length() == 8); 13946 match(Set dst (LShiftVB src shift)); 13947 size(4); 13948 ins_cost(DEFAULT_COST); // FIXME 13949 format %{ 13950 "VSHL.I8 $dst.D,$src.D,$shift\t! logical left shift packed8B" 13951 %} 13952 ins_encode %{ 13953 bool quad = false; 13954 __ vshli($dst$$FloatRegister, $src$$FloatRegister, 8, $shift$$constant, 13955 quad); 13956 %} 13957 ins_pipe( ialu_reg_reg ); // FIXME 13958%} 13959 13960instruct vsl16B_immI(vecX dst, vecX src, immI shift) %{ 13961 predicate(n->as_Vector()->length() == 16); 13962 match(Set dst (LShiftVB src shift)); 13963 size(4); 13964 ins_cost(DEFAULT_COST); // FIXME 13965 format %{ 13966 "VSHL.I8 $dst.Q,$src.Q,$shift\t! logical left shift packed16B" 13967 %} 13968 ins_encode %{ 13969 bool quad = true; 13970 __ vshli($dst$$FloatRegister, $src$$FloatRegister, 8, $shift$$constant, 13971 quad); 13972 %} 13973 ins_pipe( ialu_reg_reg ); // FIXME 13974%} 13975 13976// Shorts/Chars vector logical left/right shift 13977instruct vsl4S_reg(vecD dst, vecD src, vecD shift) %{ 13978 predicate(n->as_Vector()->length() == 4); 13979 match(Set dst (LShiftVS src shift)); 13980 match(Set dst (URShiftVS src shift)); 13981 size(4*1); 13982 ins_cost(DEFAULT_COST*1); // FIXME 13983 expand %{ 13984 vsh4S_reg(dst, src, shift); 13985 %} 13986%} 13987 13988instruct vsl8S_reg(vecX dst, vecX src, vecX shift) %{ 13989 predicate(n->as_Vector()->length() == 8); 13990 match(Set dst (LShiftVS src shift)); 13991 match(Set dst (URShiftVS src shift)); 13992 size(4*1); 13993 ins_cost(DEFAULT_COST*1); // FIXME 13994 expand %{ 13995 vsh8S_reg(dst, src, shift); 13996 %} 13997%} 13998 13999instruct vsl4S_immI(vecD dst, vecD src, immI shift) %{ 14000 predicate(n->as_Vector()->length() == 4); 14001 match(Set dst (LShiftVS src shift)); 14002 size(4); 14003 ins_cost(DEFAULT_COST); // FIXME 14004 format %{ 14005 "VSHL.I16 $dst.D,$src.D,$shift\t! logical left shift packed4S" 14006 %} 14007 ins_encode %{ 14008 bool quad = false; 14009 __ vshli($dst$$FloatRegister, $src$$FloatRegister, 16, $shift$$constant, 14010 quad); 14011 %} 14012 ins_pipe( ialu_reg_reg ); // FIXME 14013%} 14014 14015instruct vsl8S_immI(vecX dst, vecX src, immI shift) %{ 14016 predicate(n->as_Vector()->length() == 8); 14017 match(Set dst (LShiftVS src shift)); 14018 size(4); 14019 ins_cost(DEFAULT_COST); // FIXME 14020 format %{ 14021 "VSHL.I16 $dst.Q,$src.Q,$shift\t! logical left shift packed8S" 14022 %} 14023 ins_encode %{ 14024 bool quad = true; 14025 __ vshli($dst$$FloatRegister, $src$$FloatRegister, 16, $shift$$constant, 14026 quad); 14027 %} 14028 ins_pipe( ialu_reg_reg ); // FIXME 14029%} 14030 14031// Integers vector logical left/right shift 14032instruct vsl2I_reg(vecD dst, vecD src, vecD shift) %{ 14033 predicate(n->as_Vector()->length() == 2 && VM_Version::has_simd()); 14034 match(Set dst (LShiftVI src shift)); 14035 match(Set dst (URShiftVI src shift)); 14036 size(4*1); 14037 ins_cost(DEFAULT_COST*1); // FIXME 14038 expand %{ 14039 vsh2I_reg(dst, src, shift); 14040 %} 14041%} 14042 14043instruct vsl4I_reg(vecX dst, vecX src, vecX shift) %{ 14044 predicate(n->as_Vector()->length() == 4 && VM_Version::has_simd()); 14045 match(Set dst (LShiftVI src shift)); 14046 match(Set dst (URShiftVI src shift)); 14047 size(4*1); 14048 ins_cost(DEFAULT_COST*1); // FIXME 14049 expand %{ 14050 vsh4I_reg(dst, src, shift); 14051 %} 14052%} 14053 14054instruct vsl2I_immI(vecD dst, vecD src, immI shift) %{ 14055 predicate(n->as_Vector()->length() == 2 && VM_Version::has_simd()); 14056 match(Set dst (LShiftVI src shift)); 14057 size(4); 14058 ins_cost(DEFAULT_COST); // FIXME 14059 format %{ 14060 "VSHL.I32 $dst.D,$src.D,$shift\t! logical left shift packed2I" 14061 %} 14062 ins_encode %{ 14063 bool quad = false; 14064 __ vshli($dst$$FloatRegister, $src$$FloatRegister, 32, $shift$$constant, 14065 quad); 14066 %} 14067 ins_pipe( ialu_reg_reg ); // FIXME 14068%} 14069 14070instruct vsl4I_immI(vecX dst, vecX src, immI shift) %{ 14071 predicate(n->as_Vector()->length() == 4 && VM_Version::has_simd()); 14072 match(Set dst (LShiftVI src shift)); 14073 size(4); 14074 ins_cost(DEFAULT_COST); // FIXME 14075 format %{ 14076 "VSHL.I32 $dst.Q,$src.Q,$shift\t! logical left shift packed4I" 14077 %} 14078 ins_encode %{ 14079 bool quad = true; 14080 __ vshli($dst$$FloatRegister, $src$$FloatRegister, 32, $shift$$constant, 14081 quad); 14082 %} 14083 ins_pipe( ialu_reg_reg ); // FIXME 14084%} 14085 14086// Longs vector logical left/right shift 14087instruct vsl2L_reg(vecX dst, vecX src, vecX shift) %{ 14088 predicate(n->as_Vector()->length() == 2); 14089 match(Set dst (LShiftVL src shift)); 14090 match(Set dst (URShiftVL src shift)); 14091 size(4*1); 14092 ins_cost(DEFAULT_COST*1); // FIXME 14093 expand %{ 14094 vsh2L_reg(dst, src, shift); 14095 %} 14096%} 14097 14098instruct vsl2L_immI(vecX dst, vecX src, immI shift) %{ 14099 predicate(n->as_Vector()->length() == 2); 14100 match(Set dst (LShiftVL src shift)); 14101 size(4); 14102 ins_cost(DEFAULT_COST); // FIXME 14103 format %{ 14104 "VSHL.I64 $dst.Q,$src.Q,$shift\t! logical left shift packed2L" 14105 %} 14106 ins_encode %{ 14107 bool quad = true; 14108 __ vshli($dst$$FloatRegister, $src$$FloatRegister, 64, $shift$$constant, 14109 quad); 14110 %} 14111 ins_pipe( ialu_reg_reg ); // FIXME 14112%} 14113 14114// ----------------------- LogicalRightShift ----------------------------------- 14115 14116// Bytes/Shorts vector logical right shift produces incorrect Java result 14117// for negative data because java code convert short value into int with 14118// sign extension before a shift. 14119 14120// Chars vector logical right shift 14121instruct vsrl4S_immI(vecD dst, vecD src, immI shift) %{ 14122 predicate(n->as_Vector()->length() == 4); 14123 match(Set dst (URShiftVS src shift)); 14124 size(4); 14125 ins_cost(DEFAULT_COST); // FIXME 14126 format %{ 14127 "VSHR.U16 $dst.D,$src.D,$shift\t! logical right shift packed4S" 14128 %} 14129 ins_encode %{ 14130 bool quad = false; 14131 __ vshrUI($dst$$FloatRegister, $src$$FloatRegister, 16, $shift$$constant, 14132 quad); 14133 %} 14134 ins_pipe( ialu_reg_reg ); // FIXME 14135%} 14136 14137instruct vsrl8S_immI(vecX dst, vecX src, immI shift) %{ 14138 predicate(n->as_Vector()->length() == 8); 14139 match(Set dst (URShiftVS src shift)); 14140 size(4); 14141 ins_cost(DEFAULT_COST); // FIXME 14142 format %{ 14143 "VSHR.U16 $dst.Q,$src.Q,$shift\t! logical right shift packed8S" 14144 %} 14145 ins_encode %{ 14146 bool quad = true; 14147 __ vshrUI($dst$$FloatRegister, $src$$FloatRegister, 16, $shift$$constant, 14148 quad); 14149 %} 14150 ins_pipe( ialu_reg_reg ); // FIXME 14151%} 14152 14153// Integers vector logical right shift 14154instruct vsrl2I_immI(vecD dst, vecD src, immI shift) %{ 14155 predicate(n->as_Vector()->length() == 2 && VM_Version::has_simd()); 14156 match(Set dst (URShiftVI src shift)); 14157 size(4); 14158 ins_cost(DEFAULT_COST); // FIXME 14159 format %{ 14160 "VSHR.U32 $dst.D,$src.D,$shift\t! logical right shift packed2I" 14161 %} 14162 ins_encode %{ 14163 bool quad = false; 14164 __ vshrUI($dst$$FloatRegister, $src$$FloatRegister, 32, $shift$$constant, 14165 quad); 14166 %} 14167 ins_pipe( ialu_reg_reg ); // FIXME 14168%} 14169 14170instruct vsrl4I_immI(vecX dst, vecX src, immI shift) %{ 14171 predicate(n->as_Vector()->length() == 4 && VM_Version::has_simd()); 14172 match(Set dst (URShiftVI src shift)); 14173 size(4); 14174 ins_cost(DEFAULT_COST); // FIXME 14175 format %{ 14176 "VSHR.U32 $dst.Q,$src.Q,$shift\t! logical right shift packed4I" 14177 %} 14178 ins_encode %{ 14179 bool quad = true; 14180 __ vshrUI($dst$$FloatRegister, $src$$FloatRegister, 32, $shift$$constant, 14181 quad); 14182 %} 14183 ins_pipe( ialu_reg_reg ); // FIXME 14184%} 14185 14186// Longs vector logical right shift 14187instruct vsrl2L_immI(vecX dst, vecX src, immI shift) %{ 14188 predicate(n->as_Vector()->length() == 2); 14189 match(Set dst (URShiftVL src shift)); 14190 size(4); 14191 ins_cost(DEFAULT_COST); // FIXME 14192 format %{ 14193 "VSHR.U64 $dst.Q,$src.Q,$shift\t! logical right shift packed2L" 14194 %} 14195 ins_encode %{ 14196 bool quad = true; 14197 __ vshrUI($dst$$FloatRegister, $src$$FloatRegister, 64, $shift$$constant, 14198 quad); 14199 %} 14200 ins_pipe( ialu_reg_reg ); // FIXME 14201%} 14202 14203// ------------------- ArithmeticRightShift ----------------------------------- 14204 14205// Bytes vector arithmetic left/right shift based on sign 14206instruct vsha8B_reg(vecD dst, vecD src, vecD shift) %{ 14207 predicate(n->as_Vector()->length() == 8); 14208 effect(DEF dst, USE src, USE shift); 14209 size(4); 14210 ins_cost(DEFAULT_COST); // FIXME 14211 format %{ 14212 "VSHL.S8 $dst.D,$src.D,$shift.D\t! arithmetic right shift packed8B" 14213 %} 14214 ins_encode %{ 14215 bool quad = false; 14216 __ vshlSI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister, 14217 MacroAssembler::VELEM_SIZE_8, quad); 14218 %} 14219 ins_pipe( ialu_reg_reg ); // FIXME 14220%} 14221 14222instruct vsha16B_reg(vecX dst, vecX src, vecX shift) %{ 14223 predicate(n->as_Vector()->length() == 16); 14224 effect(DEF dst, USE src, USE shift); 14225 size(4); 14226 ins_cost(DEFAULT_COST); // FIXME 14227 format %{ 14228 "VSHL.S8 $dst.Q,$src.Q,$shift.Q\t! arithmetic right shift packed16B" 14229 %} 14230 ins_encode %{ 14231 bool quad = true; 14232 __ vshlSI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister, 14233 MacroAssembler::VELEM_SIZE_8, quad); 14234 %} 14235 ins_pipe( ialu_reg_reg ); // FIXME 14236%} 14237 14238// Shorts vector arithmetic left/right shift based on sign 14239instruct vsha4S_reg(vecD dst, vecD src, vecD shift) %{ 14240 predicate(n->as_Vector()->length() == 4); 14241 effect(DEF dst, USE src, USE shift); 14242 size(4); 14243 ins_cost(DEFAULT_COST); // FIXME 14244 format %{ 14245 "VSHL.S16 $dst.D,$src.D,$shift.D\t! arithmetic right shift packed4S" 14246 %} 14247 ins_encode %{ 14248 bool quad = false; 14249 __ vshlSI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister, 14250 MacroAssembler::VELEM_SIZE_16, quad); 14251 %} 14252 ins_pipe( ialu_reg_reg ); // FIXME 14253%} 14254 14255instruct vsha8S_reg(vecX dst, vecX src, vecX shift) %{ 14256 predicate(n->as_Vector()->length() == 8); 14257 effect(DEF dst, USE src, USE shift); 14258 size(4); 14259 ins_cost(DEFAULT_COST); // FIXME 14260 format %{ 14261 "VSHL.S16 $dst.Q,$src.Q,$shift.Q\t! arithmetic right shift packed8S" 14262 %} 14263 ins_encode %{ 14264 bool quad = true; 14265 __ vshlSI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister, 14266 MacroAssembler::VELEM_SIZE_16, quad); 14267 %} 14268 ins_pipe( ialu_reg_reg ); // FIXME 14269%} 14270 14271// Integers vector arithmetic left/right shift based on sign 14272instruct vsha2I_reg(vecD dst, vecD src, vecD shift) %{ 14273 predicate(n->as_Vector()->length() == 2); 14274 effect(DEF dst, USE src, USE shift); 14275 size(4); 14276 ins_cost(DEFAULT_COST); // FIXME 14277 format %{ 14278 "VSHL.S32 $dst.D,$src.D,$shift.D\t! arithmetic right shift packed2I" 14279 %} 14280 ins_encode %{ 14281 bool quad = false; 14282 __ vshlSI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister, 14283 MacroAssembler::VELEM_SIZE_32, quad); 14284 %} 14285 ins_pipe( ialu_reg_reg ); // FIXME 14286%} 14287 14288instruct vsha4I_reg(vecX dst, vecX src, vecX shift) %{ 14289 predicate(n->as_Vector()->length() == 4); 14290 effect(DEF dst, USE src, USE shift); 14291 size(4); 14292 ins_cost(DEFAULT_COST); // FIXME 14293 format %{ 14294 "VSHL.S32 $dst.Q,$src.Q,$shift.Q\t! arithmetic right shift packed4I" 14295 %} 14296 ins_encode %{ 14297 bool quad = true; 14298 __ vshlSI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister, 14299 MacroAssembler::VELEM_SIZE_32, quad); 14300 %} 14301 ins_pipe( ialu_reg_reg ); // FIXME 14302%} 14303 14304// Longs vector arithmetic left/right shift based on sign 14305instruct vsha2L_reg(vecX dst, vecX src, vecX shift) %{ 14306 predicate(n->as_Vector()->length() == 2); 14307 effect(DEF dst, USE src, USE shift); 14308 size(4); 14309 ins_cost(DEFAULT_COST); // FIXME 14310 format %{ 14311 "VSHL.S64 $dst.Q,$src.Q,$shift.Q\t! arithmetic right shift packed2L" 14312 %} 14313 ins_encode %{ 14314 bool quad = true; 14315 __ vshlSI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister, 14316 MacroAssembler::VELEM_SIZE_64, quad); 14317 %} 14318 ins_pipe( ialu_reg_reg ); // FIXME 14319%} 14320 14321// Byte vector arithmetic right shift 14322 14323instruct vsra8B_reg(vecD dst, vecD src, vecD shift) %{ 14324 predicate(n->as_Vector()->length() == 8); 14325 match(Set dst (RShiftVB src shift)); 14326 size(4); 14327 ins_cost(DEFAULT_COST); // FIXME 14328 expand %{ 14329 vsha8B_reg(dst, src, shift); 14330 %} 14331%} 14332 14333instruct vsrl16B_reg(vecX dst, vecX src, vecX shift) %{ 14334 predicate(n->as_Vector()->length() == 16); 14335 match(Set dst (RShiftVB src shift)); 14336 size(4); 14337 ins_cost(DEFAULT_COST); // FIXME 14338 expand %{ 14339 vsha16B_reg(dst, src, shift); 14340 %} 14341%} 14342 14343instruct vsrl8B_immI(vecD dst, vecD src, immI shift) %{ 14344 predicate(n->as_Vector()->length() == 8); 14345 match(Set dst (RShiftVB src shift)); 14346 size(4); 14347 ins_cost(DEFAULT_COST); // FIXME 14348 format %{ 14349 "VSHR.S8 $dst.D,$src.D,$shift\t! logical right shift packed8B" 14350 %} 14351 ins_encode %{ 14352 bool quad = false; 14353 __ vshrSI($dst$$FloatRegister, $src$$FloatRegister, 8, $shift$$constant, 14354 quad); 14355 %} 14356 ins_pipe( ialu_reg_reg ); // FIXME 14357%} 14358 14359instruct vsrl16B_immI(vecX dst, vecX src, immI shift) %{ 14360 predicate(n->as_Vector()->length() == 16); 14361 match(Set dst (RShiftVB src shift)); 14362 size(4); 14363 ins_cost(DEFAULT_COST); // FIXME 14364 format %{ 14365 "VSHR.S8 $dst.Q,$src.Q,$shift\t! logical right shift packed16B" 14366 %} 14367 ins_encode %{ 14368 bool quad = true; 14369 __ vshrSI($dst$$FloatRegister, $src$$FloatRegister, 8, $shift$$constant, 14370 quad); 14371 %} 14372 ins_pipe( ialu_reg_reg ); // FIXME 14373%} 14374 14375// Shorts vector arithmetic right shift 14376instruct vsra4S_reg(vecD dst, vecD src, vecD shift) %{ 14377 predicate(n->as_Vector()->length() == 4); 14378 match(Set dst (RShiftVS src shift)); 14379 size(4); 14380 ins_cost(DEFAULT_COST); // FIXME 14381 expand %{ 14382 vsha4S_reg(dst, src, shift); 14383 %} 14384%} 14385 14386instruct vsra8S_reg(vecX dst, vecX src, vecX shift) %{ 14387 predicate(n->as_Vector()->length() == 8); 14388 match(Set dst (RShiftVS src shift)); 14389 size(4); 14390 ins_cost(DEFAULT_COST); // FIXME 14391 expand %{ 14392 vsha8S_reg(dst, src, shift); 14393 %} 14394%} 14395 14396instruct vsra4S_immI(vecD dst, vecD src, immI shift) %{ 14397 predicate(n->as_Vector()->length() == 4); 14398 match(Set dst (RShiftVS src shift)); 14399 size(4); 14400 ins_cost(DEFAULT_COST); // FIXME 14401 format %{ 14402 "VSHR.S16 $dst.D,$src.D,$shift\t! logical right shift packed4S" 14403 %} 14404 ins_encode %{ 14405 bool quad = false; 14406 __ vshrSI($dst$$FloatRegister, $src$$FloatRegister, 16, $shift$$constant, 14407 quad); 14408 %} 14409 ins_pipe( ialu_reg_reg ); // FIXME 14410%} 14411 14412instruct vsra8S_immI(vecX dst, vecX src, immI shift) %{ 14413 predicate(n->as_Vector()->length() == 8); 14414 match(Set dst (RShiftVS src shift)); 14415 size(4); 14416 ins_cost(DEFAULT_COST); // FIXME 14417 format %{ 14418 "VSHR.S16 $dst.Q,$src.Q,$shift\t! logical right shift packed8S" 14419 %} 14420 ins_encode %{ 14421 bool quad = true; 14422 __ vshrSI($dst$$FloatRegister, $src$$FloatRegister, 16, $shift$$constant, 14423 quad); 14424 %} 14425 ins_pipe( ialu_reg_reg ); // FIXME 14426%} 14427 14428// Integers vector arithmetic right shift 14429instruct vsra2I_reg(vecD dst, vecD src, vecD shift) %{ 14430 predicate(n->as_Vector()->length() == 2); 14431 match(Set dst (RShiftVI src shift)); 14432 size(4); 14433 ins_cost(DEFAULT_COST); // FIXME 14434 expand %{ 14435 vsha2I_reg(dst, src, shift); 14436 %} 14437%} 14438 14439instruct vsra4I_reg(vecX dst, vecX src, vecX shift) %{ 14440 predicate(n->as_Vector()->length() == 4); 14441 match(Set dst (RShiftVI src shift)); 14442 size(4); 14443 ins_cost(DEFAULT_COST); // FIXME 14444 expand %{ 14445 vsha4I_reg(dst, src, shift); 14446 %} 14447%} 14448 14449instruct vsra2I_immI(vecD dst, vecD src, immI shift) %{ 14450 predicate(n->as_Vector()->length() == 2); 14451 match(Set dst (RShiftVI src shift)); 14452 size(4); 14453 ins_cost(DEFAULT_COST); // FIXME 14454 format %{ 14455 "VSHR.S32 $dst.D,$src.D,$shift\t! logical right shift packed2I" 14456 %} 14457 ins_encode %{ 14458 bool quad = false; 14459 __ vshrSI($dst$$FloatRegister, $src$$FloatRegister, 32, $shift$$constant, 14460 quad); 14461 %} 14462 ins_pipe( ialu_reg_reg ); // FIXME 14463%} 14464 14465instruct vsra4I_immI(vecX dst, vecX src, immI shift) %{ 14466 predicate(n->as_Vector()->length() == 4); 14467 match(Set dst (RShiftVI src shift)); 14468 size(4); 14469 ins_cost(DEFAULT_COST); // FIXME 14470 format %{ 14471 "VSHR.S32 $dst.Q,$src.Q,$shift\t! logical right shift packed4I" 14472 %} 14473 ins_encode %{ 14474 bool quad = true; 14475 __ vshrSI($dst$$FloatRegister, $src$$FloatRegister, 32, $shift$$constant, 14476 quad); 14477 %} 14478 ins_pipe( ialu_reg_reg ); // FIXME 14479%} 14480 14481// Longs vector arithmetic right shift 14482instruct vsra2L_reg(vecX dst, vecX src, vecX shift) %{ 14483 predicate(n->as_Vector()->length() == 2); 14484 match(Set dst (RShiftVL src shift)); 14485 size(4); 14486 ins_cost(DEFAULT_COST); // FIXME 14487 expand %{ 14488 vsha2L_reg(dst, src, shift); 14489 %} 14490%} 14491 14492instruct vsra2L_immI(vecX dst, vecX src, immI shift) %{ 14493 predicate(n->as_Vector()->length() == 2); 14494 match(Set dst (RShiftVL src shift)); 14495 size(4); 14496 ins_cost(DEFAULT_COST); // FIXME 14497 format %{ 14498 "VSHR.S64 $dst.Q,$src.Q,$shift\t! logical right shift packed2L" 14499 %} 14500 ins_encode %{ 14501 bool quad = true; 14502 __ vshrSI($dst$$FloatRegister, $src$$FloatRegister, 64, $shift$$constant, 14503 quad); 14504 %} 14505 ins_pipe( ialu_reg_reg ); // FIXME 14506%} 14507 14508// --------------------------------- AND -------------------------------------- 14509 14510instruct vandD(vecD dst, vecD src1, vecD src2) %{ 14511 predicate(n->as_Vector()->length_in_bytes() == 8); 14512 match(Set dst (AndV src1 src2)); 14513 format %{ "VAND $dst.D,$src1.D,$src2.D\t! and vectors (8 bytes)" %} 14514 ins_encode %{ 14515 bool quad = false; 14516 __ vandI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 14517 quad); 14518 %} 14519 ins_pipe( ialu_reg_reg ); // FIXME 14520%} 14521 14522instruct vandX(vecX dst, vecX src1, vecX src2) %{ 14523 predicate(n->as_Vector()->length_in_bytes() == 16); 14524 match(Set dst (AndV src1 src2)); 14525 format %{ "VAND $dst.Q,$src1.Q,$src2.Q\t! and vectors (16 bytes)" %} 14526 ins_encode %{ 14527 bool quad = true; 14528 __ vandI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 14529 quad); 14530 %} 14531 ins_pipe( ialu_reg_reg ); // FIXME 14532%} 14533 14534// --------------------------------- OR --------------------------------------- 14535 14536instruct vorD(vecD dst, vecD src1, vecD src2) %{ 14537 predicate(n->as_Vector()->length_in_bytes() == 8); 14538 match(Set dst (OrV src1 src2)); 14539 format %{ "VOR $dst.D,$src1.D,$src2.D\t! and vectors (8 bytes)" %} 14540 ins_encode %{ 14541 bool quad = false; 14542 __ vorI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 14543 quad); 14544 %} 14545 ins_pipe( ialu_reg_reg ); // FIXME 14546%} 14547 14548instruct vorX(vecX dst, vecX src1, vecX src2) %{ 14549 predicate(n->as_Vector()->length_in_bytes() == 16); 14550 match(Set dst (OrV src1 src2)); 14551 format %{ "VOR $dst.Q,$src1.Q,$src2.Q\t! and vectors (16 bytes)" %} 14552 ins_encode %{ 14553 bool quad = true; 14554 __ vorI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 14555 quad); 14556 %} 14557 ins_pipe( ialu_reg_reg ); // FIXME 14558%} 14559 14560// --------------------------------- XOR -------------------------------------- 14561 14562instruct vxorD(vecD dst, vecD src1, vecD src2) %{ 14563 predicate(n->as_Vector()->length_in_bytes() == 8); 14564 match(Set dst (XorV src1 src2)); 14565 format %{ "VXOR $dst.D,$src1.D,$src2.D\t! and vectors (8 bytes)" %} 14566 ins_encode %{ 14567 bool quad = false; 14568 __ vxorI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 14569 quad); 14570 %} 14571 ins_pipe( ialu_reg_reg ); // FIXME 14572%} 14573 14574instruct vxorX(vecX dst, vecX src1, vecX src2) %{ 14575 predicate(n->as_Vector()->length_in_bytes() == 16); 14576 match(Set dst (XorV src1 src2)); 14577 format %{ "VXOR $dst.Q,$src1.Q,$src2.Q\t! and vectors (16 bytes)" %} 14578 ins_encode %{ 14579 bool quad = true; 14580 __ vxorI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 14581 quad); 14582 %} 14583 ins_pipe( ialu_reg_reg ); // FIXME 14584%} 14585 14586 14587//----------PEEPHOLE RULES----------------------------------------------------- 14588// These must follow all instruction definitions as they use the names 14589// defined in the instructions definitions. 14590// 14591// peepmatch ( root_instr_name [preceding_instruction]* ); 14592// 14593// peepconstraint %{ 14594// (instruction_number.operand_name relational_op instruction_number.operand_name 14595// [, ...] ); 14596// // instruction numbers are zero-based using left to right order in peepmatch 14597// 14598// peepreplace ( instr_name ( [instruction_number.operand_name]* ) ); 14599// // provide an instruction_number.operand_name for each operand that appears 14600// // in the replacement instruction's match rule 14601// 14602// ---------VM FLAGS--------------------------------------------------------- 14603// 14604// All peephole optimizations can be turned off using -XX:-OptoPeephole 14605// 14606// Each peephole rule is given an identifying number starting with zero and 14607// increasing by one in the order seen by the parser. An individual peephole 14608// can be enabled, and all others disabled, by using -XX:OptoPeepholeAt=# 14609// on the command-line. 14610// 14611// ---------CURRENT LIMITATIONS---------------------------------------------- 14612// 14613// Only match adjacent instructions in same basic block 14614// Only equality constraints 14615// Only constraints between operands, not (0.dest_reg == EAX_enc) 14616// Only one replacement instruction 14617// 14618// ---------EXAMPLE---------------------------------------------------------- 14619// 14620// // pertinent parts of existing instructions in architecture description 14621// instruct movI(eRegI dst, eRegI src) %{ 14622// match(Set dst (CopyI src)); 14623// %} 14624// 14625// instruct incI_eReg(eRegI dst, immI1 src, eFlagsReg cr) %{ 14626// match(Set dst (AddI dst src)); 14627// effect(KILL cr); 14628// %} 14629// 14630// // Change (inc mov) to lea 14631// peephole %{ 14632// // increment preceeded by register-register move 14633// peepmatch ( incI_eReg movI ); 14634// // require that the destination register of the increment 14635// // match the destination register of the move 14636// peepconstraint ( 0.dst == 1.dst ); 14637// // construct a replacement instruction that sets 14638// // the destination to ( move's source register + one ) 14639// peepreplace ( incI_eReg_immI1( 0.dst 1.src 0.src ) ); 14640// %} 14641// 14642 14643// // Change load of spilled value to only a spill 14644// instruct storeI(memory mem, eRegI src) %{ 14645// match(Set mem (StoreI mem src)); 14646// %} 14647// 14648// instruct loadI(eRegI dst, memory mem) %{ 14649// match(Set dst (LoadI mem)); 14650// %} 14651// 14652// peephole %{ 14653// peepmatch ( loadI storeI ); 14654// peepconstraint ( 1.src == 0.dst, 1.mem == 0.mem ); 14655// peepreplace ( storeI( 1.mem 1.mem 1.src ) ); 14656// %} 14657 14658//----------SMARTSPILL RULES--------------------------------------------------- 14659// These must follow all instruction definitions as they use the names 14660// defined in the instructions definitions. 14661// 14662// ARM will probably not have any of these rules due to RISC instruction set. 14663 14664//----------PIPELINE----------------------------------------------------------- 14665// Rules which define the behavior of the target architectures pipeline. 14666