1 // 2 // Copyright (c) 2008, 2020, Oracle and/or its affiliates. All rights reserved. 3 // DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 // 5 // This code is free software; you can redistribute it and/or modify it 6 // under the terms of the GNU General Public License version 2 only, as 7 // published by the Free Software Foundation. 8 // 9 // This code is distributed in the hope that it will be useful, but WITHOUT 10 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 // version 2 for more details (a copy is included in the LICENSE file that 13 // accompanied this code). 14 // 15 // You should have received a copy of the GNU General Public License version 16 // 2 along with this work; if not, write to the Free Software Foundation, 17 // Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 // 19 // Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 // or visit www.oracle.com if you need additional information or have any 21 // questions. 22 // 23 24 // ARM Architecture Description File 25 26 //----------DEFINITION BLOCK--------------------------------------------------- 27 // Define name --> value mappings to inform the ADLC of an integer valued name 28 // Current support includes integer values in the range [0, 0x7FFFFFFF] 29 // Format: 30 // int_def <name> ( <int_value>, <expression>); 31 // Generated Code in ad_<arch>.hpp 32 // #define <name> (<expression>) 33 // // value == <int_value> 34 // Generated code in ad_<arch>.cpp adlc_verification() 35 // assert( <name> == <int_value>, "Expect (<expression>) to equal <int_value>"); 36 // 37 definitions %{ 38 // The default cost (of an ALU instruction). 39 int_def DEFAULT_COST ( 100, 100); 40 int_def HUGE_COST (1000000, 1000000); 41 42 // Memory refs are twice as expensive as run-of-the-mill. 43 int_def MEMORY_REF_COST ( 200, DEFAULT_COST * 2); 44 45 // Branches are even more expensive. 46 int_def BRANCH_COST ( 300, DEFAULT_COST * 3); 47 int_def CALL_COST ( 300, DEFAULT_COST * 3); 48 %} 49 50 51 //----------SOURCE BLOCK------------------------------------------------------- 52 // This is a block of C++ code which provides values, functions, and 53 // definitions necessary in the rest of the architecture description 54 source_hpp %{ 55 // Header information of the source block. 56 // Method declarations/definitions which are used outside 57 // the ad-scope can conveniently be defined here. 58 // 59 // To keep related declarations/definitions/uses close together, 60 // we switch between source %{ }% and source_hpp %{ }% freely as needed. 61 62 // Does destination need to be loaded in a register then passed to a 63 // branch instruction? 64 extern bool maybe_far_call(const CallNode *n); 65 extern bool maybe_far_call(const MachCallNode *n); 66 static inline bool cache_reachable() { 67 return MacroAssembler::_cache_fully_reachable(); 68 } 69 70 #define ldr_32 ldr 71 #define str_32 str 72 #define tst_32 tst 73 #define teq_32 teq 74 #if 1 75 extern bool PrintOptoAssembly; 76 #endif 77 78 class c2 { 79 public: 80 static OptoRegPair return_value(int ideal_reg); 81 }; 82 83 class CallStubImpl { 84 85 //-------------------------------------------------------------- 86 //---< Used for optimization in Compile::Shorten_branches >--- 87 //-------------------------------------------------------------- 88 89 public: 90 // Size of call trampoline stub. 91 static uint size_call_trampoline() { 92 return 0; // no call trampolines on this platform 93 } 94 95 // number of relocations needed by a call trampoline stub 96 static uint reloc_call_trampoline() { 97 return 0; // no call trampolines on this platform 98 } 99 }; 100 101 class HandlerImpl { 102 103 public: 104 105 static int emit_exception_handler(CodeBuffer &cbuf); 106 static int emit_deopt_handler(CodeBuffer& cbuf); 107 108 static uint size_exception_handler() { 109 return ( 3 * 4 ); 110 } 111 112 113 static uint size_deopt_handler() { 114 return ( 9 * 4 ); 115 } 116 117 }; 118 119 class Node::PD { 120 public: 121 enum NodeFlags { 122 _last_flag = Node::_last_flag 123 }; 124 }; 125 126 %} 127 128 source %{ 129 #define __ _masm. 130 131 static FloatRegister reg_to_FloatRegister_object(int register_encoding); 132 static Register reg_to_register_object(int register_encoding); 133 134 void PhaseOutput::pd_perform_mach_node_analysis() { 135 } 136 137 int MachNode::pd_alignment_required() const { 138 return 1; 139 } 140 141 int MachNode::compute_padding(int current_offset) const { 142 return 0; 143 } 144 145 // **************************************************************************** 146 147 // REQUIRED FUNCTIONALITY 148 149 // Indicate if the safepoint node needs the polling page as an input. 150 // Since ARM does not have absolute addressing, it does. 151 bool SafePointNode::needs_polling_address_input() { 152 return true; 153 } 154 155 // emit an interrupt that is caught by the debugger (for debugging compiler) 156 void emit_break(CodeBuffer &cbuf) { 157 C2_MacroAssembler _masm(&cbuf); 158 __ breakpoint(); 159 } 160 161 #ifndef PRODUCT 162 void MachBreakpointNode::format( PhaseRegAlloc *, outputStream *st ) const { 163 st->print("TA"); 164 } 165 #endif 166 167 void MachBreakpointNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { 168 emit_break(cbuf); 169 } 170 171 uint MachBreakpointNode::size(PhaseRegAlloc *ra_) const { 172 return MachNode::size(ra_); 173 } 174 175 176 void emit_nop(CodeBuffer &cbuf) { 177 C2_MacroAssembler _masm(&cbuf); 178 __ nop(); 179 } 180 181 182 void emit_call_reloc(CodeBuffer &cbuf, const MachCallNode *n, MachOper *m, RelocationHolder const& rspec) { 183 int ret_addr_offset0 = n->as_MachCall()->ret_addr_offset(); 184 int call_site_offset = cbuf.insts()->mark_off(); 185 C2_MacroAssembler _masm(&cbuf); 186 __ set_inst_mark(); // needed in emit_to_interp_stub() to locate the call 187 address target = (address)m->method(); 188 assert(n->as_MachCall()->entry_point() == target, "sanity"); 189 assert(maybe_far_call(n) == !__ reachable_from_cache(target), "sanity"); 190 assert(cache_reachable() == __ cache_fully_reachable(), "sanity"); 191 192 assert(target != NULL, "need real address"); 193 194 int ret_addr_offset = -1; 195 if (rspec.type() == relocInfo::runtime_call_type) { 196 __ call(target, rspec); 197 ret_addr_offset = __ offset(); 198 } else { 199 // scratches Rtemp 200 ret_addr_offset = __ patchable_call(target, rspec, true); 201 } 202 assert(ret_addr_offset - call_site_offset == ret_addr_offset0, "fix ret_addr_offset()"); 203 } 204 205 //============================================================================= 206 // REQUIRED FUNCTIONALITY for encoding 207 void emit_lo(CodeBuffer &cbuf, int val) { } 208 void emit_hi(CodeBuffer &cbuf, int val) { } 209 210 211 //============================================================================= 212 const RegMask& MachConstantBaseNode::_out_RegMask = PTR_REG_mask(); 213 214 int ConstantTable::calculate_table_base_offset() const { 215 int offset = -(size() / 2); 216 // flds, fldd: 8-bit offset multiplied by 4: +/- 1024 217 // ldr, ldrb : 12-bit offset: +/- 4096 218 if (!Assembler::is_simm10(offset)) { 219 offset = Assembler::min_simm10; 220 } 221 return offset; 222 } 223 224 bool MachConstantBaseNode::requires_postalloc_expand() const { return false; } 225 void MachConstantBaseNode::postalloc_expand(GrowableArray <Node *> *nodes, PhaseRegAlloc *ra_) { 226 ShouldNotReachHere(); 227 } 228 229 void MachConstantBaseNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const { 230 Compile* C = ra_->C; 231 ConstantTable& constant_table = C->output()->constant_table(); 232 C2_MacroAssembler _masm(&cbuf); 233 234 Register r = as_Register(ra_->get_encode(this)); 235 CodeSection* consts_section = __ code()->consts(); 236 int consts_size = consts_section->align_at_start(consts_section->size()); 237 assert(constant_table.size() == consts_size, "must be: %d == %d", constant_table.size(), consts_size); 238 239 // Materialize the constant table base. 240 address baseaddr = consts_section->start() + -(constant_table.table_base_offset()); 241 RelocationHolder rspec = internal_word_Relocation::spec(baseaddr); 242 __ mov_address(r, baseaddr, rspec); 243 } 244 245 uint MachConstantBaseNode::size(PhaseRegAlloc*) const { 246 return 8; 247 } 248 249 #ifndef PRODUCT 250 void MachConstantBaseNode::format(PhaseRegAlloc* ra_, outputStream* st) const { 251 char reg[128]; 252 ra_->dump_register(this, reg); 253 st->print("MOV_SLOW &constanttable,%s\t! constant table base", reg); 254 } 255 #endif 256 257 #ifndef PRODUCT 258 void MachPrologNode::format( PhaseRegAlloc *ra_, outputStream *st ) const { 259 Compile* C = ra_->C; 260 261 for (int i = 0; i < OptoPrologueNops; i++) { 262 st->print_cr("NOP"); st->print("\t"); 263 } 264 265 size_t framesize = C->output()->frame_size_in_bytes(); 266 assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned"); 267 int bangsize = C->output()->bang_size_in_bytes(); 268 // Remove two words for return addr and rbp, 269 framesize -= 2*wordSize; 270 bangsize -= 2*wordSize; 271 272 // Calls to C2R adapters often do not accept exceptional returns. 273 // We require that their callers must bang for them. But be careful, because 274 // some VM calls (such as call site linkage) can use several kilobytes of 275 // stack. But the stack safety zone should account for that. 276 // See bugs 4446381, 4468289, 4497237. 277 if (C->output()->need_stack_bang(bangsize)) { 278 st->print_cr("! stack bang (%d bytes)", bangsize); st->print("\t"); 279 } 280 st->print_cr("PUSH R_FP|R_LR_LR"); st->print("\t"); 281 if (framesize != 0) { 282 st->print ("SUB R_SP, R_SP, " SIZE_FORMAT,framesize); 283 } 284 } 285 #endif 286 287 void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { 288 Compile* C = ra_->C; 289 C2_MacroAssembler _masm(&cbuf); 290 291 for (int i = 0; i < OptoPrologueNops; i++) { 292 __ nop(); 293 } 294 295 size_t framesize = C->output()->frame_size_in_bytes(); 296 assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned"); 297 int bangsize = C->output()->bang_size_in_bytes(); 298 // Remove two words for return addr and fp, 299 framesize -= 2*wordSize; 300 bangsize -= 2*wordSize; 301 302 // Calls to C2R adapters often do not accept exceptional returns. 303 // We require that their callers must bang for them. But be careful, because 304 // some VM calls (such as call site linkage) can use several kilobytes of 305 // stack. But the stack safety zone should account for that. 306 // See bugs 4446381, 4468289, 4497237. 307 if (C->output()->need_stack_bang(bangsize)) { 308 __ arm_stack_overflow_check(bangsize, Rtemp); 309 } 310 311 __ raw_push(FP, LR); 312 if (framesize != 0) { 313 __ sub_slow(SP, SP, framesize); 314 } 315 316 // offset from scratch buffer is not valid 317 if (strcmp(cbuf.name(), "Compile::Fill_buffer") == 0) { 318 C->output()->set_frame_complete( __ offset() ); 319 } 320 321 if (C->has_mach_constant_base_node()) { 322 // NOTE: We set the table base offset here because users might be 323 // emitted before MachConstantBaseNode. 324 ConstantTable& constant_table = C->output()->constant_table(); 325 constant_table.set_table_base_offset(constant_table.calculate_table_base_offset()); 326 } 327 } 328 329 uint MachPrologNode::size(PhaseRegAlloc *ra_) const { 330 return MachNode::size(ra_); 331 } 332 333 int MachPrologNode::reloc() const { 334 return 10; // a large enough number 335 } 336 337 //============================================================================= 338 #ifndef PRODUCT 339 void MachEpilogNode::format( PhaseRegAlloc *ra_, outputStream *st ) const { 340 Compile* C = ra_->C; 341 342 size_t framesize = C->output()->frame_size_in_bytes(); 343 framesize -= 2*wordSize; 344 345 if (framesize != 0) { 346 st->print("ADD R_SP, R_SP, " SIZE_FORMAT "\n\t",framesize); 347 } 348 st->print("POP R_FP|R_LR_LR"); 349 350 if (do_polling() && ra_->C->is_method_compilation()) { 351 st->print("\n\t"); 352 st->print("MOV Rtemp, #PollAddr\t! Load Polling address\n\t"); 353 st->print("LDR Rtemp,[Rtemp]\t!Poll for Safepointing"); 354 } 355 } 356 #endif 357 358 void MachEpilogNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { 359 C2_MacroAssembler _masm(&cbuf); 360 Compile* C = ra_->C; 361 362 size_t framesize = C->output()->frame_size_in_bytes(); 363 framesize -= 2*wordSize; 364 if (framesize != 0) { 365 __ add_slow(SP, SP, framesize); 366 } 367 __ raw_pop(FP, LR); 368 369 // If this does safepoint polling, then do it here 370 if (do_polling() && ra_->C->is_method_compilation()) { 371 __ read_polling_page(Rtemp, relocInfo::poll_return_type); 372 } 373 } 374 375 uint MachEpilogNode::size(PhaseRegAlloc *ra_) const { 376 return MachNode::size(ra_); 377 } 378 379 int MachEpilogNode::reloc() const { 380 return 16; // a large enough number 381 } 382 383 const Pipeline * MachEpilogNode::pipeline() const { 384 return MachNode::pipeline_class(); 385 } 386 387 //============================================================================= 388 389 // Figure out which register class each belongs in: rc_int, rc_float, rc_stack 390 enum RC { rc_bad, rc_int, rc_float, rc_stack }; 391 static enum RC rc_class( OptoReg::Name reg ) { 392 if (!OptoReg::is_valid(reg)) return rc_bad; 393 if (OptoReg::is_stack(reg)) return rc_stack; 394 VMReg r = OptoReg::as_VMReg(reg); 395 if (r->is_Register()) return rc_int; 396 assert(r->is_FloatRegister(), "must be"); 397 return rc_float; 398 } 399 400 static inline bool is_iRegLd_memhd(OptoReg::Name src_first, OptoReg::Name src_second, int offset) { 401 int rlo = Matcher::_regEncode[src_first]; 402 int rhi = Matcher::_regEncode[src_second]; 403 if (!((rlo&1)==0 && (rlo+1 == rhi))) { 404 tty->print_cr("CAUGHT BAD LDRD/STRD"); 405 } 406 return (rlo&1)==0 && (rlo+1 == rhi) && is_memoryHD(offset); 407 } 408 409 uint MachSpillCopyNode::implementation( CodeBuffer *cbuf, 410 PhaseRegAlloc *ra_, 411 bool do_size, 412 outputStream* st ) const { 413 // Get registers to move 414 OptoReg::Name src_second = ra_->get_reg_second(in(1)); 415 OptoReg::Name src_first = ra_->get_reg_first(in(1)); 416 OptoReg::Name dst_second = ra_->get_reg_second(this ); 417 OptoReg::Name dst_first = ra_->get_reg_first(this ); 418 419 enum RC src_second_rc = rc_class(src_second); 420 enum RC src_first_rc = rc_class(src_first); 421 enum RC dst_second_rc = rc_class(dst_second); 422 enum RC dst_first_rc = rc_class(dst_first); 423 424 assert( OptoReg::is_valid(src_first) && OptoReg::is_valid(dst_first), "must move at least 1 register" ); 425 426 // Generate spill code! 427 int size = 0; 428 429 if (src_first == dst_first && src_second == dst_second) 430 return size; // Self copy, no move 431 432 #ifdef TODO 433 if (bottom_type()->isa_vect() != NULL) { 434 } 435 #endif 436 437 // Shared code does not expect instruction set capability based bailouts here. 438 // Handle offset unreachable bailout with minimal change in shared code. 439 // Bailout only for real instruction emit. 440 // This requires a single comment change in shared code. ( see output.cpp "Normal" instruction case ) 441 442 C2_MacroAssembler _masm(cbuf); 443 444 // -------------------------------------- 445 // Check for mem-mem move. Load into unused float registers and fall into 446 // the float-store case. 447 if (src_first_rc == rc_stack && dst_first_rc == rc_stack) { 448 int offset = ra_->reg2offset(src_first); 449 if (cbuf && !is_memoryfp(offset)) { 450 ra_->C->record_method_not_compilable("unable to handle large constant offsets"); 451 return 0; 452 } else { 453 if (src_second_rc != rc_bad) { 454 assert((src_first&1)==0 && src_first+1 == src_second, "pair of registers must be aligned/contiguous"); 455 src_first = OptoReg::Name(R_mem_copy_lo_num); 456 src_second = OptoReg::Name(R_mem_copy_hi_num); 457 src_first_rc = rc_float; 458 src_second_rc = rc_float; 459 if (cbuf) { 460 __ ldr_double(Rmemcopy, Address(SP, offset)); 461 } else if (!do_size) { 462 st->print(LDR_DOUBLE " R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(src_first),offset); 463 } 464 } else { 465 src_first = OptoReg::Name(R_mem_copy_lo_num); 466 src_first_rc = rc_float; 467 if (cbuf) { 468 __ ldr_float(Rmemcopy, Address(SP, offset)); 469 } else if (!do_size) { 470 st->print(LDR_FLOAT " R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(src_first),offset); 471 } 472 } 473 size += 4; 474 } 475 } 476 477 if (src_second_rc == rc_stack && dst_second_rc == rc_stack) { 478 Unimplemented(); 479 } 480 481 // -------------------------------------- 482 // Check for integer reg-reg copy 483 if (src_first_rc == rc_int && dst_first_rc == rc_int) { 484 // Else normal reg-reg copy 485 assert( src_second != dst_first, "smashed second before evacuating it" ); 486 if (cbuf) { 487 __ mov(reg_to_register_object(Matcher::_regEncode[dst_first]), reg_to_register_object(Matcher::_regEncode[src_first])); 488 #ifndef PRODUCT 489 } else if (!do_size) { 490 st->print("MOV R_%s, R_%s\t# spill", 491 Matcher::regName[dst_first], 492 Matcher::regName[src_first]); 493 #endif 494 } 495 size += 4; 496 } 497 498 // Check for integer store 499 if (src_first_rc == rc_int && dst_first_rc == rc_stack) { 500 int offset = ra_->reg2offset(dst_first); 501 if (cbuf && !is_memoryI(offset)) { 502 ra_->C->record_method_not_compilable("unable to handle large constant offsets"); 503 return 0; 504 } else { 505 if (src_second_rc != rc_bad && is_iRegLd_memhd(src_first, src_second, offset)) { 506 assert((src_first&1)==0 && src_first+1 == src_second, "pair of registers must be aligned/contiguous"); 507 if (cbuf) { 508 __ str_64(reg_to_register_object(Matcher::_regEncode[src_first]), Address(SP, offset)); 509 #ifndef PRODUCT 510 } else if (!do_size) { 511 if (size != 0) st->print("\n\t"); 512 st->print(STR_64 " R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(src_first), offset); 513 #endif 514 } 515 return size + 4; 516 } else { 517 if (cbuf) { 518 __ str_32(reg_to_register_object(Matcher::_regEncode[src_first]), Address(SP, offset)); 519 #ifndef PRODUCT 520 } else if (!do_size) { 521 if (size != 0) st->print("\n\t"); 522 st->print(STR_32 " R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(src_first), offset); 523 #endif 524 } 525 } 526 } 527 size += 4; 528 } 529 530 // Check for integer load 531 if (dst_first_rc == rc_int && src_first_rc == rc_stack) { 532 int offset = ra_->reg2offset(src_first); 533 if (cbuf && !is_memoryI(offset)) { 534 ra_->C->record_method_not_compilable("unable to handle large constant offsets"); 535 return 0; 536 } else { 537 if (src_second_rc != rc_bad && is_iRegLd_memhd(dst_first, dst_second, offset)) { 538 assert((src_first&1)==0 && src_first+1 == src_second, "pair of registers must be aligned/contiguous"); 539 if (cbuf) { 540 __ ldr_64(reg_to_register_object(Matcher::_regEncode[dst_first]), Address(SP, offset)); 541 #ifndef PRODUCT 542 } else if (!do_size) { 543 if (size != 0) st->print("\n\t"); 544 st->print(LDR_64 " R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(dst_first), offset); 545 #endif 546 } 547 return size + 4; 548 } else { 549 if (cbuf) { 550 __ ldr_32(reg_to_register_object(Matcher::_regEncode[dst_first]), Address(SP, offset)); 551 #ifndef PRODUCT 552 } else if (!do_size) { 553 if (size != 0) st->print("\n\t"); 554 st->print(LDR_32 " R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(dst_first), offset); 555 #endif 556 } 557 } 558 } 559 size += 4; 560 } 561 562 // Check for float reg-reg copy 563 if (src_first_rc == rc_float && dst_first_rc == rc_float) { 564 if (src_second_rc != rc_bad) { 565 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"); 566 if (cbuf) { 567 __ mov_double(reg_to_FloatRegister_object(Matcher::_regEncode[dst_first]), reg_to_FloatRegister_object(Matcher::_regEncode[src_first])); 568 #ifndef PRODUCT 569 } else if (!do_size) { 570 st->print(MOV_DOUBLE " R_%s, R_%s\t# spill", 571 Matcher::regName[dst_first], 572 Matcher::regName[src_first]); 573 #endif 574 } 575 return 4; 576 } 577 if (cbuf) { 578 __ mov_float(reg_to_FloatRegister_object(Matcher::_regEncode[dst_first]), reg_to_FloatRegister_object(Matcher::_regEncode[src_first])); 579 #ifndef PRODUCT 580 } else if (!do_size) { 581 st->print(MOV_FLOAT " R_%s, R_%s\t# spill", 582 Matcher::regName[dst_first], 583 Matcher::regName[src_first]); 584 #endif 585 } 586 size = 4; 587 } 588 589 // Check for float store 590 if (src_first_rc == rc_float && dst_first_rc == rc_stack) { 591 int offset = ra_->reg2offset(dst_first); 592 if (cbuf && !is_memoryfp(offset)) { 593 ra_->C->record_method_not_compilable("unable to handle large constant offsets"); 594 return 0; 595 } else { 596 // Further check for aligned-adjacent pair, so we can use a double store 597 if (src_second_rc != rc_bad) { 598 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"); 599 if (cbuf) { 600 __ str_double(reg_to_FloatRegister_object(Matcher::_regEncode[src_first]), Address(SP, offset)); 601 #ifndef PRODUCT 602 } else if (!do_size) { 603 if (size != 0) st->print("\n\t"); 604 st->print(STR_DOUBLE " R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(src_first),offset); 605 #endif 606 } 607 return size + 4; 608 } else { 609 if (cbuf) { 610 __ str_float(reg_to_FloatRegister_object(Matcher::_regEncode[src_first]), Address(SP, offset)); 611 #ifndef PRODUCT 612 } else if (!do_size) { 613 if (size != 0) st->print("\n\t"); 614 st->print(STR_FLOAT " R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(src_first),offset); 615 #endif 616 } 617 } 618 } 619 size += 4; 620 } 621 622 // Check for float load 623 if (dst_first_rc == rc_float && src_first_rc == rc_stack) { 624 int offset = ra_->reg2offset(src_first); 625 if (cbuf && !is_memoryfp(offset)) { 626 ra_->C->record_method_not_compilable("unable to handle large constant offsets"); 627 return 0; 628 } else { 629 // Further check for aligned-adjacent pair, so we can use a double store 630 if (src_second_rc != rc_bad) { 631 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"); 632 if (cbuf) { 633 __ ldr_double(reg_to_FloatRegister_object(Matcher::_regEncode[dst_first]), Address(SP, offset)); 634 #ifndef PRODUCT 635 } else if (!do_size) { 636 if (size != 0) st->print("\n\t"); 637 st->print(LDR_DOUBLE " R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(dst_first),offset); 638 #endif 639 } 640 return size + 4; 641 } else { 642 if (cbuf) { 643 __ ldr_float(reg_to_FloatRegister_object(Matcher::_regEncode[dst_first]), Address(SP, offset)); 644 #ifndef PRODUCT 645 } else if (!do_size) { 646 if (size != 0) st->print("\n\t"); 647 st->print(LDR_FLOAT " R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(dst_first),offset); 648 #endif 649 } 650 } 651 } 652 size += 4; 653 } 654 655 // check for int reg -> float reg move 656 if (src_first_rc == rc_int && dst_first_rc == rc_float) { 657 // Further check for aligned-adjacent pair, so we can use a single instruction 658 if (src_second_rc != rc_bad) { 659 assert((dst_first&1)==0 && dst_first+1 == dst_second, "pairs of registers must be aligned/contiguous"); 660 assert((src_first&1)==0 && src_first+1 == src_second, "pairs of registers must be aligned/contiguous"); 661 assert(src_second_rc == rc_int && dst_second_rc == rc_float, "unsupported"); 662 if (cbuf) { 663 __ 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])); 664 #ifndef PRODUCT 665 } else if (!do_size) { 666 if (size != 0) st->print("\n\t"); 667 st->print("FMDRR R_%s, R_%s, R_%s\t! spill",OptoReg::regname(dst_first), OptoReg::regname(src_first), OptoReg::regname(src_second)); 668 #endif 669 } 670 return size + 4; 671 } else { 672 if (cbuf) { 673 __ fmsr(reg_to_FloatRegister_object(Matcher::_regEncode[dst_first]), reg_to_register_object(Matcher::_regEncode[src_first])); 674 #ifndef PRODUCT 675 } else if (!do_size) { 676 if (size != 0) st->print("\n\t"); 677 st->print(FMSR " R_%s, R_%s\t! spill",OptoReg::regname(dst_first), OptoReg::regname(src_first)); 678 #endif 679 } 680 size += 4; 681 } 682 } 683 684 // check for float reg -> int reg move 685 if (src_first_rc == rc_float && dst_first_rc == rc_int) { 686 // Further check for aligned-adjacent pair, so we can use a single instruction 687 if (src_second_rc != rc_bad) { 688 assert((src_first&1)==0 && src_first+1 == src_second, "pairs of registers must be aligned/contiguous"); 689 assert((dst_first&1)==0 && dst_first+1 == dst_second, "pairs of registers must be aligned/contiguous"); 690 assert(src_second_rc == rc_float && dst_second_rc == rc_int, "unsupported"); 691 if (cbuf) { 692 __ 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])); 693 #ifndef PRODUCT 694 } else if (!do_size) { 695 if (size != 0) st->print("\n\t"); 696 st->print("FMRRD R_%s, R_%s, R_%s\t! spill",OptoReg::regname(dst_first), OptoReg::regname(dst_second), OptoReg::regname(src_first)); 697 #endif 698 } 699 return size + 4; 700 } else { 701 if (cbuf) { 702 __ fmrs(reg_to_register_object(Matcher::_regEncode[dst_first]), reg_to_FloatRegister_object(Matcher::_regEncode[src_first])); 703 #ifndef PRODUCT 704 } else if (!do_size) { 705 if (size != 0) st->print("\n\t"); 706 st->print(FMRS " R_%s, R_%s\t! spill",OptoReg::regname(dst_first), OptoReg::regname(src_first)); 707 #endif 708 } 709 size += 4; 710 } 711 } 712 713 // -------------------------------------------------------------------- 714 // Check for hi bits still needing moving. Only happens for misaligned 715 // arguments to native calls. 716 if (src_second == dst_second) 717 return size; // Self copy; no move 718 assert( src_second_rc != rc_bad && dst_second_rc != rc_bad, "src_second & dst_second cannot be Bad" ); 719 720 // Check for integer reg-reg copy. Hi bits are stuck up in the top 721 // 32-bits of a 64-bit register, but are needed in low bits of another 722 // register (else it's a hi-bits-to-hi-bits copy which should have 723 // happened already as part of a 64-bit move) 724 if (src_second_rc == rc_int && dst_second_rc == rc_int) { 725 if (cbuf) { 726 __ mov(reg_to_register_object(Matcher::_regEncode[dst_second]), reg_to_register_object(Matcher::_regEncode[src_second])); 727 #ifndef PRODUCT 728 } else if (!do_size) { 729 if (size != 0) st->print("\n\t"); 730 st->print("MOV R_%s, R_%s\t# spill high", 731 Matcher::regName[dst_second], 732 Matcher::regName[src_second]); 733 #endif 734 } 735 return size+4; 736 } 737 738 // Check for high word integer store 739 if (src_second_rc == rc_int && dst_second_rc == rc_stack) { 740 int offset = ra_->reg2offset(dst_second); 741 742 if (cbuf && !is_memoryP(offset)) { 743 ra_->C->record_method_not_compilable("unable to handle large constant offsets"); 744 return 0; 745 } else { 746 if (cbuf) { 747 __ str(reg_to_register_object(Matcher::_regEncode[src_second]), Address(SP, offset)); 748 #ifndef PRODUCT 749 } else if (!do_size) { 750 if (size != 0) st->print("\n\t"); 751 st->print("STR R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(src_second), offset); 752 #endif 753 } 754 } 755 return size + 4; 756 } 757 758 // Check for high word integer load 759 if (dst_second_rc == rc_int && src_second_rc == rc_stack) { 760 int offset = ra_->reg2offset(src_second); 761 if (cbuf && !is_memoryP(offset)) { 762 ra_->C->record_method_not_compilable("unable to handle large constant offsets"); 763 return 0; 764 } else { 765 if (cbuf) { 766 __ ldr(reg_to_register_object(Matcher::_regEncode[dst_second]), Address(SP, offset)); 767 #ifndef PRODUCT 768 } else if (!do_size) { 769 if (size != 0) st->print("\n\t"); 770 st->print("LDR R_%s,[R_SP + #%d]\t! spill",OptoReg::regname(dst_second), offset); 771 #endif 772 } 773 } 774 return size + 4; 775 } 776 777 Unimplemented(); 778 return 0; // Mute compiler 779 } 780 781 #ifndef PRODUCT 782 void MachSpillCopyNode::format( PhaseRegAlloc *ra_, outputStream *st ) const { 783 implementation( NULL, ra_, false, st ); 784 } 785 #endif 786 787 void MachSpillCopyNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { 788 implementation( &cbuf, ra_, false, NULL ); 789 } 790 791 uint MachSpillCopyNode::size(PhaseRegAlloc *ra_) const { 792 return implementation( NULL, ra_, true, NULL ); 793 } 794 795 //============================================================================= 796 #ifndef PRODUCT 797 void MachNopNode::format( PhaseRegAlloc *, outputStream *st ) const { 798 st->print("NOP \t# %d bytes pad for loops and calls", 4 * _count); 799 } 800 #endif 801 802 void MachNopNode::emit(CodeBuffer &cbuf, PhaseRegAlloc * ) const { 803 C2_MacroAssembler _masm(&cbuf); 804 for(int i = 0; i < _count; i += 1) { 805 __ nop(); 806 } 807 } 808 809 uint MachNopNode::size(PhaseRegAlloc *ra_) const { 810 return 4 * _count; 811 } 812 813 814 //============================================================================= 815 #ifndef PRODUCT 816 void BoxLockNode::format( PhaseRegAlloc *ra_, outputStream *st ) const { 817 int offset = ra_->reg2offset(in_RegMask(0).find_first_elem()); 818 int reg = ra_->get_reg_first(this); 819 st->print("ADD %s,R_SP+#%d",Matcher::regName[reg], offset); 820 } 821 #endif 822 823 void BoxLockNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { 824 C2_MacroAssembler _masm(&cbuf); 825 int offset = ra_->reg2offset(in_RegMask(0).find_first_elem()); 826 int reg = ra_->get_encode(this); 827 Register dst = reg_to_register_object(reg); 828 829 if (is_aimm(offset)) { 830 __ add(dst, SP, offset); 831 } else { 832 __ mov_slow(dst, offset); 833 __ add(dst, SP, dst); 834 } 835 } 836 837 uint BoxLockNode::size(PhaseRegAlloc *ra_) const { 838 // BoxLockNode is not a MachNode, so we can't just call MachNode::size(ra_) 839 assert(ra_ == ra_->C->regalloc(), "sanity"); 840 return ra_->C->output()->scratch_emit_size(this); 841 } 842 843 //============================================================================= 844 #ifndef PRODUCT 845 #define R_RTEMP "R_R12" 846 void MachUEPNode::format( PhaseRegAlloc *ra_, outputStream *st ) const { 847 st->print_cr("\nUEP:"); 848 if (UseCompressedClassPointers) { 849 st->print_cr("\tLDR_w " R_RTEMP ",[R_R0 + oopDesc::klass_offset_in_bytes]\t! Inline cache check"); 850 st->print_cr("\tdecode_klass " R_RTEMP); 851 } else { 852 st->print_cr("\tLDR " R_RTEMP ",[R_R0 + oopDesc::klass_offset_in_bytes]\t! Inline cache check"); 853 } 854 st->print_cr("\tCMP " R_RTEMP ",R_R8" ); 855 st->print ("\tB.NE SharedRuntime::handle_ic_miss_stub"); 856 } 857 #endif 858 859 void MachUEPNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { 860 C2_MacroAssembler _masm(&cbuf); 861 Register iCache = reg_to_register_object(Matcher::inline_cache_reg_encode()); 862 assert(iCache == Ricklass, "should be"); 863 Register receiver = R0; 864 865 __ load_klass(Rtemp, receiver); 866 __ cmp(Rtemp, iCache); 867 __ jump(SharedRuntime::get_ic_miss_stub(), relocInfo::runtime_call_type, noreg, ne); 868 } 869 870 uint MachUEPNode::size(PhaseRegAlloc *ra_) const { 871 return MachNode::size(ra_); 872 } 873 874 875 //============================================================================= 876 877 // Emit exception handler code. 878 int HandlerImpl::emit_exception_handler(CodeBuffer& cbuf) { 879 C2_MacroAssembler _masm(&cbuf); 880 881 address base = __ start_a_stub(size_exception_handler()); 882 if (base == NULL) { 883 ciEnv::current()->record_failure("CodeCache is full"); 884 return 0; // CodeBuffer::expand failed 885 } 886 887 int offset = __ offset(); 888 889 // OK to trash LR, because exception blob will kill it 890 __ jump(OptoRuntime::exception_blob()->entry_point(), relocInfo::runtime_call_type, LR_tmp); 891 892 assert(__ offset() - offset <= (int) size_exception_handler(), "overflow"); 893 894 __ end_a_stub(); 895 896 return offset; 897 } 898 899 int HandlerImpl::emit_deopt_handler(CodeBuffer& cbuf) { 900 // Can't use any of the current frame's registers as we may have deopted 901 // at a poll and everything can be live. 902 C2_MacroAssembler _masm(&cbuf); 903 904 address base = __ start_a_stub(size_deopt_handler()); 905 if (base == NULL) { 906 ciEnv::current()->record_failure("CodeCache is full"); 907 return 0; // CodeBuffer::expand failed 908 } 909 910 int offset = __ offset(); 911 address deopt_pc = __ pc(); 912 913 __ sub(SP, SP, wordSize); // make room for saved PC 914 __ push(LR); // save LR that may be live when we get here 915 __ mov_relative_address(LR, deopt_pc); 916 __ str(LR, Address(SP, wordSize)); // save deopt PC 917 __ pop(LR); // restore LR 918 __ jump(SharedRuntime::deopt_blob()->unpack(), relocInfo::runtime_call_type, noreg); 919 920 assert(__ offset() - offset <= (int) size_deopt_handler(), "overflow"); 921 922 __ end_a_stub(); 923 return offset; 924 } 925 926 const bool Matcher::match_rule_supported(int opcode) { 927 if (!has_match_rule(opcode)) 928 return false; 929 930 switch (opcode) { 931 case Op_PopCountI: 932 case Op_PopCountL: 933 if (!UsePopCountInstruction) 934 return false; 935 break; 936 case Op_LShiftCntV: 937 case Op_RShiftCntV: 938 case Op_AddVB: 939 case Op_AddVS: 940 case Op_AddVI: 941 case Op_AddVL: 942 case Op_SubVB: 943 case Op_SubVS: 944 case Op_SubVI: 945 case Op_SubVL: 946 case Op_MulVS: 947 case Op_MulVI: 948 case Op_LShiftVB: 949 case Op_LShiftVS: 950 case Op_LShiftVI: 951 case Op_LShiftVL: 952 case Op_RShiftVB: 953 case Op_RShiftVS: 954 case Op_RShiftVI: 955 case Op_RShiftVL: 956 case Op_URShiftVB: 957 case Op_URShiftVS: 958 case Op_URShiftVI: 959 case Op_URShiftVL: 960 case Op_AndV: 961 case Op_OrV: 962 case Op_XorV: 963 return VM_Version::has_simd(); 964 case Op_LoadVector: 965 case Op_StoreVector: 966 case Op_AddVF: 967 case Op_SubVF: 968 case Op_MulVF: 969 return VM_Version::has_vfp() || VM_Version::has_simd(); 970 case Op_AddVD: 971 case Op_SubVD: 972 case Op_MulVD: 973 case Op_DivVF: 974 case Op_DivVD: 975 return VM_Version::has_vfp(); 976 } 977 978 return true; // Per default match rules are supported. 979 } 980 981 const bool Matcher::match_rule_supported_vector(int opcode, int vlen, BasicType bt) { 982 983 // TODO 984 // identify extra cases that we might want to provide match rules for 985 // e.g. Op_ vector nodes and other intrinsics while guarding with vlen 986 bool ret_value = match_rule_supported(opcode); 987 // Add rules here. 988 989 return ret_value; // Per default match rules are supported. 990 } 991 992 const bool Matcher::has_predicated_vectors(void) { 993 return false; 994 } 995 996 const int Matcher::float_pressure(int default_pressure_threshold) { 997 return default_pressure_threshold; 998 } 999 1000 int Matcher::regnum_to_fpu_offset(int regnum) { 1001 return regnum - 32; // The FP registers are in the second chunk 1002 } 1003 1004 // Vector width in bytes 1005 const int Matcher::vector_width_in_bytes(BasicType bt) { 1006 return MaxVectorSize; 1007 } 1008 1009 // Vector ideal reg corresponding to specified size in bytes 1010 const uint Matcher::vector_ideal_reg(int size) { 1011 assert(MaxVectorSize >= size, ""); 1012 switch(size) { 1013 case 8: return Op_VecD; 1014 case 16: return Op_VecX; 1015 } 1016 ShouldNotReachHere(); 1017 return 0; 1018 } 1019 1020 // Limits on vector size (number of elements) loaded into vector. 1021 const int Matcher::max_vector_size(const BasicType bt) { 1022 assert(is_java_primitive(bt), "only primitive type vectors"); 1023 return vector_width_in_bytes(bt)/type2aelembytes(bt); 1024 } 1025 1026 const int Matcher::min_vector_size(const BasicType bt) { 1027 assert(is_java_primitive(bt), "only primitive type vectors"); 1028 return 8/type2aelembytes(bt); 1029 } 1030 1031 // ARM doesn't support misaligned vectors store/load. 1032 const bool Matcher::misaligned_vectors_ok() { 1033 return false; 1034 } 1035 1036 // ARM doesn't support AES intrinsics 1037 const bool Matcher::pass_original_key_for_aes() { 1038 return false; 1039 } 1040 1041 const bool Matcher::convL2FSupported(void) { 1042 return false; 1043 } 1044 1045 // Is this branch offset short enough that a short branch can be used? 1046 // 1047 // NOTE: If the platform does not provide any short branch variants, then 1048 // this method should return false for offset 0. 1049 bool Matcher::is_short_branch_offset(int rule, int br_size, int offset) { 1050 // The passed offset is relative to address of the branch. 1051 // On ARM a branch displacement is calculated relative to address 1052 // of the branch + 8. 1053 // 1054 // offset -= 8; 1055 // return (Assembler::is_simm24(offset)); 1056 return false; 1057 } 1058 1059 const bool Matcher::isSimpleConstant64(jlong value) { 1060 // Will one (StoreL ConL) be cheaper than two (StoreI ConI)?. 1061 return false; 1062 } 1063 1064 // No scaling for the parameter the ClearArray node. 1065 const bool Matcher::init_array_count_is_in_bytes = true; 1066 1067 // Needs 2 CMOV's for longs. 1068 const int Matcher::long_cmove_cost() { return 2; } 1069 1070 // CMOVF/CMOVD are expensive on ARM. 1071 const int Matcher::float_cmove_cost() { return ConditionalMoveLimit; } 1072 1073 // Does the CPU require late expand (see block.cpp for description of late expand)? 1074 const bool Matcher::require_postalloc_expand = false; 1075 1076 // Do we need to mask the count passed to shift instructions or does 1077 // the cpu only look at the lower 5/6 bits anyway? 1078 // FIXME: does this handle vector shifts as well? 1079 const bool Matcher::need_masked_shift_count = true; 1080 1081 const bool Matcher::convi2l_type_required = true; 1082 1083 // No support for generic vector operands. 1084 const bool Matcher::supports_generic_vector_operands = false; 1085 1086 MachOper* Matcher::pd_specialize_generic_vector_operand(MachOper* original_opnd, uint ideal_reg, bool is_temp) { 1087 ShouldNotReachHere(); // generic vector operands not supported 1088 return NULL; 1089 } 1090 1091 bool Matcher::is_generic_reg2reg_move(MachNode* m) { 1092 ShouldNotReachHere(); // generic vector operands not supported 1093 return false; 1094 } 1095 1096 bool Matcher::is_generic_vector(MachOper* opnd) { 1097 ShouldNotReachHere(); // generic vector operands not supported 1098 return false; 1099 } 1100 1101 // Should the matcher clone input 'm' of node 'n'? 1102 bool Matcher::pd_clone_node(Node* n, Node* m, Matcher::MStack& mstack) { 1103 if (is_vshift_con_pattern(n, m)) { // ShiftV src (ShiftCntV con) 1104 mstack.push(m, Visit); // m = ShiftCntV 1105 return true; 1106 } 1107 return false; 1108 } 1109 1110 // Should the Matcher clone shifts on addressing modes, expecting them 1111 // to be subsumed into complex addressing expressions or compute them 1112 // into registers? 1113 bool Matcher::pd_clone_address_expressions(AddPNode* m, Matcher::MStack& mstack, VectorSet& address_visited) { 1114 return clone_base_plus_offset_address(m, mstack, address_visited); 1115 } 1116 1117 void Compile::reshape_address(AddPNode* addp) { 1118 } 1119 1120 bool Matcher::narrow_oop_use_complex_address() { 1121 NOT_LP64(ShouldNotCallThis()); 1122 assert(UseCompressedOops, "only for compressed oops code"); 1123 return false; 1124 } 1125 1126 bool Matcher::narrow_klass_use_complex_address() { 1127 NOT_LP64(ShouldNotCallThis()); 1128 assert(UseCompressedClassPointers, "only for compressed klass code"); 1129 return false; 1130 } 1131 1132 bool Matcher::const_oop_prefer_decode() { 1133 NOT_LP64(ShouldNotCallThis()); 1134 return true; 1135 } 1136 1137 bool Matcher::const_klass_prefer_decode() { 1138 NOT_LP64(ShouldNotCallThis()); 1139 return true; 1140 } 1141 1142 // Is it better to copy float constants, or load them directly from memory? 1143 // Intel can load a float constant from a direct address, requiring no 1144 // extra registers. Most RISCs will have to materialize an address into a 1145 // register first, so they would do better to copy the constant from stack. 1146 const bool Matcher::rematerialize_float_constants = false; 1147 1148 // If CPU can load and store mis-aligned doubles directly then no fixup is 1149 // needed. Else we split the double into 2 integer pieces and move it 1150 // piece-by-piece. Only happens when passing doubles into C code as the 1151 // Java calling convention forces doubles to be aligned. 1152 const bool Matcher::misaligned_doubles_ok = false; 1153 1154 // No-op on ARM. 1155 void Matcher::pd_implicit_null_fixup(MachNode *node, uint idx) { 1156 } 1157 1158 // Advertise here if the CPU requires explicit rounding operations to implement strictfp mode. 1159 const bool Matcher::strict_fp_requires_explicit_rounding = false; 1160 1161 // Are floats converted to double when stored to stack during deoptimization? 1162 // ARM does not handle callee-save floats. 1163 bool Matcher::float_in_double() { 1164 return false; 1165 } 1166 1167 // Do ints take an entire long register or just half? 1168 // Note that we if-def off of _LP64. 1169 // The relevant question is how the int is callee-saved. In _LP64 1170 // the whole long is written but de-opt'ing will have to extract 1171 // the relevant 32 bits, in not-_LP64 only the low 32 bits is written. 1172 #ifdef _LP64 1173 const bool Matcher::int_in_long = true; 1174 #else 1175 const bool Matcher::int_in_long = false; 1176 #endif 1177 1178 // Return whether or not this register is ever used as an argument. This 1179 // function is used on startup to build the trampoline stubs in generateOptoStub. 1180 // Registers not mentioned will be killed by the VM call in the trampoline, and 1181 // arguments in those registers not be available to the callee. 1182 bool Matcher::can_be_java_arg( int reg ) { 1183 if (reg == R_R0_num || 1184 reg == R_R1_num || 1185 reg == R_R2_num || 1186 reg == R_R3_num) return true; 1187 1188 if (reg >= R_S0_num && 1189 reg <= R_S13_num) return true; 1190 return false; 1191 } 1192 1193 bool Matcher::is_spillable_arg( int reg ) { 1194 return can_be_java_arg(reg); 1195 } 1196 1197 bool Matcher::use_asm_for_ldiv_by_con( jlong divisor ) { 1198 return false; 1199 } 1200 1201 // Register for DIVI projection of divmodI 1202 RegMask Matcher::divI_proj_mask() { 1203 ShouldNotReachHere(); 1204 return RegMask(); 1205 } 1206 1207 // Register for MODI projection of divmodI 1208 RegMask Matcher::modI_proj_mask() { 1209 ShouldNotReachHere(); 1210 return RegMask(); 1211 } 1212 1213 // Register for DIVL projection of divmodL 1214 RegMask Matcher::divL_proj_mask() { 1215 ShouldNotReachHere(); 1216 return RegMask(); 1217 } 1218 1219 // Register for MODL projection of divmodL 1220 RegMask Matcher::modL_proj_mask() { 1221 ShouldNotReachHere(); 1222 return RegMask(); 1223 } 1224 1225 const RegMask Matcher::method_handle_invoke_SP_save_mask() { 1226 return FP_REGP_mask(); 1227 } 1228 1229 bool maybe_far_call(const CallNode *n) { 1230 return !MacroAssembler::_reachable_from_cache(n->as_Call()->entry_point()); 1231 } 1232 1233 bool maybe_far_call(const MachCallNode *n) { 1234 return !MacroAssembler::_reachable_from_cache(n->as_MachCall()->entry_point()); 1235 } 1236 1237 %} 1238 1239 //----------ENCODING BLOCK----------------------------------------------------- 1240 // This block specifies the encoding classes used by the compiler to output 1241 // byte streams. Encoding classes are parameterized macros used by 1242 // Machine Instruction Nodes in order to generate the bit encoding of the 1243 // instruction. Operands specify their base encoding interface with the 1244 // interface keyword. There are currently supported four interfaces, 1245 // REG_INTER, CONST_INTER, MEMORY_INTER, & COND_INTER. REG_INTER causes an 1246 // operand to generate a function which returns its register number when 1247 // queried. CONST_INTER causes an operand to generate a function which 1248 // returns the value of the constant when queried. MEMORY_INTER causes an 1249 // operand to generate four functions which return the Base Register, the 1250 // Index Register, the Scale Value, and the Offset Value of the operand when 1251 // queried. COND_INTER causes an operand to generate six functions which 1252 // return the encoding code (ie - encoding bits for the instruction) 1253 // associated with each basic boolean condition for a conditional instruction. 1254 // 1255 // Instructions specify two basic values for encoding. Again, a function 1256 // is available to check if the constant displacement is an oop. They use the 1257 // ins_encode keyword to specify their encoding classes (which must be 1258 // a sequence of enc_class names, and their parameters, specified in 1259 // the encoding block), and they use the 1260 // opcode keyword to specify, in order, their primary, secondary, and 1261 // tertiary opcode. Only the opcode sections which a particular instruction 1262 // needs for encoding need to be specified. 1263 encode %{ 1264 enc_class call_epilog %{ 1265 // nothing 1266 %} 1267 1268 enc_class Java_To_Runtime (method meth) %{ 1269 // CALL directly to the runtime 1270 emit_call_reloc(cbuf, as_MachCall(), $meth, runtime_call_Relocation::spec()); 1271 %} 1272 1273 enc_class Java_Static_Call (method meth) %{ 1274 // CALL to fixup routine. Fixup routine uses ScopeDesc info to determine 1275 // who we intended to call. 1276 1277 if ( !_method) { 1278 emit_call_reloc(cbuf, as_MachCall(), $meth, runtime_call_Relocation::spec()); 1279 } else { 1280 int method_index = resolved_method_index(cbuf); 1281 RelocationHolder rspec = _optimized_virtual ? opt_virtual_call_Relocation::spec(method_index) 1282 : static_call_Relocation::spec(method_index); 1283 emit_call_reloc(cbuf, as_MachCall(), $meth, rspec); 1284 1285 // Emit stubs for static call. 1286 address stub = CompiledStaticCall::emit_to_interp_stub(cbuf); 1287 if (stub == NULL) { 1288 ciEnv::current()->record_failure("CodeCache is full"); 1289 return; 1290 } 1291 } 1292 %} 1293 1294 enc_class save_last_PC %{ 1295 // preserve mark 1296 address mark = cbuf.insts()->mark(); 1297 debug_only(int off0 = cbuf.insts_size()); 1298 C2_MacroAssembler _masm(&cbuf); 1299 int ret_addr_offset = as_MachCall()->ret_addr_offset(); 1300 __ adr(LR, mark + ret_addr_offset); 1301 __ str(LR, Address(Rthread, JavaThread::last_Java_pc_offset())); 1302 debug_only(int off1 = cbuf.insts_size()); 1303 assert(off1 - off0 == 2 * Assembler::InstructionSize, "correct size prediction"); 1304 // restore mark 1305 cbuf.insts()->set_mark(mark); 1306 %} 1307 1308 enc_class preserve_SP %{ 1309 // preserve mark 1310 address mark = cbuf.insts()->mark(); 1311 debug_only(int off0 = cbuf.insts_size()); 1312 C2_MacroAssembler _masm(&cbuf); 1313 // FP is preserved across all calls, even compiled calls. 1314 // Use it to preserve SP in places where the callee might change the SP. 1315 __ mov(Rmh_SP_save, SP); 1316 debug_only(int off1 = cbuf.insts_size()); 1317 assert(off1 - off0 == 4, "correct size prediction"); 1318 // restore mark 1319 cbuf.insts()->set_mark(mark); 1320 %} 1321 1322 enc_class restore_SP %{ 1323 C2_MacroAssembler _masm(&cbuf); 1324 __ mov(SP, Rmh_SP_save); 1325 %} 1326 1327 enc_class Java_Dynamic_Call (method meth) %{ 1328 C2_MacroAssembler _masm(&cbuf); 1329 Register R8_ic_reg = reg_to_register_object(Matcher::inline_cache_reg_encode()); 1330 assert(R8_ic_reg == Ricklass, "should be"); 1331 __ set_inst_mark(); 1332 __ movw(R8_ic_reg, ((unsigned int)Universe::non_oop_word()) & 0xffff); 1333 __ movt(R8_ic_reg, ((unsigned int)Universe::non_oop_word()) >> 16); 1334 address virtual_call_oop_addr = __ inst_mark(); 1335 // CALL to fixup routine. Fixup routine uses ScopeDesc info to determine 1336 // who we intended to call. 1337 int method_index = resolved_method_index(cbuf); 1338 __ relocate(virtual_call_Relocation::spec(virtual_call_oop_addr, method_index)); 1339 emit_call_reloc(cbuf, as_MachCall(), $meth, RelocationHolder::none); 1340 %} 1341 1342 enc_class LdReplImmI(immI src, regD dst, iRegI tmp, int cnt, int wth) %{ 1343 // FIXME: load from constant table? 1344 // Load a constant replicated "count" times with width "width" 1345 int count = $cnt$$constant; 1346 int width = $wth$$constant; 1347 assert(count*width == 4, "sanity"); 1348 int val = $src$$constant; 1349 if (width < 4) { 1350 int bit_width = width * 8; 1351 val &= (((int)1) << bit_width) - 1; // mask off sign bits 1352 for (int i = 0; i < count - 1; i++) { 1353 val |= (val << bit_width); 1354 } 1355 } 1356 C2_MacroAssembler _masm(&cbuf); 1357 1358 if (val == -1) { 1359 __ mvn($tmp$$Register, 0); 1360 } else if (val == 0) { 1361 __ mov($tmp$$Register, 0); 1362 } else { 1363 __ movw($tmp$$Register, val & 0xffff); 1364 __ movt($tmp$$Register, (unsigned int)val >> 16); 1365 } 1366 __ fmdrr($dst$$FloatRegister, $tmp$$Register, $tmp$$Register); 1367 %} 1368 1369 enc_class LdReplImmF(immF src, regD dst, iRegI tmp) %{ 1370 // Replicate float con 2 times and pack into vector (8 bytes) in regD. 1371 float fval = $src$$constant; 1372 int val = *((int*)&fval); 1373 C2_MacroAssembler _masm(&cbuf); 1374 1375 if (val == -1) { 1376 __ mvn($tmp$$Register, 0); 1377 } else if (val == 0) { 1378 __ mov($tmp$$Register, 0); 1379 } else { 1380 __ movw($tmp$$Register, val & 0xffff); 1381 __ movt($tmp$$Register, (unsigned int)val >> 16); 1382 } 1383 __ fmdrr($dst$$FloatRegister, $tmp$$Register, $tmp$$Register); 1384 %} 1385 1386 enc_class enc_String_Compare(R0RegP str1, R1RegP str2, R2RegI cnt1, R3RegI cnt2, iRegI result, iRegI tmp1, iRegI tmp2) %{ 1387 Label Ldone, Lloop; 1388 C2_MacroAssembler _masm(&cbuf); 1389 1390 Register str1_reg = $str1$$Register; 1391 Register str2_reg = $str2$$Register; 1392 Register cnt1_reg = $cnt1$$Register; // int 1393 Register cnt2_reg = $cnt2$$Register; // int 1394 Register tmp1_reg = $tmp1$$Register; 1395 Register tmp2_reg = $tmp2$$Register; 1396 Register result_reg = $result$$Register; 1397 1398 assert_different_registers(str1_reg, str2_reg, cnt1_reg, cnt2_reg, tmp1_reg, tmp2_reg); 1399 1400 // Compute the minimum of the string lengths(str1_reg) and the 1401 // difference of the string lengths (stack) 1402 1403 // See if the lengths are different, and calculate min in str1_reg. 1404 // Stash diff in tmp2 in case we need it for a tie-breaker. 1405 __ subs_32(tmp2_reg, cnt1_reg, cnt2_reg); 1406 __ mov(cnt1_reg, AsmOperand(cnt1_reg, lsl, exact_log2(sizeof(jchar)))); // scale the limit 1407 __ mov(cnt1_reg, AsmOperand(cnt2_reg, lsl, exact_log2(sizeof(jchar))), pl); // scale the limit 1408 1409 // reallocate cnt1_reg, cnt2_reg, result_reg 1410 // Note: limit_reg holds the string length pre-scaled by 2 1411 Register limit_reg = cnt1_reg; 1412 Register chr2_reg = cnt2_reg; 1413 Register chr1_reg = tmp1_reg; 1414 // str{12} are the base pointers 1415 1416 // Is the minimum length zero? 1417 __ cmp_32(limit_reg, 0); 1418 if (result_reg != tmp2_reg) { 1419 __ mov(result_reg, tmp2_reg, eq); 1420 } 1421 __ b(Ldone, eq); 1422 1423 // Load first characters 1424 __ ldrh(chr1_reg, Address(str1_reg, 0)); 1425 __ ldrh(chr2_reg, Address(str2_reg, 0)); 1426 1427 // Compare first characters 1428 __ subs(chr1_reg, chr1_reg, chr2_reg); 1429 if (result_reg != chr1_reg) { 1430 __ mov(result_reg, chr1_reg, ne); 1431 } 1432 __ b(Ldone, ne); 1433 1434 { 1435 // Check after comparing first character to see if strings are equivalent 1436 // Check if the strings start at same location 1437 __ cmp(str1_reg, str2_reg); 1438 // Check if the length difference is zero 1439 __ cond_cmp(tmp2_reg, 0, eq); 1440 __ mov(result_reg, 0, eq); // result is zero 1441 __ b(Ldone, eq); 1442 // Strings might not be equal 1443 } 1444 1445 __ subs(chr1_reg, limit_reg, 1 * sizeof(jchar)); 1446 if (result_reg != tmp2_reg) { 1447 __ mov(result_reg, tmp2_reg, eq); 1448 } 1449 __ b(Ldone, eq); 1450 1451 // Shift str1_reg and str2_reg to the end of the arrays, negate limit 1452 __ add(str1_reg, str1_reg, limit_reg); 1453 __ add(str2_reg, str2_reg, limit_reg); 1454 __ neg(limit_reg, chr1_reg); // limit = -(limit-2) 1455 1456 // Compare the rest of the characters 1457 __ bind(Lloop); 1458 __ ldrh(chr1_reg, Address(str1_reg, limit_reg)); 1459 __ ldrh(chr2_reg, Address(str2_reg, limit_reg)); 1460 __ subs(chr1_reg, chr1_reg, chr2_reg); 1461 if (result_reg != chr1_reg) { 1462 __ mov(result_reg, chr1_reg, ne); 1463 } 1464 __ b(Ldone, ne); 1465 1466 __ adds(limit_reg, limit_reg, sizeof(jchar)); 1467 __ b(Lloop, ne); 1468 1469 // If strings are equal up to min length, return the length difference. 1470 if (result_reg != tmp2_reg) { 1471 __ mov(result_reg, tmp2_reg); 1472 } 1473 1474 // Otherwise, return the difference between the first mismatched chars. 1475 __ bind(Ldone); 1476 %} 1477 1478 enc_class enc_String_Equals(R0RegP str1, R1RegP str2, R2RegI cnt, iRegI result, iRegI tmp1, iRegI tmp2) %{ 1479 Label Lchar, Lchar_loop, Ldone, Lequal; 1480 C2_MacroAssembler _masm(&cbuf); 1481 1482 Register str1_reg = $str1$$Register; 1483 Register str2_reg = $str2$$Register; 1484 Register cnt_reg = $cnt$$Register; // int 1485 Register tmp1_reg = $tmp1$$Register; 1486 Register tmp2_reg = $tmp2$$Register; 1487 Register result_reg = $result$$Register; 1488 1489 assert_different_registers(str1_reg, str2_reg, cnt_reg, tmp1_reg, tmp2_reg, result_reg); 1490 1491 __ cmp(str1_reg, str2_reg); //same char[] ? 1492 __ b(Lequal, eq); 1493 1494 __ cbz_32(cnt_reg, Lequal); // count == 0 1495 1496 //rename registers 1497 Register limit_reg = cnt_reg; 1498 Register chr1_reg = tmp1_reg; 1499 Register chr2_reg = tmp2_reg; 1500 1501 __ logical_shift_left(limit_reg, limit_reg, exact_log2(sizeof(jchar))); 1502 1503 //check for alignment and position the pointers to the ends 1504 __ orr(chr1_reg, str1_reg, str2_reg); 1505 __ tst(chr1_reg, 0x3); 1506 1507 // notZero means at least one not 4-byte aligned. 1508 // We could optimize the case when both arrays are not aligned 1509 // but it is not frequent case and it requires additional checks. 1510 __ b(Lchar, ne); 1511 1512 // Compare char[] arrays aligned to 4 bytes. 1513 __ char_arrays_equals(str1_reg, str2_reg, limit_reg, result_reg, 1514 chr1_reg, chr2_reg, Ldone); 1515 1516 __ b(Lequal); // equal 1517 1518 // char by char compare 1519 __ bind(Lchar); 1520 __ mov(result_reg, 0); 1521 __ add(str1_reg, limit_reg, str1_reg); 1522 __ add(str2_reg, limit_reg, str2_reg); 1523 __ neg(limit_reg, limit_reg); //negate count 1524 1525 // Lchar_loop 1526 __ bind(Lchar_loop); 1527 __ ldrh(chr1_reg, Address(str1_reg, limit_reg)); 1528 __ ldrh(chr2_reg, Address(str2_reg, limit_reg)); 1529 __ cmp(chr1_reg, chr2_reg); 1530 __ b(Ldone, ne); 1531 __ adds(limit_reg, limit_reg, sizeof(jchar)); 1532 __ b(Lchar_loop, ne); 1533 1534 __ bind(Lequal); 1535 __ mov(result_reg, 1); //equal 1536 1537 __ bind(Ldone); 1538 %} 1539 1540 enc_class enc_Array_Equals(R0RegP ary1, R1RegP ary2, iRegI tmp1, iRegI tmp2, iRegI tmp3, iRegI result) %{ 1541 Label Ldone, Lloop, Lequal; 1542 C2_MacroAssembler _masm(&cbuf); 1543 1544 Register ary1_reg = $ary1$$Register; 1545 Register ary2_reg = $ary2$$Register; 1546 Register tmp1_reg = $tmp1$$Register; 1547 Register tmp2_reg = $tmp2$$Register; 1548 Register tmp3_reg = $tmp3$$Register; 1549 Register result_reg = $result$$Register; 1550 1551 assert_different_registers(ary1_reg, ary2_reg, tmp1_reg, tmp2_reg, tmp3_reg, result_reg); 1552 1553 int length_offset = arrayOopDesc::length_offset_in_bytes(); 1554 int base_offset = arrayOopDesc::base_offset_in_bytes(T_CHAR); 1555 1556 // return true if the same array 1557 __ teq(ary1_reg, ary2_reg); 1558 __ mov(result_reg, 1, eq); 1559 __ b(Ldone, eq); // equal 1560 1561 __ tst(ary1_reg, ary1_reg); 1562 __ mov(result_reg, 0, eq); 1563 __ b(Ldone, eq); // not equal 1564 1565 __ tst(ary2_reg, ary2_reg); 1566 __ mov(result_reg, 0, eq); 1567 __ b(Ldone, eq); // not equal 1568 1569 //load the lengths of arrays 1570 __ ldr_s32(tmp1_reg, Address(ary1_reg, length_offset)); // int 1571 __ ldr_s32(tmp2_reg, Address(ary2_reg, length_offset)); // int 1572 1573 // return false if the two arrays are not equal length 1574 __ teq_32(tmp1_reg, tmp2_reg); 1575 __ mov(result_reg, 0, ne); 1576 __ b(Ldone, ne); // not equal 1577 1578 __ tst(tmp1_reg, tmp1_reg); 1579 __ mov(result_reg, 1, eq); 1580 __ b(Ldone, eq); // zero-length arrays are equal 1581 1582 // load array addresses 1583 __ add(ary1_reg, ary1_reg, base_offset); 1584 __ add(ary2_reg, ary2_reg, base_offset); 1585 1586 // renaming registers 1587 Register chr1_reg = tmp3_reg; // for characters in ary1 1588 Register chr2_reg = tmp2_reg; // for characters in ary2 1589 Register limit_reg = tmp1_reg; // length 1590 1591 // set byte count 1592 __ logical_shift_left_32(limit_reg, limit_reg, exact_log2(sizeof(jchar))); 1593 1594 // Compare char[] arrays aligned to 4 bytes. 1595 __ char_arrays_equals(ary1_reg, ary2_reg, limit_reg, result_reg, 1596 chr1_reg, chr2_reg, Ldone); 1597 __ bind(Lequal); 1598 __ mov(result_reg, 1); //equal 1599 1600 __ bind(Ldone); 1601 %} 1602 %} 1603 1604 //----------FRAME-------------------------------------------------------------- 1605 // Definition of frame structure and management information. 1606 // 1607 // S T A C K L A Y O U T Allocators stack-slot number 1608 // | (to get allocators register number 1609 // G Owned by | | v add VMRegImpl::stack0) 1610 // r CALLER | | 1611 // o | +--------+ pad to even-align allocators stack-slot 1612 // w V | pad0 | numbers; owned by CALLER 1613 // t -----------+--------+----> Matcher::_in_arg_limit, unaligned 1614 // h ^ | in | 5 1615 // | | args | 4 Holes in incoming args owned by SELF 1616 // | | | | 3 1617 // | | +--------+ 1618 // V | | old out| Empty on Intel, window on Sparc 1619 // | old |preserve| Must be even aligned. 1620 // | SP-+--------+----> Matcher::_old_SP, 8 (or 16 in LP64)-byte aligned 1621 // | | in | 3 area for Intel ret address 1622 // Owned by |preserve| Empty on Sparc. 1623 // SELF +--------+ 1624 // | | pad2 | 2 pad to align old SP 1625 // | +--------+ 1 1626 // | | locks | 0 1627 // | +--------+----> VMRegImpl::stack0, 8 (or 16 in LP64)-byte aligned 1628 // | | pad1 | 11 pad to align new SP 1629 // | +--------+ 1630 // | | | 10 1631 // | | spills | 9 spills 1632 // V | | 8 (pad0 slot for callee) 1633 // -----------+--------+----> Matcher::_out_arg_limit, unaligned 1634 // ^ | out | 7 1635 // | | args | 6 Holes in outgoing args owned by CALLEE 1636 // Owned by +--------+ 1637 // CALLEE | new out| 6 Empty on Intel, window on Sparc 1638 // | new |preserve| Must be even-aligned. 1639 // | SP-+--------+----> Matcher::_new_SP, even aligned 1640 // | | | 1641 // 1642 // Note 1: Only region 8-11 is determined by the allocator. Region 0-5 is 1643 // known from SELF's arguments and the Java calling convention. 1644 // Region 6-7 is determined per call site. 1645 // Note 2: If the calling convention leaves holes in the incoming argument 1646 // area, those holes are owned by SELF. Holes in the outgoing area 1647 // are owned by the CALLEE. Holes should not be nessecary in the 1648 // incoming area, as the Java calling convention is completely under 1649 // the control of the AD file. Doubles can be sorted and packed to 1650 // avoid holes. Holes in the outgoing arguments may be nessecary for 1651 // varargs C calling conventions. 1652 // Note 3: Region 0-3 is even aligned, with pad2 as needed. Region 3-5 is 1653 // even aligned with pad0 as needed. 1654 // Region 6 is even aligned. Region 6-7 is NOT even aligned; 1655 // region 6-11 is even aligned; it may be padded out more so that 1656 // the region from SP to FP meets the minimum stack alignment. 1657 1658 frame %{ 1659 // What direction does stack grow in (assumed to be same for native & Java) 1660 stack_direction(TOWARDS_LOW); 1661 1662 // These two registers define part of the calling convention 1663 // between compiled code and the interpreter. 1664 inline_cache_reg(R_Ricklass); // Inline Cache Register or Method* for I2C 1665 interpreter_method_oop_reg(R_Rmethod); // Method Oop Register when calling interpreter 1666 1667 // Optional: name the operand used by cisc-spilling to access [stack_pointer + offset] 1668 cisc_spilling_operand_name(indOffset); 1669 1670 // Number of stack slots consumed by a Monitor enter 1671 sync_stack_slots(1 * VMRegImpl::slots_per_word); 1672 1673 // Compiled code's Frame Pointer 1674 frame_pointer(R_R13); 1675 1676 // Stack alignment requirement 1677 stack_alignment(StackAlignmentInBytes); 1678 // LP64: Alignment size in bytes (128-bit -> 16 bytes) 1679 // !LP64: Alignment size in bytes (64-bit -> 8 bytes) 1680 1681 // Number of stack slots between incoming argument block and the start of 1682 // a new frame. The PROLOG must add this many slots to the stack. The 1683 // EPILOG must remove this many slots. 1684 // FP + LR 1685 in_preserve_stack_slots(2 * VMRegImpl::slots_per_word); 1686 1687 // Number of outgoing stack slots killed above the out_preserve_stack_slots 1688 // for calls to C. Supports the var-args backing area for register parms. 1689 // ADLC doesn't support parsing expressions, so I folded the math by hand. 1690 varargs_C_out_slots_killed( 0); 1691 1692 // The after-PROLOG location of the return address. Location of 1693 // return address specifies a type (REG or STACK) and a number 1694 // representing the register number (i.e. - use a register name) or 1695 // stack slot. 1696 // Ret Addr is on stack in slot 0 if no locks or verification or alignment. 1697 // Otherwise, it is above the locks and verification slot and alignment word 1698 return_addr(STACK - 1*VMRegImpl::slots_per_word + 1699 align_up((Compile::current()->in_preserve_stack_slots() + 1700 Compile::current()->fixed_slots()), 1701 stack_alignment_in_slots())); 1702 1703 // Body of function which returns an OptoRegs array locating 1704 // arguments either in registers or in stack slots for calling 1705 // java 1706 calling_convention %{ 1707 (void) SharedRuntime::java_calling_convention(sig_bt, regs, length, is_outgoing); 1708 1709 %} 1710 1711 // Body of function which returns an OptoRegs array locating 1712 // arguments either in registers or in stack slots for callin 1713 // C. 1714 c_calling_convention %{ 1715 // This is obviously always outgoing 1716 (void) SharedRuntime::c_calling_convention(sig_bt, regs, /*regs2=*/NULL, length); 1717 %} 1718 1719 // Location of compiled Java return values. Same as C 1720 return_value %{ 1721 return c2::return_value(ideal_reg); 1722 %} 1723 1724 %} 1725 1726 //----------ATTRIBUTES--------------------------------------------------------- 1727 //----------Instruction Attributes--------------------------------------------- 1728 ins_attrib ins_cost(DEFAULT_COST); // Required cost attribute 1729 ins_attrib ins_size(32); // Required size attribute (in bits) 1730 ins_attrib ins_short_branch(0); // Required flag: is this instruction a 1731 // non-matching short branch variant of some 1732 // long branch? 1733 1734 //----------OPERANDS----------------------------------------------------------- 1735 // Operand definitions must precede instruction definitions for correct parsing 1736 // in the ADLC because operands constitute user defined types which are used in 1737 // instruction definitions. 1738 1739 //----------Simple Operands---------------------------------------------------- 1740 // Immediate Operands 1741 // Integer Immediate: 32-bit 1742 operand immI() %{ 1743 match(ConI); 1744 1745 op_cost(0); 1746 // formats are generated automatically for constants and base registers 1747 format %{ %} 1748 interface(CONST_INTER); 1749 %} 1750 1751 // Integer Immediate: 8-bit unsigned - for VMOV 1752 operand immU8() %{ 1753 predicate(0 <= n->get_int() && (n->get_int() <= 255)); 1754 match(ConI); 1755 op_cost(0); 1756 1757 format %{ %} 1758 interface(CONST_INTER); 1759 %} 1760 1761 // Integer Immediate: 16-bit 1762 operand immI16() %{ 1763 predicate((n->get_int() >> 16) == 0 && VM_Version::supports_movw()); 1764 match(ConI); 1765 op_cost(0); 1766 1767 format %{ %} 1768 interface(CONST_INTER); 1769 %} 1770 1771 // Integer Immediate: offset for half and double word loads and stores 1772 operand immIHD() %{ 1773 predicate(is_memoryHD(n->get_int())); 1774 match(ConI); 1775 op_cost(0); 1776 format %{ %} 1777 interface(CONST_INTER); 1778 %} 1779 1780 // Integer Immediate: offset for fp loads and stores 1781 operand immIFP() %{ 1782 predicate(is_memoryfp(n->get_int()) && ((n->get_int() & 3) == 0)); 1783 match(ConI); 1784 op_cost(0); 1785 1786 format %{ %} 1787 interface(CONST_INTER); 1788 %} 1789 1790 // Valid scale values for addressing modes and shifts 1791 operand immU5() %{ 1792 predicate(0 <= n->get_int() && (n->get_int() <= 31)); 1793 match(ConI); 1794 op_cost(0); 1795 1796 format %{ %} 1797 interface(CONST_INTER); 1798 %} 1799 1800 // Integer Immediate: 6-bit 1801 operand immU6Big() %{ 1802 predicate(n->get_int() >= 32 && n->get_int() <= 63); 1803 match(ConI); 1804 op_cost(0); 1805 format %{ %} 1806 interface(CONST_INTER); 1807 %} 1808 1809 // Integer Immediate: 0-bit 1810 operand immI0() %{ 1811 predicate(n->get_int() == 0); 1812 match(ConI); 1813 op_cost(0); 1814 1815 format %{ %} 1816 interface(CONST_INTER); 1817 %} 1818 1819 // Integer Immediate: the value 1 1820 operand immI_1() %{ 1821 predicate(n->get_int() == 1); 1822 match(ConI); 1823 op_cost(0); 1824 1825 format %{ %} 1826 interface(CONST_INTER); 1827 %} 1828 1829 // Integer Immediate: the value 2 1830 operand immI_2() %{ 1831 predicate(n->get_int() == 2); 1832 match(ConI); 1833 op_cost(0); 1834 1835 format %{ %} 1836 interface(CONST_INTER); 1837 %} 1838 1839 // Integer Immediate: the value 3 1840 operand immI_3() %{ 1841 predicate(n->get_int() == 3); 1842 match(ConI); 1843 op_cost(0); 1844 1845 format %{ %} 1846 interface(CONST_INTER); 1847 %} 1848 1849 // Integer Immediate: the value 4 1850 operand immI_4() %{ 1851 predicate(n->get_int() == 4); 1852 match(ConI); 1853 op_cost(0); 1854 1855 format %{ %} 1856 interface(CONST_INTER); 1857 %} 1858 1859 // Integer Immediate: the value 8 1860 operand immI_8() %{ 1861 predicate(n->get_int() == 8); 1862 match(ConI); 1863 op_cost(0); 1864 1865 format %{ %} 1866 interface(CONST_INTER); 1867 %} 1868 1869 // Int Immediate non-negative 1870 operand immU31() 1871 %{ 1872 predicate(n->get_int() >= 0); 1873 match(ConI); 1874 1875 op_cost(0); 1876 format %{ %} 1877 interface(CONST_INTER); 1878 %} 1879 1880 // Integer Immediate: the values 32-63 1881 operand immI_32_63() %{ 1882 predicate(n->get_int() >= 32 && n->get_int() <= 63); 1883 match(ConI); 1884 op_cost(0); 1885 1886 format %{ %} 1887 interface(CONST_INTER); 1888 %} 1889 1890 // Immediates for special shifts (sign extend) 1891 1892 // Integer Immediate: the value 16 1893 operand immI_16() %{ 1894 predicate(n->get_int() == 16); 1895 match(ConI); 1896 op_cost(0); 1897 1898 format %{ %} 1899 interface(CONST_INTER); 1900 %} 1901 1902 // Integer Immediate: the value 24 1903 operand immI_24() %{ 1904 predicate(n->get_int() == 24); 1905 match(ConI); 1906 op_cost(0); 1907 1908 format %{ %} 1909 interface(CONST_INTER); 1910 %} 1911 1912 // Integer Immediate: the value 255 1913 operand immI_255() %{ 1914 predicate( n->get_int() == 255 ); 1915 match(ConI); 1916 op_cost(0); 1917 1918 format %{ %} 1919 interface(CONST_INTER); 1920 %} 1921 1922 // Integer Immediate: the value 65535 1923 operand immI_65535() %{ 1924 predicate(n->get_int() == 65535); 1925 match(ConI); 1926 op_cost(0); 1927 1928 format %{ %} 1929 interface(CONST_INTER); 1930 %} 1931 1932 // Integer Immediates for arithmetic instructions 1933 1934 operand aimmI() %{ 1935 predicate(is_aimm(n->get_int())); 1936 match(ConI); 1937 op_cost(0); 1938 1939 format %{ %} 1940 interface(CONST_INTER); 1941 %} 1942 1943 operand aimmIneg() %{ 1944 predicate(is_aimm(-n->get_int())); 1945 match(ConI); 1946 op_cost(0); 1947 1948 format %{ %} 1949 interface(CONST_INTER); 1950 %} 1951 1952 operand aimmU31() %{ 1953 predicate((0 <= n->get_int()) && is_aimm(n->get_int())); 1954 match(ConI); 1955 op_cost(0); 1956 1957 format %{ %} 1958 interface(CONST_INTER); 1959 %} 1960 1961 // Integer Immediates for logical instructions 1962 1963 operand limmI() %{ 1964 predicate(is_limmI(n->get_int())); 1965 match(ConI); 1966 op_cost(0); 1967 1968 format %{ %} 1969 interface(CONST_INTER); 1970 %} 1971 1972 operand limmIlow8() %{ 1973 predicate(is_limmI_low(n->get_int(), 8)); 1974 match(ConI); 1975 op_cost(0); 1976 1977 format %{ %} 1978 interface(CONST_INTER); 1979 %} 1980 1981 operand limmU31() %{ 1982 predicate(0 <= n->get_int() && is_limmI(n->get_int())); 1983 match(ConI); 1984 op_cost(0); 1985 1986 format %{ %} 1987 interface(CONST_INTER); 1988 %} 1989 1990 operand limmIn() %{ 1991 predicate(is_limmI(~n->get_int())); 1992 match(ConI); 1993 op_cost(0); 1994 1995 format %{ %} 1996 interface(CONST_INTER); 1997 %} 1998 1999 2000 // Long Immediate: the value FF 2001 operand immL_FF() %{ 2002 predicate( n->get_long() == 0xFFL ); 2003 match(ConL); 2004 op_cost(0); 2005 2006 format %{ %} 2007 interface(CONST_INTER); 2008 %} 2009 2010 // Long Immediate: the value FFFF 2011 operand immL_FFFF() %{ 2012 predicate( n->get_long() == 0xFFFFL ); 2013 match(ConL); 2014 op_cost(0); 2015 2016 format %{ %} 2017 interface(CONST_INTER); 2018 %} 2019 2020 // Pointer Immediate: 32 or 64-bit 2021 operand immP() %{ 2022 match(ConP); 2023 2024 op_cost(5); 2025 // formats are generated automatically for constants and base registers 2026 format %{ %} 2027 interface(CONST_INTER); 2028 %} 2029 2030 operand immP0() %{ 2031 predicate(n->get_ptr() == 0); 2032 match(ConP); 2033 op_cost(0); 2034 2035 format %{ %} 2036 interface(CONST_INTER); 2037 %} 2038 2039 // Pointer Immediate 2040 operand immN() 2041 %{ 2042 match(ConN); 2043 2044 op_cost(10); 2045 format %{ %} 2046 interface(CONST_INTER); 2047 %} 2048 2049 operand immNKlass() 2050 %{ 2051 match(ConNKlass); 2052 2053 op_cost(10); 2054 format %{ %} 2055 interface(CONST_INTER); 2056 %} 2057 2058 // NULL Pointer Immediate 2059 operand immN0() 2060 %{ 2061 predicate(n->get_narrowcon() == 0); 2062 match(ConN); 2063 2064 op_cost(0); 2065 format %{ %} 2066 interface(CONST_INTER); 2067 %} 2068 2069 operand immL() %{ 2070 match(ConL); 2071 op_cost(40); 2072 // formats are generated automatically for constants and base registers 2073 format %{ %} 2074 interface(CONST_INTER); 2075 %} 2076 2077 operand immL0() %{ 2078 predicate(n->get_long() == 0L); 2079 match(ConL); 2080 op_cost(0); 2081 // formats are generated automatically for constants and base registers 2082 format %{ %} 2083 interface(CONST_INTER); 2084 %} 2085 2086 // Long Immediate: 16-bit 2087 operand immL16() %{ 2088 predicate(n->get_long() >= 0 && n->get_long() < (1<<16) && VM_Version::supports_movw()); 2089 match(ConL); 2090 op_cost(0); 2091 2092 format %{ %} 2093 interface(CONST_INTER); 2094 %} 2095 2096 // Long Immediate: low 32-bit mask 2097 operand immL_32bits() %{ 2098 predicate(n->get_long() == 0xFFFFFFFFL); 2099 match(ConL); 2100 op_cost(0); 2101 2102 format %{ %} 2103 interface(CONST_INTER); 2104 %} 2105 2106 // Double Immediate 2107 operand immD() %{ 2108 match(ConD); 2109 2110 op_cost(40); 2111 format %{ %} 2112 interface(CONST_INTER); 2113 %} 2114 2115 // Double Immediate: +0.0d. 2116 operand immD0() %{ 2117 predicate(jlong_cast(n->getd()) == 0); 2118 2119 match(ConD); 2120 op_cost(0); 2121 format %{ %} 2122 interface(CONST_INTER); 2123 %} 2124 2125 operand imm8D() %{ 2126 predicate(Assembler::double_num(n->getd()).can_be_imm8()); 2127 match(ConD); 2128 2129 op_cost(0); 2130 format %{ %} 2131 interface(CONST_INTER); 2132 %} 2133 2134 // Float Immediate 2135 operand immF() %{ 2136 match(ConF); 2137 2138 op_cost(20); 2139 format %{ %} 2140 interface(CONST_INTER); 2141 %} 2142 2143 // Float Immediate: +0.0f 2144 operand immF0() %{ 2145 predicate(jint_cast(n->getf()) == 0); 2146 match(ConF); 2147 2148 op_cost(0); 2149 format %{ %} 2150 interface(CONST_INTER); 2151 %} 2152 2153 // Float Immediate: encoded as 8 bits 2154 operand imm8F() %{ 2155 predicate(Assembler::float_num(n->getf()).can_be_imm8()); 2156 match(ConF); 2157 2158 op_cost(0); 2159 format %{ %} 2160 interface(CONST_INTER); 2161 %} 2162 2163 // Integer Register Operands 2164 // Integer Register 2165 operand iRegI() %{ 2166 constraint(ALLOC_IN_RC(int_reg)); 2167 match(RegI); 2168 match(R0RegI); 2169 match(R1RegI); 2170 match(R2RegI); 2171 match(R3RegI); 2172 match(R12RegI); 2173 2174 format %{ %} 2175 interface(REG_INTER); 2176 %} 2177 2178 // Pointer Register 2179 operand iRegP() %{ 2180 constraint(ALLOC_IN_RC(ptr_reg)); 2181 match(RegP); 2182 match(R0RegP); 2183 match(R1RegP); 2184 match(R2RegP); 2185 match(RExceptionRegP); 2186 match(R8RegP); 2187 match(R9RegP); 2188 match(RthreadRegP); // FIXME: move to sp_ptr_RegP? 2189 match(R12RegP); 2190 match(LRRegP); 2191 2192 match(sp_ptr_RegP); 2193 match(store_ptr_RegP); 2194 2195 format %{ %} 2196 interface(REG_INTER); 2197 %} 2198 2199 // GPRs + Rthread + SP 2200 operand sp_ptr_RegP() %{ 2201 constraint(ALLOC_IN_RC(sp_ptr_reg)); 2202 match(RegP); 2203 match(iRegP); 2204 match(SPRegP); // FIXME: check cost 2205 2206 format %{ %} 2207 interface(REG_INTER); 2208 %} 2209 2210 2211 operand R0RegP() %{ 2212 constraint(ALLOC_IN_RC(R0_regP)); 2213 match(iRegP); 2214 2215 format %{ %} 2216 interface(REG_INTER); 2217 %} 2218 2219 operand R1RegP() %{ 2220 constraint(ALLOC_IN_RC(R1_regP)); 2221 match(iRegP); 2222 2223 format %{ %} 2224 interface(REG_INTER); 2225 %} 2226 2227 operand R8RegP() %{ 2228 constraint(ALLOC_IN_RC(R8_regP)); 2229 match(iRegP); 2230 2231 format %{ %} 2232 interface(REG_INTER); 2233 %} 2234 2235 operand R9RegP() %{ 2236 constraint(ALLOC_IN_RC(R9_regP)); 2237 match(iRegP); 2238 2239 format %{ %} 2240 interface(REG_INTER); 2241 %} 2242 2243 operand R12RegP() %{ 2244 constraint(ALLOC_IN_RC(R12_regP)); 2245 match(iRegP); 2246 2247 format %{ %} 2248 interface(REG_INTER); 2249 %} 2250 2251 operand R2RegP() %{ 2252 constraint(ALLOC_IN_RC(R2_regP)); 2253 match(iRegP); 2254 2255 format %{ %} 2256 interface(REG_INTER); 2257 %} 2258 2259 operand RExceptionRegP() %{ 2260 constraint(ALLOC_IN_RC(Rexception_regP)); 2261 match(iRegP); 2262 2263 format %{ %} 2264 interface(REG_INTER); 2265 %} 2266 2267 operand RthreadRegP() %{ 2268 constraint(ALLOC_IN_RC(Rthread_regP)); 2269 match(iRegP); 2270 2271 format %{ %} 2272 interface(REG_INTER); 2273 %} 2274 2275 operand IPRegP() %{ 2276 constraint(ALLOC_IN_RC(IP_regP)); 2277 match(iRegP); 2278 2279 format %{ %} 2280 interface(REG_INTER); 2281 %} 2282 2283 operand SPRegP() %{ 2284 constraint(ALLOC_IN_RC(SP_regP)); 2285 match(iRegP); 2286 2287 format %{ %} 2288 interface(REG_INTER); 2289 %} 2290 2291 operand LRRegP() %{ 2292 constraint(ALLOC_IN_RC(LR_regP)); 2293 match(iRegP); 2294 2295 format %{ %} 2296 interface(REG_INTER); 2297 %} 2298 2299 operand R0RegI() %{ 2300 constraint(ALLOC_IN_RC(R0_regI)); 2301 match(iRegI); 2302 2303 format %{ %} 2304 interface(REG_INTER); 2305 %} 2306 2307 operand R1RegI() %{ 2308 constraint(ALLOC_IN_RC(R1_regI)); 2309 match(iRegI); 2310 2311 format %{ %} 2312 interface(REG_INTER); 2313 %} 2314 2315 operand R2RegI() %{ 2316 constraint(ALLOC_IN_RC(R2_regI)); 2317 match(iRegI); 2318 2319 format %{ %} 2320 interface(REG_INTER); 2321 %} 2322 2323 operand R3RegI() %{ 2324 constraint(ALLOC_IN_RC(R3_regI)); 2325 match(iRegI); 2326 2327 format %{ %} 2328 interface(REG_INTER); 2329 %} 2330 2331 operand R12RegI() %{ 2332 constraint(ALLOC_IN_RC(R12_regI)); 2333 match(iRegI); 2334 2335 format %{ %} 2336 interface(REG_INTER); 2337 %} 2338 2339 // Long Register 2340 operand iRegL() %{ 2341 constraint(ALLOC_IN_RC(long_reg)); 2342 match(RegL); 2343 match(R0R1RegL); 2344 match(R2R3RegL); 2345 //match(iRegLex); 2346 2347 format %{ %} 2348 interface(REG_INTER); 2349 %} 2350 2351 operand iRegLd() %{ 2352 constraint(ALLOC_IN_RC(long_reg_align)); 2353 match(iRegL); // FIXME: allows unaligned R11/R12? 2354 2355 format %{ %} 2356 interface(REG_INTER); 2357 %} 2358 2359 // first long arg, or return value 2360 operand R0R1RegL() %{ 2361 constraint(ALLOC_IN_RC(R0R1_regL)); 2362 match(iRegL); 2363 2364 format %{ %} 2365 interface(REG_INTER); 2366 %} 2367 2368 operand R2R3RegL() %{ 2369 constraint(ALLOC_IN_RC(R2R3_regL)); 2370 match(iRegL); 2371 2372 format %{ %} 2373 interface(REG_INTER); 2374 %} 2375 2376 // Condition Code Flag Register 2377 operand flagsReg() %{ 2378 constraint(ALLOC_IN_RC(int_flags)); 2379 match(RegFlags); 2380 2381 format %{ "apsr" %} 2382 interface(REG_INTER); 2383 %} 2384 2385 // Result of compare to 0 (TST) 2386 operand flagsReg_EQNELTGE() %{ 2387 constraint(ALLOC_IN_RC(int_flags)); 2388 match(RegFlags); 2389 2390 format %{ "apsr_EQNELTGE" %} 2391 interface(REG_INTER); 2392 %} 2393 2394 // Condition Code Register, unsigned comparisons. 2395 operand flagsRegU() %{ 2396 constraint(ALLOC_IN_RC(int_flags)); 2397 match(RegFlags); 2398 #ifdef TODO 2399 match(RegFlagsP); 2400 #endif 2401 2402 format %{ "apsr_U" %} 2403 interface(REG_INTER); 2404 %} 2405 2406 // Condition Code Register, pointer comparisons. 2407 operand flagsRegP() %{ 2408 constraint(ALLOC_IN_RC(int_flags)); 2409 match(RegFlags); 2410 2411 format %{ "apsr_P" %} 2412 interface(REG_INTER); 2413 %} 2414 2415 // Condition Code Register, long comparisons. 2416 operand flagsRegL_LTGE() %{ 2417 constraint(ALLOC_IN_RC(int_flags)); 2418 match(RegFlags); 2419 2420 format %{ "apsr_L_LTGE" %} 2421 interface(REG_INTER); 2422 %} 2423 2424 operand flagsRegL_EQNE() %{ 2425 constraint(ALLOC_IN_RC(int_flags)); 2426 match(RegFlags); 2427 2428 format %{ "apsr_L_EQNE" %} 2429 interface(REG_INTER); 2430 %} 2431 2432 operand flagsRegL_LEGT() %{ 2433 constraint(ALLOC_IN_RC(int_flags)); 2434 match(RegFlags); 2435 2436 format %{ "apsr_L_LEGT" %} 2437 interface(REG_INTER); 2438 %} 2439 2440 operand flagsRegUL_LTGE() %{ 2441 constraint(ALLOC_IN_RC(int_flags)); 2442 match(RegFlags); 2443 2444 format %{ "apsr_UL_LTGE" %} 2445 interface(REG_INTER); 2446 %} 2447 2448 operand flagsRegUL_EQNE() %{ 2449 constraint(ALLOC_IN_RC(int_flags)); 2450 match(RegFlags); 2451 2452 format %{ "apsr_UL_EQNE" %} 2453 interface(REG_INTER); 2454 %} 2455 2456 operand flagsRegUL_LEGT() %{ 2457 constraint(ALLOC_IN_RC(int_flags)); 2458 match(RegFlags); 2459 2460 format %{ "apsr_UL_LEGT" %} 2461 interface(REG_INTER); 2462 %} 2463 2464 // Condition Code Register, floating comparisons, unordered same as "less". 2465 operand flagsRegF() %{ 2466 constraint(ALLOC_IN_RC(float_flags)); 2467 match(RegFlags); 2468 2469 format %{ "fpscr_F" %} 2470 interface(REG_INTER); 2471 %} 2472 2473 // Vectors 2474 operand vecD() %{ 2475 constraint(ALLOC_IN_RC(actual_dflt_reg)); 2476 match(VecD); 2477 2478 format %{ %} 2479 interface(REG_INTER); 2480 %} 2481 2482 operand vecX() %{ 2483 constraint(ALLOC_IN_RC(vectorx_reg)); 2484 match(VecX); 2485 2486 format %{ %} 2487 interface(REG_INTER); 2488 %} 2489 2490 operand regD() %{ 2491 constraint(ALLOC_IN_RC(actual_dflt_reg)); 2492 match(RegD); 2493 match(regD_low); 2494 2495 format %{ %} 2496 interface(REG_INTER); 2497 %} 2498 2499 operand regF() %{ 2500 constraint(ALLOC_IN_RC(sflt_reg)); 2501 match(RegF); 2502 2503 format %{ %} 2504 interface(REG_INTER); 2505 %} 2506 2507 operand regD_low() %{ 2508 constraint(ALLOC_IN_RC(dflt_low_reg)); 2509 match(RegD); 2510 2511 format %{ %} 2512 interface(REG_INTER); 2513 %} 2514 2515 // Special Registers 2516 2517 // Method Register 2518 operand inline_cache_regP(iRegP reg) %{ 2519 constraint(ALLOC_IN_RC(Ricklass_regP)); 2520 match(reg); 2521 format %{ %} 2522 interface(REG_INTER); 2523 %} 2524 2525 operand interpreter_method_oop_regP(iRegP reg) %{ 2526 constraint(ALLOC_IN_RC(Rmethod_regP)); 2527 match(reg); 2528 format %{ %} 2529 interface(REG_INTER); 2530 %} 2531 2532 2533 //----------Complex Operands--------------------------------------------------- 2534 // Indirect Memory Reference 2535 operand indirect(sp_ptr_RegP reg) %{ 2536 constraint(ALLOC_IN_RC(sp_ptr_reg)); 2537 match(reg); 2538 2539 op_cost(100); 2540 format %{ "[$reg]" %} 2541 interface(MEMORY_INTER) %{ 2542 base($reg); 2543 index(0xf); // PC => no index 2544 scale(0x0); 2545 disp(0x0); 2546 %} 2547 %} 2548 2549 2550 // Indirect with Offset in ]-4096, 4096[ 2551 operand indOffset12(sp_ptr_RegP reg, immI12 offset) %{ 2552 constraint(ALLOC_IN_RC(sp_ptr_reg)); 2553 match(AddP reg offset); 2554 2555 op_cost(100); 2556 format %{ "[$reg + $offset]" %} 2557 interface(MEMORY_INTER) %{ 2558 base($reg); 2559 index(0xf); // PC => no index 2560 scale(0x0); 2561 disp($offset); 2562 %} 2563 %} 2564 2565 // Indirect with offset for float load/store 2566 operand indOffsetFP(sp_ptr_RegP reg, immIFP offset) %{ 2567 constraint(ALLOC_IN_RC(sp_ptr_reg)); 2568 match(AddP reg offset); 2569 2570 op_cost(100); 2571 format %{ "[$reg + $offset]" %} 2572 interface(MEMORY_INTER) %{ 2573 base($reg); 2574 index(0xf); // PC => no index 2575 scale(0x0); 2576 disp($offset); 2577 %} 2578 %} 2579 2580 // Indirect with Offset for half and double words 2581 operand indOffsetHD(sp_ptr_RegP reg, immIHD offset) %{ 2582 constraint(ALLOC_IN_RC(sp_ptr_reg)); 2583 match(AddP reg offset); 2584 2585 op_cost(100); 2586 format %{ "[$reg + $offset]" %} 2587 interface(MEMORY_INTER) %{ 2588 base($reg); 2589 index(0xf); // PC => no index 2590 scale(0x0); 2591 disp($offset); 2592 %} 2593 %} 2594 2595 // Indirect with Offset and Offset+4 in ]-1024, 1024[ 2596 operand indOffsetFPx2(sp_ptr_RegP reg, immX10x2 offset) %{ 2597 constraint(ALLOC_IN_RC(sp_ptr_reg)); 2598 match(AddP reg offset); 2599 2600 op_cost(100); 2601 format %{ "[$reg + $offset]" %} 2602 interface(MEMORY_INTER) %{ 2603 base($reg); 2604 index(0xf); // PC => no index 2605 scale(0x0); 2606 disp($offset); 2607 %} 2608 %} 2609 2610 // Indirect with Offset and Offset+4 in ]-4096, 4096[ 2611 operand indOffset12x2(sp_ptr_RegP reg, immI12x2 offset) %{ 2612 constraint(ALLOC_IN_RC(sp_ptr_reg)); 2613 match(AddP reg offset); 2614 2615 op_cost(100); 2616 format %{ "[$reg + $offset]" %} 2617 interface(MEMORY_INTER) %{ 2618 base($reg); 2619 index(0xf); // PC => no index 2620 scale(0x0); 2621 disp($offset); 2622 %} 2623 %} 2624 2625 // Indirect with Register Index 2626 operand indIndex(iRegP addr, iRegX index) %{ 2627 constraint(ALLOC_IN_RC(ptr_reg)); 2628 match(AddP addr index); 2629 2630 op_cost(100); 2631 format %{ "[$addr + $index]" %} 2632 interface(MEMORY_INTER) %{ 2633 base($addr); 2634 index($index); 2635 scale(0x0); 2636 disp(0x0); 2637 %} 2638 %} 2639 2640 // Indirect Memory Times Scale Plus Index Register 2641 operand indIndexScale(iRegP addr, iRegX index, immU5 scale) %{ 2642 constraint(ALLOC_IN_RC(ptr_reg)); 2643 match(AddP addr (LShiftX index scale)); 2644 2645 op_cost(100); 2646 format %{"[$addr + $index << $scale]" %} 2647 interface(MEMORY_INTER) %{ 2648 base($addr); 2649 index($index); 2650 scale($scale); 2651 disp(0x0); 2652 %} 2653 %} 2654 2655 // Operands for expressing Control Flow 2656 // NOTE: Label is a predefined operand which should not be redefined in 2657 // the AD file. It is generically handled within the ADLC. 2658 2659 //----------Conditional Branch Operands---------------------------------------- 2660 // Comparison Op - This is the operation of the comparison, and is limited to 2661 // the following set of codes: 2662 // L (<), LE (<=), G (>), GE (>=), E (==), NE (!=) 2663 // 2664 // Other attributes of the comparison, such as unsignedness, are specified 2665 // by the comparison instruction that sets a condition code flags register. 2666 // That result is represented by a flags operand whose subtype is appropriate 2667 // to the unsignedness (etc.) of the comparison. 2668 // 2669 // Later, the instruction which matches both the Comparison Op (a Bool) and 2670 // the flags (produced by the Cmp) specifies the coding of the comparison op 2671 // by matching a specific subtype of Bool operand below, such as cmpOpU. 2672 2673 operand cmpOp() %{ 2674 match(Bool); 2675 2676 format %{ "" %} 2677 interface(COND_INTER) %{ 2678 equal(0x0); 2679 not_equal(0x1); 2680 less(0xb); 2681 greater_equal(0xa); 2682 less_equal(0xd); 2683 greater(0xc); 2684 overflow(0x0); // unsupported/unimplemented 2685 no_overflow(0x0); // unsupported/unimplemented 2686 %} 2687 %} 2688 2689 // integer comparison with 0, signed 2690 operand cmpOp0() %{ 2691 match(Bool); 2692 2693 format %{ "" %} 2694 interface(COND_INTER) %{ 2695 equal(0x0); 2696 not_equal(0x1); 2697 less(0x4); 2698 greater_equal(0x5); 2699 less_equal(0xd); // unsupported 2700 greater(0xc); // unsupported 2701 overflow(0x0); // unsupported/unimplemented 2702 no_overflow(0x0); // unsupported/unimplemented 2703 %} 2704 %} 2705 2706 // Comparison Op, unsigned 2707 operand cmpOpU() %{ 2708 match(Bool); 2709 2710 format %{ "u" %} 2711 interface(COND_INTER) %{ 2712 equal(0x0); 2713 not_equal(0x1); 2714 less(0x3); 2715 greater_equal(0x2); 2716 less_equal(0x9); 2717 greater(0x8); 2718 overflow(0x0); // unsupported/unimplemented 2719 no_overflow(0x0); // unsupported/unimplemented 2720 %} 2721 %} 2722 2723 // Comparison Op, pointer (same as unsigned) 2724 operand cmpOpP() %{ 2725 match(Bool); 2726 2727 format %{ "p" %} 2728 interface(COND_INTER) %{ 2729 equal(0x0); 2730 not_equal(0x1); 2731 less(0x3); 2732 greater_equal(0x2); 2733 less_equal(0x9); 2734 greater(0x8); 2735 overflow(0x0); // unsupported/unimplemented 2736 no_overflow(0x0); // unsupported/unimplemented 2737 %} 2738 %} 2739 2740 operand cmpOpL() %{ 2741 match(Bool); 2742 2743 format %{ "L" %} 2744 interface(COND_INTER) %{ 2745 equal(0x0); 2746 not_equal(0x1); 2747 less(0xb); 2748 greater_equal(0xa); 2749 less_equal(0xd); 2750 greater(0xc); 2751 overflow(0x0); // unsupported/unimplemented 2752 no_overflow(0x0); // unsupported/unimplemented 2753 %} 2754 %} 2755 2756 operand cmpOpL_commute() %{ 2757 match(Bool); 2758 2759 format %{ "L" %} 2760 interface(COND_INTER) %{ 2761 equal(0x0); 2762 not_equal(0x1); 2763 less(0xc); 2764 greater_equal(0xd); 2765 less_equal(0xa); 2766 greater(0xb); 2767 overflow(0x0); // unsupported/unimplemented 2768 no_overflow(0x0); // unsupported/unimplemented 2769 %} 2770 %} 2771 2772 operand cmpOpUL() %{ 2773 match(Bool); 2774 2775 format %{ "UL" %} 2776 interface(COND_INTER) %{ 2777 equal(0x0); 2778 not_equal(0x1); 2779 less(0x3); 2780 greater_equal(0x2); 2781 less_equal(0x9); 2782 greater(0x8); 2783 overflow(0x0); // unsupported/unimplemented 2784 no_overflow(0x0); // unsupported/unimplemented 2785 %} 2786 %} 2787 2788 operand cmpOpUL_commute() %{ 2789 match(Bool); 2790 2791 format %{ "UL" %} 2792 interface(COND_INTER) %{ 2793 equal(0x0); 2794 not_equal(0x1); 2795 less(0x8); 2796 greater_equal(0x9); 2797 less_equal(0x2); 2798 greater(0x3); 2799 overflow(0x0); // unsupported/unimplemented 2800 no_overflow(0x0); // unsupported/unimplemented 2801 %} 2802 %} 2803 2804 2805 //----------OPERAND CLASSES---------------------------------------------------- 2806 // Operand Classes are groups of operands that are used to simplify 2807 // instruction definitions by not requiring the AD writer to specify separate 2808 // instructions for every form of operand when the instruction accepts 2809 // multiple operand types with the same basic encoding and format. The classic 2810 // case of this is memory operands. 2811 2812 opclass memoryI ( indirect, indOffset12, indIndex, indIndexScale ); 2813 opclass memoryP ( indirect, indOffset12, indIndex, indIndexScale ); 2814 opclass memoryF ( indirect, indOffsetFP ); 2815 opclass memoryF2 ( indirect, indOffsetFPx2 ); 2816 opclass memoryD ( indirect, indOffsetFP ); 2817 opclass memoryfp( indirect, indOffsetFP ); 2818 opclass memoryB ( indirect, indIndex, indOffsetHD ); 2819 opclass memoryS ( indirect, indIndex, indOffsetHD ); 2820 opclass memoryL ( indirect, indIndex, indOffsetHD ); 2821 2822 opclass memoryScaledI(indIndexScale); 2823 opclass memoryScaledP(indIndexScale); 2824 2825 // when ldrex/strex is used: 2826 opclass memoryex ( indirect ); 2827 opclass indIndexMemory( indIndex ); 2828 opclass memorylong ( indirect, indOffset12x2 ); 2829 opclass memoryvld ( indirect /* , write back mode not implemented */ ); 2830 2831 //----------PIPELINE----------------------------------------------------------- 2832 pipeline %{ 2833 2834 //----------ATTRIBUTES--------------------------------------------------------- 2835 attributes %{ 2836 fixed_size_instructions; // Fixed size instructions 2837 max_instructions_per_bundle = 4; // Up to 4 instructions per bundle 2838 instruction_unit_size = 4; // An instruction is 4 bytes long 2839 instruction_fetch_unit_size = 16; // The processor fetches one line 2840 instruction_fetch_units = 1; // of 16 bytes 2841 2842 // List of nop instructions 2843 nops( Nop_A0, Nop_A1, Nop_MS, Nop_FA, Nop_BR ); 2844 %} 2845 2846 //----------RESOURCES---------------------------------------------------------- 2847 // Resources are the functional units available to the machine 2848 resources(A0, A1, MS, BR, FA, FM, IDIV, FDIV, IALU = A0 | A1); 2849 2850 //----------PIPELINE DESCRIPTION----------------------------------------------- 2851 // Pipeline Description specifies the stages in the machine's pipeline 2852 2853 pipe_desc(A, P, F, B, I, J, S, R, E, C, M, W, X, T, D); 2854 2855 //----------PIPELINE CLASSES--------------------------------------------------- 2856 // Pipeline Classes describe the stages in which input and output are 2857 // referenced by the hardware pipeline. 2858 2859 // Integer ALU reg-reg operation 2860 pipe_class ialu_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{ 2861 single_instruction; 2862 dst : E(write); 2863 src1 : R(read); 2864 src2 : R(read); 2865 IALU : R; 2866 %} 2867 2868 // Integer ALU reg-reg long operation 2869 pipe_class ialu_reg_reg_2(iRegL dst, iRegL src1, iRegL src2) %{ 2870 instruction_count(2); 2871 dst : E(write); 2872 src1 : R(read); 2873 src2 : R(read); 2874 IALU : R; 2875 IALU : R; 2876 %} 2877 2878 // Integer ALU reg-reg long dependent operation 2879 pipe_class ialu_reg_reg_2_dep(iRegL dst, iRegL src1, iRegL src2, flagsReg cr) %{ 2880 instruction_count(1); multiple_bundles; 2881 dst : E(write); 2882 src1 : R(read); 2883 src2 : R(read); 2884 cr : E(write); 2885 IALU : R(2); 2886 %} 2887 2888 // Integer ALU reg-imm operaion 2889 pipe_class ialu_reg_imm(iRegI dst, iRegI src1) %{ 2890 single_instruction; 2891 dst : E(write); 2892 src1 : R(read); 2893 IALU : R; 2894 %} 2895 2896 // Integer ALU reg-reg operation with condition code 2897 pipe_class ialu_cc_reg_reg(iRegI dst, iRegI src1, iRegI src2, flagsReg cr) %{ 2898 single_instruction; 2899 dst : E(write); 2900 cr : E(write); 2901 src1 : R(read); 2902 src2 : R(read); 2903 IALU : R; 2904 %} 2905 2906 // Integer ALU zero-reg operation 2907 pipe_class ialu_zero_reg(iRegI dst, immI0 zero, iRegI src2) %{ 2908 single_instruction; 2909 dst : E(write); 2910 src2 : R(read); 2911 IALU : R; 2912 %} 2913 2914 // Integer ALU zero-reg operation with condition code only 2915 pipe_class ialu_cconly_zero_reg(flagsReg cr, iRegI src) %{ 2916 single_instruction; 2917 cr : E(write); 2918 src : R(read); 2919 IALU : R; 2920 %} 2921 2922 // Integer ALU reg-reg operation with condition code only 2923 pipe_class ialu_cconly_reg_reg(flagsReg cr, iRegI src1, iRegI src2) %{ 2924 single_instruction; 2925 cr : E(write); 2926 src1 : R(read); 2927 src2 : R(read); 2928 IALU : R; 2929 %} 2930 2931 // Integer ALU reg-imm operation with condition code only 2932 pipe_class ialu_cconly_reg_imm(flagsReg cr, iRegI src1) %{ 2933 single_instruction; 2934 cr : E(write); 2935 src1 : R(read); 2936 IALU : R; 2937 %} 2938 2939 // Integer ALU reg-reg-zero operation with condition code only 2940 pipe_class ialu_cconly_reg_reg_zero(flagsReg cr, iRegI src1, iRegI src2, immI0 zero) %{ 2941 single_instruction; 2942 cr : E(write); 2943 src1 : R(read); 2944 src2 : R(read); 2945 IALU : R; 2946 %} 2947 2948 // Integer ALU reg-imm-zero operation with condition code only 2949 pipe_class ialu_cconly_reg_imm_zero(flagsReg cr, iRegI src1, immI0 zero) %{ 2950 single_instruction; 2951 cr : E(write); 2952 src1 : R(read); 2953 IALU : R; 2954 %} 2955 2956 // Integer ALU reg-reg operation with condition code, src1 modified 2957 pipe_class ialu_cc_rwreg_reg(flagsReg cr, iRegI src1, iRegI src2) %{ 2958 single_instruction; 2959 cr : E(write); 2960 src1 : E(write); 2961 src1 : R(read); 2962 src2 : R(read); 2963 IALU : R; 2964 %} 2965 2966 pipe_class cmpL_reg(iRegI dst, iRegL src1, iRegL src2, flagsReg cr ) %{ 2967 multiple_bundles; 2968 dst : E(write)+4; 2969 cr : E(write); 2970 src1 : R(read); 2971 src2 : R(read); 2972 IALU : R(3); 2973 BR : R(2); 2974 %} 2975 2976 // Integer ALU operation 2977 pipe_class ialu_none(iRegI dst) %{ 2978 single_instruction; 2979 dst : E(write); 2980 IALU : R; 2981 %} 2982 2983 // Integer ALU reg operation 2984 pipe_class ialu_reg(iRegI dst, iRegI src) %{ 2985 single_instruction; may_have_no_code; 2986 dst : E(write); 2987 src : R(read); 2988 IALU : R; 2989 %} 2990 2991 // Integer ALU reg conditional operation 2992 // This instruction has a 1 cycle stall, and cannot execute 2993 // in the same cycle as the instruction setting the condition 2994 // code. We kludge this by pretending to read the condition code 2995 // 1 cycle earlier, and by marking the functional units as busy 2996 // for 2 cycles with the result available 1 cycle later than 2997 // is really the case. 2998 pipe_class ialu_reg_flags( iRegI op2_out, iRegI op2_in, iRegI op1, flagsReg cr ) %{ 2999 single_instruction; 3000 op2_out : C(write); 3001 op1 : R(read); 3002 cr : R(read); // This is really E, with a 1 cycle stall 3003 BR : R(2); 3004 MS : R(2); 3005 %} 3006 3007 // Integer ALU reg operation 3008 pipe_class ialu_move_reg_L_to_I(iRegI dst, iRegL src) %{ 3009 single_instruction; may_have_no_code; 3010 dst : E(write); 3011 src : R(read); 3012 IALU : R; 3013 %} 3014 pipe_class ialu_move_reg_I_to_L(iRegL dst, iRegI src) %{ 3015 single_instruction; may_have_no_code; 3016 dst : E(write); 3017 src : R(read); 3018 IALU : R; 3019 %} 3020 3021 // Two integer ALU reg operations 3022 pipe_class ialu_reg_2(iRegL dst, iRegL src) %{ 3023 instruction_count(2); 3024 dst : E(write); 3025 src : R(read); 3026 A0 : R; 3027 A1 : R; 3028 %} 3029 3030 // Two integer ALU reg operations 3031 pipe_class ialu_move_reg_L_to_L(iRegL dst, iRegL src) %{ 3032 instruction_count(2); may_have_no_code; 3033 dst : E(write); 3034 src : R(read); 3035 A0 : R; 3036 A1 : R; 3037 %} 3038 3039 // Integer ALU imm operation 3040 pipe_class ialu_imm(iRegI dst) %{ 3041 single_instruction; 3042 dst : E(write); 3043 IALU : R; 3044 %} 3045 3046 pipe_class ialu_imm_n(iRegI dst) %{ 3047 single_instruction; 3048 dst : E(write); 3049 IALU : R; 3050 %} 3051 3052 // Integer ALU reg-reg with carry operation 3053 pipe_class ialu_reg_reg_cy(iRegI dst, iRegI src1, iRegI src2, iRegI cy) %{ 3054 single_instruction; 3055 dst : E(write); 3056 src1 : R(read); 3057 src2 : R(read); 3058 IALU : R; 3059 %} 3060 3061 // Integer ALU cc operation 3062 pipe_class ialu_cc(iRegI dst, flagsReg cc) %{ 3063 single_instruction; 3064 dst : E(write); 3065 cc : R(read); 3066 IALU : R; 3067 %} 3068 3069 // Integer ALU cc / second IALU operation 3070 pipe_class ialu_reg_ialu( iRegI dst, iRegI src ) %{ 3071 instruction_count(1); multiple_bundles; 3072 dst : E(write)+1; 3073 src : R(read); 3074 IALU : R; 3075 %} 3076 3077 // Integer ALU cc / second IALU operation 3078 pipe_class ialu_reg_reg_ialu( iRegI dst, iRegI p, iRegI q ) %{ 3079 instruction_count(1); multiple_bundles; 3080 dst : E(write)+1; 3081 p : R(read); 3082 q : R(read); 3083 IALU : R; 3084 %} 3085 3086 // Integer ALU hi-lo-reg operation 3087 pipe_class ialu_hi_lo_reg(iRegI dst, immI src) %{ 3088 instruction_count(1); multiple_bundles; 3089 dst : E(write)+1; 3090 IALU : R(2); 3091 %} 3092 3093 // Long Constant 3094 pipe_class loadConL( iRegL dst, immL src ) %{ 3095 instruction_count(2); multiple_bundles; 3096 dst : E(write)+1; 3097 IALU : R(2); 3098 IALU : R(2); 3099 %} 3100 3101 // Pointer Constant 3102 pipe_class loadConP( iRegP dst, immP src ) %{ 3103 instruction_count(0); multiple_bundles; 3104 fixed_latency(6); 3105 %} 3106 3107 // Long Constant small 3108 pipe_class loadConLlo( iRegL dst, immL src ) %{ 3109 instruction_count(2); 3110 dst : E(write); 3111 IALU : R; 3112 IALU : R; 3113 %} 3114 3115 // [PHH] This is wrong for 64-bit. See LdImmF/D. 3116 pipe_class loadConFD(regF dst, immF src, iRegP tmp) %{ 3117 instruction_count(1); multiple_bundles; 3118 src : R(read); 3119 dst : M(write)+1; 3120 IALU : R; 3121 MS : E; 3122 %} 3123 3124 // Integer ALU nop operation 3125 pipe_class ialu_nop() %{ 3126 single_instruction; 3127 IALU : R; 3128 %} 3129 3130 // Integer ALU nop operation 3131 pipe_class ialu_nop_A0() %{ 3132 single_instruction; 3133 A0 : R; 3134 %} 3135 3136 // Integer ALU nop operation 3137 pipe_class ialu_nop_A1() %{ 3138 single_instruction; 3139 A1 : R; 3140 %} 3141 3142 // Integer Multiply reg-reg operation 3143 pipe_class imul_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{ 3144 single_instruction; 3145 dst : E(write); 3146 src1 : R(read); 3147 src2 : R(read); 3148 MS : R(5); 3149 %} 3150 3151 pipe_class mulL_reg_reg(iRegL dst, iRegL src1, iRegL src2) %{ 3152 single_instruction; 3153 dst : E(write)+4; 3154 src1 : R(read); 3155 src2 : R(read); 3156 MS : R(6); 3157 %} 3158 3159 // Integer Divide reg-reg 3160 pipe_class sdiv_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI temp, flagsReg cr) %{ 3161 instruction_count(1); multiple_bundles; 3162 dst : E(write); 3163 temp : E(write); 3164 src1 : R(read); 3165 src2 : R(read); 3166 temp : R(read); 3167 MS : R(38); 3168 %} 3169 3170 // Long Divide 3171 pipe_class divL_reg_reg(iRegL dst, iRegL src1, iRegL src2) %{ 3172 dst : E(write)+71; 3173 src1 : R(read); 3174 src2 : R(read)+1; 3175 MS : R(70); 3176 %} 3177 3178 // Floating Point Add Float 3179 pipe_class faddF_reg_reg(regF dst, regF src1, regF src2) %{ 3180 single_instruction; 3181 dst : X(write); 3182 src1 : E(read); 3183 src2 : E(read); 3184 FA : R; 3185 %} 3186 3187 // Floating Point Add Double 3188 pipe_class faddD_reg_reg(regD dst, regD src1, regD src2) %{ 3189 single_instruction; 3190 dst : X(write); 3191 src1 : E(read); 3192 src2 : E(read); 3193 FA : R; 3194 %} 3195 3196 // Floating Point Conditional Move based on integer flags 3197 pipe_class int_conditional_float_move (cmpOp cmp, flagsReg cr, regF dst, regF src) %{ 3198 single_instruction; 3199 dst : X(write); 3200 src : E(read); 3201 cr : R(read); 3202 FA : R(2); 3203 BR : R(2); 3204 %} 3205 3206 // Floating Point Conditional Move based on integer flags 3207 pipe_class int_conditional_double_move (cmpOp cmp, flagsReg cr, regD dst, regD src) %{ 3208 single_instruction; 3209 dst : X(write); 3210 src : E(read); 3211 cr : R(read); 3212 FA : R(2); 3213 BR : R(2); 3214 %} 3215 3216 // Floating Point Multiply Float 3217 pipe_class fmulF_reg_reg(regF dst, regF src1, regF src2) %{ 3218 single_instruction; 3219 dst : X(write); 3220 src1 : E(read); 3221 src2 : E(read); 3222 FM : R; 3223 %} 3224 3225 // Floating Point Multiply Double 3226 pipe_class fmulD_reg_reg(regD dst, regD src1, regD src2) %{ 3227 single_instruction; 3228 dst : X(write); 3229 src1 : E(read); 3230 src2 : E(read); 3231 FM : R; 3232 %} 3233 3234 // Floating Point Divide Float 3235 pipe_class fdivF_reg_reg(regF dst, regF src1, regF src2) %{ 3236 single_instruction; 3237 dst : X(write); 3238 src1 : E(read); 3239 src2 : E(read); 3240 FM : R; 3241 FDIV : C(14); 3242 %} 3243 3244 // Floating Point Divide Double 3245 pipe_class fdivD_reg_reg(regD dst, regD src1, regD src2) %{ 3246 single_instruction; 3247 dst : X(write); 3248 src1 : E(read); 3249 src2 : E(read); 3250 FM : R; 3251 FDIV : C(17); 3252 %} 3253 3254 // Floating Point Move/Negate/Abs Float 3255 pipe_class faddF_reg(regF dst, regF src) %{ 3256 single_instruction; 3257 dst : W(write); 3258 src : E(read); 3259 FA : R(1); 3260 %} 3261 3262 // Floating Point Move/Negate/Abs Double 3263 pipe_class faddD_reg(regD dst, regD src) %{ 3264 single_instruction; 3265 dst : W(write); 3266 src : E(read); 3267 FA : R; 3268 %} 3269 3270 // Floating Point Convert F->D 3271 pipe_class fcvtF2D(regD dst, regF src) %{ 3272 single_instruction; 3273 dst : X(write); 3274 src : E(read); 3275 FA : R; 3276 %} 3277 3278 // Floating Point Convert I->D 3279 pipe_class fcvtI2D(regD dst, regF src) %{ 3280 single_instruction; 3281 dst : X(write); 3282 src : E(read); 3283 FA : R; 3284 %} 3285 3286 // Floating Point Convert LHi->D 3287 pipe_class fcvtLHi2D(regD dst, regD src) %{ 3288 single_instruction; 3289 dst : X(write); 3290 src : E(read); 3291 FA : R; 3292 %} 3293 3294 // Floating Point Convert L->D 3295 pipe_class fcvtL2D(regD dst, iRegL src) %{ 3296 single_instruction; 3297 dst : X(write); 3298 src : E(read); 3299 FA : R; 3300 %} 3301 3302 // Floating Point Convert L->F 3303 pipe_class fcvtL2F(regF dst, iRegL src) %{ 3304 single_instruction; 3305 dst : X(write); 3306 src : E(read); 3307 FA : R; 3308 %} 3309 3310 // Floating Point Convert D->F 3311 pipe_class fcvtD2F(regD dst, regF src) %{ 3312 single_instruction; 3313 dst : X(write); 3314 src : E(read); 3315 FA : R; 3316 %} 3317 3318 // Floating Point Convert I->L 3319 pipe_class fcvtI2L(regD dst, regF src) %{ 3320 single_instruction; 3321 dst : X(write); 3322 src : E(read); 3323 FA : R; 3324 %} 3325 3326 // Floating Point Convert D->F 3327 pipe_class fcvtD2I(iRegI dst, regD src, flagsReg cr) %{ 3328 instruction_count(1); multiple_bundles; 3329 dst : X(write)+6; 3330 src : E(read); 3331 FA : R; 3332 %} 3333 3334 // Floating Point Convert D->L 3335 pipe_class fcvtD2L(regD dst, regD src, flagsReg cr) %{ 3336 instruction_count(1); multiple_bundles; 3337 dst : X(write)+6; 3338 src : E(read); 3339 FA : R; 3340 %} 3341 3342 // Floating Point Convert F->I 3343 pipe_class fcvtF2I(regF dst, regF src, flagsReg cr) %{ 3344 instruction_count(1); multiple_bundles; 3345 dst : X(write)+6; 3346 src : E(read); 3347 FA : R; 3348 %} 3349 3350 // Floating Point Convert F->L 3351 pipe_class fcvtF2L(regD dst, regF src, flagsReg cr) %{ 3352 instruction_count(1); multiple_bundles; 3353 dst : X(write)+6; 3354 src : E(read); 3355 FA : R; 3356 %} 3357 3358 // Floating Point Convert I->F 3359 pipe_class fcvtI2F(regF dst, regF src) %{ 3360 single_instruction; 3361 dst : X(write); 3362 src : E(read); 3363 FA : R; 3364 %} 3365 3366 // Floating Point Compare 3367 pipe_class faddF_fcc_reg_reg_zero(flagsRegF cr, regF src1, regF src2, immI0 zero) %{ 3368 single_instruction; 3369 cr : X(write); 3370 src1 : E(read); 3371 src2 : E(read); 3372 FA : R; 3373 %} 3374 3375 // Floating Point Compare 3376 pipe_class faddD_fcc_reg_reg_zero(flagsRegF cr, regD src1, regD src2, immI0 zero) %{ 3377 single_instruction; 3378 cr : X(write); 3379 src1 : E(read); 3380 src2 : E(read); 3381 FA : R; 3382 %} 3383 3384 // Floating Add Nop 3385 pipe_class fadd_nop() %{ 3386 single_instruction; 3387 FA : R; 3388 %} 3389 3390 // Integer Store to Memory 3391 pipe_class istore_mem_reg(memoryI mem, iRegI src) %{ 3392 single_instruction; 3393 mem : R(read); 3394 src : C(read); 3395 MS : R; 3396 %} 3397 3398 // Integer Store to Memory 3399 pipe_class istore_mem_spORreg(memoryI mem, sp_ptr_RegP src) %{ 3400 single_instruction; 3401 mem : R(read); 3402 src : C(read); 3403 MS : R; 3404 %} 3405 3406 // Float Store 3407 pipe_class fstoreF_mem_reg(memoryF mem, RegF src) %{ 3408 single_instruction; 3409 mem : R(read); 3410 src : C(read); 3411 MS : R; 3412 %} 3413 3414 // Float Store 3415 pipe_class fstoreF_mem_zero(memoryF mem, immF0 src) %{ 3416 single_instruction; 3417 mem : R(read); 3418 MS : R; 3419 %} 3420 3421 // Double Store 3422 pipe_class fstoreD_mem_reg(memoryD mem, RegD src) %{ 3423 instruction_count(1); 3424 mem : R(read); 3425 src : C(read); 3426 MS : R; 3427 %} 3428 3429 // Double Store 3430 pipe_class fstoreD_mem_zero(memoryD mem, immD0 src) %{ 3431 single_instruction; 3432 mem : R(read); 3433 MS : R; 3434 %} 3435 3436 // Integer Load (when sign bit propagation not needed) 3437 pipe_class iload_mem(iRegI dst, memoryI mem) %{ 3438 single_instruction; 3439 mem : R(read); 3440 dst : C(write); 3441 MS : R; 3442 %} 3443 3444 // Integer Load (when sign bit propagation or masking is needed) 3445 pipe_class iload_mask_mem(iRegI dst, memoryI mem) %{ 3446 single_instruction; 3447 mem : R(read); 3448 dst : M(write); 3449 MS : R; 3450 %} 3451 3452 // Float Load 3453 pipe_class floadF_mem(regF dst, memoryF mem) %{ 3454 single_instruction; 3455 mem : R(read); 3456 dst : M(write); 3457 MS : R; 3458 %} 3459 3460 // Float Load 3461 pipe_class floadD_mem(regD dst, memoryD mem) %{ 3462 instruction_count(1); multiple_bundles; // Again, unaligned argument is only multiple case 3463 mem : R(read); 3464 dst : M(write); 3465 MS : R; 3466 %} 3467 3468 // Memory Nop 3469 pipe_class mem_nop() %{ 3470 single_instruction; 3471 MS : R; 3472 %} 3473 3474 pipe_class sethi(iRegP dst, immI src) %{ 3475 single_instruction; 3476 dst : E(write); 3477 IALU : R; 3478 %} 3479 3480 pipe_class loadPollP(iRegP poll) %{ 3481 single_instruction; 3482 poll : R(read); 3483 MS : R; 3484 %} 3485 3486 pipe_class br(Universe br, label labl) %{ 3487 single_instruction_with_delay_slot; 3488 BR : R; 3489 %} 3490 3491 pipe_class br_cc(Universe br, cmpOp cmp, flagsReg cr, label labl) %{ 3492 single_instruction_with_delay_slot; 3493 cr : E(read); 3494 BR : R; 3495 %} 3496 3497 pipe_class br_reg(Universe br, cmpOp cmp, iRegI op1, label labl) %{ 3498 single_instruction_with_delay_slot; 3499 op1 : E(read); 3500 BR : R; 3501 MS : R; 3502 %} 3503 3504 pipe_class br_nop() %{ 3505 single_instruction; 3506 BR : R; 3507 %} 3508 3509 pipe_class simple_call(method meth) %{ 3510 instruction_count(2); multiple_bundles; force_serialization; 3511 fixed_latency(100); 3512 BR : R(1); 3513 MS : R(1); 3514 A0 : R(1); 3515 %} 3516 3517 pipe_class compiled_call(method meth) %{ 3518 instruction_count(1); multiple_bundles; force_serialization; 3519 fixed_latency(100); 3520 MS : R(1); 3521 %} 3522 3523 pipe_class call(method meth) %{ 3524 instruction_count(0); multiple_bundles; force_serialization; 3525 fixed_latency(100); 3526 %} 3527 3528 pipe_class tail_call(Universe ignore, label labl) %{ 3529 single_instruction; has_delay_slot; 3530 fixed_latency(100); 3531 BR : R(1); 3532 MS : R(1); 3533 %} 3534 3535 pipe_class ret(Universe ignore) %{ 3536 single_instruction; has_delay_slot; 3537 BR : R(1); 3538 MS : R(1); 3539 %} 3540 3541 // The real do-nothing guy 3542 pipe_class empty( ) %{ 3543 instruction_count(0); 3544 %} 3545 3546 pipe_class long_memory_op() %{ 3547 instruction_count(0); multiple_bundles; force_serialization; 3548 fixed_latency(25); 3549 MS : R(1); 3550 %} 3551 3552 // Check-cast 3553 pipe_class partial_subtype_check_pipe(Universe ignore, iRegP array, iRegP match ) %{ 3554 array : R(read); 3555 match : R(read); 3556 IALU : R(2); 3557 BR : R(2); 3558 MS : R; 3559 %} 3560 3561 // Convert FPU flags into +1,0,-1 3562 pipe_class floating_cmp( iRegI dst, regF src1, regF src2 ) %{ 3563 src1 : E(read); 3564 src2 : E(read); 3565 dst : E(write); 3566 FA : R; 3567 MS : R(2); 3568 BR : R(2); 3569 %} 3570 3571 // Compare for p < q, and conditionally add y 3572 pipe_class cadd_cmpltmask( iRegI p, iRegI q, iRegI y ) %{ 3573 p : E(read); 3574 q : E(read); 3575 y : E(read); 3576 IALU : R(3) 3577 %} 3578 3579 // Perform a compare, then move conditionally in a branch delay slot. 3580 pipe_class min_max( iRegI src2, iRegI srcdst ) %{ 3581 src2 : E(read); 3582 srcdst : E(read); 3583 IALU : R; 3584 BR : R; 3585 %} 3586 3587 // Define the class for the Nop node 3588 define %{ 3589 MachNop = ialu_nop; 3590 %} 3591 3592 %} 3593 3594 //----------INSTRUCTIONS------------------------------------------------------- 3595 3596 //------------Special Nop instructions for bundling - no match rules----------- 3597 // Nop using the A0 functional unit 3598 instruct Nop_A0() %{ 3599 ins_pipe(ialu_nop_A0); 3600 %} 3601 3602 // Nop using the A1 functional unit 3603 instruct Nop_A1( ) %{ 3604 ins_pipe(ialu_nop_A1); 3605 %} 3606 3607 // Nop using the memory functional unit 3608 instruct Nop_MS( ) %{ 3609 ins_pipe(mem_nop); 3610 %} 3611 3612 // Nop using the floating add functional unit 3613 instruct Nop_FA( ) %{ 3614 ins_pipe(fadd_nop); 3615 %} 3616 3617 // Nop using the branch functional unit 3618 instruct Nop_BR( ) %{ 3619 ins_pipe(br_nop); 3620 %} 3621 3622 //----------Load/Store/Move Instructions--------------------------------------- 3623 //----------Load Instructions-------------------------------------------------- 3624 // Load Byte (8bit signed) 3625 instruct loadB(iRegI dst, memoryB mem) %{ 3626 match(Set dst (LoadB mem)); 3627 ins_cost(MEMORY_REF_COST); 3628 3629 size(4); 3630 format %{ "LDRSB $dst,$mem\t! byte -> int" %} 3631 ins_encode %{ 3632 __ ldrsb($dst$$Register, $mem$$Address); 3633 %} 3634 ins_pipe(iload_mask_mem); 3635 %} 3636 3637 // Load Byte (8bit signed) into a Long Register 3638 instruct loadB2L(iRegL dst, memoryB mem) %{ 3639 match(Set dst (ConvI2L (LoadB mem))); 3640 ins_cost(MEMORY_REF_COST); 3641 3642 size(8); 3643 format %{ "LDRSB $dst.lo,$mem\t! byte -> long\n\t" 3644 "ASR $dst.hi,$dst.lo,31" %} 3645 ins_encode %{ 3646 __ ldrsb($dst$$Register, $mem$$Address); 3647 __ mov($dst$$Register->successor(), AsmOperand($dst$$Register, asr, 31)); 3648 %} 3649 ins_pipe(iload_mask_mem); 3650 %} 3651 3652 // Load Unsigned Byte (8bit UNsigned) into an int reg 3653 instruct loadUB(iRegI dst, memoryB mem) %{ 3654 match(Set dst (LoadUB mem)); 3655 ins_cost(MEMORY_REF_COST); 3656 3657 size(4); 3658 format %{ "LDRB $dst,$mem\t! ubyte -> int" %} 3659 ins_encode %{ 3660 __ ldrb($dst$$Register, $mem$$Address); 3661 %} 3662 ins_pipe(iload_mem); 3663 %} 3664 3665 // Load Unsigned Byte (8bit UNsigned) into a Long Register 3666 instruct loadUB2L(iRegL dst, memoryB mem) %{ 3667 match(Set dst (ConvI2L (LoadUB mem))); 3668 ins_cost(MEMORY_REF_COST); 3669 3670 size(8); 3671 format %{ "LDRB $dst.lo,$mem\t! ubyte -> long\n\t" 3672 "MOV $dst.hi,0" %} 3673 ins_encode %{ 3674 __ ldrb($dst$$Register, $mem$$Address); 3675 __ mov($dst$$Register->successor(), 0); 3676 %} 3677 ins_pipe(iload_mem); 3678 %} 3679 3680 // Load Unsigned Byte (8 bit UNsigned) with immediate mask into Long Register 3681 instruct loadUB2L_limmI(iRegL dst, memoryB mem, limmIlow8 mask) %{ 3682 match(Set dst (ConvI2L (AndI (LoadUB mem) mask))); 3683 3684 ins_cost(MEMORY_REF_COST + 2*DEFAULT_COST); 3685 size(12); 3686 format %{ "LDRB $dst.lo,$mem\t! ubyte -> long\n\t" 3687 "MOV $dst.hi,0\n\t" 3688 "AND $dst.lo,$dst.lo,$mask" %} 3689 ins_encode %{ 3690 __ ldrb($dst$$Register, $mem$$Address); 3691 __ mov($dst$$Register->successor(), 0); 3692 __ andr($dst$$Register, $dst$$Register, limmI_low($mask$$constant, 8)); 3693 %} 3694 ins_pipe(iload_mem); 3695 %} 3696 3697 // Load Short (16bit signed) 3698 3699 instruct loadS(iRegI dst, memoryS mem) %{ 3700 match(Set dst (LoadS mem)); 3701 ins_cost(MEMORY_REF_COST); 3702 3703 size(4); 3704 format %{ "LDRSH $dst,$mem\t! short" %} 3705 ins_encode %{ 3706 __ ldrsh($dst$$Register, $mem$$Address); 3707 %} 3708 ins_pipe(iload_mask_mem); 3709 %} 3710 3711 // Load Short (16 bit signed) to Byte (8 bit signed) 3712 instruct loadS2B(iRegI dst, memoryS mem, immI_24 twentyfour) %{ 3713 match(Set dst (RShiftI (LShiftI (LoadS mem) twentyfour) twentyfour)); 3714 ins_cost(MEMORY_REF_COST); 3715 3716 size(4); 3717 3718 format %{ "LDRSB $dst,$mem\t! short -> byte" %} 3719 ins_encode %{ 3720 __ ldrsb($dst$$Register, $mem$$Address); 3721 %} 3722 ins_pipe(iload_mask_mem); 3723 %} 3724 3725 // Load Short (16bit signed) into a Long Register 3726 instruct loadS2L(iRegL dst, memoryS mem) %{ 3727 match(Set dst (ConvI2L (LoadS mem))); 3728 ins_cost(MEMORY_REF_COST); 3729 3730 size(8); 3731 format %{ "LDRSH $dst.lo,$mem\t! short -> long\n\t" 3732 "ASR $dst.hi,$dst.lo,31" %} 3733 ins_encode %{ 3734 __ ldrsh($dst$$Register, $mem$$Address); 3735 __ mov($dst$$Register->successor(), AsmOperand($dst$$Register, asr, 31)); 3736 %} 3737 ins_pipe(iload_mask_mem); 3738 %} 3739 3740 // Load Unsigned Short/Char (16bit UNsigned) 3741 3742 3743 instruct loadUS(iRegI dst, memoryS mem) %{ 3744 match(Set dst (LoadUS mem)); 3745 ins_cost(MEMORY_REF_COST); 3746 3747 size(4); 3748 format %{ "LDRH $dst,$mem\t! ushort/char" %} 3749 ins_encode %{ 3750 __ ldrh($dst$$Register, $mem$$Address); 3751 %} 3752 ins_pipe(iload_mem); 3753 %} 3754 3755 // Load Unsigned Short/Char (16 bit UNsigned) to Byte (8 bit signed) 3756 instruct loadUS2B(iRegI dst, memoryB mem, immI_24 twentyfour) %{ 3757 match(Set dst (RShiftI (LShiftI (LoadUS mem) twentyfour) twentyfour)); 3758 ins_cost(MEMORY_REF_COST); 3759 3760 size(4); 3761 format %{ "LDRSB $dst,$mem\t! ushort -> byte" %} 3762 ins_encode %{ 3763 __ ldrsb($dst$$Register, $mem$$Address); 3764 %} 3765 ins_pipe(iload_mask_mem); 3766 %} 3767 3768 // Load Unsigned Short/Char (16bit UNsigned) into a Long Register 3769 instruct loadUS2L(iRegL dst, memoryS mem) %{ 3770 match(Set dst (ConvI2L (LoadUS mem))); 3771 ins_cost(MEMORY_REF_COST); 3772 3773 size(8); 3774 format %{ "LDRH $dst.lo,$mem\t! short -> long\n\t" 3775 "MOV $dst.hi, 0" %} 3776 ins_encode %{ 3777 __ ldrh($dst$$Register, $mem$$Address); 3778 __ mov($dst$$Register->successor(), 0); 3779 %} 3780 ins_pipe(iload_mem); 3781 %} 3782 3783 // Load Unsigned Short/Char (16bit UNsigned) with mask 0xFF into a Long Register 3784 instruct loadUS2L_immI_255(iRegL dst, memoryB mem, immI_255 mask) %{ 3785 match(Set dst (ConvI2L (AndI (LoadUS mem) mask))); 3786 ins_cost(MEMORY_REF_COST); 3787 3788 size(8); 3789 format %{ "LDRB $dst.lo,$mem\t! \n\t" 3790 "MOV $dst.hi, 0" %} 3791 ins_encode %{ 3792 __ ldrb($dst$$Register, $mem$$Address); 3793 __ mov($dst$$Register->successor(), 0); 3794 %} 3795 ins_pipe(iload_mem); 3796 %} 3797 3798 // Load Unsigned Short/Char (16bit UNsigned) with a immediate mask into a Long Register 3799 instruct loadUS2L_limmI(iRegL dst, memoryS mem, limmI mask) %{ 3800 match(Set dst (ConvI2L (AndI (LoadUS mem) mask))); 3801 ins_cost(MEMORY_REF_COST + 2*DEFAULT_COST); 3802 3803 size(12); 3804 format %{ "LDRH $dst,$mem\t! ushort/char & mask -> long\n\t" 3805 "MOV $dst.hi, 0\n\t" 3806 "AND $dst,$dst,$mask" %} 3807 ins_encode %{ 3808 __ ldrh($dst$$Register, $mem$$Address); 3809 __ mov($dst$$Register->successor(), 0); 3810 __ andr($dst$$Register, $dst$$Register, $mask$$constant); 3811 %} 3812 ins_pipe(iload_mem); 3813 %} 3814 3815 // Load Integer 3816 3817 3818 instruct loadI(iRegI dst, memoryI mem) %{ 3819 match(Set dst (LoadI mem)); 3820 ins_cost(MEMORY_REF_COST); 3821 3822 size(4); 3823 format %{ "ldr_s32 $dst,$mem\t! int" %} 3824 ins_encode %{ 3825 __ ldr_s32($dst$$Register, $mem$$Address); 3826 %} 3827 ins_pipe(iload_mem); 3828 %} 3829 3830 // Load Integer to Byte (8 bit signed) 3831 instruct loadI2B(iRegI dst, memoryS mem, immI_24 twentyfour) %{ 3832 match(Set dst (RShiftI (LShiftI (LoadI mem) twentyfour) twentyfour)); 3833 ins_cost(MEMORY_REF_COST); 3834 3835 size(4); 3836 3837 format %{ "LDRSB $dst,$mem\t! int -> byte" %} 3838 ins_encode %{ 3839 __ ldrsb($dst$$Register, $mem$$Address); 3840 %} 3841 ins_pipe(iload_mask_mem); 3842 %} 3843 3844 // Load Integer to Unsigned Byte (8 bit UNsigned) 3845 instruct loadI2UB(iRegI dst, memoryB mem, immI_255 mask) %{ 3846 match(Set dst (AndI (LoadI mem) mask)); 3847 ins_cost(MEMORY_REF_COST); 3848 3849 size(4); 3850 3851 format %{ "LDRB $dst,$mem\t! int -> ubyte" %} 3852 ins_encode %{ 3853 __ ldrb($dst$$Register, $mem$$Address); 3854 %} 3855 ins_pipe(iload_mask_mem); 3856 %} 3857 3858 // Load Integer to Short (16 bit signed) 3859 instruct loadI2S(iRegI dst, memoryS mem, immI_16 sixteen) %{ 3860 match(Set dst (RShiftI (LShiftI (LoadI mem) sixteen) sixteen)); 3861 ins_cost(MEMORY_REF_COST); 3862 3863 size(4); 3864 format %{ "LDRSH $dst,$mem\t! int -> short" %} 3865 ins_encode %{ 3866 __ ldrsh($dst$$Register, $mem$$Address); 3867 %} 3868 ins_pipe(iload_mask_mem); 3869 %} 3870 3871 // Load Integer to Unsigned Short (16 bit UNsigned) 3872 instruct loadI2US(iRegI dst, memoryS mem, immI_65535 mask) %{ 3873 match(Set dst (AndI (LoadI mem) mask)); 3874 ins_cost(MEMORY_REF_COST); 3875 3876 size(4); 3877 format %{ "LDRH $dst,$mem\t! int -> ushort/char" %} 3878 ins_encode %{ 3879 __ ldrh($dst$$Register, $mem$$Address); 3880 %} 3881 ins_pipe(iload_mask_mem); 3882 %} 3883 3884 // Load Integer into a Long Register 3885 instruct loadI2L(iRegL dst, memoryI mem) %{ 3886 match(Set dst (ConvI2L (LoadI mem))); 3887 ins_cost(MEMORY_REF_COST); 3888 3889 size(8); 3890 format %{ "LDR $dst.lo,$mem\t! int -> long\n\t" 3891 "ASR $dst.hi,$dst.lo,31\t! int->long" %} 3892 ins_encode %{ 3893 __ ldr($dst$$Register, $mem$$Address); 3894 __ mov($dst$$Register->successor(), AsmOperand($dst$$Register, asr, 31)); 3895 %} 3896 ins_pipe(iload_mask_mem); 3897 %} 3898 3899 // Load Integer with mask 0xFF into a Long Register 3900 instruct loadI2L_immI_255(iRegL dst, memoryB mem, immI_255 mask) %{ 3901 match(Set dst (ConvI2L (AndI (LoadI mem) mask))); 3902 ins_cost(MEMORY_REF_COST); 3903 3904 size(8); 3905 format %{ "LDRB $dst.lo,$mem\t! int & 0xFF -> long\n\t" 3906 "MOV $dst.hi, 0" %} 3907 ins_encode %{ 3908 __ ldrb($dst$$Register, $mem$$Address); 3909 __ mov($dst$$Register->successor(), 0); 3910 %} 3911 ins_pipe(iload_mem); 3912 %} 3913 3914 // Load Integer with mask 0xFFFF into a Long Register 3915 instruct loadI2L_immI_65535(iRegL dst, memoryS mem, immI_65535 mask) %{ 3916 match(Set dst (ConvI2L (AndI (LoadI mem) mask))); 3917 ins_cost(MEMORY_REF_COST); 3918 3919 size(8); 3920 format %{ "LDRH $dst,$mem\t! int & 0xFFFF -> long\n\t" 3921 "MOV $dst.hi, 0" %} 3922 ins_encode %{ 3923 __ ldrh($dst$$Register, $mem$$Address); 3924 __ mov($dst$$Register->successor(), 0); 3925 %} 3926 ins_pipe(iload_mask_mem); 3927 %} 3928 3929 // Load Integer with a 31-bit immediate mask into a Long Register 3930 instruct loadI2L_limmU31(iRegL dst, memoryI mem, limmU31 mask) %{ 3931 match(Set dst (ConvI2L (AndI (LoadI mem) mask))); 3932 ins_cost(MEMORY_REF_COST + 2*DEFAULT_COST); 3933 3934 size(12); 3935 format %{ "LDR $dst.lo,$mem\t! int -> long\n\t" 3936 "MOV $dst.hi, 0\n\t" 3937 "AND $dst,$dst,$mask" %} 3938 3939 ins_encode %{ 3940 __ ldr($dst$$Register, $mem$$Address); 3941 __ mov($dst$$Register->successor(), 0); 3942 __ andr($dst$$Register, $dst$$Register, $mask$$constant); 3943 %} 3944 ins_pipe(iload_mem); 3945 %} 3946 3947 // Load Integer with a 31-bit mask into a Long Register 3948 // FIXME: use iRegI mask, remove tmp? 3949 instruct loadI2L_immU31(iRegL dst, memoryI mem, immU31 mask, iRegI tmp) %{ 3950 match(Set dst (ConvI2L (AndI (LoadI mem) mask))); 3951 effect(TEMP dst, TEMP tmp); 3952 3953 ins_cost(MEMORY_REF_COST + 4*DEFAULT_COST); 3954 size(20); 3955 format %{ "LDR $mem,$dst\t! int & 31-bit mask -> long\n\t" 3956 "MOV $dst.hi, 0\n\t" 3957 "MOV_SLOW $tmp,$mask\n\t" 3958 "AND $dst,$tmp,$dst" %} 3959 ins_encode %{ 3960 __ ldr($dst$$Register, $mem$$Address); 3961 __ mov($dst$$Register->successor(), 0); 3962 __ mov_slow($tmp$$Register, $mask$$constant); 3963 __ andr($dst$$Register, $dst$$Register, $tmp$$Register); 3964 %} 3965 ins_pipe(iload_mem); 3966 %} 3967 3968 // Load Unsigned Integer into a Long Register 3969 instruct loadUI2L(iRegL dst, memoryI mem, immL_32bits mask) %{ 3970 match(Set dst (AndL (ConvI2L (LoadI mem)) mask)); 3971 ins_cost(MEMORY_REF_COST); 3972 3973 size(8); 3974 format %{ "LDR $dst.lo,$mem\t! uint -> long\n\t" 3975 "MOV $dst.hi,0" %} 3976 ins_encode %{ 3977 __ ldr($dst$$Register, $mem$$Address); 3978 __ mov($dst$$Register->successor(), 0); 3979 %} 3980 ins_pipe(iload_mem); 3981 %} 3982 3983 // Load Long 3984 3985 3986 instruct loadL(iRegLd dst, memoryL mem ) %{ 3987 predicate(!((LoadLNode*)n)->require_atomic_access()); 3988 match(Set dst (LoadL mem)); 3989 effect(TEMP dst); 3990 ins_cost(MEMORY_REF_COST); 3991 3992 size(4); 3993 format %{ "ldr_64 $dst,$mem\t! long" %} 3994 ins_encode %{ 3995 __ ldr_64($dst$$Register, $mem$$Address); 3996 %} 3997 ins_pipe(iload_mem); 3998 %} 3999 4000 instruct loadL_2instr(iRegL dst, memorylong mem ) %{ 4001 predicate(!((LoadLNode*)n)->require_atomic_access()); 4002 match(Set dst (LoadL mem)); 4003 ins_cost(MEMORY_REF_COST + DEFAULT_COST); 4004 4005 size(8); 4006 format %{ "LDR $dst.lo,$mem \t! long order of instrs reversed if $dst.lo == base($mem)\n\t" 4007 "LDR $dst.hi,$mem+4 or $mem" %} 4008 ins_encode %{ 4009 Address Amemlo = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none); 4010 Address Amemhi = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp + 4, relocInfo::none); 4011 4012 if ($dst$$Register == reg_to_register_object($mem$$base)) { 4013 __ ldr($dst$$Register->successor(), Amemhi); 4014 __ ldr($dst$$Register, Amemlo); 4015 } else { 4016 __ ldr($dst$$Register, Amemlo); 4017 __ ldr($dst$$Register->successor(), Amemhi); 4018 } 4019 %} 4020 ins_pipe(iload_mem); 4021 %} 4022 4023 instruct loadL_volatile(iRegL dst, indirect mem ) %{ 4024 predicate(((LoadLNode*)n)->require_atomic_access()); 4025 match(Set dst (LoadL mem)); 4026 ins_cost(MEMORY_REF_COST); 4027 4028 size(4); 4029 format %{ "LDMIA $dst,$mem\t! long" %} 4030 ins_encode %{ 4031 // FIXME: why is ldmia considered atomic? Should be ldrexd 4032 RegisterSet set($dst$$Register); 4033 set = set | reg_to_register_object($dst$$reg + 1); 4034 __ ldmia(reg_to_register_object($mem$$base), set); 4035 %} 4036 ins_pipe(iload_mem); 4037 %} 4038 4039 instruct loadL_volatile_fp(iRegL dst, memoryD mem ) %{ 4040 predicate(((LoadLNode*)n)->require_atomic_access()); 4041 match(Set dst (LoadL mem)); 4042 ins_cost(MEMORY_REF_COST); 4043 4044 size(8); 4045 format %{ "FLDD S14, $mem" 4046 "FMRRD $dst, S14\t! long \n't" %} 4047 ins_encode %{ 4048 __ fldd(S14, $mem$$Address); 4049 __ fmrrd($dst$$Register, $dst$$Register->successor(), S14); 4050 %} 4051 ins_pipe(iload_mem); 4052 %} 4053 4054 instruct loadL_unaligned(iRegL dst, memorylong mem ) %{ 4055 match(Set dst (LoadL_unaligned mem)); 4056 ins_cost(MEMORY_REF_COST); 4057 4058 size(8); 4059 format %{ "LDR $dst.lo,$mem\t! long order of instrs reversed if $dst.lo == base($mem)\n\t" 4060 "LDR $dst.hi,$mem+4" %} 4061 ins_encode %{ 4062 Address Amemlo = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none); 4063 Address Amemhi = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp + 4, relocInfo::none); 4064 4065 if ($dst$$Register == reg_to_register_object($mem$$base)) { 4066 __ ldr($dst$$Register->successor(), Amemhi); 4067 __ ldr($dst$$Register, Amemlo); 4068 } else { 4069 __ ldr($dst$$Register, Amemlo); 4070 __ ldr($dst$$Register->successor(), Amemhi); 4071 } 4072 %} 4073 ins_pipe(iload_mem); 4074 %} 4075 4076 // Load Range 4077 instruct loadRange(iRegI dst, memoryI mem) %{ 4078 match(Set dst (LoadRange mem)); 4079 ins_cost(MEMORY_REF_COST); 4080 4081 size(4); 4082 format %{ "LDR_u32 $dst,$mem\t! range" %} 4083 ins_encode %{ 4084 __ ldr_u32($dst$$Register, $mem$$Address); 4085 %} 4086 ins_pipe(iload_mem); 4087 %} 4088 4089 // Load Pointer 4090 4091 4092 instruct loadP(iRegP dst, memoryP mem) %{ 4093 match(Set dst (LoadP mem)); 4094 ins_cost(MEMORY_REF_COST); 4095 size(4); 4096 4097 format %{ "LDR $dst,$mem\t! ptr" %} 4098 ins_encode %{ 4099 __ ldr($dst$$Register, $mem$$Address); 4100 %} 4101 ins_pipe(iload_mem); 4102 %} 4103 4104 #ifdef XXX 4105 // FIXME XXXX 4106 //instruct loadSP(iRegP dst, memoryP mem) %{ 4107 instruct loadSP(SPRegP dst, memoryP mem, iRegP tmp) %{ 4108 match(Set dst (LoadP mem)); 4109 effect(TEMP tmp); 4110 ins_cost(MEMORY_REF_COST+1); 4111 size(8); 4112 4113 format %{ "LDR $tmp,$mem\t! ptr\n\t" 4114 "MOV $dst,$tmp\t! ptr" %} 4115 ins_encode %{ 4116 __ ldr($tmp$$Register, $mem$$Address); 4117 __ mov($dst$$Register, $tmp$$Register); 4118 %} 4119 ins_pipe(iload_mem); 4120 %} 4121 #endif 4122 4123 #ifdef _LP64 4124 // Load Compressed Pointer 4125 4126 // XXX This variant shouldn't be necessary if 6217251 is implemented 4127 instruct loadNoff(iRegN dst, memoryScaledI mem, aimmX off, iRegP tmp) %{ 4128 match(Set dst (LoadN (AddP mem off))); 4129 ins_cost(MEMORY_REF_COST + DEFAULT_COST); // assume shift/sign-extend is free 4130 effect(TEMP tmp); 4131 size(4 * 2); 4132 4133 format %{ "ldr_u32 $dst,$mem+$off\t! compressed ptr temp=$tmp" %} 4134 ins_encode %{ 4135 Register base = reg_to_register_object($mem$$base); 4136 __ add($tmp$$Register, base, $off$$constant); 4137 Address nmem = Address::make_raw($tmp$$reg, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none); 4138 __ ldr_u32($dst$$Register, nmem); 4139 %} 4140 ins_pipe(iload_mem); 4141 %} 4142 4143 instruct loadN(iRegN dst, memoryI mem) %{ 4144 match(Set dst (LoadN mem)); 4145 ins_cost(MEMORY_REF_COST); 4146 size(4); 4147 4148 format %{ "ldr_u32 $dst,$mem\t! compressed ptr" %} 4149 ins_encode %{ 4150 __ ldr_u32($dst$$Register, $mem$$Address); 4151 %} 4152 ins_pipe(iload_mem); 4153 %} 4154 #endif 4155 4156 // Load Klass Pointer 4157 instruct loadKlass(iRegP dst, memoryI mem) %{ 4158 match(Set dst (LoadKlass mem)); 4159 ins_cost(MEMORY_REF_COST); 4160 size(4); 4161 4162 format %{ "LDR $dst,$mem\t! klass ptr" %} 4163 ins_encode %{ 4164 __ ldr($dst$$Register, $mem$$Address); 4165 %} 4166 ins_pipe(iload_mem); 4167 %} 4168 4169 #ifdef _LP64 4170 // Load narrow Klass Pointer 4171 instruct loadNKlass(iRegN dst, memoryI mem) %{ 4172 match(Set dst (LoadNKlass mem)); 4173 ins_cost(MEMORY_REF_COST); 4174 size(4); 4175 4176 format %{ "ldr_u32 $dst,$mem\t! compressed klass ptr" %} 4177 ins_encode %{ 4178 __ ldr_u32($dst$$Register, $mem$$Address); 4179 %} 4180 ins_pipe(iload_mem); 4181 %} 4182 #endif 4183 4184 4185 instruct loadD(regD dst, memoryD mem) %{ 4186 match(Set dst (LoadD mem)); 4187 ins_cost(MEMORY_REF_COST); 4188 4189 size(4); 4190 // FIXME: needs to be atomic, but ARMv7 A.R.M. guarantees 4191 // only LDREXD and STREXD are 64-bit single-copy atomic 4192 format %{ "FLDD $dst,$mem" %} 4193 ins_encode %{ 4194 __ ldr_double($dst$$FloatRegister, $mem$$Address); 4195 %} 4196 ins_pipe(floadD_mem); 4197 %} 4198 4199 // Load Double - UNaligned 4200 instruct loadD_unaligned(regD_low dst, memoryF2 mem ) %{ 4201 match(Set dst (LoadD_unaligned mem)); 4202 ins_cost(MEMORY_REF_COST*2+DEFAULT_COST); 4203 size(8); 4204 format %{ "FLDS $dst.lo,$mem\t! misaligned double\n" 4205 "\tFLDS $dst.hi,$mem+4\t!" %} 4206 ins_encode %{ 4207 Address Amemlo = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none); 4208 Address Amemhi = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp + 4, relocInfo::none); 4209 __ flds($dst$$FloatRegister, Amemlo); 4210 __ flds($dst$$FloatRegister->successor(), Amemhi); 4211 %} 4212 ins_pipe(iload_mem); 4213 %} 4214 4215 4216 instruct loadF(regF dst, memoryF mem) %{ 4217 match(Set dst (LoadF mem)); 4218 4219 ins_cost(MEMORY_REF_COST); 4220 size(4); 4221 format %{ "FLDS $dst,$mem" %} 4222 ins_encode %{ 4223 __ ldr_float($dst$$FloatRegister, $mem$$Address); 4224 %} 4225 ins_pipe(floadF_mem); 4226 %} 4227 4228 4229 // // Load Constant 4230 instruct loadConI( iRegI dst, immI src ) %{ 4231 match(Set dst src); 4232 ins_cost(DEFAULT_COST * 3/2); 4233 format %{ "MOV_SLOW $dst, $src" %} 4234 ins_encode %{ 4235 __ mov_slow($dst$$Register, $src$$constant); 4236 %} 4237 ins_pipe(ialu_hi_lo_reg); 4238 %} 4239 4240 instruct loadConIMov( iRegI dst, immIMov src ) %{ 4241 match(Set dst src); 4242 size(4); 4243 format %{ "MOV $dst, $src" %} 4244 ins_encode %{ 4245 __ mov($dst$$Register, $src$$constant); 4246 %} 4247 ins_pipe(ialu_imm); 4248 %} 4249 4250 instruct loadConIMovn( iRegI dst, immIRotn src ) %{ 4251 match(Set dst src); 4252 size(4); 4253 format %{ "MVN $dst, ~$src" %} 4254 ins_encode %{ 4255 __ mvn($dst$$Register, ~$src$$constant); 4256 %} 4257 ins_pipe(ialu_imm_n); 4258 %} 4259 4260 instruct loadConI16( iRegI dst, immI16 src ) %{ 4261 match(Set dst src); 4262 size(4); 4263 format %{ "MOVW $dst, $src" %} 4264 ins_encode %{ 4265 __ movw($dst$$Register, $src$$constant); 4266 %} 4267 ins_pipe(ialu_imm_n); 4268 %} 4269 4270 instruct loadConP(iRegP dst, immP src) %{ 4271 match(Set dst src); 4272 ins_cost(DEFAULT_COST * 3/2); 4273 format %{ "MOV_SLOW $dst,$src\t!ptr" %} 4274 ins_encode %{ 4275 relocInfo::relocType constant_reloc = _opnds[1]->constant_reloc(); 4276 intptr_t val = $src$$constant; 4277 if (constant_reloc == relocInfo::oop_type) { 4278 __ mov_oop($dst$$Register, (jobject)val); 4279 } else if (constant_reloc == relocInfo::metadata_type) { 4280 __ mov_metadata($dst$$Register, (Metadata*)val); 4281 } else { 4282 __ mov_slow($dst$$Register, val); 4283 } 4284 %} 4285 ins_pipe(loadConP); 4286 %} 4287 4288 4289 instruct loadConL(iRegL dst, immL src) %{ 4290 match(Set dst src); 4291 ins_cost(DEFAULT_COST * 4); 4292 format %{ "MOV_SLOW $dst.lo, $src & 0x0FFFFFFFFL \t! long\n\t" 4293 "MOV_SLOW $dst.hi, $src >> 32" %} 4294 ins_encode %{ 4295 __ mov_slow(reg_to_register_object($dst$$reg), $src$$constant & 0x0FFFFFFFFL); 4296 __ mov_slow(reg_to_register_object($dst$$reg + 1), ((julong)($src$$constant)) >> 32); 4297 %} 4298 ins_pipe(loadConL); 4299 %} 4300 4301 instruct loadConL16( iRegL dst, immL16 src ) %{ 4302 match(Set dst src); 4303 ins_cost(DEFAULT_COST * 2); 4304 4305 size(8); 4306 format %{ "MOVW $dst.lo, $src \n\t" 4307 "MOVW $dst.hi, 0 \n\t" %} 4308 ins_encode %{ 4309 __ movw($dst$$Register, $src$$constant); 4310 __ movw($dst$$Register->successor(), 0); 4311 %} 4312 ins_pipe(ialu_imm); 4313 %} 4314 4315 instruct loadConF_imm8(regF dst, imm8F src) %{ 4316 match(Set dst src); 4317 ins_cost(DEFAULT_COST); 4318 size(4); 4319 4320 format %{ "FCONSTS $dst, $src"%} 4321 4322 ins_encode %{ 4323 __ fconsts($dst$$FloatRegister, Assembler::float_num($src$$constant).imm8()); 4324 %} 4325 ins_pipe(loadConFD); // FIXME 4326 %} 4327 4328 4329 instruct loadConF(regF dst, immF src, iRegI tmp) %{ 4330 match(Set dst src); 4331 ins_cost(DEFAULT_COST * 2); 4332 effect(TEMP tmp); 4333 size(3*4); 4334 4335 format %{ "MOV_SLOW $tmp, $src\n\t" 4336 "FMSR $dst, $tmp"%} 4337 4338 ins_encode %{ 4339 // FIXME revisit once 6961697 is in 4340 union { 4341 jfloat f; 4342 int i; 4343 } v; 4344 v.f = $src$$constant; 4345 __ mov_slow($tmp$$Register, v.i); 4346 __ fmsr($dst$$FloatRegister, $tmp$$Register); 4347 %} 4348 ins_pipe(loadConFD); // FIXME 4349 %} 4350 4351 instruct loadConD_imm8(regD dst, imm8D src) %{ 4352 match(Set dst src); 4353 ins_cost(DEFAULT_COST); 4354 size(4); 4355 4356 format %{ "FCONSTD $dst, $src"%} 4357 4358 ins_encode %{ 4359 __ fconstd($dst$$FloatRegister, Assembler::double_num($src$$constant).imm8()); 4360 %} 4361 ins_pipe(loadConFD); // FIXME 4362 %} 4363 4364 instruct loadConD(regD dst, immD src, iRegP tmp) %{ 4365 match(Set dst src); 4366 effect(TEMP tmp); 4367 ins_cost(MEMORY_REF_COST); 4368 format %{ "FLDD $dst, [$constanttablebase + $constantoffset]\t! load from constant table: double=$src" %} 4369 4370 ins_encode %{ 4371 Register r = $constanttablebase; 4372 int offset = $constantoffset($src); 4373 if (!is_memoryD(offset)) { // can't use a predicate 4374 // in load constant instructs 4375 __ add_slow($tmp$$Register, r, offset); 4376 r = $tmp$$Register; 4377 offset = 0; 4378 } 4379 __ ldr_double($dst$$FloatRegister, Address(r, offset)); 4380 %} 4381 ins_pipe(loadConFD); 4382 %} 4383 4384 // Prefetch instructions. 4385 // Must be safe to execute with invalid address (cannot fault). 4386 4387 instruct prefetchAlloc_mp( memoryP mem ) %{ 4388 predicate(VM_Version::has_multiprocessing_extensions()); 4389 match( PrefetchAllocation mem ); 4390 ins_cost(MEMORY_REF_COST); 4391 size(4); 4392 4393 format %{ "PLDW $mem\t! Prefetch allocation" %} 4394 ins_encode %{ 4395 __ pldw($mem$$Address); 4396 %} 4397 ins_pipe(iload_mem); 4398 %} 4399 4400 instruct prefetchAlloc_sp( memoryP mem ) %{ 4401 predicate(!VM_Version::has_multiprocessing_extensions()); 4402 match( PrefetchAllocation mem ); 4403 ins_cost(MEMORY_REF_COST); 4404 size(4); 4405 4406 format %{ "PLD $mem\t! Prefetch allocation" %} 4407 ins_encode %{ 4408 __ pld($mem$$Address); 4409 %} 4410 ins_pipe(iload_mem); 4411 %} 4412 4413 4414 //----------Store Instructions------------------------------------------------- 4415 // Store Byte 4416 instruct storeB(memoryB mem, store_RegI src) %{ 4417 match(Set mem (StoreB mem src)); 4418 ins_cost(MEMORY_REF_COST); 4419 4420 size(4); 4421 format %{ "STRB $src,$mem\t! byte" %} 4422 ins_encode %{ 4423 __ strb($src$$Register, $mem$$Address); 4424 %} 4425 ins_pipe(istore_mem_reg); 4426 %} 4427 4428 instruct storeCM(memoryB mem, store_RegI src) %{ 4429 match(Set mem (StoreCM mem src)); 4430 ins_cost(MEMORY_REF_COST); 4431 4432 size(4); 4433 format %{ "STRB $src,$mem\t! CMS card-mark byte" %} 4434 ins_encode %{ 4435 __ strb($src$$Register, $mem$$Address); 4436 %} 4437 ins_pipe(istore_mem_reg); 4438 %} 4439 4440 // Store Char/Short 4441 4442 4443 instruct storeC(memoryS mem, store_RegI src) %{ 4444 match(Set mem (StoreC mem src)); 4445 ins_cost(MEMORY_REF_COST); 4446 4447 size(4); 4448 format %{ "STRH $src,$mem\t! short" %} 4449 ins_encode %{ 4450 __ strh($src$$Register, $mem$$Address); 4451 %} 4452 ins_pipe(istore_mem_reg); 4453 %} 4454 4455 // Store Integer 4456 4457 4458 instruct storeI(memoryI mem, store_RegI src) %{ 4459 match(Set mem (StoreI mem src)); 4460 ins_cost(MEMORY_REF_COST); 4461 4462 size(4); 4463 format %{ "str_32 $src,$mem" %} 4464 ins_encode %{ 4465 __ str_32($src$$Register, $mem$$Address); 4466 %} 4467 ins_pipe(istore_mem_reg); 4468 %} 4469 4470 // Store Long 4471 4472 4473 instruct storeL(memoryL mem, store_RegLd src) %{ 4474 predicate(!((StoreLNode*)n)->require_atomic_access()); 4475 match(Set mem (StoreL mem src)); 4476 ins_cost(MEMORY_REF_COST); 4477 4478 size(4); 4479 format %{ "str_64 $src,$mem\t! long\n\t" %} 4480 4481 ins_encode %{ 4482 __ str_64($src$$Register, $mem$$Address); 4483 %} 4484 ins_pipe(istore_mem_reg); 4485 %} 4486 4487 instruct storeL_2instr(memorylong mem, iRegL src) %{ 4488 predicate(!((StoreLNode*)n)->require_atomic_access()); 4489 match(Set mem (StoreL mem src)); 4490 ins_cost(MEMORY_REF_COST + DEFAULT_COST); 4491 4492 size(8); 4493 format %{ "STR $src.lo,$mem\t! long\n\t" 4494 "STR $src.hi,$mem+4" %} 4495 4496 ins_encode %{ 4497 Address Amemlo = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp, relocInfo::none); 4498 Address Amemhi = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp + 4, relocInfo::none); 4499 __ str($src$$Register, Amemlo); 4500 __ str($src$$Register->successor(), Amemhi); 4501 %} 4502 ins_pipe(istore_mem_reg); 4503 %} 4504 4505 instruct storeL_volatile(indirect mem, iRegL src) %{ 4506 predicate(((StoreLNode*)n)->require_atomic_access()); 4507 match(Set mem (StoreL mem src)); 4508 ins_cost(MEMORY_REF_COST); 4509 size(4); 4510 format %{ "STMIA $src,$mem\t! long" %} 4511 ins_encode %{ 4512 // FIXME: why is stmia considered atomic? Should be strexd 4513 RegisterSet set($src$$Register); 4514 set = set | reg_to_register_object($src$$reg + 1); 4515 __ stmia(reg_to_register_object($mem$$base), set); 4516 %} 4517 ins_pipe(istore_mem_reg); 4518 %} 4519 4520 instruct storeL_volatile_fp(memoryD mem, iRegL src) %{ 4521 predicate(((StoreLNode*)n)->require_atomic_access()); 4522 match(Set mem (StoreL mem src)); 4523 ins_cost(MEMORY_REF_COST); 4524 size(8); 4525 format %{ "FMDRR S14, $src\t! long \n\t" 4526 "FSTD S14, $mem" %} 4527 ins_encode %{ 4528 __ fmdrr(S14, $src$$Register, $src$$Register->successor()); 4529 __ fstd(S14, $mem$$Address); 4530 %} 4531 ins_pipe(istore_mem_reg); 4532 %} 4533 4534 #ifdef XXX 4535 // Move SP Pointer 4536 //instruct movSP(sp_ptr_RegP dst, SPRegP src) %{ 4537 //instruct movSP(iRegP dst, SPRegP src) %{ 4538 instruct movSP(store_ptr_RegP dst, SPRegP src) %{ 4539 match(Set dst src); 4540 //predicate(!_kids[1]->_leaf->is_Proj() || _kids[1]->_leaf->as_Proj()->_con == TypeFunc::FramePtr); 4541 ins_cost(MEMORY_REF_COST); 4542 size(4); 4543 4544 format %{ "MOV $dst,$src\t! SP ptr\n\t" %} 4545 ins_encode %{ 4546 assert(false, "XXX1 got here"); 4547 __ mov($dst$$Register, SP); 4548 __ mov($dst$$Register, $src$$Register); 4549 %} 4550 ins_pipe(ialu_reg); 4551 %} 4552 #endif 4553 4554 4555 // Store Pointer 4556 4557 4558 instruct storeP(memoryP mem, store_ptr_RegP src) %{ 4559 match(Set mem (StoreP mem src)); 4560 ins_cost(MEMORY_REF_COST); 4561 size(4); 4562 4563 format %{ "STR $src,$mem\t! ptr" %} 4564 ins_encode %{ 4565 __ str($src$$Register, $mem$$Address); 4566 %} 4567 ins_pipe(istore_mem_spORreg); 4568 %} 4569 4570 4571 #ifdef _LP64 4572 // Store Compressed Pointer 4573 4574 4575 instruct storeN(memoryI mem, store_RegN src) %{ 4576 match(Set mem (StoreN mem src)); 4577 ins_cost(MEMORY_REF_COST); 4578 size(4); 4579 4580 format %{ "str_32 $src,$mem\t! compressed ptr" %} 4581 ins_encode %{ 4582 __ str_32($src$$Register, $mem$$Address); 4583 %} 4584 ins_pipe(istore_mem_reg); 4585 %} 4586 4587 4588 // Store Compressed Klass Pointer 4589 instruct storeNKlass(memoryI mem, store_RegN src) %{ 4590 match(Set mem (StoreNKlass mem src)); 4591 ins_cost(MEMORY_REF_COST); 4592 size(4); 4593 4594 format %{ "str_32 $src,$mem\t! compressed klass ptr" %} 4595 ins_encode %{ 4596 __ str_32($src$$Register, $mem$$Address); 4597 %} 4598 ins_pipe(istore_mem_reg); 4599 %} 4600 #endif 4601 4602 // Store Double 4603 4604 4605 instruct storeD(memoryD mem, regD src) %{ 4606 match(Set mem (StoreD mem src)); 4607 ins_cost(MEMORY_REF_COST); 4608 4609 size(4); 4610 // FIXME: needs to be atomic, but ARMv7 A.R.M. guarantees 4611 // only LDREXD and STREXD are 64-bit single-copy atomic 4612 format %{ "FSTD $src,$mem" %} 4613 ins_encode %{ 4614 __ str_double($src$$FloatRegister, $mem$$Address); 4615 %} 4616 ins_pipe(fstoreD_mem_reg); 4617 %} 4618 4619 4620 // Store Float 4621 4622 4623 instruct storeF( memoryF mem, regF src) %{ 4624 match(Set mem (StoreF mem src)); 4625 ins_cost(MEMORY_REF_COST); 4626 4627 size(4); 4628 format %{ "FSTS $src,$mem" %} 4629 ins_encode %{ 4630 __ str_float($src$$FloatRegister, $mem$$Address); 4631 %} 4632 ins_pipe(fstoreF_mem_reg); 4633 %} 4634 4635 4636 //----------MemBar Instructions----------------------------------------------- 4637 // Memory barrier flavors 4638 4639 // pattern-match out unnecessary membars 4640 instruct membar_storestore() %{ 4641 match(MemBarStoreStore); 4642 ins_cost(4*MEMORY_REF_COST); 4643 4644 size(4); 4645 format %{ "MEMBAR-storestore" %} 4646 ins_encode %{ 4647 __ membar(MacroAssembler::Membar_mask_bits(MacroAssembler::StoreStore), noreg); 4648 %} 4649 ins_pipe(long_memory_op); 4650 %} 4651 4652 instruct membar_acquire() %{ 4653 match(MemBarAcquire); 4654 match(LoadFence); 4655 ins_cost(4*MEMORY_REF_COST); 4656 4657 size(4); 4658 format %{ "MEMBAR-acquire" %} 4659 ins_encode %{ 4660 __ membar(MacroAssembler::Membar_mask_bits(MacroAssembler::LoadLoad | MacroAssembler::LoadStore), noreg); 4661 %} 4662 ins_pipe(long_memory_op); 4663 %} 4664 4665 instruct membar_acquire_lock() %{ 4666 match(MemBarAcquireLock); 4667 ins_cost(0); 4668 4669 size(0); 4670 format %{ "!MEMBAR-acquire (CAS in prior FastLock so empty encoding)" %} 4671 ins_encode( ); 4672 ins_pipe(empty); 4673 %} 4674 4675 instruct membar_release() %{ 4676 match(MemBarRelease); 4677 match(StoreFence); 4678 ins_cost(4*MEMORY_REF_COST); 4679 4680 size(4); 4681 format %{ "MEMBAR-release" %} 4682 ins_encode %{ 4683 __ membar(MacroAssembler::Membar_mask_bits(MacroAssembler::StoreStore | MacroAssembler::LoadStore), noreg); 4684 %} 4685 ins_pipe(long_memory_op); 4686 %} 4687 4688 instruct membar_release_lock() %{ 4689 match(MemBarReleaseLock); 4690 ins_cost(0); 4691 4692 size(0); 4693 format %{ "!MEMBAR-release (CAS in succeeding FastUnlock so empty encoding)" %} 4694 ins_encode( ); 4695 ins_pipe(empty); 4696 %} 4697 4698 instruct membar_volatile() %{ 4699 match(MemBarVolatile); 4700 ins_cost(4*MEMORY_REF_COST); 4701 4702 size(4); 4703 format %{ "MEMBAR-volatile" %} 4704 ins_encode %{ 4705 __ membar(MacroAssembler::StoreLoad, noreg); 4706 %} 4707 ins_pipe(long_memory_op); 4708 %} 4709 4710 instruct unnecessary_membar_volatile() %{ 4711 match(MemBarVolatile); 4712 predicate(Matcher::post_store_load_barrier(n)); 4713 ins_cost(0); 4714 4715 size(0); 4716 format %{ "!MEMBAR-volatile (unnecessary so empty encoding)" %} 4717 ins_encode( ); 4718 ins_pipe(empty); 4719 %} 4720 4721 //----------Register Move Instructions----------------------------------------- 4722 // instruct roundDouble_nop(regD dst) %{ 4723 // match(Set dst (RoundDouble dst)); 4724 // ins_pipe(empty); 4725 // %} 4726 4727 4728 // instruct roundFloat_nop(regF dst) %{ 4729 // match(Set dst (RoundFloat dst)); 4730 // ins_pipe(empty); 4731 // %} 4732 4733 4734 4735 // Cast Index to Pointer for unsafe natives 4736 instruct castX2P(iRegX src, iRegP dst) %{ 4737 match(Set dst (CastX2P src)); 4738 4739 format %{ "MOV $dst,$src\t! IntX->Ptr if $dst != $src" %} 4740 ins_encode %{ 4741 if ($dst$$Register != $src$$Register) { 4742 __ mov($dst$$Register, $src$$Register); 4743 } 4744 %} 4745 ins_pipe(ialu_reg); 4746 %} 4747 4748 // Cast Pointer to Index for unsafe natives 4749 instruct castP2X(iRegP src, iRegX dst) %{ 4750 match(Set dst (CastP2X src)); 4751 4752 format %{ "MOV $dst,$src\t! Ptr->IntX if $dst != $src" %} 4753 ins_encode %{ 4754 if ($dst$$Register != $src$$Register) { 4755 __ mov($dst$$Register, $src$$Register); 4756 } 4757 %} 4758 ins_pipe(ialu_reg); 4759 %} 4760 4761 //----------Conditional Move--------------------------------------------------- 4762 // Conditional move 4763 instruct cmovIP_reg(cmpOpP cmp, flagsRegP pcc, iRegI dst, iRegI src) %{ 4764 match(Set dst (CMoveI (Binary cmp pcc) (Binary dst src))); 4765 ins_cost(150); 4766 size(4); 4767 format %{ "MOV$cmp $dst,$src\t! int" %} 4768 ins_encode %{ 4769 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 4770 %} 4771 ins_pipe(ialu_reg); 4772 %} 4773 4774 4775 instruct cmovIP_immMov(cmpOpP cmp, flagsRegP pcc, iRegI dst, immIMov src) %{ 4776 match(Set dst (CMoveI (Binary cmp pcc) (Binary dst src))); 4777 ins_cost(140); 4778 size(4); 4779 format %{ "MOV$cmp $dst,$src" %} 4780 ins_encode %{ 4781 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 4782 %} 4783 ins_pipe(ialu_imm); 4784 %} 4785 4786 instruct cmovIP_imm16(cmpOpP cmp, flagsRegP pcc, iRegI dst, immI16 src) %{ 4787 match(Set dst (CMoveI (Binary cmp pcc) (Binary dst src))); 4788 ins_cost(140); 4789 size(4); 4790 format %{ "MOVw$cmp $dst,$src" %} 4791 ins_encode %{ 4792 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 4793 %} 4794 ins_pipe(ialu_imm); 4795 %} 4796 4797 instruct cmovI_reg(cmpOp cmp, flagsReg icc, iRegI dst, iRegI src) %{ 4798 match(Set dst (CMoveI (Binary cmp icc) (Binary dst src))); 4799 ins_cost(150); 4800 size(4); 4801 format %{ "MOV$cmp $dst,$src" %} 4802 ins_encode %{ 4803 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 4804 %} 4805 ins_pipe(ialu_reg); 4806 %} 4807 4808 4809 instruct cmovI_immMov(cmpOp cmp, flagsReg icc, iRegI dst, immIMov src) %{ 4810 match(Set dst (CMoveI (Binary cmp icc) (Binary dst src))); 4811 ins_cost(140); 4812 size(4); 4813 format %{ "MOV$cmp $dst,$src" %} 4814 ins_encode %{ 4815 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 4816 %} 4817 ins_pipe(ialu_imm); 4818 %} 4819 4820 instruct cmovII_imm16(cmpOp cmp, flagsReg icc, iRegI dst, immI16 src) %{ 4821 match(Set dst (CMoveI (Binary cmp icc) (Binary dst src))); 4822 ins_cost(140); 4823 size(4); 4824 format %{ "MOVw$cmp $dst,$src" %} 4825 ins_encode %{ 4826 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 4827 %} 4828 ins_pipe(ialu_imm); 4829 %} 4830 4831 instruct cmovII_reg_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegI dst, iRegI src) %{ 4832 match(Set dst (CMoveI (Binary cmp icc) (Binary dst src))); 4833 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || 4834 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne || 4835 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || 4836 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge); 4837 ins_cost(150); 4838 size(4); 4839 format %{ "MOV$cmp $dst,$src" %} 4840 ins_encode %{ 4841 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 4842 %} 4843 ins_pipe(ialu_reg); 4844 %} 4845 4846 instruct cmovII_immMov_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegI dst, immIMov src) %{ 4847 match(Set dst (CMoveI (Binary cmp icc) (Binary dst src))); 4848 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || 4849 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne || 4850 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || 4851 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge); 4852 ins_cost(140); 4853 size(4); 4854 format %{ "MOV$cmp $dst,$src" %} 4855 ins_encode %{ 4856 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 4857 %} 4858 ins_pipe(ialu_imm); 4859 %} 4860 4861 instruct cmovII_imm16_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegI dst, immI16 src) %{ 4862 match(Set dst (CMoveI (Binary cmp icc) (Binary dst src))); 4863 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || 4864 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne || 4865 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || 4866 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge); 4867 ins_cost(140); 4868 size(4); 4869 format %{ "MOVW$cmp $dst,$src" %} 4870 ins_encode %{ 4871 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 4872 %} 4873 ins_pipe(ialu_imm); 4874 %} 4875 4876 instruct cmovIIu_reg(cmpOpU cmp, flagsRegU icc, iRegI dst, iRegI src) %{ 4877 match(Set dst (CMoveI (Binary cmp icc) (Binary dst src))); 4878 ins_cost(150); 4879 size(4); 4880 format %{ "MOV$cmp $dst,$src" %} 4881 ins_encode %{ 4882 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 4883 %} 4884 ins_pipe(ialu_reg); 4885 %} 4886 4887 instruct cmovIIu_immMov(cmpOpU cmp, flagsRegU icc, iRegI dst, immIMov src) %{ 4888 match(Set dst (CMoveI (Binary cmp icc) (Binary dst src))); 4889 ins_cost(140); 4890 size(4); 4891 format %{ "MOV$cmp $dst,$src" %} 4892 ins_encode %{ 4893 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 4894 %} 4895 ins_pipe(ialu_imm); 4896 %} 4897 4898 instruct cmovIIu_imm16(cmpOpU cmp, flagsRegU icc, iRegI dst, immI16 src) %{ 4899 match(Set dst (CMoveI (Binary cmp icc) (Binary dst src))); 4900 ins_cost(140); 4901 size(4); 4902 format %{ "MOVW$cmp $dst,$src" %} 4903 ins_encode %{ 4904 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 4905 %} 4906 ins_pipe(ialu_imm); 4907 %} 4908 4909 // Conditional move 4910 instruct cmovPP_reg(cmpOpP cmp, flagsRegP pcc, iRegP dst, iRegP src) %{ 4911 match(Set dst (CMoveP (Binary cmp pcc) (Binary dst src))); 4912 ins_cost(150); 4913 size(4); 4914 format %{ "MOV$cmp $dst,$src" %} 4915 ins_encode %{ 4916 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 4917 %} 4918 ins_pipe(ialu_reg); 4919 %} 4920 4921 instruct cmovPP_imm(cmpOpP cmp, flagsRegP pcc, iRegP dst, immP0 src) %{ 4922 match(Set dst (CMoveP (Binary cmp pcc) (Binary dst src))); 4923 ins_cost(140); 4924 size(4); 4925 format %{ "MOV$cmp $dst,$src" %} 4926 ins_encode %{ 4927 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 4928 %} 4929 ins_pipe(ialu_imm); 4930 %} 4931 4932 // This instruction also works with CmpN so we don't need cmovPN_reg. 4933 instruct cmovPI_reg(cmpOp cmp, flagsReg icc, iRegP dst, iRegP src) %{ 4934 match(Set dst (CMoveP (Binary cmp icc) (Binary dst src))); 4935 ins_cost(150); 4936 4937 size(4); 4938 format %{ "MOV$cmp $dst,$src\t! ptr" %} 4939 ins_encode %{ 4940 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 4941 %} 4942 ins_pipe(ialu_reg); 4943 %} 4944 4945 instruct cmovPI_reg_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegP dst, iRegP src) %{ 4946 match(Set dst (CMoveP (Binary cmp icc) (Binary dst src))); 4947 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || 4948 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne || 4949 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || 4950 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge); 4951 ins_cost(150); 4952 4953 size(4); 4954 format %{ "MOV$cmp $dst,$src\t! ptr" %} 4955 ins_encode %{ 4956 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 4957 %} 4958 ins_pipe(ialu_reg); 4959 %} 4960 4961 instruct cmovPIu_reg(cmpOpU cmp, flagsRegU icc, iRegP dst, iRegP src) %{ 4962 match(Set dst (CMoveP (Binary cmp icc) (Binary dst src))); 4963 ins_cost(150); 4964 4965 size(4); 4966 format %{ "MOV$cmp $dst,$src\t! ptr" %} 4967 ins_encode %{ 4968 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 4969 %} 4970 ins_pipe(ialu_reg); 4971 %} 4972 4973 instruct cmovPI_imm(cmpOp cmp, flagsReg icc, iRegP dst, immP0 src) %{ 4974 match(Set dst (CMoveP (Binary cmp icc) (Binary dst src))); 4975 ins_cost(140); 4976 4977 size(4); 4978 format %{ "MOV$cmp $dst,$src\t! ptr" %} 4979 ins_encode %{ 4980 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 4981 %} 4982 ins_pipe(ialu_imm); 4983 %} 4984 4985 instruct cmovPI_imm_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegP dst, immP0 src) %{ 4986 match(Set dst (CMoveP (Binary cmp icc) (Binary dst src))); 4987 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || 4988 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne || 4989 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || 4990 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge); 4991 ins_cost(140); 4992 4993 size(4); 4994 format %{ "MOV$cmp $dst,$src\t! ptr" %} 4995 ins_encode %{ 4996 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 4997 %} 4998 ins_pipe(ialu_imm); 4999 %} 5000 5001 instruct cmovPIu_imm(cmpOpU cmp, flagsRegU icc, iRegP dst, immP0 src) %{ 5002 match(Set dst (CMoveP (Binary cmp icc) (Binary dst src))); 5003 ins_cost(140); 5004 5005 size(4); 5006 format %{ "MOV$cmp $dst,$src\t! ptr" %} 5007 ins_encode %{ 5008 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 5009 %} 5010 ins_pipe(ialu_imm); 5011 %} 5012 5013 5014 // Conditional move 5015 instruct cmovFP_reg(cmpOpP cmp, flagsRegP pcc, regF dst, regF src) %{ 5016 match(Set dst (CMoveF (Binary cmp pcc) (Binary dst src))); 5017 ins_cost(150); 5018 size(4); 5019 format %{ "FCPYS$cmp $dst,$src" %} 5020 ins_encode %{ 5021 __ fcpys($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode)); 5022 %} 5023 ins_pipe(int_conditional_float_move); 5024 %} 5025 5026 instruct cmovFI_reg(cmpOp cmp, flagsReg icc, regF dst, regF src) %{ 5027 match(Set dst (CMoveF (Binary cmp icc) (Binary dst src))); 5028 ins_cost(150); 5029 5030 size(4); 5031 format %{ "FCPYS$cmp $dst,$src" %} 5032 ins_encode %{ 5033 __ fcpys($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode)); 5034 %} 5035 ins_pipe(int_conditional_float_move); 5036 %} 5037 5038 instruct cmovFI_reg_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, regF dst, regF src) %{ 5039 match(Set dst (CMoveF (Binary cmp icc) (Binary dst src))); 5040 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || 5041 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne || 5042 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || 5043 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge); 5044 ins_cost(150); 5045 5046 size(4); 5047 format %{ "FCPYS$cmp $dst,$src" %} 5048 ins_encode %{ 5049 __ fcpys($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode)); 5050 %} 5051 ins_pipe(int_conditional_float_move); 5052 %} 5053 5054 instruct cmovFIu_reg(cmpOpU cmp, flagsRegU icc, regF dst, regF src) %{ 5055 match(Set dst (CMoveF (Binary cmp icc) (Binary dst src))); 5056 ins_cost(150); 5057 5058 size(4); 5059 format %{ "FCPYS$cmp $dst,$src" %} 5060 ins_encode %{ 5061 __ fcpys($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode)); 5062 %} 5063 ins_pipe(int_conditional_float_move); 5064 %} 5065 5066 // Conditional move 5067 instruct cmovDP_reg(cmpOpP cmp, flagsRegP pcc, regD dst, regD src) %{ 5068 match(Set dst (CMoveD (Binary cmp pcc) (Binary dst src))); 5069 ins_cost(150); 5070 size(4); 5071 format %{ "FCPYD$cmp $dst,$src" %} 5072 ins_encode %{ 5073 __ fcpyd($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode)); 5074 %} 5075 ins_pipe(int_conditional_double_move); 5076 %} 5077 5078 instruct cmovDI_reg(cmpOp cmp, flagsReg icc, regD dst, regD src) %{ 5079 match(Set dst (CMoveD (Binary cmp icc) (Binary dst src))); 5080 ins_cost(150); 5081 5082 size(4); 5083 format %{ "FCPYD$cmp $dst,$src" %} 5084 ins_encode %{ 5085 __ fcpyd($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode)); 5086 %} 5087 ins_pipe(int_conditional_double_move); 5088 %} 5089 5090 instruct cmovDI_reg_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, regD dst, regD src) %{ 5091 match(Set dst (CMoveD (Binary cmp icc) (Binary dst src))); 5092 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); 5093 ins_cost(150); 5094 5095 size(4); 5096 format %{ "FCPYD$cmp $dst,$src" %} 5097 ins_encode %{ 5098 __ fcpyd($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode)); 5099 %} 5100 ins_pipe(int_conditional_double_move); 5101 %} 5102 5103 instruct cmovDIu_reg(cmpOpU cmp, flagsRegU icc, regD dst, regD src) %{ 5104 match(Set dst (CMoveD (Binary cmp icc) (Binary dst src))); 5105 ins_cost(150); 5106 5107 size(4); 5108 format %{ "FCPYD$cmp $dst,$src" %} 5109 ins_encode %{ 5110 __ fcpyd($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode)); 5111 %} 5112 ins_pipe(int_conditional_double_move); 5113 %} 5114 5115 // Conditional move 5116 instruct cmovLP_reg(cmpOpP cmp, flagsRegP pcc, iRegL dst, iRegL src) %{ 5117 match(Set dst (CMoveL (Binary cmp pcc) (Binary dst src))); 5118 ins_cost(150); 5119 5120 size(8); 5121 format %{ "MOV$cmp $dst.lo,$src.lo\t! long\n\t" 5122 "MOV$cmp $dst.hi,$src.hi" %} 5123 ins_encode %{ 5124 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 5125 __ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode)); 5126 %} 5127 ins_pipe(ialu_reg); 5128 %} 5129 5130 // TODO: try immLRot2 instead, (0, $con$$constant) becomes 5131 // (hi($con$$constant), lo($con$$constant)) becomes 5132 instruct cmovLP_immRot(cmpOpP cmp, flagsRegP pcc, iRegL dst, immLlowRot src) %{ 5133 match(Set dst (CMoveL (Binary cmp pcc) (Binary dst src))); 5134 ins_cost(140); 5135 5136 size(8); 5137 format %{ "MOV$cmp $dst.lo,$src\t! long\n\t" 5138 "MOV$cmp $dst.hi,0" %} 5139 ins_encode %{ 5140 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 5141 __ mov($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode)); 5142 %} 5143 ins_pipe(ialu_imm); 5144 %} 5145 5146 instruct cmovLP_imm16(cmpOpP cmp, flagsRegP pcc, iRegL dst, immL16 src) %{ 5147 match(Set dst (CMoveL (Binary cmp pcc) (Binary dst src))); 5148 ins_cost(140); 5149 5150 size(8); 5151 format %{ "MOV$cmp $dst.lo,$src\t! long\n\t" 5152 "MOV$cmp $dst.hi,0" %} 5153 ins_encode %{ 5154 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 5155 __ mov($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode)); 5156 %} 5157 ins_pipe(ialu_imm); 5158 %} 5159 5160 instruct cmovLI_reg(cmpOp cmp, flagsReg icc, iRegL dst, iRegL src) %{ 5161 match(Set dst (CMoveL (Binary cmp icc) (Binary dst src))); 5162 ins_cost(150); 5163 5164 size(8); 5165 format %{ "MOV$cmp $dst.lo,$src.lo\t! long\n\t" 5166 "MOV$cmp $dst.hi,$src.hi" %} 5167 ins_encode %{ 5168 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 5169 __ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode)); 5170 %} 5171 ins_pipe(ialu_reg); 5172 %} 5173 5174 instruct cmovLI_reg_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegL dst, iRegL src) %{ 5175 match(Set dst (CMoveL (Binary cmp icc) (Binary dst src))); 5176 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || 5177 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne || 5178 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || 5179 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge); 5180 ins_cost(150); 5181 5182 size(8); 5183 format %{ "MOV$cmp $dst.lo,$src.lo\t! long\n\t" 5184 "MOV$cmp $dst.hi,$src.hi" %} 5185 ins_encode %{ 5186 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 5187 __ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode)); 5188 %} 5189 ins_pipe(ialu_reg); 5190 %} 5191 5192 // TODO: try immLRot2 instead, (0, $con$$constant) becomes 5193 // (hi($con$$constant), lo($con$$constant)) becomes 5194 instruct cmovLI_immRot(cmpOp cmp, flagsReg icc, iRegL dst, immLlowRot src) %{ 5195 match(Set dst (CMoveL (Binary cmp icc) (Binary dst src))); 5196 ins_cost(140); 5197 5198 size(8); 5199 format %{ "MOV$cmp $dst.lo,$src\t! long\n\t" 5200 "MOV$cmp $dst.hi,0" %} 5201 ins_encode %{ 5202 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 5203 __ mov($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode)); 5204 %} 5205 ins_pipe(ialu_imm); 5206 %} 5207 5208 // TODO: try immLRot2 instead, (0, $con$$constant) becomes 5209 // (hi($con$$constant), lo($con$$constant)) becomes 5210 instruct cmovLI_immRot_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegL dst, immLlowRot src) %{ 5211 match(Set dst (CMoveL (Binary cmp icc) (Binary dst src))); 5212 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || 5213 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne || 5214 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || 5215 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge); 5216 ins_cost(140); 5217 5218 size(8); 5219 format %{ "MOV$cmp $dst.lo,$src\t! long\n\t" 5220 "MOV$cmp $dst.hi,0" %} 5221 ins_encode %{ 5222 __ mov($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 5223 __ mov($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode)); 5224 %} 5225 ins_pipe(ialu_imm); 5226 %} 5227 5228 instruct cmovLI_imm16(cmpOp cmp, flagsReg icc, iRegL dst, immL16 src) %{ 5229 match(Set dst (CMoveL (Binary cmp icc) (Binary dst src))); 5230 ins_cost(140); 5231 5232 size(8); 5233 format %{ "MOV$cmp $dst.lo,$src\t! long\n\t" 5234 "MOV$cmp $dst.hi,0" %} 5235 ins_encode %{ 5236 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 5237 __ movw($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode)); 5238 %} 5239 ins_pipe(ialu_imm); 5240 %} 5241 5242 instruct cmovLI_imm16_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, iRegL dst, immL16 src) %{ 5243 match(Set dst (CMoveL (Binary cmp icc) (Binary dst src))); 5244 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || 5245 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne || 5246 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || 5247 _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge); 5248 ins_cost(140); 5249 5250 size(8); 5251 format %{ "MOV$cmp $dst.lo,$src\t! long\n\t" 5252 "MOV$cmp $dst.hi,0" %} 5253 ins_encode %{ 5254 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 5255 __ movw($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode)); 5256 %} 5257 ins_pipe(ialu_imm); 5258 %} 5259 5260 instruct cmovLIu_reg(cmpOpU cmp, flagsRegU icc, iRegL dst, iRegL src) %{ 5261 match(Set dst (CMoveL (Binary cmp icc) (Binary dst src))); 5262 ins_cost(150); 5263 5264 size(8); 5265 format %{ "MOV$cmp $dst.lo,$src.lo\t! long\n\t" 5266 "MOV$cmp $dst.hi,$src.hi" %} 5267 ins_encode %{ 5268 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 5269 __ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode)); 5270 %} 5271 ins_pipe(ialu_reg); 5272 %} 5273 5274 5275 //----------OS and Locking Instructions---------------------------------------- 5276 5277 // This name is KNOWN by the ADLC and cannot be changed. 5278 // The ADLC forces a 'TypeRawPtr::BOTTOM' output type 5279 // for this guy. 5280 instruct tlsLoadP(RthreadRegP dst) %{ 5281 match(Set dst (ThreadLocal)); 5282 5283 size(0); 5284 ins_cost(0); 5285 format %{ "! TLS is in $dst" %} 5286 ins_encode( /*empty encoding*/ ); 5287 ins_pipe(ialu_none); 5288 %} 5289 5290 instruct checkCastPP( iRegP dst ) %{ 5291 match(Set dst (CheckCastPP dst)); 5292 5293 size(0); 5294 format %{ "! checkcastPP of $dst" %} 5295 ins_encode( /*empty encoding*/ ); 5296 ins_pipe(empty); 5297 %} 5298 5299 5300 instruct castPP( iRegP dst ) %{ 5301 match(Set dst (CastPP dst)); 5302 format %{ "! castPP of $dst" %} 5303 ins_encode( /*empty encoding*/ ); 5304 ins_pipe(empty); 5305 %} 5306 5307 instruct castII( iRegI dst ) %{ 5308 match(Set dst (CastII dst)); 5309 format %{ "! castII of $dst" %} 5310 ins_encode( /*empty encoding*/ ); 5311 ins_cost(0); 5312 ins_pipe(empty); 5313 %} 5314 5315 //----------Arithmetic Instructions-------------------------------------------- 5316 // Addition Instructions 5317 // Register Addition 5318 instruct addI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{ 5319 match(Set dst (AddI src1 src2)); 5320 5321 size(4); 5322 format %{ "add_32 $dst,$src1,$src2\t! int" %} 5323 ins_encode %{ 5324 __ add_32($dst$$Register, $src1$$Register, $src2$$Register); 5325 %} 5326 ins_pipe(ialu_reg_reg); 5327 %} 5328 5329 instruct addshlI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 5330 match(Set dst (AddI (LShiftI src1 src2) src3)); 5331 5332 size(4); 5333 format %{ "add_32 $dst,$src3,$src1<<$src2\t! int" %} 5334 ins_encode %{ 5335 __ add_32($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsl, $src2$$Register)); 5336 %} 5337 ins_pipe(ialu_reg_reg); 5338 %} 5339 5340 5341 instruct addshlI_reg_imm_reg(iRegI dst, iRegI src1, immU5 src2, iRegI src3) %{ 5342 match(Set dst (AddI (LShiftI src1 src2) src3)); 5343 5344 size(4); 5345 format %{ "add_32 $dst,$src3,$src1<<$src2\t! int" %} 5346 ins_encode %{ 5347 __ add_32($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsl, $src2$$constant)); 5348 %} 5349 ins_pipe(ialu_reg_reg); 5350 %} 5351 5352 instruct addsarI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 5353 match(Set dst (AddI (RShiftI src1 src2) src3)); 5354 5355 size(4); 5356 format %{ "add_32 $dst,$src3,$src1>>$src2\t! int" %} 5357 ins_encode %{ 5358 __ add_32($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, asr, $src2$$Register)); 5359 %} 5360 ins_pipe(ialu_reg_reg); 5361 %} 5362 5363 instruct addsarI_reg_imm_reg(iRegI dst, iRegI src1, immU5 src2, iRegI src3) %{ 5364 match(Set dst (AddI (RShiftI src1 src2) src3)); 5365 5366 size(4); 5367 format %{ "add_32 $dst,$src3,$src1>>$src2\t! int" %} 5368 ins_encode %{ 5369 __ add_32($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, asr, $src2$$constant)); 5370 %} 5371 ins_pipe(ialu_reg_reg); 5372 %} 5373 5374 instruct addshrI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 5375 match(Set dst (AddI (URShiftI src1 src2) src3)); 5376 5377 size(4); 5378 format %{ "add_32 $dst,$src3,$src1>>>$src2\t! int" %} 5379 ins_encode %{ 5380 __ add_32($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsr, $src2$$Register)); 5381 %} 5382 ins_pipe(ialu_reg_reg); 5383 %} 5384 5385 instruct addshrI_reg_imm_reg(iRegI dst, iRegI src1, immU5 src2, iRegI src3) %{ 5386 match(Set dst (AddI (URShiftI src1 src2) src3)); 5387 5388 size(4); 5389 format %{ "add_32 $dst,$src3,$src1>>>$src2\t! int" %} 5390 ins_encode %{ 5391 __ add_32($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsr, $src2$$constant)); 5392 %} 5393 ins_pipe(ialu_reg_reg); 5394 %} 5395 5396 // Immediate Addition 5397 instruct addI_reg_aimmI(iRegI dst, iRegI src1, aimmI src2) %{ 5398 match(Set dst (AddI src1 src2)); 5399 5400 size(4); 5401 format %{ "add_32 $dst,$src1,$src2\t! int" %} 5402 ins_encode %{ 5403 __ add_32($dst$$Register, $src1$$Register, $src2$$constant); 5404 %} 5405 ins_pipe(ialu_reg_imm); 5406 %} 5407 5408 // Pointer Register Addition 5409 instruct addP_reg_reg(iRegP dst, iRegP src1, iRegX src2) %{ 5410 match(Set dst (AddP src1 src2)); 5411 5412 size(4); 5413 format %{ "ADD $dst,$src1,$src2\t! ptr" %} 5414 ins_encode %{ 5415 __ add($dst$$Register, $src1$$Register, $src2$$Register); 5416 %} 5417 ins_pipe(ialu_reg_reg); 5418 %} 5419 5420 5421 // shifted iRegX operand 5422 operand shiftedX(iRegX src2, shimmX src3) %{ 5423 //constraint(ALLOC_IN_RC(sp_ptr_reg)); 5424 match(LShiftX src2 src3); 5425 5426 op_cost(1); 5427 format %{ "$src2 << $src3" %} 5428 interface(MEMORY_INTER) %{ 5429 base($src2); 5430 index(0xff); 5431 scale($src3); 5432 disp(0x0); 5433 %} 5434 %} 5435 5436 instruct addshlP_reg_reg_imm(iRegP dst, iRegP src1, shiftedX src2) %{ 5437 match(Set dst (AddP src1 src2)); 5438 5439 ins_cost(DEFAULT_COST * 3/2); 5440 size(4); 5441 format %{ "ADD $dst,$src1,$src2\t! ptr" %} 5442 ins_encode %{ 5443 Register base = reg_to_register_object($src2$$base); 5444 __ add($dst$$Register, $src1$$Register, AsmOperand(base, lsl, $src2$$scale)); 5445 %} 5446 ins_pipe(ialu_reg_reg); 5447 %} 5448 5449 // Pointer Immediate Addition 5450 instruct addP_reg_aimmX(iRegP dst, iRegP src1, aimmX src2) %{ 5451 match(Set dst (AddP src1 src2)); 5452 5453 size(4); 5454 format %{ "ADD $dst,$src1,$src2\t! ptr" %} 5455 ins_encode %{ 5456 __ add($dst$$Register, $src1$$Register, $src2$$constant); 5457 %} 5458 ins_pipe(ialu_reg_imm); 5459 %} 5460 5461 // Long Addition 5462 instruct addL_reg_reg(iRegL dst, iRegL src1, iRegL src2, flagsReg ccr) %{ 5463 match(Set dst (AddL src1 src2)); 5464 effect(KILL ccr); 5465 size(8); 5466 format %{ "ADDS $dst.lo,$src1.lo,$src2.lo\t! long\n\t" 5467 "ADC $dst.hi,$src1.hi,$src2.hi" %} 5468 ins_encode %{ 5469 __ adds($dst$$Register, $src1$$Register, $src2$$Register); 5470 __ adc($dst$$Register->successor(), $src1$$Register->successor(), $src2$$Register->successor()); 5471 %} 5472 ins_pipe(ialu_reg_reg); 5473 %} 5474 5475 // TODO 5476 5477 // TODO: try immLRot2 instead, (0, $con$$constant) becomes 5478 // (hi($con$$constant), lo($con$$constant)) becomes 5479 instruct addL_reg_immRot(iRegL dst, iRegL src1, immLlowRot con, flagsReg ccr) %{ 5480 match(Set dst (AddL src1 con)); 5481 effect(KILL ccr); 5482 size(8); 5483 format %{ "ADDS $dst.lo,$src1.lo,$con\t! long\n\t" 5484 "ADC $dst.hi,$src1.hi,0" %} 5485 ins_encode %{ 5486 __ adds($dst$$Register, $src1$$Register, $con$$constant); 5487 __ adc($dst$$Register->successor(), $src1$$Register->successor(), 0); 5488 %} 5489 ins_pipe(ialu_reg_imm); 5490 %} 5491 5492 //----------Conditional_store-------------------------------------------------- 5493 // Conditional-store of the updated heap-top. 5494 // Used during allocation of the shared heap. 5495 // Sets flags (EQ) on success. 5496 5497 // LoadP-locked. 5498 instruct loadPLocked(iRegP dst, memoryex mem) %{ 5499 match(Set dst (LoadPLocked mem)); 5500 size(4); 5501 format %{ "LDREX $dst,$mem" %} 5502 ins_encode %{ 5503 __ ldrex($dst$$Register,$mem$$Address); 5504 %} 5505 ins_pipe(iload_mem); 5506 %} 5507 5508 instruct storePConditional( memoryex heap_top_ptr, iRegP oldval, iRegP newval, iRegI tmp, flagsRegP pcc ) %{ 5509 predicate(_kids[1]->_kids[0]->_leaf->Opcode() == Op_LoadPLocked); // only works in conjunction with a LoadPLocked node 5510 match(Set pcc (StorePConditional heap_top_ptr (Binary oldval newval))); 5511 effect( TEMP tmp ); 5512 size(8); 5513 format %{ "STREX $tmp,$newval,$heap_top_ptr\n\t" 5514 "CMP $tmp, 0" %} 5515 ins_encode %{ 5516 __ strex($tmp$$Register, $newval$$Register, $heap_top_ptr$$Address); 5517 __ cmp($tmp$$Register, 0); 5518 %} 5519 ins_pipe( long_memory_op ); 5520 %} 5521 5522 // Conditional-store of an intx value. 5523 instruct storeXConditional( memoryex mem, iRegX oldval, iRegX newval, iRegX tmp, flagsReg icc ) %{ 5524 match(Set icc (StoreIConditional mem (Binary oldval newval))); 5525 effect( TEMP tmp ); 5526 size(28); 5527 format %{ "loop: \n\t" 5528 "LDREX $tmp, $mem\t! If $oldval==[$mem] Then store $newval into [$mem], DOESN'T set $newval=[$mem] in any case\n\t" 5529 "XORS $tmp,$tmp, $oldval\n\t" 5530 "STREX.eq $tmp, $newval, $mem\n\t" 5531 "CMP.eq $tmp, 1 \n\t" 5532 "B.eq loop \n\t" 5533 "TEQ $tmp, 0\n\t" 5534 "membar LoadStore|LoadLoad" %} 5535 ins_encode %{ 5536 Label loop; 5537 __ bind(loop); 5538 __ ldrex($tmp$$Register, $mem$$Address); 5539 __ eors($tmp$$Register, $tmp$$Register, $oldval$$Register); 5540 __ strex($tmp$$Register, $newval$$Register, $mem$$Address, eq); 5541 __ cmp($tmp$$Register, 1, eq); 5542 __ b(loop, eq); 5543 __ teq($tmp$$Register, 0); 5544 // used by biased locking only. Requires a membar. 5545 __ membar(MacroAssembler::Membar_mask_bits(MacroAssembler::LoadStore | MacroAssembler::LoadLoad), noreg); 5546 %} 5547 ins_pipe( long_memory_op ); 5548 %} 5549 5550 // No flag versions for CompareAndSwap{P,I,L} because matcher can't match them 5551 5552 instruct compareAndSwapL_bool(memoryex mem, iRegL oldval, iRegLd newval, iRegI res, iRegLd tmp, flagsReg ccr ) %{ 5553 match(Set res (CompareAndSwapL mem (Binary oldval newval))); 5554 effect( KILL ccr, TEMP tmp); 5555 size(32); 5556 format %{ "loop: \n\t" 5557 "LDREXD $tmp, $mem\t! If $oldval==[$mem] Then store $newval into [$mem]\n\t" 5558 "CMP $tmp.lo, $oldval.lo\n\t" 5559 "CMP.eq $tmp.hi, $oldval.hi\n\t" 5560 "STREXD.eq $tmp, $newval, $mem\n\t" 5561 "MOV.ne $tmp, 0 \n\t" 5562 "XORS.eq $tmp,$tmp, 1 \n\t" 5563 "B.eq loop \n\t" 5564 "MOV $res, $tmp" %} 5565 ins_encode %{ 5566 Label loop; 5567 __ bind(loop); 5568 __ ldrexd($tmp$$Register, $mem$$Address); 5569 __ cmp($tmp$$Register, $oldval$$Register); 5570 __ cmp($tmp$$Register->successor(), $oldval$$Register->successor(), eq); 5571 __ strexd($tmp$$Register, $newval$$Register, $mem$$Address, eq); 5572 __ mov($tmp$$Register, 0, ne); 5573 __ eors($tmp$$Register, $tmp$$Register, 1, eq); 5574 __ b(loop, eq); 5575 __ mov($res$$Register, $tmp$$Register); 5576 %} 5577 ins_pipe( long_memory_op ); 5578 %} 5579 5580 5581 instruct compareAndSwapI_bool(memoryex mem, iRegI oldval, iRegI newval, iRegI res, iRegI tmp, flagsReg ccr ) %{ 5582 match(Set res (CompareAndSwapI mem (Binary oldval newval))); 5583 effect( KILL ccr, TEMP tmp); 5584 size(28); 5585 format %{ "loop: \n\t" 5586 "LDREX $tmp, $mem\t! If $oldval==[$mem] Then store $newval into [$mem]\n\t" 5587 "CMP $tmp, $oldval\n\t" 5588 "STREX.eq $tmp, $newval, $mem\n\t" 5589 "MOV.ne $tmp, 0 \n\t" 5590 "XORS.eq $tmp,$tmp, 1 \n\t" 5591 "B.eq loop \n\t" 5592 "MOV $res, $tmp" %} 5593 5594 ins_encode %{ 5595 Label loop; 5596 __ bind(loop); 5597 __ ldrex($tmp$$Register,$mem$$Address); 5598 __ cmp($tmp$$Register, $oldval$$Register); 5599 __ strex($tmp$$Register, $newval$$Register, $mem$$Address, eq); 5600 __ mov($tmp$$Register, 0, ne); 5601 __ eors($tmp$$Register, $tmp$$Register, 1, eq); 5602 __ b(loop, eq); 5603 __ mov($res$$Register, $tmp$$Register); 5604 %} 5605 ins_pipe( long_memory_op ); 5606 %} 5607 5608 instruct compareAndSwapP_bool(memoryex mem, iRegP oldval, iRegP newval, iRegI res, iRegI tmp, flagsReg ccr ) %{ 5609 match(Set res (CompareAndSwapP mem (Binary oldval newval))); 5610 effect( KILL ccr, TEMP tmp); 5611 size(28); 5612 format %{ "loop: \n\t" 5613 "LDREX $tmp, $mem\t! If $oldval==[$mem] Then store $newval into [$mem]\n\t" 5614 "CMP $tmp, $oldval\n\t" 5615 "STREX.eq $tmp, $newval, $mem\n\t" 5616 "MOV.ne $tmp, 0 \n\t" 5617 "EORS.eq $tmp,$tmp, 1 \n\t" 5618 "B.eq loop \n\t" 5619 "MOV $res, $tmp" %} 5620 5621 ins_encode %{ 5622 Label loop; 5623 __ bind(loop); 5624 __ ldrex($tmp$$Register,$mem$$Address); 5625 __ cmp($tmp$$Register, $oldval$$Register); 5626 __ strex($tmp$$Register, $newval$$Register, $mem$$Address, eq); 5627 __ mov($tmp$$Register, 0, ne); 5628 __ eors($tmp$$Register, $tmp$$Register, 1, eq); 5629 __ b(loop, eq); 5630 __ mov($res$$Register, $tmp$$Register); 5631 %} 5632 ins_pipe( long_memory_op ); 5633 %} 5634 5635 instruct xaddI_aimmI_no_res(memoryex mem, aimmI add, Universe dummy, iRegI tmp1, iRegI tmp2, flagsReg ccr) %{ 5636 predicate(n->as_LoadStore()->result_not_used()); 5637 match(Set dummy (GetAndAddI mem add)); 5638 effect(KILL ccr, TEMP tmp1, TEMP tmp2); 5639 size(20); 5640 format %{ "loop: \n\t" 5641 "LDREX $tmp1, $mem\n\t" 5642 "ADD $tmp1, $tmp1, $add\n\t" 5643 "STREX $tmp2, $tmp1, $mem\n\t" 5644 "CMP $tmp2, 0 \n\t" 5645 "B.ne loop \n\t" %} 5646 5647 ins_encode %{ 5648 Label loop; 5649 __ bind(loop); 5650 __ ldrex($tmp1$$Register,$mem$$Address); 5651 __ add($tmp1$$Register, $tmp1$$Register, $add$$constant); 5652 __ strex($tmp2$$Register, $tmp1$$Register, $mem$$Address); 5653 __ cmp($tmp2$$Register, 0); 5654 __ b(loop, ne); 5655 %} 5656 ins_pipe( long_memory_op ); 5657 %} 5658 5659 instruct xaddI_reg_no_res(memoryex mem, iRegI add, Universe dummy, iRegI tmp1, iRegI tmp2, flagsReg ccr) %{ 5660 predicate(n->as_LoadStore()->result_not_used()); 5661 match(Set dummy (GetAndAddI mem add)); 5662 effect(KILL ccr, TEMP tmp1, TEMP tmp2); 5663 size(20); 5664 format %{ "loop: \n\t" 5665 "LDREX $tmp1, $mem\n\t" 5666 "ADD $tmp1, $tmp1, $add\n\t" 5667 "STREX $tmp2, $tmp1, $mem\n\t" 5668 "CMP $tmp2, 0 \n\t" 5669 "B.ne loop \n\t" %} 5670 5671 ins_encode %{ 5672 Label loop; 5673 __ bind(loop); 5674 __ ldrex($tmp1$$Register,$mem$$Address); 5675 __ add($tmp1$$Register, $tmp1$$Register, $add$$Register); 5676 __ strex($tmp2$$Register, $tmp1$$Register, $mem$$Address); 5677 __ cmp($tmp2$$Register, 0); 5678 __ b(loop, ne); 5679 %} 5680 ins_pipe( long_memory_op ); 5681 %} 5682 5683 instruct xaddI_aimmI(memoryex mem, aimmI add, iRegI res, iRegI tmp1, iRegI tmp2, flagsReg ccr) %{ 5684 match(Set res (GetAndAddI mem add)); 5685 effect(KILL ccr, TEMP tmp1, TEMP tmp2, TEMP res); 5686 size(20); 5687 format %{ "loop: \n\t" 5688 "LDREX $res, $mem\n\t" 5689 "ADD $tmp1, $res, $add\n\t" 5690 "STREX $tmp2, $tmp1, $mem\n\t" 5691 "CMP $tmp2, 0 \n\t" 5692 "B.ne loop \n\t" %} 5693 5694 ins_encode %{ 5695 Label loop; 5696 __ bind(loop); 5697 __ ldrex($res$$Register,$mem$$Address); 5698 __ add($tmp1$$Register, $res$$Register, $add$$constant); 5699 __ strex($tmp2$$Register, $tmp1$$Register, $mem$$Address); 5700 __ cmp($tmp2$$Register, 0); 5701 __ b(loop, ne); 5702 %} 5703 ins_pipe( long_memory_op ); 5704 %} 5705 5706 instruct xaddI_reg(memoryex mem, iRegI add, iRegI res, iRegI tmp1, iRegI tmp2, flagsReg ccr) %{ 5707 match(Set res (GetAndAddI mem add)); 5708 effect(KILL ccr, TEMP tmp1, TEMP tmp2, TEMP res); 5709 size(20); 5710 format %{ "loop: \n\t" 5711 "LDREX $res, $mem\n\t" 5712 "ADD $tmp1, $res, $add\n\t" 5713 "STREX $tmp2, $tmp1, $mem\n\t" 5714 "CMP $tmp2, 0 \n\t" 5715 "B.ne loop \n\t" %} 5716 5717 ins_encode %{ 5718 Label loop; 5719 __ bind(loop); 5720 __ ldrex($res$$Register,$mem$$Address); 5721 __ add($tmp1$$Register, $res$$Register, $add$$Register); 5722 __ strex($tmp2$$Register, $tmp1$$Register, $mem$$Address); 5723 __ cmp($tmp2$$Register, 0); 5724 __ b(loop, ne); 5725 %} 5726 ins_pipe( long_memory_op ); 5727 %} 5728 5729 instruct xaddL_reg_no_res(memoryex mem, iRegL add, Universe dummy, iRegLd tmp1, iRegI tmp2, flagsReg ccr) %{ 5730 predicate(n->as_LoadStore()->result_not_used()); 5731 match(Set dummy (GetAndAddL mem add)); 5732 effect( KILL ccr, TEMP tmp1, TEMP tmp2); 5733 size(24); 5734 format %{ "loop: \n\t" 5735 "LDREXD $tmp1, $mem\n\t" 5736 "ADDS $tmp1.lo, $tmp1.lo, $add.lo\n\t" 5737 "ADC $tmp1.hi, $tmp1.hi, $add.hi\n\t" 5738 "STREXD $tmp2, $tmp1, $mem\n\t" 5739 "CMP $tmp2, 0 \n\t" 5740 "B.ne loop \n\t" %} 5741 5742 ins_encode %{ 5743 Label loop; 5744 __ bind(loop); 5745 __ ldrexd($tmp1$$Register, $mem$$Address); 5746 __ adds($tmp1$$Register, $tmp1$$Register, $add$$Register); 5747 __ adc($tmp1$$Register->successor(), $tmp1$$Register->successor(), $add$$Register->successor()); 5748 __ strexd($tmp2$$Register, $tmp1$$Register, $mem$$Address); 5749 __ cmp($tmp2$$Register, 0); 5750 __ b(loop, ne); 5751 %} 5752 ins_pipe( long_memory_op ); 5753 %} 5754 5755 // TODO: try immLRot2 instead, (0, $con$$constant) becomes 5756 // (hi($con$$constant), lo($con$$constant)) becomes 5757 instruct xaddL_immRot_no_res(memoryex mem, immLlowRot add, Universe dummy, iRegLd tmp1, iRegI tmp2, flagsReg ccr) %{ 5758 predicate(n->as_LoadStore()->result_not_used()); 5759 match(Set dummy (GetAndAddL mem add)); 5760 effect( KILL ccr, TEMP tmp1, TEMP tmp2); 5761 size(24); 5762 format %{ "loop: \n\t" 5763 "LDREXD $tmp1, $mem\n\t" 5764 "ADDS $tmp1.lo, $tmp1.lo, $add\n\t" 5765 "ADC $tmp1.hi, $tmp1.hi, 0\n\t" 5766 "STREXD $tmp2, $tmp1, $mem\n\t" 5767 "CMP $tmp2, 0 \n\t" 5768 "B.ne loop \n\t" %} 5769 5770 ins_encode %{ 5771 Label loop; 5772 __ bind(loop); 5773 __ ldrexd($tmp1$$Register, $mem$$Address); 5774 __ adds($tmp1$$Register, $tmp1$$Register, $add$$constant); 5775 __ adc($tmp1$$Register->successor(), $tmp1$$Register->successor(), 0); 5776 __ strexd($tmp2$$Register, $tmp1$$Register, $mem$$Address); 5777 __ cmp($tmp2$$Register, 0); 5778 __ b(loop, ne); 5779 %} 5780 ins_pipe( long_memory_op ); 5781 %} 5782 5783 instruct xaddL_reg(memoryex mem, iRegL add, iRegLd res, iRegLd tmp1, iRegI tmp2, flagsReg ccr) %{ 5784 match(Set res (GetAndAddL mem add)); 5785 effect( KILL ccr, TEMP tmp1, TEMP tmp2, TEMP res); 5786 size(24); 5787 format %{ "loop: \n\t" 5788 "LDREXD $res, $mem\n\t" 5789 "ADDS $tmp1.lo, $res.lo, $add.lo\n\t" 5790 "ADC $tmp1.hi, $res.hi, $add.hi\n\t" 5791 "STREXD $tmp2, $tmp1, $mem\n\t" 5792 "CMP $tmp2, 0 \n\t" 5793 "B.ne loop \n\t" %} 5794 5795 ins_encode %{ 5796 Label loop; 5797 __ bind(loop); 5798 __ ldrexd($res$$Register, $mem$$Address); 5799 __ adds($tmp1$$Register, $res$$Register, $add$$Register); 5800 __ adc($tmp1$$Register->successor(), $res$$Register->successor(), $add$$Register->successor()); 5801 __ strexd($tmp2$$Register, $tmp1$$Register, $mem$$Address); 5802 __ cmp($tmp2$$Register, 0); 5803 __ b(loop, ne); 5804 %} 5805 ins_pipe( long_memory_op ); 5806 %} 5807 5808 // TODO: try immLRot2 instead, (0, $con$$constant) becomes 5809 // (hi($con$$constant), lo($con$$constant)) becomes 5810 instruct xaddL_immRot(memoryex mem, immLlowRot add, iRegLd res, iRegLd tmp1, iRegI tmp2, flagsReg ccr) %{ 5811 match(Set res (GetAndAddL mem add)); 5812 effect( KILL ccr, TEMP tmp1, TEMP tmp2, TEMP res); 5813 size(24); 5814 format %{ "loop: \n\t" 5815 "LDREXD $res, $mem\n\t" 5816 "ADDS $tmp1.lo, $res.lo, $add\n\t" 5817 "ADC $tmp1.hi, $res.hi, 0\n\t" 5818 "STREXD $tmp2, $tmp1, $mem\n\t" 5819 "CMP $tmp2, 0 \n\t" 5820 "B.ne loop \n\t" %} 5821 5822 ins_encode %{ 5823 Label loop; 5824 __ bind(loop); 5825 __ ldrexd($res$$Register, $mem$$Address); 5826 __ adds($tmp1$$Register, $res$$Register, $add$$constant); 5827 __ adc($tmp1$$Register->successor(), $res$$Register->successor(), 0); 5828 __ strexd($tmp2$$Register, $tmp1$$Register, $mem$$Address); 5829 __ cmp($tmp2$$Register, 0); 5830 __ b(loop, ne); 5831 %} 5832 ins_pipe( long_memory_op ); 5833 %} 5834 5835 instruct xchgI(memoryex mem, iRegI newval, iRegI res, iRegI tmp, flagsReg ccr) %{ 5836 match(Set res (GetAndSetI mem newval)); 5837 effect(KILL ccr, TEMP tmp, TEMP res); 5838 size(16); 5839 format %{ "loop: \n\t" 5840 "LDREX $res, $mem\n\t" 5841 "STREX $tmp, $newval, $mem\n\t" 5842 "CMP $tmp, 0 \n\t" 5843 "B.ne loop \n\t" %} 5844 5845 ins_encode %{ 5846 Label loop; 5847 __ bind(loop); 5848 __ ldrex($res$$Register,$mem$$Address); 5849 __ strex($tmp$$Register, $newval$$Register, $mem$$Address); 5850 __ cmp($tmp$$Register, 0); 5851 __ b(loop, ne); 5852 %} 5853 ins_pipe( long_memory_op ); 5854 %} 5855 5856 instruct xchgL(memoryex mem, iRegLd newval, iRegLd res, iRegI tmp, flagsReg ccr) %{ 5857 match(Set res (GetAndSetL mem newval)); 5858 effect( KILL ccr, TEMP tmp, TEMP res); 5859 size(16); 5860 format %{ "loop: \n\t" 5861 "LDREXD $res, $mem\n\t" 5862 "STREXD $tmp, $newval, $mem\n\t" 5863 "CMP $tmp, 0 \n\t" 5864 "B.ne loop \n\t" %} 5865 5866 ins_encode %{ 5867 Label loop; 5868 __ bind(loop); 5869 __ ldrexd($res$$Register, $mem$$Address); 5870 __ strexd($tmp$$Register, $newval$$Register, $mem$$Address); 5871 __ cmp($tmp$$Register, 0); 5872 __ b(loop, ne); 5873 %} 5874 ins_pipe( long_memory_op ); 5875 %} 5876 5877 instruct xchgP(memoryex mem, iRegP newval, iRegP res, iRegI tmp, flagsReg ccr) %{ 5878 match(Set res (GetAndSetP mem newval)); 5879 effect(KILL ccr, TEMP tmp, TEMP res); 5880 size(16); 5881 format %{ "loop: \n\t" 5882 "LDREX $res, $mem\n\t" 5883 "STREX $tmp, $newval, $mem\n\t" 5884 "CMP $tmp, 0 \n\t" 5885 "B.ne loop \n\t" %} 5886 5887 ins_encode %{ 5888 Label loop; 5889 __ bind(loop); 5890 __ ldrex($res$$Register,$mem$$Address); 5891 __ strex($tmp$$Register, $newval$$Register, $mem$$Address); 5892 __ cmp($tmp$$Register, 0); 5893 __ b(loop, ne); 5894 %} 5895 ins_pipe( long_memory_op ); 5896 %} 5897 5898 //--------------------- 5899 // Subtraction Instructions 5900 // Register Subtraction 5901 instruct subI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{ 5902 match(Set dst (SubI src1 src2)); 5903 5904 size(4); 5905 format %{ "sub_32 $dst,$src1,$src2\t! int" %} 5906 ins_encode %{ 5907 __ sub_32($dst$$Register, $src1$$Register, $src2$$Register); 5908 %} 5909 ins_pipe(ialu_reg_reg); 5910 %} 5911 5912 instruct subshlI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 5913 match(Set dst (SubI src1 (LShiftI src2 src3))); 5914 5915 size(4); 5916 format %{ "SUB $dst,$src1,$src2<<$src3" %} 5917 ins_encode %{ 5918 __ sub($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$Register)); 5919 %} 5920 ins_pipe(ialu_reg_reg); 5921 %} 5922 5923 instruct subshlI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{ 5924 match(Set dst (SubI src1 (LShiftI src2 src3))); 5925 5926 size(4); 5927 format %{ "sub_32 $dst,$src1,$src2<<$src3\t! int" %} 5928 ins_encode %{ 5929 __ sub_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$constant)); 5930 %} 5931 ins_pipe(ialu_reg_reg); 5932 %} 5933 5934 instruct subsarI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 5935 match(Set dst (SubI src1 (RShiftI src2 src3))); 5936 5937 size(4); 5938 format %{ "SUB $dst,$src1,$src2>>$src3" %} 5939 ins_encode %{ 5940 __ sub($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$Register)); 5941 %} 5942 ins_pipe(ialu_reg_reg); 5943 %} 5944 5945 instruct subsarI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{ 5946 match(Set dst (SubI src1 (RShiftI src2 src3))); 5947 5948 size(4); 5949 format %{ "sub_32 $dst,$src1,$src2>>$src3\t! int" %} 5950 ins_encode %{ 5951 __ sub_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$constant)); 5952 %} 5953 ins_pipe(ialu_reg_reg); 5954 %} 5955 5956 instruct subshrI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 5957 match(Set dst (SubI src1 (URShiftI src2 src3))); 5958 5959 size(4); 5960 format %{ "SUB $dst,$src1,$src2>>>$src3" %} 5961 ins_encode %{ 5962 __ sub($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$Register)); 5963 %} 5964 ins_pipe(ialu_reg_reg); 5965 %} 5966 5967 instruct subshrI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{ 5968 match(Set dst (SubI src1 (URShiftI src2 src3))); 5969 5970 size(4); 5971 format %{ "sub_32 $dst,$src1,$src2>>>$src3\t! int" %} 5972 ins_encode %{ 5973 __ sub_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$constant)); 5974 %} 5975 ins_pipe(ialu_reg_reg); 5976 %} 5977 5978 instruct rsbshlI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 5979 match(Set dst (SubI (LShiftI src1 src2) src3)); 5980 5981 size(4); 5982 format %{ "RSB $dst,$src3,$src1<<$src2" %} 5983 ins_encode %{ 5984 __ rsb($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsl, $src2$$Register)); 5985 %} 5986 ins_pipe(ialu_reg_reg); 5987 %} 5988 5989 instruct rsbshlI_reg_imm_reg(iRegI dst, iRegI src1, immU5 src2, iRegI src3) %{ 5990 match(Set dst (SubI (LShiftI src1 src2) src3)); 5991 5992 size(4); 5993 format %{ "RSB $dst,$src3,$src1<<$src2" %} 5994 ins_encode %{ 5995 __ rsb($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsl, $src2$$constant)); 5996 %} 5997 ins_pipe(ialu_reg_reg); 5998 %} 5999 6000 instruct rsbsarI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 6001 match(Set dst (SubI (RShiftI src1 src2) src3)); 6002 6003 size(4); 6004 format %{ "RSB $dst,$src3,$src1>>$src2" %} 6005 ins_encode %{ 6006 __ rsb($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, asr, $src2$$Register)); 6007 %} 6008 ins_pipe(ialu_reg_reg); 6009 %} 6010 6011 instruct rsbsarI_reg_imm_reg(iRegI dst, iRegI src1, immU5 src2, iRegI src3) %{ 6012 match(Set dst (SubI (RShiftI src1 src2) src3)); 6013 6014 size(4); 6015 format %{ "RSB $dst,$src3,$src1>>$src2" %} 6016 ins_encode %{ 6017 __ rsb($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, asr, $src2$$constant)); 6018 %} 6019 ins_pipe(ialu_reg_reg); 6020 %} 6021 6022 instruct rsbshrI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 6023 match(Set dst (SubI (URShiftI src1 src2) src3)); 6024 6025 size(4); 6026 format %{ "RSB $dst,$src3,$src1>>>$src2" %} 6027 ins_encode %{ 6028 __ rsb($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsr, $src2$$Register)); 6029 %} 6030 ins_pipe(ialu_reg_reg); 6031 %} 6032 6033 instruct rsbshrI_reg_imm_reg(iRegI dst, iRegI src1, immU5 src2, iRegI src3) %{ 6034 match(Set dst (SubI (URShiftI src1 src2) src3)); 6035 6036 size(4); 6037 format %{ "RSB $dst,$src3,$src1>>>$src2" %} 6038 ins_encode %{ 6039 __ rsb($dst$$Register, $src3$$Register, AsmOperand($src1$$Register, lsr, $src2$$constant)); 6040 %} 6041 ins_pipe(ialu_reg_reg); 6042 %} 6043 6044 // Immediate Subtraction 6045 instruct subI_reg_aimmI(iRegI dst, iRegI src1, aimmI src2) %{ 6046 match(Set dst (SubI src1 src2)); 6047 6048 size(4); 6049 format %{ "sub_32 $dst,$src1,$src2\t! int" %} 6050 ins_encode %{ 6051 __ sub_32($dst$$Register, $src1$$Register, $src2$$constant); 6052 %} 6053 ins_pipe(ialu_reg_imm); 6054 %} 6055 6056 instruct subI_reg_immRotneg(iRegI dst, iRegI src1, aimmIneg src2) %{ 6057 match(Set dst (AddI src1 src2)); 6058 6059 size(4); 6060 format %{ "sub_32 $dst,$src1,-($src2)\t! int" %} 6061 ins_encode %{ 6062 __ sub_32($dst$$Register, $src1$$Register, -$src2$$constant); 6063 %} 6064 ins_pipe(ialu_reg_imm); 6065 %} 6066 6067 instruct subI_immRot_reg(iRegI dst, immIRot src1, iRegI src2) %{ 6068 match(Set dst (SubI src1 src2)); 6069 6070 size(4); 6071 format %{ "RSB $dst,$src2,src1" %} 6072 ins_encode %{ 6073 __ rsb($dst$$Register, $src2$$Register, $src1$$constant); 6074 %} 6075 ins_pipe(ialu_zero_reg); 6076 %} 6077 6078 // Register Subtraction 6079 instruct subL_reg_reg(iRegL dst, iRegL src1, iRegL src2, flagsReg icc ) %{ 6080 match(Set dst (SubL src1 src2)); 6081 effect (KILL icc); 6082 6083 size(8); 6084 format %{ "SUBS $dst.lo,$src1.lo,$src2.lo\t! long\n\t" 6085 "SBC $dst.hi,$src1.hi,$src2.hi" %} 6086 ins_encode %{ 6087 __ subs($dst$$Register, $src1$$Register, $src2$$Register); 6088 __ sbc($dst$$Register->successor(), $src1$$Register->successor(), $src2$$Register->successor()); 6089 %} 6090 ins_pipe(ialu_reg_reg); 6091 %} 6092 6093 // TODO 6094 6095 // Immediate Subtraction 6096 // TODO: try immLRot2 instead, (0, $con$$constant) becomes 6097 // (hi($con$$constant), lo($con$$constant)) becomes 6098 instruct subL_reg_immRot(iRegL dst, iRegL src1, immLlowRot con, flagsReg icc) %{ 6099 match(Set dst (SubL src1 con)); 6100 effect (KILL icc); 6101 6102 size(8); 6103 format %{ "SUB $dst.lo,$src1.lo,$con\t! long\n\t" 6104 "SBC $dst.hi,$src1.hi,0" %} 6105 ins_encode %{ 6106 __ subs($dst$$Register, $src1$$Register, $con$$constant); 6107 __ sbc($dst$$Register->successor(), $src1$$Register->successor(), 0); 6108 %} 6109 ins_pipe(ialu_reg_imm); 6110 %} 6111 6112 // Long negation 6113 instruct negL_reg_reg(iRegL dst, immL0 zero, iRegL src2, flagsReg icc) %{ 6114 match(Set dst (SubL zero src2)); 6115 effect (KILL icc); 6116 6117 size(8); 6118 format %{ "RSBS $dst.lo,$src2.lo,0\t! long\n\t" 6119 "RSC $dst.hi,$src2.hi,0" %} 6120 ins_encode %{ 6121 __ rsbs($dst$$Register, $src2$$Register, 0); 6122 __ rsc($dst$$Register->successor(), $src2$$Register->successor(), 0); 6123 %} 6124 ins_pipe(ialu_zero_reg); 6125 %} 6126 6127 // Multiplication Instructions 6128 // Integer Multiplication 6129 // Register Multiplication 6130 instruct mulI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{ 6131 match(Set dst (MulI src1 src2)); 6132 6133 size(4); 6134 format %{ "mul_32 $dst,$src1,$src2" %} 6135 ins_encode %{ 6136 __ mul_32($dst$$Register, $src1$$Register, $src2$$Register); 6137 %} 6138 ins_pipe(imul_reg_reg); 6139 %} 6140 6141 instruct mulL_lo1_hi2(iRegL dst, iRegL src1, iRegL src2) %{ 6142 effect(DEF dst, USE src1, USE src2); 6143 size(4); 6144 format %{ "MUL $dst.hi,$src1.lo,$src2.hi\t! long" %} 6145 ins_encode %{ 6146 __ mul($dst$$Register->successor(), $src1$$Register, $src2$$Register->successor()); 6147 %} 6148 ins_pipe(imul_reg_reg); 6149 %} 6150 6151 instruct mulL_hi1_lo2(iRegL dst, iRegL src1, iRegL src2) %{ 6152 effect(USE_DEF dst, USE src1, USE src2); 6153 size(8); 6154 format %{ "MLA $dst.hi,$src1.hi,$src2.lo,$dst.hi\t! long\n\t" 6155 "MOV $dst.lo, 0"%} 6156 ins_encode %{ 6157 __ mla($dst$$Register->successor(), $src1$$Register->successor(), $src2$$Register, $dst$$Register->successor()); 6158 __ mov($dst$$Register, 0); 6159 %} 6160 ins_pipe(imul_reg_reg); 6161 %} 6162 6163 instruct mulL_lo1_lo2(iRegL dst, iRegL src1, iRegL src2) %{ 6164 effect(USE_DEF dst, USE src1, USE src2); 6165 size(4); 6166 format %{ "UMLAL $dst.lo,$dst.hi,$src1,$src2\t! long" %} 6167 ins_encode %{ 6168 __ umlal($dst$$Register, $dst$$Register->successor(), $src1$$Register, $src2$$Register); 6169 %} 6170 ins_pipe(imul_reg_reg); 6171 %} 6172 6173 instruct mulL_reg_reg(iRegL dst, iRegL src1, iRegL src2) %{ 6174 match(Set dst (MulL src1 src2)); 6175 6176 expand %{ 6177 mulL_lo1_hi2(dst, src1, src2); 6178 mulL_hi1_lo2(dst, src1, src2); 6179 mulL_lo1_lo2(dst, src1, src2); 6180 %} 6181 %} 6182 6183 // Integer Division 6184 // Register Division 6185 instruct divI_reg_reg(R1RegI dst, R0RegI src1, R2RegI src2, LRRegP lr, flagsReg ccr) %{ 6186 match(Set dst (DivI src1 src2)); 6187 effect( KILL ccr, KILL src1, KILL src2, KILL lr); 6188 ins_cost((2+71)*DEFAULT_COST); 6189 6190 format %{ "DIV $dst,$src1,$src2 ! call to StubRoutines::Arm::idiv_irem_entry()" %} 6191 ins_encode %{ 6192 __ call(StubRoutines::Arm::idiv_irem_entry(), relocInfo::runtime_call_type); 6193 %} 6194 ins_pipe(sdiv_reg_reg); 6195 %} 6196 6197 // Register Long Division 6198 instruct divL_reg_reg(R0R1RegL dst, R2R3RegL src1, R0R1RegL src2) %{ 6199 match(Set dst (DivL src1 src2)); 6200 effect(CALL); 6201 ins_cost(DEFAULT_COST*71); 6202 format %{ "DIVL $src1,$src2,$dst\t! long ! call to SharedRuntime::ldiv" %} 6203 ins_encode %{ 6204 address target = CAST_FROM_FN_PTR(address, SharedRuntime::ldiv); 6205 __ call(target, relocInfo::runtime_call_type); 6206 %} 6207 ins_pipe(divL_reg_reg); 6208 %} 6209 6210 // Integer Remainder 6211 // Register Remainder 6212 instruct modI_reg_reg(R0RegI dst, R0RegI src1, R2RegI src2, R1RegI temp, LRRegP lr, flagsReg ccr ) %{ 6213 match(Set dst (ModI src1 src2)); 6214 effect( KILL ccr, KILL temp, KILL src2, KILL lr); 6215 6216 format %{ "MODI $dst,$src1,$src2\t ! call to StubRoutines::Arm::idiv_irem_entry" %} 6217 ins_encode %{ 6218 __ call(StubRoutines::Arm::idiv_irem_entry(), relocInfo::runtime_call_type); 6219 %} 6220 ins_pipe(sdiv_reg_reg); 6221 %} 6222 6223 // Register Long Remainder 6224 instruct modL_reg_reg(R0R1RegL dst, R2R3RegL src1, R0R1RegL src2) %{ 6225 match(Set dst (ModL src1 src2)); 6226 effect(CALL); 6227 ins_cost(MEMORY_REF_COST); // FIXME 6228 format %{ "modL $dst,$src1,$src2\t ! call to SharedRuntime::lrem" %} 6229 ins_encode %{ 6230 address target = CAST_FROM_FN_PTR(address, SharedRuntime::lrem); 6231 __ call(target, relocInfo::runtime_call_type); 6232 %} 6233 ins_pipe(divL_reg_reg); 6234 %} 6235 6236 // Integer Shift Instructions 6237 6238 // Register Shift Left 6239 instruct shlI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{ 6240 match(Set dst (LShiftI src1 src2)); 6241 6242 size(4); 6243 format %{ "LSL $dst,$src1,$src2 \n\t" %} 6244 ins_encode %{ 6245 __ mov($dst$$Register, AsmOperand($src1$$Register, lsl, $src2$$Register)); 6246 %} 6247 ins_pipe(ialu_reg_reg); 6248 %} 6249 6250 // Register Shift Left Immediate 6251 instruct shlI_reg_imm5(iRegI dst, iRegI src1, immU5 src2) %{ 6252 match(Set dst (LShiftI src1 src2)); 6253 6254 size(4); 6255 format %{ "LSL $dst,$src1,$src2\t! int" %} 6256 ins_encode %{ 6257 __ logical_shift_left($dst$$Register, $src1$$Register, $src2$$constant); 6258 %} 6259 ins_pipe(ialu_reg_imm); 6260 %} 6261 6262 instruct shlL_reg_reg_merge_hi(iRegL dst, iRegL src1, iRegI src2) %{ 6263 effect(USE_DEF dst, USE src1, USE src2); 6264 size(4); 6265 format %{"OR $dst.hi,$dst.hi,($src1.hi << $src2)" %} 6266 ins_encode %{ 6267 __ orr($dst$$Register->successor(), $dst$$Register->successor(), AsmOperand($src1$$Register->successor(), lsl, $src2$$Register)); 6268 %} 6269 ins_pipe(ialu_reg_reg); 6270 %} 6271 6272 instruct shlL_reg_reg_merge_lo(iRegL dst, iRegL src1, iRegI src2) %{ 6273 effect(USE_DEF dst, USE src1, USE src2); 6274 size(4); 6275 format %{ "LSL $dst.lo,$src1.lo,$src2 \n\t" %} 6276 ins_encode %{ 6277 __ mov($dst$$Register, AsmOperand($src1$$Register, lsl, $src2$$Register)); 6278 %} 6279 ins_pipe(ialu_reg_reg); 6280 %} 6281 6282 instruct shlL_reg_reg_overlap(iRegL dst, iRegL src1, iRegI src2, flagsReg ccr) %{ 6283 effect(DEF dst, USE src1, USE src2, KILL ccr); 6284 size(16); 6285 format %{ "SUBS $dst.hi,$src2,32 \n\t" 6286 "LSLpl $dst.hi,$src1.lo,$dst.hi \n\t" 6287 "RSBmi $dst.hi,$dst.hi,0 \n\t" 6288 "LSRmi $dst.hi,$src1.lo,$dst.hi" %} 6289 6290 ins_encode %{ 6291 // $src1$$Register and $dst$$Register->successor() can't be the same 6292 __ subs($dst$$Register->successor(), $src2$$Register, 32); 6293 __ mov($dst$$Register->successor(), AsmOperand($src1$$Register, lsl, $dst$$Register->successor()), pl); 6294 __ rsb($dst$$Register->successor(), $dst$$Register->successor(), 0, mi); 6295 __ mov($dst$$Register->successor(), AsmOperand($src1$$Register, lsr, $dst$$Register->successor()), mi); 6296 %} 6297 ins_pipe(ialu_reg_reg); 6298 %} 6299 6300 instruct shlL_reg_reg(iRegL dst, iRegL src1, iRegI src2) %{ 6301 match(Set dst (LShiftL src1 src2)); 6302 6303 expand %{ 6304 flagsReg ccr; 6305 shlL_reg_reg_overlap(dst, src1, src2, ccr); 6306 shlL_reg_reg_merge_hi(dst, src1, src2); 6307 shlL_reg_reg_merge_lo(dst, src1, src2); 6308 %} 6309 %} 6310 6311 // Register Shift Left Immediate 6312 instruct shlL_reg_imm6(iRegL dst, iRegL src1, immU6Big src2) %{ 6313 match(Set dst (LShiftL src1 src2)); 6314 6315 size(8); 6316 format %{ "LSL $dst.hi,$src1.lo,$src2-32\t! or mov if $src2==32\n\t" 6317 "MOV $dst.lo, 0" %} 6318 ins_encode %{ 6319 if ($src2$$constant == 32) { 6320 __ mov($dst$$Register->successor(), $src1$$Register); 6321 } else { 6322 __ mov($dst$$Register->successor(), AsmOperand($src1$$Register, lsl, $src2$$constant-32)); 6323 } 6324 __ mov($dst$$Register, 0); 6325 %} 6326 ins_pipe(ialu_reg_imm); 6327 %} 6328 6329 instruct shlL_reg_imm5(iRegL dst, iRegL src1, immU5 src2) %{ 6330 match(Set dst (LShiftL src1 src2)); 6331 6332 size(12); 6333 format %{ "LSL $dst.hi,$src1.lo,$src2\n\t" 6334 "OR $dst.hi, $dst.hi, $src1.lo >> 32-$src2\n\t" 6335 "LSL $dst.lo,$src1.lo,$src2" %} 6336 ins_encode %{ 6337 // The order of the following 3 instructions matters: src1.lo and 6338 // dst.hi can't overlap but src.hi and dst.hi can. 6339 __ mov($dst$$Register->successor(), AsmOperand($src1$$Register->successor(), lsl, $src2$$constant)); 6340 __ orr($dst$$Register->successor(), $dst$$Register->successor(), AsmOperand($src1$$Register, lsr, 32-$src2$$constant)); 6341 __ mov($dst$$Register, AsmOperand($src1$$Register, lsl, $src2$$constant)); 6342 %} 6343 ins_pipe(ialu_reg_imm); 6344 %} 6345 6346 // Register Arithmetic Shift Right 6347 instruct sarI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{ 6348 match(Set dst (RShiftI src1 src2)); 6349 size(4); 6350 format %{ "ASR $dst,$src1,$src2\t! int" %} 6351 ins_encode %{ 6352 __ mov($dst$$Register, AsmOperand($src1$$Register, asr, $src2$$Register)); 6353 %} 6354 ins_pipe(ialu_reg_reg); 6355 %} 6356 6357 // Register Arithmetic Shift Right Immediate 6358 instruct sarI_reg_imm5(iRegI dst, iRegI src1, immU5 src2) %{ 6359 match(Set dst (RShiftI src1 src2)); 6360 6361 size(4); 6362 format %{ "ASR $dst,$src1,$src2" %} 6363 ins_encode %{ 6364 __ mov($dst$$Register, AsmOperand($src1$$Register, asr, $src2$$constant)); 6365 %} 6366 ins_pipe(ialu_reg_imm); 6367 %} 6368 6369 // Register Shift Right Arithmetic Long 6370 instruct sarL_reg_reg_merge_lo(iRegL dst, iRegL src1, iRegI src2) %{ 6371 effect(USE_DEF dst, USE src1, USE src2); 6372 size(4); 6373 format %{ "OR $dst.lo,$dst.lo,($src1.lo >> $src2)" %} 6374 ins_encode %{ 6375 __ orr($dst$$Register, $dst$$Register, AsmOperand($src1$$Register, lsr, $src2$$Register)); 6376 %} 6377 ins_pipe(ialu_reg_reg); 6378 %} 6379 6380 instruct sarL_reg_reg_merge_hi(iRegL dst, iRegL src1, iRegI src2) %{ 6381 effect(USE_DEF dst, USE src1, USE src2); 6382 size(4); 6383 format %{ "ASR $dst.hi,$src1.hi,$src2 \n\t" %} 6384 ins_encode %{ 6385 __ mov($dst$$Register->successor(), AsmOperand($src1$$Register->successor(), asr, $src2$$Register)); 6386 %} 6387 ins_pipe(ialu_reg_reg); 6388 %} 6389 6390 instruct sarL_reg_reg_overlap(iRegL dst, iRegL src1, iRegI src2, flagsReg ccr) %{ 6391 effect(DEF dst, USE src1, USE src2, KILL ccr); 6392 size(16); 6393 format %{ "SUBS $dst.lo,$src2,32 \n\t" 6394 "ASRpl $dst.lo,$src1.hi,$dst.lo \n\t" 6395 "RSBmi $dst.lo,$dst.lo,0 \n\t" 6396 "LSLmi $dst.lo,$src1.hi,$dst.lo" %} 6397 6398 ins_encode %{ 6399 // $src1$$Register->successor() and $dst$$Register can't be the same 6400 __ subs($dst$$Register, $src2$$Register, 32); 6401 __ mov($dst$$Register, AsmOperand($src1$$Register->successor(), asr, $dst$$Register), pl); 6402 __ rsb($dst$$Register, $dst$$Register, 0, mi); 6403 __ mov($dst$$Register, AsmOperand($src1$$Register->successor(), lsl, $dst$$Register), mi); 6404 %} 6405 ins_pipe(ialu_reg_reg); 6406 %} 6407 6408 instruct sarL_reg_reg(iRegL dst, iRegL src1, iRegI src2) %{ 6409 match(Set dst (RShiftL src1 src2)); 6410 6411 expand %{ 6412 flagsReg ccr; 6413 sarL_reg_reg_overlap(dst, src1, src2, ccr); 6414 sarL_reg_reg_merge_lo(dst, src1, src2); 6415 sarL_reg_reg_merge_hi(dst, src1, src2); 6416 %} 6417 %} 6418 6419 // Register Shift Left Immediate 6420 instruct sarL_reg_imm6(iRegL dst, iRegL src1, immU6Big src2) %{ 6421 match(Set dst (RShiftL src1 src2)); 6422 6423 size(8); 6424 format %{ "ASR $dst.lo,$src1.hi,$src2-32\t! or mov if $src2==32\n\t" 6425 "ASR $dst.hi,$src1.hi, $src2" %} 6426 ins_encode %{ 6427 if ($src2$$constant == 32) { 6428 __ mov($dst$$Register, $src1$$Register->successor()); 6429 } else{ 6430 __ mov($dst$$Register, AsmOperand($src1$$Register->successor(), asr, $src2$$constant-32)); 6431 } 6432 __ mov($dst$$Register->successor(), AsmOperand($src1$$Register->successor(), asr, 0)); 6433 %} 6434 6435 ins_pipe(ialu_reg_imm); 6436 %} 6437 6438 instruct sarL_reg_imm5(iRegL dst, iRegL src1, immU5 src2) %{ 6439 match(Set dst (RShiftL src1 src2)); 6440 size(12); 6441 format %{ "LSR $dst.lo,$src1.lo,$src2\n\t" 6442 "OR $dst.lo, $dst.lo, $src1.hi << 32-$src2\n\t" 6443 "ASR $dst.hi,$src1.hi,$src2" %} 6444 ins_encode %{ 6445 // The order of the following 3 instructions matters: src1.lo and 6446 // dst.hi can't overlap but src.hi and dst.hi can. 6447 __ mov($dst$$Register, AsmOperand($src1$$Register, lsr, $src2$$constant)); 6448 __ orr($dst$$Register, $dst$$Register, AsmOperand($src1$$Register->successor(), lsl, 32-$src2$$constant)); 6449 __ mov($dst$$Register->successor(), AsmOperand($src1$$Register->successor(), asr, $src2$$constant)); 6450 %} 6451 ins_pipe(ialu_reg_imm); 6452 %} 6453 6454 // Register Shift Right 6455 instruct shrI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{ 6456 match(Set dst (URShiftI src1 src2)); 6457 size(4); 6458 format %{ "LSR $dst,$src1,$src2\t! int" %} 6459 ins_encode %{ 6460 __ mov($dst$$Register, AsmOperand($src1$$Register, lsr, $src2$$Register)); 6461 %} 6462 ins_pipe(ialu_reg_reg); 6463 %} 6464 6465 // Register Shift Right Immediate 6466 instruct shrI_reg_imm5(iRegI dst, iRegI src1, immU5 src2) %{ 6467 match(Set dst (URShiftI src1 src2)); 6468 6469 size(4); 6470 format %{ "LSR $dst,$src1,$src2" %} 6471 ins_encode %{ 6472 __ mov($dst$$Register, AsmOperand($src1$$Register, lsr, $src2$$constant)); 6473 %} 6474 ins_pipe(ialu_reg_imm); 6475 %} 6476 6477 // Register Shift Right 6478 instruct shrL_reg_reg_merge_lo(iRegL dst, iRegL src1, iRegI src2) %{ 6479 effect(USE_DEF dst, USE src1, USE src2); 6480 size(4); 6481 format %{ "OR $dst.lo,$dst,($src1.lo >>> $src2)" %} 6482 ins_encode %{ 6483 __ orr($dst$$Register, $dst$$Register, AsmOperand($src1$$Register, lsr, $src2$$Register)); 6484 %} 6485 ins_pipe(ialu_reg_reg); 6486 %} 6487 6488 instruct shrL_reg_reg_merge_hi(iRegL dst, iRegL src1, iRegI src2) %{ 6489 effect(USE_DEF dst, USE src1, USE src2); 6490 size(4); 6491 format %{ "LSR $dst.hi,$src1.hi,$src2 \n\t" %} 6492 ins_encode %{ 6493 __ mov($dst$$Register->successor(), AsmOperand($src1$$Register->successor(), lsr, $src2$$Register)); 6494 %} 6495 ins_pipe(ialu_reg_reg); 6496 %} 6497 6498 instruct shrL_reg_reg_overlap(iRegL dst, iRegL src1, iRegI src2, flagsReg ccr) %{ 6499 effect(DEF dst, USE src1, USE src2, KILL ccr); 6500 size(16); 6501 format %{ "SUBS $dst,$src2,32 \n\t" 6502 "LSRpl $dst,$src1.hi,$dst \n\t" 6503 "RSBmi $dst,$dst,0 \n\t" 6504 "LSLmi $dst,$src1.hi,$dst" %} 6505 6506 ins_encode %{ 6507 // $src1$$Register->successor() and $dst$$Register can't be the same 6508 __ subs($dst$$Register, $src2$$Register, 32); 6509 __ mov($dst$$Register, AsmOperand($src1$$Register->successor(), lsr, $dst$$Register), pl); 6510 __ rsb($dst$$Register, $dst$$Register, 0, mi); 6511 __ mov($dst$$Register, AsmOperand($src1$$Register->successor(), lsl, $dst$$Register), mi); 6512 %} 6513 ins_pipe(ialu_reg_reg); 6514 %} 6515 6516 instruct shrL_reg_reg(iRegL dst, iRegL src1, iRegI src2) %{ 6517 match(Set dst (URShiftL src1 src2)); 6518 6519 expand %{ 6520 flagsReg ccr; 6521 shrL_reg_reg_overlap(dst, src1, src2, ccr); 6522 shrL_reg_reg_merge_lo(dst, src1, src2); 6523 shrL_reg_reg_merge_hi(dst, src1, src2); 6524 %} 6525 %} 6526 6527 // Register Shift Right Immediate 6528 instruct shrL_reg_imm6(iRegL dst, iRegL src1, immU6Big src2) %{ 6529 match(Set dst (URShiftL src1 src2)); 6530 6531 size(8); 6532 format %{ "LSR $dst.lo,$src1.hi,$src2-32\t! or mov if $src2==32\n\t" 6533 "MOV $dst.hi, 0" %} 6534 ins_encode %{ 6535 if ($src2$$constant == 32) { 6536 __ mov($dst$$Register, $src1$$Register->successor()); 6537 } else { 6538 __ mov($dst$$Register, AsmOperand($src1$$Register->successor(), lsr, $src2$$constant-32)); 6539 } 6540 __ mov($dst$$Register->successor(), 0); 6541 %} 6542 6543 ins_pipe(ialu_reg_imm); 6544 %} 6545 6546 instruct shrL_reg_imm5(iRegL dst, iRegL src1, immU5 src2) %{ 6547 match(Set dst (URShiftL src1 src2)); 6548 6549 size(12); 6550 format %{ "LSR $dst.lo,$src1.lo,$src2\n\t" 6551 "OR $dst.lo, $dst.lo, $src1.hi << 32-$src2\n\t" 6552 "LSR $dst.hi,$src1.hi,$src2" %} 6553 ins_encode %{ 6554 // The order of the following 3 instructions matters: src1.lo and 6555 // dst.hi can't overlap but src.hi and dst.hi can. 6556 __ mov($dst$$Register, AsmOperand($src1$$Register, lsr, $src2$$constant)); 6557 __ orr($dst$$Register, $dst$$Register, AsmOperand($src1$$Register->successor(), lsl, 32-$src2$$constant)); 6558 __ mov($dst$$Register->successor(), AsmOperand($src1$$Register->successor(), lsr, $src2$$constant)); 6559 %} 6560 ins_pipe(ialu_reg_imm); 6561 %} 6562 6563 6564 instruct shrP_reg_imm5(iRegX dst, iRegP src1, immU5 src2) %{ 6565 match(Set dst (URShiftI (CastP2X src1) src2)); 6566 size(4); 6567 format %{ "LSR $dst,$src1,$src2\t! Cast ptr $src1 to int and shift" %} 6568 ins_encode %{ 6569 __ logical_shift_right($dst$$Register, $src1$$Register, $src2$$constant); 6570 %} 6571 ins_pipe(ialu_reg_imm); 6572 %} 6573 6574 //----------Floating Point Arithmetic Instructions----------------------------- 6575 6576 // Add float single precision 6577 instruct addF_reg_reg(regF dst, regF src1, regF src2) %{ 6578 match(Set dst (AddF src1 src2)); 6579 6580 size(4); 6581 format %{ "FADDS $dst,$src1,$src2" %} 6582 ins_encode %{ 6583 __ add_float($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister); 6584 %} 6585 6586 ins_pipe(faddF_reg_reg); 6587 %} 6588 6589 // Add float double precision 6590 instruct addD_reg_reg(regD dst, regD src1, regD src2) %{ 6591 match(Set dst (AddD src1 src2)); 6592 6593 size(4); 6594 format %{ "FADDD $dst,$src1,$src2" %} 6595 ins_encode %{ 6596 __ add_double($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister); 6597 %} 6598 6599 ins_pipe(faddD_reg_reg); 6600 %} 6601 6602 // Sub float single precision 6603 instruct subF_reg_reg(regF dst, regF src1, regF src2) %{ 6604 match(Set dst (SubF src1 src2)); 6605 6606 size(4); 6607 format %{ "FSUBS $dst,$src1,$src2" %} 6608 ins_encode %{ 6609 __ sub_float($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister); 6610 %} 6611 ins_pipe(faddF_reg_reg); 6612 %} 6613 6614 // Sub float double precision 6615 instruct subD_reg_reg(regD dst, regD src1, regD src2) %{ 6616 match(Set dst (SubD src1 src2)); 6617 6618 size(4); 6619 format %{ "FSUBD $dst,$src1,$src2" %} 6620 ins_encode %{ 6621 __ sub_double($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister); 6622 %} 6623 ins_pipe(faddD_reg_reg); 6624 %} 6625 6626 // Mul float single precision 6627 instruct mulF_reg_reg(regF dst, regF src1, regF src2) %{ 6628 match(Set dst (MulF src1 src2)); 6629 6630 size(4); 6631 format %{ "FMULS $dst,$src1,$src2" %} 6632 ins_encode %{ 6633 __ mul_float($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister); 6634 %} 6635 6636 ins_pipe(fmulF_reg_reg); 6637 %} 6638 6639 // Mul float double precision 6640 instruct mulD_reg_reg(regD dst, regD src1, regD src2) %{ 6641 match(Set dst (MulD src1 src2)); 6642 6643 size(4); 6644 format %{ "FMULD $dst,$src1,$src2" %} 6645 ins_encode %{ 6646 __ mul_double($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister); 6647 %} 6648 6649 ins_pipe(fmulD_reg_reg); 6650 %} 6651 6652 // Div float single precision 6653 instruct divF_reg_reg(regF dst, regF src1, regF src2) %{ 6654 match(Set dst (DivF src1 src2)); 6655 6656 size(4); 6657 format %{ "FDIVS $dst,$src1,$src2" %} 6658 ins_encode %{ 6659 __ div_float($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister); 6660 %} 6661 6662 ins_pipe(fdivF_reg_reg); 6663 %} 6664 6665 // Div float double precision 6666 instruct divD_reg_reg(regD dst, regD src1, regD src2) %{ 6667 match(Set dst (DivD src1 src2)); 6668 6669 size(4); 6670 format %{ "FDIVD $dst,$src1,$src2" %} 6671 ins_encode %{ 6672 __ div_double($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister); 6673 %} 6674 6675 ins_pipe(fdivD_reg_reg); 6676 %} 6677 6678 // Absolute float double precision 6679 instruct absD_reg(regD dst, regD src) %{ 6680 match(Set dst (AbsD src)); 6681 6682 size(4); 6683 format %{ "FABSd $dst,$src" %} 6684 ins_encode %{ 6685 __ abs_double($dst$$FloatRegister, $src$$FloatRegister); 6686 %} 6687 ins_pipe(faddD_reg); 6688 %} 6689 6690 // Absolute float single precision 6691 instruct absF_reg(regF dst, regF src) %{ 6692 match(Set dst (AbsF src)); 6693 format %{ "FABSs $dst,$src" %} 6694 ins_encode %{ 6695 __ abs_float($dst$$FloatRegister, $src$$FloatRegister); 6696 %} 6697 ins_pipe(faddF_reg); 6698 %} 6699 6700 instruct negF_reg(regF dst, regF src) %{ 6701 match(Set dst (NegF src)); 6702 6703 size(4); 6704 format %{ "FNEGs $dst,$src" %} 6705 ins_encode %{ 6706 __ neg_float($dst$$FloatRegister, $src$$FloatRegister); 6707 %} 6708 ins_pipe(faddF_reg); 6709 %} 6710 6711 instruct negD_reg(regD dst, regD src) %{ 6712 match(Set dst (NegD src)); 6713 6714 format %{ "FNEGd $dst,$src" %} 6715 ins_encode %{ 6716 __ neg_double($dst$$FloatRegister, $src$$FloatRegister); 6717 %} 6718 ins_pipe(faddD_reg); 6719 %} 6720 6721 // Sqrt float double precision 6722 instruct sqrtF_reg_reg(regF dst, regF src) %{ 6723 match(Set dst (ConvD2F (SqrtD (ConvF2D src)))); 6724 6725 size(4); 6726 format %{ "FSQRTS $dst,$src" %} 6727 ins_encode %{ 6728 __ sqrt_float($dst$$FloatRegister, $src$$FloatRegister); 6729 %} 6730 ins_pipe(fdivF_reg_reg); 6731 %} 6732 6733 // Sqrt float double precision 6734 instruct sqrtD_reg_reg(regD dst, regD src) %{ 6735 match(Set dst (SqrtD src)); 6736 6737 size(4); 6738 format %{ "FSQRTD $dst,$src" %} 6739 ins_encode %{ 6740 __ sqrt_double($dst$$FloatRegister, $src$$FloatRegister); 6741 %} 6742 ins_pipe(fdivD_reg_reg); 6743 %} 6744 6745 //----------Logical Instructions----------------------------------------------- 6746 // And Instructions 6747 // Register And 6748 instruct andI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{ 6749 match(Set dst (AndI src1 src2)); 6750 6751 size(4); 6752 format %{ "and_32 $dst,$src1,$src2" %} 6753 ins_encode %{ 6754 __ and_32($dst$$Register, $src1$$Register, $src2$$Register); 6755 %} 6756 ins_pipe(ialu_reg_reg); 6757 %} 6758 6759 instruct andshlI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 6760 match(Set dst (AndI src1 (LShiftI src2 src3))); 6761 6762 size(4); 6763 format %{ "AND $dst,$src1,$src2<<$src3" %} 6764 ins_encode %{ 6765 __ andr($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$Register)); 6766 %} 6767 ins_pipe(ialu_reg_reg); 6768 %} 6769 6770 instruct andshlI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{ 6771 match(Set dst (AndI src1 (LShiftI src2 src3))); 6772 6773 size(4); 6774 format %{ "and_32 $dst,$src1,$src2<<$src3" %} 6775 ins_encode %{ 6776 __ and_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$constant)); 6777 %} 6778 ins_pipe(ialu_reg_reg); 6779 %} 6780 6781 instruct andsarI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 6782 match(Set dst (AndI src1 (RShiftI src2 src3))); 6783 6784 size(4); 6785 format %{ "AND $dst,$src1,$src2>>$src3" %} 6786 ins_encode %{ 6787 __ andr($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$Register)); 6788 %} 6789 ins_pipe(ialu_reg_reg); 6790 %} 6791 6792 instruct andsarI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{ 6793 match(Set dst (AndI src1 (RShiftI src2 src3))); 6794 6795 size(4); 6796 format %{ "and_32 $dst,$src1,$src2>>$src3" %} 6797 ins_encode %{ 6798 __ and_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$constant)); 6799 %} 6800 ins_pipe(ialu_reg_reg); 6801 %} 6802 6803 instruct andshrI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 6804 match(Set dst (AndI src1 (URShiftI src2 src3))); 6805 6806 size(4); 6807 format %{ "AND $dst,$src1,$src2>>>$src3" %} 6808 ins_encode %{ 6809 __ andr($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$Register)); 6810 %} 6811 ins_pipe(ialu_reg_reg); 6812 %} 6813 6814 instruct andshrI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{ 6815 match(Set dst (AndI src1 (URShiftI src2 src3))); 6816 6817 size(4); 6818 format %{ "and_32 $dst,$src1,$src2>>>$src3" %} 6819 ins_encode %{ 6820 __ and_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$constant)); 6821 %} 6822 ins_pipe(ialu_reg_reg); 6823 %} 6824 6825 // Immediate And 6826 instruct andI_reg_limm(iRegI dst, iRegI src1, limmI src2) %{ 6827 match(Set dst (AndI src1 src2)); 6828 6829 size(4); 6830 format %{ "and_32 $dst,$src1,$src2\t! int" %} 6831 ins_encode %{ 6832 __ and_32($dst$$Register, $src1$$Register, $src2$$constant); 6833 %} 6834 ins_pipe(ialu_reg_imm); 6835 %} 6836 6837 instruct andI_reg_limmn(iRegI dst, iRegI src1, limmIn src2) %{ 6838 match(Set dst (AndI src1 src2)); 6839 6840 size(4); 6841 format %{ "bic $dst,$src1,~$src2\t! int" %} 6842 ins_encode %{ 6843 __ bic($dst$$Register, $src1$$Register, ~$src2$$constant); 6844 %} 6845 ins_pipe(ialu_reg_imm); 6846 %} 6847 6848 // Register And Long 6849 instruct andL_reg_reg(iRegL dst, iRegL src1, iRegL src2) %{ 6850 match(Set dst (AndL src1 src2)); 6851 6852 ins_cost(DEFAULT_COST); 6853 size(8); 6854 format %{ "AND $dst,$src1,$src2\t! long" %} 6855 ins_encode %{ 6856 __ andr($dst$$Register, $src1$$Register, $src2$$Register); 6857 __ andr($dst$$Register->successor(), $src1$$Register->successor(), $src2$$Register->successor()); 6858 %} 6859 ins_pipe(ialu_reg_reg); 6860 %} 6861 6862 // TODO: try immLRot2 instead, (0, $con$$constant) becomes 6863 // (hi($con$$constant), lo($con$$constant)) becomes 6864 instruct andL_reg_immRot(iRegL dst, iRegL src1, immLlowRot con) %{ 6865 match(Set dst (AndL src1 con)); 6866 ins_cost(DEFAULT_COST); 6867 size(8); 6868 format %{ "AND $dst,$src1,$con\t! long" %} 6869 ins_encode %{ 6870 __ andr($dst$$Register, $src1$$Register, $con$$constant); 6871 __ andr($dst$$Register->successor(), $src1$$Register->successor(), 0); 6872 %} 6873 ins_pipe(ialu_reg_imm); 6874 %} 6875 6876 // Or Instructions 6877 // Register Or 6878 instruct orI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{ 6879 match(Set dst (OrI src1 src2)); 6880 6881 size(4); 6882 format %{ "orr_32 $dst,$src1,$src2\t! int" %} 6883 ins_encode %{ 6884 __ orr_32($dst$$Register, $src1$$Register, $src2$$Register); 6885 %} 6886 ins_pipe(ialu_reg_reg); 6887 %} 6888 6889 instruct orshlI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 6890 match(Set dst (OrI src1 (LShiftI src2 src3))); 6891 6892 size(4); 6893 format %{ "OR $dst,$src1,$src2<<$src3" %} 6894 ins_encode %{ 6895 __ orr($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$Register)); 6896 %} 6897 ins_pipe(ialu_reg_reg); 6898 %} 6899 6900 instruct orshlI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{ 6901 match(Set dst (OrI src1 (LShiftI src2 src3))); 6902 6903 size(4); 6904 format %{ "orr_32 $dst,$src1,$src2<<$src3" %} 6905 ins_encode %{ 6906 __ orr_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$constant)); 6907 %} 6908 ins_pipe(ialu_reg_reg); 6909 %} 6910 6911 instruct orsarI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 6912 match(Set dst (OrI src1 (RShiftI src2 src3))); 6913 6914 size(4); 6915 format %{ "OR $dst,$src1,$src2>>$src3" %} 6916 ins_encode %{ 6917 __ orr($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$Register)); 6918 %} 6919 ins_pipe(ialu_reg_reg); 6920 %} 6921 6922 instruct orsarI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{ 6923 match(Set dst (OrI src1 (RShiftI src2 src3))); 6924 6925 size(4); 6926 format %{ "orr_32 $dst,$src1,$src2>>$src3" %} 6927 ins_encode %{ 6928 __ orr_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$constant)); 6929 %} 6930 ins_pipe(ialu_reg_reg); 6931 %} 6932 6933 instruct orshrI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 6934 match(Set dst (OrI src1 (URShiftI src2 src3))); 6935 6936 size(4); 6937 format %{ "OR $dst,$src1,$src2>>>$src3" %} 6938 ins_encode %{ 6939 __ orr($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$Register)); 6940 %} 6941 ins_pipe(ialu_reg_reg); 6942 %} 6943 6944 instruct orshrI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{ 6945 match(Set dst (OrI src1 (URShiftI src2 src3))); 6946 6947 size(4); 6948 format %{ "orr_32 $dst,$src1,$src2>>>$src3" %} 6949 ins_encode %{ 6950 __ orr_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$constant)); 6951 %} 6952 ins_pipe(ialu_reg_reg); 6953 %} 6954 6955 // Immediate Or 6956 instruct orI_reg_limm(iRegI dst, iRegI src1, limmI src2) %{ 6957 match(Set dst (OrI src1 src2)); 6958 6959 size(4); 6960 format %{ "orr_32 $dst,$src1,$src2" %} 6961 ins_encode %{ 6962 __ orr_32($dst$$Register, $src1$$Register, $src2$$constant); 6963 %} 6964 ins_pipe(ialu_reg_imm); 6965 %} 6966 // TODO: orn_32 with limmIn 6967 6968 // Register Or Long 6969 instruct orL_reg_reg(iRegL dst, iRegL src1, iRegL src2) %{ 6970 match(Set dst (OrL src1 src2)); 6971 6972 ins_cost(DEFAULT_COST); 6973 size(8); 6974 format %{ "OR $dst.lo,$src1.lo,$src2.lo\t! long\n\t" 6975 "OR $dst.hi,$src1.hi,$src2.hi" %} 6976 ins_encode %{ 6977 __ orr($dst$$Register, $src1$$Register, $src2$$Register); 6978 __ orr($dst$$Register->successor(), $src1$$Register->successor(), $src2$$Register->successor()); 6979 %} 6980 ins_pipe(ialu_reg_reg); 6981 %} 6982 6983 // TODO: try immLRot2 instead, (0, $con$$constant) becomes 6984 // (hi($con$$constant), lo($con$$constant)) becomes 6985 instruct orL_reg_immRot(iRegL dst, iRegL src1, immLlowRot con) %{ 6986 match(Set dst (OrL src1 con)); 6987 ins_cost(DEFAULT_COST); 6988 size(8); 6989 format %{ "OR $dst.lo,$src1.lo,$con\t! long\n\t" 6990 "OR $dst.hi,$src1.hi,$con" %} 6991 ins_encode %{ 6992 __ orr($dst$$Register, $src1$$Register, $con$$constant); 6993 __ orr($dst$$Register->successor(), $src1$$Register->successor(), 0); 6994 %} 6995 ins_pipe(ialu_reg_imm); 6996 %} 6997 6998 #ifdef TODO 6999 // Use SPRegP to match Rthread (TLS register) without spilling. 7000 // Use store_ptr_RegP to match Rthread (TLS register) without spilling. 7001 // Use sp_ptr_RegP to match Rthread (TLS register) without spilling. 7002 instruct orI_reg_castP2X(iRegI dst, iRegI src1, sp_ptr_RegP src2) %{ 7003 match(Set dst (OrI src1 (CastP2X src2))); 7004 size(4); 7005 format %{ "OR $dst,$src1,$src2" %} 7006 ins_encode %{ 7007 __ orr($dst$$Register, $src1$$Register, $src2$$Register); 7008 %} 7009 ins_pipe(ialu_reg_reg); 7010 %} 7011 #endif 7012 7013 // Xor Instructions 7014 // Register Xor 7015 instruct xorI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{ 7016 match(Set dst (XorI src1 src2)); 7017 7018 size(4); 7019 format %{ "eor_32 $dst,$src1,$src2" %} 7020 ins_encode %{ 7021 __ eor_32($dst$$Register, $src1$$Register, $src2$$Register); 7022 %} 7023 ins_pipe(ialu_reg_reg); 7024 %} 7025 7026 instruct xorshlI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 7027 match(Set dst (XorI src1 (LShiftI src2 src3))); 7028 7029 size(4); 7030 format %{ "XOR $dst,$src1,$src2<<$src3" %} 7031 ins_encode %{ 7032 __ eor($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$Register)); 7033 %} 7034 ins_pipe(ialu_reg_reg); 7035 %} 7036 7037 instruct xorshlI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{ 7038 match(Set dst (XorI src1 (LShiftI src2 src3))); 7039 7040 size(4); 7041 format %{ "eor_32 $dst,$src1,$src2<<$src3" %} 7042 ins_encode %{ 7043 __ eor_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsl, $src3$$constant)); 7044 %} 7045 ins_pipe(ialu_reg_reg); 7046 %} 7047 7048 instruct xorsarI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 7049 match(Set dst (XorI src1 (RShiftI src2 src3))); 7050 7051 size(4); 7052 format %{ "XOR $dst,$src1,$src2>>$src3" %} 7053 ins_encode %{ 7054 __ eor($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$Register)); 7055 %} 7056 ins_pipe(ialu_reg_reg); 7057 %} 7058 7059 instruct xorsarI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{ 7060 match(Set dst (XorI src1 (RShiftI src2 src3))); 7061 7062 size(4); 7063 format %{ "eor_32 $dst,$src1,$src2>>$src3" %} 7064 ins_encode %{ 7065 __ eor_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, asr, $src3$$constant)); 7066 %} 7067 ins_pipe(ialu_reg_reg); 7068 %} 7069 7070 instruct xorshrI_reg_reg_reg(iRegI dst, iRegI src1, iRegI src2, iRegI src3) %{ 7071 match(Set dst (XorI src1 (URShiftI src2 src3))); 7072 7073 size(4); 7074 format %{ "XOR $dst,$src1,$src2>>>$src3" %} 7075 ins_encode %{ 7076 __ eor($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$Register)); 7077 %} 7078 ins_pipe(ialu_reg_reg); 7079 %} 7080 7081 instruct xorshrI_reg_reg_imm(iRegI dst, iRegI src1, iRegI src2, immU5 src3) %{ 7082 match(Set dst (XorI src1 (URShiftI src2 src3))); 7083 7084 size(4); 7085 format %{ "eor_32 $dst,$src1,$src2>>>$src3" %} 7086 ins_encode %{ 7087 __ eor_32($dst$$Register, $src1$$Register, AsmOperand($src2$$Register, lsr, $src3$$constant)); 7088 %} 7089 ins_pipe(ialu_reg_reg); 7090 %} 7091 7092 // Immediate Xor 7093 instruct xorI_reg_imm(iRegI dst, iRegI src1, limmI src2) %{ 7094 match(Set dst (XorI src1 src2)); 7095 7096 size(4); 7097 format %{ "eor_32 $dst,$src1,$src2" %} 7098 ins_encode %{ 7099 __ eor_32($dst$$Register, $src1$$Register, $src2$$constant); 7100 %} 7101 ins_pipe(ialu_reg_imm); 7102 %} 7103 7104 // Register Xor Long 7105 instruct xorL_reg_reg(iRegL dst, iRegL src1, iRegL src2) %{ 7106 match(Set dst (XorL src1 src2)); 7107 ins_cost(DEFAULT_COST); 7108 size(8); 7109 format %{ "XOR $dst.hi,$src1.hi,$src2.hi\t! long\n\t" 7110 "XOR $dst.lo,$src1.lo,$src2.lo\t! long" %} 7111 ins_encode %{ 7112 __ eor($dst$$Register, $src1$$Register, $src2$$Register); 7113 __ eor($dst$$Register->successor(), $src1$$Register->successor(), $src2$$Register->successor()); 7114 %} 7115 ins_pipe(ialu_reg_reg); 7116 %} 7117 7118 // TODO: try immLRot2 instead, (0, $con$$constant) becomes 7119 // (hi($con$$constant), lo($con$$constant)) becomes 7120 instruct xorL_reg_immRot(iRegL dst, iRegL src1, immLlowRot con) %{ 7121 match(Set dst (XorL src1 con)); 7122 ins_cost(DEFAULT_COST); 7123 size(8); 7124 format %{ "XOR $dst.hi,$src1.hi,$con\t! long\n\t" 7125 "XOR $dst.lo,$src1.lo,0\t! long" %} 7126 ins_encode %{ 7127 __ eor($dst$$Register, $src1$$Register, $con$$constant); 7128 __ eor($dst$$Register->successor(), $src1$$Register->successor(), 0); 7129 %} 7130 ins_pipe(ialu_reg_imm); 7131 %} 7132 7133 //----------Convert to Boolean------------------------------------------------- 7134 instruct convI2B( iRegI dst, iRegI src, flagsReg ccr ) %{ 7135 match(Set dst (Conv2B src)); 7136 effect(KILL ccr); 7137 size(12); 7138 ins_cost(DEFAULT_COST*2); 7139 format %{ "TST $src,$src \n\t" 7140 "MOV $dst, 0 \n\t" 7141 "MOV.ne $dst, 1" %} 7142 ins_encode %{ // FIXME: can do better? 7143 __ tst($src$$Register, $src$$Register); 7144 __ mov($dst$$Register, 0); 7145 __ mov($dst$$Register, 1, ne); 7146 %} 7147 ins_pipe(ialu_reg_ialu); 7148 %} 7149 7150 instruct convP2B( iRegI dst, iRegP src, flagsReg ccr ) %{ 7151 match(Set dst (Conv2B src)); 7152 effect(KILL ccr); 7153 size(12); 7154 ins_cost(DEFAULT_COST*2); 7155 format %{ "TST $src,$src \n\t" 7156 "MOV $dst, 0 \n\t" 7157 "MOV.ne $dst, 1" %} 7158 ins_encode %{ 7159 __ tst($src$$Register, $src$$Register); 7160 __ mov($dst$$Register, 0); 7161 __ mov($dst$$Register, 1, ne); 7162 %} 7163 ins_pipe(ialu_reg_ialu); 7164 %} 7165 7166 instruct cmpLTMask_reg_reg( iRegI dst, iRegI p, iRegI q, flagsReg ccr ) %{ 7167 match(Set dst (CmpLTMask p q)); 7168 effect( KILL ccr ); 7169 ins_cost(DEFAULT_COST*3); 7170 format %{ "CMP $p,$q\n\t" 7171 "MOV $dst, #0\n\t" 7172 "MOV.lt $dst, #-1" %} 7173 ins_encode %{ 7174 __ cmp($p$$Register, $q$$Register); 7175 __ mov($dst$$Register, 0); 7176 __ mvn($dst$$Register, 0, lt); 7177 %} 7178 ins_pipe(ialu_reg_reg_ialu); 7179 %} 7180 7181 instruct cmpLTMask_reg_imm( iRegI dst, iRegI p, aimmI q, flagsReg ccr ) %{ 7182 match(Set dst (CmpLTMask p q)); 7183 effect( KILL ccr ); 7184 ins_cost(DEFAULT_COST*3); 7185 format %{ "CMP $p,$q\n\t" 7186 "MOV $dst, #0\n\t" 7187 "MOV.lt $dst, #-1" %} 7188 ins_encode %{ 7189 __ cmp($p$$Register, $q$$constant); 7190 __ mov($dst$$Register, 0); 7191 __ mvn($dst$$Register, 0, lt); 7192 %} 7193 ins_pipe(ialu_reg_reg_ialu); 7194 %} 7195 7196 instruct cadd_cmpLTMask3( iRegI p, iRegI q, iRegI y, iRegI z, flagsReg ccr ) %{ 7197 match(Set z (AddI (AndI (CmpLTMask p q) y) z)); 7198 effect( KILL ccr ); 7199 ins_cost(DEFAULT_COST*2); 7200 format %{ "CMP $p,$q\n\t" 7201 "ADD.lt $z,$y,$z" %} 7202 ins_encode %{ 7203 __ cmp($p$$Register, $q$$Register); 7204 __ add($z$$Register, $y$$Register, $z$$Register, lt); 7205 %} 7206 ins_pipe( cadd_cmpltmask ); 7207 %} 7208 7209 // FIXME: remove unused "dst" 7210 instruct cadd_cmpLTMask4( iRegI dst, iRegI p, aimmI q, iRegI y, iRegI z, flagsReg ccr ) %{ 7211 match(Set z (AddI (AndI (CmpLTMask p q) y) z)); 7212 effect( KILL ccr ); 7213 ins_cost(DEFAULT_COST*2); 7214 format %{ "CMP $p,$q\n\t" 7215 "ADD.lt $z,$y,$z" %} 7216 ins_encode %{ 7217 __ cmp($p$$Register, $q$$constant); 7218 __ add($z$$Register, $y$$Register, $z$$Register, lt); 7219 %} 7220 ins_pipe( cadd_cmpltmask ); 7221 %} 7222 7223 instruct cadd_cmpLTMask( iRegI p, iRegI q, iRegI y, flagsReg ccr ) %{ 7224 match(Set p (AddI (AndI (CmpLTMask p q) y) (SubI p q))); 7225 effect( KILL ccr ); 7226 ins_cost(DEFAULT_COST*2); 7227 format %{ "SUBS $p,$p,$q\n\t" 7228 "ADD.lt $p,$y,$p" %} 7229 ins_encode %{ 7230 __ subs($p$$Register, $p$$Register, $q$$Register); 7231 __ add($p$$Register, $y$$Register, $p$$Register, lt); 7232 %} 7233 ins_pipe( cadd_cmpltmask ); 7234 %} 7235 7236 //----------Arithmetic Conversion Instructions--------------------------------- 7237 // The conversions operations are all Alpha sorted. Please keep it that way! 7238 7239 instruct convD2F_reg(regF dst, regD src) %{ 7240 match(Set dst (ConvD2F src)); 7241 size(4); 7242 format %{ "FCVTSD $dst,$src" %} 7243 ins_encode %{ 7244 __ convert_d2f($dst$$FloatRegister, $src$$FloatRegister); 7245 %} 7246 ins_pipe(fcvtD2F); 7247 %} 7248 7249 // Convert a double to an int in a float register. 7250 // If the double is a NAN, stuff a zero in instead. 7251 7252 instruct convD2I_reg_reg(iRegI dst, regD src, regF tmp) %{ 7253 match(Set dst (ConvD2I src)); 7254 effect( TEMP tmp ); 7255 ins_cost(DEFAULT_COST*2 + MEMORY_REF_COST*2 + BRANCH_COST); // FIXME 7256 format %{ "FTOSIZD $tmp,$src\n\t" 7257 "FMRS $dst, $tmp" %} 7258 ins_encode %{ 7259 __ ftosizd($tmp$$FloatRegister, $src$$FloatRegister); 7260 __ fmrs($dst$$Register, $tmp$$FloatRegister); 7261 %} 7262 ins_pipe(fcvtD2I); 7263 %} 7264 7265 // Convert a double to a long in a double register. 7266 // If the double is a NAN, stuff a zero in instead. 7267 7268 // Double to Long conversion 7269 instruct convD2L_reg(R0R1RegL dst, regD src) %{ 7270 match(Set dst (ConvD2L src)); 7271 effect(CALL); 7272 ins_cost(MEMORY_REF_COST); // FIXME 7273 format %{ "convD2L $dst,$src\t ! call to SharedRuntime::d2l" %} 7274 ins_encode %{ 7275 #ifndef __ABI_HARD__ 7276 __ fmrrd($dst$$Register, $dst$$Register->successor(), $src$$FloatRegister); 7277 #else 7278 if ($src$$FloatRegister != D0) { 7279 __ mov_double(D0, $src$$FloatRegister); 7280 } 7281 #endif 7282 address target = CAST_FROM_FN_PTR(address, SharedRuntime::d2l); 7283 __ call(target, relocInfo::runtime_call_type); 7284 %} 7285 ins_pipe(fcvtD2L); 7286 %} 7287 7288 instruct convF2D_reg(regD dst, regF src) %{ 7289 match(Set dst (ConvF2D src)); 7290 size(4); 7291 format %{ "FCVTDS $dst,$src" %} 7292 ins_encode %{ 7293 __ convert_f2d($dst$$FloatRegister, $src$$FloatRegister); 7294 %} 7295 ins_pipe(fcvtF2D); 7296 %} 7297 7298 instruct convF2I_reg_reg(iRegI dst, regF src, regF tmp) %{ 7299 match(Set dst (ConvF2I src)); 7300 effect( TEMP tmp ); 7301 ins_cost(DEFAULT_COST*2 + MEMORY_REF_COST*2 + BRANCH_COST); // FIXME 7302 size(8); 7303 format %{ "FTOSIZS $tmp,$src\n\t" 7304 "FMRS $dst, $tmp" %} 7305 ins_encode %{ 7306 __ ftosizs($tmp$$FloatRegister, $src$$FloatRegister); 7307 __ fmrs($dst$$Register, $tmp$$FloatRegister); 7308 %} 7309 ins_pipe(fcvtF2I); 7310 %} 7311 7312 // Float to Long conversion 7313 instruct convF2L_reg(R0R1RegL dst, regF src, R0RegI arg1) %{ 7314 match(Set dst (ConvF2L src)); 7315 ins_cost(DEFAULT_COST*2 + MEMORY_REF_COST*2 + BRANCH_COST); // FIXME 7316 effect(CALL); 7317 format %{ "convF2L $dst,$src\t! call to SharedRuntime::f2l" %} 7318 ins_encode %{ 7319 #ifndef __ABI_HARD__ 7320 __ fmrs($arg1$$Register, $src$$FloatRegister); 7321 #else 7322 if($src$$FloatRegister != S0) { 7323 __ mov_float(S0, $src$$FloatRegister); 7324 } 7325 #endif 7326 address target = CAST_FROM_FN_PTR(address, SharedRuntime::f2l); 7327 __ call(target, relocInfo::runtime_call_type); 7328 %} 7329 ins_pipe(fcvtF2L); 7330 %} 7331 7332 instruct convI2D_reg_reg(iRegI src, regD_low dst) %{ 7333 match(Set dst (ConvI2D src)); 7334 ins_cost(DEFAULT_COST + MEMORY_REF_COST); // FIXME 7335 size(8); 7336 format %{ "FMSR $dst,$src \n\t" 7337 "FSITOD $dst $dst"%} 7338 ins_encode %{ 7339 __ fmsr($dst$$FloatRegister, $src$$Register); 7340 __ fsitod($dst$$FloatRegister, $dst$$FloatRegister); 7341 %} 7342 ins_pipe(fcvtI2D); 7343 %} 7344 7345 instruct convI2F_reg_reg( regF dst, iRegI src ) %{ 7346 match(Set dst (ConvI2F src)); 7347 ins_cost(DEFAULT_COST + MEMORY_REF_COST); // FIXME 7348 size(8); 7349 format %{ "FMSR $dst,$src \n\t" 7350 "FSITOS $dst, $dst"%} 7351 ins_encode %{ 7352 __ fmsr($dst$$FloatRegister, $src$$Register); 7353 __ fsitos($dst$$FloatRegister, $dst$$FloatRegister); 7354 %} 7355 ins_pipe(fcvtI2F); 7356 %} 7357 7358 instruct convI2L_reg(iRegL dst, iRegI src) %{ 7359 match(Set dst (ConvI2L src)); 7360 size(8); 7361 format %{ "MOV $dst.lo, $src \n\t" 7362 "ASR $dst.hi,$src,31\t! int->long" %} 7363 ins_encode %{ 7364 __ mov($dst$$Register, $src$$Register); 7365 __ mov($dst$$Register->successor(), AsmOperand($src$$Register, asr, 31)); 7366 %} 7367 ins_pipe(ialu_reg_reg); 7368 %} 7369 7370 // Zero-extend convert int to long 7371 instruct convI2L_reg_zex(iRegL dst, iRegI src, immL_32bits mask ) %{ 7372 match(Set dst (AndL (ConvI2L src) mask) ); 7373 size(8); 7374 format %{ "MOV $dst.lo,$src.lo\t! zero-extend int to long\n\t" 7375 "MOV $dst.hi, 0"%} 7376 ins_encode %{ 7377 __ mov($dst$$Register, $src$$Register); 7378 __ mov($dst$$Register->successor(), 0); 7379 %} 7380 ins_pipe(ialu_reg_reg); 7381 %} 7382 7383 // Zero-extend long 7384 instruct zerox_long(iRegL dst, iRegL src, immL_32bits mask ) %{ 7385 match(Set dst (AndL src mask) ); 7386 size(8); 7387 format %{ "MOV $dst.lo,$src.lo\t! zero-extend long\n\t" 7388 "MOV $dst.hi, 0"%} 7389 ins_encode %{ 7390 __ mov($dst$$Register, $src$$Register); 7391 __ mov($dst$$Register->successor(), 0); 7392 %} 7393 ins_pipe(ialu_reg_reg); 7394 %} 7395 7396 instruct MoveF2I_reg_reg(iRegI dst, regF src) %{ 7397 match(Set dst (MoveF2I src)); 7398 effect(DEF dst, USE src); 7399 ins_cost(MEMORY_REF_COST); // FIXME 7400 7401 size(4); 7402 format %{ "FMRS $dst,$src\t! MoveF2I" %} 7403 ins_encode %{ 7404 __ fmrs($dst$$Register, $src$$FloatRegister); 7405 %} 7406 ins_pipe(iload_mem); // FIXME 7407 %} 7408 7409 instruct MoveI2F_reg_reg(regF dst, iRegI src) %{ 7410 match(Set dst (MoveI2F src)); 7411 ins_cost(MEMORY_REF_COST); // FIXME 7412 7413 size(4); 7414 format %{ "FMSR $dst,$src\t! MoveI2F" %} 7415 ins_encode %{ 7416 __ fmsr($dst$$FloatRegister, $src$$Register); 7417 %} 7418 ins_pipe(iload_mem); // FIXME 7419 %} 7420 7421 instruct MoveD2L_reg_reg(iRegL dst, regD src) %{ 7422 match(Set dst (MoveD2L src)); 7423 effect(DEF dst, USE src); 7424 ins_cost(MEMORY_REF_COST); // FIXME 7425 7426 size(4); 7427 format %{ "FMRRD $dst,$src\t! MoveD2L" %} 7428 ins_encode %{ 7429 __ fmrrd($dst$$Register, $dst$$Register->successor(), $src$$FloatRegister); 7430 %} 7431 ins_pipe(iload_mem); // FIXME 7432 %} 7433 7434 instruct MoveL2D_reg_reg(regD dst, iRegL src) %{ 7435 match(Set dst (MoveL2D src)); 7436 effect(DEF dst, USE src); 7437 ins_cost(MEMORY_REF_COST); // FIXME 7438 7439 size(4); 7440 format %{ "FMDRR $dst,$src\t! MoveL2D" %} 7441 ins_encode %{ 7442 __ fmdrr($dst$$FloatRegister, $src$$Register, $src$$Register->successor()); 7443 %} 7444 ins_pipe(ialu_reg_reg); // FIXME 7445 %} 7446 7447 //----------- 7448 // Long to Double conversion 7449 7450 // Magic constant, 0x43300000 7451 instruct loadConI_x43300000(iRegI dst) %{ 7452 effect(DEF dst); 7453 size(8); 7454 format %{ "MOV_SLOW $dst,0x43300000\t! 2^52" %} 7455 ins_encode %{ 7456 __ mov_slow($dst$$Register, 0x43300000); 7457 %} 7458 ins_pipe(ialu_none); 7459 %} 7460 7461 // Magic constant, 0x41f00000 7462 instruct loadConI_x41f00000(iRegI dst) %{ 7463 effect(DEF dst); 7464 size(8); 7465 format %{ "MOV_SLOW $dst, 0x41f00000\t! 2^32" %} 7466 ins_encode %{ 7467 __ mov_slow($dst$$Register, 0x41f00000); 7468 %} 7469 ins_pipe(ialu_none); 7470 %} 7471 7472 instruct loadConI_x0(iRegI dst) %{ 7473 effect(DEF dst); 7474 size(4); 7475 format %{ "MOV $dst, 0x0\t! 0" %} 7476 ins_encode %{ 7477 __ mov($dst$$Register, 0); 7478 %} 7479 ins_pipe(ialu_none); 7480 %} 7481 7482 // Construct a double from two float halves 7483 instruct regDHi_regDLo_to_regD(regD_low dst, regD_low src1, regD_low src2) %{ 7484 effect(DEF dst, USE src1, USE src2); 7485 size(8); 7486 format %{ "FCPYS $dst.hi,$src1.hi\n\t" 7487 "FCPYS $dst.lo,$src2.lo" %} 7488 ins_encode %{ 7489 __ fcpys($dst$$FloatRegister->successor(), $src1$$FloatRegister->successor()); 7490 __ fcpys($dst$$FloatRegister, $src2$$FloatRegister); 7491 %} 7492 ins_pipe(faddD_reg_reg); 7493 %} 7494 7495 // Convert integer in high half of a double register (in the lower half of 7496 // the double register file) to double 7497 instruct convI2D_regDHi_regD(regD dst, regD_low src) %{ 7498 effect(DEF dst, USE src); 7499 size(4); 7500 format %{ "FSITOD $dst,$src" %} 7501 ins_encode %{ 7502 __ fsitod($dst$$FloatRegister, $src$$FloatRegister->successor()); 7503 %} 7504 ins_pipe(fcvtLHi2D); 7505 %} 7506 7507 // Add float double precision 7508 instruct addD_regD_regD(regD dst, regD src1, regD src2) %{ 7509 effect(DEF dst, USE src1, USE src2); 7510 size(4); 7511 format %{ "FADDD $dst,$src1,$src2" %} 7512 ins_encode %{ 7513 __ add_double($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister); 7514 %} 7515 ins_pipe(faddD_reg_reg); 7516 %} 7517 7518 // Sub float double precision 7519 instruct subD_regD_regD(regD dst, regD src1, regD src2) %{ 7520 effect(DEF dst, USE src1, USE src2); 7521 size(4); 7522 format %{ "FSUBD $dst,$src1,$src2" %} 7523 ins_encode %{ 7524 __ sub_double($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister); 7525 %} 7526 ins_pipe(faddD_reg_reg); 7527 %} 7528 7529 // Mul float double precision 7530 instruct mulD_regD_regD(regD dst, regD src1, regD src2) %{ 7531 effect(DEF dst, USE src1, USE src2); 7532 size(4); 7533 format %{ "FMULD $dst,$src1,$src2" %} 7534 ins_encode %{ 7535 __ mul_double($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister); 7536 %} 7537 ins_pipe(fmulD_reg_reg); 7538 %} 7539 7540 instruct regL_to_regD(regD dst, iRegL src) %{ 7541 // No match rule to avoid chain rule match. 7542 effect(DEF dst, USE src); 7543 ins_cost(MEMORY_REF_COST); 7544 size(4); 7545 format %{ "FMDRR $dst,$src\t! regL to regD" %} 7546 ins_encode %{ 7547 __ fmdrr($dst$$FloatRegister, $src$$Register, $src$$Register->successor()); 7548 %} 7549 ins_pipe(ialu_reg_reg); // FIXME 7550 %} 7551 7552 instruct regI_regI_to_regD(regD dst, iRegI src1, iRegI src2) %{ 7553 // No match rule to avoid chain rule match. 7554 effect(DEF dst, USE src1, USE src2); 7555 ins_cost(MEMORY_REF_COST); 7556 size(4); 7557 format %{ "FMDRR $dst,$src1,$src2\t! regI,regI to regD" %} 7558 ins_encode %{ 7559 __ fmdrr($dst$$FloatRegister, $src1$$Register, $src2$$Register); 7560 %} 7561 ins_pipe(ialu_reg_reg); // FIXME 7562 %} 7563 7564 instruct convL2D_reg_slow_fxtof(regD dst, iRegL src) %{ 7565 match(Set dst (ConvL2D src)); 7566 ins_cost(DEFAULT_COST*8 + MEMORY_REF_COST*6); // FIXME 7567 7568 expand %{ 7569 regD_low tmpsrc; 7570 iRegI ix43300000; 7571 iRegI ix41f00000; 7572 iRegI ix0; 7573 regD_low dx43300000; 7574 regD dx41f00000; 7575 regD tmp1; 7576 regD_low tmp2; 7577 regD tmp3; 7578 regD tmp4; 7579 7580 regL_to_regD(tmpsrc, src); 7581 7582 loadConI_x43300000(ix43300000); 7583 loadConI_x41f00000(ix41f00000); 7584 loadConI_x0(ix0); 7585 7586 regI_regI_to_regD(dx43300000, ix0, ix43300000); 7587 regI_regI_to_regD(dx41f00000, ix0, ix41f00000); 7588 7589 convI2D_regDHi_regD(tmp1, tmpsrc); 7590 regDHi_regDLo_to_regD(tmp2, dx43300000, tmpsrc); 7591 subD_regD_regD(tmp3, tmp2, dx43300000); 7592 mulD_regD_regD(tmp4, tmp1, dx41f00000); 7593 addD_regD_regD(dst, tmp3, tmp4); 7594 %} 7595 %} 7596 7597 instruct convL2I_reg(iRegI dst, iRegL src) %{ 7598 match(Set dst (ConvL2I src)); 7599 size(4); 7600 format %{ "MOV $dst,$src.lo\t! long->int" %} 7601 ins_encode %{ 7602 __ mov($dst$$Register, $src$$Register); 7603 %} 7604 ins_pipe(ialu_move_reg_I_to_L); 7605 %} 7606 7607 // Register Shift Right Immediate 7608 instruct shrL_reg_imm6_L2I(iRegI dst, iRegL src, immI_32_63 cnt) %{ 7609 match(Set dst (ConvL2I (RShiftL src cnt))); 7610 size(4); 7611 format %{ "ASR $dst,$src.hi,($cnt - 32)\t! long->int or mov if $cnt==32" %} 7612 ins_encode %{ 7613 if ($cnt$$constant == 32) { 7614 __ mov($dst$$Register, $src$$Register->successor()); 7615 } else { 7616 __ mov($dst$$Register, AsmOperand($src$$Register->successor(), asr, $cnt$$constant - 32)); 7617 } 7618 %} 7619 ins_pipe(ialu_reg_imm); 7620 %} 7621 7622 7623 //----------Control Flow Instructions------------------------------------------ 7624 // Compare Instructions 7625 // Compare Integers 7626 instruct compI_iReg(flagsReg icc, iRegI op1, iRegI op2) %{ 7627 match(Set icc (CmpI op1 op2)); 7628 effect( DEF icc, USE op1, USE op2 ); 7629 7630 size(4); 7631 format %{ "cmp_32 $op1,$op2\t! int" %} 7632 ins_encode %{ 7633 __ cmp_32($op1$$Register, $op2$$Register); 7634 %} 7635 ins_pipe(ialu_cconly_reg_reg); 7636 %} 7637 7638 #ifdef _LP64 7639 // Compare compressed pointers 7640 instruct compN_reg2(flagsRegU icc, iRegN op1, iRegN op2) %{ 7641 match(Set icc (CmpN op1 op2)); 7642 effect( DEF icc, USE op1, USE op2 ); 7643 7644 size(4); 7645 format %{ "cmp_32 $op1,$op2\t! int" %} 7646 ins_encode %{ 7647 __ cmp_32($op1$$Register, $op2$$Register); 7648 %} 7649 ins_pipe(ialu_cconly_reg_reg); 7650 %} 7651 #endif 7652 7653 instruct compU_iReg(flagsRegU icc, iRegI op1, iRegI op2) %{ 7654 match(Set icc (CmpU op1 op2)); 7655 7656 size(4); 7657 format %{ "cmp_32 $op1,$op2\t! unsigned int" %} 7658 ins_encode %{ 7659 __ cmp_32($op1$$Register, $op2$$Register); 7660 %} 7661 ins_pipe(ialu_cconly_reg_reg); 7662 %} 7663 7664 instruct compI_iReg_immneg(flagsReg icc, iRegI op1, aimmIneg op2) %{ 7665 match(Set icc (CmpI op1 op2)); 7666 effect( DEF icc, USE op1 ); 7667 7668 size(4); 7669 format %{ "cmn_32 $op1,-$op2\t! int" %} 7670 ins_encode %{ 7671 __ cmn_32($op1$$Register, -$op2$$constant); 7672 %} 7673 ins_pipe(ialu_cconly_reg_imm); 7674 %} 7675 7676 instruct compI_iReg_imm(flagsReg icc, iRegI op1, aimmI op2) %{ 7677 match(Set icc (CmpI op1 op2)); 7678 effect( DEF icc, USE op1 ); 7679 7680 size(4); 7681 format %{ "cmp_32 $op1,$op2\t! int" %} 7682 ins_encode %{ 7683 __ cmp_32($op1$$Register, $op2$$constant); 7684 %} 7685 ins_pipe(ialu_cconly_reg_imm); 7686 %} 7687 7688 instruct testI_reg_reg( flagsReg_EQNELTGE icc, iRegI op1, iRegI op2, immI0 zero ) %{ 7689 match(Set icc (CmpI (AndI op1 op2) zero)); 7690 size(4); 7691 format %{ "tst_32 $op2,$op1" %} 7692 7693 ins_encode %{ 7694 __ tst_32($op1$$Register, $op2$$Register); 7695 %} 7696 ins_pipe(ialu_cconly_reg_reg_zero); 7697 %} 7698 7699 instruct testshlI_reg_reg_reg( flagsReg_EQNELTGE icc, iRegI op1, iRegI op2, iRegI op3, immI0 zero ) %{ 7700 match(Set icc (CmpI (AndI op1 (LShiftI op2 op3)) zero)); 7701 size(4); 7702 format %{ "TST $op2,$op1<<$op3" %} 7703 7704 ins_encode %{ 7705 __ tst($op1$$Register, AsmOperand($op2$$Register, lsl, $op3$$Register)); 7706 %} 7707 ins_pipe(ialu_cconly_reg_reg_zero); 7708 %} 7709 7710 instruct testshlI_reg_reg_imm( flagsReg_EQNELTGE icc, iRegI op1, iRegI op2, immU5 op3, immI0 zero ) %{ 7711 match(Set icc (CmpI (AndI op1 (LShiftI op2 op3)) zero)); 7712 size(4); 7713 format %{ "tst_32 $op2,$op1<<$op3" %} 7714 7715 ins_encode %{ 7716 __ tst_32($op1$$Register, AsmOperand($op2$$Register, lsl, $op3$$constant)); 7717 %} 7718 ins_pipe(ialu_cconly_reg_reg_zero); 7719 %} 7720 7721 instruct testsarI_reg_reg_reg( flagsReg_EQNELTGE icc, iRegI op1, iRegI op2, iRegI op3, immI0 zero ) %{ 7722 match(Set icc (CmpI (AndI op1 (RShiftI op2 op3)) zero)); 7723 size(4); 7724 format %{ "TST $op2,$op1<<$op3" %} 7725 7726 ins_encode %{ 7727 __ tst($op1$$Register, AsmOperand($op2$$Register, asr, $op3$$Register)); 7728 %} 7729 ins_pipe(ialu_cconly_reg_reg_zero); 7730 %} 7731 7732 instruct testsarI_reg_reg_imm( flagsReg_EQNELTGE icc, iRegI op1, iRegI op2, immU5 op3, immI0 zero ) %{ 7733 match(Set icc (CmpI (AndI op1 (RShiftI op2 op3)) zero)); 7734 size(4); 7735 format %{ "tst_32 $op2,$op1<<$op3" %} 7736 7737 ins_encode %{ 7738 __ tst_32($op1$$Register, AsmOperand($op2$$Register, asr, $op3$$constant)); 7739 %} 7740 ins_pipe(ialu_cconly_reg_reg_zero); 7741 %} 7742 7743 instruct testshrI_reg_reg_reg( flagsReg_EQNELTGE icc, iRegI op1, iRegI op2, iRegI op3, immI0 zero ) %{ 7744 match(Set icc (CmpI (AndI op1 (URShiftI op2 op3)) zero)); 7745 size(4); 7746 format %{ "TST $op2,$op1<<$op3" %} 7747 7748 ins_encode %{ 7749 __ tst($op1$$Register, AsmOperand($op2$$Register, lsr, $op3$$Register)); 7750 %} 7751 ins_pipe(ialu_cconly_reg_reg_zero); 7752 %} 7753 7754 instruct testshrI_reg_reg_imm( flagsReg_EQNELTGE icc, iRegI op1, iRegI op2, immU5 op3, immI0 zero ) %{ 7755 match(Set icc (CmpI (AndI op1 (URShiftI op2 op3)) zero)); 7756 size(4); 7757 format %{ "tst_32 $op2,$op1<<$op3" %} 7758 7759 ins_encode %{ 7760 __ tst_32($op1$$Register, AsmOperand($op2$$Register, lsr, $op3$$constant)); 7761 %} 7762 ins_pipe(ialu_cconly_reg_reg_zero); 7763 %} 7764 7765 instruct testI_reg_imm( flagsReg_EQNELTGE icc, iRegI op1, limmI op2, immI0 zero ) %{ 7766 match(Set icc (CmpI (AndI op1 op2) zero)); 7767 size(4); 7768 format %{ "tst_32 $op2,$op1" %} 7769 7770 ins_encode %{ 7771 __ tst_32($op1$$Register, $op2$$constant); 7772 %} 7773 ins_pipe(ialu_cconly_reg_imm_zero); 7774 %} 7775 7776 instruct compL_reg_reg_LTGE(flagsRegL_LTGE xcc, iRegL op1, iRegL op2, iRegL tmp) %{ 7777 match(Set xcc (CmpL op1 op2)); 7778 effect( DEF xcc, USE op1, USE op2, TEMP tmp ); 7779 7780 size(8); 7781 format %{ "SUBS $tmp,$op1.low,$op2.low\t\t! long\n\t" 7782 "SBCS $tmp,$op1.hi,$op2.hi" %} 7783 ins_encode %{ 7784 __ subs($tmp$$Register, $op1$$Register, $op2$$Register); 7785 __ sbcs($tmp$$Register->successor(), $op1$$Register->successor(), $op2$$Register->successor()); 7786 %} 7787 ins_pipe(ialu_cconly_reg_reg); 7788 %} 7789 7790 instruct compUL_reg_reg_LTGE(flagsRegUL_LTGE xcc, iRegL op1, iRegL op2, iRegL tmp) %{ 7791 match(Set xcc (CmpUL op1 op2)); 7792 effect(DEF xcc, USE op1, USE op2, TEMP tmp); 7793 7794 size(8); 7795 format %{ "SUBS $tmp,$op1.low,$op2.low\t\t! unsigned long\n\t" 7796 "SBCS $tmp,$op1.hi,$op2.hi" %} 7797 ins_encode %{ 7798 __ subs($tmp$$Register, $op1$$Register, $op2$$Register); 7799 __ sbcs($tmp$$Register->successor(), $op1$$Register->successor(), $op2$$Register->successor()); 7800 %} 7801 ins_pipe(ialu_cconly_reg_reg); 7802 %} 7803 7804 instruct compL_reg_reg_EQNE(flagsRegL_EQNE xcc, iRegL op1, iRegL op2) %{ 7805 match(Set xcc (CmpL op1 op2)); 7806 effect( DEF xcc, USE op1, USE op2 ); 7807 7808 size(8); 7809 format %{ "TEQ $op1.hi,$op2.hi\t\t! long\n\t" 7810 "TEQ.eq $op1.lo,$op2.lo" %} 7811 ins_encode %{ 7812 __ teq($op1$$Register->successor(), $op2$$Register->successor()); 7813 __ teq($op1$$Register, $op2$$Register, eq); 7814 %} 7815 ins_pipe(ialu_cconly_reg_reg); 7816 %} 7817 7818 instruct compL_reg_reg_LEGT(flagsRegL_LEGT xcc, iRegL op1, iRegL op2, iRegL tmp) %{ 7819 match(Set xcc (CmpL op1 op2)); 7820 effect( DEF xcc, USE op1, USE op2, TEMP tmp ); 7821 7822 size(8); 7823 format %{ "SUBS $tmp,$op2.low,$op1.low\t\t! long\n\t" 7824 "SBCS $tmp,$op2.hi,$op1.hi" %} 7825 ins_encode %{ 7826 __ subs($tmp$$Register, $op2$$Register, $op1$$Register); 7827 __ sbcs($tmp$$Register->successor(), $op2$$Register->successor(), $op1$$Register->successor()); 7828 %} 7829 ins_pipe(ialu_cconly_reg_reg); 7830 %} 7831 7832 // TODO: try immLRot2 instead, (0, $con$$constant) becomes 7833 // (hi($con$$constant), lo($con$$constant)) becomes 7834 instruct compL_reg_con_LTGE(flagsRegL_LTGE xcc, iRegL op1, immLlowRot con, iRegL tmp) %{ 7835 match(Set xcc (CmpL op1 con)); 7836 effect( DEF xcc, USE op1, USE con, TEMP tmp ); 7837 7838 size(8); 7839 format %{ "SUBS $tmp,$op1.low,$con\t\t! long\n\t" 7840 "SBCS $tmp,$op1.hi,0" %} 7841 ins_encode %{ 7842 __ subs($tmp$$Register, $op1$$Register, $con$$constant); 7843 __ sbcs($tmp$$Register->successor(), $op1$$Register->successor(), 0); 7844 %} 7845 7846 ins_pipe(ialu_cconly_reg_reg); 7847 %} 7848 7849 // TODO: try immLRot2 instead, (0, $con$$constant) becomes 7850 // (hi($con$$constant), lo($con$$constant)) becomes 7851 instruct compL_reg_con_EQNE(flagsRegL_EQNE xcc, iRegL op1, immLlowRot con) %{ 7852 match(Set xcc (CmpL op1 con)); 7853 effect( DEF xcc, USE op1, USE con ); 7854 7855 size(8); 7856 format %{ "TEQ $op1.hi,0\t\t! long\n\t" 7857 "TEQ.eq $op1.lo,$con" %} 7858 ins_encode %{ 7859 __ teq($op1$$Register->successor(), 0); 7860 __ teq($op1$$Register, $con$$constant, eq); 7861 %} 7862 7863 ins_pipe(ialu_cconly_reg_reg); 7864 %} 7865 7866 // TODO: try immLRot2 instead, (0, $con$$constant) becomes 7867 // (hi($con$$constant), lo($con$$constant)) becomes 7868 instruct compL_reg_con_LEGT(flagsRegL_LEGT xcc, iRegL op1, immLlowRot con, iRegL tmp) %{ 7869 match(Set xcc (CmpL op1 con)); 7870 effect( DEF xcc, USE op1, USE con, TEMP tmp ); 7871 7872 size(8); 7873 format %{ "RSBS $tmp,$op1.low,$con\t\t! long\n\t" 7874 "RSCS $tmp,$op1.hi,0" %} 7875 ins_encode %{ 7876 __ rsbs($tmp$$Register, $op1$$Register, $con$$constant); 7877 __ rscs($tmp$$Register->successor(), $op1$$Register->successor(), 0); 7878 %} 7879 7880 ins_pipe(ialu_cconly_reg_reg); 7881 %} 7882 7883 instruct compUL_reg_reg_EQNE(flagsRegUL_EQNE xcc, iRegL op1, iRegL op2) %{ 7884 match(Set xcc (CmpUL op1 op2)); 7885 effect(DEF xcc, USE op1, USE op2); 7886 7887 size(8); 7888 format %{ "TEQ $op1.hi,$op2.hi\t\t! unsigned long\n\t" 7889 "TEQ.eq $op1.lo,$op2.lo" %} 7890 ins_encode %{ 7891 __ teq($op1$$Register->successor(), $op2$$Register->successor()); 7892 __ teq($op1$$Register, $op2$$Register, eq); 7893 %} 7894 ins_pipe(ialu_cconly_reg_reg); 7895 %} 7896 7897 instruct compUL_reg_reg_LEGT(flagsRegUL_LEGT xcc, iRegL op1, iRegL op2, iRegL tmp) %{ 7898 match(Set xcc (CmpUL op1 op2)); 7899 effect(DEF xcc, USE op1, USE op2, TEMP tmp); 7900 7901 size(8); 7902 format %{ "SUBS $tmp,$op2.low,$op1.low\t\t! unsigned long\n\t" 7903 "SBCS $tmp,$op2.hi,$op1.hi" %} 7904 ins_encode %{ 7905 __ subs($tmp$$Register, $op2$$Register, $op1$$Register); 7906 __ sbcs($tmp$$Register->successor(), $op2$$Register->successor(), $op1$$Register->successor()); 7907 %} 7908 ins_pipe(ialu_cconly_reg_reg); 7909 %} 7910 7911 // TODO: try immLRot2 instead, (0, $con$$constant) becomes 7912 // (hi($con$$constant), lo($con$$constant)) becomes 7913 instruct compUL_reg_con_LTGE(flagsRegUL_LTGE xcc, iRegL op1, immLlowRot con, iRegL tmp) %{ 7914 match(Set xcc (CmpUL op1 con)); 7915 effect(DEF xcc, USE op1, USE con, TEMP tmp); 7916 7917 size(8); 7918 format %{ "SUBS $tmp,$op1.low,$con\t\t! unsigned long\n\t" 7919 "SBCS $tmp,$op1.hi,0" %} 7920 ins_encode %{ 7921 __ subs($tmp$$Register, $op1$$Register, $con$$constant); 7922 __ sbcs($tmp$$Register->successor(), $op1$$Register->successor(), 0); 7923 %} 7924 7925 ins_pipe(ialu_cconly_reg_reg); 7926 %} 7927 7928 // TODO: try immLRot2 instead, (0, $con$$constant) becomes 7929 // (hi($con$$constant), lo($con$$constant)) becomes 7930 instruct compUL_reg_con_EQNE(flagsRegUL_EQNE xcc, iRegL op1, immLlowRot con) %{ 7931 match(Set xcc (CmpUL op1 con)); 7932 effect(DEF xcc, USE op1, USE con); 7933 7934 size(8); 7935 format %{ "TEQ $op1.hi,0\t\t! unsigned long\n\t" 7936 "TEQ.eq $op1.lo,$con" %} 7937 ins_encode %{ 7938 __ teq($op1$$Register->successor(), 0); 7939 __ teq($op1$$Register, $con$$constant, eq); 7940 %} 7941 7942 ins_pipe(ialu_cconly_reg_reg); 7943 %} 7944 7945 // TODO: try immLRot2 instead, (0, $con$$constant) becomes 7946 // (hi($con$$constant), lo($con$$constant)) becomes 7947 instruct compUL_reg_con_LEGT(flagsRegUL_LEGT xcc, iRegL op1, immLlowRot con, iRegL tmp) %{ 7948 match(Set xcc (CmpUL op1 con)); 7949 effect(DEF xcc, USE op1, USE con, TEMP tmp); 7950 7951 size(8); 7952 format %{ "RSBS $tmp,$op1.low,$con\t\t! unsigned long\n\t" 7953 "RSCS $tmp,$op1.hi,0" %} 7954 ins_encode %{ 7955 __ rsbs($tmp$$Register, $op1$$Register, $con$$constant); 7956 __ rscs($tmp$$Register->successor(), $op1$$Register->successor(), 0); 7957 %} 7958 7959 ins_pipe(ialu_cconly_reg_reg); 7960 %} 7961 7962 /* instruct testL_reg_reg(flagsRegL xcc, iRegL op1, iRegL op2, immL0 zero) %{ */ 7963 /* match(Set xcc (CmpL (AndL op1 op2) zero)); */ 7964 /* ins_encode %{ */ 7965 /* __ stop("testL_reg_reg unimplemented"); */ 7966 /* %} */ 7967 /* ins_pipe(ialu_cconly_reg_reg); */ 7968 /* %} */ 7969 7970 /* // useful for checking the alignment of a pointer: */ 7971 /* instruct testL_reg_con(flagsRegL xcc, iRegL op1, immLlowRot con, immL0 zero) %{ */ 7972 /* match(Set xcc (CmpL (AndL op1 con) zero)); */ 7973 /* ins_encode %{ */ 7974 /* __ stop("testL_reg_con unimplemented"); */ 7975 /* %} */ 7976 /* ins_pipe(ialu_cconly_reg_reg); */ 7977 /* %} */ 7978 7979 instruct compU_iReg_imm(flagsRegU icc, iRegI op1, aimmU31 op2 ) %{ 7980 match(Set icc (CmpU op1 op2)); 7981 7982 size(4); 7983 format %{ "cmp_32 $op1,$op2\t! unsigned" %} 7984 ins_encode %{ 7985 __ cmp_32($op1$$Register, $op2$$constant); 7986 %} 7987 ins_pipe(ialu_cconly_reg_imm); 7988 %} 7989 7990 // Compare Pointers 7991 instruct compP_iRegP(flagsRegP pcc, iRegP op1, iRegP op2 ) %{ 7992 match(Set pcc (CmpP op1 op2)); 7993 7994 size(4); 7995 format %{ "CMP $op1,$op2\t! ptr" %} 7996 ins_encode %{ 7997 __ cmp($op1$$Register, $op2$$Register); 7998 %} 7999 ins_pipe(ialu_cconly_reg_reg); 8000 %} 8001 8002 instruct compP_iRegP_imm(flagsRegP pcc, iRegP op1, aimmP op2 ) %{ 8003 match(Set pcc (CmpP op1 op2)); 8004 8005 size(4); 8006 format %{ "CMP $op1,$op2\t! ptr" %} 8007 ins_encode %{ 8008 assert($op2$$constant == 0 || _opnds[2]->constant_reloc() == relocInfo::none, "reloc in cmp?"); 8009 __ cmp($op1$$Register, $op2$$constant); 8010 %} 8011 ins_pipe(ialu_cconly_reg_imm); 8012 %} 8013 8014 //----------Max and Min-------------------------------------------------------- 8015 // Min Instructions 8016 // Conditional move for min 8017 instruct cmovI_reg_lt( iRegI op2, iRegI op1, flagsReg icc ) %{ 8018 effect( USE_DEF op2, USE op1, USE icc ); 8019 8020 size(4); 8021 format %{ "MOV.lt $op2,$op1\t! min" %} 8022 ins_encode %{ 8023 __ mov($op2$$Register, $op1$$Register, lt); 8024 %} 8025 ins_pipe(ialu_reg_flags); 8026 %} 8027 8028 // Min Register with Register. 8029 instruct minI_eReg(iRegI op1, iRegI op2) %{ 8030 match(Set op2 (MinI op1 op2)); 8031 ins_cost(DEFAULT_COST*2); 8032 expand %{ 8033 flagsReg icc; 8034 compI_iReg(icc,op1,op2); 8035 cmovI_reg_lt(op2,op1,icc); 8036 %} 8037 %} 8038 8039 // Max Instructions 8040 // Conditional move for max 8041 instruct cmovI_reg_gt( iRegI op2, iRegI op1, flagsReg icc ) %{ 8042 effect( USE_DEF op2, USE op1, USE icc ); 8043 format %{ "MOV.gt $op2,$op1\t! max" %} 8044 ins_encode %{ 8045 __ mov($op2$$Register, $op1$$Register, gt); 8046 %} 8047 ins_pipe(ialu_reg_flags); 8048 %} 8049 8050 // Max Register with Register 8051 instruct maxI_eReg(iRegI op1, iRegI op2) %{ 8052 match(Set op2 (MaxI op1 op2)); 8053 ins_cost(DEFAULT_COST*2); 8054 expand %{ 8055 flagsReg icc; 8056 compI_iReg(icc,op1,op2); 8057 cmovI_reg_gt(op2,op1,icc); 8058 %} 8059 %} 8060 8061 8062 //----------Float Compares---------------------------------------------------- 8063 // Compare floating, generate condition code 8064 instruct cmpF_cc(flagsRegF fcc, flagsReg icc, regF src1, regF src2) %{ 8065 match(Set icc (CmpF src1 src2)); 8066 effect(KILL fcc); 8067 8068 size(8); 8069 format %{ "FCMPs $src1,$src2\n\t" 8070 "FMSTAT" %} 8071 ins_encode %{ 8072 __ fcmps($src1$$FloatRegister, $src2$$FloatRegister); 8073 __ fmstat(); 8074 %} 8075 ins_pipe(faddF_fcc_reg_reg_zero); 8076 %} 8077 8078 instruct cmpF0_cc(flagsRegF fcc, flagsReg icc, regF src1, immF0 src2) %{ 8079 match(Set icc (CmpF src1 src2)); 8080 effect(KILL fcc); 8081 8082 size(8); 8083 format %{ "FCMPs $src1,$src2\n\t" 8084 "FMSTAT" %} 8085 ins_encode %{ 8086 __ fcmpzs($src1$$FloatRegister); 8087 __ fmstat(); 8088 %} 8089 ins_pipe(faddF_fcc_reg_reg_zero); 8090 %} 8091 8092 instruct cmpD_cc(flagsRegF fcc, flagsReg icc, regD src1, regD src2) %{ 8093 match(Set icc (CmpD src1 src2)); 8094 effect(KILL fcc); 8095 8096 size(8); 8097 format %{ "FCMPd $src1,$src2 \n\t" 8098 "FMSTAT" %} 8099 ins_encode %{ 8100 __ fcmpd($src1$$FloatRegister, $src2$$FloatRegister); 8101 __ fmstat(); 8102 %} 8103 ins_pipe(faddD_fcc_reg_reg_zero); 8104 %} 8105 8106 instruct cmpD0_cc(flagsRegF fcc, flagsReg icc, regD src1, immD0 src2) %{ 8107 match(Set icc (CmpD src1 src2)); 8108 effect(KILL fcc); 8109 8110 size(8); 8111 format %{ "FCMPZd $src1,$src2 \n\t" 8112 "FMSTAT" %} 8113 ins_encode %{ 8114 __ fcmpzd($src1$$FloatRegister); 8115 __ fmstat(); 8116 %} 8117 ins_pipe(faddD_fcc_reg_reg_zero); 8118 %} 8119 8120 // Compare floating, generate -1,0,1 8121 instruct cmpF_reg(iRegI dst, regF src1, regF src2, flagsRegF fcc) %{ 8122 match(Set dst (CmpF3 src1 src2)); 8123 effect(KILL fcc); 8124 ins_cost(DEFAULT_COST*3+BRANCH_COST*3); // FIXME 8125 size(20); 8126 // same number of instructions as code using conditional moves but 8127 // doesn't kill integer condition register 8128 format %{ "FCMPs $dst,$src1,$src2 \n\t" 8129 "VMRS $dst, FPSCR \n\t" 8130 "OR $dst, $dst, 0x08000000 \n\t" 8131 "EOR $dst, $dst, $dst << 3 \n\t" 8132 "MOV $dst, $dst >> 30" %} 8133 ins_encode %{ 8134 __ fcmps($src1$$FloatRegister, $src2$$FloatRegister); 8135 __ floating_cmp($dst$$Register); 8136 %} 8137 ins_pipe( floating_cmp ); 8138 %} 8139 8140 instruct cmpF0_reg(iRegI dst, regF src1, immF0 src2, flagsRegF fcc) %{ 8141 match(Set dst (CmpF3 src1 src2)); 8142 effect(KILL fcc); 8143 ins_cost(DEFAULT_COST*3+BRANCH_COST*3); // FIXME 8144 size(20); 8145 // same number of instructions as code using conditional moves but 8146 // doesn't kill integer condition register 8147 format %{ "FCMPZs $dst,$src1,$src2 \n\t" 8148 "VMRS $dst, FPSCR \n\t" 8149 "OR $dst, $dst, 0x08000000 \n\t" 8150 "EOR $dst, $dst, $dst << 3 \n\t" 8151 "MOV $dst, $dst >> 30" %} 8152 ins_encode %{ 8153 __ fcmpzs($src1$$FloatRegister); 8154 __ floating_cmp($dst$$Register); 8155 %} 8156 ins_pipe( floating_cmp ); 8157 %} 8158 8159 instruct cmpD_reg(iRegI dst, regD src1, regD src2, flagsRegF fcc) %{ 8160 match(Set dst (CmpD3 src1 src2)); 8161 effect(KILL fcc); 8162 ins_cost(DEFAULT_COST*3+BRANCH_COST*3); // FIXME 8163 size(20); 8164 // same number of instructions as code using conditional moves but 8165 // doesn't kill integer condition register 8166 format %{ "FCMPd $dst,$src1,$src2 \n\t" 8167 "VMRS $dst, FPSCR \n\t" 8168 "OR $dst, $dst, 0x08000000 \n\t" 8169 "EOR $dst, $dst, $dst << 3 \n\t" 8170 "MOV $dst, $dst >> 30" %} 8171 ins_encode %{ 8172 __ fcmpd($src1$$FloatRegister, $src2$$FloatRegister); 8173 __ floating_cmp($dst$$Register); 8174 %} 8175 ins_pipe( floating_cmp ); 8176 %} 8177 8178 instruct cmpD0_reg(iRegI dst, regD src1, immD0 src2, flagsRegF fcc) %{ 8179 match(Set dst (CmpD3 src1 src2)); 8180 effect(KILL fcc); 8181 ins_cost(DEFAULT_COST*3+BRANCH_COST*3); // FIXME 8182 size(20); 8183 // same number of instructions as code using conditional moves but 8184 // doesn't kill integer condition register 8185 format %{ "FCMPZd $dst,$src1,$src2 \n\t" 8186 "VMRS $dst, FPSCR \n\t" 8187 "OR $dst, $dst, 0x08000000 \n\t" 8188 "EOR $dst, $dst, $dst << 3 \n\t" 8189 "MOV $dst, $dst >> 30" %} 8190 ins_encode %{ 8191 __ fcmpzd($src1$$FloatRegister); 8192 __ floating_cmp($dst$$Register); 8193 %} 8194 ins_pipe( floating_cmp ); 8195 %} 8196 8197 //----------Branches--------------------------------------------------------- 8198 // Jump 8199 // (compare 'operand indIndex' and 'instruct addP_reg_reg' above) 8200 // FIXME 8201 instruct jumpXtnd(iRegX switch_val, iRegP tmp) %{ 8202 match(Jump switch_val); 8203 effect(TEMP tmp); 8204 ins_cost(350); 8205 format %{ "ADD $tmp, $constanttablebase, $switch_val\n\t" 8206 "LDR $tmp,[$tmp + $constantoffset]\n\t" 8207 "BX $tmp" %} 8208 size(20); 8209 ins_encode %{ 8210 Register table_reg; 8211 Register label_reg = $tmp$$Register; 8212 if (constant_offset() == 0) { 8213 table_reg = $constanttablebase; 8214 __ ldr(label_reg, Address(table_reg, $switch_val$$Register)); 8215 } else { 8216 table_reg = $tmp$$Register; 8217 int offset = $constantoffset; 8218 if (is_memoryP(offset)) { 8219 __ add(table_reg, $constanttablebase, $switch_val$$Register); 8220 __ ldr(label_reg, Address(table_reg, offset)); 8221 } else { 8222 __ mov_slow(table_reg, $constantoffset); 8223 __ add(table_reg, $constanttablebase, table_reg); 8224 __ ldr(label_reg, Address(table_reg, $switch_val$$Register)); 8225 } 8226 } 8227 __ jump(label_reg); // ldr + b better than ldr to PC for branch predictor? 8228 // __ ldr(PC, Address($table$$Register, $switch_val$$Register)); 8229 %} 8230 ins_pipe(ialu_reg_reg); 8231 %} 8232 8233 // // Direct Branch. 8234 instruct branch(label labl) %{ 8235 match(Goto); 8236 effect(USE labl); 8237 8238 size(4); 8239 ins_cost(BRANCH_COST); 8240 format %{ "B $labl" %} 8241 ins_encode %{ 8242 __ b(*($labl$$label)); 8243 %} 8244 ins_pipe(br); 8245 %} 8246 8247 // Conditional Direct Branch 8248 instruct branchCon(cmpOp cmp, flagsReg icc, label labl) %{ 8249 match(If cmp icc); 8250 effect(USE labl); 8251 8252 size(4); 8253 ins_cost(BRANCH_COST); 8254 format %{ "B$cmp $icc,$labl" %} 8255 ins_encode %{ 8256 __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode)); 8257 %} 8258 ins_pipe(br_cc); 8259 %} 8260 8261 #ifdef ARM 8262 instruct branchCon_EQNELTGE(cmpOp0 cmp, flagsReg_EQNELTGE icc, label labl) %{ 8263 match(If cmp icc); 8264 effect(USE labl); 8265 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); 8266 8267 size(4); 8268 ins_cost(BRANCH_COST); 8269 format %{ "B$cmp $icc,$labl" %} 8270 ins_encode %{ 8271 __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode)); 8272 %} 8273 ins_pipe(br_cc); 8274 %} 8275 #endif 8276 8277 8278 instruct branchConU(cmpOpU cmp, flagsRegU icc, label labl) %{ 8279 match(If cmp icc); 8280 effect(USE labl); 8281 8282 size(4); 8283 ins_cost(BRANCH_COST); 8284 format %{ "B$cmp $icc,$labl" %} 8285 ins_encode %{ 8286 __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode)); 8287 %} 8288 ins_pipe(br_cc); 8289 %} 8290 8291 instruct branchConP(cmpOpP cmp, flagsRegP pcc, label labl) %{ 8292 match(If cmp pcc); 8293 effect(USE labl); 8294 8295 size(4); 8296 ins_cost(BRANCH_COST); 8297 format %{ "B$cmp $pcc,$labl" %} 8298 ins_encode %{ 8299 __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode)); 8300 %} 8301 ins_pipe(br_cc); 8302 %} 8303 8304 instruct branchConL_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, label labl) %{ 8305 match(If cmp xcc); 8306 effect(USE labl); 8307 predicate( _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge ); 8308 8309 size(4); 8310 ins_cost(BRANCH_COST); 8311 format %{ "B$cmp $xcc,$labl" %} 8312 ins_encode %{ 8313 __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode)); 8314 %} 8315 ins_pipe(br_cc); 8316 %} 8317 8318 instruct branchConL_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, label labl) %{ 8319 match(If cmp xcc); 8320 effect(USE labl); 8321 predicate( _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ); 8322 8323 size(4); 8324 ins_cost(BRANCH_COST); 8325 format %{ "B$cmp $xcc,$labl" %} 8326 ins_encode %{ 8327 __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode)); 8328 %} 8329 ins_pipe(br_cc); 8330 %} 8331 8332 instruct branchConL_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, label labl) %{ 8333 match(If cmp xcc); 8334 effect(USE labl); 8335 predicate( _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le ); 8336 8337 size(4); 8338 ins_cost(BRANCH_COST); 8339 format %{ "B$cmp $xcc,$labl" %} 8340 ins_encode %{ 8341 __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode)); 8342 %} 8343 ins_pipe(br_cc); 8344 %} 8345 8346 instruct branchConUL_LTGE(cmpOpUL cmp, flagsRegUL_LTGE xcc, label labl) %{ 8347 match(If cmp xcc); 8348 effect(USE labl); 8349 predicate(_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge); 8350 8351 size(4); 8352 ins_cost(BRANCH_COST); 8353 format %{ "B$cmp $xcc,$labl" %} 8354 ins_encode %{ 8355 __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode)); 8356 %} 8357 ins_pipe(br_cc); 8358 %} 8359 8360 instruct branchConUL_EQNE(cmpOpUL cmp, flagsRegUL_EQNE xcc, label labl) %{ 8361 match(If cmp xcc); 8362 effect(USE labl); 8363 predicate(_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne); 8364 8365 size(4); 8366 ins_cost(BRANCH_COST); 8367 format %{ "B$cmp $xcc,$labl" %} 8368 ins_encode %{ 8369 __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode)); 8370 %} 8371 ins_pipe(br_cc); 8372 %} 8373 8374 instruct branchConUL_LEGT(cmpOpUL_commute cmp, flagsRegUL_LEGT xcc, label labl) %{ 8375 match(If cmp xcc); 8376 effect(USE labl); 8377 predicate(_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le); 8378 8379 size(4); 8380 ins_cost(BRANCH_COST); 8381 format %{ "B$cmp $xcc,$labl" %} 8382 ins_encode %{ 8383 __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode)); 8384 %} 8385 ins_pipe(br_cc); 8386 %} 8387 8388 instruct branchLoopEnd(cmpOp cmp, flagsReg icc, label labl) %{ 8389 match(CountedLoopEnd cmp icc); 8390 effect(USE labl); 8391 8392 size(4); 8393 ins_cost(BRANCH_COST); 8394 format %{ "B$cmp $icc,$labl\t! Loop end" %} 8395 ins_encode %{ 8396 __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode)); 8397 %} 8398 ins_pipe(br_cc); 8399 %} 8400 8401 // instruct branchLoopEndU(cmpOpU cmp, flagsRegU icc, label labl) %{ 8402 // match(CountedLoopEnd cmp icc); 8403 // ins_pipe(br_cc); 8404 // %} 8405 8406 // ============================================================================ 8407 // Long Compare 8408 // 8409 // Currently we hold longs in 2 registers. Comparing such values efficiently 8410 // is tricky. The flavor of compare used depends on whether we are testing 8411 // for LT, LE, or EQ. For a simple LT test we can check just the sign bit. 8412 // The GE test is the negated LT test. The LE test can be had by commuting 8413 // the operands (yielding a GE test) and then negating; negate again for the 8414 // GT test. The EQ test is done by ORcc'ing the high and low halves, and the 8415 // NE test is negated from that. 8416 8417 // Due to a shortcoming in the ADLC, it mixes up expressions like: 8418 // (foo (CmpI (CmpL X Y) 0)) and (bar (CmpI (CmpL X 0L) 0)). Note the 8419 // difference between 'Y' and '0L'. The tree-matches for the CmpI sections 8420 // are collapsed internally in the ADLC's dfa-gen code. The match for 8421 // (CmpI (CmpL X Y) 0) is silently replaced with (CmpI (CmpL X 0L) 0) and the 8422 // foo match ends up with the wrong leaf. One fix is to not match both 8423 // reg-reg and reg-zero forms of long-compare. This is unfortunate because 8424 // both forms beat the trinary form of long-compare and both are very useful 8425 // on Intel which has so few registers. 8426 8427 // instruct branchCon_long(cmpOp cmp, flagsRegL xcc, label labl) %{ 8428 // match(If cmp xcc); 8429 // ins_pipe(br_cc); 8430 // %} 8431 8432 // Manifest a CmpL3 result in an integer register. Very painful. 8433 // This is the test to avoid. 8434 instruct cmpL3_reg_reg(iRegI dst, iRegL src1, iRegL src2, flagsReg ccr ) %{ 8435 match(Set dst (CmpL3 src1 src2) ); 8436 effect( KILL ccr ); 8437 ins_cost(6*DEFAULT_COST); // FIXME 8438 size(32); 8439 format %{ 8440 "CMP $src1.hi, $src2.hi\t\t! long\n" 8441 "\tMOV.gt $dst, 1\n" 8442 "\tmvn.lt $dst, 0\n" 8443 "\tB.ne done\n" 8444 "\tSUBS $dst, $src1.lo, $src2.lo\n" 8445 "\tMOV.hi $dst, 1\n" 8446 "\tmvn.lo $dst, 0\n" 8447 "done:" %} 8448 ins_encode %{ 8449 Label done; 8450 __ cmp($src1$$Register->successor(), $src2$$Register->successor()); 8451 __ mov($dst$$Register, 1, gt); 8452 __ mvn($dst$$Register, 0, lt); 8453 __ b(done, ne); 8454 __ subs($dst$$Register, $src1$$Register, $src2$$Register); 8455 __ mov($dst$$Register, 1, hi); 8456 __ mvn($dst$$Register, 0, lo); 8457 __ bind(done); 8458 %} 8459 ins_pipe(cmpL_reg); 8460 %} 8461 8462 // Conditional move 8463 instruct cmovLL_reg_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, iRegL dst, iRegL src) %{ 8464 match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src))); 8465 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge ); 8466 8467 ins_cost(150); 8468 size(8); 8469 format %{ "MOV$cmp $dst.lo,$src.lo\t! long\n\t" 8470 "MOV$cmp $dst,$src.hi" %} 8471 ins_encode %{ 8472 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 8473 __ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode)); 8474 %} 8475 ins_pipe(ialu_reg); 8476 %} 8477 8478 instruct cmovLL_reg_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, iRegL dst, iRegL src) %{ 8479 match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src))); 8480 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ); 8481 8482 ins_cost(150); 8483 size(8); 8484 format %{ "MOV$cmp $dst.lo,$src.lo\t! long\n\t" 8485 "MOV$cmp $dst,$src.hi" %} 8486 ins_encode %{ 8487 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 8488 __ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode)); 8489 %} 8490 ins_pipe(ialu_reg); 8491 %} 8492 8493 instruct cmovLL_reg_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, iRegL dst, iRegL src) %{ 8494 match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src))); 8495 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt ); 8496 8497 ins_cost(150); 8498 size(8); 8499 format %{ "MOV$cmp $dst.lo,$src.lo\t! long\n\t" 8500 "MOV$cmp $dst,$src.hi" %} 8501 ins_encode %{ 8502 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 8503 __ mov($dst$$Register->successor(), $src$$Register->successor(), (AsmCondition)($cmp$$cmpcode)); 8504 %} 8505 ins_pipe(ialu_reg); 8506 %} 8507 8508 instruct cmovLL_imm_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, iRegL dst, immL0 src) %{ 8509 match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src))); 8510 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge ); 8511 ins_cost(140); 8512 size(8); 8513 format %{ "MOV$cmp $dst.lo,0\t! long\n\t" 8514 "MOV$cmp $dst,0" %} 8515 ins_encode %{ 8516 __ mov($dst$$Register, 0, (AsmCondition)($cmp$$cmpcode)); 8517 __ mov($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode)); 8518 %} 8519 ins_pipe(ialu_imm); 8520 %} 8521 8522 instruct cmovLL_imm_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, iRegL dst, immL0 src) %{ 8523 match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src))); 8524 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ); 8525 ins_cost(140); 8526 size(8); 8527 format %{ "MOV$cmp $dst.lo,0\t! long\n\t" 8528 "MOV$cmp $dst,0" %} 8529 ins_encode %{ 8530 __ mov($dst$$Register, 0, (AsmCondition)($cmp$$cmpcode)); 8531 __ mov($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode)); 8532 %} 8533 ins_pipe(ialu_imm); 8534 %} 8535 8536 instruct cmovLL_imm_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, iRegL dst, immL0 src) %{ 8537 match(Set dst (CMoveL (Binary cmp xcc) (Binary dst src))); 8538 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt ); 8539 ins_cost(140); 8540 size(8); 8541 format %{ "MOV$cmp $dst.lo,0\t! long\n\t" 8542 "MOV$cmp $dst,0" %} 8543 ins_encode %{ 8544 __ mov($dst$$Register, 0, (AsmCondition)($cmp$$cmpcode)); 8545 __ mov($dst$$Register->successor(), 0, (AsmCondition)($cmp$$cmpcode)); 8546 %} 8547 ins_pipe(ialu_imm); 8548 %} 8549 8550 instruct cmovIL_reg_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, iRegI dst, iRegI src) %{ 8551 match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src))); 8552 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge ); 8553 8554 ins_cost(150); 8555 size(4); 8556 format %{ "MOV$cmp $dst,$src" %} 8557 ins_encode %{ 8558 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 8559 %} 8560 ins_pipe(ialu_reg); 8561 %} 8562 8563 instruct cmovIL_reg_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, iRegI dst, iRegI src) %{ 8564 match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src))); 8565 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ); 8566 8567 ins_cost(150); 8568 size(4); 8569 format %{ "MOV$cmp $dst,$src" %} 8570 ins_encode %{ 8571 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 8572 %} 8573 ins_pipe(ialu_reg); 8574 %} 8575 8576 instruct cmovIL_reg_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, iRegI dst, iRegI src) %{ 8577 match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src))); 8578 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt ); 8579 8580 ins_cost(150); 8581 size(4); 8582 format %{ "MOV$cmp $dst,$src" %} 8583 ins_encode %{ 8584 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 8585 %} 8586 ins_pipe(ialu_reg); 8587 %} 8588 8589 instruct cmovIL_imm_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, iRegI dst, immI16 src) %{ 8590 match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src))); 8591 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge ); 8592 8593 ins_cost(140); 8594 format %{ "MOVW$cmp $dst,$src" %} 8595 ins_encode %{ 8596 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 8597 %} 8598 ins_pipe(ialu_imm); 8599 %} 8600 8601 instruct cmovIL_imm_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, iRegI dst, immI16 src) %{ 8602 match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src))); 8603 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ); 8604 8605 ins_cost(140); 8606 format %{ "MOVW$cmp $dst,$src" %} 8607 ins_encode %{ 8608 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 8609 %} 8610 ins_pipe(ialu_imm); 8611 %} 8612 8613 instruct cmovIL_imm_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, iRegI dst, immI16 src) %{ 8614 match(Set dst (CMoveI (Binary cmp xcc) (Binary dst src))); 8615 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt ); 8616 8617 ins_cost(140); 8618 format %{ "MOVW$cmp $dst,$src" %} 8619 ins_encode %{ 8620 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 8621 %} 8622 ins_pipe(ialu_imm); 8623 %} 8624 8625 instruct cmovPL_reg_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, iRegP dst, iRegP src) %{ 8626 match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src))); 8627 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge ); 8628 8629 ins_cost(150); 8630 size(4); 8631 format %{ "MOV$cmp $dst,$src" %} 8632 ins_encode %{ 8633 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 8634 %} 8635 ins_pipe(ialu_reg); 8636 %} 8637 8638 instruct cmovPL_reg_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, iRegP dst, iRegP src) %{ 8639 match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src))); 8640 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ); 8641 8642 ins_cost(150); 8643 size(4); 8644 format %{ "MOV$cmp $dst,$src" %} 8645 ins_encode %{ 8646 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 8647 %} 8648 ins_pipe(ialu_reg); 8649 %} 8650 8651 instruct cmovPL_reg_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, iRegP dst, iRegP src) %{ 8652 match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src))); 8653 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt ); 8654 8655 ins_cost(150); 8656 size(4); 8657 format %{ "MOV$cmp $dst,$src" %} 8658 ins_encode %{ 8659 __ mov($dst$$Register, $src$$Register, (AsmCondition)($cmp$$cmpcode)); 8660 %} 8661 ins_pipe(ialu_reg); 8662 %} 8663 8664 instruct cmovPL_imm_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, iRegP dst, immP0 src) %{ 8665 match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src))); 8666 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge ); 8667 8668 ins_cost(140); 8669 format %{ "MOVW$cmp $dst,$src" %} 8670 ins_encode %{ 8671 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 8672 %} 8673 ins_pipe(ialu_imm); 8674 %} 8675 8676 instruct cmovPL_imm_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, iRegP dst, immP0 src) %{ 8677 match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src))); 8678 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ); 8679 8680 ins_cost(140); 8681 format %{ "MOVW$cmp $dst,$src" %} 8682 ins_encode %{ 8683 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 8684 %} 8685 ins_pipe(ialu_imm); 8686 %} 8687 8688 instruct cmovPL_imm_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, iRegP dst, immP0 src) %{ 8689 match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src))); 8690 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt ); 8691 8692 ins_cost(140); 8693 format %{ "MOVW$cmp $dst,$src" %} 8694 ins_encode %{ 8695 __ movw($dst$$Register, $src$$constant, (AsmCondition)($cmp$$cmpcode)); 8696 %} 8697 ins_pipe(ialu_imm); 8698 %} 8699 8700 instruct cmovFL_reg_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, regF dst, regF src) %{ 8701 match(Set dst (CMoveF (Binary cmp xcc) (Binary dst src))); 8702 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge ); 8703 ins_cost(150); 8704 size(4); 8705 format %{ "FCPYS$cmp $dst,$src" %} 8706 ins_encode %{ 8707 __ fcpys($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode)); 8708 %} 8709 ins_pipe(int_conditional_float_move); 8710 %} 8711 8712 instruct cmovFL_reg_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, regF dst, regF src) %{ 8713 match(Set dst (CMoveF (Binary cmp xcc) (Binary dst src))); 8714 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ); 8715 ins_cost(150); 8716 size(4); 8717 format %{ "FCPYS$cmp $dst,$src" %} 8718 ins_encode %{ 8719 __ fcpys($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode)); 8720 %} 8721 ins_pipe(int_conditional_float_move); 8722 %} 8723 8724 instruct cmovFL_reg_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, regF dst, regF src) %{ 8725 match(Set dst (CMoveF (Binary cmp xcc) (Binary dst src))); 8726 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt ); 8727 ins_cost(150); 8728 size(4); 8729 format %{ "FCPYS$cmp $dst,$src" %} 8730 ins_encode %{ 8731 __ fcpys($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode)); 8732 %} 8733 ins_pipe(int_conditional_float_move); 8734 %} 8735 8736 instruct cmovDL_reg_LTGE(cmpOpL cmp, flagsRegL_LTGE xcc, regD dst, regD src) %{ 8737 match(Set dst (CMoveD (Binary cmp xcc) (Binary dst src))); 8738 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge ); 8739 8740 ins_cost(150); 8741 size(4); 8742 format %{ "FCPYD$cmp $dst,$src" %} 8743 ins_encode %{ 8744 __ fcpyd($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode)); 8745 %} 8746 ins_pipe(int_conditional_float_move); 8747 %} 8748 8749 instruct cmovDL_reg_EQNE(cmpOpL cmp, flagsRegL_EQNE xcc, regD dst, regD src) %{ 8750 match(Set dst (CMoveD (Binary cmp xcc) (Binary dst src))); 8751 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ); 8752 8753 ins_cost(150); 8754 size(4); 8755 format %{ "FCPYD$cmp $dst,$src" %} 8756 ins_encode %{ 8757 __ fcpyd($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode)); 8758 %} 8759 ins_pipe(int_conditional_float_move); 8760 %} 8761 8762 instruct cmovDL_reg_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, regD dst, regD src) %{ 8763 match(Set dst (CMoveD (Binary cmp xcc) (Binary dst src))); 8764 predicate(_kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt ); 8765 8766 ins_cost(150); 8767 size(4); 8768 format %{ "FCPYD$cmp $dst,$src" %} 8769 ins_encode %{ 8770 __ fcpyd($dst$$FloatRegister, $src$$FloatRegister, (AsmCondition)($cmp$$cmpcode)); 8771 %} 8772 ins_pipe(int_conditional_float_move); 8773 %} 8774 8775 // ============================================================================ 8776 // Safepoint Instruction 8777 // rather than KILL R12, it would be better to use any reg as 8778 // TEMP. Can't do that at this point because it crashes the compiler 8779 instruct safePoint_poll(iRegP poll, R12RegI tmp, flagsReg icc) %{ 8780 match(SafePoint poll); 8781 effect(USE poll, KILL tmp, KILL icc); 8782 8783 size(4); 8784 format %{ "LDR $tmp,[$poll]\t! Safepoint: poll for GC" %} 8785 ins_encode %{ 8786 __ relocate(relocInfo::poll_type); 8787 __ ldr($tmp$$Register, Address($poll$$Register)); 8788 %} 8789 ins_pipe(loadPollP); 8790 %} 8791 8792 8793 // ============================================================================ 8794 // Call Instructions 8795 // Call Java Static Instruction 8796 instruct CallStaticJavaDirect( method meth ) %{ 8797 match(CallStaticJava); 8798 predicate(! ((CallStaticJavaNode*)n)->is_method_handle_invoke()); 8799 effect(USE meth); 8800 8801 ins_cost(CALL_COST); 8802 format %{ "CALL,static ==> " %} 8803 ins_encode( Java_Static_Call( meth ), call_epilog ); 8804 ins_pipe(simple_call); 8805 %} 8806 8807 // Call Java Static Instruction (method handle version) 8808 instruct CallStaticJavaHandle( method meth ) %{ 8809 match(CallStaticJava); 8810 predicate(((CallStaticJavaNode*)n)->is_method_handle_invoke()); 8811 effect(USE meth); 8812 // FP is saved by all callees (for interpreter stack correction). 8813 // We use it here for a similar purpose, in {preserve,restore}_FP. 8814 8815 ins_cost(CALL_COST); 8816 format %{ "CALL,static/MethodHandle ==> " %} 8817 ins_encode( preserve_SP, Java_Static_Call( meth ), restore_SP, call_epilog ); 8818 ins_pipe(simple_call); 8819 %} 8820 8821 // Call Java Dynamic Instruction 8822 instruct CallDynamicJavaDirect( method meth ) %{ 8823 match(CallDynamicJava); 8824 effect(USE meth); 8825 8826 ins_cost(CALL_COST); 8827 format %{ "MOV_OOP (empty),R_R8\n\t" 8828 "CALL,dynamic ; NOP ==> " %} 8829 ins_encode( Java_Dynamic_Call( meth ), call_epilog ); 8830 ins_pipe(call); 8831 %} 8832 8833 // Call Runtime Instruction 8834 instruct CallRuntimeDirect(method meth) %{ 8835 match(CallRuntime); 8836 effect(USE meth); 8837 ins_cost(CALL_COST); 8838 format %{ "CALL,runtime" %} 8839 ins_encode( Java_To_Runtime( meth ), 8840 call_epilog ); 8841 ins_pipe(simple_call); 8842 %} 8843 8844 // Call runtime without safepoint - same as CallRuntime 8845 instruct CallLeafDirect(method meth) %{ 8846 match(CallLeaf); 8847 effect(USE meth); 8848 ins_cost(CALL_COST); 8849 format %{ "CALL,runtime leaf" %} 8850 // TODO: ned save_last_PC here? 8851 ins_encode( Java_To_Runtime( meth ), 8852 call_epilog ); 8853 ins_pipe(simple_call); 8854 %} 8855 8856 // Call runtime without safepoint - same as CallLeaf 8857 instruct CallLeafNoFPDirect(method meth) %{ 8858 match(CallLeafNoFP); 8859 effect(USE meth); 8860 ins_cost(CALL_COST); 8861 format %{ "CALL,runtime leaf nofp" %} 8862 // TODO: ned save_last_PC here? 8863 ins_encode( Java_To_Runtime( meth ), 8864 call_epilog ); 8865 ins_pipe(simple_call); 8866 %} 8867 8868 // Tail Call; Jump from runtime stub to Java code. 8869 // Also known as an 'interprocedural jump'. 8870 // Target of jump will eventually return to caller. 8871 // TailJump below removes the return address. 8872 instruct TailCalljmpInd(IPRegP jump_target, inline_cache_regP method_ptr) %{ 8873 match(TailCall jump_target method_ptr); 8874 8875 ins_cost(CALL_COST); 8876 format %{ "MOV Rexception_pc, LR\n\t" 8877 "jump $jump_target \t! $method_ptr holds method" %} 8878 ins_encode %{ 8879 __ mov(Rexception_pc, LR); // this is used only to call 8880 // StubRoutines::forward_exception_entry() 8881 // which expects PC of exception in 8882 // R5. FIXME? 8883 __ jump($jump_target$$Register); 8884 %} 8885 ins_pipe(tail_call); 8886 %} 8887 8888 8889 // Return Instruction 8890 instruct Ret() %{ 8891 match(Return); 8892 8893 format %{ "ret LR" %} 8894 8895 ins_encode %{ 8896 __ ret(LR); 8897 %} 8898 8899 ins_pipe(br); 8900 %} 8901 8902 8903 // Tail Jump; remove the return address; jump to target. 8904 // TailCall above leaves the return address around. 8905 // TailJump is used in only one place, the rethrow_Java stub (fancy_jump=2). 8906 // ex_oop (Exception Oop) is needed in %o0 at the jump. As there would be a 8907 // "restore" before this instruction (in Epilogue), we need to materialize it 8908 // in %i0. 8909 instruct tailjmpInd(IPRegP jump_target, RExceptionRegP ex_oop) %{ 8910 match( TailJump jump_target ex_oop ); 8911 ins_cost(CALL_COST); 8912 format %{ "MOV Rexception_pc, LR\n\t" 8913 "jump $jump_target \t! $ex_oop holds exc. oop" %} 8914 ins_encode %{ 8915 __ mov(Rexception_pc, LR); 8916 __ jump($jump_target$$Register); 8917 %} 8918 ins_pipe(tail_call); 8919 %} 8920 8921 // Create exception oop: created by stack-crawling runtime code. 8922 // Created exception is now available to this handler, and is setup 8923 // just prior to jumping to this handler. No code emitted. 8924 instruct CreateException( RExceptionRegP ex_oop ) 8925 %{ 8926 match(Set ex_oop (CreateEx)); 8927 ins_cost(0); 8928 8929 size(0); 8930 // use the following format syntax 8931 format %{ "! exception oop is in Rexception_obj; no code emitted" %} 8932 ins_encode(); 8933 ins_pipe(empty); 8934 %} 8935 8936 8937 // Rethrow exception: 8938 // The exception oop will come in the first argument position. 8939 // Then JUMP (not call) to the rethrow stub code. 8940 instruct RethrowException() 8941 %{ 8942 match(Rethrow); 8943 ins_cost(CALL_COST); 8944 8945 // use the following format syntax 8946 format %{ "b rethrow_stub" %} 8947 ins_encode %{ 8948 Register scratch = R1_tmp; 8949 assert_different_registers(scratch, c_rarg0, LR); 8950 __ jump(OptoRuntime::rethrow_stub(), relocInfo::runtime_call_type, scratch); 8951 %} 8952 ins_pipe(tail_call); 8953 %} 8954 8955 8956 // Die now 8957 instruct ShouldNotReachHere( ) 8958 %{ 8959 match(Halt); 8960 ins_cost(CALL_COST); 8961 8962 // Use the following format syntax 8963 format %{ "ShouldNotReachHere" %} 8964 ins_encode %{ 8965 if (is_reachable()) { 8966 __ stop(_halt_reason); 8967 } 8968 %} 8969 ins_pipe(tail_call); 8970 %} 8971 8972 // ============================================================================ 8973 // The 2nd slow-half of a subtype check. Scan the subklass's 2ndary superklass 8974 // array for an instance of the superklass. Set a hidden internal cache on a 8975 // hit (cache is checked with exposed code in gen_subtype_check()). Return 8976 // not zero for a miss or zero for a hit. The encoding ALSO sets flags. 8977 instruct partialSubtypeCheck( R0RegP index, R1RegP sub, R2RegP super, flagsRegP pcc, LRRegP lr ) %{ 8978 match(Set index (PartialSubtypeCheck sub super)); 8979 effect( KILL pcc, KILL lr ); 8980 ins_cost(DEFAULT_COST*10); 8981 format %{ "CALL PartialSubtypeCheck" %} 8982 ins_encode %{ 8983 __ call(StubRoutines::Arm::partial_subtype_check(), relocInfo::runtime_call_type); 8984 %} 8985 ins_pipe(partial_subtype_check_pipe); 8986 %} 8987 8988 /* instruct partialSubtypeCheck_vs_zero( flagsRegP pcc, o1RegP sub, o2RegP super, immP0 zero, o0RegP idx, o7RegP o7 ) %{ */ 8989 /* match(Set pcc (CmpP (PartialSubtypeCheck sub super) zero)); */ 8990 /* ins_pipe(partial_subtype_check_pipe); */ 8991 /* %} */ 8992 8993 8994 // ============================================================================ 8995 // inlined locking and unlocking 8996 8997 instruct cmpFastLock(flagsRegP pcc, iRegP object, iRegP box, iRegP scratch2, iRegP scratch ) 8998 %{ 8999 match(Set pcc (FastLock object box)); 9000 predicate(!(UseBiasedLocking && !UseOptoBiasInlining)); 9001 9002 effect(TEMP scratch, TEMP scratch2); 9003 ins_cost(DEFAULT_COST*3); 9004 9005 format %{ "FASTLOCK $object, $box; KILL $scratch, $scratch2" %} 9006 ins_encode %{ 9007 __ fast_lock($object$$Register, $box$$Register, $scratch$$Register, $scratch2$$Register); 9008 %} 9009 ins_pipe(long_memory_op); 9010 %} 9011 9012 instruct cmpFastLock_noBiasInline(flagsRegP pcc, iRegP object, iRegP box, iRegP scratch2, 9013 iRegP scratch, iRegP scratch3) %{ 9014 match(Set pcc (FastLock object box)); 9015 predicate(UseBiasedLocking && !UseOptoBiasInlining); 9016 9017 effect(TEMP scratch, TEMP scratch2, TEMP scratch3); 9018 ins_cost(DEFAULT_COST*5); 9019 9020 format %{ "FASTLOCK $object, $box; KILL $scratch, $scratch2, $scratch3" %} 9021 ins_encode %{ 9022 __ fast_lock($object$$Register, $box$$Register, $scratch$$Register, $scratch2$$Register, $scratch3$$Register); 9023 %} 9024 ins_pipe(long_memory_op); 9025 %} 9026 9027 9028 instruct cmpFastUnlock(flagsRegP pcc, iRegP object, iRegP box, iRegP scratch2, iRegP scratch ) %{ 9029 match(Set pcc (FastUnlock object box)); 9030 effect(TEMP scratch, TEMP scratch2); 9031 ins_cost(100); 9032 9033 format %{ "FASTUNLOCK $object, $box; KILL $scratch, $scratch2" %} 9034 ins_encode %{ 9035 __ fast_unlock($object$$Register, $box$$Register, $scratch$$Register, $scratch2$$Register); 9036 %} 9037 ins_pipe(long_memory_op); 9038 %} 9039 9040 // Count and Base registers are fixed because the allocator cannot 9041 // kill unknown registers. The encodings are generic. 9042 instruct clear_array(iRegX cnt, iRegP base, iRegI temp, iRegX zero, Universe dummy, flagsReg cpsr) %{ 9043 match(Set dummy (ClearArray cnt base)); 9044 effect(TEMP temp, TEMP zero, KILL cpsr); 9045 ins_cost(300); 9046 format %{ "MOV $zero,0\n" 9047 " MOV $temp,$cnt\n" 9048 "loop: SUBS $temp,$temp,4\t! Count down a dword of bytes\n" 9049 " STR.ge $zero,[$base+$temp]\t! delay slot" 9050 " B.gt loop\t\t! Clearing loop\n" %} 9051 ins_encode %{ 9052 __ mov($zero$$Register, 0); 9053 __ mov($temp$$Register, $cnt$$Register); 9054 Label(loop); 9055 __ bind(loop); 9056 __ subs($temp$$Register, $temp$$Register, 4); 9057 __ str($zero$$Register, Address($base$$Register, $temp$$Register), ge); 9058 __ b(loop, gt); 9059 %} 9060 ins_pipe(long_memory_op); 9061 %} 9062 9063 #ifdef XXX 9064 // FIXME: Why R0/R1/R2/R3? 9065 instruct string_compare(R0RegP str1, R1RegP str2, R2RegI cnt1, R3RegI cnt2, iRegI result, 9066 iRegI tmp1, iRegI tmp2, flagsReg ccr) %{ 9067 predicate(!CompactStrings); 9068 match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2))); 9069 effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL ccr, TEMP tmp1, TEMP tmp2); 9070 ins_cost(300); 9071 format %{ "String Compare $str1,$cnt1,$str2,$cnt2 -> $result // TEMP $tmp1, $tmp2" %} 9072 ins_encode( enc_String_Compare(str1, str2, cnt1, cnt2, result, tmp1, tmp2) ); 9073 9074 ins_pipe(long_memory_op); 9075 %} 9076 9077 // FIXME: Why R0/R1/R2? 9078 instruct string_equals(R0RegP str1, R1RegP str2, R2RegI cnt, iRegI result, iRegI tmp1, iRegI tmp2, 9079 flagsReg ccr) %{ 9080 predicate(!CompactStrings); 9081 match(Set result (StrEquals (Binary str1 str2) cnt)); 9082 effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt, TEMP tmp1, TEMP tmp2, TEMP result, KILL ccr); 9083 9084 ins_cost(300); 9085 format %{ "String Equals $str1,$str2,$cnt -> $result // TEMP $tmp1, $tmp2" %} 9086 ins_encode( enc_String_Equals(str1, str2, cnt, result, tmp1, tmp2) ); 9087 ins_pipe(long_memory_op); 9088 %} 9089 9090 // FIXME: Why R0/R1? 9091 instruct array_equals(R0RegP ary1, R1RegP ary2, iRegI tmp1, iRegI tmp2, iRegI tmp3, iRegI result, 9092 flagsReg ccr) %{ 9093 predicate(((AryEqNode*)n)->encoding() == StrIntrinsicNode::UU); 9094 match(Set result (AryEq ary1 ary2)); 9095 effect(USE_KILL ary1, USE_KILL ary2, TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP result, KILL ccr); 9096 9097 ins_cost(300); 9098 format %{ "Array Equals $ary1,$ary2 -> $result // TEMP $tmp1,$tmp2,$tmp3" %} 9099 ins_encode( enc_Array_Equals(ary1, ary2, tmp1, tmp2, tmp3, result)); 9100 ins_pipe(long_memory_op); 9101 %} 9102 #endif 9103 9104 //---------- Zeros Count Instructions ------------------------------------------ 9105 9106 instruct countLeadingZerosI(iRegI dst, iRegI src) %{ 9107 match(Set dst (CountLeadingZerosI src)); 9108 size(4); 9109 format %{ "CLZ_32 $dst,$src" %} 9110 ins_encode %{ 9111 __ clz_32($dst$$Register, $src$$Register); 9112 %} 9113 ins_pipe(ialu_reg); 9114 %} 9115 9116 instruct countLeadingZerosL(iRegI dst, iRegL src, iRegI tmp, flagsReg ccr) %{ 9117 match(Set dst (CountLeadingZerosL src)); 9118 effect(TEMP tmp, TEMP dst, KILL ccr); 9119 size(16); 9120 format %{ "CLZ $dst,$src.hi\n\t" 9121 "TEQ $dst,32\n\t" 9122 "CLZ.eq $tmp,$src.lo\n\t" 9123 "ADD.eq $dst, $dst, $tmp\n\t" %} 9124 ins_encode %{ 9125 __ clz($dst$$Register, $src$$Register->successor()); 9126 __ teq($dst$$Register, 32); 9127 __ clz($tmp$$Register, $src$$Register, eq); 9128 __ add($dst$$Register, $dst$$Register, $tmp$$Register, eq); 9129 %} 9130 ins_pipe(ialu_reg); 9131 %} 9132 9133 instruct countTrailingZerosI(iRegI dst, iRegI src, iRegI tmp) %{ 9134 match(Set dst (CountTrailingZerosI src)); 9135 effect(TEMP tmp); 9136 size(8); 9137 format %{ "RBIT_32 $tmp, $src\n\t" 9138 "CLZ_32 $dst,$tmp" %} 9139 ins_encode %{ 9140 __ rbit_32($tmp$$Register, $src$$Register); 9141 __ clz_32($dst$$Register, $tmp$$Register); 9142 %} 9143 ins_pipe(ialu_reg); 9144 %} 9145 9146 instruct countTrailingZerosL(iRegI dst, iRegL src, iRegI tmp, flagsReg ccr) %{ 9147 match(Set dst (CountTrailingZerosL src)); 9148 effect(TEMP tmp, TEMP dst, KILL ccr); 9149 size(24); 9150 format %{ "RBIT $tmp,$src.lo\n\t" 9151 "CLZ $dst,$tmp\n\t" 9152 "TEQ $dst,32\n\t" 9153 "RBIT $tmp,$src.hi\n\t" 9154 "CLZ.eq $tmp,$tmp\n\t" 9155 "ADD.eq $dst,$dst,$tmp\n\t" %} 9156 ins_encode %{ 9157 __ rbit($tmp$$Register, $src$$Register); 9158 __ clz($dst$$Register, $tmp$$Register); 9159 __ teq($dst$$Register, 32); 9160 __ rbit($tmp$$Register, $src$$Register->successor()); 9161 __ clz($tmp$$Register, $tmp$$Register, eq); 9162 __ add($dst$$Register, $dst$$Register, $tmp$$Register, eq); 9163 %} 9164 ins_pipe(ialu_reg); 9165 %} 9166 9167 9168 //---------- Population Count Instructions ------------------------------------- 9169 9170 instruct popCountI(iRegI dst, iRegI src, regD_low tmp) %{ 9171 predicate(UsePopCountInstruction); 9172 match(Set dst (PopCountI src)); 9173 effect(TEMP tmp); 9174 9175 format %{ "FMSR $tmp,$src\n\t" 9176 "VCNT.8 $tmp,$tmp\n\t" 9177 "VPADDL.U8 $tmp,$tmp\n\t" 9178 "VPADDL.U16 $tmp,$tmp\n\t" 9179 "FMRS $dst,$tmp" %} 9180 size(20); 9181 9182 ins_encode %{ 9183 __ fmsr($tmp$$FloatRegister, $src$$Register); 9184 __ vcnt($tmp$$FloatRegister, $tmp$$FloatRegister); 9185 __ vpaddl($tmp$$FloatRegister, $tmp$$FloatRegister, 8, 0); 9186 __ vpaddl($tmp$$FloatRegister, $tmp$$FloatRegister, 16, 0); 9187 __ fmrs($dst$$Register, $tmp$$FloatRegister); 9188 %} 9189 ins_pipe(ialu_reg); // FIXME 9190 %} 9191 9192 // Note: Long.bitCount(long) returns an int. 9193 instruct popCountL(iRegI dst, iRegL src, regD_low tmp) %{ 9194 predicate(UsePopCountInstruction); 9195 match(Set dst (PopCountL src)); 9196 effect(TEMP tmp); 9197 9198 format %{ "FMDRR $tmp,$src.lo,$src.hi\n\t" 9199 "VCNT.8 $tmp,$tmp\n\t" 9200 "VPADDL.U8 $tmp,$tmp\n\t" 9201 "VPADDL.U16 $tmp,$tmp\n\t" 9202 "VPADDL.U32 $tmp,$tmp\n\t" 9203 "FMRS $dst,$tmp" %} 9204 9205 size(32); 9206 9207 ins_encode %{ 9208 __ fmdrr($tmp$$FloatRegister, $src$$Register, $src$$Register->successor()); 9209 __ vcnt($tmp$$FloatRegister, $tmp$$FloatRegister); 9210 __ vpaddl($tmp$$FloatRegister, $tmp$$FloatRegister, 8, 0); 9211 __ vpaddl($tmp$$FloatRegister, $tmp$$FloatRegister, 16, 0); 9212 __ vpaddl($tmp$$FloatRegister, $tmp$$FloatRegister, 32, 0); 9213 __ fmrs($dst$$Register, $tmp$$FloatRegister); 9214 %} 9215 ins_pipe(ialu_reg); 9216 %} 9217 9218 9219 // ============================================================================ 9220 //------------Bytes reverse-------------------------------------------------- 9221 9222 instruct bytes_reverse_int(iRegI dst, iRegI src) %{ 9223 match(Set dst (ReverseBytesI src)); 9224 9225 size(4); 9226 format %{ "REV32 $dst,$src" %} 9227 ins_encode %{ 9228 __ rev($dst$$Register, $src$$Register); 9229 %} 9230 ins_pipe( iload_mem ); // FIXME 9231 %} 9232 9233 instruct bytes_reverse_long(iRegL dst, iRegL src) %{ 9234 match(Set dst (ReverseBytesL src)); 9235 effect(TEMP dst); 9236 size(8); 9237 format %{ "REV $dst.lo,$src.lo\n\t" 9238 "REV $dst.hi,$src.hi" %} 9239 ins_encode %{ 9240 __ rev($dst$$Register, $src$$Register->successor()); 9241 __ rev($dst$$Register->successor(), $src$$Register); 9242 %} 9243 ins_pipe( iload_mem ); // FIXME 9244 %} 9245 9246 instruct bytes_reverse_unsigned_short(iRegI dst, iRegI src) %{ 9247 match(Set dst (ReverseBytesUS src)); 9248 size(4); 9249 format %{ "REV16 $dst,$src" %} 9250 ins_encode %{ 9251 __ rev16($dst$$Register, $src$$Register); 9252 %} 9253 ins_pipe( iload_mem ); // FIXME 9254 %} 9255 9256 instruct bytes_reverse_short(iRegI dst, iRegI src) %{ 9257 match(Set dst (ReverseBytesS src)); 9258 size(4); 9259 format %{ "REVSH $dst,$src" %} 9260 ins_encode %{ 9261 __ revsh($dst$$Register, $src$$Register); 9262 %} 9263 ins_pipe( iload_mem ); // FIXME 9264 %} 9265 9266 9267 // ====================VECTOR INSTRUCTIONS===================================== 9268 9269 // Load Aligned Packed values into a Double Register 9270 instruct loadV8(vecD dst, memoryD mem) %{ 9271 predicate(n->as_LoadVector()->memory_size() == 8); 9272 match(Set dst (LoadVector mem)); 9273 ins_cost(MEMORY_REF_COST); 9274 size(4); 9275 format %{ "FLDD $mem,$dst\t! load vector (8 bytes)" %} 9276 ins_encode %{ 9277 __ ldr_double($dst$$FloatRegister, $mem$$Address); 9278 %} 9279 ins_pipe(floadD_mem); 9280 %} 9281 9282 // Load Aligned Packed values into a Double Register Pair 9283 instruct loadV16(vecX dst, memoryvld mem) %{ 9284 predicate(n->as_LoadVector()->memory_size() == 16); 9285 match(Set dst (LoadVector mem)); 9286 ins_cost(MEMORY_REF_COST); 9287 size(4); 9288 format %{ "VLD1 $mem,$dst.Q\t! load vector (16 bytes)" %} 9289 ins_encode %{ 9290 __ vld1($dst$$FloatRegister, $mem$$Address, MacroAssembler::VELEM_SIZE_16, 128); 9291 %} 9292 ins_pipe(floadD_mem); // FIXME 9293 %} 9294 9295 // Store Vector in Double register to memory 9296 instruct storeV8(memoryD mem, vecD src) %{ 9297 predicate(n->as_StoreVector()->memory_size() == 8); 9298 match(Set mem (StoreVector mem src)); 9299 ins_cost(MEMORY_REF_COST); 9300 size(4); 9301 format %{ "FSTD $src,$mem\t! store vector (8 bytes)" %} 9302 ins_encode %{ 9303 __ str_double($src$$FloatRegister, $mem$$Address); 9304 %} 9305 ins_pipe(fstoreD_mem_reg); 9306 %} 9307 9308 // Store Vector in Double Register Pair to memory 9309 instruct storeV16(memoryvld mem, vecX src) %{ 9310 predicate(n->as_StoreVector()->memory_size() == 16); 9311 match(Set mem (StoreVector mem src)); 9312 ins_cost(MEMORY_REF_COST); 9313 size(4); 9314 format %{ "VST1 $src,$mem\t! store vector (16 bytes)" %} 9315 ins_encode %{ 9316 __ vst1($src$$FloatRegister, $mem$$Address, MacroAssembler::VELEM_SIZE_16, 128); 9317 %} 9318 ins_pipe(fstoreD_mem_reg); // FIXME 9319 %} 9320 9321 // Replicate scalar to packed byte values in Double register 9322 instruct Repl8B_reg(vecD dst, iRegI src, iRegI tmp) %{ 9323 predicate(n->as_Vector()->length() == 8); 9324 match(Set dst (ReplicateB src)); 9325 ins_cost(DEFAULT_COST*4); 9326 effect(TEMP tmp); 9327 size(16); 9328 9329 // FIXME: could use PKH instruction instead? 9330 format %{ "LSL $tmp, $src, 24 \n\t" 9331 "OR $tmp, $tmp, ($tmp >> 8) \n\t" 9332 "OR $tmp, $tmp, ($tmp >> 16) \n\t" 9333 "FMDRR $dst,$tmp,$tmp\t" %} 9334 ins_encode %{ 9335 __ mov($tmp$$Register, AsmOperand($src$$Register, lsl, 24)); 9336 __ orr($tmp$$Register, $tmp$$Register, AsmOperand($tmp$$Register, lsr, 8)); 9337 __ orr($tmp$$Register, $tmp$$Register, AsmOperand($tmp$$Register, lsr, 16)); 9338 __ fmdrr($dst$$FloatRegister, $tmp$$Register, $tmp$$Register); 9339 %} 9340 ins_pipe(ialu_reg); // FIXME 9341 %} 9342 9343 // Replicate scalar to packed byte values in Double register 9344 instruct Repl8B_reg_simd(vecD dst, iRegI src) %{ 9345 predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd()); 9346 match(Set dst (ReplicateB src)); 9347 size(4); 9348 9349 format %{ "VDUP.8 $dst,$src\t" %} 9350 ins_encode %{ 9351 bool quad = false; 9352 __ vdupI($dst$$FloatRegister, $src$$Register, 9353 MacroAssembler::VELEM_SIZE_8, quad); 9354 %} 9355 ins_pipe(ialu_reg); // FIXME 9356 %} 9357 9358 // Replicate scalar to packed byte values in Double register pair 9359 instruct Repl16B_reg(vecX dst, iRegI src) %{ 9360 predicate(n->as_Vector()->length_in_bytes() == 16); 9361 match(Set dst (ReplicateB src)); 9362 size(4); 9363 9364 format %{ "VDUP.8 $dst.Q,$src\t" %} 9365 ins_encode %{ 9366 bool quad = true; 9367 __ vdupI($dst$$FloatRegister, $src$$Register, 9368 MacroAssembler::VELEM_SIZE_8, quad); 9369 %} 9370 ins_pipe(ialu_reg); // FIXME 9371 %} 9372 9373 // Replicate scalar constant to packed byte values in Double register 9374 instruct Repl8B_immI(vecD dst, immI src, iRegI tmp) %{ 9375 predicate(n->as_Vector()->length() == 8); 9376 match(Set dst (ReplicateB src)); 9377 ins_cost(DEFAULT_COST*2); 9378 effect(TEMP tmp); 9379 size(12); 9380 9381 format %{ "MOV $tmp, Repl4($src))\n\t" 9382 "FMDRR $dst,$tmp,$tmp\t" %} 9383 ins_encode( LdReplImmI(src, dst, tmp, (4), (1)) ); 9384 ins_pipe(loadConFD); // FIXME 9385 %} 9386 9387 // Replicate scalar constant to packed byte values in Double register 9388 // TODO: support negative constants with MVNI? 9389 instruct Repl8B_immU8(vecD dst, immU8 src) %{ 9390 predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd()); 9391 match(Set dst (ReplicateB src)); 9392 size(4); 9393 9394 format %{ "VMOV.U8 $dst,$src" %} 9395 ins_encode %{ 9396 bool quad = false; 9397 __ vmovI($dst$$FloatRegister, $src$$constant, 9398 MacroAssembler::VELEM_SIZE_8, quad); 9399 %} 9400 ins_pipe(loadConFD); // FIXME 9401 %} 9402 9403 // Replicate scalar constant to packed byte values in Double register pair 9404 instruct Repl16B_immU8(vecX dst, immU8 src) %{ 9405 predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd()); 9406 match(Set dst (ReplicateB src)); 9407 size(4); 9408 9409 format %{ "VMOV.U8 $dst.Q,$src" %} 9410 ins_encode %{ 9411 bool quad = true; 9412 __ vmovI($dst$$FloatRegister, $src$$constant, 9413 MacroAssembler::VELEM_SIZE_8, quad); 9414 %} 9415 ins_pipe(loadConFD); // FIXME 9416 %} 9417 9418 // Replicate scalar to packed short/char values into Double register 9419 instruct Repl4S_reg(vecD dst, iRegI src, iRegI tmp) %{ 9420 predicate(n->as_Vector()->length() == 4); 9421 match(Set dst (ReplicateS src)); 9422 ins_cost(DEFAULT_COST*3); 9423 effect(TEMP tmp); 9424 size(12); 9425 9426 // FIXME: could use PKH instruction instead? 9427 format %{ "LSL $tmp, $src, 16 \n\t" 9428 "OR $tmp, $tmp, ($tmp >> 16) \n\t" 9429 "FMDRR $dst,$tmp,$tmp\t" %} 9430 ins_encode %{ 9431 __ mov($tmp$$Register, AsmOperand($src$$Register, lsl, 16)); 9432 __ orr($tmp$$Register, $tmp$$Register, AsmOperand($tmp$$Register, lsr, 16)); 9433 __ fmdrr($dst$$FloatRegister, $tmp$$Register, $tmp$$Register); 9434 %} 9435 ins_pipe(ialu_reg); // FIXME 9436 %} 9437 9438 // Replicate scalar to packed byte values in Double register 9439 instruct Repl4S_reg_simd(vecD dst, iRegI src) %{ 9440 predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd()); 9441 match(Set dst (ReplicateS src)); 9442 size(4); 9443 9444 format %{ "VDUP.16 $dst,$src\t" %} 9445 ins_encode %{ 9446 bool quad = false; 9447 __ vdupI($dst$$FloatRegister, $src$$Register, 9448 MacroAssembler::VELEM_SIZE_16, quad); 9449 %} 9450 ins_pipe(ialu_reg); // FIXME 9451 %} 9452 9453 // Replicate scalar to packed byte values in Double register pair 9454 instruct Repl8S_reg(vecX dst, iRegI src) %{ 9455 predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd()); 9456 match(Set dst (ReplicateS src)); 9457 size(4); 9458 9459 format %{ "VDUP.16 $dst.Q,$src\t" %} 9460 ins_encode %{ 9461 bool quad = true; 9462 __ vdupI($dst$$FloatRegister, $src$$Register, 9463 MacroAssembler::VELEM_SIZE_16, quad); 9464 %} 9465 ins_pipe(ialu_reg); // FIXME 9466 %} 9467 9468 9469 // Replicate scalar constant to packed short/char values in Double register 9470 instruct Repl4S_immI(vecD dst, immI src, iRegP tmp) %{ 9471 predicate(n->as_Vector()->length() == 4); 9472 match(Set dst (ReplicateS src)); 9473 effect(TEMP tmp); 9474 size(12); 9475 ins_cost(DEFAULT_COST*4); // FIXME 9476 9477 format %{ "MOV $tmp, Repl2($src))\n\t" 9478 "FMDRR $dst,$tmp,$tmp\t" %} 9479 ins_encode( LdReplImmI(src, dst, tmp, (2), (2)) ); 9480 ins_pipe(loadConFD); // FIXME 9481 %} 9482 9483 // Replicate scalar constant to packed byte values in Double register 9484 instruct Repl4S_immU8(vecD dst, immU8 src) %{ 9485 predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd()); 9486 match(Set dst (ReplicateS src)); 9487 size(4); 9488 9489 format %{ "VMOV.U16 $dst,$src" %} 9490 ins_encode %{ 9491 bool quad = false; 9492 __ vmovI($dst$$FloatRegister, $src$$constant, 9493 MacroAssembler::VELEM_SIZE_16, quad); 9494 %} 9495 ins_pipe(loadConFD); // FIXME 9496 %} 9497 9498 // Replicate scalar constant to packed byte values in Double register pair 9499 instruct Repl8S_immU8(vecX dst, immU8 src) %{ 9500 predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd()); 9501 match(Set dst (ReplicateS src)); 9502 size(4); 9503 9504 format %{ "VMOV.U16 $dst.Q,$src" %} 9505 ins_encode %{ 9506 bool quad = true; 9507 __ vmovI($dst$$FloatRegister, $src$$constant, 9508 MacroAssembler::VELEM_SIZE_16, quad); 9509 %} 9510 ins_pipe(loadConFD); // FIXME 9511 %} 9512 9513 // Replicate scalar to packed int values in Double register 9514 instruct Repl2I_reg(vecD dst, iRegI src) %{ 9515 predicate(n->as_Vector()->length() == 2); 9516 match(Set dst (ReplicateI src)); 9517 size(4); 9518 9519 format %{ "FMDRR $dst,$src,$src\t" %} 9520 ins_encode %{ 9521 __ fmdrr($dst$$FloatRegister, $src$$Register, $src$$Register); 9522 %} 9523 ins_pipe(ialu_reg); // FIXME 9524 %} 9525 9526 // Replicate scalar to packed int values in Double register pair 9527 instruct Repl4I_reg(vecX dst, iRegI src) %{ 9528 predicate(n->as_Vector()->length() == 4); 9529 match(Set dst (ReplicateI src)); 9530 ins_cost(DEFAULT_COST*2); 9531 size(8); 9532 9533 format %{ "FMDRR $dst.lo,$src,$src\n\t" 9534 "FMDRR $dst.hi,$src,$src" %} 9535 9536 ins_encode %{ 9537 __ fmdrr($dst$$FloatRegister, $src$$Register, $src$$Register); 9538 __ fmdrr($dst$$FloatRegister->successor()->successor(), 9539 $src$$Register, $src$$Register); 9540 %} 9541 ins_pipe(ialu_reg); // FIXME 9542 %} 9543 9544 // Replicate scalar to packed int values in Double register 9545 instruct Repl2I_reg_simd(vecD dst, iRegI src) %{ 9546 predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd()); 9547 match(Set dst (ReplicateI src)); 9548 size(4); 9549 9550 format %{ "VDUP.32 $dst.D,$src\t" %} 9551 ins_encode %{ 9552 bool quad = false; 9553 __ vdupI($dst$$FloatRegister, $src$$Register, 9554 MacroAssembler::VELEM_SIZE_32, quad); 9555 %} 9556 ins_pipe(ialu_reg); // FIXME 9557 %} 9558 9559 // Replicate scalar to packed int values in Double register pair 9560 instruct Repl4I_reg_simd(vecX dst, iRegI src) %{ 9561 predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd()); 9562 match(Set dst (ReplicateI src)); 9563 size(4); 9564 9565 format %{ "VDUP.32 $dst.Q,$src\t" %} 9566 ins_encode %{ 9567 bool quad = true; 9568 __ vdupI($dst$$FloatRegister, $src$$Register, 9569 MacroAssembler::VELEM_SIZE_32, quad); 9570 %} 9571 ins_pipe(ialu_reg); // FIXME 9572 %} 9573 9574 9575 // Replicate scalar zero constant to packed int values in Double register 9576 instruct Repl2I_immI(vecD dst, immI src, iRegI tmp) %{ 9577 predicate(n->as_Vector()->length() == 2); 9578 match(Set dst (ReplicateI src)); 9579 effect(TEMP tmp); 9580 size(12); 9581 ins_cost(DEFAULT_COST*4); // FIXME 9582 9583 format %{ "MOV $tmp, Repl1($src))\n\t" 9584 "FMDRR $dst,$tmp,$tmp\t" %} 9585 ins_encode( LdReplImmI(src, dst, tmp, (1), (4)) ); 9586 ins_pipe(loadConFD); // FIXME 9587 %} 9588 9589 // Replicate scalar constant to packed byte values in Double register 9590 instruct Repl2I_immU8(vecD dst, immU8 src) %{ 9591 predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd()); 9592 match(Set dst (ReplicateI src)); 9593 size(4); 9594 9595 format %{ "VMOV.I32 $dst.D,$src" %} 9596 ins_encode %{ 9597 bool quad = false; 9598 __ vmovI($dst$$FloatRegister, $src$$constant, 9599 MacroAssembler::VELEM_SIZE_32, quad); 9600 %} 9601 ins_pipe(loadConFD); // FIXME 9602 %} 9603 9604 // Replicate scalar constant to packed byte values in Double register pair 9605 instruct Repl4I_immU8(vecX dst, immU8 src) %{ 9606 predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd()); 9607 match(Set dst (ReplicateI src)); 9608 size(4); 9609 9610 format %{ "VMOV.I32 $dst.Q,$src" %} 9611 ins_encode %{ 9612 bool quad = true; 9613 __ vmovI($dst$$FloatRegister, $src$$constant, 9614 MacroAssembler::VELEM_SIZE_32, quad); 9615 %} 9616 ins_pipe(loadConFD); // FIXME 9617 %} 9618 9619 // Replicate scalar to packed byte values in Double register pair 9620 instruct Repl2L_reg(vecX dst, iRegL src) %{ 9621 predicate(n->as_Vector()->length() == 2); 9622 match(Set dst (ReplicateL src)); 9623 size(8); 9624 ins_cost(DEFAULT_COST*2); // FIXME 9625 9626 format %{ "FMDRR $dst.D,$src.lo,$src.hi\t\n" 9627 "FMDRR $dst.D.next,$src.lo,$src.hi" %} 9628 ins_encode %{ 9629 __ fmdrr($dst$$FloatRegister, $src$$Register, $src$$Register->successor()); 9630 __ fmdrr($dst$$FloatRegister->successor()->successor(), 9631 $src$$Register, $src$$Register->successor()); 9632 %} 9633 ins_pipe(ialu_reg); // FIXME 9634 %} 9635 9636 9637 // Replicate scalar to packed float values in Double register 9638 instruct Repl2F_regI(vecD dst, iRegI src) %{ 9639 predicate(n->as_Vector()->length() == 2); 9640 match(Set dst (ReplicateF src)); 9641 size(4); 9642 9643 format %{ "FMDRR $dst.D,$src,$src\t" %} 9644 ins_encode %{ 9645 __ fmdrr($dst$$FloatRegister, $src$$Register, $src$$Register); 9646 %} 9647 ins_pipe(ialu_reg); // FIXME 9648 %} 9649 9650 // Replicate scalar to packed float values in Double register 9651 instruct Repl2F_reg_vfp(vecD dst, regF src) %{ 9652 predicate(n->as_Vector()->length() == 2); 9653 match(Set dst (ReplicateF src)); 9654 size(4*2); 9655 ins_cost(DEFAULT_COST*2); // FIXME 9656 9657 expand %{ 9658 iRegI tmp; 9659 MoveF2I_reg_reg(tmp, src); 9660 Repl2F_regI(dst,tmp); 9661 %} 9662 %} 9663 9664 // Replicate scalar to packed float values in Double register 9665 instruct Repl2F_reg_simd(vecD dst, regF src) %{ 9666 predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd()); 9667 match(Set dst (ReplicateF src)); 9668 size(4); 9669 ins_cost(DEFAULT_COST); // FIXME 9670 9671 format %{ "VDUP.32 $dst.D,$src.D\t" %} 9672 ins_encode %{ 9673 bool quad = false; 9674 __ vdupF($dst$$FloatRegister, $src$$FloatRegister, quad); 9675 %} 9676 ins_pipe(ialu_reg); // FIXME 9677 %} 9678 9679 // Replicate scalar to packed float values in Double register pair 9680 instruct Repl4F_reg(vecX dst, regF src, iRegI tmp) %{ 9681 predicate(n->as_Vector()->length() == 4); 9682 match(Set dst (ReplicateF src)); 9683 effect(TEMP tmp); 9684 size(4*3); 9685 ins_cost(DEFAULT_COST*3); // FIXME 9686 9687 format %{ "FMRS $tmp,$src\n\t" 9688 "FMDRR $dst.D,$tmp,$tmp\n\t" 9689 "FMDRR $dst.D.next,$tmp,$tmp\t" %} 9690 ins_encode %{ 9691 __ fmrs($tmp$$Register, $src$$FloatRegister); 9692 __ fmdrr($dst$$FloatRegister, $tmp$$Register, $tmp$$Register); 9693 __ fmdrr($dst$$FloatRegister->successor()->successor(), 9694 $tmp$$Register, $tmp$$Register); 9695 %} 9696 ins_pipe(ialu_reg); // FIXME 9697 %} 9698 9699 // Replicate scalar to packed float values in Double register pair 9700 instruct Repl4F_reg_simd(vecX dst, regF src) %{ 9701 predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd()); 9702 match(Set dst (ReplicateF src)); 9703 size(4); 9704 ins_cost(DEFAULT_COST); // FIXME 9705 9706 format %{ "VDUP.32 $dst.Q,$src.D\t" %} 9707 ins_encode %{ 9708 bool quad = true; 9709 __ vdupF($dst$$FloatRegister, $src$$FloatRegister, quad); 9710 %} 9711 ins_pipe(ialu_reg); // FIXME 9712 %} 9713 9714 // Replicate scalar zero constant to packed float values in Double register 9715 instruct Repl2F_immI(vecD dst, immF src, iRegI tmp) %{ 9716 predicate(n->as_Vector()->length() == 2); 9717 match(Set dst (ReplicateF src)); 9718 effect(TEMP tmp); 9719 size(12); 9720 ins_cost(DEFAULT_COST*4); // FIXME 9721 9722 format %{ "MOV $tmp, Repl1($src))\n\t" 9723 "FMDRR $dst,$tmp,$tmp\t" %} 9724 ins_encode( LdReplImmF(src, dst, tmp) ); 9725 ins_pipe(loadConFD); // FIXME 9726 %} 9727 9728 // Replicate scalar to packed double float values in Double register pair 9729 instruct Repl2D_reg(vecX dst, regD src) %{ 9730 predicate(n->as_Vector()->length() == 2); 9731 match(Set dst (ReplicateD src)); 9732 size(4*2); 9733 ins_cost(DEFAULT_COST*2); // FIXME 9734 9735 format %{ "FCPYD $dst.D.a,$src\n\t" 9736 "FCPYD $dst.D.b,$src\t" %} 9737 ins_encode %{ 9738 FloatRegister dsta = $dst$$FloatRegister; 9739 FloatRegister src = $src$$FloatRegister; 9740 __ fcpyd(dsta, src); 9741 FloatRegister dstb = dsta->successor()->successor(); 9742 __ fcpyd(dstb, src); 9743 %} 9744 ins_pipe(ialu_reg); // FIXME 9745 %} 9746 9747 // ====================VECTOR ARITHMETIC======================================= 9748 9749 // --------------------------------- ADD -------------------------------------- 9750 9751 // Bytes vector add 9752 instruct vadd8B_reg(vecD dst, vecD src1, vecD src2) %{ 9753 predicate(n->as_Vector()->length() == 8); 9754 match(Set dst (AddVB src1 src2)); 9755 format %{ "VADD.I8 $dst,$src1,$src2\t! add packed8B" %} 9756 size(4); 9757 ins_encode %{ 9758 bool quad = false; 9759 __ vaddI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 9760 MacroAssembler::VELEM_SIZE_8, quad); 9761 %} 9762 ins_pipe( ialu_reg_reg ); // FIXME 9763 %} 9764 9765 instruct vadd16B_reg(vecX dst, vecX src1, vecX src2) %{ 9766 predicate(n->as_Vector()->length() == 16); 9767 match(Set dst (AddVB src1 src2)); 9768 size(4); 9769 format %{ "VADD.I8 $dst.Q,$src1.Q,$src2.Q\t! add packed16B" %} 9770 ins_encode %{ 9771 bool quad = true; 9772 __ vaddI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 9773 MacroAssembler::VELEM_SIZE_8, quad); 9774 %} 9775 ins_pipe( ialu_reg_reg ); // FIXME 9776 %} 9777 9778 // Shorts/Chars vector add 9779 instruct vadd4S_reg(vecD dst, vecD src1, vecD src2) %{ 9780 predicate(n->as_Vector()->length() == 4); 9781 match(Set dst (AddVS src1 src2)); 9782 size(4); 9783 format %{ "VADD.I16 $dst,$src1,$src2\t! add packed4S" %} 9784 ins_encode %{ 9785 bool quad = false; 9786 __ vaddI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 9787 MacroAssembler::VELEM_SIZE_16, quad); 9788 %} 9789 ins_pipe( ialu_reg_reg ); // FIXME 9790 %} 9791 9792 instruct vadd8S_reg(vecX dst, vecX src1, vecX src2) %{ 9793 predicate(n->as_Vector()->length() == 8); 9794 match(Set dst (AddVS src1 src2)); 9795 size(4); 9796 format %{ "VADD.I16 $dst.Q,$src1.Q,$src2.Q\t! add packed8S" %} 9797 ins_encode %{ 9798 bool quad = true; 9799 __ vaddI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 9800 MacroAssembler::VELEM_SIZE_16, quad); 9801 %} 9802 ins_pipe( ialu_reg_reg ); // FIXME 9803 %} 9804 9805 // Integers vector add 9806 instruct vadd2I_reg(vecD dst, vecD src1, vecD src2) %{ 9807 predicate(n->as_Vector()->length() == 2); 9808 match(Set dst (AddVI src1 src2)); 9809 size(4); 9810 format %{ "VADD.I32 $dst.D,$src1.D,$src2.D\t! add packed2I" %} 9811 ins_encode %{ 9812 bool quad = false; 9813 __ vaddI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 9814 MacroAssembler::VELEM_SIZE_32, quad); 9815 %} 9816 ins_pipe( ialu_reg_reg ); // FIXME 9817 %} 9818 9819 instruct vadd4I_reg(vecX dst, vecX src1, vecX src2) %{ 9820 predicate(n->as_Vector()->length() == 4); 9821 match(Set dst (AddVI src1 src2)); 9822 size(4); 9823 format %{ "VADD.I32 $dst.Q,$src1.Q,$src2.Q\t! add packed4I" %} 9824 ins_encode %{ 9825 bool quad = true; 9826 __ vaddI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 9827 MacroAssembler::VELEM_SIZE_32, quad); 9828 %} 9829 ins_pipe( ialu_reg_reg ); // FIXME 9830 %} 9831 9832 // Longs vector add 9833 instruct vadd2L_reg(vecX dst, vecX src1, vecX src2) %{ 9834 predicate(n->as_Vector()->length() == 2); 9835 match(Set dst (AddVL src1 src2)); 9836 size(4); 9837 format %{ "VADD.I64 $dst.Q,$src1.Q,$src2.Q\t! add packed2L" %} 9838 ins_encode %{ 9839 bool quad = true; 9840 __ vaddI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 9841 MacroAssembler::VELEM_SIZE_64, quad); 9842 %} 9843 ins_pipe( ialu_reg_reg ); // FIXME 9844 %} 9845 9846 // Floats vector add 9847 instruct vadd2F_reg(vecD dst, vecD src1, vecD src2) %{ 9848 predicate(n->as_Vector()->length() == 2 && VM_Version::simd_math_is_compliant()); 9849 match(Set dst (AddVF src1 src2)); 9850 size(4); 9851 format %{ "VADD.F32 $dst,$src1,$src2\t! add packed2F" %} 9852 ins_encode %{ 9853 bool quad = false; 9854 __ vaddF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 9855 MacroAssembler::VFA_SIZE_F32, quad); 9856 %} 9857 ins_pipe( faddD_reg_reg ); // FIXME 9858 %} 9859 9860 instruct vadd2F_reg_vfp(vecD dst, vecD src1, vecD src2) %{ 9861 predicate(n->as_Vector()->length() == 2 && !VM_Version::simd_math_is_compliant()); 9862 match(Set dst (AddVF src1 src2)); 9863 ins_cost(DEFAULT_COST*2); // FIXME 9864 9865 size(4*2); 9866 format %{ "FADDS $dst.a,$src1.a,$src2.a\n\t" 9867 "FADDS $dst.b,$src1.b,$src2.b" %} 9868 ins_encode %{ 9869 __ add_float($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister); 9870 __ add_float($dst$$FloatRegister->successor(), 9871 $src1$$FloatRegister->successor(), 9872 $src2$$FloatRegister->successor()); 9873 %} 9874 9875 ins_pipe(faddF_reg_reg); // FIXME 9876 %} 9877 9878 instruct vadd4F_reg_simd(vecX dst, vecX src1, vecX src2) %{ 9879 predicate(n->as_Vector()->length() == 4 && VM_Version::simd_math_is_compliant()); 9880 match(Set dst (AddVF src1 src2)); 9881 size(4); 9882 format %{ "VADD.F32 $dst.Q,$src1.Q,$src2.Q\t! add packed4F" %} 9883 ins_encode %{ 9884 bool quad = true; 9885 __ vaddF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 9886 MacroAssembler::VFA_SIZE_F32, quad); 9887 %} 9888 ins_pipe( faddD_reg_reg ); // FIXME 9889 %} 9890 9891 instruct vadd4F_reg_vfp(vecX dst, vecX src1, vecX src2) %{ 9892 predicate(n->as_Vector()->length() == 4 && !VM_Version::simd_math_is_compliant()); 9893 match(Set dst (AddVF src1 src2)); 9894 size(4*4); 9895 ins_cost(DEFAULT_COST*4); // FIXME 9896 9897 format %{ "FADDS $dst.a,$src1.a,$src2.a\n\t" 9898 "FADDS $dst.b,$src1.b,$src2.b\n\t" 9899 "FADDS $dst.c,$src1.c,$src2.c\n\t" 9900 "FADDS $dst.d,$src1.d,$src2.d" %} 9901 9902 ins_encode %{ 9903 FloatRegister dsta = $dst$$FloatRegister; 9904 FloatRegister src1a = $src1$$FloatRegister; 9905 FloatRegister src2a = $src2$$FloatRegister; 9906 __ add_float(dsta, src1a, src2a); 9907 FloatRegister dstb = dsta->successor(); 9908 FloatRegister src1b = src1a->successor(); 9909 FloatRegister src2b = src2a->successor(); 9910 __ add_float(dstb, src1b, src2b); 9911 FloatRegister dstc = dstb->successor(); 9912 FloatRegister src1c = src1b->successor(); 9913 FloatRegister src2c = src2b->successor(); 9914 __ add_float(dstc, src1c, src2c); 9915 FloatRegister dstd = dstc->successor(); 9916 FloatRegister src1d = src1c->successor(); 9917 FloatRegister src2d = src2c->successor(); 9918 __ add_float(dstd, src1d, src2d); 9919 %} 9920 9921 ins_pipe(faddF_reg_reg); // FIXME 9922 %} 9923 9924 instruct vadd2D_reg_vfp(vecX dst, vecX src1, vecX src2) %{ 9925 predicate(n->as_Vector()->length() == 2); 9926 match(Set dst (AddVD src1 src2)); 9927 size(4*2); 9928 ins_cost(DEFAULT_COST*2); // FIXME 9929 9930 format %{ "FADDD $dst.a,$src1.a,$src2.a\n\t" 9931 "FADDD $dst.b,$src1.b,$src2.b" %} 9932 9933 ins_encode %{ 9934 FloatRegister dsta = $dst$$FloatRegister; 9935 FloatRegister src1a = $src1$$FloatRegister; 9936 FloatRegister src2a = $src2$$FloatRegister; 9937 __ add_double(dsta, src1a, src2a); 9938 FloatRegister dstb = dsta->successor()->successor(); 9939 FloatRegister src1b = src1a->successor()->successor(); 9940 FloatRegister src2b = src2a->successor()->successor(); 9941 __ add_double(dstb, src1b, src2b); 9942 %} 9943 9944 ins_pipe(faddF_reg_reg); // FIXME 9945 %} 9946 9947 9948 // Bytes vector sub 9949 instruct vsub8B_reg(vecD dst, vecD src1, vecD src2) %{ 9950 predicate(n->as_Vector()->length() == 8); 9951 match(Set dst (SubVB src1 src2)); 9952 size(4); 9953 format %{ "VSUB.I8 $dst,$src1,$src2\t! sub packed8B" %} 9954 ins_encode %{ 9955 bool quad = false; 9956 __ vsubI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 9957 MacroAssembler::VELEM_SIZE_8, quad); 9958 %} 9959 ins_pipe( ialu_reg_reg ); // FIXME 9960 %} 9961 9962 instruct vsub16B_reg(vecX dst, vecX src1, vecX src2) %{ 9963 predicate(n->as_Vector()->length() == 16); 9964 match(Set dst (SubVB src1 src2)); 9965 size(4); 9966 format %{ "VSUB.I8 $dst.Q,$src1.Q,$src2.Q\t! sub packed16B" %} 9967 ins_encode %{ 9968 bool quad = true; 9969 __ vsubI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 9970 MacroAssembler::VELEM_SIZE_8, quad); 9971 %} 9972 ins_pipe( ialu_reg_reg ); // FIXME 9973 %} 9974 9975 // Shorts/Chars vector sub 9976 instruct vsub4S_reg(vecD dst, vecD src1, vecD src2) %{ 9977 predicate(n->as_Vector()->length() == 4); 9978 match(Set dst (SubVS src1 src2)); 9979 size(4); 9980 format %{ "VSUB.I16 $dst,$src1,$src2\t! sub packed4S" %} 9981 ins_encode %{ 9982 bool quad = false; 9983 __ vsubI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 9984 MacroAssembler::VELEM_SIZE_16, quad); 9985 %} 9986 ins_pipe( ialu_reg_reg ); // FIXME 9987 %} 9988 9989 instruct vsub16S_reg(vecX dst, vecX src1, vecX src2) %{ 9990 predicate(n->as_Vector()->length() == 8); 9991 match(Set dst (SubVS src1 src2)); 9992 size(4); 9993 format %{ "VSUB.I16 $dst.Q,$src1.Q,$src2.Q\t! sub packed8S" %} 9994 ins_encode %{ 9995 bool quad = true; 9996 __ vsubI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 9997 MacroAssembler::VELEM_SIZE_16, quad); 9998 %} 9999 ins_pipe( ialu_reg_reg ); // FIXME 10000 %} 10001 10002 // Integers vector sub 10003 instruct vsub2I_reg(vecD dst, vecD src1, vecD src2) %{ 10004 predicate(n->as_Vector()->length() == 2); 10005 match(Set dst (SubVI src1 src2)); 10006 size(4); 10007 format %{ "VSUB.I32 $dst,$src1,$src2\t! sub packed2I" %} 10008 ins_encode %{ 10009 bool quad = false; 10010 __ vsubI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 10011 MacroAssembler::VELEM_SIZE_32, quad); 10012 %} 10013 ins_pipe( ialu_reg_reg ); // FIXME 10014 %} 10015 10016 instruct vsub4I_reg(vecX dst, vecX src1, vecX src2) %{ 10017 predicate(n->as_Vector()->length() == 4); 10018 match(Set dst (SubVI src1 src2)); 10019 size(4); 10020 format %{ "VSUB.I32 $dst.Q,$src1.Q,$src2.Q\t! sub packed4I" %} 10021 ins_encode %{ 10022 bool quad = true; 10023 __ vsubI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 10024 MacroAssembler::VELEM_SIZE_32, quad); 10025 %} 10026 ins_pipe( ialu_reg_reg ); // FIXME 10027 %} 10028 10029 // Longs vector sub 10030 instruct vsub2L_reg(vecX dst, vecX src1, vecX src2) %{ 10031 predicate(n->as_Vector()->length() == 2); 10032 match(Set dst (SubVL src1 src2)); 10033 size(4); 10034 format %{ "VSUB.I64 $dst.Q,$src1.Q,$src2.Q\t! sub packed2L" %} 10035 ins_encode %{ 10036 bool quad = true; 10037 __ vsubI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 10038 MacroAssembler::VELEM_SIZE_64, quad); 10039 %} 10040 ins_pipe( ialu_reg_reg ); // FIXME 10041 %} 10042 10043 // Floats vector sub 10044 instruct vsub2F_reg(vecD dst, vecD src1, vecD src2) %{ 10045 predicate(n->as_Vector()->length() == 2 && VM_Version::simd_math_is_compliant()); 10046 match(Set dst (SubVF src1 src2)); 10047 size(4); 10048 format %{ "VSUB.F32 $dst,$src1,$src2\t! sub packed2F" %} 10049 ins_encode %{ 10050 bool quad = false; 10051 __ vsubF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 10052 MacroAssembler::VFA_SIZE_F32, quad); 10053 %} 10054 ins_pipe( faddF_reg_reg ); // FIXME 10055 %} 10056 10057 instruct vsub2F_reg_vfp(vecD dst, vecD src1, vecD src2) %{ 10058 predicate(n->as_Vector()->length() == 2 && !VM_Version::simd_math_is_compliant()); 10059 match(Set dst (SubVF src1 src2)); 10060 size(4*2); 10061 ins_cost(DEFAULT_COST*2); // FIXME 10062 10063 format %{ "FSUBS $dst.a,$src1.a,$src2.a\n\t" 10064 "FSUBS $dst.b,$src1.b,$src2.b" %} 10065 10066 ins_encode %{ 10067 FloatRegister dsta = $dst$$FloatRegister; 10068 FloatRegister src1a = $src1$$FloatRegister; 10069 FloatRegister src2a = $src2$$FloatRegister; 10070 __ sub_float(dsta, src1a, src2a); 10071 FloatRegister dstb = dsta->successor(); 10072 FloatRegister src1b = src1a->successor(); 10073 FloatRegister src2b = src2a->successor(); 10074 __ sub_float(dstb, src1b, src2b); 10075 %} 10076 10077 ins_pipe(faddF_reg_reg); // FIXME 10078 %} 10079 10080 10081 instruct vsub4F_reg(vecX dst, vecX src1, vecX src2) %{ 10082 predicate(n->as_Vector()->length() == 4 && VM_Version::simd_math_is_compliant()); 10083 match(Set dst (SubVF src1 src2)); 10084 size(4); 10085 format %{ "VSUB.F32 $dst.Q,$src1.Q,$src2.Q\t! sub packed4F" %} 10086 ins_encode %{ 10087 bool quad = true; 10088 __ vsubF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 10089 MacroAssembler::VFA_SIZE_F32, quad); 10090 %} 10091 ins_pipe( faddF_reg_reg ); // FIXME 10092 %} 10093 10094 instruct vsub4F_reg_vfp(vecX dst, vecX src1, vecX src2) %{ 10095 predicate(n->as_Vector()->length() == 4 && !VM_Version::simd_math_is_compliant()); 10096 match(Set dst (SubVF src1 src2)); 10097 size(4*4); 10098 ins_cost(DEFAULT_COST*4); // FIXME 10099 10100 format %{ "FSUBS $dst.a,$src1.a,$src2.a\n\t" 10101 "FSUBS $dst.b,$src1.b,$src2.b\n\t" 10102 "FSUBS $dst.c,$src1.c,$src2.c\n\t" 10103 "FSUBS $dst.d,$src1.d,$src2.d" %} 10104 10105 ins_encode %{ 10106 FloatRegister dsta = $dst$$FloatRegister; 10107 FloatRegister src1a = $src1$$FloatRegister; 10108 FloatRegister src2a = $src2$$FloatRegister; 10109 __ sub_float(dsta, src1a, src2a); 10110 FloatRegister dstb = dsta->successor(); 10111 FloatRegister src1b = src1a->successor(); 10112 FloatRegister src2b = src2a->successor(); 10113 __ sub_float(dstb, src1b, src2b); 10114 FloatRegister dstc = dstb->successor(); 10115 FloatRegister src1c = src1b->successor(); 10116 FloatRegister src2c = src2b->successor(); 10117 __ sub_float(dstc, src1c, src2c); 10118 FloatRegister dstd = dstc->successor(); 10119 FloatRegister src1d = src1c->successor(); 10120 FloatRegister src2d = src2c->successor(); 10121 __ sub_float(dstd, src1d, src2d); 10122 %} 10123 10124 ins_pipe(faddF_reg_reg); // FIXME 10125 %} 10126 10127 instruct vsub2D_reg_vfp(vecX dst, vecX src1, vecX src2) %{ 10128 predicate(n->as_Vector()->length() == 2); 10129 match(Set dst (SubVD src1 src2)); 10130 size(4*2); 10131 ins_cost(DEFAULT_COST*2); // FIXME 10132 10133 format %{ "FSUBD $dst.a,$src1.a,$src2.a\n\t" 10134 "FSUBD $dst.b,$src1.b,$src2.b" %} 10135 10136 ins_encode %{ 10137 FloatRegister dsta = $dst$$FloatRegister; 10138 FloatRegister src1a = $src1$$FloatRegister; 10139 FloatRegister src2a = $src2$$FloatRegister; 10140 __ sub_double(dsta, src1a, src2a); 10141 FloatRegister dstb = dsta->successor()->successor(); 10142 FloatRegister src1b = src1a->successor()->successor(); 10143 FloatRegister src2b = src2a->successor()->successor(); 10144 __ sub_double(dstb, src1b, src2b); 10145 %} 10146 10147 ins_pipe(faddF_reg_reg); // FIXME 10148 %} 10149 10150 // Shorts/Chars vector mul 10151 instruct vmul4S_reg(vecD dst, vecD src1, vecD src2) %{ 10152 predicate(n->as_Vector()->length() == 4); 10153 match(Set dst (MulVS src1 src2)); 10154 size(4); 10155 format %{ "VMUL.I16 $dst,$src1,$src2\t! mul packed4S" %} 10156 ins_encode %{ 10157 __ vmulI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 10158 MacroAssembler::VELEM_SIZE_16, 0); 10159 %} 10160 ins_pipe( ialu_reg_reg ); // FIXME 10161 %} 10162 10163 instruct vmul8S_reg(vecX dst, vecX src1, vecX src2) %{ 10164 predicate(n->as_Vector()->length() == 8); 10165 match(Set dst (MulVS src1 src2)); 10166 size(4); 10167 format %{ "VMUL.I16 $dst.Q,$src1.Q,$src2.Q\t! mul packed8S" %} 10168 ins_encode %{ 10169 __ vmulI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 10170 MacroAssembler::VELEM_SIZE_16, 1); 10171 %} 10172 ins_pipe( ialu_reg_reg ); // FIXME 10173 %} 10174 10175 // Integers vector mul 10176 instruct vmul2I_reg(vecD dst, vecD src1, vecD src2) %{ 10177 predicate(n->as_Vector()->length() == 2); 10178 match(Set dst (MulVI src1 src2)); 10179 size(4); 10180 format %{ "VMUL.I32 $dst,$src1,$src2\t! mul packed2I" %} 10181 ins_encode %{ 10182 __ vmulI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 10183 MacroAssembler::VELEM_SIZE_32, 0); 10184 %} 10185 ins_pipe( ialu_reg_reg ); // FIXME 10186 %} 10187 10188 instruct vmul4I_reg(vecX dst, vecX src1, vecX src2) %{ 10189 predicate(n->as_Vector()->length() == 4); 10190 match(Set dst (MulVI src1 src2)); 10191 size(4); 10192 format %{ "VMUL.I32 $dst.Q,$src1.Q,$src2.Q\t! mul packed4I" %} 10193 ins_encode %{ 10194 __ vmulI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 10195 MacroAssembler::VELEM_SIZE_32, 1); 10196 %} 10197 ins_pipe( ialu_reg_reg ); // FIXME 10198 %} 10199 10200 // Floats vector mul 10201 instruct vmul2F_reg(vecD dst, vecD src1, vecD src2) %{ 10202 predicate(n->as_Vector()->length() == 2 && VM_Version::simd_math_is_compliant()); 10203 match(Set dst (MulVF src1 src2)); 10204 size(4); 10205 format %{ "VMUL.F32 $dst,$src1,$src2\t! mul packed2F" %} 10206 ins_encode %{ 10207 __ vmulF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 10208 MacroAssembler::VFA_SIZE_F32, 0); 10209 %} 10210 ins_pipe( fmulF_reg_reg ); // FIXME 10211 %} 10212 10213 instruct vmul2F_reg_vfp(vecD dst, vecD src1, vecD src2) %{ 10214 predicate(n->as_Vector()->length() == 2 && !VM_Version::simd_math_is_compliant()); 10215 match(Set dst (MulVF src1 src2)); 10216 size(4*2); 10217 ins_cost(DEFAULT_COST*2); // FIXME 10218 10219 format %{ "FMULS $dst.a,$src1.a,$src2.a\n\t" 10220 "FMULS $dst.b,$src1.b,$src2.b" %} 10221 ins_encode %{ 10222 __ mul_float($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister); 10223 __ mul_float($dst$$FloatRegister->successor(), 10224 $src1$$FloatRegister->successor(), 10225 $src2$$FloatRegister->successor()); 10226 %} 10227 10228 ins_pipe(fmulF_reg_reg); // FIXME 10229 %} 10230 10231 instruct vmul4F_reg(vecX dst, vecX src1, vecX src2) %{ 10232 predicate(n->as_Vector()->length() == 4 && VM_Version::simd_math_is_compliant()); 10233 match(Set dst (MulVF src1 src2)); 10234 size(4); 10235 format %{ "VMUL.F32 $dst.Q,$src1.Q,$src2.Q\t! mul packed4F" %} 10236 ins_encode %{ 10237 __ vmulF($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 10238 MacroAssembler::VFA_SIZE_F32, 1); 10239 %} 10240 ins_pipe( fmulF_reg_reg ); // FIXME 10241 %} 10242 10243 instruct vmul4F_reg_vfp(vecX dst, vecX src1, vecX src2) %{ 10244 predicate(n->as_Vector()->length() == 4 && !VM_Version::simd_math_is_compliant()); 10245 match(Set dst (MulVF src1 src2)); 10246 size(4*4); 10247 ins_cost(DEFAULT_COST*4); // FIXME 10248 10249 format %{ "FMULS $dst.a,$src1.a,$src2.a\n\t" 10250 "FMULS $dst.b,$src1.b,$src2.b\n\t" 10251 "FMULS $dst.c,$src1.c,$src2.c\n\t" 10252 "FMULS $dst.d,$src1.d,$src2.d" %} 10253 10254 ins_encode %{ 10255 FloatRegister dsta = $dst$$FloatRegister; 10256 FloatRegister src1a = $src1$$FloatRegister; 10257 FloatRegister src2a = $src2$$FloatRegister; 10258 __ mul_float(dsta, src1a, src2a); 10259 FloatRegister dstb = dsta->successor(); 10260 FloatRegister src1b = src1a->successor(); 10261 FloatRegister src2b = src2a->successor(); 10262 __ mul_float(dstb, src1b, src2b); 10263 FloatRegister dstc = dstb->successor(); 10264 FloatRegister src1c = src1b->successor(); 10265 FloatRegister src2c = src2b->successor(); 10266 __ mul_float(dstc, src1c, src2c); 10267 FloatRegister dstd = dstc->successor(); 10268 FloatRegister src1d = src1c->successor(); 10269 FloatRegister src2d = src2c->successor(); 10270 __ mul_float(dstd, src1d, src2d); 10271 %} 10272 10273 ins_pipe(fmulF_reg_reg); // FIXME 10274 %} 10275 10276 instruct vmul2D_reg_vfp(vecX dst, vecX src1, vecX src2) %{ 10277 predicate(n->as_Vector()->length() == 2); 10278 match(Set dst (MulVD src1 src2)); 10279 size(4*2); 10280 ins_cost(DEFAULT_COST*2); // FIXME 10281 10282 format %{ "FMULD $dst.D.a,$src1.D.a,$src2.D.a\n\t" 10283 "FMULD $dst.D.b,$src1.D.b,$src2.D.b" %} 10284 ins_encode %{ 10285 FloatRegister dsta = $dst$$FloatRegister; 10286 FloatRegister src1a = $src1$$FloatRegister; 10287 FloatRegister src2a = $src2$$FloatRegister; 10288 __ mul_double(dsta, src1a, src2a); 10289 FloatRegister dstb = dsta->successor()->successor(); 10290 FloatRegister src1b = src1a->successor()->successor(); 10291 FloatRegister src2b = src2a->successor()->successor(); 10292 __ mul_double(dstb, src1b, src2b); 10293 %} 10294 10295 ins_pipe(fmulD_reg_reg); // FIXME 10296 %} 10297 10298 10299 // Floats vector div 10300 instruct vdiv2F_reg_vfp(vecD dst, vecD src1, vecD src2) %{ 10301 predicate(n->as_Vector()->length() == 2); 10302 match(Set dst (DivVF src1 src2)); 10303 size(4*2); 10304 ins_cost(DEFAULT_COST*2); // FIXME 10305 10306 format %{ "FDIVS $dst.a,$src1.a,$src2.a\n\t" 10307 "FDIVS $dst.b,$src1.b,$src2.b" %} 10308 ins_encode %{ 10309 __ div_float($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister); 10310 __ div_float($dst$$FloatRegister->successor(), 10311 $src1$$FloatRegister->successor(), 10312 $src2$$FloatRegister->successor()); 10313 %} 10314 10315 ins_pipe(fdivF_reg_reg); // FIXME 10316 %} 10317 10318 instruct vdiv4F_reg_vfp(vecX dst, vecX src1, vecX src2) %{ 10319 predicate(n->as_Vector()->length() == 4); 10320 match(Set dst (DivVF src1 src2)); 10321 size(4*4); 10322 ins_cost(DEFAULT_COST*4); // FIXME 10323 10324 format %{ "FDIVS $dst.a,$src1.a,$src2.a\n\t" 10325 "FDIVS $dst.b,$src1.b,$src2.b\n\t" 10326 "FDIVS $dst.c,$src1.c,$src2.c\n\t" 10327 "FDIVS $dst.d,$src1.d,$src2.d" %} 10328 10329 ins_encode %{ 10330 FloatRegister dsta = $dst$$FloatRegister; 10331 FloatRegister src1a = $src1$$FloatRegister; 10332 FloatRegister src2a = $src2$$FloatRegister; 10333 __ div_float(dsta, src1a, src2a); 10334 FloatRegister dstb = dsta->successor(); 10335 FloatRegister src1b = src1a->successor(); 10336 FloatRegister src2b = src2a->successor(); 10337 __ div_float(dstb, src1b, src2b); 10338 FloatRegister dstc = dstb->successor(); 10339 FloatRegister src1c = src1b->successor(); 10340 FloatRegister src2c = src2b->successor(); 10341 __ div_float(dstc, src1c, src2c); 10342 FloatRegister dstd = dstc->successor(); 10343 FloatRegister src1d = src1c->successor(); 10344 FloatRegister src2d = src2c->successor(); 10345 __ div_float(dstd, src1d, src2d); 10346 %} 10347 10348 ins_pipe(fdivF_reg_reg); // FIXME 10349 %} 10350 10351 instruct vdiv2D_reg_vfp(vecX dst, vecX src1, vecX src2) %{ 10352 predicate(n->as_Vector()->length() == 2); 10353 match(Set dst (DivVD src1 src2)); 10354 size(4*2); 10355 ins_cost(DEFAULT_COST*2); // FIXME 10356 10357 format %{ "FDIVD $dst.D.a,$src1.D.a,$src2.D.a\n\t" 10358 "FDIVD $dst.D.b,$src1.D.b,$src2.D.b" %} 10359 ins_encode %{ 10360 FloatRegister dsta = $dst$$FloatRegister; 10361 FloatRegister src1a = $src1$$FloatRegister; 10362 FloatRegister src2a = $src2$$FloatRegister; 10363 __ div_double(dsta, src1a, src2a); 10364 FloatRegister dstb = dsta->successor()->successor(); 10365 FloatRegister src1b = src1a->successor()->successor(); 10366 FloatRegister src2b = src2a->successor()->successor(); 10367 __ div_double(dstb, src1b, src2b); 10368 %} 10369 10370 ins_pipe(fdivD_reg_reg); // FIXME 10371 %} 10372 10373 // --------------------------------- NEG -------------------------------------- 10374 10375 instruct vneg8B_reg(vecD dst, vecD src) %{ 10376 predicate(n->as_Vector()->length_in_bytes() == 8); 10377 effect(DEF dst, USE src); 10378 size(4); 10379 ins_cost(DEFAULT_COST); // FIXME 10380 format %{ "VNEG.S8 $dst.D,$src.D\t! neg packed8B" %} 10381 ins_encode %{ 10382 bool quad = false; 10383 __ vnegI($dst$$FloatRegister, $src$$FloatRegister, 10384 MacroAssembler::VELEM_SIZE_8, quad); 10385 %} 10386 ins_pipe( ialu_reg_reg ); // FIXME 10387 %} 10388 10389 instruct vneg16B_reg(vecX dst, vecX src) %{ 10390 predicate(n->as_Vector()->length_in_bytes() == 16); 10391 effect(DEF dst, USE src); 10392 size(4); 10393 ins_cost(DEFAULT_COST); // FIXME 10394 format %{ "VNEG.S8 $dst.Q,$src.Q\t! neg0 packed16B" %} 10395 ins_encode %{ 10396 bool _float = false; 10397 bool quad = true; 10398 __ vnegI($dst$$FloatRegister, $src$$FloatRegister, 10399 MacroAssembler::VELEM_SIZE_8, quad); 10400 %} 10401 ins_pipe( ialu_reg_reg ); // FIXME 10402 %} 10403 10404 // ------------------------------ Shift --------------------------------------- 10405 10406 instruct vslcntD(vecD dst, iRegI cnt) %{ 10407 predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd()); 10408 match(Set dst (LShiftCntV cnt)); 10409 size(4); 10410 ins_cost(DEFAULT_COST); // FIXME 10411 expand %{ 10412 Repl8B_reg_simd(dst, cnt); 10413 %} 10414 %} 10415 10416 instruct vslcntX(vecX dst, iRegI cnt) %{ 10417 predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd()); 10418 match(Set dst (LShiftCntV cnt)); 10419 size(4); 10420 ins_cost(DEFAULT_COST); // FIXME 10421 expand %{ 10422 Repl16B_reg(dst, cnt); 10423 %} 10424 %} 10425 10426 // Low bits of vector "shift" elements are used, so it 10427 // doesn't matter if we treat it as ints or bytes here. 10428 instruct vsrcntD(vecD dst, iRegI cnt) %{ 10429 predicate(n->as_Vector()->length_in_bytes() == 8 && VM_Version::has_simd()); 10430 match(Set dst (RShiftCntV cnt)); 10431 size(4*2); 10432 ins_cost(DEFAULT_COST*2); // FIXME 10433 10434 format %{ "VDUP.8 $dst.D,$cnt\n\t" 10435 "VNEG.S8 $dst.D,$dst.D\t! neg packed8B" %} 10436 ins_encode %{ 10437 bool quad = false; 10438 __ vdupI($dst$$FloatRegister, $cnt$$Register, 10439 MacroAssembler::VELEM_SIZE_8, quad); 10440 __ vnegI($dst$$FloatRegister, $dst$$FloatRegister, 10441 MacroAssembler::VELEM_SIZE_8, quad); 10442 %} 10443 ins_pipe( ialu_reg_reg ); // FIXME 10444 %} 10445 10446 instruct vsrcntX(vecX dst, iRegI cnt) %{ 10447 predicate(n->as_Vector()->length_in_bytes() == 16 && VM_Version::has_simd()); 10448 match(Set dst (RShiftCntV cnt)); 10449 size(4*2); 10450 ins_cost(DEFAULT_COST*2); // FIXME 10451 format %{ "VDUP.8 $dst.Q,$cnt\n\t" 10452 "VNEG.S8 $dst.Q,$dst.Q\t! neg packed16B" %} 10453 ins_encode %{ 10454 bool quad = true; 10455 __ vdupI($dst$$FloatRegister, $cnt$$Register, 10456 MacroAssembler::VELEM_SIZE_8, quad); 10457 __ vnegI($dst$$FloatRegister, $dst$$FloatRegister, 10458 MacroAssembler::VELEM_SIZE_8, quad); 10459 %} 10460 ins_pipe( ialu_reg_reg ); // FIXME 10461 %} 10462 10463 // Byte vector logical left/right shift based on sign 10464 instruct vsh8B_reg(vecD dst, vecD src, vecD shift) %{ 10465 predicate(n->as_Vector()->length() == 8); 10466 effect(DEF dst, USE src, USE shift); 10467 size(4); 10468 ins_cost(DEFAULT_COST); // FIXME 10469 format %{ 10470 "VSHL.U8 $dst.D,$src.D,$shift.D\t! logical left/right shift packed8B" 10471 %} 10472 ins_encode %{ 10473 bool quad = false; 10474 __ vshlUI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister, 10475 MacroAssembler::VELEM_SIZE_8, quad); 10476 %} 10477 ins_pipe( ialu_reg_reg ); // FIXME 10478 %} 10479 10480 instruct vsh16B_reg(vecX dst, vecX src, vecX shift) %{ 10481 predicate(n->as_Vector()->length() == 16); 10482 effect(DEF dst, USE src, USE shift); 10483 size(4); 10484 ins_cost(DEFAULT_COST); // FIXME 10485 format %{ 10486 "VSHL.U8 $dst.Q,$src.Q,$shift.Q\t! logical left/right shift packed16B" 10487 %} 10488 ins_encode %{ 10489 bool quad = true; 10490 __ vshlUI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister, 10491 MacroAssembler::VELEM_SIZE_8, quad); 10492 %} 10493 ins_pipe( ialu_reg_reg ); // FIXME 10494 %} 10495 10496 // Shorts/Char vector logical left/right shift based on sign 10497 instruct vsh4S_reg(vecD dst, vecD src, vecD shift) %{ 10498 predicate(n->as_Vector()->length() == 4); 10499 effect(DEF dst, USE src, USE shift); 10500 size(4); 10501 ins_cost(DEFAULT_COST); // FIXME 10502 format %{ 10503 "VSHL.U16 $dst.D,$src.D,$shift.D\t! logical left/right shift packed4S" 10504 %} 10505 ins_encode %{ 10506 bool quad = false; 10507 __ vshlUI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister, 10508 MacroAssembler::VELEM_SIZE_16, quad); 10509 %} 10510 ins_pipe( ialu_reg_reg ); // FIXME 10511 %} 10512 10513 instruct vsh8S_reg(vecX dst, vecX src, vecX shift) %{ 10514 predicate(n->as_Vector()->length() == 8); 10515 effect(DEF dst, USE src, USE shift); 10516 size(4); 10517 ins_cost(DEFAULT_COST); // FIXME 10518 format %{ 10519 "VSHL.U16 $dst.Q,$src.Q,$shift.Q\t! logical left/right shift packed8S" 10520 %} 10521 ins_encode %{ 10522 bool quad = true; 10523 __ vshlUI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister, 10524 MacroAssembler::VELEM_SIZE_16, quad); 10525 %} 10526 ins_pipe( ialu_reg_reg ); // FIXME 10527 %} 10528 10529 // Integers vector logical left/right shift based on sign 10530 instruct vsh2I_reg(vecD dst, vecD src, vecD shift) %{ 10531 predicate(n->as_Vector()->length() == 2); 10532 effect(DEF dst, USE src, USE shift); 10533 size(4); 10534 ins_cost(DEFAULT_COST); // FIXME 10535 format %{ 10536 "VSHL.U32 $dst.D,$src.D,$shift.D\t! logical left/right shift packed2I" 10537 %} 10538 ins_encode %{ 10539 bool quad = false; 10540 __ vshlUI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister, 10541 MacroAssembler::VELEM_SIZE_32, quad); 10542 %} 10543 ins_pipe( ialu_reg_reg ); // FIXME 10544 %} 10545 10546 instruct vsh4I_reg(vecX dst, vecX src, vecX shift) %{ 10547 predicate(n->as_Vector()->length() == 4); 10548 effect(DEF dst, USE src, USE shift); 10549 size(4); 10550 ins_cost(DEFAULT_COST); // FIXME 10551 format %{ 10552 "VSHL.U32 $dst.Q,$src.Q,$shift.Q\t! logical left/right shift packed4I" 10553 %} 10554 ins_encode %{ 10555 bool quad = true; 10556 __ vshlUI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister, 10557 MacroAssembler::VELEM_SIZE_32, quad); 10558 %} 10559 ins_pipe( ialu_reg_reg ); // FIXME 10560 %} 10561 10562 // Longs vector logical left/right shift based on sign 10563 instruct vsh2L_reg(vecX dst, vecX src, vecX shift) %{ 10564 predicate(n->as_Vector()->length() == 2); 10565 effect(DEF dst, USE src, USE shift); 10566 size(4); 10567 ins_cost(DEFAULT_COST); // FIXME 10568 format %{ 10569 "VSHL.U64 $dst.Q,$src.Q,$shift.Q\t! logical left/right shift packed2L" 10570 %} 10571 ins_encode %{ 10572 bool quad = true; 10573 __ vshlUI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister, 10574 MacroAssembler::VELEM_SIZE_64, quad); 10575 %} 10576 ins_pipe( ialu_reg_reg ); // FIXME 10577 %} 10578 10579 // ------------------------------ LeftShift ----------------------------------- 10580 10581 // Byte vector left shift 10582 instruct vsl8B_reg(vecD dst, vecD src, vecD shift) %{ 10583 predicate(n->as_Vector()->length() == 8); 10584 match(Set dst (LShiftVB src shift)); 10585 size(4*1); 10586 ins_cost(DEFAULT_COST*1); // FIXME 10587 expand %{ 10588 vsh8B_reg(dst, src, shift); 10589 %} 10590 %} 10591 10592 instruct vsl16B_reg(vecX dst, vecX src, vecX shift) %{ 10593 predicate(n->as_Vector()->length() == 16); 10594 match(Set dst (LShiftVB src shift)); 10595 size(4*1); 10596 ins_cost(DEFAULT_COST*1); // FIXME 10597 expand %{ 10598 vsh16B_reg(dst, src, shift); 10599 %} 10600 %} 10601 10602 instruct vsl8B_immI(vecD dst, vecD src, immI shift) %{ 10603 predicate(n->as_Vector()->length() == 8); 10604 match(Set dst (LShiftVB src (LShiftCntV shift))); 10605 size(4); 10606 ins_cost(DEFAULT_COST); // FIXME 10607 format %{ 10608 "VSHL.I8 $dst.D,$src.D,$shift\t! logical left shift packed8B" 10609 %} 10610 ins_encode %{ 10611 bool quad = false; 10612 __ vshli($dst$$FloatRegister, $src$$FloatRegister, 8, $shift$$constant, 10613 quad); 10614 %} 10615 ins_pipe( ialu_reg_reg ); // FIXME 10616 %} 10617 10618 instruct vsl16B_immI(vecX dst, vecX src, immI shift) %{ 10619 predicate(n->as_Vector()->length() == 16); 10620 match(Set dst (LShiftVB src (LShiftCntV shift))); 10621 size(4); 10622 ins_cost(DEFAULT_COST); // FIXME 10623 format %{ 10624 "VSHL.I8 $dst.Q,$src.Q,$shift\t! logical left shift packed16B" 10625 %} 10626 ins_encode %{ 10627 bool quad = true; 10628 __ vshli($dst$$FloatRegister, $src$$FloatRegister, 8, $shift$$constant, 10629 quad); 10630 %} 10631 ins_pipe( ialu_reg_reg ); // FIXME 10632 %} 10633 10634 // Shorts/Chars vector logical left/right shift 10635 instruct vsl4S_reg(vecD dst, vecD src, vecD shift) %{ 10636 predicate(n->as_Vector()->length() == 4); 10637 match(Set dst (LShiftVS src shift)); 10638 match(Set dst (URShiftVS src shift)); 10639 size(4*1); 10640 ins_cost(DEFAULT_COST*1); // FIXME 10641 expand %{ 10642 vsh4S_reg(dst, src, shift); 10643 %} 10644 %} 10645 10646 instruct vsl8S_reg(vecX dst, vecX src, vecX shift) %{ 10647 predicate(n->as_Vector()->length() == 8); 10648 match(Set dst (LShiftVS src shift)); 10649 match(Set dst (URShiftVS src shift)); 10650 size(4*1); 10651 ins_cost(DEFAULT_COST*1); // FIXME 10652 expand %{ 10653 vsh8S_reg(dst, src, shift); 10654 %} 10655 %} 10656 10657 instruct vsl4S_immI(vecD dst, vecD src, immI shift) %{ 10658 predicate(n->as_Vector()->length() == 4); 10659 match(Set dst (LShiftVS src (LShiftCntV shift))); 10660 size(4); 10661 ins_cost(DEFAULT_COST); // FIXME 10662 format %{ 10663 "VSHL.I16 $dst.D,$src.D,$shift\t! logical left shift packed4S" 10664 %} 10665 ins_encode %{ 10666 bool quad = false; 10667 __ vshli($dst$$FloatRegister, $src$$FloatRegister, 16, $shift$$constant, 10668 quad); 10669 %} 10670 ins_pipe( ialu_reg_reg ); // FIXME 10671 %} 10672 10673 instruct vsl8S_immI(vecX dst, vecX src, immI shift) %{ 10674 predicate(n->as_Vector()->length() == 8); 10675 match(Set dst (LShiftVS src shift)); 10676 size(4); 10677 ins_cost(DEFAULT_COST); // FIXME 10678 format %{ 10679 "VSHL.I16 $dst.Q,$src.Q,$shift\t! logical left shift packed8S" 10680 %} 10681 ins_encode %{ 10682 bool quad = true; 10683 __ vshli($dst$$FloatRegister, $src$$FloatRegister, 16, $shift$$constant, 10684 quad); 10685 %} 10686 ins_pipe( ialu_reg_reg ); // FIXME 10687 %} 10688 10689 // Integers vector logical left/right shift 10690 instruct vsl2I_reg(vecD dst, vecD src, vecD shift) %{ 10691 predicate(n->as_Vector()->length() == 2 && VM_Version::has_simd()); 10692 match(Set dst (LShiftVI src shift)); 10693 match(Set dst (URShiftVI src shift)); 10694 size(4*1); 10695 ins_cost(DEFAULT_COST*1); // FIXME 10696 expand %{ 10697 vsh2I_reg(dst, src, shift); 10698 %} 10699 %} 10700 10701 instruct vsl4I_reg(vecX dst, vecX src, vecX shift) %{ 10702 predicate(n->as_Vector()->length() == 4 && VM_Version::has_simd()); 10703 match(Set dst (LShiftVI src shift)); 10704 match(Set dst (URShiftVI src shift)); 10705 size(4*1); 10706 ins_cost(DEFAULT_COST*1); // FIXME 10707 expand %{ 10708 vsh4I_reg(dst, src, shift); 10709 %} 10710 %} 10711 10712 instruct vsl2I_immI(vecD dst, vecD src, immI shift) %{ 10713 predicate(n->as_Vector()->length() == 2 && VM_Version::has_simd()); 10714 match(Set dst (LShiftVI src (LShiftCntV shift))); 10715 size(4); 10716 ins_cost(DEFAULT_COST); // FIXME 10717 format %{ 10718 "VSHL.I32 $dst.D,$src.D,$shift\t! logical left shift packed2I" 10719 %} 10720 ins_encode %{ 10721 bool quad = false; 10722 __ vshli($dst$$FloatRegister, $src$$FloatRegister, 32, $shift$$constant, 10723 quad); 10724 %} 10725 ins_pipe( ialu_reg_reg ); // FIXME 10726 %} 10727 10728 instruct vsl4I_immI(vecX dst, vecX src, immI shift) %{ 10729 predicate(n->as_Vector()->length() == 4 && VM_Version::has_simd()); 10730 match(Set dst (LShiftVI src (LShiftCntV shift))); 10731 size(4); 10732 ins_cost(DEFAULT_COST); // FIXME 10733 format %{ 10734 "VSHL.I32 $dst.Q,$src.Q,$shift\t! logical left shift packed4I" 10735 %} 10736 ins_encode %{ 10737 bool quad = true; 10738 __ vshli($dst$$FloatRegister, $src$$FloatRegister, 32, $shift$$constant, 10739 quad); 10740 %} 10741 ins_pipe( ialu_reg_reg ); // FIXME 10742 %} 10743 10744 // Longs vector logical left/right shift 10745 instruct vsl2L_reg(vecX dst, vecX src, vecX shift) %{ 10746 predicate(n->as_Vector()->length() == 2); 10747 match(Set dst (LShiftVL src shift)); 10748 match(Set dst (URShiftVL src shift)); 10749 size(4*1); 10750 ins_cost(DEFAULT_COST*1); // FIXME 10751 expand %{ 10752 vsh2L_reg(dst, src, shift); 10753 %} 10754 %} 10755 10756 instruct vsl2L_immI(vecX dst, vecX src, immI shift) %{ 10757 predicate(n->as_Vector()->length() == 2); 10758 match(Set dst (LShiftVL src (LShiftCntV shift))); 10759 size(4); 10760 ins_cost(DEFAULT_COST); // FIXME 10761 format %{ 10762 "VSHL.I64 $dst.Q,$src.Q,$shift\t! logical left shift packed2L" 10763 %} 10764 ins_encode %{ 10765 bool quad = true; 10766 __ vshli($dst$$FloatRegister, $src$$FloatRegister, 64, $shift$$constant, 10767 quad); 10768 %} 10769 ins_pipe( ialu_reg_reg ); // FIXME 10770 %} 10771 10772 // ----------------------- LogicalRightShift ----------------------------------- 10773 10774 // Bytes/Shorts vector logical right shift produces incorrect Java result 10775 // for negative data because java code convert short value into int with 10776 // sign extension before a shift. 10777 10778 // Chars vector logical right shift 10779 instruct vsrl4S_immI(vecD dst, vecD src, immI shift) %{ 10780 predicate(n->as_Vector()->length() == 4); 10781 match(Set dst (URShiftVS src (RShiftCntV shift))); 10782 size(4); 10783 ins_cost(DEFAULT_COST); // FIXME 10784 format %{ 10785 "VSHR.U16 $dst.D,$src.D,$shift\t! logical right shift packed4S" 10786 %} 10787 ins_encode %{ 10788 bool quad = false; 10789 __ vshrUI($dst$$FloatRegister, $src$$FloatRegister, 16, $shift$$constant, 10790 quad); 10791 %} 10792 ins_pipe( ialu_reg_reg ); // FIXME 10793 %} 10794 10795 instruct vsrl8S_immI(vecX dst, vecX src, immI shift) %{ 10796 predicate(n->as_Vector()->length() == 8); 10797 match(Set dst (URShiftVS src (RShiftCntV shift))); 10798 size(4); 10799 ins_cost(DEFAULT_COST); // FIXME 10800 format %{ 10801 "VSHR.U16 $dst.Q,$src.Q,$shift\t! logical right shift packed8S" 10802 %} 10803 ins_encode %{ 10804 bool quad = true; 10805 __ vshrUI($dst$$FloatRegister, $src$$FloatRegister, 16, $shift$$constant, 10806 quad); 10807 %} 10808 ins_pipe( ialu_reg_reg ); // FIXME 10809 %} 10810 10811 // Integers vector logical right shift 10812 instruct vsrl2I_immI(vecD dst, vecD src, immI shift) %{ 10813 predicate(n->as_Vector()->length() == 2 && VM_Version::has_simd()); 10814 match(Set dst (URShiftVI src (RShiftCntV shift))); 10815 size(4); 10816 ins_cost(DEFAULT_COST); // FIXME 10817 format %{ 10818 "VSHR.U32 $dst.D,$src.D,$shift\t! logical right shift packed2I" 10819 %} 10820 ins_encode %{ 10821 bool quad = false; 10822 __ vshrUI($dst$$FloatRegister, $src$$FloatRegister, 32, $shift$$constant, 10823 quad); 10824 %} 10825 ins_pipe( ialu_reg_reg ); // FIXME 10826 %} 10827 10828 instruct vsrl4I_immI(vecX dst, vecX src, immI shift) %{ 10829 predicate(n->as_Vector()->length() == 4 && VM_Version::has_simd()); 10830 match(Set dst (URShiftVI src (RShiftCntV shift))); 10831 size(4); 10832 ins_cost(DEFAULT_COST); // FIXME 10833 format %{ 10834 "VSHR.U32 $dst.Q,$src.Q,$shift\t! logical right shift packed4I" 10835 %} 10836 ins_encode %{ 10837 bool quad = true; 10838 __ vshrUI($dst$$FloatRegister, $src$$FloatRegister, 32, $shift$$constant, 10839 quad); 10840 %} 10841 ins_pipe( ialu_reg_reg ); // FIXME 10842 %} 10843 10844 // Longs vector logical right shift 10845 instruct vsrl2L_immI(vecX dst, vecX src, immI shift) %{ 10846 predicate(n->as_Vector()->length() == 2); 10847 match(Set dst (URShiftVL src (RShiftCntV shift))); 10848 size(4); 10849 ins_cost(DEFAULT_COST); // FIXME 10850 format %{ 10851 "VSHR.U64 $dst.Q,$src.Q,$shift\t! logical right shift packed2L" 10852 %} 10853 ins_encode %{ 10854 bool quad = true; 10855 __ vshrUI($dst$$FloatRegister, $src$$FloatRegister, 64, $shift$$constant, 10856 quad); 10857 %} 10858 ins_pipe( ialu_reg_reg ); // FIXME 10859 %} 10860 10861 // ------------------- ArithmeticRightShift ----------------------------------- 10862 10863 // Bytes vector arithmetic left/right shift based on sign 10864 instruct vsha8B_reg(vecD dst, vecD src, vecD shift) %{ 10865 predicate(n->as_Vector()->length() == 8); 10866 effect(DEF dst, USE src, USE shift); 10867 size(4); 10868 ins_cost(DEFAULT_COST); // FIXME 10869 format %{ 10870 "VSHL.S8 $dst.D,$src.D,$shift.D\t! arithmetic right shift packed8B" 10871 %} 10872 ins_encode %{ 10873 bool quad = false; 10874 __ vshlSI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister, 10875 MacroAssembler::VELEM_SIZE_8, quad); 10876 %} 10877 ins_pipe( ialu_reg_reg ); // FIXME 10878 %} 10879 10880 instruct vsha16B_reg(vecX dst, vecX src, vecX shift) %{ 10881 predicate(n->as_Vector()->length() == 16); 10882 effect(DEF dst, USE src, USE shift); 10883 size(4); 10884 ins_cost(DEFAULT_COST); // FIXME 10885 format %{ 10886 "VSHL.S8 $dst.Q,$src.Q,$shift.Q\t! arithmetic right shift packed16B" 10887 %} 10888 ins_encode %{ 10889 bool quad = true; 10890 __ vshlSI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister, 10891 MacroAssembler::VELEM_SIZE_8, quad); 10892 %} 10893 ins_pipe( ialu_reg_reg ); // FIXME 10894 %} 10895 10896 // Shorts vector arithmetic left/right shift based on sign 10897 instruct vsha4S_reg(vecD dst, vecD src, vecD shift) %{ 10898 predicate(n->as_Vector()->length() == 4); 10899 effect(DEF dst, USE src, USE shift); 10900 size(4); 10901 ins_cost(DEFAULT_COST); // FIXME 10902 format %{ 10903 "VSHL.S16 $dst.D,$src.D,$shift.D\t! arithmetic right shift packed4S" 10904 %} 10905 ins_encode %{ 10906 bool quad = false; 10907 __ vshlSI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister, 10908 MacroAssembler::VELEM_SIZE_16, quad); 10909 %} 10910 ins_pipe( ialu_reg_reg ); // FIXME 10911 %} 10912 10913 instruct vsha8S_reg(vecX dst, vecX src, vecX shift) %{ 10914 predicate(n->as_Vector()->length() == 8); 10915 effect(DEF dst, USE src, USE shift); 10916 size(4); 10917 ins_cost(DEFAULT_COST); // FIXME 10918 format %{ 10919 "VSHL.S16 $dst.Q,$src.Q,$shift.Q\t! arithmetic right shift packed8S" 10920 %} 10921 ins_encode %{ 10922 bool quad = true; 10923 __ vshlSI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister, 10924 MacroAssembler::VELEM_SIZE_16, quad); 10925 %} 10926 ins_pipe( ialu_reg_reg ); // FIXME 10927 %} 10928 10929 // Integers vector arithmetic left/right shift based on sign 10930 instruct vsha2I_reg(vecD dst, vecD src, vecD shift) %{ 10931 predicate(n->as_Vector()->length() == 2); 10932 effect(DEF dst, USE src, USE shift); 10933 size(4); 10934 ins_cost(DEFAULT_COST); // FIXME 10935 format %{ 10936 "VSHL.S32 $dst.D,$src.D,$shift.D\t! arithmetic right shift packed2I" 10937 %} 10938 ins_encode %{ 10939 bool quad = false; 10940 __ vshlSI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister, 10941 MacroAssembler::VELEM_SIZE_32, quad); 10942 %} 10943 ins_pipe( ialu_reg_reg ); // FIXME 10944 %} 10945 10946 instruct vsha4I_reg(vecX dst, vecX src, vecX shift) %{ 10947 predicate(n->as_Vector()->length() == 4); 10948 effect(DEF dst, USE src, USE shift); 10949 size(4); 10950 ins_cost(DEFAULT_COST); // FIXME 10951 format %{ 10952 "VSHL.S32 $dst.Q,$src.Q,$shift.Q\t! arithmetic right shift packed4I" 10953 %} 10954 ins_encode %{ 10955 bool quad = true; 10956 __ vshlSI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister, 10957 MacroAssembler::VELEM_SIZE_32, quad); 10958 %} 10959 ins_pipe( ialu_reg_reg ); // FIXME 10960 %} 10961 10962 // Longs vector arithmetic left/right shift based on sign 10963 instruct vsha2L_reg(vecX dst, vecX src, vecX shift) %{ 10964 predicate(n->as_Vector()->length() == 2); 10965 effect(DEF dst, USE src, USE shift); 10966 size(4); 10967 ins_cost(DEFAULT_COST); // FIXME 10968 format %{ 10969 "VSHL.S64 $dst.Q,$src.Q,$shift.Q\t! arithmetic right shift packed2L" 10970 %} 10971 ins_encode %{ 10972 bool quad = true; 10973 __ vshlSI($dst$$FloatRegister, $shift$$FloatRegister, $src$$FloatRegister, 10974 MacroAssembler::VELEM_SIZE_64, quad); 10975 %} 10976 ins_pipe( ialu_reg_reg ); // FIXME 10977 %} 10978 10979 // Byte vector arithmetic right shift 10980 10981 instruct vsra8B_reg(vecD dst, vecD src, vecD shift) %{ 10982 predicate(n->as_Vector()->length() == 8); 10983 match(Set dst (RShiftVB src shift)); 10984 size(4); 10985 ins_cost(DEFAULT_COST); // FIXME 10986 expand %{ 10987 vsha8B_reg(dst, src, shift); 10988 %} 10989 %} 10990 10991 instruct vsrl16B_reg(vecX dst, vecX src, vecX shift) %{ 10992 predicate(n->as_Vector()->length() == 16); 10993 match(Set dst (RShiftVB src shift)); 10994 size(4); 10995 ins_cost(DEFAULT_COST); // FIXME 10996 expand %{ 10997 vsha16B_reg(dst, src, shift); 10998 %} 10999 %} 11000 11001 instruct vsrl8B_immI(vecD dst, vecD src, immI shift) %{ 11002 predicate(n->as_Vector()->length() == 8); 11003 match(Set dst (RShiftVB src shift)); 11004 size(4); 11005 ins_cost(DEFAULT_COST); // FIXME 11006 format %{ 11007 "VSHR.S8 $dst.D,$src.D,$shift\t! logical right shift packed8B" 11008 %} 11009 ins_encode %{ 11010 bool quad = false; 11011 __ vshrSI($dst$$FloatRegister, $src$$FloatRegister, 8, $shift$$constant, 11012 quad); 11013 %} 11014 ins_pipe( ialu_reg_reg ); // FIXME 11015 %} 11016 11017 instruct vsrl16B_immI(vecX dst, vecX src, immI shift) %{ 11018 predicate(n->as_Vector()->length() == 16); 11019 match(Set dst (RShiftVB src shift)); 11020 size(4); 11021 ins_cost(DEFAULT_COST); // FIXME 11022 format %{ 11023 "VSHR.S8 $dst.Q,$src.Q,$shift\t! logical right shift packed16B" 11024 %} 11025 ins_encode %{ 11026 bool quad = true; 11027 __ vshrSI($dst$$FloatRegister, $src$$FloatRegister, 8, $shift$$constant, 11028 quad); 11029 %} 11030 ins_pipe( ialu_reg_reg ); // FIXME 11031 %} 11032 11033 // Shorts vector arithmetic right shift 11034 instruct vsra4S_reg(vecD dst, vecD src, vecD shift) %{ 11035 predicate(n->as_Vector()->length() == 4); 11036 match(Set dst (RShiftVS src shift)); 11037 size(4); 11038 ins_cost(DEFAULT_COST); // FIXME 11039 expand %{ 11040 vsha4S_reg(dst, src, shift); 11041 %} 11042 %} 11043 11044 instruct vsra8S_reg(vecX dst, vecX src, vecX shift) %{ 11045 predicate(n->as_Vector()->length() == 8); 11046 match(Set dst (RShiftVS src shift)); 11047 size(4); 11048 ins_cost(DEFAULT_COST); // FIXME 11049 expand %{ 11050 vsha8S_reg(dst, src, shift); 11051 %} 11052 %} 11053 11054 instruct vsra4S_immI(vecD dst, vecD src, immI shift) %{ 11055 predicate(n->as_Vector()->length() == 4); 11056 match(Set dst (RShiftVS src shift)); 11057 size(4); 11058 ins_cost(DEFAULT_COST); // FIXME 11059 format %{ 11060 "VSHR.S16 $dst.D,$src.D,$shift\t! logical right shift packed4S" 11061 %} 11062 ins_encode %{ 11063 bool quad = false; 11064 __ vshrSI($dst$$FloatRegister, $src$$FloatRegister, 16, $shift$$constant, 11065 quad); 11066 %} 11067 ins_pipe( ialu_reg_reg ); // FIXME 11068 %} 11069 11070 instruct vsra8S_immI(vecX dst, vecX src, immI shift) %{ 11071 predicate(n->as_Vector()->length() == 8); 11072 match(Set dst (RShiftVS src shift)); 11073 size(4); 11074 ins_cost(DEFAULT_COST); // FIXME 11075 format %{ 11076 "VSHR.S16 $dst.Q,$src.Q,$shift\t! logical right shift packed8S" 11077 %} 11078 ins_encode %{ 11079 bool quad = true; 11080 __ vshrSI($dst$$FloatRegister, $src$$FloatRegister, 16, $shift$$constant, 11081 quad); 11082 %} 11083 ins_pipe( ialu_reg_reg ); // FIXME 11084 %} 11085 11086 // Integers vector arithmetic right shift 11087 instruct vsra2I_reg(vecD dst, vecD src, vecD shift) %{ 11088 predicate(n->as_Vector()->length() == 2); 11089 match(Set dst (RShiftVI src shift)); 11090 size(4); 11091 ins_cost(DEFAULT_COST); // FIXME 11092 expand %{ 11093 vsha2I_reg(dst, src, shift); 11094 %} 11095 %} 11096 11097 instruct vsra4I_reg(vecX dst, vecX src, vecX shift) %{ 11098 predicate(n->as_Vector()->length() == 4); 11099 match(Set dst (RShiftVI src shift)); 11100 size(4); 11101 ins_cost(DEFAULT_COST); // FIXME 11102 expand %{ 11103 vsha4I_reg(dst, src, shift); 11104 %} 11105 %} 11106 11107 instruct vsra2I_immI(vecD dst, vecD src, immI shift) %{ 11108 predicate(n->as_Vector()->length() == 2); 11109 match(Set dst (RShiftVI src shift)); 11110 size(4); 11111 ins_cost(DEFAULT_COST); // FIXME 11112 format %{ 11113 "VSHR.S32 $dst.D,$src.D,$shift\t! logical right shift packed2I" 11114 %} 11115 ins_encode %{ 11116 bool quad = false; 11117 __ vshrSI($dst$$FloatRegister, $src$$FloatRegister, 32, $shift$$constant, 11118 quad); 11119 %} 11120 ins_pipe( ialu_reg_reg ); // FIXME 11121 %} 11122 11123 instruct vsra4I_immI(vecX dst, vecX src, immI shift) %{ 11124 predicate(n->as_Vector()->length() == 4); 11125 match(Set dst (RShiftVI src shift)); 11126 size(4); 11127 ins_cost(DEFAULT_COST); // FIXME 11128 format %{ 11129 "VSHR.S32 $dst.Q,$src.Q,$shift\t! logical right shift packed4I" 11130 %} 11131 ins_encode %{ 11132 bool quad = true; 11133 __ vshrSI($dst$$FloatRegister, $src$$FloatRegister, 32, $shift$$constant, 11134 quad); 11135 %} 11136 ins_pipe( ialu_reg_reg ); // FIXME 11137 %} 11138 11139 // Longs vector arithmetic right shift 11140 instruct vsra2L_reg(vecX dst, vecX src, vecX shift) %{ 11141 predicate(n->as_Vector()->length() == 2); 11142 match(Set dst (RShiftVL src shift)); 11143 size(4); 11144 ins_cost(DEFAULT_COST); // FIXME 11145 expand %{ 11146 vsha2L_reg(dst, src, shift); 11147 %} 11148 %} 11149 11150 instruct vsra2L_immI(vecX dst, vecX src, immI shift) %{ 11151 predicate(n->as_Vector()->length() == 2); 11152 match(Set dst (RShiftVL src shift)); 11153 size(4); 11154 ins_cost(DEFAULT_COST); // FIXME 11155 format %{ 11156 "VSHR.S64 $dst.Q,$src.Q,$shift\t! logical right shift packed2L" 11157 %} 11158 ins_encode %{ 11159 bool quad = true; 11160 __ vshrSI($dst$$FloatRegister, $src$$FloatRegister, 64, $shift$$constant, 11161 quad); 11162 %} 11163 ins_pipe( ialu_reg_reg ); // FIXME 11164 %} 11165 11166 // --------------------------------- AND -------------------------------------- 11167 11168 instruct vandD(vecD dst, vecD src1, vecD src2) %{ 11169 predicate(n->as_Vector()->length_in_bytes() == 8); 11170 match(Set dst (AndV src1 src2)); 11171 format %{ "VAND $dst.D,$src1.D,$src2.D\t! and vectors (8 bytes)" %} 11172 ins_encode %{ 11173 bool quad = false; 11174 __ vandI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 11175 quad); 11176 %} 11177 ins_pipe( ialu_reg_reg ); // FIXME 11178 %} 11179 11180 instruct vandX(vecX dst, vecX src1, vecX src2) %{ 11181 predicate(n->as_Vector()->length_in_bytes() == 16); 11182 match(Set dst (AndV src1 src2)); 11183 format %{ "VAND $dst.Q,$src1.Q,$src2.Q\t! and vectors (16 bytes)" %} 11184 ins_encode %{ 11185 bool quad = true; 11186 __ vandI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 11187 quad); 11188 %} 11189 ins_pipe( ialu_reg_reg ); // FIXME 11190 %} 11191 11192 // --------------------------------- OR --------------------------------------- 11193 11194 instruct vorD(vecD dst, vecD src1, vecD src2) %{ 11195 predicate(n->as_Vector()->length_in_bytes() == 8); 11196 match(Set dst (OrV src1 src2)); 11197 format %{ "VOR $dst.D,$src1.D,$src2.D\t! and vectors (8 bytes)" %} 11198 ins_encode %{ 11199 bool quad = false; 11200 __ vorI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 11201 quad); 11202 %} 11203 ins_pipe( ialu_reg_reg ); // FIXME 11204 %} 11205 11206 instruct vorX(vecX dst, vecX src1, vecX src2) %{ 11207 predicate(n->as_Vector()->length_in_bytes() == 16); 11208 match(Set dst (OrV src1 src2)); 11209 format %{ "VOR $dst.Q,$src1.Q,$src2.Q\t! and vectors (16 bytes)" %} 11210 ins_encode %{ 11211 bool quad = true; 11212 __ vorI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 11213 quad); 11214 %} 11215 ins_pipe( ialu_reg_reg ); // FIXME 11216 %} 11217 11218 // --------------------------------- XOR -------------------------------------- 11219 11220 instruct vxorD(vecD dst, vecD src1, vecD src2) %{ 11221 predicate(n->as_Vector()->length_in_bytes() == 8); 11222 match(Set dst (XorV src1 src2)); 11223 format %{ "VXOR $dst.D,$src1.D,$src2.D\t! and vectors (8 bytes)" %} 11224 ins_encode %{ 11225 bool quad = false; 11226 __ vxorI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 11227 quad); 11228 %} 11229 ins_pipe( ialu_reg_reg ); // FIXME 11230 %} 11231 11232 instruct vxorX(vecX dst, vecX src1, vecX src2) %{ 11233 predicate(n->as_Vector()->length_in_bytes() == 16); 11234 match(Set dst (XorV src1 src2)); 11235 format %{ "VXOR $dst.Q,$src1.Q,$src2.Q\t! and vectors (16 bytes)" %} 11236 ins_encode %{ 11237 bool quad = true; 11238 __ vxorI($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, 11239 quad); 11240 %} 11241 ins_pipe( ialu_reg_reg ); // FIXME 11242 %} 11243 11244 11245 //----------PEEPHOLE RULES----------------------------------------------------- 11246 // These must follow all instruction definitions as they use the names 11247 // defined in the instructions definitions. 11248 // 11249 // peepmatch ( root_instr_name [preceding_instruction]* ); 11250 // 11251 // peepconstraint %{ 11252 // (instruction_number.operand_name relational_op instruction_number.operand_name 11253 // [, ...] ); 11254 // // instruction numbers are zero-based using left to right order in peepmatch 11255 // 11256 // peepreplace ( instr_name ( [instruction_number.operand_name]* ) ); 11257 // // provide an instruction_number.operand_name for each operand that appears 11258 // // in the replacement instruction's match rule 11259 // 11260 // ---------VM FLAGS--------------------------------------------------------- 11261 // 11262 // All peephole optimizations can be turned off using -XX:-OptoPeephole 11263 // 11264 // Each peephole rule is given an identifying number starting with zero and 11265 // increasing by one in the order seen by the parser. An individual peephole 11266 // can be enabled, and all others disabled, by using -XX:OptoPeepholeAt=# 11267 // on the command-line. 11268 // 11269 // ---------CURRENT LIMITATIONS---------------------------------------------- 11270 // 11271 // Only match adjacent instructions in same basic block 11272 // Only equality constraints 11273 // Only constraints between operands, not (0.dest_reg == EAX_enc) 11274 // Only one replacement instruction 11275 // 11276 // ---------EXAMPLE---------------------------------------------------------- 11277 // 11278 // // pertinent parts of existing instructions in architecture description 11279 // instruct movI(eRegI dst, eRegI src) %{ 11280 // match(Set dst (CopyI src)); 11281 // %} 11282 // 11283 // instruct incI_eReg(eRegI dst, immI1 src, eFlagsReg cr) %{ 11284 // match(Set dst (AddI dst src)); 11285 // effect(KILL cr); 11286 // %} 11287 // 11288 // // Change (inc mov) to lea 11289 // peephole %{ 11290 // // increment preceeded by register-register move 11291 // peepmatch ( incI_eReg movI ); 11292 // // require that the destination register of the increment 11293 // // match the destination register of the move 11294 // peepconstraint ( 0.dst == 1.dst ); 11295 // // construct a replacement instruction that sets 11296 // // the destination to ( move's source register + one ) 11297 // peepreplace ( incI_eReg_immI1( 0.dst 1.src 0.src ) ); 11298 // %} 11299 // 11300 11301 // // Change load of spilled value to only a spill 11302 // instruct storeI(memory mem, eRegI src) %{ 11303 // match(Set mem (StoreI mem src)); 11304 // %} 11305 // 11306 // instruct loadI(eRegI dst, memory mem) %{ 11307 // match(Set dst (LoadI mem)); 11308 // %} 11309 // 11310 // peephole %{ 11311 // peepmatch ( loadI storeI ); 11312 // peepconstraint ( 1.src == 0.dst, 1.mem == 0.mem ); 11313 // peepreplace ( storeI( 1.mem 1.mem 1.src ) ); 11314 // %} 11315 11316 //----------SMARTSPILL RULES--------------------------------------------------- 11317 // These must follow all instruction definitions as they use the names 11318 // defined in the instructions definitions. 11319 // 11320 // ARM will probably not have any of these rules due to RISC instruction set. 11321 11322 //----------PIPELINE----------------------------------------------------------- 11323 // Rules which define the behavior of the target architectures pipeline.